Cesium 轨迹巡航效果
话不多说,先上图!

在这篇文章中,我将分享如何使用 Cesium 实现一个动态的无人机巡航轨迹效果。通过该功能,我们可以模拟无人机沿着指定路径飞行,并实时展示其位置、速度、高度等信息。以下是功能的详细介绍和实现过程。
实现思路
-
路径绘制:
-
动态飞行:
-
状态更新:
核心代码
以下是实现无人机巡航轨迹的核心代码片段:
1. 路径绘制
const positions = [];
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 鼠标左键点击添加路径点
handler.setInputAction(function (movement) {
const cartesian = viewer.scene.pickPosition(movement.position);
if (cartesian) {
positions.push(cartesian);
if (positions.length >= 2) {
drawPolyline(positions);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 绘制路径
function drawPolyline(positions) {
viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(() => positions, false),
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.YELLOW
}),
width: 10,
clampToGround: true
}
});
}
2. 动态飞行
const sampledPosition = new Cesium.SampledPositionProperty();
const start = Cesium.JulianDate.fromDate(new Date());
const stop = Cesium.JulianDate.addSeconds(start, 60, new Cesium.JulianDate());
// 添加路径点和时间点
positions.forEach((position, index) => {
const time = Cesium.JulianDate.addSeconds(start, index * 10, new Cesium.JulianDate());
sampledPosition.addSample(time, position);
});
// 添加无人机模型
viewer.entities.add({
position: sampledPosition,
orientation: new Cesium.VelocityOrientationProperty(sampledPosition),
model: {
uri: "/GroundVehicle.glb",
scale: 1.0
}
});
// 设置时间范围
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
viewer.clock.multiplier = 10;
3. 状态更新
function updateStatus(time) {
const position = sampledPosition.getValue(time);
const cartographic = Cesium.Cartographic.fromCartesian(position);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
console.log(`经度: ${longitude}, 纬度: ${latitude}, 高度: ${height}`);
}
viewer.clock.onTick.addEventListener(updateStatus);
完整代码
📄 dynamicObject.js
import core from "./Core.js";
import getPosition from "./getPosition.js";
/**
* 创建浏览对象。
* @constructor xp
* @time 2022-12-25
* @param {*} viewer
* @param {*} cesium
*/
function dynamicObject(viewer, cesium) {
this._viewer = viewer;
this._cesium = cesium;
this._core = new core();
this._getPosition = new getPosition(this._viewer, this._cesium);
this._entityFly = null;
}
/**
* 这个方法用于创建浏览对象
* @returns {Promise.<Object>} 返回一个Cesium的对象。
*
*/
// var ploylinejl = {
// polyline: {},
// cameraRoll: null,
// cameraPitch: null,
// cameraPosition: null,
// cameraHeading: null,
// positions: [],
// distance: [],
// Totaltime: "",
// dsq: null
// };
dynamicObject.prototype.executeFlycesium = function (method) {
//设置浏览路径
// var polylines = {};
var _this = this;
var PolyLinePrimitive = (function () {
function execute(positions) {
this.options = {
polyline: {
show: true,
positions: [],
material: new _this._cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: _this._cesium.Color.YELLOW
}),
width: 10,
clampToGround: true
}
};
this.positions = positions;
this._init();
}
execute.prototype._init = function () {
var _self = this;
var _update = function () {
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new _this._cesium.CallbackProperty(
_update,
false
);
this.flycesium = _this._viewer.entities.add(this.options);
_this.item = this.flycesium;
};
return execute;
})();
var handler = (this.handler = new _this._cesium.ScreenSpaceEventHandler(
_this._viewer.scene.canvas
));
var positions = [];
// var flyceium = null;
var distance = 0;
var poly = undefined;
var ploylinejl = {
polyline: {},
cameraRoll: null,
cameraPitch: null,
cameraPosition: null,
cameraHeading: null,
positions: [],
distance: [],
Totaltime: ""
};
//导入tool提示框
var tooltip = this._core.CreateTooltip();
//设置鼠标样式
this._core.mouse(this._viewer.container, 1, window.SmartEarthRootUrl);
handler.setInputAction(function (movement) {
var cartesian = _this._getPosition.getMousePosition(movement);
if (_this._core.getBrowser().pc === "pc" && positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
if (positions.length >= 2) {
if (!_this._cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
}
distance = _this._core.getSpaceDistancem(positions, _this._cesium);
}
}, this._cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动
handler.setInputAction(function (movement) {
tooltip.showAt(movement.endPosition, "左键开始,右键结束!");
var cartesian = _this._getPosition.getMousePosition(movement);
if (positions.length >= 2) {
if (!_this._cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
} else {
if (cartesian) {
positions.pop();
//cartesian.y += (1 + Math.random());
positions.push(cartesian);
}
}
distance = _this._core.getSpaceDistancem(positions, _this._cesium);
}
}, this._cesium.ScreenSpaceEventType.MOUSE_MOVE);
//单击鼠标右键结束画线
handler.setInputAction(function () {
_this.end();
}, this._cesium.ScreenSpaceEventType.RIGHT_CLICK);
this.end = function (type) {
handler.destroy();
tooltip.show(false);
//设置鼠标样式
_this._core.mouse(_this._viewer.container, 0);
_this.end = undefined;
_this._viewer.entities.remove(_this.item);
if (type === "cancel" || positions.length < 2) {
return;
}
distance = _this._core.getSpaceDistancem(positions, _this._cesium);
ploylinejl.polyline = poly;
ploylinejl.positions = positions;
ploylinejl.distance = parseFloat(distance);
//转化成浏览对象
_this.setFlycesium(ploylinejl, function (flyceium) {
_this.flyceium = flyceium;
_this.ploylinejl = ploylinejl;
if (typeof method == "function") {
method(flyceium);
}
});
};
return this;
};
/**
* 设置获取浏览对象
*/
dynamicObject.prototype.setFlycesium = function (drawHelper, callback) {
var _this = this;
var coordinates = [];
// var position = null;
// var heading = null;
// var pitch = null;
// var roll = null;
var maxHeight = 0;
for (var i = 0; i < drawHelper.positions.length; i++) {
var cartographic = _this._cesium.Cartographic.fromCartesian(
drawHelper.positions[i]
); //世界坐标转地理坐标(弧度)
var point = [
(cartographic.longitude / Math.PI) * 180,
(cartographic.latitude / Math.PI) * 180,
cartographic.height
]; //地理坐标(弧度)转经纬度坐标
//console.log(point);
coordinates.push(point);
}
this._core.getPmfxPro(
drawHelper.positions,
25,
0,
_this._cesium,
_this._viewer,
data => {
maxHeight = data.max;
var time;
time = (drawHelper.distance / 50).toFixed(1);
var pathsData = {
id: _this._core.getuid(),
name: "新建路线",
distance: drawHelper.distance,
showPoint: false,
showLine: true,
showModel: true,
isLoop: false,
Totaltime: Math.round(time),
speed: 50,
height: (maxHeight + 200).toFixed(2),
pitch: -20,
range: 100,
mode: 0,
url: "/GroundVehicle.glb",
geojson: {
// orientation: {heading: heading, pitch: pitch, roll: roll},
// position: position,
geometry: { type: "LineString", coordinates: coordinates }
}
};
callback && callback(pathsData);
}
);
};
/**
* 开始浏览
*/
dynamicObject.prototype.Start = function (data, url, funs) {
var _this = this;
// var pathsData = data.geojson;
if (!data.Totaltime) {
data.Totaltime = 3000;
}
if (_this._entityFly) {
_this.exit();
}
// _this._viewer.camera.setView({
// destination: pathsData.position,
// orientation: pathsData.orientation,
// });
fun = funs;
setTimeout(function () {
_this.executeFly3D(data, url);
}, 200);
return this;
};
var entityFly = null;
var entityModel = null;
//var start;
var fun = null;
var entityhd = {
start: null,
time: null,
longitude: 0,
latitude: 0,
cameraHeight: 100,
//timedifference: null,
speed: 50,
multiplier: 1,
position: 0
};
// var stop;
var velocityVector, velocityVectorProperty, velocityOrientationProperty;
var AngleProperty, property;
var wheelAngle = 0;
/**
* 播放路径动画
* @param {Object} data 数据
* @param {Object} data.geojson 路线数据
* @param {Number} [data.lineHeight] 路线高度,默认贴地
* @param {Boolean} [data.isLoop=false] 是否循环播放
* @param {String} [url] 模型路径
*/
dynamicObject.prototype.executeFly3D = function (data, url) {
var _this = this;
var pathsData = data.geojson;
velocityVector = new _this._cesium.Cartesian3();
AngleProperty = new _this._cesium.SampledProperty(Number);
property = new _this._cesium.SampledPositionProperty();
if (pathsData && pathsData.geometry) {
var positionA = pathsData.geometry.coordinates;
var position = [];
var position1 = [];
if (positionA.length > 0) {
for (var i = 0; i < positionA.length; i++) {
var x = positionA[i][0];
var y = positionA[i][1];
var z = positionA[i][2];
data.lineHeight !== void 0 && (z = data.lineHeight);
position1.push(x, y, z);
position.push({ x: x, y: y, z: z });
}
} else {
return;
}
_this._viewer.clock.clockRange = data.isLoop
? _this._cesium.ClockRange.LOOP_STOP
: _this._cesium.ClockRange.CLAMPED; //Loop at the end
_this._viewer.clock.multiplier = data.multiplier || 1;
_this._viewer.clock.canAnimate = false;
_this._viewer.clock.shouldAnimate = true; //设置时间轴动态效果
entityhd.distance = data.distance;
entityhd.cameraHeight = data.height;
entityhd.lineHeight = data.lineHeight;
entityhd.pitch = data.pitch;
entityhd.range = data.range;
entityhd.speed = data.speed || 50;
entityhd.Totaltime = data.distance / entityhd.speed;
entityhd.start = _this._cesium.JulianDate.fromDate(new Date());
entityhd.stop = _this._cesium.JulianDate.addSeconds(
entityhd.start,
entityhd.Totaltime,
new _this._cesium.JulianDate()
);
//Make sure viewer is at the desired time.
_this._viewer.clock.startTime = entityhd.start.clone();
_this._viewer.clock.stopTime = entityhd.stop.clone();
_this._viewer.clock.currentTime = entityhd.start.clone();
var _position = _this.computeCirclularFlight(position);
entityhd.position = _position;
entityhd.degrees = position;
velocityOrientationProperty = new _this._cesium.VelocityOrientationProperty(
_position
);
var mode = {};
if (url !== "") {
mode = {
show: _this._cesium.defaultValue(data.showModel, true),
scale: _this._cesium.defaultValue(data.modelScale, 1),
uri: url
};
} else {
// const modelUrl = Cesium.buildModuleUrl(
// "Assets/GltfModels/CesiumAir/Cesium_Air.glb"
// );
mode = {
show: _this._cesium.defaultValue(data.showModel, true),
scale: _this._cesium.defaultValue(data.modelScale, 1)
// uri: modelUrl
};
}
if (data.modelData) {
mode = _this._core.extend(mode, data.modelData);
}
changeFlyView = function () {};
entityFly = _this._viewer.entities.add({
//Set the entity availability to the same interval as the simulation time.
availability: new _this._cesium.TimeIntervalCollection([
new _this._cesium.TimeInterval({
start: entityhd.start,
stop: entityhd.stop
})
]),
position: _position,
//Show the path as a pink line sampled in 1 second increments.
polyline: {
clampToGround: entityhd.lineHeight === void 0,
positions: Cesium.Cartesian3.fromDegreesArrayHeights(position1),
show: _this._cesium.defaultValue(data.showLine, true),
material: new _this._cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: _this._cesium.Color.YELLOW
}),
width: 10
},
label: {
text: new _this._cesium.CallbackProperty(updateSpeedLabel, false),
font: "20px sans-serif",
showBackground: false,
distanceDisplayCondition: new _this._cesium.DistanceDisplayCondition(
0.0,
100.0
),
eyeOffset: new _this._cesium.Cartesian3(0, 3.5, 0)
}
});
// console.log(_position);
entityModel = _this._viewer.entities.add({
availability: new _this._cesium.TimeIntervalCollection([
new _this._cesium.TimeInterval({
start: entityhd.start,
stop: entityhd.stop
})
]),
position: _position,
orientation: velocityOrientationProperty,
point: {
show: _this._cesium.defaultValue(data.showPoint, false),
color: _this._cesium.Color.RED,
outlineColor: _this._cesium.Color.WHITE,
outlineWidth: 2,
pixelSize: 10
},
model: mode,
billboard: data.image,
viewFrom:
data.viewFrom || new _this._cesium.Cartesian3(500.0, 500.0, 500.0)
});
entitymodels = entityFly;
_this._viewer.trackedEntity = entityModel;
_this._entityFly = entityFly;
data.mode && _this.changeFlyMode(data.mode);
// setTimeout(function () {
// // _this._viewer.camera.zoomOut(500.0);//缩小地图,避免底图没有数据
// _this._viewer.camera.zoomOut(300.0);//缩小地图,避免底图没有数据
// }, 100);
} else {
return;
}
function updateSpeedLabel(time) {
//alert(time);
//entityhd.time = time;
// var de = entitymodels;
// var camera = _this._viewer.camera;
if (
_this._viewer.clock.clockRange !== 2 &&
Cesium.JulianDate.equals(
_this._viewer.clock.currentTime,
_this._viewer.clock.stopTime
)
) {
entityFly.label.text = "";
_this.exit();
if (fun != null && typeof fun === "function") {
fun("end");
}
changeFlyView = function () {};
return;
}
try {
var position = entitymodels.position.getValue(
_this._viewer.clock.currentTime
);
var cartographic = _this._cesium.Cartographic.fromCartesian(position);
//经度
entityhd.longitude = _this._cesium.Math.toDegrees(cartographic.longitude);
//纬度
entityhd.latitude = _this._cesium.Math.toDegrees(cartographic.latitude);
if (entityhd.lineHeight === void 0) {
let height1 = _this._viewer.scene.sampleHeight(cartographic, [
entityModel,
entitymodels
]);
let height2 = _this._viewer.scene.globe.getHeight(cartographic);
entityModel.position = _this._cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
height2 > height1 ? height2 : height1
);
}
} catch (er) {
console.log(er);
}
try {
velocityVectorProperty.getValue(time, velocityVector);
changeFlyView(time);
var metersPerSecond = _this._cesium.Cartesian3.magnitude(velocityVector);
var kmPerHour = Math.round(metersPerSecond * 3.6);
kmPerHour += " km/h";
//已漫游时间
entityhd.time = _this._cesium.JulianDate.secondsDifference(
time,
entityhd.start
);
//已漫游比例
entityhd.ratio = entityhd.time / entityhd.Totaltime;
//已漫游距离
entityhd.distanceTraveled = entityhd.ratio * entityhd.distance;
//运行速度
entityhd.speed = kmPerHour;
//漫游高程
entityhd.height = cartographic.height;
//地面高程
entityhd.globeHeight = _this._viewer.scene.globe.getHeight(cartographic);
if (fun != null && typeof fun === "function") {
fun(entityhd);
}
} catch (er) {
console.log(er);
}
return "";
}
};
// var hpr = new Cesium.HeadingPitchRoll();
var flyPosition;
// var Quaternion = new Cesium.Quaternion();
// var _heading = 0;
var entitymodels = null;
//改变视角
var changeFlyView;
function getHeading(time) {
wheelAngle = AngleProperty.getValue(time);
entityhd.heading = wheelAngle;
}
function getFlyPosition(position) {
var cartographic = Cesium.Cartographic.fromCartesian(position);
var lon = Cesium.Math.toDegrees(cartographic.longitude);
var lat = Cesium.Math.toDegrees(cartographic.latitude);
return Cesium.Cartesian3.fromDegrees(lon, lat, entityhd.cameraHeight || 100);
}
/**
* 显示点
*/
dynamicObject.prototype.showPoint = function (isShow) {
entityModel && entityModel.point && (entityModel.point.show = isShow);
};
/**
* 显示线
*/
dynamicObject.prototype.showLine = function (isShow) {
entityFly && entityFly.polyline && (entityFly.polyline.show = isShow);
};
/**
* 显示模型
*/
dynamicObject.prototype.showModel = function (isShow) {
entityModel && entityModel.model && (entityModel.model.show = isShow);
};
//飞行高度
dynamicObject.prototype.setFlyHeight = function (height) {
entityhd.cameraHeight = height;
};
//飞行距离
dynamicObject.prototype.setFlyDistance = function (distance) {
entityhd.range = distance;
};
//飞行俯仰角
dynamicObject.prototype.setFlyPitch = function (pitch) {
entityhd.pitch = pitch;
};
//飞行模式
dynamicObject.prototype.changeFlyMode = function (index) {
var _this = this;
switch (index) {
case 0:
changeFlyView = function () {};
_this.BindingModel(true);
break;
case 1:
this.BindingModel(false);
changeFlyView = function (time) {
getHeading(time);
_this.exeuteVisualAngle(
_this._cesium.Math.toRadians(entityhd.heading),
_this._cesium.Math.toRadians(entityhd.pitch),
entityhd.range
);
};
break;
case 2:
this.BindingModel(false);
changeFlyView = function (time) {
getHeading(time);
flyPosition = _this._entityFly.position.getValue(
_this._viewer.clock.currentTime
);
if (!flyPosition) return;
flyPosition = getFlyPosition(flyPosition);
_this._viewer.camera.setView({
destination: flyPosition,
orientation: {
heading: _this._cesium.Math.toRadians(entityhd.heading),
pitch: _this._cesium.Math.toRadians(-90),
roll: 0.0
}
});
};
break;
}
};
/**
* 加速
*/
dynamicObject.prototype.faster = function () {
this._viewer.animation.viewModel.faster();
};
/**
* 减速
*/
dynamicObject.prototype.slower = function () {
// 倍率减
this._viewer.animation.viewModel.slower();
};
/**
* 设置倍数
*/
dynamicObject.prototype.setMultiplier = function (multiplier) {
this._viewer.clock.multiplier = parseFloat(multiplier);
};
/**
* 是否暂停
*/
dynamicObject.prototype.isPause = function (isPause) {
var clockViewModel = this._viewer.clockViewModel;
clockViewModel.shouldAnimate = !isPause;
};
/**
* 结束飞行
*/
dynamicObject.prototype.exit = function () {
this.isPause(true);
this._viewer.clock.multiplier = 1;
this.executeSignout();
this.BindingModel(false);
this._viewer.entities.remove(entityFly);
this._viewer.entities.remove(entityModel);
entityFly = null;
entityModel = null;
this._entityFly = null;
};
//lable回调函数
dynamicObject.prototype.updateSpeedLabel = function () {
//if (fun && typeof fun === 'function') {
// fun(_this._entityFly);
//}
//this.entityhd = {
// start: null,
// time: null
//};
//this.entityhd.time = time;
//if (this.fun != null && typeof fun === 'function') {
// fun(_this._entityFly);
//}
//return "";
};
//添加时间位置样本
dynamicObject.prototype.computeCirclularFlight = function (position) {
var _this = this;
velocityVectorProperty = new _this._cesium.VelocityVectorProperty(
property,
false
);
var _time, time, _position, _position1;
for (var i = 0; i < position.length; i++) {
if (i === 0) {
//起点
time = _this._cesium.JulianDate.addSeconds(
entityhd.start,
0,
new _this._cesium.JulianDate()
);
_position = _this._cesium.Cartesian3.fromDegrees(
position[0].x,
position[0].y,
entityhd.lineHeight
);
property.addSample(time, _position);
//计算两点方位角
wheelAngle = _this._core.TwoPointAzimuth(
position[0].x,
position[0].y,
position[1].x,
position[1].y
);
AngleProperty.addSample(time, wheelAngle);
}
try {
if (i > 0 && i != position.length - 1) {
_position = new _this._cesium.Cartesian3(
property._property._values[i * 3 - 3],
property._property._values[i * 3 - 2],
property._property._values[i * 3 - 1]
);
_position1 = _this._cesium.Cartesian3.fromDegrees(
position[i].x,
position[i].y,
_this._cesium.defaultValue(entityhd.lineHeight, position[i].z)
);
var positions = [
_this._cesium.Cartographic.fromCartesian(_position),
_this._cesium.Cartographic.fromCartesian(_position1)
];
var a = new _this._cesium.EllipsoidGeodesic(positions[0], positions[1]);
var long = a.surfaceDistance;
time = _this._cesium.JulianDate.addSeconds(
property._property._times[i - 1],
0.5,
new _this._cesium.JulianDate()
);
_time = _this._cesium.JulianDate.addSeconds(
property._property._times[i - 1],
long / entityhd.speed,
new _this._cesium.JulianDate()
);
property.addSample(_time, _position1);
//计算两点方位角
wheelAngle = _this._core.TwoPointAzimuth(
position[i - 1].x,
position[i - 1].y,
position[i].x,
position[i].y
);
AngleProperty.addSample(time, wheelAngle);
AngleProperty.addSample(_time, wheelAngle);
}
} catch (e) {
console.log(e);
}
}
return property;
};
/**
* 暂停浏览
*/
dynamicObject.prototype.executePauseFly3DPaths = function () {
var clockViewModel = this._viewer.clockViewModel;
if (clockViewModel.shouldAnimate) {
clockViewModel.shouldAnimate = false;
} else if (this._viewer.clockViewModel.canAnimate) {
clockViewModel.shouldAnimate = true;
}
};
/**
* 添加对象
*/
dynamicObject.prototype.changeModel = function (url) {
entityModel.model.uri = url;
};
//浏览方式飞向视点
/**
* 获取视野点
*/
dynamicObject.prototype.PointView = function () {
var originalCameraLocation = {
position: Viewer.camera.position.clone(),
orientation: {
heading: Viewer.camera.heading,
pitch: Viewer.camera.pitch,
roll: Viewer.camera.roll
}
};
return originalCameraLocation;
};
/**
* 开始浏览。
* @param {Paths}
* @returns {Object} 返回一个json对象。
*/
dynamicObject.prototype.PlayPaths = function () {
var that = this;
setInterval(function () {
viewer.camera.setView({
// Cesium的坐标是以地心为原点,一向指向南美洲,一向指向亚洲,一向指向北极州
// fromDegrees()方法,将经纬度和高程转换为世界坐标
destination: that._cesium.Cartesian3.fromDegrees(117.48, 30.67, 15000.0),
orientation: {
// 指向
heading: that._cesium.Math.toRadians(90, 0),
// 视角
pitch: that._cesium.Math.toRadians(-90),
roll: 0.0
}
});
}, 2000);
};
/**
* 绑定模型
* @param {binding} 是否绑定。
*/
dynamicObject.prototype.BindingModel = function (binding) {
if (binding) {
this._viewer.trackedEntity = entityModel;
} else {
this._viewer.trackedEntity = undefined;
this._viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}
};
/**
* 改变视角
* @returns {Object} 返回一个json对象。
*/
dynamicObject.prototype.exeuteVisualAngle = function (
viewHeading,
viewPitch,
viewRange
) {
var hpRange = { heading: null, pitch: null, range: null };
hpRange.heading = viewHeading || this._cesium.Math.toRadians(90);
hpRange.pitch = viewPitch || this._cesium.Math.toRadians(0);
hpRange.range = viewRange || 1000;
var center = this._entityFly.position.getValue(
this._viewer.clock.currentTime
);
if (!center) return;
center = getFlyPosition(center);
var hpRanges = new this._cesium.HeadingPitchRange(
hpRange.heading,
hpRange.pitch,
hpRange.range
);
//if (center) this._viewer.camera.lookAt(center, hpRange);
this._viewer.camera.lookAt(center, hpRanges);
};
/**
* 是否显示路线
* @returns {Object} 返回一个json对象。
*/
dynamicObject.prototype.Pathshow = function (route) {
this._entityFly.polyline.show = route;
};
/**
* 是否显示点
* @returns {Object} 返回一个json对象。
*/
dynamicObject.prototype.Pointshow = function (route) {
entityModel._point.show = route;
};
/**
* 是否显示模型
* @returns {Object} 返回一个json对象。
*/
dynamicObject.prototype.Modelshow = function (route) {
entityModel._model.show = route;
};
/**
* 向前飞行漫游路径
* @returns {Object} 返回一个json对象。
*/
dynamicObject.prototype.executePlayForwardFly3DPaths = function () {
var clockViewModel = this._viewer.clockViewModel;
var multiplier = clockViewModel.multiplier;
if (multiplier < 0) {
clockViewModel.multiplier = -multiplier;
}
clockViewModel.shouldAnimate = true;
};
/**
* 向后飞行漫游路径
*/
dynamicObject.prototype.executePlayReverseFly3DPaths = function () {
var clockViewModel = this._viewer.clockViewModel;
var multiplier = clockViewModel.multiplier;
if (multiplier > 0) {
clockViewModel.multiplier = -multiplier;
}
clockViewModel.shouldAnimate = true;
};
/**
* 退出飞行漫游路径
*/
dynamicObject.prototype.executeSignout = function () {
var start = this._cesium.JulianDate.fromDate(new Date());
this._viewer.clock.startTime = start.clone();
var stop = this._cesium.JulianDate.addSeconds(
start,
86400,
new this._cesium.JulianDate()
);
this._viewer.clock.stopTime = stop.clone();
//this.cesiumViewer.entities.remove(this.entityFly);
};
/**
* 结束当前操作
*/
dynamicObject.prototype.forceEndHanlder = function () {
if (this.handler) {
this.handler.destroy();
this.handler = undefined;
}
};
export default dynamicObject;
📄 Core.js
/**
* 工具类
* @constructor xp
* @alias Core
* @constructor
*
*/
function Core () { }
//根据经纬度获取高度
Core.prototype.getHeightsFromLonLat = function (
positions,
Cesium,
Viewer,
callback
) {
var camera = Viewer.camera;
var heights = [];
if (
Viewer.scene &&
Viewer.scene.terrainProvider &&
Viewer.scene.terrainProvider._layers
) {
//根据经纬度计算出地形高度。
var promise = Cesium.sampleTerrainMostDetailed(
Viewer.terrainProvider,
positions
);
// var cameraHeight = camera.positionCartographic.height;
Cesium.when(promise, function (updatedPositions) {
updatedPositions.forEach(function (item) {
heights.push(item.height);
});
if (typeof callback === "function") {
callback(heights);
}
});
} else {
positions.forEach(function (p) {
heights.push(Viewer.scene.globe.getHeight(p));
});
if (typeof callback === "function") {
callback(heights);
}
}
};
/**
* 创建鼠标Tooltip提示框。
*
* @param {*} [styleOrText] 提示框样式或文本内容
* @param {String} [styleOrText.origin='center'] 对齐方式(center/top/bottom)
* @param {String} [styleOrText.color='black'] 提示框颜色(black/white/yellow)
* @param {String} [styleOrText.id=undefined] 提示框唯一id(可选)
* @param {Object} position 显示位置
* @param {Boolean} show 是否显示(如果为true,styleOrText必须为显示的文本内容)
* @returns {Tooltip} Tooltip提示框。
*
* @example
* sgworld.Core.CreateTooltip('这里是提示信息', {x:500, y:500}, true);
* 或
* tooltip = sgworld.Core.CreateTooltip();
* tooltip.showAt({x:500, y:500}, '这里是提示信息');
*
* tooltip.show(false); //隐藏提示框
* tooltip.show(true); //显示提示框
*/
Core.prototype.CreateTooltip = function (styleOrText = {}, position, show) {
var style, _x, _y, _color, id;
if (typeof styleOrText === "object") {
style = styleOrText;
}
if (style && style.origin) {
style.origin === "center" && ((_x = 15), (_y = -12));
style.origin === "top" && ((_x = 15), (_y = -44));
style.origin === "bottom" && ((_x = 15), (_y = 20));
} else {
(_x = 15), (_y = 20);
}
if (style && style.color) {
style.color === "white" &&
(_color = "background: rgba(255, 255, 255, 0.8);color: black;");
style.color === "black" &&
(_color = "background: rgba(0, 0, 0, 0.5);color: white;");
style.color === "yellow" &&
(_color =
"color: black;background-color: #ffcc33;border: 1px solid white;");
} else {
_color = "background: rgba(0, 0, 0, 0.5);color: white;";
}
if (style && style.id) {
id = "toolTip" + style.id;
} else {
id = "toolTip";
}
var tooltip = document.getElementById(id);
if (!tooltip) {
// 创建一个新的 div 元素
var elementbottom = document.createElement("div");
// 将元素添加到 .cesium-viewer 容器中
var cesiumViewer = document.querySelector(".cesium-viewer");
if (cesiumViewer) {
cesiumViewer.appendChild(elementbottom);
}
// 构建 HTML 字符串
var html =
'<div id="' +
id +
'" style="display: none;pointer-events: none;position: absolute;z-index: 1000;opacity: 0.8;border-radius: 4px;padding: 4px 8px;white-space: nowrap;font-family:黑体;color:white;font-weight: bolder;font-size: 14px;' +
_color +
'"></div>';
// 创建一个临时容器来解析 HTML 字符串
var tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
// 将解析后的第一个子元素(即 tooltip)添加到 .cesium-viewer 容器中
if (cesiumViewer) {
cesiumViewer.appendChild(tempDiv.firstElementChild);
}
// 获取刚刚创建的 tooltip 元素
tooltip = document.getElementById(id);
}
if (show) {
tooltip.innerHTML = styleOrText;
tooltip.style.left = position.x + _x + "px";
tooltip.style.top = position.y + _y + "px";
tooltip.style.display = "block";
} else {
tooltip.style.display = "none";
}
return {
tooltip: tooltip,
style: style,
showAt: function (position, text) {
this.tooltip.innerHTML = text;
if (this.style && this.style.origin) {
this.style.origin === "center" &&
((_x = 15), (_y = -this.tooltip.offsetHeight / 2));
this.style.origin === "top" &&
((_x = 15), (_y = -this.tooltip.offsetHeight - 20));
this.style.origin === "bottom" && ((_x = 15), (_y = 20));
} else {
(_x = 15), (_y = -this.tooltip.offsetHeight / 2);
}
this.tooltip.style.left = position.x + _x + "px";
this.tooltip.style.top = position.y + _y + "px";
this.tooltip.style.display = "block";
},
show: function (show) {
if (show) {
this.tooltip.style.display = "block";
} else {
this.tooltip.style.display = "none";
}
}
};
};
/**
* 修改鼠标样式。
*
* @param {DOM} container html DOM节点
* @param {Number} [cursorstyle=0] 鼠标类型(0为默认,1为使用cur图标)
* @param {String} url cur图标路径。
*
* @example
* sgworld.Core.mouse(Viewer.container, 1, 'draw.cur');
*/
Core.prototype.mouse = function (container, cursorstyle, url) {
if (cursorstyle == 1) {
container.style.cursor = "url(" + url + "),auto";
} else {
container.style.cursor = "default";
}
};
// 判断是否为手机浏览器
Core.prototype.getBrowser = function () {
var ua = navigator.userAgent.toLowerCase();
var btypeInfo = (ua.match(/firefox|chrome|safari|opera/g) || "other")[0];
if ((ua.match(/msie|trident/g) || [])[0]) {
btypeInfo = "msie";
}
var pc = "";
var prefix = "";
var plat = "";
//如果没有触摸事件 判定为PC
var isTocuh =
"ontouchstart" in window ||
ua.indexOf("touch") !== -1 ||
ua.indexOf("mobile") !== -1;
if (isTocuh) {
if (ua.indexOf("ipad") !== -1) {
pc = "pad";
} else if (ua.indexOf("mobile") !== -1) {
pc = "mobile";
} else if (ua.indexOf("android") !== -1) {
pc = "androidPad";
} else {
pc = "pc";
}
} else {
pc = "pc";
}
switch (btypeInfo) {
case "chrome":
case "safari":
case "mobile":
prefix = "webkit";
break;
case "msie":
prefix = "ms";
break;
case "firefox":
prefix = "Moz";
break;
case "opera":
prefix = "O";
break;
default:
prefix = "webkit";
break;
}
plat =
ua.indexOf("android") > 0 ? "android" : navigator.platform.toLowerCase();
return {
version: (ua.match(/[\s\S]+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1], //版本
plat: plat, //系统
type: btypeInfo, //浏览器
pc: pc,
prefix: prefix, //前缀
isMobile: pc == "pc" ? false : true //是否是移动端
};
};
//空间距离测量用米
Core.prototype.getSpaceDistancem = function (positions, Cesium) {
var distance = 0;
for (var i = 0; i < positions.length - 1; i++) {
var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
var point2cartographic = Cesium.Cartographic.fromCartesian(
positions[i + 1]
);
/**根据经纬度计算出距离**/
var geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(point1cartographic, point2cartographic);
var s = geodesic.surfaceDistance;
//console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
//返回两点之间的距离
s = Math.sqrt(
Math.pow(s, 2) +
Math.pow(point2cartographic.height - point1cartographic.height, 2)
);
distance = distance + s;
}
return distance.toFixed(2);
};
//根据位置(Cartographic)获取3DTiles和Primitives高度
Core.prototype.get3DTileOrPrimitivesHeights = function (position, Viewer) {
return Viewer.scene.sampleHeight(position);
};
//剖面分析
Core.prototype.getPmfxPro = function (
_positions,
pointSum1,
cyjj,
Cesium,
viewer,
methond
) {
let _this = this;
//起止点相关信息
let pmx = {
gcs: [],
min: 99999,
max: 0,
juli: 0.0,
cys: 0
};
let positions = [];
let pointNum = [];
//获取总间隔点数和距离
for (let i = 0; i < _positions.length - 1; i++) {
let julifr = _this.getSpaceDistancem(
[_positions[i], _positions[i + 1]],
Cesium
);
julifr = parseFloat(julifr);
pmx.juli += julifr;
if (cyjj == 0) {
} else {
pointSum1 = parseInt(julifr / cyjj);
}
pointNum.push(pointSum1);
pmx.cys += pointSum1;
}
let startAnalyse = () => {
pointNum.forEach((num, i) => {
let startPoint = _positions[i];
let endPoint = _positions[i + 1];
//起点
let scartographic = Cesium.Cartographic.fromCartesian(startPoint);
let slongitude = Cesium.Math.toDegrees(scartographic.longitude);
let slatitude = Cesium.Math.toDegrees(scartographic.latitude);
//终点
let ecartographic = Cesium.Cartographic.fromCartesian(endPoint);
let elongitude = Cesium.Math.toDegrees(ecartographic.longitude);
let elatitude = Cesium.Math.toDegrees(ecartographic.latitude);
let pointSum = num; //取样点个数
let addXTT =
Cesium.Math.lerp(slongitude, elongitude, 1.0 / pointSum) - slongitude;
let addYTT =
Cesium.Math.lerp(slatitude, elatitude, 1.0 / pointSum) - slatitude;
let Cartesian;
i === 0 && positions.push(scartographic);
for (let j = 0; j < pointSum; j++) {
let longitude = slongitude + (j + 1) * addXTT;
let latitude = slatitude + (j + 1) * addYTT;
Cartesian = Cesium.Cartesian3.fromDegrees(longitude, latitude);
positions.push(Cesium.Cartographic.fromCartesian(Cartesian));
}
});
positions.push(
Cesium.Cartographic.fromCartesian(_positions[_positions.length - 1])
);
let heightArr = [];
pmx.allPoint = positions;
this.getHeightsFromLonLat(positions, Cesium, viewer, function (data) {
if (data) {
heightArr = data;
let changeDepthTest = viewer.scene.globe.depthTestAgainstTerrain;
viewer.scene.globe.depthTestAgainstTerrain = true;
for (let i = 0; i < heightArr.length; i++) {
let modelHeight = _this.get3DTileOrPrimitivesHeights(
positions[i],
viewer
);
if (modelHeight !== undefined) {
heightArr[i] = modelHeight;
}
let he = heightArr[i].toFixed(2);
if (parseFloat(he) < parseFloat(pmx.min)) {
pmx.min = parseFloat(he);
}
if (parseFloat(he) > parseFloat(pmx.max)) {
pmx.max = parseFloat(he);
}
pmx.gcs.push(he);
}
viewer.scene.globe.depthTestAgainstTerrain = changeDepthTest;
methond && typeof methond == "function" && methond(pmx);
}
});
};
if (pmx.cys > 1000) {
layuiLayer &&
layuiLayer.msg("当前采样点数过多,是否继续分析?", {
time: 0,
btn: ["继续", "取消"],
btnAlign: "c",
yes: index => {
layuiLayer.close(index);
setTimeout(() => {
startAnalyse();
}, 10);
},
btn2: () => {
methond && typeof methond == "function" && methond(pmx);
}
});
} else {
setTimeout(() => {
startAnalyse();
}, 10);
}
};
/**
* 获取uuid
*/
Core.prototype.uuid = function (len, radix) {
var chars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
var uuid = [],
i;
var uuid = [],
i;
radix = radix || chars.length;
if (len) {
// Compact form
for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
} else {
// rfc4122, version 4 form
var r;
// rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-";
uuid[14] = "4";
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | (Math.random() * 16);
uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
}
}
}
return uuid.join("");
};
Core.prototype.getuid = function () {
// var idStr = Date.now().toString(36);
// idStr += Math.random().toString(36).substr(3);
// return idStr;
// return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
// var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
// return v.toString(16);
// });
return this.uuid(8, 16);
};
/**
* 对象参数合并
* @param {Object} o 对象
* @param {Object} n 被合并的对象
* @param {Boolean} [override=false] 是否覆盖原属性值
* @param {Boolean} [mergeTheSame=false] 是否只合并相同属性
*/
Core.prototype.extend = function (
o,
n,
override = false,
mergeTheSame = false
) {
for (var key in n) {
if (mergeTheSame) {
if (o.hasOwnProperty(key)) {
o[key] = n[key];
}
} else {
if (!o.hasOwnProperty(key) || override) {
o[key] = n[key];
}
}
}
return o;
};
/**
* 两点方位角
* @param {number} lon1 起点经度
* @param {number} lat1 起点纬度
* @param {number} lon2 终点经度
* @param {number} lat2 终点纬度
*/
Core.prototype.TwoPointAzimuth = function (lon1, lat1, lon2, lat2) {
var result = 0.0;
var getRad = function (d) {
return (d * Math.PI) / 180.0;
};
var ilat1 = Math.round(0.5 + lat1 * 360000.0);
var ilat2 = Math.round(0.5 + lat2 * 360000.0);
var ilon1 = Math.round(0.5 + lon1 * 360000.0);
var ilon2 = Math.round(0.5 + lon2 * 360000.0);
lat1 = getRad(lat1);
lon1 = getRad(lon1);
lat2 = getRad(lat2);
lon2 = getRad(lon2);
if (ilat1 === ilat2 && ilon1 === ilon2) {
return result;
} else if (ilon1 === ilon2) {
if (ilat1 > ilat2) result = 180.0;
} else {
var c = Math.acos(
Math.sin(lat2) * Math.sin(lat1) +
Math.cos(lat2) * Math.cos(lat1) * Math.cos(lon2 - lon1)
);
var A = Math.asin((Math.cos(lat2) * Math.sin(lon2 - lon1)) / Math.sin(c));
result = (A * 180) / Math.PI;
if (ilat2 > ilat1 && ilon2 > ilon1) {
} else if (ilat2 < ilat1 && ilon2 < ilon1) {
result = 180.0 - result;
} else if (ilat2 < ilat1 && ilon2 > ilon1) {
result = 180.0 - result;
} else if (ilat2 > ilat1 && ilon2 < ilon1) {
result += 360.0;
}
}
return result;
};
export default Core;
📄 getPosition.js
/**
*
* 获取位置。
* xp
* @alias getPosition
* @constructor
*
*/
function getPosition (viewer, cesium) {
this._viewer = viewer;
this._cesium = cesium;
}
getPosition.prototype.getPosition = function () {
return this._viewer.camera.position;
};
getPosition.prototype.getDegrees = function () {
var cartographic = this._viewer.camera.positionCartographic;
var Degrees = {
lon: this._cesium.Math.toDegrees(cartographic.longitude),
lat: this._cesium.Math.toDegrees(cartographic.latitude),
height: cartographic.height
};
return Degrees;
};
/**
* 获取鼠标当前世界坐标
* @param {object} [movement] 鼠标屏幕位置
* @param {Array/Object} [objectsToExclude] 排除的实体对象
* @param {number} [type] 类型(0为模型优先,1为地形优先),默认模型优先
* @param {boolean} [isAdsorption] true|false 是否吸附,默认否
* @param {number} [distance] 吸附半径,默认30
**/
getPosition.prototype.getMousePosition = function (
movement,
objectsToExclude,
type,
isAdsorption,
distance
) {
var mousePosition = movement.endPosition || movement.position || movement;
type === undefined && (type = 0);
isAdsorption = this._cesium.defaultValue(isAdsorption, false);
this.defaultDepthTest === undefined &&
(this.defaultDepthTest =
!!this._viewer.scene.globe.depthTestAgainstTerrain);
var ray, cartesian, _cartesian, feature;
//this.isObjectsToExcludeShow(objectsToExclude, false);
var width = isAdsorption ? (distance ? distance : 30) : 1;
if (type !== 0) {
//地形优先
//开启深度检测
this._viewer.scene.globe.depthTestAgainstTerrain = true;
ray = this._viewer.camera.getPickRay(mousePosition);
ray && (cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene));
//isAdsorption && (mousePosition = this.getAdsorptionPosition(mousePosition, objectsToExclude));
if (!objectsToExclude || objectsToExclude.length === 0) {
feature = this._viewer.scene.pick(mousePosition);
if (feature && feature.id && !this.id3DGraphic(feature.id)) {
feature = undefined;
}
} else {
feature = this._viewer.scene.drillPick(
mousePosition,
objectsToExclude.length,
width,
width
);
feature = this.getNotExcludedObj(feature, objectsToExclude);
}
if (feature && !isAdsorption) {
this._viewer.scene.pick(mousePosition);
_cartesian = this._viewer.scene.pickPosition(mousePosition);
if (_cartesian) {
cartesian = _cartesian;
}
} else {
cartesian &&
isAdsorption &&
(_cartesian = this._getAdsorptionPosition(
mousePosition,
feature,
distance
)); //吸附
if (_cartesian) {
cartesian = _cartesian;
}
}
} else {
//模型优先
if (!objectsToExclude || objectsToExclude.length === 0) {
feature = this._viewer.scene.pick(mousePosition);
if (feature && feature.id && !this.id3DGraphic(feature.id)) {
feature = undefined;
}
} else {
feature = this._viewer.scene.drillPick(
mousePosition,
(objectsToExclude &&
objectsToExclude.length &&
objectsToExclude.length + 1) ||
1,
width,
width
);
feature = this.getNotExcludedObj(feature, objectsToExclude);
}
if (feature && !isAdsorption) {
this._viewer.scene.pick(mousePosition);
cartesian = this._viewer.scene.pickPosition(mousePosition);
} else if (feature && isAdsorption) {
this._viewer.scene.pick(mousePosition);
cartesian = this._viewer.scene.pickPosition(mousePosition);
_cartesian = this._getAdsorptionPosition(
mousePosition,
feature,
distance
); //吸附
if (_cartesian) {
cartesian = _cartesian;
}
} else {
//开启深度检测
this._viewer.scene.globe.depthTestAgainstTerrain = true;
ray = this._viewer.camera.getPickRay(mousePosition);
ray &&
(cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene));
}
}
this._viewer.scene.globe.depthTestAgainstTerrain = !!this.defaultDepthTest;
this.defaultDepthTest = undefined;
// console.log(cartesian);
if (!cartesian) {
console.log("未拾取到坐标!");
return;
}
return cartesian;
};
/**
* 获取鼠标当前经纬度
* @param {object} [movement] 鼠标屏幕位置
* @param {Array/Object} [objectsToExclude] 排除的实体对象
* @param {number} [type] 类型(0为模型优先,1为地形优先),默认模型优先
* @param {boolean} [isAdsorption] true|false 是否吸附,默认否
* @param {number} [distance] 吸附半径,默认30
*/
getPosition.prototype.getMouseDegrees = function (
movement,
objectsToExclude,
type,
isAdsorption,
distance
) {
var mousePosition = movement.endPosition || movement.position || movement;
type === undefined && (type = 0);
isAdsorption = this._cesium.defaultValue(isAdsorption, false);
this.defaultDepthTest === undefined &&
(this.defaultDepthTest =
!!this._viewer.scene.globe.depthTestAgainstTerrain);
var ray, cartesian, _cartesian, feature;
//this.isObjectsToExcludeShow(objectsToExclude, false);
var width = isAdsorption ? (distance ? distance : 30) : 1;
if (type !== 0) {
//地形优先
//开启深度检测
this._viewer.scene.globe.depthTestAgainstTerrain = true;
ray = this._viewer.camera.getPickRay(mousePosition);
ray && (cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene));
//isAdsorption && (mousePosition = this.getAdsorptionPosition(mousePosition, objectsToExclude));
if (!objectsToExclude || objectsToExclude.length === 0) {
feature = this._viewer.scene.pick(mousePosition);
if (feature && feature.id && !this.id3DGraphic(feature.id)) {
feature = undefined;
}
} else {
feature = this._viewer.scene.drillPick(
mousePosition,
(objectsToExclude &&
objectsToExclude.length &&
objectsToExclude.length + 1) ||
1,
width,
width
);
feature = this.getNotExcludedObj(feature, objectsToExclude);
}
if (feature && !isAdsorption) {
this._viewer.scene.pick(mousePosition);
_cartesian = this._viewer.scene.pickPosition(mousePosition);
if (_cartesian) {
cartesian = _cartesian;
}
} else {
cartesian &&
isAdsorption &&
(_cartesian = this._getAdsorptionPosition(
mousePosition,
feature,
distance
)); //吸附
if (_cartesian) {
cartesian = _cartesian;
}
}
} else {
//模型优先
if (!objectsToExclude || objectsToExclude.length === 0) {
feature = this._viewer.scene.pick(mousePosition);
if (feature && feature.id && !this.id3DGraphic(feature.id)) {
feature = undefined;
}
} else {
feature = this._viewer.scene.drillPick(
mousePosition,
(objectsToExclude &&
objectsToExclude.length &&
objectsToExclude.length + 1) ||
1,
width,
width
);
feature = this.getNotExcludedObj(feature, objectsToExclude);
}
if (feature && !isAdsorption) {
this._viewer.scene.pick(mousePosition);
cartesian = this._viewer.scene.pickPosition(mousePosition);
} else if (feature && isAdsorption) {
this._viewer.scene.pick(mousePosition);
cartesian = this._viewer.scene.pickPosition(mousePosition);
_cartesian = this._getAdsorptionPosition(
mousePosition,
feature,
distance
); //吸附
if (_cartesian) {
cartesian = _cartesian;
}
} else {
//开启深度检测
this._viewer.scene.globe.depthTestAgainstTerrain = true;
ray = this._viewer.camera.getPickRay(mousePosition);
ray &&
(cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene));
}
}
this._viewer.scene.globe.depthTestAgainstTerrain = !!this.defaultDepthTest;
this.defaultDepthTest = undefined;
if (!cartesian) {
console.log("未拾取到坐标!");
return;
}
var cartographic = this._cesium.Cartographic.fromCartesian(cartesian);
return {
lon: this._cesium.Math.toDegrees(cartographic.longitude),
lat: this._cesium.Math.toDegrees(cartographic.latitude),
height: cartographic.height
};
};
//判断是否是三维图形
getPosition.prototype.id3DGraphic = function (graphic) {
let threeD = true;
if (graphic.polyline || graphic.point || graphic.label || graphic.billboard) {
threeD = false;
} else if (graphic.polygon && graphic.polygon.extrudedHeight == undefined) {
threeD = false;
} else if (
graphic.rectangle &&
graphic.rectangle.extrudedHeight == undefined
) {
threeD = false;
} else if (graphic.ellipse && graphic.ellipse.extrudedHeight == undefined) {
threeD = false;
} else if (graphic.corridor && graphic.corridor.extrudedHeight == undefined) {
threeD = false;
}
return threeD;
};
//吸附坐标-屏幕坐标
getPosition.prototype.getAdsorptionPosition = function (
mousePosition,
objectsToExclude
) {
var dis = 5; //吸附半径
var ave = 3; //采样数
var object = this._viewer.scene.drillPick(
mousePosition,
(objectsToExclude &&
objectsToExclude.length &&
objectsToExclude.length + 1) ||
3,
dis + 3,
dis + 3
); //3为默认拾取范围
var need = false;
for (var i = 0; i < object.length; i++) {
if (object[i] && !this.isExcluded(object[i], objectsToExclude)) {
need = true;
break;
}
}
if (need) {
object = this._viewer.scene.pick(mousePosition, 1, 1);
if (object && !this.isExcluded(object, objectsToExclude)) {
return mousePosition;
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x + i, y: mousePosition.y },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x + i, y: mousePosition.y };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x + i, y: mousePosition.y + i },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x + i, y: mousePosition.y + i };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x, y: mousePosition.y + i },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x, y: mousePosition.y + i };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x - i, y: mousePosition.y + i },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x - i, y: mousePosition.y + i };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x - i, y: mousePosition.y },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x - i, y: mousePosition.y };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x - i, y: mousePosition.y - i },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x - i, y: mousePosition.y - i };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x, y: mousePosition.y - i },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x, y: mousePosition.y - i };
}
}
for (var i = dis / ave; i <= dis; i += dis / ave) {
object = this._viewer.scene.pick(
{ x: mousePosition.x + i, y: mousePosition.y - i },
1,
1
);
if (object && !this.isExcluded(object, objectsToExclude)) {
return { x: mousePosition.x + i, y: mousePosition.y - i };
}
}
}
return mousePosition;
};
//吸附坐标
getPosition.prototype._getAdsorptionPosition = function (
mousePosition,
feature,
distance
) {
var dis = distance ? distance : 30; //吸附半径
if (feature) {
feature = this.getFeature(feature);
var _PosArr = [];
var CanvasCoordinates;
for (var i = 0; i < feature.position.length; i++) {
CanvasCoordinates = this._viewer.scene.cartesianToCanvasCoordinates(
feature.position[i]
);
if (CanvasCoordinates) {
CanvasCoordinates.index = i;
_PosArr.push(CanvasCoordinates);
}
}
var compare = function (obj1, obj2) {
var val1 = obj1.x;
var val2 = obj2.x;
if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
} else {
return 0;
}
};
_PosArr = _PosArr.sort(compare);
if (_PosArr && _PosArr.length > 1) {
//二分法算最接近下标
var n = Math.log(_PosArr.length) / Math.log(2);
var m = 0;
var maxn = _PosArr.length;
var minn = 0;
var zd = -1;
for (var i = 0; i < n; i++) {
m = Math.floor((maxn + minn) / 2);
if (mousePosition.x - _PosArr[m].x > dis) {
minn = m;
} else if (mousePosition.x - _PosArr[m].x < -dis) {
maxn = m;
} else if (Math.abs(mousePosition.x - _PosArr[m].x) < dis) {
zd = m;
break;
}
}
if (zd !== -1) {
for (var i = m; i < maxn; i++) {
if (Math.abs(mousePosition.x - _PosArr[i].x) > dis) {
maxn = i;
break;
}
}
for (var i = m; i > minn; i--) {
if (Math.abs(mousePosition.x - _PosArr[i].x) > dis) {
minn = i + 1;
break;
}
}
for (var i = minn; i < maxn; i++) {
if (Math.abs(mousePosition.y - _PosArr[i].y) < dis) {
return feature.position[_PosArr[i].index];
}
}
}
}
if (_PosArr && _PosArr.length === 1) {
if (
Math.abs(mousePosition.x - _PosArr[0].x) < dis &&
Math.abs(mousePosition.y - _PosArr[0].y) < dis
) {
return feature.position[0];
}
}
}
};
getPosition.prototype.getFeature = function (obj) {
var position;
var data = {
position: [],
object: []
};
if (obj && obj.id) {
if (obj.id instanceof this._cesium.Entity) {
var entity = obj.id;
if (entity.billboard) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "billboard",
feature: entity.billboard
});
}
if (entity.box) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "box",
feature: entity.box
});
}
if (entity.corridor) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "corridor",
feature: entity.corridor
});
}
if (entity.cylinder) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "cylinder",
feature: entity.cylinder
});
}
if (entity.ellipse) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "ellipse",
feature: entity.ellipse
});
}
if (entity.ellipsoid) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "ellipsoid",
feature: entity.ellipsoid
});
}
if (entity.label) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "label",
feature: entity.label
});
}
if (entity.model) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "model",
feature: entity.model
});
}
if (entity.path) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "path",
feature: entity.path
});
}
if (entity.plane) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "plane",
feature: entity.plane
});
}
if (entity.point) {
position = entity.position.getValue(this._viewer.clock.currentTime);
data.position.push(position);
data.object.push({
type: "point",
feature: entity.point
});
}
if (entity.polygon) {
position = entity.polygon.hierarchy.getValue(
this._viewer.clock.currentTime
);
data.position = data.position.concat(position.positions);
data.object.push({
type: "polygon",
feature: entity.polygon
});
}
if (entity.polyline) {
position = entity.polyline.positions.getValue(
this._viewer.clock.currentTime
);
data.position = data.position.concat(position);
data.object.push({
type: "polyline",
feature: entity.polyline
});
}
if (entity.polylineVolume) {
position = entity.polylineVolume.positions.getValue(
this._viewer.clock.currentTime
);
data.position = data.position.concat(position);
data.object.push({
type: "polylineVolume",
feature: entity.polylineVolume
});
}
if (entity.rectangle) {
position = entity.rectangle.coordinates.getValue(
this._viewer.clock.currentTime
);
data.position = data.position.concat(position);
data.object.push({
type: "rectangle",
feature: entity.rectangle
});
}
if (entity.wall) {
position = entity.wall.positions.getValue(
this._viewer.clock.currentTime
);
data.position = data.position.concat(position);
data.object.push({
type: "wall",
feature: entity.wall
});
}
}
}
if (obj && obj.primitive) {
if (obj.primitive instanceof this._cesium.Model) {
position = obj.primitive.positionObj;
data.position.push(position);
data.object.push({
type: "model",
feature: obj.primitive
});
}
}
return data;
};
//是否包含对象
getPosition.prototype.isExcluded = function (object, objectsToExclude) {
if (
!this._cesium.defined(object) ||
!this._cesium.defined(objectsToExclude) ||
objectsToExclude.length === 0
) {
return false;
}
return (
objectsToExclude.indexOf(object) > -1 ||
objectsToExclude.indexOf(object.primitive) > -1 ||
objectsToExclude.indexOf(object.id) > -1
);
};
//获取不包含的对象
getPosition.prototype.getNotExcludedObj = function (
objectOrArr,
objectsToExclude
) {
if (objectOrArr.length === 0) {
return false;
} else if (
!this._cesium.defined(objectsToExclude) ||
objectsToExclude.length === 0
) {
return objectOrArr;
}
for (var i = 0; i < objectOrArr.length; i++) {
if (objectOrArr[i] && !this.isExcluded(objectOrArr[i], objectsToExclude)) {
return objectOrArr[i];
}
}
return false;
};
//控制对象显隐
getPosition.prototype.isObjectsToExcludeShow = function (
objectsToExclude,
isShow
) {
if (
!this._cesium.defined(objectsToExclude) ||
objectsToExclude.length === 0
) {
return;
}
if (objectsToExclude instanceof Array) {
objectsToExclude.forEach(function (item) {
item.show = isShow;
});
} else {
objectsToExclude.show = isShow;
}
};
export default getPosition;
调用方法
const _dynamicObject = new dynamicObject(window.viewer, Cesium);
_dynamicObject.executeFlycesium(data => {
data.showPoint = true;
data.showLine = true;
data.mode = 2; // 飞行模式
_dynamicObject.Start(data, data.url);
});