easy-three-utils 0.0.397 → 0.0.398

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.
@@ -1,11 +1,8 @@
1
1
  .profile-echarts-box {
2
- position: absolute;
3
- bottom: 30px;
4
- left: 20vw;
5
- z-index: 180;
6
2
 
7
3
  .profile-echarts {
8
- width: 60vw;
4
+ min-width: 500px;
9
5
  height: 300px;
6
+ width: 100%;
10
7
  }
11
8
  }
@@ -9,6 +9,7 @@ const ProFileEchartCom: React.FC<{
9
9
  value: (number | string)[][]
10
10
  }
11
11
  display: boolean
12
+ style?: React.CSSProperties
12
13
  }> = memo((props) => {
13
14
 
14
15
  const { data, display } = props
@@ -117,7 +118,7 @@ const ProFileEchartCom: React.FC<{
117
118
 
118
119
  return (
119
120
  <>
120
- <div className={Styles['profile-echarts-box']} style={{ display: display ? '' : 'none' }}>
121
+ <div className={Styles['profile-echarts-box']} style={{ display: display ? '' : 'none', ...props.style }}>
121
122
  <div ref={chartRef} className={Styles['profile-echarts']} />
122
123
  </div>
123
124
  </>
@@ -1,271 +1,303 @@
1
1
  import * as Cesium from 'cesium'
2
+ import glsl from "../glsl/viewable"
2
3
 
3
- const useProfileAnalysis = (viewer: Cesium.Viewer, options: {
4
- collection: Cesium.CustomDataSource
4
+ const useViewshedAnalysis = (viewer: Cesium.Viewer, options: {
5
+ collection: Cesium.CustomDataSource
5
6
  }) => {
6
7
 
7
- let handler = null
8
- let positions = []
9
- let positionsCartographic = []
10
- let positions_Inter = []
11
- let poly = null
12
- let distance = null
13
- let cartesian = null
14
- let DistanceArray = []
15
- let profileItem: {
16
- distance: number
17
- point: ReturnType<typeof cartesian3ToDegrees>
18
- }[] = []
8
+ let i = 0
9
+ let handler: Cesium.ScreenSpaceEventHandler | null = null
10
+ let viewPosition = null
11
+ let viewDistance = 100.0
12
+ let viewHeading = 0.0
13
+ let viewPitch = 0.0
14
+ let horizontalViewAngle = 90.0
15
+ let verticalViewAngle = 60.0
16
+ let visibleAreaColor = Cesium.Color.GREEN
17
+ let invisibleAreaColor = Cesium.Color.RED
18
+ let enabled = true
19
+ let softShadows = true
20
+ let size = 2048
21
+ let lightCamera = null
22
+ let shadowMap = null
23
+ let sketch = null
24
+ let postStage = null
25
+ let frustumOutline = null
19
26
 
20
- class PolyLinePrimitive {
21
- options: Cesium.Entity.ConstructorOptions
22
- positions: Cesium.Cartesian3[]
27
+ const add = () => {
28
+ createLightCamera()
29
+ createShadowMap()
30
+ drawFrustumOutline()
31
+ drawSketch()
32
+ createPostStage()
33
+ }
23
34
 
24
- constructor(positions: Cesium.Cartesian3[]) {
25
- this.options = {
26
- polyline: {
27
- show: true,
28
- positions: [],
29
- width: 3,
30
- material: Cesium.Color.fromCssColorString("rgb(249, 157, 11)"),
31
- clampToGround: true
32
- }
33
- }
34
- this.positions = positions
35
- this.init()
36
- }
35
+ const update = () => {
36
+ removeAll()
37
+ add()
38
+ }
37
39
 
38
- init = () => {
39
- const _self = this
40
- const _update = function () {
41
- return _self.positions
42
- }
43
- this.options.polyline.positions = new Cesium.CallbackProperty(_update, false)
44
- options.collection.entities.add(this.options)
45
- }
46
- }
40
+ const removeAll = () => {
41
+ stopDraw()
47
42
 
48
- const draw = (cb: (data: {
49
- min: number;
50
- value: (number | string)[][]
51
- }) => void) => {
52
- if (handler) {
53
- console.log('请使用右键结束上次测量!')
54
- return
55
- }
56
- options.collection.entities.removeAll()
57
- handler = new Cesium.ScreenSpaceEventHandler((viewer.scene as any)._imageryLayerCollection)
58
- leftClickEvent()
59
- mouseMoveEvent()
60
- rightClickEvent(cb)
43
+ if (sketch) {
44
+ options.collection.entities.remove(sketch)
45
+ sketch = null
61
46
  }
62
-
63
- const stopDraw = () => {
64
- if (handler) {
65
- handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
66
- handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
67
- handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
68
- handler.destroy()
69
- handler = null
70
- }
71
-
72
- positions = []
73
- positionsCartographic = []
74
- positions_Inter = []
75
- poly = null
76
- distance = null
77
- cartesian = null
78
- DistanceArray = []
79
- profileItem = []
47
+ if (postStage) {
48
+ viewer.scene.postProcessStages.remove(postStage)
49
+ postStage = null
80
50
  }
81
-
82
- const removeAll = () => {
83
- stopDraw()
84
- options.collection.entities.removeAll()
51
+ if (frustumOutline) {
52
+ viewer.scene.primitives.remove(frustumOutline)
53
+ frustumOutline = null
85
54
  }
55
+ }
86
56
 
87
- const leftClickEvent = () => {
88
- handler.setInputAction(((movement) => {
89
- cartesian = viewer.scene.pickPosition(movement.position)
90
- if (positions.length == 0) {
91
- positions.push(cartesian.clone())
92
- }
93
- positions.push(cartesian)
94
- if (poly) {
95
- interPoints(poly.positions)
96
- distance = getSpaceDistance(positions_Inter)
97
- } else {
98
- distance = getSpaceDistance(positions)
99
- }
57
+ const updatePosition = (position) => {
58
+ viewDistance = Cesium.Cartesian3.distance(viewPosition, position)
59
+ viewHeading = getHeading(viewPosition, position)
60
+ viewPitch = getPitch(viewPosition, position)
61
+ }
100
62
 
101
- const textDisance = distance + "米"
102
- DistanceArray.push(distance)
103
- options.collection.entities.add({
104
- position: positions[positions.length - 1],
105
- point: {
106
- color: Cesium.Color.fromCssColorString("rgb(249, 157, 11)"),
107
- outlineColor: Cesium.Color.WHITE,
108
- outlineWidth: 2,
109
- pixelSize: 10
110
- },
111
- label: {
112
- text: textDisance,
113
- scale: 0.5,
114
- font: "normal 28px MicroSoft YaHei",
115
- style: Cesium.LabelStyle.FILL_AND_OUTLINE,
116
- pixelOffset: new Cesium.Cartesian2(0, -30),
117
- outlineWidth: 9,
118
- outlineColor: Cesium.Color.WHITE,
119
- heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
120
- disableDepthTestDistance: Number.POSITIVE_INFINITY
121
- }
122
- })
123
- }) as Cesium.ScreenSpaceEventHandler.PositionedEventCallback, Cesium.ScreenSpaceEventType.LEFT_CLICK)
124
- }
63
+ const createLightCamera = () => {
64
+ const camera = new Cesium.Camera(viewer.scene)
65
+ camera.position = viewPosition
66
+ camera.frustum.near = viewDistance * 0.001
67
+ camera.frustum.far = viewDistance
125
68
 
126
- const mouseMoveEvent = () => {
127
- handler.setInputAction(((movement) => {
128
- cartesian = viewer.scene.pickPosition(movement.endPosition)
129
- if (positions.length >= 2) {
130
- if (!Cesium.defined(poly)) {
131
- poly = new PolyLinePrimitive(positions)
132
- } else {
133
- positions.pop()
134
- positions.push(cartesian)
135
- }
136
- }
137
- }) as Cesium.ScreenSpaceEventHandler.MotionEventCallback, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
138
- }
69
+ const hr = Cesium.Math.toRadians(horizontalViewAngle)
70
+ const vr = Cesium.Math.toRadians(verticalViewAngle)
71
+ const aspectRatio = (viewDistance * Math.tan(hr / 2) * 2) / (viewDistance * Math.tan(vr / 2) * 2);
72
+ (camera.frustum as any).aspectRatio = aspectRatio;
73
+ (camera.frustum as any).fov = Math.max(hr, vr)
139
74
 
140
- const rightClickEvent = (cb: (data: {
141
- min: number;
142
- value: (number | string)[][]
143
- }) => void) => {
144
- handler.setInputAction((() => {
145
- positions.pop()
146
- createProfileChart(profileItem, cb)
147
- stopDraw()
148
- }) as Cesium.ScreenSpaceEventHandler.PositionedEventCallback, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
149
- }
75
+ camera.setView({
76
+ destination: viewPosition,
77
+ orientation: {
78
+ heading: Cesium.Math.toRadians(viewHeading || 0),
79
+ pitch: Cesium.Math.toRadians(viewPitch || 0),
80
+ roll: 0
81
+ }
82
+ })
83
+ lightCamera = camera
84
+ }
150
85
 
151
- const cartesian3ToDegrees = (pos: Cesium.Cartesian3) => {
152
- const ellipsoid = viewer.scene.globe.ellipsoid
153
- const cartographic = ellipsoid.cartesianToCartographic(pos)
154
- const lat = Cesium.Math.toDegrees(cartographic.latitude)
155
- const lon = Cesium.Math.toDegrees(cartographic.longitude)
156
- const height = cartographic.height
86
+ const createShadowMap = () => {
87
+ const shadow = new (Cesium.ShadowMap as any)({
88
+ context: (viewer.scene as any).context,
89
+ lightCamera: lightCamera,
90
+ enabled: enabled,
91
+ isPointLight: true,
92
+ pointLightRadius: viewDistance,
93
+ cascadesEnabled: false,
94
+ size: size,
95
+ softShadows: softShadows,
96
+ normalOffset: false,
97
+ fromLightSource: false
98
+ })
99
+ viewer.scene.shadowMap = shadow
100
+ shadowMap = shadow
101
+ }
157
102
 
158
- return {
159
- lat,
160
- lon,
161
- height
162
- }
163
- }
103
+ const createPostStage = () => {
104
+ const fs = glsl
105
+ const cutomPostStage = new Cesium.PostProcessStage({
106
+ fragmentShader: fs,
107
+ uniforms: {
108
+ shadowMap_textureCube: () => {
109
+ shadowMap.update(Reflect.get(viewer.scene, '_frameState'))
110
+ return Reflect.get(shadowMap, '_shadowMapTexture')
111
+ },
112
+ shadowMap_matrix: () => {
113
+ shadowMap.update(Reflect.get(viewer.scene, '_frameState'))
114
+ return Reflect.get(shadowMap, '_shadowMapMatrix')
115
+ },
116
+ shadowMap_lightPositionEC: () => {
117
+ shadowMap.update(Reflect.get(viewer.scene, '_frameState'))
118
+ return Reflect.get(shadowMap, '_lightPositionEC')
119
+ },
120
+ shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness: () => {
121
+ shadowMap.update(Reflect.get(viewer.scene, '_frameState'))
122
+ const bias = shadowMap._pointBias
123
+ return Cesium.Cartesian4.fromElements(
124
+ bias.normalOffsetScale,
125
+ shadowMap._distance,
126
+ shadowMap.maximumDistance,
127
+ 0.0,
128
+ new Cesium.Cartesian4()
129
+ )
130
+ },
131
+ shadowMap_texelSizeDepthBiasAndNormalShadingSmooth: () => {
132
+ shadowMap.update(Reflect.get(viewer.scene, '_frameState'))
133
+ const bias = shadowMap._pointBias
134
+ const texelStepSize = new Cesium.Cartesian2(
135
+ 1.0 / shadowMap._textureSize.x,
136
+ 1.0 / shadowMap._textureSize.y
137
+ )
138
+ return Cesium.Cartesian4.fromElements(
139
+ texelStepSize.x,
140
+ texelStepSize.y,
141
+ bias.depthBias,
142
+ bias.normalShadingSmooth,
143
+ new Cesium.Cartesian4()
144
+ )
145
+ },
146
+ camera_projection_matrix: lightCamera.frustum.projectionMatrix,
147
+ camera_view_matrix: lightCamera.viewMatrix,
148
+ helsing_viewDistance: () => viewDistance,
149
+ helsing_visibleAreaColor: visibleAreaColor,
150
+ helsing_invisibleAreaColor: invisibleAreaColor
151
+ }
152
+ })
153
+ postStage = viewer.scene.postProcessStages.add(cutomPostStage)
154
+ }
164
155
 
165
- const getSpaceDistance = (positions: Cesium.Cartesian3[]) => {
166
- profileItem = [
167
- {
168
- point: cartesian3ToDegrees(positions[0]),
169
- distance: 0
170
- }
171
- ]
172
- let distance = 0
173
- for (let i = 0; i < positions.length - 1; i++) {
174
- const point1cartographic = Cesium.Cartographic.fromCartesian(positions[i])
175
- const point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1])
176
- const geodesic = new Cesium.EllipsoidGeodesic()
177
- geodesic.setEndPoints(point1cartographic, point2cartographic)
178
- let s = geodesic.surfaceDistance
179
- s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2))
180
- distance = distance + s
156
+ const drawFrustumOutline = () => {
157
+ const direction = lightCamera.directionWC
158
+ const up = lightCamera.upWC
159
+ const right = Cesium.Cartesian3.negate(lightCamera.rightWC, new Cesium.Cartesian3())
160
+ const rotation = Cesium.Matrix3.setColumn(
161
+ new Cesium.Matrix3(),
162
+ 0,
163
+ right,
164
+ new Cesium.Matrix3()
165
+ )
166
+ Cesium.Matrix3.setColumn(rotation, 1, up, rotation)
167
+ Cesium.Matrix3.setColumn(rotation, 2, direction, rotation)
168
+ const orientation = Cesium.Quaternion.fromRotationMatrix(rotation, new Cesium.Quaternion())
181
169
 
182
- const m_Item = {
183
- point: cartesian3ToDegrees(positions[i + 1]),
184
- distance: distance
185
- }
186
- profileItem.push(m_Item)
187
- }
188
- return distance.toFixed(2)
189
- }
170
+ const instance = new Cesium.GeometryInstance({
171
+ geometry: new Cesium.FrustumOutlineGeometry({
172
+ frustum: lightCamera.frustum,
173
+ origin: viewPosition,
174
+ orientation
175
+ }),
176
+ attributes: {
177
+ color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOWGREEN),
178
+ show: new Cesium.ShowGeometryInstanceAttribute(true)
179
+ }
180
+ })
190
181
 
191
- const interPoints = (positions: Cesium.Cartesian3[]) => {
192
- positionsCartographic = []
193
- var terrainSamplePositions = []
194
- for (let index = 0; index < positions.length - 1; index++) {
195
- const element = positions[index]
196
- var ellipsoid = viewer.scene.globe.ellipsoid
197
- var cartographic = ellipsoid.cartesianToCartographic(element)
198
- positionsCartographic.push(cartographic)
199
- }
200
- for (let i = 0; i < positionsCartographic.length; i++) {
201
- const m_Cartographic0 = positionsCartographic[i]
202
- const m_Cartographic1 = positionsCartographic[i + 1]
203
- if (m_Cartographic1) {
204
- var a = Math.abs(m_Cartographic0.longitude - m_Cartographic1.longitude) * 10000000
205
- var b = Math.abs(m_Cartographic0.latitude - m_Cartographic1.latitude) * 10000000
206
- if (a > b) b = a
207
- let length = parseInt((b / 2) as any)
208
- if (length > 1000) length = 1000
209
- if (length < 2) length = 2
210
- for (var j = 0; j < length; j++) {
211
- terrainSamplePositions.push(
212
- new Cesium.Cartographic(
213
- Cesium.Math.lerp(m_Cartographic0.longitude, m_Cartographic1.longitude, j / (length - 1)),
214
- Cesium.Math.lerp(m_Cartographic0.latitude, m_Cartographic1.latitude, j / (length - 1))
215
- )
216
- )
217
- }
218
- terrainSamplePositions.pop()
219
- } else {
220
- terrainSamplePositions.push(m_Cartographic0)
221
- }
222
- }
223
- positions_Inter = []
224
- for (var n = 0; n < terrainSamplePositions.length; n++) {
225
- var m_cartographic = terrainSamplePositions[n]
226
- var height = viewer.scene.globe.getHeight(m_cartographic)
227
- var point = Cesium.Cartesian3.fromDegrees(m_cartographic.longitude / Math.PI * 180, m_cartographic.latitude / Math.PI * 180, height)
228
- positions_Inter.push(point)
229
- }
230
- }
182
+ frustumOutline = viewer.scene.primitives.add(
183
+ new Cesium.Primitive({
184
+ geometryInstances: [instance],
185
+ appearance: new Cesium.PerInstanceColorAppearance({
186
+ flat: true,
187
+ translucent: false
188
+ })
189
+ })
190
+ )
191
+ }
231
192
 
232
- const createProfileChart = (pos: typeof profileItem, cb: (data: {
233
- min: number;
234
- value: (number | string)[][]
235
- }) => void) => {
236
- const ProfileData = []
237
- const ProfileData_Lon = []
193
+ const drawSketch = () => {
194
+ sketch = options.collection.entities.add({
195
+ name: 'sketch',
196
+ position: viewPosition,
197
+ orientation: new Cesium.CallbackProperty(() => {
198
+ return Cesium.Transforms.headingPitchRollQuaternion(
199
+ viewPosition,
200
+ Cesium.HeadingPitchRoll.fromDegrees(
201
+ viewHeading - horizontalViewAngle,
202
+ viewPitch,
203
+ 0.5
204
+ )
205
+ )
206
+ }, false),
207
+ ellipsoid: {
208
+ radii: new Cesium.CallbackProperty(
209
+ () => new Cesium.Cartesian3(viewDistance, viewDistance, viewDistance),
210
+ false
211
+ ),
212
+ innerRadii: new Cesium.Cartesian3(2.0, 2.0, 2.0),
213
+ minimumClock: Cesium.Math.toRadians(-horizontalViewAngle / 2),
214
+ maximumClock: Cesium.Math.toRadians(horizontalViewAngle / 2),
215
+ minimumCone: Cesium.Math.toRadians(verticalViewAngle + 7.75),
216
+ maximumCone: Cesium.Math.toRadians(180 - verticalViewAngle - 7.75),
217
+ fill: false,
218
+ outline: true,
219
+ subdivisions: 256,
220
+ stackPartitions: 64,
221
+ slicePartitions: 64,
222
+ outlineColor: Cesium.Color.YELLOWGREEN
223
+ }
224
+ })
225
+ }
238
226
 
239
- let min = 0
227
+ const getHeading = (from, to) => {
228
+ const result = new Cesium.Cartesian3()
229
+ const matrix4 = Cesium.Matrix4.inverse(Cesium.Transforms.eastNorthUpToFixedFrame(from), new Cesium.Matrix4())
230
+ Cesium.Matrix4.multiplyByPoint(matrix4, to, result)
231
+ Cesium.Cartesian3.normalize(result, result)
232
+ return Cesium.Math.toDegrees(Math.atan2(result.x, result.y))
233
+ }
240
234
 
241
- for (let index = 0; index < pos.length; index++) {
242
- const el = pos[index]
243
- const m_distance = el.distance.toFixed(2)
235
+ const getPitch = (from, to) => {
236
+ const result = new Cesium.Cartesian3()
237
+ const matrix4 = Cesium.Matrix4.inverse(Cesium.Transforms.eastNorthUpToFixedFrame(from), new Cesium.Matrix4())
238
+ Cesium.Matrix4.multiplyByPoint(matrix4, to, result)
239
+ Cesium.Cartesian3.normalize(result, result)
240
+ return Cesium.Math.toDegrees(Math.asin(result.z))
241
+ }
244
242
 
245
- const m_Lon = el.point.lon.toFixed(5)
246
- const m_Lat = el.point.lat.toFixed(5)
247
- const m_height = Number(el.point.height.toFixed(2))
243
+ const leftClickEvent = () => {
244
+ handler.setInputAction(((movement) => {
245
+ i++
246
+ if (i === 1) {
247
+ let startPosition = viewer.scene.pickPosition(movement.position)
248
+ if (!startPosition) return
249
+ viewPosition = startPosition
250
+ mouseMoveEvent()
251
+ }
252
+ if (i === 2) {
253
+ i = 0
254
+ let endPosition = viewer.scene.pickPosition(movement.position)
255
+ updatePosition(endPosition)
256
+ update()
257
+ stopDraw()
258
+ }
259
+ }) as Cesium.ScreenSpaceEventHandler.PositionedEventCallback, Cesium.ScreenSpaceEventType.LEFT_CLICK)
260
+ }
248
261
 
249
- if (m_height < min) {
250
- min = m_height
251
- }
252
- var m_data = [m_distance, m_height]
253
- ProfileData.push(m_data)
254
- ProfileData_Lon.push([m_Lon, m_Lat])
255
- }
262
+ const mouseMoveEvent = () => {
263
+ handler.setInputAction(((movement) => {
264
+ const endPosition = viewer.scene.pickPosition(movement.endPosition)
265
+ if (!endPosition) return
266
+ updatePosition(endPosition)
267
+ if (!sketch) {
268
+ drawSketch()
269
+ }
270
+ }) as Cesium.ScreenSpaceEventHandler.MotionEventCallback, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
271
+ }
256
272
 
257
- cb({
258
- min,
259
- value: ProfileData
260
- })
273
+ const draw = () => {
274
+ if (handler) {
275
+ console.log('请先结束上次测量!')
276
+ return
261
277
  }
278
+ handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
279
+ leftClickEvent()
280
+ viewer.scene.camera.frustum.near = 100.0
281
+ viewer.scene.logarithmicDepthBuffer = true
282
+ viewer.scene.globe.enableLighting = false
283
+ viewer.scene.globe.showGroundAtmosphere = false
284
+ }
262
285
 
263
- return {
264
- draw,
265
- removeAll
286
+ const stopDraw = () => {
287
+ if (handler) {
288
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
289
+ handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
290
+ handler.destroy()
291
+ handler = null
266
292
  }
293
+ }
294
+
295
+ return {
296
+ draw,
297
+ removeAll
298
+ }
267
299
  }
268
300
 
269
301
  export {
270
- useProfileAnalysis
302
+ useViewshedAnalysis
271
303
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-three-utils",
3
- "version": "0.0.397",
3
+ "version": "0.0.398",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -8,5 +8,5 @@
8
8
  "author": "",
9
9
  "license": "ISC",
10
10
  "types": "./index.d.ts",
11
- "description": "新增热力图v1.1"
11
+ "description": "修复剖面分析点击位置不正确的bug"
12
12
  }