@jorgmoritz/gis-manager 0.1.36 → 0.1.37
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/dist/{VertexDetailInfo-Cz9y16HG.d.cts → VertexDetailInfo-DYr1P_fe.d.cts} +7 -3
- package/dist/{VertexDetailInfo-Cz9y16HG.d.ts → VertexDetailInfo-DYr1P_fe.d.ts} +7 -3
- package/dist/index.cjs +1083 -716
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +323 -34
- package/dist/index.d.ts +323 -34
- package/dist/index.js +1077 -717
- package/dist/index.js.map +1 -1
- package/dist/vue/index.cjs +824 -670
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.d.cts +1 -1
- package/dist/vue/index.d.ts +1 -1
- package/dist/vue/index.js +824 -670
- package/dist/vue/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2633,7 +2633,7 @@ var FrustumPyramid = class {
|
|
|
2633
2633
|
showAt(apex, headingDeg, pitchDeg = 0, rollDeg = 0, fovDeg, lengthOverride) {
|
|
2634
2634
|
if (this.destroyed) return;
|
|
2635
2635
|
const C = this.CesiumNS;
|
|
2636
|
-
const length = Math.max(1, lengthOverride ?? this.opts.length ??
|
|
2636
|
+
const length = Math.max(1, lengthOverride ?? this.opts.length ?? 500);
|
|
2637
2637
|
const lakeEdge = this.opts.color ?? C.Color.fromCssColorString("#1e90ff");
|
|
2638
2638
|
const alpha = this.opts.fillAlpha ?? 0.25;
|
|
2639
2639
|
const lakeFill = (this.opts.fillColor ?? C.Color.fromCssColorString("#1e90ff")).withAlpha(alpha);
|
|
@@ -2816,8 +2816,6 @@ var AirplaneCursor = class {
|
|
|
2816
2816
|
__publicField(this, "angleStep");
|
|
2817
2817
|
/** 加速倍率(按住 Shift 生效) */
|
|
2818
2818
|
__publicField(this, "fastFactor");
|
|
2819
|
-
/** 最小高度(米) */
|
|
2820
|
-
__publicField(this, "minHeight");
|
|
2821
2819
|
/** 外部传入的行为配置与回调 */
|
|
2822
2820
|
__publicField(this, "opts");
|
|
2823
2821
|
// 使用内联的 _FrustumPyramid
|
|
@@ -2845,7 +2843,6 @@ var AirplaneCursor = class {
|
|
|
2845
2843
|
this.step = opts.stepMeters ?? 2;
|
|
2846
2844
|
this.angleStep = opts.angleStepDeg ?? 1;
|
|
2847
2845
|
this.fastFactor = opts.fastFactor ?? 5;
|
|
2848
|
-
this.minHeight = opts.minHeight ?? 0;
|
|
2849
2846
|
this.currentFOV = opts.fovDeg ?? 50;
|
|
2850
2847
|
this.ensureEntity(opts.color ?? C.Color.CYAN.withAlpha(0.9));
|
|
2851
2848
|
this.attachKeyboard(opts);
|
|
@@ -3070,11 +3067,8 @@ var AirplaneCursor = class {
|
|
|
3070
3067
|
}
|
|
3071
3068
|
if (this.keysPressed.has("z")) {
|
|
3072
3069
|
const newPos = addVec(pose.position, C.Cartesian3.multiplyByScalar(u3, -step, new C.Cartesian3()));
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
setPos(newPos);
|
|
3076
|
-
moved = true;
|
|
3077
|
-
}
|
|
3070
|
+
setPos(newPos);
|
|
3071
|
+
moved = true;
|
|
3078
3072
|
}
|
|
3079
3073
|
if (this.keysPressed.has("q")) {
|
|
3080
3074
|
pose.heading = clampDeg(pose.heading - ang);
|
|
@@ -3127,8 +3121,8 @@ var AirplaneCursor = class {
|
|
|
3127
3121
|
this.viewer.dataSources.add(layer);
|
|
3128
3122
|
}
|
|
3129
3123
|
this.frustum = new FrustumPyramid(this.CesiumNS, layer, {
|
|
3130
|
-
fov: this.opts.fovDeg ??
|
|
3131
|
-
length:
|
|
3124
|
+
fov: this.opts.fovDeg ?? 40,
|
|
3125
|
+
length: 80,
|
|
3132
3126
|
color: this.opts.color,
|
|
3133
3127
|
fillAlpha: 0.25,
|
|
3134
3128
|
width: 2,
|
|
@@ -3136,14 +3130,17 @@ var AirplaneCursor = class {
|
|
|
3136
3130
|
logAngles: false,
|
|
3137
3131
|
logThrottleMs: 300
|
|
3138
3132
|
});
|
|
3133
|
+
const frustumFovScale = 0.6;
|
|
3134
|
+
const frustumLengthScale = 0.1;
|
|
3139
3135
|
this.frustum.showAtDynamic(
|
|
3140
3136
|
() => this.pose.position,
|
|
3141
3137
|
() => this.pose.heading,
|
|
3142
3138
|
() => this.pose.pitch,
|
|
3143
3139
|
() => this.pose.roll,
|
|
3144
|
-
() => this.currentFOV,
|
|
3145
|
-
//
|
|
3146
|
-
() => 1e3
|
|
3140
|
+
() => this.currentFOV * frustumFovScale,
|
|
3141
|
+
// 缩小 FOV
|
|
3142
|
+
() => 1e3 * frustumLengthScale
|
|
3143
|
+
// 缩小深度(1000 -> 100)
|
|
3147
3144
|
);
|
|
3148
3145
|
try {
|
|
3149
3146
|
this.heightMarker = new HeightMarker(this.CesiumNS, this.viewer, layer);
|
|
@@ -3659,7 +3656,7 @@ function calculatePathDistance(CesiumNS, positions, targetIndex, hiddenClimbInde
|
|
|
3659
3656
|
if (targetIndex < 0 || targetIndex >= positions.length) return 0;
|
|
3660
3657
|
const C = CesiumNS;
|
|
3661
3658
|
let totalDistance = 0;
|
|
3662
|
-
const startIndex =
|
|
3659
|
+
const startIndex = 1;
|
|
3663
3660
|
if (targetIndex <= startIndex) return 0;
|
|
3664
3661
|
for (let i = startIndex; i <= targetIndex; i++) {
|
|
3665
3662
|
try {
|
|
@@ -3702,9 +3699,11 @@ var VertexInsertionHandler = class {
|
|
|
3702
3699
|
* @param heightMarkers 高度标记数组(引用)
|
|
3703
3700
|
* @param airplaneCursor 飞机游标(可选)
|
|
3704
3701
|
* @param poseOrient 顶点姿态(可选)
|
|
3702
|
+
* @param useGlobalHeightFlags 🆕 是否使用全局高度标志数组(引用,可选)
|
|
3703
|
+
* @param altitudeModeOptions 🆕 高度模式选项(可选)
|
|
3705
3704
|
* @returns 实际插入的索引
|
|
3706
3705
|
*/
|
|
3707
|
-
insertVertex(insertAt, position, positions, handles, headings, pitches, rolls, fovs, editedIndices, vertexLabelManager, heightMarkers, airplaneCursor, poseOrient) {
|
|
3706
|
+
insertVertex(insertAt, position, positions, handles, headings, pitches, rolls, fovs, editedIndices, vertexLabelManager, heightMarkers, airplaneCursor, poseOrient, useGlobalHeightFlags) {
|
|
3708
3707
|
const C = this.CesiumNS;
|
|
3709
3708
|
if (this.hiddenClimbIndex === 1 && insertAt <= 1) {
|
|
3710
3709
|
insertAt = 2;
|
|
@@ -3739,6 +3738,12 @@ var VertexInsertionHandler = class {
|
|
|
3739
3738
|
pitches.splice(insertAt, 0, pose.pitch);
|
|
3740
3739
|
rolls.splice(insertAt, 0, pose.roll);
|
|
3741
3740
|
fovs.splice(insertAt, 0, 50);
|
|
3741
|
+
if (useGlobalHeightFlags) {
|
|
3742
|
+
for (let i = useGlobalHeightFlags.length - 1; i >= insertAt; i--) {
|
|
3743
|
+
useGlobalHeightFlags[i + 1] = useGlobalHeightFlags[i];
|
|
3744
|
+
}
|
|
3745
|
+
useGlobalHeightFlags[insertAt] = true;
|
|
3746
|
+
}
|
|
3742
3747
|
return insertAt;
|
|
3743
3748
|
}
|
|
3744
3749
|
/**
|
|
@@ -3947,7 +3952,6 @@ var VertexDragHandler = class {
|
|
|
3947
3952
|
__publicField(this, "CesiumNS");
|
|
3948
3953
|
__publicField(this, "viewer");
|
|
3949
3954
|
__publicField(this, "hiddenClimbIndex");
|
|
3950
|
-
__publicField(this, "minHeight");
|
|
3951
3955
|
__publicField(this, "callbacks");
|
|
3952
3956
|
__publicField(this, "dragState", null);
|
|
3953
3957
|
__publicField(this, "canvas");
|
|
@@ -3956,7 +3960,6 @@ var VertexDragHandler = class {
|
|
|
3956
3960
|
this.CesiumNS = options.CesiumNS;
|
|
3957
3961
|
this.viewer = options.viewer;
|
|
3958
3962
|
this.hiddenClimbIndex = options.hiddenClimbIndex;
|
|
3959
|
-
this.minHeight = options.minHeight ?? 0;
|
|
3960
3963
|
this.callbacks = callbacks;
|
|
3961
3964
|
this.canvas = this.viewer.scene.canvas;
|
|
3962
3965
|
this.setupKeyboardListeners();
|
|
@@ -4132,7 +4135,7 @@ var VertexDragHandler = class {
|
|
|
4132
4135
|
const cameraHeight = this.viewer.camera.positionCartographic.height;
|
|
4133
4136
|
const scaleFactor = Math.max(cameraHeight / 1e3, 0.5);
|
|
4134
4137
|
const heightDelta = -deltaY * scaleFactor;
|
|
4135
|
-
const newHeight =
|
|
4138
|
+
const newHeight = this.dragState.startHeight + heightDelta;
|
|
4136
4139
|
const newPosition = C.Cartesian3.fromDegrees(
|
|
4137
4140
|
this.dragState.startLonLat.lon,
|
|
4138
4141
|
this.dragState.startLonLat.lat,
|
|
@@ -4217,6 +4220,83 @@ var VertexDragHandler = class {
|
|
|
4217
4220
|
}
|
|
4218
4221
|
};
|
|
4219
4222
|
|
|
4223
|
+
// src/core/path-manager/utils/TerrainHeightQuery.ts
|
|
4224
|
+
async function queryTerrainHeights(CesiumNS, viewer, positions) {
|
|
4225
|
+
const C = CesiumNS;
|
|
4226
|
+
if (!positions || positions.length === 0) {
|
|
4227
|
+
return [];
|
|
4228
|
+
}
|
|
4229
|
+
const cartographics = positions.map((pos) => {
|
|
4230
|
+
try {
|
|
4231
|
+
return C.Cartographic.fromCartesian(pos);
|
|
4232
|
+
} catch {
|
|
4233
|
+
return new C.Cartographic(0, 0, 0);
|
|
4234
|
+
}
|
|
4235
|
+
});
|
|
4236
|
+
const terrainProvider = viewer.terrainProvider;
|
|
4237
|
+
if (!terrainProvider || !C.sampleTerrainMostDetailed) {
|
|
4238
|
+
console.warn("[TerrainHeightQuery] \u65E0\u53EF\u7528\u5730\u5F62\u63D0\u4F9B\u8005\uFF0C\u4F7F\u7528\u540C\u6B65\u56DE\u9000\u65B9\u6848");
|
|
4239
|
+
return positions.map((pos) => queryTerrainHeightSync(CesiumNS, viewer, pos));
|
|
4240
|
+
}
|
|
4241
|
+
try {
|
|
4242
|
+
const sampledPositions = await C.sampleTerrainMostDetailed(
|
|
4243
|
+
terrainProvider,
|
|
4244
|
+
cartographics
|
|
4245
|
+
);
|
|
4246
|
+
return sampledPositions.map((carto) => {
|
|
4247
|
+
const height = carto?.height;
|
|
4248
|
+
return typeof height === "number" && !isNaN(height) ? height : 0;
|
|
4249
|
+
});
|
|
4250
|
+
} catch (error) {
|
|
4251
|
+
console.warn("[TerrainHeightQuery] \u5F02\u6B65\u67E5\u8BE2\u5931\u8D25\uFF0C\u4F7F\u7528\u540C\u6B65\u56DE\u9000:", error);
|
|
4252
|
+
return positions.map((pos) => queryTerrainHeightSync(CesiumNS, viewer, pos));
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
function queryTerrainHeightSync(CesiumNS, viewer, position) {
|
|
4256
|
+
const C = CesiumNS;
|
|
4257
|
+
try {
|
|
4258
|
+
const cartographic = C.Cartographic.fromCartesian(position);
|
|
4259
|
+
const globe = viewer.scene.globe;
|
|
4260
|
+
if (globe && typeof globe.getHeight === "function") {
|
|
4261
|
+
const height = globe.getHeight(cartographic);
|
|
4262
|
+
if (typeof height === "number" && !isNaN(height)) {
|
|
4263
|
+
return height;
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
} catch (error) {
|
|
4267
|
+
console.warn("[TerrainHeightQuery] \u540C\u6B65\u67E5\u8BE2\u5931\u8D25:", error);
|
|
4268
|
+
}
|
|
4269
|
+
return 0;
|
|
4270
|
+
}
|
|
4271
|
+
async function queryTerrainHeightAsync(CesiumNS, viewer, position) {
|
|
4272
|
+
const heights = await queryTerrainHeights(CesiumNS, viewer, [position]);
|
|
4273
|
+
return heights[0] ?? 0;
|
|
4274
|
+
}
|
|
4275
|
+
function calculateAbsoluteHeight(altitudeMode, defaultAltitude, startPointAltitude, terrainHeight) {
|
|
4276
|
+
switch (altitudeMode) {
|
|
4277
|
+
case "absolute":
|
|
4278
|
+
return defaultAltitude;
|
|
4279
|
+
case "relativeToStart":
|
|
4280
|
+
return startPointAltitude + defaultAltitude;
|
|
4281
|
+
case "relativeToGround":
|
|
4282
|
+
return terrainHeight + defaultAltitude;
|
|
4283
|
+
default:
|
|
4284
|
+
return defaultAltitude;
|
|
4285
|
+
}
|
|
4286
|
+
}
|
|
4287
|
+
function calculateRelativeHeight(altitudeMode, absoluteHeight, startPointAltitude, terrainHeight) {
|
|
4288
|
+
switch (altitudeMode) {
|
|
4289
|
+
case "absolute":
|
|
4290
|
+
return absoluteHeight;
|
|
4291
|
+
case "relativeToStart":
|
|
4292
|
+
return absoluteHeight - startPointAltitude;
|
|
4293
|
+
case "relativeToGround":
|
|
4294
|
+
return absoluteHeight - terrainHeight;
|
|
4295
|
+
default:
|
|
4296
|
+
return absoluteHeight;
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
|
|
4220
4300
|
// src/core/path-manager/editing/PathEditingEventHandler.ts
|
|
4221
4301
|
var PathEditingEventHandler = class {
|
|
4222
4302
|
constructor(options, callbacks) {
|
|
@@ -4239,8 +4319,7 @@ var PathEditingEventHandler = class {
|
|
|
4239
4319
|
{
|
|
4240
4320
|
CesiumNS: this.CesiumNS,
|
|
4241
4321
|
viewer: this.viewer,
|
|
4242
|
-
hiddenClimbIndex: this.hiddenClimbIndex
|
|
4243
|
-
minHeight: options.minHeight
|
|
4322
|
+
hiddenClimbIndex: this.hiddenClimbIndex
|
|
4244
4323
|
},
|
|
4245
4324
|
{
|
|
4246
4325
|
onDragStart: (index) => {
|
|
@@ -4475,23 +4554,14 @@ var PathEditingEventHandler = class {
|
|
|
4475
4554
|
buildVertexContextMenuItems(vertexIndex) {
|
|
4476
4555
|
const menuItems = [];
|
|
4477
4556
|
const positions = this.callbacks.getPositions?.() || [];
|
|
4478
|
-
const
|
|
4479
|
-
|
|
4480
|
-
const isStartPoint = vertexIndex === 0 || this.hiddenClimbIndex === 1 && vertexIndex === 1;
|
|
4481
|
-
if (canDelete && !isStartPoint) {
|
|
4557
|
+
const canDelete = positions.length > 1;
|
|
4558
|
+
if (canDelete) {
|
|
4482
4559
|
menuItems.push({
|
|
4483
4560
|
label: `\u5220\u9664\u822A\u70B9 ${this.getVertexDisplayNumber(vertexIndex)}`,
|
|
4484
4561
|
action: () => {
|
|
4485
4562
|
this.handleDeleteVertex(vertexIndex);
|
|
4486
4563
|
}
|
|
4487
4564
|
});
|
|
4488
|
-
} else if (isStartPoint) {
|
|
4489
|
-
menuItems.push({
|
|
4490
|
-
label: "\u8D77\u70B9\u4E0D\u53EF\u5220\u9664",
|
|
4491
|
-
action: () => {
|
|
4492
|
-
},
|
|
4493
|
-
disabled: true
|
|
4494
|
-
});
|
|
4495
4565
|
} else {
|
|
4496
4566
|
menuItems.push({
|
|
4497
4567
|
label: "\u81F3\u5C11\u4FDD\u7559\u4E00\u4E2A\u822A\u70B9",
|
|
@@ -4503,12 +4573,10 @@ var PathEditingEventHandler = class {
|
|
|
4503
4573
|
return menuItems;
|
|
4504
4574
|
}
|
|
4505
4575
|
/**
|
|
4506
|
-
*
|
|
4576
|
+
* 获取顶点的显示编号
|
|
4577
|
+
* 🆕 不再跳过隐藏爬升点,直接返回索引
|
|
4507
4578
|
*/
|
|
4508
4579
|
getVertexDisplayNumber(index) {
|
|
4509
|
-
if (this.hiddenClimbIndex === 1 && index > 1) {
|
|
4510
|
-
return index - 1;
|
|
4511
|
-
}
|
|
4512
4580
|
return index;
|
|
4513
4581
|
}
|
|
4514
4582
|
/**
|
|
@@ -4540,18 +4608,17 @@ var PathEditingEventHandler = class {
|
|
|
4540
4608
|
};
|
|
4541
4609
|
}
|
|
4542
4610
|
const totalVertices = positions.length;
|
|
4543
|
-
const totalVisibleVertices = totalVertices
|
|
4544
|
-
const isStartPoint =
|
|
4545
|
-
const isHiddenClimb =
|
|
4546
|
-
const canDelete =
|
|
4611
|
+
const totalVisibleVertices = totalVertices;
|
|
4612
|
+
const isStartPoint = false;
|
|
4613
|
+
const isHiddenClimb = false;
|
|
4614
|
+
const canDelete = totalVertices > 1;
|
|
4547
4615
|
let pathProperties;
|
|
4548
4616
|
if (entity) {
|
|
4549
4617
|
try {
|
|
4550
4618
|
const props = entity.properties;
|
|
4551
4619
|
pathProperties = {
|
|
4552
4620
|
altitudeMode: props?._altitudeMode?.getValue?.() ?? props?._altitudeMode,
|
|
4553
|
-
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
4554
|
-
hasHiddenClimb: props?._hasHiddenClimb?.getValue?.() ?? props?._hasHiddenClimb
|
|
4621
|
+
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
4555
4622
|
};
|
|
4556
4623
|
} catch {
|
|
4557
4624
|
}
|
|
@@ -4590,11 +4657,9 @@ var PathEditingEventHandler = class {
|
|
|
4590
4657
|
}
|
|
4591
4658
|
/**
|
|
4592
4659
|
* 处理插入顶点
|
|
4660
|
+
* 🆕 不再跳过隐藏爬升点
|
|
4593
4661
|
*/
|
|
4594
4662
|
handleInsertVertex(insertAt, pose, type) {
|
|
4595
|
-
if (this.hiddenClimbIndex === 1 && insertAt <= 1) {
|
|
4596
|
-
insertAt = 2;
|
|
4597
|
-
}
|
|
4598
4663
|
if (this.callbacks.onInsertVertex) {
|
|
4599
4664
|
this.callbacks.onInsertVertex(insertAt, pose.position, {
|
|
4600
4665
|
heading: pose.heading,
|
|
@@ -4625,6 +4690,10 @@ var PathEditingEventHandler = class {
|
|
|
4625
4690
|
}
|
|
4626
4691
|
/**
|
|
4627
4692
|
* 🆕 处理快速编辑模式的点击
|
|
4693
|
+
* 根据 altitudeMode 计算航点高度:
|
|
4694
|
+
* - absolute: 航点高度 = defaultAltitude
|
|
4695
|
+
* - relativeToGround: 航点高度 = 地形高度 + defaultAltitude
|
|
4696
|
+
* - relativeToStart: 航点高度 = 起飞点高度 + defaultAltitude
|
|
4628
4697
|
*/
|
|
4629
4698
|
handleQuickEditClick(movement) {
|
|
4630
4699
|
const position = this.getPositionFromMouse(movement);
|
|
@@ -4634,11 +4703,9 @@ var PathEditingEventHandler = class {
|
|
|
4634
4703
|
}
|
|
4635
4704
|
const quickEditOptions = this.callbacks.getQuickEditOptions?.();
|
|
4636
4705
|
if (!quickEditOptions) return;
|
|
4637
|
-
const {
|
|
4706
|
+
const { defaultAltitude, altitudeMode } = quickEditOptions;
|
|
4707
|
+
const newPosition = this.calculatePositionByAltitudeMode(position, defaultAltitude, altitudeMode);
|
|
4638
4708
|
const C = this.CesiumNS;
|
|
4639
|
-
const originalCarto = C.Cartographic.fromCartesian(position);
|
|
4640
|
-
const originalHeight = originalCarto.height;
|
|
4641
|
-
const newPosition = this.applyClimbHeight(position, climbHeight, altitudeMode);
|
|
4642
4709
|
const newCarto = C.Cartographic.fromCartesian(newPosition);
|
|
4643
4710
|
const newHeight = newCarto.height;
|
|
4644
4711
|
const positions = this.callbacks.getPositions?.() || [];
|
|
@@ -4653,8 +4720,7 @@ var PathEditingEventHandler = class {
|
|
|
4653
4720
|
insertAt,
|
|
4654
4721
|
heading: heading.toFixed(2),
|
|
4655
4722
|
altitudeMode,
|
|
4656
|
-
|
|
4657
|
-
originalHeight: originalHeight.toFixed(2),
|
|
4723
|
+
defaultAltitude,
|
|
4658
4724
|
finalHeight: newHeight.toFixed(2)
|
|
4659
4725
|
});
|
|
4660
4726
|
this.callbacks.onInsertVertex(insertAt, newPosition, {
|
|
@@ -4666,21 +4732,35 @@ var PathEditingEventHandler = class {
|
|
|
4666
4732
|
}
|
|
4667
4733
|
}
|
|
4668
4734
|
/**
|
|
4669
|
-
* 🆕
|
|
4735
|
+
* 🆕 根据高度模式计算航点位置
|
|
4736
|
+
* - absolute: 航点高度 = defaultAltitude
|
|
4737
|
+
* - relativeToGround: 航点高度 = 地形高度 + defaultAltitude
|
|
4738
|
+
* - relativeToStart: 航点高度 = 起飞点高度 + defaultAltitude
|
|
4670
4739
|
*/
|
|
4671
|
-
|
|
4740
|
+
calculatePositionByAltitudeMode(position, defaultAltitude, altitudeMode) {
|
|
4672
4741
|
const C = this.CesiumNS;
|
|
4673
4742
|
try {
|
|
4674
4743
|
const cartographic = C.Cartographic.fromCartesian(position);
|
|
4675
4744
|
const lon = C.Math.toDegrees(cartographic.longitude);
|
|
4676
4745
|
const lat = C.Math.toDegrees(cartographic.latitude);
|
|
4677
|
-
let
|
|
4678
|
-
if (altitudeMode === "
|
|
4679
|
-
|
|
4680
|
-
} else if (altitudeMode === "
|
|
4681
|
-
|
|
4746
|
+
let finalHeight;
|
|
4747
|
+
if (altitudeMode === "absolute") {
|
|
4748
|
+
finalHeight = defaultAltitude;
|
|
4749
|
+
} else if (altitudeMode === "relativeToGround") {
|
|
4750
|
+
const terrainHeight = queryTerrainHeightSync(this.CesiumNS, this.viewer, position);
|
|
4751
|
+
finalHeight = terrainHeight + defaultAltitude;
|
|
4752
|
+
} else if (altitudeMode === "relativeToStart") {
|
|
4753
|
+
const startPointAltitude = this.callbacks.getStartPointAltitude?.() ?? 0;
|
|
4754
|
+
finalHeight = startPointAltitude + defaultAltitude;
|
|
4755
|
+
} else {
|
|
4756
|
+
finalHeight = defaultAltitude;
|
|
4682
4757
|
}
|
|
4683
|
-
|
|
4758
|
+
console.log("[QuickEdit] \u9AD8\u5EA6\u8BA1\u7B97:", {
|
|
4759
|
+
altitudeMode,
|
|
4760
|
+
defaultAltitude,
|
|
4761
|
+
finalHeight
|
|
4762
|
+
});
|
|
4763
|
+
return C.Cartesian3.fromDegrees(lon, lat, finalHeight);
|
|
4684
4764
|
} catch (error) {
|
|
4685
4765
|
console.error("[QuickEdit] \u9AD8\u5EA6\u8BA1\u7B97\u5931\u8D25:", error);
|
|
4686
4766
|
return position;
|
|
@@ -4772,19 +4852,19 @@ var VertexHandleStyleManager = class {
|
|
|
4772
4852
|
__publicField(this, "selectedStyle");
|
|
4773
4853
|
const C = CesiumNS;
|
|
4774
4854
|
this.normalStyle = {
|
|
4775
|
-
pixelSize: options?.normal?.pixelSize ??
|
|
4855
|
+
pixelSize: options?.normal?.pixelSize ?? 6,
|
|
4776
4856
|
color: options?.normal?.color ?? C.Color.YELLOW,
|
|
4777
4857
|
outlineColor: options?.normal?.outlineColor ?? C.Color.BLACK,
|
|
4778
4858
|
outlineWidth: options?.normal?.outlineWidth ?? 1
|
|
4779
4859
|
};
|
|
4780
4860
|
this.editedStyle = {
|
|
4781
|
-
pixelSize: options?.edited?.pixelSize ??
|
|
4861
|
+
pixelSize: options?.edited?.pixelSize ?? 6,
|
|
4782
4862
|
color: options?.edited?.color ?? C.Color.CYAN,
|
|
4783
4863
|
outlineColor: options?.edited?.outlineColor ?? C.Color.BLACK,
|
|
4784
4864
|
outlineWidth: options?.edited?.outlineWidth ?? 1
|
|
4785
4865
|
};
|
|
4786
4866
|
this.selectedStyle = {
|
|
4787
|
-
pixelSize: options?.selected?.pixelSize ??
|
|
4867
|
+
pixelSize: options?.selected?.pixelSize ?? 8,
|
|
4788
4868
|
color: options?.selected?.color ?? C.Color.ORANGE,
|
|
4789
4869
|
outlineColor: options?.selected?.outlineColor ?? C.Color.BLACK,
|
|
4790
4870
|
outlineWidth: options?.selected?.outlineWidth ?? 2
|
|
@@ -4992,18 +5072,57 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
4992
5072
|
} catch {
|
|
4993
5073
|
positions = [];
|
|
4994
5074
|
}
|
|
4995
|
-
|
|
5075
|
+
const hiddenClimbIndex = void 0;
|
|
5076
|
+
let currentAltitudeMode = "absolute";
|
|
5077
|
+
let currentDefaultAltitude = 100;
|
|
4996
5078
|
try {
|
|
4997
5079
|
const props = entity.properties;
|
|
4998
|
-
const
|
|
4999
|
-
if (
|
|
5080
|
+
const storedMode = props?._altitudeMode?.getValue?.() ?? props?._altitudeMode;
|
|
5081
|
+
if (storedMode === "absolute" || storedMode === "relativeToGround" || storedMode === "relativeToStart") {
|
|
5082
|
+
currentAltitudeMode = storedMode;
|
|
5083
|
+
}
|
|
5084
|
+
const storedDefaultAlt = props?._defaultAltitude?.getValue?.() ?? props?._defaultAltitude;
|
|
5085
|
+
if (typeof storedDefaultAlt === "number") {
|
|
5086
|
+
currentDefaultAltitude = storedDefaultAlt;
|
|
5087
|
+
}
|
|
5000
5088
|
} catch {
|
|
5001
5089
|
}
|
|
5090
|
+
if (options?.altitudeMode) {
|
|
5091
|
+
currentAltitudeMode = options.altitudeMode;
|
|
5092
|
+
}
|
|
5093
|
+
if (options?.defaultAltitude !== void 0) {
|
|
5094
|
+
currentDefaultAltitude = options.defaultAltitude;
|
|
5095
|
+
}
|
|
5096
|
+
let startPointAltitude = 0;
|
|
5097
|
+
try {
|
|
5098
|
+
if (positions.length > 0) {
|
|
5099
|
+
const startCarto = C.Cartographic.fromCartesian(positions[0]);
|
|
5100
|
+
startPointAltitude = startCarto.height ?? 0;
|
|
5101
|
+
}
|
|
5102
|
+
} catch {
|
|
5103
|
+
}
|
|
5104
|
+
const terrainHeightsCache = /* @__PURE__ */ new Map();
|
|
5105
|
+
const useGlobalHeightFlags = [];
|
|
5106
|
+
try {
|
|
5107
|
+
const props = entity.properties;
|
|
5108
|
+
const storedFlags = props?._useGlobalHeightFlags?.getValue?.() ?? props?._useGlobalHeightFlags;
|
|
5109
|
+
if (Array.isArray(storedFlags)) {
|
|
5110
|
+
storedFlags.forEach((flag, idx) => {
|
|
5111
|
+
useGlobalHeightFlags[idx] = flag;
|
|
5112
|
+
});
|
|
5113
|
+
}
|
|
5114
|
+
} catch {
|
|
5115
|
+
}
|
|
5116
|
+
while (useGlobalHeightFlags.length < positions.length) {
|
|
5117
|
+
useGlobalHeightFlags.push(false);
|
|
5118
|
+
}
|
|
5002
5119
|
let quickEditEnabled = false;
|
|
5003
5120
|
let quickEditOptions = {
|
|
5004
5121
|
enabled: false,
|
|
5005
|
-
climbHeight:
|
|
5006
|
-
|
|
5122
|
+
climbHeight: currentDefaultAltitude,
|
|
5123
|
+
// 使用当前默认高度
|
|
5124
|
+
altitudeMode: currentAltitudeMode
|
|
5125
|
+
// 使用当前高度模式
|
|
5007
5126
|
};
|
|
5008
5127
|
if (options?.quickEdit) {
|
|
5009
5128
|
if (typeof options.quickEdit === "boolean") {
|
|
@@ -5036,33 +5155,23 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5036
5155
|
} catch {
|
|
5037
5156
|
}
|
|
5038
5157
|
const handles = positions.map((p, i) => {
|
|
5039
|
-
if (hiddenClimbIndex === i) return void 0;
|
|
5040
|
-
const isStartPoint = i === 0;
|
|
5041
5158
|
const h = existing[i];
|
|
5042
5159
|
if (h) {
|
|
5043
5160
|
try {
|
|
5044
5161
|
h.position = p;
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
h.point.outlineWidth = 1;
|
|
5051
|
-
}
|
|
5162
|
+
h.point = h.point ?? { pixelSize: 6 };
|
|
5163
|
+
h.point.pixelSize = 6;
|
|
5164
|
+
h.point.color = C.Color.YELLOW;
|
|
5165
|
+
h.point.outlineColor = C.Color.BLACK;
|
|
5166
|
+
h.point.outlineWidth = 1;
|
|
5052
5167
|
h.properties = { _type: "path-vertex", _ownerId: ownerId, _vertexIndex: i };
|
|
5053
5168
|
} catch {
|
|
5054
5169
|
}
|
|
5055
5170
|
return h;
|
|
5056
5171
|
}
|
|
5057
|
-
if (isStartPoint) {
|
|
5058
|
-
return layer.entities.add({
|
|
5059
|
-
position: p,
|
|
5060
|
-
properties: { _type: "path-vertex", _ownerId: ownerId, _vertexIndex: i }
|
|
5061
|
-
});
|
|
5062
|
-
}
|
|
5063
5172
|
return layer.entities.add({
|
|
5064
5173
|
position: p,
|
|
5065
|
-
point: { pixelSize:
|
|
5174
|
+
point: { pixelSize: 6, color: C.Color.YELLOW, outlineColor: C.Color.BLACK, outlineWidth: 1 },
|
|
5066
5175
|
properties: { _type: "path-vertex", _ownerId: ownerId, _vertexIndex: i }
|
|
5067
5176
|
});
|
|
5068
5177
|
});
|
|
@@ -5079,8 +5188,6 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5079
5188
|
};
|
|
5080
5189
|
const createOrUpdateMarkerForIndex = (idx) => {
|
|
5081
5190
|
try {
|
|
5082
|
-
if (hiddenClimbIndex === 1 && idx === 1) return;
|
|
5083
|
-
if (idx === 0) return;
|
|
5084
5191
|
const pos = positions[idx];
|
|
5085
5192
|
if (!pos) return;
|
|
5086
5193
|
const markerLayer = ensureMarkerLayer();
|
|
@@ -5162,7 +5269,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5162
5269
|
};
|
|
5163
5270
|
const getTotalDistance = () => {
|
|
5164
5271
|
if (positions.length < 2) return 0;
|
|
5165
|
-
return calculatePathDistance(CesiumNS, positions, positions.length - 1
|
|
5272
|
+
return calculatePathDistance(CesiumNS, positions, positions.length - 1);
|
|
5166
5273
|
};
|
|
5167
5274
|
const vertexInsertionHandler = new VertexInsertionHandler({
|
|
5168
5275
|
CesiumNS,
|
|
@@ -5171,7 +5278,40 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5171
5278
|
hiddenClimbIndex
|
|
5172
5279
|
});
|
|
5173
5280
|
let cursorStart = positions[positions.length - 1];
|
|
5174
|
-
if (!cursorStart) cursorStart = positions[
|
|
5281
|
+
if (!cursorStart) cursorStart = positions[0];
|
|
5282
|
+
if (!cursorStart) {
|
|
5283
|
+
try {
|
|
5284
|
+
const cameraPos = viewer.camera.positionCartographic;
|
|
5285
|
+
if (cameraPos) {
|
|
5286
|
+
let initialHeight = currentDefaultAltitude;
|
|
5287
|
+
if (currentAltitudeMode === "relativeToGround") {
|
|
5288
|
+
const terrainHeight = queryTerrainHeightSync(
|
|
5289
|
+
CesiumNS,
|
|
5290
|
+
viewer,
|
|
5291
|
+
C.Cartesian3.fromRadians(cameraPos.longitude, cameraPos.latitude, 0)
|
|
5292
|
+
);
|
|
5293
|
+
initialHeight = terrainHeight + currentDefaultAltitude;
|
|
5294
|
+
console.log("[PathEditing] relativeToGround \u6A21\u5F0F\uFF0C\u5730\u5F62\u9AD8\u5EA6:", terrainHeight, "\u521D\u59CB\u9AD8\u5EA6:", initialHeight);
|
|
5295
|
+
} else if (currentAltitudeMode === "relativeToStart") {
|
|
5296
|
+
initialHeight = currentDefaultAltitude;
|
|
5297
|
+
console.log("[PathEditing] relativeToStart \u6A21\u5F0F\uFF08\u7A7A\u822A\u7EBF\uFF09\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u9AD8\u5EA6:", initialHeight);
|
|
5298
|
+
}
|
|
5299
|
+
cursorStart = C.Cartesian3.fromRadians(
|
|
5300
|
+
cameraPos.longitude,
|
|
5301
|
+
cameraPos.latitude,
|
|
5302
|
+
initialHeight
|
|
5303
|
+
);
|
|
5304
|
+
console.log("[PathEditing] \u7A7A\u822A\u7EBF\uFF0C\u4F7F\u7528\u76F8\u673A\u4F4D\u7F6E\u521D\u59CB\u5316\u6E38\u6807:", {
|
|
5305
|
+
lon: C.Math.toDegrees(cameraPos.longitude),
|
|
5306
|
+
lat: C.Math.toDegrees(cameraPos.latitude),
|
|
5307
|
+
height: initialHeight,
|
|
5308
|
+
altitudeMode: currentAltitudeMode
|
|
5309
|
+
});
|
|
5310
|
+
}
|
|
5311
|
+
} catch (error) {
|
|
5312
|
+
console.warn("[PathEditing] \u65E0\u6CD5\u83B7\u53D6\u76F8\u673A\u4F4D\u7F6E:", error);
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5175
5315
|
let airplaneCursor;
|
|
5176
5316
|
const insertVertex = (insertAt, p3, poseOrient) => {
|
|
5177
5317
|
console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u524D positions \u957F\u5EA6:", positions.length, "insertAt:", insertAt);
|
|
@@ -5188,7 +5328,9 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5188
5328
|
vertexLabelManager,
|
|
5189
5329
|
heightMarkers,
|
|
5190
5330
|
airplaneCursor,
|
|
5191
|
-
poseOrient
|
|
5331
|
+
poseOrient,
|
|
5332
|
+
useGlobalHeightFlags
|
|
5333
|
+
// 🆕 传递 useGlobalHeightFlags
|
|
5192
5334
|
);
|
|
5193
5335
|
console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length, "actualIndex:", actualIndex);
|
|
5194
5336
|
entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
|
|
@@ -5197,16 +5339,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5197
5339
|
};
|
|
5198
5340
|
const deleteVertex = (deleteAt) => {
|
|
5199
5341
|
try {
|
|
5200
|
-
if (
|
|
5201
|
-
console.warn("Cannot delete start point");
|
|
5202
|
-
return;
|
|
5203
|
-
}
|
|
5204
|
-
if (hiddenClimbIndex !== void 0 && deleteAt === hiddenClimbIndex) {
|
|
5205
|
-
console.warn("Cannot delete hidden climb point");
|
|
5206
|
-
return;
|
|
5207
|
-
}
|
|
5208
|
-
const visibleVertexCount = positions.length - (hiddenClimbIndex === 1 ? 1 : 0);
|
|
5209
|
-
if (visibleVertexCount <= 1) {
|
|
5342
|
+
if (positions.length <= 1) {
|
|
5210
5343
|
console.warn("Cannot delete last vertex");
|
|
5211
5344
|
return;
|
|
5212
5345
|
}
|
|
@@ -5230,6 +5363,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5230
5363
|
rolls.splice(deleteAt, 1);
|
|
5231
5364
|
fovs.splice(deleteAt, 1);
|
|
5232
5365
|
heightMarkers.splice(deleteAt, 1);
|
|
5366
|
+
useGlobalHeightFlags.splice(deleteAt, 1);
|
|
5233
5367
|
console.log("[PathEditing] \u5220\u9664\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length);
|
|
5234
5368
|
entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
|
|
5235
5369
|
const newEditedIndices = /* @__PURE__ */ new Set();
|
|
@@ -5291,9 +5425,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5291
5425
|
}
|
|
5292
5426
|
},
|
|
5293
5427
|
// frustumLengthFactor: options?.preview?.lengthFactor ?? 0.3,
|
|
5294
|
-
fovDeg: options?.preview?.fov ?? 50
|
|
5295
|
-
minHeight: options?.minHeight
|
|
5296
|
-
// 传递最小高度限制
|
|
5428
|
+
fovDeg: options?.preview?.fov ?? 50
|
|
5297
5429
|
});
|
|
5298
5430
|
if (options?.preview?.enabled !== false && airplaneCursor) {
|
|
5299
5431
|
preview = new PathPreview(CesiumNS, viewer, {
|
|
@@ -5337,8 +5469,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5337
5469
|
{
|
|
5338
5470
|
CesiumNS,
|
|
5339
5471
|
viewer,
|
|
5340
|
-
hiddenClimbIndex
|
|
5341
|
-
minHeight: options?.minHeight
|
|
5472
|
+
hiddenClimbIndex
|
|
5342
5473
|
},
|
|
5343
5474
|
{
|
|
5344
5475
|
onVertexSelect: (index) => setActiveIndex(index),
|
|
@@ -5369,7 +5500,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5369
5500
|
},
|
|
5370
5501
|
onDeleteVertex: (index) => {
|
|
5371
5502
|
const totalBefore = positions.length;
|
|
5372
|
-
const displayNumber =
|
|
5503
|
+
const displayNumber = index;
|
|
5373
5504
|
deleteVertex(index);
|
|
5374
5505
|
if (options?.onVertexDeleteDetail) {
|
|
5375
5506
|
try {
|
|
@@ -5422,7 +5553,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5422
5553
|
};
|
|
5423
5554
|
} catch {
|
|
5424
5555
|
}
|
|
5425
|
-
const displayNumber =
|
|
5556
|
+
const displayNumber = index;
|
|
5426
5557
|
const dragMoveInfo = {
|
|
5427
5558
|
index,
|
|
5428
5559
|
displayNumber,
|
|
@@ -5439,6 +5570,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5439
5570
|
onVertexDragEnd: (index, finalPosition) => {
|
|
5440
5571
|
editedIndices.add(index);
|
|
5441
5572
|
positions[index] = finalPosition;
|
|
5573
|
+
useGlobalHeightFlags[index] = false;
|
|
5442
5574
|
if (handles[index]) {
|
|
5443
5575
|
handleStyleManager.applyStyle(handles[index], "edited");
|
|
5444
5576
|
}
|
|
@@ -5485,10 +5617,29 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5485
5617
|
getCursorPose: () => airplaneCursor?.getPose(),
|
|
5486
5618
|
// 🆕 快速编辑回调
|
|
5487
5619
|
getQuickEditEnabled: () => quickEditEnabled,
|
|
5488
|
-
getQuickEditOptions: () =>
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5620
|
+
getQuickEditOptions: () => {
|
|
5621
|
+
let climbHeight = 0;
|
|
5622
|
+
try {
|
|
5623
|
+
const props = entity.properties;
|
|
5624
|
+
climbHeight = props?._climbHeight?.getValue?.() ?? props?._climbHeight ?? 0;
|
|
5625
|
+
} catch {
|
|
5626
|
+
}
|
|
5627
|
+
return {
|
|
5628
|
+
climbHeight,
|
|
5629
|
+
defaultAltitude: currentDefaultAltitude,
|
|
5630
|
+
altitudeMode: currentAltitudeMode
|
|
5631
|
+
};
|
|
5632
|
+
},
|
|
5633
|
+
// 🆕 高度模式相关回调
|
|
5634
|
+
getStartPointAltitude: () => startPointAltitude,
|
|
5635
|
+
getDefaultAltitude: () => currentDefaultAltitude,
|
|
5636
|
+
// 🆕 useGlobalHeightFlags 相关回调
|
|
5637
|
+
getUseGlobalHeightFlags: () => useGlobalHeightFlags,
|
|
5638
|
+
setUseGlobalHeightFlag: (index, value) => {
|
|
5639
|
+
if (index >= 0 && index < useGlobalHeightFlags.length) {
|
|
5640
|
+
useGlobalHeightFlags[index] = value;
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5492
5643
|
}
|
|
5493
5644
|
);
|
|
5494
5645
|
const cleanupSession = () => {
|
|
@@ -5528,6 +5679,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5528
5679
|
const buildVertexDetailInfo = (index) => {
|
|
5529
5680
|
const position = positions[index];
|
|
5530
5681
|
let coordinates = { longitude: 0, latitude: 0, height: 0 };
|
|
5682
|
+
let ellipsoidHeight = 0;
|
|
5531
5683
|
try {
|
|
5532
5684
|
const cartographic = C.Cartographic.fromCartesian(position);
|
|
5533
5685
|
coordinates = {
|
|
@@ -5535,8 +5687,16 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5535
5687
|
latitude: C.Math.toDegrees(cartographic.latitude),
|
|
5536
5688
|
height: cartographic.height
|
|
5537
5689
|
};
|
|
5690
|
+
ellipsoidHeight = cartographic.height ?? 0;
|
|
5538
5691
|
} catch {
|
|
5539
5692
|
}
|
|
5693
|
+
const terrainHeight = terrainHeightsCache.get(index) ?? 0;
|
|
5694
|
+
const relativeHeight = calculateRelativeHeight(
|
|
5695
|
+
currentAltitudeMode,
|
|
5696
|
+
ellipsoidHeight,
|
|
5697
|
+
startPointAltitude,
|
|
5698
|
+
terrainHeight
|
|
5699
|
+
);
|
|
5540
5700
|
const pose = {
|
|
5541
5701
|
heading: headings[index] ?? 0,
|
|
5542
5702
|
pitch: pitches[index] ?? 0,
|
|
@@ -5544,18 +5704,17 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5544
5704
|
fov: fovs[index] ?? 50
|
|
5545
5705
|
};
|
|
5546
5706
|
const totalVertices = positions.length;
|
|
5547
|
-
const totalVisibleVertices = totalVertices
|
|
5548
|
-
const isStartPoint =
|
|
5549
|
-
const isHiddenClimb =
|
|
5550
|
-
const canDelete =
|
|
5551
|
-
const displayNumber =
|
|
5707
|
+
const totalVisibleVertices = totalVertices;
|
|
5708
|
+
const isStartPoint = false;
|
|
5709
|
+
const isHiddenClimb = false;
|
|
5710
|
+
const canDelete = totalVertices > 1;
|
|
5711
|
+
const displayNumber = index;
|
|
5552
5712
|
let pathProperties;
|
|
5553
5713
|
try {
|
|
5554
5714
|
const props = entity.properties;
|
|
5555
5715
|
pathProperties = {
|
|
5556
5716
|
altitudeMode: props?._altitudeMode?.getValue?.() ?? props?._altitudeMode,
|
|
5557
|
-
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
5558
|
-
hasHiddenClimb: props?._hasHiddenClimb?.getValue?.() ?? props?._hasHiddenClimb
|
|
5717
|
+
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
5559
5718
|
};
|
|
5560
5719
|
} catch {
|
|
5561
5720
|
}
|
|
@@ -5571,44 +5730,68 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5571
5730
|
totalVisibleVertices,
|
|
5572
5731
|
totalVertices,
|
|
5573
5732
|
entity,
|
|
5574
|
-
pathProperties
|
|
5733
|
+
pathProperties,
|
|
5734
|
+
useGlobalHeight: useGlobalHeightFlags[index] ?? false,
|
|
5735
|
+
// 🆕 添加 useGlobalHeight
|
|
5736
|
+
ellipsoidHeight,
|
|
5737
|
+
// 🆕 添加椭球高度
|
|
5738
|
+
relativeHeight
|
|
5739
|
+
// 🆕 添加相对高度
|
|
5575
5740
|
};
|
|
5576
5741
|
};
|
|
5577
5742
|
return {
|
|
5578
5743
|
/** 保存并退出编辑模式 */
|
|
5579
5744
|
saveAndStop: () => {
|
|
5580
5745
|
stateManager.persistToEntity(positions, headings, pitches, rolls, fovs);
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5746
|
+
try {
|
|
5747
|
+
entity.properties._altitudeMode = currentAltitudeMode;
|
|
5748
|
+
entity.properties._defaultAltitude = currentDefaultAltitude;
|
|
5749
|
+
entity.properties._useGlobalHeightFlags = useGlobalHeightFlags.slice();
|
|
5750
|
+
} catch {
|
|
5751
|
+
}
|
|
5752
|
+
let altitudeMode = currentAltitudeMode;
|
|
5585
5753
|
let climbHeight;
|
|
5586
|
-
let hasHiddenClimb;
|
|
5587
5754
|
try {
|
|
5588
5755
|
const props = entity.properties;
|
|
5589
|
-
altitudeMode = props?._altitudeMode?.getValue?.() ?? props?._altitudeMode;
|
|
5590
5756
|
climbHeight = props?._climbHeight?.getValue?.() ?? props?._climbHeight;
|
|
5591
|
-
hasHiddenClimb = props?._hasHiddenClimb?.getValue?.() ?? props?._hasHiddenClimb;
|
|
5592
5757
|
} catch {
|
|
5593
5758
|
}
|
|
5594
|
-
const waypointData = positions.map((position, index) =>
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5759
|
+
const waypointData = positions.map((position, index) => {
|
|
5760
|
+
let ellipsoidHeight = 0;
|
|
5761
|
+
try {
|
|
5762
|
+
const carto = C.Cartographic.fromCartesian(position);
|
|
5763
|
+
ellipsoidHeight = carto.height ?? 0;
|
|
5764
|
+
} catch {
|
|
5765
|
+
}
|
|
5766
|
+
const terrainHeight = terrainHeightsCache.get(index) ?? 0;
|
|
5767
|
+
const relativeHeight = calculateRelativeHeight(
|
|
5768
|
+
currentAltitudeMode,
|
|
5769
|
+
ellipsoidHeight,
|
|
5770
|
+
startPointAltitude,
|
|
5771
|
+
terrainHeight
|
|
5772
|
+
);
|
|
5773
|
+
return {
|
|
5774
|
+
position,
|
|
5775
|
+
heading: headings[index] ?? 0,
|
|
5776
|
+
pitch: pitches[index] ?? -10,
|
|
5777
|
+
roll: rolls[index] ?? 0,
|
|
5778
|
+
fov: fovs[index] ?? 50,
|
|
5779
|
+
index,
|
|
5780
|
+
distance: calculatePathDistance(CesiumNS, positions, index),
|
|
5781
|
+
ellipsoidHeight,
|
|
5782
|
+
relativeHeight,
|
|
5783
|
+
useGlobalHeight: useGlobalHeightFlags[index] ?? false
|
|
5784
|
+
// 🆕 添加 useGlobalHeight
|
|
5785
|
+
};
|
|
5786
|
+
});
|
|
5603
5787
|
cleanupSession();
|
|
5604
5788
|
return {
|
|
5605
5789
|
entity,
|
|
5606
5790
|
positions: positions.slice(),
|
|
5607
|
-
startPoint,
|
|
5608
5791
|
climbHeight,
|
|
5609
5792
|
waypointData,
|
|
5610
5793
|
altitudeMode,
|
|
5611
|
-
|
|
5794
|
+
defaultAltitude: currentDefaultAltitude
|
|
5612
5795
|
};
|
|
5613
5796
|
},
|
|
5614
5797
|
/** 不保存退出(回滚到进入编辑时的状态) */
|
|
@@ -5831,45 +6014,32 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5831
6014
|
*/
|
|
5832
6015
|
getCursorPose: () => airplaneCursor?.getPose(),
|
|
5833
6016
|
/**
|
|
5834
|
-
* 🆕
|
|
5835
|
-
*
|
|
5836
|
-
* @param
|
|
6017
|
+
* 🆕 更新爬升高度(climbHeight)
|
|
6018
|
+
* 更新实体属性中的 _climbHeight 值
|
|
6019
|
+
* @param newClimbHeight 新的爬升高度(米)
|
|
5837
6020
|
* @returns 是否更新成功
|
|
5838
6021
|
*/
|
|
5839
|
-
updateClimbHeight: function(
|
|
5840
|
-
if (hiddenClimbIndex !== 1 || positions.length < 2) {
|
|
5841
|
-
console.warn("[updateClimbHeight] No hidden climb point exists");
|
|
5842
|
-
return false;
|
|
5843
|
-
}
|
|
6022
|
+
updateClimbHeight: function(newClimbHeight) {
|
|
5844
6023
|
try {
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
const success = this.updateWaypointAltitude(1, newAltitude);
|
|
5849
|
-
if (success) {
|
|
5850
|
-
try {
|
|
5851
|
-
entity.properties._climbHeight = climbHeight;
|
|
5852
|
-
} catch {
|
|
5853
|
-
}
|
|
5854
|
-
console.log("[updateClimbHeight] \u2705 \u722C\u5347\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", climbHeight, "\u7C73");
|
|
5855
|
-
}
|
|
5856
|
-
return success;
|
|
6024
|
+
entity.properties._climbHeight = newClimbHeight;
|
|
6025
|
+
console.log("[updateClimbHeight] \u2705 \u722C\u5347\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", newClimbHeight, "\u7C73");
|
|
6026
|
+
return true;
|
|
5857
6027
|
} catch (error) {
|
|
5858
6028
|
console.error("[updateClimbHeight] Error:", error);
|
|
5859
6029
|
return false;
|
|
5860
6030
|
}
|
|
5861
6031
|
},
|
|
5862
6032
|
/**
|
|
5863
|
-
* 🆕
|
|
5864
|
-
* @returns
|
|
6033
|
+
* 🆕 获取第一个航点信息
|
|
6034
|
+
* @returns 第一个航点的经纬度和高度
|
|
5865
6035
|
*/
|
|
5866
6036
|
getStartPoint: () => {
|
|
5867
6037
|
if (positions.length < 1) return null;
|
|
5868
6038
|
try {
|
|
5869
|
-
const
|
|
5870
|
-
const carto = C.Cartographic.fromCartesian(
|
|
6039
|
+
const firstPos = positions[0];
|
|
6040
|
+
const carto = C.Cartographic.fromCartesian(firstPos);
|
|
5871
6041
|
return {
|
|
5872
|
-
position:
|
|
6042
|
+
position: firstPos,
|
|
5873
6043
|
latitude: C.Math.toDegrees(carto.latitude),
|
|
5874
6044
|
longitude: C.Math.toDegrees(carto.longitude),
|
|
5875
6045
|
altitude: carto.height
|
|
@@ -5877,6 +6047,123 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5877
6047
|
} catch {
|
|
5878
6048
|
return null;
|
|
5879
6049
|
}
|
|
6050
|
+
},
|
|
6051
|
+
/**
|
|
6052
|
+
* 🆕 获取当前高度模式
|
|
6053
|
+
*/
|
|
6054
|
+
getAltitudeMode: () => currentAltitudeMode,
|
|
6055
|
+
/**
|
|
6056
|
+
* 🆕 获取当前默认高度
|
|
6057
|
+
*/
|
|
6058
|
+
getDefaultAltitude: () => currentDefaultAltitude,
|
|
6059
|
+
/**
|
|
6060
|
+
* 🆕 更新默认高度
|
|
6061
|
+
*/
|
|
6062
|
+
updateDefaultAltitude: (altitude) => {
|
|
6063
|
+
currentDefaultAltitude = altitude;
|
|
6064
|
+
quickEditOptions.climbHeight = altitude;
|
|
6065
|
+
try {
|
|
6066
|
+
entity.properties._defaultAltitude = altitude;
|
|
6067
|
+
} catch {
|
|
6068
|
+
}
|
|
6069
|
+
console.log("[updateDefaultAltitude] \u2705 \u9ED8\u8BA4\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", altitude, "\u7C73");
|
|
6070
|
+
},
|
|
6071
|
+
/**
|
|
6072
|
+
* 🆕 切换高度计算模式(异步,会重算所有航点高度)
|
|
6073
|
+
* @param newMode 新的高度模式
|
|
6074
|
+
* @param newDefaultAltitude 新的默认高度(可选)
|
|
6075
|
+
* @param options 选项(terrainProvider, onProgress)
|
|
6076
|
+
* @returns 切换结果 { success: boolean; error?: string }
|
|
6077
|
+
*/
|
|
6078
|
+
changeAltitudeMode: async (newMode, newDefaultAltitude, options2) => {
|
|
6079
|
+
try {
|
|
6080
|
+
const onProgress = options2?.onProgress;
|
|
6081
|
+
if (newMode === "relativeToGround") {
|
|
6082
|
+
const terrainProvider = options2?.terrainProvider ?? viewer.terrainProvider;
|
|
6083
|
+
const C_any = C;
|
|
6084
|
+
if (!terrainProvider || C_any.EllipsoidTerrainProvider && terrainProvider instanceof C_any.EllipsoidTerrainProvider) {
|
|
6085
|
+
console.error("[changeAltitudeMode] \u274C relativeToGround \u6A21\u5F0F\u9700\u8981\u6709\u6548\u7684 terrain \u56FE\u5C42");
|
|
6086
|
+
onProgress?.("error");
|
|
6087
|
+
return {
|
|
6088
|
+
success: false,
|
|
6089
|
+
error: "Terrain provider required for relativeToGround mode"
|
|
6090
|
+
};
|
|
6091
|
+
}
|
|
6092
|
+
}
|
|
6093
|
+
onProgress?.("loading");
|
|
6094
|
+
const oldMode = currentAltitudeMode;
|
|
6095
|
+
if (newDefaultAltitude !== void 0) {
|
|
6096
|
+
currentDefaultAltitude = newDefaultAltitude;
|
|
6097
|
+
quickEditOptions.climbHeight = newDefaultAltitude;
|
|
6098
|
+
}
|
|
6099
|
+
if (newMode === "relativeToGround" || oldMode === "relativeToGround") {
|
|
6100
|
+
const terrainHeights = await queryTerrainHeights(CesiumNS, viewer, positions);
|
|
6101
|
+
terrainHeights.forEach((height, index) => {
|
|
6102
|
+
terrainHeightsCache.set(index, height);
|
|
6103
|
+
});
|
|
6104
|
+
console.log("[changeAltitudeMode] \u5DF2\u67E5\u8BE2\u5730\u5F62\u9AD8\u5EA6:", terrainHeights);
|
|
6105
|
+
}
|
|
6106
|
+
if (newMode !== oldMode) {
|
|
6107
|
+
console.log("[changeAltitudeMode] \u5207\u6362\u9AD8\u5EA6\u6A21\u5F0F:", oldMode, "->", newMode);
|
|
6108
|
+
for (let i = 0; i < positions.length; i++) {
|
|
6109
|
+
const currentPos = positions[i];
|
|
6110
|
+
const carto = C.Cartographic.fromCartesian(currentPos);
|
|
6111
|
+
const currentAbsoluteHeight = carto.height ?? 0;
|
|
6112
|
+
const oldTerrainHeight = terrainHeightsCache.get(i) ?? 0;
|
|
6113
|
+
const relativeHeight = calculateRelativeHeight(
|
|
6114
|
+
oldMode,
|
|
6115
|
+
currentAbsoluteHeight,
|
|
6116
|
+
startPointAltitude,
|
|
6117
|
+
oldTerrainHeight
|
|
6118
|
+
);
|
|
6119
|
+
const newTerrainHeight = terrainHeightsCache.get(i) ?? 0;
|
|
6120
|
+
const newAbsoluteHeight = calculateAbsoluteHeight(
|
|
6121
|
+
newMode,
|
|
6122
|
+
relativeHeight,
|
|
6123
|
+
startPointAltitude,
|
|
6124
|
+
newTerrainHeight
|
|
6125
|
+
);
|
|
6126
|
+
const newPosition = C.Cartesian3.fromRadians(
|
|
6127
|
+
carto.longitude,
|
|
6128
|
+
carto.latitude,
|
|
6129
|
+
newAbsoluteHeight
|
|
6130
|
+
);
|
|
6131
|
+
positions[i] = newPosition;
|
|
6132
|
+
if (handles[i]) {
|
|
6133
|
+
try {
|
|
6134
|
+
handles[i].position = newPosition;
|
|
6135
|
+
} catch {
|
|
6136
|
+
}
|
|
6137
|
+
}
|
|
6138
|
+
try {
|
|
6139
|
+
vertexLabelManager.updateLabelPosition(i, newPosition);
|
|
6140
|
+
} catch {
|
|
6141
|
+
}
|
|
6142
|
+
try {
|
|
6143
|
+
createOrUpdateMarkerForIndex(i);
|
|
6144
|
+
} catch {
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
6147
|
+
currentAltitudeMode = newMode;
|
|
6148
|
+
quickEditOptions.altitudeMode = newMode;
|
|
6149
|
+
try {
|
|
6150
|
+
entity.properties._altitudeMode = newMode;
|
|
6151
|
+
entity.properties._defaultAltitude = currentDefaultAltitude;
|
|
6152
|
+
} catch {
|
|
6153
|
+
}
|
|
6154
|
+
entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
|
|
6155
|
+
}
|
|
6156
|
+
console.log("[changeAltitudeMode] \u2705 \u9AD8\u5EA6\u6A21\u5F0F\u5207\u6362\u5B8C\u6210:", {
|
|
6157
|
+
mode: newMode,
|
|
6158
|
+
defaultAltitude: currentDefaultAltitude
|
|
6159
|
+
});
|
|
6160
|
+
onProgress?.("done");
|
|
6161
|
+
return { success: true };
|
|
6162
|
+
} catch (error) {
|
|
6163
|
+
console.error("[changeAltitudeMode] Error:", error);
|
|
6164
|
+
options2?.onProgress?.("error");
|
|
6165
|
+
return { success: false, error: String(error) };
|
|
6166
|
+
}
|
|
5880
6167
|
}
|
|
5881
6168
|
};
|
|
5882
6169
|
}
|
|
@@ -5886,221 +6173,18 @@ function fovToFocalLength(fovDeg) {
|
|
|
5886
6173
|
return sensorWidth / (2 * Math.tan(fovRad / 2));
|
|
5887
6174
|
}
|
|
5888
6175
|
|
|
5889
|
-
// src/core/path-manager/ArrowShape.ts
|
|
5890
|
-
var ArrowShape = class {
|
|
5891
|
-
constructor(CesiumNS, opts = {}) {
|
|
5892
|
-
this.CesiumNS = CesiumNS;
|
|
5893
|
-
__publicField(this, "height");
|
|
5894
|
-
__publicField(this, "shaftHeight");
|
|
5895
|
-
__publicField(this, "headHeight");
|
|
5896
|
-
__publicField(this, "shaftRadius");
|
|
5897
|
-
__publicField(this, "headRadius");
|
|
5898
|
-
__publicField(this, "baseRadius");
|
|
5899
|
-
__publicField(this, "color");
|
|
5900
|
-
__publicField(this, "shaftAlpha");
|
|
5901
|
-
__publicField(this, "headAlpha");
|
|
5902
|
-
__publicField(this, "baseAlpha");
|
|
5903
|
-
__publicField(this, "outline");
|
|
5904
|
-
__publicField(this, "outlineColor");
|
|
5905
|
-
// 动态缩放相关
|
|
5906
|
-
__publicField(this, "dynamicScale");
|
|
5907
|
-
__publicField(this, "viewer");
|
|
5908
|
-
__publicField(this, "referenceDistance");
|
|
5909
|
-
__publicField(this, "minScale");
|
|
5910
|
-
__publicField(this, "maxScale");
|
|
5911
|
-
__publicField(this, "cachedScaleFactor", 1);
|
|
5912
|
-
const C = this.CesiumNS;
|
|
5913
|
-
this.shaftHeight = opts.shaftHeight ?? 17;
|
|
5914
|
-
this.headHeight = opts.headHeight ?? 8;
|
|
5915
|
-
this.height = opts.height ?? this.shaftHeight + this.headHeight;
|
|
5916
|
-
this.shaftRadius = opts.shaftRadius ?? 3;
|
|
5917
|
-
this.headRadius = opts.headRadius ?? 6;
|
|
5918
|
-
this.baseRadius = opts.baseRadius ?? 8;
|
|
5919
|
-
this.color = opts.color ? C.Color.fromCssColorString(opts.color) : C.Color.fromCssColorString("#FFD700");
|
|
5920
|
-
this.shaftAlpha = opts.shaftAlpha ?? 1;
|
|
5921
|
-
this.headAlpha = opts.headAlpha ?? 1;
|
|
5922
|
-
this.baseAlpha = opts.baseAlpha ?? 0.65;
|
|
5923
|
-
this.outline = opts.outline ?? false;
|
|
5924
|
-
this.outlineColor = opts.outlineColor ? C.Color.fromCssColorString(opts.outlineColor) : this.color.darken(0.3, new C.Color());
|
|
5925
|
-
this.dynamicScale = opts.dynamicScale ?? false;
|
|
5926
|
-
this.viewer = opts.viewer;
|
|
5927
|
-
this.referenceDistance = opts.referenceDistance ?? 500;
|
|
5928
|
-
this.minScale = opts.minScale ?? 0.3;
|
|
5929
|
-
this.maxScale = opts.maxScale ?? 3;
|
|
5930
|
-
}
|
|
5931
|
-
/**
|
|
5932
|
-
* Create arrow entities at given position
|
|
5933
|
-
* Returns array of 3 entities: [shaft, head, base]
|
|
5934
|
-
*
|
|
5935
|
-
* @param layer - Cesium CustomDataSource to add entities to
|
|
5936
|
-
* @param position - Ground position (Cartesian3)
|
|
5937
|
-
* @param baseHeight - Ground height in meters
|
|
5938
|
-
* @param properties - Additional properties for entities
|
|
5939
|
-
* @returns Array of created entities [shaft, head, base]
|
|
5940
|
-
*/
|
|
5941
|
-
createEntities(layer, position, baseHeight, properties) {
|
|
5942
|
-
const C = this.CesiumNS;
|
|
5943
|
-
const entities = [];
|
|
5944
|
-
const carto = C.Cartographic.fromCartesian(position);
|
|
5945
|
-
const lon = C.Math.toDegrees(carto.longitude);
|
|
5946
|
-
const lat = C.Math.toDegrees(carto.latitude);
|
|
5947
|
-
const computeScaleFactor = () => {
|
|
5948
|
-
if (!this.dynamicScale || !this.viewer) return 1;
|
|
5949
|
-
try {
|
|
5950
|
-
const cameraPos = this.viewer.camera.positionWC;
|
|
5951
|
-
const distance = C.Cartesian3.distance(cameraPos, position);
|
|
5952
|
-
const rawScale = distance / this.referenceDistance;
|
|
5953
|
-
return Math.max(this.minScale, Math.min(this.maxScale, rawScale));
|
|
5954
|
-
} catch {
|
|
5955
|
-
return 1;
|
|
5956
|
-
}
|
|
5957
|
-
};
|
|
5958
|
-
if (this.dynamicScale && this.viewer) {
|
|
5959
|
-
this.viewer.scene.preRender.addEventListener(() => {
|
|
5960
|
-
this.cachedScaleFactor = computeScaleFactor();
|
|
5961
|
-
});
|
|
5962
|
-
}
|
|
5963
|
-
const hpr = new C.HeadingPitchRoll(0, 0, 0);
|
|
5964
|
-
const baseOrientation = C.Transforms.headingPitchRollQuaternion(position, hpr);
|
|
5965
|
-
const fixedOrientation = new C.ConstantProperty(baseOrientation);
|
|
5966
|
-
const getShaftPosition = () => {
|
|
5967
|
-
const scale = this.cachedScaleFactor;
|
|
5968
|
-
return C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight * scale / 2);
|
|
5969
|
-
};
|
|
5970
|
-
const getHeadPosition = () => {
|
|
5971
|
-
const scale = this.cachedScaleFactor;
|
|
5972
|
-
return C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight * scale + this.headHeight * scale / 2);
|
|
5973
|
-
};
|
|
5974
|
-
const shaftEntity = layer.entities.add({
|
|
5975
|
-
position: this.dynamicScale ? new C.CallbackProperty(getShaftPosition, false) : new C.ConstantPositionProperty(C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight / 2)),
|
|
5976
|
-
orientation: fixedOrientation,
|
|
5977
|
-
cylinder: {
|
|
5978
|
-
length: this.dynamicScale ? new C.CallbackProperty(() => this.shaftHeight * this.cachedScaleFactor, false) : this.shaftHeight,
|
|
5979
|
-
topRadius: this.dynamicScale ? new C.CallbackProperty(() => this.shaftRadius * this.cachedScaleFactor, false) : this.shaftRadius,
|
|
5980
|
-
bottomRadius: this.dynamicScale ? new C.CallbackProperty(() => this.shaftRadius * this.cachedScaleFactor, false) : this.shaftRadius,
|
|
5981
|
-
material: this.color.withAlpha(this.shaftAlpha),
|
|
5982
|
-
outline: this.outline,
|
|
5983
|
-
outlineColor: this.outlineColor,
|
|
5984
|
-
outlineWidth: 2
|
|
5985
|
-
},
|
|
5986
|
-
properties: {
|
|
5987
|
-
...properties,
|
|
5988
|
-
_arrowPart: "shaft"
|
|
5989
|
-
}
|
|
5990
|
-
});
|
|
5991
|
-
entities.push(shaftEntity);
|
|
5992
|
-
const headEntity = layer.entities.add({
|
|
5993
|
-
position: this.dynamicScale ? new C.CallbackProperty(getHeadPosition, false) : new C.ConstantPositionProperty(C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight + this.headHeight / 2)),
|
|
5994
|
-
orientation: fixedOrientation,
|
|
5995
|
-
cylinder: {
|
|
5996
|
-
length: this.dynamicScale ? new C.CallbackProperty(() => this.headHeight * this.cachedScaleFactor, false) : this.headHeight,
|
|
5997
|
-
topRadius: 0,
|
|
5998
|
-
// Creates cone shape
|
|
5999
|
-
bottomRadius: this.dynamicScale ? new C.CallbackProperty(() => this.headRadius * this.cachedScaleFactor, false) : this.headRadius,
|
|
6000
|
-
material: this.color.withAlpha(this.headAlpha),
|
|
6001
|
-
outline: this.outline,
|
|
6002
|
-
outlineColor: this.outlineColor,
|
|
6003
|
-
outlineWidth: 2
|
|
6004
|
-
},
|
|
6005
|
-
properties: {
|
|
6006
|
-
...properties,
|
|
6007
|
-
_arrowPart: "head"
|
|
6008
|
-
}
|
|
6009
|
-
});
|
|
6010
|
-
entities.push(headEntity);
|
|
6011
|
-
const baseEntity = layer.entities.add({
|
|
6012
|
-
position,
|
|
6013
|
-
ellipse: {
|
|
6014
|
-
semiMajorAxis: this.dynamicScale ? new C.CallbackProperty(() => this.baseRadius * this.cachedScaleFactor, false) : this.baseRadius,
|
|
6015
|
-
semiMinorAxis: this.dynamicScale ? new C.CallbackProperty(() => this.baseRadius * this.cachedScaleFactor, false) : this.baseRadius,
|
|
6016
|
-
height: baseHeight,
|
|
6017
|
-
material: this.color.withAlpha(this.baseAlpha),
|
|
6018
|
-
outline: this.outline,
|
|
6019
|
-
outlineColor: this.outlineColor,
|
|
6020
|
-
outlineWidth: 2
|
|
6021
|
-
},
|
|
6022
|
-
properties: {
|
|
6023
|
-
...properties,
|
|
6024
|
-
_arrowPart: "base"
|
|
6025
|
-
}
|
|
6026
|
-
});
|
|
6027
|
-
entities.push(baseEntity);
|
|
6028
|
-
return entities;
|
|
6029
|
-
}
|
|
6030
|
-
/**
|
|
6031
|
-
* Get the color
|
|
6032
|
-
*/
|
|
6033
|
-
getColor() {
|
|
6034
|
-
return this.color;
|
|
6035
|
-
}
|
|
6036
|
-
/**
|
|
6037
|
-
* Update arrow color
|
|
6038
|
-
*/
|
|
6039
|
-
setColor(color) {
|
|
6040
|
-
const C = this.CesiumNS;
|
|
6041
|
-
this.color = C.Color.fromCssColorString(color);
|
|
6042
|
-
}
|
|
6043
|
-
/**
|
|
6044
|
-
* Update dimensions
|
|
6045
|
-
*/
|
|
6046
|
-
setDimensions(opts) {
|
|
6047
|
-
if (opts.shaftHeight !== void 0) this.shaftHeight = opts.shaftHeight;
|
|
6048
|
-
if (opts.headHeight !== void 0) this.headHeight = opts.headHeight;
|
|
6049
|
-
if (opts.shaftRadius !== void 0) this.shaftRadius = opts.shaftRadius;
|
|
6050
|
-
if (opts.headRadius !== void 0) this.headRadius = opts.headRadius;
|
|
6051
|
-
if (opts.baseRadius !== void 0) this.baseRadius = opts.baseRadius;
|
|
6052
|
-
this.height = this.shaftHeight + this.headHeight;
|
|
6053
|
-
}
|
|
6054
|
-
/**
|
|
6055
|
-
* Update transparency
|
|
6056
|
-
*/
|
|
6057
|
-
setAlpha(opts) {
|
|
6058
|
-
if (opts.shaftAlpha !== void 0) this.shaftAlpha = opts.shaftAlpha;
|
|
6059
|
-
if (opts.headAlpha !== void 0) this.headAlpha = opts.headAlpha;
|
|
6060
|
-
if (opts.baseAlpha !== void 0) this.baseAlpha = opts.baseAlpha;
|
|
6061
|
-
}
|
|
6062
|
-
/**
|
|
6063
|
-
* Get current dimensions
|
|
6064
|
-
*/
|
|
6065
|
-
getDimensions() {
|
|
6066
|
-
return {
|
|
6067
|
-
height: this.height,
|
|
6068
|
-
shaftHeight: this.shaftHeight,
|
|
6069
|
-
headHeight: this.headHeight,
|
|
6070
|
-
shaftRadius: this.shaftRadius,
|
|
6071
|
-
headRadius: this.headRadius,
|
|
6072
|
-
baseRadius: this.baseRadius
|
|
6073
|
-
};
|
|
6074
|
-
}
|
|
6075
|
-
/**
|
|
6076
|
-
* Get current alpha values
|
|
6077
|
-
*/
|
|
6078
|
-
getAlpha() {
|
|
6079
|
-
return {
|
|
6080
|
-
shaftAlpha: this.shaftAlpha,
|
|
6081
|
-
headAlpha: this.headAlpha,
|
|
6082
|
-
baseAlpha: this.baseAlpha
|
|
6083
|
-
};
|
|
6084
|
-
}
|
|
6085
|
-
/**
|
|
6086
|
-
* Get total height
|
|
6087
|
-
*/
|
|
6088
|
-
getHeight() {
|
|
6089
|
-
return this.height;
|
|
6090
|
-
}
|
|
6091
|
-
};
|
|
6092
|
-
|
|
6093
6176
|
// src/core/path-manager/startPathDrawing.ts
|
|
6094
6177
|
function startPathDrawing(CesiumNS, viewer, options, onComplete) {
|
|
6095
6178
|
const C = CesiumNS;
|
|
6096
6179
|
const layer = options?.layer ?? new C.CustomDataSource("Paths");
|
|
6097
6180
|
if (!options?.layer) viewer.dataSources.add(layer);
|
|
6098
6181
|
const altitudeMode = options?.altitudeMode ?? "absolute";
|
|
6099
|
-
const climbHeight = Number(options?.climbHeight) ||
|
|
6100
|
-
const
|
|
6101
|
-
|
|
6102
|
-
let hasStart = false;
|
|
6182
|
+
const climbHeight = Number(options?.climbHeight) || 0;
|
|
6183
|
+
const defaultAltitude = options?.defaultAltitude ?? options?.defaultHeight ?? 100;
|
|
6184
|
+
const DEFAULT_MAIN_WIDTH = options?.width ?? 3;
|
|
6103
6185
|
let createdEntity = void 0;
|
|
6186
|
+
let entityCreated = false;
|
|
6187
|
+
let editSession = void 0;
|
|
6104
6188
|
const getPositionFromMouse = (movement) => {
|
|
6105
6189
|
const scene = viewer.scene;
|
|
6106
6190
|
const winPos = movement?.position ?? movement?.endPosition ?? movement;
|
|
@@ -6116,129 +6200,54 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
|
|
|
6116
6200
|
}
|
|
6117
6201
|
return cart;
|
|
6118
6202
|
};
|
|
6119
|
-
const toCartographic = (cart) => {
|
|
6120
|
-
try {
|
|
6121
|
-
return C.Cartographic.fromCartesian(cart);
|
|
6122
|
-
} catch {
|
|
6123
|
-
return void 0;
|
|
6124
|
-
}
|
|
6125
|
-
};
|
|
6126
6203
|
let handler;
|
|
6127
|
-
const positions = [];
|
|
6128
|
-
const tempHandles = [];
|
|
6129
6204
|
handler = new C.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
6130
6205
|
handler.setInputAction((movement) => {
|
|
6131
|
-
if (hasStart) return;
|
|
6132
6206
|
const picked = getPositionFromMouse(movement);
|
|
6133
6207
|
if (!picked) return;
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
const groundPos = C.Cartesian3.fromDegrees(
|
|
6138
|
-
C.Math.toDegrees(carto.longitude),
|
|
6139
|
-
C.Math.toDegrees(carto.latitude),
|
|
6140
|
-
startCartographic.height
|
|
6141
|
-
);
|
|
6142
|
-
positions.push(groundPos);
|
|
6143
|
-
const arrowCarto = toCartographic(groundPos);
|
|
6144
|
-
const baseHeight = arrowCarto ? arrowCarto.height : 0;
|
|
6145
|
-
const arrowShape = new ArrowShape(CesiumNS, {
|
|
6146
|
-
shaftHeight: 12,
|
|
6147
|
-
headHeight: 12,
|
|
6148
|
-
shaftRadius: 4,
|
|
6149
|
-
headRadius: 8,
|
|
6150
|
-
baseRadius: 12,
|
|
6151
|
-
color: "#FFD700",
|
|
6152
|
-
shaftAlpha: 1,
|
|
6153
|
-
headAlpha: 1,
|
|
6154
|
-
baseAlpha: 0.5,
|
|
6155
|
-
// 启用动态缩放,和无人机模型一样根据相机距离调整大小
|
|
6156
|
-
dynamicScale: true,
|
|
6157
|
-
viewer,
|
|
6158
|
-
referenceDistance: 300,
|
|
6159
|
-
minScale: 0.3,
|
|
6160
|
-
maxScale: 2
|
|
6161
|
-
});
|
|
6162
|
-
const arrowEntities = arrowShape.createEntities(
|
|
6163
|
-
layer,
|
|
6164
|
-
groundPos,
|
|
6165
|
-
baseHeight,
|
|
6166
|
-
{ _type: "path-vertex", _vertexIndex: 0, _isStart: true }
|
|
6167
|
-
);
|
|
6168
|
-
tempHandles.push(...arrowEntities);
|
|
6169
|
-
hasStart = true;
|
|
6170
|
-
if (climbHeight > 0) {
|
|
6171
|
-
const climbPos = C.Cartesian3.fromDegrees(
|
|
6172
|
-
C.Math.toDegrees(startCartographic.longitude),
|
|
6173
|
-
C.Math.toDegrees(startCartographic.latitude),
|
|
6174
|
-
startCartographic.height + climbHeight
|
|
6175
|
-
);
|
|
6176
|
-
positions.push(climbPos);
|
|
6177
|
-
}
|
|
6178
|
-
let created;
|
|
6179
|
-
try {
|
|
6180
|
-
const id = `${options?.idPrefix ?? "path"}-${Date.now().toString(36)}`;
|
|
6181
|
-
const pathPositions = new C.CallbackProperty(() => {
|
|
6182
|
-
const p = created?.polyline?.positions;
|
|
6183
|
-
if (p && typeof p.getValue === "function") {
|
|
6184
|
-
try {
|
|
6185
|
-
return p.getValue();
|
|
6186
|
-
} catch {
|
|
6187
|
-
}
|
|
6188
|
-
}
|
|
6189
|
-
return positions.slice();
|
|
6190
|
-
}, false);
|
|
6191
|
-
created = layer.entities.add({
|
|
6192
|
-
id,
|
|
6193
|
-
name: "Path",
|
|
6194
|
-
polyline: {
|
|
6195
|
-
positions: pathPositions,
|
|
6196
|
-
width: DEFAULT_MAIN_WIDTH,
|
|
6197
|
-
material: new C.PolylineOutlineMaterialProperty({
|
|
6198
|
-
color: C.Color.LIME,
|
|
6199
|
-
outlineColor: C.Color.WHITE,
|
|
6200
|
-
outlineWidth: 2
|
|
6201
|
-
}),
|
|
6202
|
-
clampToGround: false
|
|
6203
|
-
},
|
|
6204
|
-
properties: {
|
|
6205
|
-
_altitudeMode: altitudeMode,
|
|
6206
|
-
_climbHeight: climbHeight,
|
|
6207
|
-
_hasHiddenClimb: climbHeight > 0
|
|
6208
|
-
}
|
|
6209
|
-
});
|
|
6210
|
-
createdEntity = created;
|
|
6208
|
+
if (!entityCreated) {
|
|
6209
|
+
entityCreated = true;
|
|
6210
|
+
let created;
|
|
6211
6211
|
try {
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6212
|
+
const id = `${options?.idPrefix ?? "path"}-${Date.now().toString(36)}`;
|
|
6213
|
+
const positions = [];
|
|
6214
|
+
const pathPositions = new C.CallbackProperty(() => positions.slice(), false);
|
|
6215
|
+
created = layer.entities.add({
|
|
6216
|
+
id,
|
|
6217
|
+
name: "Path",
|
|
6218
|
+
polyline: {
|
|
6219
|
+
positions: pathPositions,
|
|
6220
|
+
width: DEFAULT_MAIN_WIDTH,
|
|
6221
|
+
material: C.Color.fromCssColorString("#00E676"),
|
|
6222
|
+
clampToGround: false
|
|
6223
|
+
},
|
|
6224
|
+
properties: {
|
|
6225
|
+
_altitudeMode: altitudeMode,
|
|
6226
|
+
_defaultAltitude: defaultAltitude,
|
|
6227
|
+
_climbHeight: climbHeight,
|
|
6228
|
+
_useGlobalHeightFlags: []
|
|
6229
|
+
// 🆕 空数组,航点由编辑模式添加
|
|
6222
6230
|
}
|
|
6223
6231
|
});
|
|
6224
|
-
|
|
6225
|
-
}
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
handler = void 0;
|
|
6232
|
-
}
|
|
6233
|
-
if (created) {
|
|
6234
|
-
try {
|
|
6235
|
-
onComplete?.(created);
|
|
6236
|
-
} catch {
|
|
6232
|
+
createdEntity = created;
|
|
6233
|
+
} finally {
|
|
6234
|
+
try {
|
|
6235
|
+
handler?.destroy();
|
|
6236
|
+
} catch {
|
|
6237
|
+
}
|
|
6238
|
+
handler = void 0;
|
|
6237
6239
|
}
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6240
|
+
if (created) {
|
|
6241
|
+
try {
|
|
6242
|
+
onComplete?.(created);
|
|
6243
|
+
} catch {
|
|
6244
|
+
}
|
|
6245
|
+
try {
|
|
6246
|
+
const auto = options?.autoStartEditing;
|
|
6247
|
+
const editOptions = {
|
|
6248
|
+
// 🔧 默认使用自由编辑模式(快速编辑和自由编辑互斥)
|
|
6249
|
+
quickEdit: false
|
|
6250
|
+
};
|
|
6242
6251
|
if (typeof auto === "object" && auto.preview) {
|
|
6243
6252
|
editOptions.preview = auto.preview;
|
|
6244
6253
|
} else {
|
|
@@ -6260,30 +6269,35 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
|
|
|
6260
6269
|
if (autoOpts.onVertexDeleteDetail) {
|
|
6261
6270
|
editOptions.onVertexDeleteDetail = autoOpts.onVertexDeleteDetail;
|
|
6262
6271
|
}
|
|
6263
|
-
|
|
6272
|
+
editOptions.altitudeMode = altitudeMode;
|
|
6273
|
+
editOptions.defaultAltitude = defaultAltitude;
|
|
6274
|
+
editOptions.climbHeight = climbHeight;
|
|
6275
|
+
editSession = startPathEditing(CesiumNS, viewer, created, editOptions);
|
|
6276
|
+
console.log("[startPathDrawing] \u7F16\u8F91\u6A21\u5F0F\u5DF2\u542F\u52A8\uFF0C\u81EA\u7531\u7F16\u8F91\u6A21\u5F0F\uFF0C\u4F7F\u7528\u98DE\u673A\u6E38\u6807\u6DFB\u52A0\u822A\u70B9");
|
|
6264
6277
|
if (editSession && options?.onEditingStarted) {
|
|
6265
6278
|
try {
|
|
6266
6279
|
options.onEditingStarted(editSession);
|
|
6267
6280
|
} catch {
|
|
6268
6281
|
}
|
|
6269
6282
|
}
|
|
6283
|
+
} catch (error) {
|
|
6284
|
+
console.error("[startPathDrawing] \u8FDB\u5165\u7F16\u8F91\u6A21\u5F0F\u5931\u8D25:", error);
|
|
6270
6285
|
}
|
|
6271
|
-
} catch {
|
|
6272
6286
|
}
|
|
6273
6287
|
}
|
|
6274
6288
|
}, C.ScreenSpaceEventType.LEFT_CLICK);
|
|
6275
6289
|
return {
|
|
6276
6290
|
stop: () => {
|
|
6277
|
-
for (const h of tempHandles) {
|
|
6278
|
-
try {
|
|
6279
|
-
layer.entities.remove(h);
|
|
6280
|
-
} catch {
|
|
6281
|
-
}
|
|
6282
|
-
}
|
|
6283
6291
|
try {
|
|
6284
6292
|
handler?.destroy();
|
|
6285
6293
|
} catch {
|
|
6286
6294
|
}
|
|
6295
|
+
if (editSession) {
|
|
6296
|
+
try {
|
|
6297
|
+
editSession.stop();
|
|
6298
|
+
} catch {
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6287
6301
|
if (createdEntity) {
|
|
6288
6302
|
try {
|
|
6289
6303
|
layer.entities.remove(createdEntity);
|
|
@@ -6342,102 +6356,31 @@ function parsePoseFromAction(action) {
|
|
|
6342
6356
|
result.roll = parsed.roll;
|
|
6343
6357
|
}
|
|
6344
6358
|
if (result.fov === void 0 && typeof parsed.fov === "number") {
|
|
6345
|
-
result.fov = parsed.fov;
|
|
6346
|
-
}
|
|
6347
|
-
return result;
|
|
6348
|
-
} catch (error) {
|
|
6349
|
-
const numbers = action.match(/-?\d+\.?\d*/g);
|
|
6350
|
-
if (numbers && numbers.length >= 4) {
|
|
6351
|
-
return {
|
|
6352
|
-
heading: parseFloat(numbers[0]),
|
|
6353
|
-
pitch: parseFloat(numbers[1]),
|
|
6354
|
-
roll: parseFloat(numbers[2]),
|
|
6355
|
-
fov: parseFloat(numbers[3])
|
|
6356
|
-
};
|
|
6357
|
-
}
|
|
6358
|
-
return {};
|
|
6359
|
-
}
|
|
6360
|
-
}
|
|
6361
|
-
function parseCoordinate(value) {
|
|
6362
|
-
if (typeof value === "number") {
|
|
6363
|
-
return value;
|
|
6364
|
-
}
|
|
6365
|
-
if (typeof value === "string") {
|
|
6366
|
-
const parsed = parseFloat(value);
|
|
6367
|
-
return isNaN(parsed) ? 0 : parsed;
|
|
6368
|
-
}
|
|
6369
|
-
return 0;
|
|
6370
|
-
}
|
|
6371
|
-
function parseTakeOffRefPoint(takeOffRefPoint, takeOffSecurityHeight, CesiumNS) {
|
|
6372
|
-
if (!takeOffRefPoint || typeof takeOffRefPoint !== "string" || takeOffRefPoint.trim() === "") {
|
|
6373
|
-
return null;
|
|
6374
|
-
}
|
|
6375
|
-
const C = CesiumNS;
|
|
6376
|
-
let longitude;
|
|
6377
|
-
let latitude;
|
|
6378
|
-
let height;
|
|
6379
|
-
const trimmed = takeOffRefPoint.trim();
|
|
6380
|
-
if (trimmed.includes(",")) {
|
|
6381
|
-
try {
|
|
6382
|
-
const parts = trimmed.split(",").map((p) => p.trim());
|
|
6383
|
-
if (parts.length >= 2) {
|
|
6384
|
-
latitude = parseFloat(parts[0]);
|
|
6385
|
-
longitude = parseFloat(parts[1]);
|
|
6386
|
-
height = parts.length >= 3 ? parseFloat(parts[2]) : takeOffSecurityHeight;
|
|
6387
|
-
if (isNaN(latitude) || isNaN(longitude) || isNaN(height)) {
|
|
6388
|
-
throw new Error("\u65E0\u6CD5\u89E3\u6790\u9017\u53F7\u5206\u9694\u7684\u5750\u6807\u503C");
|
|
6389
|
-
}
|
|
6390
|
-
const startPosition = C.Cartesian3.fromDegrees(longitude, latitude, height);
|
|
6391
|
-
const climbPosition = C.Cartesian3.fromDegrees(
|
|
6392
|
-
longitude,
|
|
6393
|
-
latitude,
|
|
6394
|
-
height + takeOffSecurityHeight
|
|
6395
|
-
);
|
|
6396
|
-
return {
|
|
6397
|
-
startPosition,
|
|
6398
|
-
climbPosition
|
|
6399
|
-
};
|
|
6400
|
-
}
|
|
6401
|
-
} catch (error) {
|
|
6402
|
-
}
|
|
6403
|
-
}
|
|
6404
|
-
try {
|
|
6405
|
-
const parsed = JSON.parse(takeOffRefPoint);
|
|
6406
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
6407
|
-
return null;
|
|
6408
|
-
}
|
|
6409
|
-
if (typeof parsed.longitude === "number") {
|
|
6410
|
-
longitude = parsed.longitude;
|
|
6411
|
-
} else if (typeof parsed.lon === "number") {
|
|
6412
|
-
longitude = parsed.lon;
|
|
6413
|
-
} else {
|
|
6414
|
-
return null;
|
|
6415
|
-
}
|
|
6416
|
-
if (typeof parsed.latitude === "number") {
|
|
6417
|
-
latitude = parsed.latitude;
|
|
6418
|
-
} else if (typeof parsed.lat === "number") {
|
|
6419
|
-
latitude = parsed.lat;
|
|
6420
|
-
} else {
|
|
6421
|
-
return null;
|
|
6422
|
-
}
|
|
6423
|
-
if (typeof parsed.height === "number") {
|
|
6424
|
-
height = parsed.height;
|
|
6425
|
-
} else {
|
|
6426
|
-
height = takeOffSecurityHeight;
|
|
6427
|
-
}
|
|
6428
|
-
const startPosition = C.Cartesian3.fromDegrees(longitude, latitude, height);
|
|
6429
|
-
const climbPosition = C.Cartesian3.fromDegrees(
|
|
6430
|
-
longitude,
|
|
6431
|
-
latitude,
|
|
6432
|
-
height + takeOffSecurityHeight
|
|
6433
|
-
);
|
|
6434
|
-
return {
|
|
6435
|
-
startPosition,
|
|
6436
|
-
climbPosition
|
|
6437
|
-
};
|
|
6359
|
+
result.fov = parsed.fov;
|
|
6360
|
+
}
|
|
6361
|
+
return result;
|
|
6438
6362
|
} catch (error) {
|
|
6439
|
-
|
|
6363
|
+
const numbers = action.match(/-?\d+\.?\d*/g);
|
|
6364
|
+
if (numbers && numbers.length >= 4) {
|
|
6365
|
+
return {
|
|
6366
|
+
heading: parseFloat(numbers[0]),
|
|
6367
|
+
pitch: parseFloat(numbers[1]),
|
|
6368
|
+
roll: parseFloat(numbers[2]),
|
|
6369
|
+
fov: parseFloat(numbers[3])
|
|
6370
|
+
};
|
|
6371
|
+
}
|
|
6372
|
+
return {};
|
|
6373
|
+
}
|
|
6374
|
+
}
|
|
6375
|
+
function parseCoordinate(value) {
|
|
6376
|
+
if (typeof value === "number") {
|
|
6377
|
+
return value;
|
|
6378
|
+
}
|
|
6379
|
+
if (typeof value === "string") {
|
|
6380
|
+
const parsed = parseFloat(value);
|
|
6381
|
+
return isNaN(parsed) ? 0 : parsed;
|
|
6440
6382
|
}
|
|
6383
|
+
return 0;
|
|
6441
6384
|
}
|
|
6442
6385
|
function convertSinoflyWayline(data, options) {
|
|
6443
6386
|
const {
|
|
@@ -6461,11 +6404,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
6461
6404
|
if (data.waylineId === void 0 || data.waylineId === null) {
|
|
6462
6405
|
throw new Error("[sinoflyAdapter] waylineId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
6463
6406
|
}
|
|
6464
|
-
const takeOffInfo = parseTakeOffRefPoint(
|
|
6465
|
-
data.takeOffRefPoint,
|
|
6466
|
-
data.takeOffSecurityHeight,
|
|
6467
|
-
CesiumNS
|
|
6468
|
-
);
|
|
6469
6407
|
let waypoints = data.waypointInfo;
|
|
6470
6408
|
if (filterWaypoint) {
|
|
6471
6409
|
waypoints = waypoints.filter(filterWaypoint);
|
|
@@ -6473,31 +6411,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
6473
6411
|
if (sortByIndex) {
|
|
6474
6412
|
waypoints = [...waypoints].sort((a, b) => a.index - b.index);
|
|
6475
6413
|
}
|
|
6476
|
-
const finalWaypointData = [];
|
|
6477
|
-
if (takeOffInfo) {
|
|
6478
|
-
finalWaypointData.push({
|
|
6479
|
-
position: takeOffInfo.startPosition,
|
|
6480
|
-
heading: defaultHeading,
|
|
6481
|
-
pitch: defaultPitch,
|
|
6482
|
-
roll: defaultRoll,
|
|
6483
|
-
fov: defaultFov,
|
|
6484
|
-
index: 0
|
|
6485
|
-
});
|
|
6486
|
-
finalWaypointData.push({
|
|
6487
|
-
position: takeOffInfo.climbPosition,
|
|
6488
|
-
heading: defaultHeading,
|
|
6489
|
-
pitch: defaultPitch,
|
|
6490
|
-
roll: defaultRoll,
|
|
6491
|
-
fov: defaultFov,
|
|
6492
|
-
index: 1
|
|
6493
|
-
});
|
|
6494
|
-
}
|
|
6495
|
-
let waypointStartIndex;
|
|
6496
|
-
if (takeOffInfo) {
|
|
6497
|
-
waypointStartIndex = 2;
|
|
6498
|
-
} else {
|
|
6499
|
-
waypointStartIndex = 0;
|
|
6500
|
-
}
|
|
6501
6414
|
const convertedWaypoints = waypoints.map((wp, idx) => {
|
|
6502
6415
|
try {
|
|
6503
6416
|
if (!wp) {
|
|
@@ -6533,15 +6446,16 @@ function convertSinoflyWayline(data, options) {
|
|
|
6533
6446
|
pitch,
|
|
6534
6447
|
roll,
|
|
6535
6448
|
fov,
|
|
6536
|
-
index:
|
|
6537
|
-
//
|
|
6449
|
+
index: idx,
|
|
6450
|
+
// 从 0 开始分配 index
|
|
6451
|
+
useGlobalHeight: false
|
|
6452
|
+
// 🆕 从服务端加载的航点默认使用实际高度
|
|
6538
6453
|
};
|
|
6539
6454
|
} catch (error) {
|
|
6540
6455
|
throw new Error(`\u822A\u70B9 ${idx} \u8F6C\u6362\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
6541
6456
|
}
|
|
6542
6457
|
});
|
|
6543
|
-
|
|
6544
|
-
if (!Array.isArray(waypointData)) {
|
|
6458
|
+
if (!Array.isArray(convertedWaypoints)) {
|
|
6545
6459
|
throw new Error("[sinoflyAdapter] waypointData \u4E0D\u662F\u6570\u7EC4");
|
|
6546
6460
|
}
|
|
6547
6461
|
const metadata = {
|
|
@@ -6552,8 +6466,8 @@ function convertSinoflyWayline(data, options) {
|
|
|
6552
6466
|
autoFlightSpeed: data.autoFlightSpeed,
|
|
6553
6467
|
distance: data.distance,
|
|
6554
6468
|
duration: data.duration,
|
|
6555
|
-
|
|
6556
|
-
|
|
6469
|
+
climbHeight: data.takeOffSecurityHeight
|
|
6470
|
+
// 使用 climbHeight 作为字段名
|
|
6557
6471
|
};
|
|
6558
6472
|
if (data.stationId !== void 0) metadata.stationId = data.stationId;
|
|
6559
6473
|
if (data.subarrayId !== void 0) metadata.subarrayId = data.subarrayId;
|
|
@@ -6563,7 +6477,7 @@ function convertSinoflyWayline(data, options) {
|
|
|
6563
6477
|
id: `wayline-${data.waylineId}`,
|
|
6564
6478
|
name: data.waylineName || `\u822A\u7EBF-${data.waylineId}`,
|
|
6565
6479
|
description: `\u822A\u7EBFID: ${data.waylineId}, \u7C7B\u578B: ${data.waylineType}, \u822A\u70B9\u6570: ${data.waypointNumber}`,
|
|
6566
|
-
waypointData,
|
|
6480
|
+
waypointData: convertedWaypoints,
|
|
6567
6481
|
metadata
|
|
6568
6482
|
};
|
|
6569
6483
|
}
|
|
@@ -6594,7 +6508,6 @@ function renderFlightPath(CesiumNS, viewer, options) {
|
|
|
6594
6508
|
let entityId;
|
|
6595
6509
|
let entityName;
|
|
6596
6510
|
let entityDescription;
|
|
6597
|
-
let hasHiddenClimb;
|
|
6598
6511
|
let altitudeMode;
|
|
6599
6512
|
let climbHeight;
|
|
6600
6513
|
try {
|
|
@@ -6610,12 +6523,8 @@ function renderFlightPath(CesiumNS, viewer, options) {
|
|
|
6610
6523
|
entityId = options.id ?? converted.id ?? `wayline-${sinoflyData.waylineId}`;
|
|
6611
6524
|
entityName = options.name ?? converted.name;
|
|
6612
6525
|
entityDescription = options.description ?? converted.description;
|
|
6613
|
-
const sortedWaypoints2 = [...waypointData].sort((a, b) => a.index - b.index);
|
|
6614
|
-
const hasIndex1 = sortedWaypoints2.some((wp) => wp.index === 1);
|
|
6615
|
-
const hasTakeOffRefPoint = converted.metadata?.hasTakeOffRefPoint ?? !!sinoflyData.takeOffRefPoint;
|
|
6616
|
-
hasHiddenClimb = options.hasHiddenClimb ?? (hasTakeOffRefPoint && hasIndex1);
|
|
6617
6526
|
altitudeMode = options.altitudeMode ?? converted.metadata?.altitudeMode;
|
|
6618
|
-
climbHeight = options.climbHeight ?? converted.metadata?.climbHeight
|
|
6527
|
+
climbHeight = options.climbHeight ?? converted.metadata?.climbHeight;
|
|
6619
6528
|
} catch (error) {
|
|
6620
6529
|
console.error("[renderFlightPath] Sinofly \u6570\u636E\u8F6C\u6362\u5931\u8D25:", error);
|
|
6621
6530
|
throw new Error(`Sinofly \u6570\u636E\u8F6C\u6362\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -6637,66 +6546,25 @@ function renderFlightPath(CesiumNS, viewer, options) {
|
|
|
6637
6546
|
layer = new C.CustomDataSource(`flight-path-datasource-${Date.now()}`);
|
|
6638
6547
|
viewer.dataSources.add(layer);
|
|
6639
6548
|
}
|
|
6640
|
-
const hiddenClimbIndex =
|
|
6641
|
-
const
|
|
6549
|
+
const hiddenClimbIndex = void 0;
|
|
6550
|
+
const useGlobalHeightFlags = sortedWaypoints.map((wp) => wp.useGlobalHeight ?? false);
|
|
6642
6551
|
const entity = layer.entities.add({
|
|
6643
6552
|
id: entityId,
|
|
6644
6553
|
name: entityName,
|
|
6645
6554
|
description: entityDescription,
|
|
6646
6555
|
polyline: {
|
|
6647
6556
|
positions: positions.slice(),
|
|
6648
|
-
width: options.style?.width ??
|
|
6649
|
-
material: options.style?.material ?? options.style?.color ??
|
|
6650
|
-
color: C.Color.GREEN,
|
|
6651
|
-
outlineColor: C.Color.WHITE,
|
|
6652
|
-
outlineWidth: 3
|
|
6653
|
-
}),
|
|
6557
|
+
width: options.style?.width ?? 3,
|
|
6558
|
+
material: options.style?.material ?? options.style?.color ?? C.Color.fromCssColorString("#00E676"),
|
|
6654
6559
|
clampToGround: false
|
|
6655
6560
|
},
|
|
6656
6561
|
properties: {
|
|
6657
6562
|
_altitudeMode: altitudeMode,
|
|
6658
6563
|
_climbHeight: climbHeight,
|
|
6659
|
-
|
|
6564
|
+
_useGlobalHeightFlags: useGlobalHeightFlags
|
|
6565
|
+
// 🆕 保存 useGlobalHeightFlags
|
|
6660
6566
|
}
|
|
6661
6567
|
});
|
|
6662
|
-
const shouldShowArrow = hasStartPoint && hasHiddenClimb;
|
|
6663
|
-
if (shouldShowArrow) {
|
|
6664
|
-
try {
|
|
6665
|
-
const startPosition = positions[0];
|
|
6666
|
-
const carto = C.Cartographic.fromCartesian(startPosition);
|
|
6667
|
-
const baseHeight = carto ? carto.height : 0;
|
|
6668
|
-
const arrowShape = new ArrowShape(CesiumNS, {
|
|
6669
|
-
shaftHeight: 12,
|
|
6670
|
-
headHeight: 12,
|
|
6671
|
-
shaftRadius: 4,
|
|
6672
|
-
headRadius: 8,
|
|
6673
|
-
baseRadius: 12,
|
|
6674
|
-
color: "#FFD700",
|
|
6675
|
-
shaftAlpha: 0.98,
|
|
6676
|
-
headAlpha: 0.98,
|
|
6677
|
-
baseAlpha: 0.65,
|
|
6678
|
-
// 启用动态缩放
|
|
6679
|
-
dynamicScale: true,
|
|
6680
|
-
viewer,
|
|
6681
|
-
referenceDistance: 300,
|
|
6682
|
-
minScale: 0.3,
|
|
6683
|
-
maxScale: 2
|
|
6684
|
-
});
|
|
6685
|
-
arrowShape.createEntities(
|
|
6686
|
-
layer,
|
|
6687
|
-
startPosition,
|
|
6688
|
-
baseHeight,
|
|
6689
|
-
{
|
|
6690
|
-
_type: "path-vertex",
|
|
6691
|
-
_ownerId: entityId,
|
|
6692
|
-
_vertexIndex: 0,
|
|
6693
|
-
_isStart: true
|
|
6694
|
-
}
|
|
6695
|
-
);
|
|
6696
|
-
} catch (error) {
|
|
6697
|
-
console.error("Failed to create start arrow:", error);
|
|
6698
|
-
}
|
|
6699
|
-
}
|
|
6700
6568
|
try {
|
|
6701
6569
|
const vertexLabelManager = new VertexLabelManager(
|
|
6702
6570
|
CesiumNS,
|
|
@@ -6737,8 +6605,6 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6737
6605
|
} catch (e) {
|
|
6738
6606
|
console.warn("[renderFlightPathPreview] \u65E0\u6CD5\u83B7\u53D6\u822A\u70B9\u6570\u636E:", e);
|
|
6739
6607
|
}
|
|
6740
|
-
const hasHiddenClimb = entity.properties?._hasHiddenClimb?.getValue?.() ?? false;
|
|
6741
|
-
const hiddenClimbIndex = hasHiddenClimb ? 1 : void 0;
|
|
6742
6608
|
const updateWaypointHighlight = (newIndex) => {
|
|
6743
6609
|
if (!vertexLabelManager || positions.length === 0) return;
|
|
6744
6610
|
const editedIndices = /* @__PURE__ */ new Set();
|
|
@@ -6758,14 +6624,7 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6758
6624
|
const ownerId = properties._ownerId?.getValue?.(C.JulianDate.now());
|
|
6759
6625
|
const vertexIndex = properties._vertexIndex?.getValue?.(C.JulianDate.now());
|
|
6760
6626
|
if (type === "vertex-label" && ownerId === entity.id && vertexIndex !== void 0) {
|
|
6761
|
-
|
|
6762
|
-
if (hiddenClimbIndex === 1) {
|
|
6763
|
-
if (vertexIndex >= 2) {
|
|
6764
|
-
displayIndex = vertexIndex - 2;
|
|
6765
|
-
}
|
|
6766
|
-
} else {
|
|
6767
|
-
displayIndex = vertexIndex;
|
|
6768
|
-
}
|
|
6627
|
+
const displayIndex = vertexIndex;
|
|
6769
6628
|
selectedWaypointIndex = vertexIndex;
|
|
6770
6629
|
updateWaypointHighlight(selectedWaypointIndex);
|
|
6771
6630
|
if (options.onWaypointClick) {
|
|
@@ -6783,18 +6642,10 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6783
6642
|
updateWaypointHighlight(null);
|
|
6784
6643
|
return;
|
|
6785
6644
|
}
|
|
6786
|
-
|
|
6787
|
-
if (hiddenClimbIndex === 1) {
|
|
6788
|
-
actualIndex = index + 2;
|
|
6789
|
-
}
|
|
6790
|
-
selectedWaypointIndex = actualIndex;
|
|
6645
|
+
selectedWaypointIndex = index;
|
|
6791
6646
|
updateWaypointHighlight(selectedWaypointIndex);
|
|
6792
6647
|
},
|
|
6793
6648
|
getSelectedWaypoint: () => {
|
|
6794
|
-
if (selectedWaypointIndex === null) return null;
|
|
6795
|
-
if (hiddenClimbIndex === 1) {
|
|
6796
|
-
return selectedWaypointIndex >= 2 ? selectedWaypointIndex - 2 : null;
|
|
6797
|
-
}
|
|
6798
6649
|
return selectedWaypointIndex;
|
|
6799
6650
|
},
|
|
6800
6651
|
destroy: () => {
|
|
@@ -6804,6 +6655,299 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6804
6655
|
return { entity, controller };
|
|
6805
6656
|
}
|
|
6806
6657
|
|
|
6658
|
+
// src/core/path-manager/FlightSimulator.ts
|
|
6659
|
+
var FlightSimulator = class {
|
|
6660
|
+
constructor(CesiumNS, viewer, options) {
|
|
6661
|
+
__publicField(this, "CesiumNS");
|
|
6662
|
+
__publicField(this, "viewer");
|
|
6663
|
+
__publicField(this, "options");
|
|
6664
|
+
__publicField(this, "state", "idle");
|
|
6665
|
+
__publicField(this, "progress", 0);
|
|
6666
|
+
__publicField(this, "waypoints", []);
|
|
6667
|
+
__publicField(this, "totalDistance", 0);
|
|
6668
|
+
__publicField(this, "currentDistance", 0);
|
|
6669
|
+
__publicField(this, "airplaneCursor");
|
|
6670
|
+
__publicField(this, "trackEntity");
|
|
6671
|
+
__publicField(this, "passedTrackEntity");
|
|
6672
|
+
__publicField(this, "animationFrameId");
|
|
6673
|
+
__publicField(this, "lastTimestamp");
|
|
6674
|
+
__publicField(this, "onStateChange", new Emitter());
|
|
6675
|
+
/**
|
|
6676
|
+
* 动画循环
|
|
6677
|
+
*/
|
|
6678
|
+
__publicField(this, "animate", (timestamp) => {
|
|
6679
|
+
if (this.state !== "playing") return;
|
|
6680
|
+
if (this.lastTimestamp === void 0) {
|
|
6681
|
+
this.lastTimestamp = timestamp;
|
|
6682
|
+
}
|
|
6683
|
+
const deltaTime = (timestamp - this.lastTimestamp) / 1e3;
|
|
6684
|
+
this.lastTimestamp = timestamp;
|
|
6685
|
+
this.currentDistance += this.options.speed * deltaTime;
|
|
6686
|
+
if (this.currentDistance >= this.totalDistance) {
|
|
6687
|
+
if (this.options.loop) {
|
|
6688
|
+
this.currentDistance = 0;
|
|
6689
|
+
} else {
|
|
6690
|
+
this.currentDistance = this.totalDistance;
|
|
6691
|
+
this.setState("stopped");
|
|
6692
|
+
return;
|
|
6693
|
+
}
|
|
6694
|
+
}
|
|
6695
|
+
this.progress = this.totalDistance > 0 ? this.currentDistance / this.totalDistance : 0;
|
|
6696
|
+
if (this.airplaneCursor) {
|
|
6697
|
+
const position = this.getCurrentPosition();
|
|
6698
|
+
const { heading, pitch, roll } = this.getCurrentPose();
|
|
6699
|
+
this.airplaneCursor.setPose(position, heading, pitch, roll);
|
|
6700
|
+
}
|
|
6701
|
+
this.viewer.scene.requestRender();
|
|
6702
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
6703
|
+
});
|
|
6704
|
+
this.CesiumNS = CesiumNS;
|
|
6705
|
+
this.viewer = viewer;
|
|
6706
|
+
this.options = {
|
|
6707
|
+
waylineData: options.waylineData,
|
|
6708
|
+
speed: options.speed ?? 10,
|
|
6709
|
+
loop: options.loop ?? false,
|
|
6710
|
+
showFrustum: options.showFrustum ?? true,
|
|
6711
|
+
layer: options.layer,
|
|
6712
|
+
trackHighlight: options.trackHighlight
|
|
6713
|
+
};
|
|
6714
|
+
this.initWaypoints();
|
|
6715
|
+
this.createEntities();
|
|
6716
|
+
}
|
|
6717
|
+
/**
|
|
6718
|
+
* 初始化航点数据
|
|
6719
|
+
*/
|
|
6720
|
+
initWaypoints() {
|
|
6721
|
+
const C = this.CesiumNS;
|
|
6722
|
+
const converted = convertSinoflyWayline(this.options.waylineData, { CesiumNS: this.CesiumNS });
|
|
6723
|
+
if (!converted.waypointData || converted.waypointData.length < 2) {
|
|
6724
|
+
console.warn("[FlightSimulator] \u822A\u70B9\u6570\u91CF\u4E0D\u8DB3");
|
|
6725
|
+
return;
|
|
6726
|
+
}
|
|
6727
|
+
const tempWaypoints = converted.waypointData.map((wp) => ({
|
|
6728
|
+
cartesian: wp.position,
|
|
6729
|
+
heading: wp.heading ?? 0,
|
|
6730
|
+
pitch: wp.pitch ?? 0,
|
|
6731
|
+
roll: wp.roll ?? 0,
|
|
6732
|
+
cumulativeDistance: 0
|
|
6733
|
+
}));
|
|
6734
|
+
let cumulativeDistance = 0;
|
|
6735
|
+
for (let i = 0; i < tempWaypoints.length; i++) {
|
|
6736
|
+
if (i > 0) {
|
|
6737
|
+
const prevCartesian = tempWaypoints[i - 1].cartesian;
|
|
6738
|
+
const currCartesian = tempWaypoints[i].cartesian;
|
|
6739
|
+
cumulativeDistance += C.Cartesian3.distance(prevCartesian, currCartesian);
|
|
6740
|
+
}
|
|
6741
|
+
tempWaypoints[i].cumulativeDistance = cumulativeDistance;
|
|
6742
|
+
}
|
|
6743
|
+
this.waypoints = tempWaypoints;
|
|
6744
|
+
this.totalDistance = cumulativeDistance;
|
|
6745
|
+
}
|
|
6746
|
+
/**
|
|
6747
|
+
* 创建可视化实体
|
|
6748
|
+
*/
|
|
6749
|
+
createEntities() {
|
|
6750
|
+
if (this.waypoints.length === 0) return;
|
|
6751
|
+
const firstWaypoint = this.waypoints[0];
|
|
6752
|
+
this.airplaneCursor = new AirplaneCursor(
|
|
6753
|
+
this.CesiumNS,
|
|
6754
|
+
this.viewer,
|
|
6755
|
+
firstWaypoint.cartesian,
|
|
6756
|
+
{
|
|
6757
|
+
// 禁用键盘控制(仿真模式下不需要手动控制)
|
|
6758
|
+
stepMeters: 0,
|
|
6759
|
+
angleStepDeg: 0,
|
|
6760
|
+
fovDeg: 50
|
|
6761
|
+
}
|
|
6762
|
+
);
|
|
6763
|
+
this.airplaneCursor.setPose(
|
|
6764
|
+
firstWaypoint.cartesian,
|
|
6765
|
+
firstWaypoint.heading,
|
|
6766
|
+
firstWaypoint.pitch,
|
|
6767
|
+
firstWaypoint.roll
|
|
6768
|
+
);
|
|
6769
|
+
if (this.options.trackHighlight?.enabled) {
|
|
6770
|
+
this.createTrackHighlight();
|
|
6771
|
+
}
|
|
6772
|
+
}
|
|
6773
|
+
/**
|
|
6774
|
+
* 创建航迹高亮
|
|
6775
|
+
*/
|
|
6776
|
+
createTrackHighlight() {
|
|
6777
|
+
const C = this.CesiumNS;
|
|
6778
|
+
const entities = this.options.layer?.entities ?? this.viewer.entities;
|
|
6779
|
+
const highlightOpts = this.options.trackHighlight;
|
|
6780
|
+
const allPositions = this.waypoints.map((wp) => wp.cartesian);
|
|
6781
|
+
this.trackEntity = entities.add({
|
|
6782
|
+
id: `flight-simulator-track-${Date.now()}`,
|
|
6783
|
+
polyline: {
|
|
6784
|
+
positions: allPositions,
|
|
6785
|
+
width: highlightOpts.width ?? 4,
|
|
6786
|
+
material: (highlightOpts.color ?? C.Color.CYAN).withAlpha(0.3),
|
|
6787
|
+
clampToGround: false
|
|
6788
|
+
},
|
|
6789
|
+
properties: {
|
|
6790
|
+
_type: "flight-simulator-track"
|
|
6791
|
+
}
|
|
6792
|
+
});
|
|
6793
|
+
this.passedTrackEntity = entities.add({
|
|
6794
|
+
id: `flight-simulator-passed-track-${Date.now()}`,
|
|
6795
|
+
polyline: {
|
|
6796
|
+
positions: new C.CallbackProperty(() => this.getPassedPositions(), false),
|
|
6797
|
+
width: (highlightOpts.width ?? 4) + 2,
|
|
6798
|
+
material: highlightOpts.color ?? C.Color.CYAN,
|
|
6799
|
+
clampToGround: false
|
|
6800
|
+
},
|
|
6801
|
+
properties: {
|
|
6802
|
+
_type: "flight-simulator-passed-track"
|
|
6803
|
+
}
|
|
6804
|
+
});
|
|
6805
|
+
}
|
|
6806
|
+
/**
|
|
6807
|
+
* 获取当前位置
|
|
6808
|
+
*/
|
|
6809
|
+
getCurrentPosition() {
|
|
6810
|
+
if (this.waypoints.length === 0) {
|
|
6811
|
+
return this.CesiumNS.Cartesian3.ZERO;
|
|
6812
|
+
}
|
|
6813
|
+
const C = this.CesiumNS;
|
|
6814
|
+
for (let i = 1; i < this.waypoints.length; i++) {
|
|
6815
|
+
const prev = this.waypoints[i - 1];
|
|
6816
|
+
const curr = this.waypoints[i];
|
|
6817
|
+
if (this.currentDistance <= curr.cumulativeDistance) {
|
|
6818
|
+
const segmentStart = prev.cumulativeDistance;
|
|
6819
|
+
const segmentEnd = curr.cumulativeDistance;
|
|
6820
|
+
const segmentLength = segmentEnd - segmentStart;
|
|
6821
|
+
if (segmentLength <= 0) {
|
|
6822
|
+
return prev.cartesian;
|
|
6823
|
+
}
|
|
6824
|
+
const t = (this.currentDistance - segmentStart) / segmentLength;
|
|
6825
|
+
return C.Cartesian3.lerp(prev.cartesian, curr.cartesian, t, new C.Cartesian3());
|
|
6826
|
+
}
|
|
6827
|
+
}
|
|
6828
|
+
return this.waypoints[this.waypoints.length - 1].cartesian;
|
|
6829
|
+
}
|
|
6830
|
+
/**
|
|
6831
|
+
* 获取当前姿态(用于更新 AirplaneCursor)
|
|
6832
|
+
*/
|
|
6833
|
+
getCurrentPose() {
|
|
6834
|
+
const C = this.CesiumNS;
|
|
6835
|
+
let heading = 0;
|
|
6836
|
+
let pitch = 0;
|
|
6837
|
+
let roll = 0;
|
|
6838
|
+
for (let i = 1; i < this.waypoints.length; i++) {
|
|
6839
|
+
const prev = this.waypoints[i - 1];
|
|
6840
|
+
const curr = this.waypoints[i];
|
|
6841
|
+
if (this.currentDistance <= curr.cumulativeDistance) {
|
|
6842
|
+
const segmentStart = prev.cumulativeDistance;
|
|
6843
|
+
const segmentEnd = curr.cumulativeDistance;
|
|
6844
|
+
const segmentLength = segmentEnd - segmentStart;
|
|
6845
|
+
if (segmentLength > 0) {
|
|
6846
|
+
const t = (this.currentDistance - segmentStart) / segmentLength;
|
|
6847
|
+
heading = C.Math.lerp(prev.heading, curr.heading, t);
|
|
6848
|
+
pitch = C.Math.lerp(prev.pitch, curr.pitch, t);
|
|
6849
|
+
roll = C.Math.lerp(prev.roll, curr.roll, t);
|
|
6850
|
+
} else {
|
|
6851
|
+
heading = prev.heading;
|
|
6852
|
+
pitch = prev.pitch;
|
|
6853
|
+
roll = prev.roll;
|
|
6854
|
+
}
|
|
6855
|
+
break;
|
|
6856
|
+
}
|
|
6857
|
+
}
|
|
6858
|
+
return { heading, pitch, roll };
|
|
6859
|
+
}
|
|
6860
|
+
/**
|
|
6861
|
+
* 获取已飞过的位置数组
|
|
6862
|
+
*/
|
|
6863
|
+
getPassedPositions() {
|
|
6864
|
+
const positions = [];
|
|
6865
|
+
for (let i = 0; i < this.waypoints.length; i++) {
|
|
6866
|
+
const wp = this.waypoints[i];
|
|
6867
|
+
if (wp.cumulativeDistance <= this.currentDistance) {
|
|
6868
|
+
positions.push(wp.cartesian);
|
|
6869
|
+
} else {
|
|
6870
|
+
positions.push(this.getCurrentPosition());
|
|
6871
|
+
break;
|
|
6872
|
+
}
|
|
6873
|
+
}
|
|
6874
|
+
return positions;
|
|
6875
|
+
}
|
|
6876
|
+
/**
|
|
6877
|
+
* 设置状态并发射事件
|
|
6878
|
+
*/
|
|
6879
|
+
setState(newState) {
|
|
6880
|
+
if (this.state === newState) return;
|
|
6881
|
+
this.state = newState;
|
|
6882
|
+
this.onStateChange.emit({ state: newState, progress: this.progress });
|
|
6883
|
+
}
|
|
6884
|
+
// ==================== 公共方法 ====================
|
|
6885
|
+
start() {
|
|
6886
|
+
if (this.waypoints.length < 2) {
|
|
6887
|
+
console.warn("[FlightSimulator] \u822A\u70B9\u6570\u91CF\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5F00\u59CB\u4EFF\u771F");
|
|
6888
|
+
return;
|
|
6889
|
+
}
|
|
6890
|
+
this.currentDistance = 0;
|
|
6891
|
+
this.progress = 0;
|
|
6892
|
+
this.lastTimestamp = void 0;
|
|
6893
|
+
this.setState("playing");
|
|
6894
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
6895
|
+
}
|
|
6896
|
+
pause() {
|
|
6897
|
+
if (this.state !== "playing") return;
|
|
6898
|
+
if (this.animationFrameId !== void 0) {
|
|
6899
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
6900
|
+
this.animationFrameId = void 0;
|
|
6901
|
+
}
|
|
6902
|
+
this.lastTimestamp = void 0;
|
|
6903
|
+
this.setState("paused");
|
|
6904
|
+
}
|
|
6905
|
+
resume() {
|
|
6906
|
+
if (this.state !== "paused") return;
|
|
6907
|
+
this.lastTimestamp = void 0;
|
|
6908
|
+
this.setState("playing");
|
|
6909
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
6910
|
+
}
|
|
6911
|
+
stop() {
|
|
6912
|
+
if (this.animationFrameId !== void 0) {
|
|
6913
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
6914
|
+
this.animationFrameId = void 0;
|
|
6915
|
+
}
|
|
6916
|
+
this.currentDistance = 0;
|
|
6917
|
+
this.progress = 0;
|
|
6918
|
+
this.lastTimestamp = void 0;
|
|
6919
|
+
this.setState("stopped");
|
|
6920
|
+
this.viewer.scene.requestRender();
|
|
6921
|
+
}
|
|
6922
|
+
destroy() {
|
|
6923
|
+
this.stop();
|
|
6924
|
+
const entities = this.options.layer?.entities ?? this.viewer.entities;
|
|
6925
|
+
if (this.airplaneCursor) {
|
|
6926
|
+
this.airplaneCursor.destroy();
|
|
6927
|
+
this.airplaneCursor = void 0;
|
|
6928
|
+
}
|
|
6929
|
+
if (this.trackEntity) {
|
|
6930
|
+
entities.remove(this.trackEntity);
|
|
6931
|
+
this.trackEntity = void 0;
|
|
6932
|
+
}
|
|
6933
|
+
if (this.passedTrackEntity) {
|
|
6934
|
+
entities.remove(this.passedTrackEntity);
|
|
6935
|
+
this.passedTrackEntity = void 0;
|
|
6936
|
+
}
|
|
6937
|
+
this.waypoints = [];
|
|
6938
|
+
this.setState("idle");
|
|
6939
|
+
}
|
|
6940
|
+
setSpeed(speed) {
|
|
6941
|
+
this.options.speed = Math.max(0.1, speed);
|
|
6942
|
+
}
|
|
6943
|
+
getState() {
|
|
6944
|
+
return this.state;
|
|
6945
|
+
}
|
|
6946
|
+
getProgress() {
|
|
6947
|
+
return this.progress;
|
|
6948
|
+
}
|
|
6949
|
+
};
|
|
6950
|
+
|
|
6807
6951
|
// src/core/CZMLPathManager.ts
|
|
6808
6952
|
var _CZMLPathManager = class _CZMLPathManager {
|
|
6809
6953
|
constructor(CesiumNS, viewer) {
|
|
@@ -7080,6 +7224,20 @@ var _CZMLPathManager = class _CZMLPathManager {
|
|
|
7080
7224
|
options
|
|
7081
7225
|
);
|
|
7082
7226
|
}
|
|
7227
|
+
/**
|
|
7228
|
+
* Start flight simulation/preview for a wayline.
|
|
7229
|
+
* Animates an aircraft model along the wayline path with controls for play/pause/stop.
|
|
7230
|
+
* @param options - Configuration for the flight simulator
|
|
7231
|
+
* @returns A controller object with start/pause/resume/stop/destroy methods
|
|
7232
|
+
*/
|
|
7233
|
+
startFlightPreview(options) {
|
|
7234
|
+
const simulator = new FlightSimulator(
|
|
7235
|
+
this.CesiumNS,
|
|
7236
|
+
this.viewer,
|
|
7237
|
+
options
|
|
7238
|
+
);
|
|
7239
|
+
return simulator;
|
|
7240
|
+
}
|
|
7083
7241
|
// ensureLayerForEntity moved into path-editing module
|
|
7084
7242
|
};
|
|
7085
7243
|
__publicField(_CZMLPathManager, "SAMPLES_KEY", "__czmlPathSamples__");
|
|
@@ -10731,6 +10889,226 @@ var Selector = class {
|
|
|
10731
10889
|
}
|
|
10732
10890
|
};
|
|
10733
10891
|
|
|
10892
|
+
// src/core/PointCloudPicker.ts
|
|
10893
|
+
var PointCloudPicker = class {
|
|
10894
|
+
constructor(CesiumNS, viewer) {
|
|
10895
|
+
this.CesiumNS = CesiumNS;
|
|
10896
|
+
this.viewer = viewer;
|
|
10897
|
+
__publicField(this, "handler");
|
|
10898
|
+
__publicField(this, "markerEntity");
|
|
10899
|
+
__publicField(this, "isPaused", false);
|
|
10900
|
+
}
|
|
10901
|
+
/**
|
|
10902
|
+
* 在指定屏幕位置进行一次点云拾取
|
|
10903
|
+
* @param windowPosition 屏幕坐标 { x, y }
|
|
10904
|
+
* @param options 拾取选项
|
|
10905
|
+
* @returns 拾取结果
|
|
10906
|
+
*/
|
|
10907
|
+
pickAt(windowPosition, options) {
|
|
10908
|
+
const C = this.CesiumNS;
|
|
10909
|
+
const scene = this.viewer.scene;
|
|
10910
|
+
const fetchProperties = options?.fetchProperties ?? true;
|
|
10911
|
+
const pointCloudOnly = options?.pointCloudOnly ?? true;
|
|
10912
|
+
const picked = scene.pick(windowPosition);
|
|
10913
|
+
let tileset;
|
|
10914
|
+
let content;
|
|
10915
|
+
let featureId;
|
|
10916
|
+
if (picked) {
|
|
10917
|
+
if (picked.primitive instanceof C.Cesium3DTileset) {
|
|
10918
|
+
tileset = picked.primitive;
|
|
10919
|
+
} else if (picked.tileset instanceof C.Cesium3DTileset) {
|
|
10920
|
+
tileset = picked.tileset;
|
|
10921
|
+
}
|
|
10922
|
+
if (picked.content) {
|
|
10923
|
+
content = picked.content;
|
|
10924
|
+
}
|
|
10925
|
+
if (typeof picked.featureId === "number") {
|
|
10926
|
+
featureId = picked.featureId;
|
|
10927
|
+
}
|
|
10928
|
+
}
|
|
10929
|
+
if (pointCloudOnly && !tileset) {
|
|
10930
|
+
return { success: false, screenPosition: windowPosition };
|
|
10931
|
+
}
|
|
10932
|
+
let position;
|
|
10933
|
+
if (scene.pickPositionSupported) {
|
|
10934
|
+
try {
|
|
10935
|
+
position = scene.pickPosition(windowPosition);
|
|
10936
|
+
} catch {
|
|
10937
|
+
}
|
|
10938
|
+
}
|
|
10939
|
+
if (!position || !C.defined(position)) {
|
|
10940
|
+
try {
|
|
10941
|
+
const ray = this.viewer.camera.getPickRay(windowPosition);
|
|
10942
|
+
if (ray) {
|
|
10943
|
+
position = scene.globe?.pick(ray, scene);
|
|
10944
|
+
}
|
|
10945
|
+
} catch {
|
|
10946
|
+
}
|
|
10947
|
+
}
|
|
10948
|
+
if (!position || !C.defined(position)) {
|
|
10949
|
+
return { success: false, screenPosition: windowPosition, tileset };
|
|
10950
|
+
}
|
|
10951
|
+
let coordinates;
|
|
10952
|
+
try {
|
|
10953
|
+
const cartographic = C.Cartographic.fromCartesian(position);
|
|
10954
|
+
coordinates = {
|
|
10955
|
+
longitude: C.Math.toDegrees(cartographic.longitude),
|
|
10956
|
+
latitude: C.Math.toDegrees(cartographic.latitude),
|
|
10957
|
+
height: cartographic.height
|
|
10958
|
+
};
|
|
10959
|
+
} catch {
|
|
10960
|
+
}
|
|
10961
|
+
let properties;
|
|
10962
|
+
let color;
|
|
10963
|
+
if (fetchProperties && content && featureId !== void 0) {
|
|
10964
|
+
try {
|
|
10965
|
+
const feature = content.getFeature?.(featureId);
|
|
10966
|
+
if (feature) {
|
|
10967
|
+
properties = {};
|
|
10968
|
+
const propertyIds = feature.getPropertyIds?.() ?? [];
|
|
10969
|
+
for (const propId of propertyIds) {
|
|
10970
|
+
try {
|
|
10971
|
+
properties[propId] = feature.getProperty(propId);
|
|
10972
|
+
} catch {
|
|
10973
|
+
}
|
|
10974
|
+
}
|
|
10975
|
+
try {
|
|
10976
|
+
const c = feature.color;
|
|
10977
|
+
if (c) {
|
|
10978
|
+
color = {
|
|
10979
|
+
red: c.red,
|
|
10980
|
+
green: c.green,
|
|
10981
|
+
blue: c.blue,
|
|
10982
|
+
alpha: c.alpha
|
|
10983
|
+
};
|
|
10984
|
+
}
|
|
10985
|
+
} catch {
|
|
10986
|
+
}
|
|
10987
|
+
}
|
|
10988
|
+
} catch {
|
|
10989
|
+
}
|
|
10990
|
+
}
|
|
10991
|
+
return {
|
|
10992
|
+
success: true,
|
|
10993
|
+
position,
|
|
10994
|
+
coordinates,
|
|
10995
|
+
tileset,
|
|
10996
|
+
content,
|
|
10997
|
+
featureId,
|
|
10998
|
+
properties,
|
|
10999
|
+
color,
|
|
11000
|
+
screenPosition: windowPosition
|
|
11001
|
+
};
|
|
11002
|
+
}
|
|
11003
|
+
/**
|
|
11004
|
+
* 开启点云拾取会话
|
|
11005
|
+
* @param onPick 拾取回调函数
|
|
11006
|
+
* @param options 拾取选项
|
|
11007
|
+
* @returns 拾取会话对象
|
|
11008
|
+
*/
|
|
11009
|
+
startPicking(onPick, options) {
|
|
11010
|
+
const C = this.CesiumNS;
|
|
11011
|
+
const canvas = this.viewer.scene.canvas;
|
|
11012
|
+
const prevCursor = canvas?.style?.cursor;
|
|
11013
|
+
const cursor = options?.cursor ?? "crosshair";
|
|
11014
|
+
if (canvas) canvas.style.cursor = cursor;
|
|
11015
|
+
this.handler = new C.ScreenSpaceEventHandler(canvas);
|
|
11016
|
+
this.isPaused = false;
|
|
11017
|
+
const showMarker = options?.showMarker ?? true;
|
|
11018
|
+
const markerColor = options?.markerColor ?? C.Color.YELLOW;
|
|
11019
|
+
const markerSize = options?.markerSize ?? 10;
|
|
11020
|
+
const handler = this.handler;
|
|
11021
|
+
if (handler) {
|
|
11022
|
+
handler.setInputAction(
|
|
11023
|
+
(movement) => {
|
|
11024
|
+
if (this.isPaused) return;
|
|
11025
|
+
const result = this.pickAt(movement.position, {
|
|
11026
|
+
fetchProperties: options?.fetchProperties ?? true,
|
|
11027
|
+
pointCloudOnly: options?.pointCloudOnly ?? true
|
|
11028
|
+
});
|
|
11029
|
+
if (showMarker && result.success && result.position) {
|
|
11030
|
+
this.showMarker(result.position, markerColor, markerSize);
|
|
11031
|
+
}
|
|
11032
|
+
onPick(result);
|
|
11033
|
+
},
|
|
11034
|
+
C.ScreenSpaceEventType.LEFT_CLICK
|
|
11035
|
+
);
|
|
11036
|
+
}
|
|
11037
|
+
return {
|
|
11038
|
+
stop: () => {
|
|
11039
|
+
this.stopPicking();
|
|
11040
|
+
if (canvas) canvas.style.cursor = prevCursor ?? "";
|
|
11041
|
+
},
|
|
11042
|
+
pause: () => {
|
|
11043
|
+
this.isPaused = true;
|
|
11044
|
+
},
|
|
11045
|
+
resume: () => {
|
|
11046
|
+
this.isPaused = false;
|
|
11047
|
+
},
|
|
11048
|
+
isPaused: () => this.isPaused
|
|
11049
|
+
};
|
|
11050
|
+
}
|
|
11051
|
+
/**
|
|
11052
|
+
* 停止拾取会话
|
|
11053
|
+
*/
|
|
11054
|
+
stopPicking() {
|
|
11055
|
+
try {
|
|
11056
|
+
this.handler?.destroy();
|
|
11057
|
+
} catch {
|
|
11058
|
+
}
|
|
11059
|
+
this.handler = void 0;
|
|
11060
|
+
this.removeMarker();
|
|
11061
|
+
}
|
|
11062
|
+
/**
|
|
11063
|
+
* 显示标记点
|
|
11064
|
+
*/
|
|
11065
|
+
showMarker(position, color, size) {
|
|
11066
|
+
const C = this.CesiumNS;
|
|
11067
|
+
this.removeMarker();
|
|
11068
|
+
this.markerEntity = this.viewer.entities.add({
|
|
11069
|
+
position,
|
|
11070
|
+
point: {
|
|
11071
|
+
pixelSize: size,
|
|
11072
|
+
color,
|
|
11073
|
+
outlineColor: C.Color.WHITE,
|
|
11074
|
+
outlineWidth: 2,
|
|
11075
|
+
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
11076
|
+
heightReference: C.HeightReference.NONE
|
|
11077
|
+
}
|
|
11078
|
+
});
|
|
11079
|
+
}
|
|
11080
|
+
/**
|
|
11081
|
+
* 移除标记点
|
|
11082
|
+
*/
|
|
11083
|
+
removeMarker() {
|
|
11084
|
+
if (this.markerEntity) {
|
|
11085
|
+
try {
|
|
11086
|
+
this.viewer.entities.remove(this.markerEntity);
|
|
11087
|
+
} catch {
|
|
11088
|
+
}
|
|
11089
|
+
this.markerEntity = void 0;
|
|
11090
|
+
}
|
|
11091
|
+
}
|
|
11092
|
+
/**
|
|
11093
|
+
* 获取当前标记点位置
|
|
11094
|
+
*/
|
|
11095
|
+
getMarkerPosition() {
|
|
11096
|
+
if (!this.markerEntity) return void 0;
|
|
11097
|
+
const pos = this.markerEntity.position;
|
|
11098
|
+
if (typeof pos?.getValue === "function") {
|
|
11099
|
+
return pos.getValue(this.CesiumNS.JulianDate.now());
|
|
11100
|
+
}
|
|
11101
|
+
return pos;
|
|
11102
|
+
}
|
|
11103
|
+
/**
|
|
11104
|
+
* 销毁拾取器
|
|
11105
|
+
*/
|
|
11106
|
+
destroy() {
|
|
11107
|
+
this.stopPicking();
|
|
11108
|
+
this.removeMarker();
|
|
11109
|
+
}
|
|
11110
|
+
};
|
|
11111
|
+
|
|
10734
11112
|
// src/utils/pathToSinoflyAdapter.ts
|
|
10735
11113
|
function convertCartesian3ToLatLonHeight(CesiumNS, position) {
|
|
10736
11114
|
const C = CesiumNS;
|
|
@@ -10809,23 +11187,6 @@ function convertPoseToActionGroup(heading, pitch, roll, fov, waypointIndex) {
|
|
|
10809
11187
|
return "{}";
|
|
10810
11188
|
}
|
|
10811
11189
|
}
|
|
10812
|
-
function convertStartPointToTakeOffRefPoint(CesiumNS, position) {
|
|
10813
|
-
const C = CesiumNS;
|
|
10814
|
-
try {
|
|
10815
|
-
const cartographic = C.Cartographic.fromCartesian(position);
|
|
10816
|
-
const longitude = C.Math.toDegrees(cartographic.longitude);
|
|
10817
|
-
const latitude = C.Math.toDegrees(cartographic.latitude);
|
|
10818
|
-
const height = cartographic.height;
|
|
10819
|
-
return JSON.stringify({
|
|
10820
|
-
longitude,
|
|
10821
|
-
latitude,
|
|
10822
|
-
height
|
|
10823
|
-
});
|
|
10824
|
-
} catch (error) {
|
|
10825
|
-
console.error("[pathToSinoflyAdapter] takeOffRefPoint \u751F\u6210\u5931\u8D25:", error);
|
|
10826
|
-
return "";
|
|
10827
|
-
}
|
|
10828
|
-
}
|
|
10829
11190
|
function convertPathToSinofly(data, options) {
|
|
10830
11191
|
const {
|
|
10831
11192
|
CesiumNS,
|
|
@@ -10869,10 +11230,6 @@ function convertPathToSinofly(data, options) {
|
|
|
10869
11230
|
}
|
|
10870
11231
|
const distance = data.waypointData[data.waypointData.length - 1]?.distance ?? 0;
|
|
10871
11232
|
const takeOffSecurityHeight = data.climbHeight ?? 0;
|
|
10872
|
-
let takeOffRefPoint;
|
|
10873
|
-
if (data.hasHiddenClimb && data.startPoint?.position) {
|
|
10874
|
-
takeOffRefPoint = convertStartPointToTakeOffRefPoint(CesiumNS, data.startPoint.position);
|
|
10875
|
-
}
|
|
10876
11233
|
const waypointInfo = data.waypointData.map((wp, idx) => {
|
|
10877
11234
|
const newIndex = idx;
|
|
10878
11235
|
const { latitude, longitude, altitude } = convertCartesian3ToLatLonHeight(
|
|
@@ -10889,7 +11246,11 @@ function convertPathToSinofly(data, options) {
|
|
|
10889
11246
|
longitude,
|
|
10890
11247
|
altitude,
|
|
10891
11248
|
action,
|
|
10892
|
-
noReturn: defaultNoReturn
|
|
11249
|
+
noReturn: defaultNoReturn,
|
|
11250
|
+
// 🆕 添加高度相关字段
|
|
11251
|
+
ellipsoidHeight: wp.ellipsoidHeight,
|
|
11252
|
+
relativeHeight: wp.relativeHeight,
|
|
11253
|
+
useGlobalHeight: wp.useGlobalHeight
|
|
10893
11254
|
};
|
|
10894
11255
|
if (waypointCreateUserId) waypoint.createUserId = waypointCreateUserId;
|
|
10895
11256
|
if (waypointCreateTime) waypoint.createTime = waypointCreateTime;
|
|
@@ -10917,7 +11278,6 @@ function convertPathToSinofly(data, options) {
|
|
|
10917
11278
|
photoNumber,
|
|
10918
11279
|
waypointInfo
|
|
10919
11280
|
};
|
|
10920
|
-
if (takeOffRefPoint) sinoflyData.takeOffRefPoint = takeOffRefPoint;
|
|
10921
11281
|
if (thumbnailFileId !== void 0) sinoflyData.thumbnailFileId = thumbnailFileId;
|
|
10922
11282
|
if (stationId !== void 0) sinoflyData.stationId = stationId;
|
|
10923
11283
|
if (subarrayId !== void 0) sinoflyData.subarrayId = subarrayId;
|
|
@@ -11321,14 +11681,18 @@ exports.CameraEventBus = CameraEventBus;
|
|
|
11321
11681
|
exports.CameraFOVController = CameraFOVController;
|
|
11322
11682
|
exports.CameraManager = CameraManager;
|
|
11323
11683
|
exports.Emitter = Emitter;
|
|
11684
|
+
exports.FlightSimulator = FlightSimulator;
|
|
11324
11685
|
exports.FrustumPyramid = FrustumPyramid;
|
|
11325
11686
|
exports.LayerManager = LayerManager;
|
|
11326
11687
|
exports.PathSafetyChecker = PathSafetyChecker;
|
|
11688
|
+
exports.PointCloudPicker = PointCloudPicker;
|
|
11327
11689
|
exports.PolygonEditor = PolygonEditor;
|
|
11328
11690
|
exports.SceneManager = SceneManager;
|
|
11329
11691
|
exports.Selector = Selector;
|
|
11330
11692
|
exports.StateManager = StateManager;
|
|
11331
11693
|
exports.assertCesiumAssetsConfigured = assertCesiumAssetsConfigured;
|
|
11694
|
+
exports.calculateAbsoluteHeight = calculateAbsoluteHeight;
|
|
11695
|
+
exports.calculateRelativeHeight = calculateRelativeHeight;
|
|
11332
11696
|
exports.configureCesiumAssets = configureCesiumAssets;
|
|
11333
11697
|
exports.configureCesiumIonToken = configureCesiumIonToken;
|
|
11334
11698
|
exports.convertPathToSinofly = convertPathToSinofly;
|
|
@@ -11340,6 +11704,9 @@ exports.getCesiumIonToken = getCesiumIonToken;
|
|
|
11340
11704
|
exports.globalCameraEventBus = globalCameraEventBus;
|
|
11341
11705
|
exports.globalState = globalState;
|
|
11342
11706
|
exports.placeholder = placeholder;
|
|
11707
|
+
exports.queryTerrainHeightAsync = queryTerrainHeightAsync;
|
|
11708
|
+
exports.queryTerrainHeightSync = queryTerrainHeightSync;
|
|
11709
|
+
exports.queryTerrainHeights = queryTerrainHeights;
|
|
11343
11710
|
exports.renderFlightPath = renderFlightPath;
|
|
11344
11711
|
exports.renderFlightPathPreview = renderFlightPathPreview;
|
|
11345
11712
|
exports.toggle2D3D = toggle2D3D;
|