@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,726 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
import { isLocallyHidden } from '../../store/local-visibility.js';
|
|
4
|
+
import { layerDrawFactors } from '../renderers/draw-factors.js';
|
|
5
|
+
import { getRenderableTerrainTiles, getTerrainMeshSize, getTerrainTileData, } from '../terrain/detect.js';
|
|
6
|
+
import { DrapeTileStore } from '../terrain/drape/bin-store.js';
|
|
7
|
+
import { drapeSelectionKey } from '../terrain/drape/binning.js';
|
|
8
|
+
import { canDrape, collectDrapeElements, drapeLayerSource, } from '../terrain/drape/pass.js';
|
|
9
|
+
import { QuadDrapeRenderer } from '../terrain/drape/quad.js';
|
|
10
|
+
import { DRAPE_MAX_SOURCES, DrapeRenderer } from '../terrain/drape/renderer.js';
|
|
11
|
+
import { buildTileKeySet, resolveTileEdges, wrappedTileKey } from '../terrain/drape/stitch.js';
|
|
12
|
+
import { circumferenceAtLatitude, tileCenterLatitude } from '../terrain/metrics.js';
|
|
13
|
+
import { getTerrainDrapeDebug, setDrapePaintedDatasets, setTerrainDrapeDebug, } from '../terrain/state.js';
|
|
14
|
+
/**
|
|
15
|
+
* Lower bound of the zoom at which the analytic drape is used
|
|
16
|
+
*
|
|
17
|
+
* A view wider than this is handled by the vertex displacement path and the fills are drawn
|
|
18
|
+
* without depth. There are three reasons.
|
|
19
|
+
*
|
|
20
|
+
* - Over a wide area the relief is only a dozen or so pixels on screen, so there is no benefit
|
|
21
|
+
* in solving it as ground pixels (with the depth off, the punch-through of the vertex
|
|
22
|
+
* displacement disappears by construction as well)
|
|
23
|
+
* - A wide-area tile holds all of the features, so the budget of the analytic evaluation is
|
|
24
|
+
* often exceeded and it degenerates. Fixing the boundary by zoom keeps the paths from
|
|
25
|
+
* flapping within the band (every flap re-bakes the retained batches, so the fills disappear
|
|
26
|
+
* for a few seconds)
|
|
27
|
+
* - Over a wide area, building the index costs on the order of 20 ms per tile. Not going
|
|
28
|
+
* through it reduces the stutter of zooming
|
|
29
|
+
*/
|
|
30
|
+
export const TERRAIN_ANALYTIC_MIN_ZOOM = 11;
|
|
31
|
+
/**
|
|
32
|
+
* Time that may be spent building the tile index in one frame (milliseconds)
|
|
33
|
+
*
|
|
34
|
+
* Only the tiles that newly entered the view are built, so it is usually 1 to 3 tiles. What
|
|
35
|
+
* exceeds the budget is deferred to the next frame (at least one tile is always built). With the
|
|
36
|
+
* time slicing off (`timeSlicing: false` of the rendering settings) every tile is built in the
|
|
37
|
+
* frame.
|
|
38
|
+
*/
|
|
39
|
+
const DRAPE_BIN_BUDGET_MS = 8;
|
|
40
|
+
/**
|
|
41
|
+
* Number of consecutive frames before the analytic drape counts as "in use"
|
|
42
|
+
*
|
|
43
|
+
* A dataset drops its polygons and lines from the retained batch once it hands them to the
|
|
44
|
+
* drape, so if the decision to hand over flickers, the re-baking goes back and forth and the
|
|
45
|
+
* fills disappear. The hand-over happens only once things have settled, and it is taken back
|
|
46
|
+
* immediately once the drape can no longer be used (only one side is relaxed).
|
|
47
|
+
*/
|
|
48
|
+
export const DRAPE_STABLE_FRAMES = 10;
|
|
49
|
+
/**
|
|
50
|
+
* Upper limit of the frames that may keep drawing with the previous plan while waiting for the
|
|
51
|
+
* index
|
|
52
|
+
*
|
|
53
|
+
* Even if the index stays unbuildable, the old plan must not be kept forever. Beyond 60 frames
|
|
54
|
+
* (about a second) it is redrawn with whatever could be built.
|
|
55
|
+
*/
|
|
56
|
+
export const DRAPE_STALE_PLAN_MAX_FRAMES = 60;
|
|
57
|
+
/**
|
|
58
|
+
* Number of edges for which the analytic drape is allowed in a wide band
|
|
59
|
+
*
|
|
60
|
+
* Over a wide area one tile holds all of the features, so the cost of building the index is
|
|
61
|
+
* determined by the number of edges. A few thousand can be built in under a millisecond per
|
|
62
|
+
* tile.
|
|
63
|
+
*/
|
|
64
|
+
export const DRAPE_WIDE_EDGE_BUDGET = 20000;
|
|
65
|
+
/**
|
|
66
|
+
* Zoom used to estimate the margin of the index
|
|
67
|
+
*
|
|
68
|
+
* The thickness of a line changes with the factor from its base zoom, so the margin changes
|
|
69
|
+
* with the zoom too. The index cannot be rebuilt for the fraction of every frame, however, so
|
|
70
|
+
* it is rounded to one step and pushed to the safe side (half a step thicker).
|
|
71
|
+
*/
|
|
72
|
+
const marginZoom = (zoom) => Math.round(zoom) + 0.5;
|
|
73
|
+
/** The diagnostic values of a frame without terrain */
|
|
74
|
+
const TERRAIN_OFF_DEBUG = {
|
|
75
|
+
used: false,
|
|
76
|
+
reason: 'terrain-off',
|
|
77
|
+
featureCount: 0,
|
|
78
|
+
edgeCount: 0,
|
|
79
|
+
tileCount: 0,
|
|
80
|
+
maxRunsPerCell: 0,
|
|
81
|
+
maxEdgesPerCell: 0,
|
|
82
|
+
maxTileEdges: 0,
|
|
83
|
+
truncatedCells: 0,
|
|
84
|
+
unfitTiles: 0,
|
|
85
|
+
insideRuns: 0,
|
|
86
|
+
excluded: 0,
|
|
87
|
+
immediate: 0,
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Plans the analytic drape frame by frame
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
export class DrapePlanner {
|
|
95
|
+
constructor(deps) {
|
|
96
|
+
Object.defineProperty(this, "deps", {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
configurable: true,
|
|
99
|
+
writable: true,
|
|
100
|
+
value: void 0
|
|
101
|
+
});
|
|
102
|
+
/**
|
|
103
|
+
* Store of the binning results per tile
|
|
104
|
+
*
|
|
105
|
+
* The index only changes on an edit or when the view is swapped, so it is cached per tile and
|
|
106
|
+
* only the tiles that newly entered the view are built within the budget of the frame (there is
|
|
107
|
+
* no re-binning every frame).
|
|
108
|
+
*/
|
|
109
|
+
Object.defineProperty(this, "tileStore", {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value: new DrapeTileStore()
|
|
114
|
+
});
|
|
115
|
+
/** Factors per source (x = opacity, y = size). Rewritten every frame */
|
|
116
|
+
Object.defineProperty(this, "sourceFactors", {
|
|
117
|
+
enumerable: true,
|
|
118
|
+
configurable: true,
|
|
119
|
+
writable: true,
|
|
120
|
+
value: new Float32Array(DRAPE_MAX_SOURCES * 2)
|
|
121
|
+
});
|
|
122
|
+
/**
|
|
123
|
+
* The analytic drape (the path that paints features as ground pixels)
|
|
124
|
+
*
|
|
125
|
+
* It is used only when the terrain is active and the features fit in the budget. When it
|
|
126
|
+
* cannot be used, it falls back to the previous vertex displacement path (two stages).
|
|
127
|
+
*/
|
|
128
|
+
Object.defineProperty(this, "drapeRenderer", {
|
|
129
|
+
enumerable: true,
|
|
130
|
+
configurable: true,
|
|
131
|
+
writable: true,
|
|
132
|
+
value: null
|
|
133
|
+
});
|
|
134
|
+
/**
|
|
135
|
+
* Analytic drape of the textured quads (Image, and the fill of a quad that carries text)
|
|
136
|
+
*
|
|
137
|
+
* It holds independently of the drape of polygons and lines. A quad does not need its style
|
|
138
|
+
* packed into a texture and can be drawn with the uniforms of its four corners and a single
|
|
139
|
+
* texture, so it can be used even in a frame where a dataset makes the polygons
|
|
140
|
+
* and lines degenerate.
|
|
141
|
+
*/
|
|
142
|
+
Object.defineProperty(this, "quadDrapeRenderer", {
|
|
143
|
+
enumerable: true,
|
|
144
|
+
configurable: true,
|
|
145
|
+
writable: true,
|
|
146
|
+
value: null
|
|
147
|
+
});
|
|
148
|
+
/** Revision of the features and styles (advanced by a Store change; triggers re-binning) */
|
|
149
|
+
Object.defineProperty(this, "revision", {
|
|
150
|
+
enumerable: true,
|
|
151
|
+
configurable: true,
|
|
152
|
+
writable: true,
|
|
153
|
+
value: 0
|
|
154
|
+
});
|
|
155
|
+
/** Key of the conditions under which the elements were collected most recently */
|
|
156
|
+
Object.defineProperty(this, "collectKey", {
|
|
157
|
+
enumerable: true,
|
|
158
|
+
configurable: true,
|
|
159
|
+
writable: true,
|
|
160
|
+
value: ''
|
|
161
|
+
});
|
|
162
|
+
/** The set of elements collected most recently */
|
|
163
|
+
Object.defineProperty(this, "collected", {
|
|
164
|
+
enumerable: true,
|
|
165
|
+
configurable: true,
|
|
166
|
+
writable: true,
|
|
167
|
+
value: null
|
|
168
|
+
});
|
|
169
|
+
/**
|
|
170
|
+
* Whether it is light enough to use the analytic drape even in a wide band
|
|
171
|
+
*
|
|
172
|
+
* It is decided by the number of edges of the elements collected last. It does not hold for
|
|
173
|
+
* heavy data such as administrative boundaries, and always holds on a map with only freehand
|
|
174
|
+
* lines or a few polygons. It does not hold before collecting (the first time), so it switches
|
|
175
|
+
* one frame late.
|
|
176
|
+
*/
|
|
177
|
+
Object.defineProperty(this, "lightEnough", {
|
|
178
|
+
enumerable: true,
|
|
179
|
+
configurable: true,
|
|
180
|
+
writable: true,
|
|
181
|
+
value: false
|
|
182
|
+
});
|
|
183
|
+
/** The most recent plan */
|
|
184
|
+
Object.defineProperty(this, "plan", {
|
|
185
|
+
enumerable: true,
|
|
186
|
+
configurable: true,
|
|
187
|
+
writable: true,
|
|
188
|
+
value: null
|
|
189
|
+
});
|
|
190
|
+
/** Identifies the pack the current plan was built from (a new pack invalidates it) */
|
|
191
|
+
Object.defineProperty(this, "planPackId", {
|
|
192
|
+
enumerable: true,
|
|
193
|
+
configurable: true,
|
|
194
|
+
writable: true,
|
|
195
|
+
value: -1
|
|
196
|
+
});
|
|
197
|
+
/** Number of frames in which the analytic drape has stayed usable */
|
|
198
|
+
Object.defineProperty(this, "stableFrames", {
|
|
199
|
+
enumerable: true,
|
|
200
|
+
configurable: true,
|
|
201
|
+
writable: true,
|
|
202
|
+
value: 0
|
|
203
|
+
});
|
|
204
|
+
/** Number of consecutive frames that keep drawing with the previous plan */
|
|
205
|
+
Object.defineProperty(this, "stalePlanFrames", {
|
|
206
|
+
enumerable: true,
|
|
207
|
+
configurable: true,
|
|
208
|
+
writable: true,
|
|
209
|
+
value: 0
|
|
210
|
+
});
|
|
211
|
+
/** The set of hand-overs currently reported to the datasets (kept to prevent flapping) */
|
|
212
|
+
Object.defineProperty(this, "handoff", {
|
|
213
|
+
enumerable: true,
|
|
214
|
+
configurable: true,
|
|
215
|
+
writable: true,
|
|
216
|
+
value: null
|
|
217
|
+
});
|
|
218
|
+
/** Whether the most recent frame left work for later frames (see `hasPendingWork`) */
|
|
219
|
+
Object.defineProperty(this, "pendingWork", {
|
|
220
|
+
enumerable: true,
|
|
221
|
+
configurable: true,
|
|
222
|
+
writable: true,
|
|
223
|
+
value: false
|
|
224
|
+
});
|
|
225
|
+
this.deps = deps;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Whether the most recent frame left work that later frames finish on their own: tiles of the
|
|
229
|
+
* index not built yet (the previous plan drawn meanwhile), or a hand-over to the datasets
|
|
230
|
+
* waiting for the drape to stay usable (`DRAPE_STABLE_FRAMES`). A repaint is requested for
|
|
231
|
+
* each, so the work finishes without the host doing anything
|
|
232
|
+
*/
|
|
233
|
+
get hasPendingWork() {
|
|
234
|
+
return this.pendingWork;
|
|
235
|
+
}
|
|
236
|
+
/** The drape renderer (null until a frame needed it, and after the GPU side was dropped) */
|
|
237
|
+
get renderer() {
|
|
238
|
+
return this.drapeRenderer;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* The Store features that do not go on the drape (drawn by the other paths)
|
|
242
|
+
*
|
|
243
|
+
* Empty when there is no plan.
|
|
244
|
+
*/
|
|
245
|
+
get excluded() {
|
|
246
|
+
return this.plan?.excluded ?? new Set();
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* The breaks of the stacking order (images) of the pack being drawn
|
|
250
|
+
*
|
|
251
|
+
* They are taken from "the pack being drawn". Taking them from the pack that was just
|
|
252
|
+
* collected would make the numbers disagree with the element list while the index is being
|
|
253
|
+
* rebuilt (while the old pack is still being drawn), and the sectioned drawing would paint
|
|
254
|
+
* different elements or nothing at all.
|
|
255
|
+
*/
|
|
256
|
+
get quadBreaks() {
|
|
257
|
+
return this.tileStore.quadBreaks;
|
|
258
|
+
}
|
|
259
|
+
/** Whether some element of the pack being drawn is selected */
|
|
260
|
+
get hasSelection() {
|
|
261
|
+
return (this.tileStore.pack?.markedCount ?? 0) > 0;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Marks the collected elements stale (a change of the geometry, the style, the membership or
|
|
265
|
+
* the order)
|
|
266
|
+
*/
|
|
267
|
+
invalidate() {
|
|
268
|
+
this.revision++;
|
|
269
|
+
}
|
|
270
|
+
/** The quad drape renderer (created on first use) */
|
|
271
|
+
quadRenderer(gl) {
|
|
272
|
+
if (!this.quadDrapeRenderer)
|
|
273
|
+
this.quadDrapeRenderer = new QuadDrapeRenderer(gl);
|
|
274
|
+
return this.quadDrapeRenderer;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Decides whether the analytic drape is used in this frame
|
|
278
|
+
*
|
|
279
|
+
* It also reports the datasets that hand their polygons and lines over to the drape, and
|
|
280
|
+
* those it is actually painting in this frame.
|
|
281
|
+
*/
|
|
282
|
+
planFrame(input) {
|
|
283
|
+
const { terrain } = this.deps;
|
|
284
|
+
const { mapTerrain, dpr, zoom, rawZoom } = input;
|
|
285
|
+
let drapeUsable = false;
|
|
286
|
+
this.pendingWork = false;
|
|
287
|
+
// The analytic drape is used even in a wide band when building the index is light. Cutting
|
|
288
|
+
// uniformly by zoom alone would swap "a picture pinned to the ground" and "a flat picture" at
|
|
289
|
+
// the boundary of the band, making the positions and the look of the features jump. It is
|
|
290
|
+
// heavy only when the features are many, so it is decided by cost (the test on the amount is
|
|
291
|
+
// inside prepare; here only the band is looked at)
|
|
292
|
+
// The band is decided with the real zoom. The zoom that the rendering reads is a value that
|
|
293
|
+
// absorbs the settlements while at rest, and it drifts up to about 0.2 from the real zoom.
|
|
294
|
+
// Deciding the band with it would take the path out of the band while the real zoom is inside
|
|
295
|
+
// it, making the features look peeled off the ground (beaded lines, flat polygons)
|
|
296
|
+
// The elements are collected before the band is decided (the band is decided by cost, so the
|
|
297
|
+
// cost has to be known first). The collected result is folded behind a key, so there is no
|
|
298
|
+
// cost as long as the contents do not change
|
|
299
|
+
if (mapTerrain !== null)
|
|
300
|
+
this.collect(input.resolveStyles, dpr, zoom);
|
|
301
|
+
const analyticBand = rawZoom > TERRAIN_ANALYTIC_MIN_ZOOM || this.lightEnough;
|
|
302
|
+
if (mapTerrain !== null && analyticBand) {
|
|
303
|
+
drapeUsable = this.prepare(input.gl, mapTerrain, input.resolveStyles, dpr, zoom);
|
|
304
|
+
}
|
|
305
|
+
else if (mapTerrain !== null) {
|
|
306
|
+
// A wide band is handled by the vertex displacement path (no index is built either)
|
|
307
|
+
this.plan = null;
|
|
308
|
+
if (getTerrainDrapeDebug(terrain).reason !== 'wide-zoom') {
|
|
309
|
+
setTerrainDrapeDebug(terrain, {
|
|
310
|
+
...getTerrainDrapeDebug(terrain),
|
|
311
|
+
used: false,
|
|
312
|
+
reason: 'wide-zoom',
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else if (getTerrainDrapeDebug(terrain).reason !== 'terrain-off') {
|
|
317
|
+
setTerrainDrapeDebug(terrain, { ...TERRAIN_OFF_DEBUG });
|
|
318
|
+
}
|
|
319
|
+
// Report the datasets that hand their polygons and lines to the analytic drape. A
|
|
320
|
+
// dataset that handed them over does not push solid polygons and lines onto its retained
|
|
321
|
+
// batch (the same thing is not drawn twice). The decision to hand over is made only once
|
|
322
|
+
// things have settled (DRAPE_STABLE_FRAMES). It is released immediately only for a reason
|
|
323
|
+
// that settles "the analytic path will not be used any more" (terrain off, wide band, budget
|
|
324
|
+
// exceeded and so on), while a transient failure (an unresolved DEM) keeps the previous
|
|
325
|
+
// decision. Releasing the hand-over on a single frame of jitter would run a storm of
|
|
326
|
+
// re-baking polygons and lines on every pan.
|
|
327
|
+
this.stableFrames = drapeUsable ? this.stableFrames + 1 : 0;
|
|
328
|
+
if (drapeUsable && this.stableFrames >= DRAPE_STABLE_FRAMES) {
|
|
329
|
+
this.handoff = this.collected?.drapedDatasets ?? null;
|
|
330
|
+
}
|
|
331
|
+
else if (drapeUsable) {
|
|
332
|
+
// The hand-over is decided by the frames to come: they are asked for, so that it settles
|
|
333
|
+
// on a map that is not moving as well
|
|
334
|
+
this.pendingWork = true;
|
|
335
|
+
this.deps.map?.triggerRepaint?.();
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
const reason = getTerrainDrapeDebug(terrain).reason;
|
|
339
|
+
if (reason !== 'no-dem-tiles')
|
|
340
|
+
this.handoff = null;
|
|
341
|
+
}
|
|
342
|
+
this.deps.datasets?.setDrapedDatasets(this.handoff);
|
|
343
|
+
// "Whether it is actually painting right now" is reported as well. The hand-over decision
|
|
344
|
+
// waits until things settle, so for the few frames between the drape starting to paint and
|
|
345
|
+
// the decision coming back, only the selection highlight falls to the immediate path and
|
|
346
|
+
// becomes a billboard (the reason is drapePaintedDatasets in terrain/context.ts)
|
|
347
|
+
setDrapePaintedDatasets(terrain, drapeUsable ? (this.collected?.drapedDatasets ?? null) : null);
|
|
348
|
+
return drapeUsable;
|
|
349
|
+
}
|
|
350
|
+
/** Records how many features went to the immediate path in a frame that used the drape */
|
|
351
|
+
reportImmediate(count) {
|
|
352
|
+
const { terrain } = this.deps;
|
|
353
|
+
setTerrainDrapeDebug(terrain, { ...getTerrainDrapeDebug(terrain), immediate: count });
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* The draw instructions of the analytic drape (the stitching per tile is derived exactly
|
|
357
|
+
* once)
|
|
358
|
+
*
|
|
359
|
+
* The sectioned drawing (interleaving the images, drawing a segment per slot) draws the same
|
|
360
|
+
* tile several times, so the derivation is done once per frame.
|
|
361
|
+
*/
|
|
362
|
+
buildDraws(input) {
|
|
363
|
+
const { store, terrain } = this.deps;
|
|
364
|
+
const { mapTerrain, getProjectionData } = input;
|
|
365
|
+
let ready = false;
|
|
366
|
+
const tileDraws = [];
|
|
367
|
+
const fallbackQuads = [];
|
|
368
|
+
const pendingQuads = [];
|
|
369
|
+
const drawnQuadBreaks = input.drapeUsable ? this.tileStore.quadBreaks : [];
|
|
370
|
+
const drapeRenderer = this.drapeRenderer;
|
|
371
|
+
const drapePlan = this.plan;
|
|
372
|
+
if (input.drapeUsable && drapeRenderer && drapePlan) {
|
|
373
|
+
ready = drapeRenderer.ensure(input.shaderData, drapePlan.meshSize);
|
|
374
|
+
if (!ready) {
|
|
375
|
+
setTerrainDrapeDebug(terrain, {
|
|
376
|
+
...getTerrainDrapeDebug(terrain),
|
|
377
|
+
used: false,
|
|
378
|
+
reason: drapeRenderer.lastError || 'ensure-failed',
|
|
379
|
+
});
|
|
380
|
+
// The images that were to be interleaved between the sections are drawn by the first
|
|
381
|
+
// slot. They are excluded from the later layer rendering, so without a drawer only the
|
|
382
|
+
// images would disappear
|
|
383
|
+
for (const brk of drawnQuadBreaks) {
|
|
384
|
+
const quadFeature = store.getFeature(brk.featureId);
|
|
385
|
+
if (!quadFeature?.visible || isLocallyHidden(quadFeature, store))
|
|
386
|
+
continue;
|
|
387
|
+
fallbackQuads.push(quadFeature);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// The DEM is looked up once per tile in this frame. The same tile also shows up as the
|
|
392
|
+
// constraint source of a neighbour, so the repeated lookups are folded here
|
|
393
|
+
const frameTerrain = new Map();
|
|
394
|
+
const terrainOf = (tile) => {
|
|
395
|
+
const hit = frameTerrain.get(tile);
|
|
396
|
+
if (hit !== undefined)
|
|
397
|
+
return hit;
|
|
398
|
+
const data = mapTerrain ? getTerrainTileData(mapTerrain, tile) : null;
|
|
399
|
+
frameTerrain.set(tile, data);
|
|
400
|
+
return data;
|
|
401
|
+
};
|
|
402
|
+
// Fix the tiles that are actually drawn in this frame first. The "neighbour" of the
|
|
403
|
+
// stitching is taken from here. Treating a tile that is not drawn as a neighbour would
|
|
404
|
+
// constrain to a polyline that nobody draws
|
|
405
|
+
const drawable = [];
|
|
406
|
+
for (const planTile of drapePlan.tiles) {
|
|
407
|
+
// The DEM texture and matrix are the values of this frame. Baking them in would keep
|
|
408
|
+
// solving the ground with the coarse elevation of the moment the parent tile stood in.
|
|
409
|
+
const data = terrainOf(planTile.tile);
|
|
410
|
+
if (!data)
|
|
411
|
+
continue;
|
|
412
|
+
// getProjectionData throws when the shape of tileID does not match. This keeps the
|
|
413
|
+
// whole rendering from failing if it changes between versions.
|
|
414
|
+
let tileProjection = null;
|
|
415
|
+
try {
|
|
416
|
+
tileProjection = getProjectionData({
|
|
417
|
+
tileID: planTile.tile.tileID,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
tileProjection = null;
|
|
422
|
+
}
|
|
423
|
+
if (!tileProjection)
|
|
424
|
+
continue;
|
|
425
|
+
drawable.push({ plan: planTile, terrain: data, projection: tileProjection });
|
|
426
|
+
}
|
|
427
|
+
const drawnKeys = buildTileKeySet(drawable.map((d) => d.plan.tile));
|
|
428
|
+
const drawnByKey = new Map();
|
|
429
|
+
for (const item of drawable)
|
|
430
|
+
drawnByKey.set(wrappedTileKey(item.plan.tile), item.plan.tile);
|
|
431
|
+
// The step, the coordinate transform, the spacing and the DEM of the constraint target
|
|
432
|
+
// are all derived here. They all come from the same single moment of the terrain tile
|
|
433
|
+
// state, so the mismatch "the DEM is new but the step is old" cannot happen. An edge
|
|
434
|
+
// whose neighbour DEM cannot be looked up drops the constraint itself (keeping only the
|
|
435
|
+
// spacing would constrain to a polyline that samples its own DEM coarsely, and the crack
|
|
436
|
+
// would come back just there)
|
|
437
|
+
const segmentMeshSize = drapePlan.meshSize;
|
|
438
|
+
for (const item of drawable) {
|
|
439
|
+
const edges = resolveTileEdges(drawnKeys, item.plan.tile, segmentMeshSize, (n) => {
|
|
440
|
+
const neighbor = drawnByKey.get(wrappedTileKey(n));
|
|
441
|
+
return neighbor ? terrainOf(neighbor) : null;
|
|
442
|
+
});
|
|
443
|
+
tileDraws.push({
|
|
444
|
+
draw: {
|
|
445
|
+
tileID: item.plan.tile.tileID,
|
|
446
|
+
terrain: item.terrain,
|
|
447
|
+
cellOffset: item.plan.cellOffset,
|
|
448
|
+
grid: item.plan.grid,
|
|
449
|
+
groundMeters: item.plan.groundMeters,
|
|
450
|
+
edges,
|
|
451
|
+
},
|
|
452
|
+
projection: item.projection,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
// The breaks of the stacking order (images). The element list is cut at the positions of
|
|
456
|
+
// the images, each section is drawn as a range, and the quad drape of the image is
|
|
457
|
+
// interleaved in between.
|
|
458
|
+
const elementsTotal = this.tileStore.elementCount;
|
|
459
|
+
for (const brk of drawnQuadBreaks) {
|
|
460
|
+
const quadFeature = store.getFeature(brk.featureId);
|
|
461
|
+
if (!quadFeature?.visible || isLocallyHidden(quadFeature, store))
|
|
462
|
+
continue;
|
|
463
|
+
pendingQuads.push({
|
|
464
|
+
at: Math.min(brk.afterElements, elementsTotal),
|
|
465
|
+
feature: quadFeature,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return { ready, tileDraws, pendingQuads, fallbackQuads };
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Drops the GPU side (the drape renderers) and what points into it
|
|
474
|
+
*
|
|
475
|
+
* The plan and the index point into the pack uploaded to the drape renderer, so they go with
|
|
476
|
+
* it (the next frame collects and uploads again).
|
|
477
|
+
*/
|
|
478
|
+
releaseGpu() {
|
|
479
|
+
if (this.drapeRenderer) {
|
|
480
|
+
this.drapeRenderer.dispose();
|
|
481
|
+
this.drapeRenderer = null;
|
|
482
|
+
}
|
|
483
|
+
if (this.quadDrapeRenderer) {
|
|
484
|
+
this.quadDrapeRenderer.dispose();
|
|
485
|
+
this.quadDrapeRenderer = null;
|
|
486
|
+
}
|
|
487
|
+
this.plan = null;
|
|
488
|
+
this.planPackId = -1;
|
|
489
|
+
this.collectKey = '';
|
|
490
|
+
this.collected = null;
|
|
491
|
+
this.tileStore.clear();
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Collects the elements (called before the band is decided)
|
|
495
|
+
*
|
|
496
|
+
* The band (the range of zooms where the analytic drape is used) is decided by "the cost of
|
|
497
|
+
* building the index", so the elements have to be collected first for the cost to be known. If
|
|
498
|
+
* they were collected only inside the band, a map opened at a wide zoom would never learn the
|
|
499
|
+
* cost and would stay outside the band even when it is light (in the field this appeared as
|
|
500
|
+
* "polygons are not drawn at low zooms"). The collected result is folded behind a key, so from
|
|
501
|
+
* the second time on nothing happens as long as the contents do not change.
|
|
502
|
+
*/
|
|
503
|
+
collect(resolveStyles, dpr, zoom) {
|
|
504
|
+
const { store, datasets: manager } = this.deps;
|
|
505
|
+
const datasets = manager?.listInternal() ?? [];
|
|
506
|
+
const key = [
|
|
507
|
+
this.revision,
|
|
508
|
+
dpr,
|
|
509
|
+
marginZoom(zoom),
|
|
510
|
+
store.getLayerOrder().join('/'),
|
|
511
|
+
datasets.map((c) => `${c.id}:${c.drapeRevision}:${c.visible ? 1 : 0}:${c.order}`).join(','),
|
|
512
|
+
bakedLayerOpacityKey(store, datasets.length),
|
|
513
|
+
].join('|');
|
|
514
|
+
let collected = this.collected;
|
|
515
|
+
if (key !== this.collectKey || !collected) {
|
|
516
|
+
collected = collectDrapeElements(store, resolveStyles(), dpr, datasets);
|
|
517
|
+
this.collectKey = key;
|
|
518
|
+
this.collected = collected;
|
|
519
|
+
this.lightEnough = collected.edgeCount <= DRAPE_WIDE_EDGE_BUDGET;
|
|
520
|
+
this.tileStore.sync(key, collected.elements, collected.quadBreaks, collected.entryStarts, collected.aboveStoreStart);
|
|
521
|
+
}
|
|
522
|
+
return collected;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Preparation of the analytic drape (indexing the tiles)
|
|
526
|
+
*
|
|
527
|
+
* The elements are collected only "when the contents, the styles or the stacking order
|
|
528
|
+
* changed", and the tiles are indexed only "when a new tile entered the view". The elements are
|
|
529
|
+
* not collected again just because the view moved (collecting them again would mean rebuilding
|
|
530
|
+
* the whole index).
|
|
531
|
+
*/
|
|
532
|
+
prepare(gl, terrain, resolveStyles, dpr, zoom) {
|
|
533
|
+
const { map, datasets: manager } = this.deps;
|
|
534
|
+
const context = this.deps.terrain;
|
|
535
|
+
const tiles = getRenderableTerrainTiles(terrain);
|
|
536
|
+
if (tiles.length === 0)
|
|
537
|
+
return false;
|
|
538
|
+
const datasets = manager?.listInternal() ?? [];
|
|
539
|
+
const collected = this.collect(resolveStyles, dpr, zoom);
|
|
540
|
+
// The factors per source (which follow the zoom) are rewritten every frame, because baking
|
|
541
|
+
// them into the elements would mean rebuilding the index on every zoom movement
|
|
542
|
+
const drapeSourceFactors = this.sourceFactors;
|
|
543
|
+
drapeSourceFactors.fill(1);
|
|
544
|
+
for (let i = 0; i < datasets.length && i + 1 < DRAPE_MAX_SOURCES; i++) {
|
|
545
|
+
const factors = datasets[i].drapeFactors(zoom);
|
|
546
|
+
drapeSourceFactors[(i + 1) * 2] = factors.opacity;
|
|
547
|
+
drapeSourceFactors[(i + 1) * 2 + 1] = factors.scale;
|
|
548
|
+
}
|
|
549
|
+
// The opacity of each Store layer goes into its own source (read from the Store every frame,
|
|
550
|
+
// so a change of the opacity does not rebuild the index)
|
|
551
|
+
for (const [layerId, source] of collected.layerSources) {
|
|
552
|
+
drapeSourceFactors[source * 2] = layerDrawFactors(this.deps.store.getLayer(layerId)).opacity;
|
|
553
|
+
}
|
|
554
|
+
// The selection highlight is reported every frame too. It does not touch the index
|
|
555
|
+
// (binning); only one texel of the style table changes. Mixing the selection into the key of
|
|
556
|
+
// the dataset would rebuild the index of every tile on every single click.
|
|
557
|
+
const selectionKeys = new Set();
|
|
558
|
+
for (const dataset of datasets) {
|
|
559
|
+
for (const id of dataset.getSelectedIds()) {
|
|
560
|
+
selectionKeys.add(drapeSelectionKey(dataset.id, id));
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
this.tileStore.setSelection(selectionKeys);
|
|
564
|
+
const usable = canDrape({ vertexCount: collected.vertexCount });
|
|
565
|
+
const debugBase = {
|
|
566
|
+
featureCount: collected.elements.length,
|
|
567
|
+
edgeCount: collected.edgeCount,
|
|
568
|
+
tileCount: tiles.length,
|
|
569
|
+
maxRunsPerCell: 0,
|
|
570
|
+
maxEdgesPerCell: 0,
|
|
571
|
+
maxTileEdges: 0,
|
|
572
|
+
truncatedCells: 0,
|
|
573
|
+
unfitTiles: 0,
|
|
574
|
+
insideRuns: 0,
|
|
575
|
+
excluded: collected.excluded.size,
|
|
576
|
+
immediate: 0,
|
|
577
|
+
};
|
|
578
|
+
if (!usable || collected.elements.length === 0) {
|
|
579
|
+
setTerrainDrapeDebug(context, {
|
|
580
|
+
...debugBase,
|
|
581
|
+
used: false,
|
|
582
|
+
reason: collected.elements.length === 0 ? 'no-drapeable-features' : 'vertex-budget',
|
|
583
|
+
});
|
|
584
|
+
this.plan = { tiles: [], excluded: collected.excluded, usable: false, meshSize: 128 };
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
// Prepare the tile index (only the new tiles, within the budget of the frame). Skipping it
|
|
588
|
+
// while moving was introduced once and then withdrawn: during a zoom almost every tile
|
|
589
|
+
// becomes a "new tile", so the fills vanish entirely and are seen coming back one tile at a
|
|
590
|
+
// time after the movement stops. The occasional build hitch (27 to 59 ms on a huge wide-area
|
|
591
|
+
// tile) remains, but it is milder than fills that keep disappearing.
|
|
592
|
+
const drapeTiles = tiles.map((t) => ({ x: t.x, y: t.y, z: t.z }));
|
|
593
|
+
const budget = this.deps.timeSlicing === false ? Number.POSITIVE_INFINITY : DRAPE_BIN_BUDGET_MS;
|
|
594
|
+
const prepared = this.tileStore.prepare(drapeTiles, budget, marginZoom(zoom));
|
|
595
|
+
if (prepared.pending) {
|
|
596
|
+
this.pendingWork = true;
|
|
597
|
+
map?.triggerRepaint?.();
|
|
598
|
+
}
|
|
599
|
+
debugBase.maxTileEdges = prepared.maxTileEdges;
|
|
600
|
+
debugBase.truncatedCells = prepared.truncatedCells;
|
|
601
|
+
debugBase.unfitTiles = prepared.unfitTiles;
|
|
602
|
+
debugBase.maxEdgesPerCell = prepared.maxEdgesPerCell;
|
|
603
|
+
debugBase.maxRunsPerCell = prepared.maxRunsPerCell;
|
|
604
|
+
if (prepared.overflow) {
|
|
605
|
+
setTerrainDrapeDebug(context, { ...debugBase, used: false, reason: 'cell-overflow' });
|
|
606
|
+
this.plan = { tiles: [], excluded: collected.excluded, usable: false, meshSize: 128 };
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
if (!this.drapeRenderer)
|
|
610
|
+
this.drapeRenderer = new DrapeRenderer(gl);
|
|
611
|
+
const meshSize = getTerrainMeshSize(terrain);
|
|
612
|
+
const planTiles = [];
|
|
613
|
+
// The number of tiles that have a DEM but whose index could not be built yet. When the zoom
|
|
614
|
+
// step changes, the tiles of the view are replaced wholesale and, within the budget
|
|
615
|
+
// (DRAPE_BIN_BUDGET_MS), they can only be built over several frames. Such a tile cannot be
|
|
616
|
+
// drawn meanwhile, so a single missing coarse tile in the distance blanks a wide part of the
|
|
617
|
+
// screen for a moment
|
|
618
|
+
let unindexed = 0;
|
|
619
|
+
// An edge whose neighbour is a coarser tile constrains its elevation to the polyline of the
|
|
620
|
+
// coarse side (this removes the gap of a T junction by construction; terrain/drape/stitch.ts)
|
|
621
|
+
for (const tile of tiles) {
|
|
622
|
+
// A tile without a single DEM cannot be drawn later either, so it is dropped. The texture
|
|
623
|
+
// itself is looked up again on every draw, so it is not held here.
|
|
624
|
+
if (!getTerrainTileData(terrain, tile))
|
|
625
|
+
continue;
|
|
626
|
+
const entry = this.tileStore.entryOf(tile);
|
|
627
|
+
// A tile whose index is not built yet appears on a later frame (drawing continues with the
|
|
628
|
+
// previous pack, so what is already shown never disappears)
|
|
629
|
+
if (!entry) {
|
|
630
|
+
unindexed++;
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
// "The ground size of that tile", used for the gradient of the shading
|
|
634
|
+
const tileLat = tileCenterLatitude(tile.y, tile.z);
|
|
635
|
+
const groundMeters = circumferenceAtLatitude(tileLat) / 2 ** tile.z;
|
|
636
|
+
// The stitching per edge is not decided here. The step, the coordinate transform and the
|
|
637
|
+
// spacing are derived at the same single moment as the DEM they are bundled with (right
|
|
638
|
+
// before drawing)
|
|
639
|
+
planTiles.push({ tile, cellOffset: entry.cellOffset, grid: entry.grid, groundMeters });
|
|
640
|
+
}
|
|
641
|
+
const pack = this.tileStore.pack;
|
|
642
|
+
const drapePlan = this.plan;
|
|
643
|
+
if (planTiles.length === 0 || !pack) {
|
|
644
|
+
// In a transient state (only the DEM / index of a new region entered by panning is
|
|
645
|
+
// unresolved) the previous plan is kept and drawing continues. Falling back to an empty
|
|
646
|
+
// plan here would make drapeUsable false for one frame, so the "hand-over" of the
|
|
647
|
+
// datasets would flap between released and restored, and a storm of re-baking polygons
|
|
648
|
+
// and lines (chunk.step on the order of 30 ms) plus a re-collection of drape.collect would
|
|
649
|
+
// run on every pan (measured). The tiles of the previous plan look their DEM up again at
|
|
650
|
+
// draw time, so what is still in view keeps coming out correctly and what disappeared is
|
|
651
|
+
// replaced at the next resolution.
|
|
652
|
+
if (drapePlan?.usable && drapePlan.tiles.length > 0) {
|
|
653
|
+
setTerrainDrapeDebug(context, { ...debugBase, used: true, reason: 'stale-plan' });
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
656
|
+
setTerrainDrapeDebug(context, { ...debugBase, used: false, reason: 'no-dem-tiles' });
|
|
657
|
+
this.plan = { tiles: [], excluded: collected.excluded, usable: false, meshSize };
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
// While the index is incomplete, drawing continues with the previous plan if that one covers
|
|
661
|
+
// more of the view. Drawing with only the tiles that could be built makes the distance drop
|
|
662
|
+
// out for one frame in the middle of a zoom, which looks like a flash. The tiles of the
|
|
663
|
+
// previous plan look their DEM up again on every draw, so their positions are correct and
|
|
664
|
+
// only the index is coarse. To keep it from settling into the previous plan forever, it is
|
|
665
|
+
// kept for a limited number of frames only
|
|
666
|
+
if (unindexed > 0 &&
|
|
667
|
+
drapePlan?.usable &&
|
|
668
|
+
drapePlan.tiles.length > planTiles.length &&
|
|
669
|
+
// The positions of the previous plan are positions within the pack it was built from.
|
|
670
|
+
// Drawing with the previous plan after the pack was swapped would point into the index of
|
|
671
|
+
// a different pack
|
|
672
|
+
this.planPackId === pack.id) {
|
|
673
|
+
this.stalePlanFrames++;
|
|
674
|
+
if (this.stalePlanFrames <= DRAPE_STALE_PLAN_MAX_FRAMES) {
|
|
675
|
+
setTerrainDrapeDebug(context, {
|
|
676
|
+
...debugBase,
|
|
677
|
+
used: true,
|
|
678
|
+
reason: 'stale-plan',
|
|
679
|
+
tileCount: drapePlan.tiles.length,
|
|
680
|
+
});
|
|
681
|
+
this.pendingWork = true;
|
|
682
|
+
map?.triggerRepaint?.();
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
this.stalePlanFrames = 0;
|
|
688
|
+
}
|
|
689
|
+
const uploaded = this.drapeRenderer?.upload(pack) ?? false;
|
|
690
|
+
if (!uploaded) {
|
|
691
|
+
// The tables do not fit in the textures of this GPU: the frame is drawn without the
|
|
692
|
+
// analytic drape, like an index over its budget
|
|
693
|
+
setTerrainDrapeDebug(context, { ...debugBase, used: false, reason: 'texture-limit' });
|
|
694
|
+
this.plan = { tiles: [], excluded: collected.excluded, usable: false, meshSize };
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
setTerrainDrapeDebug(context, {
|
|
698
|
+
...debugBase,
|
|
699
|
+
used: true,
|
|
700
|
+
reason: 'ok',
|
|
701
|
+
tileCount: planTiles.length,
|
|
702
|
+
});
|
|
703
|
+
this.plan = { tiles: planTiles, excluded: collected.excluded, usable: true, meshSize };
|
|
704
|
+
this.planPackId = pack.id;
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* The opacities of the Store layers that have no drape source of their own
|
|
710
|
+
*
|
|
711
|
+
* Those layers have their opacity baked into the colors of their elements, so a change of it
|
|
712
|
+
* has to collect the elements again. Empty while every layer has a source (the usual case).
|
|
713
|
+
*/
|
|
714
|
+
function bakedLayerOpacityKey(store, datasetCount) {
|
|
715
|
+
let key = '';
|
|
716
|
+
let layerIndex = 0;
|
|
717
|
+
for (const layerId of store.getLayerOrder()) {
|
|
718
|
+
const layer = store.getLayer(layerId);
|
|
719
|
+
if (!layer)
|
|
720
|
+
continue;
|
|
721
|
+
if (drapeLayerSource(layerIndex++, datasetCount) === 0) {
|
|
722
|
+
key += `${layerId}:${layerDrawFactors(layer).opacity},`;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return key;
|
|
726
|
+
}
|