@jorgmoritz/gis-manager 0.1.36 → 0.1.38
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 +1110 -705
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +328 -34
- package/dist/index.d.ts +328 -34
- package/dist/index.js +1104 -706
- package/dist/index.js.map +1 -1
- package/dist/vue/index.cjs +871 -679
- 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 +871 -679
- package/dist/vue/index.js.map +1 -1
- package/package.json +1 -1
package/dist/vue/index.cjs
CHANGED
|
@@ -2589,7 +2589,7 @@ var FrustumPyramid = class {
|
|
|
2589
2589
|
showAt(apex, headingDeg, pitchDeg = 0, rollDeg = 0, fovDeg, lengthOverride) {
|
|
2590
2590
|
if (this.destroyed) return;
|
|
2591
2591
|
const C = this.CesiumNS;
|
|
2592
|
-
const length = Math.max(1, lengthOverride ?? this.opts.length ??
|
|
2592
|
+
const length = Math.max(1, lengthOverride ?? this.opts.length ?? 500);
|
|
2593
2593
|
const lakeEdge = this.opts.color ?? C.Color.fromCssColorString("#1e90ff");
|
|
2594
2594
|
const alpha = this.opts.fillAlpha ?? 0.25;
|
|
2595
2595
|
const lakeFill = (this.opts.fillColor ?? C.Color.fromCssColorString("#1e90ff")).withAlpha(alpha);
|
|
@@ -2772,8 +2772,6 @@ var AirplaneCursor = class {
|
|
|
2772
2772
|
__publicField(this, "angleStep");
|
|
2773
2773
|
/** 加速倍率(按住 Shift 生效) */
|
|
2774
2774
|
__publicField(this, "fastFactor");
|
|
2775
|
-
/** 最小高度(米) */
|
|
2776
|
-
__publicField(this, "minHeight");
|
|
2777
2775
|
/** 外部传入的行为配置与回调 */
|
|
2778
2776
|
__publicField(this, "opts");
|
|
2779
2777
|
// 使用内联的 _FrustumPyramid
|
|
@@ -2801,7 +2799,6 @@ var AirplaneCursor = class {
|
|
|
2801
2799
|
this.step = opts.stepMeters ?? 2;
|
|
2802
2800
|
this.angleStep = opts.angleStepDeg ?? 1;
|
|
2803
2801
|
this.fastFactor = opts.fastFactor ?? 5;
|
|
2804
|
-
this.minHeight = opts.minHeight ?? 0;
|
|
2805
2802
|
this.currentFOV = opts.fovDeg ?? 50;
|
|
2806
2803
|
this.ensureEntity(opts.color ?? C.Color.CYAN.withAlpha(0.9));
|
|
2807
2804
|
this.attachKeyboard(opts);
|
|
@@ -3026,11 +3023,8 @@ var AirplaneCursor = class {
|
|
|
3026
3023
|
}
|
|
3027
3024
|
if (this.keysPressed.has("z")) {
|
|
3028
3025
|
const newPos = addVec(pose.position, C.Cartesian3.multiplyByScalar(u3, -step, new C.Cartesian3()));
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
setPos(newPos);
|
|
3032
|
-
moved = true;
|
|
3033
|
-
}
|
|
3026
|
+
setPos(newPos);
|
|
3027
|
+
moved = true;
|
|
3034
3028
|
}
|
|
3035
3029
|
if (this.keysPressed.has("q")) {
|
|
3036
3030
|
pose.heading = clampDeg(pose.heading - ang);
|
|
@@ -3083,8 +3077,8 @@ var AirplaneCursor = class {
|
|
|
3083
3077
|
this.viewer.dataSources.add(layer);
|
|
3084
3078
|
}
|
|
3085
3079
|
this.frustum = new FrustumPyramid(this.CesiumNS, layer, {
|
|
3086
|
-
fov: this.opts.fovDeg ??
|
|
3087
|
-
length:
|
|
3080
|
+
fov: this.opts.fovDeg ?? 40,
|
|
3081
|
+
length: 80,
|
|
3088
3082
|
color: this.opts.color,
|
|
3089
3083
|
fillAlpha: 0.25,
|
|
3090
3084
|
width: 2,
|
|
@@ -3092,14 +3086,17 @@ var AirplaneCursor = class {
|
|
|
3092
3086
|
logAngles: false,
|
|
3093
3087
|
logThrottleMs: 300
|
|
3094
3088
|
});
|
|
3089
|
+
const frustumFovScale = 0.6;
|
|
3090
|
+
const frustumLengthScale = 0.1;
|
|
3095
3091
|
this.frustum.showAtDynamic(
|
|
3096
3092
|
() => this.pose.position,
|
|
3097
3093
|
() => this.pose.heading,
|
|
3098
3094
|
() => this.pose.pitch,
|
|
3099
3095
|
() => this.pose.roll,
|
|
3100
|
-
() => this.currentFOV,
|
|
3101
|
-
//
|
|
3102
|
-
() => 1e3
|
|
3096
|
+
() => this.currentFOV * frustumFovScale,
|
|
3097
|
+
// 缩小 FOV
|
|
3098
|
+
() => 1e3 * frustumLengthScale
|
|
3099
|
+
// 缩小深度(1000 -> 100)
|
|
3103
3100
|
);
|
|
3104
3101
|
try {
|
|
3105
3102
|
this.heightMarker = new HeightMarker(this.CesiumNS, this.viewer, layer);
|
|
@@ -3615,7 +3612,7 @@ function calculatePathDistance(CesiumNS, positions, targetIndex, hiddenClimbInde
|
|
|
3615
3612
|
if (targetIndex < 0 || targetIndex >= positions.length) return 0;
|
|
3616
3613
|
const C = CesiumNS;
|
|
3617
3614
|
let totalDistance = 0;
|
|
3618
|
-
const startIndex =
|
|
3615
|
+
const startIndex = 1;
|
|
3619
3616
|
if (targetIndex <= startIndex) return 0;
|
|
3620
3617
|
for (let i = startIndex; i <= targetIndex; i++) {
|
|
3621
3618
|
try {
|
|
@@ -3658,9 +3655,11 @@ var VertexInsertionHandler = class {
|
|
|
3658
3655
|
* @param heightMarkers 高度标记数组(引用)
|
|
3659
3656
|
* @param airplaneCursor 飞机游标(可选)
|
|
3660
3657
|
* @param poseOrient 顶点姿态(可选)
|
|
3658
|
+
* @param useGlobalHeightFlags 🆕 是否使用全局高度标志数组(引用,可选)
|
|
3659
|
+
* @param altitudeModeOptions 🆕 高度模式选项(可选)
|
|
3661
3660
|
* @returns 实际插入的索引
|
|
3662
3661
|
*/
|
|
3663
|
-
insertVertex(insertAt, position, positions, handles, headings, pitches, rolls, fovs, editedIndices, vertexLabelManager, heightMarkers, airplaneCursor, poseOrient) {
|
|
3662
|
+
insertVertex(insertAt, position, positions, handles, headings, pitches, rolls, fovs, editedIndices, vertexLabelManager, heightMarkers, airplaneCursor, poseOrient, useGlobalHeightFlags) {
|
|
3664
3663
|
const C = this.CesiumNS;
|
|
3665
3664
|
if (this.hiddenClimbIndex === 1 && insertAt <= 1) {
|
|
3666
3665
|
insertAt = 2;
|
|
@@ -3695,6 +3694,12 @@ var VertexInsertionHandler = class {
|
|
|
3695
3694
|
pitches.splice(insertAt, 0, pose.pitch);
|
|
3696
3695
|
rolls.splice(insertAt, 0, pose.roll);
|
|
3697
3696
|
fovs.splice(insertAt, 0, 50);
|
|
3697
|
+
if (useGlobalHeightFlags) {
|
|
3698
|
+
for (let i = useGlobalHeightFlags.length - 1; i >= insertAt; i--) {
|
|
3699
|
+
useGlobalHeightFlags[i + 1] = useGlobalHeightFlags[i];
|
|
3700
|
+
}
|
|
3701
|
+
useGlobalHeightFlags[insertAt] = true;
|
|
3702
|
+
}
|
|
3698
3703
|
return insertAt;
|
|
3699
3704
|
}
|
|
3700
3705
|
/**
|
|
@@ -3903,7 +3908,6 @@ var VertexDragHandler = class {
|
|
|
3903
3908
|
__publicField(this, "CesiumNS");
|
|
3904
3909
|
__publicField(this, "viewer");
|
|
3905
3910
|
__publicField(this, "hiddenClimbIndex");
|
|
3906
|
-
__publicField(this, "minHeight");
|
|
3907
3911
|
__publicField(this, "callbacks");
|
|
3908
3912
|
__publicField(this, "dragState", null);
|
|
3909
3913
|
__publicField(this, "canvas");
|
|
@@ -3912,7 +3916,6 @@ var VertexDragHandler = class {
|
|
|
3912
3916
|
this.CesiumNS = options.CesiumNS;
|
|
3913
3917
|
this.viewer = options.viewer;
|
|
3914
3918
|
this.hiddenClimbIndex = options.hiddenClimbIndex;
|
|
3915
|
-
this.minHeight = options.minHeight ?? 0;
|
|
3916
3919
|
this.callbacks = callbacks;
|
|
3917
3920
|
this.canvas = this.viewer.scene.canvas;
|
|
3918
3921
|
this.setupKeyboardListeners();
|
|
@@ -4088,7 +4091,7 @@ var VertexDragHandler = class {
|
|
|
4088
4091
|
const cameraHeight = this.viewer.camera.positionCartographic.height;
|
|
4089
4092
|
const scaleFactor = Math.max(cameraHeight / 1e3, 0.5);
|
|
4090
4093
|
const heightDelta = -deltaY * scaleFactor;
|
|
4091
|
-
const newHeight =
|
|
4094
|
+
const newHeight = this.dragState.startHeight + heightDelta;
|
|
4092
4095
|
const newPosition = C.Cartesian3.fromDegrees(
|
|
4093
4096
|
this.dragState.startLonLat.lon,
|
|
4094
4097
|
this.dragState.startLonLat.lat,
|
|
@@ -4173,6 +4176,79 @@ var VertexDragHandler = class {
|
|
|
4173
4176
|
}
|
|
4174
4177
|
};
|
|
4175
4178
|
|
|
4179
|
+
// src/core/path-manager/utils/TerrainHeightQuery.ts
|
|
4180
|
+
async function queryTerrainHeights(CesiumNS, viewer, positions) {
|
|
4181
|
+
const C = CesiumNS;
|
|
4182
|
+
if (!positions || positions.length === 0) {
|
|
4183
|
+
return [];
|
|
4184
|
+
}
|
|
4185
|
+
const cartographics = positions.map((pos) => {
|
|
4186
|
+
try {
|
|
4187
|
+
return C.Cartographic.fromCartesian(pos);
|
|
4188
|
+
} catch {
|
|
4189
|
+
return new C.Cartographic(0, 0, 0);
|
|
4190
|
+
}
|
|
4191
|
+
});
|
|
4192
|
+
const terrainProvider = viewer.terrainProvider;
|
|
4193
|
+
if (!terrainProvider || !C.sampleTerrainMostDetailed) {
|
|
4194
|
+
console.warn("[TerrainHeightQuery] \u65E0\u53EF\u7528\u5730\u5F62\u63D0\u4F9B\u8005\uFF0C\u4F7F\u7528\u540C\u6B65\u56DE\u9000\u65B9\u6848");
|
|
4195
|
+
return positions.map((pos) => queryTerrainHeightSync(CesiumNS, viewer, pos));
|
|
4196
|
+
}
|
|
4197
|
+
try {
|
|
4198
|
+
const sampledPositions = await C.sampleTerrainMostDetailed(
|
|
4199
|
+
terrainProvider,
|
|
4200
|
+
cartographics
|
|
4201
|
+
);
|
|
4202
|
+
return sampledPositions.map((carto) => {
|
|
4203
|
+
const height = carto?.height;
|
|
4204
|
+
return typeof height === "number" && !isNaN(height) ? height : 0;
|
|
4205
|
+
});
|
|
4206
|
+
} catch (error) {
|
|
4207
|
+
console.warn("[TerrainHeightQuery] \u5F02\u6B65\u67E5\u8BE2\u5931\u8D25\uFF0C\u4F7F\u7528\u540C\u6B65\u56DE\u9000:", error);
|
|
4208
|
+
return positions.map((pos) => queryTerrainHeightSync(CesiumNS, viewer, pos));
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
function queryTerrainHeightSync(CesiumNS, viewer, position) {
|
|
4212
|
+
const C = CesiumNS;
|
|
4213
|
+
try {
|
|
4214
|
+
const cartographic = C.Cartographic.fromCartesian(position);
|
|
4215
|
+
const globe = viewer.scene.globe;
|
|
4216
|
+
if (globe && typeof globe.getHeight === "function") {
|
|
4217
|
+
const height = globe.getHeight(cartographic);
|
|
4218
|
+
if (typeof height === "number" && !isNaN(height)) {
|
|
4219
|
+
return height;
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
} catch (error) {
|
|
4223
|
+
console.warn("[TerrainHeightQuery] \u540C\u6B65\u67E5\u8BE2\u5931\u8D25:", error);
|
|
4224
|
+
}
|
|
4225
|
+
return 0;
|
|
4226
|
+
}
|
|
4227
|
+
function calculateAbsoluteHeight(altitudeMode, defaultAltitude, startPointAltitude, terrainHeight) {
|
|
4228
|
+
switch (altitudeMode) {
|
|
4229
|
+
case "absolute":
|
|
4230
|
+
return defaultAltitude;
|
|
4231
|
+
case "relativeToStart":
|
|
4232
|
+
return startPointAltitude + defaultAltitude;
|
|
4233
|
+
case "relativeToGround":
|
|
4234
|
+
return terrainHeight + defaultAltitude;
|
|
4235
|
+
default:
|
|
4236
|
+
return defaultAltitude;
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
4239
|
+
function calculateRelativeHeight(altitudeMode, absoluteHeight, startPointAltitude, terrainHeight) {
|
|
4240
|
+
switch (altitudeMode) {
|
|
4241
|
+
case "absolute":
|
|
4242
|
+
return absoluteHeight;
|
|
4243
|
+
case "relativeToStart":
|
|
4244
|
+
return absoluteHeight - startPointAltitude;
|
|
4245
|
+
case "relativeToGround":
|
|
4246
|
+
return absoluteHeight - terrainHeight;
|
|
4247
|
+
default:
|
|
4248
|
+
return absoluteHeight;
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
|
|
4176
4252
|
// src/core/path-manager/editing/PathEditingEventHandler.ts
|
|
4177
4253
|
var PathEditingEventHandler = class {
|
|
4178
4254
|
constructor(options, callbacks) {
|
|
@@ -4195,8 +4271,7 @@ var PathEditingEventHandler = class {
|
|
|
4195
4271
|
{
|
|
4196
4272
|
CesiumNS: this.CesiumNS,
|
|
4197
4273
|
viewer: this.viewer,
|
|
4198
|
-
hiddenClimbIndex: this.hiddenClimbIndex
|
|
4199
|
-
minHeight: options.minHeight
|
|
4274
|
+
hiddenClimbIndex: this.hiddenClimbIndex
|
|
4200
4275
|
},
|
|
4201
4276
|
{
|
|
4202
4277
|
onDragStart: (index) => {
|
|
@@ -4431,23 +4506,14 @@ var PathEditingEventHandler = class {
|
|
|
4431
4506
|
buildVertexContextMenuItems(vertexIndex) {
|
|
4432
4507
|
const menuItems = [];
|
|
4433
4508
|
const positions = this.callbacks.getPositions?.() || [];
|
|
4434
|
-
const
|
|
4435
|
-
|
|
4436
|
-
const isStartPoint = vertexIndex === 0 || this.hiddenClimbIndex === 1 && vertexIndex === 1;
|
|
4437
|
-
if (canDelete && !isStartPoint) {
|
|
4509
|
+
const canDelete = positions.length > 1;
|
|
4510
|
+
if (canDelete) {
|
|
4438
4511
|
menuItems.push({
|
|
4439
4512
|
label: `\u5220\u9664\u822A\u70B9 ${this.getVertexDisplayNumber(vertexIndex)}`,
|
|
4440
4513
|
action: () => {
|
|
4441
4514
|
this.handleDeleteVertex(vertexIndex);
|
|
4442
4515
|
}
|
|
4443
4516
|
});
|
|
4444
|
-
} else if (isStartPoint) {
|
|
4445
|
-
menuItems.push({
|
|
4446
|
-
label: "\u8D77\u70B9\u4E0D\u53EF\u5220\u9664",
|
|
4447
|
-
action: () => {
|
|
4448
|
-
},
|
|
4449
|
-
disabled: true
|
|
4450
|
-
});
|
|
4451
4517
|
} else {
|
|
4452
4518
|
menuItems.push({
|
|
4453
4519
|
label: "\u81F3\u5C11\u4FDD\u7559\u4E00\u4E2A\u822A\u70B9",
|
|
@@ -4459,12 +4525,10 @@ var PathEditingEventHandler = class {
|
|
|
4459
4525
|
return menuItems;
|
|
4460
4526
|
}
|
|
4461
4527
|
/**
|
|
4462
|
-
*
|
|
4528
|
+
* 获取顶点的显示编号
|
|
4529
|
+
* 🆕 不再跳过隐藏爬升点,直接返回索引
|
|
4463
4530
|
*/
|
|
4464
4531
|
getVertexDisplayNumber(index) {
|
|
4465
|
-
if (this.hiddenClimbIndex === 1 && index > 1) {
|
|
4466
|
-
return index - 1;
|
|
4467
|
-
}
|
|
4468
4532
|
return index;
|
|
4469
4533
|
}
|
|
4470
4534
|
/**
|
|
@@ -4496,18 +4560,17 @@ var PathEditingEventHandler = class {
|
|
|
4496
4560
|
};
|
|
4497
4561
|
}
|
|
4498
4562
|
const totalVertices = positions.length;
|
|
4499
|
-
const totalVisibleVertices = totalVertices
|
|
4500
|
-
const isStartPoint =
|
|
4501
|
-
const isHiddenClimb =
|
|
4502
|
-
const canDelete =
|
|
4563
|
+
const totalVisibleVertices = totalVertices;
|
|
4564
|
+
const isStartPoint = false;
|
|
4565
|
+
const isHiddenClimb = false;
|
|
4566
|
+
const canDelete = totalVertices > 1;
|
|
4503
4567
|
let pathProperties;
|
|
4504
4568
|
if (entity) {
|
|
4505
4569
|
try {
|
|
4506
4570
|
const props = entity.properties;
|
|
4507
4571
|
pathProperties = {
|
|
4508
4572
|
altitudeMode: props?._altitudeMode?.getValue?.() ?? props?._altitudeMode,
|
|
4509
|
-
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
4510
|
-
hasHiddenClimb: props?._hasHiddenClimb?.getValue?.() ?? props?._hasHiddenClimb
|
|
4573
|
+
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
4511
4574
|
};
|
|
4512
4575
|
} catch {
|
|
4513
4576
|
}
|
|
@@ -4546,11 +4609,9 @@ var PathEditingEventHandler = class {
|
|
|
4546
4609
|
}
|
|
4547
4610
|
/**
|
|
4548
4611
|
* 处理插入顶点
|
|
4612
|
+
* 🆕 不再跳过隐藏爬升点
|
|
4549
4613
|
*/
|
|
4550
4614
|
handleInsertVertex(insertAt, pose, type) {
|
|
4551
|
-
if (this.hiddenClimbIndex === 1 && insertAt <= 1) {
|
|
4552
|
-
insertAt = 2;
|
|
4553
|
-
}
|
|
4554
4615
|
if (this.callbacks.onInsertVertex) {
|
|
4555
4616
|
this.callbacks.onInsertVertex(insertAt, pose.position, {
|
|
4556
4617
|
heading: pose.heading,
|
|
@@ -4581,6 +4642,10 @@ var PathEditingEventHandler = class {
|
|
|
4581
4642
|
}
|
|
4582
4643
|
/**
|
|
4583
4644
|
* 🆕 处理快速编辑模式的点击
|
|
4645
|
+
* 根据 altitudeMode 计算航点高度:
|
|
4646
|
+
* - absolute: 航点高度 = defaultAltitude
|
|
4647
|
+
* - relativeToGround: 航点高度 = 地形高度 + defaultAltitude
|
|
4648
|
+
* - relativeToStart: 航点高度 = 起飞点高度 + defaultAltitude
|
|
4584
4649
|
*/
|
|
4585
4650
|
handleQuickEditClick(movement) {
|
|
4586
4651
|
const position = this.getPositionFromMouse(movement);
|
|
@@ -4590,11 +4655,9 @@ var PathEditingEventHandler = class {
|
|
|
4590
4655
|
}
|
|
4591
4656
|
const quickEditOptions = this.callbacks.getQuickEditOptions?.();
|
|
4592
4657
|
if (!quickEditOptions) return;
|
|
4593
|
-
const {
|
|
4658
|
+
const { defaultAltitude, altitudeMode } = quickEditOptions;
|
|
4659
|
+
const newPosition = this.calculatePositionByAltitudeMode(position, defaultAltitude, altitudeMode);
|
|
4594
4660
|
const C = this.CesiumNS;
|
|
4595
|
-
const originalCarto = C.Cartographic.fromCartesian(position);
|
|
4596
|
-
const originalHeight = originalCarto.height;
|
|
4597
|
-
const newPosition = this.applyClimbHeight(position, climbHeight, altitudeMode);
|
|
4598
4661
|
const newCarto = C.Cartographic.fromCartesian(newPosition);
|
|
4599
4662
|
const newHeight = newCarto.height;
|
|
4600
4663
|
const positions = this.callbacks.getPositions?.() || [];
|
|
@@ -4609,8 +4672,7 @@ var PathEditingEventHandler = class {
|
|
|
4609
4672
|
insertAt,
|
|
4610
4673
|
heading: heading.toFixed(2),
|
|
4611
4674
|
altitudeMode,
|
|
4612
|
-
|
|
4613
|
-
originalHeight: originalHeight.toFixed(2),
|
|
4675
|
+
defaultAltitude,
|
|
4614
4676
|
finalHeight: newHeight.toFixed(2)
|
|
4615
4677
|
});
|
|
4616
4678
|
this.callbacks.onInsertVertex(insertAt, newPosition, {
|
|
@@ -4622,21 +4684,35 @@ var PathEditingEventHandler = class {
|
|
|
4622
4684
|
}
|
|
4623
4685
|
}
|
|
4624
4686
|
/**
|
|
4625
|
-
* 🆕
|
|
4687
|
+
* 🆕 根据高度模式计算航点位置
|
|
4688
|
+
* - absolute: 航点高度 = defaultAltitude
|
|
4689
|
+
* - relativeToGround: 航点高度 = 地形高度 + defaultAltitude
|
|
4690
|
+
* - relativeToStart: 航点高度 = 起飞点高度 + defaultAltitude
|
|
4626
4691
|
*/
|
|
4627
|
-
|
|
4692
|
+
calculatePositionByAltitudeMode(position, defaultAltitude, altitudeMode) {
|
|
4628
4693
|
const C = this.CesiumNS;
|
|
4629
4694
|
try {
|
|
4630
4695
|
const cartographic = C.Cartographic.fromCartesian(position);
|
|
4631
4696
|
const lon = C.Math.toDegrees(cartographic.longitude);
|
|
4632
4697
|
const lat = C.Math.toDegrees(cartographic.latitude);
|
|
4633
|
-
let
|
|
4634
|
-
if (altitudeMode === "
|
|
4635
|
-
|
|
4636
|
-
} else if (altitudeMode === "
|
|
4637
|
-
|
|
4698
|
+
let finalHeight;
|
|
4699
|
+
if (altitudeMode === "absolute") {
|
|
4700
|
+
finalHeight = defaultAltitude;
|
|
4701
|
+
} else if (altitudeMode === "relativeToGround") {
|
|
4702
|
+
const terrainHeight = queryTerrainHeightSync(this.CesiumNS, this.viewer, position);
|
|
4703
|
+
finalHeight = terrainHeight + defaultAltitude;
|
|
4704
|
+
} else if (altitudeMode === "relativeToStart") {
|
|
4705
|
+
const startPointAltitude = this.callbacks.getStartPointAltitude?.() ?? 0;
|
|
4706
|
+
finalHeight = startPointAltitude + defaultAltitude;
|
|
4707
|
+
} else {
|
|
4708
|
+
finalHeight = defaultAltitude;
|
|
4638
4709
|
}
|
|
4639
|
-
|
|
4710
|
+
console.log("[QuickEdit] \u9AD8\u5EA6\u8BA1\u7B97:", {
|
|
4711
|
+
altitudeMode,
|
|
4712
|
+
defaultAltitude,
|
|
4713
|
+
finalHeight
|
|
4714
|
+
});
|
|
4715
|
+
return C.Cartesian3.fromDegrees(lon, lat, finalHeight);
|
|
4640
4716
|
} catch (error) {
|
|
4641
4717
|
console.error("[QuickEdit] \u9AD8\u5EA6\u8BA1\u7B97\u5931\u8D25:", error);
|
|
4642
4718
|
return position;
|
|
@@ -4728,19 +4804,19 @@ var VertexHandleStyleManager = class {
|
|
|
4728
4804
|
__publicField(this, "selectedStyle");
|
|
4729
4805
|
const C = CesiumNS;
|
|
4730
4806
|
this.normalStyle = {
|
|
4731
|
-
pixelSize: options?.normal?.pixelSize ??
|
|
4807
|
+
pixelSize: options?.normal?.pixelSize ?? 6,
|
|
4732
4808
|
color: options?.normal?.color ?? C.Color.YELLOW,
|
|
4733
4809
|
outlineColor: options?.normal?.outlineColor ?? C.Color.BLACK,
|
|
4734
4810
|
outlineWidth: options?.normal?.outlineWidth ?? 1
|
|
4735
4811
|
};
|
|
4736
4812
|
this.editedStyle = {
|
|
4737
|
-
pixelSize: options?.edited?.pixelSize ??
|
|
4813
|
+
pixelSize: options?.edited?.pixelSize ?? 6,
|
|
4738
4814
|
color: options?.edited?.color ?? C.Color.CYAN,
|
|
4739
4815
|
outlineColor: options?.edited?.outlineColor ?? C.Color.BLACK,
|
|
4740
4816
|
outlineWidth: options?.edited?.outlineWidth ?? 1
|
|
4741
4817
|
};
|
|
4742
4818
|
this.selectedStyle = {
|
|
4743
|
-
pixelSize: options?.selected?.pixelSize ??
|
|
4819
|
+
pixelSize: options?.selected?.pixelSize ?? 8,
|
|
4744
4820
|
color: options?.selected?.color ?? C.Color.ORANGE,
|
|
4745
4821
|
outlineColor: options?.selected?.outlineColor ?? C.Color.BLACK,
|
|
4746
4822
|
outlineWidth: options?.selected?.outlineWidth ?? 2
|
|
@@ -4948,18 +5024,57 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
4948
5024
|
} catch {
|
|
4949
5025
|
positions = [];
|
|
4950
5026
|
}
|
|
4951
|
-
|
|
5027
|
+
const hiddenClimbIndex = void 0;
|
|
5028
|
+
let currentAltitudeMode = "absolute";
|
|
5029
|
+
let currentDefaultAltitude = 100;
|
|
5030
|
+
try {
|
|
5031
|
+
const props = entity.properties;
|
|
5032
|
+
const storedMode = props?._altitudeMode?.getValue?.() ?? props?._altitudeMode;
|
|
5033
|
+
if (storedMode === "absolute" || storedMode === "relativeToGround" || storedMode === "relativeToStart") {
|
|
5034
|
+
currentAltitudeMode = storedMode;
|
|
5035
|
+
}
|
|
5036
|
+
const storedDefaultAlt = props?._defaultAltitude?.getValue?.() ?? props?._defaultAltitude;
|
|
5037
|
+
if (typeof storedDefaultAlt === "number") {
|
|
5038
|
+
currentDefaultAltitude = storedDefaultAlt;
|
|
5039
|
+
}
|
|
5040
|
+
} catch {
|
|
5041
|
+
}
|
|
5042
|
+
if (options?.altitudeMode) {
|
|
5043
|
+
currentAltitudeMode = options.altitudeMode;
|
|
5044
|
+
}
|
|
5045
|
+
if (options?.defaultAltitude !== void 0) {
|
|
5046
|
+
currentDefaultAltitude = options.defaultAltitude;
|
|
5047
|
+
}
|
|
5048
|
+
let startPointAltitude = 0;
|
|
5049
|
+
try {
|
|
5050
|
+
if (positions.length > 0) {
|
|
5051
|
+
const startCarto = C.Cartographic.fromCartesian(positions[0]);
|
|
5052
|
+
startPointAltitude = startCarto.height ?? 0;
|
|
5053
|
+
}
|
|
5054
|
+
} catch {
|
|
5055
|
+
}
|
|
5056
|
+
const terrainHeightsCache = /* @__PURE__ */ new Map();
|
|
5057
|
+
const useGlobalHeightFlags = [];
|
|
4952
5058
|
try {
|
|
4953
5059
|
const props = entity.properties;
|
|
4954
|
-
const
|
|
4955
|
-
if (
|
|
5060
|
+
const storedFlags = props?._useGlobalHeightFlags?.getValue?.() ?? props?._useGlobalHeightFlags;
|
|
5061
|
+
if (Array.isArray(storedFlags)) {
|
|
5062
|
+
storedFlags.forEach((flag, idx) => {
|
|
5063
|
+
useGlobalHeightFlags[idx] = flag;
|
|
5064
|
+
});
|
|
5065
|
+
}
|
|
4956
5066
|
} catch {
|
|
4957
5067
|
}
|
|
5068
|
+
while (useGlobalHeightFlags.length < positions.length) {
|
|
5069
|
+
useGlobalHeightFlags.push(false);
|
|
5070
|
+
}
|
|
4958
5071
|
let quickEditEnabled = false;
|
|
4959
5072
|
let quickEditOptions = {
|
|
4960
5073
|
enabled: false,
|
|
4961
|
-
climbHeight:
|
|
4962
|
-
|
|
5074
|
+
climbHeight: currentDefaultAltitude,
|
|
5075
|
+
// 使用当前默认高度
|
|
5076
|
+
altitudeMode: currentAltitudeMode
|
|
5077
|
+
// 使用当前高度模式
|
|
4963
5078
|
};
|
|
4964
5079
|
if (options?.quickEdit) {
|
|
4965
5080
|
if (typeof options.quickEdit === "boolean") {
|
|
@@ -4992,33 +5107,23 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
4992
5107
|
} catch {
|
|
4993
5108
|
}
|
|
4994
5109
|
const handles = positions.map((p, i) => {
|
|
4995
|
-
if (hiddenClimbIndex === i) return void 0;
|
|
4996
|
-
const isStartPoint = i === 0;
|
|
4997
5110
|
const h2 = existing[i];
|
|
4998
5111
|
if (h2) {
|
|
4999
5112
|
try {
|
|
5000
5113
|
h2.position = p;
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
h2.point.outlineWidth = 1;
|
|
5007
|
-
}
|
|
5114
|
+
h2.point = h2.point ?? { pixelSize: 6 };
|
|
5115
|
+
h2.point.pixelSize = 6;
|
|
5116
|
+
h2.point.color = C.Color.YELLOW;
|
|
5117
|
+
h2.point.outlineColor = C.Color.BLACK;
|
|
5118
|
+
h2.point.outlineWidth = 1;
|
|
5008
5119
|
h2.properties = { _type: "path-vertex", _ownerId: ownerId, _vertexIndex: i };
|
|
5009
5120
|
} catch {
|
|
5010
5121
|
}
|
|
5011
5122
|
return h2;
|
|
5012
5123
|
}
|
|
5013
|
-
if (isStartPoint) {
|
|
5014
|
-
return layer.entities.add({
|
|
5015
|
-
position: p,
|
|
5016
|
-
properties: { _type: "path-vertex", _ownerId: ownerId, _vertexIndex: i }
|
|
5017
|
-
});
|
|
5018
|
-
}
|
|
5019
5124
|
return layer.entities.add({
|
|
5020
5125
|
position: p,
|
|
5021
|
-
point: { pixelSize:
|
|
5126
|
+
point: { pixelSize: 6, color: C.Color.YELLOW, outlineColor: C.Color.BLACK, outlineWidth: 1 },
|
|
5022
5127
|
properties: { _type: "path-vertex", _ownerId: ownerId, _vertexIndex: i }
|
|
5023
5128
|
});
|
|
5024
5129
|
});
|
|
@@ -5035,8 +5140,6 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5035
5140
|
};
|
|
5036
5141
|
const createOrUpdateMarkerForIndex = (idx) => {
|
|
5037
5142
|
try {
|
|
5038
|
-
if (hiddenClimbIndex === 1 && idx === 1) return;
|
|
5039
|
-
if (idx === 0) return;
|
|
5040
5143
|
const pos = positions[idx];
|
|
5041
5144
|
if (!pos) return;
|
|
5042
5145
|
const markerLayer = ensureMarkerLayer();
|
|
@@ -5118,7 +5221,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5118
5221
|
};
|
|
5119
5222
|
const getTotalDistance = () => {
|
|
5120
5223
|
if (positions.length < 2) return 0;
|
|
5121
|
-
return calculatePathDistance(CesiumNS, positions, positions.length - 1
|
|
5224
|
+
return calculatePathDistance(CesiumNS, positions, positions.length - 1);
|
|
5122
5225
|
};
|
|
5123
5226
|
const vertexInsertionHandler = new VertexInsertionHandler({
|
|
5124
5227
|
CesiumNS,
|
|
@@ -5127,7 +5230,40 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5127
5230
|
hiddenClimbIndex
|
|
5128
5231
|
});
|
|
5129
5232
|
let cursorStart = positions[positions.length - 1];
|
|
5130
|
-
if (!cursorStart) cursorStart = positions[
|
|
5233
|
+
if (!cursorStart) cursorStart = positions[0];
|
|
5234
|
+
if (!cursorStart) {
|
|
5235
|
+
try {
|
|
5236
|
+
const cameraPos = viewer.camera.positionCartographic;
|
|
5237
|
+
if (cameraPos) {
|
|
5238
|
+
let initialHeight = currentDefaultAltitude;
|
|
5239
|
+
if (currentAltitudeMode === "relativeToGround") {
|
|
5240
|
+
const terrainHeight = queryTerrainHeightSync(
|
|
5241
|
+
CesiumNS,
|
|
5242
|
+
viewer,
|
|
5243
|
+
C.Cartesian3.fromRadians(cameraPos.longitude, cameraPos.latitude, 0)
|
|
5244
|
+
);
|
|
5245
|
+
initialHeight = terrainHeight + currentDefaultAltitude;
|
|
5246
|
+
console.log("[PathEditing] relativeToGround \u6A21\u5F0F\uFF0C\u5730\u5F62\u9AD8\u5EA6:", terrainHeight, "\u521D\u59CB\u9AD8\u5EA6:", initialHeight);
|
|
5247
|
+
} else if (currentAltitudeMode === "relativeToStart") {
|
|
5248
|
+
initialHeight = currentDefaultAltitude;
|
|
5249
|
+
console.log("[PathEditing] relativeToStart \u6A21\u5F0F\uFF08\u7A7A\u822A\u7EBF\uFF09\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u9AD8\u5EA6:", initialHeight);
|
|
5250
|
+
}
|
|
5251
|
+
cursorStart = C.Cartesian3.fromRadians(
|
|
5252
|
+
cameraPos.longitude,
|
|
5253
|
+
cameraPos.latitude,
|
|
5254
|
+
initialHeight
|
|
5255
|
+
);
|
|
5256
|
+
console.log("[PathEditing] \u7A7A\u822A\u7EBF\uFF0C\u4F7F\u7528\u76F8\u673A\u4F4D\u7F6E\u521D\u59CB\u5316\u6E38\u6807:", {
|
|
5257
|
+
lon: C.Math.toDegrees(cameraPos.longitude),
|
|
5258
|
+
lat: C.Math.toDegrees(cameraPos.latitude),
|
|
5259
|
+
height: initialHeight,
|
|
5260
|
+
altitudeMode: currentAltitudeMode
|
|
5261
|
+
});
|
|
5262
|
+
}
|
|
5263
|
+
} catch (error) {
|
|
5264
|
+
console.warn("[PathEditing] \u65E0\u6CD5\u83B7\u53D6\u76F8\u673A\u4F4D\u7F6E:", error);
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5131
5267
|
let airplaneCursor;
|
|
5132
5268
|
const insertVertex = (insertAt, p3, poseOrient) => {
|
|
5133
5269
|
console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u524D positions \u957F\u5EA6:", positions.length, "insertAt:", insertAt);
|
|
@@ -5144,7 +5280,9 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5144
5280
|
vertexLabelManager,
|
|
5145
5281
|
heightMarkers,
|
|
5146
5282
|
airplaneCursor,
|
|
5147
|
-
poseOrient
|
|
5283
|
+
poseOrient,
|
|
5284
|
+
useGlobalHeightFlags
|
|
5285
|
+
// 🆕 传递 useGlobalHeightFlags
|
|
5148
5286
|
);
|
|
5149
5287
|
console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length, "actualIndex:", actualIndex);
|
|
5150
5288
|
entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
|
|
@@ -5153,16 +5291,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5153
5291
|
};
|
|
5154
5292
|
const deleteVertex = (deleteAt) => {
|
|
5155
5293
|
try {
|
|
5156
|
-
if (
|
|
5157
|
-
console.warn("Cannot delete start point");
|
|
5158
|
-
return;
|
|
5159
|
-
}
|
|
5160
|
-
if (hiddenClimbIndex !== void 0 && deleteAt === hiddenClimbIndex) {
|
|
5161
|
-
console.warn("Cannot delete hidden climb point");
|
|
5162
|
-
return;
|
|
5163
|
-
}
|
|
5164
|
-
const visibleVertexCount = positions.length - (hiddenClimbIndex === 1 ? 1 : 0);
|
|
5165
|
-
if (visibleVertexCount <= 1) {
|
|
5294
|
+
if (positions.length <= 1) {
|
|
5166
5295
|
console.warn("Cannot delete last vertex");
|
|
5167
5296
|
return;
|
|
5168
5297
|
}
|
|
@@ -5186,6 +5315,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5186
5315
|
rolls.splice(deleteAt, 1);
|
|
5187
5316
|
fovs.splice(deleteAt, 1);
|
|
5188
5317
|
heightMarkers.splice(deleteAt, 1);
|
|
5318
|
+
useGlobalHeightFlags.splice(deleteAt, 1);
|
|
5189
5319
|
console.log("[PathEditing] \u5220\u9664\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length);
|
|
5190
5320
|
entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
|
|
5191
5321
|
const newEditedIndices = /* @__PURE__ */ new Set();
|
|
@@ -5247,9 +5377,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5247
5377
|
}
|
|
5248
5378
|
},
|
|
5249
5379
|
// frustumLengthFactor: options?.preview?.lengthFactor ?? 0.3,
|
|
5250
|
-
fovDeg: options?.preview?.fov ?? 50
|
|
5251
|
-
minHeight: options?.minHeight
|
|
5252
|
-
// 传递最小高度限制
|
|
5380
|
+
fovDeg: options?.preview?.fov ?? 50
|
|
5253
5381
|
});
|
|
5254
5382
|
if (options?.preview?.enabled !== false && airplaneCursor) {
|
|
5255
5383
|
preview = new PathPreview(CesiumNS, viewer, {
|
|
@@ -5293,8 +5421,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5293
5421
|
{
|
|
5294
5422
|
CesiumNS,
|
|
5295
5423
|
viewer,
|
|
5296
|
-
hiddenClimbIndex
|
|
5297
|
-
minHeight: options?.minHeight
|
|
5424
|
+
hiddenClimbIndex
|
|
5298
5425
|
},
|
|
5299
5426
|
{
|
|
5300
5427
|
onVertexSelect: (index) => setActiveIndex(index),
|
|
@@ -5325,7 +5452,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5325
5452
|
},
|
|
5326
5453
|
onDeleteVertex: (index) => {
|
|
5327
5454
|
const totalBefore = positions.length;
|
|
5328
|
-
const displayNumber =
|
|
5455
|
+
const displayNumber = index;
|
|
5329
5456
|
deleteVertex(index);
|
|
5330
5457
|
if (options?.onVertexDeleteDetail) {
|
|
5331
5458
|
try {
|
|
@@ -5378,7 +5505,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5378
5505
|
};
|
|
5379
5506
|
} catch {
|
|
5380
5507
|
}
|
|
5381
|
-
const displayNumber =
|
|
5508
|
+
const displayNumber = index;
|
|
5382
5509
|
const dragMoveInfo = {
|
|
5383
5510
|
index,
|
|
5384
5511
|
displayNumber,
|
|
@@ -5395,6 +5522,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5395
5522
|
onVertexDragEnd: (index, finalPosition) => {
|
|
5396
5523
|
editedIndices.add(index);
|
|
5397
5524
|
positions[index] = finalPosition;
|
|
5525
|
+
useGlobalHeightFlags[index] = false;
|
|
5398
5526
|
if (handles[index]) {
|
|
5399
5527
|
handleStyleManager.applyStyle(handles[index], "edited");
|
|
5400
5528
|
}
|
|
@@ -5441,10 +5569,29 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5441
5569
|
getCursorPose: () => airplaneCursor?.getPose(),
|
|
5442
5570
|
// 🆕 快速编辑回调
|
|
5443
5571
|
getQuickEditEnabled: () => quickEditEnabled,
|
|
5444
|
-
getQuickEditOptions: () =>
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5572
|
+
getQuickEditOptions: () => {
|
|
5573
|
+
let climbHeight = 0;
|
|
5574
|
+
try {
|
|
5575
|
+
const props = entity.properties;
|
|
5576
|
+
climbHeight = props?._climbHeight?.getValue?.() ?? props?._climbHeight ?? 0;
|
|
5577
|
+
} catch {
|
|
5578
|
+
}
|
|
5579
|
+
return {
|
|
5580
|
+
climbHeight,
|
|
5581
|
+
defaultAltitude: currentDefaultAltitude,
|
|
5582
|
+
altitudeMode: currentAltitudeMode
|
|
5583
|
+
};
|
|
5584
|
+
},
|
|
5585
|
+
// 🆕 高度模式相关回调
|
|
5586
|
+
getStartPointAltitude: () => startPointAltitude,
|
|
5587
|
+
getDefaultAltitude: () => currentDefaultAltitude,
|
|
5588
|
+
// 🆕 useGlobalHeightFlags 相关回调
|
|
5589
|
+
getUseGlobalHeightFlags: () => useGlobalHeightFlags,
|
|
5590
|
+
setUseGlobalHeightFlag: (index, value) => {
|
|
5591
|
+
if (index >= 0 && index < useGlobalHeightFlags.length) {
|
|
5592
|
+
useGlobalHeightFlags[index] = value;
|
|
5593
|
+
}
|
|
5594
|
+
}
|
|
5448
5595
|
}
|
|
5449
5596
|
);
|
|
5450
5597
|
const cleanupSession = () => {
|
|
@@ -5484,6 +5631,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5484
5631
|
const buildVertexDetailInfo = (index) => {
|
|
5485
5632
|
const position = positions[index];
|
|
5486
5633
|
let coordinates = { longitude: 0, latitude: 0, height: 0 };
|
|
5634
|
+
let ellipsoidHeight = 0;
|
|
5487
5635
|
try {
|
|
5488
5636
|
const cartographic = C.Cartographic.fromCartesian(position);
|
|
5489
5637
|
coordinates = {
|
|
@@ -5491,8 +5639,16 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5491
5639
|
latitude: C.Math.toDegrees(cartographic.latitude),
|
|
5492
5640
|
height: cartographic.height
|
|
5493
5641
|
};
|
|
5642
|
+
ellipsoidHeight = cartographic.height ?? 0;
|
|
5494
5643
|
} catch {
|
|
5495
5644
|
}
|
|
5645
|
+
const terrainHeight = terrainHeightsCache.get(index) ?? 0;
|
|
5646
|
+
const relativeHeight = calculateRelativeHeight(
|
|
5647
|
+
currentAltitudeMode,
|
|
5648
|
+
ellipsoidHeight,
|
|
5649
|
+
startPointAltitude,
|
|
5650
|
+
terrainHeight
|
|
5651
|
+
);
|
|
5496
5652
|
const pose = {
|
|
5497
5653
|
heading: headings[index] ?? 0,
|
|
5498
5654
|
pitch: pitches[index] ?? 0,
|
|
@@ -5500,18 +5656,17 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5500
5656
|
fov: fovs[index] ?? 50
|
|
5501
5657
|
};
|
|
5502
5658
|
const totalVertices = positions.length;
|
|
5503
|
-
const totalVisibleVertices = totalVertices
|
|
5504
|
-
const isStartPoint =
|
|
5505
|
-
const isHiddenClimb =
|
|
5506
|
-
const canDelete =
|
|
5507
|
-
const displayNumber =
|
|
5659
|
+
const totalVisibleVertices = totalVertices;
|
|
5660
|
+
const isStartPoint = false;
|
|
5661
|
+
const isHiddenClimb = false;
|
|
5662
|
+
const canDelete = totalVertices > 1;
|
|
5663
|
+
const displayNumber = index;
|
|
5508
5664
|
let pathProperties;
|
|
5509
5665
|
try {
|
|
5510
5666
|
const props = entity.properties;
|
|
5511
5667
|
pathProperties = {
|
|
5512
5668
|
altitudeMode: props?._altitudeMode?.getValue?.() ?? props?._altitudeMode,
|
|
5513
|
-
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
5514
|
-
hasHiddenClimb: props?._hasHiddenClimb?.getValue?.() ?? props?._hasHiddenClimb
|
|
5669
|
+
climbHeight: props?._climbHeight?.getValue?.() ?? props?._climbHeight
|
|
5515
5670
|
};
|
|
5516
5671
|
} catch {
|
|
5517
5672
|
}
|
|
@@ -5527,44 +5682,68 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5527
5682
|
totalVisibleVertices,
|
|
5528
5683
|
totalVertices,
|
|
5529
5684
|
entity,
|
|
5530
|
-
pathProperties
|
|
5685
|
+
pathProperties,
|
|
5686
|
+
useGlobalHeight: useGlobalHeightFlags[index] ?? false,
|
|
5687
|
+
// 🆕 添加 useGlobalHeight
|
|
5688
|
+
ellipsoidHeight,
|
|
5689
|
+
// 🆕 添加椭球高度
|
|
5690
|
+
relativeHeight
|
|
5691
|
+
// 🆕 添加相对高度
|
|
5531
5692
|
};
|
|
5532
5693
|
};
|
|
5533
5694
|
return {
|
|
5534
5695
|
/** 保存并退出编辑模式 */
|
|
5535
5696
|
saveAndStop: () => {
|
|
5536
5697
|
stateManager.persistToEntity(positions, headings, pitches, rolls, fovs);
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5698
|
+
try {
|
|
5699
|
+
entity.properties._altitudeMode = currentAltitudeMode;
|
|
5700
|
+
entity.properties._defaultAltitude = currentDefaultAltitude;
|
|
5701
|
+
entity.properties._useGlobalHeightFlags = useGlobalHeightFlags.slice();
|
|
5702
|
+
} catch {
|
|
5703
|
+
}
|
|
5704
|
+
let altitudeMode = currentAltitudeMode;
|
|
5541
5705
|
let climbHeight;
|
|
5542
|
-
let hasHiddenClimb;
|
|
5543
5706
|
try {
|
|
5544
5707
|
const props = entity.properties;
|
|
5545
|
-
altitudeMode = props?._altitudeMode?.getValue?.() ?? props?._altitudeMode;
|
|
5546
5708
|
climbHeight = props?._climbHeight?.getValue?.() ?? props?._climbHeight;
|
|
5547
|
-
hasHiddenClimb = props?._hasHiddenClimb?.getValue?.() ?? props?._hasHiddenClimb;
|
|
5548
5709
|
} catch {
|
|
5549
5710
|
}
|
|
5550
|
-
const waypointData = positions.map((position, index) =>
|
|
5551
|
-
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5711
|
+
const waypointData = positions.map((position, index) => {
|
|
5712
|
+
let ellipsoidHeight = 0;
|
|
5713
|
+
try {
|
|
5714
|
+
const carto = C.Cartographic.fromCartesian(position);
|
|
5715
|
+
ellipsoidHeight = carto.height ?? 0;
|
|
5716
|
+
} catch {
|
|
5717
|
+
}
|
|
5718
|
+
const terrainHeight = terrainHeightsCache.get(index) ?? 0;
|
|
5719
|
+
const relativeHeight = calculateRelativeHeight(
|
|
5720
|
+
currentAltitudeMode,
|
|
5721
|
+
ellipsoidHeight,
|
|
5722
|
+
startPointAltitude,
|
|
5723
|
+
terrainHeight
|
|
5724
|
+
);
|
|
5725
|
+
return {
|
|
5726
|
+
position,
|
|
5727
|
+
heading: headings[index] ?? 0,
|
|
5728
|
+
pitch: pitches[index] ?? -10,
|
|
5729
|
+
roll: rolls[index] ?? 0,
|
|
5730
|
+
fov: fovs[index] ?? 50,
|
|
5731
|
+
index,
|
|
5732
|
+
distance: calculatePathDistance(CesiumNS, positions, index),
|
|
5733
|
+
ellipsoidHeight,
|
|
5734
|
+
relativeHeight,
|
|
5735
|
+
useGlobalHeight: useGlobalHeightFlags[index] ?? false
|
|
5736
|
+
// 🆕 添加 useGlobalHeight
|
|
5737
|
+
};
|
|
5738
|
+
});
|
|
5559
5739
|
cleanupSession();
|
|
5560
5740
|
return {
|
|
5561
5741
|
entity,
|
|
5562
5742
|
positions: positions.slice(),
|
|
5563
|
-
startPoint,
|
|
5564
5743
|
climbHeight,
|
|
5565
5744
|
waypointData,
|
|
5566
5745
|
altitudeMode,
|
|
5567
|
-
|
|
5746
|
+
defaultAltitude: currentDefaultAltitude
|
|
5568
5747
|
};
|
|
5569
5748
|
},
|
|
5570
5749
|
/** 不保存退出(回滚到进入编辑时的状态) */
|
|
@@ -5787,45 +5966,32 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5787
5966
|
*/
|
|
5788
5967
|
getCursorPose: () => airplaneCursor?.getPose(),
|
|
5789
5968
|
/**
|
|
5790
|
-
* 🆕
|
|
5791
|
-
*
|
|
5792
|
-
* @param
|
|
5969
|
+
* 🆕 更新爬升高度(climbHeight)
|
|
5970
|
+
* 更新实体属性中的 _climbHeight 值
|
|
5971
|
+
* @param newClimbHeight 新的爬升高度(米)
|
|
5793
5972
|
* @returns 是否更新成功
|
|
5794
5973
|
*/
|
|
5795
|
-
updateClimbHeight: function(
|
|
5796
|
-
if (hiddenClimbIndex !== 1 || positions.length < 2) {
|
|
5797
|
-
console.warn("[updateClimbHeight] No hidden climb point exists");
|
|
5798
|
-
return false;
|
|
5799
|
-
}
|
|
5974
|
+
updateClimbHeight: function(newClimbHeight) {
|
|
5800
5975
|
try {
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
const success = this.updateWaypointAltitude(1, newAltitude);
|
|
5805
|
-
if (success) {
|
|
5806
|
-
try {
|
|
5807
|
-
entity.properties._climbHeight = climbHeight;
|
|
5808
|
-
} catch {
|
|
5809
|
-
}
|
|
5810
|
-
console.log("[updateClimbHeight] \u2705 \u722C\u5347\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", climbHeight, "\u7C73");
|
|
5811
|
-
}
|
|
5812
|
-
return success;
|
|
5976
|
+
entity.properties._climbHeight = newClimbHeight;
|
|
5977
|
+
console.log("[updateClimbHeight] \u2705 \u722C\u5347\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", newClimbHeight, "\u7C73");
|
|
5978
|
+
return true;
|
|
5813
5979
|
} catch (error) {
|
|
5814
5980
|
console.error("[updateClimbHeight] Error:", error);
|
|
5815
5981
|
return false;
|
|
5816
5982
|
}
|
|
5817
5983
|
},
|
|
5818
5984
|
/**
|
|
5819
|
-
* 🆕
|
|
5820
|
-
* @returns
|
|
5985
|
+
* 🆕 获取第一个航点信息
|
|
5986
|
+
* @returns 第一个航点的经纬度和高度
|
|
5821
5987
|
*/
|
|
5822
5988
|
getStartPoint: () => {
|
|
5823
5989
|
if (positions.length < 1) return null;
|
|
5824
5990
|
try {
|
|
5825
|
-
const
|
|
5826
|
-
const carto = C.Cartographic.fromCartesian(
|
|
5991
|
+
const firstPos = positions[0];
|
|
5992
|
+
const carto = C.Cartographic.fromCartesian(firstPos);
|
|
5827
5993
|
return {
|
|
5828
|
-
position:
|
|
5994
|
+
position: firstPos,
|
|
5829
5995
|
latitude: C.Math.toDegrees(carto.latitude),
|
|
5830
5996
|
longitude: C.Math.toDegrees(carto.longitude),
|
|
5831
5997
|
altitude: carto.height
|
|
@@ -5833,6 +5999,123 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
|
|
|
5833
5999
|
} catch {
|
|
5834
6000
|
return null;
|
|
5835
6001
|
}
|
|
6002
|
+
},
|
|
6003
|
+
/**
|
|
6004
|
+
* 🆕 获取当前高度模式
|
|
6005
|
+
*/
|
|
6006
|
+
getAltitudeMode: () => currentAltitudeMode,
|
|
6007
|
+
/**
|
|
6008
|
+
* 🆕 获取当前默认高度
|
|
6009
|
+
*/
|
|
6010
|
+
getDefaultAltitude: () => currentDefaultAltitude,
|
|
6011
|
+
/**
|
|
6012
|
+
* 🆕 更新默认高度
|
|
6013
|
+
*/
|
|
6014
|
+
updateDefaultAltitude: (altitude) => {
|
|
6015
|
+
currentDefaultAltitude = altitude;
|
|
6016
|
+
quickEditOptions.climbHeight = altitude;
|
|
6017
|
+
try {
|
|
6018
|
+
entity.properties._defaultAltitude = altitude;
|
|
6019
|
+
} catch {
|
|
6020
|
+
}
|
|
6021
|
+
console.log("[updateDefaultAltitude] \u2705 \u9ED8\u8BA4\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", altitude, "\u7C73");
|
|
6022
|
+
},
|
|
6023
|
+
/**
|
|
6024
|
+
* 🆕 切换高度计算模式(异步,会重算所有航点高度)
|
|
6025
|
+
* @param newMode 新的高度模式
|
|
6026
|
+
* @param newDefaultAltitude 新的默认高度(可选)
|
|
6027
|
+
* @param options 选项(terrainProvider, onProgress)
|
|
6028
|
+
* @returns 切换结果 { success: boolean; error?: string }
|
|
6029
|
+
*/
|
|
6030
|
+
changeAltitudeMode: async (newMode, newDefaultAltitude, options2) => {
|
|
6031
|
+
try {
|
|
6032
|
+
const onProgress = options2?.onProgress;
|
|
6033
|
+
if (newMode === "relativeToGround") {
|
|
6034
|
+
const terrainProvider = options2?.terrainProvider ?? viewer.terrainProvider;
|
|
6035
|
+
const C_any = C;
|
|
6036
|
+
if (!terrainProvider || C_any.EllipsoidTerrainProvider && terrainProvider instanceof C_any.EllipsoidTerrainProvider) {
|
|
6037
|
+
console.error("[changeAltitudeMode] \u274C relativeToGround \u6A21\u5F0F\u9700\u8981\u6709\u6548\u7684 terrain \u56FE\u5C42");
|
|
6038
|
+
onProgress?.("error");
|
|
6039
|
+
return {
|
|
6040
|
+
success: false,
|
|
6041
|
+
error: "Terrain provider required for relativeToGround mode"
|
|
6042
|
+
};
|
|
6043
|
+
}
|
|
6044
|
+
}
|
|
6045
|
+
onProgress?.("loading");
|
|
6046
|
+
const oldMode = currentAltitudeMode;
|
|
6047
|
+
if (newDefaultAltitude !== void 0) {
|
|
6048
|
+
currentDefaultAltitude = newDefaultAltitude;
|
|
6049
|
+
quickEditOptions.climbHeight = newDefaultAltitude;
|
|
6050
|
+
}
|
|
6051
|
+
if (newMode === "relativeToGround" || oldMode === "relativeToGround") {
|
|
6052
|
+
const terrainHeights = await queryTerrainHeights(CesiumNS, viewer, positions);
|
|
6053
|
+
terrainHeights.forEach((height, index) => {
|
|
6054
|
+
terrainHeightsCache.set(index, height);
|
|
6055
|
+
});
|
|
6056
|
+
console.log("[changeAltitudeMode] \u5DF2\u67E5\u8BE2\u5730\u5F62\u9AD8\u5EA6:", terrainHeights);
|
|
6057
|
+
}
|
|
6058
|
+
if (newMode !== oldMode) {
|
|
6059
|
+
console.log("[changeAltitudeMode] \u5207\u6362\u9AD8\u5EA6\u6A21\u5F0F:", oldMode, "->", newMode);
|
|
6060
|
+
for (let i = 0; i < positions.length; i++) {
|
|
6061
|
+
const currentPos = positions[i];
|
|
6062
|
+
const carto = C.Cartographic.fromCartesian(currentPos);
|
|
6063
|
+
const currentAbsoluteHeight = carto.height ?? 0;
|
|
6064
|
+
const oldTerrainHeight = terrainHeightsCache.get(i) ?? 0;
|
|
6065
|
+
const relativeHeight = calculateRelativeHeight(
|
|
6066
|
+
oldMode,
|
|
6067
|
+
currentAbsoluteHeight,
|
|
6068
|
+
startPointAltitude,
|
|
6069
|
+
oldTerrainHeight
|
|
6070
|
+
);
|
|
6071
|
+
const newTerrainHeight = terrainHeightsCache.get(i) ?? 0;
|
|
6072
|
+
const newAbsoluteHeight = calculateAbsoluteHeight(
|
|
6073
|
+
newMode,
|
|
6074
|
+
relativeHeight,
|
|
6075
|
+
startPointAltitude,
|
|
6076
|
+
newTerrainHeight
|
|
6077
|
+
);
|
|
6078
|
+
const newPosition = C.Cartesian3.fromRadians(
|
|
6079
|
+
carto.longitude,
|
|
6080
|
+
carto.latitude,
|
|
6081
|
+
newAbsoluteHeight
|
|
6082
|
+
);
|
|
6083
|
+
positions[i] = newPosition;
|
|
6084
|
+
if (handles[i]) {
|
|
6085
|
+
try {
|
|
6086
|
+
handles[i].position = newPosition;
|
|
6087
|
+
} catch {
|
|
6088
|
+
}
|
|
6089
|
+
}
|
|
6090
|
+
try {
|
|
6091
|
+
vertexLabelManager.updateLabelPosition(i, newPosition);
|
|
6092
|
+
} catch {
|
|
6093
|
+
}
|
|
6094
|
+
try {
|
|
6095
|
+
createOrUpdateMarkerForIndex(i);
|
|
6096
|
+
} catch {
|
|
6097
|
+
}
|
|
6098
|
+
}
|
|
6099
|
+
currentAltitudeMode = newMode;
|
|
6100
|
+
quickEditOptions.altitudeMode = newMode;
|
|
6101
|
+
try {
|
|
6102
|
+
entity.properties._altitudeMode = newMode;
|
|
6103
|
+
entity.properties._defaultAltitude = currentDefaultAltitude;
|
|
6104
|
+
} catch {
|
|
6105
|
+
}
|
|
6106
|
+
entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
|
|
6107
|
+
}
|
|
6108
|
+
console.log("[changeAltitudeMode] \u2705 \u9AD8\u5EA6\u6A21\u5F0F\u5207\u6362\u5B8C\u6210:", {
|
|
6109
|
+
mode: newMode,
|
|
6110
|
+
defaultAltitude: currentDefaultAltitude
|
|
6111
|
+
});
|
|
6112
|
+
onProgress?.("done");
|
|
6113
|
+
return { success: true };
|
|
6114
|
+
} catch (error) {
|
|
6115
|
+
console.error("[changeAltitudeMode] Error:", error);
|
|
6116
|
+
options2?.onProgress?.("error");
|
|
6117
|
+
return { success: false, error: String(error) };
|
|
6118
|
+
}
|
|
5836
6119
|
}
|
|
5837
6120
|
};
|
|
5838
6121
|
}
|
|
@@ -5842,221 +6125,18 @@ function fovToFocalLength(fovDeg) {
|
|
|
5842
6125
|
return sensorWidth / (2 * Math.tan(fovRad / 2));
|
|
5843
6126
|
}
|
|
5844
6127
|
|
|
5845
|
-
// src/core/path-manager/ArrowShape.ts
|
|
5846
|
-
var ArrowShape = class {
|
|
5847
|
-
constructor(CesiumNS, opts = {}) {
|
|
5848
|
-
this.CesiumNS = CesiumNS;
|
|
5849
|
-
__publicField(this, "height");
|
|
5850
|
-
__publicField(this, "shaftHeight");
|
|
5851
|
-
__publicField(this, "headHeight");
|
|
5852
|
-
__publicField(this, "shaftRadius");
|
|
5853
|
-
__publicField(this, "headRadius");
|
|
5854
|
-
__publicField(this, "baseRadius");
|
|
5855
|
-
__publicField(this, "color");
|
|
5856
|
-
__publicField(this, "shaftAlpha");
|
|
5857
|
-
__publicField(this, "headAlpha");
|
|
5858
|
-
__publicField(this, "baseAlpha");
|
|
5859
|
-
__publicField(this, "outline");
|
|
5860
|
-
__publicField(this, "outlineColor");
|
|
5861
|
-
// 动态缩放相关
|
|
5862
|
-
__publicField(this, "dynamicScale");
|
|
5863
|
-
__publicField(this, "viewer");
|
|
5864
|
-
__publicField(this, "referenceDistance");
|
|
5865
|
-
__publicField(this, "minScale");
|
|
5866
|
-
__publicField(this, "maxScale");
|
|
5867
|
-
__publicField(this, "cachedScaleFactor", 1);
|
|
5868
|
-
const C = this.CesiumNS;
|
|
5869
|
-
this.shaftHeight = opts.shaftHeight ?? 17;
|
|
5870
|
-
this.headHeight = opts.headHeight ?? 8;
|
|
5871
|
-
this.height = opts.height ?? this.shaftHeight + this.headHeight;
|
|
5872
|
-
this.shaftRadius = opts.shaftRadius ?? 3;
|
|
5873
|
-
this.headRadius = opts.headRadius ?? 6;
|
|
5874
|
-
this.baseRadius = opts.baseRadius ?? 8;
|
|
5875
|
-
this.color = opts.color ? C.Color.fromCssColorString(opts.color) : C.Color.fromCssColorString("#FFD700");
|
|
5876
|
-
this.shaftAlpha = opts.shaftAlpha ?? 1;
|
|
5877
|
-
this.headAlpha = opts.headAlpha ?? 1;
|
|
5878
|
-
this.baseAlpha = opts.baseAlpha ?? 0.65;
|
|
5879
|
-
this.outline = opts.outline ?? false;
|
|
5880
|
-
this.outlineColor = opts.outlineColor ? C.Color.fromCssColorString(opts.outlineColor) : this.color.darken(0.3, new C.Color());
|
|
5881
|
-
this.dynamicScale = opts.dynamicScale ?? false;
|
|
5882
|
-
this.viewer = opts.viewer;
|
|
5883
|
-
this.referenceDistance = opts.referenceDistance ?? 500;
|
|
5884
|
-
this.minScale = opts.minScale ?? 0.3;
|
|
5885
|
-
this.maxScale = opts.maxScale ?? 3;
|
|
5886
|
-
}
|
|
5887
|
-
/**
|
|
5888
|
-
* Create arrow entities at given position
|
|
5889
|
-
* Returns array of 3 entities: [shaft, head, base]
|
|
5890
|
-
*
|
|
5891
|
-
* @param layer - Cesium CustomDataSource to add entities to
|
|
5892
|
-
* @param position - Ground position (Cartesian3)
|
|
5893
|
-
* @param baseHeight - Ground height in meters
|
|
5894
|
-
* @param properties - Additional properties for entities
|
|
5895
|
-
* @returns Array of created entities [shaft, head, base]
|
|
5896
|
-
*/
|
|
5897
|
-
createEntities(layer, position, baseHeight, properties) {
|
|
5898
|
-
const C = this.CesiumNS;
|
|
5899
|
-
const entities = [];
|
|
5900
|
-
const carto = C.Cartographic.fromCartesian(position);
|
|
5901
|
-
const lon = C.Math.toDegrees(carto.longitude);
|
|
5902
|
-
const lat = C.Math.toDegrees(carto.latitude);
|
|
5903
|
-
const computeScaleFactor = () => {
|
|
5904
|
-
if (!this.dynamicScale || !this.viewer) return 1;
|
|
5905
|
-
try {
|
|
5906
|
-
const cameraPos = this.viewer.camera.positionWC;
|
|
5907
|
-
const distance = C.Cartesian3.distance(cameraPos, position);
|
|
5908
|
-
const rawScale = distance / this.referenceDistance;
|
|
5909
|
-
return Math.max(this.minScale, Math.min(this.maxScale, rawScale));
|
|
5910
|
-
} catch {
|
|
5911
|
-
return 1;
|
|
5912
|
-
}
|
|
5913
|
-
};
|
|
5914
|
-
if (this.dynamicScale && this.viewer) {
|
|
5915
|
-
this.viewer.scene.preRender.addEventListener(() => {
|
|
5916
|
-
this.cachedScaleFactor = computeScaleFactor();
|
|
5917
|
-
});
|
|
5918
|
-
}
|
|
5919
|
-
const hpr = new C.HeadingPitchRoll(0, 0, 0);
|
|
5920
|
-
const baseOrientation = C.Transforms.headingPitchRollQuaternion(position, hpr);
|
|
5921
|
-
const fixedOrientation = new C.ConstantProperty(baseOrientation);
|
|
5922
|
-
const getShaftPosition = () => {
|
|
5923
|
-
const scale = this.cachedScaleFactor;
|
|
5924
|
-
return C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight * scale / 2);
|
|
5925
|
-
};
|
|
5926
|
-
const getHeadPosition = () => {
|
|
5927
|
-
const scale = this.cachedScaleFactor;
|
|
5928
|
-
return C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight * scale + this.headHeight * scale / 2);
|
|
5929
|
-
};
|
|
5930
|
-
const shaftEntity = layer.entities.add({
|
|
5931
|
-
position: this.dynamicScale ? new C.CallbackProperty(getShaftPosition, false) : new C.ConstantPositionProperty(C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight / 2)),
|
|
5932
|
-
orientation: fixedOrientation,
|
|
5933
|
-
cylinder: {
|
|
5934
|
-
length: this.dynamicScale ? new C.CallbackProperty(() => this.shaftHeight * this.cachedScaleFactor, false) : this.shaftHeight,
|
|
5935
|
-
topRadius: this.dynamicScale ? new C.CallbackProperty(() => this.shaftRadius * this.cachedScaleFactor, false) : this.shaftRadius,
|
|
5936
|
-
bottomRadius: this.dynamicScale ? new C.CallbackProperty(() => this.shaftRadius * this.cachedScaleFactor, false) : this.shaftRadius,
|
|
5937
|
-
material: this.color.withAlpha(this.shaftAlpha),
|
|
5938
|
-
outline: this.outline,
|
|
5939
|
-
outlineColor: this.outlineColor,
|
|
5940
|
-
outlineWidth: 2
|
|
5941
|
-
},
|
|
5942
|
-
properties: {
|
|
5943
|
-
...properties,
|
|
5944
|
-
_arrowPart: "shaft"
|
|
5945
|
-
}
|
|
5946
|
-
});
|
|
5947
|
-
entities.push(shaftEntity);
|
|
5948
|
-
const headEntity = layer.entities.add({
|
|
5949
|
-
position: this.dynamicScale ? new C.CallbackProperty(getHeadPosition, false) : new C.ConstantPositionProperty(C.Cartesian3.fromDegrees(lon, lat, baseHeight + this.shaftHeight + this.headHeight / 2)),
|
|
5950
|
-
orientation: fixedOrientation,
|
|
5951
|
-
cylinder: {
|
|
5952
|
-
length: this.dynamicScale ? new C.CallbackProperty(() => this.headHeight * this.cachedScaleFactor, false) : this.headHeight,
|
|
5953
|
-
topRadius: 0,
|
|
5954
|
-
// Creates cone shape
|
|
5955
|
-
bottomRadius: this.dynamicScale ? new C.CallbackProperty(() => this.headRadius * this.cachedScaleFactor, false) : this.headRadius,
|
|
5956
|
-
material: this.color.withAlpha(this.headAlpha),
|
|
5957
|
-
outline: this.outline,
|
|
5958
|
-
outlineColor: this.outlineColor,
|
|
5959
|
-
outlineWidth: 2
|
|
5960
|
-
},
|
|
5961
|
-
properties: {
|
|
5962
|
-
...properties,
|
|
5963
|
-
_arrowPart: "head"
|
|
5964
|
-
}
|
|
5965
|
-
});
|
|
5966
|
-
entities.push(headEntity);
|
|
5967
|
-
const baseEntity = layer.entities.add({
|
|
5968
|
-
position,
|
|
5969
|
-
ellipse: {
|
|
5970
|
-
semiMajorAxis: this.dynamicScale ? new C.CallbackProperty(() => this.baseRadius * this.cachedScaleFactor, false) : this.baseRadius,
|
|
5971
|
-
semiMinorAxis: this.dynamicScale ? new C.CallbackProperty(() => this.baseRadius * this.cachedScaleFactor, false) : this.baseRadius,
|
|
5972
|
-
height: baseHeight,
|
|
5973
|
-
material: this.color.withAlpha(this.baseAlpha),
|
|
5974
|
-
outline: this.outline,
|
|
5975
|
-
outlineColor: this.outlineColor,
|
|
5976
|
-
outlineWidth: 2
|
|
5977
|
-
},
|
|
5978
|
-
properties: {
|
|
5979
|
-
...properties,
|
|
5980
|
-
_arrowPart: "base"
|
|
5981
|
-
}
|
|
5982
|
-
});
|
|
5983
|
-
entities.push(baseEntity);
|
|
5984
|
-
return entities;
|
|
5985
|
-
}
|
|
5986
|
-
/**
|
|
5987
|
-
* Get the color
|
|
5988
|
-
*/
|
|
5989
|
-
getColor() {
|
|
5990
|
-
return this.color;
|
|
5991
|
-
}
|
|
5992
|
-
/**
|
|
5993
|
-
* Update arrow color
|
|
5994
|
-
*/
|
|
5995
|
-
setColor(color) {
|
|
5996
|
-
const C = this.CesiumNS;
|
|
5997
|
-
this.color = C.Color.fromCssColorString(color);
|
|
5998
|
-
}
|
|
5999
|
-
/**
|
|
6000
|
-
* Update dimensions
|
|
6001
|
-
*/
|
|
6002
|
-
setDimensions(opts) {
|
|
6003
|
-
if (opts.shaftHeight !== void 0) this.shaftHeight = opts.shaftHeight;
|
|
6004
|
-
if (opts.headHeight !== void 0) this.headHeight = opts.headHeight;
|
|
6005
|
-
if (opts.shaftRadius !== void 0) this.shaftRadius = opts.shaftRadius;
|
|
6006
|
-
if (opts.headRadius !== void 0) this.headRadius = opts.headRadius;
|
|
6007
|
-
if (opts.baseRadius !== void 0) this.baseRadius = opts.baseRadius;
|
|
6008
|
-
this.height = this.shaftHeight + this.headHeight;
|
|
6009
|
-
}
|
|
6010
|
-
/**
|
|
6011
|
-
* Update transparency
|
|
6012
|
-
*/
|
|
6013
|
-
setAlpha(opts) {
|
|
6014
|
-
if (opts.shaftAlpha !== void 0) this.shaftAlpha = opts.shaftAlpha;
|
|
6015
|
-
if (opts.headAlpha !== void 0) this.headAlpha = opts.headAlpha;
|
|
6016
|
-
if (opts.baseAlpha !== void 0) this.baseAlpha = opts.baseAlpha;
|
|
6017
|
-
}
|
|
6018
|
-
/**
|
|
6019
|
-
* Get current dimensions
|
|
6020
|
-
*/
|
|
6021
|
-
getDimensions() {
|
|
6022
|
-
return {
|
|
6023
|
-
height: this.height,
|
|
6024
|
-
shaftHeight: this.shaftHeight,
|
|
6025
|
-
headHeight: this.headHeight,
|
|
6026
|
-
shaftRadius: this.shaftRadius,
|
|
6027
|
-
headRadius: this.headRadius,
|
|
6028
|
-
baseRadius: this.baseRadius
|
|
6029
|
-
};
|
|
6030
|
-
}
|
|
6031
|
-
/**
|
|
6032
|
-
* Get current alpha values
|
|
6033
|
-
*/
|
|
6034
|
-
getAlpha() {
|
|
6035
|
-
return {
|
|
6036
|
-
shaftAlpha: this.shaftAlpha,
|
|
6037
|
-
headAlpha: this.headAlpha,
|
|
6038
|
-
baseAlpha: this.baseAlpha
|
|
6039
|
-
};
|
|
6040
|
-
}
|
|
6041
|
-
/**
|
|
6042
|
-
* Get total height
|
|
6043
|
-
*/
|
|
6044
|
-
getHeight() {
|
|
6045
|
-
return this.height;
|
|
6046
|
-
}
|
|
6047
|
-
};
|
|
6048
|
-
|
|
6049
6128
|
// src/core/path-manager/startPathDrawing.ts
|
|
6050
6129
|
function startPathDrawing(CesiumNS, viewer, options, onComplete) {
|
|
6051
6130
|
const C = CesiumNS;
|
|
6052
6131
|
const layer = options?.layer ?? new C.CustomDataSource("Paths");
|
|
6053
6132
|
if (!options?.layer) viewer.dataSources.add(layer);
|
|
6054
6133
|
const altitudeMode = options?.altitudeMode ?? "absolute";
|
|
6055
|
-
const climbHeight = Number(options?.climbHeight) ||
|
|
6056
|
-
const
|
|
6057
|
-
|
|
6058
|
-
let hasStart = false;
|
|
6134
|
+
const climbHeight = Number(options?.climbHeight) || 0;
|
|
6135
|
+
const defaultAltitude = options?.defaultAltitude ?? options?.defaultHeight ?? 100;
|
|
6136
|
+
const DEFAULT_MAIN_WIDTH = options?.width ?? 3;
|
|
6059
6137
|
let createdEntity = void 0;
|
|
6138
|
+
let entityCreated = false;
|
|
6139
|
+
let editSession = void 0;
|
|
6060
6140
|
const getPositionFromMouse = (movement) => {
|
|
6061
6141
|
const scene = viewer.scene;
|
|
6062
6142
|
const winPos = movement?.position ?? movement?.endPosition ?? movement;
|
|
@@ -6072,129 +6152,54 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
|
|
|
6072
6152
|
}
|
|
6073
6153
|
return cart;
|
|
6074
6154
|
};
|
|
6075
|
-
const toCartographic = (cart) => {
|
|
6076
|
-
try {
|
|
6077
|
-
return C.Cartographic.fromCartesian(cart);
|
|
6078
|
-
} catch {
|
|
6079
|
-
return void 0;
|
|
6080
|
-
}
|
|
6081
|
-
};
|
|
6082
6155
|
let handler;
|
|
6083
|
-
const positions = [];
|
|
6084
|
-
const tempHandles = [];
|
|
6085
6156
|
handler = new C.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
6086
6157
|
handler.setInputAction((movement) => {
|
|
6087
|
-
if (hasStart) return;
|
|
6088
6158
|
const picked = getPositionFromMouse(movement);
|
|
6089
6159
|
if (!picked) return;
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
const groundPos = C.Cartesian3.fromDegrees(
|
|
6094
|
-
C.Math.toDegrees(carto.longitude),
|
|
6095
|
-
C.Math.toDegrees(carto.latitude),
|
|
6096
|
-
startCartographic.height
|
|
6097
|
-
);
|
|
6098
|
-
positions.push(groundPos);
|
|
6099
|
-
const arrowCarto = toCartographic(groundPos);
|
|
6100
|
-
const baseHeight = arrowCarto ? arrowCarto.height : 0;
|
|
6101
|
-
const arrowShape = new ArrowShape(CesiumNS, {
|
|
6102
|
-
shaftHeight: 12,
|
|
6103
|
-
headHeight: 12,
|
|
6104
|
-
shaftRadius: 4,
|
|
6105
|
-
headRadius: 8,
|
|
6106
|
-
baseRadius: 12,
|
|
6107
|
-
color: "#FFD700",
|
|
6108
|
-
shaftAlpha: 1,
|
|
6109
|
-
headAlpha: 1,
|
|
6110
|
-
baseAlpha: 0.5,
|
|
6111
|
-
// 启用动态缩放,和无人机模型一样根据相机距离调整大小
|
|
6112
|
-
dynamicScale: true,
|
|
6113
|
-
viewer,
|
|
6114
|
-
referenceDistance: 300,
|
|
6115
|
-
minScale: 0.3,
|
|
6116
|
-
maxScale: 2
|
|
6117
|
-
});
|
|
6118
|
-
const arrowEntities = arrowShape.createEntities(
|
|
6119
|
-
layer,
|
|
6120
|
-
groundPos,
|
|
6121
|
-
baseHeight,
|
|
6122
|
-
{ _type: "path-vertex", _vertexIndex: 0, _isStart: true }
|
|
6123
|
-
);
|
|
6124
|
-
tempHandles.push(...arrowEntities);
|
|
6125
|
-
hasStart = true;
|
|
6126
|
-
if (climbHeight > 0) {
|
|
6127
|
-
const climbPos = C.Cartesian3.fromDegrees(
|
|
6128
|
-
C.Math.toDegrees(startCartographic.longitude),
|
|
6129
|
-
C.Math.toDegrees(startCartographic.latitude),
|
|
6130
|
-
startCartographic.height + climbHeight
|
|
6131
|
-
);
|
|
6132
|
-
positions.push(climbPos);
|
|
6133
|
-
}
|
|
6134
|
-
let created;
|
|
6135
|
-
try {
|
|
6136
|
-
const id = `${options?.idPrefix ?? "path"}-${Date.now().toString(36)}`;
|
|
6137
|
-
const pathPositions = new C.CallbackProperty(() => {
|
|
6138
|
-
const p = created?.polyline?.positions;
|
|
6139
|
-
if (p && typeof p.getValue === "function") {
|
|
6140
|
-
try {
|
|
6141
|
-
return p.getValue();
|
|
6142
|
-
} catch {
|
|
6143
|
-
}
|
|
6144
|
-
}
|
|
6145
|
-
return positions.slice();
|
|
6146
|
-
}, false);
|
|
6147
|
-
created = layer.entities.add({
|
|
6148
|
-
id,
|
|
6149
|
-
name: "Path",
|
|
6150
|
-
polyline: {
|
|
6151
|
-
positions: pathPositions,
|
|
6152
|
-
width: DEFAULT_MAIN_WIDTH,
|
|
6153
|
-
material: new C.PolylineOutlineMaterialProperty({
|
|
6154
|
-
color: C.Color.LIME,
|
|
6155
|
-
outlineColor: C.Color.WHITE,
|
|
6156
|
-
outlineWidth: 2
|
|
6157
|
-
}),
|
|
6158
|
-
clampToGround: false
|
|
6159
|
-
},
|
|
6160
|
-
properties: {
|
|
6161
|
-
_altitudeMode: altitudeMode,
|
|
6162
|
-
_climbHeight: climbHeight,
|
|
6163
|
-
_hasHiddenClimb: climbHeight > 0
|
|
6164
|
-
}
|
|
6165
|
-
});
|
|
6166
|
-
createdEntity = created;
|
|
6160
|
+
if (!entityCreated) {
|
|
6161
|
+
entityCreated = true;
|
|
6162
|
+
let created;
|
|
6167
6163
|
try {
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6164
|
+
const id = `${options?.idPrefix ?? "path"}-${Date.now().toString(36)}`;
|
|
6165
|
+
const positions = [];
|
|
6166
|
+
const pathPositions = new C.CallbackProperty(() => positions.slice(), false);
|
|
6167
|
+
created = layer.entities.add({
|
|
6168
|
+
id,
|
|
6169
|
+
name: "Path",
|
|
6170
|
+
polyline: {
|
|
6171
|
+
positions: pathPositions,
|
|
6172
|
+
width: DEFAULT_MAIN_WIDTH,
|
|
6173
|
+
material: C.Color.fromCssColorString("#00E676"),
|
|
6174
|
+
clampToGround: false
|
|
6175
|
+
},
|
|
6176
|
+
properties: {
|
|
6177
|
+
_altitudeMode: altitudeMode,
|
|
6178
|
+
_defaultAltitude: defaultAltitude,
|
|
6179
|
+
_climbHeight: climbHeight,
|
|
6180
|
+
_useGlobalHeightFlags: []
|
|
6181
|
+
// 🆕 空数组,航点由编辑模式添加
|
|
6178
6182
|
}
|
|
6179
6183
|
});
|
|
6180
|
-
|
|
6181
|
-
}
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
handler = void 0;
|
|
6188
|
-
}
|
|
6189
|
-
if (created) {
|
|
6190
|
-
try {
|
|
6191
|
-
onComplete?.(created);
|
|
6192
|
-
} catch {
|
|
6184
|
+
createdEntity = created;
|
|
6185
|
+
} finally {
|
|
6186
|
+
try {
|
|
6187
|
+
handler?.destroy();
|
|
6188
|
+
} catch {
|
|
6189
|
+
}
|
|
6190
|
+
handler = void 0;
|
|
6193
6191
|
}
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6192
|
+
if (created) {
|
|
6193
|
+
try {
|
|
6194
|
+
onComplete?.(created);
|
|
6195
|
+
} catch {
|
|
6196
|
+
}
|
|
6197
|
+
try {
|
|
6198
|
+
const auto = options?.autoStartEditing;
|
|
6199
|
+
const editOptions = {
|
|
6200
|
+
// 🔧 默认使用自由编辑模式(快速编辑和自由编辑互斥)
|
|
6201
|
+
quickEdit: false
|
|
6202
|
+
};
|
|
6198
6203
|
if (typeof auto === "object" && auto.preview) {
|
|
6199
6204
|
editOptions.preview = auto.preview;
|
|
6200
6205
|
} else {
|
|
@@ -6216,30 +6221,35 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
|
|
|
6216
6221
|
if (autoOpts.onVertexDeleteDetail) {
|
|
6217
6222
|
editOptions.onVertexDeleteDetail = autoOpts.onVertexDeleteDetail;
|
|
6218
6223
|
}
|
|
6219
|
-
|
|
6224
|
+
editOptions.altitudeMode = altitudeMode;
|
|
6225
|
+
editOptions.defaultAltitude = defaultAltitude;
|
|
6226
|
+
editOptions.climbHeight = climbHeight;
|
|
6227
|
+
editSession = startPathEditing(CesiumNS, viewer, created, editOptions);
|
|
6228
|
+
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");
|
|
6220
6229
|
if (editSession && options?.onEditingStarted) {
|
|
6221
6230
|
try {
|
|
6222
6231
|
options.onEditingStarted(editSession);
|
|
6223
6232
|
} catch {
|
|
6224
6233
|
}
|
|
6225
6234
|
}
|
|
6235
|
+
} catch (error) {
|
|
6236
|
+
console.error("[startPathDrawing] \u8FDB\u5165\u7F16\u8F91\u6A21\u5F0F\u5931\u8D25:", error);
|
|
6226
6237
|
}
|
|
6227
|
-
} catch {
|
|
6228
6238
|
}
|
|
6229
6239
|
}
|
|
6230
6240
|
}, C.ScreenSpaceEventType.LEFT_CLICK);
|
|
6231
6241
|
return {
|
|
6232
6242
|
stop: () => {
|
|
6233
|
-
for (const h2 of tempHandles) {
|
|
6234
|
-
try {
|
|
6235
|
-
layer.entities.remove(h2);
|
|
6236
|
-
} catch {
|
|
6237
|
-
}
|
|
6238
|
-
}
|
|
6239
6243
|
try {
|
|
6240
6244
|
handler?.destroy();
|
|
6241
6245
|
} catch {
|
|
6242
6246
|
}
|
|
6247
|
+
if (editSession) {
|
|
6248
|
+
try {
|
|
6249
|
+
editSession.stop();
|
|
6250
|
+
} catch {
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6243
6253
|
if (createdEntity) {
|
|
6244
6254
|
try {
|
|
6245
6255
|
layer.entities.remove(createdEntity);
|
|
@@ -6324,77 +6334,6 @@ function parseCoordinate(value) {
|
|
|
6324
6334
|
}
|
|
6325
6335
|
return 0;
|
|
6326
6336
|
}
|
|
6327
|
-
function parseTakeOffRefPoint(takeOffRefPoint, takeOffSecurityHeight, CesiumNS) {
|
|
6328
|
-
if (!takeOffRefPoint || typeof takeOffRefPoint !== "string" || takeOffRefPoint.trim() === "") {
|
|
6329
|
-
return null;
|
|
6330
|
-
}
|
|
6331
|
-
const C = CesiumNS;
|
|
6332
|
-
let longitude;
|
|
6333
|
-
let latitude;
|
|
6334
|
-
let height;
|
|
6335
|
-
const trimmed = takeOffRefPoint.trim();
|
|
6336
|
-
if (trimmed.includes(",")) {
|
|
6337
|
-
try {
|
|
6338
|
-
const parts = trimmed.split(",").map((p) => p.trim());
|
|
6339
|
-
if (parts.length >= 2) {
|
|
6340
|
-
latitude = parseFloat(parts[0]);
|
|
6341
|
-
longitude = parseFloat(parts[1]);
|
|
6342
|
-
height = parts.length >= 3 ? parseFloat(parts[2]) : takeOffSecurityHeight;
|
|
6343
|
-
if (isNaN(latitude) || isNaN(longitude) || isNaN(height)) {
|
|
6344
|
-
throw new Error("\u65E0\u6CD5\u89E3\u6790\u9017\u53F7\u5206\u9694\u7684\u5750\u6807\u503C");
|
|
6345
|
-
}
|
|
6346
|
-
const startPosition = C.Cartesian3.fromDegrees(longitude, latitude, height);
|
|
6347
|
-
const climbPosition = C.Cartesian3.fromDegrees(
|
|
6348
|
-
longitude,
|
|
6349
|
-
latitude,
|
|
6350
|
-
height + takeOffSecurityHeight
|
|
6351
|
-
);
|
|
6352
|
-
return {
|
|
6353
|
-
startPosition,
|
|
6354
|
-
climbPosition
|
|
6355
|
-
};
|
|
6356
|
-
}
|
|
6357
|
-
} catch (error) {
|
|
6358
|
-
}
|
|
6359
|
-
}
|
|
6360
|
-
try {
|
|
6361
|
-
const parsed = JSON.parse(takeOffRefPoint);
|
|
6362
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
6363
|
-
return null;
|
|
6364
|
-
}
|
|
6365
|
-
if (typeof parsed.longitude === "number") {
|
|
6366
|
-
longitude = parsed.longitude;
|
|
6367
|
-
} else if (typeof parsed.lon === "number") {
|
|
6368
|
-
longitude = parsed.lon;
|
|
6369
|
-
} else {
|
|
6370
|
-
return null;
|
|
6371
|
-
}
|
|
6372
|
-
if (typeof parsed.latitude === "number") {
|
|
6373
|
-
latitude = parsed.latitude;
|
|
6374
|
-
} else if (typeof parsed.lat === "number") {
|
|
6375
|
-
latitude = parsed.lat;
|
|
6376
|
-
} else {
|
|
6377
|
-
return null;
|
|
6378
|
-
}
|
|
6379
|
-
if (typeof parsed.height === "number") {
|
|
6380
|
-
height = parsed.height;
|
|
6381
|
-
} else {
|
|
6382
|
-
height = takeOffSecurityHeight;
|
|
6383
|
-
}
|
|
6384
|
-
const startPosition = C.Cartesian3.fromDegrees(longitude, latitude, height);
|
|
6385
|
-
const climbPosition = C.Cartesian3.fromDegrees(
|
|
6386
|
-
longitude,
|
|
6387
|
-
latitude,
|
|
6388
|
-
height + takeOffSecurityHeight
|
|
6389
|
-
);
|
|
6390
|
-
return {
|
|
6391
|
-
startPosition,
|
|
6392
|
-
climbPosition
|
|
6393
|
-
};
|
|
6394
|
-
} catch (error) {
|
|
6395
|
-
return null;
|
|
6396
|
-
}
|
|
6397
|
-
}
|
|
6398
6337
|
function convertSinoflyWayline(data, options) {
|
|
6399
6338
|
const {
|
|
6400
6339
|
CesiumNS,
|
|
@@ -6417,11 +6356,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
6417
6356
|
if (data.waylineId === void 0 || data.waylineId === null) {
|
|
6418
6357
|
throw new Error("[sinoflyAdapter] waylineId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
6419
6358
|
}
|
|
6420
|
-
const takeOffInfo = parseTakeOffRefPoint(
|
|
6421
|
-
data.takeOffRefPoint,
|
|
6422
|
-
data.takeOffSecurityHeight,
|
|
6423
|
-
CesiumNS
|
|
6424
|
-
);
|
|
6425
6359
|
let waypoints = data.waypointInfo;
|
|
6426
6360
|
if (filterWaypoint) {
|
|
6427
6361
|
waypoints = waypoints.filter(filterWaypoint);
|
|
@@ -6429,31 +6363,6 @@ function convertSinoflyWayline(data, options) {
|
|
|
6429
6363
|
if (sortByIndex) {
|
|
6430
6364
|
waypoints = [...waypoints].sort((a, b) => a.index - b.index);
|
|
6431
6365
|
}
|
|
6432
|
-
const finalWaypointData = [];
|
|
6433
|
-
if (takeOffInfo) {
|
|
6434
|
-
finalWaypointData.push({
|
|
6435
|
-
position: takeOffInfo.startPosition,
|
|
6436
|
-
heading: defaultHeading,
|
|
6437
|
-
pitch: defaultPitch,
|
|
6438
|
-
roll: defaultRoll,
|
|
6439
|
-
fov: defaultFov,
|
|
6440
|
-
index: 0
|
|
6441
|
-
});
|
|
6442
|
-
finalWaypointData.push({
|
|
6443
|
-
position: takeOffInfo.climbPosition,
|
|
6444
|
-
heading: defaultHeading,
|
|
6445
|
-
pitch: defaultPitch,
|
|
6446
|
-
roll: defaultRoll,
|
|
6447
|
-
fov: defaultFov,
|
|
6448
|
-
index: 1
|
|
6449
|
-
});
|
|
6450
|
-
}
|
|
6451
|
-
let waypointStartIndex;
|
|
6452
|
-
if (takeOffInfo) {
|
|
6453
|
-
waypointStartIndex = 2;
|
|
6454
|
-
} else {
|
|
6455
|
-
waypointStartIndex = 0;
|
|
6456
|
-
}
|
|
6457
6366
|
const convertedWaypoints = waypoints.map((wp, idx) => {
|
|
6458
6367
|
try {
|
|
6459
6368
|
if (!wp) {
|
|
@@ -6489,15 +6398,16 @@ function convertSinoflyWayline(data, options) {
|
|
|
6489
6398
|
pitch,
|
|
6490
6399
|
roll,
|
|
6491
6400
|
fov,
|
|
6492
|
-
index:
|
|
6493
|
-
//
|
|
6401
|
+
index: idx,
|
|
6402
|
+
// 从 0 开始分配 index
|
|
6403
|
+
useGlobalHeight: false
|
|
6404
|
+
// 🆕 从服务端加载的航点默认使用实际高度
|
|
6494
6405
|
};
|
|
6495
6406
|
} catch (error) {
|
|
6496
6407
|
throw new Error(`\u822A\u70B9 ${idx} \u8F6C\u6362\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
6497
6408
|
}
|
|
6498
6409
|
});
|
|
6499
|
-
|
|
6500
|
-
if (!Array.isArray(waypointData)) {
|
|
6410
|
+
if (!Array.isArray(convertedWaypoints)) {
|
|
6501
6411
|
throw new Error("[sinoflyAdapter] waypointData \u4E0D\u662F\u6570\u7EC4");
|
|
6502
6412
|
}
|
|
6503
6413
|
const metadata = {
|
|
@@ -6508,8 +6418,8 @@ function convertSinoflyWayline(data, options) {
|
|
|
6508
6418
|
autoFlightSpeed: data.autoFlightSpeed,
|
|
6509
6419
|
distance: data.distance,
|
|
6510
6420
|
duration: data.duration,
|
|
6511
|
-
|
|
6512
|
-
|
|
6421
|
+
climbHeight: data.takeOffSecurityHeight
|
|
6422
|
+
// 使用 climbHeight 作为字段名
|
|
6513
6423
|
};
|
|
6514
6424
|
if (data.stationId !== void 0) metadata.stationId = data.stationId;
|
|
6515
6425
|
if (data.subarrayId !== void 0) metadata.subarrayId = data.subarrayId;
|
|
@@ -6519,7 +6429,7 @@ function convertSinoflyWayline(data, options) {
|
|
|
6519
6429
|
id: `wayline-${data.waylineId}`,
|
|
6520
6430
|
name: data.waylineName || `\u822A\u7EBF-${data.waylineId}`,
|
|
6521
6431
|
description: `\u822A\u7EBFID: ${data.waylineId}, \u7C7B\u578B: ${data.waylineType}, \u822A\u70B9\u6570: ${data.waypointNumber}`,
|
|
6522
|
-
waypointData,
|
|
6432
|
+
waypointData: convertedWaypoints,
|
|
6523
6433
|
metadata
|
|
6524
6434
|
};
|
|
6525
6435
|
}
|
|
@@ -6532,7 +6442,6 @@ function renderFlightPath(CesiumNS, viewer, options) {
|
|
|
6532
6442
|
let entityId;
|
|
6533
6443
|
let entityName;
|
|
6534
6444
|
let entityDescription;
|
|
6535
|
-
let hasHiddenClimb;
|
|
6536
6445
|
let altitudeMode;
|
|
6537
6446
|
let climbHeight;
|
|
6538
6447
|
try {
|
|
@@ -6548,12 +6457,8 @@ function renderFlightPath(CesiumNS, viewer, options) {
|
|
|
6548
6457
|
entityId = options.id ?? converted.id ?? `wayline-${sinoflyData.waylineId}`;
|
|
6549
6458
|
entityName = options.name ?? converted.name;
|
|
6550
6459
|
entityDescription = options.description ?? converted.description;
|
|
6551
|
-
const sortedWaypoints2 = [...waypointData].sort((a, b) => a.index - b.index);
|
|
6552
|
-
const hasIndex1 = sortedWaypoints2.some((wp) => wp.index === 1);
|
|
6553
|
-
const hasTakeOffRefPoint = converted.metadata?.hasTakeOffRefPoint ?? !!sinoflyData.takeOffRefPoint;
|
|
6554
|
-
hasHiddenClimb = options.hasHiddenClimb ?? (hasTakeOffRefPoint && hasIndex1);
|
|
6555
6460
|
altitudeMode = options.altitudeMode ?? converted.metadata?.altitudeMode;
|
|
6556
|
-
climbHeight = options.climbHeight ?? converted.metadata?.climbHeight
|
|
6461
|
+
climbHeight = options.climbHeight ?? converted.metadata?.climbHeight;
|
|
6557
6462
|
} catch (error) {
|
|
6558
6463
|
console.error("[renderFlightPath] Sinofly \u6570\u636E\u8F6C\u6362\u5931\u8D25:", error);
|
|
6559
6464
|
throw new Error(`Sinofly \u6570\u636E\u8F6C\u6362\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -6575,66 +6480,25 @@ function renderFlightPath(CesiumNS, viewer, options) {
|
|
|
6575
6480
|
layer = new C.CustomDataSource(`flight-path-datasource-${Date.now()}`);
|
|
6576
6481
|
viewer.dataSources.add(layer);
|
|
6577
6482
|
}
|
|
6578
|
-
const hiddenClimbIndex =
|
|
6579
|
-
const
|
|
6483
|
+
const hiddenClimbIndex = void 0;
|
|
6484
|
+
const useGlobalHeightFlags = sortedWaypoints.map((wp) => wp.useGlobalHeight ?? false);
|
|
6580
6485
|
const entity = layer.entities.add({
|
|
6581
6486
|
id: entityId,
|
|
6582
6487
|
name: entityName,
|
|
6583
6488
|
description: entityDescription,
|
|
6584
6489
|
polyline: {
|
|
6585
6490
|
positions: positions.slice(),
|
|
6586
|
-
width: options.style?.width ??
|
|
6587
|
-
material: options.style?.material ?? options.style?.color ??
|
|
6588
|
-
color: C.Color.GREEN,
|
|
6589
|
-
outlineColor: C.Color.WHITE,
|
|
6590
|
-
outlineWidth: 3
|
|
6591
|
-
}),
|
|
6491
|
+
width: options.style?.width ?? 3,
|
|
6492
|
+
material: options.style?.material ?? options.style?.color ?? C.Color.fromCssColorString("#00E676"),
|
|
6592
6493
|
clampToGround: false
|
|
6593
6494
|
},
|
|
6594
6495
|
properties: {
|
|
6595
6496
|
_altitudeMode: altitudeMode,
|
|
6596
6497
|
_climbHeight: climbHeight,
|
|
6597
|
-
|
|
6498
|
+
_useGlobalHeightFlags: useGlobalHeightFlags
|
|
6499
|
+
// 🆕 保存 useGlobalHeightFlags
|
|
6598
6500
|
}
|
|
6599
6501
|
});
|
|
6600
|
-
const shouldShowArrow = hasStartPoint && hasHiddenClimb;
|
|
6601
|
-
if (shouldShowArrow) {
|
|
6602
|
-
try {
|
|
6603
|
-
const startPosition = positions[0];
|
|
6604
|
-
const carto = C.Cartographic.fromCartesian(startPosition);
|
|
6605
|
-
const baseHeight = carto ? carto.height : 0;
|
|
6606
|
-
const arrowShape = new ArrowShape(CesiumNS, {
|
|
6607
|
-
shaftHeight: 12,
|
|
6608
|
-
headHeight: 12,
|
|
6609
|
-
shaftRadius: 4,
|
|
6610
|
-
headRadius: 8,
|
|
6611
|
-
baseRadius: 12,
|
|
6612
|
-
color: "#FFD700",
|
|
6613
|
-
shaftAlpha: 0.98,
|
|
6614
|
-
headAlpha: 0.98,
|
|
6615
|
-
baseAlpha: 0.65,
|
|
6616
|
-
// 启用动态缩放
|
|
6617
|
-
dynamicScale: true,
|
|
6618
|
-
viewer,
|
|
6619
|
-
referenceDistance: 300,
|
|
6620
|
-
minScale: 0.3,
|
|
6621
|
-
maxScale: 2
|
|
6622
|
-
});
|
|
6623
|
-
arrowShape.createEntities(
|
|
6624
|
-
layer,
|
|
6625
|
-
startPosition,
|
|
6626
|
-
baseHeight,
|
|
6627
|
-
{
|
|
6628
|
-
_type: "path-vertex",
|
|
6629
|
-
_ownerId: entityId,
|
|
6630
|
-
_vertexIndex: 0,
|
|
6631
|
-
_isStart: true
|
|
6632
|
-
}
|
|
6633
|
-
);
|
|
6634
|
-
} catch (error) {
|
|
6635
|
-
console.error("Failed to create start arrow:", error);
|
|
6636
|
-
}
|
|
6637
|
-
}
|
|
6638
6502
|
try {
|
|
6639
6503
|
const vertexLabelManager = new VertexLabelManager(
|
|
6640
6504
|
CesiumNS,
|
|
@@ -6675,8 +6539,6 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6675
6539
|
} catch (e) {
|
|
6676
6540
|
console.warn("[renderFlightPathPreview] \u65E0\u6CD5\u83B7\u53D6\u822A\u70B9\u6570\u636E:", e);
|
|
6677
6541
|
}
|
|
6678
|
-
const hasHiddenClimb = entity.properties?._hasHiddenClimb?.getValue?.() ?? false;
|
|
6679
|
-
const hiddenClimbIndex = hasHiddenClimb ? 1 : void 0;
|
|
6680
6542
|
const updateWaypointHighlight = (newIndex) => {
|
|
6681
6543
|
if (!vertexLabelManager || positions.length === 0) return;
|
|
6682
6544
|
const editedIndices = /* @__PURE__ */ new Set();
|
|
@@ -6696,14 +6558,7 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6696
6558
|
const ownerId = properties._ownerId?.getValue?.(C.JulianDate.now());
|
|
6697
6559
|
const vertexIndex = properties._vertexIndex?.getValue?.(C.JulianDate.now());
|
|
6698
6560
|
if (type === "vertex-label" && ownerId === entity.id && vertexIndex !== void 0) {
|
|
6699
|
-
|
|
6700
|
-
if (hiddenClimbIndex === 1) {
|
|
6701
|
-
if (vertexIndex >= 2) {
|
|
6702
|
-
displayIndex = vertexIndex - 2;
|
|
6703
|
-
}
|
|
6704
|
-
} else {
|
|
6705
|
-
displayIndex = vertexIndex;
|
|
6706
|
-
}
|
|
6561
|
+
const displayIndex = vertexIndex;
|
|
6707
6562
|
selectedWaypointIndex = vertexIndex;
|
|
6708
6563
|
updateWaypointHighlight(selectedWaypointIndex);
|
|
6709
6564
|
if (options.onWaypointClick) {
|
|
@@ -6721,18 +6576,10 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6721
6576
|
updateWaypointHighlight(null);
|
|
6722
6577
|
return;
|
|
6723
6578
|
}
|
|
6724
|
-
|
|
6725
|
-
if (hiddenClimbIndex === 1) {
|
|
6726
|
-
actualIndex = index + 2;
|
|
6727
|
-
}
|
|
6728
|
-
selectedWaypointIndex = actualIndex;
|
|
6579
|
+
selectedWaypointIndex = index;
|
|
6729
6580
|
updateWaypointHighlight(selectedWaypointIndex);
|
|
6730
6581
|
},
|
|
6731
6582
|
getSelectedWaypoint: () => {
|
|
6732
|
-
if (selectedWaypointIndex === null) return null;
|
|
6733
|
-
if (hiddenClimbIndex === 1) {
|
|
6734
|
-
return selectedWaypointIndex >= 2 ? selectedWaypointIndex - 2 : null;
|
|
6735
|
-
}
|
|
6736
6583
|
return selectedWaypointIndex;
|
|
6737
6584
|
},
|
|
6738
6585
|
destroy: () => {
|
|
@@ -6742,6 +6589,299 @@ function renderFlightPathPreview(CesiumNS, viewer, options) {
|
|
|
6742
6589
|
return { entity, controller };
|
|
6743
6590
|
}
|
|
6744
6591
|
|
|
6592
|
+
// src/core/path-manager/FlightSimulator.ts
|
|
6593
|
+
var FlightSimulator = class {
|
|
6594
|
+
constructor(CesiumNS, viewer, options) {
|
|
6595
|
+
__publicField(this, "CesiumNS");
|
|
6596
|
+
__publicField(this, "viewer");
|
|
6597
|
+
__publicField(this, "options");
|
|
6598
|
+
__publicField(this, "state", "idle");
|
|
6599
|
+
__publicField(this, "progress", 0);
|
|
6600
|
+
__publicField(this, "waypoints", []);
|
|
6601
|
+
__publicField(this, "totalDistance", 0);
|
|
6602
|
+
__publicField(this, "currentDistance", 0);
|
|
6603
|
+
__publicField(this, "airplaneCursor");
|
|
6604
|
+
__publicField(this, "trackEntity");
|
|
6605
|
+
__publicField(this, "passedTrackEntity");
|
|
6606
|
+
__publicField(this, "animationFrameId");
|
|
6607
|
+
__publicField(this, "lastTimestamp");
|
|
6608
|
+
__publicField(this, "onStateChange", new Emitter());
|
|
6609
|
+
/**
|
|
6610
|
+
* 动画循环
|
|
6611
|
+
*/
|
|
6612
|
+
__publicField(this, "animate", (timestamp) => {
|
|
6613
|
+
if (this.state !== "playing") return;
|
|
6614
|
+
if (this.lastTimestamp === void 0) {
|
|
6615
|
+
this.lastTimestamp = timestamp;
|
|
6616
|
+
}
|
|
6617
|
+
const deltaTime = (timestamp - this.lastTimestamp) / 1e3;
|
|
6618
|
+
this.lastTimestamp = timestamp;
|
|
6619
|
+
this.currentDistance += this.options.speed * deltaTime;
|
|
6620
|
+
if (this.currentDistance >= this.totalDistance) {
|
|
6621
|
+
if (this.options.loop) {
|
|
6622
|
+
this.currentDistance = 0;
|
|
6623
|
+
} else {
|
|
6624
|
+
this.currentDistance = this.totalDistance;
|
|
6625
|
+
this.setState("stopped");
|
|
6626
|
+
return;
|
|
6627
|
+
}
|
|
6628
|
+
}
|
|
6629
|
+
this.progress = this.totalDistance > 0 ? this.currentDistance / this.totalDistance : 0;
|
|
6630
|
+
if (this.airplaneCursor) {
|
|
6631
|
+
const position = this.getCurrentPosition();
|
|
6632
|
+
const { heading, pitch, roll } = this.getCurrentPose();
|
|
6633
|
+
this.airplaneCursor.setPose(position, heading, pitch, roll);
|
|
6634
|
+
}
|
|
6635
|
+
this.viewer.scene.requestRender();
|
|
6636
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
6637
|
+
});
|
|
6638
|
+
this.CesiumNS = CesiumNS;
|
|
6639
|
+
this.viewer = viewer;
|
|
6640
|
+
this.options = {
|
|
6641
|
+
waylineData: options.waylineData,
|
|
6642
|
+
speed: options.speed ?? 10,
|
|
6643
|
+
loop: options.loop ?? false,
|
|
6644
|
+
showFrustum: options.showFrustum ?? true,
|
|
6645
|
+
layer: options.layer,
|
|
6646
|
+
trackHighlight: options.trackHighlight
|
|
6647
|
+
};
|
|
6648
|
+
this.initWaypoints();
|
|
6649
|
+
this.createEntities();
|
|
6650
|
+
}
|
|
6651
|
+
/**
|
|
6652
|
+
* 初始化航点数据
|
|
6653
|
+
*/
|
|
6654
|
+
initWaypoints() {
|
|
6655
|
+
const C = this.CesiumNS;
|
|
6656
|
+
const converted = convertSinoflyWayline(this.options.waylineData, { CesiumNS: this.CesiumNS });
|
|
6657
|
+
if (!converted.waypointData || converted.waypointData.length < 2) {
|
|
6658
|
+
console.warn("[FlightSimulator] \u822A\u70B9\u6570\u91CF\u4E0D\u8DB3");
|
|
6659
|
+
return;
|
|
6660
|
+
}
|
|
6661
|
+
const tempWaypoints = converted.waypointData.map((wp) => ({
|
|
6662
|
+
cartesian: wp.position,
|
|
6663
|
+
heading: wp.heading ?? 0,
|
|
6664
|
+
pitch: wp.pitch ?? 0,
|
|
6665
|
+
roll: wp.roll ?? 0,
|
|
6666
|
+
cumulativeDistance: 0
|
|
6667
|
+
}));
|
|
6668
|
+
let cumulativeDistance = 0;
|
|
6669
|
+
for (let i = 0; i < tempWaypoints.length; i++) {
|
|
6670
|
+
if (i > 0) {
|
|
6671
|
+
const prevCartesian = tempWaypoints[i - 1].cartesian;
|
|
6672
|
+
const currCartesian = tempWaypoints[i].cartesian;
|
|
6673
|
+
cumulativeDistance += C.Cartesian3.distance(prevCartesian, currCartesian);
|
|
6674
|
+
}
|
|
6675
|
+
tempWaypoints[i].cumulativeDistance = cumulativeDistance;
|
|
6676
|
+
}
|
|
6677
|
+
this.waypoints = tempWaypoints;
|
|
6678
|
+
this.totalDistance = cumulativeDistance;
|
|
6679
|
+
}
|
|
6680
|
+
/**
|
|
6681
|
+
* 创建可视化实体
|
|
6682
|
+
*/
|
|
6683
|
+
createEntities() {
|
|
6684
|
+
if (this.waypoints.length === 0) return;
|
|
6685
|
+
const firstWaypoint = this.waypoints[0];
|
|
6686
|
+
this.airplaneCursor = new AirplaneCursor(
|
|
6687
|
+
this.CesiumNS,
|
|
6688
|
+
this.viewer,
|
|
6689
|
+
firstWaypoint.cartesian,
|
|
6690
|
+
{
|
|
6691
|
+
// 禁用键盘控制(仿真模式下不需要手动控制)
|
|
6692
|
+
stepMeters: 0,
|
|
6693
|
+
angleStepDeg: 0,
|
|
6694
|
+
fovDeg: 50
|
|
6695
|
+
}
|
|
6696
|
+
);
|
|
6697
|
+
this.airplaneCursor.setPose(
|
|
6698
|
+
firstWaypoint.cartesian,
|
|
6699
|
+
firstWaypoint.heading,
|
|
6700
|
+
firstWaypoint.pitch,
|
|
6701
|
+
firstWaypoint.roll
|
|
6702
|
+
);
|
|
6703
|
+
if (this.options.trackHighlight?.enabled) {
|
|
6704
|
+
this.createTrackHighlight();
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
/**
|
|
6708
|
+
* 创建航迹高亮
|
|
6709
|
+
*/
|
|
6710
|
+
createTrackHighlight() {
|
|
6711
|
+
const C = this.CesiumNS;
|
|
6712
|
+
const entities = this.options.layer?.entities ?? this.viewer.entities;
|
|
6713
|
+
const highlightOpts = this.options.trackHighlight;
|
|
6714
|
+
const allPositions = this.waypoints.map((wp) => wp.cartesian);
|
|
6715
|
+
this.trackEntity = entities.add({
|
|
6716
|
+
id: `flight-simulator-track-${Date.now()}`,
|
|
6717
|
+
polyline: {
|
|
6718
|
+
positions: allPositions,
|
|
6719
|
+
width: highlightOpts.width ?? 4,
|
|
6720
|
+
material: (highlightOpts.color ?? C.Color.CYAN).withAlpha(0.3),
|
|
6721
|
+
clampToGround: false
|
|
6722
|
+
},
|
|
6723
|
+
properties: {
|
|
6724
|
+
_type: "flight-simulator-track"
|
|
6725
|
+
}
|
|
6726
|
+
});
|
|
6727
|
+
this.passedTrackEntity = entities.add({
|
|
6728
|
+
id: `flight-simulator-passed-track-${Date.now()}`,
|
|
6729
|
+
polyline: {
|
|
6730
|
+
positions: new C.CallbackProperty(() => this.getPassedPositions(), false),
|
|
6731
|
+
width: (highlightOpts.width ?? 4) + 2,
|
|
6732
|
+
material: highlightOpts.color ?? C.Color.CYAN,
|
|
6733
|
+
clampToGround: false
|
|
6734
|
+
},
|
|
6735
|
+
properties: {
|
|
6736
|
+
_type: "flight-simulator-passed-track"
|
|
6737
|
+
}
|
|
6738
|
+
});
|
|
6739
|
+
}
|
|
6740
|
+
/**
|
|
6741
|
+
* 获取当前位置
|
|
6742
|
+
*/
|
|
6743
|
+
getCurrentPosition() {
|
|
6744
|
+
if (this.waypoints.length === 0) {
|
|
6745
|
+
return this.CesiumNS.Cartesian3.ZERO;
|
|
6746
|
+
}
|
|
6747
|
+
const C = this.CesiumNS;
|
|
6748
|
+
for (let i = 1; i < this.waypoints.length; i++) {
|
|
6749
|
+
const prev = this.waypoints[i - 1];
|
|
6750
|
+
const curr = this.waypoints[i];
|
|
6751
|
+
if (this.currentDistance <= curr.cumulativeDistance) {
|
|
6752
|
+
const segmentStart = prev.cumulativeDistance;
|
|
6753
|
+
const segmentEnd = curr.cumulativeDistance;
|
|
6754
|
+
const segmentLength = segmentEnd - segmentStart;
|
|
6755
|
+
if (segmentLength <= 0) {
|
|
6756
|
+
return prev.cartesian;
|
|
6757
|
+
}
|
|
6758
|
+
const t = (this.currentDistance - segmentStart) / segmentLength;
|
|
6759
|
+
return C.Cartesian3.lerp(prev.cartesian, curr.cartesian, t, new C.Cartesian3());
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
return this.waypoints[this.waypoints.length - 1].cartesian;
|
|
6763
|
+
}
|
|
6764
|
+
/**
|
|
6765
|
+
* 获取当前姿态(用于更新 AirplaneCursor)
|
|
6766
|
+
*/
|
|
6767
|
+
getCurrentPose() {
|
|
6768
|
+
const C = this.CesiumNS;
|
|
6769
|
+
let heading = 0;
|
|
6770
|
+
let pitch = 0;
|
|
6771
|
+
let roll = 0;
|
|
6772
|
+
for (let i = 1; i < this.waypoints.length; i++) {
|
|
6773
|
+
const prev = this.waypoints[i - 1];
|
|
6774
|
+
const curr = this.waypoints[i];
|
|
6775
|
+
if (this.currentDistance <= curr.cumulativeDistance) {
|
|
6776
|
+
const segmentStart = prev.cumulativeDistance;
|
|
6777
|
+
const segmentEnd = curr.cumulativeDistance;
|
|
6778
|
+
const segmentLength = segmentEnd - segmentStart;
|
|
6779
|
+
if (segmentLength > 0) {
|
|
6780
|
+
const t = (this.currentDistance - segmentStart) / segmentLength;
|
|
6781
|
+
heading = C.Math.lerp(prev.heading, curr.heading, t);
|
|
6782
|
+
pitch = C.Math.lerp(prev.pitch, curr.pitch, t);
|
|
6783
|
+
roll = C.Math.lerp(prev.roll, curr.roll, t);
|
|
6784
|
+
} else {
|
|
6785
|
+
heading = prev.heading;
|
|
6786
|
+
pitch = prev.pitch;
|
|
6787
|
+
roll = prev.roll;
|
|
6788
|
+
}
|
|
6789
|
+
break;
|
|
6790
|
+
}
|
|
6791
|
+
}
|
|
6792
|
+
return { heading, pitch, roll };
|
|
6793
|
+
}
|
|
6794
|
+
/**
|
|
6795
|
+
* 获取已飞过的位置数组
|
|
6796
|
+
*/
|
|
6797
|
+
getPassedPositions() {
|
|
6798
|
+
const positions = [];
|
|
6799
|
+
for (let i = 0; i < this.waypoints.length; i++) {
|
|
6800
|
+
const wp = this.waypoints[i];
|
|
6801
|
+
if (wp.cumulativeDistance <= this.currentDistance) {
|
|
6802
|
+
positions.push(wp.cartesian);
|
|
6803
|
+
} else {
|
|
6804
|
+
positions.push(this.getCurrentPosition());
|
|
6805
|
+
break;
|
|
6806
|
+
}
|
|
6807
|
+
}
|
|
6808
|
+
return positions;
|
|
6809
|
+
}
|
|
6810
|
+
/**
|
|
6811
|
+
* 设置状态并发射事件
|
|
6812
|
+
*/
|
|
6813
|
+
setState(newState) {
|
|
6814
|
+
if (this.state === newState) return;
|
|
6815
|
+
this.state = newState;
|
|
6816
|
+
this.onStateChange.emit({ state: newState, progress: this.progress });
|
|
6817
|
+
}
|
|
6818
|
+
// ==================== 公共方法 ====================
|
|
6819
|
+
start() {
|
|
6820
|
+
if (this.waypoints.length < 2) {
|
|
6821
|
+
console.warn("[FlightSimulator] \u822A\u70B9\u6570\u91CF\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5F00\u59CB\u4EFF\u771F");
|
|
6822
|
+
return;
|
|
6823
|
+
}
|
|
6824
|
+
this.currentDistance = 0;
|
|
6825
|
+
this.progress = 0;
|
|
6826
|
+
this.lastTimestamp = void 0;
|
|
6827
|
+
this.setState("playing");
|
|
6828
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
6829
|
+
}
|
|
6830
|
+
pause() {
|
|
6831
|
+
if (this.state !== "playing") return;
|
|
6832
|
+
if (this.animationFrameId !== void 0) {
|
|
6833
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
6834
|
+
this.animationFrameId = void 0;
|
|
6835
|
+
}
|
|
6836
|
+
this.lastTimestamp = void 0;
|
|
6837
|
+
this.setState("paused");
|
|
6838
|
+
}
|
|
6839
|
+
resume() {
|
|
6840
|
+
if (this.state !== "paused") return;
|
|
6841
|
+
this.lastTimestamp = void 0;
|
|
6842
|
+
this.setState("playing");
|
|
6843
|
+
this.animationFrameId = requestAnimationFrame(this.animate);
|
|
6844
|
+
}
|
|
6845
|
+
stop() {
|
|
6846
|
+
if (this.animationFrameId !== void 0) {
|
|
6847
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
6848
|
+
this.animationFrameId = void 0;
|
|
6849
|
+
}
|
|
6850
|
+
this.currentDistance = 0;
|
|
6851
|
+
this.progress = 0;
|
|
6852
|
+
this.lastTimestamp = void 0;
|
|
6853
|
+
this.setState("stopped");
|
|
6854
|
+
this.viewer.scene.requestRender();
|
|
6855
|
+
}
|
|
6856
|
+
destroy() {
|
|
6857
|
+
this.stop();
|
|
6858
|
+
const entities = this.options.layer?.entities ?? this.viewer.entities;
|
|
6859
|
+
if (this.airplaneCursor) {
|
|
6860
|
+
this.airplaneCursor.destroy();
|
|
6861
|
+
this.airplaneCursor = void 0;
|
|
6862
|
+
}
|
|
6863
|
+
if (this.trackEntity) {
|
|
6864
|
+
entities.remove(this.trackEntity);
|
|
6865
|
+
this.trackEntity = void 0;
|
|
6866
|
+
}
|
|
6867
|
+
if (this.passedTrackEntity) {
|
|
6868
|
+
entities.remove(this.passedTrackEntity);
|
|
6869
|
+
this.passedTrackEntity = void 0;
|
|
6870
|
+
}
|
|
6871
|
+
this.waypoints = [];
|
|
6872
|
+
this.setState("idle");
|
|
6873
|
+
}
|
|
6874
|
+
setSpeed(speed) {
|
|
6875
|
+
this.options.speed = Math.max(0.1, speed);
|
|
6876
|
+
}
|
|
6877
|
+
getState() {
|
|
6878
|
+
return this.state;
|
|
6879
|
+
}
|
|
6880
|
+
getProgress() {
|
|
6881
|
+
return this.progress;
|
|
6882
|
+
}
|
|
6883
|
+
};
|
|
6884
|
+
|
|
6745
6885
|
// src/core/CZMLPathManager.ts
|
|
6746
6886
|
var _CZMLPathManager = class _CZMLPathManager {
|
|
6747
6887
|
constructor(CesiumNS, viewer) {
|
|
@@ -7018,6 +7158,20 @@ var _CZMLPathManager = class _CZMLPathManager {
|
|
|
7018
7158
|
options
|
|
7019
7159
|
);
|
|
7020
7160
|
}
|
|
7161
|
+
/**
|
|
7162
|
+
* Start flight simulation/preview for a wayline.
|
|
7163
|
+
* Animates an aircraft model along the wayline path with controls for play/pause/stop.
|
|
7164
|
+
* @param options - Configuration for the flight simulator
|
|
7165
|
+
* @returns A controller object with start/pause/resume/stop/destroy methods
|
|
7166
|
+
*/
|
|
7167
|
+
startFlightPreview(options) {
|
|
7168
|
+
const simulator = new FlightSimulator(
|
|
7169
|
+
this.CesiumNS,
|
|
7170
|
+
this.viewer,
|
|
7171
|
+
options
|
|
7172
|
+
);
|
|
7173
|
+
return simulator;
|
|
7174
|
+
}
|
|
7021
7175
|
// ensureLayerForEntity moved into path-editing module
|
|
7022
7176
|
};
|
|
7023
7177
|
__publicField(_CZMLPathManager, "SAMPLES_KEY", "__czmlPathSamples__");
|
|
@@ -8096,7 +8250,9 @@ var PolygonEditor = class {
|
|
|
8096
8250
|
polygon: {
|
|
8097
8251
|
hierarchy: positions,
|
|
8098
8252
|
material: faceColor,
|
|
8099
|
-
outline: false
|
|
8253
|
+
outline: false,
|
|
8254
|
+
// 🔧 修复:设置 heightReference 使多边形贴合地形
|
|
8255
|
+
heightReference: C.HeightReference.CLAMP_TO_GROUND
|
|
8100
8256
|
}
|
|
8101
8257
|
});
|
|
8102
8258
|
const ring = positions.slice();
|
|
@@ -8109,15 +8265,51 @@ var PolygonEditor = class {
|
|
|
8109
8265
|
width: 1,
|
|
8110
8266
|
material: lineColor,
|
|
8111
8267
|
clampToGround: true
|
|
8268
|
+
// 轮廓线已经设置了 clampToGround
|
|
8112
8269
|
},
|
|
8113
8270
|
properties: { _ownerId: id, _type: "polygon-outline" }
|
|
8114
8271
|
});
|
|
8115
8272
|
this.applyDashedOutlineStyle(outlineEntity, lineColor, 3, 10);
|
|
8116
8273
|
const displayText = name.includes("_") ? name.split("_")[1] : name;
|
|
8274
|
+
const firstPoint = points[0];
|
|
8275
|
+
this.createLabelWithTerrainHeight(
|
|
8276
|
+
layer,
|
|
8277
|
+
id,
|
|
8278
|
+
displayText,
|
|
8279
|
+
firstPoint.lon,
|
|
8280
|
+
firstPoint.lat,
|
|
8281
|
+
lineColor
|
|
8282
|
+
);
|
|
8283
|
+
return entity;
|
|
8284
|
+
} catch (err) {
|
|
8285
|
+
console.error(`[PolygonEditor] \u521B\u5EFA\u591A\u8FB9\u5F62\u5931\u8D25:`, err);
|
|
8286
|
+
return null;
|
|
8287
|
+
}
|
|
8288
|
+
}
|
|
8289
|
+
/**
|
|
8290
|
+
* 辅助方法:使用地形采样创建标签
|
|
8291
|
+
* 先尝试获取地形高度,如果失败则使用 heightReference
|
|
8292
|
+
*/
|
|
8293
|
+
async createLabelWithTerrainHeight(layer, ownerId, displayText, lon, lat, lineColor) {
|
|
8294
|
+
const C = this.CesiumNS;
|
|
8295
|
+
try {
|
|
8296
|
+
let terrainHeight = 0;
|
|
8297
|
+
const terrainProvider = this.viewer.terrainProvider;
|
|
8298
|
+
if (terrainProvider && typeof C.sampleTerrainMostDetailed === "function") {
|
|
8299
|
+
try {
|
|
8300
|
+
const positions = [C.Cartographic.fromDegrees(lon, lat)];
|
|
8301
|
+
const updatedPositions = await C.sampleTerrainMostDetailed(terrainProvider, positions);
|
|
8302
|
+
if (updatedPositions && updatedPositions[0] && updatedPositions[0].height !== void 0) {
|
|
8303
|
+
terrainHeight = updatedPositions[0].height;
|
|
8304
|
+
}
|
|
8305
|
+
} catch (e) {
|
|
8306
|
+
}
|
|
8307
|
+
}
|
|
8308
|
+
const labelPosition = C.Cartesian3.fromDegrees(lon, lat, terrainHeight + 1);
|
|
8117
8309
|
layer.entities.add({
|
|
8118
|
-
id: `${
|
|
8310
|
+
id: `${ownerId}-label`,
|
|
8119
8311
|
name: "Polygon Label",
|
|
8120
|
-
position:
|
|
8312
|
+
position: labelPosition,
|
|
8121
8313
|
label: {
|
|
8122
8314
|
text: displayText,
|
|
8123
8315
|
font: "bold 16px Microsoft YaHei, SimHei, sans-serif",
|
|
@@ -8127,14 +8319,14 @@ var PolygonEditor = class {
|
|
|
8127
8319
|
style: C.LabelStyle.FILL_AND_OUTLINE,
|
|
8128
8320
|
verticalOrigin: C.VerticalOrigin.BOTTOM,
|
|
8129
8321
|
pixelOffset: new C.Cartesian2(0, -10),
|
|
8130
|
-
disableDepthTestDistance: Number.POSITIVE_INFINITY
|
|
8322
|
+
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
8323
|
+
// 仍然设置 heightReference 作为备用
|
|
8324
|
+
heightReference: C.HeightReference.CLAMP_TO_GROUND
|
|
8131
8325
|
},
|
|
8132
|
-
properties: { _ownerId:
|
|
8326
|
+
properties: { _ownerId: ownerId, _type: "polygon-label" }
|
|
8133
8327
|
});
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
console.error(`[PolygonEditor] \u521B\u5EFA\u591A\u8FB9\u5F62\u5931\u8D25:`, err);
|
|
8137
|
-
return null;
|
|
8328
|
+
} catch (e) {
|
|
8329
|
+
console.warn(`[PolygonEditor] \u521B\u5EFA\u6807\u7B7E\u5931\u8D25:`, e);
|
|
8138
8330
|
}
|
|
8139
8331
|
}
|
|
8140
8332
|
/**
|