@navaramap/three 0.0.6 → 0.0.7

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.
Files changed (35) hide show
  1. package/dist/assets/fontWorker-DaqfXmZf.js +2 -0
  2. package/dist/assets/fontWorker-DaqfXmZf.js.map +1 -0
  3. package/dist/assets/index-Dydat1h1.js +25 -0
  4. package/dist/assets/index-Dydat1h1.js.map +1 -0
  5. package/dist/assets/{navara_wasm_font_worker_bg-DympKYVX.wasm → navara_wasm_font_worker_bg-XvE_oYPr.wasm} +0 -0
  6. package/dist/assets/{navara_wasm_worker_bg-Bx_l45cW.wasm → navara_wasm_worker_bg-Dg9fnGLP.wasm} +0 -0
  7. package/dist/index.d.ts +140 -4
  8. package/dist/index.js +5385 -5022
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.umd.cjs +164 -86
  11. package/dist/index.umd.cjs.map +1 -1
  12. package/package.json +12 -12
  13. package/src/declutter/DeclutterManager.test.ts +65 -0
  14. package/src/declutter/DeclutterManager.ts +60 -1
  15. package/src/declutter/types.ts +17 -0
  16. package/src/event/feature.ts +45 -2
  17. package/src/event/worker.ts +18 -0
  18. package/src/index.ts +51 -2
  19. package/src/layers/effect/TransparentPassEffectDesc.ts +1 -1
  20. package/src/mesh/nvLineGeometry.test.ts +88 -0
  21. package/src/mesh/nvLineGeometry.ts +148 -0
  22. package/src/mesh/polygonOutline.ts +126 -42
  23. package/src/mesh/sdfText/batchedSdfText.test.ts +377 -0
  24. package/src/mesh/sdfText/batchedSdfText.ts +192 -21
  25. package/src/mesh/sdfText/labelVisibility.test.ts +106 -0
  26. package/src/mesh/sdfText/labelVisibility.ts +131 -0
  27. package/src/mesh/sdfText/pendingSettlement.test.ts +151 -0
  28. package/src/mesh/sdfText/pendingSettlement.ts +68 -0
  29. package/src/pick/pickTerrain.ts +22 -18
  30. package/src/terrain/sampleTerrainMostDetailed.test.ts +236 -0
  31. package/src/terrain/sampleTerrainMostDetailed.ts +447 -0
  32. package/dist/assets/fontWorker-JfTCpd38.js +0 -2
  33. package/dist/assets/fontWorker-JfTCpd38.js.map +0 -1
  34. package/dist/assets/index-B3U_DvcP.js +0 -25
  35. package/dist/assets/index-B3U_DvcP.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ import { FontWorkerMemoryStats } from '@navaramap/font';
29
29
  import { Geometry } from 'geojson';
30
30
  import { Group } from 'three';
31
31
  import { InstancedMesh as InstancedMesh_2 } from 'three';
32
+ import { Intersection } from 'three';
32
33
  import { Light as Light_2 } from 'three';
33
34
  import { Line2 } from 'three-stdlib';
34
35
  import { Material } from 'three';
@@ -53,6 +54,7 @@ import { PlaneGeometry } from 'three';
53
54
  import { PointsMaterial } from 'three';
54
55
  import { PrecomputedTextures } from '@takram/three-atmosphere';
55
56
  import { Ray as Ray_3 } from 'three';
57
+ import { Raycaster } from 'three';
56
58
  import { RenderPass as RenderPass_2 } from 'postprocessing';
57
59
  import { Scene } from 'three';
58
60
  import { ShaderLibShader } from 'three';
@@ -982,6 +984,8 @@ export declare class BatchedSdfTextMesh extends InstancedMesh<Object3D> implemen
982
984
  private _labels;
983
985
  /** Sparse batchIndex → label; labels are created on first per-feature touch. */
984
986
  private _labelByIndex;
987
+ /** In-flight per-feature text preparations; see {@link whenLabelsSettled}. */
988
+ private _pendingTextPrepares;
985
989
  private _glyphs;
986
990
  private _slots;
987
991
  private _labelData;
@@ -989,6 +993,9 @@ export declare class BatchedSdfTextMesh extends InstancedMesh<Object3D> implemen
989
993
  private _maxWidth;
990
994
  private _lineHeight;
991
995
  private _textAlign;
996
+ /** Labels currently parked in `prepareDeferred`, so the per-pass promotion
997
+ * scan can bail without touching `_labels` when nothing is parked. */
998
+ private _deferredCount;
992
999
  /** Layer-level declutter settings, mirrored from the material. */
993
1000
  private _declutter;
994
1001
  private _declutterPriority;
@@ -1062,6 +1069,24 @@ export declare class BatchedSdfTextMesh extends InstancedMesh<Object3D> implemen
1062
1069
  * declutter pass to re-place on its next update. */
1063
1070
  private _markDeclutterDirty;
1064
1071
  setActive(active: boolean): void;
1072
+ /**
1073
+ * Resolves once every per-feature text preparation currently in flight has
1074
+ * landed (glyph runs written), bounded by `timeoutMs`.
1075
+ *
1076
+ * The tile-LOD swap on the Rust side hides a parent tile the moment its
1077
+ * children report rendered, so the caller must not report this batch
1078
+ * rendered while labels are still shaping — the swap would show a batch
1079
+ * that draws nothing (a tile-shaped blank).
1080
+ *
1081
+ * Only preparations already started are awaited. With declutter enabled,
1082
+ * `setTextByBatchIndex` parks unprepared text until a placement pass
1083
+ * confirms the anchor is on screen, so those labels are not yet in flight
1084
+ * and this resolves immediately — cached text (the common case for a child
1085
+ * tile repeating its parent's strings) applies synchronously and needs no
1086
+ * wait either. The gate therefore only bites on the non-decluttered path;
1087
+ * decluttered swaps rely on the placement handoff in {@link setActive}.
1088
+ */
1089
+ whenLabelsSettled(timeoutMs: number): Promise<void>;
1065
1090
  onBeforePicking(): void;
1066
1091
  onAfterPicking(): void;
1067
1092
  getRenderable(): Object3D;
@@ -1069,6 +1094,17 @@ export declare class BatchedSdfTextMesh extends InstancedMesh<Object3D> implemen
1069
1094
  _update(m: TextMesh, needRender?: () => void): Promise<void>;
1070
1095
  private _applyUpdate;
1071
1096
  setTextByBatchIndex(batchIndex: number, text: string): void;
1097
+ /** Kick off async font preparation for `text`, then lay it out — unless a
1098
+ * newer text supersedes it while the fonts load. */
1099
+ private _prepareAndApply;
1100
+ private _clearDeferred;
1101
+ /**
1102
+ * Promote parked labels whose anchor became potentially visible: start
1103
+ * their font preparation and apply the text when it lands. Runs at the
1104
+ * start of every placement pass (see {@link DeclutterParticipant}) — the
1105
+ * cadence at which visibility can actually change.
1106
+ */
1107
+ prepareDeferredLabels(camera: PerspectiveCamera): void;
1072
1108
  setFeatureColorByBatchIndex(batchIndex: number, color: Color_3): void;
1073
1109
  setFeatureShowByBatchIndex(batchIndex: number, rawVisible: boolean): void;
1074
1110
  setFeatureHeightByBatchIndex(batchIndex: number, height: number): void;
@@ -2003,6 +2039,14 @@ declare class Core {
2003
2039
  * through the per-slot material path).
2004
2040
  */
2005
2041
  getRasterTileStates(handle: bigint): RasterTileState[];
2042
+ /**
2043
+ * Read back a stored source as the plain description object `addSource`
2044
+ * accepts — including engine defaults and partial-update merges (inline
2045
+ * GeoJSON `data` is not read back). `undefined` for unknown ids. Used by
2046
+ * `view.sampleTerrainMostDetailed` to sample against the exact config
2047
+ * the view renders with.
2048
+ */
2049
+ getSourceDescription(source_id: string): any;
2006
2050
  getTile(handle: bigint): TransferableTile | undefined;
2007
2051
  getTileElevationDecoder(handle: bigint): ElevationDecoder | undefined;
2008
2052
  getTransferablePolygonBatchedFeature(batched_feature_id: bigint): ReturnedTransferablePolygonBatchedFeature | undefined;
@@ -2560,6 +2604,13 @@ declare type DeclutterCandidate = {
2560
2604
  /** Participant-defined id (label slot for text batches, instance index for
2561
2605
  * sprites) passed back to `applyDeclutter`. */
2562
2606
  handle: number;
2607
+ /**
2608
+ * Stable identity of what the candidate displays (label text for text
2609
+ * batches). Feeds the manager's shown-content registry so a tile swap can
2610
+ * hand placement over to the replacing batch's identical label without a
2611
+ * hide/fade-in blink. Omit for candidates that don't participate.
2612
+ */
2613
+ contentKey?: string;
2563
2614
  };
2564
2615
 
2565
2616
  /**
@@ -2622,6 +2673,11 @@ declare class DeclutterManager {
2622
2673
  * drift toggles frame to frame instead of flickering. Its full box is
2623
2674
  * still claimed against competitors. */
2624
2675
  static readonly HYSTERESIS_PX = 6;
2676
+ /** Anchor distance (m) within which two same-content candidates count as
2677
+ * the same label for the tile-swap handoff. Covers the anchor drift a
2678
+ * zoom level's tile-grid quantization (and per-tile terrain heights)
2679
+ * introduces, while staying far below distinct same-name places. */
2680
+ static readonly HANDOFF_TOLERANCE_M = 2000;
2625
2681
  private _participants;
2626
2682
  /** Set when the label set changed (register/update/text change) so the next
2627
2683
  * update re-places even with a static camera. */
@@ -2629,6 +2685,10 @@ declare class DeclutterManager {
2629
2685
  private _prevCamera;
2630
2686
  private _lastRunAt;
2631
2687
  private _lastStepAt;
2688
+ /** Shown candidates of the most recent pass, keyed by content, as flat xyz
2689
+ * anchor triplets. Read by {@link wasRecentlyShown} when a tile swap
2690
+ * activates a replacement batch. */
2691
+ private _shownByContent;
2632
2692
  private _candidates;
2633
2693
  /** Packed candidate input for the kernel; grows as the label count does. */
2634
2694
  private _input;
@@ -2648,6 +2708,15 @@ declare class DeclutterManager {
2648
2708
  /** Signal that candidates changed (text, positions, visibility, style) so
2649
2709
  * the next update re-runs placement even if the camera is still. */
2650
2710
  markDirty(): void;
2711
+ /**
2712
+ * Whether the most recent pass showed `contentKey` anchored within
2713
+ * {@link DeclutterManager.HANDOFF_TOLERANCE_M} of (x, y, z) — i.e. an
2714
+ * equivalent label (typically the swapped-out tile's copy) already holds
2715
+ * this screen space. A batch activating in a tile swap uses this to seed
2716
+ * such labels as granted instead of fading them in from hidden, which
2717
+ * would blink the whole tile's labels out for a pass-plus-fade.
2718
+ */
2719
+ wasRecentlyShown(contentKey: string, x: number, y: number, z: number): boolean;
2651
2720
  /**
2652
2721
  * Run a placement pass if one is due, then advance any active show/hide
2653
2722
  * fades. `widthPx`/`heightPx` are the viewport in CSS pixels (matching the
@@ -2683,6 +2752,14 @@ declare type DeclutterParticipant = {
2683
2752
  * anything is fading; returns true while any label is still mid-fade.
2684
2753
  */
2685
2754
  stepDeclutterFade: (deltaMs: number) => boolean;
2755
+ /**
2756
+ * Optional: start preparation (font loading, shaping) for labels that
2757
+ * parked it while their anchor was out of view. Called at the start of
2758
+ * every placement pass with the camera the pass will use — the cadence at
2759
+ * which visibility can actually change. Preparation is asynchronous, so
2760
+ * promoted labels join a *later* pass once their text is applied.
2761
+ */
2762
+ prepareDeferredLabels?: (camera: PerspectiveCamera) => void;
2686
2763
  };
2687
2764
 
2688
2765
  declare type DeclutterUpdateResult =
@@ -3251,6 +3328,13 @@ export declare class EllipsoidGeodesic {
3251
3328
  constructor(start: LatLngHeight, end: LatLngHeight);
3252
3329
  /** Distance in meters between start and end points */
3253
3330
  get distance(): number;
3331
+ /**
3332
+ * Whether the geodesic solve converged. `false` for near-antipodal
3333
+ * endpoints, where `distance` is only a rough estimate and the
3334
+ * interpolation methods snap to the endpoints instead of following the
3335
+ * unreliable solution.
3336
+ */
3337
+ get converged(): boolean;
3254
3338
  /** Heading at the start point in radians */
3255
3339
  get startHeading(): number;
3256
3340
  /** Heading at the end point in radians */
@@ -7194,7 +7278,10 @@ declare class PolygonMesh_2 {
7194
7278
  export declare class PolygonOutlineMesh extends Line2 implements FeatureMesh {
7195
7279
  readonly ctx: EventContext;
7196
7280
  private resizeEventUnsubscribe?;
7281
+ /** True when the geometry carries RTE high/low positions (GeoJSON path). */
7282
+ private useRTE;
7197
7283
  constructor(ctx: EventContext, mesh: PolygonMesh_2);
7284
+ raycast(raycaster: Raycaster, intersects: Intersection[]): void;
7198
7285
  private initGeometry;
7199
7286
  private initScaleNormalCapAttributes;
7200
7287
  private initMaterial;
@@ -8171,6 +8258,32 @@ export declare type RTEUserData = {
8171
8258
  };
8172
8259
  };
8173
8260
 
8261
+ export declare type SampledTerrainPosition = {
8262
+ /** Latitude in radians, echoed from the input. */
8263
+ lat: number;
8264
+ /** Longitude in radians, echoed from the input. */
8265
+ lng: number;
8266
+ /**
8267
+ * Terrain height in meters, or `undefined` when no tile covering the
8268
+ * position could be fetched or decoded.
8269
+ */
8270
+ height: number | undefined;
8271
+ /** Zoom level the height was sampled at; `undefined` on failure. */
8272
+ level: number | undefined;
8273
+ };
8274
+
8275
+ export declare type SampleTerrainOptions = {
8276
+ /** Aborts in-flight tile fetches and rejects with the abort reason. */
8277
+ signal?: AbortSignal;
8278
+ /**
8279
+ * Sample at this fixed zoom level instead of probing down from the
8280
+ * source's `maxZoom`. A tile missing at this level yields `undefined`
8281
+ * heights rather than falling back to a coarser level (Cesium's
8282
+ * `sampleTerrain` semantics).
8283
+ */
8284
+ level?: number;
8285
+ };
8286
+
8174
8287
  declare class SceneGroup extends Group {
8175
8288
  get tileScenes(): TileScene[];
8176
8289
  }
@@ -9675,10 +9788,29 @@ declare class ThreeView<D extends Descriptions = EmptyDescriptions> extends Even
9675
9788
  cameraFreeLook(enabled: boolean, target?: LatLngHeight): void;
9676
9789
  /**
9677
9790
  * Samples the terrain height at a given geodetic position synchronously.
9678
- * @param pos - Geodetic position (lat in radians, lng in radians; height is ignored)
9791
+ * @param pos - Geodetic position (lat in radians, lng in radians)
9679
9792
  * @returns Terrain height in meters, or undefined if terrain data not loaded
9680
9793
  */
9681
- sampleTerrainHeight(pos: LatLngHeight): number | undefined;
9794
+ sampleTerrainHeight(pos: LatLng): number | undefined;
9795
+ /**
9796
+ * Samples terrain heights at the most detailed zoom level the terrain
9797
+ * source provides, fetching the needed tiles over the network — unlike
9798
+ * {@link sampleTerrainHeight}, which reads only tiles already resident for
9799
+ * rendering and returns coarse-LOD heights (or nothing) when the camera is
9800
+ * far away. Use this to place objects on the ground before the camera has
9801
+ * streamed the area in.
9802
+ *
9803
+ * `source` is a registered `quantized-mesh` / `raster-dem` source: the
9804
+ * {@link Source} handle returned by `addSource`, or its id. The stored
9805
+ * config (including engine defaults and partial-update merges) is what gets
9806
+ * sampled.
9807
+ *
9808
+ * @param source - A registered terrain source (handle or id)
9809
+ * @param positions - Geodetic positions (lat/lng in radians)
9810
+ * @param options - Optional abort signal and fixed-level sampling
9811
+ * @returns One result per input position, in the same order
9812
+ */
9813
+ sampleTerrainMostDetailed(source: SourceRef, positions: LatLng[], options?: SampleTerrainOptions): Promise<SampledTerrainPosition[]>;
9682
9814
  /**
9683
9815
  * Observes terrain height changes at a position. Callback is invoked each time terrain data updates.
9684
9816
  * @param pos - Geodetic position to observe (lat in radians, lng in radians)
@@ -10313,9 +10445,13 @@ declare class TransferablePolygonGeometry {
10313
10445
  declare class TransferablePolygonOutlineGeometry {
10314
10446
  free(): void;
10315
10447
  [Symbol.dispose](): void;
10316
- constructor(position?: TransferableFloatAttribute | null, scale_normal_and_cap?: TransferableFloatAttribute | null, skip_indices?: number | null, batch_index?: TransferableFloatAttribute | null);
10448
+ constructor(position?: TransferableFloatAttribute | null, position_3d_high?: TransferableFloatAttribute | null, position_3d_low?: TransferableFloatAttribute | null, scale_normal_and_cap?: TransferableFloatAttribute | null, skip_indices?: number | null, batch_index?: TransferableFloatAttribute | null);
10317
10449
  get batch_index(): TransferableFloatAttribute | undefined;
10318
10450
  set batch_index(value: TransferableFloatAttribute | null | undefined);
10451
+ get position_3d_high(): TransferableFloatAttribute | undefined;
10452
+ set position_3d_high(value: TransferableFloatAttribute | null | undefined);
10453
+ get position_3d_low(): TransferableFloatAttribute | undefined;
10454
+ set position_3d_low(value: TransferableFloatAttribute | null | undefined);
10319
10455
  get position(): TransferableFloatAttribute | undefined;
10320
10456
  set position(value: TransferableFloatAttribute | null | undefined);
10321
10457
  get scale_normal_and_cap(): TransferableFloatAttribute | undefined;
@@ -10414,7 +10550,7 @@ export declare type TransparentPassConfig = Description_4 & EffectConfig;
10414
10550
 
10415
10551
  export declare class TransparentPassEffectDesc extends EffectDesc<TransparentPassConfig, TransparentPassUpdate, RenderPass> {
10416
10552
  static key: string;
10417
- static insertAfter: string[];
10553
+ static insertBefore: string[];
10418
10554
  light: Group< Object3DEventMap>;
10419
10555
  lightsSyncMap: Map<any, any>;
10420
10556
  createPass(): RenderPass;