@jorgmoritz/gis-manager 0.1.43 → 0.1.44

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/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.42"};
16
+ version: "0.1.43"};
17
17
 
18
18
  // src/utils/version.ts
19
19
  var version = package_default.version;
@@ -2004,14 +2004,15 @@ var HeightMarker = class {
2004
2004
  polyline: {
2005
2005
  positions: [C.Cartesian3.ZERO, C.Cartesian3.ZERO],
2006
2006
  width: this.opts.width ?? 2,
2007
- material: color,
2007
+ material: C.Color.YELLOW.withAlpha(0.4),
2008
+ // 黄色半透明垂直线
2008
2009
  clampToGround: false
2009
2010
  // vertical line in 3D space
2010
2011
  },
2011
2012
  ellipse: {
2012
- semiMajorAxis: this.opts.circleRadius ?? 5,
2013
- semiMinorAxis: this.opts.circleRadius ?? 5,
2014
- material: color.withAlpha ? color.withAlpha(0.65) : color,
2013
+ semiMajorAxis: this.opts.circleRadius ?? 3,
2014
+ semiMinorAxis: this.opts.circleRadius ?? 3,
2015
+ material: color.withAlpha ? color.withAlpha(0.45) : color,
2015
2016
  outline: true,
2016
2017
  outlineColor: color,
2017
2018
  heightReference: C.HeightReference.CLAMP_TO_GROUND
@@ -2022,12 +2023,13 @@ var HeightMarker = class {
2022
2023
  position: C.Cartesian3.ZERO,
2023
2024
  label: {
2024
2025
  text: "",
2025
- font: "14px sans-serif",
2026
+ font: "10px sans-serif",
2027
+ // 字体改小
2026
2028
  style: C.LabelStyle.FILL_AND_OUTLINE,
2027
2029
  fillColor: C.Color.BLACK,
2028
2030
  outlineColor: C.Color.WHITE,
2029
- outlineWidth: 3,
2030
- pixelOffset: new C.Cartesian2(0, -6),
2031
+ outlineWidth: 2,
2032
+ pixelOffset: new C.Cartesian2(0, -4),
2031
2033
  showBackground: false,
2032
2034
  horizontalOrigin: C.HorizontalOrigin.CENTER,
2033
2035
  verticalOrigin: C.VerticalOrigin.BOTTOM,
@@ -3553,6 +3555,8 @@ var AirplaneCursor = class {
3553
3555
  __publicField(this, "cachedScaleFactor", 1);
3554
3556
  // 相机变化事件监听器
3555
3557
  __publicField(this, "cameraChangedListener");
3558
+ /** 飞机游标模型可见性,默认 false */
3559
+ __publicField(this, "visible", false);
3556
3560
  const C = this.CesiumNS;
3557
3561
  this.opts = opts;
3558
3562
  this.pose = { position: startPosition, heading: 0, pitch: -10, roll: 0 };
@@ -3560,6 +3564,7 @@ var AirplaneCursor = class {
3560
3564
  this.angleStep = opts.angleStepDeg ?? 1;
3561
3565
  this.fastFactor = opts.fastFactor ?? 5;
3562
3566
  this.currentFOV = opts.fovDeg ?? DEFAULT_FOV;
3567
+ this.visible = opts.visible ?? false;
3563
3568
  this.ensureEntity(opts.color ?? C.Color.CYAN.withAlpha(0.9));
3564
3569
  this.attachKeyboard(opts);
3565
3570
  this.setupFOVListener();
@@ -3614,6 +3619,8 @@ var AirplaneCursor = class {
3614
3619
  runAnimations: true,
3615
3620
  clampAnimations: false
3616
3621
  },
3622
+ show: this.visible,
3623
+ // 根据 visible 设置初始显示状态
3617
3624
  properties: { _type: "airplane-cursor" }
3618
3625
  });
3619
3626
  this.entity = this.modelEntity;
@@ -3841,6 +3848,18 @@ var AirplaneCursor = class {
3841
3848
  altitude
3842
3849
  };
3843
3850
  }
3851
+ /** 设置飞机游标可见性 */
3852
+ setVisible(visible) {
3853
+ this.visible = visible;
3854
+ if (this.modelEntity) {
3855
+ this.modelEntity.show = visible;
3856
+ }
3857
+ this.viewer.scene?.requestRender?.();
3858
+ }
3859
+ /** 获取当前可见性状态 */
3860
+ isVisible() {
3861
+ return this.visible;
3862
+ }
3844
3863
  /** 获取内部实体(用于拾取识别) */
3845
3864
  getEntity() {
3846
3865
  return this.entity;
@@ -5070,6 +5089,44 @@ function calculateRelativeHeight(altitudeMode, absoluteHeight, startPointAltitud
5070
5089
  }
5071
5090
  }
5072
5091
 
5092
+ // src/utils/geometryUtils.ts
5093
+ function calculateDistanceAndMidpoint(CesiumNS, point1, point2) {
5094
+ const C = CesiumNS;
5095
+ const distance = C.Cartesian3.distance(point1, point2);
5096
+ const midpoint = new C.Cartesian3();
5097
+ C.Cartesian3.midpoint(point1, point2, midpoint);
5098
+ return { distance, midpoint };
5099
+ }
5100
+ function calculateDistance(CesiumNS, point1, point2) {
5101
+ const C = CesiumNS;
5102
+ return C.Cartesian3.distance(point1, point2);
5103
+ }
5104
+ function calculateMidpoint(CesiumNS, point1, point2) {
5105
+ const C = CesiumNS;
5106
+ const midpoint = new C.Cartesian3();
5107
+ C.Cartesian3.midpoint(point1, point2, midpoint);
5108
+ return midpoint;
5109
+ }
5110
+ function calculateHeadingBetweenPoints(CesiumNS, point1, point2) {
5111
+ const C = CesiumNS;
5112
+ try {
5113
+ const fromCarto = C.Cartographic.fromCartesian(point1);
5114
+ const toCarto = C.Cartographic.fromCartesian(point2);
5115
+ const deltaLon = toCarto.longitude - fromCarto.longitude;
5116
+ let heading = Math.atan2(
5117
+ Math.sin(deltaLon) * Math.cos(toCarto.latitude),
5118
+ Math.cos(fromCarto.latitude) * Math.sin(toCarto.latitude) - Math.sin(fromCarto.latitude) * Math.cos(toCarto.latitude) * Math.cos(deltaLon)
5119
+ );
5120
+ heading = C.Math.toDegrees(heading);
5121
+ if (heading > 180) heading -= 360;
5122
+ if (heading < -180) heading += 360;
5123
+ return heading;
5124
+ } catch (error) {
5125
+ console.error("[calculateHeadingBetweenPoints] Error:", error);
5126
+ return 0;
5127
+ }
5128
+ }
5129
+
5073
5130
  // src/core/path-manager/editing/PathEditingEventHandler.ts
5074
5131
  var PathEditingEventHandler = class {
5075
5132
  constructor(options, callbacks) {
@@ -5130,36 +5187,14 @@ var PathEditingEventHandler = class {
5130
5187
  if (typeof index === "number") {
5131
5188
  if (currentActiveIndex === index) {
5132
5189
  this.vertexDragHandler.startDrag(index, movement.position);
5133
- } else {
5134
- if (this.callbacks.onVertexSelect) {
5135
- this.callbacks.onVertexSelect(index);
5136
- }
5137
- console.log("[PathEditingEventHandler] \u9876\u70B9\u88AB\u70B9\u51FB\uFF0C\u7D22\u5F15:", index, "\u56DE\u8C03\u5B58\u5728:", !!this.callbacks.onVertexSelectDetail);
5138
- if (this.callbacks.onVertexSelectDetail) {
5139
- try {
5140
- const detailInfo = this.buildVertexDetailInfo(index);
5141
- console.log("[PathEditingEventHandler] \u8C03\u7528 onVertexSelectDetail \u56DE\u8C03");
5142
- this.callbacks.onVertexSelectDetail(detailInfo);
5143
- } catch (error) {
5144
- console.error("[PathEditingEventHandler] Error building vertex detail info:", error);
5145
- }
5146
- }
5147
5190
  }
5148
5191
  return;
5149
5192
  }
5150
5193
  }
5151
5194
  const idx = pickVertexIndex(this.viewer, movement.position, this.hiddenClimbIndex);
5152
5195
  if (typeof idx === "number") {
5153
- if (this.callbacks.onVertexSelect) {
5154
- this.callbacks.onVertexSelect(idx);
5155
- }
5156
- if (this.callbacks.onVertexSelectDetail) {
5157
- try {
5158
- const detailInfo = this.buildVertexDetailInfo(idx);
5159
- this.callbacks.onVertexSelectDetail(detailInfo);
5160
- } catch (error) {
5161
- console.error("Error building vertex detail info:", error);
5162
- }
5196
+ if (currentActiveIndex === idx) {
5197
+ this.vertexDragHandler.startDrag(idx, movement.position);
5163
5198
  }
5164
5199
  }
5165
5200
  }, C.ScreenSpaceEventType.LEFT_DOWN);
@@ -5178,6 +5213,26 @@ var PathEditingEventHandler = class {
5178
5213
  if (this.vertexDragHandler.isDragging()) {
5179
5214
  return;
5180
5215
  }
5216
+ const scene = this.viewer.scene;
5217
+ const picked = scene.pick?.(movement.position);
5218
+ const entity = picked?.id;
5219
+ if (entity?.properties?._type?.getValue?.() === "vertex-label") {
5220
+ const labelIndex = entity.properties._vertexIndex?.getValue?.();
5221
+ if (typeof labelIndex === "number") {
5222
+ if (this.callbacks.onVertexSelect) {
5223
+ this.callbacks.onVertexSelect(labelIndex);
5224
+ }
5225
+ if (this.callbacks.onVertexSelectDetail) {
5226
+ try {
5227
+ const detailInfo = this.buildVertexDetailInfo(labelIndex);
5228
+ this.callbacks.onVertexSelectDetail(detailInfo);
5229
+ } catch (error) {
5230
+ console.error("Error building vertex detail info:", error);
5231
+ }
5232
+ }
5233
+ return;
5234
+ }
5235
+ }
5181
5236
  const idx = pickVertexIndex(this.viewer, movement.position, this.hiddenClimbIndex);
5182
5237
  if (typeof idx === "number") {
5183
5238
  if (this.callbacks.onVertexSelect) {
@@ -5193,6 +5248,45 @@ var PathEditingEventHandler = class {
5193
5248
  }
5194
5249
  return;
5195
5250
  }
5251
+ const CLICK_THRESHOLD_PIXELS = 25;
5252
+ const positions = this.callbacks.getPositions?.() || [];
5253
+ if (positions.length > 0) {
5254
+ const clickPos = movement.position;
5255
+ let minDistance = Infinity;
5256
+ let nearestIndex = -1;
5257
+ for (let i = 0; i < positions.length; i++) {
5258
+ try {
5259
+ const screenPos = C.SceneTransforms.wgs84ToWindowCoordinates(
5260
+ scene,
5261
+ positions[i]
5262
+ );
5263
+ if (screenPos) {
5264
+ const dx = screenPos.x - clickPos.x;
5265
+ const dy = screenPos.y - clickPos.y;
5266
+ const distance = Math.sqrt(dx * dx + dy * dy);
5267
+ if (distance < minDistance) {
5268
+ minDistance = distance;
5269
+ nearestIndex = i;
5270
+ }
5271
+ }
5272
+ } catch {
5273
+ }
5274
+ }
5275
+ if (minDistance < CLICK_THRESHOLD_PIXELS && nearestIndex >= 0) {
5276
+ if (this.callbacks.onVertexSelect) {
5277
+ this.callbacks.onVertexSelect(nearestIndex);
5278
+ }
5279
+ if (this.callbacks.onVertexSelectDetail) {
5280
+ try {
5281
+ const detailInfo = this.buildVertexDetailInfo(nearestIndex);
5282
+ this.callbacks.onVertexSelectDetail(detailInfo);
5283
+ } catch (error) {
5284
+ console.error("Error building vertex detail info:", error);
5285
+ }
5286
+ }
5287
+ return;
5288
+ }
5289
+ }
5196
5290
  const quickEditEnabled = this.callbacks.getQuickEditEnabled?.();
5197
5291
  if (quickEditEnabled) {
5198
5292
  this.handleQuickEditClick(movement);
@@ -5296,6 +5390,14 @@ var PathEditingEventHandler = class {
5296
5390
  this.handleInsertVertex(activeIndex + 1, pose, "after");
5297
5391
  }
5298
5392
  });
5393
+ if (activeIndex < positions.length - 1) {
5394
+ menuItems.push({
5395
+ label: "\u5728\u4E2D\u95F4\u63D2\u5165\u822A\u70B9",
5396
+ action: () => {
5397
+ this.handleInsertMidpoint(activeIndex);
5398
+ }
5399
+ });
5400
+ }
5299
5401
  } else if (pose && visibleVertexCount <= 1) {
5300
5402
  menuItems.push({
5301
5403
  label: "\u6DFB\u52A0\u7B2C\u4E00\u4E2A\u822A\u70B9",
@@ -5442,6 +5544,27 @@ var PathEditingEventHandler = class {
5442
5544
  });
5443
5545
  }
5444
5546
  }
5547
+ /**
5548
+ * 🆕 在选中航点和下一个航点中间插入新航点
5549
+ */
5550
+ handleInsertMidpoint(activeIndex) {
5551
+ const positions = this.callbacks.getPositions?.() || [];
5552
+ const poseData = this.callbacks.getPoseData?.();
5553
+ if (activeIndex >= positions.length - 1) {
5554
+ console.warn("[handleInsertMidpoint] \u9009\u4E2D\u822A\u70B9\u662F\u6700\u540E\u4E00\u4E2A\uFF0C\u65E0\u6CD5\u63D2\u5165\u4E2D\u70B9");
5555
+ return;
5556
+ }
5557
+ const point1 = positions[activeIndex];
5558
+ const point2 = positions[activeIndex + 1];
5559
+ const { midpoint } = calculateDistanceAndMidpoint(this.CesiumNS, point1, point2);
5560
+ const heading = calculateHeadingBetweenPoints(this.CesiumNS, point1, point2);
5561
+ const pitch = poseData?.pitches[activeIndex] ?? -10;
5562
+ const roll = poseData?.rolls[activeIndex] ?? 0;
5563
+ console.log("[handleInsertMidpoint] \u5728\u7D22\u5F15", activeIndex, "\u548C", activeIndex + 1, "\u4E4B\u95F4\u63D2\u5165\u4E2D\u70B9");
5564
+ if (this.callbacks.onInsertVertex) {
5565
+ this.callbacks.onInsertVertex(activeIndex + 1, midpoint, { heading, pitch, roll });
5566
+ }
5567
+ }
5445
5568
  /**
5446
5569
  * 处理删除顶点
5447
5570
  */
@@ -5890,23 +6013,37 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5890
6013
  while (useGlobalHeightFlags.length < positions.length) {
5891
6014
  useGlobalHeightFlags.push(false);
5892
6015
  }
5893
- let quickEditEnabled = false;
6016
+ const waypointIds = [];
6017
+ if (options?.waypointIds && Array.isArray(options.waypointIds)) {
6018
+ const offset = 0;
6019
+ for (let i = 0; i < offset; i++) {
6020
+ waypointIds[i] = void 0;
6021
+ }
6022
+ options.waypointIds.forEach((id, idx) => {
6023
+ waypointIds[offset + idx] = id;
6024
+ });
6025
+ }
6026
+ while (waypointIds.length < positions.length) {
6027
+ waypointIds.push(void 0);
6028
+ }
6029
+ let quickEditEnabled = true;
5894
6030
  let quickEditOptions = {
5895
- enabled: false,
6031
+ enabled: true,
5896
6032
  climbHeight: currentDefaultAltitude,
5897
6033
  // 使用当前默认高度
5898
6034
  altitudeMode: currentAltitudeMode
5899
6035
  // 使用当前高度模式
5900
6036
  };
5901
- if (options?.quickEdit) {
6037
+ if (options?.quickEdit !== void 0) {
5902
6038
  if (typeof options.quickEdit === "boolean") {
5903
6039
  quickEditEnabled = options.quickEdit;
5904
6040
  quickEditOptions.enabled = options.quickEdit;
5905
6041
  } else {
5906
- quickEditEnabled = options.quickEdit.enabled ?? false;
6042
+ quickEditEnabled = options.quickEdit.enabled ?? true;
5907
6043
  quickEditOptions = {
5908
6044
  ...quickEditOptions,
5909
- ...options.quickEdit
6045
+ ...options.quickEdit,
6046
+ enabled: options.quickEdit.enabled ?? true
5910
6047
  };
5911
6048
  }
5912
6049
  }
@@ -6001,6 +6138,8 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6001
6138
  const stateManager = new PathStateManager(entity, positions, headings, pitches, rolls, fovs);
6002
6139
  let activeIndex;
6003
6140
  let editedIndices = /* @__PURE__ */ new Set();
6141
+ let isUpdatingFromCursor = false;
6142
+ let isUpdatingFromDrag = false;
6004
6143
  const handleStyleManager = new VertexHandleStyleManager(CesiumNS);
6005
6144
  const setActiveIndex = (idx) => {
6006
6145
  if (activeIndex !== void 0 && handles[activeIndex]) {
@@ -6106,6 +6245,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6106
6245
  useGlobalHeightFlags
6107
6246
  // 🆕 传递 useGlobalHeightFlags
6108
6247
  );
6248
+ waypointIds.splice(actualIndex, 0, void 0);
6109
6249
  console.log("[PathEditing] \u63D2\u5165\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length, "actualIndex:", actualIndex);
6110
6250
  entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
6111
6251
  setActiveIndex(actualIndex);
@@ -6138,6 +6278,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6138
6278
  fovs.splice(deleteAt, 1);
6139
6279
  heightMarkers.splice(deleteAt, 1);
6140
6280
  useGlobalHeightFlags.splice(deleteAt, 1);
6281
+ waypointIds.splice(deleteAt, 1);
6141
6282
  console.log("[PathEditing] \u5220\u9664\u9876\u70B9\u540E positions \u957F\u5EA6:", positions.length);
6142
6283
  entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
6143
6284
  const newEditedIndices = /* @__PURE__ */ new Set();
@@ -6224,12 +6365,36 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6224
6365
  }
6225
6366
  airplaneCursor.updateOptions({
6226
6367
  onPose: (pose) => {
6368
+ if (isUpdatingFromDrag) return;
6227
6369
  try {
6228
6370
  if (preview) {
6229
6371
  preview.setPose(pose.position, pose.heading, pose.pitch, pose.roll, 50);
6230
6372
  }
6231
6373
  } catch {
6232
6374
  }
6375
+ if (activeIndex !== void 0 && !isUpdatingFromCursor) {
6376
+ isUpdatingFromCursor = true;
6377
+ try {
6378
+ positions[activeIndex] = pose.position;
6379
+ headings[activeIndex] = pose.heading;
6380
+ pitches[activeIndex] = pose.pitch;
6381
+ rolls[activeIndex] = pose.roll;
6382
+ if (handles[activeIndex]) {
6383
+ handles[activeIndex].position = pose.position;
6384
+ }
6385
+ vertexLabelManager.updateLabelPosition(activeIndex, pose.position);
6386
+ createOrUpdateMarkerForIndex(activeIndex);
6387
+ editedIndices.add(activeIndex);
6388
+ useGlobalHeightFlags[activeIndex] = false;
6389
+ try {
6390
+ entity.polyline.positions = positions.slice();
6391
+ } catch {
6392
+ }
6393
+ viewer.scene?.requestRender?.();
6394
+ } finally {
6395
+ isUpdatingFromCursor = false;
6396
+ }
6397
+ }
6233
6398
  }
6234
6399
  });
6235
6400
  }
@@ -6305,24 +6470,38 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6305
6470
  },
6306
6471
  onVertexDragMove: (index, newPosition) => {
6307
6472
  console.log("[PathEditing] onVertexDragMove \u88AB\u8C03\u7528, index:", index);
6308
- positions[index] = newPosition;
6309
- if (handles[index]) {
6473
+ if (isUpdatingFromCursor) return;
6474
+ isUpdatingFromDrag = true;
6475
+ try {
6476
+ positions[index] = newPosition;
6477
+ if (handles[index]) {
6478
+ try {
6479
+ handles[index].position = newPosition;
6480
+ } catch {
6481
+ }
6482
+ }
6310
6483
  try {
6311
- handles[index].position = newPosition;
6484
+ vertexLabelManager.updateLabelPosition(index, newPosition);
6312
6485
  } catch {
6313
6486
  }
6314
- }
6315
- try {
6316
- vertexLabelManager.updateLabelPosition(index, newPosition);
6317
- } catch {
6318
- }
6319
- try {
6320
- entity.polyline.positions = positions.slice();
6321
- } catch {
6322
- }
6323
- try {
6324
- viewer.scene.requestRender();
6325
- } catch {
6487
+ try {
6488
+ entity.polyline.positions = positions.slice();
6489
+ } catch {
6490
+ }
6491
+ try {
6492
+ viewer.scene.requestRender();
6493
+ } catch {
6494
+ }
6495
+ if (airplaneCursor && index === activeIndex) {
6496
+ airplaneCursor.setPose(
6497
+ newPosition,
6498
+ headings[index] ?? 0,
6499
+ pitches[index] ?? -10,
6500
+ rolls[index] ?? 0
6501
+ );
6502
+ }
6503
+ } finally {
6504
+ isUpdatingFromDrag = false;
6326
6505
  }
6327
6506
  if (options?.onVertexDragMoveDetail) {
6328
6507
  try {
@@ -6526,6 +6705,55 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6526
6705
  // 🆕 添加相对高度
6527
6706
  };
6528
6707
  };
6708
+ if (options?.initialClickPosition && positions.length === 0) {
6709
+ console.log("[PathEditing] \u5904\u7406\u521D\u59CB\u70B9\u51FB\u4F4D\u7F6E\uFF0C\u7ACB\u5373\u6DFB\u52A0\u7B2C\u4E00\u4E2A\u822A\u70B9");
6710
+ let finalPosition = options.initialClickPosition;
6711
+ try {
6712
+ const cartographic = C.Cartographic.fromCartesian(options.initialClickPosition);
6713
+ const lon = C.Math.toDegrees(cartographic.longitude);
6714
+ const lat = C.Math.toDegrees(cartographic.latitude);
6715
+ let finalHeight;
6716
+ if (currentAltitudeMode === "absolute") {
6717
+ finalHeight = currentDefaultAltitude;
6718
+ } else if (currentAltitudeMode === "relativeToGround") {
6719
+ const terrainHeight = queryTerrainHeightSync(CesiumNS, viewer, options.initialClickPosition);
6720
+ finalHeight = terrainHeight + currentDefaultAltitude;
6721
+ } else if (currentAltitudeMode === "relativeToStart") {
6722
+ finalHeight = currentDefaultAltitude;
6723
+ } else {
6724
+ finalHeight = currentDefaultAltitude;
6725
+ }
6726
+ finalPosition = C.Cartesian3.fromDegrees(lon, lat, finalHeight);
6727
+ console.log("[PathEditing] \u521D\u59CB\u822A\u70B9\u9AD8\u5EA6\u8BA1\u7B97:", {
6728
+ altitudeMode: currentAltitudeMode,
6729
+ defaultAltitude: currentDefaultAltitude,
6730
+ finalHeight
6731
+ });
6732
+ } catch (error) {
6733
+ console.warn("[PathEditing] \u8BA1\u7B97\u521D\u59CB\u822A\u70B9\u9AD8\u5EA6\u5931\u8D25:", error);
6734
+ }
6735
+ const totalBefore = positions.length;
6736
+ insertVertex(0, finalPosition, { heading: 0, pitch: -10, roll: 0 });
6737
+ if (options?.onVertexInsertDetail) {
6738
+ try {
6739
+ const totalAfter = positions.length;
6740
+ const newVertex = buildVertexDetailInfo(0);
6741
+ const operationInfo = {
6742
+ type: "insert",
6743
+ index: 0,
6744
+ displayNumber: newVertex.displayNumber,
6745
+ totalVerticesBefore: totalBefore,
6746
+ totalVerticesAfter: totalAfter,
6747
+ newVertex,
6748
+ timestamp: /* @__PURE__ */ new Date(),
6749
+ totalDistance: getTotalDistance()
6750
+ };
6751
+ options.onVertexInsertDetail(operationInfo);
6752
+ } catch (error) {
6753
+ console.error("[PathEditing] \u89E6\u53D1 onVertexInsertDetail \u56DE\u8C03\u5931\u8D25:", error);
6754
+ }
6755
+ }
6756
+ }
6529
6757
  return {
6530
6758
  /** 保存并退出编辑模式 */
6531
6759
  saveAndStop: () => {
@@ -6567,8 +6795,10 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6567
6795
  distance: calculatePathDistance(CesiumNS, positions, index),
6568
6796
  ellipsoidHeight,
6569
6797
  relativeHeight,
6570
- useGlobalHeight: useGlobalHeightFlags[index] ?? false
6798
+ useGlobalHeight: useGlobalHeightFlags[index] ?? false,
6571
6799
  // 🆕 添加 useGlobalHeight
6800
+ waypointId: waypointIds[index]
6801
+ // 🆕 添加 waypointId(原有航点保留ID,新插入航点为 undefined)
6572
6802
  };
6573
6803
  });
6574
6804
  cleanupSession();
@@ -6951,6 +7181,67 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
6951
7181
  options2?.onProgress?.("error");
6952
7182
  return { success: false, error: String(error) };
6953
7183
  }
7184
+ },
7185
+ /**
7186
+ * 🆕 获取当前选中航点索引
7187
+ * @returns 当前选中的航点索引,如果没有选中则返回 undefined
7188
+ */
7189
+ getActiveIndex: () => {
7190
+ return activeIndex;
7191
+ },
7192
+ /**
7193
+ * 🆕 在选中航点和下一个航点中间插入新航点
7194
+ * @param index 选中航点的索引(如果不传则使用当前选中的航点)
7195
+ * @returns 是否插入成功
7196
+ */
7197
+ insertMidpoint: (index) => {
7198
+ const targetIndex = index ?? activeIndex;
7199
+ if (targetIndex === void 0) {
7200
+ console.warn("[insertMidpoint] \u6CA1\u6709\u9009\u4E2D\u822A\u70B9");
7201
+ return false;
7202
+ }
7203
+ if (targetIndex >= positions.length - 1) {
7204
+ console.warn("[insertMidpoint] \u9009\u4E2D\u822A\u70B9\u662F\u6700\u540E\u4E00\u4E2A\uFF0C\u65E0\u6CD5\u63D2\u5165\u4E2D\u70B9");
7205
+ return false;
7206
+ }
7207
+ const point1 = positions[targetIndex];
7208
+ const point2 = positions[targetIndex + 1];
7209
+ const midpoint = C.Cartesian3.midpoint(point1, point2, new C.Cartesian3());
7210
+ const carto1 = C.Cartographic.fromCartesian(point1);
7211
+ const carto2 = C.Cartographic.fromCartesian(point2);
7212
+ const deltaLon = carto2.longitude - carto1.longitude;
7213
+ let heading = Math.atan2(
7214
+ Math.sin(deltaLon) * Math.cos(carto2.latitude),
7215
+ Math.cos(carto1.latitude) * Math.sin(carto2.latitude) - Math.sin(carto1.latitude) * Math.cos(carto2.latitude) * Math.cos(deltaLon)
7216
+ );
7217
+ heading = C.Math.toDegrees(heading);
7218
+ if (heading > 180) heading -= 360;
7219
+ if (heading < -180) heading += 360;
7220
+ const pitch = pitches[targetIndex] ?? -10;
7221
+ const roll = rolls[targetIndex] ?? 0;
7222
+ console.log("[insertMidpoint] \u5728\u7D22\u5F15", targetIndex, "\u548C", targetIndex + 1, "\u4E4B\u95F4\u63D2\u5165\u4E2D\u70B9");
7223
+ const totalBefore = positions.length;
7224
+ insertVertex(targetIndex + 1, midpoint, { heading, pitch, roll });
7225
+ if (options?.onVertexInsertDetail) {
7226
+ try {
7227
+ const totalAfter = positions.length;
7228
+ const newVertex = buildVertexDetailInfo(targetIndex + 1);
7229
+ const operationInfo = {
7230
+ type: "insert",
7231
+ index: targetIndex + 1,
7232
+ displayNumber: newVertex.displayNumber,
7233
+ totalVerticesBefore: totalBefore,
7234
+ totalVerticesAfter: totalAfter,
7235
+ newVertex,
7236
+ timestamp: /* @__PURE__ */ new Date(),
7237
+ totalDistance: getTotalDistance()
7238
+ };
7239
+ options.onVertexInsertDetail(operationInfo);
7240
+ } catch (error) {
7241
+ console.error("Error in onVertexInsertDetail:", error);
7242
+ }
7243
+ }
7244
+ return true;
6954
7245
  }
6955
7246
  };
6956
7247
  }
@@ -7032,8 +7323,8 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
7032
7323
  try {
7033
7324
  const auto = options?.autoStartEditing;
7034
7325
  const editOptions = {
7035
- // 默认使用自由编辑模式(快速编辑和自由编辑互斥)
7036
- quickEdit: false
7326
+ // 🔧 修复:默认使用快速编辑模式,用户点击地图即可添加航点
7327
+ quickEdit: true
7037
7328
  };
7038
7329
  if (typeof auto === "object" && auto.preview) {
7039
7330
  editOptions.preview = auto.preview;
@@ -7059,8 +7350,9 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
7059
7350
  editOptions.altitudeMode = altitudeMode;
7060
7351
  editOptions.defaultAltitude = defaultAltitude;
7061
7352
  editOptions.climbHeight = climbHeight;
7353
+ editOptions.initialClickPosition = picked;
7062
7354
  editSession = startPathEditing(CesiumNS, viewer, created, editOptions);
7063
- 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");
7355
+ console.log("[startPathDrawing] \u7F16\u8F91\u6A21\u5F0F\u5DF2\u542F\u52A8\uFF0C\u5FEB\u901F\u7F16\u8F91\u6A21\u5F0F\uFF0C\u70B9\u51FB\u5730\u56FE\u6DFB\u52A0\u822A\u70B9");
7064
7356
  if (editSession && options?.onEditingStarted) {
7065
7357
  try {
7066
7358
  options.onEditingStarted(editSession);
@@ -12063,8 +12355,8 @@ function convertPathToSinofly(data, options) {
12063
12355
  );
12064
12356
  const action = convertPoseToActionGroup(wp.heading, wp.pitch, wp.roll, wp.fov, newIndex);
12065
12357
  const waypoint = {
12066
- waypointId: "",
12067
- // 由服务器自动生成
12358
+ waypointId: wp.waypointId ?? "",
12359
+ // 🆕 使用传入的 waypointId,新航点为空字符串
12068
12360
  waylineId,
12069
12361
  index: newIndex,
12070
12362
  latitude,
@@ -12519,7 +12811,11 @@ exports.StateManager = StateManager;
12519
12811
  exports.assertCesiumAssetsConfigured = assertCesiumAssetsConfigured;
12520
12812
  exports.calculateAbsoluteHeight = calculateAbsoluteHeight;
12521
12813
  exports.calculateBoundsDiagonal = calculateBoundsDiagonal;
12814
+ exports.calculateDistance = calculateDistance;
12815
+ exports.calculateDistanceAndMidpoint = calculateDistanceAndMidpoint;
12522
12816
  exports.calculateGeoBounds = calculateGeoBounds;
12817
+ exports.calculateHeadingBetweenPoints = calculateHeadingBetweenPoints;
12818
+ exports.calculateMidpoint = calculateMidpoint;
12523
12819
  exports.calculateRelativeHeight = calculateRelativeHeight;
12524
12820
  exports.configureCesiumAssets = configureCesiumAssets;
12525
12821
  exports.configureCesiumIonToken = configureCesiumIonToken;