cesium做垂直测量
完整代码
<template>
<div id="cesiumContainer" style="height: 100vh;"></div>
<div id="toolbar" style="position: fixed;top:20px;left:220px;">
<el-breadcrumb>
<el-breadcrumb-item>量测</el-breadcrumb-item>
<el-breadcrumb-item>垂直距离</el-breadcrumb-item>
</el-breadcrumb>
<el-row class="mb-4" style="margin-top: 15px">
<el-button type="primary" @click="handleDrawPolyline">画线</el-button>
<el-button type="primary" @click="handleDrawPolylineCancel">清除</el-button>
</el-row>
</div>
</template>
<script setup>
import {onMounted, ref} from "vue";
import * as Cesium from "cesium";
import InitCesium from "../js/InitCesiumHide.js";
import DrawVerticalDistance from "@/assets/utils/measure/DrawVerticalDistance.js";
let viewer = null;
let verticalDistance = null;
onMounted(() => {
let initCesium = new InitCesium('cesiumContainer')
viewer = initCesium.initViewer({});
verticalDistance = new DrawVerticalDistance(viewer);
flyToRight2();
})
const handleDrawPolyline = () => {
if (verticalDistance) {
// 开始量算
verticalDistance.start();
}
}
const handleDrawPolylineCancel = () => {
if (!verticalDistance) return;
verticalDistance.destroy();
}
const flyToRight2 = async () => {
let tileset = await Cesium.Cesium3DTileset.fromUrl('/src/assets/tileset/12/tileset.json', {});
update3dtilesMaxtrix(tileset);
viewer.scene.primitives.add(tileset);
viewer.flyTo(tileset);
}
function update3dtilesMaxtrix(tileSet) {
//调整参数
let params = {
tx: 113.06265738392063, //模型中心X轴坐标(经度,单位:十进制度)
ty: 22.646803971034342, //模型中心Y轴坐标(纬度,单位:十进制度)
tz: 40, //模型中心Z轴坐标(高程,单位:米)
rx: 0, //X轴(经度)方向旋转角度(单位:度)
ry: 0, //Y轴(纬度)方向旋转角度(单位:度)
rz: 2, //Z轴(高程)方向旋转角度(单位:度)
scale: 1.3, //缩放比例
};
//旋转
const mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx));
const my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry));
const mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz));
const rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
const rotationY = Cesium.Matrix4.fromRotationTranslation(my);
const rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
//平移
const position = Cesium.Cartesian3.fromDegrees(
params.tx,
params.ty,
params.tz
);
const m = Cesium.Transforms.eastNorthUpToFixedFrame(position);
//旋转、平移矩阵相乘
Cesium.Matrix4.multiply(m, rotationX, m);
Cesium.Matrix4.multiply(m, rotationY, m);
Cesium.Matrix4.multiply(m, rotationZ, m);
//比例缩放
const scale = Cesium.Matrix4.fromUniformScale(params.scale);
Cesium.Matrix4.multiply(m, scale, m);
// console.log("矩阵m:", m);
//赋值给tileset
tileSet._root.transform = m;
}
</script>
<style scoped>
#cesiumContainer {
overflow: hidden;
}
</style>
<style>
.el-breadcrumb__inner {
color: #ffffff !important;
}
</style>
InitCesiumHide
import * as Cesium from "cesium";
class InitCesiumHide {
constructor(cesiumContainer, options) {
this.cesiumContainer = cesiumContainer;
}
initViewer(options) {
Cesium.Ion.defaultAccessToken = 'token';
// 西南东北,默认显示中国
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(90, -20, 110, 90);
return new Cesium.Viewer(this.cesiumContainer, {
animation: false, // 隐藏动画控件
baseLayerPicker: false, // 隐藏图层选择控件
fullscreenButton: false, // 隐藏全屏按钮
vrButton: false, // 隐藏VR按钮,默认false
geocoder: false, // 隐藏地名查找控件 地理编码
homeButton: false, // 隐藏Home按钮
infoBox: false, // 隐藏点击要素之后显示的信息窗口
sceneModePicker: false, // 隐藏场景模式选择控件
selectionIndicator: false, // 显示实体对象选择框,默认true
timeline: false, // 隐藏时间线控件
navigationHelpButton: false, // 隐藏帮助按钮
scene3DOnly: true, // 每个几何实例将只在3D中呈现,以节省GPU内存
shouldAnimate: true, // 开启动画自动播放
sceneMode: 3, // 初始场景模式 1:2D 2:2D循环 3:3D,默认3
requestRenderMode: true, // 减少Cesium渲染新帧总时间并减少Cesium在应用程序中总体CPU使用率
...options
});
}
}
export default InitCesiumHide
DrawVerticalDistance
import BaseMeasure from "./baseMeasure";
import '../prompt/prompt.css'
import Prompt from '../prompt/prompt.js'
import * as Cesium from "cesium";
/**
* 三角测量类
* @class
* @augments BaseMeasure
* @alias BaseMeasure.MeasureTriangle
*/
class DrawVerticalDistance extends BaseMeasure {
constructor(viewer, opt) {
super(viewer, opt);
if (!opt) opt = {};
this.unitType = "length";
this.style = opt.style || {};
//线
this.heightfloatLabel = null;
this.spaceDistancefloatLabel = null;
this.horizonDistancefloatLabel = null;
this.heightLine = null;
this.spaceLine = null;
this.horizonLine = null;
this.firstPosition = null;
this.endPosition = null;
this.midPosition = undefined;
this.lowPosition = undefined;
this.highPosition = undefined;
}
//开始测量
start(callback) {
if (!this.prompt && this.promptStyle.show) {
this.prompt = new Prompt(this.viewer, this.promptStyle)
}
var that = this;
this.state = 1;
that.handler.setInputAction((evt) => { //单击开始绘制
var cartesian = that.getCatesian3FromPX(evt.position, that.viewer);
if (!cartesian) return;
if (!that.firstPosition) {
that.firstPosition = cartesian.clone();
that.heightfloatLabel = that.createLabel(cartesian, "");
that.spaceDistancefloatLabel = that.createLabel(cartesian, "", 10);
that.horizonDistancefloatLabel = that.createLabel(cartesian, "");
let point = that.createPoint(cartesian.clone());
point.wz = 0;
that.controlPoints.push(point);
} else {
that.endPosition = cartesian;
that.computerPosition(that.firstPosition, that.endPosition);
let point = that.createPoint(cartesian.clone());
point.wz = 1;
that.controlPoints.push(point);
if (that.handler) {
that.handler.destroy();
that.handler = null;
}
if (that.prompt) {
that.prompt.destroy();
that.prompt = null;
}
that.state = "endCreate";
if (callback) callback();
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) {
that.state = "creating";
if (!that.firstPosition) {
that.prompt.update(evt.endPosition, "左键点击确定起点,再次点击确定终点并结束");
return;
}
that.prompt.update(evt.endPosition, "左键点击确定起点,再次点击确定终点并结束");
var cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer);
if (!cartesian) return;
that.endPosition = cartesian;
that.computerPosition(that.firstPosition, that.endPosition);
if (that.firstPosition && that.endPosition && !that.heightLine) {
that.heightLine = that.viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(function () {
return [that.lowPosition, that.midPosition]
}, false),
show: true,
material: new Cesium.PolylineOutlineMaterialProperty({
color: Cesium.Color.GOLD,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK,
}),
width: 3,
}
});
that.heightLine.objId = that.objId;
that.horizonLine = that.viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(function () {
return [that.highPosition, that.midPosition]
}, false),
show: true,
material: new Cesium.PolylineOutlineMaterialProperty({
color: Cesium.Color.GOLD,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK,
}),
width: 3,
}
});
that.horizonLine.objId = that.objId;
}
if (that.heightLine) that.createLabels();
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
//计算正上方的点
computerPosition(p1, p2) {
const cartographic1 = Cesium.Cartographic.fromCartesian(p1.clone());
const cartographic2 = Cesium.Cartographic.fromCartesian(p2.clone());
if (cartographic1.height > cartographic2.height) {
this.highPosition = p1.clone();
this.lowPosition = p2.clone();
this.midPosition = Cesium.Cartesian3.fromRadians(cartographic2.longitude, cartographic2.latitude, cartographic1.height);
} else {
this.lowPosition = p1.clone();
this.highPosition = p2.clone();
this.midPosition = Cesium.Cartesian3.fromRadians(cartographic1.longitude, cartographic1.latitude, cartographic2.height);
}
}
startEdit(callback) {
if (!(this.state == "endCrerate" || this.state == "endEdit")) return;
this.state = "startEdit";
if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
let that = this;
for (let i = 0; i < that.controlPoints.length; i++) {
let point = that.controlPoints[i];
if (point) point.show = true;
}
this.modifyHandler.setInputAction(function (evt) {
let pick = that.viewer.scene.pick(evt.position);
if (Cesium.defined(pick) && pick.id) {
if (!pick.id.objId)
that.modifyPoint = pick.id;
that.forbidDrawWorld(true);
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
this.modifyHandler.setInputAction(function (evt) {
if (!that.modifyPoint) return;
let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer);
if (!cartesian) return;
that.modifyPoint.position.setValue(cartesian.clone());
if (that.modifyPoint.wz == 0) {
that.firstPosition = cartesian.clone()
} else {
that.endPosition = cartesian.clone()
}
that.computerPosition(that.firstPosition, that.endPosition);
that.createLabels();
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.modifyHandler.setInputAction(function (evt) {
if (!that.modifyPoint) return;
that.modifyPoint = null;
that.forbidDrawWorld(false);
that.state = "endEdit";
if (callback) callback();
}, Cesium.ScreenSpaceEventType.LEFT_UP);
}
endEdit() {
let that = this;
this.state = "endEdit";
if (this.modifyHandler) {
this.modifyHandler.destroy();
this.modifyHandler = null;
}
for (let i = 0; i < that.controlPoints.length; i++) {
let point = that.controlPoints[i];
if (point) point.show = false;
}
}
createLabels() {
let that = this;
//高度差
var height = Math.abs(Cesium.Cartographic.fromCartesian(that.highPosition).height - Cesium.Cartographic.fromCartesian(that.lowPosition).height);
var height_mid = Cesium.Cartesian3.midpoint(that.lowPosition, that.midPosition, new Cesium.Cartesian3());
that.heightfloatLabel.show = true;
that.heightfloatLabel.position.setValue(height_mid);
let text1 = that.formateLength(height, that.unit);
that.heightfloatLabel.label.text = "垂直距离:" + text1;
that.heightfloatLabel.length = height;
}
claer() {
this.destroy();
}
//清除测量结果
destroy() {
this.state = "no";
let that = this;
if (that.heightLine) {
that.viewer.entities.remove(that.heightLine);
that.heightLine = null;
}
// if (this.spaceLine) {
// this.viewer.entities.remove(this.spaceLine);
// this.spaceLine = null;
// }
if (that.horizonLine) {
that.viewer.entities.remove(that.horizonLine);
that.horizonLine = null;
}
if (that.heightfloatLabel) {
that.viewer.entities.remove(that.heightfloatLabel);
that.heightfloatLabel = null;
}
that.heightfloatLabel = null;
if (this.spaceDistancefloatLabel) {
this.viewer.entities.remove(this.spaceDistancefloatLabel);
this.spaceDistancefloatLabel = null;
}
that.spaceDistancefloatLabel = null;
if (that.horizonDistancefloatLabel) {
that.viewer.entities.remove(that.horizonDistancefloatLabel);
that.horizonDistancefloatLabel = null;
}
that.horizonDistancefloatLabel = null;
if (that.prompt) {
that.prompt.destroy();
that.prompt = null;
}
if (that.handler) {
that.handler.destroy();
that.handler = null;
}
}
setUnit(unit) {
if (this.heightfloatLabel) {
let text1 = this.formateLength(this.heightfloatLabel.length, unit);
this.heightfloatLabel.label.text = "垂直距离:" + text1;
}
this.unit = unit;
}
}
export default DrawVerticalDistance;
效果图