easy-three-utils 0.0.347 → 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;
@@ -89,7 +90,11 @@ const useCesium = () => {
89
90
  const measure = hooks.useMeasure(viewer, {
90
91
  distanceCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_DISTANCE),
91
92
  heightCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_HEIGHT),
92
- areaCollection: customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.MEASURE_AREA)
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)
93
98
  })
94
99
 
95
100
  if (config.controllerStyle === cesiumConfigDict.EControllerStyle.THREE) {
@@ -102,7 +107,8 @@ const useCesium = () => {
102
107
  drawPolygon,
103
108
  clipping,
104
109
  weather,
105
- measure
110
+ measure,
111
+ slope
106
112
  })
107
113
 
108
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;
@@ -6,13 +6,24 @@ enum ECollectionWhiteListNames {
6
6
 
7
7
  MEASURE_DISTANCE = 'measure_distance',
8
8
  MEASURE_HEIGHT = 'measure_height',
9
- MEASURE_AREA = 'measure_area'
9
+ MEASURE_AREA = 'measure_area',
10
+ MEASURE_ALTITUDE = 'measure_altitude',
11
+
12
+ SLOPE = 'slope'
10
13
  }
11
14
 
12
15
  const useCustomCollection = (viewer: Cesium.Viewer) => {
13
16
 
14
17
  let collectionNames: string[] = ([])
15
- let whiteList: string[] = ['polygon', 'polygon_node', 'measure_distance', 'measure_height', 'measure_area']
18
+ let whiteList: string[] = [
19
+ 'polygon',
20
+ 'polygon_node',
21
+ 'measure_distance',
22
+ 'measure_height',
23
+ 'measure_area',
24
+ 'measure_altitude',
25
+ 'slope'
26
+ ]
16
27
 
17
28
  const addCollection = (name: string) => {
18
29
  const index = collectionNames.findIndex(item => item === name)
@@ -4,7 +4,8 @@ import * as turf from "@turf/turf"
4
4
  const useMeasure = (viewer: Cesium.Viewer, options: {
5
5
  distanceCollection: Cesium.CustomDataSource,
6
6
  heightCollection: Cesium.CustomDataSource,
7
- areaCollection: Cesium.CustomDataSource
7
+ areaCollection: Cesium.CustomDataSource,
8
+ altitudeCollection: Cesium.CustomDataSource
8
9
  }) => {
9
10
 
10
11
  const angleMeasurement = () => {
@@ -107,7 +108,7 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
107
108
  position: p2,
108
109
  label: {
109
110
  text: angleDeg.toFixed(2) + '°',
110
- font: 'normal 22px MicroSoft YaHei',
111
+ font: 'normal 28px MicroSoft YaHei',
111
112
  style: Cesium.LabelStyle.FILL_AND_OUTLINE,
112
113
  fillColor: Cesium.Color.WHITE,
113
114
  verticalOrigin: Cesium.VerticalOrigin.CENTER,
@@ -611,7 +612,7 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
611
612
  const now = Date.now()
612
613
  if (now - lastClickTime < MIN_INTERVAL) return
613
614
  lastClickTime = now
614
-
615
+
615
616
  let position = viewer.scene.pickPosition(e.position)
616
617
  if (!position) {
617
618
  const ellipsoid = viewer.scene.globe.ellipsoid
@@ -737,16 +738,83 @@ const useMeasure = (viewer: Cesium.Viewer, options: {
737
738
  }
738
739
  }
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
+ }
804
+ }
805
+
740
806
  const angle = angleMeasurement()
741
807
  const distance = distanceMeasurement()
742
808
  const height = heightMeasurement()
743
809
  const area = areaMeasurement()
810
+ const altitude = altitudeMeasurement()
744
811
 
745
812
  return {
746
813
  angle,
747
814
  distance,
748
815
  height,
749
- area
816
+ area,
817
+ altitude
750
818
  }
751
819
  }
752
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.347",
3
+ "version": "0.0.348",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"