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