import * as mars3d from "mars3d"
|
|
export let map // mars3d.Map三维地图对象
|
export let graphicLayer // 矢量图层对象
|
|
// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
|
export const mapOptions = {
|
scene: {
|
center: {
|
lat: 31.799613,
|
lng: 117.27357,
|
alt: 72.55,
|
heading: 59.8,
|
pitch: -18,
|
roll: 0
|
}
|
},
|
control: {
|
clockAnimate: true, // 时钟动画控制(左下角)
|
timeline: true, // 是否显示时间线控件
|
compass: { bottom: "380px", left: "5px" }
|
}
|
}
|
|
export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中
|
|
// 时间控制参数
|
const args = {
|
space: 100,
|
time: 5,
|
martTimeInter: null,
|
cleanTimeInter: null
|
}
|
|
/**
|
* 初始化地图业务,生命周期钩子函数(必须)
|
* 框架在地图初始化完成后自动调用该函数
|
* @param {mars3d.Map} mapInstance 地图对象
|
* @returns {void} 无
|
*/
|
export function onMounted(mapInstance) {
|
map = mapInstance // 记录map
|
map.toolbar.style.bottom = "55px" // 修改toolbar控件的样式
|
|
addLayer()
|
}
|
|
/**
|
* 释放当前地图业务的生命周期函数
|
* @returns {void} 无
|
*/
|
export function onUnmounted() {
|
map = null
|
}
|
|
function addLayer() {
|
// 创建Graphic图层
|
graphicLayer = new mars3d.layer.GraphicLayer()
|
map.addLayer(graphicLayer)
|
|
// 合肥高铁
|
const coors = [
|
[117.277697, 31.800233, 45],
|
[117.262022, 31.798983, 45],
|
[117.229506, 31.793351, 45],
|
[117.215719, 31.791085, 45],
|
[117.207234, 31.79079, 45],
|
[117.180246, 31.790688, 45],
|
[117.168311, 31.789785, 45],
|
[117.152322, 31.789855, 45],
|
[117.125297, 31.788849, 45],
|
[117.091144, 31.787516, 45]
|
]
|
|
const positions = mars3d.PointTrans.lonlats2cartesians(coors)
|
|
// 插值求新路线(按固定间隔米数插值) positions输入的值需为笛卡尔空间xyz坐标数组
|
const positionsNew = mars3d.PolyUtil.interLine(positions, {
|
minDistance: 20 // 间隔20米
|
})
|
|
// 求对比的贴地地面高度(用于echarts展示)
|
mars3d.PolyUtil.computeSurfacePoints({
|
scene: map.scene,
|
positions: positionsNew // 需要计算的源路线坐标数组
|
}).then((result) => {
|
// raisedPositions为含高程信息的新坐标数组,noHeight为标识是否存在无地形数据。
|
console.log("含高程信息的新坐标数组", result.positions)
|
|
inintRoad(positionsNew, result.positions)
|
})
|
}
|
|
// 构造动态高铁 positions:设计的路线 positionsTD地面的贴地路线(用于比较)
|
function inintRoad(positionsSJ, positionsTD) {
|
const heightArray = []
|
const heightTDArray = []
|
const mpoints = []
|
for (let i = 0; i < positionsSJ.length; i++) {
|
const position = positionsSJ[i]
|
const carto = Cesium.Cartographic.fromCartesian(position)
|
const x = Cesium.Math.toDegrees(carto.longitude)
|
const y = Cesium.Math.toDegrees(carto.latitude)
|
|
const height = mars3d.Util.formatNum(carto.height) // 设计高度 当小数点后面的数字一致时,会省略小数点,不显示
|
const tdHeight = mars3d.Util.formatNum(Cesium.Cartographic.fromCartesian(positionsTD[i]).height) // 地面高度
|
|
heightArray.push(height)
|
heightTDArray.push(tdHeight)
|
mpoints.push([x, y, height, tdHeight])
|
}
|
|
// 距离数组
|
const positionsLineFirst = positionsTD[0]
|
const distanceArray = positionsTD.map(function (data) {
|
return Math.round(Cesium.Cartesian3.distance(data, positionsLineFirst)) // 计算两点之间的距离,返回距离
|
})
|
|
// 显示echarts
|
eventTarget.fire("dataLoaded", { heightArray, heightTDArray, distanceArray })
|
// 画线
|
const primitive = new mars3d.graphic.PolylinePrimitive({
|
id: "设计路线",
|
positions: positionsSJ,
|
style: {
|
width: 3,
|
color: Cesium.Color.RED,
|
materialType: mars3d.MaterialType.PolylineDash, // 虚线
|
dashLength: 20
|
}
|
})
|
graphicLayer.addGraphic(primitive)
|
|
const primitiveTD = new mars3d.graphic.PolylinePrimitive({
|
id: "贴地路线",
|
positions: positionsTD,
|
style: {
|
width: 3,
|
color: Cesium.Color.YELLOW
|
}
|
})
|
graphicLayer.addGraphic(primitiveTD)
|
|
// =================计算路线====================
|
const start = map.clock.currentTime.clone()
|
|
const counts = mpoints.length
|
|
const arrProperty = []
|
|
// 16组车身+头尾2个车头 共18组
|
for (let j = 0; j < 18; j++) {
|
const stime = Cesium.JulianDate.addSeconds(start, j, new Cesium.JulianDate()) // 每隔j秒,添加一次时间
|
|
const property = new Cesium.SampledPositionProperty()
|
|
for (let i = 0; i < counts; i++) {
|
const time = Cesium.JulianDate.addSeconds(stime, i + 1, new Cesium.JulianDate())
|
const point = Cesium.Cartesian3.fromDegrees(mpoints[i][0], mpoints[i][1], mpoints[i][2] + 0.5)
|
property.addSample(time, point) // 添加新样本,时间、位置
|
}
|
|
property.setInterpolationOptions({
|
interpolationDegree: 1,
|
interpolationAlgorithm: Cesium.LinearApproximation
|
})
|
|
arrProperty.push(property)
|
}
|
|
// =================时间相关====================
|
|
const stop = Cesium.JulianDate.addSeconds(start, counts + 60, new Cesium.JulianDate())
|
map.clock.startTime = start.clone()
|
map.clock.stopTime = stop.clone()
|
map.clock.currentTime = start.clone()
|
map.clock.multiplier = 1 // 当前速度,默认为1
|
map.clock.shouldAnimate = true // 是否开启时钟动画,默认true
|
// map.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 到达终止时间后循环
|
|
if (map.controls.timeline) {
|
map.controls.timeline.zoomTo(start, stop)
|
}
|
|
const availability = new Cesium.TimeIntervalCollection([
|
new Cesium.TimeInterval({
|
start: start,
|
stop: Cesium.JulianDate.addSeconds(start, counts, new Cesium.JulianDate())
|
})
|
])
|
|
// =================添加高铁车头================
|
const graphicHead = addTrainHead(arrProperty[0], availability)
|
map.trackedEntity = graphicHead.entity // 设置相机的视角跟随的Entity实例
|
|
// =================添加车身====================
|
const len = arrProperty.length
|
for (let j = 1; j < len - 1; j++) {
|
addTrainBody(arrProperty[j], availability)
|
}
|
|
// =================添加高铁车尾================
|
addTrainHead(arrProperty[len - 1], availability, true) // 车尾部的反向车头
|
|
// ==============添加铁路,定时更新================
|
addRailway(graphicHead, mpoints)
|
|
// ==============更新echarts================
|
let lastDistance
|
|
function locTrain() {
|
const t = parseInt(map.clock.currentTime.secondsOfDay - map.clock.startTime.secondsOfDay) // 时间差
|
|
if (t >= heightArray.length) {
|
// 高铁运行结束之后
|
clearInterval(args.martTimeInter)
|
clearInterval(args.cleanTimeInter)
|
return
|
}
|
if (lastDistance === t) {
|
return
|
}
|
lastDistance = t
|
updateEchartsDistance(t, heightArray[t])
|
}
|
args.martTimeInter = setInterval(locTrain, 100)
|
}
|
|
// 添加车头
|
function addTrainHead(position, availability, rotatePI) {
|
const graphicModel = new mars3d.graphic.ModelEntity({
|
name: "和谐号车头",
|
position: position,
|
orientation: new Cesium.VelocityOrientationProperty(position),
|
availability: availability,
|
style: {
|
url: "//data.mars3d.cn/gltf/mars/train/heada.glb",
|
scale: 0.001,
|
minimumPixelSize: 16,
|
heading: rotatePI ? 90 : -90
|
}
|
})
|
graphicLayer.addGraphic(graphicModel)
|
return graphicModel
|
}
|
|
// 添加车身
|
function addTrainBody(position, availability) {
|
const graphicModel = new mars3d.graphic.ModelEntity({
|
name: "和谐号车身",
|
position: position,
|
orientation: new Cesium.VelocityOrientationProperty(position),
|
availability: availability,
|
style: {
|
url: "//data.mars3d.cn/gltf/mars/train/body.glb",
|
scale: 0.001,
|
minimumPixelSize: 16,
|
heading: -90
|
}
|
})
|
graphicLayer.addGraphic(graphicModel)
|
return graphicModel
|
}
|
|
// 添加铁路,定时更新
|
function addRailway(graphicHead, mpoints) {
|
const positions = []
|
const orientations = []
|
|
const times = graphicHead.position._property._times
|
const start = times[0].clone()
|
const counts = times.length
|
|
for (let k = 1; k < counts; k++) {
|
const time = times[k]
|
|
const position = graphicHead.position.getValue(time)
|
positions.push(position)
|
|
const orientation = graphicHead.orientation.getValue(time)
|
orientations.push(orientation)
|
}
|
|
let i = 0
|
const roadNum = 80
|
|
function addroad() {
|
const space = Math.round(map.clock.currentTime.secondsOfDay - map.clock.startTime.secondsOfDay)
|
let spa = space + args.space
|
if (spa > counts) {
|
spa = counts
|
}
|
for (; i < spa; i++) {
|
const availability = new Cesium.TimeIntervalCollection([
|
new Cesium.TimeInterval({
|
start: Cesium.JulianDate.addSeconds(start, -roadNum + i, new Cesium.JulianDate()),
|
stop: Cesium.JulianDate.addSeconds(start, roadNum + i, new Cesium.JulianDate())
|
})
|
])
|
|
// 当高度在地下时,添加地下隧道
|
if (mpoints[i][2] - mpoints[i][3] < -20 || (i > 2 && mpoints[i - 3][2] - mpoints[i - 3][3] < -20)) {
|
// mpoints[i][2] -- 设计高度;mpoints[i][3] -- 贴地高度
|
const id = "s" + i
|
const graphic = graphicLayer.getGraphicById(id)
|
if (!graphic) {
|
const graphicModel = new mars3d.graphic.ModelEntity({
|
id: id,
|
position: positions[i],
|
orientation: orientations[i],
|
availability: availability,
|
style: {
|
url: "//data.mars3d.cn/gltf/mars/railway/suidao.glb",
|
scale: 0.001
|
}
|
})
|
graphicLayer.addGraphic(graphicModel)
|
} else {
|
graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay
|
}
|
}
|
|
// 添加轨道地面
|
const id = "xl" + i
|
const graphic = graphicLayer.getGraphicById(id)
|
if (!graphic) {
|
const graphicModel = new mars3d.graphic.ModelEntity({
|
id: id,
|
position: positions[i],
|
orientation: orientations[i],
|
availability: availability,
|
style: {
|
url: "//data.mars3d.cn/gltf/mars/railway/railway.glb",
|
scale: 0.001
|
}
|
})
|
graphicLayer.addGraphic(graphicModel)
|
} else {
|
graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay
|
}
|
|
// 添加轨道支架
|
if (mpoints[i][2] - mpoints[i][3] > 20 && i % 5 === 0) {
|
const id = "xq" + i
|
const graphic = graphicLayer.getGraphicById(id)
|
if (!graphic) {
|
const graphicModel = new mars3d.graphic.ModelEntity({
|
id: id,
|
position: positions[i],
|
orientation: orientations[i],
|
availability: availability,
|
style: {
|
url: "//data.mars3d.cn/gltf/mars/railway/bridge.glb",
|
scale: 0.001
|
}
|
})
|
graphicLayer.addGraphic(graphicModel)
|
} else {
|
graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay
|
}
|
}
|
|
// 添加轨道边的柱子
|
if (i % 12 === 0) {
|
const id = "xd" + i
|
const graphic = graphicLayer.getGraphicById(id)
|
if (!graphic) {
|
const graphicModel = new mars3d.graphic.ModelEntity({
|
id: id,
|
position: positions[i],
|
orientation: orientations[i],
|
availability: availability,
|
style: {
|
url: "//data.mars3d.cn/gltf/mars/railway/jiazi.glb",
|
scale: 0.001
|
}
|
})
|
graphicLayer.addGraphic(graphicModel)
|
} else {
|
graphic.entity.availability._intervals[0].stop.secondsOfDay = availability._intervals[0].stop.secondsOfDay
|
}
|
}
|
}
|
|
// 移除铁路
|
for (let j = args.statate; j < args.statate - args.space; j++) {
|
removeGraphic("s" + j)
|
removeGraphic("xl" + j)
|
removeGraphic("xq" + j)
|
removeGraphic("xd" + j)
|
args.statate = j
|
}
|
}
|
|
addroad()
|
|
args.cleanTimeInter = setInterval(addroad, args.time)
|
args.statate = 0
|
}
|
|
function removeGraphic(id) {
|
const graphic = graphicLayer.getGraphicById(id)
|
if (graphic) {
|
if (graphic.entity.availability._intervals[0].stop.secondsOfDay < map.clock.currentTime.secondsOfDay) {
|
graphic.remove(true)
|
}
|
}
|
}
|
|
function updateEchartsDistance(loc, height) {
|
eventTarget.fire("dataUpdated", { loc, height })
|
}
|