@jorgmoritz/gis-manager 0.1.38 → 0.1.40

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.
@@ -1509,6 +1509,11 @@ var HeightMarker = class {
1509
1509
  }
1510
1510
  };
1511
1511
 
1512
+ // src/core/path-manager/constants.ts
1513
+ var DEFAULT_FOV = 172;
1514
+ var SENSOR_WIDTH = 36;
1515
+ var FOCAL_LENGTH_PRESETS = [112, 56, 14, 7, 3, 1];
1516
+
1512
1517
  // src/core/path-manager/CameraFOVController.ts
1513
1518
  var CameraFOVController = class {
1514
1519
  constructor(opts = {}) {
@@ -1540,8 +1545,8 @@ var CameraFOVController = class {
1540
1545
  this.updateDisplay();
1541
1546
  this.emitChange();
1542
1547
  });
1543
- this.sensorWidth = opts.sensorWidth ?? 36;
1544
- this.focalLengthPresets = opts.focalLengthPresets ?? [112, 56, 14, 7, 3, 1];
1548
+ this.sensorWidth = opts.sensorWidth ?? SENSOR_WIDTH;
1549
+ this.focalLengthPresets = opts.focalLengthPresets ?? FOCAL_LENGTH_PRESETS;
1545
1550
  if (opts.minFOV === void 0 || opts.maxFOV === void 0) {
1546
1551
  const minFocalLength = Math.min(...this.focalLengthPresets);
1547
1552
  const maxFocalLength = Math.max(...this.focalLengthPresets);
@@ -1551,7 +1556,7 @@ var CameraFOVController = class {
1551
1556
  this.minFOV = opts.minFOV;
1552
1557
  this.maxFOV = opts.maxFOV;
1553
1558
  }
1554
- this.currentFOV = opts.initialFOV ?? this.focalLengthToFOVDirect(56);
1559
+ this.currentFOV = opts.initialFOV ?? DEFAULT_FOV;
1555
1560
  this.useGlobalEventBus = opts.useGlobalEventBus ?? true;
1556
1561
  this.createUI();
1557
1562
  this.setupExternalFOVListener();
@@ -1901,7 +1906,7 @@ var CameraFOVController = class {
1901
1906
 
1902
1907
  // src/core/path-manager/PathPreview.ts
1903
1908
  var PathPreview = class {
1904
- // 当前 FOV 值
1909
+ // 折叠按钮
1905
1910
  constructor(CesiumNS, mainViewer, opts = {}) {
1906
1911
  this.CesiumNS = CesiumNS;
1907
1912
  this.mainViewer = mainViewer;
@@ -1910,16 +1915,18 @@ var PathPreview = class {
1910
1915
  // Lightweight overlay viewer
1911
1916
  __publicField(this, "containerEl");
1912
1917
  // Container for the overlay viewer
1913
- __publicField(this, "footprintEntity");
1914
- // Entity for ground footprint polygon
1915
1918
  __publicField(this, "destroyed", false);
1916
1919
  // Track if the instance has been destroyed
1917
1920
  __publicField(this, "fovController");
1918
1921
  // FOV 控制器
1919
1922
  __publicField(this, "currentFOV");
1923
+ // 当前 FOV 值
1924
+ __publicField(this, "collapsed", false);
1925
+ // 折叠状态
1926
+ __publicField(this, "toggleBtn");
1920
1927
  /** 已加载的 3D Tiles 实例(预览窗口独立的) */
1921
1928
  __publicField(this, "tilesets", /* @__PURE__ */ new Map());
1922
- this.currentFOV = opts.fov ?? 50;
1929
+ this.currentFOV = opts.fov ?? DEFAULT_FOV;
1923
1930
  this.ensureViewer();
1924
1931
  this.ensureFOVController();
1925
1932
  }
@@ -1931,9 +1938,9 @@ var PathPreview = class {
1931
1938
  host = document.createElement("div");
1932
1939
  host.style.position = "absolute";
1933
1940
  host.style.right = "10px";
1934
- host.style.bottom = "10px";
1935
- host.style.width = "480px";
1936
- host.style.height = "320px";
1941
+ host.style.bottom = "80px";
1942
+ host.style.width = "320px";
1943
+ host.style.height = "200px";
1937
1944
  host.style.border = "1px solid rgba(255, 255, 255, 1)";
1938
1945
  host.style.borderRadius = "6px";
1939
1946
  host.style.overflow = "hidden";
@@ -1943,6 +1950,7 @@ var PathPreview = class {
1943
1950
  parent?.appendChild(host);
1944
1951
  } catch {
1945
1952
  }
1953
+ this.createToggleButton(host);
1946
1954
  }
1947
1955
  this.containerEl = host;
1948
1956
  const v = new C.Viewer(host, {
@@ -1977,6 +1985,157 @@ var PathPreview = class {
1977
1985
  this.syncFromMainViewer();
1978
1986
  this.disableUserInteraction();
1979
1987
  }
1988
+ /**
1989
+ * 创建折叠按钮
1990
+ */
1991
+ createToggleButton(container) {
1992
+ if (typeof document === "undefined") return;
1993
+ this.toggleBtn = document.createElement("div");
1994
+ this.toggleBtn.style.cssText = `
1995
+ position: absolute;
1996
+ top: 6px;
1997
+ left: 6px;
1998
+ width: 24px;
1999
+ height: 24px;
2000
+ background: rgba(0, 0, 0, 0.6);
2001
+ border: 1px solid rgba(255, 255, 255, 0.5);
2002
+ border-radius: 4px;
2003
+ cursor: pointer;
2004
+ z-index: 20;
2005
+ display: flex;
2006
+ align-items: center;
2007
+ justify-content: center;
2008
+ transition: all 0.2s;
2009
+ pointer-events: auto;
2010
+ `;
2011
+ this.toggleBtn.innerHTML = `
2012
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="white" style="transition: transform 0.2s;">
2013
+ <path d="M4 2 L8 6 L4 10" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
2014
+ </svg>
2015
+ `;
2016
+ this.toggleBtn.addEventListener("mouseenter", () => {
2017
+ if (this.toggleBtn) {
2018
+ this.toggleBtn.style.background = "rgba(47, 119, 251, 0.8)";
2019
+ }
2020
+ });
2021
+ this.toggleBtn.addEventListener("mouseleave", () => {
2022
+ if (this.toggleBtn) {
2023
+ this.toggleBtn.style.background = "rgba(0, 0, 0, 0.6)";
2024
+ }
2025
+ });
2026
+ this.toggleBtn.addEventListener("click", (e) => {
2027
+ e.stopPropagation();
2028
+ this.toggle();
2029
+ });
2030
+ container.appendChild(this.toggleBtn);
2031
+ }
2032
+ /**
2033
+ * 切换折叠状态
2034
+ */
2035
+ toggle() {
2036
+ if (this.collapsed) {
2037
+ this.expand();
2038
+ } else {
2039
+ this.collapse();
2040
+ }
2041
+ }
2042
+ /**
2043
+ * 折叠预览窗口
2044
+ */
2045
+ collapse() {
2046
+ if (this.collapsed || !this.containerEl) return;
2047
+ this.collapsed = true;
2048
+ this.containerEl.dataset.originalWidth = this.containerEl.style.width;
2049
+ this.containerEl.dataset.originalHeight = this.containerEl.style.height;
2050
+ this.containerEl.style.width = "36px";
2051
+ this.containerEl.style.height = "36px";
2052
+ this.containerEl.style.overflow = "hidden";
2053
+ if (this.overlayViewer) {
2054
+ const viewerContainer = this.overlayViewer.container;
2055
+ if (viewerContainer) {
2056
+ viewerContainer.style.display = "none";
2057
+ }
2058
+ }
2059
+ this.hideFOVController();
2060
+ if (this.toggleBtn) {
2061
+ this.toggleBtn.style.cssText = `
2062
+ position: absolute;
2063
+ top: 2px;
2064
+ left: 2px;
2065
+ right: 2px;
2066
+ bottom: 2px;
2067
+ width: auto;
2068
+ height: auto;
2069
+ background: rgba(47, 119, 251, 0.9);
2070
+ border: 1px solid rgba(255, 255, 255, 0.8);
2071
+ border-radius: 4px;
2072
+ cursor: pointer;
2073
+ z-index: 20;
2074
+ display: flex;
2075
+ align-items: center;
2076
+ justify-content: center;
2077
+ transition: all 0.2s;
2078
+ pointer-events: auto;
2079
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
2080
+ `;
2081
+ this.toggleBtn.innerHTML = `
2082
+ <svg width="16" height="16" viewBox="0 0 12 12" fill="white">
2083
+ <path d="M8 2 L4 6 L8 10" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
2084
+ </svg>
2085
+ `;
2086
+ }
2087
+ this.containerEl.style.display = "block";
2088
+ }
2089
+ /**
2090
+ * 展开预览窗口
2091
+ */
2092
+ expand() {
2093
+ if (!this.collapsed || !this.containerEl) return;
2094
+ this.collapsed = false;
2095
+ this.containerEl.style.width = this.containerEl.dataset.originalWidth || "320px";
2096
+ this.containerEl.style.height = this.containerEl.dataset.originalHeight || "200px";
2097
+ if (this.overlayViewer) {
2098
+ const viewerContainer = this.overlayViewer.container;
2099
+ if (viewerContainer) {
2100
+ viewerContainer.style.display = "block";
2101
+ }
2102
+ }
2103
+ this.showFOVController();
2104
+ if (this.toggleBtn) {
2105
+ this.toggleBtn.style.cssText = `
2106
+ position: absolute;
2107
+ top: 6px;
2108
+ left: 6px;
2109
+ width: 24px;
2110
+ height: 24px;
2111
+ background: rgba(0, 0, 0, 0.6);
2112
+ border: 1px solid rgba(255, 255, 255, 0.5);
2113
+ border-radius: 4px;
2114
+ cursor: pointer;
2115
+ z-index: 20;
2116
+ display: flex;
2117
+ align-items: center;
2118
+ justify-content: center;
2119
+ transition: all 0.2s;
2120
+ pointer-events: auto;
2121
+ `;
2122
+ this.toggleBtn.innerHTML = `
2123
+ <svg width="12" height="12" viewBox="0 0 12 12" fill="white">
2124
+ <path d="M4 2 L8 6 L4 10" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
2125
+ </svg>
2126
+ `;
2127
+ }
2128
+ try {
2129
+ this.overlayViewer?.scene?.requestRender?.();
2130
+ } catch {
2131
+ }
2132
+ }
2133
+ /**
2134
+ * 获取折叠状态
2135
+ */
2136
+ isCollapsed() {
2137
+ return this.collapsed;
2138
+ }
1980
2139
  /**
1981
2140
  * 从主 viewer 同步配置
1982
2141
  * 共享 Provider(安全)而非 DataSource
@@ -2232,28 +2391,6 @@ var PathPreview = class {
2232
2391
  console.warn("[PathPreview] Failed to update FOV:", e);
2233
2392
  }
2234
2393
  }
2235
- // private ensureFootprint(): void {
2236
- // const C: any = this.CesiumNS as any;
2237
- // if (this.footprintEntity) return;
2238
- // this.footprintEntity = (this.layer.entities as any).add({
2239
- // polygon: {
2240
- // // Only show when we have at least 3 ground hit points
2241
- // show: new C.CallbackProperty(() => (this._footprintPositions?.length ?? 0) >= 3, false),
2242
- // hierarchy: new C.CallbackProperty(() => {
2243
- // const arr = this._footprintPositions;
2244
- // return arr && arr.length >= 3 ? arr.slice() : undefined;
2245
- // }, false),
2246
- // material: C.Color.CYAN.withAlpha(0.18),
2247
- // outline: true,
2248
- // outlineColor: C.Color.CYAN.withAlpha(0.7),
2249
- // outlineWidth: 1,
2250
- // // Use per-position heights from globe intersections to avoid terrain-ground primitive path
2251
- // perPositionHeight: true,
2252
- // },
2253
- // properties: { _type: 'preview-footprint' },
2254
- // });
2255
- // }
2256
- // private _footprintPositions: any[] | undefined;
2257
2394
  /**
2258
2395
  * Set the camera pose and field of view for the overlay viewer.
2259
2396
  * @param cartesian cartesian position
@@ -2273,29 +2410,6 @@ var PathPreview = class {
2273
2410
  orientation: { heading: h2, pitch: p, roll: r }
2274
2411
  });
2275
2412
  }
2276
- // // Recompute footprint using overlay scene
2277
- // try {
2278
- // const scene: any = v.scene;
2279
- // const w = scene?.canvas?.width ?? 256;
2280
- // const hgt = scene?.canvas?.height ?? 144;
2281
- // const corners = [
2282
- // new C.Cartesian2(2, 2),
2283
- // new C.Cartesian2(w - 2, 2),
2284
- // new C.Cartesian2(w - 2, hgt - 2),
2285
- // new C.Cartesian2(2, hgt - 2),
2286
- // ];
2287
- // const pts: any[] = [];
2288
- // for (const c of corners) {
2289
- // const ray = v.camera.getPickRay(c);
2290
- // if (!ray) continue;
2291
- // const hit = scene.globe?.pick?.(ray, scene);
2292
- // if (hit) pts.push(hit);
2293
- // }
2294
- // // this._footprintPositions = pts.length >= 3 ? pts : undefined;
2295
- // v.scene?.requestRender?.();
2296
- // (this.mainViewer.scene as any)?.requestRender?.();
2297
- // } catch {}
2298
- // }
2299
2413
  /**
2300
2414
  * 设置 FOV(如果启用了 FOV 控制器)
2301
2415
  */
@@ -2362,7 +2476,11 @@ var PathPreview = class {
2362
2476
  } catch {
2363
2477
  }
2364
2478
  this.fovController = void 0;
2365
- this.footprintEntity = void 0;
2479
+ try {
2480
+ this.toggleBtn?.remove();
2481
+ } catch {
2482
+ }
2483
+ this.toggleBtn = void 0;
2366
2484
  try {
2367
2485
  this.tilesets.forEach((tileset) => {
2368
2486
  try {
@@ -2416,7 +2534,7 @@ var FrustumPyramid = class {
2416
2534
  */
2417
2535
  computeFrustumGeometry(apex, headingDeg, pitchDeg, rollDeg, fovDeg, length) {
2418
2536
  const C = this.CesiumNS;
2419
- const fov = Math.max(1, Math.min(120, fovDeg ?? this.opts.fov ?? 50));
2537
+ const fov = Math.max(1, Math.min(120, fovDeg ?? this.opts.fov ?? DEFAULT_FOV));
2420
2538
  const aspectRatio = this.opts.aspectRatio ?? 4 / 3;
2421
2539
  const halfFovH = C.Math.toRadians(fov / 2);
2422
2540
  const halfWidth = Math.tan(halfFovH) * length;
@@ -2595,7 +2713,7 @@ var FrustumPyramid = class {
2595
2713
  const lakeFill = (this.opts.fillColor ?? C.Color.fromCssColorString("#1e90ff")).withAlpha(alpha);
2596
2714
  const width = this.opts.width ?? 3;
2597
2715
  this.ensureEntities(lakeEdge, width, lakeFill);
2598
- const effectiveFov = Math.max(1, Math.min(120, fovDeg ?? this.opts.fov ?? 50));
2716
+ const effectiveFov = Math.max(1, Math.min(120, fovDeg ?? this.opts.fov ?? DEFAULT_FOV));
2599
2717
  const aspectRatio = this.opts.aspectRatio ?? 4 / 3;
2600
2718
  this.logAnglesIfChanged(effectiveFov, aspectRatio, headingDeg, pitchDeg);
2601
2719
  const { apex: apexPos, corners, baseCenter } = this.computeFrustumGeometry(
@@ -2799,7 +2917,7 @@ var AirplaneCursor = class {
2799
2917
  this.step = opts.stepMeters ?? 2;
2800
2918
  this.angleStep = opts.angleStepDeg ?? 1;
2801
2919
  this.fastFactor = opts.fastFactor ?? 5;
2802
- this.currentFOV = opts.fovDeg ?? 50;
2920
+ this.currentFOV = opts.fovDeg ?? DEFAULT_FOV;
2803
2921
  this.ensureEntity(opts.color ?? C.Color.CYAN.withAlpha(0.9));
2804
2922
  this.attachKeyboard(opts);
2805
2923
  this.setupFOVListener();
@@ -3077,7 +3195,8 @@ var AirplaneCursor = class {
3077
3195
  this.viewer.dataSources.add(layer);
3078
3196
  }
3079
3197
  this.frustum = new FrustumPyramid(this.CesiumNS, layer, {
3080
- fov: this.opts.fovDeg ?? 40,
3198
+ fov: this.opts.fovDeg ?? DEFAULT_FOV,
3199
+ // 使用统一的默认 FOV
3081
3200
  length: 80,
3082
3201
  color: this.opts.color,
3083
3202
  fillAlpha: 0.25,
@@ -3086,8 +3205,8 @@ var AirplaneCursor = class {
3086
3205
  logAngles: false,
3087
3206
  logThrottleMs: 300
3088
3207
  });
3089
- const frustumFovScale = 0.6;
3090
- const frustumLengthScale = 0.1;
3208
+ const frustumFovScale = 0.5;
3209
+ const frustumLengthScale = 0.2;
3091
3210
  this.frustum.showAtDynamic(
3092
3211
  () => this.pose.position,
3093
3212
  () => this.pose.heading,
@@ -5168,11 +5287,11 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5168
5287
  const fArr = getArr("_vertexFov");
5169
5288
  pitches[i] = typeof pArr?.[i] === "number" ? pArr[i] : -10;
5170
5289
  rolls[i] = typeof rArr?.[i] === "number" ? rArr[i] : 0;
5171
- fovs[i] = typeof fArr?.[i] === "number" ? fArr[i] : 50;
5290
+ fovs[i] = typeof fArr?.[i] === "number" ? fArr[i] : DEFAULT_FOV;
5172
5291
  } catch {
5173
5292
  pitches[i] = -10;
5174
5293
  rolls[i] = 0;
5175
- fovs[i] = 50;
5294
+ fovs[i] = DEFAULT_FOV;
5176
5295
  }
5177
5296
  }
5178
5297
  entity.polyline.positions = new C.CallbackProperty(() => positions.slice(), false);
@@ -5201,7 +5320,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5201
5320
  headings[activeIndex] ?? 0,
5202
5321
  pitches[activeIndex] ?? -10,
5203
5322
  0,
5204
- fovs[activeIndex] ?? 50
5323
+ fovs[activeIndex] ?? DEFAULT_FOV
5205
5324
  );
5206
5325
  }
5207
5326
  } catch {
@@ -5377,13 +5496,13 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5377
5496
  }
5378
5497
  },
5379
5498
  // frustumLengthFactor: options?.preview?.lengthFactor ?? 0.3,
5380
- fovDeg: options?.preview?.fov ?? 50
5499
+ fovDeg: options?.preview?.fov ?? DEFAULT_FOV
5381
5500
  });
5382
5501
  if (options?.preview?.enabled !== false && airplaneCursor) {
5383
5502
  preview = new PathPreview(CesiumNS, viewer, {
5384
5503
  container: options?.preview?.container,
5385
5504
  showFootprint: options?.preview?.showFootprint ?? false,
5386
- fov: options?.preview?.fov ?? 50,
5505
+ fov: options?.preview?.fov ?? DEFAULT_FOV,
5387
5506
  pitch: options?.preview?.pitch ?? -10,
5388
5507
  roll: options?.preview?.roll ?? 0
5389
5508
  });
@@ -5395,7 +5514,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5395
5514
  initialPose.heading,
5396
5515
  initialPose.pitch,
5397
5516
  initialPose.roll,
5398
- options?.preview?.fov ?? 50
5517
+ options?.preview?.fov ?? DEFAULT_FOV
5399
5518
  );
5400
5519
  } catch {
5401
5520
  console.warn("PathEditing: failed to set initial preview pose");
@@ -5653,7 +5772,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5653
5772
  heading: headings[index] ?? 0,
5654
5773
  pitch: pitches[index] ?? 0,
5655
5774
  roll: rolls[index] ?? 0,
5656
- fov: fovs[index] ?? 50
5775
+ fov: fovs[index] ?? DEFAULT_FOV
5657
5776
  };
5658
5777
  const totalVertices = positions.length;
5659
5778
  const totalVisibleVertices = totalVertices;
@@ -5727,7 +5846,7 @@ function startPathEditing(CesiumNS, viewer, entityOrId, options) {
5727
5846
  heading: headings[index] ?? 0,
5728
5847
  pitch: pitches[index] ?? -10,
5729
5848
  roll: rolls[index] ?? 0,
5730
- fov: fovs[index] ?? 50,
5849
+ fov: fovs[index] ?? DEFAULT_FOV,
5731
5850
  index,
5732
5851
  distance: calculatePathDistance(CesiumNS, positions, index),
5733
5852
  ellipsoidHeight,
@@ -6197,7 +6316,7 @@ function startPathDrawing(CesiumNS, viewer, options, onComplete) {
6197
6316
  try {
6198
6317
  const auto = options?.autoStartEditing;
6199
6318
  const editOptions = {
6200
- // 🔧 默认使用自由编辑模式(快速编辑和自由编辑互斥)
6319
+ // 默认使用自由编辑模式(快速编辑和自由编辑互斥)
6201
6320
  quickEdit: false
6202
6321
  };
6203
6322
  if (typeof auto === "object" && auto.preview) {