cesium实现网格化的相关方法
已经封装js 自行调用
javascript
/**
* 三维网格分析 + 无人机仿真工具类
* 功能:三维网格剖分、航线网格生成、多边形/圆柱/立方体网格、无人机动态仿真
* 特点:纯功能类,不创建地图,所有数据由外部传入,无任何写死配置
*/
import * as Cesium from 'cesium';
/**
* 地球半径常量(米)
*/
const M_PER_DEG = 111319.49079327357;
/**
* 网格剖分各级配置(经纬度步长、行列数)
* 索引对应网格层级 1~10
*/
const LEVELS = [
null,
{ lon: 6.0, lat: 4.0, cols: 60, rows: 22 },
{ lon: 0.5, lat: 0.5, cols: 12, rows: 8 },
{ lon: 0.25, lat: 0.25, cols: 2, rows: 2 },
{ lon: 1 / 60, lat: 1 / 60, cols: 15, rows: 15 },
{ lon: 4 / 3600, lat: 4 / 3600, cols: 15, rows: 15 },
{ lon: 2 / 3600, lat: 2 / 3600, cols: 2, rows: 2 },
{ lon: 0.25 / 3600, lat: 0.25 / 3600, cols: 8, rows: 8 },
{ lon: 1 / 32 / 3600, lat: 1 / 32 / 3600, cols: 8, rows: 8 },
{ lon: 1 / 256 / 3600, lat: 1 / 256 / 3600, cols: 8, rows: 8 },
{ lon: 1 / 2048 / 3600, lat: 1 / 2048 / 3600, cols: 8, rows: 8 }
];
/**
* 最大网格数量限制,防止性能爆炸
*/
const MAX_GRIDS = 50000;
/**
* 无人机仿真全局状态(单例模式,避免多实例冲突)
*/
const sim = {
running: false, // 是否正在运行
paused: false, // 是否暂停
startMs: 0, // 开始时间戳
totalPausedMs: 0, // 总暂停时长
pauseStartMs: 0, // 暂停开始时间
routeMeters: 0, // 航线总长度(米)
segments: [], // 航线段列表
grids: [], // 网格数据
codeToIdx: new Map(), // 网格编码 → 索引映射
entities: [], // 绘制的实体对象
drone: null, // 无人机实体
route: null, // 航线实体
alt: 100, // 默认飞行高度
speed: 10, // 速度系数
rate: 5, // 速率系数
level: 7, // 网格层级
currentIdx: -1, // 当前所在网格索引
lastPos: null // 最后位置(暂停时使用)
};
export default class GridSimulation {
/**
* 构造函数
* @param {Cesium.Viewer} viewer - 外部传入的Cesium地图实例
*/
constructor(viewer) {
if (!viewer) throw new Error("必须传入 Cesium Viewer 实例");
this.map = viewer; // 保存外部传入的viewer
}
// ==========================
// 新增:结果展示函数
// ==========================
/**
* 展示结果(返回HTML文本)
* @param {String} html - 要展示的内容
* @returns {String} html文本
*/
showResult (html) {
console.log(html);
return html;
}
/**
* 生成网格列表摘要(最多显示前30条)
* @param {Array} list - 网格数组
* @returns {String} 拼接好的HTML摘要
*/
listSummary (list) {
let h = '<b>共 ' + list.length + ' 个网格</b><br>';
list.slice(0, 30).forEach((g, i) => {
h += i + 1 + '. <code>' + g.code + '</code><br>';
});
if (list.length > 30) h += '... 仅显示前 30 条';
return h;
}
/**
* 绘制单点网格
* @param {Object} bounds - 网格范围 {min_lon,min_lat,max_lon,max_lat,min_alt,max_alt}
* @returns {Object} { list: 网格数组, html: 展示文本 }
*/
drawPointGrid (bounds) {
this.clearAll();
this.drawGrid(bounds, Cesium.Color.YELLOW.withAlpha(0.5));
this.flyToGrids([bounds]);
// 构造返回数据
const list = [bounds];
const html = this.showResult(this.listSummary(list));
return { list, html };
}
/**
* 绘制航线网格
* @param {Object} start - 起点 {lat,lon,alt}
* @param {Object} end - 终点 {lat,lon,alt}
* @param {number} level - 网格层级
* @returns {Object} { list: 网格数组, html: 展示文本 }
*/
drawLineGrid (start, end, level = 7) {
this.clearAll();
const list = this.queryLineGrids(start, end, level);
list.forEach(g => this.drawGrid(g, Cesium.Color.LIME.withAlpha(0.35)));
this.map.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
start.lon, start.lat, start.alt,
end.lon, end.lat, end.alt
]),
width: 3,
material: Cesium.Color.RED
}
});
this.flyToGrids(list);
const html = this.showResult(this.listSummary(list));
return { list, html };
}
/**
* 绘制圆柱范围网格
* @param {Object} center - 中心点 {lat,lon}
* @param {number} radius - 半径(米)
* @param {number} minAlt - 最低高度
* @param {number} maxAlt - 最高高度
* @param {number} level - 网格层级
* @returns {Object} { list: 网格数组, html: 展示文本 }
*/
drawCylinderGrid (center, radius, minAlt, maxAlt, level = 7) {
this.clearAll();
const list = this.queryCylinderGrids(center, radius, minAlt, maxAlt, level);
list.forEach(g => this.drawGrid(g, Cesium.Color.ORANGE.withAlpha(0.35)));
this.map.entities.add({
position: Cesium.Cartesian3.fromDegrees(center.lon, center.lat, (minAlt + maxAlt) / 2),
cylinder: {
length: maxAlt - minAlt,
topRadius: radius,
bottomRadius: radius,
material: Cesium.Color.RED.withAlpha(0.12),
outline: true,
outlineColor: Cesium.Color.RED
}
});
this.flyToGrids(list);
const html = this.showResult(this.listSummary(list));
return { list, html };
}
/**
* 绘制多边形范围网格
* @param {Array} points - 点数组 [{lat,lon},...]
* @param {number} minAlt - 最低高度
* @param {number} maxAlt - 最高高度
* @param {number} level - 网格层级
* @returns {Object} { list: 网格数组, html: 展示文本 }
*/
drawPrismGrid (points, minAlt, maxAlt, level = 7) {
this.clearAll();
const list = this.queryPrismGrids(points, minAlt, maxAlt, level);
list.forEach(g => this.drawGrid(g, Cesium.Color.MAGENTA.withAlpha(0.35)));
const arr = [];
points.forEach(p => arr.push(p.lon, p.lat, maxAlt));
arr.push(points[0].lon, points[0].lat, maxAlt);
this.map.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(arr),
width: 3,
material: Cesium.Color.RED
}
});
this.flyToGrids(list);
const html = this.showResult(this.listSummary(list));
return { list, html };
}
/**
* 绘制立方体范围网格
* @param {number} minLat
* @param {number} maxLat
* @param {number} minLon
* @param {number} maxLon
* @param {number} minAlt
* @param {number} maxAlt
* @param {number} level
* @returns {Object} { list: 网格数组, html: 展示文本 }
*/
drawCuboidGrid (minLat, maxLat, minLon, maxLon, minAlt, maxAlt, level = 7) {
this.clearAll();
const list = this.queryCuboidGrids(minLat, maxLat, minLon, maxLon, minAlt, maxAlt, level);
list.forEach(g => this.drawGrid(g, Cesium.Color.BLUE.withAlpha(0.35)));
this.map.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(minLon, minLat, maxLon, maxLat),
material: Cesium.Color.RED.withAlpha(0.12),
outline: true,
outlineColor: Cesium.Color.RED,
height: minAlt,
extrudedHeight: maxAlt
}
});
this.flyToGrids(list);
const html = this.showResult(this.listSummary(list));
return { list, html };
}
/**
* 启动无人机仿真
* @param {Array} routePoints - 航线点位 [{lat,lon},...]
* @param {Object} options - 配置 {alt,speed,rate,level}
* @param {Function} onStatusUpdate - 实时状态回调函数
*/
startSimulation (routePoints, options = {}, onStatusUpdate = null) {
if (!this.map) return;
// 恢复暂停
if (sim.paused) {
sim.paused = false;
sim.totalPausedMs += performance.now() - sim.pauseStartMs;
requestAnimationFrame(() => this.simTick(onStatusUpdate));
return;
}
if (sim.running) return;
// 外部传入配置
const { alt = 100, speed = 10, rate = 5, level = 7 } = options;
sim.alt = alt;
sim.speed = speed;
sim.rate = rate;
sim.level = level;
sim.lastPos = { ...routePoints[0], alt };
this.resetSim();
const pts = routePoints;
if (pts.length < 2) {
alert('航线至少需要2个点');
return;
}
// 构建航线段
let cum = 0;
for (let i = 0; i < pts.length - 1; i++) {
const a = pts[i];
const b = pts[i + 1];
const d = this.distM(a.lat, a.lon, b.lat, b.lon);
sim.segments.push({ a, b, dist: d, start: cum });
cum += d;
}
sim.routeMeters = cum;
// 生成网格
const map = new Map();
for (const seg of sim.segments) {
const list = this.queryLineGrids(
{ lat: seg.a.lat, lon: seg.a.lon, alt: sim.alt },
{ lat: seg.b.lat, lon: seg.b.lon, alt: sim.alt },
sim.level
);
for (const g of list) if (!map.has(g.code)) map.set(g.code, g);
}
sim.grids = [...map.values()];
sim.grids.forEach((g, i) => sim.codeToIdx.set(g.code, i));
// 绘制网格
sim.grids.forEach(g => {
const e = this.map.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(g.min_lon, g.min_lat, g.max_lon, g.max_lat),
material: Cesium.Color.LIME.withAlpha(0.35),
outline: true,
outlineColor: Cesium.Color.WHITE,
height: g.min_alt,
extrudedHeight: g.max_alt
}
});
sim.entities.push(e);
});
// 绘制航线
const arr = [];
pts.forEach(p => arr.push(p.lon, p.lat, sim.alt));
sim.route = this.map.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(arr),
width: 3,
material: Cesium.Color.YELLOW,
clampToGround: false
}
});
// 绘制无人机(动态点位)
sim.drone = this.map.entities.add({
position: new Cesium.CallbackProperty(() => {
const p = this.computeDronePos();
return Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.alt);
}, false),
point: {
pixelSize: 14,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
disableDepthTestDistance: Number.POSITIVE_INFINITY
},
label: {
text: '🚁 UAV',
font: '14px sans-serif',
fillColor: Cesium.Color.YELLOW,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK,
pixelOffset: new Cesium.Cartesian2(0, -22),
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
});
// 相机飞行
this.flyToGrids(sim.grids);
sim.running = true;
sim.startMs = performance.now();
sim.totalPausedMs = 0;
requestAnimationFrame(() => this.simTick(onStatusUpdate));
}
/**
* 暂停仿真
*/
pauseSim () {
if (!sim.running || sim.paused) return;
const currentPos = this.computeDronePos();
if (currentPos) sim.lastPos = currentPos;
sim.paused = true;
sim.pauseStartMs = performance.now();
}
/**
* 重置仿真 + 清空所有实体
*/
resetSim () {
sim.running = false;
sim.paused = false;
sim.routeMeters = 0;
sim.segments = [];
sim.grids = [];
sim.codeToIdx = new Map();
sim.entities = [];
sim.drone = null;
sim.route = null;
sim.currentIdx = -1;
if (this.map) this.map.entities.removeAll();
}
// ==================== 核心算法 ====================
/**
* 计算无人机实时位置
*/
computeDronePos () {
if (sim.paused || !sim.running) return sim.lastPos;
const elapsed = performance.now() - sim.startMs - sim.totalPausedMs;
const travelled = Math.min(sim.routeMeters, (elapsed / 1000) * sim.speed * sim.rate);
let s = sim.segments[sim.segments.length - 1];
for (const seg of sim.segments) {
if (travelled <= seg.start + seg.dist) {
s = seg;
break;
}
}
const t = s.dist > 0 ? (travelled - s.start) / s.dist : 0;
const pos = {
lat: s.a.lat + t * (s.b.lat - s.a.lat),
lon: s.a.lon + t * (s.b.lon - s.a.lon),
alt: sim.alt,
travelled
};
sim.lastPos = pos;
return pos;
}
/**
* 仿真帧更新(支持实时状态回调)
*/
simTick (onStatusUpdate) {
if (!sim.running || sim.paused) return;
const p = this.computeDronePos();
const code = this.toCode(this.encode(p.lat, p.lon, p.alt, sim.level));
const idx = sim.codeToIdx.has(code) ? sim.codeToIdx.get(code) : sim.currentIdx;
// 实时状态数据
const status = {
travelled: p.travelled, // 【已飞行距离】
totalDistance: sim.routeMeters, // 【航线总长度】
percent: (p.travelled / sim.routeMeters) * 100, // 【飞行进度百分比】
lat: p.lat, // 【无人机当前纬度】
lon: p.lon, // 【无人机当前经度】
alt: p.alt, // 【无人机当前高度】
currentGridCode: code, // 【当前所在的网格编码】
currentGridIndex: idx, // 【当前网格在列表里的序号】
passedGrids: idx, // 【已经飞过多少个网格】
totalGrids: sim.grids.length, // 【整条航线一共有多少网格】
remainingGrids: sim.grids.length - idx - 1 // 【还剩多少网格没飞】
};
// 回调返回状态
if (typeof onStatusUpdate === 'function') {
onStatusUpdate(status);
}
// 网格高亮更新
if (idx !== sim.currentIdx) {
sim.entities.forEach((e, i) => {
let c = i < idx ? Cesium.Color.BLUE.withAlpha(0.4)
: i === idx ? Cesium.Color.RED.withAlpha(0.6)
: Cesium.Color.LIME.withAlpha(0.35);
e.rectangle.material = c;
});
sim.currentIdx = idx;
}
// 到达终点
if (p.travelled >= sim.routeMeters) {
sim.entities.forEach(e => { e.rectangle.material = Cesium.Color.BLUE.withAlpha(0.4) });
sim.running = false;
return;
}
requestAnimationFrame(() => this.simTick(onStatusUpdate));
}
/**
* 多边形网格生成
*/
queryPrismGrids (poly, bottomAlt, topAlt, level) {
let minLat = Infinity, maxLat = -Infinity, minLon = Infinity, maxLon = -Infinity;
poly.forEach(p => {
minLat = Math.min(minLat, p.lat);
maxLat = Math.max(maxLat, p.lat);
minLon = Math.min(minLon, p.lon);
maxLon = Math.max(maxLon, p.lon);
});
const all = this.queryCuboidGrids(minLat, maxLat, minLon, maxLon, bottomAlt, topAlt, level);
return all.filter(g => this.pointInPoly(g.center.lat, g.center.lon, poly) && g.center.alt >= bottomAlt && g.center.alt <= topAlt);
}
/**
* 射线法判断点是否在多边形内
*/
pointInPoly (lat, lon, poly) {
let inside = false;
for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
const xi = poly[i].lon, yi = poly[i].lat, xj = poly[j].lon, yj = poly[j].lat;
if (yi > lat !== yj > lat && lon < ((xj - xi) * (lat - yi)) / (yj - yi + 1e-18) + xi) inside = !inside;
}
return inside;
}
/**
* 圆柱范围网格
*/
queryCylinderGrids (center, radius, bottomAlt, topAlt, level) {
const dLat = radius / M_PER_DEG;
const dLon = radius / (M_PER_DEG * Math.cos((center.lat * Math.PI) / 180));
const all = this.queryCuboidGrids(center.lat - dLat, center.lat + dLat, center.lon - dLon, center.lon + dLon, bottomAlt, topAlt, level);
return all.filter(g => this.distM(center.lat, center.lon, g.center.lat, g.center.lon) <= radius && g.center.alt >= bottomAlt && g.center.alt <= topAlt);
}
/**
* 立方体范围网格(基础网格生成)
*/
queryCuboidGrids (minLat, maxLat, minLon, maxLon, minAlt, maxAlt, level) {
const L = LEVELS[level];
const dLat = L.lat * 0.999, dLon = L.lon * 0.999, dAlt = L.lat * M_PER_DEG * 0.999;
const map = new Map();
const add = (p) => {
const g = this.encode(p[0], p[1], p[2], level);
const k = this.keyOf(g);
if (!map.has(k)) map.set(k, this.gridInfo(g));
};
for (let la = minLat; la <= maxLat + 1e-12; la += dLat)
for (let lo = minLon; lo <= maxLon + 1e-12; lo += dLon)
for (let al = minAlt; al <= maxAlt + 1e-12; al += dAlt) {
add([Math.min(la, maxLat), Math.min(lo, maxLon), Math.min(al, maxAlt)]);
if (map.size > MAX_GRIDS) throw new Error('网格数量超出限制');
}
add([maxLat, maxLon, maxAlt]);
return [...map.values()];
}
/**
* 两点间距离(米)
*/
distM (lat1, lon1, lat2, lon2) {
const R = 6371008.8;
const dLat = ((lat2 - lat1) * Math.PI) / 180;
const dLon = ((lon2 - lon1) * Math.PI) / 180;
const a = Math.sin(dLat / 2) ** 2 + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(a));
}
/**
* 绘制单个网格
*/
drawGrid (g, color) {
this.map.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(g.min_lon, g.min_lat, g.max_lon, g.max_lat),
material: color || Cesium.Color.CYAN.withAlpha(0.35),
outline: true,
outlineColor: Cesium.Color.WHITE,
height: g.min_alt,
extrudedHeight: g.max_alt
}
});
}
/**
* 相机飞行到网格区域
*/
flyToGrids (list) {
if (!list.length) return;
let mnLat = 90, mxLat = -90, mnLon = 180, mxLon = -180;
list.forEach(g => {
mnLat = Math.min(mnLat, g.max_lat);
mxLat = Math.max(mxLat, g.min_lat);
mnLon = Math.min(mnLon, g.min_lon);
mxLon = Math.max(mxLon, g.max_lon);
});
this.map.camera.flyTo({
destination: Cesium.Rectangle.fromDegrees(mnLon, mnLat, mxLon, mxLat),
duration: 1
});
}
/**
* 航线网格生成
*/
queryLineGrids (a, b, level) {
const L = LEVELS[level];
const step = Math.min(L.lat, L.lon) * 0.5;
const dLat = b.lat - a.lat, dLon = b.lon - a.lon, dAlt = b.alt - a.alt;
const dist = this.distM(a.lat, a.lon, b.lat, b.lon);
const steps = Math.max(1, Math.ceil(dist / step) + 1);
const map = new Map();
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const g = this.encode(a.lat + t * dLat, a.lon + t * dLon, a.alt + t * dAlt, level);
const k = this.keyOf(g);
if (!map.has(k)) map.set(k, this.gridInfo(g));
if (map.size > MAX_GRIDS) throw new Error('网格数量超出限制');
}
return [...map.values()];
}
/**
* 高度步长
*/
altSize (lvl) { return LEVELS[lvl].lat * M_PER_DEG; }
/**
* 数字转36进制(编码用)
*/
b36 (n) { return n.toString(36).toUpperCase(); }
/**
* 网格编码解码 → 经纬度范围
*/
decodeBox (g) {
let lon0 = -180 + g.lonZone * 6;
let latAbs0 = g.latBand * 4;
let altAbs0 = g.altIdx[0] * this.altSize(1);
for (let i = 0; i < g.cols.length; i++) {
const L = LEVELS[i + 2];
lon0 += g.cols[i] * L.lon;
latAbs0 += g.rows[i] * L.lat;
altAbs0 += g.altIdx[i + 1] * L.lat * M_PER_DEG;
}
const Llast = LEVELS[g.level];
const lonMin = lon0, lonMax = lon0 + Llast.lon;
let latMin, latMax;
if (g.hemi === 'N') {
latMin = latAbs0;
latMax = latAbs0 + Llast.lat;
} else {
latMin = -(latAbs0 + Llast.lat);
latMax = -latAbs0;
}
let altMin, altMax;
if (g.altSign === 0) {
altMin = altAbs0;
altMax = altAbs0 + Llast.lat * M_PER_DEG;
} else {
altMin = -(altAbs0 + Llast.lat * M_PER_DEG);
altMax = -altAbs0;
}
return {
min_lat: latMin,
max_lat: latMax,
min_lon: lonMin,
max_lon: lonMax,
min_alt: altMin,
max_alt: altMax
};
}
/**
* 获取网格完整信息
*/
gridInfo (g) {
const b = this.decodeBox(g);
return Object.assign({
code: this.toCode(g),
level: g.level,
center: {
lat: (b.min_lat + b.max_lat) / 2,
lon: (b.min_lon + b.max_lon) / 2,
alt: (b.min_alt + b.max_alt) / 2
}
}, b);
}
/**
* 网格编码转字符串
*/
toCode (g) {
let s = g.hemi + String(g.lonZone + 1).padStart(2, '0') + String.fromCharCode(65 + g.latBand);
for (let i = 0; i < g.cols.length; i++)
s += '-' + this.b36(g.rows[i]) + this.b36(g.cols[i]);
s += ' / H' + g.altSign;
for (let i = 0; i < g.altIdx.length; i++)
s += '-' + this.b36(g.altIdx[i]);
return s;
}
/**
* 获取网格唯一标识
*/
keyOf (g) { return this.toCode(g); }
/**
* 经纬度高度 → 网格编码
*/
encode (lat, lon, alt, level) {
const hemi = lat >= 0 ? 'N' : 'S';
const absLat = Math.abs(lat);
let lonZone = Math.floor((lon + 180) / 6);
if (lonZone === 60) lonZone = 59;
const latBand = Math.min(21, Math.floor(absLat / 4));
let lon0 = -180 + lonZone * 6;
let lat0 = latBand * 4;
let remLon = lon - lon0;
let remLat = absLat - lat0;
const altSign = alt >= 0 ? 0 : 1;
let absAlt = Math.abs(alt);
const alt1 = Math.floor(absAlt / this.altSize(1));
let remAlt = absAlt - alt1 * this.altSize(1);
const cols = [], rows = [], altIdx = [alt1];
for (let i = 2; i <= level; i++) {
const L = LEVELS[i];
let c = Math.floor(remLon / L.lon);
let r = Math.floor(remLat / L.lat);
let a = Math.floor(remAlt / (L.lat * M_PER_DEG));
if (c >= L.cols) c = L.cols - 1;
if (r >= L.rows) r = L.rows - 1;
if (a < 0) a = 0;
cols.push(c);
rows.push(r);
altIdx.push(a);
remLon -= c * L.lon;
remLat -= r * L.lat;
remAlt -= a * L.lat * M_PER_DEG;
}
return { hemi, lonZone, latBand, cols, rows, altSign, altIdx, level };
}
/**
* 清空所有实体
*/
clearAll () { this.map.entities.removeAll(); }
}
javascript
<template>
<div id="map" class="map">
<div class="data">
<button @click="drawPoint">坐标点网格</button>
<button @click="drawLine">航线网格</button>
<button @click="drawCylinder">圆柱网格</button>
<button @click="drawPrism">多边形网格</button>
<button @click="drawCuboid">立方体网格</button>
<div style="margin-top:10px;">
<button @click="startSim">▶ 开始仿真</button>
<button @click="s.pauseSim()">⏸ 暂停</button>
<button @click="s.resetSim()">⏹ 重置</button>
</div>
</div>
</div>
</template>
<script>
window.CESIUM_BASE_URL = '/';
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
import GridSimulation from './gridSimulation';
export default {
mounted () {
this.initViewer();
},
methods: {
async initViewer () {
Cesium.Ion.defaultAccessToken = ''; // 设置 Cesium Ion 访问令牌
const viewer = new Cesium.Viewer('map', {
terrain: Cesium.Terrain.fromWorldTerrain(), // 使用全球地形
homeButton: false, // 不显示首页按钮
sceneModePicker: true, // 显示场景模式切换器
baseLayerPicker: false, // 隐藏底图切换器
animation: false, // 不显示动画控件
infoBox: false, // 隐藏要素信息框
selectionIndicator: false, // 隐藏选取指示器
geocoder: false, // 隐藏地名搜索控件
timeline: true, // 临时显示时间线控件
fullscreenButton: false, // 不显示全屏按钮
shouldAnimate: false, // 不启用场景动画
navigationHelpButton: false, // 隐藏导航帮助按钮
selectionIndicator: false, // 再次隐藏选取指示器
timeline: false, // 隐藏时间线控件
});
viewer.cesiumWidget.creditContainer.style.display = 'none' // 隐藏 Cesium 版权信息显示
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.3975, 39.9087, 3000.0), // 飞到指定经纬度位置
orientation: {
heading: Cesium.Math.toRadians(0.0), // 方向角为 0
pitch: Cesium.Math.toRadians(-45.0), // 俯仰角 -45 度
roll: 0.0 // 侧倾角 0
},
duration: 0 // 立即跳转,无动画
});
// ===== 传入 viewer =====
this.s = new GridSimulation(viewer);
},
// ===== 所有数据自己定义,外部传入 =====
drawPoint () {
const bounds = {
min_lon: 116.39743,
min_lat: 39.90868,
max_lon: 116.3975,
max_lat: 39.90875,
min_alt: 100,
max_alt: 120,
};
let res = this.s.drawPointGrid(bounds);
console.log("🚀 ~ res:", res)
},
drawLine () {
const start = { lat: 39.9087, lon: 116.3975, alt: 120 };
const end = { lat: 39.912, lon: 116.402, alt: 200 };
let res = this.s.drawLineGrid(start, end, 7);
console.log("🚀 ~ res:", res);
},
drawCylinder () {
const center = { lat: 39.9087, lon: 116.3975 };
let res = this.s.drawCylinderGrid(center, 100, 0, 100, 7);
console.log("🚀 ~ res:", res);
},
drawPrism () {
const points = [
{ lat: 39.9087, lon: 116.3975 },
{ lat: 39.909, lon: 116.398 },
{ lat: 39.9085, lon: 116.399 },
];
let res = this.s.drawPrismGrid(points, 0, 100, 7);
console.log("🚀 ~ res:", res);
},
drawCuboid () {
let res = this.s.drawCuboidGrid(39.9086, 39.9088, 116.3974, 116.3976, 0, 100, 7);
console.log("🚀 ~ res:", res);
},
startSim () {
const route = [
{ lat: 39.9080, lon: 116.3960 },
{ lat: 39.9095, lon: 116.3980 },
{ lat: 39.9110, lon: 116.4000 },
];
const options = { alt: 100, speed: 10, level: 7 };
// let res = this.s.startSimulation(route, options);
this.s.startSimulation(route, options, (status) => {
console.log(status) // 你要的所有实时数据
})
// console.log("🚀 ~ res:", res);
},
},
};
</script>
<style scoped>
.map {
width: 100%;
height: 100vh;
}
.data {
position: absolute;
top: 10px;
left: 10px;
background: rgba(255, 255, 255, 0.8);
z-index: 1000;
padding: 10px;
}
</style>