@jorgmoritz/gis-manager 0.1.47 → 0.1.49

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.46"};
16
+ version: "0.1.48"};
17
17
 
18
18
  // src/utils/version.ts
19
19
  var version = package_default.version;
@@ -3176,12 +3176,13 @@ var FrustumPyramid = class {
3176
3176
  * - 用 apex 的地表法线作为世界 up,重建无滚转的 right/up,从而避免 pitch 时的视觉侧倾
3177
3177
  * - 基于 fov 与 aspectRatio 求得底面半宽半高,沿 forward 推进 length 得到 baseCenter
3178
3178
  */
3179
- computeFrustumGeometry(apex, headingDeg, pitchDeg, rollDeg, fovDeg, length) {
3179
+ computeFrustumGeometry(apex, headingDeg, pitchDeg, _rollDeg, fovDeg, length) {
3180
3180
  const C = this.CesiumNS;
3181
3181
  const fov = Math.max(1, Math.min(120, fovDeg ?? this.opts.fov ?? DEFAULT_FOV));
3182
3182
  const aspectRatio = this.opts.aspectRatio ?? 4 / 3;
3183
3183
  const halfFovH = C.Math.toRadians(fov / 2);
3184
- const halfWidth = Math.tan(halfFovH) * length;
3184
+ const baseScale = 0.4;
3185
+ const halfWidth = Math.tan(halfFovH) * length * baseScale;
3185
3186
  const halfHeight = halfWidth / aspectRatio;
3186
3187
  const enu = C.Transforms.eastNorthUpToFixedFrame(apex);
3187
3188
  const eastCol = C.Matrix4.getColumn(enu, 0, new C.Cartesian4());
@@ -4271,7 +4272,7 @@ var VertexLabelManager = class {
4271
4272
  startColor: options?.startColor ?? "#FF6B6B",
4272
4273
  outlineColor: options?.outlineColor ?? "#FFFFFF",
4273
4274
  textColor: options?.textColor ?? "#FFFFFF",
4274
- pixelOffsetY: options?.pixelOffsetY ?? -10
4275
+ pixelOffsetY: options?.pixelOffsetY ?? 0
4275
4276
  };
4276
4277
  }
4277
4278
  /**
@@ -4328,7 +4329,7 @@ var VertexLabelManager = class {
4328
4329
  const blob = new Blob([svg], { type: "image/svg+xml" });
4329
4330
  const url = URL.createObjectURL(blob);
4330
4331
  const C = this.CesiumNS;
4331
- const firstWaypointIndex = this.hiddenClimbIndex === 1 ? 2 : 1;
4332
+ const firstWaypointIndex = this.hiddenClimbIndex === 1 ? 2 : 0;
4332
4333
  return this.layer.entities.add({
4333
4334
  position,
4334
4335
  billboard: {
@@ -7887,7 +7888,7 @@ function renderFlightPath(CesiumNS, viewer, options) {
7887
7888
  description: entityDescription,
7888
7889
  polyline: {
7889
7890
  positions: positions.slice(),
7890
- width: options.style?.width ?? 3,
7891
+ width: options.style?.width ?? 5,
7891
7892
  material: options.style?.material ?? options.style?.color ?? C.Color.fromCssColorString("#00E676"),
7892
7893
  clampToGround: false
7893
7894
  },
@@ -9158,7 +9159,7 @@ var PolygonEditor = class {
9158
9159
  this.editHandles = positions.map(
9159
9160
  (p, i) => layer.entities.add({
9160
9161
  position: p,
9161
- point: { pixelSize: 7, color: point_color },
9162
+ point: { pixelSize: 7, color: point_color, outlineColor: C.Color.BLACK, outlineWidth: 1 },
9162
9163
  properties: { _vertexIndex: i }
9163
9164
  })
9164
9165
  );
@@ -9240,6 +9241,24 @@ var PolygonEditor = class {
9240
9241
  return void 0;
9241
9242
  }
9242
9243
  };
9244
+ const highlightHandle = (index) => {
9245
+ const handle = this.editHandles[index];
9246
+ if (handle && handle.point) {
9247
+ handle.point.pixelSize = 10;
9248
+ handle.point.color = C.Color.YELLOW;
9249
+ handle.point.outlineColor = C.Color.RED;
9250
+ handle.point.outlineWidth = 2;
9251
+ }
9252
+ };
9253
+ const unhighlightHandle = (index) => {
9254
+ const handle = this.editHandles[index];
9255
+ if (handle && handle.point) {
9256
+ handle.point.pixelSize = 7;
9257
+ handle.point.color = point_color;
9258
+ handle.point.outlineColor = C.Color.BLACK;
9259
+ handle.point.outlineWidth = 1;
9260
+ }
9261
+ };
9243
9262
  this.handler && this.handler.setInputAction(
9244
9263
  (movement) => {
9245
9264
  const picked = this.viewer.scene.pick?.(movement.position);
@@ -9249,6 +9268,7 @@ var PolygonEditor = class {
9249
9268
  if (typeof idx === "number") {
9250
9269
  this.draggingIndex = idx;
9251
9270
  this.originalPositionOnDrag = positions[idx];
9271
+ highlightHandle(idx);
9252
9272
  if (this.segmentHighlight) {
9253
9273
  try {
9254
9274
  layer.entities.remove(this.segmentHighlight);
@@ -9277,7 +9297,7 @@ var PolygonEditor = class {
9277
9297
  positions.splice(insertIndex, 0, insertPoint);
9278
9298
  const newHandle = layer.entities.add({
9279
9299
  position: insertPoint,
9280
- point: { pixelSize: 7, color: point_color },
9300
+ point: { pixelSize: 7, color: point_color, outlineColor: C.Color.BLACK, outlineWidth: 1 },
9281
9301
  properties: { _vertexIndex: insertIndex }
9282
9302
  });
9283
9303
  this.editHandles.splice(insertIndex, 0, newHandle);
@@ -9289,6 +9309,7 @@ var PolygonEditor = class {
9289
9309
  });
9290
9310
  this.draggingIndex = insertIndex;
9291
9311
  this.originalPositionOnDrag = insertPoint;
9312
+ highlightHandle(insertIndex);
9292
9313
  if (this.segmentHighlight) {
9293
9314
  try {
9294
9315
  layer.entities.remove(this.segmentHighlight);
@@ -9305,6 +9326,7 @@ var PolygonEditor = class {
9305
9326
  }
9306
9327
  }
9307
9328
  } else {
9329
+ unhighlightHandle(this.draggingIndex);
9308
9330
  this.draggingIndex = void 0;
9309
9331
  this.originalPositionOnDrag = void 0;
9310
9332
  }
@@ -9442,7 +9464,10 @@ var PolygonEditor = class {
9442
9464
  if (this.draggingIndex !== void 0 && this.originalPositionOnDrag) {
9443
9465
  positions[this.draggingIndex] = this.originalPositionOnDrag;
9444
9466
  const handle = this.editHandles[this.draggingIndex];
9445
- if (handle) handle.position = this.originalPositionOnDrag;
9467
+ if (handle) {
9468
+ handle.position = this.originalPositionOnDrag;
9469
+ unhighlightHandle(this.draggingIndex);
9470
+ }
9446
9471
  this.draggingIndex = void 0;
9447
9472
  this.originalPositionOnDrag = void 0;
9448
9473
  }
@@ -11248,6 +11273,89 @@ var PolygonEditor = class {
11248
11273
  }
11249
11274
  };
11250
11275
 
11276
+ // src/utils/LayerOrderManager.ts
11277
+ function bringDataSourceToTop(viewer, layerName) {
11278
+ const layers = viewer.dataSources.getByName(layerName);
11279
+ if (layers.length === 0) {
11280
+ return false;
11281
+ }
11282
+ const layer = layers[0];
11283
+ const currentIndex = viewer.dataSources.indexOf(layer);
11284
+ const lastIndex = viewer.dataSources.length - 1;
11285
+ if (currentIndex === lastIndex) {
11286
+ return true;
11287
+ }
11288
+ viewer.dataSources.remove(layer, false);
11289
+ viewer.dataSources.add(layer);
11290
+ return true;
11291
+ }
11292
+ function bringPrimitiveCollectionToTop(viewer, collection) {
11293
+ const primitives = viewer.scene.primitives;
11294
+ const targetGuid = collection._guid;
11295
+ let foundIndex = -1;
11296
+ let foundPrimitive = null;
11297
+ const count = primitives.length;
11298
+ for (let i = 0; i < count; i++) {
11299
+ const p = primitives.get(i);
11300
+ if (p === collection || p._guid === targetGuid) {
11301
+ foundIndex = i;
11302
+ foundPrimitive = p;
11303
+ break;
11304
+ }
11305
+ }
11306
+ if (foundIndex < 0) {
11307
+ console.warn("[LayerOrderManager] bringPrimitiveCollectionToTop: collection not found in primitives");
11308
+ return false;
11309
+ }
11310
+ if (foundIndex === count - 1) {
11311
+ return true;
11312
+ }
11313
+ primitives.raiseToTop(foundPrimitive);
11314
+ return true;
11315
+ }
11316
+ function ensureLayerAbove(viewer, topLayerName, bottomLayerName) {
11317
+ const topLayers = viewer.dataSources.getByName(topLayerName);
11318
+ if (topLayers.length === 0) {
11319
+ return;
11320
+ }
11321
+ if (!bottomLayerName) {
11322
+ bringDataSourceToTop(viewer, topLayerName);
11323
+ return;
11324
+ }
11325
+ const bottomLayers = viewer.dataSources.getByName(bottomLayerName);
11326
+ if (bottomLayers.length === 0) {
11327
+ bringDataSourceToTop(viewer, topLayerName);
11328
+ return;
11329
+ }
11330
+ const topLayer = topLayers[0];
11331
+ const bottomLayer = bottomLayers[0];
11332
+ const topIndex = viewer.dataSources.indexOf(topLayer);
11333
+ const bottomIndex = viewer.dataSources.indexOf(bottomLayer);
11334
+ if (topIndex > bottomIndex) {
11335
+ return;
11336
+ }
11337
+ bringDataSourceToTop(viewer, topLayerName);
11338
+ }
11339
+ function getDataSourceIndex(viewer, layerName) {
11340
+ const layers = viewer.dataSources.getByName(layerName);
11341
+ if (layers.length === 0) {
11342
+ return -1;
11343
+ }
11344
+ return viewer.dataSources.indexOf(layers[0]);
11345
+ }
11346
+ function getDataSourceOrder(viewer) {
11347
+ const result = [];
11348
+ const count = viewer.dataSources.length;
11349
+ for (let i = 0; i < count; i++) {
11350
+ const ds = viewer.dataSources.get(i);
11351
+ result.push({
11352
+ name: ds.name,
11353
+ index: i
11354
+ });
11355
+ }
11356
+ return result;
11357
+ }
11358
+
11251
11359
  // src/core/CZMLManager.ts
11252
11360
  var CZMLManager = class {
11253
11361
  constructor(CesiumNS, viewer) {
@@ -11524,16 +11632,7 @@ var CZMLManager = class {
11524
11632
  } else {
11525
11633
  layer = this.viewer.dataSources.getByName("subarray")[0];
11526
11634
  }
11527
- const inverterLayers = this.viewer.dataSources.getByName("inverter");
11528
- if (inverterLayers.length > 0) {
11529
- const inverterLayer = inverterLayers[0];
11530
- const index = this.viewer.dataSources.indexOf(inverterLayer);
11531
- const lastIndex = this.viewer.dataSources.length - 1;
11532
- if (index >= 0 && index < lastIndex) {
11533
- this.viewer.dataSources.remove(inverterLayer, false);
11534
- this.viewer.dataSources.add(inverterLayer);
11535
- }
11536
- }
11635
+ ensureLayerAbove(this.viewer, "inverter", "subarray");
11537
11636
  } else if (type == "inverter") {
11538
11637
  if (this.viewer.dataSources.getByName("inverter").length < 1) {
11539
11638
  const data = new this.CesiumNS.CustomDataSource("inverter");
@@ -11542,14 +11641,7 @@ var CZMLManager = class {
11542
11641
  } else {
11543
11642
  layer = this.viewer.dataSources.getByName("inverter")[0];
11544
11643
  }
11545
- if (layer) {
11546
- const index = this.viewer.dataSources.indexOf(layer);
11547
- const lastIndex = this.viewer.dataSources.length - 1;
11548
- if (index >= 0 && index < lastIndex) {
11549
- this.viewer.dataSources.remove(layer, false);
11550
- this.viewer.dataSources.add(layer);
11551
- }
11552
- }
11644
+ bringDataSourceToTop(this.viewer, "inverter");
11553
11645
  } else {
11554
11646
  if (this.viewer.dataSources.getByName("other").length < 1) {
11555
11647
  const data = new this.CesiumNS.CustomDataSource("other");
@@ -11558,14 +11650,7 @@ var CZMLManager = class {
11558
11650
  } else {
11559
11651
  layer = this.viewer.dataSources.getByName("other")[0];
11560
11652
  }
11561
- if (layer) {
11562
- const index = this.viewer.dataSources.indexOf(layer);
11563
- const lastIndex = this.viewer.dataSources.length - 1;
11564
- if (index >= 0 && index < lastIndex) {
11565
- this.viewer.dataSources.remove(layer, false);
11566
- this.viewer.dataSources.add(layer);
11567
- }
11568
- }
11653
+ bringDataSourceToTop(this.viewer, "other");
11569
11654
  }
11570
11655
  const session = this.polygonEditor.startDrawing(type, layer, (entity) => {
11571
11656
  this.cancelActivePolygonDrawing();
@@ -11670,14 +11755,7 @@ var CZMLManager = class {
11670
11755
  } else {
11671
11756
  layer = this.viewer.dataSources.getByName("other")[0];
11672
11757
  }
11673
- if (layer) {
11674
- const index = this.viewer.dataSources.indexOf(layer);
11675
- const lastIndex = this.viewer.dataSources.length - 1;
11676
- if (index >= 0 && index < lastIndex) {
11677
- this.viewer.dataSources.remove(layer, false);
11678
- this.viewer.dataSources.add(layer);
11679
- }
11680
- }
11758
+ bringDataSourceToTop(this.viewer, "other");
11681
11759
  return this.polygonEditor.startPointDrawing?.(layer, iconSvg, onComplete);
11682
11760
  }
11683
11761
  // New: start editing an existing polygon entity's vertices
@@ -11715,36 +11793,11 @@ var CZMLManager = class {
11715
11793
  const dataSource = this.getEntityDataSource(entity);
11716
11794
  if (!dataSource) return void 0;
11717
11795
  if (dataSource.name === "inverter") {
11718
- const index = this.viewer.dataSources.indexOf(dataSource);
11719
- const lastIndex = this.viewer.dataSources.length - 1;
11720
- if (index >= 0 && index < lastIndex) {
11721
- this.viewer.dataSources.remove(dataSource, false);
11722
- this.viewer.dataSources.add(dataSource);
11723
- }
11724
- }
11725
- if (dataSource.name === "subarray") {
11726
- const inverterLayers = this.viewer.dataSources.getByName("inverter");
11727
- if (inverterLayers.length > 0) {
11728
- const inverterLayer = inverterLayers[0];
11729
- const index = this.viewer.dataSources.indexOf(inverterLayer);
11730
- const lastIndex = this.viewer.dataSources.length - 1;
11731
- if (index >= 0 && index < lastIndex) {
11732
- this.viewer.dataSources.remove(inverterLayer, false);
11733
- this.viewer.dataSources.add(inverterLayer);
11734
- }
11735
- }
11736
- }
11737
- if (dataSource.name === "other") {
11738
- const otherLayers = this.viewer.dataSources.getByName("other");
11739
- if (otherLayers.length > 0) {
11740
- const otherLayer = otherLayers[0];
11741
- const index = this.viewer.dataSources.indexOf(otherLayer);
11742
- const lastIndex = this.viewer.dataSources.length - 1;
11743
- if (index >= 0 && index < lastIndex) {
11744
- this.viewer.dataSources.remove(otherLayer, false);
11745
- this.viewer.dataSources.add(otherLayer);
11746
- }
11747
- }
11796
+ bringDataSourceToTop(this.viewer, "inverter");
11797
+ } else if (dataSource.name === "subarray") {
11798
+ ensureLayerAbove(this.viewer, "inverter", "subarray");
11799
+ } else if (dataSource.name === "other") {
11800
+ bringDataSourceToTop(this.viewer, "other");
11748
11801
  }
11749
11802
  return this.polygonEditor.startEditing(entity, dataSource, onComplete);
11750
11803
  }
@@ -13260,6 +13313,976 @@ var PathSafetyChecker = class {
13260
13313
  }
13261
13314
  };
13262
13315
 
13316
+ // src/core/polygon-manager/MassPolygonManager.ts
13317
+ var MassPolygonManager = class {
13318
+ constructor(CesiumNS, viewer) {
13319
+ __publicField(this, "CesiumNS");
13320
+ __publicField(this, "viewer");
13321
+ // 图层容器
13322
+ __publicField(this, "layerCollection");
13323
+ __publicField(this, "layerName");
13324
+ // Primitives
13325
+ __publicField(this, "primitive");
13326
+ __publicField(this, "outlinePrimitive");
13327
+ __publicField(this, "labelCollection");
13328
+ // 数据存储
13329
+ __publicField(this, "polygonDataMap", /* @__PURE__ */ new Map());
13330
+ __publicField(this, "currentStyle");
13331
+ __publicField(this, "currentOptions", {});
13332
+ __publicField(this, "isClampToGround", false);
13333
+ __publicField(this, "polygonHeight", 0);
13334
+ // 多边形统一高度
13335
+ // 交互配置(内部使用,回调可选)
13336
+ __publicField(this, "interactionOptions");
13337
+ // 事件处理器
13338
+ __publicField(this, "hoverHandler");
13339
+ __publicField(this, "clickHandler");
13340
+ // 悬停状态
13341
+ __publicField(this, "highlightedId");
13342
+ __publicField(this, "originalHighlightFillColor");
13343
+ __publicField(this, "originalHighlightOutlineColor");
13344
+ // 选中状态
13345
+ __publicField(this, "selectedId");
13346
+ __publicField(this, "originalSelectFillColor");
13347
+ __publicField(this, "originalSelectOutlineColor");
13348
+ // 节流相关
13349
+ __publicField(this, "lastPickTime", 0);
13350
+ __publicField(this, "pickThrottleMs", 50);
13351
+ // 悬停标签
13352
+ __publicField(this, "hoverLabel");
13353
+ // ========== 编辑支持方法 ==========
13354
+ // 隐藏的多边形原始颜色存储
13355
+ __publicField(this, "hiddenPolygonColors", /* @__PURE__ */ new Map());
13356
+ this.CesiumNS = CesiumNS;
13357
+ this.viewer = viewer;
13358
+ this.currentStyle = {
13359
+ fillColor: "rgba(0, 150, 255, 0.5)",
13360
+ outlineColor: "rgba(255, 255, 255, 0.8)",
13361
+ outlineWidth: 1
13362
+ };
13363
+ this.interactionOptions = {
13364
+ enableHover: false,
13365
+ enableClick: false,
13366
+ highlightStyle: {
13367
+ fillColor: "rgba(255, 255, 0, 0.7)",
13368
+ outlineColor: "rgba(255, 255, 0, 1)"
13369
+ },
13370
+ selectStyle: {
13371
+ fillColor: "rgba(0, 255, 128, 0.7)",
13372
+ outlineColor: "rgba(0, 255, 128, 1)"
13373
+ },
13374
+ showHoverLabel: true,
13375
+ hoverLabelStyle: {
13376
+ font: "14px sans-serif",
13377
+ fillColor: "#ffffff",
13378
+ outlineColor: "#000000",
13379
+ outlineWidth: 2,
13380
+ backgroundColor: "rgba(0,0,0,0.7)",
13381
+ backgroundPadding: [8, 4],
13382
+ pixelOffset: [0, -20]
13383
+ },
13384
+ onHover: void 0,
13385
+ onClick: void 0
13386
+ };
13387
+ }
13388
+ /**
13389
+ * 获取图层名称
13390
+ */
13391
+ getLayerName() {
13392
+ return this.layerName;
13393
+ }
13394
+ /**
13395
+ * 获取图层容器(PrimitiveCollection)
13396
+ * 用于图层顺序管理
13397
+ */
13398
+ getLayerCollection() {
13399
+ return this.layerCollection;
13400
+ }
13401
+ /**
13402
+ * 批量创建多边形
13403
+ */
13404
+ create(polygons, options) {
13405
+ const C = this.CesiumNS;
13406
+ this.clear();
13407
+ this.currentOptions = options ?? {};
13408
+ this.layerName = options?.layerName;
13409
+ if (options?.style) {
13410
+ this.currentStyle = { ...this.currentStyle, ...options.style };
13411
+ }
13412
+ if (options?.interaction) {
13413
+ const interaction = options.interaction;
13414
+ this.interactionOptions = {
13415
+ enableHover: interaction.enableHover ?? false,
13416
+ enableClick: interaction.enableClick ?? false,
13417
+ highlightStyle: {
13418
+ fillColor: interaction.highlightStyle?.fillColor ?? this.interactionOptions.highlightStyle.fillColor,
13419
+ outlineColor: interaction.highlightStyle?.outlineColor ?? this.interactionOptions.highlightStyle.outlineColor
13420
+ },
13421
+ selectStyle: {
13422
+ fillColor: interaction.selectStyle?.fillColor ?? this.interactionOptions.selectStyle.fillColor,
13423
+ outlineColor: interaction.selectStyle?.outlineColor ?? this.interactionOptions.selectStyle.outlineColor
13424
+ },
13425
+ showHoverLabel: interaction.showHoverLabel ?? true,
13426
+ hoverLabelStyle: {
13427
+ font: interaction.hoverLabelStyle?.font ?? this.interactionOptions.hoverLabelStyle.font,
13428
+ fillColor: interaction.hoverLabelStyle?.fillColor ?? this.interactionOptions.hoverLabelStyle.fillColor,
13429
+ outlineColor: interaction.hoverLabelStyle?.outlineColor ?? this.interactionOptions.hoverLabelStyle.outlineColor,
13430
+ outlineWidth: interaction.hoverLabelStyle?.outlineWidth ?? this.interactionOptions.hoverLabelStyle.outlineWidth,
13431
+ backgroundColor: interaction.hoverLabelStyle?.backgroundColor ?? this.interactionOptions.hoverLabelStyle.backgroundColor,
13432
+ backgroundPadding: interaction.hoverLabelStyle?.backgroundPadding ?? this.interactionOptions.hoverLabelStyle.backgroundPadding,
13433
+ pixelOffset: interaction.hoverLabelStyle?.pixelOffset ?? this.interactionOptions.hoverLabelStyle.pixelOffset
13434
+ },
13435
+ onHover: interaction.onHover,
13436
+ onClick: interaction.onClick
13437
+ };
13438
+ }
13439
+ this.isClampToGround = options?.clampToGround ?? false;
13440
+ const asynchronous = options?.asynchronous ?? true;
13441
+ this.polygonHeight = options?.height ?? 0;
13442
+ if (this.isClampToGround && this.viewer.scene.globe) {
13443
+ this.viewer.scene.globe.depthTestAgainstTerrain = true;
13444
+ }
13445
+ this.layerCollection = new C.PrimitiveCollection();
13446
+ this.viewer.scene.primitives.add(this.layerCollection);
13447
+ this.polygonDataMap.clear();
13448
+ for (const polygon of polygons) {
13449
+ this.polygonDataMap.set(polygon.id, polygon);
13450
+ }
13451
+ const fillInstances = [];
13452
+ const outlineInstances = [];
13453
+ const fillColor = C.Color.fromCssColorString(this.currentStyle.fillColor);
13454
+ const outlineColor = C.Color.fromCssColorString(this.currentStyle.outlineColor);
13455
+ for (const polygon of polygons) {
13456
+ if (polygon.points.length < 3) {
13457
+ console.warn(`[MassPolygonManager] \u591A\u8FB9\u5F62 ${polygon.id} \u9876\u70B9\u6570\u4E0D\u8DB3\uFF0C\u5DF2\u8DF3\u8FC7`);
13458
+ continue;
13459
+ }
13460
+ const positions = this.convertPointsToCartesian(polygon.points);
13461
+ const polygonGeometry = new C.PolygonGeometry({
13462
+ polygonHierarchy: new C.PolygonHierarchy(positions),
13463
+ perPositionHeight: false,
13464
+ height: this.polygonHeight
13465
+ // 使用配置的高度
13466
+ });
13467
+ fillInstances.push(new C.GeometryInstance({
13468
+ geometry: polygonGeometry,
13469
+ id: polygon.id,
13470
+ attributes: {
13471
+ color: C.ColorGeometryInstanceAttribute.fromColor(fillColor),
13472
+ show: new C.ShowGeometryInstanceAttribute(true)
13473
+ }
13474
+ }));
13475
+ const outlinePositionsWithHeight = polygon.points.map(
13476
+ (p) => C.Cartesian3.fromDegrees(p.lon, p.lat, this.polygonHeight)
13477
+ );
13478
+ outlinePositionsWithHeight.push(outlinePositionsWithHeight[0]);
13479
+ const outlineGeometry = new C.PolylineGeometry({
13480
+ positions: outlinePositionsWithHeight,
13481
+ width: this.currentStyle.outlineWidth
13482
+ });
13483
+ outlineInstances.push(new C.GeometryInstance({
13484
+ geometry: outlineGeometry,
13485
+ id: `${polygon.id}-outline`,
13486
+ attributes: {
13487
+ color: C.ColorGeometryInstanceAttribute.fromColor(outlineColor),
13488
+ show: new C.ShowGeometryInstanceAttribute(true)
13489
+ }
13490
+ }));
13491
+ }
13492
+ if (fillInstances.length > 0) {
13493
+ const appearance = new C.PerInstanceColorAppearance({ flat: true, translucent: true });
13494
+ this.primitive = new C.Primitive({ geometryInstances: fillInstances, appearance, asynchronous });
13495
+ this.layerCollection.add(this.primitive);
13496
+ }
13497
+ if (outlineInstances.length > 0) {
13498
+ const appearance = new C.PolylineColorAppearance();
13499
+ this.outlinePrimitive = new C.Primitive({ geometryInstances: outlineInstances, appearance, asynchronous });
13500
+ this.layerCollection.add(this.outlinePrimitive);
13501
+ }
13502
+ this.labelCollection = new C.LabelCollection();
13503
+ this.layerCollection.add(this.labelCollection);
13504
+ if (this.interactionOptions.enableHover) {
13505
+ this.setupHoverHandler();
13506
+ }
13507
+ if (this.interactionOptions.enableClick) {
13508
+ this.setupClickHandler();
13509
+ }
13510
+ this.viewer.scene.requestRender();
13511
+ return {
13512
+ primitive: this.primitive,
13513
+ count: fillInstances.length
13514
+ };
13515
+ }
13516
+ /**
13517
+ * 设置悬停事件处理器
13518
+ */
13519
+ setupHoverHandler() {
13520
+ if (this.hoverHandler) {
13521
+ this.hoverHandler.destroy();
13522
+ }
13523
+ const C = this.CesiumNS;
13524
+ this.hoverHandler = new C.ScreenSpaceEventHandler(this.viewer.scene.canvas);
13525
+ this.hoverHandler.setInputAction(
13526
+ (movement) => {
13527
+ const now = Date.now();
13528
+ if (now - this.lastPickTime < this.pickThrottleMs) return;
13529
+ this.lastPickTime = now;
13530
+ const pickedObject = this.viewer.scene.pick(movement.endPosition);
13531
+ if (pickedObject?.id && typeof pickedObject.id === "string") {
13532
+ const polygonId = pickedObject.id.endsWith("-outline") ? pickedObject.id.replace("-outline", "") : pickedObject.id;
13533
+ if (this.polygonDataMap.has(polygonId)) {
13534
+ if (this.highlightedId !== polygonId) {
13535
+ this.clearHighlight();
13536
+ this.highlightPolygon(polygonId);
13537
+ const data = this.polygonDataMap.get(polygonId);
13538
+ if (data) this.showLabel(data);
13539
+ this.interactionOptions.onHover?.(polygonId, data ?? null);
13540
+ }
13541
+ } else {
13542
+ this.handleMouseLeave();
13543
+ }
13544
+ } else {
13545
+ this.handleMouseLeave();
13546
+ }
13547
+ },
13548
+ C.ScreenSpaceEventType.MOUSE_MOVE
13549
+ );
13550
+ }
13551
+ /**
13552
+ * 设置点击事件处理器
13553
+ */
13554
+ setupClickHandler() {
13555
+ if (this.clickHandler) {
13556
+ this.clickHandler.destroy();
13557
+ }
13558
+ const C = this.CesiumNS;
13559
+ this.clickHandler = new C.ScreenSpaceEventHandler(this.viewer.scene.canvas);
13560
+ this.clickHandler.setInputAction(
13561
+ (movement) => {
13562
+ const pickedObject = this.viewer.scene.pick(movement.position);
13563
+ if (pickedObject?.id && typeof pickedObject.id === "string") {
13564
+ const polygonId = pickedObject.id.endsWith("-outline") ? pickedObject.id.replace("-outline", "") : pickedObject.id;
13565
+ if (this.polygonDataMap.has(polygonId)) {
13566
+ if (this.selectedId === polygonId) {
13567
+ this.deselect();
13568
+ this.interactionOptions.onClick?.(null, null);
13569
+ } else {
13570
+ this.select(polygonId);
13571
+ const data = this.polygonDataMap.get(polygonId);
13572
+ this.interactionOptions.onClick?.(polygonId, data ?? null);
13573
+ }
13574
+ } else {
13575
+ if (this.selectedId) {
13576
+ this.deselect();
13577
+ this.interactionOptions.onClick?.(null, null);
13578
+ }
13579
+ }
13580
+ } else {
13581
+ if (this.selectedId) {
13582
+ this.deselect();
13583
+ this.interactionOptions.onClick?.(null, null);
13584
+ }
13585
+ }
13586
+ },
13587
+ C.ScreenSpaceEventType.LEFT_CLICK
13588
+ );
13589
+ }
13590
+ /**
13591
+ * 处理鼠标离开
13592
+ */
13593
+ handleMouseLeave() {
13594
+ if (this.highlightedId) {
13595
+ this.clearHighlight();
13596
+ this.hideLabel();
13597
+ this.interactionOptions.onHover?.(null, null);
13598
+ }
13599
+ }
13600
+ /**
13601
+ * 高亮指定多边形(悬停)
13602
+ */
13603
+ highlightPolygon(id) {
13604
+ if (id === this.selectedId) return;
13605
+ const C = this.CesiumNS;
13606
+ if (!this.primitive) return;
13607
+ try {
13608
+ const fillAttributes = this.primitive.getGeometryInstanceAttributes?.(id);
13609
+ if (fillAttributes?.color) {
13610
+ this.originalHighlightFillColor = new Uint8Array(fillAttributes.color);
13611
+ const highlightColor = C.Color.fromCssColorString(this.interactionOptions.highlightStyle.fillColor);
13612
+ fillAttributes.color = C.ColorGeometryInstanceAttribute.toValue(highlightColor);
13613
+ }
13614
+ if (this.outlinePrimitive) {
13615
+ const outlineAttributes = this.outlinePrimitive.getGeometryInstanceAttributes?.(`${id}-outline`);
13616
+ if (outlineAttributes?.color) {
13617
+ this.originalHighlightOutlineColor = new Uint8Array(outlineAttributes.color);
13618
+ const highlightColor = C.Color.fromCssColorString(this.interactionOptions.highlightStyle.outlineColor);
13619
+ outlineAttributes.color = C.ColorGeometryInstanceAttribute.toValue(highlightColor);
13620
+ }
13621
+ }
13622
+ this.highlightedId = id;
13623
+ this.viewer.scene.requestRender();
13624
+ } catch (e) {
13625
+ }
13626
+ }
13627
+ /**
13628
+ * 清除悬停高亮
13629
+ */
13630
+ clearHighlight() {
13631
+ if (!this.highlightedId) return;
13632
+ try {
13633
+ if (this.primitive && this.originalHighlightFillColor) {
13634
+ const fillAttributes = this.primitive.getGeometryInstanceAttributes?.(this.highlightedId);
13635
+ if (fillAttributes) {
13636
+ fillAttributes.color = this.originalHighlightFillColor;
13637
+ }
13638
+ }
13639
+ if (this.outlinePrimitive && this.originalHighlightOutlineColor) {
13640
+ const outlineAttributes = this.outlinePrimitive.getGeometryInstanceAttributes?.(`${this.highlightedId}-outline`);
13641
+ if (outlineAttributes) {
13642
+ outlineAttributes.color = this.originalHighlightOutlineColor;
13643
+ }
13644
+ }
13645
+ this.highlightedId = void 0;
13646
+ this.originalHighlightFillColor = void 0;
13647
+ this.originalHighlightOutlineColor = void 0;
13648
+ this.viewer.scene.requestRender();
13649
+ } catch (e) {
13650
+ }
13651
+ }
13652
+ /**
13653
+ * 选中指定多边形
13654
+ * @param id 多边形 ID
13655
+ * @returns 是否选中成功
13656
+ */
13657
+ select(id) {
13658
+ if (!this.polygonDataMap.has(id)) return false;
13659
+ if (this.selectedId && this.selectedId !== id) {
13660
+ this.deselect();
13661
+ }
13662
+ if (this.highlightedId === id) {
13663
+ this.clearHighlight();
13664
+ }
13665
+ const C = this.CesiumNS;
13666
+ if (!this.primitive) return false;
13667
+ try {
13668
+ const fillAttributes = this.primitive.getGeometryInstanceAttributes?.(id);
13669
+ if (fillAttributes?.color) {
13670
+ this.originalSelectFillColor = new Uint8Array(fillAttributes.color);
13671
+ const selectColor = C.Color.fromCssColorString(this.interactionOptions.selectStyle.fillColor);
13672
+ fillAttributes.color = C.ColorGeometryInstanceAttribute.toValue(selectColor);
13673
+ }
13674
+ if (this.outlinePrimitive) {
13675
+ const outlineAttributes = this.outlinePrimitive.getGeometryInstanceAttributes?.(`${id}-outline`);
13676
+ if (outlineAttributes?.color) {
13677
+ this.originalSelectOutlineColor = new Uint8Array(outlineAttributes.color);
13678
+ const selectColor = C.Color.fromCssColorString(this.interactionOptions.selectStyle.outlineColor);
13679
+ outlineAttributes.color = C.ColorGeometryInstanceAttribute.toValue(selectColor);
13680
+ }
13681
+ }
13682
+ this.selectedId = id;
13683
+ this.viewer.scene.requestRender();
13684
+ return true;
13685
+ } catch (e) {
13686
+ return false;
13687
+ }
13688
+ }
13689
+ /**
13690
+ * 取消选中
13691
+ */
13692
+ deselect() {
13693
+ if (!this.selectedId) return;
13694
+ try {
13695
+ if (this.primitive && this.originalSelectFillColor) {
13696
+ const fillAttributes = this.primitive.getGeometryInstanceAttributes?.(this.selectedId);
13697
+ if (fillAttributes) {
13698
+ fillAttributes.color = this.originalSelectFillColor;
13699
+ }
13700
+ }
13701
+ if (this.outlinePrimitive && this.originalSelectOutlineColor) {
13702
+ const outlineAttributes = this.outlinePrimitive.getGeometryInstanceAttributes?.(`${this.selectedId}-outline`);
13703
+ if (outlineAttributes) {
13704
+ outlineAttributes.color = this.originalSelectOutlineColor;
13705
+ }
13706
+ }
13707
+ this.selectedId = void 0;
13708
+ this.originalSelectFillColor = void 0;
13709
+ this.originalSelectOutlineColor = void 0;
13710
+ this.viewer.scene.requestRender();
13711
+ } catch (e) {
13712
+ }
13713
+ }
13714
+ /**
13715
+ * 获取当前选中的多边形数据
13716
+ */
13717
+ getSelected() {
13718
+ if (!this.selectedId) return null;
13719
+ return this.polygonDataMap.get(this.selectedId) ?? null;
13720
+ }
13721
+ /**
13722
+ * 获取当前选中的多边形 ID
13723
+ */
13724
+ getSelectedId() {
13725
+ return this.selectedId ?? null;
13726
+ }
13727
+ /**
13728
+ * 计算多边形中心点
13729
+ */
13730
+ calculatePolygonCenter(points) {
13731
+ let sumLon = 0, sumLat = 0, sumHeight = 0;
13732
+ for (const p of points) {
13733
+ sumLon += p.lon;
13734
+ sumLat += p.lat;
13735
+ sumHeight += p.height ?? 0;
13736
+ }
13737
+ return {
13738
+ lon: sumLon / points.length,
13739
+ lat: sumLat / points.length,
13740
+ height: sumHeight / points.length
13741
+ };
13742
+ }
13743
+ /**
13744
+ * 显示悬停标签
13745
+ */
13746
+ showLabel(polygonData) {
13747
+ if (!this.interactionOptions.showHoverLabel || !polygonData.name) return;
13748
+ if (!this.labelCollection) return;
13749
+ const C = this.CesiumNS;
13750
+ const style = this.interactionOptions.hoverLabelStyle;
13751
+ this.hideLabel();
13752
+ const center = this.calculatePolygonCenter(polygonData.points);
13753
+ const position = C.Cartesian3.fromDegrees(center.lon, center.lat, this.polygonHeight);
13754
+ this.hoverLabel = this.labelCollection.add({
13755
+ position,
13756
+ text: polygonData.name,
13757
+ font: style.font,
13758
+ fillColor: C.Color.fromCssColorString(style.fillColor),
13759
+ outlineColor: C.Color.fromCssColorString(style.outlineColor),
13760
+ outlineWidth: style.outlineWidth,
13761
+ style: C.LabelStyle.FILL_AND_OUTLINE,
13762
+ showBackground: true,
13763
+ backgroundColor: C.Color.fromCssColorString(style.backgroundColor),
13764
+ backgroundPadding: new C.Cartesian2(style.backgroundPadding[0], style.backgroundPadding[1]),
13765
+ pixelOffset: new C.Cartesian2(style.pixelOffset[0], style.pixelOffset[1]),
13766
+ verticalOrigin: C.VerticalOrigin.BOTTOM,
13767
+ horizontalOrigin: C.HorizontalOrigin.CENTER,
13768
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
13769
+ });
13770
+ }
13771
+ /**
13772
+ * 隐藏悬停标签
13773
+ */
13774
+ hideLabel() {
13775
+ if (this.hoverLabel && this.labelCollection) {
13776
+ this.labelCollection.remove(this.hoverLabel);
13777
+ this.hoverLabel = void 0;
13778
+ this.viewer.scene.requestRender();
13779
+ }
13780
+ }
13781
+ /**
13782
+ * 根据 ID 获取多边形数据
13783
+ */
13784
+ getById(id) {
13785
+ return this.polygonDataMap.get(id);
13786
+ }
13787
+ /**
13788
+ * 获取所有多边形数据
13789
+ */
13790
+ getAll() {
13791
+ return Array.from(this.polygonDataMap.values());
13792
+ }
13793
+ /**
13794
+ * 获取多边形数量
13795
+ */
13796
+ getCount() {
13797
+ return this.polygonDataMap.size;
13798
+ }
13799
+ /**
13800
+ * 获取所有多边形的边界框
13801
+ */
13802
+ getBounds() {
13803
+ if (this.polygonDataMap.size === 0) return null;
13804
+ const allPoints = [];
13805
+ for (const polygon of this.polygonDataMap.values()) {
13806
+ for (const point of polygon.points) {
13807
+ allPoints.push({ lon: point.lon, lat: point.lat, alt: point.height });
13808
+ }
13809
+ }
13810
+ return calculateGeoBounds(allPoints);
13811
+ }
13812
+ /**
13813
+ * 飞行到所有多边形的范围
13814
+ */
13815
+ flyToBounds(options) {
13816
+ const bounds = this.getBounds();
13817
+ if (!bounds) {
13818
+ console.warn("[MassPolygonManager] \u6CA1\u6709\u591A\u8FB9\u5F62\u6570\u636E\uFF0C\u65E0\u6CD5\u98DE\u884C");
13819
+ return;
13820
+ }
13821
+ const C = this.CesiumNS;
13822
+ const camera = this.viewer.camera;
13823
+ const duration = options?.duration ?? 2;
13824
+ const padding = options?.padding ?? 0.2;
13825
+ const pitch = options?.pitch ?? C.Math.toRadians(-45);
13826
+ const heading = options?.heading ?? 0;
13827
+ const paddedWest = bounds.west - bounds.width * padding;
13828
+ const paddedEast = bounds.east + bounds.width * padding;
13829
+ const paddedSouth = bounds.south - bounds.height * padding;
13830
+ const paddedNorth = bounds.north + bounds.height * padding;
13831
+ const earthRadius = 6371e3;
13832
+ const rectWidth = (paddedEast - paddedWest) * (Math.PI / 180) * earthRadius * Math.cos(bounds.centerLat * Math.PI / 180);
13833
+ const rectHeight = (paddedNorth - paddedSouth) * (Math.PI / 180) * earthRadius;
13834
+ const frustum = camera.frustum;
13835
+ const fovy = frustum.fovy || frustum.fov || C.Math.toRadians(60);
13836
+ const canvas = this.viewer.scene.canvas;
13837
+ const aspectRatio = canvas.width / canvas.height;
13838
+ const fovx = 2 * Math.atan(Math.tan(fovy / 2) * aspectRatio);
13839
+ const absPitch = Math.abs(pitch);
13840
+ const sinPitch = Math.sin(absPitch) || 0.707;
13841
+ const altitudeForHeight = rectHeight / 2 / Math.tan(fovy / 2) / sinPitch;
13842
+ const altitudeForWidth = rectWidth / 2 / Math.tan(fovx / 2) / sinPitch;
13843
+ const altitude = Math.max(altitudeForHeight, altitudeForWidth, 500) * 1.1;
13844
+ const destination = C.Cartesian3.fromDegrees(bounds.centerLon, bounds.centerLat, altitude);
13845
+ const orientation = { heading, pitch, roll: 0 };
13846
+ if (duration > 0) {
13847
+ camera.flyTo({ destination, orientation, duration });
13848
+ } else {
13849
+ camera.setView({ destination, orientation });
13850
+ }
13851
+ console.log(`[MassPolygonManager] \u98DE\u884C\u5230\u8FB9\u754C: \u4E2D\u5FC3(${bounds.centerLon.toFixed(6)}, ${bounds.centerLat.toFixed(6)}), \u9AD8\u5EA6: ${altitude.toFixed(0)}m`);
13852
+ }
13853
+ /**
13854
+ * 设置可见性
13855
+ */
13856
+ setVisibility(visible) {
13857
+ if (this.layerCollection) {
13858
+ this.layerCollection.show = visible;
13859
+ }
13860
+ this.viewer.scene.requestRender();
13861
+ }
13862
+ /**
13863
+ * 更新样式(需要重新创建所有多边形)
13864
+ */
13865
+ updateStyle(style) {
13866
+ this.currentStyle = { ...this.currentStyle, ...style };
13867
+ const polygons = Array.from(this.polygonDataMap.values());
13868
+ if (polygons.length > 0) {
13869
+ this.create(polygons, { ...this.currentOptions, style: this.currentStyle });
13870
+ }
13871
+ }
13872
+ /**
13873
+ * 清除所有多边形
13874
+ */
13875
+ clear() {
13876
+ if (this.hoverHandler) {
13877
+ this.hoverHandler.destroy();
13878
+ this.hoverHandler = void 0;
13879
+ }
13880
+ if (this.clickHandler) {
13881
+ this.clickHandler.destroy();
13882
+ this.clickHandler = void 0;
13883
+ }
13884
+ this.highlightedId = void 0;
13885
+ this.selectedId = void 0;
13886
+ this.originalHighlightFillColor = void 0;
13887
+ this.originalHighlightOutlineColor = void 0;
13888
+ this.originalSelectFillColor = void 0;
13889
+ this.originalSelectOutlineColor = void 0;
13890
+ this.hoverLabel = void 0;
13891
+ if (this.layerCollection) {
13892
+ this.viewer.scene.primitives.remove(this.layerCollection);
13893
+ this.layerCollection = void 0;
13894
+ }
13895
+ this.primitive = void 0;
13896
+ this.outlinePrimitive = void 0;
13897
+ this.labelCollection = void 0;
13898
+ this.polygonDataMap.clear();
13899
+ this.viewer.scene.requestRender();
13900
+ }
13901
+ /**
13902
+ * 销毁并释放资源
13903
+ */
13904
+ destroy() {
13905
+ this.clear();
13906
+ }
13907
+ /**
13908
+ * 将 PolygonPoint 数组转换为 Cartesian3 数组
13909
+ */
13910
+ convertPointsToCartesian(points) {
13911
+ const C = this.CesiumNS;
13912
+ return points.map((p) => C.Cartesian3.fromDegrees(p.lon, p.lat, p.height ?? 0));
13913
+ }
13914
+ /**
13915
+ * 隐藏指定多边形(编辑时使用)
13916
+ * 通过设置 show 属性为 false 实现视觉隐藏,保留数据
13917
+ * @param id 多边形 ID
13918
+ * @returns 是否成功隐藏
13919
+ */
13920
+ hidePolygon(id) {
13921
+ if (!this.polygonDataMap.has(id)) {
13922
+ console.warn(`[MassPolygonManager] hidePolygon: \u591A\u8FB9\u5F62 ${id} \u4E0D\u5B58\u5728`);
13923
+ return false;
13924
+ }
13925
+ const C = this.CesiumNS;
13926
+ if (!this.primitive) return false;
13927
+ if (!this.primitive.ready) {
13928
+ console.warn(`[MassPolygonManager] hidePolygon: Primitive \u5C1A\u672A\u51C6\u5907\u597D\uFF0C\u65E0\u6CD5\u9690\u85CF\u591A\u8FB9\u5F62 ${id}`);
13929
+ return false;
13930
+ }
13931
+ try {
13932
+ const fillAttributes = this.primitive.getGeometryInstanceAttributes?.(id);
13933
+ if (!fillAttributes) {
13934
+ console.warn(`[MassPolygonManager] hidePolygon: \u65E0\u6CD5\u83B7\u53D6\u591A\u8FB9\u5F62 ${id} \u7684\u586B\u5145\u5C5E\u6027`);
13935
+ return false;
13936
+ }
13937
+ const originalFill = fillAttributes.color ? new Uint8Array(fillAttributes.color) : new Uint8Array([255, 255, 255, 255]);
13938
+ let originalOutline = new Uint8Array([255, 255, 255, 255]);
13939
+ if (this.outlinePrimitive && this.outlinePrimitive.ready) {
13940
+ const outlineAttributes = this.outlinePrimitive.getGeometryInstanceAttributes?.(`${id}-outline`);
13941
+ if (outlineAttributes?.color) {
13942
+ originalOutline = new Uint8Array(outlineAttributes.color);
13943
+ }
13944
+ if (outlineAttributes?.show !== void 0) {
13945
+ outlineAttributes.show = C.ShowGeometryInstanceAttribute.toValue(false);
13946
+ }
13947
+ }
13948
+ this.hiddenPolygonColors.set(id, {
13949
+ fill: originalFill,
13950
+ outline: originalOutline
13951
+ });
13952
+ if (fillAttributes.show !== void 0) {
13953
+ fillAttributes.show = C.ShowGeometryInstanceAttribute.toValue(false);
13954
+ this.viewer.scene.requestRender();
13955
+ console.log(`[MassPolygonManager] \u5DF2\u9690\u85CF\u591A\u8FB9\u5F62: ${id}`);
13956
+ return true;
13957
+ }
13958
+ console.warn(`[MassPolygonManager] hidePolygon: \u591A\u8FB9\u5F62 ${id} \u4E0D\u652F\u6301 show \u5C5E\u6027`);
13959
+ return false;
13960
+ } catch (e) {
13961
+ console.error(`[MassPolygonManager] hidePolygon \u5931\u8D25:`, e);
13962
+ return false;
13963
+ }
13964
+ }
13965
+ /**
13966
+ * 异步隐藏指定多边形(等待 Primitive 就绪后再隐藏)
13967
+ * @param id 多边形 ID
13968
+ * @param timeout 超时时间(毫秒),默认 5000ms
13969
+ * @returns Promise<boolean> 是否成功隐藏
13970
+ */
13971
+ async hidePolygonAsync(id, timeout = 5e3) {
13972
+ if (!this.polygonDataMap.has(id)) {
13973
+ console.warn(`[MassPolygonManager] hidePolygonAsync: \u591A\u8FB9\u5F62 ${id} \u4E0D\u5B58\u5728`);
13974
+ return false;
13975
+ }
13976
+ if (!this.primitive) return false;
13977
+ if (this.primitive.ready) {
13978
+ return this.hidePolygon(id);
13979
+ }
13980
+ console.log(`[MassPolygonManager] hidePolygonAsync: \u7B49\u5F85 Primitive \u51C6\u5907\u597D...`);
13981
+ const startTime = Date.now();
13982
+ return new Promise((resolve) => {
13983
+ const checkReady = () => {
13984
+ if (this.primitive?.ready) {
13985
+ console.log(`[MassPolygonManager] hidePolygonAsync: Primitive \u5DF2\u51C6\u5907\u597D`);
13986
+ resolve(this.hidePolygon(id));
13987
+ } else if (Date.now() - startTime > timeout) {
13988
+ console.error(`[MassPolygonManager] hidePolygonAsync: \u7B49\u5F85 Primitive \u8D85\u65F6`);
13989
+ resolve(false);
13990
+ } else {
13991
+ requestAnimationFrame(checkReady);
13992
+ }
13993
+ };
13994
+ checkReady();
13995
+ });
13996
+ }
13997
+ /**
13998
+ * 显示指定多边形(取消编辑或编辑失败时恢复)
13999
+ * 恢复 show 状态为 true
14000
+ * @param id 多边形 ID
14001
+ * @returns 是否成功显示
14002
+ */
14003
+ showPolygon(id) {
14004
+ const savedColors = this.hiddenPolygonColors.get(id);
14005
+ if (!savedColors) {
14006
+ console.warn(`[MassPolygonManager] showPolygon: \u591A\u8FB9\u5F62 ${id} \u672A\u88AB\u9690\u85CF\u6216\u72B6\u6001\u672A\u4FDD\u5B58`);
14007
+ return false;
14008
+ }
14009
+ const C = this.CesiumNS;
14010
+ if (!this.primitive) return false;
14011
+ try {
14012
+ const fillAttributes = this.primitive.getGeometryInstanceAttributes?.(id);
14013
+ if (!fillAttributes) {
14014
+ console.warn(`[MassPolygonManager] showPolygon: \u65E0\u6CD5\u83B7\u53D6\u591A\u8FB9\u5F62 ${id} \u7684\u5C5E\u6027`);
14015
+ return false;
14016
+ }
14017
+ if (fillAttributes.show !== void 0) {
14018
+ fillAttributes.show = C.ShowGeometryInstanceAttribute.toValue(true);
14019
+ }
14020
+ if (this.outlinePrimitive && this.outlinePrimitive.ready) {
14021
+ const outlineAttributes = this.outlinePrimitive.getGeometryInstanceAttributes?.(`${id}-outline`);
14022
+ if (outlineAttributes?.show !== void 0) {
14023
+ outlineAttributes.show = C.ShowGeometryInstanceAttribute.toValue(true);
14024
+ }
14025
+ }
14026
+ this.hiddenPolygonColors.delete(id);
14027
+ this.viewer.scene.requestRender();
14028
+ console.log(`[MassPolygonManager] \u5DF2\u663E\u793A\u591A\u8FB9\u5F62: ${id}`);
14029
+ return true;
14030
+ } catch (e) {
14031
+ console.error(`[MassPolygonManager] showPolygon \u5931\u8D25:`, e);
14032
+ return false;
14033
+ }
14034
+ }
14035
+ /**
14036
+ * 检查多边形是否被隐藏
14037
+ * @param id 多边形 ID
14038
+ * @returns 是否被隐藏
14039
+ */
14040
+ isPolygonHidden(id) {
14041
+ return this.hiddenPolygonColors.has(id);
14042
+ }
14043
+ /**
14044
+ * 更新单个多边形的坐标
14045
+ * 内部实现:更新 polygonDataMap,然后重建整个 Primitive
14046
+ * (Primitive 不支持单个 instance 的几何修改,只能重建)
14047
+ * @param id 多边形 ID
14048
+ * @param newPoints 新的坐标点数组
14049
+ * @returns 是否更新成功
14050
+ */
14051
+ updatePolygon(id, newPoints) {
14052
+ const existingData = this.polygonDataMap.get(id);
14053
+ if (!existingData) {
14054
+ console.warn(`[MassPolygonManager] updatePolygon: \u591A\u8FB9\u5F62 ${id} \u4E0D\u5B58\u5728`);
14055
+ return false;
14056
+ }
14057
+ if (newPoints.length < 3) {
14058
+ console.warn(`[MassPolygonManager] updatePolygon: \u65B0\u5750\u6807\u70B9\u6570\u91CF\u4E0D\u8DB3 (${newPoints.length})`);
14059
+ return false;
14060
+ }
14061
+ existingData.points = newPoints;
14062
+ this.polygonDataMap.set(id, existingData);
14063
+ this.hiddenPolygonColors.delete(id);
14064
+ this.rebuild();
14065
+ console.log(`[MassPolygonManager] \u5DF2\u66F4\u65B0\u591A\u8FB9\u5F62: ${id}, \u65B0\u5750\u6807\u70B9\u6570\u91CF: ${newPoints.length}`);
14066
+ return true;
14067
+ }
14068
+ /**
14069
+ * 更新多边形数据(坐标和/或名称)
14070
+ * @param id 多边形 ID
14071
+ * @param data 要更新的数据
14072
+ * @returns 是否更新成功
14073
+ */
14074
+ updatePolygonData(id, data) {
14075
+ const existingData = this.polygonDataMap.get(id);
14076
+ if (!existingData) {
14077
+ console.warn(`[MassPolygonManager] updatePolygonData: \u591A\u8FB9\u5F62 ${id} \u4E0D\u5B58\u5728`);
14078
+ return false;
14079
+ }
14080
+ if (data.points !== void 0) {
14081
+ if (data.points.length < 3) {
14082
+ console.warn(`[MassPolygonManager] updatePolygonData: \u65B0\u5750\u6807\u70B9\u6570\u91CF\u4E0D\u8DB3`);
14083
+ return false;
14084
+ }
14085
+ existingData.points = data.points;
14086
+ }
14087
+ if (data.name !== void 0) {
14088
+ existingData.name = data.name;
14089
+ }
14090
+ this.polygonDataMap.set(id, existingData);
14091
+ if (data.points !== void 0) {
14092
+ this.hiddenPolygonColors.delete(id);
14093
+ this.rebuild();
14094
+ }
14095
+ return true;
14096
+ }
14097
+ /**
14098
+ * 重建所有 Primitive(保留当前数据和配置)
14099
+ * 用于坐标更新后刷新渲染
14100
+ */
14101
+ rebuild() {
14102
+ const polygons = Array.from(this.polygonDataMap.values());
14103
+ if (polygons.length === 0) {
14104
+ this.clear();
14105
+ return;
14106
+ }
14107
+ const wasSelectedId = this.selectedId;
14108
+ this.create(polygons, this.currentOptions);
14109
+ if (wasSelectedId && this.polygonDataMap.has(wasSelectedId)) {
14110
+ this.select(wasSelectedId);
14111
+ }
14112
+ console.log(`[MassPolygonManager] \u5DF2\u91CD\u5EFA ${polygons.length} \u4E2A\u591A\u8FB9\u5F62`);
14113
+ }
14114
+ /**
14115
+ * 删除指定多边形
14116
+ * @param id 多边形 ID
14117
+ * @returns 是否删除成功
14118
+ */
14119
+ removePolygon(id) {
14120
+ if (!this.polygonDataMap.has(id)) {
14121
+ console.warn(`[MassPolygonManager] removePolygon: \u591A\u8FB9\u5F62 ${id} \u4E0D\u5B58\u5728`);
14122
+ return false;
14123
+ }
14124
+ if (this.selectedId === id) {
14125
+ this.deselect();
14126
+ }
14127
+ this.hiddenPolygonColors.delete(id);
14128
+ this.polygonDataMap.delete(id);
14129
+ this.rebuild();
14130
+ console.log(`[MassPolygonManager] \u5DF2\u5220\u9664\u591A\u8FB9\u5F62: ${id}`);
14131
+ return true;
14132
+ }
14133
+ /**
14134
+ * 添加新多边形
14135
+ * @param polygon 多边形数据
14136
+ * @returns 是否添加成功
14137
+ */
14138
+ addPolygon(polygon) {
14139
+ if (this.polygonDataMap.has(polygon.id)) {
14140
+ console.warn(`[MassPolygonManager] addPolygon: \u591A\u8FB9\u5F62 ${polygon.id} \u5DF2\u5B58\u5728`);
14141
+ return false;
14142
+ }
14143
+ if (polygon.points.length < 3) {
14144
+ console.warn(`[MassPolygonManager] addPolygon: \u5750\u6807\u70B9\u6570\u91CF\u4E0D\u8DB3`);
14145
+ return false;
14146
+ }
14147
+ this.polygonDataMap.set(polygon.id, polygon);
14148
+ this.rebuild();
14149
+ console.log(`[MassPolygonManager] \u5DF2\u6DFB\u52A0\u591A\u8FB9\u5F62: ${polygon.id}`);
14150
+ return true;
14151
+ }
14152
+ };
14153
+
14154
+ // src/utils/LODManager.ts
14155
+ var LODManager = class {
14156
+ constructor(CesiumNS, viewer, config) {
14157
+ __publicField(this, "viewer");
14158
+ __publicField(this, "config");
14159
+ __publicField(this, "targets", /* @__PURE__ */ new Set());
14160
+ __publicField(this, "removeListener");
14161
+ __publicField(this, "lastCheckTime", 0);
14162
+ __publicField(this, "isRunning", false);
14163
+ __publicField(this, "currentVisibility", true);
14164
+ __publicField(this, "onPreRender", () => {
14165
+ if (this.isRunning) {
14166
+ this.checkVisibility();
14167
+ }
14168
+ });
14169
+ this.viewer = viewer;
14170
+ this.config = {
14171
+ minHeight: config?.minHeight ?? 0,
14172
+ maxHeight: config?.maxHeight ?? Infinity,
14173
+ checkInterval: config?.checkInterval ?? 200
14174
+ };
14175
+ }
14176
+ /**
14177
+ * 添加 LOD 控制目标
14178
+ * @param target 具有 show 属性的对象
14179
+ */
14180
+ addTarget(target) {
14181
+ this.targets.add(target);
14182
+ target.show = this.currentVisibility;
14183
+ }
14184
+ /**
14185
+ * 移除 LOD 控制目标
14186
+ * @param target 要移除的目标
14187
+ */
14188
+ removeTarget(target) {
14189
+ this.targets.delete(target);
14190
+ }
14191
+ /**
14192
+ * 清除所有目标
14193
+ */
14194
+ clearTargets() {
14195
+ this.targets.clear();
14196
+ }
14197
+ /**
14198
+ * 获取当前相机高度
14199
+ */
14200
+ getCameraHeight() {
14201
+ const cartographic = this.viewer.camera.positionCartographic;
14202
+ return cartographic?.height ?? 0;
14203
+ }
14204
+ /**
14205
+ * 检查并更新可见性
14206
+ */
14207
+ checkVisibility() {
14208
+ const now = Date.now();
14209
+ if (now - this.lastCheckTime < this.config.checkInterval) {
14210
+ return;
14211
+ }
14212
+ this.lastCheckTime = now;
14213
+ const height = this.getCameraHeight();
14214
+ const shouldShow = height >= this.config.minHeight && height <= this.config.maxHeight;
14215
+ if (shouldShow !== this.currentVisibility) {
14216
+ this.currentVisibility = shouldShow;
14217
+ this.updateTargetsVisibility(shouldShow);
14218
+ }
14219
+ }
14220
+ /**
14221
+ * 更新所有目标的可见性
14222
+ */
14223
+ updateTargetsVisibility(visible) {
14224
+ for (const target of this.targets) {
14225
+ target.show = visible;
14226
+ }
14227
+ this.viewer.scene.requestRender();
14228
+ }
14229
+ /**
14230
+ * 启动 LOD 管理
14231
+ */
14232
+ start() {
14233
+ if (this.isRunning) return;
14234
+ this.isRunning = true;
14235
+ this.lastCheckTime = 0;
14236
+ this.checkVisibility();
14237
+ this.removeListener = this.viewer.camera.changed.addEventListener(() => {
14238
+ this.checkVisibility();
14239
+ });
14240
+ this.viewer.scene.preRender.addEventListener(this.onPreRender);
14241
+ }
14242
+ /**
14243
+ * 停止 LOD 管理
14244
+ */
14245
+ stop() {
14246
+ if (!this.isRunning) return;
14247
+ this.isRunning = false;
14248
+ if (this.removeListener) {
14249
+ this.removeListener();
14250
+ this.removeListener = void 0;
14251
+ }
14252
+ this.viewer.scene.preRender.removeEventListener(this.onPreRender);
14253
+ }
14254
+ /**
14255
+ * 更新配置
14256
+ */
14257
+ updateConfig(config) {
14258
+ if (config.minHeight !== void 0) this.config.minHeight = config.minHeight;
14259
+ if (config.maxHeight !== void 0) this.config.maxHeight = config.maxHeight;
14260
+ if (config.checkInterval !== void 0) this.config.checkInterval = config.checkInterval;
14261
+ this.lastCheckTime = 0;
14262
+ this.checkVisibility();
14263
+ }
14264
+ /**
14265
+ * 强制设置可见性(忽略 LOD 规则)
14266
+ */
14267
+ forceVisibility(visible) {
14268
+ this.currentVisibility = visible;
14269
+ this.updateTargetsVisibility(visible);
14270
+ }
14271
+ /**
14272
+ * 获取当前可见性状态
14273
+ */
14274
+ isVisible() {
14275
+ return this.currentVisibility;
14276
+ }
14277
+ /**
14278
+ * 销毁管理器
14279
+ */
14280
+ destroy() {
14281
+ this.stop();
14282
+ this.clearTargets();
14283
+ }
14284
+ };
14285
+
13263
14286
  // src/index.ts
13264
14287
  var placeholder = { ready: true };
13265
14288
  var droneModelUrl = wurenji_default;
@@ -13272,7 +14295,9 @@ exports.CameraManager = CameraManager;
13272
14295
  exports.Emitter = Emitter;
13273
14296
  exports.FlightSimulator = FlightSimulator;
13274
14297
  exports.FrustumPyramid = FrustumPyramid;
14298
+ exports.LODManager = LODManager;
13275
14299
  exports.LayerManager = LayerManager;
14300
+ exports.MassPolygonManager = MassPolygonManager;
13276
14301
  exports.PathSafetyChecker = PathSafetyChecker;
13277
14302
  exports.PointCloudPicker = PointCloudPicker;
13278
14303
  exports.PolygonEditor = PolygonEditor;
@@ -13281,6 +14306,8 @@ exports.SceneManager = SceneManager;
13281
14306
  exports.Selector = Selector;
13282
14307
  exports.StateManager = StateManager;
13283
14308
  exports.assertCesiumAssetsConfigured = assertCesiumAssetsConfigured;
14309
+ exports.bringDataSourceToTop = bringDataSourceToTop;
14310
+ exports.bringPrimitiveCollectionToTop = bringPrimitiveCollectionToTop;
13284
14311
  exports.calculateAbsoluteHeight = calculateAbsoluteHeight;
13285
14312
  exports.calculateBoundsDiagonal = calculateBoundsDiagonal;
13286
14313
  exports.calculateDistance = calculateDistance;
@@ -13296,9 +14323,12 @@ exports.convertSinoflyWayline = convertSinoflyWayline;
13296
14323
  exports.convertSinoflyWaylines = convertSinoflyWaylines;
13297
14324
  exports.droneModelUrl = droneModelUrl;
13298
14325
  exports.ensureCesiumIonToken = ensureCesiumIonToken;
14326
+ exports.ensureLayerAbove = ensureLayerAbove;
13299
14327
  exports.expandBounds = expandBounds;
13300
14328
  exports.getCesiumBaseUrl = getCesiumBaseUrl;
13301
14329
  exports.getCesiumIonToken = getCesiumIonToken;
14330
+ exports.getDataSourceIndex = getDataSourceIndex;
14331
+ exports.getDataSourceOrder = getDataSourceOrder;
13302
14332
  exports.globalCameraEventBus = globalCameraEventBus;
13303
14333
  exports.globalState = globalState;
13304
14334
  exports.isPointInBounds = isPointInBounds;