@hzab/map-combine 0.0.1 → 0.1.0

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,100 +1,229 @@
1
+ import { fill } from "lodash";
2
+
1
3
  import { Tile3D } from "../basic/Tile3D";
2
4
  import { CesiumMap } from "./CesiumMap";
3
5
 
6
+ import { arrayFillByLen } from "../utils";
7
+
4
8
  function create3DTile(tile3d: Tile3D) {
5
9
  const tileset = new Cesium.Cesium3DTileset({
6
10
  show: tile3d.show,
7
11
  url: tile3d.src,
8
12
  });
9
- tileset.maximumScreenSpaceError = 18 * (1 - tile3d.quality)
10
- tileset.readyPromise
11
- return tileset
13
+ tileset.maximumScreenSpaceError = 18 * (1 - tile3d.quality);
14
+ tileset.readyPromise;
15
+ return tileset;
12
16
  }
13
17
 
14
18
  function updateMatrix(tileset: any, tile3d: Tile3D, origin: any) {
15
-
19
+ const options = tile3d._option;
20
+ // 中心点移动到指定经纬度
16
21
  if (tile3d.coordinates) {
17
- // const center = Cesium.Matrix4.multiplyByPoint(tileset.modelMatrix, tileset.boundingSphere.center, new Cesium.Cartesian3())
18
- // const cartographic = Cesium.Cartographic.fromCartesian(center)
19
- // console.log(Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height);
20
- // cartographic.height = 0
21
- // const transform = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude));
22
- // const res = Cesium.Matrix4.inverse(transform, new Cesium.Matrix4());
23
- // console.log(inverse);
24
-
25
- const target = Cesium.Cartesian3.fromDegrees(...tile3d.coordinates)
22
+ const target = Cesium.Cartesian3.fromDegrees(...tile3d.coordinates);
26
23
  tileset.modelMatrix = Cesium.Matrix4.fromTranslation(Cesium.Cartesian3.subtract(target, origin, target));
27
24
  } else {
28
- tileset.modelMatrix = Cesium.Matrix4.IDENTITY
25
+ tileset.modelMatrix = Cesium.Matrix4.IDENTITY;
26
+ }
27
+ // 旋转
28
+ if (Array.isArray(options.rotates)) {
29
+ const rotates: [number, number, number] = arrayFillByLen([...options.rotates], 3, 0);
30
+ rotate(...rotates, tileset);
31
+ }
32
+ // 平移
33
+ if (options.translates) {
34
+ const translates: [number, number, number] = arrayFillByLen([...options.translates], 3, 0);
35
+ translate(...translates, tileset);
36
+ }
37
+ // 缩放
38
+ if (options.scales) {
39
+ const scales: [number, number, number] = arrayFillByLen([...options.scales], 3, 1);
40
+ scale(...scales, tileset);
29
41
  }
30
-
31
-
32
42
  }
33
43
 
34
44
  export function drawTile3D(map: CesiumMap, tile3d: Tile3D) {
35
- const { viewer } = map
36
- let tileset = create3DTile(tile3d)
37
- let origin
45
+ const { viewer } = map;
46
+ let tileset = create3DTile(tile3d);
47
+ let origin;
48
+
38
49
  viewer.scene.primitives.add(tileset).readyPromise.then(() => {
39
- const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)
40
- origin = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude)
41
- updateMatrix(tileset, tile3d, origin)
42
- tile3d.event.trigger('ready');
50
+ const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
51
+ origin = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude);
52
+ updateMatrix(tileset, tile3d, origin);
53
+ tile3d.event.trigger("ready");
43
54
 
44
55
  // (window as any).getCenter = () => {
45
56
  // const center = tileset.boundingSphere.center
46
57
  // const cartographic = Cesium.Cartographic.fromCartesian(center)
47
58
  // console.log(Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height);
48
59
  // }
49
-
50
60
  });
51
61
 
52
62
  const onUpdate = (e: Set<string>) => {
53
-
54
- e.forEach(key => {
63
+ e.forEach((key) => {
55
64
  switch (key) {
56
- case 'show':
57
- tileset.show = tile3d.show
65
+ case "show":
66
+ tileset.show = tile3d.show;
58
67
  break;
59
- case 'src':
60
- viewer.scene.primitives.remove(tileset)
61
- tileset = create3DTile(tile3d)
68
+ case "src":
69
+ viewer.scene.primitives.remove(tileset);
70
+ tileset = create3DTile(tile3d);
62
71
  viewer.scene.primitives.add(tileset).readyPromise.then(() => {
63
- const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)
64
- origin = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude)
65
- updateMatrix(tileset, tile3d, origin)
66
- tile3d.event.trigger('ready');
67
-
72
+ const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
73
+ origin = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude);
74
+ updateMatrix(tileset, tile3d, origin);
75
+ tile3d.event.trigger("ready");
68
76
  });
69
77
  break;
70
- case 'coordinates':
71
- if (!e.has('src')) {
72
- updateMatrix(tileset, tile3d, origin)
78
+ case "coordinates":
79
+ if (!e.has("src")) {
80
+ updateMatrix(tileset, tile3d, origin);
73
81
  }
74
82
  break;
75
83
 
76
- case 'quality':
77
- tileset.maximumScreenSpaceError = 18 * (1 - tile3d.quality)
84
+ case "quality":
85
+ tileset.maximumScreenSpaceError = 18 * (1 - tile3d.quality);
78
86
  break;
79
87
  default:
80
- throw new Error(`${key} 还不支持修改`)
88
+ throw new Error(`${key} 还不支持修改`);
81
89
  }
82
- })
83
-
84
-
85
- }
90
+ });
91
+ };
86
92
  const onFocus = () => {
87
93
  viewer.flyTo(tileset);
88
- }
94
+ };
89
95
 
90
96
  const onDestroy = () => {
91
- viewer.scene.primitives.remove(tileset)
92
- tile3d.event.off('update', onUpdate)
93
- tile3d.event.off('focus', onFocus)
94
- tile3d.event.off('destroy', onDestroy)
97
+ viewer.scene.primitives.remove(tileset);
98
+ tile3d.event.off("update", onUpdate);
99
+ tile3d.event.off("focus", onFocus);
100
+ tile3d.event.off("destroy", onDestroy);
101
+ };
102
+
103
+ tile3d.tileset = tileset;
104
+ tile3d.translate = function (x: number, y: number, z: number, _tileset) {
105
+ return tileset.readyPromise.then((argument) => {
106
+ console.log("debug translate tileset.readyPromise");
107
+ test();
108
+ translate(x, y, z, _tileset || tileset);
109
+ });
110
+ };
111
+ tile3d.rotate = function (x: number, y: number, z: number, _tileset) {
112
+ return tileset.readyPromise.then((argument) => {
113
+ rotate(x, y, z, _tileset || tileset);
114
+ });
115
+ };
116
+ tile3d.scale = function (x: number, y: number, z: number, _tileset) {
117
+ return tileset.readyPromise.then((argument) => {
118
+ scale(x, y, z, _tileset || tileset);
119
+ });
120
+ };
121
+
122
+ tile3d.event.on("update", onUpdate);
123
+ tile3d.event.on("focus", onFocus);
124
+ tile3d.event.on("destroy", onDestroy);
125
+ }
126
+
127
+ function test() {
128
+ console.log("debug test");
129
+ }
130
+
131
+ /** 基于本地的 ENU 坐标系的偏移,也就是垂直于地表向上为 Z,东为 X,北为 Y
132
+ * @param dx x轴偏移量。单位:米
133
+ * @param dy y轴偏移量。单位:米
134
+ * @param dz z轴偏移量。单位:米
135
+ * @param tileset Cesium3DTileset
136
+ */
137
+ function translate(dx: number, dy: number, dz: number, tileset) {
138
+ console.log("debug translate", dx, dy, dz);
139
+ if (dx === 0 && dy === 0 && dz === 0) return;
140
+ console.log("debug translate", dx, dy, dz);
141
+
142
+ try {
143
+ const { Cartesian3, Matrix4, Transforms } = Cesium;
144
+ // 对于3DTileset,我们需要的结果是一个模型矩阵,那么平移就是计算一个世界坐标下的平移矩阵。
145
+ // 获取中心点
146
+ const origin = tileset.boundingSphere.center;
147
+ // 以该点建立ENU坐标系
148
+ const toWorldMatrix = Transforms.eastNorthUpToFixedFrame(origin);
149
+ // 该坐标系下平移后的位置
150
+ const translatePosition = new Cartesian3(dx, dy, dz);
151
+ // 获取平移后位置的世界坐标
152
+ const worldPosition = Matrix4.multiplyByPoint(toWorldMatrix, translatePosition, new Cartesian3());
153
+ // 计算世界坐标下的各个平移量
154
+ const offset = Cartesian3.subtract(worldPosition, origin, new Cartesian3());
155
+ // 从世界坐标下的平移量计算世界坐标的平移矩阵
156
+ const translateMatrix = Matrix4.fromTranslation(offset);
157
+ // 应用平移矩阵。这里应该与原本的模型矩阵点乘,而不是直接赋值
158
+ tileset.modelMatrix = Matrix4.multiply(translateMatrix, tileset.modelMatrix, new Matrix4());
159
+ } catch (error) {
160
+ console.error(error);
95
161
  }
96
- tile3d.event.on('update', onUpdate)
97
- tile3d.event.on('focus', onFocus)
98
- tile3d.event.on('destroy', onDestroy)
162
+ }
99
163
 
100
- }
164
+ /** 基于本地的 ENU 坐标系的旋转,也就是垂直于地表向上为 Z,东为 X,北为 Y
165
+ * https://blog.csdn.net/weixin_70945905/article/details/142419968
166
+ * @param rx 绕X轴旋转的角度。单位:度
167
+ * @param ry 绕Y轴旋转的角度。单位:度
168
+ * @param rz 绕Z轴旋转的角度。单位:度
169
+ * @param tileset Cesium3DTileset
170
+ */
171
+ function rotate(rx: number, ry: number, rz: number, tileset) {
172
+ console.log("debug rotate ", rx, ry, rz);
173
+ if (rx === 0 && ry === 0 && rz === 0) return;
174
+ const { Matrix3, Matrix4, Transforms, Math: CesiumMath } = Cesium;
175
+ // 获取中心点。
176
+ const origin = tileset.boundingSphere.center;
177
+ // 以该点建立 ENU 坐标系
178
+ const toWorldMatrix = Transforms.eastNorthUpToFixedFrame(origin);
179
+ // 获取 ENU 矩阵的逆矩阵。也就是可以将世界坐标重新转为 ENU 坐标系的矩阵
180
+ const toLocalMatrix = Matrix4.inverse(toWorldMatrix, new Matrix4());
181
+ // 计算旋转矩阵
182
+ const rotateMatrix = Matrix4.clone(Matrix4.IDENTITY);
183
+ if (rx !== 0) {
184
+ const rotateXMatrix = Matrix4.fromRotationTranslation(Matrix3.fromRotationX(CesiumMath.toRadians(rx)));
185
+ Matrix4.multiply(rotateXMatrix, rotateMatrix, rotateMatrix);
186
+ }
187
+ if (ry !== 0) {
188
+ const rotateYMatrix = Matrix4.fromRotationTranslation(Matrix3.fromRotationY(CesiumMath.toRadians(ry)));
189
+ Matrix4.multiply(rotateYMatrix, rotateMatrix, rotateMatrix);
190
+ }
191
+ if (rz !== 0) {
192
+ const rotateZMatrix = Matrix4.fromRotationTranslation(Matrix3.fromRotationZ(CesiumMath.toRadians(rz)));
193
+ Matrix4.multiply(rotateZMatrix, rotateMatrix, rotateMatrix);
194
+ }
195
+ // ENU 坐标系下的结果矩阵
196
+ const localResultMatrix = Matrix4.multiply(rotateMatrix, toLocalMatrix, new Matrix4());
197
+ // 世界坐标系下的结果矩阵
198
+ const worldResultMatrix = Matrix4.multiply(toWorldMatrix, localResultMatrix, new Matrix4());
199
+ // 应用结果
200
+ tileset.modelMatrix = Matrix4.multiply(worldResultMatrix, tileset.modelMatrix, new Matrix4());
201
+ }
202
+
203
+ /** 基于本地的 ENU 坐标系的缩放,也就是垂直于地表向上为 Z,东为 X,北为 Y
204
+ * @param sx x 轴缩放倍数
205
+ * @param sy y 轴缩放倍数
206
+ * @param sz z 轴缩放倍数
207
+ * @param tileset Cesium3DTileset
208
+ */
209
+ function scale(sx: number, sy: number, sz: number, tileset) {
210
+ if (sx <= 0 || sy <= 0 || sz <= 0) throw Error("缩放倍数必须大于0");
211
+ if (sx === 1 && sy === 1 && sz === 1) return;
212
+ const { Cartesian3, Matrix4, Transforms } = Cesium;
213
+ // 具体步骤是将 3DTileset 先转为 ENU 坐标系,再在 ENU 坐标系下计算缩放后的结果,再转回世界坐标系。一个步骤代表一个矩阵
214
+
215
+ // 获取中心点。
216
+ const origin = tileset.boundingSphere.center;
217
+ // 以该点建立 ENU 坐标系
218
+ const toWorldMatrix = Transforms.eastNorthUpToFixedFrame(origin);
219
+ // 获取ENU矩阵的逆矩阵。也就是可以将世界坐标重新转为 ENU 坐标系的矩阵
220
+ const toLocalMatrix = Matrix4.inverse(toWorldMatrix, new Matrix4());
221
+ // 计算缩放矩阵
222
+ const scaleMatrix = Matrix4.fromScale(new Cartesian3(sx, sy, sz));
223
+ // ENU 坐标系下的结果矩阵
224
+ const localResultMatrix = Matrix4.multiply(scaleMatrix, toLocalMatrix, new Matrix4());
225
+ // 世界坐标系下的结果矩阵
226
+ const worldResultMatrix = Matrix4.multiply(toWorldMatrix, localResultMatrix, new Matrix4());
227
+ // 应用结果
228
+ tileset.modelMatrix = Matrix4.multiply(worldResultMatrix, tileset.modelMatrix, new Matrix4());
229
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ @author : Caven Chen
3
+ @date : 2023-05-18
4
+ */
5
+
6
+ import {
7
+ AMapImageryProvider,
8
+ BaiduImageryProvider,
9
+ GeoVisImageryProvider,
10
+ GoogleImageryProvider,
11
+ TdtImageryProvider,
12
+ TencentImageryProvider,
13
+ CustomGeographicTilingScheme,
14
+ CustomMercatorTilingScheme,
15
+ } from "./modules";
16
+
17
+ if (window && window.Cesium) {
18
+ if (Object.isFrozen(window.Cesium)) {
19
+ window.AMapImageryProvider = AMapImageryProvider;
20
+ window.BaiduImageryProvider = BaiduImageryProvider;
21
+ window.GeoVisImageryProvider = GeoVisImageryProvider;
22
+ window.GoogleImageryProvider = GoogleImageryProvider;
23
+ window.TdtImageryProvider = TdtImageryProvider;
24
+ window.TencentImageryProvider = TencentImageryProvider;
25
+ window.CustomGeographicTilingScheme = CustomGeographicTilingScheme;
26
+ window.CustomMercatorTilingScheme = CustomMercatorTilingScheme;
27
+ } else {
28
+ window.Cesium.AMapImageryProvider = AMapImageryProvider;
29
+ window.Cesium.BaiduImageryProvider = BaiduImageryProvider;
30
+ window.Cesium.GeoVisImageryProvider = GeoVisImageryProvider;
31
+ window.Cesium.GoogleImageryProvider = GoogleImageryProvider;
32
+ window.Cesium.TdtImageryProvider = TdtImageryProvider;
33
+ window.Cesium.TencentImageryProvider = TencentImageryProvider;
34
+ window.Cesium.CustomGeographicTilingScheme = CustomGeographicTilingScheme;
35
+ window.Cesium.CustomMercatorTilingScheme = CustomMercatorTilingScheme;
36
+ }
37
+ }
38
+
39
+ export {
40
+ AMapImageryProvider,
41
+ BaiduImageryProvider,
42
+ GeoVisImageryProvider,
43
+ GoogleImageryProvider,
44
+ TdtImageryProvider,
45
+ TencentImageryProvider,
46
+ CustomGeographicTilingScheme,
47
+ CustomMercatorTilingScheme,
48
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @Author: Caven Chen
3
+ */
4
+
5
+ export { default as AMapImageryProvider } from "./provider/AMapImageryProvider.js";
6
+ export { default as BaiduImageryProvider } from "./provider/BaiduImageryProvider.js";
7
+ export { default as GeoVisImageryProvider } from "./provider/GeoVisImageryProvider.js";
8
+ export { default as GoogleImageryProvider } from "./provider/GoogleImageryProvider.js";
9
+ export { default as TdtImageryProvider } from "./provider/TdtImageryProvider.js";
10
+ export { default as TencentImageryProvider } from "./provider/TencentImageryProvider.js";
11
+ export { default as CustomGeographicTilingScheme } from "./tiling-scheme/CustomGeographicTilingScheme.js";
12
+ export { default as CustomMercatorTilingScheme } from "./tiling-scheme/CustomMercatorTilingScheme.js";