/* eslint-disable no-irregular-whitespace */
|
/* eslint-disable no-mixed-spaces-and-tabs */
|
import { Cesium, wutu3d } from '@/global';
|
import { Evented, isArray } from './Event';
|
import {
|
setEntityAttributes,
|
Cartesian3_to_WGS84,
|
getClockViewModel,
|
checkWgs84Point,
|
} from './utils';
|
import { Fence } from './Fence';
|
import * as R from 'ramda';
|
import { Beams } from './Beams';
|
import { DrawOption } from './draw';
|
import { PointCluster } from './Cluster';
|
|
const SINGLE_MAP_IMAGE =
|
'./libs/map/Cesium/Assets/Textures/waterNormalsSmall.jpg';
|
const UI_CHANGE_EVENT = 'ui';
|
|
/**
|
* 地图主类
|
* @extends {Evented}
|
*/
|
export class Map extends Evented {
|
constructor(container, option) {
|
super();
|
this.option = R.merge(
|
{
|
sceneModePicker: false, // 视图模型选择按钮
|
|
fullscreenButton: false, // 全屏按钮
|
|
homeButton: false, // 回到初始化视图按钮
|
|
baseLayerPicker: false, // 底图选择按钮
|
|
navigationHelpButton: false, // 导航工具按钮
|
|
// 底图
|
imageryProvider: null,
|
// 背景色,只有在底图无效的情况下才有用
|
backgroundColor: null,
|
|
// 初始化视图值
|
viewpoint: null,
|
|
// 显示罗盘控件
|
showCompass: false,
|
|
// 当前时间
|
currentTime: undefined,
|
|
// 自定义数据源
|
dataSources: [],
|
},
|
option || {}
|
);
|
|
// 视图控制器
|
const viewer = (this.viewer = this._initViewer(container));
|
|
// 隐藏Cesium官网信息
|
this.viewer._cesiumWidget._creditContainer.style.display = 'none';
|
|
if (!this.option.imageryProvider) {
|
viewer.scene.skyBox = null;
|
viewer.scene.sun.show = false;
|
viewer.scene.moon.show = false;
|
viewer.scene.globe.show = false;
|
viewer.scene.backgroundColor = Cesium.Color.fromCssColorString(
|
this.option.backgroundColor || 'rgba(0, 13, 22, 1)'
|
);
|
viewer.scene.globe.depthTestAgainstTerrain = false;
|
viewer.scene.logarithmicDepthBuffer = false;
|
}
|
|
// 实始化地图初始点
|
this.viewer.camera.flyHome = () => {
|
this.option.viewpoint &&
|
this.setViewpoint(this.option.viewpoint, {
|
duration: 1,
|
});
|
};
|
|
this.viewer.scene.globe.depthTestAgainstTerrain = false;
|
|
// 安装指南针、罗盘插件
|
if (Cesium.viewerCesiumNavigationMixin && this.option.showCompass) {
|
const ops = {};
|
ops.enableCompass = true; //罗盘
|
ops.enableZoomControls = true; //缩放
|
ops.enableDistanceLegend = true; //比例尺
|
ops.enableCompassOuterRing = true; //指南针外环
|
this.viewer.extend(Cesium.viewerCesiumNavigationMixin, ops);
|
}
|
|
// 初始化数据源
|
this._initDataSources();
|
|
// 三维瓦片模型集合
|
this.models = [];
|
this.tileModelCollection = new Cesium.PrimitiveCollection('tilemodel');
|
this.viewer.scene.primitives.add(this.tileModelCollection);
|
|
// 绘制工具
|
this.measureTool = new wutu3d.analysi.Measure({
|
viewer: viewer,
|
removeScreenSpaceEvent: true,
|
label: {
|
font_size: 18,
|
border_width: 4,
|
background: false,
|
},
|
});
|
|
// 绘制工具
|
this.plotDrawTool = new wutu3d.Draw(viewer, { hasEdit: false });
|
|
// 交互
|
this._initEvent();
|
|
this.popups = [];
|
|
// 修改鼠标事件
|
// this.viewer.scene.screenSpaceCameraController.zoomEventTypes = [
|
// Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH
|
// ];
|
|
// this.viewer.scene.screenSpaceCameraController.tiltEventTypes = [
|
// Cesium.CameraEventType.PINCH, Cesium.CameraEventType.RIGHT_DRAG
|
// ];
|
|
// 视点管理
|
this.viewPoints = [];
|
|
// 漫游
|
this.romas = [];
|
// 漫游工具
|
this._romaTool = new wutu3d.Draw(this.viewer, {
|
hasEdit: true,
|
});
|
|
this.beams = new Beams(this);
|
|
// 实始化地图视点
|
if (this.option.viewpoint) {
|
this.setViewpoint(this.option.viewpoint);
|
}
|
}
|
|
_initDataSources() {
|
this.dataSources = {};
|
this.option.dataSources.forEach(source => {
|
const _source = (this.dataSources[source] = new Cesium.CustomDataSource(
|
source
|
));
|
this.viewer.dataSources.add(_source);
|
});
|
}
|
|
/**
|
* 遍历所有数据源
|
* @param {Function} callback
|
*/
|
eachDataSources(callback) {
|
Object.keys(key => {
|
callback && callback(this.dataSources[key]);
|
});
|
}
|
|
/**
|
* 获取数据源
|
* @param {String} dataSource
|
* @returns Cesium.CustomDataSource
|
*/
|
getDataSource(dataSource) {
|
return this.dataSources[dataSource];
|
}
|
|
/**
|
* 设置数据源可见度
|
* @param {Boolean} visible
|
* @param {String} dataSource 数据源ID,如果不提供,则设置所有对象
|
*/
|
setDataSourceVisible(visible, dataSource) {
|
if (dataSource && this.dataSources[dataSource]) {
|
this.dataSources[dataSource].show = visible;
|
} else if (!dataSource) {
|
this.eachDataSources(ds => {
|
ds.show = visible;
|
});
|
}
|
}
|
|
/**
|
* 清除数据源
|
* @param {String|undefined} 数据源ID,如果不提供,则清空所有数据源
|
*/
|
clearDataSourceEntities(dataSource) {
|
if (dataSource && this.dataSources[dataSource]) {
|
this.dataSources[dataSource].entities.removeAll();
|
} else if (!dataSource) {
|
this.eachDataSources(ds => {
|
ds.entities.removeAll();
|
});
|
}
|
}
|
|
/**
|
* 初始化事件
|
* @private
|
*/
|
_initEvent() {
|
// this.viewer.wutu3d.keyboardRoam.bind({
|
// speedRatio: 150, //平移步长,值越大步长越小。
|
// dirStep: 25, //相机原地旋转步长,值越大步长越小。
|
// rotateStep: 1.0, //相机围绕目标点旋转速率,0.3 - 2.0
|
// minPitch: 0.1, //最小仰角 0 - 1
|
// maxPitch: 0.95, //最大仰角 0 - 1
|
// });
|
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
|
const viewer = this.viewer;
|
const plotDrawTool = this.plotDrawTool;
|
const _mergeEvt = event => {
|
try {
|
let eventPosition = event.endPosition || event.position;
|
let position1 = viewer.scene.pickPosition(eventPosition);
|
if (position1) {
|
let c = Cesium.Cartographic.fromCartesian(position1); //笛卡尔坐标转为经纬度(弧度)
|
let point = [
|
Cesium.Math.toDegrees(c.longitude),
|
Cesium.Math.toDegrees(c.latitude),
|
c.height,
|
];
|
event.pointWithHeight = point;
|
}
|
|
let position = viewer.camera.pickEllipsoid(
|
eventPosition,
|
viewer.scene.globe.ellipsoid
|
);
|
let pick = viewer.scene.pick(eventPosition);
|
if (
|
Cesium.defined(pick) &&
|
pick.id &&
|
pick.id instanceof Cesium.Entity
|
) {
|
event.entity = pick.id;
|
if (event.entity.attribute && event.entity.attribute.attr) {
|
event.attr = { ...event.entity.attribute.attr };
|
} else {
|
event.attr = null;
|
}
|
} else {
|
event.entity = null;
|
event.attr = null;
|
}
|
event.editPlot = plotDrawTool.getCurrentEntity();
|
event.cartesian3 = position;
|
event.latLngPosition = position && Cartesian3_to_WGS84(position);
|
|
var ray = viewer.camera.getPickRay(eventPosition);
|
let cartesian2 = viewer.scene.globe.pick(ray, viewer.scene);
|
event.latLngPositionGlobe =
|
cartesian2 && Cartesian3_to_WGS84(cartesian2);
|
} catch (e) {}
|
};
|
|
this.handler.setInputAction(evt => {
|
_mergeEvt(evt);
|
this.fire('click', evt);
|
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
|
this.handler.setInputAction(evt => {
|
_mergeEvt(evt);
|
this.fire('mousemove', evt);
|
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
|
// this.plotDrawTool.on(wutu3d.draw.event.DrawStop, (e) => {
|
// this.fire("drawStop", e);
|
// });
|
|
// this.plotDrawTool.on(wutu3d.draw.event.DrawAddPoint, (e) => {
|
// this.fire("drawUpdate", e);
|
// });
|
|
// this.plotDrawTool.on(wutu3d.draw.event.DrawRemovePoint, (e) => {
|
// this.fire("drawUpdate", e);
|
// });
|
|
// this.plotDrawTool.on(wutu3d.draw.event.EditMovePoint, (e) => {
|
// this.fire("drawUpdate", e);
|
// console.log(e);
|
// });
|
this.handler.setInputAction(evt => {
|
this.fire(UI_CHANGE_EVENT);
|
}, Cesium.ScreenSpaceEventType.WHEEL);
|
this.on(UI_CHANGE_EVENT, e => PointCluster(this, e));
|
}
|
|
/**
|
* 根据模型ID获取模型
|
* @param {String} id 模型ID
|
* @return {Object|undefined}
|
*/
|
getModel(id) {
|
return this.models.filter(d => d.id === id)[0];
|
}
|
|
/**
|
* 定位至模型
|
* @param {String} id 模型ID
|
*/
|
flyToModel(id) {
|
const model = this.getModel(id);
|
if (!model || !model.model) return;
|
this.viewer.flyTo(model.model);
|
}
|
|
/**
|
* 添加模型
|
* @param {String}
|
* @param {Object} param 模型参数
|
* @param {String} param.id 模型ID
|
* @param {String} param.name 模型名称
|
* @param {String} param.link 模型链接地址
|
* @param {String} param.visible 模型可见度
|
* @param {String} param.maximumScreenSpaceError 模型精度,1最高,越大越模糊,默认为4
|
* @param {String} param.modifyZ 模型Z值高度修复,默认为0
|
* @return {Object}
|
*/
|
addModel(option) {
|
if (R.type(option) === 'String') {
|
return this.tileModelCollection.add(
|
new Cesium.Cesium3DTileset({
|
url: option,
|
})
|
);
|
}
|
const {
|
maximumScreenSpaceError,
|
id,
|
name,
|
link,
|
visible,
|
modelMatrix,
|
loaded,
|
focus,
|
color,
|
maximumMemoryUsage,
|
callback,
|
} = option || {};
|
let modifyZ = option.modifyZ;
|
let transform = option.transform;
|
var tileset = this.tileModelCollection.add(
|
new Cesium.Cesium3DTileset({
|
url: link,
|
show: visible === undefined ? true : !!visible,
|
...option,
|
maximumScreenSpaceError: maximumScreenSpaceError || 16,
|
modelMatrix: Cesium.Matrix4.fromArray(
|
modelMatrix || [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
),
|
maximumMemoryUsage: maximumMemoryUsage || 1024,
|
})
|
);
|
if (modifyZ && !transform) {
|
transform = { tz: modifyZ };
|
}
|
let _transform = R.merge(
|
{
|
tx: 0.0,
|
ty: 0.0,
|
tz: 0.0,
|
rx: 0.0,
|
ry: 0.0,
|
rz: 0.0,
|
scale: 1.0,
|
},
|
transform || {}
|
);
|
tileset.readyPromise
|
.then(tileset => {
|
var boundingSphere = tileset.boundingSphere;
|
var cartographic = Cesium.Cartographic.fromCartesian(
|
boundingSphere.center
|
);
|
var surface = Cesium.Cartesian3.fromRadians(
|
cartographic.longitude,
|
cartographic.latitude,
|
0.0
|
);
|
var offset = Cesium.Cartesian3.fromRadians(
|
cartographic.longitude,
|
cartographic.latitude,
|
cartographic.height
|
);
|
let lnglat = Cartesian3_to_WGS84(offset);
|
if (transform) {
|
_transform = R.merge(_transform, {
|
tx: _transform.tx || lnglat.x || 0.0,
|
ty: _transform.ty || lnglat.y || 0.0,
|
});
|
tileset._computeTransform = _transform;
|
tileset._root.transform = this.update3dtilesMaxtrix(_transform);
|
} else {
|
tileset._computeTransform = R.merge(
|
{
|
tx: lnglat.x,
|
ty: lnglat.y,
|
tz: lnglat.z,
|
// tz: 0.0,
|
rx: 0.0,
|
ry: 0.0,
|
rz: 0.0,
|
scale: 1.0,
|
},
|
transform || {}
|
);
|
}
|
if (color) {
|
this.setModelColor(tileset, color);
|
}
|
if (focus) {
|
this.viewer.flyTo(tileset);
|
}
|
console.log(1);
|
if (callback) {
|
console.log(callback);
|
callback(tileset);
|
}
|
// viewer.zoomTo(tileset);
|
})
|
.otherwise(function() {});
|
|
tileset.allTilesLoaded.addEventListener(() => {
|
loaded && loaded(tileset);
|
});
|
|
var _model = {
|
...option,
|
name,
|
id: id || Cesium.createGuid(),
|
link: link,
|
model: tileset,
|
visible: visible === undefined ? true : !!visible,
|
modelMatrix: modelMatrix,
|
transform: _transform,
|
maximumScreenSpaceError: maximumScreenSpaceError,
|
};
|
this.models.push(_model);
|
this.fire(UI_CHANGE_EVENT);
|
return _model;
|
}
|
|
removeModels() {
|
this.models.forEach(model => {
|
if (
|
model.model &&
|
model.model instanceof Cesium.Cesium3DTileset &&
|
this.tileModelCollection.contains(model.model)
|
) {
|
this.tileModelCollection.remove(model.model);
|
}
|
});
|
this.models = [];
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
// 设置模型颜色
|
setModelColor(id, color) {
|
const tileset =
|
id instanceof Cesium.Cesium3DTileset
|
? id
|
: this.models.filter(d => d.id === id)[0].model;
|
if (!tileset) return;
|
if (!color) {
|
tileset.style = undefined;
|
} else {
|
tileset.style = new Cesium.Cesium3DTileStyle();
|
tileset.style.color = {
|
evaluateColor: (f, r) => {
|
return Cesium.Color.fromCssColorString(color);
|
},
|
};
|
}
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
// 设置模型位置、旋转角度
|
setModelTransform(id, transform) {
|
if (!transform) return;
|
const model = this.models.filter(d => d.id === id)[0];
|
if (!model) return null;
|
const tileset = model.model;
|
const _transform = R.merge(model.model._computeTransform, transform);
|
this._setTilesetTransform(tileset, _transform);
|
this.fire(UI_CHANGE_EVENT);
|
return this;
|
}
|
|
_setTilesetTransform(tileset, transform) {
|
if (tileset instanceof Cesium.Cesium3DTileset && transform) {
|
tileset._root.transform = this.update3dtilesMaxtrix(transform);
|
this.zoom3dtiles(tileset, transform);
|
return true;
|
}
|
}
|
|
/**
|
* 模型绽放
|
* @param {*} tileset
|
* @param {*} transform
|
* @returns
|
*/
|
zoom3dtiles(tileset, transform) {
|
if (!tileset) return;
|
var scale = (transform.scale || 1) * 1;
|
|
tileset._root.customTransform = {
|
matrix: {
|
origin: tileset._root.transform.clone(),
|
rotation: Cesium.Matrix4.IDENTITY,
|
translation: Cesium.Matrix4.IDENTITY,
|
},
|
};
|
|
var m1 = Cesium.Matrix4.fromScale(
|
new Cesium.Cartesian3(scale, scale, scale)
|
);
|
tileset._root.customTransform.matrix.scale = m1;
|
tileset._root.customTransform.scale = scale;
|
var m2 = new Cesium.Matrix4();
|
Cesium.Matrix4.multiply(
|
tileset._root.customTransform.matrix.origin,
|
tileset._root.customTransform.matrix.rotation,
|
m2
|
);
|
Cesium.Matrix4.multiply(m2, tileset._root.customTransform.matrix.scale, m2);
|
Cesium.Matrix4.multiply(
|
m2,
|
tileset._root.customTransform.matrix.translation,
|
tileset._root.transform
|
);
|
}
|
|
update3dtilesMaxtrix(params) {
|
var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
|
var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
|
var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
|
var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
|
var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
|
var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
|
//平移
|
var position = Cesium.Cartesian3.fromDegrees(
|
params.tx,
|
params.ty,
|
params.tz
|
);
|
var m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
|
//旋转、平移矩阵相乘
|
Cesium.Matrix4.multiply(m, rotationX, m);
|
Cesium.Matrix4.multiply(m, rotationY, m);
|
Cesium.Matrix4.multiply(m, rotationZ, m);
|
return m;
|
}
|
|
//设置模型位置
|
setModelPosition(tileset, lon, lat, alt) {
|
tileset._modelLon = lon || tileset._modelLon;
|
tileset._modelLat = lat || tileset._modelLat;
|
tileset._modelAlt = Cesium.defined(alt) ? alt : tileset._modelAlt;
|
//平移
|
let position = Cesium.Cartesian3.fromDegrees(
|
tileset._modelLon,
|
tileset._modelLat,
|
tileset._modelAlt
|
);
|
let m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
|
//赋值给tileset
|
tileset._root.transform = m;
|
}
|
|
/**
|
* 根据模型ID删除模型
|
* @param {String} id 模型ID
|
* @return this
|
*/
|
removeModel(id) {
|
const model = this.models.filter(d => d.id === id)[0];
|
if (model && model.model) {
|
if (
|
model.model instanceof Cesium.Cesium3DTileset &&
|
this.tileModelCollection.contains(model.model)
|
) {
|
this.tileModelCollection.remove(model.model);
|
}
|
this.models = this.models.filter(d => d.id !== id);
|
}
|
return this;
|
}
|
|
/**
|
* 设置模型可见度
|
* @param {String} id 模型ID
|
* @param {Boolean} visible 可见性
|
* @return this
|
*/
|
setModelVisible(id, visible) {
|
const model = this.models.filter(d => d.id === id)[0];
|
if (model && model.model) {
|
if (model.model instanceof Cesium.Cesium3DTileset) {
|
model.model.show = visible;
|
}
|
for (let i = 0; i < this.models.length; i++) {
|
let md = this.models[i];
|
if (md.id === model.id) {
|
md.visible = visible;
|
}
|
}
|
}
|
return this;
|
}
|
|
/**
|
* 获取视图中心值
|
* @return {Object} {x, y, z, heading, roll, pitch}
|
*/
|
getViewPoint() {
|
const viewer = this.viewer;
|
return wutu3d.point.getCameraView(viewer, true);
|
}
|
|
/**
|
* 设置视图中心
|
* @param {Object} viewpoint {x, y, z, heading, roll, pitch}
|
*/
|
setViewpoint(viewpoint, options) {
|
if (viewpoint) {
|
this.viewer.wutu3d.centerAt(viewpoint, options);
|
}
|
}
|
|
/**
|
* 初始化视图控制器
|
* @private
|
* @param {String|HTMLElement} container 地图DIV容器
|
* @return {Cesium.Viewer}
|
*/
|
_initViewer(container) {
|
const {
|
sceneModePicker,
|
vrButton,
|
baseLayerPicker,
|
fullscreenButton,
|
navigationHelpButton,
|
imageryProvider,
|
homeButton,
|
currentTime,
|
} = this.option;
|
let viewer = new Cesium.Viewer(container || 'map', {
|
geocoder: false,
|
homeButton: homeButton,
|
sceneModePicker: sceneModePicker,
|
fullscreenButton: fullscreenButton,
|
vrButton: vrButton,
|
baseLayerPicker: baseLayerPicker,
|
infoBox: false,
|
selectionIndicator: false,
|
animation: false,
|
timeline: false,
|
shouldAnimate: true,
|
clockViewModel: currentTime ? getClockViewModel(currentTime) : undefined,
|
navigationHelpButton: navigationHelpButton,
|
navigationInstructionsInitiallyVisible: false,
|
imageryProvider:
|
imageryProvider ||
|
new Cesium.SingleTileImageryProvider({
|
url: SINGLE_MAP_IMAGE,
|
}),
|
contextOptions: {
|
webgl: {
|
alpha: true,
|
},
|
},
|
...this.option,
|
dataSources: undefined,
|
});
|
|
viewer.wutu3d = new wutu3d.ViewerEx(viewer, {
|
contextmenu: false,
|
center: this.option.viewpoint || undefined,
|
mouseZoom: false,
|
contextmenuItems: [],
|
});
|
|
return viewer;
|
}
|
|
_plusEntity(entity) {
|
if (!entity) return;
|
let attr = entity.attribute && entity.attribute.attr;
|
let style =
|
entity.attribute && (entity.attribute.style || (attr && attr.style));
|
if (entity.billboard) {
|
entity.billboard.translucencyByDistance = undefined;
|
entity.billboard.disableDepthTestDistance = Number.POSITIVE_INFINITY;
|
entity.billboard.eyeOffset = new Cesium.Cartesian3(0, 0, -10);
|
}
|
if (entity.label) {
|
entity.label.translucencyByDistance = undefined;
|
entity.label.disableDepthTestDistance = Number.POSITIVE_INFINITY;
|
entity.label.eyeOffset = new Cesium.Cartesian3(0, 0, -10);
|
}
|
if (style && attr && attr.animateLine) {
|
entity.polyline.material = new wutu3d.LineFlowMaterial({
|
//动画线材质
|
color: Cesium.Color.fromCssColorString(style.color || '#ff0000'),
|
duration: style.duration || 10000, //时长,控制速度
|
url: style.image || './images/texture/route.png',
|
});
|
}
|
if (style && attr && attr.wave) {
|
entity.ellipse.material = new wutu3d.CircleWaveMaterial({
|
duration: style.duration, //动画时长,单位:毫秒
|
color: Cesium.Color.fromCssColorString(style.color),
|
gradient: style.gradient || 0,
|
count: style.count || 2,
|
});
|
}
|
if (attr && attr.isBeam) {
|
const wgs84PosArr = this.plotDrawTool.getCoordinates(entity)[0];
|
this.beams.add(
|
attr.id || entity.id,
|
{ x: wgs84PosArr[0], y: wgs84PosArr[1] },
|
style
|
);
|
}
|
}
|
|
deltePlotsByKeyValues(queryObject) {
|
const entites = this.queryPlotsByKeyValues(queryObject);
|
entites.forEach(entity => {
|
entity && this.plotDrawTool.deleteEntity(entity);
|
});
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 查询绘制元素
|
* @param {Object} queryObject
|
* @returns
|
*/
|
queryPlotsByKeyValues(queryObject) {
|
let arrs = [];
|
const keys = Object.keys(queryObject);
|
const entities = this.plotDrawTool.getEntitys();
|
for (let i = 0; i < entities.length; i++) {
|
let entity = entities[i];
|
let attr = entity && entity.attribute && entity.attribute.attr;
|
let flag = true;
|
for (let j = 0; j < keys.length; j++) {
|
let key = keys[j];
|
if (attr[key] !== queryObject[key]) {
|
flag = false;
|
break;
|
}
|
}
|
if (flag) {
|
arrs.push(entity);
|
}
|
}
|
return arrs;
|
}
|
|
/**
|
* 查询元素
|
* @param {*} entities
|
* @param {*} queryObject
|
* @returns
|
*/
|
queryEntitiesByKeyValues(entities, queryObject) {
|
if (!queryObject) return [];
|
let arrs = [];
|
const keys = Object.keys(queryObject);
|
const array = entities._entities._array;
|
for (let i = 0; i < array.length; i++) {
|
let entity = array[i];
|
let attr = entity && entity.attribute;
|
if (!attr) {
|
continue;
|
}
|
let flag = true;
|
for (let j = 0; j < keys.length; j++) {
|
let key = keys[j];
|
if (attr[key] !== queryObject[key]) {
|
flag = false;
|
break;
|
}
|
}
|
if (flag) {
|
arrs.push(entity);
|
}
|
}
|
return arrs;
|
}
|
|
/**
|
* 删除元素
|
* @param {*} entities
|
* @param {*} queryObject
|
*/
|
deleteEntitiesByKeyValues(entities, queryObject) {
|
const targets = this.queryEntitiesByKeyValues(entities, queryObject);
|
targets.forEach(target => {
|
entities.remove(target);
|
});
|
}
|
|
/**
|
* 定位到图标上
|
* @param {*} queryObject
|
* @param {*} option
|
* @returns
|
*/
|
focusMarker(queryObject, option) {
|
if (!queryObject) return;
|
option = option || {};
|
const target = this.queryPlotsByKeyValues(queryObject)[0];
|
if (!target) return;
|
this.viewer.flyTo(target, {
|
duration: 0.5,
|
...option,
|
});
|
}
|
|
/**
|
* 定位到标绘上
|
* @param {*} option Cesium viewer flyTo Options
|
*/
|
flyToPlots(option) {
|
if (this.plotDrawTool.getEntitys().length > 0) {
|
this.viewer.flyTo(this.plotDrawTool.dataSource, {
|
duration: 1,
|
...option,
|
});
|
}
|
return this;
|
}
|
|
/**
|
* 开启编辑
|
* @param {Boolean} editable
|
*/
|
setPlotEditable(editable) {
|
const pt = this.plotDrawTool;
|
pt.hasEdit(editable);
|
if (!editable) {
|
pt.stopDraw();
|
pt.stopEditing();
|
}
|
}
|
|
/**
|
* 是否编辑中
|
*/
|
isPlotEditing() {
|
return this.plotDrawTool._hasEdit;
|
}
|
|
_addLabel(entity, option) {
|
if (!entity || !option || !option.text || !option.showLabel) return;
|
entity.label = new Cesium.LabelGraphics({
|
style: Cesium.LabelStyle.FILL,
|
pixelOffset: new Cesium.Cartesian2(0, (-64 - 10) * option.iconScale),
|
translucencyByDistance: undefined,
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
eyeOffset: new Cesium.Cartesian3(0, 0, -10),
|
showBackground: true,
|
font: '14px Microsoft yahei',
|
backgroundColor: new Cesium.Color(0.0, 0.0, 0.0, 0.8),
|
backgroundPadding: new Cesium.Cartesian2(8, 6),
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
...option,
|
});
|
}
|
|
/**
|
* 添加图标
|
* @param {Object} option
|
* @returns Cesium.Entity
|
*/
|
addMarker({ text, textStyle, showLabel, icon, iconStyle, attr, wgs84Pos }) {
|
if (!wgs84Pos || !checkWgs84Point(wgs84Pos.x, wgs84Pos.y)) return null;
|
attr = attr || {};
|
showLabel = showLabel === undefined ? true : showLabel;
|
iconStyle = iconStyle || {};
|
const ops = {
|
type: 'billboard',
|
style: {
|
image: icon,
|
...iconStyle,
|
},
|
attr: { id: attr.mac || undefined, type: 'marker', ...attr },
|
};
|
const position = Cesium.Cartesian3.fromDegrees(wgs84Pos.x, wgs84Pos.y);
|
let entity = this.plotDrawTool.attributeToEntity(ops, position);
|
entity.billboard.disableDepthTestDistance = Number.POSITIVE_INFINITY;
|
entity.billboard.eyeOffset = new Cesium.Cartesian3(0, 0, -10);
|
this._addLabel(entity, {
|
showLabel,
|
text,
|
...textStyle,
|
iconScale: iconStyle.scale || 0.5,
|
});
|
this._plusEntity(entity);
|
this.fire(UI_CHANGE_EVENT);
|
return entity;
|
}
|
|
/**
|
* 添加面
|
* @param {Object} option
|
* @returns Cesium.Entity
|
*/
|
addPolygon({ style, attr, wgs84Poss }) {
|
style = style || {};
|
wgs84Poss = wgs84Poss || [];
|
const positions = wgs84Poss.map(wgs84Pos => {
|
let point = wgs84Pos;
|
if (isArray(wgs84Pos)) {
|
point = {
|
x: wgs84Pos[0],
|
y: wgs84Pos[1],
|
z: wgs84Pos[2],
|
};
|
}
|
return Cesium.Cartesian3.fromDegrees(point.x, point.y, point.z || 0);
|
});
|
const entity = this.plotDrawTool.attributeToEntity(
|
{
|
type: 'polygon',
|
style: {
|
...DrawOption.polygon,
|
...style,
|
},
|
attr: {
|
...(attr || {}),
|
},
|
},
|
positions
|
);
|
this._plusEntity(entity);
|
return entity;
|
}
|
|
/**
|
* 添加线
|
* @param {Object} option
|
* @returns Engity
|
*/
|
addPolyline({ attr, style, wgs84Poss }) {
|
style = style || {};
|
wgs84Poss = wgs84Poss || [];
|
const positions = wgs84Poss.map(wgs84Pos => {
|
let point = wgs84Pos;
|
if (isArray(wgs84Pos)) {
|
point = {
|
x: wgs84Pos[0],
|
y: wgs84Pos[1],
|
z: wgs84Pos[2],
|
};
|
}
|
return Cesium.Cartesian3.fromDegrees(point.x, point.y, point.z || 0);
|
});
|
const entity = this.plotDrawTool.attributeToEntity(
|
{
|
type: 'polyline',
|
style: {
|
...DrawOption.polyline,
|
...style,
|
},
|
attr: {
|
...(attr || {}),
|
},
|
},
|
positions
|
);
|
this._plusEntity(entity);
|
return entity;
|
}
|
|
/**
|
* 开始绘制
|
* @param {Object} drawOption 绘制参数,详见说明user.md
|
* @param {Function} callback 绘制完成时加回调
|
*/
|
startDraw(drawOption, callback) {
|
let option = {
|
success: entity => {
|
setEntityAttributes(entity, {
|
id: entity.id,
|
});
|
this._plusEntity(entity);
|
callback && callback(entity);
|
this.fire(UI_CHANGE_EVENT);
|
},
|
...drawOption,
|
};
|
this.plotDrawTool.startDraw(option);
|
}
|
|
/**
|
* 通过代码添加点位
|
* @param {Object} drawOption 绘制选项
|
* @param {Array} position 位置坐标
|
*/
|
createPlot(drawOption, position) {
|
if (
|
!drawOption ||
|
!drawOption.type ||
|
!drawOption.style ||
|
!position ||
|
position[0] === undefined ||
|
position.length < 2
|
)
|
return null;
|
var entity = this.plotDrawTool.attributeToEntity(
|
drawOption,
|
wutu3d.draw.util.lonlat2cartesian([
|
position[0],
|
position[1],
|
position[2] || 0,
|
])
|
);
|
setEntityAttributes(entity, {
|
id: entity.id,
|
});
|
this._plusEntity(entity);
|
return entity;
|
}
|
|
/**
|
* 获取对象
|
* @param {String} id 对象ID
|
*/
|
getPlotById(id) {
|
return this.plotDrawTool.getEntityById(id);
|
}
|
|
/**
|
* 更新对象样式
|
* @param {String} id 对象ID
|
* @param {Object} style 样式对象
|
*/
|
updatePlotStyle(id, style) {
|
if (!id || !style) return;
|
const entity = this.getPlotById(id);
|
if (!entity || !entity.attribute) return;
|
const attribute = entity.attribute;
|
let type = attribute.type;
|
if (type === 'circle') {
|
type = 'ellipse';
|
}
|
if (wutu3d.draw.attr[type]) {
|
wutu3d.draw.attr[type].style2Entity(style, entity[type]);
|
this._plusEntity(entity);
|
}
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 更新样式属性
|
* @param {String} id 对象ID
|
* @param {Object} attrs
|
*/
|
updatePlotAttribute(id, attrs) {
|
const entity = this.getPlotById(id);
|
setEntityAttributes(entity, attrs);
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 删除绘制对象
|
* @param {String} id 对象ID
|
*/
|
deletePlot(id) {
|
const entity = this.getPlotById(id);
|
entity && this.plotDrawTool.deleteEntity(entity);
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 加载GeoJSON
|
* @param {GeoJSON} geojson
|
*/
|
loadGeoJSON(geojson) {
|
this.plotDrawTool.loadJson(geojson);
|
const entities = this.plotDrawTool.getEntitys();
|
for (let i = 0; i < entities.length; i++) {
|
this._plusEntity(entities[i]);
|
}
|
setTimeout(() => {
|
this.fire(UI_CHANGE_EVENT);
|
}, 1000);
|
}
|
|
/**
|
* 将绘制对象转为Geojson数据
|
*/
|
toGeoJSON() {
|
return this.plotDrawTool.toGeoJSON();
|
}
|
|
// 清除所有绘制对象
|
clearAllPlots() {
|
let pt = this.plotDrawTool;
|
pt.stopEditing();
|
pt.clearDraw();
|
pt.deleteAll();
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
addFence(geojson, option) {
|
if (!geojson || !geojson.features) return;
|
if (!this.fenceDataSource) {
|
const dataSource = (this.fenceDataSource = new Cesium.CustomDataSource(
|
'fence'
|
));
|
dataSource.show = true;
|
this.viewer.dataSources.add(dataSource);
|
}
|
option = option || {};
|
|
const color = option.color || '#ff9900';
|
const height = option.height || 50.0;
|
const showDynamic = option.showDynamic;
|
|
let dataSource = this.fenceDataSource;
|
geojson.features.forEach(feature => {
|
const coordinates = feature.geometry.coordinates[0][0];
|
let positions = [];
|
coordinates.forEach(c => {
|
let position = Cesium.Cartesian3.fromDegrees(c[0], c[1], c[2] || 0.5);
|
positions.push(position);
|
});
|
dataSource.fence = new Fence(
|
dataSource,
|
positions,
|
height,
|
Cesium.Color.fromCssColorString(color),
|
showDynamic
|
);
|
});
|
return this.fenceDataSource;
|
}
|
|
rain(enable) {
|
if (enable) {
|
this.rainPost = new Cesium.PostProcessStage({
|
fragmentShader: wutu3d.scene.RainFS,
|
});
|
this.viewer.scene.postProcessStages.add(this.rainPost);
|
} else {
|
this.rainPost &&
|
this.viewer.scene.postProcessStages.remove(this.rainPost);
|
}
|
}
|
|
snow(enable) {
|
if (enable) {
|
this.snowPost = new Cesium.PostProcessStage({
|
fragmentShader: wutu3d.scene.SnowFS,
|
});
|
this.viewer.scene.postProcessStages.add(this.snowPost);
|
} else {
|
this.snowPost &&
|
this.viewer.scene.postProcessStages.remove(this.snowPost);
|
}
|
}
|
|
/**
|
* 获取屏幕中心点三维坐标
|
* @return {Cesium.Cartesian3}
|
*/
|
getScreenCenterPosition() {
|
const { scene, canvas, camera } = this.viewer;
|
const screenPosition = new Cesium.Cartesian2(
|
canvas.width / 2,
|
canvas.height / 2
|
);
|
return scene.globe.pick(camera.getPickRay(screenPosition), scene);
|
}
|
|
_getRomaPathGeometry(roma) {
|
const { path } = roma || {};
|
if (!path || !path.length) return null;
|
const coordinates = path.map(p => p.concat(0.5));
|
return {
|
type: 'FeatureCollection',
|
features: [
|
{
|
type: 'Feature',
|
properties: {
|
type: 'polyline',
|
style: {
|
width: 6,
|
color: 'rgba(255, 255, 0, 0.1)',
|
},
|
},
|
geometry: {
|
type: 'LineString',
|
coordinates: coordinates,
|
},
|
},
|
],
|
};
|
}
|
|
_startDrawRoma(title, callback) {
|
this.stopRoma();
|
const tool = this._romaTool;
|
tool.deleteAll();
|
tool.startDraw({
|
type: 'polyline',
|
style: {
|
width: 6,
|
lineType: 'solid',
|
color: '#ff0000',
|
},
|
success: entity => {
|
const path = tool.toGeoJSON();
|
const _path = path.features[0].geometry.coordinates.map(d =>
|
d.slice(0, 2)
|
);
|
// {id:2, title: "漫游路线2", height:1.5, path: [], speed:1, x: 0, y:0, z:0, type: "gs"},
|
this.addRoma({
|
title: title || '漫游线路' + this.romas.length,
|
path: _path,
|
speed: 1,
|
type: 'dy',
|
height: 1.7,
|
});
|
callback && callback();
|
this.fire(UI_CHANGE_EVENT);
|
},
|
});
|
}
|
|
setRomas(romas) {
|
this.romas = romas;
|
this.fire(UI_CHANGE_EVENT);
|
return this;
|
}
|
|
addRoma({ title, path, speed, x, y, z, type }) {
|
this.romas.push({
|
id: Cesium.createGuid(),
|
title,
|
path,
|
speed,
|
x,
|
y,
|
z,
|
type,
|
});
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 移除漫游
|
* @param {*} id
|
*/
|
removeRoma(id) {
|
if (id) {
|
if (id === this._currentRoma) {
|
this.stopRoma();
|
}
|
this.romas = this.romas.filter(d => d.id !== id);
|
}
|
this.fire(UI_CHANGE_EVENT);
|
return this;
|
}
|
|
/**
|
* 播放漫游
|
* @param {*} id
|
*/
|
playRoma(id, showPath) {
|
const roma = this.romas.filter(d => d.id === id)[0];
|
if (!roma) return;
|
this.stopRoma();
|
const path = this._getRomaPathGeometry(roma);
|
if (!path) return;
|
if (showPath) {
|
this._romaTool.loadJson(path);
|
}
|
this._currentRoma = roma.id;
|
var flyDataPoints = path.features[0].geometry.coordinates.map(d => {
|
return [d[0], d[1], 1.5];
|
});
|
var flydata = {
|
name: 'plan1',
|
interpolation: false, //是否setInterpolationOptions插值
|
clockLoop: true, //是否循环播放
|
// dy 第一视角, gs 跟随
|
camera: {
|
type: 'dy',
|
followedX: 5,
|
followedZ: 0.5,
|
},
|
points: flyDataPoints,
|
// "clampToGround": true,
|
speed: 16, // km/h
|
};
|
this._romaFlyline = new wutu3d.FlyLine(this.viewer, flydata);
|
this._romaFlyline.start();
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 停止漫游
|
*/
|
stopRoma() {
|
if (this._romaFlyline) {
|
this._romaFlyline.stop();
|
}
|
this._currentRoma = null;
|
this.fire(UI_CHANGE_EVENT);
|
}
|
|
/**
|
* 开启或关闭阴影
|
* @param {Boolean} enable
|
*/
|
setShadows(enable) {
|
this.viewer.scene.globe.enableLighting = enable;
|
this.viewer.shadows = enable;
|
}
|
|
// 开始日照模拟
|
startClockMock(speed) {
|
speed = speed || 1;
|
const viewer = this.viewer;
|
// 起始时间
|
var start = new Cesium.JulianDate();
|
// 结束时间
|
var stop = Cesium.JulianDate.addSeconds(
|
start,
|
86400,
|
new Cesium.JulianDate()
|
);
|
// 设置始时钟始时间
|
viewer.clock.startTime = start.clone();
|
// 设置时钟当前时间
|
viewer.clock.currentTime = start.clone();
|
// 设置始终停止时间
|
viewer.clock.stopTime = stop.clone();
|
viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER;
|
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
|
// 时间速率,数字越大时间过的越快
|
viewer.clock.multiplier = speed * 9000;
|
viewer.clock.shouldAnimate = true;
|
return this;
|
}
|
|
// 停止日照模拟
|
stopClockMock() {
|
const viewer = this.viewer;
|
// 起始时间
|
var start = new Cesium.JulianDate();
|
// 结束时间
|
var stop = Cesium.JulianDate.addDays(start, 1, new Cesium.JulianDate());
|
// 设置始时钟始时间
|
viewer.clock.startTime = start.clone();
|
// 设置时钟当前时间
|
viewer.clock.currentTime = start.clone();
|
// 设置始终停止时间
|
viewer.clock.stopTime = stop.clone();
|
viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER;
|
viewer.clock.clockRange = Cesium.ClockRange.UNBOUNDED;
|
// 时间速率,数字越大时间过的越快
|
viewer.clock.multiplier = 1;
|
viewer.clock.shouldAnimate = false;
|
return this;
|
}
|
|
// 设置视点
|
setViewPoints(viewPoints) {
|
this.viewPoints = viewPoints || [];
|
}
|
|
addViewPoint({ title } = {}) {
|
this.viewPoints.push({
|
id: Cesium.createGuid(),
|
title: title,
|
viewPoint: this.getViewPoint(),
|
});
|
}
|
|
removeViewPoint(id) {
|
this.viewPoints = this.viewPoints.filter(v => v.id !== id);
|
}
|
|
focusViewPoint(id) {
|
const viewPoint = this.viewPoints.filter(v => v.id === id)[0];
|
if (!viewPoint) return;
|
this.flyToViewPoint(viewPoint.viewPoint);
|
}
|
|
destroy() {
|
this.measureTool.clearMeasure();
|
this.clearAllPlots();
|
this.removeModels();
|
// this.viewer.destroy();
|
// this.viewer = null;
|
// this.fire(UI_CHANGE_EVENT);
|
}
|
}
|