// import { AsyncExecute } from "../common/AsyncExecute";
import { Guid } from "@gvol-org/geovis-brain-core";
import { Http } from "../Http";
import { FeatureCollection } from "../models/FeatureCollection";
import { ImageCollection } from "../models/ImageCollection";
import { Layer } from "@gvol-org/geovis-brain-core";
import { Palette } from "../models/Palette";
import { Subject } from "rxjs";
import { Geometry } from "../models/Geometry";
import { Image } from "../models/Image";
import { Feature } from "../models/Feature";
import * as turf from '@turf/turf';
import { MosaicData } from "../models/MosaicData";
import { Widget } from "../uisdk/Widget";
import { codeParams, ifOverLoadingObject } from "../common/FunParams";
import { ui } from "../uisdk/ui";
import mapboxgl from "mapbox-gl";
import Compare from "mapbox-gl-compare";
import { AddLayer } from "../models/AddLayer";
import { processMapSDK } from "@gvol-org/geovis-brain-core";
import { MapUtil } from "@gvol-org/geovis-brain-core";
import { BatchProcessing } from "../batchProcessingsdk/BatchProcessing";
// declare const mapboxgl: any;
/**
* Class description
* @summary sdk
*/
export class MapSdk {
static map: any;
//因为mapbox可能会变,所以要保存初始值
static originalMapbox: any;
/** features的像素信息在运行时保存的(目的:不用请求接口获取) */
static featuresGeometry: Array<any> = [];
/** features的图层信息在运行时保存的(目的:不用请求接口获取) */
static featuresLayerInfo: Array<any> = [];
static stateChanged$ = new Subject();
static loadTileSubject$ = new Subject();
static setSubject(sub: any) {
MapSdk.stateChanged$ = sub;
}
//用于设置layer的波段等内容
static addLayerSubject$ = new Subject();
static scaleMap = new Map<number, number>();
static mapUI: HTMLElement;//ui组件容器
constructor() {
}
// /**
// * 设置一个Mapbox实例.
// *@param {any} mapbox -Mapbox实例.
// */
private static setMap(mapbox: any) {
MapSdk.map = mapbox;
MapSdk.originalMapbox = mapbox;
MapSdk.scaleMap.set(0, 156543.03);
MapSdk.scaleMap.set(1, 78271.52);
MapSdk.scaleMap.set(2, 39135.76);
MapSdk.scaleMap.set(3, 19567.88);
MapSdk.scaleMap.set(4, 9783.94);
MapSdk.scaleMap.set(5, 4891.97);
MapSdk.scaleMap.set(6, 2445.98);
MapSdk.scaleMap.set(7, 1222.99);
MapSdk.scaleMap.set(8, 611.50);
MapSdk.scaleMap.set(9, 305.75);
MapSdk.scaleMap.set(10, 152.87);
MapSdk.scaleMap.set(11, 76.44);
MapSdk.scaleMap.set(12, 38.22);
MapSdk.scaleMap.set(13, 19.11);
MapSdk.scaleMap.set(14, 9.55);
MapSdk.scaleMap.set(15, 4.78);
MapSdk.scaleMap.set(16, 2.39);
MapSdk.scaleMap.set(17, 1.19);
MapSdk.scaleMap.set(18, 0.60);
MapSdk.scaleMap.set(19, 0.30);
BatchProcessing.image.setBatchProcessMap(this);
}
//存放所有创建过的layer
public static layerList: Array<Layer> = [];
//public static layerMap: Map<string, Layer> = new Map();
//存放bbox
//public static bboxMap: Map<string, any> = new Map();
//触发保存结果
private static keepResult(data: any) {
// Http.runDataSubject$.next({
// type: 'layer',
// content: {
// type: data.type,
// params: data.params,
// bbox: data.bbox,
// }
// });
}
//运行结果调用
public static runResult(data: any) {
if (data) {
switch (data.type) {
case "Geojson":
{
const { geojsonData, sourceId, layerId, style, render_sld } = data.params;
MapUtil.addSourceByGeojson(this.map, geojsonData, sourceId, layerId, style, render_sld);//绘制图层
data.bbox = turf.bbox(geojsonData);
}
break;
case "Pbf":
{
const { serviceInfo, sourceId, layerId, visParams } = data.params;
MapUtil.addSourceByPbf(this.map, serviceInfo, sourceId, layerId, visParams);//绘制图层
}
break;
case "Url":
{
const {
serviceInfo,
sourceId,
layerId,
urlTiles,
visible,
visParams
} = data.params;
MapUtil.addSourceByUrl(
this.map,
serviceInfo,
sourceId,
layerId,
urlTiles,
visible,
visParams
);//绘制图层
}
break;
case "Mvt":
{
const { serviceInfo, sourceId, layerId, visParams } = data.params;
MapUtil.addSourceByMvt(this.map, serviceInfo, sourceId, layerId, visParams);//绘制图层
}
break;
}
if (data.bbox) {
MapSdk.map.fitBounds(data.bbox);//视角飞入
}
}
}
/**
* 在地图上添加图层,图层类型可以是Image、Geometry、Feature、FeatureCollection,返回图层唯一的ID
* @param {Image|Geometry|Feature|FeatureCollection} image 作为图层添加的图像数据
* @param {Object} [visParams] 可选参数,属性:style(应用到图层的样式),palette(用于图层的调色板), crop(WKT类型的Geometry对象或gpkg文件路径),min, max, gamma, brightness
* @param {String} [name] 可选参数,给予图层的名称。
* @param {Boolean} [visible] 可选参数,该图层是否可见,默认为true
* @return {String} 添加图层的Id
* @tutorial Map
*/
//@imagepath
//
//返回一个layer对象
public static addLayer(
image: Image | Geometry | Feature | FeatureCollection | MosaicData,
visParams?: Object,
name?: string,
visible?: boolean,
) {
let options = { id: Guid.newGuid(), image, visParams, name, visible };
return MapUtil.addLayer(options, this);
}
/**
* 根据提供的ID移除图层
* @param {String} Id 待删除图层的ID
* @tutorial Map
*/
public static removeLayer(id: string) {
if (this.layerList) {
let res = this.layerList.find((v: any) => { return v.id == id });
res?.onLoadCompleted(() => {
res?.mapboxLayresId.forEach((lid: any) => {
this.map.removeLayer(lid);
});
res?.mapboxSourcesId.forEach((sid: any) => {
this.map.removeSource(sid);
});
});
}
}
/**
* 设置地图中心显示
* @param {Number} lon 地图显示中心点的经度
* @param {Number} lat 地图显示中心点的经度
* @param {Number} [zoom] 可选参数,地图显示缩放级别(0-24)
* @tutorial Map
*/
public static setCenter(lon: number, lat: number, zoom?: number) {
MapSdk.map.setCenter([lon, lat]);
if (zoom) {
MapSdk.map.setZoom(zoom);
}
}
/**
* 设置地图显示缩放级别
* @param {Number} zoom 地图显示缩放级别(0-24)
* @tutorial Map
*/
public static setZoom(zoom: number) {
MapSdk.map.setZoom(zoom);
}
/**
* 放大地图
* @tutorial Map
*/
public static zoomIn() {
MapSdk.map.zoomIn();
}
/**
* 缩小地图
* @tutorial Map
*/
public static zoomOut() {
MapSdk.map.zoomOut();
}
/**
* 清空已添加的所有图层
* @param {String} [param] 影像的url
* @tutorial Map
*/
public static clear() {
if (this.layerList) {
this.layerList?.forEach((data: any) => {
data?.onLoadCompleted(() => {
data?.mapboxLayresId.forEach((lid: any) => {
this.map.removeLayer(lid);
});
data?.mapboxSourcesId.forEach((sid: any) => {
this.map.removeSource(sid);
});
});
});
}
BatchProcessing.image.clearMap();
}
/**
* 清空已添加的所有图层, no onLoadCompleted
* @param {String} [param] 影像的url
* @tutorial Map
*/
public static clearCurrent() {
// this.layerMap.forEach(function (value, key, map) {
// value.mapboxLayresId.forEach((lid) => {
// MapSdk.mapbox.removeLayer(lid);
// });
// value.mapboxSourcesId.forEach((sid) => {
// MapSdk.mapbox.removeSource(sid);
// });
// MapSdk.layerMap.delete(key);
// });
}
/**
* 相机飞入到制定图层位置
* @param {String | Array<number>} param 图层的Id
* @tutorial Map
*/
public static flyto(param: string | Array<number>) {
MapUtil.flyto(this, param);
}
/**
* 图层过滤显示
* @param {String} id 图层的id
* @param {String} classId 过滤的图层类别
*/
public static setFilter(id: string, classId: string) {
MapUtil.setFilter(this, id, classId);
}
/**
* 返回当前地图视图的近似像素比例,单位为米
* @returns number
* @tutorial Map
*/
public static getScale() {
let zoomLevel = Math.round(MapSdk.map.getZoom()) + 1;
if (MapSdk.scaleMap.has(zoomLevel)) {
return MapSdk.scaleMap.get(zoomLevel);
}
return null;
}
/**
* 修改地图底图
* @param {String} mapTypeId 可以是 "SATELLITE"、"ROADMAP" 或 "TERRAIN" 之一
* @tutorial Map
*/
public static setOptions(mapTypeId:string): any {
return null;
}
/**
* 返回地图视图的当前缩放级别
* @returns number
* @tutorial Map
*/
public static getZoom(): number {
const zoom = MapSdk.map.getZoom();
return zoom
}
/**
* 返回地图视图的地理中心
* @returns Geometry.Point
* @tutorial Map
*/
public static getCenter() {
const center = MapSdk.map.getCenter();
return { lng: center.lng, lat: center.lat }
}
/**
* 返回地图视图的地理边界
* @param {boolean} asGeoJSON optional 如果asGeoJSON为true,则返回GeoJSON格式的边界
* @returns GeoJSONGeometry|Array<Number>|String
* @tutorial Map
*/
public static getBounds(asGeoJSON?: boolean) {
const bounds = MapSdk.map.getBounds(asGeoJSON)
return bounds
}
private static setMapUI(mapUI: any) {
this.mapUI = mapUI;
}
/**
* 在地图上添加自定义ui
* @param {Widget} ui 自定义ui
* @tutorial Map
*/
public static addUI(ui: Widget) {
if (this.mapUI) {
// console.log("addUI Code", ui['expressions']);
if (!Http.isRunAddUICode) {
Http.runDataSubject$.next({
type: 'ui',
content: Http.codeContent,
});
Http.isRunAddUICode = true;
}
if (ui.el) {
let style = ui.style();
// console.log('mapStyle:', style);
if (!style.get('position')) {
style.set('position', 'absolute');
if (!style.get('right') && !style.get('bottom') && !style.get('left') && !style.get('top')) {
style.set('left', '50%');
style.set('top', '10px');
}
}
style.set('z-index', '99');
if (ui.getType() == 'Map') {
if (!style.get('width') && !style.get('height')) {
style.set('width', '300px');
style.set('height', '200px');
}
}
}
this.mapUI.appendChild(ui.el as HTMLElement);
Http.createUIMapSubject$.next(ui);
if (ui['cht']) {
(ui.el as HTMLElement).style.width = '300px';
ui['cht']?.resize();
}
}
}
/**
* 移除地图上的自定义ui
* @param {Widget} ui 自定义ui
* @tutorial Map
*/
public static removeUI(ui: Widget) {
if (this.mapUI) {
this.mapUI.removeChild(ui.el as HTMLElement);
}
}
//代替flyto,使用value接口
/**
* 相机飞入到指定图层位置
* @param {Object} object 图层对象
* @param {Number} [zoom] 地图显示缩放级别(0-24)
*/
public static async centerObject(object: Object, zoom?: number) {
await MapUtil.centerObject(this, object, zoom);
// console.log("centerObject mapsdk", runData)
}
//卷帘加的底图,为了适配屏幕布局变化进行resize
public static compareMapList: any[] = [];
/**
* 卷帘
* @param {Image} left 左侧显示的Image实例
* @param {Image} right 右侧显示的Image实例
* @param {any[]} additionLayer 额外在左右两侧地图上都需要加的图层
* @tutorial Map
*/
public static CompareImage(left: Image, right?: Image, additionLayer?: any[]) {
this.compareMapList = [];
//先清除原有地图
ui.root.clear();
const link = document.createElement("link"); // 创建 link 元素
link.rel = "stylesheet"; // 设置 link 的 rel 属性为 stylesheet
link.href = "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-compare/v0.4.0/mapbox-gl-compare.css"; // 设置 link 的 href 属性为 CSS 文件的 URL
link.type = "text/css";
(ui.root.el as any).appendChild(link); // 将 link 元素添加到指定元素的子节点中
let mapStyle = {
position: "absolute",
top: 0,
bottom: 0,
width: "100%",
height: "100%",
"z-index": 1
}
let beforeDiv = ui.Panel(undefined, undefined, mapStyle);
(beforeDiv.el as any).id = "before";
let afterDiv = ui.Panel(undefined, undefined, mapStyle);
(afterDiv.el as any).id = "after";
let compareStyle = {
height: "100%",
width: "100%",
position: "absolute",
left: "0px",
top: "0px",
"z-index": 1
}
let compareDiv = ui.Panel([beforeDiv, afterDiv], ui.Panel.Layout.flow('horizontal'), compareStyle);
(compareDiv.el as any).id = "comparison-container";
ui.root.add(compareDiv);
// 创建卷帘
mapboxgl.accessToken = 'pk.eyJ1IjoiYXJhcGF5IiwiYSI6ImNsNXEyYXJhMDB2MWkzaWw4dWgxcWptOHYifQ.UYSWGUj_ufnOu-7KACtl4w';
let center = MapSdk.getCenter();
let zoom = MapSdk.getZoom();
let mapStatus = {
center: [center.lng, center.lat],
zoom: zoom
}
let mapboxStyle = MapSdk.map.getStyle();
let beforeMap = new AddLayer("before", mapStatus, mapboxStyle);
let afterMap = new AddLayer("after", mapStatus, mapboxStyle);
this.compareMapList.push(beforeMap.map);
this.compareMapList.push(afterMap.map);
let leftLayer = undefined;
let rightLayer = undefined;
if (left) {
let leftLayerid = beforeMap.addLayer(left);
leftLayer = beforeMap.layerList.find((v: any) => { return v.id == leftLayerid });
// 加上额外的图层
if (additionLayer && additionLayer.length > 0) {
leftLayer.onLoadCompleted(() => {
additionLayer.forEach(la => {
let tempLayerid = beforeMap.addLayer(la, { style: { polygonFillOpacity: 0 } });
let tempLayer = beforeMap.layerList.find((v: any) => { return v.id == tempLayerid });
//每次都把新加的图层置于顶层
for (let x = 0; x < tempLayer.mapboxLayresId.length; x++) {
beforeMap.map.moveLayer(tempLayer.mapboxLayresId[x], undefined);
}
})
})
}
}
if (right) {
let rightLayerid = afterMap.addLayer(right);
rightLayer = afterMap.layerList.find((v: any) => { return v.id == rightLayerid });
// 加上额外的图层
if (additionLayer && additionLayer.length > 0) {
rightLayer.onLoadCompleted(() => {
additionLayer.forEach(la => {
let tempLayerid = afterMap.addLayer(la, { style: { polygonFillOpacity: 0 } });
let tempLayer = afterMap.layerList.find((v: any) => { return v.id == tempLayerid });
//每次都把新加的图层置于顶层
for (let x = 0; x < tempLayer.mapboxLayresId.length; x++) {
afterMap.map.moveLayer(tempLayer.mapboxLayresId[x], undefined);
}
})
})
}
}
if (leftLayer && !rightLayer) {
beforeMap.flyto(leftLayer.id);
} else if (rightLayer) {
afterMap.flyto(rightLayer.id);
}
const container = '#comparison-container';
const map = new Compare(beforeMap.map, afterMap.map, container, {});
}
}
processMapSDK(MapSdk, "MapSdk", codeParams, ifOverLoadingObject);