@jorgmoritz/gis-manager 0.1.26 → 0.1.28

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.
@@ -74,6 +74,8 @@ interface VertexOperationInfo {
74
74
  newPosition?: Cesium.Cartesian3;
75
75
  /** 时间戳 */
76
76
  timestamp: Date;
77
+ /** 🆕 航线总里程(米) */
78
+ totalDistance?: number;
77
79
  }
78
80
  /**
79
81
  * 🆕 顶点拖动中信息(实时)
@@ -74,6 +74,8 @@ interface VertexOperationInfo {
74
74
  newPosition?: Cesium.Cartesian3;
75
75
  /** 时间戳 */
76
76
  timestamp: Date;
77
+ /** 🆕 航线总里程(米) */
78
+ totalDistance?: number;
77
79
  }
78
80
  /**
79
81
  * 🆕 顶点拖动中信息(实时)
package/dist/index.cjs CHANGED
@@ -13,7 +13,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
13
13
  // package.json
14
14
  var package_default = {
15
15
  name: "@jorgmoritz/gis-manager",
16
- version: "0.1.25"};
16
+ version: "0.1.27"};
17
17
 
18
18
  // src/utils/version.ts
19
19
  var version = package_default.version;
@@ -1229,6 +1229,7 @@ var SceneManager = class {
1229
1229
  const tileset = await this.apply3Dtiles(url);
1230
1230
  if (tileset) {
1231
1231
  tileset._customId = layer_id;
1232
+ tileset._url = url;
1232
1233
  this.viewer.scene.primitives.add(tileset);
1233
1234
  console.log(`[SceneManager] \u65B0\u5EFA 3DTiles_id`, tileset._customId);
1234
1235
  }
@@ -1960,6 +1961,8 @@ var PathPreview = class {
1960
1961
  __publicField(this, "fovController");
1961
1962
  // FOV 控制器
1962
1963
  __publicField(this, "currentFOV");
1964
+ /** 已加载的 3D Tiles 实例(预览窗口独立的) */
1965
+ __publicField(this, "tilesets", /* @__PURE__ */ new Map());
1963
1966
  this.currentFOV = opts.fov ?? 50;
1964
1967
  this.ensureViewer();
1965
1968
  this.ensureFOVController();
@@ -2014,8 +2017,201 @@ var PathPreview = class {
2014
2017
  }
2015
2018
  } catch {
2016
2019
  }
2017
- v.scene;
2018
2020
  this.overlayViewer = v;
2021
+ this.syncFromMainViewer();
2022
+ this.disableUserInteraction();
2023
+ }
2024
+ /**
2025
+ * 从主 viewer 同步配置
2026
+ * 共享 Provider(安全)而非 DataSource
2027
+ */
2028
+ syncFromMainViewer() {
2029
+ if (!this.overlayViewer) return;
2030
+ this.syncImageryLayers();
2031
+ this.syncTerrainProvider();
2032
+ this.syncSceneSettings();
2033
+ this.sync3DTiles();
2034
+ }
2035
+ /**
2036
+ * 同步影像图层(共享 ImageryProvider)
2037
+ */
2038
+ syncImageryLayers() {
2039
+ const v = this.overlayViewer;
2040
+ if (!v) return;
2041
+ try {
2042
+ v.imageryLayers?.removeAll?.();
2043
+ const mainImageryLayers = this.mainViewer.imageryLayers;
2044
+ for (let i = 0; i < mainImageryLayers.length; i++) {
2045
+ const layer = mainImageryLayers.get(i);
2046
+ try {
2047
+ v.imageryLayers?.addImageryProvider?.(layer.imageryProvider);
2048
+ } catch {
2049
+ }
2050
+ }
2051
+ } catch (e) {
2052
+ console.warn("[PathPreview] Failed to sync imagery layers:", e);
2053
+ }
2054
+ }
2055
+ /**
2056
+ * 同步地形提供者(共享 TerrainProvider)
2057
+ */
2058
+ syncTerrainProvider() {
2059
+ const v = this.overlayViewer;
2060
+ if (!v) return;
2061
+ try {
2062
+ if (this.mainViewer.terrainProvider) {
2063
+ v.terrainProvider = this.mainViewer.terrainProvider;
2064
+ }
2065
+ } catch (e) {
2066
+ console.warn("[PathPreview] Failed to sync terrain provider:", e);
2067
+ }
2068
+ }
2069
+ /**
2070
+ * 同步 3D Tiles(点云、倾斜摄影等)
2071
+ * 注意:Primitive 不能直接共享,需要创建独立实例
2072
+ * 此方法查找主 viewer 中的 tileset 并尝试使用相同 URL 创建新实例
2073
+ */
2074
+ sync3DTiles() {
2075
+ const v = this.overlayViewer;
2076
+ if (!v) return;
2077
+ const C = this.CesiumNS;
2078
+ const mainPrimitives = this.mainViewer.scene.primitives;
2079
+ try {
2080
+ for (let i = 0; i < mainPrimitives.length; i++) {
2081
+ const primitive = mainPrimitives.get(i);
2082
+ if (primitive && primitive instanceof C.Cesium3DTileset) {
2083
+ const customId = primitive._customId;
2084
+ const url = primitive._url || primitive.resource?.url;
2085
+ if (url && customId && !this.tilesets.has(customId)) {
2086
+ this.add3DTiles(url, customId);
2087
+ }
2088
+ }
2089
+ }
2090
+ } catch (e) {
2091
+ console.warn("[PathPreview] Failed to sync 3DTiles:", e);
2092
+ }
2093
+ }
2094
+ /**
2095
+ * 手动添加 3D Tiles 到预览窗口
2096
+ * @param url 3D Tiles URL
2097
+ * @param id 唯一标识符
2098
+ */
2099
+ async add3DTiles(url, id) {
2100
+ const v = this.overlayViewer;
2101
+ if (!v) return void 0;
2102
+ if (this.tilesets.has(id)) {
2103
+ return this.tilesets.get(id);
2104
+ }
2105
+ const C = this.CesiumNS;
2106
+ try {
2107
+ const tileset = await C.Cesium3DTileset.fromUrl(url, {
2108
+ maximumScreenSpaceError: 16
2109
+ });
2110
+ if (tileset) {
2111
+ tileset._customId = id;
2112
+ tileset._url = url;
2113
+ v.scene.primitives.add(tileset);
2114
+ this.tilesets.set(id, tileset);
2115
+ console.log("[PathPreview] Added 3DTiles:", id);
2116
+ }
2117
+ return tileset;
2118
+ } catch (e) {
2119
+ console.warn("[PathPreview] Failed to add 3DTiles:", url, e);
2120
+ return void 0;
2121
+ }
2122
+ }
2123
+ /**
2124
+ * 移除 3D Tiles
2125
+ */
2126
+ remove3DTiles(id) {
2127
+ const v = this.overlayViewer;
2128
+ if (!v) return;
2129
+ const tileset = this.tilesets.get(id);
2130
+ if (tileset) {
2131
+ try {
2132
+ v.scene.primitives.remove(tileset);
2133
+ } catch {
2134
+ }
2135
+ this.tilesets.delete(id);
2136
+ }
2137
+ }
2138
+ /**
2139
+ * 同步场景设置(Globe、天空、雾效等)
2140
+ */
2141
+ syncSceneSettings() {
2142
+ const v = this.overlayViewer;
2143
+ if (!v) return;
2144
+ const s = v.scene;
2145
+ const mainScene = this.mainViewer.scene;
2146
+ try {
2147
+ if (s.globe && mainScene.globe) {
2148
+ s.globe.show = mainScene.globe.show;
2149
+ s.globe.enableLighting = mainScene.globe.enableLighting;
2150
+ s.globe.baseColor = mainScene.globe.baseColor;
2151
+ s.globe.showGroundAtmosphere = mainScene.globe.showGroundAtmosphere;
2152
+ s.globe.depthTestAgainstTerrain = mainScene.globe.depthTestAgainstTerrain;
2153
+ }
2154
+ if (mainScene.skyBox) {
2155
+ s.skyBox = mainScene.skyBox;
2156
+ } else {
2157
+ s.skyBox = void 0;
2158
+ }
2159
+ if (mainScene.skyAtmosphere) {
2160
+ s.skyAtmosphere.show = mainScene.skyAtmosphere.show;
2161
+ }
2162
+ if (s.fog && mainScene.fog) {
2163
+ s.fog.enabled = mainScene.fog.enabled;
2164
+ s.fog.density = mainScene.fog.density;
2165
+ }
2166
+ v.shadows = this.mainViewer.shadows;
2167
+ if (s.postProcessStages?.fxaa && mainScene.postProcessStages?.fxaa) {
2168
+ s.postProcessStages.fxaa.enabled = mainScene.postProcessStages.fxaa.enabled;
2169
+ }
2170
+ } catch (e) {
2171
+ console.warn("[PathPreview] Failed to sync scene settings:", e);
2172
+ }
2173
+ }
2174
+ /**
2175
+ * 禁用用户交互,相机仅通过 setPose() 控制
2176
+ */
2177
+ disableUserInteraction() {
2178
+ const v = this.overlayViewer;
2179
+ if (!v) return;
2180
+ const s = v.scene;
2181
+ try {
2182
+ const scc = s.screenSpaceCameraController;
2183
+ if (scc) {
2184
+ scc.enableInputs = false;
2185
+ scc.enableRotate = false;
2186
+ scc.enableTranslate = false;
2187
+ scc.enableZoom = false;
2188
+ scc.enableTilt = false;
2189
+ scc.enableLook = false;
2190
+ scc.inertiaSpin = 0;
2191
+ scc.inertiaZoom = 0;
2192
+ scc.inertiaTranslate = 0;
2193
+ }
2194
+ const canvas = s?.canvas ?? v.scene?.canvas;
2195
+ if (canvas && canvas.style) {
2196
+ canvas.style.pointerEvents = "none";
2197
+ try {
2198
+ canvas.setAttribute("tabindex", "-1");
2199
+ } catch {
2200
+ }
2201
+ }
2202
+ v.trackedEntity = void 0;
2203
+ if (v.clock) {
2204
+ v.clock.shouldAnimate = false;
2205
+ }
2206
+ } catch (e) {
2207
+ console.warn("[PathPreview] Failed to disable user interaction:", e);
2208
+ }
2209
+ }
2210
+ /**
2211
+ * 刷新同步(运行时更新)
2212
+ */
2213
+ refresh() {
2214
+ this.syncFromMainViewer();
2019
2215
  }
2020
2216
  /**
2021
2217
  * 创建 FOV 控制器
@@ -2177,30 +2373,63 @@ var PathPreview = class {
2177
2373
  this.fovController.hide();
2178
2374
  }
2179
2375
  }
2180
- // destroy(): void {
2181
- // if (this.destroyed) return;
2182
- // this.destroyed = true;
2183
- // // try {
2184
- // // if (this.footprintEntity) (this.layer.entities as any).remove(this.footprintEntity);
2185
- // // } catch {}
2186
- // this.footprintEntity = undefined;
2187
- //
2188
- // // 销毁 FOV 控制器
2189
- // try {
2190
- // this.fovController?.destroy();
2191
- // } catch {}
2192
- // this.fovController = undefined;
2193
- //
2194
- // try {
2195
- // (this.overlayViewer as any)?.destroy?.();
2196
- // } catch {}
2197
- // this.overlayViewer = undefined;
2198
- // try {
2199
- // if (this.containerEl && this.containerEl.parentElement)
2200
- // this.containerEl.parentElement.removeChild(this.containerEl);
2201
- // } catch {}
2202
- // this.containerEl = undefined;
2203
- // }
2376
+ /**
2377
+ * 显示预览窗口
2378
+ */
2379
+ show() {
2380
+ if (this.containerEl) {
2381
+ this.containerEl.style.display = "block";
2382
+ }
2383
+ }
2384
+ /**
2385
+ * 隐藏预览窗口
2386
+ */
2387
+ hide() {
2388
+ if (this.containerEl) {
2389
+ this.containerEl.style.display = "none";
2390
+ }
2391
+ }
2392
+ /**
2393
+ * 获取预览 viewer 实例
2394
+ */
2395
+ getOverlayViewer() {
2396
+ return this.overlayViewer;
2397
+ }
2398
+ /**
2399
+ * 销毁预览窗口,释放所有资源
2400
+ */
2401
+ destroy() {
2402
+ if (this.destroyed) return;
2403
+ this.destroyed = true;
2404
+ try {
2405
+ this.fovController?.destroy();
2406
+ } catch {
2407
+ }
2408
+ this.fovController = void 0;
2409
+ this.footprintEntity = void 0;
2410
+ try {
2411
+ this.tilesets.forEach((tileset) => {
2412
+ try {
2413
+ this.overlayViewer?.scene?.primitives?.remove?.(tileset);
2414
+ } catch {
2415
+ }
2416
+ });
2417
+ this.tilesets.clear();
2418
+ } catch {
2419
+ }
2420
+ try {
2421
+ this.overlayViewer?.destroy?.();
2422
+ } catch {
2423
+ }
2424
+ this.overlayViewer = void 0;
2425
+ try {
2426
+ if (this.containerEl && this.containerEl.parentElement) {
2427
+ this.containerEl.parentElement.removeChild(this.containerEl);
2428
+ }
2429
+ } catch {
2430
+ }
2431
+ this.containerEl = void 0;
2432
+ }
2204
2433
  };
2205
2434
 
2206
2435
  // src/core/path-manager/FrustumPyramid.ts
@@ -2936,11 +3165,11 @@ var AirplaneCursor = class {
2936
3165
  setPos(addVec(pose.position, C.Cartesian3.multiplyByScalar(e3, step, new C.Cartesian3())));
2937
3166
  moved = true;
2938
3167
  }
2939
- if (this.keysPressed.has("z")) {
3168
+ if (this.keysPressed.has("c")) {
2940
3169
  setPos(addVec(pose.position, C.Cartesian3.multiplyByScalar(u3, step, new C.Cartesian3())));
2941
3170
  moved = true;
2942
3171
  }
2943
- if (this.keysPressed.has("c")) {
3172
+ if (this.keysPressed.has("z")) {
2944
3173
  setPos(addVec(pose.position, C.Cartesian3.multiplyByScalar(u3, -step, new C.Cartesian3())));
2945
3174
  moved = true;
2946
3175
  }
@@ -4088,6 +4317,7 @@ var PathEditingEventHandler = class {
4088
4317
  __publicField(this, "contextMenuManager");
4089
4318
  __publicField(this, "vertexDragHandler");
4090
4319
  __publicField(this, "callbacks");
4320
+ __publicField(this, "keydownListener");
4091
4321
  this.CesiumNS = options.CesiumNS;
4092
4322
  this.viewer = options.viewer;
4093
4323
  this.hiddenClimbIndex = options.hiddenClimbIndex;
@@ -4212,6 +4442,37 @@ var PathEditingEventHandler = class {
4212
4442
  }
4213
4443
  this.handleRightClick(movement);
4214
4444
  }, C.ScreenSpaceEventType.RIGHT_CLICK);
4445
+ this.keydownListener = (e) => {
4446
+ if (e.code !== "Space") return;
4447
+ const target = e.target;
4448
+ if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable) {
4449
+ return;
4450
+ }
4451
+ if (this.vertexDragHandler.isDragging()) return;
4452
+ e.preventDefault();
4453
+ this.handleSpaceKeyInsert();
4454
+ };
4455
+ document.addEventListener("keydown", this.keydownListener);
4456
+ }
4457
+ /**
4458
+ * 处理空格键快捷插入航点
4459
+ * 在飞机游标当前位置,将航点添加到所有航点末尾
4460
+ */
4461
+ handleSpaceKeyInsert() {
4462
+ const airplaneCursor = this.callbacks.getAirplaneCursor?.();
4463
+ if (!airplaneCursor) {
4464
+ console.warn("[PathEditingEventHandler] \u7A7A\u683C\u952E\u63D2\u5165\uFF1A\u98DE\u673A\u6E38\u6807\u4E0D\u5B58\u5728");
4465
+ return;
4466
+ }
4467
+ const pose = airplaneCursor.getPose();
4468
+ if (!pose || !pose.position) {
4469
+ console.warn("[PathEditingEventHandler] \u7A7A\u683C\u952E\u63D2\u5165\uFF1A\u65E0\u6CD5\u83B7\u53D6\u6E38\u6807\u59FF\u6001");
4470
+ return;
4471
+ }
4472
+ const positions = this.callbacks.getPositions?.() || [];
4473
+ const insertAt = positions.length;
4474
+ console.log("[PathEditingEventHandler] \u7A7A\u683C\u952E\u5FEB\u6377\u63D2\u5165\u822A\u70B9\uFF0C\u4F4D\u7F6E\u7D22\u5F15:", insertAt);
4475
+ this.handleInsertVertex(insertAt, pose, "after");
4215
4476
  }
4216
4477
  /**
4217
4478
  * 处理右键点击事件
@@ -4226,12 +4487,13 @@ var PathEditingEventHandler = class {
4226
4487
  const entity = picked?.id;
4227
4488
  const airplaneCursor = this.callbacks.getAirplaneCursor?.();
4228
4489
  const vertexIndex = pickVertexIndex(this.viewer, movement.position, this.hiddenClimbIndex);
4490
+ const viewportPosition = this.canvasToViewportPosition(movement.position);
4229
4491
  if (typeof vertexIndex === "number") {
4230
4492
  const menuItems = this.buildVertexContextMenuItems(vertexIndex);
4231
- this.contextMenuManager.show(movement.position, menuItems);
4493
+ this.contextMenuManager.show(viewportPosition, menuItems);
4232
4494
  } else if (airplaneCursor && airplaneCursor.containsEntity(entity)) {
4233
4495
  const menuItems = this.buildAirplaneCursorContextMenuItems();
4234
- this.contextMenuManager.show(movement.position, menuItems);
4496
+ this.contextMenuManager.show(viewportPosition, menuItems);
4235
4497
  }
4236
4498
  } catch (error) {
4237
4499
  console.error("Error handling right click:", error);
@@ -4535,6 +4797,18 @@ var PathEditingEventHandler = class {
4535
4797
  return 0;
4536
4798
  }
4537
4799
  }
4800
+ /**
4801
+ * 将 canvas 坐标转换为视口坐标
4802
+ * Cesium 事件返回的坐标是相对于 canvas 的,而菜单需要相对于视口的坐标
4803
+ */
4804
+ canvasToViewportPosition(canvasPosition) {
4805
+ const canvas = this.viewer.scene.canvas;
4806
+ const rect = canvas.getBoundingClientRect();
4807
+ return {
4808
+ x: canvasPosition.x + rect.left,
4809
+ y: canvasPosition.y + rect.top
4810
+ };
4811
+ }
4538
4812
  /**
4539
4813
  * 🆕 从鼠标事件获取位置
4540
4814
  */
@@ -4560,6 +4834,10 @@ var PathEditingEventHandler = class {
4560
4834
  * 销毁事件处理器
4561
4835
  */
4562
4836
  destroy() {
4837
+ if (this.keydownListener) {
4838
+ document.removeEventListener("keydown", this.keydownListener);
4839
+ this.keydownListener = void 0;
4840
+ }
4563
4841
  try {
4564
4842
  this.vertexDragHandler.destroy();
4565
4843
  } catch {
@@ -4971,6 +5249,10 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
4971
5249
  } catch {
4972
5250
  }
4973
5251
  };
5252
+ const getTotalDistance = () => {
5253
+ if (positions.length < 2) return 0;
5254
+ return calculatePathDistance(CesiumNS, positions, positions.length - 1, hiddenClimbIndex);
5255
+ };
4974
5256
  const vertexInsertionHandler = new VertexInsertionHandler({
4975
5257
  CesiumNS,
4976
5258
  layer,
@@ -4981,6 +5263,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
4981
5263
  if (!cursorStart) cursorStart = positions[hiddenClimbIndex === 1 ? 1 : 0];
4982
5264
  let airplaneCursor;
4983
5265
  const insertVertex = (insertAt, p3, poseOrient) => {
5266
+ console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u524D positions \u957F\u5EA6:", positions.length, "insertAt:", insertAt);
4984
5267
  const actualIndex = vertexInsertionHandler.insertVertex(
4985
5268
  insertAt,
4986
5269
  p3,
@@ -4996,6 +5279,8 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
4996
5279
  airplaneCursor,
4997
5280
  poseOrient
4998
5281
  );
5282
+ console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length, "actualIndex:", actualIndex);
5283
+ entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
4999
5284
  setActiveIndex(actualIndex);
5000
5285
  createOrUpdateMarkerForIndex(actualIndex);
5001
5286
  };
@@ -5026,6 +5311,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5026
5311
  } catch {
5027
5312
  }
5028
5313
  }
5314
+ console.log("[PathEditing] \u5220\u9664\u9876\u70B9\u524D positions \u957F\u5EA6:", positions.length, "deleteAt:", deleteAt);
5029
5315
  positions.splice(deleteAt, 1);
5030
5316
  handles.splice(deleteAt, 1);
5031
5317
  headings.splice(deleteAt, 1);
@@ -5033,6 +5319,8 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5033
5319
  rolls.splice(deleteAt, 1);
5034
5320
  fovs.splice(deleteAt, 1);
5035
5321
  heightMarkers.splice(deleteAt, 1);
5322
+ console.log("[PathEditing] \u5220\u9664\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length);
5323
+ entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
5036
5324
  const newEditedIndices = /* @__PURE__ */ new Set();
5037
5325
  editedIndices.forEach((idx) => {
5038
5326
  if (idx < deleteAt) {
@@ -5155,7 +5443,9 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5155
5443
  totalVerticesBefore: totalBefore,
5156
5444
  totalVerticesAfter: totalAfter,
5157
5445
  newVertex,
5158
- timestamp: /* @__PURE__ */ new Date()
5446
+ timestamp: /* @__PURE__ */ new Date(),
5447
+ totalDistance: getTotalDistance()
5448
+ // 🆕 航线总里程
5159
5449
  };
5160
5450
  options.onVertexInsertDetail(operationInfo);
5161
5451
  } catch (error) {
@@ -5176,7 +5466,9 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5176
5466
  displayNumber,
5177
5467
  totalVerticesBefore: totalBefore,
5178
5468
  totalVerticesAfter: totalAfter,
5179
- timestamp: /* @__PURE__ */ new Date()
5469
+ timestamp: /* @__PURE__ */ new Date(),
5470
+ totalDistance: getTotalDistance()
5471
+ // 🆕 航线总里程
5180
5472
  };
5181
5473
  options.onVertexDeleteDetail(operationInfo);
5182
5474
  } catch (error) {
@@ -5256,7 +5548,9 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5256
5548
  totalVerticesAfter: positions.length,
5257
5549
  newVertex: vertexInfo,
5258
5550
  newPosition: finalPosition,
5259
- timestamp: /* @__PURE__ */ new Date()
5551
+ timestamp: /* @__PURE__ */ new Date(),
5552
+ totalDistance: getTotalDistance()
5553
+ // 🆕 航线总里程
5260
5554
  };
5261
5555
  options.onVertexDragCompleteDetail(operationInfo);
5262
5556
  } catch (error) {
@@ -5285,6 +5579,18 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5285
5579
  );
5286
5580
  const cleanupSession = () => {
5287
5581
  setActiveIndex(void 0);
5582
+ try {
5583
+ handles.forEach((handle) => {
5584
+ if (handle) {
5585
+ try {
5586
+ layer.entities.remove(handle);
5587
+ } catch {
5588
+ }
5589
+ }
5590
+ });
5591
+ handles.length = 0;
5592
+ } catch {
5593
+ }
5288
5594
  try {
5289
5595
  heightMarkers.forEach((m) => m?.destroy());
5290
5596
  } catch {
@@ -5609,7 +5915,55 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5609
5915
  /**
5610
5916
  * 🆕 获取游标当前姿态(包含高度)
5611
5917
  */
5612
- getCursorPose: () => airplaneCursor?.getPose()
5918
+ getCursorPose: () => airplaneCursor?.getPose(),
5919
+ /**
5920
+ * 🆕 动态更新爬升高度(climbHeight)
5921
+ * 更新隐藏爬升点(index 1)的高度,实现安全飞行高度的动态调节
5922
+ * @param climbHeight 新的爬升高度(米)
5923
+ * @returns 是否更新成功
5924
+ */
5925
+ updateClimbHeight: function(climbHeight) {
5926
+ if (hiddenClimbIndex !== 1 || positions.length < 2) {
5927
+ console.warn("[updateClimbHeight] No hidden climb point exists");
5928
+ return false;
5929
+ }
5930
+ try {
5931
+ const startPos = positions[0];
5932
+ const startCarto = C.Cartographic.fromCartesian(startPos);
5933
+ const newAltitude = startCarto.height + climbHeight;
5934
+ const success = this.updateWaypointAltitude(1, newAltitude);
5935
+ if (success) {
5936
+ try {
5937
+ entity.properties._climbHeight = climbHeight;
5938
+ } catch {
5939
+ }
5940
+ console.log("[updateClimbHeight] \u2705 \u722C\u5347\u9AD8\u5EA6\u5DF2\u66F4\u65B0:", climbHeight, "\u7C73");
5941
+ }
5942
+ return success;
5943
+ } catch (error) {
5944
+ console.error("[updateClimbHeight] Error:", error);
5945
+ return false;
5946
+ }
5947
+ },
5948
+ /**
5949
+ * 🆕 获取起飞点信息
5950
+ * @returns 起飞点的经纬度和高度
5951
+ */
5952
+ getStartPoint: () => {
5953
+ if (positions.length < 1) return null;
5954
+ try {
5955
+ const startPos = positions[0];
5956
+ const carto = C.Cartographic.fromCartesian(startPos);
5957
+ return {
5958
+ position: startPos,
5959
+ latitude: C.Math.toDegrees(carto.latitude),
5960
+ longitude: C.Math.toDegrees(carto.longitude),
5961
+ altitude: carto.height
5962
+ };
5963
+ } catch {
5964
+ return null;
5965
+ }
5966
+ }
5613
5967
  };
5614
5968
  }
5615
5969
  function fovToFocalLength(fovDeg) {
@@ -5785,6 +6139,7 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
5785
6139
  const DEFAULT_MAIN_WIDTH = options?.width ?? 6;
5786
6140
  let startCartographic;
5787
6141
  let hasStart = false;
6142
+ let createdEntity = void 0;
5788
6143
  const getPositionFromMouse = (movement) => {
5789
6144
  const scene = viewer.scene;
5790
6145
  const winPos = movement?.position ?? movement?.endPosition ?? movement;
@@ -5885,6 +6240,7 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
5885
6240
  _hasHiddenClimb: climbHeight > 0
5886
6241
  }
5887
6242
  });
6243
+ createdEntity = created;
5888
6244
  try {
5889
6245
  tempHandles.forEach((hh, idx) => {
5890
6246
  try {
@@ -5921,8 +6277,21 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
5921
6277
  } else {
5922
6278
  editOptions.preview = { enabled: true };
5923
6279
  }
5924
- if (options?.onVertexSelectDetail) {
5925
- editOptions.onVertexSelectDetail = options.onVertexSelectDetail;
6280
+ const autoOpts = typeof auto === "object" ? auto : {};
6281
+ if (autoOpts.onVertexSelectDetail) {
6282
+ editOptions.onVertexSelectDetail = autoOpts.onVertexSelectDetail;
6283
+ }
6284
+ if (autoOpts.onVertexDragMoveDetail) {
6285
+ editOptions.onVertexDragMoveDetail = autoOpts.onVertexDragMoveDetail;
6286
+ }
6287
+ if (autoOpts.onVertexDragCompleteDetail) {
6288
+ editOptions.onVertexDragCompleteDetail = autoOpts.onVertexDragCompleteDetail;
6289
+ }
6290
+ if (autoOpts.onVertexInsertDetail) {
6291
+ editOptions.onVertexInsertDetail = autoOpts.onVertexInsertDetail;
6292
+ }
6293
+ if (autoOpts.onVertexDeleteDetail) {
6294
+ editOptions.onVertexDeleteDetail = autoOpts.onVertexDeleteDetail;
5926
6295
  }
5927
6296
  const editSession = startPathEditing(CesiumNS, viewer, created, editOptions);
5928
6297
  if (editSession && options?.onEditingStarted) {
@@ -5948,6 +6317,12 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
5948
6317
  handler?.destroy();
5949
6318
  } catch {
5950
6319
  }
6320
+ if (createdEntity) {
6321
+ try {
6322
+ layer.entities.remove(createdEntity);
6323
+ } catch {
6324
+ }
6325
+ }
5951
6326
  }
5952
6327
  };
5953
6328
  }