@lijuhong1981/cesium.utils 0.0.0-stage → 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.
Files changed (99) hide show
  1. package/README.md +62 -2
  2. package/package.json +33 -4
  3. package/src/additions/Geographic.js +603 -0
  4. package/src/additions/GeographicTransform.js +291 -0
  5. package/src/additions/GeometryInstanceAttributes.js +164 -0
  6. package/src/additions/ModelMatrixTransforms.js +822 -0
  7. package/src/additions/PropertyChangedListener.js +72 -0
  8. package/src/additions/PropertyType.js +30 -0
  9. package/src/additions/StTransforms.js +266 -0
  10. package/src/additions/TranslationRotationScaleTransform.js +809 -0
  11. package/src/additions/index.js +8 -0
  12. package/src/index.js +4 -0
  13. package/src/parses/index.js +46 -0
  14. package/src/parses/parseAltitude.js +32 -0
  15. package/src/parses/parseArcType.js +26 -0
  16. package/src/parses/parseAttitudeToHeadingPitchRoll.js +26 -0
  17. package/src/parses/parseAttitudeToMatrix3.js +17 -0
  18. package/src/parses/parseAttitudeToQuaternion.js +21 -0
  19. package/src/parses/parseCartographicToCartesian.js +21 -0
  20. package/src/parses/parseCartographicsToPositions.js +20 -0
  21. package/src/parses/parseClassificationType.js +24 -0
  22. package/src/parses/parseClockRange.js +26 -0
  23. package/src/parses/parseColorBlendMode.js +26 -0
  24. package/src/parses/parseCornerType.js +24 -0
  25. package/src/parses/parseCullFace.js +28 -0
  26. package/src/parses/parseEulerToHeadingPitchRoll.js +21 -0
  27. package/src/parses/parseEulerToQuaternion.js +18 -0
  28. package/src/parses/parseGeographicToCartesian.js +21 -0
  29. package/src/parses/parseGeographicsToPositions.js +20 -0
  30. package/src/parses/parseHeading.js +28 -0
  31. package/src/parses/parseHeightReference.js +24 -0
  32. package/src/parses/parseHorizontalOrigin.js +26 -0
  33. package/src/parses/parseLabelStyle.js +26 -0
  34. package/src/parses/parseLatitude.js +28 -0
  35. package/src/parses/parseLongitude.js +28 -0
  36. package/src/parses/parsePitch.js +26 -0
  37. package/src/parses/parseRoll.js +26 -0
  38. package/src/parses/parseRotationToHeadingPitchRoll.js +40 -0
  39. package/src/parses/parseRotationToMatrix3.js +25 -0
  40. package/src/parses/parseRotationToQuaternion.js +27 -0
  41. package/src/parses/parseShadowMode.js +26 -0
  42. package/src/parses/parseToBoundingRectangle.js +33 -0
  43. package/src/parses/parseToCartesian2.js +35 -0
  44. package/src/parses/parseToCartesian3.js +37 -0
  45. package/src/parses/parseToCartesian3Array.js +21 -0
  46. package/src/parses/parseToCartesian4.js +39 -0
  47. package/src/parses/parseToCartographic.js +31 -0
  48. package/src/parses/parseToColor.js +33 -0
  49. package/src/parses/parseToDistanceDisplayCondition.js +41 -0
  50. package/src/parses/parseToGeographic.js +31 -0
  51. package/src/parses/parseToHeadingPitchRange.js +45 -0
  52. package/src/parses/parseToJulianDate.js +23 -0
  53. package/src/parses/parseToNearFarScalar.js +33 -0
  54. package/src/parses/parseToPlane.js +37 -0
  55. package/src/parses/parseToPolygonHierarchy.js +48 -0
  56. package/src/parses/parseToRange.js +26 -0
  57. package/src/parses/parseToRectangle.js +32 -0
  58. package/src/parses/parseToTimeInterval.js +45 -0
  59. package/src/parses/parseVerticalOrigin.js +28 -0
  60. package/src/revisions/BoundingSphere.revise.js +107 -0
  61. package/src/revisions/Camera.revise.js +366 -0
  62. package/src/revisions/Cartesian.revise.js +313 -0
  63. package/src/revisions/Cartographic.revise.js +443 -0
  64. package/src/revisions/Check.revise.js +164 -0
  65. package/src/revisions/Color.revise.js +271 -0
  66. package/src/revisions/DistanceDisplayCondition.revise.js +37 -0
  67. package/src/revisions/Ellipsoid.revise.js +64 -0
  68. package/src/revisions/Geometry.revise.js +79 -0
  69. package/src/revisions/Globe.revise.js +92 -0
  70. package/src/revisions/HeadingPitchRoll.revise.js +328 -0
  71. package/src/revisions/JulianDate.revise.js +28 -0
  72. package/src/revisions/Material.revise.js +308 -0
  73. package/src/revisions/Math.revise.js +98 -0
  74. package/src/revisions/Matrix.revise.js +578 -0
  75. package/src/revisions/POI.revise.js +178 -0
  76. package/src/revisions/Plane.revise.js +43 -0
  77. package/src/revisions/PolylinePipeline.revise.js +54 -0
  78. package/src/revisions/PostProcessStageLibrary.revise.js +1143 -0
  79. package/src/revisions/Primitive.revise.js +83 -0
  80. package/src/revisions/Property.revise.js +37 -0
  81. package/src/revisions/Quaternion.revise.js +66 -0
  82. package/src/revisions/Rectangle.revise.js +570 -0
  83. package/src/revisions/SceneTransforms.revise.js +82 -0
  84. package/src/revisions/Spherical.revise.js +35 -0
  85. package/src/revisions/index.js +25 -0
  86. package/src/utils/Scratch.js +165 -0
  87. package/src/utils/computeCirclePositions.js +48 -0
  88. package/src/utils/computeCircleRadius.js +19 -0
  89. package/src/utils/computeModelMatrix.js +109 -0
  90. package/src/utils/computeStTransform.js +57 -0
  91. package/src/utils/createGeometry.js +114 -0
  92. package/src/utils/createPointCloudGeometry.js +79 -0
  93. package/src/utils/getGeometryInstanceAttributes.js +43 -0
  94. package/src/utils/getPositionFromTarget.js +29 -0
  95. package/src/utils/getRenderState.js +35 -0
  96. package/src/utils/index.js +13 -0
  97. package/src/utils/isColorMaterial.js +13 -0
  98. package/src/utils/isTranslucent.js +13 -0
  99. package/src/utils/resolveModelMatrixByFixedFrame.js +30 -0
@@ -0,0 +1,809 @@
1
+ import parseNumber from "@lijuhong1981/jsmath/src/parseNumber.js";
2
+ import parseAttitudeToHeadingPitchRoll from "../parses/parseAttitudeToHeadingPitchRoll.js";
3
+ import parseEulerToHeadingPitchRoll from "../parses/parseEulerToHeadingPitchRoll.js";
4
+ import parseRotationToHeadingPitchRoll from "../parses/parseRotationToHeadingPitchRoll.js";
5
+ import parseToCartesian3 from "../parses/parseToCartesian3.js";
6
+ import Scratch from "../utils/Scratch.js";
7
+ import PropertyChangedListener from "./PropertyChangedListener.js";
8
+ import { Cartesian3, Math as CesiumMath, Check, Event, HeadingPitchRoll, Matrix4, Quaternion } from "cesium";
9
+
10
+ /**
11
+ * 旋转参考系类型枚举,用于指定旋转所基于的坐标系。
12
+ * 该对象已被 Object.freeze 冻结,不可修改。
13
+ */
14
+ const RotationFrameType = Object.freeze({
15
+ /** 无特殊参考系,使用标准东-北-天坐标系 */
16
+ NONE: 0x00,
17
+ /** 相机参考系 */
18
+ CAMERA: 0x01,
19
+ /** 三维文本参考系 */
20
+ TEXT3D: 0x02,
21
+ });
22
+
23
+ /**
24
+ * 将变换矩阵分解为平移、旋转(朝向/俯仰/翻滚)、缩放分量,并按参考系类型对俯仰与翻滚进行换算。
25
+ * @param {Matrix4} matrix 待分解的变换矩阵
26
+ * @param {Cartesian3} translation 输出参数,接收平移分量
27
+ * @param {HeadingPitchRoll} headingPitchRoll 输出参数,接收旋转分量
28
+ * @param {Cartesian3} scale 输出参数,接收缩放分量
29
+ * @param {number} rotationFrameType 旋转参考系类型,取值参考 RotationFrameType
30
+ * @returns {void}
31
+ */
32
+ function decompose(matrix, translation, headingPitchRoll, scale, rotationFrameType) {
33
+ Matrix4.getTranslation(matrix, translation);
34
+ Matrix4.getHeadingPitchRoll(matrix, headingPitchRoll);
35
+ if (rotationFrameType === RotationFrameType.CAMERA) {
36
+ const pitch = headingPitchRoll.roll;
37
+ const roll = -headingPitchRoll.pitch;
38
+ headingPitchRoll.pitch = pitch;
39
+ headingPitchRoll.roll = roll;
40
+ } else if (rotationFrameType === RotationFrameType.TEXT3D) {
41
+ const pitch = headingPitchRoll.roll;
42
+ const roll = headingPitchRoll.pitch;
43
+ headingPitchRoll.pitch = pitch;
44
+ headingPitchRoll.roll = roll;
45
+ }
46
+ Matrix4.getScale(matrix, scale);
47
+ }
48
+
49
+ /**
50
+ * 平移-旋转-缩放变换类,继承自 PropertyChangedListener。
51
+ * 以平移、旋转(HeadingPitchRoll / 四元数 / 欧拉角 / 姿态)、缩放维护 4x4 变换矩阵,
52
+ * 支持多种旋转表示方式以及本地/世界坐标下的平移与旋转操作,并在变化时触发相应事件。
53
+ */
54
+ class TranslationRotationScaleTransform extends PropertyChangedListener {
55
+ /**
56
+ * 创建平移-旋转-缩放变换实例。
57
+ * @param {object} [options={}] 配置项
58
+ * @param {Matrix4} [options.matrix] 初始变换矩阵,默认单位矩阵
59
+ * @param {object} [options.owner] 宿主对象,未提供时默认为当前实例
60
+ * @param {boolean} [options.updateByPerFrame=true] 是否逐帧自动更新矩阵
61
+ * @param {number} [options.rotationFrameType] 旋转参考系类型,取值参考 RotationFrameType
62
+ * @param {function} [options.onPropertyValueChanged] 属性变更回调函数
63
+ */
64
+ constructor(options = {}) {
65
+ super(options.onPropertyValueChanged);
66
+
67
+ const matrix = options.matrix ?? Matrix4.IDENTITY.clone(new Matrix4());
68
+ Check.instanceOf('matrix', matrix, Matrix4);
69
+ this.owner = options.owner ?? this;
70
+ this.updateByPerFrame = options.updateByPerFrame ?? true;
71
+
72
+ this._matrix = matrix;
73
+ this._translation = new Cartesian3();
74
+ this._rotation = new HeadingPitchRoll();
75
+ this._rotationFrameType = options.rotationFrameType ?? RotationFrameType.NONE;
76
+ this._scale = new Cartesian3(1, 1, 1);
77
+
78
+ this.matrixChanged = new Event();
79
+
80
+ decompose(this._matrix, this._translation, this._rotation, this._scale, this._rotationFrameType);
81
+
82
+ this.setTransforms(options);
83
+ }
84
+
85
+ /**
86
+ * 根据传入的配置对象设置平移、旋转、缩放等变换参数。
87
+ * @param {object} transforms 变换配置,可包含 translation、attitude、rotation、scale、scale3
88
+ * @returns {void}
89
+ */
90
+ setTransforms(transforms) {
91
+ if (!transforms)
92
+ return;
93
+
94
+ if (transforms.translation)
95
+ this.translation = transforms.translation;
96
+ if (transforms.attitude)
97
+ this.attitude = transforms.attitude;
98
+ else if (transforms.rotation)
99
+ this.rotation = transforms.rotation;
100
+ if (transforms.scale)
101
+ this.scale = transforms.scale;
102
+ else if (transforms.scale3)
103
+ this.scale = transforms.scale3;
104
+ }
105
+
106
+ /**
107
+ * @deprecated The matrixChangeEvent property has deprecated, use matrixChanged instead.
108
+ */
109
+ get matrixChangeEvent() {
110
+ console.warn("The matrixChangeEvent property has deprecated, use matrixChanged instead.");
111
+ return this.matrixChanged;
112
+ }
113
+
114
+ /**
115
+ * 设置平移分量。
116
+ * @param {Cartesian3|Array|object} value 平移分量
117
+ * @returns {void}
118
+ */
119
+ set translation(value) {
120
+ value = parseToCartesian3(value, Scratch.scratchTranslation, 0.0);
121
+ if (!Cartesian3.equals(value, this._translation)) {
122
+ value.clone(this._translation);
123
+ this.raisePropertyChangeEvent('translation', this._translation);
124
+ if (!this.updateByPerFrame)
125
+ this.updateMatrix(true);
126
+ else
127
+ this.needsUpdate = true;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * 获取平移分量。
133
+ * @returns {Cartesian3} 平移分量
134
+ */
135
+ get translation() {
136
+ return this._translation;
137
+ }
138
+
139
+ /**
140
+ * 设置旋转参考系类型。
141
+ * @param {number} value 旋转参考系类型,取值参考 RotationFrameType
142
+ * @returns {void}
143
+ */
144
+ set rotationFrameType(value) {
145
+ if (this._rotationFrameType !== value) {
146
+ this._rotationFrameType = value;
147
+ if (!this.updateByPerFrame)
148
+ this.updateMatrix(true);
149
+ else
150
+ this.needsUpdate = true;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * 获取旋转参考系类型。
156
+ * @returns {number} 旋转参考系类型,取值参考 RotationFrameType
157
+ */
158
+ get rotationFrameType() {
159
+ return this._rotationFrameType;
160
+ }
161
+
162
+ /**
163
+ * 以 HeadingPitchRoll 形式设置旋转量。
164
+ * @param {HeadingPitchRoll|Array|object} value 旋转量
165
+ * @returns {void}
166
+ */
167
+ set rotation(value) {
168
+ value = parseRotationToHeadingPitchRoll(value, Scratch.scratchHeadingPitchRoll);
169
+ if (!HeadingPitchRoll.equals(value, this._rotation)) {
170
+ value.clone(this._rotation);
171
+ this.raisePropertyChangeEvent('rotation', this._rotation);
172
+ if (!this.updateByPerFrame)
173
+ this.updateMatrix(true);
174
+ else
175
+ this.needsUpdate = true;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * 获取旋转量(HeadingPitchRoll 形式)。
181
+ * @returns {HeadingPitchRoll} 旋转量
182
+ */
183
+ get rotation() {
184
+ return this._rotation;
185
+ }
186
+
187
+ /**
188
+ * 以角度制设置旋转量。
189
+ * @param {HeadingPitchRoll|Array|object} value 旋转量(角度制)
190
+ * @returns {void}
191
+ */
192
+ set rotationDegrees(value) {
193
+ value = parseRotationToHeadingPitchRoll(value, Scratch.scratchHeadingPitchRoll, true);
194
+ this.rotation = value;
195
+ }
196
+
197
+ /**
198
+ * 获取角度制表示的旋转量。
199
+ * @returns {HeadingPitchRoll|undefined} 旋转量(角度制)
200
+ */
201
+ get rotationDegrees() {
202
+ if (this._rotation)
203
+ return this._rotation.toDegrees();
204
+ }
205
+
206
+ /**
207
+ * 以姿态(yaw、pitch、roll)设置旋转量。
208
+ * @param {Array|object} value 姿态数据
209
+ * @returns {void}
210
+ */
211
+ set attitude(value) {
212
+ value = parseAttitudeToHeadingPitchRoll(value, Scratch.scratchHeadingPitchRoll);
213
+ this.rotation = value;
214
+ }
215
+
216
+ /**
217
+ * 获取姿态(yaw、pitch、roll,角度制)。
218
+ * @returns {HeadingPitchRoll|undefined} 姿态数据
219
+ */
220
+ get attitude() {
221
+ return this.rotationDegrees;
222
+ }
223
+
224
+ /**
225
+ * 以欧拉角(弧度制)设置旋转量。
226
+ * @param {Cartesian3|Array|object} value 欧拉角(弧度制)
227
+ * @returns {void}
228
+ */
229
+ set euler(value) {
230
+ value = parseEulerToHeadingPitchRoll(value, Scratch.scratchHeadingPitchRoll, false);
231
+ this.rotation = value;
232
+ }
233
+
234
+ /**
235
+ * 获取欧拉角(弧度制)表示的旋转量。
236
+ * @returns {Cartesian3|undefined} 欧拉角(弧度制)
237
+ */
238
+ get euler() {
239
+ if (this._rotation)
240
+ return this._rotation.toEuler();
241
+ }
242
+
243
+ /**
244
+ * 以欧拉角(角度制)设置旋转量。
245
+ * @param {Cartesian3|Array|object} value 欧拉角(角度制)
246
+ * @returns {void}
247
+ */
248
+ set eulerDegrees(value) {
249
+ value = parseEulerToHeadingPitchRoll(value, Scratch.scratchHeadingPitchRoll, true);
250
+ this.rotation = value;
251
+ }
252
+
253
+ /**
254
+ * 获取欧拉角(角度制)表示的旋转量。
255
+ * @returns {Cartesian3|undefined} 欧拉角(角度制)
256
+ */
257
+ get eulerDegrees() {
258
+ if (this._rotation)
259
+ return this._rotation.toEulerDegrees();
260
+ }
261
+
262
+ /**
263
+ * 以四元数设置旋转量。
264
+ * @param {Quaternion} value 四元数
265
+ * @returns {void}
266
+ */
267
+ set quaternion(value) {
268
+ value = HeadingPitchRoll.fromQuaternion(value, Scratch.scratchHeadingPitchRoll);
269
+ this.rotation = value;
270
+ }
271
+
272
+ /**
273
+ * 获取四元数表示的旋转量。
274
+ * @returns {Quaternion|undefined} 四元数
275
+ */
276
+ get quaternion() {
277
+ if (this._rotation)
278
+ return Quaternion.fromHeadingPitchRoll(this._rotation);
279
+ }
280
+
281
+ /**
282
+ * 设置缩放分量。
283
+ * @param {Cartesian3|Array|object} value 缩放分量
284
+ * @returns {void}
285
+ */
286
+ set scale(value) {
287
+ value = parseToCartesian3(value, Scratch.scratchScale3, 1.0);
288
+ if (!Cartesian3.equals(value, this._scale)) {
289
+ value.clone(this._scale);
290
+ this.raisePropertyChangeEvent('scale', this._scale);
291
+ if (!this.updateByPerFrame)
292
+ this.updateMatrix(true);
293
+ else
294
+ this.needsUpdate = true;
295
+ }
296
+ }
297
+
298
+ /**
299
+ * 获取缩放分量。
300
+ * @returns {Cartesian3} 缩放分量
301
+ */
302
+ get scale() {
303
+ return this._scale;
304
+ }
305
+
306
+ /**
307
+ * 设置平移分量,支持传入 Cartesian3 对象或 x、y、z 分量。
308
+ * @param {Cartesian3|number} x Cartesian3 对象或 x 分量
309
+ * @param {number} [y] y 分量
310
+ * @param {number} [z] z 分量
311
+ * @returns {void}
312
+ */
313
+ setTranslation(x, y, z) {
314
+ if (typeof x === 'object') {
315
+ this.translation = x;
316
+ } else {
317
+ this.translation = Cartesian3.fromElements(x, y, z, Scratch.scratchTranslation);
318
+ }
319
+ }
320
+
321
+ /**
322
+ * 获取平移分量的克隆。
323
+ * @param {Cartesian3} [result] 用于存储结果的 Cartesian3 实例
324
+ * @returns {Cartesian3} 平移分量副本
325
+ */
326
+ getTranslation(result) {
327
+ return this._translation.clone(result);
328
+ }
329
+
330
+ /**
331
+ * 平移变换。
332
+ * @param {Cartesian3|number} x Cartesian3 对象或 x 分量
333
+ * @param {number|boolean} [y] y 分量;当 x 为对象时表示 local
334
+ * @param {number} [z] z 分量
335
+ * @param {boolean} [local=true] 是否在本地坐标系平移,false 表示世界坐标系
336
+ * @returns {void}
337
+ */
338
+ translate(x, y, z, local = true) {
339
+ let translate;
340
+ if (typeof x === 'object') {
341
+ local = y ?? true;
342
+ translate = parseToCartesian3(x, Scratch.scratchTranslate, 0.0);
343
+ } else {
344
+ translate = Cartesian3.fromElements(x, y, z, Scratch.scratchTranslate);
345
+ }
346
+ if (Cartesian3.equals(translate, Cartesian3.ZERO))
347
+ return;
348
+ if (local) {
349
+ Matrix4.multiplyByTranslation(this._matrix, translate, this._matrix);
350
+ Matrix4.getTranslation(this._matrix, this._translation);
351
+ this.raisePropertyChangeEvent('translation', this._translation);
352
+ if (!this.updateByPerFrame)
353
+ this.matrixChanged.raiseEvent(this.owner, this._matrix);
354
+ else
355
+ this.needsUpdate = true;
356
+ } else {
357
+ Cartesian3.add(this._translation, translate, this._translation);
358
+ this.raisePropertyChangeEvent('translation', this._translation);
359
+ if (!this.updateByPerFrame)
360
+ this.updateMatrix(true);
361
+ else
362
+ this.needsUpdate = true;
363
+ }
364
+ }
365
+
366
+ /**
367
+ * 沿指定轴平移指定距离。
368
+ * @param {Cartesian3} axis 平移轴方向
369
+ * @param {number} distance 平移距离
370
+ * @param {boolean} [local=true] 是否在本地坐标系平移,false 表示世界坐标系
371
+ * @returns {void}
372
+ */
373
+ translateOnAxis(axis, distance, local = true) {
374
+ distance = parseNumber(distance);
375
+ if (distance !== 0) {
376
+ Cartesian3.normalize(axis, axis);
377
+ const translate = Cartesian3.multiplyByScalar(axis, distance, Scratch.scratchTranslate);
378
+ this.translate(translate, local);
379
+ }
380
+ }
381
+
382
+ /**
383
+ * 沿 X 轴平移指定距离。
384
+ * @param {number} value 平移距离
385
+ * @param {boolean} [local=true] 是否在本地坐标系平移,false 表示世界坐标系
386
+ * @returns {void}
387
+ */
388
+ translateX(value, local = true) {
389
+ value = parseNumber(value);
390
+ if (value !== 0) {
391
+ this.translate(value, 0, 0, local);
392
+ }
393
+ }
394
+
395
+ /**
396
+ * 沿 Y 轴平移指定距离。
397
+ * @param {number} value 平移距离
398
+ * @param {boolean} [local=true] 是否在本地坐标系平移,false 表示世界坐标系
399
+ * @returns {void}
400
+ */
401
+ translateY(value, local = true) {
402
+ value = parseNumber(value);
403
+ if (value !== 0) {
404
+ this.translate(0, value, 0, local);
405
+ }
406
+ }
407
+
408
+ /**
409
+ * 沿 Z 轴平移指定距离。
410
+ * @param {number} value 平移距离
411
+ * @param {boolean} [local=true] 是否在本地坐标系平移,false 表示世界坐标系
412
+ * @returns {void}
413
+ */
414
+ translateZ(value, local = true) {
415
+ value = parseNumber(value);
416
+ if (value !== 0) {
417
+ this.translate(0, 0, value, local);
418
+ }
419
+ }
420
+
421
+ /**
422
+ * 设置旋转量,支持传入 HeadingPitchRoll 对象或 heading、pitch、roll 分量。
423
+ * @param {HeadingPitchRoll|number} heading HeadingPitchRoll 对象或朝向角
424
+ * @param {number|boolean} [pitch] 俯仰角;当 heading 为对象时表示 degrees
425
+ * @param {number} [roll] 翻滚角
426
+ * @param {boolean} [degrees] 旋转量是否为角度制
427
+ * @returns {void}
428
+ */
429
+ setRotation(heading, pitch, roll, degrees) {
430
+ let rotation;
431
+ if (typeof heading === 'object') {
432
+ rotation = heading;
433
+ degrees = pitch;
434
+ } else {
435
+ rotation = {
436
+ heading: heading,
437
+ pitch: pitch,
438
+ roll: roll,
439
+ };
440
+ }
441
+ this.rotation = parseRotationToHeadingPitchRoll(rotation, Scratch.scratchHeadingPicthRoll, degrees);
442
+ }
443
+
444
+ /**
445
+ * 获取旋转量的克隆。
446
+ * @param {HeadingPitchRoll} [result] 用于存储结果的实例
447
+ * @returns {HeadingPitchRoll} 旋转量副本
448
+ */
449
+ getRotation(result) {
450
+ return this._rotation.clone(result);
451
+ }
452
+
453
+ /**
454
+ * 设置姿态(yaw、pitch、roll),支持传入对象或数值。
455
+ * @param {object|number} yaw 姿态对象或 yaw 分量
456
+ * @param {number} [pitch] pitch 分量
457
+ * @param {number} [roll] roll 分量
458
+ * @returns {void}
459
+ */
460
+ setAttitude(yaw, pitch, roll) {
461
+ if (typeof yaw === 'object')
462
+ this.attitude = yaw;
463
+ else
464
+ this.rotation = HeadingPitchRoll.fromDegrees(yaw, pitch, roll, Scratch.scratchHeadingPicthRoll);
465
+ }
466
+
467
+ /**
468
+ * 获取姿态(yaw、pitch、roll,角度制)。
469
+ * @param {HeadingPitchRoll} [result] 用于存储结果的实例
470
+ * @returns {HeadingPitchRoll} 姿态数据
471
+ */
472
+ getAttitude(result) {
473
+ return this._rotation.toDegrees(result);
474
+ }
475
+
476
+ /**
477
+ * 设置欧拉角,支持传入 Cartesian3 对象或 x、y、z 分量。
478
+ * @param {Cartesian3|number} x Cartesian3 对象或 x 分量
479
+ * @param {number|boolean} [y] y 分量;当 x 为对象时表示 degrees
480
+ * @param {number} [z] z 分量
481
+ * @param {boolean} [degrees] 欧拉角是否为角度制
482
+ * @returns {void}
483
+ */
484
+ setEuler(x, y, z, degrees) {
485
+ let euler;
486
+ if (typeof x === 'object') {
487
+ euler = x;
488
+ degrees = y;
489
+ } else {
490
+ euler = Cartesian3.fromElements(x, y, z, Scratch.scratchEuler);
491
+ }
492
+ this.rotation = parseEulerToHeadingPitchRoll(euler, Scratch.scratchHeadingPicthRoll, degrees);
493
+ }
494
+
495
+ /**
496
+ * 获取欧拉角。
497
+ * @param {Cartesian3} [result] 用于存储结果的实例
498
+ * @returns {Cartesian3} 欧拉角
499
+ */
500
+ getEuler(result) {
501
+ return this._rotation.toEuler(result);
502
+ }
503
+
504
+ /**
505
+ * 旋转,支持传入 HeadingPitchRoll 对象或 heading、pitch、roll 分量。
506
+ * @param {HeadingPitchRoll|number} heading HeadingPitchRoll 对象或朝向角
507
+ * @param {number|boolean} [pitch] 俯仰角;当 heading 为对象时表示 degrees
508
+ * @param {number} [roll] 翻滚角
509
+ * @param {boolean} [degrees] 旋转量是否为角度制
510
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
511
+ * @returns {void}
512
+ */
513
+ rotate(heading, pitch, roll, degrees, local = true) {
514
+ let rotate;
515
+ if (typeof heading === 'object') {
516
+ rotate = heading;
517
+ degrees = pitch;
518
+ } else {
519
+ rotate = {
520
+ heading: heading,
521
+ pitch: pitch,
522
+ roll: roll,
523
+ };
524
+ }
525
+ rotate = parseRotationToHeadingPitchRoll(rotate, Scratch.scratchHeadingPicthRoll, degrees);
526
+ if (HeadingPitchRoll.equals(rotate, HeadingPitchRoll.ZERO))
527
+ return;
528
+ if (local) {
529
+ if (this._rotationFrameType === RotationFrameType.CAMERA) {
530
+ const pitch = rotate.pitch;
531
+ const roll = rotate.roll;
532
+ rotate.pitch = -roll;
533
+ rotate.roll = pitch;
534
+ } else if (this._rotationFrameType === RotationFrameType.TEXT3D) {
535
+ const pitch = rotate.pitch;
536
+ const roll = rotate.roll;
537
+ rotate.pitch = roll;
538
+ rotate.roll = pitch;
539
+ }
540
+ Matrix4.multiplyByHeadingPitchRoll(this._matrix, rotate, this._matrix);
541
+ Matrix4.getHeadingPitchRoll(this._matrix, this._rotation);
542
+ if (this._rotationFrameType === RotationFrameType.CAMERA) {
543
+ const pitch = this._rotation.roll;
544
+ const roll = -this._rotation.pitch;
545
+ this._rotation.pitch = pitch;
546
+ this._rotation.roll = roll;
547
+ } else if (this._rotationFrameType === RotationFrameType.TEXT3D) {
548
+ const pitch = this._rotation.roll;
549
+ const roll = this._rotation.pitch;
550
+ this._rotation.pitch = pitch;
551
+ this._rotation.roll = roll;
552
+ }
553
+ this.raisePropertyChangeEvent('rotation', this._rotation);
554
+ if (!this.updateByPerFrame)
555
+ this.matrixChanged.raiseEvent(this.owner, this._matrix);
556
+ else
557
+ this.needsUpdate = true;
558
+ } else {
559
+ this._rotation.heading += rotate.heading;
560
+ this._rotation.pitch += rotate.pitch;
561
+ this._rotation.roll += rotate.roll;
562
+ this.raisePropertyChangeEvent('rotation', this._rotation);
563
+ if (!this.updateByPerFrame)
564
+ this.updateMatrix(true);
565
+ else
566
+ this.needsUpdate = true;
567
+ }
568
+ }
569
+
570
+ /**
571
+ * 按欧拉角旋转,支持传入 Cartesian3 对象或 x、y、z 分量。
572
+ * @param {Cartesian3|number} x Cartesian3 对象或 x 分量
573
+ * @param {number|boolean} [y] y 分量;当 x 为对象时表示 degrees
574
+ * @param {number} [z] z 分量
575
+ * @param {boolean} [degrees] 欧拉角是否为角度制
576
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
577
+ * @returns {void}
578
+ */
579
+ rotateByEuler(x, y, z, degrees, local = true) {
580
+ let rotate;
581
+ if (typeof x === 'object') {
582
+ rotate = x;
583
+ degrees = y;
584
+ } else {
585
+ rotate = Cartesian3.fromElements(x, y, z, Scratch.scratchEuler);
586
+ }
587
+ rotate = parseEulerToHeadingPitchRoll(rotate, Scratch.scratchHeadingPicthRoll, degrees);
588
+ if (this._rotationFrameType === RotationFrameType.CAMERA) {
589
+ const pitch = rotate.pitch;
590
+ const roll = rotate.roll;
591
+ rotate.pitch = -roll;
592
+ rotate.roll = pitch;
593
+ } else if (this._rotationFrameType === RotationFrameType.TEXT3D) {
594
+ const pitch = rotate.pitch;
595
+ const roll = rotate.roll;
596
+ rotate.pitch = roll;
597
+ rotate.roll = pitch;
598
+ }
599
+ this.rotate(rotate, degrees, local);
600
+ }
601
+
602
+ /**
603
+ * 绕指定轴旋转指定角度。
604
+ * @param {Cartesian3} axis 旋转轴方向
605
+ * @param {number} value 旋转角度
606
+ * @param {boolean} [degrees] 旋转角度是否为角度制
607
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
608
+ * @returns {void}
609
+ */
610
+ rotateOnAxis(axis, value, degrees, local = true) {
611
+ value = parseNumber(value);
612
+ if (value !== 0) {
613
+ axis = Cartesian3.normalize(axis, Scratch.scratchNormal);
614
+ if (degrees)
615
+ value = CesiumMath.toRadians(value);
616
+ const quaternion = Quaternion.fromAxisAngle(axis, value, Scratch.scratchQuaternion);
617
+ const rotate = HeadingPitchRoll.fromQuaternion(quaternion, Scratch.scratchHeadingPicthRoll);
618
+ this.rotate(rotate, degrees, local);
619
+ }
620
+ }
621
+
622
+ /**
623
+ * 绕朝向(Heading)轴旋转。
624
+ * @param {number} value 旋转角度
625
+ * @param {boolean} [degrees] 旋转角度是否为角度制
626
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
627
+ * @returns {void}
628
+ */
629
+ rotateHeading(value, degrees, local = true) {
630
+ value = parseNumber(value);
631
+ if (value !== 0) {
632
+ this.rotate(value, 0, 0, degrees, local);
633
+ }
634
+ }
635
+
636
+ /**
637
+ * 绕俯仰(Pitch)轴旋转。
638
+ * @param {number} value 旋转角度
639
+ * @param {boolean} [degrees] 旋转角度是否为角度制
640
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
641
+ * @returns {void}
642
+ */
643
+ rotatePitch(value, degrees, local = true) {
644
+ value = parseNumber(value);
645
+ if (value !== 0) {
646
+ this.rotate(0, value, 0, degrees, local);
647
+ }
648
+ }
649
+
650
+ /**
651
+ * 绕翻滚(Roll)轴旋转。
652
+ * @param {number} value 旋转角度
653
+ * @param {boolean} [degrees] 旋转角度是否为角度制
654
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
655
+ * @returns {void}
656
+ */
657
+ rotateRoll(value, degrees, local = true) {
658
+ value = parseNumber(value);
659
+ if (value !== 0) {
660
+ this.rotate(0, 0, value, degrees, local);
661
+ }
662
+ }
663
+
664
+ /**
665
+ * 绕 X 轴旋转。
666
+ * @param {number} value 旋转角度
667
+ * @param {boolean} [degrees] 旋转角度是否为角度制
668
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
669
+ * @returns {void}
670
+ */
671
+ rotateX(value, degrees, local = true) {
672
+ value = parseNumber(value);
673
+ if (value !== 0) {
674
+ // this.rotateOnAxis(Cartesian3.UNIT_X, value, degrees);
675
+ this.rotateByEuler(value, 0, 0, degrees, local);
676
+ }
677
+ }
678
+
679
+ /**
680
+ * 绕 Y 轴旋转。
681
+ * @param {number} value 旋转角度
682
+ * @param {boolean} [degrees] 旋转角度是否为角度制
683
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
684
+ * @returns {void}
685
+ */
686
+ rotateY(value, degrees, local = true) {
687
+ value = parseNumber(value);
688
+ if (value !== 0) {
689
+ // this.rotateOnAxis(Cartesian3.UNIT_Y, value, degrees);
690
+ this.rotateByEuler(0, value, 0, degrees, local);
691
+ }
692
+ }
693
+
694
+ /**
695
+ * 绕 Z 轴旋转。
696
+ * @param {number} value 旋转角度
697
+ * @param {boolean} [degrees] 旋转角度是否为角度制
698
+ * @param {boolean} [local=true] 是否在本地坐标系旋转,false 表示世界坐标系
699
+ * @returns {void}
700
+ */
701
+ rotateZ(value, degrees, local = true) {
702
+ value = parseNumber(value);
703
+ if (value !== 0) {
704
+ // this.rotateOnAxis(Cartesian3.UNIT_Z, value, degrees);
705
+ this.rotateByEuler(0, 0, value, degrees, local);
706
+ }
707
+ }
708
+
709
+ /**
710
+ * 设置缩放分量,支持传入 Cartesian3 对象或 x、y、z 分量。
711
+ * @param {Cartesian3|number} x Cartesian3 对象或 x 分量
712
+ * @param {number} [y] y 分量
713
+ * @param {number} [z] z 分量
714
+ * @returns {void}
715
+ */
716
+ setScale(x, y, z) {
717
+ if (typeof x === 'object')
718
+ this.scale = x;
719
+ else
720
+ this.scale = Cartesian3.fromElements(x, y, z, Scratch.scratchScale3);
721
+ }
722
+
723
+ /**
724
+ * 获取缩放分量的克隆。
725
+ * @param {Cartesian3} [result] 用于存储结果的 Cartesian3 实例
726
+ * @returns {Cartesian3} 缩放分量副本
727
+ */
728
+ getScale(result) {
729
+ return this._scale.clone(result);
730
+ }
731
+
732
+ // set matrix(value) {
733
+ // Check.instanceOf('matrix', value, Matrix4);
734
+ // if (!Matrix4.equals(value, this._matrix)) {
735
+ // value.clone(this._matrix);
736
+
737
+ // decompose(this._matrix, this._translation, this._rotation, this._scale, this._rotationFrameType);
738
+
739
+ // this.matrixChanged.raiseEvent(this.owner, this._matrix);
740
+ // }
741
+ // }
742
+
743
+ /**
744
+ * 获取当前的 4x4 变换矩阵。
745
+ * @returns {Matrix4} 变换矩阵
746
+ */
747
+ get matrix() {
748
+ return this._matrix;
749
+ }
750
+
751
+ // getMatrix(result) {
752
+ // return this._matrix.clone(result);
753
+ // }
754
+
755
+ /**
756
+ * 根据当前平移、旋转、缩放重新计算变换矩阵。
757
+ * @param {boolean} [force] 是否强制更新矩阵
758
+ * @returns {boolean|undefined} 更新成功返回 true,无需更新时返回 undefined
759
+ */
760
+ updateMatrix(force) {
761
+ if (force || this.needsUpdate) {
762
+ let rotation;
763
+ if (this._rotationFrameType === RotationFrameType.CAMERA) {
764
+ rotation = this._rotation.clone(Scratch.scratchHeadingPicthRoll);
765
+ rotation.pitch = -this._rotation.roll;
766
+ rotation.roll = this._rotation.pitch;
767
+ } else if (this._rotationFrameType === RotationFrameType.TEXT3D) {
768
+ rotation = this._rotation.clone(Scratch.scratchHeadingPicthRoll);
769
+ rotation.pitch = this._rotation.roll;
770
+ rotation.roll = this._rotation.pitch;
771
+ } else {
772
+ rotation = this._rotation;
773
+ }
774
+ const quaternion = Quaternion.fromHeadingPitchRoll(rotation, Scratch.scratchQuaternion);
775
+ Matrix4.fromTranslationQuaternionRotationScale(this._translation, quaternion, this._scale, this._matrix);
776
+ this.matrixChanged.raiseEvent(this.owner, this._matrix);
777
+ this.needsUpdate = false;
778
+ return true;
779
+ }
780
+ }
781
+
782
+ /**
783
+ * 每帧更新,逐帧模式下按需更新变换矩阵。
784
+ * @param {object} [frameState] 帧状态对象
785
+ * @returns {boolean|undefined} 逐帧更新时返回矩阵更新结果
786
+ */
787
+ update(frameState) {
788
+ if (this.isDestroyed())
789
+ return;
790
+ // if (frameState)
791
+ // this.ellipsoid = frameState.scene.ellipsoid;
792
+ // else
793
+ // this.ellipsoid = this.owner.ellipsoid;
794
+ if (this.updateByPerFrame)
795
+ return this.updateMatrix();
796
+ }
797
+
798
+ /**
799
+ * 销毁实例时清理资源,清空矩阵变更事件并调用父类销毁逻辑。
800
+ * @returns {void}
801
+ */
802
+ onDestroy() {
803
+ this.matrixChanged.clear();
804
+ super.onDestroy();
805
+ }
806
+ };
807
+
808
+ export default TranslationRotationScaleTransform;
809
+ export { TranslationRotationScaleTransform, TranslationRotationScaleTransform as MatrixTransform, RotationFrameType };