easy-three-utils 0.0.346 → 0.0.348

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cesium/index.ts CHANGED
@@ -13,6 +13,7 @@ type TCesiumUtilsType = {
13
13
  clipping: ReturnType<typeof hooks.useClipping>;
14
14
  weather: ReturnType<typeof hooks.useWeather>;
15
15
  measure: ReturnType<typeof hooks.useMeasure>;
16
+ slope: ReturnType<typeof hooks.useSlope>;
16
17
  }
17
18
 
18
19
  let config;
@@ -87,7 +88,13 @@ const useCesium = () => {
87
88
  const clipping = hooks.useClipping(viewer)
88
89
  const weather = hooks.useWeather(viewer)
89
90
  const measure = hooks.useMeasure(viewer, {
90
- distanceCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_DISTANCE)
91
+ distanceCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_DISTANCE),
92
+ heightCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_HEIGHT),
93
+ areaCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_AREA),
94
+ altitudeCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_ALTITUDE)
95
+ })
96
+ const slope = hooks.useSlope(viewer, {
97
+ collection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.SLOPE)
91
98
  })
92
99
 
93
100
  if (config.controllerStyle === cesiumConfigDict.EControllerStyle.THREE) {
@@ -100,7 +107,8 @@ const useCesium = () => {
100
107
  drawPolygon,
101
108
  clipping,
102
109
  weather,
103
- measure
110
+ measure,
111
+ slope
104
112
  })
105
113
 
106
114
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
@@ -3,6 +3,7 @@ import { useDrawPolygon } from './useDrawPolygon'
3
3
  import { useClipping } from './useClipping'
4
4
  import { useWeather, EWeatherType } from './useWeather'
5
5
  import { useMeasure } from './useMeasure'
6
+ import { useSlope } from './useSlope'
6
7
 
7
8
  const dict = {
8
9
  ECollectionWhiteListNames,
@@ -15,6 +16,7 @@ export {
15
16
  useClipping,
16
17
  useWeather,
17
18
  useMeasure,
19
+ useSlope,
18
20
 
19
21
  dict
20
22
  }
@@ -0,0 +1,195 @@
1
+ // import CreateRemindertip from "./ReminderTip";
2
+ import * as Cesium from 'cesium'
3
+
4
+ const CreatePolygonOnGround = function ({ viewer, collection }, resultList, options, callback, cb) {
5
+ if (!viewer) throw new Error("no viewer object!");
6
+ options = options || {};
7
+ let id = options.id || setSessionid(); //Polygon的id
8
+ if (collection.entities.getById(id))
9
+ throw new Error("the id parameter is an unique value");
10
+ let color = options.color || Cesium.Color.RED; //Polygon的填充色
11
+ let outlineColor = options.outlineColor || color.withAlpha(1); //Polygon的轮廓线颜色
12
+ let outlineWidth = options.outlineWidth || 2; //Polygon的轮廓线宽度
13
+ let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
14
+ cb && cb(handler)
15
+ let toolTip = "左键点击开始绘制";
16
+ let anchorpoints = [];
17
+ let polygon = undefined;
18
+ let drawStatus = true;
19
+ handler.setInputAction(function (event) {
20
+ let pixPos = event.position;
21
+ let cartesian = getCatesian3FromPX(viewer, pixPos);
22
+ if (anchorpoints.length == 0) {
23
+ toolTip = "左键添加第二个点";
24
+ anchorpoints.push(cartesian);
25
+ let linePoints = new Cesium.CallbackProperty(function () {
26
+ let verPoints = anchorpoints.concat([anchorpoints[0]]);
27
+ return verPoints;
28
+ }, false);
29
+ let dynamicPositions = new Cesium.CallbackProperty(function () {
30
+ return new Cesium.PolygonHierarchy(anchorpoints);
31
+ }, false);
32
+ polygon = collection.entities.add({
33
+ name: "Polygon",
34
+ id: id,
35
+ polyline: {
36
+ positions: linePoints,
37
+ width: outlineWidth,
38
+ material: outlineColor,
39
+ clampToGround: true,
40
+ },
41
+ polygon: {
42
+ heightReference: Cesium.HeightReference.None,
43
+ hierarchy: dynamicPositions,
44
+ material: color,
45
+ },
46
+ });
47
+ polygon.GeoType = "Polygon";
48
+ } else {
49
+ toolTip = "左键添加点,Ctrl+Z回退,右键完成绘制";
50
+ }
51
+ anchorpoints.push(cartesian);
52
+ }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
53
+
54
+ handler.setInputAction(function (movement) {
55
+ let endPos = movement.endPosition;
56
+ // CreateRemindertip(toolTip, endPos, true);
57
+ if (Cesium.defined(polygon)) {
58
+ anchorpoints.pop();
59
+ let cartesian = getCatesian3FromPX(viewer, endPos);
60
+ anchorpoints.push(cartesian);
61
+ }
62
+ if (anchorpoints.length === 3) {
63
+ polygon.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
64
+ }
65
+ }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
66
+
67
+ handler.setInputAction(function (event) {
68
+ anchorpoints.pop();
69
+ polygon.pottingPoint = anchorpoints;
70
+ resultList.push(polygon);
71
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_DOWN)
72
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
73
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
74
+ handler.destroy();
75
+ handler = null
76
+ // CreateRemindertip(toolTip, event.position, false);
77
+ drawStatus = false;
78
+ if (typeof callback == "function") callback(polygon);
79
+ }, Cesium.ScreenSpaceEventType.RIGHT_DOWN);
80
+
81
+ //Ctrl + Z回退
82
+ document.onkeydown = function (event) {
83
+ if (event.ctrlKey && window.event.keyCode == 90) {
84
+ if (!drawStatus) {
85
+ return false;
86
+ }
87
+ anchorpoints.pop();
88
+ if (anchorpoints.length == 2) {
89
+ toolTip = "左键添加第二个点";
90
+ }
91
+ }
92
+ };
93
+ };
94
+ function getCatesian3FromPX(viewer, px) {
95
+ let picks = viewer.scene.drillPick(px);
96
+ let cartesian = null;
97
+ let isOn3dtiles = false,
98
+ isOnTerrain = false;
99
+ // drillPick
100
+ for (let i in picks) {
101
+ let pick = picks[i];
102
+ if (
103
+ (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
104
+ (pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
105
+ (pick && pick.primitive instanceof Cesium.Model)
106
+ ) {
107
+ //模型上拾取
108
+ isOn3dtiles = true;
109
+ }
110
+ // 3dtilset
111
+ if (isOn3dtiles) {
112
+ viewer.scene.pick(px);
113
+ cartesian = viewer.scene.pickPosition(px);
114
+ if (cartesian) {
115
+ let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
116
+ if (cartographic.height < 0) cartographic.height = 0;
117
+ let lon = Cesium.Math.toDegrees(cartographic.longitude),
118
+ lat = Cesium.Math.toDegrees(cartographic.latitude),
119
+ height = cartographic.height;
120
+ cartesian = transformWGS84ToCartesian(viewer, {
121
+ lng: lon,
122
+ lat: lat,
123
+ alt: height,
124
+ });
125
+ }
126
+ }
127
+ }
128
+ // 地形
129
+ let boolTerrain =
130
+ viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
131
+ // Terrain
132
+ if (!isOn3dtiles && !boolTerrain) {
133
+ let ray = viewer.scene.camera.getPickRay(px);
134
+ if (!ray) return null;
135
+ cartesian = viewer.scene.globe.pick(ray, viewer.scene);
136
+ isOnTerrain = true;
137
+ }
138
+ // 地球
139
+ if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
140
+ cartesian = viewer.scene.camera.pickEllipsoid(
141
+ px,
142
+ viewer.scene.globe.ellipsoid
143
+ );
144
+ }
145
+ if (cartesian) {
146
+ let position = transformCartesianToWGS84(viewer, cartesian);
147
+ if (position.alt < 0) {
148
+ cartesian = transformWGS84ToCartesian(viewer, position, 0.1);
149
+ }
150
+ return cartesian;
151
+ }
152
+ return false;
153
+ }
154
+
155
+ /***
156
+ * 坐标转换 84转笛卡尔
157
+ * @param {Object} {lng,lat,alt} 地理坐标
158
+ * @return {Object} Cartesian3 三维位置坐标
159
+ */
160
+ function transformWGS84ToCartesian(viewer, position, alt) {
161
+ return position
162
+ ? Cesium.Cartesian3.fromDegrees(
163
+ position.lng || position.lon,
164
+ position.lat,
165
+ (position.alt = alt || position.alt),
166
+ Cesium.Ellipsoid.WGS84
167
+ )
168
+ : Cesium.Cartesian3.ZERO;
169
+ }
170
+
171
+ /***
172
+ * 坐标转换 笛卡尔转84
173
+ * @param {Object} Cartesian3 三维位置坐标
174
+ * @return {Object} {lng,lat,alt} 地理坐标
175
+ */
176
+ function transformCartesianToWGS84(viewer, cartesian) {
177
+ let ellipsoid = Cesium.Ellipsoid.WGS84;
178
+ let cartographic = ellipsoid.cartesianToCartographic(cartesian);
179
+ return {
180
+ lng: Cesium.Math.toDegrees(cartographic.longitude),
181
+ lat: Cesium.Math.toDegrees(cartographic.latitude),
182
+ alt: cartographic.height,
183
+ };
184
+ }
185
+ function setSessionid(num) {
186
+ let len = num || 32;
187
+ let chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
188
+ let maxPos = chars.length;
189
+ let pwd = "";
190
+ for (let i = 0; i < len; i++) {
191
+ pwd += chars.charAt(Math.floor(Math.random() * maxPos));
192
+ }
193
+ return pwd;
194
+ }
195
+ export default CreatePolygonOnGround;
@@ -0,0 +1,71 @@
1
+ const CreateRemindertip = function (arr, position, show) {
2
+ let tooltip = document.getElementById("toolTip");
3
+ let style, _x, _y, _color;
4
+ if (arr && typeof arr === "object") {
5
+ style = arr;
6
+ }
7
+ if (style && style.origin) {
8
+ style.origin === "center" && ((_x = 15), (_y = -12));
9
+ style.origin === "top" && ((_x = 15), (_y = -44));
10
+ style.origin === "bottom" && ((_x = 15), (_y = 20));
11
+ } else {
12
+ (_x = 15), (_y = 20);
13
+ }
14
+ if (style && style.color) {
15
+ style.color === "white" &&
16
+ (_color = "background: rgba(255, 255, 255, 0.8);color: black;");
17
+ style.color === "black" &&
18
+ (_color = "background: rgba(0, 0, 0, 0.5);color: white;");
19
+ style.color === "yellow" &&
20
+ (_color =
21
+ "color: black;background-color: #ffcc33;border: 1px solid white;");
22
+ } else {
23
+ _color = "background: rgba(0, 0, 0, 0.5);color: white;";
24
+ }
25
+ if (!tooltip) {
26
+ const viewerDom = document.getElementsByClassName("cesium-viewer")[0];
27
+ let elementbottom = document.createElement("div");
28
+ viewerDom.append(elementbottom);
29
+ let html =
30
+ '<div id="toolTip" style="display: none;pointer-events: none;position: absolute;z-index: 1000;opacity: 0.8;border-radius: 4px;padding: 4px 8px;white-space: nowrap;font-family:黑体;color:white;font-weight: bolder;font-size: 14px;' +
31
+ _color +
32
+ '"></div>';
33
+ viewerDom.insertAdjacentHTML("beforeend", html);
34
+ tooltip = document.getElementById("toolTip");
35
+ }
36
+ if (show) {
37
+ tooltip.innerHTML = arr;
38
+ tooltip.style.left = position.x + _x + "px";
39
+ tooltip.style.top = position.y + _y + "px";
40
+ tooltip.style.display = "block";
41
+ } else {
42
+ tooltip.style.display = "none";
43
+ }
44
+ return {
45
+ tooltip: tooltip,
46
+ style: style,
47
+ showAt: function (position, text) {
48
+ this.tooltip.innerHTML = text;
49
+ if (this.style && this.style.origin) {
50
+ this.style.origin === "center" &&
51
+ ((_x = 15), (_y = -this.tooltip.offsetHeight / 2));
52
+ this.style.origin === "top" &&
53
+ ((_x = 15), (_y = -this.tooltip.offsetHeight - 20));
54
+ this.style.origin === "bottom" && ((_x = 15), (_y = 20));
55
+ } else {
56
+ (_x = 15), (_y = -this.tooltip.offsetHeight / 2);
57
+ }
58
+ this.tooltip.style.left = position.x + _x + "px";
59
+ this.tooltip.style.top = position.y + _y + "px";
60
+ this.tooltip.style.display = "block";
61
+ },
62
+ show: function (show) {
63
+ if (show) {
64
+ this.tooltip.style.display = "block";
65
+ } else {
66
+ this.tooltip.style.display = "none";
67
+ }
68
+ },
69
+ };
70
+ };
71
+ export default CreateRemindertip;
@@ -5,12 +5,25 @@ enum ECollectionWhiteListNames {
5
5
  POLYGON = 'polygon',
6
6
 
7
7
  MEASURE_DISTANCE = 'measure_distance',
8
+ MEASURE_HEIGHT = 'measure_height',
9
+ MEASURE_AREA = 'measure_area',
10
+ MEASURE_ALTITUDE = 'measure_altitude',
11
+
12
+ SLOPE = 'slope'
8
13
  }
9
14
 
10
15
  const useCustomCollection = (viewer: Cesium.Viewer) => {
11
16
 
12
17
  let collectionNames: string[] = ([])
13
- let whiteList: string[] = ['polygon', 'polygon_node']
18
+ let whiteList: string[] = [
19
+ 'polygon',
20
+ 'polygon_node',
21
+ 'measure_distance',
22
+ 'measure_height',
23
+ 'measure_area',
24
+ 'measure_altitude',
25
+ 'slope'
26
+ ]
14
27
 
15
28
  const addCollection = (name: string) => {
16
29
  const index = collectionNames.findIndex(item => item === name)
@@ -1,17 +1,13 @@
1
1
  import * as Cesium from 'cesium'
2
+ import * as turf from "@turf/turf"
2
3
 
3
4
  const useMeasure = (viewer: Cesium.Viewer, options: {
4
- distanceCollection: Cesium.CustomDataSource
5
+ distanceCollection: Cesium.CustomDataSource,
6
+ heightCollection: Cesium.CustomDataSource,
7
+ areaCollection: Cesium.CustomDataSource,
8
+ altitudeCollection: Cesium.CustomDataSource
5
9
  }) => {
6
10
 
7
- const point = {
8
- color: Cesium.Color.fromCssColorString("rgb(249,157,11)"),
9
- outlineColor: Cesium.Color.WHITE,
10
- outlineWidth: 2,
11
- pixelSize: 10,
12
- heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
13
- }
14
-
15
11
  const angleMeasurement = () => {
16
12
  let anglePoints = []
17
13
  let angleEntities = []
@@ -66,7 +62,7 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
66
62
  }
67
63
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
68
64
 
69
- angleMeasurementHandler.setInputAction(function (movement) {
65
+ angleMeasurementHandler.setInputAction((movement) => {
70
66
  if (anglePoints.length > 0 && anglePoints.length < 3) {
71
67
  const ray = viewer.camera.getPickRay(movement.endPosition)
72
68
  const cartesian = viewer.scene.globe.pick(ray, viewer.scene)
@@ -112,7 +108,7 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
112
108
  position: p2,
113
109
  label: {
114
110
  text: angleDeg.toFixed(2) + '°',
115
- font: 'normal 22px MicroSoft YaHei',
111
+ font: 'normal 28px MicroSoft YaHei',
116
112
  style: Cesium.LabelStyle.FILL_AND_OUTLINE,
117
113
  fillColor: Cesium.Color.WHITE,
118
114
  verticalOrigin: Cesium.VerticalOrigin.CENTER,
@@ -154,11 +150,20 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
154
150
  const distanceMeasurement = () => {
155
151
  let positions = []
156
152
  let tempPositions = []
153
+ let currentLineEntity: Cesium.Entity
157
154
  let handler = null
158
155
 
156
+ const point = {
157
+ color: Cesium.Color.fromCssColorString("rgb(249,157,11)"),
158
+ outlineColor: Cesium.Color.WHITE,
159
+ outlineWidth: 2,
160
+ pixelSize: 10,
161
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
162
+ }
163
+
159
164
  const draw = () => {
160
165
  if (handler) {
161
- console.log('请先右键结束上次测量!');
166
+ console.log('请使用右键结束上次测量!')
162
167
  return
163
168
  }
164
169
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
@@ -168,6 +173,10 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
168
173
  }
169
174
 
170
175
  const stopDraw = () => {
176
+ if (currentLineEntity) {
177
+ options.distanceCollection.entities.remove(currentLineEntity)
178
+ }
179
+
171
180
  if (handler) {
172
181
  handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
173
182
  handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
@@ -181,11 +190,12 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
181
190
  }
182
191
 
183
192
  const removeAll = () => {
193
+ stopDraw()
184
194
  options.distanceCollection.entities.removeAll()
185
195
  }
186
196
 
187
197
  const createLine = () => {
188
- options.distanceCollection.entities.add({
198
+ currentLineEntity = options.distanceCollection.entities.add({
189
199
  polyline: {
190
200
  positions: new Cesium.CallbackProperty(() => tempPositions, false),
191
201
  material: Cesium.Color.fromCssColorString("rgb(249,157,11)"),
@@ -232,7 +242,14 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
232
242
  }
233
243
 
234
244
  const leftClickEvent = () => {
245
+ let lastClickTime = 0
246
+ const MIN_INTERVAL = 250
247
+
235
248
  handler.setInputAction(event => {
249
+ const now = Date.now()
250
+ if (now - lastClickTime < MIN_INTERVAL) return
251
+ lastClickTime = now
252
+
236
253
  let position = viewer.scene.pickPosition(event.position)
237
254
  if (!position)
238
255
  position = viewer.scene.camera.pickEllipsoid(event.position, viewer.scene.globe.ellipsoid)
@@ -266,7 +283,7 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
266
283
 
267
284
  const rightClickEvent = () => {
268
285
  handler.setInputAction(() => {
269
- if (positions.length < 1) {
286
+ if (positions.length <= 1) {
270
287
  removeAll()
271
288
  stopDraw()
272
289
  } else {
@@ -290,15 +307,514 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
290
307
  }
291
308
 
292
309
  const heightMeasurement = () => {
310
+ let positions = []
311
+ let currentLineEntity: Cesium.Entity
312
+ let currentPointEntities: Cesium.Entity[] = []
313
+ let currentLabelEntity: Cesium.Entity
314
+ let handler = null
315
+
316
+ const cartesian3Point3 = (pos) => {
317
+ const ellipsoid = viewer.scene.globe.ellipsoid
318
+ const cartographic = ellipsoid.cartesianToCartographic(pos)
319
+ return [
320
+ Cesium.Math.toDegrees(cartographic.longitude),
321
+ Cesium.Math.toDegrees(cartographic.latitude),
322
+ cartographic.height
323
+ ]
324
+ }
325
+
326
+ const draw = () => {
327
+ if (handler) {
328
+ console.log('请先结束上次测量!')
329
+ return
330
+ }
331
+ handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
332
+ leftClickEvent()
333
+ mouseMoveEvent()
334
+ }
335
+
336
+ const createLine = () => {
337
+ currentLineEntity = options.heightCollection.entities.add({
338
+ polyline: {
339
+ positions: new Cesium.CallbackProperty(() => positions, false),
340
+ width: 2,
341
+ material: Cesium.Color.fromCssColorString("rgb(249,157,11)")
342
+ }
343
+ })
344
+ }
345
+
346
+ const createPoint = (index) => {
347
+ const entity = options.heightCollection.entities.add({
348
+ position: new Cesium.CallbackProperty(() => positions[index], false) as Cesium.CallbackPositionProperty,
349
+ point: {
350
+ color: Cesium.Color.fromCssColorString("rgb(249,157,11)"),
351
+ outlineColor: Cesium.Color.WHITE,
352
+ outlineWidth: 2,
353
+ pixelSize: 10
354
+ }
355
+ })
356
+
357
+ currentPointEntities.push(entity)
358
+ }
359
+
360
+ const createLabel = () => {
361
+ currentLabelEntity = options.heightCollection.entities.add({
362
+ position: new Cesium.CallbackProperty(() => positions[1], false) as Cesium.CallbackPositionProperty,
363
+ label: {
364
+ text: "",
365
+ scale: 0.5,
366
+ font: "normal 28px MicroSoft YaHei",
367
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
368
+ pixelOffset: new Cesium.Cartesian2(0, -30),
369
+ outlineWidth: 9,
370
+ outlineColor: Cesium.Color.WHITE
371
+ }
372
+ })
373
+ }
374
+
375
+ const leftClickEvent = () => {
376
+ let lastClickTime = 0
377
+ const MIN_INTERVAL = 250
378
+
379
+ handler.setInputAction(e => {
380
+ const now = Date.now()
381
+ if (now - lastClickTime < MIN_INTERVAL) return
382
+ lastClickTime = now
383
+
384
+ let position = viewer.scene.pickPosition(e.position)
385
+ if (!position) position = viewer.scene.camera.pickEllipsoid(e.position, viewer.scene.globe.ellipsoid)
386
+ if (!position) return
387
+
388
+ if (positions.length === 0) {
389
+ positions.push(position)
390
+ createPoint(0)
391
+ createLine()
392
+ createLabel()
393
+ } else if (positions.length > 2) {
394
+ options.heightCollection.entities.add({
395
+ polyline: {
396
+ positions: positions,
397
+ width: 2,
398
+ material: Cesium.Color.fromCssColorString("rgb(249,157,11)")
399
+ }
400
+ })
401
+
402
+ positions.forEach(pos => {
403
+ options.heightCollection.entities.add({
404
+ position: pos,
405
+ point: {
406
+ color: Cesium.Color.fromCssColorString("rgb(249,157,11)"),
407
+ outlineColor: Cesium.Color.WHITE,
408
+ outlineWidth: 2,
409
+ pixelSize: 10
410
+ }
411
+ })
412
+ })
413
+
414
+ options.heightCollection.entities.add({
415
+ position: positions[1],
416
+ label: {
417
+ text: currentLabelEntity.label.text,
418
+ scale: 0.5,
419
+ font: "normal 28px MicroSoft YaHei",
420
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
421
+ pixelOffset: new Cesium.Cartesian2(0, -30),
422
+ outlineWidth: 9,
423
+ outlineColor: Cesium.Color.WHITE
424
+ }
425
+ })
426
+
427
+ stopDraw()
428
+ }
429
+ }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
430
+ }
431
+
432
+ const mouseMoveEvent = () => {
433
+ handler.setInputAction(e => {
434
+ let position = viewer.scene.pickPosition(e.endPosition)
435
+ if (!position) position = viewer.scene.camera.pickEllipsoid(e.startPosition, viewer.scene.globe.ellipsoid)
436
+ if (!position) return
437
+
438
+ handleMove(position)
439
+ }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
440
+ }
441
+
442
+ const handleMove = (position) => {
443
+ if (positions.length < 1) return
444
+ const first = cartesian3Point3(positions[0])
445
+ const move = cartesian3Point3(position)
446
+
447
+ const h = move[2] - first[2]
448
+ first[2] = move[2]
449
+ const twoPos = Cesium.Cartesian3.fromDegrees(first[0], first[1], move[2])
450
+
451
+ if (positions.length < 2) {
452
+ positions.push(twoPos, position)
453
+ createPoint(1)
454
+ createPoint(2)
455
+ } else {
456
+ positions[1] = twoPos
457
+ positions[2] = position
458
+ if (currentLabelEntity) {
459
+ (currentLabelEntity.label.text as any) = `高度:${h.toFixed(3)} 米`
460
+ }
461
+ }
462
+ }
463
+
464
+ const stopDraw = () => {
465
+ if (handler) {
466
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
467
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
468
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
469
+ handler.destroy()
470
+ handler = null
471
+ }
472
+
473
+ if (currentLineEntity) {
474
+ options.heightCollection.entities.remove(currentLineEntity)
475
+ currentLineEntity = null
476
+ }
477
+ if (currentLabelEntity) {
478
+ options.heightCollection.entities.remove(currentLabelEntity)
479
+ currentLabelEntity = null
480
+ }
481
+ if (currentPointEntities.length) {
482
+ currentPointEntities.forEach(entity => options.heightCollection.entities.remove(entity))
483
+ currentPointEntities = []
484
+ }
485
+
486
+ positions = []
487
+ }
488
+
489
+ const removeAll = () => {
490
+ stopDraw()
491
+ options.heightCollection.entities.removeAll()
492
+ }
493
+
494
+ return {
495
+ draw,
496
+ removeAll
497
+ }
498
+ }
499
+
500
+ const areaMeasurement = () => {
501
+ let handler = null
502
+ let currentPolygonEntity = null
503
+ let currentLabelEntity = null
504
+ let positions = []
505
+ let tempPositions = []
506
+ let height = undefined
507
+
508
+ const draw = () => {
509
+ if (handler) {
510
+ console.log('请使用右键结束上次测量!')
511
+ return
512
+ }
513
+ handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
514
+ leftClickEvent()
515
+ mouseMoveEvent()
516
+ rightClickEvent()
517
+ }
293
518
 
519
+ const stopDraw = () => {
520
+ if (handler) {
521
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
522
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
523
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
524
+ handler.destroy()
525
+ handler = null
526
+ }
527
+
528
+ tempPositions = []
529
+ positions = []
530
+ currentPolygonEntity = null
531
+ currentLabelEntity = null
532
+ height = undefined
533
+ }
534
+
535
+ const removeAll = () => {
536
+ stopDraw()
537
+ options.areaCollection.entities.removeAll()
538
+ }
539
+
540
+ const createPolygon = () => {
541
+ currentPolygonEntity = options.areaCollection.entities.add({
542
+ polygon: {
543
+ hierarchy: new Cesium.CallbackProperty(() => {
544
+ return new Cesium.PolygonHierarchy(tempPositions)
545
+ }, false),
546
+ material: Cesium.Color.fromCssColorString("rgb(249, 157, 11,.6)")
547
+ },
548
+ polyline: {
549
+ clampToGround: true,
550
+ positions: new Cesium.CallbackProperty(() => {
551
+ return tempPositions.concat(tempPositions[0])
552
+ }, false),
553
+ width: 1,
554
+ material: new Cesium.PolylineOutlineMaterialProperty({
555
+ outlineWidth: 2,
556
+ outlineColor: Cesium.Color.WHITE
557
+ })
558
+ }
559
+ })
560
+ }
561
+
562
+ const createPoint = () => {
563
+ options.areaCollection.entities.add({
564
+ position: positions[positions.length - 1],
565
+ point: {
566
+ color: Cesium.Color.fromCssColorString("rgb(249, 157, 11)"),
567
+ outlineColor: Cesium.Color.WHITE,
568
+ outlineWidth: 2,
569
+ pixelSize: 10,
570
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
571
+ }
572
+ })
573
+ }
574
+
575
+ const createLabel = () => {
576
+ currentLabelEntity = options.areaCollection.entities.add({
577
+ position: new Cesium.CallbackProperty(() => getCenterPosition(), false) as Cesium.CallbackPositionProperty,
578
+ label: {
579
+ text: new Cesium.CallbackProperty(() => {
580
+ return "面积 " + computeArea(tempPositions)
581
+ }, false),
582
+ scale: 0.5,
583
+ font: "normal 28px MicroSoft YaHei",
584
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
585
+ pixelOffset: new Cesium.Cartesian2(0, -30),
586
+ outlineWidth: 9,
587
+ outlineColor: Cesium.Color.WHITE,
588
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
589
+ }
590
+ })
591
+ }
592
+
593
+ const getCenterPosition = () => {
594
+ if (tempPositions.length < 3) return tempPositions[0]
595
+ const points = tempPositions.map(p => {
596
+ const c = cartesian3ToPoint3D(p)
597
+ return [c.x, c.y]
598
+ })
599
+ const geo = turf.lineString(points)
600
+ const bbox = turf.bbox(geo)
601
+ const bboxPolygon = turf.bboxPolygon(bbox)
602
+ const center = turf.center(bboxPolygon)
603
+ const [lon, lat] = center.geometry.coordinates
604
+ return Cesium.Cartesian3.fromDegrees(lon, lat, height + 0.3)
605
+ }
606
+
607
+ const leftClickEvent = () => {
608
+ let lastClickTime = 0
609
+ const MIN_INTERVAL = 250
610
+
611
+ handler.setInputAction(e => {
612
+ const now = Date.now()
613
+ if (now - lastClickTime < MIN_INTERVAL) return
614
+ lastClickTime = now
615
+
616
+ let position = viewer.scene.pickPosition(e.position)
617
+ if (!position) {
618
+ const ellipsoid = viewer.scene.globe.ellipsoid
619
+ position = viewer.scene.camera.pickEllipsoid(e.position, ellipsoid)
620
+ }
621
+ if (!position) return
622
+
623
+ positions.push(position)
624
+ height = unifiedHeight(positions, height)
625
+ if (positions.length === 1) {
626
+ createPolygon()
627
+ }
628
+ createPoint()
629
+ }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
630
+ }
631
+
632
+ const mouseMoveEvent = () => {
633
+ handler.setInputAction(e => {
634
+ let position = viewer.scene.pickPosition(e.endPosition)
635
+ if (!position)
636
+ position = viewer.scene.camera.pickEllipsoid(
637
+ e.startPosition,
638
+ viewer.scene.globe.ellipsoid
639
+ )
640
+ if (!position) return
641
+ handleMoveEvent(position)
642
+ }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
643
+ }
644
+
645
+ const rightClickEvent = () => {
646
+ handler.setInputAction(e => {
647
+ if (positions.length < 3) {
648
+ stopDraw()
649
+ removeAll()
650
+ } else {
651
+ tempPositions = [...positions]
652
+ currentPolygonEntity.polygon.hierarchy = new Cesium.PolygonHierarchy(tempPositions)
653
+ currentLabelEntity.position = getCenterPosition()
654
+ currentLabelEntity.label.text = "总面积为 " + computeArea(positions)
655
+ stopDraw()
656
+ }
657
+ }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
658
+ }
659
+
660
+ const handleMoveEvent = (position) => {
661
+ if (positions.length < 1) return
662
+ height = unifiedHeight(positions, height)
663
+ tempPositions = positions.concat(position)
664
+ if (tempPositions.length >= 3 && !currentLabelEntity) createLabel()
665
+ }
666
+
667
+ const unifiedHeight = (positions, height) => {
668
+ if (!height) height = getPositionHeight(positions[0])
669
+ for (let i = 0; i < positions.length; i++) {
670
+ const p = cartesian3ToPoint3D(positions[i])
671
+ positions[i] = Cesium.Cartesian3.fromDegrees(p.x, p.y, height)
672
+ }
673
+ return height
674
+ }
675
+
676
+ const computeArea = (points) => {
677
+ let res = 0
678
+ for (let i = 0; i < points.length - 2; i++) {
679
+ const j = (i + 1) % points.length
680
+ const k = (i + 2) % points.length
681
+ const angle = Angle(points[i], points[j], points[k])
682
+ const dis1 = distance(points[j], points[0])
683
+ const dis2 = distance(points[k], points[0])
684
+ res += (dis1 * dis2 * Math.sin(angle)) / 2
685
+ }
686
+ return res < 1000000
687
+ ? Math.abs(res).toFixed(4) + " 平方米"
688
+ : Math.abs(res / 1000000).toFixed(4) + " 平方公里"
689
+ }
690
+
691
+ const Bearing = (from, to) => {
692
+ from = Cesium.Cartographic.fromCartesian(from)
693
+ to = Cesium.Cartographic.fromCartesian(to)
694
+ const lat1 = from.latitude, lon1 = from.longitude
695
+ const lat2 = to.latitude, lon2 = to.longitude
696
+ let angle = -Math.atan2(
697
+ Math.sin(lon1 - lon2) * Math.cos(lat2),
698
+ Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
699
+ )
700
+ if (angle < 0) angle += Math.PI * 2.0
701
+ return (angle * 180.0) / Math.PI
702
+ }
703
+
704
+ const Angle = (p1, p2, p3) => {
705
+ const b21 = Bearing(p2, p1)
706
+ const b23 = Bearing(p2, p3)
707
+ let angle = b21 - b23
708
+ if (angle < 0) angle += 360
709
+ return angle
710
+ }
711
+
712
+ const distance = (p1, p2) => {
713
+ const c1 = Cesium.Cartographic.fromCartesian(p1)
714
+ const c2 = Cesium.Cartographic.fromCartesian(p2)
715
+ const geodesic = new Cesium.EllipsoidGeodesic()
716
+ geodesic.setEndPoints(c1, c2)
717
+ let s = geodesic.surfaceDistance
718
+ return Math.sqrt(s * s + Math.pow(c2.height - c1.height, 2))
719
+ }
720
+
721
+ const getPositionHeight = (p) => {
722
+ const c = Cesium.Cartographic.fromCartesian(p)
723
+ return c.height
724
+ }
725
+
726
+ const cartesian3ToPoint3D = (p) => {
727
+ const c = Cesium.Cartographic.fromCartesian(p)
728
+ return {
729
+ x: Cesium.Math.toDegrees(c.longitude),
730
+ y: Cesium.Math.toDegrees(c.latitude),
731
+ z: c.height
732
+ }
733
+ }
734
+
735
+ return {
736
+ draw,
737
+ removeAll
738
+ }
739
+ }
740
+
741
+ const altitudeMeasurement = () => {
742
+ let handler = null
743
+
744
+ const enable = () => {
745
+ disable();
746
+
747
+ (viewer.container as HTMLElement).style.cursor = "crosshair"
748
+
749
+ handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
750
+ handler.setInputAction(async (event) => {
751
+ const cartesian = viewer.scene.pickPosition(event.position)
752
+ if (!cartesian) return
753
+
754
+ const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
755
+ const lon = Cesium.Math.toDegrees(cartographic.longitude)
756
+ const lat = Cesium.Math.toDegrees(cartographic.latitude)
757
+ const height = await getHeightFromLonLat(lon, lat)
758
+
759
+ options.altitudeCollection.entities.add({
760
+ position: Cesium.Cartesian3.fromDegrees(lon, lat, height + 2),
761
+ point: {
762
+ color: Cesium.Color.fromCssColorString("rgb(249, 157, 11)"),
763
+ outlineColor: Cesium.Color.WHITE,
764
+ outlineWidth: 2,
765
+ pixelSize: 10,
766
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
767
+ },
768
+ label: {
769
+ text: `${height.toFixed(2)} m`,
770
+ scale: 0.5,
771
+ font: "normal 28px MicroSoft YaHei",
772
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
773
+ pixelOffset: new Cesium.Cartesian2(0, -30),
774
+ outlineWidth: 9,
775
+ outlineColor: Cesium.Color.WHITE
776
+ },
777
+ })
778
+ }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
779
+ }
780
+
781
+ const getHeightFromLonLat = async (lon, lat) => {
782
+ const positions = [Cesium.Cartographic.fromDegrees(lon, lat)]
783
+ const updated = await Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, positions)
784
+ return updated[0].height || 0
785
+ }
786
+
787
+ const disable = () => {
788
+ if (handler) {
789
+ handler.destroy()
790
+ handler = null
791
+ }
792
+ (viewer.container as HTMLElement).style.cursor = "default"
793
+ }
794
+
795
+ const removeAll = () => {
796
+ options.altitudeCollection.entities.removeAll()
797
+ }
798
+
799
+ return {
800
+ enable,
801
+ disable,
802
+ removeAll
803
+ }
294
804
  }
295
805
 
296
806
  const angle = angleMeasurement()
297
807
  const distance = distanceMeasurement()
808
+ const height = heightMeasurement()
809
+ const area = areaMeasurement()
810
+ const altitude = altitudeMeasurement()
298
811
 
299
812
  return {
300
813
  angle,
301
- distance
814
+ distance,
815
+ height,
816
+ area,
817
+ altitude
302
818
  }
303
819
  }
304
820
 
@@ -0,0 +1,300 @@
1
+ import * as Cesium from "cesium"
2
+ import * as turf from "@turf/turf"
3
+ import CreatePolygonOnGround from "./lib/CreatePolygonOnGround"
4
+ // import CreateRemindertip from "./lib/ReminderTip"
5
+
6
+ const useSlope = (viewer: Cesium.Viewer, options: {
7
+ collection: Cesium.CustomDataSource
8
+ }) => {
9
+
10
+ let result = []
11
+ // let handler = null
12
+ // let toolTip = ""
13
+ let arrowWidth = 20
14
+
15
+ const Cartesian3ListToWGS84 = (cartesianList) => {
16
+ const ellipsoid = Cesium.Ellipsoid.WGS84
17
+ return cartesianList.map((cartesian) => {
18
+ const cartographic = ellipsoid.cartesianToCartographic(cartesian)
19
+ return {
20
+ lng: Cesium.Math.toDegrees(cartographic.longitude),
21
+ lat: Cesium.Math.toDegrees(cartographic.latitude),
22
+ alt: cartographic.height,
23
+ }
24
+ })
25
+ }
26
+
27
+ const calculateSlopeColor = (value, alpha) => {
28
+ if (value < 0.0087) return `rgba(85,182,43,${alpha})`
29
+ if (value < 0.0349) return `rgba(135,211,43,${alpha})`
30
+ if (value < 0.0874) return `rgba(204,244,44,${alpha})`
31
+ if (value < 0.2679) return `rgba(245,233,44,${alpha})`
32
+ if (value < 0.7002) return `rgba(255,138,43,${alpha})`
33
+ if (value < 1.4281) return `rgba(255,84,43,${alpha})`
34
+ return `rgba(255,32,43,${alpha})`
35
+ }
36
+
37
+ // const openTip = () => {
38
+ // handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
39
+ // handler.setInputAction((movement) => {
40
+ // const pick = viewer.scene.pick(movement.endPosition)
41
+ // if (pick && pick.id && pick.id.type === "SlopeAspect") {
42
+ // toolTip = pick.id.value.toFixed(2)
43
+ // CreateRemindertip(toolTip, movement.endPosition, true)
44
+ // } else {
45
+ // toolTip = ""
46
+ // CreateRemindertip(toolTip, movement.endPosition, false)
47
+ // }
48
+ // }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
49
+ // }
50
+
51
+ // const closeTip = () => {
52
+ // if (handler) {
53
+ // handler.destroy()
54
+ // handler = null
55
+ // }
56
+ // }
57
+
58
+ const drawByDistance = (distance = 0.1, onDrawStart?: (ev: () => void) => void, onComplete?: () => void) => {
59
+ const width = distance * 200 > 35 ? 35 : distance * 200
60
+ arrowWidth = width < 15 ? 15 : width
61
+
62
+ CreatePolygonOnGround({
63
+ viewer,
64
+ collection: options.collection
65
+ }, [],
66
+ {
67
+ color: Cesium.Color.RED.withAlpha(0.1),
68
+ outlineColor: Cesium.Color.YELLOW,
69
+ outlineWidth: 2,
70
+ },
71
+ (polygon) => {
72
+ const degrees = Cartesian3ListToWGS84(polygon.pottingPoint)
73
+ options.collection.entities.remove(polygon)
74
+
75
+ const boundary = degrees.map((p) => [p.lng, p.lat])
76
+ const bbox = turf.bbox(turf.polygon([boundary.concat([boundary[0]])]))
77
+ const mask = turf.polygon([boundary.concat([boundary[0]])])
78
+ const gridSquare = turf.squareGrid(bbox, distance, { mask })
79
+ createEllipse(gridSquare)
80
+
81
+ onComplete && onComplete()
82
+ },
83
+ (drawHandler: () => void) => onDrawStart && onDrawStart(drawHandler)
84
+ )
85
+ }
86
+
87
+ const drawByNum = (num = 10, onDrawStart?: (ev: () => void) => void, onComplete?: () => void) => {
88
+ CreatePolygonOnGround({
89
+ viewer,
90
+ collection: options.collection
91
+ }, [],
92
+ {
93
+ color: Cesium.Color.RED.withAlpha(0.1),
94
+ outlineColor: Cesium.Color.YELLOW,
95
+ outlineWidth: 2,
96
+ },
97
+ (polygon) => {
98
+ const degrees = Cartesian3ListToWGS84(polygon.pottingPoint)
99
+ options.collection.entities.remove(polygon)
100
+
101
+ const boundary = degrees.map((p) => [p.lng, p.lat])
102
+ const bbox = turf.bbox(turf.polygon([boundary.concat([boundary[0]])]))
103
+
104
+ const [minX, minY, maxX, maxY] = bbox
105
+ const step = Math.max(maxX - minX, maxY - minY) / num
106
+
107
+ const width = step * 2000 > 35 ? 35 : step * 2000
108
+ arrowWidth = width < 15 ? 15 : width
109
+
110
+ const mask = turf.polygon([boundary.concat([boundary[0]])])
111
+ const gridSquare = turf.squareGrid(bbox, step, {
112
+ units: "degrees",
113
+ mask,
114
+ })
115
+ createEllipse(gridSquare)
116
+
117
+ onComplete && onComplete()
118
+ },
119
+ (drawHandler: () => void) => { onDrawStart && onDrawStart(drawHandler) }
120
+ )
121
+ }
122
+
123
+ const createEllipse = (gridSquare) => {
124
+ const boxResults = []
125
+
126
+ for (const feature of gridSquare.features) {
127
+ const coordinates = feature.geometry.coordinates[0]
128
+ const centerdegree = [
129
+ (coordinates[0][0] + coordinates[2][0]) / 2,
130
+ (coordinates[0][1] + coordinates[2][1]) / 2,
131
+ ]
132
+ const centerCarto = Cesium.Cartographic.fromDegrees(
133
+ centerdegree[0],
134
+ centerdegree[1]
135
+ )
136
+ boxResults.push(centerCarto)
137
+
138
+ for (let i = 0; i < coordinates.length; i++) {
139
+ const coord = coordinates[i]
140
+ const carto = Cesium.Cartographic.fromDegrees(coord[0], coord[1])
141
+ boxResults.push(carto)
142
+
143
+ const next = coordinates[i + 1]
144
+ if (next) {
145
+ const mid = Cesium.Cartographic.fromDegrees(
146
+ (coord[0] + next[0]) / 2,
147
+ (coord[1] + next[1]) / 2
148
+ )
149
+ boxResults.push(mid)
150
+ }
151
+ }
152
+ }
153
+
154
+ Cesium.sampleTerrainMostDetailed(viewer.scene.terrainProvider, boxResults)
155
+ .then((updatePositions) => {
156
+ const group = []
157
+ for (let i = 0; i < updatePositions.length; i += 10) {
158
+ const slice = updatePositions.slice(i, i + 10)
159
+ if (slice.length) group.push(slice)
160
+ }
161
+ calculateSlope(group)
162
+ })
163
+ }
164
+
165
+ const createPolygonInstance = (points, color) => {
166
+ const positions = points
167
+ .slice(1, -1)
168
+ .map((p) => Cesium.Cartographic.toCartesian(p))
169
+ const polygon = new Cesium.PolygonGeometry({
170
+ polygonHierarchy: new Cesium.PolygonHierarchy(positions),
171
+ })
172
+
173
+ return new Cesium.GeometryInstance({
174
+ geometry: polygon,
175
+ attributes: {
176
+ color: Cesium.ColorGeometryInstanceAttribute.fromColor(
177
+ Cesium.Color.fromCssColorString(color)
178
+ ),
179
+ show: new Cesium.ShowGeometryInstanceAttribute(true),
180
+ },
181
+ })
182
+ }
183
+
184
+ const createArrowInstance = (target, center, diagonal, heightDiff, slope) => {
185
+ const mid0 = new Cesium.Cartographic(
186
+ (target.longitude + center.longitude) / 2,
187
+ (target.latitude + center.latitude) / 2,
188
+ (target.height + center.height) / 2
189
+ )
190
+ const mid1 = new Cesium.Cartographic(
191
+ (diagonal.longitude + center.longitude) / 2,
192
+ (diagonal.latitude + center.latitude) / 2,
193
+ (diagonal.height + center.height) / 2
194
+ )
195
+
196
+ const positions =
197
+ heightDiff > 0
198
+ ? [
199
+ Cesium.Cartographic.toCartesian(mid0),
200
+ Cesium.Cartographic.toCartesian(mid1),
201
+ ]
202
+ : [
203
+ Cesium.Cartographic.toCartesian(mid1),
204
+ Cesium.Cartographic.toCartesian(mid0),
205
+ ]
206
+
207
+ return new Cesium.GeometryInstance({
208
+ id: { type: "SlopeAspect", value: slope },
209
+ geometry: new Cesium.GroundPolylineGeometry({
210
+ positions,
211
+ width: arrowWidth,
212
+ }),
213
+ attributes: {
214
+ color: Cesium.ColorGeometryInstanceAttribute.fromColor(
215
+ Cesium.Color.BLUE.withAlpha(0.6)
216
+ ),
217
+ show: new Cesium.ShowGeometryInstanceAttribute(true),
218
+ },
219
+ })
220
+ }
221
+
222
+ const calculateSlope = (groups) => {
223
+ const polygons = []
224
+ const arrows = []
225
+
226
+ for (const ellipse of groups) {
227
+ const center = ellipse[0]
228
+ let maxHD = 0
229
+ let maxIndex = 0
230
+
231
+ for (let i = 1; i < ellipse.length; i++) {
232
+ const hd = ellipse[i].height - center.height
233
+ if (Math.abs(hd) > Math.abs(maxHD)) {
234
+ maxHD = hd
235
+ maxIndex = i
236
+ }
237
+ }
238
+
239
+ const p0 = new Cesium.Cartographic(center.longitude, center.latitude, 0)
240
+ const p1 = new Cesium.Cartographic(
241
+ ellipse[maxIndex].longitude,
242
+ ellipse[maxIndex].latitude,
243
+ 0
244
+ )
245
+
246
+ const dist = Cesium.Cartesian3.distance(
247
+ Cesium.Cartographic.toCartesian(p0),
248
+ Cesium.Cartographic.toCartesian(p1)
249
+ )
250
+ const slope = Math.abs(maxHD / dist)
251
+ const color = calculateSlopeColor(slope, 0.4)
252
+
253
+ polygons.push(createPolygonInstance(ellipse, color))
254
+
255
+ const diag = ellipse[maxIndex > 4 ? maxIndex - 4 : maxIndex + 4]
256
+ arrows.push(createArrowInstance(ellipse[maxIndex], center, diag, maxHD, slope))
257
+ }
258
+
259
+ const polyPrimitive = viewer.scene.primitives.add(
260
+ new Cesium.GroundPrimitive({
261
+ geometryInstances: polygons,
262
+ appearance: new Cesium.PerInstanceColorAppearance({
263
+ translucent: true,
264
+ closed: false,
265
+ }),
266
+ })
267
+ )
268
+
269
+ const arrowPrimitive = viewer.scene.primitives.add(
270
+ new Cesium.GroundPolylinePrimitive({
271
+ geometryInstances: arrows,
272
+ appearance: new Cesium.PolylineMaterialAppearance({
273
+ material: new Cesium.Material({
274
+ fabric: {
275
+ type: "PolylineArrow",
276
+ uniforms: { color: new Cesium.Color(1, 1, 0, 0.8) },
277
+ },
278
+ }),
279
+ }),
280
+ })
281
+ )
282
+
283
+ result.push(polyPrimitive, arrowPrimitive)
284
+ }
285
+
286
+ const removeAll = () => {
287
+ result.forEach((p) => viewer.scene.primitives.remove(p))
288
+ result = []
289
+ }
290
+
291
+ return {
292
+ drawByDistance,
293
+ drawByNum,
294
+ removeAll
295
+ }
296
+ }
297
+
298
+ export {
299
+ useSlope
300
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-three-utils",
3
- "version": "0.0.346",
3
+ "version": "0.0.348",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"