@jorgmoritz/gis-manager 0.1.33 → 0.1.35

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.d.cts CHANGED
@@ -2114,8 +2114,14 @@ interface PathSafetyCheckOptions {
2114
2114
  pointCloudSafetyDistance?: number;
2115
2115
  /** 航点间最小距离(米),相邻航点之间的最小距离,默认 0(不检测) */
2116
2116
  minWaypointDistance?: number;
2117
- /** 采样间隔(米),每隔多少米采样一次,默认 5 */
2117
+ /** 采样间隔(米),每隔多少米采样一次,默认 10 */
2118
2118
  sampleInterval?: number;
2119
+ /**
2120
+ * 快速模式:减少射线检测数量以提升速度,默认 true
2121
+ * - true: 8方向检测(速度快)
2122
+ * - false: 16方向检测(精度高)
2123
+ */
2124
+ fastMode?: boolean;
2119
2125
  }
2120
2126
  /**
2121
2127
  * 航线安全检测器
@@ -2125,6 +2131,11 @@ declare class PathSafetyChecker {
2125
2131
  private CesiumNS;
2126
2132
  private viewer;
2127
2133
  constructor(CesiumNS: typeof Cesium, viewer: Cesium.Viewer);
2134
+ /**
2135
+ * 检测场景中是否有3D点云数据(Cesium3DTileset)
2136
+ * @returns 是否存在点云数据
2137
+ */
2138
+ hasPointCloudData(): boolean;
2128
2139
  /**
2129
2140
  * 检测整条路径的安全性
2130
2141
  * @param positions 航点位置数组
package/dist/index.d.ts CHANGED
@@ -2114,8 +2114,14 @@ interface PathSafetyCheckOptions {
2114
2114
  pointCloudSafetyDistance?: number;
2115
2115
  /** 航点间最小距离(米),相邻航点之间的最小距离,默认 0(不检测) */
2116
2116
  minWaypointDistance?: number;
2117
- /** 采样间隔(米),每隔多少米采样一次,默认 5 */
2117
+ /** 采样间隔(米),每隔多少米采样一次,默认 10 */
2118
2118
  sampleInterval?: number;
2119
+ /**
2120
+ * 快速模式:减少射线检测数量以提升速度,默认 true
2121
+ * - true: 8方向检测(速度快)
2122
+ * - false: 16方向检测(精度高)
2123
+ */
2124
+ fastMode?: boolean;
2119
2125
  }
2120
2126
  /**
2121
2127
  * 航线安全检测器
@@ -2125,6 +2131,11 @@ declare class PathSafetyChecker {
2125
2131
  private CesiumNS;
2126
2132
  private viewer;
2127
2133
  constructor(CesiumNS: typeof Cesium, viewer: Cesium.Viewer);
2134
+ /**
2135
+ * 检测场景中是否有3D点云数据(Cesium3DTileset)
2136
+ * @returns 是否存在点云数据
2137
+ */
2138
+ hasPointCloudData(): boolean;
2128
2139
  /**
2129
2140
  * 检测整条路径的安全性
2130
2141
  * @param positions 航点位置数组
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
11
11
  // package.json
12
12
  var package_default = {
13
13
  name: "@jorgmoritz/gis-manager",
14
- version: "0.1.33"};
14
+ version: "0.1.35"};
15
15
 
16
16
  // src/utils/version.ts
17
17
  var version = package_default.version;
@@ -2814,6 +2814,8 @@ var AirplaneCursor = class {
2814
2814
  __publicField(this, "angleStep");
2815
2815
  /** 加速倍率(按住 Shift 生效) */
2816
2816
  __publicField(this, "fastFactor");
2817
+ /** 最小高度(米) */
2818
+ __publicField(this, "minHeight");
2817
2819
  /** 外部传入的行为配置与回调 */
2818
2820
  __publicField(this, "opts");
2819
2821
  // 使用内联的 _FrustumPyramid
@@ -2841,6 +2843,7 @@ var AirplaneCursor = class {
2841
2843
  this.step = opts.stepMeters ?? 2;
2842
2844
  this.angleStep = opts.angleStepDeg ?? 1;
2843
2845
  this.fastFactor = opts.fastFactor ?? 5;
2846
+ this.minHeight = opts.minHeight ?? 0;
2844
2847
  this.currentFOV = opts.fovDeg ?? 50;
2845
2848
  this.ensureEntity(opts.color ?? C.Color.CYAN.withAlpha(0.9));
2846
2849
  this.attachKeyboard(opts);
@@ -3064,8 +3067,12 @@ var AirplaneCursor = class {
3064
3067
  moved = true;
3065
3068
  }
3066
3069
  if (this.keysPressed.has("z")) {
3067
- setPos(addVec(pose.position, C.Cartesian3.multiplyByScalar(u3, -step, new C.Cartesian3())));
3068
- moved = true;
3070
+ const newPos = addVec(pose.position, C.Cartesian3.multiplyByScalar(u3, -step, new C.Cartesian3()));
3071
+ const newCarto = C.Cartographic.fromCartesian(newPos);
3072
+ if (newCarto && newCarto.height >= this.minHeight) {
3073
+ setPos(newPos);
3074
+ moved = true;
3075
+ }
3069
3076
  }
3070
3077
  if (this.keysPressed.has("q")) {
3071
3078
  pose.heading = clampDeg(pose.heading - ang);
@@ -3938,6 +3945,7 @@ var VertexDragHandler = class {
3938
3945
  __publicField(this, "CesiumNS");
3939
3946
  __publicField(this, "viewer");
3940
3947
  __publicField(this, "hiddenClimbIndex");
3948
+ __publicField(this, "minHeight");
3941
3949
  __publicField(this, "callbacks");
3942
3950
  __publicField(this, "dragState", null);
3943
3951
  __publicField(this, "canvas");
@@ -3946,6 +3954,7 @@ var VertexDragHandler = class {
3946
3954
  this.CesiumNS = options.CesiumNS;
3947
3955
  this.viewer = options.viewer;
3948
3956
  this.hiddenClimbIndex = options.hiddenClimbIndex;
3957
+ this.minHeight = options.minHeight ?? 0;
3949
3958
  this.callbacks = callbacks;
3950
3959
  this.canvas = this.viewer.scene.canvas;
3951
3960
  this.setupKeyboardListeners();
@@ -4121,7 +4130,7 @@ var VertexDragHandler = class {
4121
4130
  const cameraHeight = this.viewer.camera.positionCartographic.height;
4122
4131
  const scaleFactor = Math.max(cameraHeight / 1e3, 0.5);
4123
4132
  const heightDelta = -deltaY * scaleFactor;
4124
- const newHeight = Math.max(0, this.dragState.startHeight + heightDelta);
4133
+ const newHeight = Math.max(this.minHeight, this.dragState.startHeight + heightDelta);
4125
4134
  const newPosition = C.Cartesian3.fromDegrees(
4126
4135
  this.dragState.startLonLat.lon,
4127
4136
  this.dragState.startLonLat.lat,
@@ -4228,7 +4237,8 @@ var PathEditingEventHandler = class {
4228
4237
  {
4229
4238
  CesiumNS: this.CesiumNS,
4230
4239
  viewer: this.viewer,
4231
- hiddenClimbIndex: this.hiddenClimbIndex
4240
+ hiddenClimbIndex: this.hiddenClimbIndex,
4241
+ minHeight: options.minHeight
4232
4242
  },
4233
4243
  {
4234
4244
  onDragStart: (index) => {
@@ -5279,7 +5289,9 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5279
5289
  }
5280
5290
  },
5281
5291
  // frustumLengthFactor: options?.preview?.lengthFactor ?? 0.3,
5282
- fovDeg: options?.preview?.fov ?? 50
5292
+ fovDeg: options?.preview?.fov ?? 50,
5293
+ minHeight: options?.minHeight
5294
+ // 传递最小高度限制
5283
5295
  });
5284
5296
  if (options?.preview?.enabled !== false && airplaneCursor) {
5285
5297
  preview = new PathPreview(CesiumNS, viewer, {
@@ -5323,7 +5335,8 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5323
5335
  {
5324
5336
  CesiumNS,
5325
5337
  viewer,
5326
- hiddenClimbIndex
5338
+ hiddenClimbIndex,
5339
+ minHeight: options?.minHeight
5327
5340
  },
5328
5341
  {
5329
5342
  onVertexSelect: (index) => setActiveIndex(index),
@@ -10926,6 +10939,21 @@ var PathSafetyChecker = class {
10926
10939
  this.CesiumNS = CesiumNS;
10927
10940
  this.viewer = viewer;
10928
10941
  }
10942
+ /**
10943
+ * 检测场景中是否有3D点云数据(Cesium3DTileset)
10944
+ * @returns 是否存在点云数据
10945
+ */
10946
+ hasPointCloudData() {
10947
+ const primitives = this.viewer.scene.primitives;
10948
+ for (let i = 0; i < primitives.length; i++) {
10949
+ const primitive = primitives.get(i);
10950
+ if (primitive && (primitive.constructor?.name === "Cesium3DTileset" || primitive._url !== void 0 || // 我们自己加载的带 _url 标记
10951
+ primitive.tileset !== void 0)) {
10952
+ return true;
10953
+ }
10954
+ }
10955
+ return false;
10956
+ }
10929
10957
  /**
10930
10958
  * 检测整条路径的安全性
10931
10959
  * @param positions 航点位置数组
@@ -10936,17 +10964,21 @@ var PathSafetyChecker = class {
10936
10964
  const terrainSafetyDistance = options?.terrainSafetyDistance ?? defaultDistance;
10937
10965
  const pointCloudSafetyDistance = options?.pointCloudSafetyDistance ?? defaultDistance;
10938
10966
  const minWaypointDistance = options?.minWaypointDistance ?? 0;
10939
- const sampleInterval = options?.sampleInterval ?? 5;
10967
+ const sampleInterval = options?.sampleInterval ?? 10;
10968
+ const fastMode = options?.fastMode ?? true;
10940
10969
  const results = [];
10941
10970
  const startSegment = 1 ;
10971
+ const hasPointCloud = this.hasPointCloudData();
10972
+ const effectivePointCloudSafetyDistance = hasPointCloud ? pointCloudSafetyDistance : 0;
10942
10973
  console.log("=".repeat(60));
10943
10974
  console.log("[PathSafetyChecker] \u5F00\u59CB\u5B89\u5168\u68C0\u6D4B");
10944
10975
  console.log(` \u5730\u5F62\u5B89\u5168\u8DDD\u79BB: ${terrainSafetyDistance}m`);
10945
- console.log(` \u70B9\u4E91\u5B89\u5168\u8DDD\u79BB: ${pointCloudSafetyDistance}m`);
10976
+ console.log(` \u70B9\u4E91\u5B89\u5168\u8DDD\u79BB: ${pointCloudSafetyDistance}m${!hasPointCloud ? " (\u573A\u666F\u65E0\u70B9\u4E91\u6570\u636E\uFF0C\u8DF3\u8FC7\u68C0\u6D4B)" : ""}`);
10946
10977
  if (minWaypointDistance > 0) {
10947
10978
  console.log(` \u822A\u70B9\u95F4\u6700\u5C0F\u8DDD\u79BB: ${minWaypointDistance}m`);
10948
10979
  }
10949
10980
  console.log(` \u91C7\u6837\u95F4\u9694: ${sampleInterval}m`);
10981
+ console.log(` \u68C0\u6D4B\u6A21\u5F0F: ${fastMode ? "\u5FEB\u901F(8\u65B9\u5411)" : "\u7CBE\u786E(16\u65B9\u5411)"}`);
10950
10982
  console.log(` \u822A\u70B9\u603B\u6570: ${positions.length}`);
10951
10983
  console.log(` \u68C0\u6D4B\u822A\u6BB5: ${startSegment} ~ ${positions.length - 2}`);
10952
10984
  console.log("=".repeat(60));
@@ -10962,9 +10994,11 @@ var PathSafetyChecker = class {
10962
10994
  i,
10963
10995
  i + 1,
10964
10996
  terrainSafetyDistance,
10965
- pointCloudSafetyDistance,
10997
+ effectivePointCloudSafetyDistance,
10998
+ // 使用有效的点云安全距离(无点云时为0,跳过检测)
10966
10999
  minWaypointDistance,
10967
- sampleInterval
11000
+ sampleInterval,
11001
+ fastMode
10968
11002
  );
10969
11003
  results.push(segmentResult);
10970
11004
  const terrainStatus = segmentResult.minTerrainDistance < 0 ? "\u2753" : segmentResult.isTerrainSafe ? "\u2705" : "\u26A0\uFE0F";
@@ -11018,7 +11052,7 @@ var PathSafetyChecker = class {
11018
11052
  * 检测单个航段的安全性
11019
11053
  * 支持多方向检测(上下左右前后6方向)和按间隔采样
11020
11054
  */
11021
- checkSegment(from, to, fromIndex, toIndex, terrainSafetyDistance, pointCloudSafetyDistance, minWaypointDistance, sampleInterval) {
11055
+ checkSegment(from, to, fromIndex, toIndex, terrainSafetyDistance, pointCloudSafetyDistance, minWaypointDistance, sampleInterval, fastMode = true) {
11022
11056
  const C = this.CesiumNS;
11023
11057
  const scene = this.viewer.scene;
11024
11058
  const dangerPoints = [];
@@ -11066,7 +11100,7 @@ var PathSafetyChecker = class {
11066
11100
  }
11067
11101
  const up2 = C.Cartesian3.cross(right, forward, new C.Cartesian3());
11068
11102
  C.Cartesian3.normalize(up2, up2);
11069
- const numDirections = 16;
11103
+ const numDirections = fastMode ? 8 : 16;
11070
11104
  for (let d = 0; d < numDirections; d++) {
11071
11105
  const angle = d / numDirections * Math.PI * 2;
11072
11106
  const outwardDir = new C.Cartesian3();
@@ -11080,40 +11114,37 @@ var PathSafetyChecker = class {
11080
11114
  C.Cartesian3.add(samplePoint, surfacePoint, surfacePoint);
11081
11115
  const inwardDir = C.Cartesian3.negate(outwardDir, new C.Cartesian3());
11082
11116
  const ray = new C.Ray(surfacePoint, inwardDir);
11083
- const intersections = scene.drillPickFromRay(ray, 10);
11084
- for (const intersection of intersections || []) {
11085
- if (!intersection?.position) continue;
11086
- const primitive = intersection.object?.primitive;
11087
- const primitiveName = primitive?.constructor?.name || "";
11088
- if (primitiveName === "Polyline" || primitiveName === "PointPrimitive" || primitiveName === "PointPrimitiveCollection" || primitiveName === "Billboard" || primitiveName === "Label" || primitiveName === "Cylinder" || primitiveName === "Ellipse" || primitiveName === "Model" || primitiveName === "ModelExperimental" || primitiveName === "Globe" || primitiveName === "GlobeSurfaceTile") {
11089
- continue;
11090
- }
11091
- if (primitiveName === "Primitive" && primitive?.appearance) {
11092
- const appearanceName = primitive.appearance?.constructor?.name || "";
11093
- if (appearanceName === "PerInstanceColorAppearance" || appearanceName === "MaterialAppearance" || appearanceName === "EllipsoidSurfaceAppearance") {
11094
- continue;
11095
- }
11096
- }
11097
- const is3DTiles = primitive?.tileset !== void 0 || primitive?._tileset !== void 0 || intersection.object?.content?.tileset !== void 0;
11098
- if (!is3DTiles && primitiveName !== "Cesium3DTilePointFeature") {
11117
+ const intersection = scene.pickFromRay(ray);
11118
+ if (!intersection?.position) continue;
11119
+ const primitive = intersection.object?.primitive;
11120
+ const primitiveName = primitive?.constructor?.name || "";
11121
+ if (primitiveName === "Polyline" || primitiveName === "PointPrimitive" || primitiveName === "PointPrimitiveCollection" || primitiveName === "Billboard" || primitiveName === "Label" || primitiveName === "Cylinder" || primitiveName === "Ellipse" || primitiveName === "Model" || primitiveName === "ModelExperimental" || primitiveName === "Globe" || primitiveName === "GlobeSurfaceTile") {
11122
+ continue;
11123
+ }
11124
+ if (primitiveName === "Primitive" && primitive?.appearance) {
11125
+ const appearanceName = primitive.appearance?.constructor?.name || "";
11126
+ if (appearanceName === "PerInstanceColorAppearance" || appearanceName === "MaterialAppearance" || appearanceName === "EllipsoidSurfaceAppearance") {
11099
11127
  continue;
11100
11128
  }
11101
- if (i === 0 && d === 0) {
11102
- console.log("[\u8C03\u8BD5] \u68C0\u6D4B\u5230\u70B9\u4E91\u5BF9\u8C61:", primitiveName);
11103
- console.log("[\u8C03\u8BD5] primitive:", primitive);
11104
- }
11105
- const distFromCenter = C.Cartesian3.distance(samplePoint, intersection.position);
11106
- minPointCloudDistance = Math.min(minPointCloudDistance, distFromCenter);
11107
- if (distFromCenter < pointCloudSafetyDistance) {
11108
- const alreadyAdded = dangerPoints.some(
11109
- (p) => C.Cartesian3.distance(p, samplePoint) < 0.1
11110
- );
11111
- if (!alreadyAdded) {
11112
- dangerPoints.push(C.Cartesian3.clone(samplePoint));
11113
- console.log(`[\u5371\u9669] \u91C7\u6837\u70B9 ${i}, \u65B9\u5411 ${d}: \u70B9\u4E91(${primitiveName})\u5728\u5706\u67F1\u4F53\u5185\uFF0C\u8DDD\u4E2D\u5FC3 ${distFromCenter.toFixed(1)}m`);
11114
- }
11129
+ }
11130
+ const is3DTiles = primitive?.tileset !== void 0 || primitive?._tileset !== void 0 || intersection.object?.content?.tileset !== void 0;
11131
+ if (!is3DTiles && primitiveName !== "Cesium3DTilePointFeature") {
11132
+ continue;
11133
+ }
11134
+ if (i === 0 && d === 0) {
11135
+ console.log("[\u8C03\u8BD5] \u68C0\u6D4B\u5230\u70B9\u4E91\u5BF9\u8C61:", primitiveName);
11136
+ console.log("[\u8C03\u8BD5] primitive:", primitive);
11137
+ }
11138
+ const distFromCenter = C.Cartesian3.distance(samplePoint, intersection.position);
11139
+ minPointCloudDistance = Math.min(minPointCloudDistance, distFromCenter);
11140
+ if (distFromCenter < pointCloudSafetyDistance) {
11141
+ const alreadyAdded = dangerPoints.some(
11142
+ (p) => C.Cartesian3.distance(p, samplePoint) < 0.1
11143
+ );
11144
+ if (!alreadyAdded) {
11145
+ dangerPoints.push(C.Cartesian3.clone(samplePoint));
11146
+ console.log(`[\u5371\u9669] \u91C7\u6837\u70B9 ${i}, \u65B9\u5411 ${d}: \u70B9\u4E91(${primitiveName})\u5728\u5706\u67F1\u4F53\u5185\uFF0C\u8DDD\u4E2D\u5FC3 ${distFromCenter.toFixed(1)}m`);
11115
11147
  }
11116
- break;
11117
11148
  }
11118
11149
  }
11119
11150
  } catch (e) {