@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,122 @@
|
|
|
1
|
+
import type { Store } from '../../../store/store.js';
|
|
2
|
+
import type { Feature } from '../../../store/types.js';
|
|
3
|
+
import type { RetainedStyleResolver } from '../../renderers/retained.js';
|
|
4
|
+
import { type DrapeElement, type DrapeQuadBreak } from './binning.js';
|
|
5
|
+
export type { DrapeQuadBreak };
|
|
6
|
+
/**
|
|
7
|
+
* The upper bound on the number of edges one tile of the view can handle
|
|
8
|
+
*
|
|
9
|
+
* A tile that exceeds it is degraded without being built (building it and then throwing it
|
|
10
|
+
* away would stall the frame for exactly that time). Measured on 8,172 administrative
|
|
11
|
+
* boundaries, one tile at z13 to z16 has a few thousand to 20,000 edges, so there is plenty of
|
|
12
|
+
* room.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DRAPE_MAX_EDGES_PER_TILE = 120000;
|
|
15
|
+
/**
|
|
16
|
+
* The upper bound on the number of vertices that can be put on the drape (for the whole map)
|
|
17
|
+
*
|
|
18
|
+
* The cost of holding the Mercator coordinates (16 bytes per vertex) and the cost of scanning
|
|
19
|
+
* the bounding boxes per tile are capped here. 8,172 administrative boundaries (about 1.1
|
|
20
|
+
* million vertices) fit. A map that exceeds it is drawn with the previous vertex displacement
|
|
21
|
+
* path.
|
|
22
|
+
*/
|
|
23
|
+
export declare const DRAPE_MAX_VERTICES = 4000000;
|
|
24
|
+
/** The collected elements, and the Store features that could not be put on the drape */
|
|
25
|
+
export interface DrapeCollectResult {
|
|
26
|
+
/** The elements in draw order */
|
|
27
|
+
readonly elements: DrapeElement[];
|
|
28
|
+
/** The IDs of the Store features that cannot be put on the drape (points, images, dashed
|
|
29
|
+
* lines and so on) */
|
|
30
|
+
readonly excluded: Set<string>;
|
|
31
|
+
/** The breaks in the stacking order (the positions of the images; dataset order =
|
|
32
|
+
* ascending afterElements) */
|
|
33
|
+
readonly quadBreaks: DrapeQuadBreak[];
|
|
34
|
+
/**
|
|
35
|
+
* The starting position of each entry of the stack (an index into the element list)
|
|
36
|
+
*
|
|
37
|
+
* The index that lets a frame (the CustomLayer of each interval) paint only the elements of
|
|
38
|
+
* its own interval. The elements of the datasets below the stack come before the starting
|
|
39
|
+
* position of the first entry, and the elements of the datasets above the stack are laid
|
|
40
|
+
* out from aboveStoreStart on.
|
|
41
|
+
*/
|
|
42
|
+
readonly entryStarts: ReadonlyMap<string, number>;
|
|
43
|
+
/** The index at which the elements of the datasets above the stack begin (= the end of
|
|
44
|
+
* the elements of the stack) */
|
|
45
|
+
readonly aboveStoreStart: number;
|
|
46
|
+
/** The total number of edges */
|
|
47
|
+
readonly edgeCount: number;
|
|
48
|
+
/** The total number of vertices */
|
|
49
|
+
readonly vertexCount: number;
|
|
50
|
+
/** The IDs of the datasets put on the drape */
|
|
51
|
+
readonly drapedDatasets: Set<string>;
|
|
52
|
+
/**
|
|
53
|
+
* The factor source of each Store layer (layer ID → source)
|
|
54
|
+
*
|
|
55
|
+
* The opacity of a layer is written into its source every frame, so a change of the opacity
|
|
56
|
+
* does not rebuild the index. A layer past the capacity of the sources is not listed: its
|
|
57
|
+
* opacity is baked into the colors of its elements instead (see {@link drapeLayerSource}).
|
|
58
|
+
*/
|
|
59
|
+
readonly layerSources: ReadonlyMap<string, number>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The factor source of the Store layer at `layerIndex` (among the Store layers of the stacking
|
|
63
|
+
* order), or 0 when the sources are used up
|
|
64
|
+
*
|
|
65
|
+
* Source 0 is the neutral source (factor 1), 1 to `datasetCount` are the
|
|
66
|
+
* datasets, and the Store layers follow. A layer that gets 0 has its opacity baked into the
|
|
67
|
+
* colors of its elements, so the planner puts the opacity of such a layer into the key of the
|
|
68
|
+
* dataset (a change of it collects again).
|
|
69
|
+
*/
|
|
70
|
+
export declare function drapeLayerSource(layerIndex: number, datasetCount: number): number;
|
|
71
|
+
/**
|
|
72
|
+
* The view of a dataset restricted to the part the drape needs
|
|
73
|
+
*
|
|
74
|
+
* The implementation in `display/dataset.ts` satisfies this shape. To keep the type
|
|
75
|
+
* dependency one-directional, only the structure is declared here.
|
|
76
|
+
*/
|
|
77
|
+
export interface DrapeDatasetSource {
|
|
78
|
+
readonly id: string;
|
|
79
|
+
readonly order: 'below-store' | 'layer-order' | 'above-store';
|
|
80
|
+
readonly visible: boolean;
|
|
81
|
+
/** The version of the contents, the style and the thinning (when it changes, the index is
|
|
82
|
+
* rebuilt) */
|
|
83
|
+
readonly drapeRevision: number;
|
|
84
|
+
/** The features to put on the drape (with the thinning and the rule colors already
|
|
85
|
+
* applied, in draw order) */
|
|
86
|
+
drapeFeatures(): Feature[];
|
|
87
|
+
/** The IDs of the selected features (needed so that the drape can draw the selection
|
|
88
|
+
* highlight) */
|
|
89
|
+
getSelectedIds(): string[];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Collects the elements of the analytic drape from the Store and the datasets
|
|
93
|
+
*
|
|
94
|
+
* The draw order is datasets (below-store) -> the Store's stack (a mixture of
|
|
95
|
+
* layers and the datasets that take part in the stack) -> datasets
|
|
96
|
+
* (above-store). It is aligned with the draw order in `view/layer/render.ts`.
|
|
97
|
+
*
|
|
98
|
+
* It is not narrowed down by the view. Narrowing it down would change the element order every
|
|
99
|
+
* time the view moves and require rebuilding the tile indices (the narrowing down within a
|
|
100
|
+
* tile is done by `binTile` using the bounding boxes).
|
|
101
|
+
*/
|
|
102
|
+
export declare function collectDrapeElements(store: Store, styles: RetainedStyleResolver, pixelRatio: number, datasets: readonly DrapeDatasetSource[]): DrapeCollectResult;
|
|
103
|
+
/**
|
|
104
|
+
* Whether the analytic drape may be used
|
|
105
|
+
*
|
|
106
|
+
* The conditions under which it cannot be used (degrade and drop to the vertex displacement
|
|
107
|
+
* path):
|
|
108
|
+
*
|
|
109
|
+
* - The total number of vertices exceeds the budget (a size at which holding the Mercator
|
|
110
|
+
* coordinates is not realistic)
|
|
111
|
+
* - The edges of a single tile exceed the budget (`binTile` returns overflow without building
|
|
112
|
+
* it)
|
|
113
|
+
* - Too many cells exceeded the per-cell budget (likewise)
|
|
114
|
+
*
|
|
115
|
+
* The presence of datasets is not in itself a reason to degrade. Custom types
|
|
116
|
+
* and overlay rendering are no obstacle either. Features that do not go on the drape are
|
|
117
|
+
* routed to the previous immediate path as `excluded`, and overlays are drawn inside
|
|
118
|
+
* renderLayers as before (both come after the drape).
|
|
119
|
+
*/
|
|
120
|
+
export declare function canDrape(options: {
|
|
121
|
+
vertexCount: number;
|
|
122
|
+
}): boolean;
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* The orchestration of the analytic drape
|
|
5
|
+
*
|
|
6
|
+
* It maps the features of the Store and the features of datasets into "a form
|
|
7
|
+
* that can be evaluated analytically" (a list of edges + a style). The point is to put both
|
|
8
|
+
* into a single list, and the stacking order is preserved by "compositing every element in
|
|
9
|
+
* style order within the same surface evaluation".
|
|
10
|
+
*
|
|
11
|
+
* Previously the presence of even one dataset dropped everything to the vertex displacement
|
|
12
|
+
* path, but that path only holds together while an exact match with maplibre's terrain mesh is
|
|
13
|
+
* maintained, and it was the origin of the symptoms when the match broke down (wedges, holes,
|
|
14
|
+
* streaks, seams and ribbons).
|
|
15
|
+
*
|
|
16
|
+
* When it does not hold, the caller drops to the previous vertex displacement path (a
|
|
17
|
+
* two-stage arrangement). The condition for dropping is decided here by `canDrape`.
|
|
18
|
+
*/
|
|
19
|
+
import { getCreatedZoom } from '../../../shared/utils/property.js';
|
|
20
|
+
import { getDisplayFeatures, isLocallyHidden } from '../../../store/local-visibility.js';
|
|
21
|
+
import { layerDrawFactors } from '../../renderers/draw-factors.js';
|
|
22
|
+
import { drapeSelectionKey, } from './binning.js';
|
|
23
|
+
import { drapeBoundsOf, drapeGeometryOf } from './geometry.js';
|
|
24
|
+
import { DRAPE_MAX_SOURCES } from './renderer.js';
|
|
25
|
+
/** The feature types the drape can handle */
|
|
26
|
+
const DRAPEABLE_TYPES = new Set([
|
|
27
|
+
'Polygon',
|
|
28
|
+
'MultiPolygon',
|
|
29
|
+
'LineString',
|
|
30
|
+
'MultiLineString',
|
|
31
|
+
// A freehand line is a polyline too. It is treated like a line and painted as ground
|
|
32
|
+
// pixels
|
|
33
|
+
'Freehand',
|
|
34
|
+
]);
|
|
35
|
+
/**
|
|
36
|
+
* The upper bound on the number of edges one tile of the view can handle
|
|
37
|
+
*
|
|
38
|
+
* A tile that exceeds it is degraded without being built (building it and then throwing it
|
|
39
|
+
* away would stall the frame for exactly that time). Measured on 8,172 administrative
|
|
40
|
+
* boundaries, one tile at z13 to z16 has a few thousand to 20,000 edges, so there is plenty of
|
|
41
|
+
* room.
|
|
42
|
+
*/
|
|
43
|
+
export const DRAPE_MAX_EDGES_PER_TILE = 120000;
|
|
44
|
+
/**
|
|
45
|
+
* The upper bound on the number of vertices that can be put on the drape (for the whole map)
|
|
46
|
+
*
|
|
47
|
+
* The cost of holding the Mercator coordinates (16 bytes per vertex) and the cost of scanning
|
|
48
|
+
* the bounding boxes per tile are capped here. 8,172 administrative boundaries (about 1.1
|
|
49
|
+
* million vertices) fit. A map that exceeds it is drawn with the previous vertex displacement
|
|
50
|
+
* path.
|
|
51
|
+
*/
|
|
52
|
+
export const DRAPE_MAX_VERTICES = 4000000;
|
|
53
|
+
/**
|
|
54
|
+
* The factor source of the Store layer at `layerIndex` (among the Store layers of the stacking
|
|
55
|
+
* order), or 0 when the sources are used up
|
|
56
|
+
*
|
|
57
|
+
* Source 0 is the neutral source (factor 1), 1 to `datasetCount` are the
|
|
58
|
+
* datasets, and the Store layers follow. A layer that gets 0 has its opacity baked into the
|
|
59
|
+
* colors of its elements, so the planner puts the opacity of such a layer into the key of the
|
|
60
|
+
* dataset (a change of it collects again).
|
|
61
|
+
*/
|
|
62
|
+
export function drapeLayerSource(layerIndex, datasetCount) {
|
|
63
|
+
const source = datasetCount + 1 + layerIndex;
|
|
64
|
+
return source < DRAPE_MAX_SOURCES ? source : 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Collects the elements of the analytic drape from the Store and the datasets
|
|
68
|
+
*
|
|
69
|
+
* The draw order is datasets (below-store) -> the Store's stack (a mixture of
|
|
70
|
+
* layers and the datasets that take part in the stack) -> datasets
|
|
71
|
+
* (above-store). It is aligned with the draw order in `view/layer/render.ts`.
|
|
72
|
+
*
|
|
73
|
+
* It is not narrowed down by the view. Narrowing it down would change the element order every
|
|
74
|
+
* time the view moves and require rebuilding the tile indices (the narrowing down within a
|
|
75
|
+
* tile is done by `binTile` using the bounding boxes).
|
|
76
|
+
*/
|
|
77
|
+
export function collectDrapeElements(store, styles, pixelRatio, datasets) {
|
|
78
|
+
const visible = getDisplayFeatures(store);
|
|
79
|
+
const byLayer = new Map();
|
|
80
|
+
for (const feature of visible) {
|
|
81
|
+
if (isLocallyHidden(feature, store))
|
|
82
|
+
continue;
|
|
83
|
+
const list = byLayer.get(feature.layerId);
|
|
84
|
+
if (list)
|
|
85
|
+
list.push(feature);
|
|
86
|
+
else
|
|
87
|
+
byLayer.set(feature.layerId, [feature]);
|
|
88
|
+
}
|
|
89
|
+
const context = {
|
|
90
|
+
elements: [],
|
|
91
|
+
excluded: new Set(),
|
|
92
|
+
quadBreaks: [],
|
|
93
|
+
entryStarts: new Map(),
|
|
94
|
+
edgeCount: 0,
|
|
95
|
+
vertexCount: 0,
|
|
96
|
+
drapedDatasets: new Set(),
|
|
97
|
+
styles,
|
|
98
|
+
pixelRatio,
|
|
99
|
+
layerSources: new Map(),
|
|
100
|
+
};
|
|
101
|
+
const byId = new Map();
|
|
102
|
+
for (const dataset of datasets)
|
|
103
|
+
byId.set(dataset.id, dataset);
|
|
104
|
+
let source = 1;
|
|
105
|
+
const sourceOf = new Map();
|
|
106
|
+
for (const dataset of datasets) {
|
|
107
|
+
sourceOf.set(dataset.id, source++);
|
|
108
|
+
}
|
|
109
|
+
for (const dataset of datasets) {
|
|
110
|
+
if (dataset.order !== 'below-store')
|
|
111
|
+
continue;
|
|
112
|
+
collectDataset(context, dataset, sourceOf.get(dataset.id) ?? 0);
|
|
113
|
+
}
|
|
114
|
+
let layerIndex = 0;
|
|
115
|
+
for (const layerId of store.getLayerOrder()) {
|
|
116
|
+
context.entryStarts.set(layerId, context.elements.length);
|
|
117
|
+
const layer = store.getLayer(layerId);
|
|
118
|
+
if (!layer) {
|
|
119
|
+
const dataset = byId.get(layerId);
|
|
120
|
+
if (dataset && dataset.order === 'layer-order') {
|
|
121
|
+
collectDataset(context, dataset, sourceOf.get(dataset.id) ?? 0);
|
|
122
|
+
}
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const layerSource = drapeLayerSource(layerIndex++, datasets.length);
|
|
126
|
+
if (layerSource > 0)
|
|
127
|
+
context.layerSources.set(layerId, layerSource);
|
|
128
|
+
// A layer without a source of its own has its opacity baked into its colors
|
|
129
|
+
const bakedOpacity = layerSource > 0 ? 1 : layerDrawFactors(layer).opacity;
|
|
130
|
+
for (const feature of byLayer.get(layerId) ?? []) {
|
|
131
|
+
collectStoreFeature(context, feature, layer, layerSource, bakedOpacity);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const aboveStoreStart = context.elements.length;
|
|
135
|
+
for (const dataset of datasets) {
|
|
136
|
+
if (dataset.order !== 'above-store')
|
|
137
|
+
continue;
|
|
138
|
+
collectDataset(context, dataset, sourceOf.get(dataset.id) ?? 0);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
elements: context.elements,
|
|
142
|
+
excluded: context.excluded,
|
|
143
|
+
quadBreaks: context.quadBreaks,
|
|
144
|
+
entryStarts: context.entryStarts,
|
|
145
|
+
aboveStoreStart,
|
|
146
|
+
edgeCount: context.edgeCount,
|
|
147
|
+
vertexCount: context.vertexCount,
|
|
148
|
+
drapedDatasets: context.drapedDatasets,
|
|
149
|
+
layerSources: context.layerSources,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Puts a single Store feature on (what cannot be put on goes into excluded)
|
|
154
|
+
*
|
|
155
|
+
* @param source The factor source of its layer (0 = none of its own)
|
|
156
|
+
* @param bakedOpacity The opacity of its layer when it has no source of its own (1 otherwise)
|
|
157
|
+
*/
|
|
158
|
+
function collectStoreFeature(context, feature, layer, source, bakedOpacity) {
|
|
159
|
+
if (!DRAPEABLE_TYPES.has(feature.type)) {
|
|
160
|
+
context.excluded.add(feature.id);
|
|
161
|
+
// An image is remembered as a break in the stacking order. It is drawn by the quad drape,
|
|
162
|
+
// but "which elements it is above and which it is below" is decided at this position
|
|
163
|
+
if (feature.type === 'Image') {
|
|
164
|
+
context.quadBreaks.push({ featureId: feature.id, afterElements: context.elements.length });
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (feature.type === 'Polygon' || feature.type === 'MultiPolygon') {
|
|
169
|
+
const { fillColor, strokeStyle } = context.styles.getPolygonStyles(feature, layer);
|
|
170
|
+
// Dashed lines are not put through the analytic evaluation (solving the accumulated
|
|
171
|
+
// distance along the outline from the pixel is not implemented). Drawing them as solid
|
|
172
|
+
// lines would change the appearance, so features with dashed lines are routed to the
|
|
173
|
+
// previous vertex displacement path.
|
|
174
|
+
if (strokeStyle.lineStyle !== 'solid') {
|
|
175
|
+
context.excluded.add(feature.id);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const hasStroke = strokeStyle.opacity > 0 && strokeStyle.width > 0;
|
|
179
|
+
const rings = polygonRings(feature);
|
|
180
|
+
if (rings.length === 0)
|
|
181
|
+
return;
|
|
182
|
+
if (fillColor[3] <= 0 && !hasStroke)
|
|
183
|
+
return;
|
|
184
|
+
const polygonWidth = widthOf(feature, strokeStyle.width, context.pixelRatio);
|
|
185
|
+
pushElement(context, feature, 0, rings, {
|
|
186
|
+
fill: [fillColor[0], fillColor[1], fillColor[2], fillColor[3] * bakedOpacity],
|
|
187
|
+
stroke: [
|
|
188
|
+
strokeStyle.color[0],
|
|
189
|
+
strokeStyle.color[1],
|
|
190
|
+
strokeStyle.color[2],
|
|
191
|
+
strokeStyle.color[3] * (hasStroke ? strokeStyle.opacity : 0) * bakedOpacity,
|
|
192
|
+
],
|
|
193
|
+
strokeWidthPx: hasStroke ? polygonWidth.px : 0,
|
|
194
|
+
source,
|
|
195
|
+
widthZoom: polygonWidth.zoom,
|
|
196
|
+
// A Store selection is expressed by the selection UI (the box and the handles). The
|
|
197
|
+
// drape does not change the color
|
|
198
|
+
selectionKey: '',
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const strokeStyle = context.styles.getLineStringStrokeStyle(feature, layer);
|
|
203
|
+
if (strokeStyle.lineStyle !== 'solid') {
|
|
204
|
+
context.excluded.add(feature.id);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (strokeStyle.opacity <= 0 || strokeStyle.width <= 0)
|
|
208
|
+
return;
|
|
209
|
+
const paths = linePaths(feature);
|
|
210
|
+
if (paths.length === 0)
|
|
211
|
+
return;
|
|
212
|
+
const lineWidth = widthOf(feature, strokeStyle.width, context.pixelRatio);
|
|
213
|
+
pushElement(context, feature, 1, paths, {
|
|
214
|
+
fill: [0, 0, 0, 0],
|
|
215
|
+
stroke: [
|
|
216
|
+
strokeStyle.color[0],
|
|
217
|
+
strokeStyle.color[1],
|
|
218
|
+
strokeStyle.color[2],
|
|
219
|
+
strokeStyle.color[3] * strokeStyle.opacity * bakedOpacity,
|
|
220
|
+
],
|
|
221
|
+
strokeWidthPx: lineWidth.px,
|
|
222
|
+
source,
|
|
223
|
+
widthZoom: lineWidth.zoom,
|
|
224
|
+
selectionKey: '',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Puts a single dataset on
|
|
229
|
+
*
|
|
230
|
+
* So that the retained batch side does not draw the same features that were put on, the caller
|
|
231
|
+
* tells the dataset "the polygons and lines are drawn by the drape"
|
|
232
|
+
* (`drapedDatasets`). The test here and `collectFeature` in `display/retained.ts` form a
|
|
233
|
+
* pair, so the condition must never be changed on only one side.
|
|
234
|
+
*/
|
|
235
|
+
function collectDataset(context, dataset, source) {
|
|
236
|
+
if (!dataset.visible)
|
|
237
|
+
return;
|
|
238
|
+
context.drapedDatasets.add(dataset.id);
|
|
239
|
+
for (const feature of dataset.drapeFeatures()) {
|
|
240
|
+
if (!feature.visible)
|
|
241
|
+
continue;
|
|
242
|
+
if (feature.type === 'Polygon' || feature.type === 'MultiPolygon') {
|
|
243
|
+
const { fillColor, strokeStyle } = context.styles.getPolygonStyles(feature);
|
|
244
|
+
const hasStroke = strokeStyle.opacity > 0 && strokeStyle.width > 0;
|
|
245
|
+
// A dashed outline is drawn by the immediate path on the retained batch side (the
|
|
246
|
+
// paired test)
|
|
247
|
+
if (hasStroke && strokeStyle.lineStyle !== 'solid')
|
|
248
|
+
continue;
|
|
249
|
+
if (!hasStroke && fillColor[3] <= 0)
|
|
250
|
+
continue;
|
|
251
|
+
const rings = polygonRings(feature);
|
|
252
|
+
if (rings.length === 0)
|
|
253
|
+
continue;
|
|
254
|
+
const width = widthOf(feature, strokeStyle.width, context.pixelRatio);
|
|
255
|
+
pushElement(context, feature.coordinates, 0, rings, {
|
|
256
|
+
fill: fillColor,
|
|
257
|
+
stroke: [
|
|
258
|
+
strokeStyle.color[0],
|
|
259
|
+
strokeStyle.color[1],
|
|
260
|
+
strokeStyle.color[2],
|
|
261
|
+
hasStroke ? strokeStyle.color[3] : 0,
|
|
262
|
+
],
|
|
263
|
+
strokeWidthPx: hasStroke ? width.px : 0,
|
|
264
|
+
source,
|
|
265
|
+
widthZoom: width.zoom,
|
|
266
|
+
selectionKey: drapeSelectionKey(dataset.id, feature.id),
|
|
267
|
+
});
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (feature.type !== 'LineString' &&
|
|
271
|
+
feature.type !== 'MultiLineString' &&
|
|
272
|
+
feature.type !== 'Freehand') {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const strokeStyle = context.styles.getLineStringStrokeStyle(feature);
|
|
276
|
+
if (strokeStyle.lineStyle !== 'solid')
|
|
277
|
+
continue;
|
|
278
|
+
if (strokeStyle.opacity <= 0 || strokeStyle.width <= 0)
|
|
279
|
+
continue;
|
|
280
|
+
const paths = linePaths(feature);
|
|
281
|
+
if (paths.length === 0)
|
|
282
|
+
continue;
|
|
283
|
+
const width = widthOf(feature, strokeStyle.width, context.pixelRatio);
|
|
284
|
+
pushElement(context, feature.coordinates, 1, paths, {
|
|
285
|
+
fill: [0, 0, 0, 0],
|
|
286
|
+
stroke: [
|
|
287
|
+
strokeStyle.color[0],
|
|
288
|
+
strokeStyle.color[1],
|
|
289
|
+
strokeStyle.color[2],
|
|
290
|
+
strokeStyle.color[3] * strokeStyle.opacity,
|
|
291
|
+
],
|
|
292
|
+
strokeWidthPx: width.px,
|
|
293
|
+
source,
|
|
294
|
+
widthZoom: width.zoom,
|
|
295
|
+
selectionKey: drapeSelectionKey(dataset.id, feature.id),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Resolves the line width with the same convention as the retained batch path
|
|
301
|
+
*
|
|
302
|
+
* A feature without a `createdZoom` is fixed in screen pixels (the rendering scale applies),
|
|
303
|
+
* and a feature with one scales by `2^(zoom - createdZoom)`. So that the thickness does not
|
|
304
|
+
* change with the presence of terrain, the drape follows the same convention.
|
|
305
|
+
*/
|
|
306
|
+
function widthOf(feature, width, pixelRatio) {
|
|
307
|
+
const createdZoom = getCreatedZoom(feature);
|
|
308
|
+
if (createdZoom !== undefined && Number.isFinite(createdZoom)) {
|
|
309
|
+
return { px: width, zoom: createdZoom };
|
|
310
|
+
}
|
|
311
|
+
return { px: width * pixelRatio, zoom: -1 };
|
|
312
|
+
}
|
|
313
|
+
/** The rings of a polygon (with the closing point dropped) */
|
|
314
|
+
function polygonRings(feature) {
|
|
315
|
+
return feature.type === 'Polygon'
|
|
316
|
+
? openRings(feature.coordinates)
|
|
317
|
+
: feature.coordinates.flatMap((part) => openRings(part));
|
|
318
|
+
}
|
|
319
|
+
/** The paths of a line */
|
|
320
|
+
function linePaths(feature) {
|
|
321
|
+
const paths = feature.type === 'LineString' || feature.type === 'Freehand'
|
|
322
|
+
? [feature.coordinates]
|
|
323
|
+
: feature.coordinates;
|
|
324
|
+
return paths.filter((path) => path.length >= 2);
|
|
325
|
+
}
|
|
326
|
+
/** Pushes an element */
|
|
327
|
+
function pushElement(context, cacheKey, kind, paths, style) {
|
|
328
|
+
const bounds = drapeBoundsOf(cacheKey, paths);
|
|
329
|
+
if (bounds.maxX < bounds.minX)
|
|
330
|
+
return;
|
|
331
|
+
let edges = 0;
|
|
332
|
+
for (const path of paths) {
|
|
333
|
+
context.vertexCount += path.length;
|
|
334
|
+
edges += kind === 0 ? path.length : path.length - 1;
|
|
335
|
+
}
|
|
336
|
+
if (edges === 0)
|
|
337
|
+
return;
|
|
338
|
+
context.elements.push({
|
|
339
|
+
kind,
|
|
340
|
+
bounds,
|
|
341
|
+
// The geometry is built only after passing the tile narrowing (what is outside the view
|
|
342
|
+
// is not converted)
|
|
343
|
+
geometry: () => drapeGeometryOf(cacheKey, paths, kind === 0),
|
|
344
|
+
...style,
|
|
345
|
+
});
|
|
346
|
+
context.edgeCount += edges;
|
|
347
|
+
}
|
|
348
|
+
/** Turns it into an array of rings with the closing point dropped */
|
|
349
|
+
function openRings(rings) {
|
|
350
|
+
const out = [];
|
|
351
|
+
for (const ring of rings) {
|
|
352
|
+
if (ring.length < 3)
|
|
353
|
+
continue;
|
|
354
|
+
const first = ring[0];
|
|
355
|
+
const last = ring[ring.length - 1];
|
|
356
|
+
out.push(first[0] === last[0] && first[1] === last[1] ? ring.slice(0, -1) : ring);
|
|
357
|
+
}
|
|
358
|
+
return out;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Whether the analytic drape may be used
|
|
362
|
+
*
|
|
363
|
+
* The conditions under which it cannot be used (degrade and drop to the vertex displacement
|
|
364
|
+
* path):
|
|
365
|
+
*
|
|
366
|
+
* - The total number of vertices exceeds the budget (a size at which holding the Mercator
|
|
367
|
+
* coordinates is not realistic)
|
|
368
|
+
* - The edges of a single tile exceed the budget (`binTile` returns overflow without building
|
|
369
|
+
* it)
|
|
370
|
+
* - Too many cells exceeded the per-cell budget (likewise)
|
|
371
|
+
*
|
|
372
|
+
* The presence of datasets is not in itself a reason to degrade. Custom types
|
|
373
|
+
* and overlay rendering are no obstacle either. Features that do not go on the drape are
|
|
374
|
+
* routed to the previous immediate path as `excluded`, and overlays are drawn inside
|
|
375
|
+
* renderLayers as before (both come after the drape).
|
|
376
|
+
*/
|
|
377
|
+
export function canDrape(options) {
|
|
378
|
+
return options.vertexCount <= DRAPE_MAX_VERTICES;
|
|
379
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Precomputation of the text (glyphs) placed on the analytic drape
|
|
3
|
+
*
|
|
4
|
+
* The text of a quad with a fill and text is drawn by "looking up the glyph's occupancy
|
|
5
|
+
* rectangle from the pixel's local coordinates and referencing the SDF atlas,
|
|
6
|
+
* within the same per-pixel evaluation as the fill". Because the fill and the
|
|
7
|
+
* text become pixels of a single surface, neither a tear caused by a subdivision
|
|
8
|
+
* mismatch nor a missing stroke can exist in principle, and since SDF is
|
|
9
|
+
* resolution-independent the text stays crisp even on a huge quad.
|
|
10
|
+
*
|
|
11
|
+
* It is impossible for the fragment shader to sweep through every glyph each
|
|
12
|
+
* time, so the quad's local coordinates are cut into a grid in the same manner as
|
|
13
|
+
* the edge binning of polygons and lines (`binning.ts`), and "the list of glyphs
|
|
14
|
+
* that cover that cell" is computed in advance for each cell. The lists are laid
|
|
15
|
+
* out contiguously in cell order, and a cell holds only (start, count) (the same
|
|
16
|
+
* way of holding data as the run of the edge binning). Because no separate index
|
|
17
|
+
* array is needed, there is one texture fewer.
|
|
18
|
+
*
|
|
19
|
+
* This runs only when the content, style or size of such a quad changes. It does
|
|
20
|
+
* not run every frame (the caller caches it by key).
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The number of elements per glyph in {@link QuadDrapeGlyphs.glyphs}: 8.
|
|
24
|
+
*
|
|
25
|
+
* The occupancy rectangle (x0, y0, x1, y1) and the atlas UV (u0, v0, u1, v1). The
|
|
26
|
+
* occupancy rectangle is in the quad's local 0..1 coordinates.
|
|
27
|
+
*/
|
|
28
|
+
export declare const QUAD_GLYPH_STRIDE = 8;
|
|
29
|
+
/** The upper limit of the grid subdivision count of the bins (per side) */
|
|
30
|
+
export declare const QUAD_GLYPH_MAX_GRID = 32;
|
|
31
|
+
/**
|
|
32
|
+
* The upper limit of the glyphs one cell can hold
|
|
33
|
+
*
|
|
34
|
+
* Anything beyond it is discarded. Dozens of glyphs overlapping in one cell happens
|
|
35
|
+
* only when extremely small text is packed onto an extremely large quad, and in that
|
|
36
|
+
* case many characters fall into a single pixel, so discarding them does not show.
|
|
37
|
+
*/
|
|
38
|
+
export declare const QUAD_GLYPH_MAX_PER_CELL = 64;
|
|
39
|
+
/** The result of the binning */
|
|
40
|
+
export interface QuadGlyphBins {
|
|
41
|
+
/** The grid subdivision count (per side). 0 means there is no text */
|
|
42
|
+
readonly grid: number;
|
|
43
|
+
/** (start, count, 0, 0) per cell. Length = grid * grid * 4 */
|
|
44
|
+
readonly cells: Float32Array;
|
|
45
|
+
/** The glyphs laid out in cell order (QUAD_GLYPH_STRIDE elements each) */
|
|
46
|
+
readonly entries: Float32Array;
|
|
47
|
+
/** The number of glyphs contained in entries (duplicates included) */
|
|
48
|
+
readonly entryCount: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Decides the grid subdivision count from the number of glyphs
|
|
52
|
+
*
|
|
53
|
+
* It aims for a coarseness of roughly one glyph per cell. Making it too fine only
|
|
54
|
+
* increases the duplication of "glyphs that straddle several cells", so it is
|
|
55
|
+
* stopped at the upper limit.
|
|
56
|
+
*/
|
|
57
|
+
export declare function chooseQuadGlyphGrid(count: number): number;
|
|
58
|
+
/**
|
|
59
|
+
* Bins the glyphs into the grid of local coordinates
|
|
60
|
+
*
|
|
61
|
+
* @param glyphs The glyph array (QUAD_GLYPH_STRIDE elements each)
|
|
62
|
+
* @param count The number of glyphs
|
|
63
|
+
*/
|
|
64
|
+
export declare function binQuadGlyphs(glyphs: Float32Array, count: number): QuadGlyphBins;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Precomputation of the text (glyphs) placed on the analytic drape
|
|
5
|
+
*
|
|
6
|
+
* The text of a quad with a fill and text is drawn by "looking up the glyph's occupancy
|
|
7
|
+
* rectangle from the pixel's local coordinates and referencing the SDF atlas,
|
|
8
|
+
* within the same per-pixel evaluation as the fill". Because the fill and the
|
|
9
|
+
* text become pixels of a single surface, neither a tear caused by a subdivision
|
|
10
|
+
* mismatch nor a missing stroke can exist in principle, and since SDF is
|
|
11
|
+
* resolution-independent the text stays crisp even on a huge quad.
|
|
12
|
+
*
|
|
13
|
+
* It is impossible for the fragment shader to sweep through every glyph each
|
|
14
|
+
* time, so the quad's local coordinates are cut into a grid in the same manner as
|
|
15
|
+
* the edge binning of polygons and lines (`binning.ts`), and "the list of glyphs
|
|
16
|
+
* that cover that cell" is computed in advance for each cell. The lists are laid
|
|
17
|
+
* out contiguously in cell order, and a cell holds only (start, count) (the same
|
|
18
|
+
* way of holding data as the run of the edge binning). Because no separate index
|
|
19
|
+
* array is needed, there is one texture fewer.
|
|
20
|
+
*
|
|
21
|
+
* This runs only when the content, style or size of such a quad changes. It does
|
|
22
|
+
* not run every frame (the caller caches it by key).
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The number of elements per glyph in {@link QuadDrapeGlyphs.glyphs}: 8.
|
|
26
|
+
*
|
|
27
|
+
* The occupancy rectangle (x0, y0, x1, y1) and the atlas UV (u0, v0, u1, v1). The
|
|
28
|
+
* occupancy rectangle is in the quad's local 0..1 coordinates.
|
|
29
|
+
*/
|
|
30
|
+
export const QUAD_GLYPH_STRIDE = 8;
|
|
31
|
+
/** The upper limit of the grid subdivision count of the bins (per side) */
|
|
32
|
+
export const QUAD_GLYPH_MAX_GRID = 32;
|
|
33
|
+
/**
|
|
34
|
+
* The upper limit of the glyphs one cell can hold
|
|
35
|
+
*
|
|
36
|
+
* Anything beyond it is discarded. Dozens of glyphs overlapping in one cell happens
|
|
37
|
+
* only when extremely small text is packed onto an extremely large quad, and in that
|
|
38
|
+
* case many characters fall into a single pixel, so discarding them does not show.
|
|
39
|
+
*/
|
|
40
|
+
export const QUAD_GLYPH_MAX_PER_CELL = 64;
|
|
41
|
+
/**
|
|
42
|
+
* Decides the grid subdivision count from the number of glyphs
|
|
43
|
+
*
|
|
44
|
+
* It aims for a coarseness of roughly one glyph per cell. Making it too fine only
|
|
45
|
+
* increases the duplication of "glyphs that straddle several cells", so it is
|
|
46
|
+
* stopped at the upper limit.
|
|
47
|
+
*/
|
|
48
|
+
export function chooseQuadGlyphGrid(count) {
|
|
49
|
+
if (count <= 0)
|
|
50
|
+
return 0;
|
|
51
|
+
return Math.min(QUAD_GLYPH_MAX_GRID, Math.max(1, Math.ceil(Math.sqrt(count))));
|
|
52
|
+
}
|
|
53
|
+
/** Rounds a value to an integer in 0..max */
|
|
54
|
+
function clampCell(value, max) {
|
|
55
|
+
if (!Number.isFinite(value))
|
|
56
|
+
return 0;
|
|
57
|
+
return Math.min(max, Math.max(0, Math.floor(value)));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Bins the glyphs into the grid of local coordinates
|
|
61
|
+
*
|
|
62
|
+
* @param glyphs The glyph array (QUAD_GLYPH_STRIDE elements each)
|
|
63
|
+
* @param count The number of glyphs
|
|
64
|
+
*/
|
|
65
|
+
export function binQuadGlyphs(glyphs, count) {
|
|
66
|
+
const grid = chooseQuadGlyphGrid(count);
|
|
67
|
+
if (grid === 0) {
|
|
68
|
+
return { grid: 0, cells: new Float32Array(0), entries: new Float32Array(0), entryCount: 0 };
|
|
69
|
+
}
|
|
70
|
+
// The glyph numbers per cell (put into every cell it covers. Same as the edge
|
|
71
|
+
// binning)
|
|
72
|
+
const buckets = [];
|
|
73
|
+
for (let i = 0; i < grid * grid; i++)
|
|
74
|
+
buckets.push([]);
|
|
75
|
+
for (let g = 0; g < count; g++) {
|
|
76
|
+
const base = g * QUAD_GLYPH_STRIDE;
|
|
77
|
+
const x0 = glyphs[base];
|
|
78
|
+
const y0 = glyphs[base + 1];
|
|
79
|
+
const x1 = glyphs[base + 2];
|
|
80
|
+
const y1 = glyphs[base + 3];
|
|
81
|
+
if (!(x1 > x0) || !(y1 > y0))
|
|
82
|
+
continue;
|
|
83
|
+
// A glyph that sticks out of the fill is pulled into the edge cell (it is
|
|
84
|
+
// rejected by the rectangle test, so it does no harm)
|
|
85
|
+
const cx0 = clampCell(x0 * grid, grid - 1);
|
|
86
|
+
const cx1 = clampCell(x1 * grid, grid - 1);
|
|
87
|
+
const cy0 = clampCell(y0 * grid, grid - 1);
|
|
88
|
+
const cy1 = clampCell(y1 * grid, grid - 1);
|
|
89
|
+
for (let cy = cy0; cy <= cy1; cy++) {
|
|
90
|
+
for (let cx = cx0; cx <= cx1; cx++) {
|
|
91
|
+
const bucket = buckets[cy * grid + cx];
|
|
92
|
+
if (bucket.length >= QUAD_GLYPH_MAX_PER_CELL)
|
|
93
|
+
continue;
|
|
94
|
+
bucket.push(g);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
let entryCount = 0;
|
|
99
|
+
for (const bucket of buckets)
|
|
100
|
+
entryCount += bucket.length;
|
|
101
|
+
const cells = new Float32Array(grid * grid * 4);
|
|
102
|
+
const entries = new Float32Array(entryCount * QUAD_GLYPH_STRIDE);
|
|
103
|
+
let cursor = 0;
|
|
104
|
+
for (let c = 0; c < buckets.length; c++) {
|
|
105
|
+
const bucket = buckets[c];
|
|
106
|
+
cells[c * 4] = cursor;
|
|
107
|
+
cells[c * 4 + 1] = bucket.length;
|
|
108
|
+
for (const g of bucket) {
|
|
109
|
+
const src = g * QUAD_GLYPH_STRIDE;
|
|
110
|
+
const dst = cursor * QUAD_GLYPH_STRIDE;
|
|
111
|
+
for (let k = 0; k < QUAD_GLYPH_STRIDE; k++)
|
|
112
|
+
entries[dst + k] = glyphs[src + k];
|
|
113
|
+
cursor++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { grid, cells, entries, entryCount };
|
|
117
|
+
}
|