├── .gitignore ├── README.md ├── env.d.ts ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── Index.vue ├── js │ ├── measure │ │ ├── baseMeasure.js │ │ ├── measureAzimuth.js │ │ ├── measureGroundDistance.js │ │ ├── measureHeight.js │ │ ├── measureLnglat.js │ │ ├── measureSection.js │ │ ├── measureSpaceArea.js │ │ ├── measureSpaceDistance.js │ │ ├── measureTool.js │ │ └── measureTriangle.js │ ├── prompt │ │ ├── prompt.css │ │ └── prompt.js │ └── util.js └── main.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cesium量算插件 2 | ### [在线体验](http://mapgl.com/shareCode/#/Measure) 3 | gitee:https://gitee.com/caozl1132/CesiumExp-measure 4 | github:https://github.com/gitgitczl/CesiumExp-measure 5 | 6 | ps:如果可以的话,希望大家能给我个star,好让我有更新下去的动力; 7 | 8 | *** 9 | 实现原理: 10 | 其中距离量算的原理是用了Cartesian3提供的distance方法进行了计算; 11 | 面积计算是使用了开源的turf库来进行计算的,此处我只做了空间面积计算,并没有做贴地面积计算,贴地面积计算的原理和空间面积计算一样,只不过贴地时对面做了微分; 12 | 方位角使用了矩阵计算了正北方向的夹角; 13 | 坐标是一个普通的Cartesian3转经纬度; 14 | 15 | *** 16 | 两种调用方法: 17 | 此处调用和我另一个标绘组件的方法类型,一种是使用MeasureTool这个工具类进行统一控制(推荐使用),另一种是直接new 所需的标绘类。 18 | 1、直接通过Tool工具类进行控制: 19 | ``` 20 | measureTool = new MeasureTool(viewer); 21 | // 通过on可以实现状态监听 22 | measureTool.on("endCreate",function(measureObj){ 23 | // 标绘结束的回调 24 | ...... 25 | }); 26 | ``` 27 | 28 | 2、直接new 具体标绘类型,如下进行贴地距离测量: 29 | ``` 30 | let mg = new MeasureGroundDistance(viewer); 31 | mg.starte(); 32 | ``` 33 | *** 34 | 其它: 35 | qq群:606645466(GIS之家共享交流群) 36 | 37 | [更多案例地址](http://mapgl.com/shareCode/)    [更多免费数据](http://mapgl.com/shareData/)    [开发文档说明](http://mapgl.com/3dapi/) 38 | 39 | [其它源码下载(标绘、量算、动态材质、漫游、地图分析等)](http://mapgl.com/introduce/) 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 三维案例共享 11 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cesium-example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "run-p type-check build-only", 8 | "preview": "vite preview", 9 | "build-only": "vite build", 10 | "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false" 11 | }, 12 | "dependencies": { 13 | "@turf/turf": "^6.5.0", 14 | "ant-design-vue": "^3.2.20", 15 | "turf": "^3.0.14", 16 | "vue": "^3.3.2", 17 | "vue-router": "^4.2.0" 18 | }, 19 | "devDependencies": { 20 | "@tsconfig/node18": "^2.0.1", 21 | "@types/node": "^18.16.8", 22 | "@vitejs/plugin-vue": "^4.2.3", 23 | "@vue/tsconfig": "^0.4.0", 24 | "npm-run-all": "^4.1.5", 25 | "typescript": "~5.0.4", 26 | "vite": "^4.3.5", 27 | "vue-tsc": "^1.6.4" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitgitczl/CesiumExp-measure/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/Index.vue: -------------------------------------------------------------------------------- 1 | 10 | 117 | 118 | 136 | 137 | -------------------------------------------------------------------------------- /src/js/measure/baseMeasure.js: -------------------------------------------------------------------------------- 1 | import * as turf from '@turf/turf' 2 | /** 3 | * 量算基类 4 | * @description 量算基类,一般不直接实例化,而实例化其子类(见下方Classes) 5 | * @class 6 | * @alias BaseMeasure 7 | */ 8 | class BaseMeasure { 9 | /** 10 | * @param {Cesium.Viewer} viewer 地图viewer对象 11 | * @param {Object} opt 基础配置 12 | */ 13 | constructor(viewer, opt) { 14 | opt = opt || {}; 15 | this.viewer = viewer; 16 | 17 | /** 18 | * @property {String} objId 唯一标识id 19 | */ 20 | this.objId = Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0)); 21 | 22 | /** 23 | * @property {String} state 标识当前状态 no startCreate creating endCreate startEdit endEdit editing 24 | */ 25 | this.state = null; 26 | this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 27 | this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 28 | this.floatLable = null; 29 | /** 30 | * 31 | * @property {String} unit 单位 32 | */ 33 | this.unit = opt.unit; 34 | 35 | this.controlPoints = []; 36 | this.pointStyle = {}; 37 | this.modifyPoint = null; 38 | 39 | /** 40 | * @property {Object} promptStyle 鼠标弹窗样式 41 | */ 42 | this.promptStyle = opt.prompt || { 43 | show: true, 44 | offset: { 45 | x: 20, 46 | y: 20 47 | } 48 | } 49 | } 50 | 51 | endCreate(){} 52 | /** 53 | * 结束当前操作 包括编辑和绘制 54 | */ 55 | done(){ 56 | 57 | } 58 | 59 | createLine(positions, clampToGround) { 60 | if (!positions) return; 61 | let ent = this.viewer.entities.add({ 62 | polyline: { 63 | positions: new Cesium.CallbackProperty(function () { 64 | return positions 65 | }, false), 66 | show: true, 67 | material: new Cesium.PolylineOutlineMaterialProperty({ 68 | color: Cesium.Color.GOLD, 69 | outlineWidth: 1, 70 | outlineColor: Cesium.Color.BLACK, 71 | }), 72 | disableDepthTestDistance: Number.POSITIVE_INFINITY, 73 | width: 3, 74 | clampToGround: clampToGround 75 | } 76 | }); 77 | return ent; 78 | } 79 | 80 | // 操作控制 81 | forbidDrawWorld(isForbid) { 82 | this.viewer.scene.screenSpaceCameraController.enableRotate = !isForbid; 83 | this.viewer.scene.screenSpaceCameraController.enableTilt = !isForbid; 84 | this.viewer.scene.screenSpaceCameraController.enableTranslate = !isForbid; 85 | this.viewer.scene.screenSpaceCameraController.enableInputs = !isForbid; 86 | } 87 | 88 | createLabel(c, text) { 89 | if (!c) return; 90 | return this.viewer.entities.add({ 91 | position: c, 92 | label: { 93 | text: text || "", 94 | font: '18px Helvetica', 95 | fillColor: Cesium.Color.WHITE, 96 | outlineColor: Cesium.Color.BLACK, 97 | outlineWidth: 2, 98 | disableDepthTestDistance: Number.POSITIVE_INFINITY, 99 | style: Cesium.LabelStyle.FILL_AND_OUTLINE, 100 | pixelOffset: new Cesium.Cartesian2(0, -20) 101 | } 102 | }); 103 | } 104 | 105 | /** 106 | * 设置单位 107 | * @param {String} unit 108 | */ 109 | setUnit(unit) { 110 | if (!unit) return; 111 | this.unit = unit; 112 | } 113 | 114 | // 角度计算 115 | getAzimuthtAndCenter(mtx, positions) { 116 | if (!positions || positions.length < 2) return; 117 | let center = positions[0].clone(); 118 | mtx = mtx || Cesium.Transforms.eastNorthUpToFixedFrame(center.clone()); 119 | let mtxInverse = Cesium.Matrix4.inverse(mtx, new Cesium.Matrix4()); 120 | 121 | let aim = positions[1].clone(); 122 | center = Cesium.Matrix4.multiplyByPoint(mtxInverse, center, new Cesium.Cartesian3()); 123 | aim = Cesium.Matrix4.multiplyByPoint(mtxInverse, aim, new Cesium.Cartesian3()); 124 | 125 | let newC = Cesium.Cartesian3.subtract(aim, center, new Cesium.Cartesian3()); 126 | newC = Cesium.Cartesian3.normalize(newC, new Cesium.Cartesian3()); 127 | const north = new Cesium.Cartesian3(0, 1, 0); 128 | const arc_north = Cesium.Cartesian3.dot(north, newC); 129 | // east用于判断与正北是否大于180度 130 | const east = new Cesium.Cartesian3(1, 0, 0); 131 | const arc_east = Cesium.Cartesian3.dot(east, aim); 132 | const radians_north = Math.acos(arc_north); 133 | let dg = Cesium.Math.toDegrees(radians_north); 134 | if (arc_east < 0) dg = 360 - dg; 135 | return dg; 136 | } 137 | 138 | formateLength(val, dw) { 139 | if (val == undefined) return; 140 | dw = dw || "m"; 141 | let dwStr = ''; 142 | if (dw == "km" || dw == "千米") { 143 | dwStr += (Number(val) / 1000).toFixed(2) + "km"; 144 | } else if (dw == "m" || dw == "米") { 145 | dwStr += Number(val).toFixed(2) + "m"; 146 | } else { 147 | 148 | } 149 | return dwStr; 150 | } 151 | 152 | formateArea(val, dw) { 153 | if (val == undefined) return; 154 | let dwStr = ''; 155 | dw = dw || "m"; 156 | if (dw == "km" || dw == "平方千米") { 157 | dwStr += (Number(val) / 1000000).toFixed(2) + "km²"; 158 | } else if (dw == "m" || dw == "平方米") { 159 | dwStr += Number(val).toFixed(2) + "m²"; 160 | } else { 161 | 162 | } 163 | return dwStr; 164 | } 165 | 166 | //兼容模型和地形上坐标拾取 167 | getCatesian3FromPX(px, viewer) { 168 | var picks = viewer.scene.drillPick(px); 169 | viewer.scene.render(); 170 | var cartesian; 171 | var isOn3dtiles = false; 172 | for (var i = 0; i < picks.length; i++) { 173 | if ((picks[i] && picks[i].primitive) && picks[i].primitive instanceof Cesium.Cesium3DTileset) { //模型上拾取 174 | isOn3dtiles = true; 175 | break; 176 | } 177 | } 178 | if (isOn3dtiles) { 179 | cartesian = viewer.scene.pickPosition(px); 180 | } else { 181 | var ray = viewer.camera.getPickRay(px); 182 | if (!ray) return null; 183 | cartesian = viewer.scene.globe.pick(ray, viewer.scene); 184 | } 185 | return cartesian; 186 | } 187 | 188 | // 获取长度 189 | getGroundLength(positions, callback) { 190 | var that = this; 191 | var ellipsoid = this.viewer.scene.globe.ellipsoid; 192 | let len = this.getLength(positions[0], positions[1]); 193 | if (!this.viewer.terrainProvider.availability) { 194 | console.log("缺少地形数据,或地形加载失败!"); 195 | if (callback) callback(len); 196 | return; 197 | } 198 | 199 | let granularity = 0.00001; 200 | 201 | if (len > 10000) { 202 | granularity = granularity * 10; 203 | } else if (len > 50000) { 204 | granularity = granularity * 100; 205 | } else if (len > 100000) { 206 | granularity = granularity * 5000; 207 | } else { 208 | granularity = granularity * 10000; 209 | } 210 | 211 | var surfacePositions = Cesium.PolylinePipeline.generateArc({ 212 | positions: positions, 213 | granularity: 0.00001 214 | }); 215 | if (!surfacePositions) return; 216 | var cartographicArray = []; 217 | var tempHeight = Cesium.Cartographic.fromCartesian(positions[0]).height; 218 | for (var i = 0; i < surfacePositions.length; i += 3) { 219 | var cartesian = Cesium.Cartesian3.unpack(surfacePositions, i); 220 | cartographicArray.push(ellipsoid.cartesianToCartographic(cartesian)); 221 | } 222 | 223 | 224 | Cesium.when(Cesium.sampleTerrainMostDetailed(that.viewer.terrainProvider, cartographicArray), function (updateLnglats) { 225 | var allLength = 0; 226 | var offset = 10.0; 227 | for (var i = 0; i < updateLnglats.length; i++) { 228 | var item = updateLnglats[i]; 229 | if (!item.height) { //当未获取到当前坐标下的地形高度时 手动设置为初始点的高度 230 | item.height = tempHeight; 231 | } else { 232 | item.height += offset; 233 | } 234 | } 235 | var raisedPositions = ellipsoid.cartographicArrayToCartesianArray(updateLnglats); //转为世界坐标数组 236 | for (var z = 0; z < raisedPositions.length - 1; z++) { 237 | allLength += Cesium.Cartesian3.distance(raisedPositions[z], raisedPositions[z + 1]); 238 | } 239 | if (allLength) 240 | callback(allLength); 241 | }); 242 | 243 | } 244 | 245 | 246 | 247 | // 坡度量算 248 | getSlope(position, callback) { 249 | if (!position) return; 250 | // 求出该点周围两点的坐标 构建平面 251 | var ctg = Cesium.Cartographic.fromCartesian(position); 252 | var random = 1 / 100000; 253 | var lat = Cesium.Math.toDegrees(ctg.latitude); 254 | var lng = Cesium.Math.toDegrees(ctg.longitude); 255 | var height = ctg.height; 256 | var newCtg1 = Cesium.Cartographic.fromDegrees(lng, lat + random); 257 | var newCtg2 = Cesium.Cartographic.fromDegrees(lng + random, lat); 258 | var that = this; 259 | Cesium.when(Cesium.sampleTerrainMostDetailed(this.viewer.terrainProvider, [newCtg1, newCtg2]), function (updateLnglats) { 260 | for (var i = 0; i < updateLnglats.length; i++) { 261 | var item = updateLnglats[i]; 262 | item.height = item.height ? item.height : height; 263 | } 264 | var raisedPositions = that.viewer.scene.globe.ellipsoid.cartographicArrayToCartesianArray(updateLnglats); //转为世界坐标数组 265 | var newPosition1 = raisedPositions[0]; 266 | var newPosition2 = raisedPositions[1]; 267 | var mtx = Cesium.Transforms.eastNorthUpToFixedFrame(position); 268 | var mtx_inverse = Cesium.Matrix4.inverse(mtx, new Cesium.Matrix4()); 269 | 270 | position = Cesium.Matrix4.multiplyByPoint(mtx_inverse, position, new Cesium.Cartesian3()); 271 | newPosition1 = Cesium.Matrix4.multiplyByPoint(mtx_inverse, newPosition1, new Cesium.Cartesian3()); 272 | newPosition2 = Cesium.Matrix4.multiplyByPoint(mtx_inverse, newPosition2, new Cesium.Cartesian3()); 273 | 274 | var v1 = Cesium.Cartesian3.subtract(newPosition1, position, new Cesium.Cartesian3()); 275 | var v2 = Cesium.Cartesian3.subtract(newPosition2, position, new Cesium.Cartesian3()); 276 | var cross = Cesium.Cartesian3.cross(v1, v2, new Cesium.Cartesian3()); 277 | cross = Cesium.Cartesian3.normalize(cross, new Cesium.Cartesian3()); 278 | var z = new Cesium.Cartesian3(0, 0, 1); 279 | var arc = Cesium.Cartesian3.dot(cross, z); 280 | var radians_north = Math.acos(arc); 281 | var dg = Cesium.Math.toDegrees(radians_north); 282 | dg = dg > 90 ? (180 - dg) : dg; 283 | if (callback) callback(dg); 284 | }); 285 | } 286 | 287 | getLength(c1, c2) { 288 | if (!c1 || !c2) return 0; 289 | return Cesium.Cartesian3.distance(c1, c2) || 0; 290 | } 291 | 292 | //调用第三方插件计算面积 turf 293 | getAreaAndCenter(positions) { 294 | if (!positions || positions.length < 1) return; 295 | var cartographics = []; 296 | var turfPoints = []; 297 | for (var i = 0; i < positions.length; i++) { 298 | var cartesian3 = positions[i]; 299 | var cartographic = Cesium.Cartographic.fromCartesian(cartesian3); 300 | cartographics.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]); 301 | turfPoints.push(turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)])); 302 | } 303 | if (!cartographics.length) return; 304 | cartographics = cartographics.concat([cartographics[0]]); 305 | var polygon = turf.polygon([cartographics]); 306 | var area = turf.area(polygon); 307 | //获取当前范围的中心点 308 | var features = turf.featureCollection(turfPoints); 309 | var turfCenter = turf.center(features); 310 | var center = turfCenter.geometry.coordinates; 311 | 312 | return { 313 | area: area, 314 | center: Cesium.Cartesian3.fromDegrees(center[0], center[1]) 315 | }; 316 | } 317 | 318 | // 构建控制点 319 | createPoint(position) { 320 | if (!position) return; 321 | this.pointStyle.color = this.pointStyle.color || Cesium.Color.AQUA; 322 | this.pointStyle.outlineColor = this.pointStyle.color || Cesium.Color.WHITE; 323 | 324 | let color = this.pointStyle.color instanceof Cesium.Color ? this.pointStyle.color : Cesium.Color.fromCssColorString(this.pointStyle.color); 325 | color = color.withAlpha(this.pointStyle.colorAlpha || 0.8); 326 | 327 | let outlineColor = this.pointStyle.outlineColor instanceof Cesium.Color ? this.pointStyle.outlineColor : Cesium.Color.fromCssColorString(this.pointStyle.outlineColor); 328 | outlineColor = outlineColor.withAlpha(this.pointStyle.outlineColorAlpha || 0.8); 329 | 330 | return this.viewer.entities.add({ 331 | position: position, 332 | point: { 333 | pixelSize: this.pointStyle.pixelSize || 6, 334 | color: color, 335 | outlineWidth: this.pointStyle.outlineWidth || 1, 336 | outlineColor: outlineColor, 337 | disableDepthTestDistance: Number.POSITIVE_INFINITY 338 | }, 339 | show: false 340 | }); 341 | } 342 | 343 | /** 344 | * 销毁 345 | */ 346 | destroy(){ 347 | 348 | } 349 | 350 | /** 351 | * 结束编辑 352 | */ 353 | endEdit(){} 354 | 355 | /** 356 | * 357 | * 开始编辑 358 | * @param {Function} callback 编辑成功后回调函数 359 | */ 360 | startEdit(){ 361 | 362 | } 363 | 364 | /** 365 | * 开始绘制 366 | * @param {Function} callback 绘制成功后回调函数 367 | */ 368 | start(){} 369 | 370 | } 371 | 372 | export default BaseMeasure; -------------------------------------------------------------------------------- /src/js/measure/measureAzimuth.js: -------------------------------------------------------------------------------- 1 | //方位角测量js 2 | import BaseMeasure from "./baseMeasure"; 3 | import '../prompt/prompt.css' 4 | import Prompt from '../prompt/prompt.js' 5 | /** 6 | * 方位角测量类 7 | * @class 8 | * @augments BaseMeasure 9 | * @alias BaseMeasure.MeasureAzimutht 10 | */ 11 | class MeasureAzimutht extends BaseMeasure { 12 | /** 13 | * 14 | * @param {Cesium.Viewer} viewer 地图viewer对象 15 | * @param {Object} opt 基础配置 16 | */ 17 | constructor(viewer, opt) { 18 | super(viewer, opt); 19 | 20 | /** 21 | * @property {Object} style 绘制样式(polyline),具体配置见{@link style}; 22 | */ 23 | this.style = opt.style || {}; 24 | 25 | /** 26 | * @property {Cesium.Entity} polyline 线 27 | */ 28 | this.polyline = null; 29 | this.floatLabel = null; 30 | 31 | /** 32 | * @property {Cesium.Cartesian3[]} positions 线坐标数组 33 | */ 34 | this.positions = []; 35 | this.mtx = null; 36 | this.azimutht = null; 37 | } 38 | 39 | /** 40 | * 开始绘制 41 | * @param {Function} callback 绘制成功后回调函数 42 | */ 43 | start(callback) { 44 | let that = this; 45 | this.state = "startCreate"; 46 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 47 | 48 | this.handler.setInputAction(function (evt) { //单击开始绘制 49 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 50 | if (!cartesian) return; 51 | if (that.positions.length == 2) { 52 | that.positions.pop(); 53 | let point = that.createPoint(cartesian.clone()); 54 | point.wz = 1; 55 | that.controlPoints.push(point); 56 | that.state = "endCreate"; 57 | that.endCreate(); 58 | if (callback) callback(that.azimutht); 59 | } 60 | 61 | if (!that.polyline) { 62 | that.polyline = that.createLine(that.positions, true); 63 | that.polyline.objId = that.objId; 64 | that.polyline.polyline.width = 6; 65 | that.polyline.polyline.material = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.YELLOW); 66 | } 67 | 68 | that.positions.push(cartesian); 69 | if (that.positions.length == 1) { 70 | that.mtx = Cesium.Transforms.eastNorthUpToFixedFrame(that.positions[0].clone()); 71 | that.floatLabel = that.createLabel(cartesian, ""); 72 | let point = that.createPoint(cartesian.clone()); 73 | point.wz = 0; 74 | that.controlPoints.push(point); 75 | } 76 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 77 | 78 | this.handler.setInputAction(function (evt) { 79 | if (that.positions.length < 1) { 80 | that.prompt.update(evt.endPosition, "单击开始测量"); 81 | return; 82 | } 83 | that.prompt.update(evt.endPosition, "单击结束"); 84 | that.state = "creating"; 85 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 86 | if (!cartesian) return; 87 | 88 | if (that.positions.length < 2) { 89 | that.positions.push(cartesian.clone()); 90 | } else { 91 | that.positions[1] = cartesian.clone(); 92 | } 93 | 94 | if (that.floatLabel) { 95 | that.azimutht = that.getAzimuthtAndCenter(that.mtx, that.positions); 96 | that.floatLabel.label.text = "方位角:" + that.azimutht.toFixed(2); 97 | } 98 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 99 | } 100 | 101 | /** 102 | * 结束创建 103 | */ 104 | endCreate() { 105 | let that = this; 106 | that.state = "endCreate"; 107 | if (that.prompt) { 108 | that.prompt.destroy(); 109 | that.prompt = null; 110 | } 111 | if (that.handler) { 112 | that.handler.destroy(); 113 | that.handler = null; 114 | } 115 | } 116 | 117 | done() { 118 | if (this.state == "startCreate") { 119 | this.destroy(); 120 | } else if (this.state == "startEdit" || this.state == "editing") { 121 | this.endEdit(); 122 | } else { 123 | this.endCreate(); 124 | } 125 | } 126 | 127 | /** 128 | * 129 | * 开始编辑 130 | * @param {Function} callback 编辑成功后回调函数 131 | */ 132 | startEdit(callback) { 133 | if (!((this.state == "endCrerate" || this.state == "endEdit") && this.polyline)) return; 134 | this.state = "startEdit";; 135 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 136 | let that = this; 137 | for (let i = 0; i < that.controlPoints.length; i++) { 138 | let point = that.controlPoints[i]; 139 | if (point) point.show = true; 140 | } 141 | this.modifyHandler.setInputAction(function (evt) { 142 | let pick = that.viewer.scene.pick(evt.position); 143 | if (Cesium.defined(pick) && pick.id) { 144 | if (!pick.id.objId) 145 | that.modifyPoint = pick.id; 146 | that.forbidDrawWorld(true); 147 | } 148 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 149 | this.modifyHandler.setInputAction(function (evt) { 150 | if (that.positions.length < 1 || !that.modifyPoint) return; 151 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 152 | if (!cartesian) return; 153 | that.modifyPoint.position.setValue(cartesian.clone()); 154 | if (that.modifyPoint.wz == 0) { 155 | that.floatLabel.position.setValue(cartesian.clone()); 156 | that.mtx = Cesium.Transforms.eastNorthUpToFixedFrame(that.positions[0].clone()); 157 | } 158 | that.positions[that.modifyPoint.wz] = cartesian.clone(); 159 | that.azimutht = that.getAzimuthtAndCenter(that.mtx, that.positions); 160 | that.floatLabel.label.text = "方位角:" + that.azimutht.toFixed(2); 161 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 162 | 163 | this.modifyHandler.setInputAction(function (evt) { 164 | if (!that.modifyPoint) return; 165 | that.modifyPoint = null; 166 | that.lastPosition = null; 167 | that.nextPosition = null; 168 | that.forbidDrawWorld(false); 169 | if (callback) callback(); 170 | that.state = "endEdit"; 171 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 172 | } 173 | 174 | /** 175 | * 结束编辑 176 | */ 177 | endEdit() { 178 | let that = this; 179 | this.state = "endEdit";; 180 | if (this.modifyHandler) { 181 | this.modifyHandler.destroy(); 182 | this.modifyHandler = null; 183 | } 184 | for (let i = 0; i < that.controlPoints.length; i++) { 185 | let point = that.controlPoints[i]; 186 | if (point) point.show = false; 187 | } 188 | } 189 | 190 | 191 | /** 192 | * 销毁 193 | */ 194 | destroy() { 195 | if (this.polyline) { 196 | this.viewer.entities.remove(this.polyline); 197 | this.polyline = null; 198 | } 199 | if (this.floatLabel) { 200 | this.viewer.entities.remove(this.floatLabel); 201 | this.floatLabel = null; 202 | } 203 | this.floatLable = null; 204 | 205 | if (this.handler) { 206 | this.handler.destroy(); 207 | this.handler = null; 208 | } 209 | this.state = "no"; 210 | if (this.prompt) { 211 | this.prompt.destroy(); 212 | this.prompt = null; 213 | } 214 | } 215 | } 216 | 217 | export default MeasureAzimutht; 218 | 219 | -------------------------------------------------------------------------------- /src/js/measure/measureGroundDistance.js: -------------------------------------------------------------------------------- 1 | // 贴地距离量算js 2 | import BaseMeasure from "./baseMeasure"; 3 | import '../prompt/prompt.css' 4 | import Prompt from '../prompt/prompt.js' 5 | /** 6 | * 贴地距离测量类 7 | * @class 8 | * @augments BaseMeasure 9 | * @alias BaseMeasure.MeasureGroundDistance 10 | */ 11 | class MeasureGroundDistance extends BaseMeasure { 12 | constructor(viewer, opt) { 13 | super(viewer, opt); 14 | this.unitType = "length"; 15 | this.type = "groundDistance" 16 | if (!opt) opt = {}; 17 | this.style = opt.style || {}; 18 | this.viewer = viewer; 19 | //线 20 | this.polyline = null; 21 | //线坐标 22 | this.positions = []; 23 | //标签数组 24 | this.labels = []; 25 | this.nowLabel = null; // 编辑时 当前点的label 26 | this.nextlabel = null; // 编辑时 下一个点的label 27 | this.lastPosition = null;// 编辑时 上一个点的坐标 28 | this.nextPosition = null;// 编辑时 下一个点的坐标 29 | this.modifyPoint = null; 30 | this.lastCartesian = null; 31 | this.allDistance = 0; 32 | this.prompt; 33 | this.movePush = false; 34 | this.floatDistance = -1; 35 | } 36 | 37 | //开始测量 38 | start(callback) { 39 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 40 | let that = this; 41 | this.state = "startCreate"; 42 | this.handler.setInputAction(function (evt) { //单击开始绘制 43 | that.state = "creating"; 44 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 45 | if (!cartesian) return; 46 | if (that.movePush) { 47 | that.positions.pop(); 48 | that.movePush = false; 49 | } 50 | 51 | if (!that.floatLable) { 52 | that.floatLable = that.createLabel(cartesian, ""); 53 | that.floatLable.wz = 0; 54 | that.floatLable.show = false; 55 | } 56 | 57 | let label = that.createLabel(cartesian, ""); 58 | label.wz = that.positions.length; 59 | that.labels.push(label); 60 | 61 | let point = that.createPoint(cartesian.clone()); 62 | point.wz = that.positions.length; 63 | that.controlPoints.push(point); 64 | 65 | if (that.positions.length == 0) { 66 | label.label.text = "起点"; 67 | } else { 68 | that.lastDistance = that.floatDistance; 69 | that.allDistance += that.floatDistance; 70 | let text = that.formateLength(that.floatDistance); 71 | label.label.text = text; 72 | label.distance = that.floatDistance; 73 | } 74 | 75 | that.positions.push(cartesian.clone()); 76 | that.lastCartesian = cartesian.clone(); 77 | 78 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 79 | this.handler.setInputAction(function (evt) { 80 | that.state = "creating"; 81 | if (that.positions.length < 1) { 82 | that.prompt.update(evt.endPosition, "单击开始测量"); 83 | return; 84 | } 85 | 86 | that.prompt.update(evt.endPosition, "双击结束,右键取消上一步"); 87 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 88 | if (!cartesian) return; 89 | if (!that.movePush) { 90 | that.positions.push(cartesian); 91 | that.movePush = true; 92 | } else { 93 | that.positions[that.positions.length - 1] = cartesian.clone(); 94 | } 95 | 96 | if (!Cesium.defined(that.polyline)) { 97 | that.polyline = that.createLine(that.positions, true); 98 | that.polyline.objId = that.objId; 99 | } 100 | if (!that.lastCartesian) return; 101 | that.getGroundLength([cartesian, that.lastCartesian], function (distance) { 102 | that.floatLable.show = true; 103 | that.floatLable.label.text = that.formateLength(distance, that.unit); 104 | that.floatLable.position.setValue(cartesian); 105 | that.floatLable.distance = distance; 106 | if (distance) that.floatDistance = distance; 107 | /* if (that.fun) that.fun(distance); */ 108 | }); 109 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 110 | 111 | this.handler.setInputAction(function (evt) { 112 | that.state = "creating"; 113 | if (!that.polyline) return; 114 | if (that.positions.length <= 2) return; // 默认最后一个不给删除 115 | 116 | that.positions.splice(that.positions.length - 2, 1); 117 | that.viewer.entities.remove(that.labels.pop()); 118 | that.viewer.entities.remove(that.controlPoints.pop()); // 移除最后一个 119 | 120 | that.allDistance = that.allDistance - that.lastDistance; 121 | if (that.positions.length == 1) { 122 | if (that.polyline) { 123 | that.viewer.entities.remove(that.polyline); 124 | that.polyline = null; 125 | } 126 | that.prompt.update(evt.endPosition, "单击开始测量"); 127 | that.floatLable.show = false; 128 | that.positions = []; 129 | } 130 | 131 | if (!that.movePush) { 132 | that.lastCartesian = that.positions[that.positions.length - 1]; 133 | } else { 134 | that.lastCartesian = that.positions[that.positions.length - 2]; 135 | } 136 | 137 | 138 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 139 | if (!cartesian) return; 140 | that.getGroundLength([cartesian, that.positions[that.positions.length - 2]], function (distance) { 141 | that.floatLable.show = true; 142 | that.floatLable.label.text = that.formateLength(distance, that.unit); 143 | that.floatLable.distance = distance; 144 | that.floatLable.position.setValue(cartesian); 145 | }); 146 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 147 | 148 | this.handler.setInputAction(function (evt) { //双击结束绘制 149 | // 移除双击事件多生成的最后一个 150 | that.positions.pop(); 151 | that.viewer.entities.remove(that.labels.pop()); 152 | that.viewer.entities.remove(that.controlPoints.pop()); 153 | 154 | that.movePush = false; 155 | that.endCreate(); 156 | if (callback) callback(); 157 | }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); 158 | } 159 | 160 | endCreate() { 161 | let that = this; 162 | if (!that.polyline) return; 163 | that.floatLable.show = false; 164 | that.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 165 | that.viewer.trackedEntity = undefined; 166 | 167 | let allDistance = that.formateLength(that.allDistance, that.unit); 168 | that.labels[that.labels.length - 1].label.text = "总长:" + allDistance; 169 | 170 | if (that.handler) { 171 | that.handler.destroy(); 172 | that.handler = null; 173 | } 174 | if (that.prompt) { 175 | that.prompt.destroy(); 176 | that.prompt = null; 177 | } 178 | that.state = "endCreate"; 179 | } 180 | 181 | done() { 182 | if (this.state == "startCreate") { 183 | this.destroy(); 184 | } else if (this.state == "creating") { 185 | if (this.positions.length <= 2 && this.movePush == true) { 186 | this.destroy(); 187 | } else { 188 | this.endCreate(); 189 | } 190 | } else if (this.state == "startEdit" || this.state == "editing") { 191 | this.endEdit(); 192 | } else { 193 | 194 | } 195 | } 196 | 197 | // 开始编辑 198 | startEdit(callback) { 199 | 200 | if (!((this.state == "endCrerate" || this.state == "endEdit") && this.polyline)) return; 201 | this.state = "startEdit"; 202 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 203 | let that = this; 204 | for (let i = 0; i < that.controlPoints.length; i++) { 205 | let point = that.controlPoints[i]; 206 | if (point) point.show = true; 207 | } 208 | this.modifyHandler.setInputAction(function (evt) { 209 | let pick = that.viewer.scene.pick(evt.position); 210 | if (Cesium.defined(pick) && pick.id) { 211 | if (!pick.id.objId) 212 | that.modifyPoint = pick.id; 213 | that.forbidDrawWorld(true); 214 | let wz = that.modifyPoint.wz; 215 | // 重新计算左右距离 216 | let nextIndex = wz + 1; 217 | let lastIndex = wz - 1; 218 | that.nowLabel = that.labels[wz]; 219 | if (lastIndex >= 0) { 220 | that.lastPosition = that.positions[lastIndex]; 221 | } 222 | if (nextIndex <= that.positions.length - 1) { 223 | that.nextPosition = that.positions[nextIndex]; 224 | that.nextlabel = that.labels[nextIndex]; 225 | } 226 | } 227 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 228 | this.modifyHandler.setInputAction(function (evt) { 229 | 230 | if (that.positions.length < 1 || !that.modifyPoint) return; 231 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 232 | 233 | if (!cartesian) return; 234 | that.modifyPoint.position.setValue(cartesian); 235 | 236 | let wz = that.modifyPoint.wz; 237 | that.positions[wz] = cartesian.clone(); 238 | that.state = "editing"; 239 | that.nowLabel.position.setValue(cartesian.clone()); 240 | let changeDis1 = 0; 241 | let changeDis2 = 0; 242 | if (that.nowLabel && that.lastPosition) { 243 | that.getGroundLength([cartesian.clone(), that.lastPosition.clone()], function (distance) { 244 | that.nowLabel.label.text = that.formateLength(distance, that.unit); 245 | changeDis1 = distance - that.nowLabel.distance; 246 | that.nowLabel.distance = distance; 247 | // 计算总长 248 | that.allDistance = that.allDistance + changeDis1 + changeDis2; 249 | let allDistance = that.formateLength(that.allDistance, that.unit); 250 | that.labels[that.labels.length - 1].label.text = "总长:" + allDistance; 251 | }); 252 | } 253 | if (that.nextPosition && that.nextlabel) { 254 | that.getGroundLength([cartesian.clone(), that.nextPosition.clone()], function (distance) { 255 | that.nextlabel.label.text = that.formateLength(distance, that.unit); 256 | changeDis2 = distance - that.nextlabel.distance; 257 | that.nextlabel.distance = distance; 258 | // 计算总长 259 | that.allDistance = that.allDistance + changeDis1 + changeDis2; 260 | let allDistance = that.formateLength(that.allDistance, that.unit); 261 | that.labels[that.labels.length - 1].label.text = "总长:" + allDistance; 262 | }); 263 | } 264 | 265 | 266 | 267 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 268 | 269 | this.modifyHandler.setInputAction(function (evt) { 270 | if (!that.modifyPoint) return; 271 | that.modifyPoint = null; 272 | that.lastPosition = null; 273 | that.nextPosition = null; 274 | that.forbidDrawWorld(false); 275 | if (callback) callback(); 276 | that.state = "endEdit"; 277 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 278 | } 279 | 280 | /** 281 | * 结束编辑 282 | */ 283 | endEdit() { 284 | let that = this; 285 | this.state = "endEdit";; 286 | if (this.modifyHandler) { 287 | this.modifyHandler.destroy(); 288 | this.modifyHandler = null; 289 | } 290 | for (let i = 0; i < that.controlPoints.length; i++) { 291 | let point = that.controlPoints[i]; 292 | if (point) point.show = false; 293 | } 294 | } 295 | 296 | 297 | /** 298 | * 销毁 299 | */ 300 | destroy() { 301 | if (this.polyline) { 302 | this.viewer.entities.remove(this.polyline); 303 | this.polyline = null; 304 | } 305 | for (let i = 0; i < this.labels.length; i++) { 306 | this.viewer.entities.remove(this.labels[i]); 307 | } 308 | this.labels = []; 309 | for (let ind = 0; ind < this.controlPoints.length; ind++) { 310 | this.viewer.entities.remove(this.controlPoints[ind]); 311 | } 312 | this.controlPoints = []; 313 | this.modifyPoint = null; 314 | if (this.floatLable) { 315 | this.viewer.entities.remove(this.floatLable); 316 | this.floatLable = null; 317 | } 318 | this.floatLable = null; 319 | 320 | if (this.prompt) { 321 | this.prompt.destroy(); 322 | this.prompt = null; 323 | } 324 | if (this.handler) { 325 | this.handler.destroy(); 326 | this.handler = null; 327 | } 328 | if (this.modifyHandler) { 329 | this.modifyHandler.destroy(); 330 | this.modifyHandler = null; 331 | } 332 | this.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 333 | this.viewer.trackedEntity = undefined; 334 | this.state = "no"; 335 | } 336 | 337 | // 设置单位 338 | setUnit(unit) { 339 | for (let i = 1; i < this.labels.length; i++) { 340 | let labelEnt = this.labels[i]; 341 | let distance = labelEnt.distance; 342 | let label = labelEnt.label; 343 | if (!label) continue; 344 | if (i == this.labels.length - 1) { 345 | label.text = "总长:" + this.formateLength(distance, unit); 346 | } else { 347 | label.text = this.formateLength(distance, unit); 348 | } 349 | } 350 | this.unit = unit; 351 | } 352 | 353 | } 354 | export default MeasureGroundDistance; -------------------------------------------------------------------------------- /src/js/measure/measureHeight.js: -------------------------------------------------------------------------------- 1 | //高度测量js 2 | import BaseMeasure from "./baseMeasure"; 3 | import '../prompt/prompt.css' 4 | import Prompt from '../prompt/prompt.js' 5 | /** 6 | * 高度测量类 7 | * @class 8 | * @augments BaseMeasure 9 | * @alias BaseMeasure.MeasureHeight 10 | */ 11 | class MeasureHeight extends BaseMeasure { 12 | constructor(viewer, opt) { 13 | super(viewer, opt); 14 | if (!opt) opt = {}; 15 | this.unitType = "length"; 16 | this.style = opt.style || {}; 17 | this.viewer = viewer; 18 | this.polyline = null; 19 | this.floatLabel = null; 20 | this.positions = []; 21 | } 22 | 23 | //开始测量 24 | start(callback) { 25 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 26 | this.state = "startCreate"; 27 | let that = this; 28 | this.handler.setInputAction(function (evt) { //单击开始绘制 29 | that.state = "creating" 30 | var cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 31 | if (!cartesian) return; 32 | 33 | if (that.positions.length == 2) { 34 | that.positions[1] = cartesian.clone(); 35 | 36 | let point = that.createPoint(cartesian.clone()); 37 | point.wz = 1; 38 | that.controlPoints.push(point); 39 | 40 | that.endCreate(); 41 | if (callback) callback(); 42 | } else { 43 | that.polyline = that.createLine(that.positions, false); 44 | that.polyline.objId = that.objId; 45 | if (!that.floatLabel) that.floatLabel = that.createLabel(cartesian.clone(), ""); 46 | that.positions.push(cartesian.clone()); 47 | let point = that.createPoint(cartesian.clone()); 48 | point.wz = 0; 49 | that.controlPoints.push(point); 50 | } 51 | 52 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 53 | 54 | this.handler.setInputAction(function (evt) { 55 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 56 | that.state = "creating" 57 | if (that.positions.length < 1) { 58 | that.prompt.update(evt.endPosition, "单击开始测量"); 59 | return; 60 | } 61 | that.prompt.update(evt.endPosition, "单击结束"); 62 | if (!cartesian) return; 63 | if (that.positions.length < 2) { 64 | that.positions.push(cartesian.clone()); 65 | } else { 66 | that.positions[1] = cartesian.clone(); 67 | } 68 | 69 | let heightAndCenter = that.getHeightAndCenter(that.positions[0], that.positions[1]); 70 | let text = that.formateLength(heightAndCenter.height, that.unit); 71 | that.floatLabel.label.text = "高度差:" + text; 72 | that.floatLabel.length = heightAndCenter.height; 73 | if (heightAndCenter.center) that.floatLabel.position.setValue(heightAndCenter.center); 74 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 75 | } 76 | 77 | endCreate() { 78 | let that = this; 79 | if (that.handler) { 80 | that.handler.destroy(); 81 | that.handler = null; 82 | } 83 | if (that.prompt) { 84 | that.prompt.destroy(); 85 | that.prompt = null; 86 | } 87 | that.state = "endCreate"; 88 | } 89 | done() { 90 | if (this.state == "startCreate") { 91 | this.destroy(); 92 | } else if (this.state == "startEdit" || this.state == "editing") { 93 | this.endEdit(); 94 | } else { 95 | this.endCreate(); 96 | } 97 | } 98 | 99 | startEdit(callback) { 100 | if (!((this.state == "endCrerate" || this.state == "endEdit") && this.polyline)) return; 101 | this.state = "startEdit";; 102 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 103 | let that = this; 104 | for (let i = 0; i < that.controlPoints.length; i++) { 105 | let point = that.controlPoints[i]; 106 | if (point) point.show = true; 107 | } 108 | this.modifyHandler.setInputAction(function (evt) { 109 | let pick = that.viewer.scene.pick(evt.position); 110 | if (Cesium.defined(pick) && pick.id) { 111 | if (!pick.id.objId) 112 | that.modifyPoint = pick.id; 113 | that.forbidDrawWorld(true); 114 | } 115 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 116 | 117 | this.modifyHandler.setInputAction(function (evt) { 118 | if (that.positions.length < 1 || !that.modifyPoint) return; 119 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 120 | if (!cartesian) return; 121 | that.modifyPoint.position.setValue(cartesian.clone()); 122 | 123 | that.positions[that.modifyPoint.wz] = cartesian.clone(); 124 | let heightAndCenter = that.getHeightAndCenter(that.positions[0], that.positions[1]); 125 | let text = that.formateLength(heightAndCenter.height, that.unit); 126 | that.floatLabel.label.text = "高度差:" + text; 127 | that.floatLabel.length = heightAndCenter.height; 128 | if (heightAndCenter.center) that.floatLabel.position.setValue(heightAndCenter.center); 129 | 130 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 131 | 132 | this.modifyHandler.setInputAction(function (evt) { 133 | if (!that.modifyPoint) return; 134 | that.modifyPoint = null; 135 | that.lastPosition = null; 136 | that.nextPosition = null; 137 | that.forbidDrawWorld(false); 138 | if (callback) callback(); 139 | that.state = "endEdit"; 140 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 141 | } 142 | 143 | endEdit() { 144 | let that = this; 145 | this.state = "endEdit";; 146 | if (this.modifyHandler) { 147 | this.modifyHandler.destroy(); 148 | this.modifyHandler = null; 149 | } 150 | for (let i = 0; i < that.controlPoints.length; i++) { 151 | let point = that.controlPoints[i]; 152 | if (point) point.show = false; 153 | } 154 | } 155 | 156 | //清除测量结果 157 | destroy() { 158 | if (this.polyline) { 159 | this.viewer.entities.remove(this.polyline); 160 | this.polyline = null; 161 | } 162 | if (this.floatLabel) { 163 | this.viewer.entities.remove(this.floatLabel); 164 | this.floatLabel = null; 165 | } 166 | if (this.prompt) { 167 | this.prompt.destroy(); 168 | this.prompt = null; 169 | } 170 | if (this.handler) { 171 | this.handler.destroy(); 172 | this.handler = null; 173 | } 174 | 175 | this.state = "no"; 176 | } 177 | getHeightAndCenter(p1, p2) { 178 | if (!p1 || !p2) return; 179 | var cartographic1 = Cesium.Cartographic.fromCartesian(p1); 180 | var cartographic2 = Cesium.Cartographic.fromCartesian(p2); 181 | var height = Math.abs(cartographic1.height - cartographic2.height); 182 | return { 183 | height: height, 184 | center: Cesium.Cartesian3.midpoint(p1, p2, new Cesium.Cartesian3()) 185 | }; 186 | } 187 | 188 | setUnit(unit) { 189 | let text = this.formateLength(this.floatLabel.length, unit); 190 | this.floatLabel.label.text = "高度差:" + text; 191 | this.unit = unit; 192 | } 193 | } 194 | 195 | export default MeasureHeight; -------------------------------------------------------------------------------- /src/js/measure/measureLnglat.js: -------------------------------------------------------------------------------- 1 | //经纬度 测量js 2 | import BaseMeasure from "./baseMeasure"; 3 | import util from "../util"; 4 | 5 | /** 6 | * 坐标测量类 7 | * @class 8 | * @augments BaseMeasure 9 | * @alias BaseMeasure.MeasureLnglat 10 | */ 11 | class MeasureLnglat extends BaseMeasure { 12 | constructor(viewer, opt) { 13 | super(viewer, opt); 14 | if (!opt) opt = {}; 15 | this.style = opt.style || {}; 16 | this.point = null; 17 | this.position = null; 18 | this.state = 0; 19 | } 20 | 21 | start(callback) { 22 | this.state = "startCreate"; 23 | var that = this; 24 | this.handler.setInputAction(function (evt) { //单击开始绘制 25 | if (that.handler) { 26 | that.handler.destroy(); 27 | that.handler = null; 28 | } 29 | that.state = "endCreate"; 30 | if (callback) callback(); 31 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 32 | this.handler.setInputAction(function (evt) { 33 | that.state = "creating"; 34 | var cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 35 | if (!cartesian) return; 36 | that.position = cartesian.clone(); 37 | if (!Cesium.defined(that.point)) { 38 | that.point = that.createPoint(); 39 | that.point.objId = that.objId; 40 | } 41 | var lnglat = util.cartesianToLnglat(cartesian,that.viewer); 42 | that.point.label.text = "经度:" + lnglat[0].toFixed(6) + "\n纬度:" + lnglat[1].toFixed(6) + "\n高度:" + lnglat[2].toFixed(2) + " m"; 43 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 44 | 45 | } 46 | 47 | endCreate() { 48 | let that = this; 49 | if (that.handler) { 50 | that.handler.destroy(); 51 | that.handler = null; 52 | } 53 | that.state = "endCreate"; 54 | } 55 | done() { 56 | if (this.state == "startCreate") { 57 | this.destroy(); 58 | } else if (this.state == "startEdit" || this.state == "editing") { 59 | this.endEdit(); 60 | } else { 61 | this.endCreate(); 62 | } 63 | } 64 | 65 | startEdit() { 66 | if (!((this.state == "endCrerate" || this.state == "endEdit") && this.point)) return; 67 | this.state = "startEdit";; 68 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 69 | this.modifyHandler.setInputAction(function (evt) { 70 | let pick = that.viewer.scene.pick(evt.position); 71 | if (Cesium.defined(pick) && pick.id) { 72 | if (!pick.id.objId) 73 | that.modifyPoint = pick.id; 74 | that.forbidDrawWorld(true); 75 | } 76 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 77 | 78 | this.modifyHandler.setInputAction(function (evt) { 79 | if (that.positions.length < 1 || !that.modifyPoint) return; 80 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 81 | if (!cartesian) return; 82 | that.modifyPoint.position.setValue(cartesian.clone()); 83 | 84 | that.positions[that.modifyPoint.wz] = cartesian.clone(); 85 | let heightAndCenter = that.getHeightAndCenter(that.positions[0], that.positions[1]); 86 | let text = that.formateLength(heightAndCenter.height, that.unit); 87 | that.floatLabel.label.text = "高度差:" + text; 88 | that.floatLabel.length = heightAndCenter.height; 89 | if (heightAndCenter.center) that.floatLabel.position.setValue(heightAndCenter.center); 90 | 91 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 92 | 93 | this.modifyHandler.setInputAction(function (evt) { 94 | if (!that.modifyPoint) return; 95 | that.modifyPoint = null; 96 | that.lastPosition = null; 97 | that.nextPosition = null; 98 | that.forbidDrawWorld(false); 99 | if (callback) callback(); 100 | that.state = "endEdit"; 101 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 102 | } 103 | 104 | endEdit() { 105 | 106 | } 107 | 108 | //清除测量结果 109 | destroy() { 110 | this.state = "no"; 111 | if (this.point) { 112 | this.viewer.entities.remove(this.point); 113 | this.point = null; 114 | } 115 | 116 | if (this.handler) { 117 | this.handler.destroy(); 118 | this.handler = null; 119 | } 120 | } 121 | 122 | createPoint() { 123 | var that = this; 124 | var point = this.viewer.entities.add({ 125 | position: new Cesium.CallbackProperty(function () { 126 | return that.position 127 | }, false), 128 | point: { 129 | show: true, 130 | outlineColor: Cesium.Color.YELLOW, 131 | outlineColor: Cesium.Color.WHITE, 132 | pixelSize: 6, 133 | outlineWidth: 2, 134 | disableDepthTestDistance: Number.MAX_VALUE 135 | }, 136 | label: { 137 | font: '18px Helvetica', 138 | fillColor: Cesium.Color.WHITE, 139 | outlineColor: Cesium.Color.BLACK, 140 | outlineWidth: 2, 141 | disableDepthTestDistance: Number.POSITIVE_INFINITY, 142 | style: Cesium.LabelStyle.FILL_AND_OUTLINE, 143 | pixelOffset: new Cesium.Cartesian2(0, -60) 144 | } 145 | }); 146 | return point; 147 | } 148 | 149 | } 150 | 151 | 152 | export default MeasureLnglat; -------------------------------------------------------------------------------- /src/js/measure/measureSection.js: -------------------------------------------------------------------------------- 1 | //剖面分析js 2 | import BaseMeasure from "./baseMeasure"; 3 | 4 | /** 5 | * 剖面测量类 6 | * @class 7 | * @augments BaseMeasure 8 | * @alias BaseMeasure.MeasureSection 9 | */ 10 | class MeasureSection extends BaseMeasure { 11 | constructor(viewer, opt) { 12 | super(viewer, opt); 13 | this.style = opt.style || {}; 14 | this.viewer = viewer; 15 | //线 16 | this.polyline = null; 17 | //线坐标 18 | this.positions = []; 19 | //标签数组 20 | this.movePush = false; 21 | this.prompt; 22 | this.isStart = false; 23 | this.firstPosition = null; 24 | this.state = "no"; 25 | } 26 | 27 | //开始测量 28 | start(callback) { 29 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer,this.promptStyle); 30 | var that = this; 31 | that.state = "startCreate"; 32 | this.handler.setInputAction(function (evt) { //单击开始绘制 33 | var cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 34 | if (!cartesian) return; 35 | if (!that.isStart) { 36 | that.isStart = true; 37 | that.firstPosition = cartesian; 38 | } else { 39 | if (that.handler) { 40 | that.handler.destroy(); 41 | that.handler = null; 42 | } 43 | if (that.prompt) { 44 | that.prompt.destroy(); 45 | that.prompt = null; 46 | } 47 | 48 | // 生成剖面图数据 49 | that.getHeight(that.positions, function (data) { 50 | callback(data); 51 | }); 52 | that.state = "endCreate"; 53 | } 54 | 55 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 56 | this.handler.setInputAction(function (evt) { //移动时绘制线 57 | that.state = "creating"; 58 | if (!that.isStart) { 59 | that.prompt.update(evt.endPosition, "单击开始"); 60 | return; 61 | } 62 | that.prompt.update(evt.endPosition, "再次单击结束"); 63 | var cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 64 | that.positions = [that.firstPosition, cartesian]; 65 | if (!that.polyline) { 66 | that.polyline = that.viewer.entities.add({ 67 | polyline: { 68 | show: true, 69 | positions: new Cesium.CallbackProperty(function () { 70 | return that.positions 71 | }, false), 72 | material: Cesium.Color.GREEN, 73 | width: 3, 74 | clampToGround: true 75 | } 76 | }); 77 | } 78 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 79 | } 80 | //清除测量结果 81 | destroy() { 82 | if (this.polyline) { 83 | this.viewer.entities.remove(this.polyline); 84 | this.polyline = null; 85 | } 86 | 87 | if (this.prompt) { 88 | this.prompt.destroy(); 89 | this.prompt = null; 90 | } 91 | if (this.handler) { 92 | this.handler.destroy(); 93 | this.handler = null; 94 | } 95 | this.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 96 | this.viewer.trackedEntity = undefined; 97 | 98 | this.state = "no"; 99 | 100 | } 101 | 102 | getHeight(positions, callback) { 103 | if (!positions || positions.length < 1) return; 104 | // 求出该点周围两点的坐标 构建平面 105 | positions = util.lerpPositions(positions); 106 | var ctgs = []; 107 | positions.forEach(function (item) { 108 | ctgs.push(Cesium.Cartographic.fromCartesian(item)); 109 | }); 110 | if (!ctgs || ctgs.length < 1) return; 111 | var first = Cesium.Cartographic.fromCartesian(positions[0]); 112 | var height = first.height; 113 | Cesium.when(Cesium.sampleTerrainMostDetailed(this.viewer.terrainProvider, ctgs), function (updateLnglats) { 114 | for (var i = 0; i < updateLnglats.length; i++) { 115 | var item = updateLnglats[i]; 116 | item.height = item.height ? item.height : height; 117 | } 118 | if (callback) callback({ 119 | positions: positions, 120 | lnglats: updateLnglats 121 | }) 122 | }); 123 | } 124 | } 125 | 126 | 127 | export default MeasureSection; -------------------------------------------------------------------------------- /src/js/measure/measureSpaceArea.js: -------------------------------------------------------------------------------- 1 | //空间面积测量js 2 | import BaseMeasure from "./baseMeasure"; 3 | import '../prompt/prompt.css' 4 | import Prompt from '../prompt/prompt.js' 5 | 6 | /** 7 | * 空间面积测量类 8 | * @class 9 | * @augments BaseMeasure 10 | * @alias BaseMeasure.MeasureSpaceArea 11 | */ 12 | class MeasureSpaceArea extends BaseMeasure { 13 | constructor(viewer, opt) { 14 | super(viewer, opt); 15 | if (!opt) opt = {}; 16 | this.unitType = "area"; 17 | this.style = opt.style || {}; 18 | this.viewer = viewer; 19 | this.polyline = null; 20 | this.polygon = null; 21 | //面积标签 22 | this.positions = []; 23 | this.movePush = false; 24 | this.prompt = undefined; 25 | } 26 | 27 | //开始测量 28 | start(callback) { 29 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 30 | var that = this; 31 | this.state = "startCreate"; 32 | this.handler.setInputAction(function (evt) { 33 | that.state = "creating"; 34 | var cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 35 | if (!cartesian) return; 36 | if (that.movePush) { 37 | that.positions.pop(); 38 | that.movePush = false; 39 | } 40 | let point = that.createPoint(cartesian.clone()); 41 | point.wz = that.positions.length; // 和坐标点关联 42 | that.controlPoints.push(point); 43 | that.positions.push(cartesian); 44 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 45 | 46 | this.handler.setInputAction(function (evt) { 47 | that.state = "creating"; 48 | if (that.positions.length < 1) { 49 | that.prompt.update(evt.endPosition, "单击开始绘制"); 50 | return; 51 | } 52 | that.prompt.update(evt.endPosition, "双击结束,右键取消上一步"); 53 | var cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 54 | if (that.positions.length >= 1) { 55 | if (!that.movePush) { 56 | that.positions.push(cartesian); 57 | that.movePush = true; 58 | } else { 59 | that.positions[that.positions.length - 1] = cartesian; 60 | } 61 | if (that.positions.length == 2) { 62 | if (!Cesium.defined(that.polyline)) { 63 | that.polyline = that.createPolyline(); 64 | } 65 | } 66 | if (that.positions.length == 3) { 67 | if (!Cesium.defined(that.polygon)) { 68 | that.polygon = that.createPolygon(); 69 | that.polygon.isFilter = true; 70 | that.polygon.objId = that.objId; 71 | /* if (that.polyline) that.polyline.show = false; */ 72 | } 73 | if (!that.floatLabel) { 74 | that.floatLabel = that.createLabel(cartesian, ""); 75 | that.floatLabel.label.heightReference = 1; 76 | } 77 | } 78 | if (that.polygon) { 79 | let areaCenter = that.getAreaAndCenter(that.positions) 80 | var area = areaCenter.area; 81 | var center = areaCenter.center; 82 | 83 | var text = that.formateArea(area, that.unit); 84 | that.floatLabel.label.text = "面积:" + text; 85 | that.floatLabel.area = area; 86 | if (center) that.floatLabel.position.setValue(center); 87 | that.floatLabel.show = true; 88 | } 89 | } 90 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 91 | 92 | this.handler.setInputAction(function (evt) { 93 | that.state = "creating"; 94 | if (!that.polyline && !that.polygon) return; 95 | that.positions.splice(that.positions.length - 2, 1); 96 | that.viewer.entities.remove(that.controlPoints.pop()); 97 | if (that.positions.length == 2) { 98 | if (that.polygon) { 99 | that.viewer.entities.remove(that.polygon); 100 | that.polygon = null; 101 | if (that.polyline) that.polyline.show = true; 102 | } 103 | that.floatLabel.show = false; 104 | } 105 | 106 | if (that.positions.length == 1) { 107 | if (that.polyline) { 108 | that.viewer.entities.remove(that.polyline); 109 | that.polyline = null; 110 | } 111 | that.prompt.update(evt.endPosition, "单击开始测量"); 112 | that.positions = []; 113 | that.movePush = false; 114 | } 115 | 116 | if (that.positions.length > 2) { 117 | var areaCenter = that.getAreaAndCenter(that.positions); 118 | var area = areaCenter.area; 119 | var center = areaCenter.center; 120 | var text = that.formateArea(area, that.unit); 121 | that.floatLabel.label.text = "面积:" + text; 122 | if (center) that.floatLabel.position.setValue(center); 123 | that.floatLabel.area = area; 124 | that.floatLabel.show = true; 125 | } 126 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 127 | 128 | this.handler.setInputAction(function (evt) { //双击结束绘制 129 | if (!that.polygon) { 130 | return; 131 | } 132 | 133 | that.positions.pop(); 134 | that.viewer.entities.remove(that.controlPoints.pop()); // 移除最后一个 135 | 136 | that.movePush = false; 137 | that.endCreate(); 138 | if (callback) callback(that.polyline); 139 | }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); 140 | } 141 | 142 | endCreate() { 143 | let that = this; 144 | that.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 145 | that.viewer.trackedEntity = undefined; 146 | 147 | const areaCenter = that.getAreaAndCenter(that.positions) 148 | let area = areaCenter.area; 149 | let center = areaCenter.center; 150 | let text = that.formateArea(area, that.unit); 151 | that.floatLabel.label.text = "面积:" + text; 152 | that.floatLabel.area = area; 153 | if (center) that.floatLabel.position.setValue(center); 154 | 155 | if (that.handler) { 156 | that.handler.destroy(); 157 | that.handler = null; 158 | } 159 | 160 | if (that.prompt) { 161 | that.prompt.destroy(); 162 | that.prompt = null; 163 | } 164 | 165 | 166 | that.state = "endCreate"; 167 | } 168 | 169 | done() { 170 | if (this.state == "startCreate") { 171 | this.destroy(); 172 | } else if (this.state == "creating") { 173 | if (this.positions.length <= 2 && this.movePush == true) { 174 | this.destroy(); 175 | } else { 176 | this.endCreate(); 177 | } 178 | } else if (this.state == "startEdit" || this.state == "editing") { 179 | this.endEdit(); 180 | } else { 181 | 182 | } 183 | } 184 | 185 | startEdit(callback) { 186 | if (!((this.state == "endCrerate" || this.state == "endEdit") && this.polygon)) return; 187 | this.state = "startEdit";; 188 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 189 | let that = this; 190 | for (let i = 0; i < that.controlPoints.length; i++) { 191 | let point = that.controlPoints[i]; 192 | if (point) point.show = true; 193 | } 194 | this.modifyHandler.setInputAction(function (evt) { 195 | let pick = that.viewer.scene.pick(evt.position); 196 | if (Cesium.defined(pick) && pick.id) { 197 | if (!pick.id.objId) 198 | that.modifyPoint = pick.id; 199 | that.forbidDrawWorld(true); 200 | 201 | } 202 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 203 | this.modifyHandler.setInputAction(function (evt) { 204 | if (that.positions.length < 1 || !that.modifyPoint) return; 205 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 206 | 207 | if (!cartesian) return; 208 | that.modifyPoint.position.setValue(cartesian); 209 | 210 | let wz = that.modifyPoint.wz; 211 | that.positions[wz] = cartesian.clone(); 212 | 213 | var areaCenter = that.getAreaAndCenter(that.positions); 214 | var area = areaCenter.area; 215 | var center = areaCenter.center; 216 | var text = that.formateArea(area, that.unit); 217 | that.floatLabel.label.text = "面积:" + text; 218 | that.floatLabel.area = area; 219 | if (center) that.floatLabel.position.setValue(center); 220 | 221 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 222 | 223 | this.modifyHandler.setInputAction(function (evt) { 224 | if (!that.modifyPoint) return; 225 | that.modifyPoint = null; 226 | that.forbidDrawWorld(false); 227 | if (callback) callback(); 228 | that.state = "endEdit"; 229 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 230 | } 231 | 232 | endEdit() { 233 | let that = this; 234 | this.state = "endEdit";; 235 | if (this.modifyHandler) { 236 | this.modifyHandler.destroy(); 237 | this.modifyHandler = null; 238 | } 239 | for (let i = 0; i < that.controlPoints.length; i++) { 240 | let point = that.controlPoints[i]; 241 | if (point) point.show = false; 242 | } 243 | } 244 | 245 | 246 | //清除测量结果 247 | destroy() { 248 | this.state = "no"; 249 | if (this.polyline) { 250 | this.viewer.entities.remove(this.polyline); 251 | this.polyline = null; 252 | } 253 | if (this.polygon) { 254 | this.viewer.entities.remove(this.polygon); 255 | this.polygon = null; 256 | } 257 | if (this.floatLabel) { 258 | this.viewer.entities.remove(this.floatLabel); 259 | this.floatLabel = null; 260 | } 261 | if (this.handler) { 262 | this.handler.destroy(); 263 | this.handler = null; 264 | } 265 | for (let i = 0; i < this.controlPoints.length; i++) { 266 | let point = this.controlPoints[i]; 267 | this.viewer.entities.remove(point); 268 | } 269 | 270 | this.floatLable = null; 271 | } 272 | 273 | createPolyline() { 274 | var that = this; 275 | var polyline = this.viewer.entities.add({ 276 | polyline: { 277 | positions: new Cesium.CallbackProperty(function () { 278 | let linePositions = that.positions.concat([that.positions[0]]); 279 | return linePositions 280 | }, false), 281 | material: Cesium.Color.GOLD, 282 | width: 2, 283 | clampToGround: true 284 | } 285 | }); 286 | return polyline; 287 | } 288 | createPolygon() { 289 | var that = this; 290 | var polygon = this.viewer.entities.add({ 291 | polygon: new Cesium.PolygonGraphics({ 292 | hierarchy: new Cesium.CallbackProperty(function () { 293 | return new Cesium.PolygonHierarchy(that.positions); 294 | }, false), 295 | material: this.style.material || Cesium.Color.WHITE.withAlpha(0.6), 296 | fill: true 297 | }) 298 | }); 299 | return polygon; 300 | } 301 | setUnit(unit) { 302 | this.unit = unit; 303 | var text = this.formateArea(this.floatLabel.area, unit); 304 | this.floatLabel.label.text = "面积:" + text; 305 | } 306 | } 307 | 308 | 309 | 310 | export default MeasureSpaceArea; -------------------------------------------------------------------------------- /src/js/measure/measureSpaceDistance.js: -------------------------------------------------------------------------------- 1 | //空间距离量算js 2 | import MeasureGroundDistance from "./measureGroundDistance"; 3 | import BaseMeasure from "./baseMeasure"; 4 | import '../prompt/prompt.css' 5 | import Prompt from '../prompt/prompt.js' 6 | 7 | /** 8 | * 空间距离测量类 9 | * @class 10 | * @augments BaseMeasure 11 | * @alias BaseMeasure.MeasureSpaceDistance 12 | */ 13 | class MeasureSpaceDistance extends BaseMeasure { 14 | constructor(viewer, opt) { 15 | super(viewer, opt); 16 | this.unitType = "length"; 17 | this.type = "spaceDistance"; 18 | 19 | /** 20 | * @property {Number} allDistance 总长度 21 | */ 22 | this.allDistance = 0; 23 | this.labels = []; 24 | this.positions = []; 25 | //线 26 | this.polyline = null; 27 | this.nowLabel = null; // 编辑时 当前点的label 28 | this.nextlabel = null; // 编辑时 下一个点的label 29 | this.lastPosition = null;// 编辑时 上一个点的坐标 30 | this.nextPosition = null;// 编辑时 下一个点的坐标 31 | } 32 | 33 | //开始测量 34 | start(callback) { 35 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 36 | let that = this; 37 | this.state = "startCreate"; 38 | this.handler.setInputAction(function (evt) { //单击开始绘制 39 | that.state = "creating"; 40 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 41 | if (!cartesian) return; 42 | if (that.movePush) { 43 | that.positions.pop(); 44 | that.movePush = false; 45 | } 46 | let label; 47 | if (that.positions.length == 0) { 48 | label = that.createLabel(cartesian, "起点"); 49 | that.floatLable = that.createLabel(cartesian, ""); 50 | that.floatLable.wz = 0; 51 | that.floatLable.show = false; 52 | } else { 53 | let distance = that.getLength(cartesian, that.lastCartesian); 54 | that.lastDistance = distance; 55 | that.allDistance += distance; 56 | let text = that.formateLength(distance, that.unit); 57 | label = that.createLabel(cartesian, text); 58 | label.wz = that.positions.length;// 和坐标点关联 59 | label.distance = distance; 60 | } 61 | that.labels.push(label); 62 | let point = that.createPoint(cartesian.clone()); 63 | point.wz = that.positions.length; // 和坐标点关联 64 | that.controlPoints.push(point); 65 | that.positions.push(cartesian); 66 | that.lastCartesian = cartesian.clone(); 67 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 68 | 69 | this.handler.setInputAction(function (evt) { 70 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 71 | if (!cartesian) return; 72 | that.state = "creating"; 73 | if (that.positions.length < 1) { 74 | that.prompt.update(evt.endPosition, "单击开始测量"); 75 | return; 76 | } else { 77 | that.prompt.update(evt.endPosition, "双击结束,右键取消上一步"); 78 | that.floatLable.show = true; 79 | 80 | if (!that.movePush) { 81 | that.positions.push(cartesian); 82 | that.movePush = true; 83 | } else { 84 | that.positions[that.positions.length - 1] = cartesian; 85 | } 86 | 87 | if (!Cesium.defined(that.polyline)) { 88 | that.polyline = that.createLine(that.positions, false); 89 | that.polyline.objId = that.objId; 90 | } 91 | if (!that.lastCartesian) return; 92 | let distance = that.getLength(cartesian, that.lastCartesian); 93 | that.floatLable.show = true; 94 | that.floatLable.label.text = that.formateLength(distance, that.unit); 95 | that.floatLable.distance = distance; 96 | that.floatLable.position.setValue(cartesian); 97 | } 98 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 99 | 100 | this.handler.setInputAction(function (evt) { 101 | that.state = "creating"; 102 | if (!that.polyline) return; 103 | if (that.positions.length <= 2) return; // 默认第一个不给删除 104 | that.positions.splice(that.positions.length - 2, 1); 105 | that.viewer.entities.remove(that.labels.pop()); 106 | that.viewer.entities.remove(that.controlPoints.pop()); // 移除最后一个 107 | that.allDistance = that.allDistance - that.lastDistance; 108 | if (that.positions.length == 1) { 109 | if (that.polyline) { 110 | that.viewer.entities.remove(that.polyline); 111 | that.polyline = null; 112 | } 113 | that.prompt.update(evt.endPosition, "单击开始测量"); 114 | that.movePush = false; 115 | that.floatLable.show = false; 116 | that.positions = []; 117 | } 118 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 119 | if (!cartesian) return; 120 | let distance = that.getLength(cartesian, that.positions[that.positions.length - 2]); 121 | that.floatLable.show = true; 122 | that.floatLable.label.text = that.formateLength(distance, that.unit); 123 | that.floatLable.distance = distance; 124 | that.floatLable.position.setValue(cartesian); 125 | 126 | if (!that.movePush) { 127 | that.lastCartesian = that.positions[that.positions.length - 1]; 128 | } else { 129 | that.lastCartesian = that.positions[that.positions.length - 2]; 130 | } 131 | 132 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 133 | 134 | this.handler.setInputAction(function (evt) { //双击结束绘制 135 | if (!that.polyline) return; 136 | 137 | that.positions.pop(); 138 | that.viewer.entities.remove(that.labels.pop()); 139 | that.viewer.entities.remove(that.controlPoints.pop()); // 移除最后一个 140 | 141 | that.movePush = false; 142 | that.endCreate(); 143 | if (callback) callback(); 144 | }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); 145 | } 146 | 147 | 148 | endCreate() { 149 | let that = this; 150 | if (!that.polyline) return; 151 | that.floatLable.show = false; 152 | that.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 153 | that.viewer.trackedEntity = undefined; 154 | 155 | let allDistance = that.formateLength(that.allDistance, that.unit); 156 | that.labels[that.labels.length - 1].label.text = "总长:" + allDistance; 157 | 158 | if (that.prompt) { 159 | that.prompt.destroy(); 160 | that.prompt = null; 161 | } 162 | 163 | if (that.handler) { 164 | that.handler.destroy(); 165 | that.handler = null; 166 | } 167 | that.state = "endCreate"; 168 | } 169 | 170 | done() { 171 | if (this.state == "startCreate") { 172 | this.destroy(); 173 | } else if (this.state == "creating") { 174 | if (this.positions.length <= 2 && this.movePush == true) { 175 | this.destroy(); 176 | } else { 177 | this.endCreate(); 178 | } 179 | } else if (this.state == "startEdit" || this.state == "editing") { 180 | this.endEdit(); 181 | } else { 182 | 183 | } 184 | } 185 | 186 | // 开始编辑 187 | startEdit(callback) { 188 | if (!((this.state == "endCrerate" || this.state == "endEdit") && this.polyline)) return; 189 | this.state = "startEdit";; 190 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 191 | let that = this; 192 | for (let i = 0; i < that.controlPoints.length; i++) { 193 | let point = that.controlPoints[i]; 194 | if (point) point.show = true; 195 | } 196 | this.modifyHandler.setInputAction(function (evt) { 197 | let pick = that.viewer.scene.pick(evt.position); 198 | if (Cesium.defined(pick) && pick.id) { 199 | if (!pick.id.objId) 200 | that.modifyPoint = pick.id; 201 | that.forbidDrawWorld(true); 202 | let wz = that.modifyPoint.wz; 203 | // 重新计算左右距离 204 | let nextIndex = wz + 1; 205 | let lastIndex = wz - 1; 206 | that.nowLabel = that.labels[wz]; 207 | if (lastIndex >= 0) { 208 | that.lastPosition = that.positions[lastIndex]; 209 | } 210 | if (nextIndex <= that.positions.length - 1) { 211 | that.nextPosition = that.positions[nextIndex]; 212 | that.nextlabel = that.labels[nextIndex]; 213 | } 214 | } 215 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 216 | this.modifyHandler.setInputAction(function (evt) { 217 | if (that.positions.length < 1 || !that.modifyPoint) return; 218 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 219 | 220 | if (!cartesian) return; 221 | that.modifyPoint.position.setValue(cartesian); 222 | 223 | let wz = that.modifyPoint.wz; 224 | that.positions[wz] = cartesian.clone(); 225 | that.state = "editing"; 226 | that.nowLabel.position.setValue(cartesian.clone()); 227 | 228 | let changeDis1 = 0; 229 | if (that.nowLabel && that.lastPosition) { 230 | let distance = that.getLength(cartesian.clone(), that.lastPosition.clone()); 231 | that.nowLabel.label.text = that.formateLength(distance, that.unit); 232 | changeDis1 = distance - that.nowLabel.distance; 233 | that.nowLabel.distance = distance; 234 | } 235 | 236 | let changeDis2 = 0; 237 | if (that.nextPosition && that.nextlabel) { 238 | let distance = that.getLength(cartesian.clone(), that.nextPosition.clone()); 239 | that.nextlabel.label.text = that.formateLength(distance, that.unit); 240 | changeDis2 = distance - that.nextlabel.distance; 241 | that.nextlabel.distance = distance; 242 | } 243 | 244 | // 计算总长 245 | that.allDistance = that.allDistance + changeDis1 + changeDis2; 246 | let allDistance = that.formateLength(that.allDistance, that.unit); 247 | that.labels[that.labels.length - 1].label.text = "总长:" + allDistance; 248 | 249 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 250 | 251 | this.modifyHandler.setInputAction(function (evt) { 252 | if (!that.modifyPoint) return; 253 | that.modifyPoint = null; 254 | that.lastPosition = null; 255 | that.nextPosition = null; 256 | that.forbidDrawWorld(false); 257 | if (callback) callback(); 258 | that.state = "endEdit"; 259 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 260 | } 261 | 262 | 263 | 264 | 265 | endEdit() { 266 | let that = this; 267 | this.state = "endEdit";; 268 | if (this.modifyHandler) { 269 | this.modifyHandler.destroy(); 270 | this.modifyHandler = null; 271 | } 272 | for (let i = 0; i < that.controlPoints.length; i++) { 273 | let point = that.controlPoints[i]; 274 | if (point) point.show = false; 275 | } 276 | } 277 | 278 | //清除测量结果 279 | destroy() { 280 | if (this.polyline) { 281 | this.viewer.entities.remove(this.polyline); 282 | this.polyline = null; 283 | } 284 | for (let i = 0; i < this.labels.length; i++) { 285 | this.viewer.entities.remove(this.labels[i]); 286 | } 287 | this.labels = []; 288 | for (let ind = 0; ind < this.controlPoints.length; ind++) { 289 | this.viewer.entities.remove(this.controlPoints[ind]); 290 | } 291 | this.controlPoints = []; 292 | this.modifyPoint = null; 293 | if (this.floatLable) { 294 | this.viewer.entities.remove(this.floatLable); 295 | this.floatLable = null; 296 | } 297 | this.floatLable = null; 298 | 299 | if (this.prompt) { 300 | this.prompt.destroy(); 301 | this.prompt = null; 302 | } 303 | if (this.handler) { 304 | this.handler.destroy(); 305 | this.handler = null; 306 | } 307 | if (this.modifyHandler) { 308 | this.modifyHandler.destroy(); 309 | this.modifyHandler = null; 310 | } 311 | this.movePush = false; 312 | this.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 313 | this.viewer.trackedEntity = undefined; 314 | this.state = "no"; 315 | } 316 | 317 | // 设置单位 318 | setUnit(unit) { 319 | for (let i = 1; i < this.labels.length; i++) { 320 | let labelEnt = this.labels[i]; 321 | let distance = labelEnt.distance; 322 | let label = labelEnt.label; 323 | if (!label) continue; 324 | if (i == this.labels.length - 1) { 325 | label.text = "总长:" + this.formateLength(distance, unit); 326 | } else { 327 | label.text = this.formateLength(distance, unit); 328 | } 329 | } 330 | this.unit = unit; 331 | } 332 | } 333 | 334 | export default MeasureSpaceDistance; 335 | 336 | -------------------------------------------------------------------------------- /src/js/measure/measureTool.js: -------------------------------------------------------------------------------- 1 | import MeasureSpaceDistance from './measureSpaceDistance'; 2 | import MeasureGroundDistance from './measureGroundDistance'; 3 | import MeasureSpaceArea from './measureSpaceArea'; 4 | import MeasureHeight from './measureHeight'; 5 | import MeasureTriangle from './measureTriangle'; 6 | import MeasureLnglat from './measureLnglat'; 7 | import MeasureAzimutht from './measureAzimuth'; 8 | import MeasureSection from './measureSection'; 9 | 10 | /** 11 | * 量算控制类 12 | * @description 量算控制类,通过此类对象,可进行不同类型的量算操作,而不用多次new 不同类型的量算对象。 13 | * @class 14 | */ 15 | class MeasureTool { 16 | /** 17 | * @param {Cesium.viewer} viewer 地图viewer对象 18 | * @param {Object} obj 基础配置 19 | */ 20 | constructor(viewer, obj) { 21 | if (!viewer) { 22 | console.warn("缺少必要参数!--viewer"); 23 | return; 24 | } 25 | obj = obj || {}; 26 | this.viewer = viewer; 27 | 28 | /** 29 | * @property {Object} nowDrawMeasureObj 当前测量对象 30 | */ 31 | this.nowDrawMeasureObj = null; 32 | 33 | /** 34 | * @property {Array} measureObjArr 测量对象数组 35 | */ 36 | this.measureObjArr = []; 37 | this.nowEditMeasureObj = null; 38 | this.handler = null; 39 | 40 | /** 41 | * @property {Boolean} [canEdit=true] 测量对象是否可编辑 42 | */ 43 | this.canEdit = obj.canEdit == undefined ? true : obj.canEdit; 44 | 45 | /** 46 | * @property {Boolean} [intoEdit=true] 绘制完成后,是否进入编辑状态(当canEdit==true,才起作用) 47 | */ 48 | this.intoEdit = obj.intoEdit == undefined ? true : obj.intoEdit; 49 | this.bindEdit(); 50 | 51 | /** 52 | * @property {Object} nowDrawMeasureObj 当前绘制对象,绘制完成后为undifined 53 | */ 54 | this.nowDrawMeasureObj = undefined; 55 | 56 | /** 57 | * @property {Object} nowEditMeasureObj 当前编辑对象,编辑完成后为undifined 58 | */ 59 | this.nowEditMeasureObj = undefined; 60 | } 61 | 62 | /** 63 | * 事件绑定 64 | * @param {String} type 事件类型(startEdit 开始编辑时 / endEdit 编辑结束时 / end 创建完成后) 65 | * @param {Function} fun 绑定函数 66 | */ 67 | on(type, fun) { 68 | if (type == "endCreate") { 69 | this.endCreateFun = fun; 70 | } 71 | 72 | if (type == "startEdit") { 73 | this.startEditFun = fun; 74 | } 75 | 76 | if (type == "endEdit") { 77 | this.endEditFun = fun; 78 | } 79 | 80 | } 81 | 82 | /** 83 | * 开始量算 84 | * @param {Object} opt 85 | * @param {Number} opt.type 量算类型(1~空间距离测量/2~贴地距离测量/3~空间面积测量/4~高度测量/5~三角测量/6~坐标量算/7~方位角测量/8~剖面测量/9~单点坡度) 86 | */ 87 | start(opt) { 88 | opt = opt || {}; 89 | if (!opt.type) return; 90 | let ms; 91 | this.endEdit(); 92 | if (this.nowDrawMeasureObj && ( 93 | this.nowDrawMeasureObj.state != "endCreate" && 94 | this.nowDrawMeasureObj.state != "endEdit") && 95 | this.nowDrawMeasureObj.state != "no") return; 96 | 97 | switch (Number(opt.type)) { 98 | case 1: // 空间距离测量 99 | ms = new MeasureSpaceDistance(this.viewer, opt); 100 | break; 101 | case 2: // 贴地距离测量 102 | ms = new MeasureGroundDistance(this.viewer, opt); 103 | break; 104 | case 3: // 空间面积测量 105 | ms = new MeasureSpaceArea(this.viewer, opt); 106 | break; 107 | case 4: // 高度测量 108 | ms = new MeasureHeight(this.viewer, opt); 109 | break; 110 | case 5: // 三角测量 111 | ms = new MeasureTriangle(this.viewer, opt); 112 | break; 113 | case 6: // 坐标量算 114 | ms = new MeasureLnglat(this.viewer, opt); 115 | break; 116 | case 7: // 方位角测量 117 | ms = new MeasureAzimutht(this.viewer, opt); 118 | break; 119 | case 8: // 剖面测量 120 | ms = new MeasureSection(this.viewer, opt); 121 | break; 122 | /* case 9: // 单点坡度 123 | ms = new MeasureSlope(this.viewer, opt); 124 | break; */ 125 | /* case 10: //贴模型距离 126 | ms = new MeasureTilesetDistance(this.viewer); 127 | break; */ 128 | case 11: // 单点坡度 129 | ms = new MeasureSlopePolygon(this.viewer); 130 | break; 131 | default: 132 | break; 133 | } 134 | this.nowDrawMeasureObj = ms; 135 | let that = this; 136 | if (ms) { 137 | this.changeCursor(true); 138 | ms.start(function (res) { 139 | that.changeCursor(false); 140 | if (that.intoEdit) { 141 | ms.startEdit(); 142 | if (that.startEditFun) that.startEditFun(ms); 143 | } 144 | if (opt.success) opt.success(ms, res) 145 | if (that.endCreateFun) that.endCreateFun(ms, res); 146 | that.nowDrawMeasureObj = undefined; 147 | that.measureObjArr.push(ms); 148 | }); 149 | } 150 | } 151 | 152 | /** 153 | * 绑定编辑 154 | */ 155 | bindEdit() { 156 | let that = this; 157 | // 如果是线 面 则需要先选中 158 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 159 | this.handler.setInputAction(function (evt) { 160 | if (!that.canEdit) return; 161 | // 若当前正在绘制 则无法进行编辑操作 162 | if (that.nowDrawMeasureObj) return; 163 | let pick = that.viewer.scene.pick(evt.position); 164 | if (Cesium.defined(pick) && pick.id && pick.id.objId) { 165 | // 选中实体 166 | for (let i = 0; i < that.measureObjArr.length; i++) { 167 | if ( 168 | pick.id.objId == that.measureObjArr[i].objId && 169 | (that.measureObjArr[i].state == "endCreate" || 170 | that.measureObjArr[i].state == "endEdit") 171 | ) { 172 | // 结束上一个编辑 173 | if (that.nowEditMeasureObj) { 174 | // 结束除当前选中实体的所有编辑操作 175 | that.nowEditMeasureObj.endEdit(); 176 | if (that.endEditFun) that.endEditFun(that.nowEditMeasureObj); 177 | that.nowEditMeasureObj = undefined; 178 | } 179 | // 开始当前编辑 180 | that.measureObjArr[i].startEdit(); 181 | that.nowEditMeasureObj = that.measureObjArr[i]; 182 | if (that.startEditFun) that.startEditFun(that.nowEditMeasureObj); // 开始编辑 183 | break; 184 | } 185 | } 186 | } else { 187 | // 未选中实体 则结束编辑 188 | if (that.nowEditMeasureObj) { 189 | that.nowEditMeasureObj.endEdit(); 190 | if (that.endEditFun) that.endEditFun(that.nowEditMeasureObj); // 结束事件 191 | that.nowEditMeasureObj = undefined; 192 | } 193 | } 194 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 195 | } 196 | 197 | /** 198 | * 结束的当前操作 199 | */ 200 | done() { 201 | 202 | if (this.nowEditMeasureObj) { 203 | this.nowEditMeasureObj.done(); 204 | if (this.endEditFun) this.endEditFun(this.nowEditMeasureObj); 205 | this.nowEditMeasureObj = undefined; 206 | } 207 | 208 | if (this.nowDrawMeasureObj) { 209 | this.nowDrawMeasureObj.done(); 210 | this.measureObjArr.push(this.nowDrawMeasureObj); 211 | if (this.endCreateFun) this.endCreateFun(this.nowDrawMeasureObj); 212 | this.nowDrawMeasureObj = undefined; 213 | } 214 | } 215 | 216 | /** 217 | * 结束编辑 218 | */ 219 | endEdit() { 220 | if (this.nowEditMeasureObj) { 221 | // 结束除当前选中实体的所有编辑操作 222 | this.nowEditMeasureObj.endEdit(); 223 | if (this.endEditFun) this.endEditFun(this.nowEditMeasureObj); // 结束事件 224 | this.nowEditMeasureObj = null; 225 | } 226 | for (let i = 0; i < this.measureObjArr.length; i++) { 227 | this.measureObjArr[i].endEdit(); 228 | } 229 | } 230 | 231 | /** 232 | * 清除 233 | */ 234 | clear() { 235 | for (var i = 0; i < this.measureObjArr.length; i++) { 236 | if (this.measureObjArr[i]) { 237 | this.measureObjArr[i].endEdit(); 238 | this.measureObjArr[i].destroy(); 239 | } 240 | } 241 | this.measureObjArr = []; 242 | if (this.nowDrawMeasureObj) { 243 | this.nowDrawMeasureObj.destroy(); 244 | this.nowDrawMeasureObj = null; // 当前编辑对象 245 | } 246 | this.changeCursor(false); 247 | } 248 | 249 | /** 250 | * 销毁 251 | */ 252 | destroy() { 253 | this.clear(); 254 | if (this.handler) { 255 | this.handler.destroy(); 256 | this.handler = null; 257 | } 258 | } 259 | 260 | /** 261 | * 设置单位 262 | */ 263 | setUnit(unit) { 264 | if (!unit) return; 265 | this.nowDrawMeasureObj.setUnit(unit); 266 | } 267 | 268 | /** 269 | * 修改鼠标样式 270 | * @param {Boolean} isopen false为默认鼠标样式 271 | */ 272 | changeCursor(isopen) { 273 | let body = document.getElementsByTagName("body"); 274 | body[0].style.cursor = isopen ? "crosshair" : "default"; 275 | } 276 | 277 | /** 278 | * 根据id获取量算对象 279 | * @param {*} id 280 | * @returns {Object} measureObj为图层对象,index为图层对象在数组中位置 281 | */ 282 | getMeasureObjById(id) { 283 | if (!id) return; 284 | let res = {}; 285 | for (let i = 0; i < this.measureObjArr.length; i++) { 286 | if (this.measureObjArr[i].attr.id == id) { 287 | res = { 288 | measureObj: this.measureObjArr[i], 289 | index: i 290 | } 291 | break; 292 | } 293 | } 294 | return res; 295 | } 296 | 297 | /** 298 | * 根据objId获取量算对象 299 | * @param {*} id 300 | * @returns {Object} measureObj为图层对象,index为图层对象在数组中位置 301 | */ 302 | getMeasureObjByObjId(id) { 303 | if (!id) return; 304 | let res = {}; 305 | for (let i = 0; i < this.measureObjArr.length; i++) { 306 | if (this.measureObjArr[i].objId == id) { 307 | res = { 308 | measureObj: this.measureObjArr[i], 309 | index: i 310 | } 311 | break; 312 | } 313 | } 314 | return res; 315 | } 316 | 317 | /** 318 | * 删除单个量算对象 319 | * @param {Object} measureObj 320 | */ 321 | removeOne(measureObj) { 322 | if (!measureObj) return; 323 | let res = this.getMeasureObjByObjId(measureObj.objId); 324 | if (res.measureObj) { 325 | this.measureObjArr.splice(res.index, 1); 326 | res.measureObj.destroy(); 327 | } 328 | } 329 | } 330 | 331 | export default MeasureTool; -------------------------------------------------------------------------------- /src/js/measure/measureTriangle.js: -------------------------------------------------------------------------------- 1 | //三角测量js 2 | import BaseMeasure from "./baseMeasure"; 3 | import '../prompt/prompt.css' 4 | import Prompt from '../prompt/prompt.js' 5 | 6 | /** 7 | * 三角测量类 8 | * @class 9 | * @augments BaseMeasure 10 | * @alias BaseMeasure.MeasureTriangle 11 | */ 12 | class MeasureTriangle extends BaseMeasure { 13 | constructor(viewer, opt) { 14 | super(viewer, opt); 15 | if (!opt) opt = {}; 16 | this.unitType = "length"; 17 | this.style = opt.style || {}; 18 | //线 19 | this.heightfloatLabel = null; 20 | this.spaceDistancefloatLabel = null; 21 | this.horizonDistancefloatLabel = null; 22 | this.heightLine = null; 23 | this.spaceLine = null; 24 | this.horizonLine = null; 25 | this.firstPosition = null; 26 | this.endPosition = null; 27 | this.midPosition = undefined; 28 | this.lowPosition = undefined; 29 | this.highPosition = undefined; 30 | 31 | } 32 | 33 | //开始测量 34 | start(callback) { 35 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 36 | var that = this; 37 | this.state = 1; 38 | this.handler.setInputAction(function (evt) { //单击开始绘制 39 | var cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 40 | if (!cartesian) return; 41 | if (!that.firstPosition) { 42 | that.firstPosition = cartesian.clone(); 43 | that.heightfloatLabel = that.createLabel(cartesian, ""); 44 | that.spaceDistancefloatLabel = that.createLabel(cartesian, ""); 45 | that.horizonDistancefloatLabel = that.createLabel(cartesian, ""); 46 | 47 | let point = that.createPoint(cartesian.clone()); 48 | point.wz = 0; 49 | that.controlPoints.push(point); 50 | 51 | } else { 52 | that.endPosition = cartesian; 53 | that.computerPosition(that.firstPosition, that.endPosition); 54 | 55 | let point = that.createPoint(cartesian.clone()); 56 | point.wz = 1; 57 | that.controlPoints.push(point); 58 | 59 | if (that.handler) { 60 | that.handler.destroy(); 61 | that.handler = null; 62 | } 63 | 64 | if (that.prompt) { 65 | that.prompt.destroy(); 66 | that.prompt = null; 67 | } 68 | that.state = "endCreate"; 69 | if (callback) callback(); 70 | } 71 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 72 | this.handler.setInputAction(function (evt) { 73 | that.state = "creating"; 74 | if (!that.firstPosition) { 75 | that.prompt.update(evt.endPosition, "单击开始测量"); 76 | return; 77 | } 78 | that.prompt.update(evt.endPosition, "单击结束"); 79 | 80 | var cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 81 | if (!cartesian) return; 82 | that.endPosition = cartesian; 83 | that.computerPosition(that.firstPosition, that.endPosition); 84 | 85 | if (that.firstPosition && that.endPosition && !that.spaceLine) { 86 | that.spaceLine = that.viewer.entities.add({ 87 | polyline: { 88 | positions: new Cesium.CallbackProperty(function () { 89 | return [that.firstPosition, that.endPosition] 90 | }, false), 91 | show: true, 92 | material: new Cesium.PolylineOutlineMaterialProperty({ 93 | color: Cesium.Color.GOLD, 94 | outlineWidth: 2, 95 | outlineColor: Cesium.Color.BLACK, 96 | }), 97 | width: 3, 98 | } 99 | }); 100 | that.spaceLine.objId = that.objId; 101 | 102 | that.heightLine = that.viewer.entities.add({ 103 | polyline: { 104 | positions: new Cesium.CallbackProperty(function () { 105 | return [that.lowPosition, that.midPosition] 106 | }, false), 107 | show: true, 108 | material: new Cesium.PolylineOutlineMaterialProperty({ 109 | color: Cesium.Color.GOLD, 110 | outlineWidth: 2, 111 | outlineColor: Cesium.Color.BLACK, 112 | }), 113 | width: 3, 114 | } 115 | }); 116 | that.heightLine.objId = that.objId; 117 | 118 | that.horizonLine = that.viewer.entities.add({ 119 | polyline: { 120 | positions: new Cesium.CallbackProperty(function () { 121 | return [that.highPosition, that.midPosition] 122 | }, false), 123 | show: true, 124 | material: new Cesium.PolylineOutlineMaterialProperty({ 125 | color: Cesium.Color.GOLD, 126 | outlineWidth: 2, 127 | outlineColor: Cesium.Color.BLACK, 128 | }), 129 | width: 3, 130 | } 131 | }); 132 | that.horizonLine.objId = that.objId; 133 | } 134 | if (that.spaceLine) that.createLabels(); 135 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 136 | } 137 | 138 | //计算正上方的点 139 | computerPosition(p1, p2) { 140 | const cartographic1 = Cesium.Cartographic.fromCartesian(p1.clone()); 141 | const cartographic2 = Cesium.Cartographic.fromCartesian(p2.clone()); 142 | if (cartographic1.height > cartographic2.height) { 143 | this.highPosition = p1.clone(); 144 | this.lowPosition = p2.clone(); 145 | this.midPosition = Cesium.Cartesian3.fromRadians(cartographic2.longitude, cartographic2.latitude, cartographic1.height); 146 | } else { 147 | this.lowPosition = p1.clone(); 148 | this.highPosition = p2.clone(); 149 | this.midPosition = Cesium.Cartesian3.fromRadians(cartographic1.longitude, cartographic1.latitude, cartographic2.height); 150 | } 151 | } 152 | 153 | startEdit(callback) { 154 | if (!(this.state == "endCrerate" || this.state == "endEdit")) return; 155 | this.state = "startEdit";; 156 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 157 | let that = this; 158 | 159 | for (let i = 0; i < that.controlPoints.length; i++) { 160 | let point = that.controlPoints[i]; 161 | if (point) point.show = true; 162 | } 163 | this.modifyHandler.setInputAction(function (evt) { 164 | let pick = that.viewer.scene.pick(evt.position); 165 | if (Cesium.defined(pick) && pick.id) { 166 | if (!pick.id.objId) 167 | that.modifyPoint = pick.id; 168 | that.forbidDrawWorld(true); 169 | } 170 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 171 | 172 | this.modifyHandler.setInputAction(function (evt) { 173 | if (!that.modifyPoint) return; 174 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 175 | if (!cartesian) return; 176 | that.modifyPoint.position.setValue(cartesian.clone()); 177 | 178 | if (that.modifyPoint.wz == 0) { 179 | that.firstPosition = cartesian.clone() 180 | } else { 181 | that.endPosition = cartesian.clone() 182 | } 183 | 184 | that.computerPosition(that.firstPosition, that.endPosition); 185 | that.createLabels(); 186 | 187 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 188 | 189 | this.modifyHandler.setInputAction(function (evt) { 190 | if (!that.modifyPoint) return; 191 | that.modifyPoint = null; 192 | that.forbidDrawWorld(false); 193 | that.state = "endEdit"; 194 | if (callback) callback(); 195 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 196 | } 197 | 198 | endEdit() { 199 | let that = this; 200 | this.state = "endEdit";; 201 | if (this.modifyHandler) { 202 | this.modifyHandler.destroy(); 203 | this.modifyHandler = null; 204 | } 205 | for (let i = 0; i < that.controlPoints.length; i++) { 206 | let point = that.controlPoints[i]; 207 | if (point) point.show = false; 208 | } 209 | } 210 | 211 | createLabels() { 212 | let that = this; 213 | //高度差 214 | var height = Math.abs(Cesium.Cartographic.fromCartesian(that.highPosition).height - Cesium.Cartographic.fromCartesian(that.lowPosition).height); 215 | var height_mid = Cesium.Cartesian3.midpoint(that.lowPosition, that.midPosition, new Cesium.Cartesian3()); 216 | that.heightfloatLabel.show = true; 217 | that.heightfloatLabel.position.setValue(height_mid); 218 | let text1 = that.formateLength(height, that.unit); 219 | that.heightfloatLabel.label.text = "高度差:" + text1; 220 | that.heightfloatLabel.length = height; 221 | //水平距离 222 | var horizonDistance = Cesium.Cartesian3.distance(that.highPosition, that.midPosition); 223 | var horizon_mid = Cesium.Cartesian3.midpoint(that.highPosition, that.midPosition, new Cesium.Cartesian3()); 224 | that.horizonDistancefloatLabel.show = true; 225 | that.horizonDistancefloatLabel.position.setValue(horizon_mid); 226 | let text2 = that.formateLength(horizonDistance, that.unit); 227 | that.horizonDistancefloatLabel.label.text = "水平距离:" + text2; 228 | that.horizonDistancefloatLabel.length = horizonDistance; 229 | //空间距离 230 | var spaceDistance = Cesium.Cartesian3.distance(that.endPosition, that.firstPosition); 231 | var space_mid = Cesium.Cartesian3.midpoint(that.endPosition, that.firstPosition, new Cesium.Cartesian3()); 232 | that.spaceDistancefloatLabel.show = true; 233 | that.spaceDistancefloatLabel.position.setValue(space_mid); 234 | let text3 = that.formateLength(spaceDistance, that.unit); 235 | that.spaceDistancefloatLabel.label.text = "空间距离:" + text3; 236 | that.spaceDistancefloatLabel.length = spaceDistance; 237 | } 238 | 239 | //清除测量结果 240 | destroy() { 241 | this.state = "no"; 242 | if (this.heightLine) { 243 | this.viewer.entities.remove(this.heightLine); 244 | this.heightLine = null; 245 | } 246 | if (this.spaceLine) { 247 | this.viewer.entities.remove(this.spaceLine); 248 | this.spaceLine = null; 249 | } 250 | if (this.horizonLine) { 251 | this.viewer.entities.remove(this.horizonLine); 252 | this.horizonLine = null; 253 | } 254 | if (this.heightfloatLabel) { 255 | this.viewer.entities.remove(this.heightfloatLabel); 256 | this.heightfloatLabel = null; 257 | } 258 | this.heightfloatLabel = null; 259 | if (this.spaceDistancefloatLabel) { 260 | this.viewer.entities.remove(this.spaceDistancefloatLabel); 261 | this.spaceDistancefloatLabel = null; 262 | } 263 | this.spaceDistancefloatLabel = null; 264 | if (this.horizonDistancefloatLabel) { 265 | this.viewer.entities.remove(this.horizonDistancefloatLabel); 266 | this.horizonDistancefloatLabel = null; 267 | } 268 | this.horizonDistancefloatLabel = null; 269 | if (this.prompt) { 270 | this.prompt.destroy(); 271 | this.prompt = null; 272 | } 273 | if (this.handler) { 274 | this.handler.destroy(); 275 | this.handler = null; 276 | } 277 | } 278 | 279 | 280 | setUnit(unit) { 281 | if (this.heightfloatLabel) { 282 | let text1 = this.formateLength(this.heightfloatLabel.length, unit); 283 | this.heightfloatLabel.label.text = "高度差:" + text1; 284 | } 285 | 286 | if (this.horizonDistancefloatLabel) { 287 | let text2 = this.formateLength(this.horizonDistancefloatLabel.length, unit); 288 | this.horizonDistancefloatLabel.label.text = "水平距离:" + text2; 289 | } 290 | 291 | if (this.spaceDistancefloatLabel) { 292 | let text3 = this.formateLength(this.spaceDistancefloatLabel.length, unit); 293 | this.spaceDistancefloatLabel.label.text = "空间距离:" + text3; 294 | } 295 | 296 | 297 | this.unit = unit; 298 | } 299 | } 300 | 301 | export default MeasureTriangle; -------------------------------------------------------------------------------- /src/js/prompt/prompt.css: -------------------------------------------------------------------------------- 1 | .easy3d-prompt { 2 | position: absolute; 3 | top: -9999px; 4 | left: -9999px; 5 | } 6 | 7 | .prompt-close { 8 | position: absolute; 9 | top: 0; 10 | right: 0; 11 | padding: 4px 4px 0 0; 12 | border: none; 13 | text-align: center; 14 | width: 18px; 15 | height: 14px; 16 | font: 16px/14px Tahoma, Verdana, sans-serif; 17 | color: #c3c3c3; 18 | text-decoration: none; 19 | font-weight: bold; 20 | background: transparent; 21 | } 22 | 23 | .prompt-content-container { 24 | /* 不给padding撑不开div */ 25 | max-width: 400px; 26 | border-radius: 4px; 27 | padding: 1px; 28 | background: white; 29 | color: #333; 30 | box-shadow: 0 3px 14px rgb(0 0 0 / 40%); 31 | 32 | } 33 | 34 | .prompt-content { 35 | margin: 13px 19px; 36 | } 37 | 38 | .prompt-anchor-container { 39 | 40 | position: absolute; 41 | width: 40px; 42 | 43 | height: 20px; 44 | left: 50%; 45 | margin-left: -20px; 46 | overflow: hidden ; 47 | pointer-events: none; 48 | } 49 | 50 | .prompt-anchor { 51 | margin: -10px auto 0; 52 | background: white; 53 | width: 17px; 54 | height: 17px; 55 | -webkit-transform: rotate(45deg); 56 | transform: rotate(45deg); 57 | } -------------------------------------------------------------------------------- /src/js/prompt/prompt.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 气泡窗类 4 | * @class 5 | * 6 | */ 7 | import "./prompt.css" 8 | class Prompt { 9 | /** 10 | * @param {Cesium.Viewer} viewer 地图viewer对象 11 | * @param {Object} opt 12 | * @param {Cesium.Cartesian3 | Array} [opt.position] 弹窗坐标 (type=2时生效) 13 | * @param {Boolean} opt.show 是否显示 14 | * @param {Function} [opt.success] 创建成功的回调函数 15 | * @param {Number} [opt.type=1] 1~位置变化提示框 / 2~固定坐标提示框 16 | * @param {Cesium.Cartesian3 | Array} opt.position 固定坐标提示框的坐标( cartesian3 / [101,30] ),type为1时,可不设置此参数 17 | * @param {Boolean} [opt.anchor=true] 是否显示锚点 18 | * @param {Boolean} [opt.closeBtn=true] 是否显示关闭按钮 19 | * @param {String} opt.className 自定义class 20 | * @param {String} opt.content 弹窗内容 21 | * @param {Function} [opt.close] 关闭弹窗时的回调函数 22 | * @param {Object} [opt.offset] 偏移参数 23 | * @param {Number} [opt.offset.x] 横坐标偏移像素单位 24 | * @param {Number} [opt.offset.y] 纵坐标偏移像素单位 25 | * @param {Object} [opt.style] 弹窗面板样式 26 | * @param {String} [opt.style.background='white'] 背景色 27 | * @param {String} [opt.style.boxShadow] 弹窗阴影(css属性) 28 | * @param {String} [opt.style.color] 弹窗颜色 29 | * 30 | */ 31 | constructor(viewer, opt) { 32 | this.viewer = viewer; 33 | if (!this.viewer) return; 34 | this.type = "prompt"; 35 | // 默认值 36 | opt = opt || {}; 37 | const promptType = opt.type == undefined ? 1 : opt.type; 38 | let defaultOpt = { 39 | id: (new Date().getTime() + "" + Math.floor(Math.random() * 10000)), 40 | type: promptType, 41 | anchor: promptType == 2 ? true : false, 42 | closeBtn: promptType == 2 ? true : false, 43 | offset: promptType == 2 ? { x: 0, y: -20 } : { x: 10, y: 10 }, 44 | content: "", 45 | show: true, 46 | style: { 47 | background: "rgba(0,0,0,0.5)", 48 | color: "white" 49 | } 50 | } 51 | 52 | this.opt = Object.assign(defaultOpt, opt); 53 | 54 | /** 55 | * @property {Object} attr 相关属性 56 | */ 57 | this.attr = this.opt; 58 | // ====================== 创建弹窗内容 start ====================== 59 | const mapid = this.viewer.container.id; 60 | 61 | /** 62 | * @property {Boolearn} isShow 当前显示状态 63 | */ 64 | this.isShow = this.opt.show == undefined ? true : this.opt.show; // 是否显示 65 | let anchorHtml = ``; 66 | let closeHtml = ``; 67 | const background = this.opt.style.background; 68 | const color = this.opt.style.color; 69 | if (this.opt.anchor) { 70 | anchorHtml += ` 71 |
72 |
73 |
74 |
75 | `; 76 | } 77 | if (this.opt.closeBtn) { // 移动提示框 不显示关闭按钮 78 | closeHtml = `x`; 79 | } 80 | let boxShadow = this.opt.style.boxShadow; 81 | const promptId = "prompt-" + this.opt.id; 82 | const promptConenet = ` 83 | 84 |
85 |
86 | ${this.opt.content} 87 |
88 |
89 | 90 | ${anchorHtml} 91 | 92 | ${closeHtml} 93 | `; 94 | // 构建弹窗元素 95 | this.promptDiv = window.document.createElement("div"); 96 | this.promptDiv.className = `easy3d-prompt ${this.opt.className}`; 97 | this.promptDiv.id = promptId; 98 | this.promptDiv.innerHTML = promptConenet; 99 | let mapDom = window.document.getElementById(mapid); 100 | mapDom.appendChild(this.promptDiv); 101 | const clsBtn = window.document.getElementById(`prompt-close-${this.opt.id}`); 102 | let that = this; 103 | if (clsBtn) { 104 | clsBtn.addEventListener("click", (e) => { 105 | that.hide(); 106 | if (that.opt.close) that.opt.close(); 107 | }) 108 | } 109 | 110 | /** 111 | * @property {Object} promptDom 弹窗div 112 | */ 113 | this.promptDom = window.document.getElementById(promptId); 114 | 115 | this.position = this.transPosition(this.opt.position); 116 | // ====================== 创建弹窗内容 end ====================== 117 | 118 | if (promptType == 2) this.bindRender(); // 固定位置弹窗 绑定实时渲染 当到地球背面时 隐藏 119 | if (this.opt.show == false) this.hide(); 120 | this.containerW = this.viewer.container.offsetWidth; 121 | this.containerH = this.viewer.container.offsetHeight; 122 | this.containerLeft = this.viewer.container.offsetLeft; 123 | this.containerTop = this.viewer.container.offsetTop; 124 | 125 | /** 126 | * @property {Number} contentW 弹窗宽度 127 | */ 128 | this.contentW = Math.ceil(Number(this.promptDom.offsetWidth)); // 宽度 129 | 130 | /** 131 | * @property {Number} contentH 弹窗高度 132 | */ 133 | this.contentH = this.promptDom.offsetHeight; // 高度 134 | 135 | if (this.opt.success) this.opt.success(); 136 | } 137 | 138 | /** 139 | * 销毁 140 | */ 141 | destroy() { 142 | if (this.promptDiv) { 143 | window.document.getElementById(this.viewer.container.id).removeChild(this.promptDiv); 144 | this.promptDiv = null; 145 | } 146 | if (this.rendHandler) { 147 | this.rendHandler(); 148 | this.rendHandler = null; 149 | } 150 | } 151 | // 实时监听 152 | bindRender() { 153 | let that = this; 154 | this.rendHandler = this.viewer.scene.postRender.addEventListener(function () { 155 | if (!that.isShow && that.promptDom) { 156 | that.promptDom.style.display = "none"; 157 | return; 158 | } 159 | if (!that.position) return; 160 | if (that.position instanceof Cesium.Cartesian3) { 161 | let px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(that.viewer.scene, that.position); 162 | if (!px) return; 163 | const occluder = new Cesium.EllipsoidalOccluder(that.viewer.scene.globe.ellipsoid, that.viewer.scene.camera.position); 164 | // 当前点位是否可见 是否在地球背面 165 | const res = occluder.isPointVisible(that.position); 166 | if (res) { 167 | if (that.promptDom) that.promptDom.style.display = "block"; 168 | } else { 169 | if (that.promptDom) that.promptDom.style.display = "none"; 170 | } 171 | that.setByPX({ 172 | x: px.x, 173 | y: px.y 174 | }); 175 | } else { 176 | that.setByPX({ 177 | x: that.position.x, 178 | y: that.position.y 179 | }); 180 | } 181 | 182 | }, this); 183 | } 184 | 185 | /** 186 | * 187 | * @param {Cesium.Cartesian3 | Object} px 弹窗坐标 188 | * @param {String} html 弹窗内容 189 | */ 190 | update(px, html) { 191 | if (px instanceof Cesium.Cartesian3) { 192 | this.position = px.clone(); 193 | px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, px); 194 | } 195 | this.contentW = Math.ceil(Number(this.promptDom.offsetWidth)); // 宽度 196 | this.contentH = this.promptDom.offsetHeight; // 高度 197 | if (px) this.setByPX(px); 198 | if (html) this.setContent(html); 199 | } 200 | 201 | // 判断是否在当前视野内 202 | isInView() { 203 | if (!this.position) return false; 204 | let px = null; 205 | if (this.position instanceof Cesium.Cartesian2) { 206 | px = this.position; 207 | } else { 208 | px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, this.position); 209 | } 210 | const occluder = new Cesium.EllipsoidalOccluder(this.viewer.scene.globe.ellipsoid, this.viewer.scene.camera.position); 211 | // 是否在地球背面 212 | const res = occluder.isPointVisible(this.position); 213 | let isin = false; 214 | if (!px) return isin; 215 | if ( 216 | px.x > this.containerLeft && 217 | px.x < (this.containerLeft + this.containerW) && 218 | px.y > this.containerTop && 219 | px.y < (this.containerTop + this.containerH) 220 | ) { 221 | isin = true; 222 | } 223 | return res && isin; 224 | } 225 | 226 | /** 227 | * 是否可见 228 | * @param {Boolean} isShow true可见,false不可见 229 | */ 230 | setVisible(isShow) { 231 | let isin = this.isInView(this.position); 232 | if (isin && isShow) { 233 | this.isShow = true; 234 | if (this.promptDom) this.promptDom.style.display = "block"; 235 | } else { 236 | this.isShow = false; 237 | if (this.promptDom) this.promptDom.style.display = "none"; 238 | } 239 | } 240 | 241 | /** 242 | * 显示 243 | */ 244 | show() { 245 | this.setVisible(true); 246 | } 247 | 248 | /** 249 | * 隐藏 250 | */ 251 | hide() { 252 | this.setVisible(false); 253 | } 254 | 255 | /** 256 | * 设置弹窗内容 257 | * @param {String} content 内容 258 | */ 259 | setContent(content) { 260 | let pc = window.document.getElementById(`prompt-content-${this.opt.id}`); 261 | pc.innerHTML = content; 262 | } 263 | 264 | /** 265 | * 设置弹窗坐标 266 | * @param {Object} opt 屏幕坐标 267 | */ 268 | setByPX(opt) { 269 | if (!opt) return; 270 | if (this.promptDom) { 271 | const contentW = this.promptDom.offsetWidth; // 宽度 272 | const contentH = this.promptDom.offsetHeight; // 高度 273 | if (this.opt.type == 1) { 274 | this.promptDom.style.left = ((Number(opt.x) + Number(this.opt.offset.x || 0))) + "px"; 275 | this.promptDom.style.top = ((Number(opt.y) + Number(this.opt.offset.y || 0))) + "px"; 276 | } else { 277 | this.promptDom.style.left = ((Number(opt.x) + Number(this.opt.offset.x || 0)) - Number(this.contentW) / 2) + "px"; 278 | this.promptDom.style.top = ((Number(opt.y) + Number(this.opt.offset.y || 0)) - Number(this.contentH)) + "px"; 279 | } 280 | } 281 | } 282 | 283 | // 坐标转换 284 | transPosition(p) { 285 | let position; 286 | if (Array.isArray(p)) { 287 | const posi = Cesium.Cartesian3.fromDegrees(p[0], p[1], p[2] || 0); 288 | position = posi.clone(); 289 | } else if (p instanceof Cesium.Cartesian3) { 290 | position = p.clone(); 291 | } else { // 像素类型 292 | position = p; 293 | } 294 | return position; 295 | } 296 | } 297 | 298 | export default Prompt; -------------------------------------------------------------------------------- /src/js/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 三维基础方法 3 | * @example util.getCameraView(viewer); 4 | * @exports util 5 | * @alias util 6 | */ 7 | let util = {}; 8 | /** 9 | * 世界坐标转经纬度 10 | * @param {Cesium.Cartesian3 } cartesian 世界坐标 11 | * @param {Cesium.Viewer} viewer 当前viewer对象 12 | * @returns { Array } 经纬度坐标s 13 | */ 14 | util.cartesianToLnglat = function (cartesian, viewer) { 15 | if (!cartesian) return []; 16 | viewer = viewer || window.viewer; 17 | var lnglat = Cesium.Cartographic.fromCartesian(cartesian); 18 | var lat = Cesium.Math.toDegrees(lnglat.latitude); 19 | var lng = Cesium.Math.toDegrees(lnglat.longitude); 20 | var hei = lnglat.height; 21 | return [lng, lat, hei]; 22 | } 23 | 24 | util.getViewCenter = (viewer) => { 25 | if (!viewer) return; 26 | var rectangle = viewer.camera.computeViewRectangle(); 27 | var west = rectangle.west / Math.PI * 180; 28 | var north = rectangle.north / Math.PI * 180; 29 | var east = rectangle.east / Math.PI * 180; 30 | var south = rectangle.south / Math.PI * 180; 31 | return [(east + west) / 2, (north + south) / 2] 32 | } 33 | 34 | /** 35 | * 世界坐标数组转经纬度数组 36 | * @param {Cesium.Cartesian3[]} cartesians 世界坐标数组 37 | * @param {Cesium.Viewer} viewer 当前viewer对象 38 | * @returns { Array } 经纬度坐标数组 39 | */ 40 | util.cartesiansToLnglats = function (cartesians, viewer) { 41 | if (!cartesians || cartesians.length < 1) return; 42 | viewer = viewer || window.viewer; 43 | if (!viewer) { 44 | console.log('util.cartesiansToLnglats方法缺少viewer对象'); 45 | return; 46 | } 47 | var arr = []; 48 | for (var i = 0; i < cartesians.length; i++) { 49 | arr.push(util.cartesianToLnglat(cartesians[i], viewer)); 50 | } 51 | return arr; 52 | } 53 | 54 | /** 55 | * 经纬度坐标数组转世界坐标数组 56 | * @param {Array[]} lnglats 经纬度坐标数组 57 | * @returns {Cesium.Cartesian3[]} cartesians 世界坐标数组 58 | * @example util.lnglatsToCartesians([[117,40],[118.41]]) 59 | */ 60 | util.lnglatsToCartesians = function (lnglats) { 61 | if (!lnglats || lnglats.length < 1) return; 62 | var arr = []; 63 | for (var i = 0; i < lnglats.length; i++) { 64 | var c3 = Cesium.Cartesian3.fromDegrees(lnglats[i][0], lnglats[i][1], lnglats[i][2] || 0); 65 | arr.push(c3); 66 | } 67 | return arr; 68 | } 69 | 70 | /** 71 | * 视角定位方法 72 | * @param {Object} opt 定位参数 73 | * @param {Cartesian3|Array} opt.center 当前定位中心点 74 | * @param {Number} opt.heading 当前定位偏转角度 默认为0 75 | * @param {Number} opt.pitch 当前定位仰俯角 默认为-60 76 | * @param {Number} opt.range 当前定位距离 默认为1000米 77 | * @param {Cesium.Viewer} viewer 当前viewer对象 78 | */ 79 | util.flyTo = function (opt, viewer) { 80 | if (!viewer) { 81 | console.log('util.flyTo缺少viewer对象'); 82 | return; 83 | } 84 | opt = opt || {}; 85 | let center = opt.center; 86 | if (!center) { 87 | console.log("缺少定位坐标!"); 88 | return; 89 | } 90 | if (center instanceof Cesium.Cartesian3) { 91 | viewer.camera.flyToBoundingSphere(new Cesium.BoundingSphere(center), { 92 | offset: new Cesium.HeadingPitchRange( 93 | Cesium.Math.toRadians(opt.heading || 0), 94 | Cesium.Math.toRadians(opt.pitch || -60), 95 | opt.range || 10000 96 | ) 97 | }); 98 | } 99 | if (center instanceof Array) { 100 | var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(center[0], center[1], center[2])); 101 | viewer.camera.flyToBoundingSphere(boundingSphere, { 102 | offset: new Cesium.HeadingPitchRange( 103 | Cesium.Math.toRadians(opt.heading || 0), 104 | Cesium.Math.toRadians(opt.pitch || -60), 105 | opt.range || 10000 106 | ) 107 | }); 108 | } 109 | } 110 | 111 | /** 112 | * 获取当相机姿态 113 | * @param {Cesium.Viewer} viewer 当前viewer对象 114 | * @returns {Object} cameraView 当前相机姿态 115 | */ 116 | util.getCameraView = function (viewer) { 117 | viewer = viewer || window.viewer; 118 | if (!viewer) { 119 | console.log('util.getCameraView缺少viewer对象'); 120 | return; 121 | } 122 | var camera = viewer.camera; 123 | var position = camera.position; 124 | var heading = camera.heading; 125 | var pitch = camera.pitch; 126 | var roll = camera.roll; 127 | var lnglat = Cesium.Cartographic.fromCartesian(position); 128 | 129 | var cameraV = { 130 | "x": Cesium.Math.toDegrees(lnglat.longitude), 131 | "y": Cesium.Math.toDegrees(lnglat.latitude), 132 | "z": lnglat.height, 133 | "heading": Cesium.Math.toDegrees(heading), 134 | "pitch": Cesium.Math.toDegrees(pitch), 135 | "roll": Cesium.Math.toDegrees(roll) 136 | }; 137 | return cameraV; 138 | } 139 | 140 | /** 141 | * 设置相机姿态 一般和getCameraView搭配使用 142 | * @param {Object} cameraView 相机姿态参数 143 | * @param {Number} cameraView.duration 定位所需时间 144 | * @param {Cesium.Viewer} viewer 当前viewer对象 145 | */ 146 | util.setCameraView = function (obj, viewer) { 147 | viewer = viewer || window.viewer; 148 | if (!viewer) { 149 | console.log('util.setCameraView缺少viewer对象'); 150 | return; 151 | } 152 | if (!obj) return; 153 | var position = obj.destination || Cesium.Cartesian3.fromDegrees(obj.x, obj.y, obj.z); // 兼容cartesian3和xyz 154 | viewer.camera.flyTo({ 155 | destination: position, 156 | orientation: { 157 | heading: Cesium.Math.toRadians(obj.heading || 0), 158 | pitch: Cesium.Math.toRadians(obj.pitch || 0), 159 | roll: Cesium.Math.toRadians(obj.roll || 0) 160 | }, 161 | duration: obj.duration === undefined ? 3 : obj.duration, 162 | complete: obj.complete 163 | }); 164 | } 165 | 166 | /** 167 | * 计算当前三角形面积 168 | * @param {Cesium.Cartesian3 } pos1 当前点坐标1 169 | * @param {Cesium.Cartesian3 } pos2 当前点坐标2 170 | * @param {Cesium.Cartesian3 } pos3 当前点坐标3 171 | * @returns {Number} area,面积 172 | */ 173 | util.computeAreaOfTriangle = function (pos1, pos2, pos3) { 174 | if (!pos1 || !pos2 || !pos3) { 175 | console.log("传入坐标有误!"); 176 | return 0; 177 | } 178 | var a = Cesium.Cartesian3.distance(pos1, pos2); 179 | var b = Cesium.Cartesian3.distance(pos2, pos3); 180 | var c = Cesium.Cartesian3.distance(pos3, pos1); 181 | var S = (a + b + c) / 2; 182 | return Math.sqrt(S * (S - a) * (S - b) * (S - c)); 183 | } 184 | 185 | export default util; 186 | 187 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './Index.vue' 3 | import Antd from "ant-design-vue"; 4 | import "ant-design-vue/dist/antd.css"; 5 | const app = createApp(App) 6 | app.use(Antd); 7 | app.mount('#app') 8 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "baseUrl": ".", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node18/tsconfig.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "module": "ESNext", 7 | "types": ["node"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)) 12 | } 13 | } 14 | }) 15 | --------------------------------------------------------------------------------