@accelint/map-toolkit 1.5.0 → 3.0.0
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/CHANGELOG.md +83 -0
- package/README.md +8 -1
- package/catalog-info.yaml +9 -6
- package/dist/camera/events.js +1 -1
- package/dist/camera/index.d.ts +1 -1
- package/dist/camera/index.js +1 -1
- package/dist/camera/store.d.ts +1 -1
- package/dist/camera/store.js +3 -5
- package/dist/camera/store.js.map +1 -1
- package/dist/camera/types.d.ts +1 -1
- package/dist/camera/types.js +1 -1
- package/dist/cursor-coordinates/constants.js +1 -1
- package/dist/cursor-coordinates/index.d.ts +1 -1
- package/dist/cursor-coordinates/index.js +1 -1
- package/dist/cursor-coordinates/store.d.ts +1 -1
- package/dist/cursor-coordinates/store.js +1 -1
- package/dist/cursor-coordinates/types.d.ts +1 -1
- package/dist/cursor-coordinates/types.js +1 -1
- package/dist/cursor-coordinates/use-cursor-coordinates.d.ts +1 -1
- package/dist/cursor-coordinates/use-cursor-coordinates.js +4 -9
- package/dist/cursor-coordinates/use-cursor-coordinates.js.map +1 -1
- package/dist/deckgl/base-map/constants.js +1 -1
- package/dist/deckgl/base-map/controls.d.ts +1 -1
- package/dist/deckgl/base-map/controls.js +1 -1
- package/dist/deckgl/base-map/events.js +1 -1
- package/dist/deckgl/base-map/index.d.ts +3 -3
- package/dist/deckgl/base-map/index.js +1 -1
- package/dist/deckgl/base-map/provider.d.ts +1 -1
- package/dist/deckgl/base-map/provider.js +1 -1
- package/dist/deckgl/base-map/types.d.ts +1 -1
- package/dist/deckgl/base-map/types.js +1 -1
- package/dist/deckgl/extensions/coffin-corner/coffin-corner-extension.d.ts +144 -0
- package/dist/deckgl/extensions/coffin-corner/coffin-corner-extension.js +535 -0
- package/dist/deckgl/extensions/coffin-corner/coffin-corner-extension.js.map +1 -0
- package/dist/deckgl/extensions/coffin-corner/index.d.ts +17 -0
- package/dist/deckgl/extensions/coffin-corner/index.js +19 -0
- package/dist/deckgl/extensions/coffin-corner/store.d.ts +96 -0
- package/dist/deckgl/extensions/coffin-corner/store.js +173 -0
- package/dist/deckgl/extensions/coffin-corner/store.js.map +1 -0
- package/dist/deckgl/extensions/coffin-corner/types.d.ts +76 -0
- package/dist/deckgl/extensions/coffin-corner/types.js +27 -0
- package/dist/deckgl/extensions/coffin-corner/types.js.map +1 -0
- package/dist/deckgl/extensions/coffin-corner/use-coffin-corner.d.ts +81 -0
- package/dist/deckgl/extensions/coffin-corner/use-coffin-corner.js +75 -0
- package/dist/deckgl/extensions/coffin-corner/use-coffin-corner.js.map +1 -0
- package/dist/deckgl/extensions/index.d.ts +15 -0
- package/dist/deckgl/extensions/index.js +16 -0
- package/dist/deckgl/index.d.ts +9 -4
- package/dist/deckgl/index.js +6 -2
- package/dist/deckgl/saved-viewports/index.d.ts +1 -1
- package/dist/deckgl/saved-viewports/index.js +1 -1
- package/dist/deckgl/saved-viewports/storage.d.ts +1 -1
- package/dist/deckgl/saved-viewports/storage.js +5 -10
- package/dist/deckgl/saved-viewports/storage.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/constants.js +70 -26
- package/dist/deckgl/shapes/display-shape-layer/constants.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/fiber.d.ts +1 -1
- package/dist/deckgl/shapes/display-shape-layer/fiber.js +1 -1
- package/dist/deckgl/shapes/display-shape-layer/index.d.ts +93 -38
- package/dist/deckgl/shapes/display-shape-layer/index.js +433 -187
- package/dist/deckgl/shapes/display-shape-layer/index.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js +1 -1
- package/dist/deckgl/shapes/display-shape-layer/store.js +1 -1
- package/dist/deckgl/shapes/display-shape-layer/types.d.ts +116 -19
- package/dist/deckgl/shapes/display-shape-layer/types.js +1 -1
- package/dist/deckgl/shapes/display-shape-layer/use-select-shape.d.ts +1 -1
- package/dist/deckgl/shapes/display-shape-layer/use-select-shape.js +1 -1
- package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js +66 -36
- package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/utils/elevation.js +407 -0
- package/dist/deckgl/shapes/display-shape-layer/utils/elevation.js.map +1 -0
- package/dist/deckgl/shapes/display-shape-layer/utils/icon-config.js +106 -0
- package/dist/deckgl/shapes/display-shape-layer/utils/icon-config.js.map +1 -0
- package/dist/deckgl/shapes/display-shape-layer/utils/labels.d.ts +1 -1
- package/dist/deckgl/shapes/display-shape-layer/utils/labels.js +28 -39
- package/dist/deckgl/shapes/display-shape-layer/utils/labels.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/utils/radius-label.js +53 -0
- package/dist/deckgl/shapes/display-shape-layer/utils/radius-label.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/constants.js +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/events.d.ts +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/events.js +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/fiber.js +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/index.d.ts +8 -4
- package/dist/deckgl/shapes/draw-shape-layer/index.js +11 -17
- package/dist/deckgl/shapes/draw-shape-layer/index.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js +6 -5
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js +4 -3
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js +6 -20
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js +6 -33
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js +16 -12
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/modes/index.js +2 -32
- package/dist/deckgl/shapes/draw-shape-layer/modes/index.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/store.js +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/types.d.ts +3 -3
- package/dist/deckgl/shapes/draw-shape-layer/types.js +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.d.ts +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.js +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js +3 -8
- package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/constants.js +17 -2
- package/dist/deckgl/shapes/edit-shape-layer/constants.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/events.d.ts +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/events.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/fiber.d.ts +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/fiber.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/index.d.ts +12 -6
- package/dist/deckgl/shapes/edit-shape-layer/index.js +72 -27
- package/dist/deckgl/shapes/edit-shape-layer/index.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js +4 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js +4 -3
- package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js +5 -3
- package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/index.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/point-translate-mode.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/point-translate-mode.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/store.js +83 -14
- package/dist/deckgl/shapes/edit-shape-layer/store.js.map +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/types.d.ts +18 -4
- package/dist/deckgl/shapes/edit-shape-layer/types.js +1 -1
- package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.d.ts +2 -2
- package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js +8 -4
- package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js.map +1 -1
- package/dist/deckgl/shapes/index.d.ts +5 -4
- package/dist/deckgl/shapes/index.js +3 -2
- package/dist/deckgl/shapes/shared/constants.d.ts +4 -3
- package/dist/deckgl/shapes/shared/constants.js +51 -11
- package/dist/deckgl/shapes/shared/constants.js.map +1 -1
- package/dist/deckgl/shapes/shared/events.d.ts +5 -1
- package/dist/deckgl/shapes/shared/events.js +1 -1
- package/dist/deckgl/shapes/shared/events.js.map +1 -1
- package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js +19 -16
- package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js.map +1 -1
- package/dist/deckgl/shapes/shared/types.d.ts +182 -54
- package/dist/deckgl/shapes/shared/types.js +155 -2
- package/dist/deckgl/shapes/shared/types.js.map +1 -1
- package/dist/deckgl/shapes/shared/utils/duplicate-shape.d.ts +56 -0
- package/dist/deckgl/shapes/shared/utils/duplicate-shape.js +131 -0
- package/dist/deckgl/shapes/shared/utils/duplicate-shape.js.map +1 -0
- package/dist/deckgl/shapes/shared/utils/geometry-measurements.js +29 -24
- package/dist/deckgl/shapes/shared/utils/geometry-measurements.js.map +1 -1
- package/dist/deckgl/shapes/shared/utils/layer-config.js +15 -9
- package/dist/deckgl/shapes/shared/utils/layer-config.js.map +1 -1
- package/dist/deckgl/shapes/shared/utils/mode-utils.js +50 -20
- package/dist/deckgl/shapes/shared/utils/mode-utils.js.map +1 -1
- package/dist/deckgl/shapes/shared/utils/pick-filtering.js +22 -15
- package/dist/deckgl/shapes/shared/utils/pick-filtering.js.map +1 -1
- package/dist/deckgl/shapes/shared/utils/style-utils.d.ts +38 -14
- package/dist/deckgl/shapes/shared/utils/style-utils.js +43 -32
- package/dist/deckgl/shapes/shared/utils/style-utils.js.map +1 -1
- package/dist/deckgl/symbol-layer/fiber.d.ts +4 -2
- package/dist/deckgl/symbol-layer/fiber.js +1 -1
- package/dist/deckgl/symbol-layer/fiber.js.map +1 -1
- package/dist/deckgl/symbol-layer/index.d.ts +1 -1
- package/dist/deckgl/symbol-layer/index.js +1 -1
- package/dist/deckgl/text-layer/character-sets.js +1 -1
- package/dist/deckgl/text-layer/default-settings.d.ts +1 -1
- package/dist/deckgl/text-layer/default-settings.js +1 -1
- package/dist/deckgl/text-layer/fiber.d.ts +1 -1
- package/dist/deckgl/text-layer/fiber.js +1 -1
- package/dist/deckgl/text-layer/index.d.ts +1 -1
- package/dist/deckgl/text-layer/index.js +1 -1
- package/dist/deckgl/text-settings.d.ts +3 -3
- package/dist/deckgl/text-settings.js +1 -1
- package/dist/map-cursor/events.js +1 -1
- package/dist/map-cursor/index.d.ts +1 -1
- package/dist/map-cursor/index.js +1 -1
- package/dist/map-cursor/store.d.ts +1 -1
- package/dist/map-cursor/store.js +1 -1
- package/dist/map-cursor/types.d.ts +1 -1
- package/dist/map-cursor/types.js +1 -1
- package/dist/map-cursor/use-map-cursor.d.ts +1 -1
- package/dist/map-cursor/use-map-cursor.js +1 -1
- package/dist/map-mode/events.js +1 -1
- package/dist/map-mode/index.d.ts +1 -1
- package/dist/map-mode/index.js +1 -1
- package/dist/map-mode/store.d.ts +1 -1
- package/dist/map-mode/store.js +3 -8
- package/dist/map-mode/store.js.map +1 -1
- package/dist/map-mode/types.d.ts +1 -1
- package/dist/map-mode/types.js +1 -1
- package/dist/map-mode/use-map-mode.d.ts +1 -1
- package/dist/map-mode/use-map-mode.js +1 -1
- package/dist/maplibre/hooks/use-maplibre.d.ts +1 -1
- package/dist/maplibre/hooks/use-maplibre.js +1 -1
- package/dist/maplibre/index.d.ts +1 -1
- package/dist/maplibre/index.js +1 -1
- package/dist/shared/cleanup.d.ts +1 -1
- package/dist/shared/cleanup.js +1 -1
- package/dist/shared/constants.js +1 -1
- package/dist/shared/create-map-store.d.ts +1 -1
- package/dist/shared/create-map-store.js +1 -1
- package/dist/shared/logger.js +31 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/units.d.ts +15 -56
- package/dist/shared/units.js +2 -53
- package/dist/shared/units.js.map +1 -1
- package/dist/viewport/index.d.ts +3 -4
- package/dist/viewport/index.js +2 -3
- package/dist/viewport/store.d.ts +1 -1
- package/dist/viewport/store.js +1 -1
- package/dist/viewport/types.d.ts +9 -5
- package/dist/viewport/types.js +1 -1
- package/dist/viewport/utils.d.ts +4 -4
- package/dist/viewport/utils.js +17 -9
- package/dist/viewport/utils.js.map +1 -1
- package/dist/viewport/viewport-size.d.ts +7 -6
- package/dist/viewport/viewport-size.js +3 -3
- package/dist/viewport/viewport-size.js.map +1 -1
- package/package.json +29 -20
- package/dist/hotkey-manager/dist/react/use-hotkey.js +0 -39
- package/dist/hotkey-manager/dist/react/use-hotkey.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at https://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -14,24 +14,22 @@
|
|
|
14
14
|
'use client';
|
|
15
15
|
|
|
16
16
|
import { ShapeEvents } from "../shared/events.js";
|
|
17
|
-
import {
|
|
17
|
+
import { isCircleShape, isLineGeometry, isPointType, isPolygonGeometry } from "../shared/types.js";
|
|
18
|
+
import { DEFAULT_TEXT_SIZE, DEFAULT_TEXT_STYLE } from "../../text-settings.js";
|
|
19
|
+
import { SHAPE_LAYER_IDS } from "../shared/constants.js";
|
|
18
20
|
import { getDashArray, getFillColor, getLineColor } from "../shared/utils/style-utils.js";
|
|
19
|
-
import {
|
|
21
|
+
import { BRIGHTNESS_FACTOR, DEFAULT_DISPLAY_PROPS, DISPLAY_EXTENSIONS, HIGHLIGHT_COLOR_TUPLE, MAP_INTERACTION, MATERIAL_SETTINGS } from "./constants.js";
|
|
22
|
+
import { getLabelPosition2d } from "./utils/labels.js";
|
|
20
23
|
import { createShapeLabelLayer } from "./shape-label-layer.js";
|
|
21
|
-
import {
|
|
24
|
+
import { applyOverlayOpacity, brightenColor, getHighlightLineWidth, getHoverLineWidth, getOverlayFillColor } from "./utils/display-style.js";
|
|
25
|
+
import { buildIndicatorLineData, classifyElevatedFeatures, createCurtainPolygonFeatures, flattenFeatureTo2D, getFeatureElevation, partitionCurtains } from "./utils/elevation.js";
|
|
26
|
+
import { getIconConfig, getIconLayerProps, getIconUpdateTriggers } from "./utils/icon-config.js";
|
|
27
|
+
import { getRadiusLabelText } from "./utils/radius-label.js";
|
|
22
28
|
import { Broadcast } from "@accelint/bus";
|
|
23
|
-
import { getLogger } from "@accelint/logger";
|
|
24
29
|
import { CompositeLayer } from "@deck.gl/core";
|
|
25
|
-
import {
|
|
26
|
-
import { GeoJsonLayer, IconLayer } from "@deck.gl/layers";
|
|
30
|
+
import { GeoJsonLayer, LineLayer, TextLayer } from "@deck.gl/layers";
|
|
27
31
|
|
|
28
32
|
//#region src/deckgl/shapes/display-shape-layer/index.ts
|
|
29
|
-
const logger = getLogger({
|
|
30
|
-
enabled: process.env.NODE_ENV !== "production",
|
|
31
|
-
level: "warn",
|
|
32
|
-
prefix: "[DisplayShapeLayer]",
|
|
33
|
-
pretty: true
|
|
34
|
-
});
|
|
35
33
|
/**
|
|
36
34
|
* Typed event bus instance for shape events.
|
|
37
35
|
* Provides type-safe event emission for shape interactions.
|
|
@@ -46,24 +44,28 @@ const shapeBus = Broadcast.getInstance();
|
|
|
46
44
|
* ## Features
|
|
47
45
|
* - **Multiple geometry types**: Point, LineString, Polygon, and Circle
|
|
48
46
|
* - **Icon support**: Custom icons for Point geometries via icon atlases
|
|
49
|
-
* - **Interactive selection**: Click handling with
|
|
50
|
-
* - **Hover effects**:
|
|
47
|
+
* - **Interactive selection**: Click handling with brightness overlay on polygon select, optional highlight outline for non-Point shapes (if showHighlight=true). Point geometries use coffin corner brackets instead.
|
|
48
|
+
* - **Hover effects**: Polygon fills brighten via material lighting; outline width increases by 2px on hover
|
|
51
49
|
* - **Customizable labels**: Flexible label positioning with per-shape or global options
|
|
52
50
|
* - **Style properties**: Full control over colors, border/outline patterns, and opacity
|
|
53
51
|
* - **Event bus integration**: Automatically emits shape events via @accelint/bus
|
|
54
52
|
* - **Multi-map support**: Events include map instance ID for isolation
|
|
55
53
|
*
|
|
56
|
-
* ##
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* -
|
|
54
|
+
* ## Interaction Philosophy
|
|
55
|
+
* Interactions never modify a shape's innate styling. Hover and selection are always
|
|
56
|
+
* additive overlays rendered apart from the main layer using opacity-scaled fill colors
|
|
57
|
+
* and material-based brightness — the base shape is never altered.
|
|
60
58
|
*
|
|
61
59
|
* ## Layer Structure
|
|
62
|
-
* Renders
|
|
63
|
-
* 1. **Highlight layer**: Selection
|
|
64
|
-
* 2. **
|
|
65
|
-
* 3. **
|
|
66
|
-
* 4. **
|
|
60
|
+
* Renders sublayers in this order (bottom to top):
|
|
61
|
+
* 1. **Highlight layer**: Selection outline for non-polygon, non-Point shapes (when showHighlight enabled)
|
|
62
|
+
* 2. **Select layer**: Selection brightness overlay for polygon shapes
|
|
63
|
+
* 3. **Hover layer**: Hover brightness overlay for polygon shapes
|
|
64
|
+
* 4. **Elevation visualization**: Curtains (LineStrings) or wireframes (polygons) — elevation only
|
|
65
|
+
* 5. **Elevation indicators**: Vertical strut lines for elevated non-polygon shapes — elevation only
|
|
66
|
+
* 6. **Main GeoJsonLayer**: Shape geometries with styling and interaction; includes CoffinCornerExtension
|
|
67
|
+
* which propagates to the icon/scatterplot sublayer for Point hover/select bracket feedback
|
|
68
|
+
* 7. **Label layer**: Text labels (if showLabels enabled)
|
|
67
69
|
*
|
|
68
70
|
* ## Icon Atlas Constraint
|
|
69
71
|
* When using icons for Point geometries, all shapes in a single layer must share the
|
|
@@ -124,6 +126,12 @@ const shapeBus = Broadcast.getInstance();
|
|
|
124
126
|
var DisplayShapeLayer = class extends CompositeLayer {
|
|
125
127
|
/** Cache for transformed features to avoid recreating objects on every render */
|
|
126
128
|
featuresCache = null;
|
|
129
|
+
/** Cache for elevation classification and curtain features */
|
|
130
|
+
elevationCache = null;
|
|
131
|
+
/** Cache for elevation indicator line segments */
|
|
132
|
+
indicatorCache = null;
|
|
133
|
+
/** Cached coffin corner color tuple — avoids new array reference per render when highlight hasn't changed. */
|
|
134
|
+
coffinCornerColorCache = null;
|
|
127
135
|
static layerName = "DisplayShapeLayer";
|
|
128
136
|
static defaultProps = { ...DEFAULT_DISPLAY_PROPS };
|
|
129
137
|
/**
|
|
@@ -135,19 +143,82 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
135
143
|
lastHoveredId: void 0
|
|
136
144
|
});
|
|
137
145
|
this.featuresCache = null;
|
|
146
|
+
this.elevationCache = null;
|
|
147
|
+
this.indicatorCache = null;
|
|
148
|
+
this.coffinCornerColorCache = null;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Resolved highlight color — uses prop if provided, falls back to default.
|
|
152
|
+
*/
|
|
153
|
+
get resolvedHighlight() {
|
|
154
|
+
return this.props.highlightColor ?? HIGHLIGHT_COLOR_TUPLE;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Coffin corner bracket color derived from resolvedHighlight with forced full opacity.
|
|
158
|
+
* Cached to avoid a new array reference per render triggering deck.gl prop-change detection.
|
|
159
|
+
*/
|
|
160
|
+
get coffinCornerColor() {
|
|
161
|
+
const highlight = this.resolvedHighlight;
|
|
162
|
+
if (this.coffinCornerColorCache?.source !== highlight) this.coffinCornerColorCache = {
|
|
163
|
+
source: highlight,
|
|
164
|
+
color: [
|
|
165
|
+
highlight[0],
|
|
166
|
+
highlight[1],
|
|
167
|
+
highlight[2],
|
|
168
|
+
255
|
|
169
|
+
]
|
|
170
|
+
};
|
|
171
|
+
return this.coffinCornerColorCache.color;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Handle picking events from the main shapes layer
|
|
175
|
+
*/
|
|
176
|
+
handleMainLayerPick(info, mode) {
|
|
177
|
+
if (mode === "query") this.handleShapeClick(info);
|
|
178
|
+
if (mode === "hover" || !mode) {
|
|
179
|
+
if (info.index !== void 0 && info.index !== this.state?.hoverIndex) this.setState({ hoverIndex: info.index });
|
|
180
|
+
this.handleShapeHover(info);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Handle picking events from curtain layers and map back to original LineString
|
|
185
|
+
*/
|
|
186
|
+
handleCurtainPick(info, mode) {
|
|
187
|
+
if (!info.object) return;
|
|
188
|
+
const curtainShapeId = info.object.properties?.shapeId;
|
|
189
|
+
if (!curtainShapeId) return;
|
|
190
|
+
const features = this.getFeaturesWithId();
|
|
191
|
+
const featureIndex = this.featuresCache?.shapeIdToIndex.get(curtainShapeId);
|
|
192
|
+
if (featureIndex === void 0) return;
|
|
193
|
+
const modifiedInfo = {
|
|
194
|
+
...info,
|
|
195
|
+
index: featureIndex,
|
|
196
|
+
object: features[featureIndex]
|
|
197
|
+
};
|
|
198
|
+
if (mode === "query") this.handleShapeClick(modifiedInfo);
|
|
199
|
+
if (mode === "hover" || !mode) {
|
|
200
|
+
if (featureIndex !== this.state?.hoverIndex) this.setState({ hoverIndex: featureIndex });
|
|
201
|
+
this.handleShapeHover(modifiedInfo);
|
|
202
|
+
}
|
|
203
|
+
return modifiedInfo;
|
|
138
204
|
}
|
|
139
205
|
/**
|
|
140
206
|
* Override getPickingInfo to handle events from sublayers
|
|
141
207
|
* This is the correct pattern for CompositeLayer event handling
|
|
142
208
|
*/
|
|
143
209
|
getPickingInfo({ info, mode, sourceLayer }) {
|
|
210
|
+
if ((mode === "hover" || !mode) && (info.index === void 0 || info.index < 0)) {
|
|
211
|
+
if (this.state?.hoverIndex !== void 0) this.setState({ hoverIndex: void 0 });
|
|
212
|
+
this.handleShapeHover(info);
|
|
213
|
+
return info;
|
|
214
|
+
}
|
|
144
215
|
if (sourceLayer?.id === `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}`) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
216
|
+
this.handleMainLayerPick(info, mode);
|
|
217
|
+
return info;
|
|
218
|
+
}
|
|
219
|
+
if (sourceLayer?.id?.includes("-elevation-curtain")) {
|
|
220
|
+
const curtainInfo = this.handleCurtainPick(info, mode);
|
|
221
|
+
if (curtainInfo) return curtainInfo;
|
|
151
222
|
}
|
|
152
223
|
return info;
|
|
153
224
|
}
|
|
@@ -160,20 +231,25 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
160
231
|
if (this.featuresCache?.data === data) return this.featuresCache.features;
|
|
161
232
|
const features = [];
|
|
162
233
|
const shapeIdToIndex = /* @__PURE__ */ new Map();
|
|
234
|
+
const normalizedLineColors = [];
|
|
163
235
|
for (const [i, shape] of data.entries()) {
|
|
164
|
-
|
|
236
|
+
let feature = {
|
|
165
237
|
...shape.feature,
|
|
166
238
|
properties: {
|
|
167
239
|
...shape.feature.properties,
|
|
168
240
|
shapeId: shape.id
|
|
169
241
|
}
|
|
170
|
-
}
|
|
242
|
+
};
|
|
243
|
+
if (isPolygonGeometry(feature.geometry) && getFeatureElevation(feature) > 0) feature = flattenFeatureTo2D(feature);
|
|
244
|
+
features.push(feature);
|
|
171
245
|
shapeIdToIndex.set(shape.id, i);
|
|
246
|
+
normalizedLineColors.push(getLineColor(shape.feature));
|
|
172
247
|
}
|
|
173
248
|
this.featuresCache = {
|
|
174
249
|
data,
|
|
175
250
|
features,
|
|
176
|
-
shapeIdToIndex
|
|
251
|
+
shapeIdToIndex,
|
|
252
|
+
normalizedLineColors
|
|
177
253
|
};
|
|
178
254
|
return features;
|
|
179
255
|
}
|
|
@@ -182,10 +258,12 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
182
258
|
* Used by event handlers to get full shape without storing in feature properties.
|
|
183
259
|
*/
|
|
184
260
|
getShapeById(shapeId) {
|
|
185
|
-
|
|
261
|
+
const index = this.featuresCache?.shapeIdToIndex.get(shapeId);
|
|
262
|
+
return index !== void 0 ? this.props.data[index] : void 0;
|
|
186
263
|
}
|
|
187
264
|
/**
|
|
188
|
-
* Handle shape click
|
|
265
|
+
* Handle shape click — emits `shapes:selected` via bus and calls `onShapeClick` callback.
|
|
266
|
+
* @param info - deck.gl picking info from the clicked sublayer.
|
|
189
267
|
*/
|
|
190
268
|
handleShapeClick = (info) => {
|
|
191
269
|
const { onShapeClick, mapId } = this.props;
|
|
@@ -201,208 +279,192 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
201
279
|
if (onShapeClick) onShapeClick(shape);
|
|
202
280
|
};
|
|
203
281
|
/**
|
|
204
|
-
* Handle shape hover
|
|
282
|
+
* Handle shape hover — emits `shapes:hovered` via bus (deduplicated by shapeId) and calls `onShapeHover` callback.
|
|
283
|
+
* @param info - deck.gl picking info from the hovered sublayer.
|
|
205
284
|
*/
|
|
206
285
|
handleShapeHover = (info) => {
|
|
207
286
|
const { onShapeHover, mapId } = this.props;
|
|
208
|
-
const shapeId = info.object?.properties?.shapeId
|
|
209
|
-
const shape = shapeId ? this.getShapeById(shapeId)
|
|
287
|
+
const shapeId = info.object?.properties?.shapeId;
|
|
288
|
+
const shape = shapeId ? this.getShapeById(shapeId) : void 0;
|
|
210
289
|
if (shapeId !== this.state?.lastHoveredId) {
|
|
211
290
|
this.setState({ lastHoveredId: shapeId });
|
|
212
291
|
shapeBus.emit(ShapeEvents.hovered, {
|
|
213
|
-
shapeId,
|
|
292
|
+
shapeId: shapeId ?? null,
|
|
214
293
|
mapId
|
|
215
294
|
});
|
|
216
295
|
}
|
|
217
296
|
if (onShapeHover) onShapeHover(shape);
|
|
218
297
|
};
|
|
219
298
|
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
299
|
+
* Get or compute elevation-derived data (feature classification + curtain features).
|
|
300
|
+
* Cached on features identity and applyBaseOpacity to avoid per-frame recomputation.
|
|
301
|
+
*/
|
|
302
|
+
getElevationData(features, applyBaseOpacity) {
|
|
303
|
+
if (this.elevationCache !== null && this.elevationCache.features === features && this.elevationCache.applyBaseOpacity === applyBaseOpacity) return this.elevationCache;
|
|
304
|
+
const classification = classifyElevatedFeatures(features, getFeatureElevation);
|
|
305
|
+
const curtainFeatures = createCurtainPolygonFeatures(classification.lines, applyBaseOpacity);
|
|
306
|
+
this.elevationCache = {
|
|
307
|
+
features,
|
|
308
|
+
applyBaseOpacity,
|
|
309
|
+
classification,
|
|
310
|
+
curtainFeatures
|
|
311
|
+
};
|
|
312
|
+
return {
|
|
313
|
+
classification,
|
|
314
|
+
curtainFeatures
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Render highlight sublayer (underneath main layer).
|
|
319
|
+
* Point geometries skip this layer — they use coffin corner brackets
|
|
320
|
+
* via CoffinCornerExtension on the main layer's icon/scatterplot sublayer instead.
|
|
222
321
|
*/
|
|
223
322
|
renderHighlightLayer(features) {
|
|
224
|
-
const { selectedShapeId, showHighlight
|
|
225
|
-
if (!selectedShapeId || showHighlight === false) return
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
if (selectedFeature
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
323
|
+
const { selectedShapeId, showHighlight } = this.props;
|
|
324
|
+
if (!selectedShapeId || showHighlight === false) return [];
|
|
325
|
+
const featureIndex = this.featuresCache?.shapeIdToIndex.get(selectedShapeId);
|
|
326
|
+
const selectedFeature = featureIndex !== void 0 ? features[featureIndex] : void 0;
|
|
327
|
+
if (!selectedFeature) return [];
|
|
328
|
+
if (isPointType(selectedFeature.geometry)) return [];
|
|
329
|
+
const highlightFeature = flattenFeatureTo2D(selectedFeature);
|
|
330
|
+
const lineColor = this.resolvedHighlight;
|
|
331
|
+
return [new GeoJsonLayer({
|
|
232
332
|
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY_HIGHLIGHT}`,
|
|
233
|
-
data: [
|
|
234
|
-
filled:
|
|
333
|
+
data: [highlightFeature],
|
|
334
|
+
filled: false,
|
|
235
335
|
stroked: true,
|
|
236
336
|
lineWidthUnits: "pixels",
|
|
237
337
|
lineWidthMinPixels: MAP_INTERACTION.LINE_WIDTH_MIN_PIXELS,
|
|
238
|
-
|
|
239
|
-
0,
|
|
240
|
-
0,
|
|
241
|
-
0,
|
|
242
|
-
0
|
|
243
|
-
],
|
|
244
|
-
getLineColor: () => highlightColor || getHighlightColor(),
|
|
338
|
+
getLineColor: lineColor,
|
|
245
339
|
getLineWidth: getHighlightLineWidth,
|
|
246
340
|
pickable: false,
|
|
247
341
|
updateTriggers: {
|
|
248
|
-
getLineColor: [highlightColor],
|
|
342
|
+
getLineColor: [this.props.highlightColor],
|
|
249
343
|
getLineWidth: [selectedShapeId, features]
|
|
250
344
|
}
|
|
251
|
-
});
|
|
345
|
+
})];
|
|
252
346
|
}
|
|
253
347
|
/**
|
|
254
|
-
* Render
|
|
255
|
-
*
|
|
348
|
+
* Render selection overlay layer for polygon shapes.
|
|
349
|
+
* Mirrors renderHoverLayer but triggers on selectedShapeId instead of hover.
|
|
350
|
+
* When a shape is both selected and hovered, both layers stack for a brighter combined effect.
|
|
256
351
|
*/
|
|
257
|
-
|
|
258
|
-
const { selectedShapeId } = this.props;
|
|
259
|
-
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const iconMapping = firstPointIcon?.mapping;
|
|
274
|
-
if (!(iconAtlas && iconMapping)) {
|
|
275
|
-
logger.warn("Point shape has icon style but missing iconAtlas or iconMapping - coffin corners will not render");
|
|
276
|
-
return null;
|
|
277
|
-
}
|
|
278
|
-
const extendedMapping = {
|
|
279
|
-
...iconMapping,
|
|
280
|
-
[COFFIN_CORNERS.HOVER_ICON]: {
|
|
281
|
-
x: 0,
|
|
282
|
-
y: 0,
|
|
283
|
-
width: 76,
|
|
284
|
-
height: 76,
|
|
285
|
-
mask: false
|
|
286
|
-
},
|
|
287
|
-
[COFFIN_CORNERS.SELECTED_ICON]: {
|
|
288
|
-
x: 76,
|
|
289
|
-
y: 0,
|
|
290
|
-
width: 76,
|
|
291
|
-
height: 76,
|
|
292
|
-
mask: false
|
|
293
|
-
},
|
|
294
|
-
[COFFIN_CORNERS.SELECTED_HOVER_ICON]: {
|
|
295
|
-
x: 152,
|
|
296
|
-
y: 0,
|
|
297
|
-
width: 76,
|
|
298
|
-
height: 76,
|
|
299
|
-
mask: false
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
return new IconLayer({
|
|
303
|
-
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}-coffin-corners`,
|
|
304
|
-
data: pointFeatures,
|
|
305
|
-
iconAtlas,
|
|
306
|
-
iconMapping: extendedMapping,
|
|
307
|
-
getIcon: (d) => {
|
|
308
|
-
const shapeId = d.properties?.shapeId;
|
|
309
|
-
const isSelected = shapeId === selectedShapeId;
|
|
310
|
-
const featureIndex = shapeId ? shapeIdToIndex.get(shapeId) : void 0;
|
|
311
|
-
if (isSelected && hoverIndex !== void 0 && featureIndex === hoverIndex) return COFFIN_CORNERS.SELECTED_HOVER_ICON;
|
|
312
|
-
if (isSelected) return COFFIN_CORNERS.SELECTED_ICON;
|
|
313
|
-
return COFFIN_CORNERS.HOVER_ICON;
|
|
314
|
-
},
|
|
315
|
-
getSize: COFFIN_CORNERS.SIZE,
|
|
316
|
-
getPosition: (d) => {
|
|
317
|
-
return d.geometry.type === "Point" ? d.geometry.coordinates : [0, 0];
|
|
318
|
-
},
|
|
319
|
-
getPixelOffset: (d) => {
|
|
320
|
-
return [-1, -(d.properties?.styleProperties?.icon?.size ?? MAP_INTERACTION.ICON_SIZE) / 2];
|
|
321
|
-
},
|
|
322
|
-
billboard: false,
|
|
352
|
+
renderSelectLayer(features) {
|
|
353
|
+
const { selectedShapeId, enableElevation } = this.props;
|
|
354
|
+
if (!selectedShapeId) return [];
|
|
355
|
+
const featureIndex = this.featuresCache?.shapeIdToIndex.get(selectedShapeId);
|
|
356
|
+
const selectedFeature = featureIndex !== void 0 ? features[featureIndex] : void 0;
|
|
357
|
+
if (!selectedFeature) return [];
|
|
358
|
+
if (!isPolygonGeometry(selectedFeature.geometry)) return [];
|
|
359
|
+
return [new GeoJsonLayer({
|
|
360
|
+
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY_SELECTION}`,
|
|
361
|
+
data: [selectedFeature],
|
|
362
|
+
filled: true,
|
|
363
|
+
stroked: false,
|
|
364
|
+
getFillColor: getOverlayFillColor,
|
|
365
|
+
extruded: enableElevation,
|
|
366
|
+
getElevation: getFeatureElevation,
|
|
367
|
+
material: MATERIAL_SETTINGS.HOVER_OR_SELECT,
|
|
323
368
|
pickable: false,
|
|
324
369
|
updateTriggers: {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
selectedShapeId,
|
|
329
|
-
this.state?.hoverIndex
|
|
330
|
-
]
|
|
370
|
+
data: [features, selectedShapeId],
|
|
371
|
+
getFillColor: [features],
|
|
372
|
+
getElevation: [features]
|
|
331
373
|
}
|
|
332
|
-
});
|
|
374
|
+
})];
|
|
333
375
|
}
|
|
334
376
|
/**
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
377
|
+
* Render hover layer for all polygon shapes (2D and 3D).
|
|
378
|
+
* Overlays the shape's base fill with brighter material lighting.
|
|
379
|
+
* Stacks with other interaction layers (e.g. selection highlight underneath).
|
|
338
380
|
*/
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
381
|
+
renderHoverLayer(features) {
|
|
382
|
+
const { enableElevation, selectedShapeId } = this.props;
|
|
383
|
+
const hoverIndex = this.state?.hoverIndex;
|
|
384
|
+
if (hoverIndex === void 0) return [];
|
|
385
|
+
const hoveredFeature = features[hoverIndex];
|
|
386
|
+
if (!hoveredFeature) return [];
|
|
387
|
+
if (!isPolygonGeometry(hoveredFeature.geometry)) return [];
|
|
388
|
+
const material = hoveredFeature.properties?.shapeId === selectedShapeId ? MATERIAL_SETTINGS.HOVER_AND_SELECT : MATERIAL_SETTINGS.HOVER_OR_SELECT;
|
|
389
|
+
return [new GeoJsonLayer({
|
|
390
|
+
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}-hover`,
|
|
391
|
+
data: [hoveredFeature],
|
|
392
|
+
filled: true,
|
|
393
|
+
stroked: false,
|
|
394
|
+
getFillColor: getOverlayFillColor,
|
|
395
|
+
extruded: enableElevation,
|
|
396
|
+
getElevation: getFeatureElevation,
|
|
397
|
+
material,
|
|
398
|
+
pickable: false,
|
|
399
|
+
updateTriggers: {
|
|
400
|
+
data: [features, hoverIndex],
|
|
401
|
+
getFillColor: [features],
|
|
402
|
+
getElevation: [features],
|
|
403
|
+
material: [selectedShapeId, hoverIndex]
|
|
404
|
+
}
|
|
405
|
+
})];
|
|
349
406
|
}
|
|
350
407
|
/**
|
|
351
408
|
* Render main shapes layer
|
|
352
409
|
*/
|
|
353
410
|
renderMainLayer(features) {
|
|
354
411
|
const { pickable, applyBaseOpacity, selectedShapeId } = this.props;
|
|
355
|
-
const { hasIcons, atlas: iconAtlas, mapping: iconMapping } =
|
|
412
|
+
const { hasIcons, atlas: iconAtlas, mapping: iconMapping } = getIconConfig(features);
|
|
413
|
+
const hoveredFeature = this.state?.hoverIndex !== void 0 ? features[this.state.hoverIndex] : void 0;
|
|
414
|
+
const hoveredEntityId = hoveredFeature?.geometry.type === "Point" ? hoveredFeature.properties?.shapeId : void 0;
|
|
356
415
|
return new GeoJsonLayer({
|
|
357
416
|
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}`,
|
|
358
417
|
data: features,
|
|
359
418
|
filled: true,
|
|
360
419
|
stroked: true,
|
|
361
420
|
getFillColor: (d) => getFillColor(d, applyBaseOpacity),
|
|
362
|
-
getLineColor,
|
|
421
|
+
getLineColor: (d, info) => {
|
|
422
|
+
const baseColor = this.featuresCache?.normalizedLineColors[info?.index ?? -1] ?? getLineColor(d);
|
|
423
|
+
const isHovered = info?.index === this.state?.hoverIndex;
|
|
424
|
+
const isSelected = d.properties?.shapeId === selectedShapeId;
|
|
425
|
+
if (isHovered && isSelected) return brightenColor(baseColor, BRIGHTNESS_FACTOR.HOVER_AND_SELECT);
|
|
426
|
+
if (isHovered || isSelected) return brightenColor(baseColor, BRIGHTNESS_FACTOR.HOVER_OR_SELECT);
|
|
427
|
+
return baseColor;
|
|
428
|
+
},
|
|
363
429
|
getLineWidth: (d, info) => {
|
|
430
|
+
if (this.props.enableElevation && isLineGeometry(d.geometry) && getFeatureElevation(d) > 0) return d.properties?.styleProperties?.lineWidth ?? 2;
|
|
364
431
|
return getHoverLineWidth(d, info?.index === this.state?.hoverIndex);
|
|
365
432
|
},
|
|
366
433
|
lineWidthUnits: "pixels",
|
|
367
434
|
lineWidthMinPixels: MAP_INTERACTION.LINE_WIDTH_MIN_PIXELS,
|
|
368
435
|
lineWidthMaxPixels: 20,
|
|
436
|
+
extruded: this.props.enableElevation ?? false,
|
|
437
|
+
getElevation: getFeatureElevation,
|
|
438
|
+
...this.props.enableElevation ? { material: MATERIAL_SETTINGS.NORMAL } : {},
|
|
369
439
|
pointType: hasIcons ? "icon" : "circle",
|
|
370
440
|
getPointRadius: (d) => {
|
|
371
441
|
return d.properties?.styleProperties?.icon?.size ?? 2;
|
|
372
442
|
},
|
|
373
443
|
pointRadiusUnits: "pixels",
|
|
374
|
-
...hasIcons
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
getIconColor: getLineColor,
|
|
382
|
-
getIconPixelOffset: (d) => {
|
|
383
|
-
return [-1, -(d.properties?.styleProperties?.icon?.size ?? MAP_INTERACTION.ICON_SIZE) / 2];
|
|
384
|
-
},
|
|
385
|
-
iconBillboard: false
|
|
386
|
-
} : {},
|
|
387
|
-
extensions: [new PathStyleExtension({ dash: true })],
|
|
388
|
-
getDashArray: (d) => {
|
|
389
|
-
if (d.properties?.shapeId === selectedShapeId) return DASH_ARRAYS.dotted;
|
|
390
|
-
return getDashArray(d);
|
|
391
|
-
},
|
|
444
|
+
...getIconLayerProps(hasIcons, iconAtlas, iconMapping),
|
|
445
|
+
selectedEntityId: selectedShapeId,
|
|
446
|
+
hoveredEntityId,
|
|
447
|
+
getEntityId: (d) => d.properties?.shapeId,
|
|
448
|
+
selectedCoffinCornerColor: this.coffinCornerColor,
|
|
449
|
+
extensions: DISPLAY_EXTENSIONS,
|
|
450
|
+
getDashArray,
|
|
392
451
|
pickable,
|
|
393
452
|
autoHighlight: false,
|
|
453
|
+
...this.props.enableElevation ? { parameters: {
|
|
454
|
+
depthTest: true,
|
|
455
|
+
depthCompare: "less-equal"
|
|
456
|
+
} } : {},
|
|
394
457
|
updateTriggers: {
|
|
395
458
|
getFillColor: [features, applyBaseOpacity],
|
|
396
|
-
getLineColor: [
|
|
459
|
+
getLineColor: [
|
|
460
|
+
features,
|
|
461
|
+
this.state?.hoverIndex,
|
|
462
|
+
selectedShapeId
|
|
463
|
+
],
|
|
397
464
|
getLineWidth: [features, this.state?.hoverIndex],
|
|
398
|
-
getDashArray: [features
|
|
465
|
+
getDashArray: [features],
|
|
399
466
|
getPointRadius: [features],
|
|
400
|
-
...hasIcons
|
|
401
|
-
getIcon: [features],
|
|
402
|
-
getIconSize: [features],
|
|
403
|
-
getIconColor: [features],
|
|
404
|
-
getIconPixelOffset: [features]
|
|
405
|
-
} : {}
|
|
467
|
+
...getIconUpdateTriggers(hasIcons, features)
|
|
406
468
|
}
|
|
407
469
|
});
|
|
408
470
|
}
|
|
@@ -415,32 +477,216 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
415
477
|
*/
|
|
416
478
|
renderLabelsLayer() {
|
|
417
479
|
const { showLabels, data, labelOptions } = this.props;
|
|
418
|
-
if (showLabels === "never") return
|
|
480
|
+
if (showLabels === "never") return [];
|
|
419
481
|
let labelData = data;
|
|
420
482
|
if (showLabels === "hover") {
|
|
421
483
|
const hoverIndex = this.state?.hoverIndex;
|
|
422
|
-
if (hoverIndex === void 0) return
|
|
484
|
+
if (hoverIndex === void 0) return [];
|
|
423
485
|
const hoveredShape = data[hoverIndex];
|
|
424
486
|
labelData = hoveredShape ? [hoveredShape] : [];
|
|
425
487
|
}
|
|
426
|
-
if (labelData.length === 0) return
|
|
427
|
-
return createShapeLabelLayer({
|
|
488
|
+
if (labelData.length === 0) return [];
|
|
489
|
+
return [createShapeLabelLayer({
|
|
428
490
|
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY_LABELS}`,
|
|
429
491
|
data: labelData,
|
|
430
492
|
labelOptions
|
|
493
|
+
})];
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Render radius label layer for hovered circle shapes.
|
|
497
|
+
* Shows the circle's radius value converted to the configured display unit.
|
|
498
|
+
*
|
|
499
|
+
* Positioning relative to the shape's label:
|
|
500
|
+
* - When showLabels is 'always' or 'hover': appears below the label
|
|
501
|
+
* - When showLabels is 'never': appears in the label's position
|
|
502
|
+
*/
|
|
503
|
+
renderRadiusLabelLayer() {
|
|
504
|
+
const { data, unit, showLabels, labelOptions } = this.props;
|
|
505
|
+
const hoverIndex = this.state?.hoverIndex;
|
|
506
|
+
const hoveredShape = hoverIndex !== void 0 ? data[hoverIndex] : void 0;
|
|
507
|
+
const radiusText = hoveredShape && isCircleShape(hoveredShape) ? getRadiusLabelText(hoveredShape, unit) : void 0;
|
|
508
|
+
const labelPosition = radiusText && hoveredShape ? getLabelPosition2d(hoveredShape, labelOptions) : void 0;
|
|
509
|
+
if (!labelPosition) return [];
|
|
510
|
+
const pixelOffset = showLabels !== "never" ? [labelPosition.pixelOffset[0], labelPosition.pixelOffset[1] + DEFAULT_TEXT_SIZE + 2] : labelPosition.pixelOffset;
|
|
511
|
+
return [new TextLayer({
|
|
512
|
+
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}-radius-label`,
|
|
513
|
+
data: [{
|
|
514
|
+
text: radiusText,
|
|
515
|
+
position: labelPosition.coordinates
|
|
516
|
+
}],
|
|
517
|
+
getText: (d) => d.text,
|
|
518
|
+
getPosition: (d) => d.position,
|
|
519
|
+
getPixelOffset: pixelOffset,
|
|
520
|
+
getTextAnchor: labelPosition.textAnchor,
|
|
521
|
+
getAlignmentBaseline: labelPosition.alignmentBaseline,
|
|
522
|
+
...DEFAULT_TEXT_STYLE,
|
|
523
|
+
getAngle: 0,
|
|
524
|
+
background: false,
|
|
525
|
+
fontFamily: "Roboto MonoVariable, monospace",
|
|
526
|
+
pickable: false,
|
|
527
|
+
updateTriggers: {
|
|
528
|
+
getText: [hoverIndex, unit],
|
|
529
|
+
getPosition: [hoverIndex, labelOptions],
|
|
530
|
+
getPixelOffset: [
|
|
531
|
+
hoverIndex,
|
|
532
|
+
labelOptions,
|
|
533
|
+
showLabels
|
|
534
|
+
],
|
|
535
|
+
getTextAnchor: [hoverIndex, labelOptions],
|
|
536
|
+
getAlignmentBaseline: [hoverIndex, labelOptions]
|
|
537
|
+
}
|
|
538
|
+
})];
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Render vertical elevation indicator lines for non-polygon shapes.
|
|
542
|
+
* Creates vertical "strut" lines from ground level to elevated features.
|
|
543
|
+
* For LineStrings, creates a "curtain" effect with vertical lines at each coordinate.
|
|
544
|
+
* Polygons use wireframe extrusion instead.
|
|
545
|
+
*/
|
|
546
|
+
renderElevationIndicatorLayer(features, elevatedNonPolygons) {
|
|
547
|
+
if (elevatedNonPolygons.length === 0) return [];
|
|
548
|
+
const { selectedShapeId } = this.props;
|
|
549
|
+
const hoverIndex = this.state?.hoverIndex;
|
|
550
|
+
const cache = this.indicatorCache;
|
|
551
|
+
let lineData;
|
|
552
|
+
if (cache !== null && cache.features === features && cache.selectedShapeId === selectedShapeId && cache.hoverIndex === hoverIndex) lineData = cache.lineData;
|
|
553
|
+
else {
|
|
554
|
+
lineData = buildIndicatorLineData(elevatedNonPolygons, features, selectedShapeId, hoverIndex);
|
|
555
|
+
this.indicatorCache = {
|
|
556
|
+
features,
|
|
557
|
+
selectedShapeId,
|
|
558
|
+
hoverIndex,
|
|
559
|
+
lineData
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
if (lineData.length === 0) return [];
|
|
563
|
+
return [new LineLayer({
|
|
564
|
+
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}-elevation-indicators`,
|
|
565
|
+
data: lineData,
|
|
566
|
+
getSourcePosition: (d) => d.source,
|
|
567
|
+
getTargetPosition: (d) => d.target,
|
|
568
|
+
getColor: (d) => d.color,
|
|
569
|
+
getWidth: 2,
|
|
570
|
+
widthUnits: "pixels",
|
|
571
|
+
pickable: false,
|
|
572
|
+
updateTriggers: {
|
|
573
|
+
data: [
|
|
574
|
+
features,
|
|
575
|
+
selectedShapeId,
|
|
576
|
+
hoverIndex
|
|
577
|
+
],
|
|
578
|
+
getColor: [
|
|
579
|
+
features,
|
|
580
|
+
selectedShapeId,
|
|
581
|
+
hoverIndex
|
|
582
|
+
]
|
|
583
|
+
}
|
|
584
|
+
})];
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Create a single curtain GeoJsonLayer with shared configuration.
|
|
588
|
+
*/
|
|
589
|
+
createCurtainGeoJsonLayer(idSuffix, data, getFillColor$1, dataTriggers, fillColorTriggers) {
|
|
590
|
+
return new GeoJsonLayer({
|
|
591
|
+
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}-${idSuffix}`,
|
|
592
|
+
data,
|
|
593
|
+
filled: true,
|
|
594
|
+
stroked: false,
|
|
595
|
+
_full3d: true,
|
|
596
|
+
getFillColor: getFillColor$1,
|
|
597
|
+
pickable: this.props.pickable ?? true,
|
|
598
|
+
parameters: {
|
|
599
|
+
depthTest: true,
|
|
600
|
+
depthCompare: "less-equal"
|
|
601
|
+
},
|
|
602
|
+
updateTriggers: {
|
|
603
|
+
data: dataTriggers,
|
|
604
|
+
getFillColor: fillColorTriggers
|
|
605
|
+
}
|
|
431
606
|
});
|
|
432
607
|
}
|
|
433
608
|
/**
|
|
434
|
-
* Render
|
|
609
|
+
* Render curtain layers for elevated LineStrings.
|
|
610
|
+
* Creates three separate layers for main, hovered, and selected states.
|
|
611
|
+
*/
|
|
612
|
+
renderCurtainLayers(features, allCurtainFeatures) {
|
|
613
|
+
const layers = [];
|
|
614
|
+
const { selectedShapeId } = this.props;
|
|
615
|
+
const hoverIndex = this.state?.hoverIndex;
|
|
616
|
+
const hoveredShapeId = hoverIndex !== void 0 && features[hoverIndex] ? features[hoverIndex].properties?.shapeId : void 0;
|
|
617
|
+
const { main, hovered, selected } = partitionCurtains(allCurtainFeatures, hoveredShapeId, selectedShapeId);
|
|
618
|
+
const isSelectedHovered = selectedShapeId === hoveredShapeId;
|
|
619
|
+
const dataTriggers = [
|
|
620
|
+
features,
|
|
621
|
+
hoveredShapeId,
|
|
622
|
+
selectedShapeId
|
|
623
|
+
];
|
|
624
|
+
if (main.length > 0) layers.push(this.createCurtainGeoJsonLayer("elevation-curtain", main, (d) => d.properties.fillColor, dataTriggers, [features, this.props.applyBaseOpacity]));
|
|
625
|
+
if (hovered.length > 0) {
|
|
626
|
+
const hoveredColor = applyOverlayOpacity(brightenColor(hovered[0].properties.lineColor, BRIGHTNESS_FACTOR.HOVER_OR_SELECT));
|
|
627
|
+
layers.push(this.createCurtainGeoJsonLayer("elevation-curtain-hover", hovered, () => hoveredColor, dataTriggers, [features]));
|
|
628
|
+
}
|
|
629
|
+
if (selected.length > 0) {
|
|
630
|
+
const factor = isSelectedHovered ? BRIGHTNESS_FACTOR.HOVER_AND_SELECT : BRIGHTNESS_FACTOR.HOVER_OR_SELECT;
|
|
631
|
+
const selectedColor = applyOverlayOpacity(brightenColor(selected[0].properties.lineColor, factor));
|
|
632
|
+
layers.push(this.createCurtainGeoJsonLayer("elevation-curtain-selected", selected, () => selectedColor, dataTriggers, [features, isSelectedHovered]));
|
|
633
|
+
}
|
|
634
|
+
return layers;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Render elevation visualization layers (curtains for lines, wireframes for polygons).
|
|
638
|
+
*/
|
|
639
|
+
renderElevationVisualizationLayer(features, allCurtainFeatures, elevatedPolygons) {
|
|
640
|
+
const layers = [];
|
|
641
|
+
if (allCurtainFeatures.length > 0) layers.push(...this.renderCurtainLayers(features, allCurtainFeatures));
|
|
642
|
+
if (elevatedPolygons.length > 0) {
|
|
643
|
+
const { applyBaseOpacity } = this.props;
|
|
644
|
+
layers.push(new GeoJsonLayer({
|
|
645
|
+
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY}-elevation-wireframe`,
|
|
646
|
+
data: elevatedPolygons,
|
|
647
|
+
filled: false,
|
|
648
|
+
stroked: false,
|
|
649
|
+
extruded: true,
|
|
650
|
+
wireframe: true,
|
|
651
|
+
getElevation: getFeatureElevation,
|
|
652
|
+
getFillColor: (d) => getFillColor(d, applyBaseOpacity),
|
|
653
|
+
getLineColor,
|
|
654
|
+
pickable: false,
|
|
655
|
+
parameters: {
|
|
656
|
+
depthTest: true,
|
|
657
|
+
depthCompare: "less-equal"
|
|
658
|
+
},
|
|
659
|
+
updateTriggers: {
|
|
660
|
+
getElevation: [features],
|
|
661
|
+
getFillColor: [features, applyBaseOpacity],
|
|
662
|
+
getLineColor: [features]
|
|
663
|
+
}
|
|
664
|
+
}));
|
|
665
|
+
}
|
|
666
|
+
return layers;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Render all sublayers.
|
|
670
|
+
* @returns Ordered array of sublayers (highlight, select, hover, elevation, main, labels) from bottom to top.
|
|
435
671
|
*/
|
|
436
672
|
renderLayers() {
|
|
437
673
|
const features = this.getFeaturesWithId();
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this.
|
|
441
|
-
this.
|
|
442
|
-
this.
|
|
443
|
-
]
|
|
674
|
+
const enableElevation = this.props.enableElevation ?? false;
|
|
675
|
+
const layers = [
|
|
676
|
+
...this.renderHighlightLayer(features),
|
|
677
|
+
...this.renderSelectLayer(features),
|
|
678
|
+
...this.renderHoverLayer(features)
|
|
679
|
+
];
|
|
680
|
+
if (enableElevation) {
|
|
681
|
+
const { classification, curtainFeatures } = this.getElevationData(features, this.props.applyBaseOpacity);
|
|
682
|
+
const { polygons, nonPolygons } = classification;
|
|
683
|
+
layers.push(...this.renderElevationVisualizationLayer(features, curtainFeatures, polygons));
|
|
684
|
+
layers.push(...this.renderElevationIndicatorLayer(features, nonPolygons));
|
|
685
|
+
}
|
|
686
|
+
layers.push(this.renderMainLayer(features));
|
|
687
|
+
layers.push(...this.renderLabelsLayer());
|
|
688
|
+
layers.push(...this.renderRadiusLabelLayer());
|
|
689
|
+
return layers;
|
|
444
690
|
}
|
|
445
691
|
};
|
|
446
692
|
|