@sakuzu/maplibre-gl-draw 1.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 +43 -0
- package/LICENSE +661 -0
- package/README.ja.md +248 -0
- package/README.md +255 -0
- package/THIRD_PARTY_NOTICES.md +275 -0
- package/dist/api/api.d.ts +1259 -0
- package/dist/api/api.js +86 -0
- package/dist/api/context.d.ts +173 -0
- package/dist/api/context.js +193 -0
- package/dist/api/display-api.d.ts +1 -0
- package/dist/api/display-api.js +23 -0
- package/dist/api/event-api.d.ts +13 -0
- package/dist/api/event-api.js +17 -0
- package/dist/api/extension-api.d.ts +46 -0
- package/dist/api/extension-api.js +85 -0
- package/dist/api/feature-api.d.ts +11 -0
- package/dist/api/feature-api.js +101 -0
- package/dist/api/geometry/apply.d.ts +51 -0
- package/dist/api/geometry/apply.js +114 -0
- package/dist/api/geometry/boolean.d.ts +28 -0
- package/dist/api/geometry/boolean.js +65 -0
- package/dist/api/geometry/buffer.d.ts +11 -0
- package/dist/api/geometry/buffer.js +105 -0
- package/dist/api/geometry/split.d.ts +16 -0
- package/dist/api/geometry/split.js +75 -0
- package/dist/api/geometry/targets.d.ts +76 -0
- package/dist/api/geometry/targets.js +158 -0
- package/dist/api/geometry/types.d.ts +31 -0
- package/dist/api/geometry/types.js +3 -0
- package/dist/api/geometry-operations.d.ts +162 -0
- package/dist/api/geometry-operations.js +94 -0
- package/dist/api/group-api.d.ts +10 -0
- package/dist/api/group-api.js +78 -0
- package/dist/api/import-export/constants.d.ts +29 -0
- package/dist/api/import-export/constants.js +40 -0
- package/dist/api/import-export/embedded-file.d.ts +13 -0
- package/dist/api/import-export/embedded-file.js +31 -0
- package/dist/api/import-export/file-name.d.ts +10 -0
- package/dist/api/import-export/file-name.js +20 -0
- package/dist/api/import-export/format-detection.d.ts +12 -0
- package/dist/api/import-export/format-detection.js +29 -0
- package/dist/api/import-export/geojson-export.d.ts +19 -0
- package/dist/api/import-export/geojson-export.js +262 -0
- package/dist/api/import-export/geojson-import.d.ts +34 -0
- package/dist/api/import-export/geojson-import.js +538 -0
- package/dist/api/import-export/geometry-validation.d.ts +20 -0
- package/dist/api/import-export/geometry-validation.js +107 -0
- package/dist/api/import-export/image-import.d.ts +12 -0
- package/dist/api/import-export/image-import.js +53 -0
- package/dist/api/import-export/index.d.ts +9 -0
- package/dist/api/import-export/index.js +107 -0
- package/dist/api/import-export/native-format.d.ts +15 -0
- package/dist/api/import-export/native-format.js +126 -0
- package/dist/api/import-export/native-validation.d.ts +28 -0
- package/dist/api/import-export/native-validation.js +212 -0
- package/dist/api/import-export/own-property.d.ts +10 -0
- package/dist/api/import-export/own-property.js +19 -0
- package/dist/api/import-export/style-validation.d.ts +27 -0
- package/dist/api/import-export/style-validation.js +49 -0
- package/dist/api/import-export/types.d.ts +26 -0
- package/dist/api/import-export/types.js +3 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.js +3 -0
- package/dist/api/input-api.d.ts +158 -0
- package/dist/api/input-api.js +144 -0
- package/dist/api/instance-api.d.ts +38 -0
- package/dist/api/instance-api.js +136 -0
- package/dist/api/layer-api.d.ts +12 -0
- package/dist/api/layer-api.js +62 -0
- package/dist/api/selection-api.d.ts +7 -0
- package/dist/api/selection-api.js +78 -0
- package/dist/api/snapping-api.d.ts +125 -0
- package/dist/api/snapping-api.js +50 -0
- package/dist/api/topology-api.d.ts +30 -0
- package/dist/api/topology-api.js +16 -0
- package/dist/api/tracing-api.d.ts +31 -0
- package/dist/api/tracing-api.js +16 -0
- package/dist/dispatcher/hit-test/box-strategies.d.ts +19 -0
- package/dist/dispatcher/hit-test/box-strategies.js +275 -0
- package/dist/dispatcher/hit-test/box-strategy.d.ts +59 -0
- package/dist/dispatcher/hit-test/box-strategy.js +37 -0
- package/dist/dispatcher/hit-test/globe-shape.d.ts +46 -0
- package/dist/dispatcher/hit-test/globe-shape.js +70 -0
- package/dist/dispatcher/hit-test/index.d.ts +14 -0
- package/dist/dispatcher/hit-test/index.js +9 -0
- package/dist/dispatcher/hit-test/local-frame.d.ts +77 -0
- package/dist/dispatcher/hit-test/local-frame.js +112 -0
- package/dist/dispatcher/hit-test/segment-grid.d.ts +32 -0
- package/dist/dispatcher/hit-test/segment-grid.js +79 -0
- package/dist/dispatcher/hit-test/service.d.ts +120 -0
- package/dist/dispatcher/hit-test/service.js +333 -0
- package/dist/dispatcher/hit-test/strategies/base.d.ts +136 -0
- package/dist/dispatcher/hit-test/strategies/base.js +66 -0
- package/dist/dispatcher/hit-test/strategies/circle.d.ts +10 -0
- package/dist/dispatcher/hit-test/strategies/circle.js +56 -0
- package/dist/dispatcher/hit-test/strategies/image.d.ts +22 -0
- package/dist/dispatcher/hit-test/strategies/image.js +115 -0
- package/dist/dispatcher/hit-test/strategies/index.d.ts +11 -0
- package/dist/dispatcher/hit-test/strategies/index.js +10 -0
- package/dist/dispatcher/hit-test/strategies/line.d.ts +17 -0
- package/dist/dispatcher/hit-test/strategies/line.js +30 -0
- package/dist/dispatcher/hit-test/strategies/multi.d.ts +44 -0
- package/dist/dispatcher/hit-test/strategies/multi.js +141 -0
- package/dist/dispatcher/hit-test/strategies/point.d.ts +20 -0
- package/dist/dispatcher/hit-test/strategies/point.js +29 -0
- package/dist/dispatcher/hit-test/strategies/polygon.d.ts +52 -0
- package/dist/dispatcher/hit-test/strategies/polygon.js +138 -0
- package/dist/dispatcher/hit-test/topmost.d.ts +48 -0
- package/dist/dispatcher/hit-test/topmost.js +157 -0
- package/dist/dispatcher/hit-test/visibility-lookup.d.ts +23 -0
- package/dist/dispatcher/hit-test/visibility-lookup.js +40 -0
- package/dist/dispatcher/index.d.ts +15 -0
- package/dist/dispatcher/index.js +3 -0
- package/dist/dispatcher/input-router.d.ts +1 -0
- package/dist/dispatcher/input-router.js +288 -0
- package/dist/dispatcher/normalizer.d.ts +1 -0
- package/dist/dispatcher/normalizer.js +513 -0
- package/dist/dispatcher/types.d.ts +144 -0
- package/dist/dispatcher/types.js +15 -0
- package/dist/display/chunk-set.d.ts +24 -0
- package/dist/display/chunk-set.js +533 -0
- package/dist/display/chunk.d.ts +1 -0
- package/dist/display/chunk.js +104 -0
- package/dist/display/columnar/index.d.ts +12 -0
- package/dist/display/columnar/index.js +13 -0
- package/dist/display/columnar/prepare.d.ts +42 -0
- package/dist/display/columnar/prepare.js +116 -0
- package/dist/display/columnar/source.d.ts +1 -0
- package/dist/display/columnar/source.js +531 -0
- package/dist/display/columnar/table.d.ts +1 -0
- package/dist/display/columnar/table.js +471 -0
- package/dist/display/columnar/types.d.ts +223 -0
- package/dist/display/columnar/types.js +3 -0
- package/dist/display/dataset.d.ts +2 -0
- package/dist/display/dataset.js +891 -0
- package/dist/display/index.d.ts +13 -0
- package/dist/display/index.js +3 -0
- package/dist/display/interaction.d.ts +1 -0
- package/dist/display/interaction.js +90 -0
- package/dist/display/manager.d.ts +1 -0
- package/dist/display/manager.js +440 -0
- package/dist/display/packed-rtree.d.ts +1 -0
- package/dist/display/packed-rtree.js +244 -0
- package/dist/display/partition.d.ts +1 -0
- package/dist/display/partition.js +226 -0
- package/dist/display/provider.d.ts +1 -0
- package/dist/display/provider.js +342 -0
- package/dist/display/retained.d.ts +40 -0
- package/dist/display/retained.js +898 -0
- package/dist/display/selection.d.ts +13 -0
- package/dist/display/selection.js +226 -0
- package/dist/display/source.d.ts +1 -0
- package/dist/display/source.js +119 -0
- package/dist/display/spatial.d.ts +1 -0
- package/dist/display/spatial.js +71 -0
- package/dist/display/style.d.ts +1 -0
- package/dist/display/style.js +126 -0
- package/dist/display/thinning.d.ts +65 -0
- package/dist/display/thinning.js +910 -0
- package/dist/display/triangulation.d.ts +1 -0
- package/dist/display/triangulation.js +0 -0
- package/dist/display/types.d.ts +561 -0
- package/dist/display/types.js +43 -0
- package/dist/extension/feature-handler.d.ts +182 -0
- package/dist/extension/feature-handler.js +3 -0
- package/dist/extension/index.d.ts +9 -0
- package/dist/extension/index.js +3 -0
- package/dist/extension/renderers.d.ts +208 -0
- package/dist/extension/renderers.js +3 -0
- package/dist/geometry/angle.d.ts +47 -0
- package/dist/geometry/angle.js +44 -0
- package/dist/geometry/bbox.d.ts +48 -0
- package/dist/geometry/bbox.js +83 -0
- package/dist/geometry/boolean.d.ts +162 -0
- package/dist/geometry/boolean.js +331 -0
- package/dist/geometry/buffer.d.ts +72 -0
- package/dist/geometry/buffer.js +218 -0
- package/dist/geometry/circle.d.ts +55 -0
- package/dist/geometry/circle.js +107 -0
- package/dist/geometry/coords.d.ts +97 -0
- package/dist/geometry/coords.js +149 -0
- package/dist/geometry/distance.d.ts +79 -0
- package/dist/geometry/distance.js +111 -0
- package/dist/geometry/errors.d.ts +74 -0
- package/dist/geometry/errors.js +104 -0
- package/dist/geometry/index.d.ts +28 -0
- package/dist/geometry/index.js +38 -0
- package/dist/geometry/measure.d.ts +81 -0
- package/dist/geometry/measure.js +236 -0
- package/dist/geometry/predicates.d.ts +62 -0
- package/dist/geometry/predicates.js +132 -0
- package/dist/geometry/simplify.d.ts +74 -0
- package/dist/geometry/simplify.js +159 -0
- package/dist/geometry/split.d.ts +68 -0
- package/dist/geometry/split.js +430 -0
- package/dist/geometry/types.d.ts +95 -0
- package/dist/geometry/types.js +3 -0
- package/dist/geometry/units.d.ts +35 -0
- package/dist/geometry/units.js +41 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +20 -0
- package/dist/maplibre-gl-draw.d.ts +47 -0
- package/dist/maplibre-gl-draw.js +407 -0
- package/dist/messages.d.ts +64 -0
- package/dist/messages.js +36 -0
- package/dist/modes/cursor.d.ts +1 -0
- package/dist/modes/cursor.js +72 -0
- package/dist/modes/draw/circle.d.ts +1 -0
- package/dist/modes/draw/circle.js +222 -0
- package/dist/modes/draw/commit-layer.d.ts +26 -0
- package/dist/modes/draw/commit-layer.js +31 -0
- package/dist/modes/draw/freehand.d.ts +1 -0
- package/dist/modes/draw/freehand.js +264 -0
- package/dist/modes/draw/image.d.ts +1 -0
- package/dist/modes/draw/image.js +60 -0
- package/dist/modes/draw/index.d.ts +9 -0
- package/dist/modes/draw/index.js +11 -0
- package/dist/modes/draw/line.d.ts +1 -0
- package/dist/modes/draw/line.js +363 -0
- package/dist/modes/draw/point.d.ts +1 -0
- package/dist/modes/draw/point.js +87 -0
- package/dist/modes/draw/polygon.d.ts +1 -0
- package/dist/modes/draw/polygon.js +378 -0
- package/dist/modes/draw/trace-support.d.ts +79 -0
- package/dist/modes/draw/trace-support.js +161 -0
- package/dist/modes/handler.d.ts +285 -0
- package/dist/modes/handler.js +3 -0
- package/dist/modes/index.d.ts +7 -0
- package/dist/modes/index.js +3 -0
- package/dist/modes/manager.d.ts +15 -0
- package/dist/modes/manager.js +196 -0
- package/dist/modes/select/box-selection.d.ts +52 -0
- package/dist/modes/select/box-selection.js +140 -0
- package/dist/modes/select/click-handler.d.ts +32 -0
- package/dist/modes/select/click-handler.js +166 -0
- package/dist/modes/select/cursor-handler.d.ts +15 -0
- package/dist/modes/select/cursor-handler.js +59 -0
- package/dist/modes/select/drag/auxiliary.d.ts +26 -0
- package/dist/modes/select/drag/auxiliary.js +56 -0
- package/dist/modes/select/drag/intermediate-writes.d.ts +1 -0
- package/dist/modes/select/drag/intermediate-writes.js +171 -0
- package/dist/modes/select/drag/move.d.ts +24 -0
- package/dist/modes/select/drag/move.js +59 -0
- package/dist/modes/select/drag/operation.d.ts +30 -0
- package/dist/modes/select/drag/operation.js +18 -0
- package/dist/modes/select/drag/radius.d.ts +15 -0
- package/dist/modes/select/drag/radius.js +49 -0
- package/dist/modes/select/drag/transform.d.ts +17 -0
- package/dist/modes/select/drag/transform.js +155 -0
- package/dist/modes/select/drag/vertex.d.ts +17 -0
- package/dist/modes/select/drag/vertex.js +163 -0
- package/dist/modes/select/drag-handler.d.ts +1 -0
- package/dist/modes/select/drag-handler.js +254 -0
- package/dist/modes/select/hit-helpers.d.ts +40 -0
- package/dist/modes/select/hit-helpers.js +51 -0
- package/dist/modes/select/mode.d.ts +1 -0
- package/dist/modes/select/mode.js +397 -0
- package/dist/modes/select/shortcut-handler.d.ts +40 -0
- package/dist/modes/select/shortcut-handler.js +128 -0
- package/dist/operations/index.d.ts +9 -0
- package/dist/operations/index.js +3 -0
- package/dist/operations/layer-operations.d.ts +1 -0
- package/dist/operations/layer-operations.js +350 -0
- package/dist/operations/resize.d.ts +71 -0
- package/dist/operations/resize.js +252 -0
- package/dist/operations/rotate.d.ts +17 -0
- package/dist/operations/rotate.js +166 -0
- package/dist/operations/selection-operations.d.ts +20 -0
- package/dist/operations/selection-operations.js +159 -0
- package/dist/operations/shared-vertex.d.ts +1 -0
- package/dist/operations/shared-vertex.js +210 -0
- package/dist/operations/trace-graph.d.ts +96 -0
- package/dist/operations/trace-graph.js +283 -0
- package/dist/operations/vertex.d.ts +1 -0
- package/dist/operations/vertex.js +538 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/mutation-hooks.d.ts +28 -0
- package/dist/plugins/mutation-hooks.js +84 -0
- package/dist/plugins/plugin-context.d.ts +1 -0
- package/dist/plugins/plugin-context.js +367 -0
- package/dist/plugins/plugin-manager.d.ts +103 -0
- package/dist/plugins/plugin-manager.js +316 -0
- package/dist/plugins/plugin.d.ts +529 -0
- package/dist/plugins/plugin.js +3 -0
- package/dist/shared/config/constants.d.ts +66 -0
- package/dist/shared/config/constants.js +60 -0
- package/dist/shared/config/feature-style.d.ts +155 -0
- package/dist/shared/config/feature-style.js +154 -0
- package/dist/shared/config/index.d.ts +17 -0
- package/dist/shared/config/index.js +8 -0
- package/dist/shared/config/rendering.d.ts +107 -0
- package/dist/shared/config/rendering.js +33 -0
- package/dist/shared/config/selection-highlight.d.ts +29 -0
- package/dist/shared/config/selection-highlight.js +35 -0
- package/dist/shared/config/selection.d.ts +273 -0
- package/dist/shared/config/selection.js +266 -0
- package/dist/shared/config/topology.d.ts +33 -0
- package/dist/shared/config/topology.js +17 -0
- package/dist/shared/config/trace.d.ts +40 -0
- package/dist/shared/config/trace.js +17 -0
- package/dist/shared/math/angle.d.ts +21 -0
- package/dist/shared/math/angle.js +34 -0
- package/dist/shared/math/circle.d.ts +6 -0
- package/dist/shared/math/circle.js +10 -0
- package/dist/shared/math/constants.d.ts +48 -0
- package/dist/shared/math/constants.js +59 -0
- package/dist/shared/math/distance.d.ts +78 -0
- package/dist/shared/math/distance.js +147 -0
- package/dist/shared/math/globe-subdivision.d.ts +62 -0
- package/dist/shared/math/globe-subdivision.js +99 -0
- package/dist/shared/math/index.d.ts +17 -0
- package/dist/shared/math/index.js +21 -0
- package/dist/shared/math/intersection.d.ts +63 -0
- package/dist/shared/math/intersection.js +236 -0
- package/dist/shared/math/longitude.d.ts +20 -0
- package/dist/shared/math/longitude.js +31 -0
- package/dist/shared/math/mercator-plane.d.ts +27 -0
- package/dist/shared/math/mercator-plane.js +26 -0
- package/dist/shared/math/obb.d.ts +65 -0
- package/dist/shared/math/obb.js +107 -0
- package/dist/shared/math/rotation.d.ts +93 -0
- package/dist/shared/math/rotation.js +186 -0
- package/dist/shared/math/segment-grid.d.ts +69 -0
- package/dist/shared/math/segment-grid.js +159 -0
- package/dist/shared/math/transform.d.ts +140 -0
- package/dist/shared/math/transform.js +189 -0
- package/dist/shared/types/events.d.ts +128 -0
- package/dist/shared/types/events.js +3 -0
- package/dist/shared/types/model.d.ts +950 -0
- package/dist/shared/types/model.js +3 -0
- package/dist/shared/types/selection-box.d.ts +23 -0
- package/dist/shared/types/selection-box.js +3 -0
- package/dist/shared/types/style.d.ts +68 -0
- package/dist/shared/types/style.js +3 -0
- package/dist/shared/utils/color.d.ts +49 -0
- package/dist/shared/utils/color.js +180 -0
- package/dist/shared/utils/coordinates.d.ts +52 -0
- package/dist/shared/utils/coordinates.js +75 -0
- package/dist/shared/utils/embedded-image.d.ts +34 -0
- package/dist/shared/utils/embedded-image.js +161 -0
- package/dist/shared/utils/event-emitter.d.ts +262 -0
- package/dist/shared/utils/event-emitter.js +44 -0
- package/dist/shared/utils/feature-bbox.d.ts +8 -0
- package/dist/shared/utils/feature-bbox.js +207 -0
- package/dist/shared/utils/feature-segments.d.ts +23 -0
- package/dist/shared/utils/feature-segments.js +179 -0
- package/dist/shared/utils/id.d.ts +1 -0
- package/dist/shared/utils/id.js +35 -0
- package/dist/shared/utils/image.d.ts +34 -0
- package/dist/shared/utils/image.js +106 -0
- package/dist/shared/utils/index.d.ts +15 -0
- package/dist/shared/utils/index.js +24 -0
- package/dist/shared/utils/map.d.ts +26 -0
- package/dist/shared/utils/map.js +35 -0
- package/dist/shared/utils/name-generator.d.ts +197 -0
- package/dist/shared/utils/name-generator.js +337 -0
- package/dist/shared/utils/pixel-ratio.d.ts +111 -0
- package/dist/shared/utils/pixel-ratio.js +85 -0
- package/dist/shared/utils/property.d.ts +88 -0
- package/dist/shared/utils/property.js +140 -0
- package/dist/shared/utils/vertex-ref.d.ts +23 -0
- package/dist/shared/utils/vertex-ref.js +20 -0
- package/dist/snapping/custom-targets.d.ts +1 -0
- package/dist/snapping/custom-targets.js +21 -0
- package/dist/snapping/geometry.d.ts +1 -0
- package/dist/snapping/geometry.js +61 -0
- package/dist/snapping/index.d.ts +14 -0
- package/dist/snapping/index.js +4 -0
- package/dist/snapping/indicator.d.ts +19 -0
- package/dist/snapping/indicator.js +145 -0
- package/dist/snapping/providers/display.d.ts +72 -0
- package/dist/snapping/providers/display.js +268 -0
- package/dist/snapping/providers/guide.d.ts +69 -0
- package/dist/snapping/providers/guide.js +187 -0
- package/dist/snapping/providers/intersection.d.ts +1 -0
- package/dist/snapping/providers/intersection.js +92 -0
- package/dist/snapping/providers/shared.d.ts +39 -0
- package/dist/snapping/providers/shared.js +146 -0
- package/dist/snapping/providers/store.d.ts +1 -0
- package/dist/snapping/providers/store.js +132 -0
- package/dist/snapping/service.d.ts +1 -0
- package/dist/snapping/service.js +272 -0
- package/dist/snapping/types.d.ts +267 -0
- package/dist/snapping/types.js +66 -0
- package/dist/store/change-merger.d.ts +1 -0
- package/dist/store/change-merger.js +102 -0
- package/dist/store/draw-store.d.ts +1 -0
- package/dist/store/draw-store.js +396 -0
- package/dist/store/event-bridge.d.ts +1 -0
- package/dist/store/event-bridge.js +161 -0
- package/dist/store/index.d.ts +12 -0
- package/dist/store/index.js +4 -0
- package/dist/store/local-visibility.d.ts +21 -0
- package/dist/store/local-visibility.js +27 -0
- package/dist/store/lock.d.ts +67 -0
- package/dist/store/lock.js +54 -0
- package/dist/store/memory/change-bus.d.ts +60 -0
- package/dist/store/memory/change-bus.js +232 -0
- package/dist/store/memory/file-store.d.ts +15 -0
- package/dist/store/memory/file-store.js +33 -0
- package/dist/store/memory/frozen.d.ts +21 -0
- package/dist/store/memory/frozen.js +51 -0
- package/dist/store/memory/ui-state.d.ts +51 -0
- package/dist/store/memory/ui-state.js +223 -0
- package/dist/store/memory.d.ts +26 -0
- package/dist/store/memory.js +708 -0
- package/dist/store/spatial/index.d.ts +6 -0
- package/dist/store/spatial/index.js +4 -0
- package/dist/store/spatial/spatial-index.d.ts +90 -0
- package/dist/store/spatial/spatial-index.js +148 -0
- package/dist/store/spatial/store-spatial-index.d.ts +60 -0
- package/dist/store/spatial/store-spatial-index.js +125 -0
- package/dist/store/store.d.ts +417 -0
- package/dist/store/store.js +3 -0
- package/dist/store/types.d.ts +8 -0
- package/dist/store/types.js +3 -0
- package/dist/store/writable-layer.d.ts +35 -0
- package/dist/store/writable-layer.js +20 -0
- package/dist/view/cache/buffer.d.ts +28 -0
- package/dist/view/cache/buffer.js +176 -0
- package/dist/view/cache/earcut.d.ts +1 -0
- package/dist/view/cache/earcut.js +122 -0
- package/dist/view/cache/style-rule.d.ts +1 -0
- package/dist/view/cache/style-rule.js +97 -0
- package/dist/view/cache/terrain-fill.d.ts +30 -0
- package/dist/view/cache/terrain-fill.js +60 -0
- package/dist/view/cache/texture.d.ts +14 -0
- package/dist/view/cache/texture.js +292 -0
- package/dist/view/coordinator.d.ts +27 -0
- package/dist/view/coordinator.js +72 -0
- package/dist/view/feature-companion.d.ts +173 -0
- package/dist/view/feature-companion.js +108 -0
- package/dist/view/globe-subdivision.d.ts +78 -0
- package/dist/view/globe-subdivision.js +128 -0
- package/dist/view/index.d.ts +47 -0
- package/dist/view/index.js +20 -0
- package/dist/view/layer/attach.d.ts +20 -0
- package/dist/view/layer/attach.js +47 -0
- package/dist/view/layer/blend.d.ts +57 -0
- package/dist/view/layer/blend.js +14 -0
- package/dist/view/layer/custom-layer.d.ts +1 -0
- package/dist/view/layer/custom-layer.js +509 -0
- package/dist/view/layer/depth-state.d.ts +14 -0
- package/dist/view/layer/depth-state.js +44 -0
- package/dist/view/layer/display-list.d.ts +1 -0
- package/dist/view/layer/display-list.js +111 -0
- package/dist/view/layer/drape-planner.d.ts +139 -0
- package/dist/view/layer/drape-planner.js +726 -0
- package/dist/view/layer/frame-render.d.ts +57 -0
- package/dist/view/layer/frame-render.js +209 -0
- package/dist/view/layer/frame-state.d.ts +147 -0
- package/dist/view/layer/frame-state.js +484 -0
- package/dist/view/layer/gl-state.d.ts +77 -0
- package/dist/view/layer/gl-state.js +132 -0
- package/dist/view/layer/index.d.ts +6 -0
- package/dist/view/layer/index.js +5 -0
- package/dist/view/layer/render-scope.d.ts +30 -0
- package/dist/view/layer/render-scope.js +28 -0
- package/dist/view/layer/render.d.ts +87 -0
- package/dist/view/layer/render.js +187 -0
- package/dist/view/layer/renderers.d.ts +81 -0
- package/dist/view/layer/renderers.js +142 -0
- package/dist/view/layer/slot-manager.d.ts +26 -0
- package/dist/view/layer/slot-manager.js +133 -0
- package/dist/view/layer/slots.d.ts +33 -0
- package/dist/view/layer/slots.js +50 -0
- package/dist/view/layer/store-retained-bbox.d.ts +36 -0
- package/dist/view/layer/store-retained-bbox.js +188 -0
- package/dist/view/layer/store-retained-chunk.d.ts +97 -0
- package/dist/view/layer/store-retained-chunk.js +94 -0
- package/dist/view/layer/store-retained-classify.d.ts +34 -0
- package/dist/view/layer/store-retained-classify.js +88 -0
- package/dist/view/layer/store-retained-collect.d.ts +24 -0
- package/dist/view/layer/store-retained-collect.js +121 -0
- package/dist/view/layer/store-retained-coord-patch.d.ts +119 -0
- package/dist/view/layer/store-retained-coord-patch.js +168 -0
- package/dist/view/layer/store-retained-immediate.d.ts +63 -0
- package/dist/view/layer/store-retained-immediate.js +49 -0
- package/dist/view/layer/store-retained-invalidation.d.ts +96 -0
- package/dist/view/layer/store-retained-invalidation.js +192 -0
- package/dist/view/layer/store-retained.d.ts +198 -0
- package/dist/view/layer/store-retained.js +430 -0
- package/dist/view/layer/terrain-resolver.d.ts +1 -0
- package/dist/view/layer/terrain-resolver.js +174 -0
- package/dist/view/renderers/batch-manager.d.ts +61 -0
- package/dist/view/renderers/batch-manager.js +718 -0
- package/dist/view/renderers/draw-factors.d.ts +60 -0
- package/dist/view/renderers/draw-factors.js +35 -0
- package/dist/view/renderers/drawer.d.ts +1 -0
- package/dist/view/renderers/drawer.js +346 -0
- package/dist/view/renderers/image.d.ts +1 -0
- package/dist/view/renderers/image.js +255 -0
- package/dist/view/renderers/line/dash.d.ts +31 -0
- package/dist/view/renderers/line/dash.js +152 -0
- package/dist/view/renderers/line/line-geometry.d.ts +39 -0
- package/dist/view/renderers/line/line-geometry.js +460 -0
- package/dist/view/renderers/line/line-gl.d.ts +1 -0
- package/dist/view/renderers/line/line-gl.js +236 -0
- package/dist/view/renderers/line/line-shader.d.ts +1 -0
- package/dist/view/renderers/line/line-shader.js +364 -0
- package/dist/view/renderers/line/line-types.d.ts +43 -0
- package/dist/view/renderers/line/line-types.js +3 -0
- package/dist/view/renderers/line/line-uniforms.d.ts +1 -0
- package/dist/view/renderers/line/line-uniforms.js +390 -0
- package/dist/view/renderers/line/sdf-line.d.ts +92 -0
- package/dist/view/renderers/line/sdf-line.js +567 -0
- package/dist/view/renderers/point/billboard-depth.d.ts +10 -0
- package/dist/view/renderers/point/billboard-depth.js +56 -0
- package/dist/view/renderers/point/point-instance.d.ts +124 -0
- package/dist/view/renderers/point/point-instance.js +738 -0
- package/dist/view/renderers/point/point-sdf.d.ts +58 -0
- package/dist/view/renderers/point/point-sdf.js +170 -0
- package/dist/view/renderers/point/point-shape.d.ts +99 -0
- package/dist/view/renderers/point/point-shape.js +504 -0
- package/dist/view/renderers/point/point-style.d.ts +1 -0
- package/dist/view/renderers/point/point-style.js +46 -0
- package/dist/view/renderers/polygon/batch.d.ts +26 -0
- package/dist/view/renderers/polygon/batch.js +336 -0
- package/dist/view/renderers/polygon/earcut-input.d.ts +37 -0
- package/dist/view/renderers/polygon/earcut-input.js +55 -0
- package/dist/view/renderers/polygon/earcut-sliced.d.ts +69 -0
- package/dist/view/renderers/polygon/earcut-sliced.js +960 -0
- package/dist/view/renderers/polygon/fill.d.ts +74 -0
- package/dist/view/renderers/polygon/fill.js +251 -0
- package/dist/view/renderers/polygon/sdf-polygon.d.ts +62 -0
- package/dist/view/renderers/polygon/sdf-polygon.js +919 -0
- package/dist/view/renderers/polygon/terrain-cull.d.ts +3 -0
- package/dist/view/renderers/polygon/terrain-cull.js +14 -0
- package/dist/view/renderers/polygon/triangulator.d.ts +41 -0
- package/dist/view/renderers/polygon/triangulator.js +3 -0
- package/dist/view/renderers/retained.d.ts +43 -0
- package/dist/view/renderers/retained.js +3 -0
- package/dist/view/renderers/stroke.d.ts +121 -0
- package/dist/view/renderers/stroke.js +621 -0
- package/dist/view/shaders/frame.d.ts +8 -0
- package/dist/view/shaders/frame.js +37 -0
- package/dist/view/shaders/helpers.d.ts +238 -0
- package/dist/view/shaders/helpers.js +611 -0
- package/dist/view/shaders/initializer.d.ts +27 -0
- package/dist/view/shaders/initializer.js +125 -0
- package/dist/view/shaders/projection.d.ts +123 -0
- package/dist/view/shaders/projection.js +299 -0
- package/dist/view/shaders/quad-grid.d.ts +77 -0
- package/dist/view/shaders/quad-grid.js +128 -0
- package/dist/view/shaders/quad.d.ts +189 -0
- package/dist/view/shaders/quad.js +582 -0
- package/dist/view/shaders/retained-origin.d.ts +50 -0
- package/dist/view/shaders/retained-origin.js +67 -0
- package/dist/view/shaders/terrain-shade.d.ts +23 -0
- package/dist/view/shaders/terrain-shade.js +93 -0
- package/dist/view/style-rule.d.ts +166 -0
- package/dist/view/style-rule.js +300 -0
- package/dist/view/terrain/anchor.d.ts +135 -0
- package/dist/view/terrain/anchor.js +226 -0
- package/dist/view/terrain/context.d.ts +132 -0
- package/dist/view/terrain/context.js +437 -0
- package/dist/view/terrain/dem-atlas.d.ts +97 -0
- package/dist/view/terrain/dem-atlas.js +534 -0
- package/dist/view/terrain/detect.d.ts +126 -0
- package/dist/view/terrain/detect.js +198 -0
- package/dist/view/terrain/drape/bin-store.d.ts +179 -0
- package/dist/view/terrain/drape/bin-store.js +529 -0
- package/dist/view/terrain/drape/binning.d.ts +259 -0
- package/dist/view/terrain/drape/binning.js +604 -0
- package/dist/view/terrain/drape/edge-constrain.d.ts +37 -0
- package/dist/view/terrain/drape/edge-constrain.js +175 -0
- package/dist/view/terrain/drape/geometry.d.ts +95 -0
- package/dist/view/terrain/drape/geometry.js +260 -0
- package/dist/view/terrain/drape/mesh.d.ts +50 -0
- package/dist/view/terrain/drape/mesh.js +86 -0
- package/dist/view/terrain/drape/pass.d.ts +122 -0
- package/dist/view/terrain/drape/pass.js +379 -0
- package/dist/view/terrain/drape/quad-glyphs.d.ts +64 -0
- package/dist/view/terrain/drape/quad-glyphs.js +117 -0
- package/dist/view/terrain/drape/quad.d.ts +249 -0
- package/dist/view/terrain/drape/quad.js +835 -0
- package/dist/view/terrain/drape/renderer.d.ts +184 -0
- package/dist/view/terrain/drape/renderer.js +706 -0
- package/dist/view/terrain/drape/shared.d.ts +80 -0
- package/dist/view/terrain/drape/shared.js +173 -0
- package/dist/view/terrain/drape/stitch.d.ts +155 -0
- package/dist/view/terrain/drape/stitch.js +228 -0
- package/dist/view/terrain/ground.d.ts +72 -0
- package/dist/view/terrain/ground.js +151 -0
- package/dist/view/terrain/metrics.d.ts +180 -0
- package/dist/view/terrain/metrics.js +231 -0
- package/dist/view/terrain/occlusion.d.ts +11 -0
- package/dist/view/terrain/occlusion.js +129 -0
- package/dist/view/terrain/polygon.d.ts +86 -0
- package/dist/view/terrain/polygon.js +301 -0
- package/dist/view/terrain/shade.d.ts +48 -0
- package/dist/view/terrain/shade.js +45 -0
- package/dist/view/terrain/state.d.ts +99 -0
- package/dist/view/terrain/state.js +186 -0
- package/dist/view/terrain/tessellation.d.ts +265 -0
- package/dist/view/terrain/tessellation.js +924 -0
- package/dist/view/terrain/tiling.d.ts +56 -0
- package/dist/view/terrain/tiling.js +155 -0
- package/dist/view/terrain/upstream-terrain.d.ts +82 -0
- package/dist/view/terrain/upstream-terrain.js +116 -0
- package/dist/view/ui/auxiliary-handles.d.ts +151 -0
- package/dist/view/ui/auxiliary-handles.js +22 -0
- package/dist/view/ui/bounds.d.ts +53 -0
- package/dist/view/ui/bounds.js +149 -0
- package/dist/view/ui/box-selection.d.ts +1 -0
- package/dist/view/ui/box-selection.js +83 -0
- package/dist/view/ui/handle-test.d.ts +1 -0
- package/dist/view/ui/handle-test.js +437 -0
- package/dist/view/ui/handle-thinning.d.ts +122 -0
- package/dist/view/ui/handle-thinning.js +430 -0
- package/dist/view/ui/handles.d.ts +25 -0
- package/dist/view/ui/handles.js +673 -0
- package/dist/view/ui/helper.d.ts +19 -0
- package/dist/view/ui/helper.js +76 -0
- package/dist/view/ui/index.d.ts +15 -0
- package/dist/view/ui/index.js +15 -0
- package/dist/view/ui/selection-scope.d.ts +25 -0
- package/dist/view/ui/selection-scope.js +34 -0
- package/dist/view/ui/selection-ui/bounding-box.d.ts +44 -0
- package/dist/view/ui/selection-ui/bounding-box.js +240 -0
- package/dist/view/ui/selection-ui/extension-registry.d.ts +76 -0
- package/dist/view/ui/selection-ui/extension-registry.js +78 -0
- package/dist/view/ui/selection-ui/index.d.ts +12 -0
- package/dist/view/ui/selection-ui/index.js +12 -0
- package/dist/view/ui/selection-ui/renderer.d.ts +29 -0
- package/dist/view/ui/selection-ui/renderer.js +227 -0
- package/dist/view/ui/selection-ui/types.d.ts +55 -0
- package/dist/view/ui/selection-ui/types.js +3 -0
- package/dist/view/ui/selection-ui-drawer.d.ts +52 -0
- package/dist/view/ui/selection-ui-drawer.js +329 -0
- package/dist/view/ui/tentative.d.ts +1 -0
- package/dist/view/ui/tentative.js +320 -0
- package/dist/view/viewport.d.ts +119 -0
- package/dist/view/viewport.js +254 -0
- package/package.json +113 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/** The largest screen error of the baked offsets that is accepted (CSS px) */
|
|
4
|
+
export const RETAINED_ORIGIN_TOLERANCE_PX = 0.1;
|
|
5
|
+
/** The unit roundoff of Float32 */
|
|
6
|
+
const FLOAT32_ROUNDOFF = 2 ** -24;
|
|
7
|
+
/** The width of the world in CSS px at zoom 0 (the tile size of maplibre) */
|
|
8
|
+
const WORLD_SIZE_PX = 512;
|
|
9
|
+
/** The latitude where Web Mercator stops (the scale diverges at the poles) */
|
|
10
|
+
const MAX_MERCATOR_LATITUDE = 85.0511287798;
|
|
11
|
+
/**
|
|
12
|
+
* The center of a bounding box
|
|
13
|
+
*/
|
|
14
|
+
export function boundsCenter(bounds) {
|
|
15
|
+
return [(bounds.minX + bounds.maxX) / 2, (bounds.minY + bounds.maxY) / 2];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The screen error (CSS px) that the baked offsets of a batch leave in a region
|
|
19
|
+
*
|
|
20
|
+
* It is the bound described in the module comment, measured at the corner of the region
|
|
21
|
+
* farthest from the origin. A latitude difference is longer on screen by 1 / cos φ, so it is
|
|
22
|
+
* weighted with the highest latitude of the region.
|
|
23
|
+
*
|
|
24
|
+
* @param origin The origin of the batch
|
|
25
|
+
* @param region The region on screen (longitude / latitude)
|
|
26
|
+
* @param zoom The zoom of the camera
|
|
27
|
+
*/
|
|
28
|
+
export function retainedOriginErrorPx(origin, region, zoom) {
|
|
29
|
+
const dLng = Math.max(Math.abs(region.minX - origin[0]), Math.abs(region.maxX - origin[0]));
|
|
30
|
+
const dLat = Math.max(Math.abs(region.minY - origin[1]), Math.abs(region.maxY - origin[1]));
|
|
31
|
+
const lat = Math.min(Math.max(Math.abs(region.minY), Math.abs(region.maxY)), MAX_MERCATOR_LATITUDE);
|
|
32
|
+
const latScale = 1 / Math.cos((lat * Math.PI) / 180);
|
|
33
|
+
const pxPerDegree = (WORLD_SIZE_PX * 2 ** zoom) / 360;
|
|
34
|
+
return 2 * FLOAT32_ROUNDOFF * Math.max(dLng, dLat * latScale) * pxPerDegree;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The origin a batch should be built with again for the current view (null = keep it)
|
|
38
|
+
*
|
|
39
|
+
* The region on screen is the extent of the batch clipped to the view. When the current origin
|
|
40
|
+
* leaves more than the tolerance there, the center of that region is proposed, provided it at
|
|
41
|
+
* least halves the error (so that a region that is large on screen, where no origin can do
|
|
42
|
+
* better, does not rebuild every frame).
|
|
43
|
+
*
|
|
44
|
+
* @param origin The origin the batch was built with
|
|
45
|
+
* @param extent The extent of the batch (null when unknown: kept)
|
|
46
|
+
* @param view The view (null when unknown: the whole extent is taken as on screen)
|
|
47
|
+
* @param zoom The zoom of the camera
|
|
48
|
+
*/
|
|
49
|
+
export function rebasedRetainedOrigin(origin, extent, view, zoom) {
|
|
50
|
+
if (!extent)
|
|
51
|
+
return null;
|
|
52
|
+
const region = view
|
|
53
|
+
? {
|
|
54
|
+
minX: Math.max(extent.minX, view.minX),
|
|
55
|
+
minY: Math.max(extent.minY, view.minY),
|
|
56
|
+
maxX: Math.min(extent.maxX, view.maxX),
|
|
57
|
+
maxY: Math.min(extent.maxY, view.maxY),
|
|
58
|
+
}
|
|
59
|
+
: extent;
|
|
60
|
+
if (!(region.minX <= region.maxX && region.minY <= region.maxY))
|
|
61
|
+
return null;
|
|
62
|
+
const error = retainedOriginErrorPx(origin, region, zoom);
|
|
63
|
+
if (!(error > RETAINED_ORIGIN_TOLERANCE_PX))
|
|
64
|
+
return null;
|
|
65
|
+
const candidate = boundsCenter(region);
|
|
66
|
+
return retainedOriginErrorPx(candidate, region, zoom) < error / 2 ? candidate : null;
|
|
67
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vertex side: GLSL that hands over the sample position for the shading
|
|
3
|
+
*
|
|
4
|
+
* Place it after OFFSET_MODE_GLSL and call `emitShadeOffset(a_pos)` inside
|
|
5
|
+
* main. A draw that does not call it leaves the varying undefined, so a shader
|
|
6
|
+
* that has a fill must call it exactly once on every branch.
|
|
7
|
+
*/
|
|
8
|
+
export declare const TERRAIN_SHADE_VERTEX_GLSL = "\nout vec2 v_shade_offset;\n\nvoid emitShadeOffset(vec2 lngLatOffset) {\n v_shade_offset = shade_mercator_offset(lngLatOffset);\n}\n";
|
|
9
|
+
/**
|
|
10
|
+
* Fragment side: GLSL that produces the coefficient applied to the polygon fill
|
|
11
|
+
*
|
|
12
|
+
* `terrainFillShade()` returns 1.0 on flat ground and when terrain is
|
|
13
|
+
* disabled. When terrain is disabled (`u_shade_strength` is 0) it returns
|
|
14
|
+
* without reading the DEM, so the cost and the pixels are the same as before
|
|
15
|
+
* terrain was introduced.
|
|
16
|
+
*
|
|
17
|
+
* The shading is applied even on frames that draw polygons and lines flat (the
|
|
18
|
+
* zoomed-out band). Stopping the vertex displacement is a measure to avoid
|
|
19
|
+
* cliffs; it does not mean the relief of the ground surface no longer needs to
|
|
20
|
+
* be readable. If anything, that band is exactly the boundary where the paths
|
|
21
|
+
* swap over.
|
|
22
|
+
*/
|
|
23
|
+
export declare const TERRAIN_SHADE_FRAGMENT_GLSL: string;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Terrain shading applied to the polygon fill of the vertex displacement path
|
|
5
|
+
*
|
|
6
|
+
* There are two paths for laying a polygon fill onto the ground surface:
|
|
7
|
+
* analytic drape (painting it as pixels of the ground surface) and vertex
|
|
8
|
+
* displacement (lifting the vertices of the feature and painting them). The
|
|
9
|
+
* path is switched by cost, so even on the same map it swaps over depending on
|
|
10
|
+
* the camera angle and the amount of data. If the fill looks different between
|
|
11
|
+
* the paths, the picture jumps at that switch. In practice it showed up as
|
|
12
|
+
* "tilting makes relief appear on the polygon, and straightening it brings
|
|
13
|
+
* back a uniform color".
|
|
14
|
+
*
|
|
15
|
+
* So the same shading as the analytic drape is applied to the fill of the
|
|
16
|
+
* vertex displacement path as well. The formula shares the single place in
|
|
17
|
+
* `terrain/shade.ts` (same light source, same normalization, same clamp); only
|
|
18
|
+
* the way samples are taken differs. The drape reads the DEM in tile
|
|
19
|
+
* coordinates, while this one reads the DEM atlas with the Mercator relative
|
|
20
|
+
* coordinates handed over from the vertex.
|
|
21
|
+
*
|
|
22
|
+
* It is applied only to polygon fills. Lines, points, labels and handles are
|
|
23
|
+
* left unshaded for readability (the same convention as the drape path).
|
|
24
|
+
*/
|
|
25
|
+
import { TERRAIN_SHADE_CORE_GLSL } from '../terrain/shade.js';
|
|
26
|
+
import { DEM_SAMPLE_GLSL } from './helpers.js';
|
|
27
|
+
/**
|
|
28
|
+
* Vertex side: GLSL that hands over the sample position for the shading
|
|
29
|
+
*
|
|
30
|
+
* Place it after OFFSET_MODE_GLSL and call `emitShadeOffset(a_pos)` inside
|
|
31
|
+
* main. A draw that does not call it leaves the varying undefined, so a shader
|
|
32
|
+
* that has a fill must call it exactly once on every branch.
|
|
33
|
+
*/
|
|
34
|
+
export const TERRAIN_SHADE_VERTEX_GLSL = `
|
|
35
|
+
out vec2 v_shade_offset;
|
|
36
|
+
|
|
37
|
+
void emitShadeOffset(vec2 lngLatOffset) {
|
|
38
|
+
v_shade_offset = shade_mercator_offset(lngLatOffset);
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
/**
|
|
42
|
+
* Fragment side: GLSL that produces the coefficient applied to the polygon fill
|
|
43
|
+
*
|
|
44
|
+
* `terrainFillShade()` returns 1.0 on flat ground and when terrain is
|
|
45
|
+
* disabled. When terrain is disabled (`u_shade_strength` is 0) it returns
|
|
46
|
+
* without reading the DEM, so the cost and the pixels are the same as before
|
|
47
|
+
* terrain was introduced.
|
|
48
|
+
*
|
|
49
|
+
* The shading is applied even on frames that draw polygons and lines flat (the
|
|
50
|
+
* zoomed-out band). Stopping the vertex displacement is a measure to avoid
|
|
51
|
+
* cliffs; it does not mean the relief of the ground surface no longer needs to
|
|
52
|
+
* be readable. If anything, that band is exactly the boundary where the paths
|
|
53
|
+
* swap over.
|
|
54
|
+
*/
|
|
55
|
+
export const TERRAIN_SHADE_FRAGMENT_GLSL = `
|
|
56
|
+
in vec2 v_shade_offset;
|
|
57
|
+
|
|
58
|
+
// Shading (an aid for reading the terrain). Same light source and same formula as the ground,
|
|
59
|
+
// applied to the fill only
|
|
60
|
+
uniform vec3 u_light_dir; // unit vector in the map coordinate system (east, north, up)
|
|
61
|
+
uniform float u_shade_strength;
|
|
62
|
+
` +
|
|
63
|
+
DEM_SAMPLE_GLSL +
|
|
64
|
+
TERRAIN_SHADE_CORE_GLSL +
|
|
65
|
+
`
|
|
66
|
+
float terrainFillShade() {
|
|
67
|
+
if (u_shade_strength <= 0.0) return 1.0;
|
|
68
|
+
|
|
69
|
+
// The sample width is one texel of the DEM atlas. rect.zw = 1/width, 1/height
|
|
70
|
+
// (Mercator), so the Mercator width of a texel is 1/(rect.zw * size).
|
|
71
|
+
vec2 texel = 1.0 / max(u_dem_atlas_rect.zw * u_dem_atlas_size, vec2(1e-9));
|
|
72
|
+
|
|
73
|
+
// The ground distance of Mercator 1.0 (meters). It is exactly the reciprocal of the
|
|
74
|
+
// meters -> Mercator z coefficient (u_elevation_params.x). It uses the same value as the
|
|
75
|
+
// conversion applied when the vertex adds the elevation, so the unit of the gradient
|
|
76
|
+
// never drifts.
|
|
77
|
+
float meters = 1.0 / max(u_elevation_params.x, 1e-12);
|
|
78
|
+
|
|
79
|
+
// Outside the atlas, the clamp in dem_elevation_meters returns the edge value. The
|
|
80
|
+
// gradient goes thin there, but since the atlas covers the terrain tiles in view, this
|
|
81
|
+
// does not happen in the range where the polygon fill is applied (only the coarse tiles
|
|
82
|
+
// on the horizon side fall outside the range).
|
|
83
|
+
float ex1 = dem_elevation_meters(v_shade_offset + vec2(texel.x, 0.0));
|
|
84
|
+
float ex0 = dem_elevation_meters(v_shade_offset - vec2(texel.x, 0.0));
|
|
85
|
+
float ey1 = dem_elevation_meters(v_shade_offset + vec2(0.0, texel.y));
|
|
86
|
+
float ey0 = dem_elevation_meters(v_shade_offset - vec2(0.0, texel.y));
|
|
87
|
+
|
|
88
|
+
float dzdEast = (ex1 - ex0) / (2.0 * texel.x * meters);
|
|
89
|
+
// Mercator y points south, so flip north
|
|
90
|
+
float dzdNorth = -(ey1 - ey0) / (2.0 * texel.y * meters);
|
|
91
|
+
return terrainShadeFromGradient(dzdEast, dzdNorth);
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Style rules of a layer
|
|
3
|
+
*
|
|
4
|
+
* A set of pure functions that evaluate the declarative style rule a layer holds
|
|
5
|
+
* (`Layer.styleRule`) and derive a color from the attributes of a feature. So that the
|
|
6
|
+
* same functions can be used both from rendering (FeatureDrawer) and from
|
|
7
|
+
* datasets, they depend on neither the Store, nor WebGL, nor the DOM.
|
|
8
|
+
*
|
|
9
|
+
* The priority of evaluation is "the feature's own color > the layer's rule > the default
|
|
10
|
+
* color". Whether a feature has its own color is decided by the presence of the color
|
|
11
|
+
* property of the relevant channel, to match the existing style resolution (FeatureDrawer
|
|
12
|
+
* merges `style.fillColor` and the like into the defaults property by property).
|
|
13
|
+
* Therefore the rule does apply to a feature that only holds things other than colors,
|
|
14
|
+
* such as `{ strokeWidth: 3 }`.
|
|
15
|
+
*
|
|
16
|
+
* When the attribute is missing or its type does not match, it falls back to the rule's
|
|
17
|
+
* `other` rather than to the default color. This is so that the caller can tell
|
|
18
|
+
* "the rule is not taking effect" apart from "there is no value".
|
|
19
|
+
*/
|
|
20
|
+
import { type Messages } from '../messages.js';
|
|
21
|
+
import type { Feature, FeatureStyle, FeatureType, StyleRule } from '../store/types.js';
|
|
22
|
+
/**
|
|
23
|
+
* One row of a legend derived by {@link deriveLegend}: a label and a color.
|
|
24
|
+
*
|
|
25
|
+
* It holds only a label and a color. The library does not draw the legend UI.
|
|
26
|
+
*/
|
|
27
|
+
export interface LegendEntry {
|
|
28
|
+
/** The displayed label */
|
|
29
|
+
label: string;
|
|
30
|
+
/** The color (in #RRGGBB form) */
|
|
31
|
+
color: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Which color property of a feature style the rule color goes to, by geometry type.
|
|
35
|
+
*
|
|
36
|
+
* It expresses which style property the rule's color becomes, per geometry type.
|
|
37
|
+
*
|
|
38
|
+
* - point: `pointColor` (Point / MultiPoint)
|
|
39
|
+
* - stroke: `strokeColor` (LineString / MultiLineString / Freehand)
|
|
40
|
+
* - fill: `fillColor` (Polygon / MultiPolygon / Circle)
|
|
41
|
+
*/
|
|
42
|
+
export type StyleRuleChannel = 'point' | 'stroke' | 'fill';
|
|
43
|
+
/**
|
|
44
|
+
* Returns the channel that carries the rule color for a feature type.
|
|
45
|
+
*
|
|
46
|
+
* Types other than the known ones (Image and custom types) return 'fill'.
|
|
47
|
+
*
|
|
48
|
+
* @param type The feature type
|
|
49
|
+
* @returns `'point'`, `'stroke'` or `'fill'`
|
|
50
|
+
*/
|
|
51
|
+
export declare function getStyleRuleChannel(type: FeatureType): StyleRuleChannel;
|
|
52
|
+
/**
|
|
53
|
+
* Evaluates a style rule against the attributes of a feature and returns a color.
|
|
54
|
+
*
|
|
55
|
+
* When the attribute is missing or its type does not match, the rule's `other` is
|
|
56
|
+
* returned. `single` does not look at attributes, so it is always the same color.
|
|
57
|
+
* `categorical` matches strings, numbers and booleans by `String(value)`; `graduated` and
|
|
58
|
+
* `continuous` take finite numbers only (a numeric string gives `other`). `continuous`
|
|
59
|
+
* clamps values outside `min`..`max` and returns the first ramp color when `max <= min`. It
|
|
60
|
+
* is a pure function.
|
|
61
|
+
*
|
|
62
|
+
* @param rule The style rule
|
|
63
|
+
* @param properties The attributes of the feature
|
|
64
|
+
* @returns The color in `#RRGGBB` form
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { evaluateStyleRule, type StyleRule } from '@sakuzu/maplibre-gl-draw';
|
|
69
|
+
*
|
|
70
|
+
* const rule: StyleRule = {
|
|
71
|
+
* kind: 'graduated',
|
|
72
|
+
* property: 'population',
|
|
73
|
+
* breaks: [1000, 10000],
|
|
74
|
+
* colors: ['#fee8c8', '#fdbb84', '#e34a33'],
|
|
75
|
+
* other: '#cccccc',
|
|
76
|
+
* };
|
|
77
|
+
* evaluateStyleRule(rule, { population: 5000 }); // '#fdbb84'
|
|
78
|
+
* evaluateStyleRule(rule, { population: '5000' }); // '#cccccc' (not a number)
|
|
79
|
+
* evaluateStyleRule(rule, {}); // '#cccccc'
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare function evaluateStyleRule(rule: StyleRule, properties: Record<string, unknown> | undefined): string;
|
|
83
|
+
/**
|
|
84
|
+
* Returns the rule color of a feature, or null when there is no rule.
|
|
85
|
+
*
|
|
86
|
+
* Returns null when there is no rule. The precedence of the feature's own style is a
|
|
87
|
+
* per-channel decision, so it is not decided here (`applyRuleColor` does it).
|
|
88
|
+
*
|
|
89
|
+
* @param feature The target feature
|
|
90
|
+
* @param rule The style rule of the layer (undefined when it is not set)
|
|
91
|
+
* @returns The rule color (in #RRGGBB form). null when there is no rule
|
|
92
|
+
*/
|
|
93
|
+
export declare function resolveRuleColor(feature: Feature, rule: StyleRule | undefined): string | null;
|
|
94
|
+
/**
|
|
95
|
+
* Returns the style of a feature with the rule color put on the color property of a
|
|
96
|
+
* channel.
|
|
97
|
+
*
|
|
98
|
+
* A feature that has its own color property for the relevant channel beats the rule, so
|
|
99
|
+
* in that case the original style is returned as is. Properties other than colors (stroke
|
|
100
|
+
* width, opacity and so on) are used together with the rule color.
|
|
101
|
+
*
|
|
102
|
+
* @param style The feature's own style
|
|
103
|
+
* @param ruleColor The rule color (null means there is no rule)
|
|
104
|
+
* @param channel The channel that carries the rule color
|
|
105
|
+
* @returns The effective style: the input itself when `ruleColor` is null or the feature
|
|
106
|
+
* has its own color for the channel, otherwise a new object
|
|
107
|
+
*/
|
|
108
|
+
export declare function applyRuleColor(style: FeatureStyle | undefined, ruleColor: string | null, channel: StyleRuleChannel): FeatureStyle | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Returns the effective style of a feature under the style rule of its layer.
|
|
111
|
+
*
|
|
112
|
+
* A combination of `resolveRuleColor` and `applyRuleColor`. The rendering path that uses a
|
|
113
|
+
* cache caches only the resolution of the rule color, so it calls the two separately.
|
|
114
|
+
*
|
|
115
|
+
* @param feature The target feature
|
|
116
|
+
* @param rule The style rule of the layer
|
|
117
|
+
* @param channel The channel that carries the rule color
|
|
118
|
+
* @returns The effective style
|
|
119
|
+
*/
|
|
120
|
+
export declare function resolveFeatureStyle(feature: Feature, rule: StyleRule | undefined, channel: StyleRuleChannel): FeatureStyle | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* Derives the rows of a legend from a style rule; the library does not draw the legend.
|
|
123
|
+
*
|
|
124
|
+
* Every label that is not a value of the data comes from the messages table (English by
|
|
125
|
+
* default; see `Messages`). The rules for turning labels into strings are as follows.
|
|
126
|
+
*
|
|
127
|
+
* - single: 1 entry. The label is `legendAll` ("All")
|
|
128
|
+
* - categorical: the keys of `map` become the labels as they are, lined up in declaration
|
|
129
|
+
* order. `legendOther` ("Other", the color of `other`) is appended at the end
|
|
130
|
+
* - graduated: the boundary notation of each class (`legendBelow` "Below 10",
|
|
131
|
+
* `legendRange` "10 to below 20", `legendAtLeast` "20 or more"). `legendOther` is
|
|
132
|
+
* appended at the end
|
|
133
|
+
* - continuous: only the 2 end points `min` and `max` (no intermediate colors).
|
|
134
|
+
* `legendOther` is appended at the end
|
|
135
|
+
*
|
|
136
|
+
* Numbers are turned into strings with `String()`. Locale formatting is up to the caller.
|
|
137
|
+
*
|
|
138
|
+
* @param rule The style rule
|
|
139
|
+
* @param messages The entries of the messages table to use (default: `MESSAGES_EN`;
|
|
140
|
+
* missing entries fall back to it)
|
|
141
|
+
* @returns The legend rows, in the order to show them
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* import { deriveLegend, type StyleRule } from '@sakuzu/maplibre-gl-draw';
|
|
146
|
+
*
|
|
147
|
+
* const rule: StyleRule = {
|
|
148
|
+
* kind: 'graduated',
|
|
149
|
+
* property: 'population',
|
|
150
|
+
* breaks: [1000, 10000],
|
|
151
|
+
* colors: ['#fee8c8', '#fdbb84', '#e34a33'],
|
|
152
|
+
* other: '#cccccc',
|
|
153
|
+
* };
|
|
154
|
+
* deriveLegend(rule);
|
|
155
|
+
* // [
|
|
156
|
+
* // { label: 'Below 1000', color: '#fee8c8' },
|
|
157
|
+
* // { label: '1000 to below 10000', color: '#fdbb84' },
|
|
158
|
+
* // { label: '10000 or more', color: '#e34a33' },
|
|
159
|
+
* // { label: 'Other', color: '#cccccc' },
|
|
160
|
+
* // ]
|
|
161
|
+
*
|
|
162
|
+
* // In the language of the host application
|
|
163
|
+
* deriveLegend(rule, { legendOther: 'Autres', legendBelow: (upper) => `Moins de ${upper}` });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export declare function deriveLegend(rule: StyleRule, messages?: Partial<Messages>): LegendEntry[];
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Style rules of a layer
|
|
5
|
+
*
|
|
6
|
+
* A set of pure functions that evaluate the declarative style rule a layer holds
|
|
7
|
+
* (`Layer.styleRule`) and derive a color from the attributes of a feature. So that the
|
|
8
|
+
* same functions can be used both from rendering (FeatureDrawer) and from
|
|
9
|
+
* datasets, they depend on neither the Store, nor WebGL, nor the DOM.
|
|
10
|
+
*
|
|
11
|
+
* The priority of evaluation is "the feature's own color > the layer's rule > the default
|
|
12
|
+
* color". Whether a feature has its own color is decided by the presence of the color
|
|
13
|
+
* property of the relevant channel, to match the existing style resolution (FeatureDrawer
|
|
14
|
+
* merges `style.fillColor` and the like into the defaults property by property).
|
|
15
|
+
* Therefore the rule does apply to a feature that only holds things other than colors,
|
|
16
|
+
* such as `{ strokeWidth: 3 }`.
|
|
17
|
+
*
|
|
18
|
+
* When the attribute is missing or its type does not match, it falls back to the rule's
|
|
19
|
+
* `other` rather than to the default color. This is so that the caller can tell
|
|
20
|
+
* "the rule is not taking effect" apart from "there is no value".
|
|
21
|
+
*/
|
|
22
|
+
import { MESSAGES_EN, resolveMessages } from '../messages.js';
|
|
23
|
+
import { interpolateHexColor } from '../shared/utils/color.js';
|
|
24
|
+
/** The name of the FeatureStyle color property corresponding to each channel */
|
|
25
|
+
const CHANNEL_COLOR_PROPERTY = {
|
|
26
|
+
point: 'pointColor',
|
|
27
|
+
stroke: 'strokeColor',
|
|
28
|
+
fill: 'fillColor',
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Returns the channel that carries the rule color for a feature type.
|
|
32
|
+
*
|
|
33
|
+
* Types other than the known ones (Image and custom types) return 'fill'.
|
|
34
|
+
*
|
|
35
|
+
* @param type The feature type
|
|
36
|
+
* @returns `'point'`, `'stroke'` or `'fill'`
|
|
37
|
+
*/
|
|
38
|
+
export function getStyleRuleChannel(type) {
|
|
39
|
+
switch (type) {
|
|
40
|
+
case 'Point':
|
|
41
|
+
case 'MultiPoint':
|
|
42
|
+
return 'point';
|
|
43
|
+
case 'LineString':
|
|
44
|
+
case 'MultiLineString':
|
|
45
|
+
case 'Freehand':
|
|
46
|
+
return 'stroke';
|
|
47
|
+
default:
|
|
48
|
+
return 'fill';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Computes the key string of categorical
|
|
53
|
+
*
|
|
54
|
+
* Strings, numbers and booleans are turned into strings with `String()` and matched
|
|
55
|
+
* against the keys of the map. Anything else (objects, arrays, null, undefined) is not
|
|
56
|
+
* matched.
|
|
57
|
+
*/
|
|
58
|
+
function toCategoricalKey(value) {
|
|
59
|
+
if (typeof value === 'string')
|
|
60
|
+
return value;
|
|
61
|
+
if (typeof value === 'number')
|
|
62
|
+
return Number.isFinite(value) ? String(value) : null;
|
|
63
|
+
if (typeof value === 'boolean')
|
|
64
|
+
return String(value);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Computes the number used by graduated / continuous
|
|
69
|
+
*
|
|
70
|
+
* No type conversion is done. Non-numbers (numeric strings included), NaN and Infinity
|
|
71
|
+
* give null.
|
|
72
|
+
*/
|
|
73
|
+
function toFiniteNumber(value) {
|
|
74
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Computes the class of graduated
|
|
78
|
+
*
|
|
79
|
+
* `breaks` are the boundary values in ascending order (n of them) and `colors` has n + 1
|
|
80
|
+
* entries. If the value v is below `breaks[i]` it is `colors[i]`, and if it is below no
|
|
81
|
+
* boundary at all it is `colors[n]`.
|
|
82
|
+
*/
|
|
83
|
+
function graduatedIndex(breaks, value) {
|
|
84
|
+
for (let i = 0; i < breaks.length; i++) {
|
|
85
|
+
if (value < breaks[i])
|
|
86
|
+
return i;
|
|
87
|
+
}
|
|
88
|
+
return breaks.length;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Evaluates a style rule against the attributes of a feature and returns a color.
|
|
92
|
+
*
|
|
93
|
+
* When the attribute is missing or its type does not match, the rule's `other` is
|
|
94
|
+
* returned. `single` does not look at attributes, so it is always the same color.
|
|
95
|
+
* `categorical` matches strings, numbers and booleans by `String(value)`; `graduated` and
|
|
96
|
+
* `continuous` take finite numbers only (a numeric string gives `other`). `continuous`
|
|
97
|
+
* clamps values outside `min`..`max` and returns the first ramp color when `max <= min`. It
|
|
98
|
+
* is a pure function.
|
|
99
|
+
*
|
|
100
|
+
* @param rule The style rule
|
|
101
|
+
* @param properties The attributes of the feature
|
|
102
|
+
* @returns The color in `#RRGGBB` form
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* import { evaluateStyleRule, type StyleRule } from '@sakuzu/maplibre-gl-draw';
|
|
107
|
+
*
|
|
108
|
+
* const rule: StyleRule = {
|
|
109
|
+
* kind: 'graduated',
|
|
110
|
+
* property: 'population',
|
|
111
|
+
* breaks: [1000, 10000],
|
|
112
|
+
* colors: ['#fee8c8', '#fdbb84', '#e34a33'],
|
|
113
|
+
* other: '#cccccc',
|
|
114
|
+
* };
|
|
115
|
+
* evaluateStyleRule(rule, { population: 5000 }); // '#fdbb84'
|
|
116
|
+
* evaluateStyleRule(rule, { population: '5000' }); // '#cccccc' (not a number)
|
|
117
|
+
* evaluateStyleRule(rule, {}); // '#cccccc'
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export function evaluateStyleRule(rule, properties) {
|
|
121
|
+
if (rule.kind === 'single') {
|
|
122
|
+
return rule.color;
|
|
123
|
+
}
|
|
124
|
+
return evaluateStyleRuleValue(rule, properties?.[rule.property]);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Evaluates a style rule against the value of the attribute it reads
|
|
128
|
+
*
|
|
129
|
+
* The same result as `evaluateStyleRule(rule, { [rule.property]: value })`, for a caller that
|
|
130
|
+
* holds the attribute as a column rather than as the properties of a feature.
|
|
131
|
+
*
|
|
132
|
+
* @internal
|
|
133
|
+
*/
|
|
134
|
+
export function evaluateStyleRuleValue(rule, value) {
|
|
135
|
+
if (rule.kind === 'single') {
|
|
136
|
+
return rule.color;
|
|
137
|
+
}
|
|
138
|
+
if (rule.kind === 'categorical') {
|
|
139
|
+
const key = toCategoricalKey(value);
|
|
140
|
+
if (key === null)
|
|
141
|
+
return rule.other;
|
|
142
|
+
const color = rule.map[key];
|
|
143
|
+
return color ?? rule.other;
|
|
144
|
+
}
|
|
145
|
+
const numeric = toFiniteNumber(value);
|
|
146
|
+
if (numeric === null)
|
|
147
|
+
return rule.other;
|
|
148
|
+
if (rule.kind === 'graduated') {
|
|
149
|
+
const color = rule.colors[graduatedIndex(rule.breaks, numeric)];
|
|
150
|
+
// An invalid rule whose colors count falls short of breaks + 1 falls back to other
|
|
151
|
+
return color ?? rule.other;
|
|
152
|
+
}
|
|
153
|
+
// continuous: linearly interpolates the 2 colors of the ramp over min..max
|
|
154
|
+
// (out-of-range values are clamped)
|
|
155
|
+
const [from, to] = rule.ramp;
|
|
156
|
+
if (!(rule.max > rule.min))
|
|
157
|
+
return from;
|
|
158
|
+
const t = Math.min(1, Math.max(0, (numeric - rule.min) / (rule.max - rule.min)));
|
|
159
|
+
return interpolateHexColor(from, to, t);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Returns the rule color of a feature, or null when there is no rule.
|
|
163
|
+
*
|
|
164
|
+
* Returns null when there is no rule. The precedence of the feature's own style is a
|
|
165
|
+
* per-channel decision, so it is not decided here (`applyRuleColor` does it).
|
|
166
|
+
*
|
|
167
|
+
* @param feature The target feature
|
|
168
|
+
* @param rule The style rule of the layer (undefined when it is not set)
|
|
169
|
+
* @returns The rule color (in #RRGGBB form). null when there is no rule
|
|
170
|
+
*/
|
|
171
|
+
export function resolveRuleColor(feature, rule) {
|
|
172
|
+
if (!rule)
|
|
173
|
+
return null;
|
|
174
|
+
return evaluateStyleRule(rule, feature.properties);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Returns the style of a feature with the rule color put on the color property of a
|
|
178
|
+
* channel.
|
|
179
|
+
*
|
|
180
|
+
* A feature that has its own color property for the relevant channel beats the rule, so
|
|
181
|
+
* in that case the original style is returned as is. Properties other than colors (stroke
|
|
182
|
+
* width, opacity and so on) are used together with the rule color.
|
|
183
|
+
*
|
|
184
|
+
* @param style The feature's own style
|
|
185
|
+
* @param ruleColor The rule color (null means there is no rule)
|
|
186
|
+
* @param channel The channel that carries the rule color
|
|
187
|
+
* @returns The effective style: the input itself when `ruleColor` is null or the feature
|
|
188
|
+
* has its own color for the channel, otherwise a new object
|
|
189
|
+
*/
|
|
190
|
+
export function applyRuleColor(style, ruleColor, channel) {
|
|
191
|
+
if (ruleColor === null)
|
|
192
|
+
return style;
|
|
193
|
+
const property = CHANNEL_COLOR_PROPERTY[channel];
|
|
194
|
+
if (style?.[property])
|
|
195
|
+
return style;
|
|
196
|
+
return { ...style, [property]: ruleColor };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Returns the effective style of a feature under the style rule of its layer.
|
|
200
|
+
*
|
|
201
|
+
* A combination of `resolveRuleColor` and `applyRuleColor`. The rendering path that uses a
|
|
202
|
+
* cache caches only the resolution of the rule color, so it calls the two separately.
|
|
203
|
+
*
|
|
204
|
+
* @param feature The target feature
|
|
205
|
+
* @param rule The style rule of the layer
|
|
206
|
+
* @param channel The channel that carries the rule color
|
|
207
|
+
* @returns The effective style
|
|
208
|
+
*/
|
|
209
|
+
export function resolveFeatureStyle(feature, rule, channel) {
|
|
210
|
+
const style = feature.style;
|
|
211
|
+
return applyRuleColor(style, resolveRuleColor(feature, rule), channel);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Builds the class label of graduated
|
|
215
|
+
*
|
|
216
|
+
* Numbers are turned into strings with `String()` as they are (formatting such as digit
|
|
217
|
+
* grouping and units is the caller's responsibility).
|
|
218
|
+
*/
|
|
219
|
+
function graduatedLabel(breaks, index, messages) {
|
|
220
|
+
if (breaks.length === 0)
|
|
221
|
+
return messages.legendAll;
|
|
222
|
+
if (index === 0)
|
|
223
|
+
return messages.legendBelow(String(breaks[0]));
|
|
224
|
+
if (index >= breaks.length)
|
|
225
|
+
return messages.legendAtLeast(String(breaks[breaks.length - 1]));
|
|
226
|
+
return messages.legendRange(String(breaks[index - 1]), String(breaks[index]));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Derives the rows of a legend from a style rule; the library does not draw the legend.
|
|
230
|
+
*
|
|
231
|
+
* Every label that is not a value of the data comes from the messages table (English by
|
|
232
|
+
* default; see `Messages`). The rules for turning labels into strings are as follows.
|
|
233
|
+
*
|
|
234
|
+
* - single: 1 entry. The label is `legendAll` ("All")
|
|
235
|
+
* - categorical: the keys of `map` become the labels as they are, lined up in declaration
|
|
236
|
+
* order. `legendOther` ("Other", the color of `other`) is appended at the end
|
|
237
|
+
* - graduated: the boundary notation of each class (`legendBelow` "Below 10",
|
|
238
|
+
* `legendRange` "10 to below 20", `legendAtLeast` "20 or more"). `legendOther` is
|
|
239
|
+
* appended at the end
|
|
240
|
+
* - continuous: only the 2 end points `min` and `max` (no intermediate colors).
|
|
241
|
+
* `legendOther` is appended at the end
|
|
242
|
+
*
|
|
243
|
+
* Numbers are turned into strings with `String()`. Locale formatting is up to the caller.
|
|
244
|
+
*
|
|
245
|
+
* @param rule The style rule
|
|
246
|
+
* @param messages The entries of the messages table to use (default: `MESSAGES_EN`;
|
|
247
|
+
* missing entries fall back to it)
|
|
248
|
+
* @returns The legend rows, in the order to show them
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* import { deriveLegend, type StyleRule } from '@sakuzu/maplibre-gl-draw';
|
|
253
|
+
*
|
|
254
|
+
* const rule: StyleRule = {
|
|
255
|
+
* kind: 'graduated',
|
|
256
|
+
* property: 'population',
|
|
257
|
+
* breaks: [1000, 10000],
|
|
258
|
+
* colors: ['#fee8c8', '#fdbb84', '#e34a33'],
|
|
259
|
+
* other: '#cccccc',
|
|
260
|
+
* };
|
|
261
|
+
* deriveLegend(rule);
|
|
262
|
+
* // [
|
|
263
|
+
* // { label: 'Below 1000', color: '#fee8c8' },
|
|
264
|
+
* // { label: '1000 to below 10000', color: '#fdbb84' },
|
|
265
|
+
* // { label: '10000 or more', color: '#e34a33' },
|
|
266
|
+
* // { label: 'Other', color: '#cccccc' },
|
|
267
|
+
* // ]
|
|
268
|
+
*
|
|
269
|
+
* // In the language of the host application
|
|
270
|
+
* deriveLegend(rule, { legendOther: 'Autres', legendBelow: (upper) => `Moins de ${upper}` });
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
export function deriveLegend(rule, messages) {
|
|
274
|
+
const table = messages ? resolveMessages(messages) : MESSAGES_EN;
|
|
275
|
+
if (rule.kind === 'single') {
|
|
276
|
+
return [{ label: table.legendAll, color: rule.color }];
|
|
277
|
+
}
|
|
278
|
+
if (rule.kind === 'categorical') {
|
|
279
|
+
const entries = Object.keys(rule.map).map((key) => ({
|
|
280
|
+
label: key,
|
|
281
|
+
color: rule.map[key],
|
|
282
|
+
}));
|
|
283
|
+
entries.push({ label: table.legendOther, color: rule.other });
|
|
284
|
+
return entries;
|
|
285
|
+
}
|
|
286
|
+
if (rule.kind === 'graduated') {
|
|
287
|
+
const count = Math.min(rule.colors.length, rule.breaks.length + 1);
|
|
288
|
+
const entries = [];
|
|
289
|
+
for (let i = 0; i < count; i++) {
|
|
290
|
+
entries.push({ label: graduatedLabel(rule.breaks, i, table), color: rule.colors[i] });
|
|
291
|
+
}
|
|
292
|
+
entries.push({ label: table.legendOther, color: rule.other });
|
|
293
|
+
return entries;
|
|
294
|
+
}
|
|
295
|
+
return [
|
|
296
|
+
{ label: String(rule.min), color: rule.ramp[0] },
|
|
297
|
+
{ label: String(rule.max), color: rule.ramp[1] },
|
|
298
|
+
{ label: table.legendOther, color: rule.other },
|
|
299
|
+
];
|
|
300
|
+
}
|