@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,919 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* SDFPolygonRenderer
|
|
5
|
+
*
|
|
6
|
+
* A renderer that draws the fill and stroke of a polygon in a single draw call.
|
|
7
|
+
* - fill: filled with a triangulation (earcut)
|
|
8
|
+
* - stroke: high quality line rendering with the HHAA (Half-plane Anti-Aliasing) method
|
|
9
|
+
*
|
|
10
|
+
* Batching is possible while preserving the z-order.
|
|
11
|
+
*/
|
|
12
|
+
import earcut from 'earcut';
|
|
13
|
+
import { RENDERING_DEFAULTS } from '../../../shared/math/index.js';
|
|
14
|
+
import { resolveContentPixelRatio, resolvePixelRatio } from '../../../shared/utils/pixel-ratio.js';
|
|
15
|
+
import { EarcutCache } from '../../cache/earcut.js';
|
|
16
|
+
import { getSurfaceTessellationStep, tessellateSurfaceFill } from '../../globe-subdivision.js';
|
|
17
|
+
import { getRenderFrame } from '../../shaders/frame.js';
|
|
18
|
+
import { calculateLngLatOffset, calculateOffsetUniforms, createProgram, getProjectionTransitionUniform, OFFSET_MODE_GLSL, } from '../../shaders/helpers.js';
|
|
19
|
+
import { ProjectionUniformManager } from '../../shaders/projection.js';
|
|
20
|
+
import { TERRAIN_SHADE_FRAGMENT_GLSL, TERRAIN_SHADE_VERTEX_GLSL, } from '../../shaders/terrain-shade.js';
|
|
21
|
+
import { TerrainContext } from '../../terrain/context.js';
|
|
22
|
+
import { TERRAIN_MAX_TILED_COARSEN } from '../../terrain/metrics.js';
|
|
23
|
+
import { batchTessellationFactor, polygonTessellationStep, ringBoundingCells, tessellateRings, } from '../../terrain/polygon.js';
|
|
24
|
+
import { reportTerrainCoarsening } from '../../terrain/state.js';
|
|
25
|
+
import { NEUTRAL_DRAW_FACTORS } from '../draw-factors.js';
|
|
26
|
+
import { buildEarcutInput } from './earcut-input.js';
|
|
27
|
+
import { drawFillWithTerrainCull } from './terrain-cull.js';
|
|
28
|
+
/** Floats per vertex: pos(2) + color(4) + type(1) + prev(2) + next(2) + side(1) + extra(3) */
|
|
29
|
+
const VERTEX_STRIDE = 15;
|
|
30
|
+
/**
|
|
31
|
+
* Rounds the origin of the relative coordinates to Float32
|
|
32
|
+
*/
|
|
33
|
+
function normalizeOrigin(origin) {
|
|
34
|
+
return [Math.fround(origin[0]), Math.fround(origin[1])];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The default origin of a polygon batch (the first coordinate of the outer ring of the
|
|
38
|
+
* first polygon)
|
|
39
|
+
*/
|
|
40
|
+
function defaultPolygonOrigin(polygons) {
|
|
41
|
+
const first = polygons[0]?.coordinates[0]?.[0];
|
|
42
|
+
return first ? [first[0], first[1]] : [0, 0];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* SDFPolygonRenderer
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
export class SDFPolygonRenderer {
|
|
50
|
+
constructor(gl, pixelRatio, scope = {}) {
|
|
51
|
+
Object.defineProperty(this, "gl", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
configurable: true,
|
|
54
|
+
writable: true,
|
|
55
|
+
value: void 0
|
|
56
|
+
});
|
|
57
|
+
Object.defineProperty(this, "program", {
|
|
58
|
+
enumerable: true,
|
|
59
|
+
configurable: true,
|
|
60
|
+
writable: true,
|
|
61
|
+
value: null
|
|
62
|
+
});
|
|
63
|
+
Object.defineProperty(this, "variantName", {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
writable: true,
|
|
67
|
+
value: ''
|
|
68
|
+
});
|
|
69
|
+
// Projection uniform management
|
|
70
|
+
Object.defineProperty(this, "projectionUniformManager", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true,
|
|
73
|
+
writable: true,
|
|
74
|
+
value: void 0
|
|
75
|
+
});
|
|
76
|
+
// Uniform locations (renderer specific)
|
|
77
|
+
Object.defineProperty(this, "viewportLoc", {
|
|
78
|
+
enumerable: true,
|
|
79
|
+
configurable: true,
|
|
80
|
+
writable: true,
|
|
81
|
+
value: null
|
|
82
|
+
});
|
|
83
|
+
Object.defineProperty(this, "zoomLoc", {
|
|
84
|
+
enumerable: true,
|
|
85
|
+
configurable: true,
|
|
86
|
+
writable: true,
|
|
87
|
+
value: null
|
|
88
|
+
});
|
|
89
|
+
Object.defineProperty(this, "miterLimitLoc", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
configurable: true,
|
|
92
|
+
writable: true,
|
|
93
|
+
value: null
|
|
94
|
+
});
|
|
95
|
+
Object.defineProperty(this, "sizeScaleLoc", {
|
|
96
|
+
enumerable: true,
|
|
97
|
+
configurable: true,
|
|
98
|
+
writable: true,
|
|
99
|
+
value: null
|
|
100
|
+
});
|
|
101
|
+
Object.defineProperty(this, "opacityLoc", {
|
|
102
|
+
enumerable: true,
|
|
103
|
+
configurable: true,
|
|
104
|
+
writable: true,
|
|
105
|
+
value: null
|
|
106
|
+
});
|
|
107
|
+
// A record of the renderer specific uniforms written last (for memoization within a frame)
|
|
108
|
+
//
|
|
109
|
+
// Retained mode passes through here once per chunk, but neither the viewport nor the
|
|
110
|
+
// miter limit changes within a frame. Writes of the same value are skipped, and they
|
|
111
|
+
// are rewritten once the frame changes (see shaders/frame.ts).
|
|
112
|
+
Object.defineProperty(this, "memoFrame", {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
configurable: true,
|
|
115
|
+
writable: true,
|
|
116
|
+
value: -1
|
|
117
|
+
});
|
|
118
|
+
Object.defineProperty(this, "memoViewportWidth", {
|
|
119
|
+
enumerable: true,
|
|
120
|
+
configurable: true,
|
|
121
|
+
writable: true,
|
|
122
|
+
value: Number.NaN
|
|
123
|
+
});
|
|
124
|
+
Object.defineProperty(this, "memoViewportHeight", {
|
|
125
|
+
enumerable: true,
|
|
126
|
+
configurable: true,
|
|
127
|
+
writable: true,
|
|
128
|
+
value: Number.NaN
|
|
129
|
+
});
|
|
130
|
+
Object.defineProperty(this, "memoZoom", {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
configurable: true,
|
|
133
|
+
writable: true,
|
|
134
|
+
value: Number.NaN
|
|
135
|
+
});
|
|
136
|
+
Object.defineProperty(this, "memoMiterLimit", {
|
|
137
|
+
enumerable: true,
|
|
138
|
+
configurable: true,
|
|
139
|
+
writable: true,
|
|
140
|
+
value: Number.NaN
|
|
141
|
+
});
|
|
142
|
+
Object.defineProperty(this, "memoFactorsFrame", {
|
|
143
|
+
enumerable: true,
|
|
144
|
+
configurable: true,
|
|
145
|
+
writable: true,
|
|
146
|
+
value: -1
|
|
147
|
+
});
|
|
148
|
+
Object.defineProperty(this, "memoSizeScale", {
|
|
149
|
+
enumerable: true,
|
|
150
|
+
configurable: true,
|
|
151
|
+
writable: true,
|
|
152
|
+
value: Number.NaN
|
|
153
|
+
});
|
|
154
|
+
Object.defineProperty(this, "memoOpacity", {
|
|
155
|
+
enumerable: true,
|
|
156
|
+
configurable: true,
|
|
157
|
+
writable: true,
|
|
158
|
+
value: Number.NaN
|
|
159
|
+
});
|
|
160
|
+
// Stores the offset uniforms
|
|
161
|
+
Object.defineProperty(this, "offsetUniforms", {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
configurable: true,
|
|
164
|
+
writable: true,
|
|
165
|
+
value: null
|
|
166
|
+
});
|
|
167
|
+
// Buffers
|
|
168
|
+
Object.defineProperty(this, "vertexBuffer", {
|
|
169
|
+
enumerable: true,
|
|
170
|
+
configurable: true,
|
|
171
|
+
writable: true,
|
|
172
|
+
value: null
|
|
173
|
+
});
|
|
174
|
+
Object.defineProperty(this, "indexBuffer", {
|
|
175
|
+
enumerable: true,
|
|
176
|
+
configurable: true,
|
|
177
|
+
writable: true,
|
|
178
|
+
value: null
|
|
179
|
+
});
|
|
180
|
+
Object.defineProperty(this, "vao", {
|
|
181
|
+
enumerable: true,
|
|
182
|
+
configurable: true,
|
|
183
|
+
writable: true,
|
|
184
|
+
value: null
|
|
185
|
+
});
|
|
186
|
+
/** The injected pixel ratio (when not injected it is read from window each time) */
|
|
187
|
+
Object.defineProperty(this, "pixelRatio", {
|
|
188
|
+
enumerable: true,
|
|
189
|
+
configurable: true,
|
|
190
|
+
writable: true,
|
|
191
|
+
value: void 0
|
|
192
|
+
});
|
|
193
|
+
/** The terrain state of the draw instance */
|
|
194
|
+
Object.defineProperty(this, "terrain", {
|
|
195
|
+
enumerable: true,
|
|
196
|
+
configurable: true,
|
|
197
|
+
writable: true,
|
|
198
|
+
value: void 0
|
|
199
|
+
});
|
|
200
|
+
/** Triangulation results of the draw instance, keyed by feature id */
|
|
201
|
+
Object.defineProperty(this, "earcutCache", {
|
|
202
|
+
enumerable: true,
|
|
203
|
+
configurable: true,
|
|
204
|
+
writable: true,
|
|
205
|
+
value: void 0
|
|
206
|
+
});
|
|
207
|
+
this.gl = gl;
|
|
208
|
+
this.pixelRatio = pixelRatio;
|
|
209
|
+
this.terrain = scope.terrain ?? new TerrainContext();
|
|
210
|
+
this.earcutCache = scope.earcut ?? new EarcutCache();
|
|
211
|
+
this.projectionUniformManager = new ProjectionUniformManager(gl, {
|
|
212
|
+
surface: true,
|
|
213
|
+
terrain: this.terrain,
|
|
214
|
+
});
|
|
215
|
+
this.vertexBuffer = gl.createBuffer();
|
|
216
|
+
this.indexBuffer = gl.createBuffer();
|
|
217
|
+
this.vao = gl.createVertexArray();
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Ensures the shader (recreating it when necessary)
|
|
221
|
+
*/
|
|
222
|
+
ensureShader(shaderData) {
|
|
223
|
+
if (this.variantName !== shaderData.variantName) {
|
|
224
|
+
if (this.program) {
|
|
225
|
+
this.gl.deleteProgram(this.program);
|
|
226
|
+
}
|
|
227
|
+
this.program = this.createShaderProgram(shaderData.vertexShaderPrelude, shaderData.define);
|
|
228
|
+
this.variantName = shaderData.variantName;
|
|
229
|
+
// Get the projection uniform locations
|
|
230
|
+
this.projectionUniformManager.getLocations(this.program);
|
|
231
|
+
// Get the renderer specific uniform locations
|
|
232
|
+
this.viewportLoc = this.gl.getUniformLocation(this.program, 'u_viewport');
|
|
233
|
+
this.zoomLoc = this.gl.getUniformLocation(this.program, 'u_zoom');
|
|
234
|
+
this.miterLimitLoc = this.gl.getUniformLocation(this.program, 'u_miterLimit');
|
|
235
|
+
this.sizeScaleLoc = this.gl.getUniformLocation(this.program, 'u_size_scale');
|
|
236
|
+
this.opacityLoc = this.gl.getUniformLocation(this.program, 'u_opacity');
|
|
237
|
+
// A recreated program also resets its uniforms to their initial values, so the
|
|
238
|
+
// record is discarded
|
|
239
|
+
this.resetUniformMemo();
|
|
240
|
+
// Set up the VAO
|
|
241
|
+
this.setupVAO();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Sets the uniforms for offset mode
|
|
246
|
+
*/
|
|
247
|
+
setOffsetUniforms(uniforms) {
|
|
248
|
+
this.offsetUniforms = uniforms;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Discards the record of the values written last
|
|
252
|
+
*/
|
|
253
|
+
resetUniformMemo() {
|
|
254
|
+
this.memoFrame = -1;
|
|
255
|
+
this.memoViewportWidth = Number.NaN;
|
|
256
|
+
this.memoViewportHeight = Number.NaN;
|
|
257
|
+
this.memoZoom = Number.NaN;
|
|
258
|
+
this.memoMiterLimit = Number.NaN;
|
|
259
|
+
this.memoFactorsFrame = -1;
|
|
260
|
+
this.memoSizeScale = Number.NaN;
|
|
261
|
+
this.memoOpacity = Number.NaN;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Writes the viewport, zoom and miter limit (shared by immediate mode and retained mode)
|
|
265
|
+
*
|
|
266
|
+
* If the value is the same it is not rewritten. Once the frame changes the whole set is
|
|
267
|
+
* rewritten.
|
|
268
|
+
*/
|
|
269
|
+
setShapeUniforms(viewport, zoomValue) {
|
|
270
|
+
const gl = this.gl;
|
|
271
|
+
const frame = getRenderFrame();
|
|
272
|
+
const staleFrame = this.memoFrame !== frame;
|
|
273
|
+
if (this.viewportLoc &&
|
|
274
|
+
(staleFrame ||
|
|
275
|
+
this.memoViewportWidth !== viewport[0] ||
|
|
276
|
+
this.memoViewportHeight !== viewport[1])) {
|
|
277
|
+
gl.uniform2f(this.viewportLoc, viewport[0], viewport[1]);
|
|
278
|
+
this.memoViewportWidth = viewport[0];
|
|
279
|
+
this.memoViewportHeight = viewport[1];
|
|
280
|
+
}
|
|
281
|
+
if (this.zoomLoc && (staleFrame || this.memoZoom !== zoomValue)) {
|
|
282
|
+
gl.uniform1f(this.zoomLoc, zoomValue);
|
|
283
|
+
this.memoZoom = zoomValue;
|
|
284
|
+
}
|
|
285
|
+
if (this.miterLimitLoc &&
|
|
286
|
+
(staleFrame || this.memoMiterLimit !== RENDERING_DEFAULTS.MITER_LIMIT)) {
|
|
287
|
+
gl.uniform1f(this.miterLimitLoc, RENDERING_DEFAULTS.MITER_LIMIT);
|
|
288
|
+
this.memoMiterLimit = RENDERING_DEFAULTS.MITER_LIMIT;
|
|
289
|
+
}
|
|
290
|
+
this.memoFrame = frame;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Creates the shader program
|
|
294
|
+
*/
|
|
295
|
+
createShaderProgram(prelude, define) {
|
|
296
|
+
const projTransitionUniform = getProjectionTransitionUniform(prelude);
|
|
297
|
+
// Vertex shader
|
|
298
|
+
// a_type: 0=fill, 1=stroke
|
|
299
|
+
// fill: uses only a_pos and a_color
|
|
300
|
+
// stroke: uses a_pos, a_color, a_prev, a_next, a_side and a_extra
|
|
301
|
+
const vertexSource = `#version 300 es
|
|
302
|
+
${prelude}
|
|
303
|
+
${define}
|
|
304
|
+
${projTransitionUniform}${OFFSET_MODE_GLSL}${TERRAIN_SHADE_VERTEX_GLSL}
|
|
305
|
+
|
|
306
|
+
layout(location = 0) in vec2 a_pos; // current position (relative, 64-bit on CPU)
|
|
307
|
+
layout(location = 1) in vec4 a_color; // color (RGBA)
|
|
308
|
+
layout(location = 2) in float a_type; // 0=fill, 1=stroke
|
|
309
|
+
layout(location = 3) in vec2 a_prev; // previous vertex (relative coords, for stroke)
|
|
310
|
+
layout(location = 4) in vec2 a_next; // next vertex (relative coords, for stroke)
|
|
311
|
+
layout(location = 5) in float a_side; // left or right (for stroke: 1=left, -1=right)
|
|
312
|
+
layout(location = 6) in vec3 a_extra; // x=t(0-1), y=strokeWidth, z=createdZoom
|
|
313
|
+
|
|
314
|
+
uniform vec2 u_viewport;
|
|
315
|
+
uniform float u_zoom;
|
|
316
|
+
uniform float u_miterLimit;
|
|
317
|
+
uniform float u_size_scale; // the size factor at draw time (default 1)
|
|
318
|
+
|
|
319
|
+
out vec4 v_color;
|
|
320
|
+
out float v_type;
|
|
321
|
+
out float v_dist; // the SDF distance (for stroke)
|
|
322
|
+
out float v_halfWidth; // the half width of the line (for stroke)
|
|
323
|
+
|
|
324
|
+
void main() {
|
|
325
|
+
// The shading sample position is passed in both the fill and the outline branch (so
|
|
326
|
+
// that no undefined varying is left; only the fill fragment actually reads it)
|
|
327
|
+
emitShadeOffset(a_pos);
|
|
328
|
+
|
|
329
|
+
if (a_type < 0.5) {
|
|
330
|
+
// Fill: high precision version (uses relative coords computed at 64-bit precision on CPU)
|
|
331
|
+
gl_Position = project_position_to_clipspace_from_offset(a_pos, u_projection_matrix);
|
|
332
|
+
v_color = a_color;
|
|
333
|
+
v_type = 0.0;
|
|
334
|
+
v_dist = 0.0;
|
|
335
|
+
v_halfWidth = 0.0;
|
|
336
|
+
} else {
|
|
337
|
+
// Stroke: line rendering with the HHAA method (high precision version)
|
|
338
|
+
// Compute the clip coordinates (uses the relative coords already computed on the CPU side)
|
|
339
|
+
vec4 clipPos = project_position_to_clipspace_from_offset(a_pos, u_projection_matrix);
|
|
340
|
+
vec4 clipPrev = project_position_to_clipspace_from_offset(a_prev, u_projection_matrix);
|
|
341
|
+
vec4 clipNext = project_position_to_clipspace_from_offset(a_next, u_projection_matrix);
|
|
342
|
+
|
|
343
|
+
// NDC coordinates
|
|
344
|
+
vec2 ndcPos = clipPos.xy / clipPos.w;
|
|
345
|
+
vec2 ndcPrev = clipPrev.xy / clipPrev.w;
|
|
346
|
+
vec2 ndcNext = clipNext.xy / clipNext.w;
|
|
347
|
+
|
|
348
|
+
// Screen coordinates
|
|
349
|
+
vec2 screenPos = (ndcPos * 0.5 + 0.5) * u_viewport;
|
|
350
|
+
vec2 screenPrev = (ndcPrev * 0.5 + 0.5) * u_viewport;
|
|
351
|
+
vec2 screenNext = (ndcNext * 0.5 + 0.5) * u_viewport;
|
|
352
|
+
|
|
353
|
+
// Direction vectors
|
|
354
|
+
vec2 dirPrev = normalize(screenPos - screenPrev);
|
|
355
|
+
vec2 dirNext = normalize(screenNext - screenPos);
|
|
356
|
+
|
|
357
|
+
// Normals (the left side is positive)
|
|
358
|
+
vec2 normalPrev = vec2(-dirPrev.y, dirPrev.x);
|
|
359
|
+
vec2 normalNext = vec2(-dirNext.y, dirNext.x);
|
|
360
|
+
|
|
361
|
+
// Miter normal
|
|
362
|
+
vec2 miterNormal = normalize(normalPrev + normalNext);
|
|
363
|
+
|
|
364
|
+
// Miter scale
|
|
365
|
+
float cosHalfAngle = dot(miterNormal, normalPrev);
|
|
366
|
+
float miterScale = 1.0 / max(cosHalfAngle, 0.1);
|
|
367
|
+
miterScale = min(miterScale, u_miterLimit);
|
|
368
|
+
|
|
369
|
+
// Line width computation that takes createdZoom into account
|
|
370
|
+
// strokeWidth < 0 means "a fixed width of -strokeWidth pixels (zoom independent)".
|
|
371
|
+
// It is a convention for drawing features that have no createdZoom mixed into the
|
|
372
|
+
// same batch (= the same u_zoom) as features with a variable width.
|
|
373
|
+
float strokeWidth = a_extra.y;
|
|
374
|
+
float createdZoom = a_extra.z;
|
|
375
|
+
// u_size_scale is the size factor at draw time (default 1). It is multiplied
|
|
376
|
+
// outside the branch so that it takes effect whichever branch the data goes through.
|
|
377
|
+
float lineWidth = (strokeWidth >= 0.0
|
|
378
|
+
? strokeWidth * pow(2.0, u_zoom - createdZoom)
|
|
379
|
+
: -strokeWidth) * u_size_scale;
|
|
380
|
+
float halfWidth = lineWidth / 2.0;
|
|
381
|
+
|
|
382
|
+
// Expand by 1 pixel for HHAA
|
|
383
|
+
float expandedHalfWidth = halfWidth + 1.0;
|
|
384
|
+
|
|
385
|
+
// Screen space offset
|
|
386
|
+
vec2 screenOffset = miterNormal * a_side * expandedHalfWidth * miterScale;
|
|
387
|
+
vec2 finalScreenPos = screenPos + screenOffset;
|
|
388
|
+
|
|
389
|
+
// Back to NDC
|
|
390
|
+
vec2 finalNdc = (finalScreenPos / u_viewport) * 2.0 - 1.0;
|
|
391
|
+
gl_Position = vec4(finalNdc * clipPos.w, clipPos.z, clipPos.w);
|
|
392
|
+
|
|
393
|
+
v_color = a_color;
|
|
394
|
+
v_type = 1.0;
|
|
395
|
+
v_dist = a_side * expandedHalfWidth;
|
|
396
|
+
v_halfWidth = halfWidth;
|
|
397
|
+
}
|
|
398
|
+
}`;
|
|
399
|
+
// Fragment shader
|
|
400
|
+
const fragmentSource = `#version 300 es
|
|
401
|
+
precision highp float;
|
|
402
|
+
|
|
403
|
+
in vec4 v_color;
|
|
404
|
+
in float v_type;
|
|
405
|
+
in float v_dist;
|
|
406
|
+
in float v_halfWidth;
|
|
407
|
+
|
|
408
|
+
uniform float u_opacity; // the opacity factor at draw time (default 1)
|
|
409
|
+
|
|
410
|
+
out vec4 fragColor;
|
|
411
|
+
${TERRAIN_SHADE_FRAGMENT_GLSL}
|
|
412
|
+
void main() {
|
|
413
|
+
// Blending is non-premultiplied, so the factor is applied to the alpha only
|
|
414
|
+
if (v_type < 0.5) {
|
|
415
|
+
// Fill: output with the same terrain shading as the ground applied to the brightness
|
|
416
|
+
// (1.0 when there is no terrain). It is not applied to the outline (lines, points,
|
|
417
|
+
// labels and handles are by convention unshaded)
|
|
418
|
+
fragColor = vec4(v_color.rgb * terrainFillShade(), v_color.a * u_opacity);
|
|
419
|
+
} else {
|
|
420
|
+
// Stroke: anti-aliasing with the HHAA method
|
|
421
|
+
float d = abs(v_dist) - v_halfWidth;
|
|
422
|
+
float alpha = 1.0 - smoothstep(-1.0, 1.0, d);
|
|
423
|
+
|
|
424
|
+
if (alpha < 0.01) discard;
|
|
425
|
+
|
|
426
|
+
fragColor = vec4(v_color.rgb, v_color.a * alpha * u_opacity);
|
|
427
|
+
}
|
|
428
|
+
}`;
|
|
429
|
+
return createProgram(this.gl, vertexSource, fragmentSource);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Sets up the VAO
|
|
433
|
+
*/
|
|
434
|
+
setupVAO() {
|
|
435
|
+
const gl = this.gl;
|
|
436
|
+
gl.bindVertexArray(this.vao);
|
|
437
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
438
|
+
this.setupVertexAttribs();
|
|
439
|
+
// The ELEMENT_ARRAY_BUFFER binding is part of the VAO state
|
|
440
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
441
|
+
gl.bindVertexArray(null);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Sets up the vertex attributes (called while the vertex buffer is bound to ARRAY_BUFFER)
|
|
445
|
+
*
|
|
446
|
+
* The same layout is used by immediate mode and retained mode.
|
|
447
|
+
*/
|
|
448
|
+
setupVertexAttribs() {
|
|
449
|
+
const gl = this.gl;
|
|
450
|
+
// stride: pos(2) + color(4) + type(1) + prev(2) + next(2) + side(1) + extra(3) = 15 floats = 60 bytes
|
|
451
|
+
const stride = 60;
|
|
452
|
+
// a_pos: location 0
|
|
453
|
+
gl.enableVertexAttribArray(0);
|
|
454
|
+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, 0);
|
|
455
|
+
// a_color: location 1
|
|
456
|
+
gl.enableVertexAttribArray(1);
|
|
457
|
+
gl.vertexAttribPointer(1, 4, gl.FLOAT, false, stride, 8);
|
|
458
|
+
// a_type: location 2
|
|
459
|
+
gl.enableVertexAttribArray(2);
|
|
460
|
+
gl.vertexAttribPointer(2, 1, gl.FLOAT, false, stride, 24);
|
|
461
|
+
// a_prev: location 3
|
|
462
|
+
gl.enableVertexAttribArray(3);
|
|
463
|
+
gl.vertexAttribPointer(3, 2, gl.FLOAT, false, stride, 28);
|
|
464
|
+
// a_next: location 4
|
|
465
|
+
gl.enableVertexAttribArray(4);
|
|
466
|
+
gl.vertexAttribPointer(4, 2, gl.FLOAT, false, stride, 36);
|
|
467
|
+
// a_side: location 5
|
|
468
|
+
gl.enableVertexAttribArray(5);
|
|
469
|
+
gl.vertexAttribPointer(5, 1, gl.FLOAT, false, stride, 44);
|
|
470
|
+
// a_extra: location 6
|
|
471
|
+
gl.enableVertexAttribArray(6);
|
|
472
|
+
gl.vertexAttribPointer(6, 3, gl.FLOAT, false, stride, 48);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Sets the projection uniforms (supporting offset mode + globe mode)
|
|
476
|
+
* @param projectionData MapLibre's ProjectionData
|
|
477
|
+
* @param zoom The current zoom level (used for switching offset mode)
|
|
478
|
+
*/
|
|
479
|
+
setProjectionUniforms(projectionData, zoom) {
|
|
480
|
+
this.projectionUniformManager.setUniforms(projectionData, zoom, this.offsetUniforms);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Batch-draws multiple polygons
|
|
484
|
+
*
|
|
485
|
+
* Draws the fill and stroke of each polygon in a single draw call.
|
|
486
|
+
* The z-order is preserved by the order of the array.
|
|
487
|
+
*
|
|
488
|
+
* @param factors The factors used at draw time (the opacity of the layer being drawn; scale 1
|
|
489
|
+
* and opacity 1 when omitted)
|
|
490
|
+
* @returns The number of indices drawn (for debugging)
|
|
491
|
+
*/
|
|
492
|
+
drawBatch(polygons, projectionData, zoom, viewport, factors = NEUTRAL_DRAW_FACTORS) {
|
|
493
|
+
if (!this.program || polygons.length === 0)
|
|
494
|
+
return 0;
|
|
495
|
+
const gl = this.gl;
|
|
496
|
+
// Compute relative coordinates on the CPU side (offset mode: computed at 64-bit precision)
|
|
497
|
+
const centerLngLat = this.offsetUniforms?.centerLngLat ?? [0, 0];
|
|
498
|
+
const { vertexData, indexData } = this.buildGeometry(polygons, centerLngLat, true);
|
|
499
|
+
if (indexData.length === 0)
|
|
500
|
+
return 0;
|
|
501
|
+
// Transfer the data to the buffer
|
|
502
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
503
|
+
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.DYNAMIC_DRAW);
|
|
504
|
+
// Draw
|
|
505
|
+
gl.useProgram(this.program);
|
|
506
|
+
this.setProjectionUniforms(projectionData, zoom);
|
|
507
|
+
this.setShapeUniforms(viewport, zoom);
|
|
508
|
+
// Always written (1 when the caller has none) so that no factor of an earlier draw is left
|
|
509
|
+
this.setDrawFactors(factors);
|
|
510
|
+
gl.bindVertexArray(this.vao);
|
|
511
|
+
// The ELEMENT_ARRAY_BUFFER binding is VAO state, so the transfer is done after
|
|
512
|
+
// binding the VAO
|
|
513
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.DYNAMIC_DRAW);
|
|
514
|
+
drawFillWithTerrainCull(gl, this.terrain, () => {
|
|
515
|
+
gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_INT, 0);
|
|
516
|
+
});
|
|
517
|
+
gl.bindVertexArray(null);
|
|
518
|
+
return indexData.length;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Writes the factors used at draw time
|
|
522
|
+
*
|
|
523
|
+
* Uniforms are residual state per program, so they are always reset to 1 even on paths
|
|
524
|
+
* that do not use the factors (immediate mode, the retained drawing of the Store). If
|
|
525
|
+
* the value already written is the same, it is not rewritten.
|
|
526
|
+
*/
|
|
527
|
+
setDrawFactors(factors) {
|
|
528
|
+
const gl = this.gl;
|
|
529
|
+
const frame = getRenderFrame();
|
|
530
|
+
const staleFrame = this.memoFactorsFrame !== frame;
|
|
531
|
+
if (this.sizeScaleLoc && (staleFrame || this.memoSizeScale !== factors.scale)) {
|
|
532
|
+
gl.uniform1f(this.sizeScaleLoc, factors.scale);
|
|
533
|
+
this.memoSizeScale = factors.scale;
|
|
534
|
+
}
|
|
535
|
+
if (this.opacityLoc && (staleFrame || this.memoOpacity !== factors.opacity)) {
|
|
536
|
+
gl.uniform1f(this.opacityLoc, factors.opacity);
|
|
537
|
+
this.memoOpacity = factors.opacity;
|
|
538
|
+
}
|
|
539
|
+
this.memoFactorsFrame = frame;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Builds a retained-mode polygon batch
|
|
543
|
+
*
|
|
544
|
+
* earcut and the construction of the vertex array are finished here, so that in
|
|
545
|
+
* subsequent frames drawing takes only the bind + uniforms + draw call of
|
|
546
|
+
* `drawRetained`. The vertex data does not depend on the camera (the projection is done
|
|
547
|
+
* with per-frame uniforms).
|
|
548
|
+
*
|
|
549
|
+
* The earcut result is not put into the shared cache (the build happens only once, and
|
|
550
|
+
* the cache used by the drawing of the Store must not be polluted with the features
|
|
551
|
+
* of datasets). However, when options.triangulator is passed, both the caching and the
|
|
552
|
+
* time slicing of the triangulation become its responsibility
|
|
553
|
+
* (display/triangulation.ts).
|
|
554
|
+
*
|
|
555
|
+
* @returns The built batch. null when the shader is not initialized or there are no
|
|
556
|
+
* vertices
|
|
557
|
+
*/
|
|
558
|
+
buildRetained(polygons, options = {}) {
|
|
559
|
+
if (!this.program || polygons.length === 0)
|
|
560
|
+
return null;
|
|
561
|
+
const gl = this.gl;
|
|
562
|
+
// The origin of the relative coordinates is fixed per batch (it is not made to depend
|
|
563
|
+
// on the camera center)
|
|
564
|
+
const origin = normalizeOrigin(options.origin ?? defaultPolygonOrigin(polygons));
|
|
565
|
+
const { vertexData, indexData } = this.buildGeometry(polygons, origin, false, options.triangulator);
|
|
566
|
+
if (indexData.length === 0)
|
|
567
|
+
return null;
|
|
568
|
+
const vao = gl.createVertexArray();
|
|
569
|
+
gl.bindVertexArray(vao);
|
|
570
|
+
const vertexBuffer = gl.createBuffer();
|
|
571
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
|
572
|
+
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
|
|
573
|
+
this.setupVertexAttribs();
|
|
574
|
+
// The ELEMENT_ARRAY_BUFFER binding is part of the VAO state
|
|
575
|
+
const indexBuffer = gl.createBuffer();
|
|
576
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
|
577
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
|
|
578
|
+
gl.bindVertexArray(null);
|
|
579
|
+
return {
|
|
580
|
+
vao,
|
|
581
|
+
vertexBuffer,
|
|
582
|
+
indexBuffer,
|
|
583
|
+
indexCount: indexData.length,
|
|
584
|
+
origin,
|
|
585
|
+
widthZoom: options.widthZoom ?? null,
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Draws a retained-mode polygon batch
|
|
590
|
+
*
|
|
591
|
+
* Neither earcut nor bufferData is performed. The projection uniforms are recomputed
|
|
592
|
+
* each frame from the origin of the batch (the vertex data is not rebuilt).
|
|
593
|
+
*
|
|
594
|
+
* @param factors The factors used at draw time (when omitted, scale 1 and opacity 1, as
|
|
595
|
+
* before)
|
|
596
|
+
*/
|
|
597
|
+
drawRetained(batch, zoom, projectionData, viewport, factors = NEUTRAL_DRAW_FACTORS) {
|
|
598
|
+
if (!this.program || batch.indexCount === 0)
|
|
599
|
+
return;
|
|
600
|
+
const gl = this.gl;
|
|
601
|
+
gl.useProgram(this.program);
|
|
602
|
+
// The center of the linearization is aligned to the camera center (if it were
|
|
603
|
+
// linearized around the origin of the batch, the residual of the Mercator
|
|
604
|
+
// approximation would become a displacement of several pixels at vertices far from
|
|
605
|
+
// the center). The vertices are relative to the origin, so that difference is passed
|
|
606
|
+
// via u_origin_shift
|
|
607
|
+
const cameraUniforms = this.offsetUniforms;
|
|
608
|
+
if (cameraUniforms) {
|
|
609
|
+
this.projectionUniformManager.setUniforms(projectionData, zoom, cameraUniforms, [
|
|
610
|
+
batch.origin[0] - cameraUniforms.centerLngLat[0],
|
|
611
|
+
batch.origin[1] - cameraUniforms.centerLngLat[1],
|
|
612
|
+
]);
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
// Fallback (normally custom-layer has already called setOffsetUniforms each frame)
|
|
616
|
+
this.projectionUniformManager.setUniforms(projectionData, zoom, calculateOffsetUniforms(batch.origin, projectionData.mainMatrix));
|
|
617
|
+
}
|
|
618
|
+
this.setShapeUniforms(viewport, batch.widthZoom ?? zoom);
|
|
619
|
+
this.setDrawFactors(factors);
|
|
620
|
+
gl.bindVertexArray(batch.vao);
|
|
621
|
+
drawFillWithTerrainCull(gl, this.terrain, () => {
|
|
622
|
+
gl.drawElements(gl.TRIANGLES, batch.indexCount, gl.UNSIGNED_INT, 0);
|
|
623
|
+
});
|
|
624
|
+
gl.bindVertexArray(null);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Disposes of a retained-mode polygon batch
|
|
628
|
+
*/
|
|
629
|
+
disposeRetained(batch) {
|
|
630
|
+
const gl = this.gl;
|
|
631
|
+
gl.deleteVertexArray(batch.vao);
|
|
632
|
+
gl.deleteBuffer(batch.vertexBuffer);
|
|
633
|
+
gl.deleteBuffer(batch.indexBuffer);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Decides the subdivision step used for this batch (null on a flat map without terrain)
|
|
637
|
+
*
|
|
638
|
+
* The step is the terrain's, or on the globe the cell of its fills (`globe-subdivision.ts`).
|
|
639
|
+
*
|
|
640
|
+
* A batch whose total cell count exceeds the budget drops every feature uniformly onto
|
|
641
|
+
* a coarser grid. The per-feature cap (TERRAIN_MAX_SUBDIVISION_POINTS) is insurance
|
|
642
|
+
* against "one huge polygon" and does not help against "thousands of small polygons".
|
|
643
|
+
* With 8,172 administrative boundaries, even at a few hundred cells each (far below the
|
|
644
|
+
* cap) the total reached 1.7 million cells, and a single build took 34 seconds
|
|
645
|
+
* (measured).
|
|
646
|
+
*/
|
|
647
|
+
batchTerrainStep(polygons) {
|
|
648
|
+
const base = getSurfaceTessellationStep(this.terrain, 'fill');
|
|
649
|
+
if (!base)
|
|
650
|
+
return null;
|
|
651
|
+
let totalCells = 0;
|
|
652
|
+
for (const polygon of polygons) {
|
|
653
|
+
// Only the outer ring is looked at (an inner ring is inside the outer ring, so it
|
|
654
|
+
// does not change the total)
|
|
655
|
+
const outer = polygon.coordinates[0];
|
|
656
|
+
if (outer)
|
|
657
|
+
totalCells += ringBoundingCells(outer, base.grid, base.region);
|
|
658
|
+
}
|
|
659
|
+
const factor = batchTessellationFactor(totalCells);
|
|
660
|
+
// A coarsely subdivided polygon sinks into the depth easily. This is reported so that
|
|
661
|
+
// the bias can be matched
|
|
662
|
+
reportTerrainCoarsening(this.terrain, factor);
|
|
663
|
+
if (factor <= 1)
|
|
664
|
+
return base;
|
|
665
|
+
// While subdividing in alignment with the actual tile mesh, the coarsening is kept to
|
|
666
|
+
// a few steps of powers of 2 (it keeps riding on a subset of the mesh nodes, so
|
|
667
|
+
// valley floors do not sink)
|
|
668
|
+
if (base.tiling) {
|
|
669
|
+
return { ...base, coarsen: Math.min(factor, TERRAIN_MAX_TILED_COARSEN) };
|
|
670
|
+
}
|
|
671
|
+
return { grid: base.grid * factor, maxPoints: base.maxPoints, region: base.region };
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Builds the vertex array and index array of the batch (shared by immediate mode and
|
|
675
|
+
* retained mode)
|
|
676
|
+
*
|
|
677
|
+
* The indices are laid out in the order "fill of polygon 0 -> outline of polygon 0 ->
|
|
678
|
+
* fill of polygon 1 -> ...", so the z-order is preserved even with a single
|
|
679
|
+
* drawElements.
|
|
680
|
+
*
|
|
681
|
+
* @param centerLngLat The origin of the relative coordinates
|
|
682
|
+
* @param useEarcutCache Whether to put the triangulation result into the draw instance's cache
|
|
683
|
+
* @param triangulator The supplier of triangulations (earcut is called on the spot when
|
|
684
|
+
* omitted)
|
|
685
|
+
*/
|
|
686
|
+
buildGeometry(polygons, centerLngLat, useEarcutCache, triangulator) {
|
|
687
|
+
// Pass 1: collect the triangulations and the rings, and count the required array lengths
|
|
688
|
+
const records = [];
|
|
689
|
+
let totalVertices = 0;
|
|
690
|
+
let totalIndices = 0;
|
|
691
|
+
// Subdivide on a grid only while terrain is active or the globe is drawn (on a flat map
|
|
692
|
+
// without terrain it passes through as null). The total cell count of the whole batch is
|
|
693
|
+
// estimated first, and if it exceeds the budget everything is coarsened uniformly. A
|
|
694
|
+
// per-feature cap alone cannot stop a batch with thousands of features (a
|
|
695
|
+
// dataset). The factor is made single for the whole batch (if it varied per feature,
|
|
696
|
+
// adjacent features would ride on different grids and disagree at their shared boundary).
|
|
697
|
+
const terrainStep = this.batchTerrainStep(polygons);
|
|
698
|
+
for (const polygon of polygons) {
|
|
699
|
+
const style = polygon.style;
|
|
700
|
+
// Flatten all rings to build the earcut input (inner rings are treated as holes)
|
|
701
|
+
const { flatCoords, holeIndices, rings } = buildEarcutInput(polygon.coordinates);
|
|
702
|
+
if (rings.length === 0)
|
|
703
|
+
continue;
|
|
704
|
+
// The step actually used for this feature. It is received from the result of
|
|
705
|
+
// subdividing the fill and the same value is used for the outline as well. If the
|
|
706
|
+
// fill were coarsened because the budget ran out while the outline stayed fine, the
|
|
707
|
+
// two would ride on different grids and diverge in a wedge shape.
|
|
708
|
+
let polygonStep = null;
|
|
709
|
+
// 1. Fill
|
|
710
|
+
let fillCoords = null;
|
|
711
|
+
let fillIndices = null;
|
|
712
|
+
if (style.fillOpacity > 0) {
|
|
713
|
+
const indices = this.triangulate(polygon, flatCoords, holeIndices, useEarcutCache, triangulator);
|
|
714
|
+
if (indices && indices.length > 0) {
|
|
715
|
+
// Subdivision points are placed inside the triangles too. Subdividing only the
|
|
716
|
+
// edges still lets the center of a triangle pierce the terrain
|
|
717
|
+
if (terrainStep) {
|
|
718
|
+
const tessellated = tessellateSurfaceFill(this.terrain, polygon.featureId, polygon.partIndex ?? 0, flatCoords, indices, terrainStep);
|
|
719
|
+
polygonStep = tessellated.step;
|
|
720
|
+
fillCoords = tessellated.flatCoords;
|
|
721
|
+
fillIndices = tessellated.indices;
|
|
722
|
+
}
|
|
723
|
+
else {
|
|
724
|
+
fillCoords = flatCoords;
|
|
725
|
+
fillIndices = indices;
|
|
726
|
+
}
|
|
727
|
+
totalVertices += fillCoords.length / 2;
|
|
728
|
+
totalIndices += fillIndices.length;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
// 2. Stroke (the outer ring and each inner ring are drawn as their own closed path)
|
|
732
|
+
// A width of 0 means "no outline". A negative width is the fixed-width convention,
|
|
733
|
+
// so it is included among the things to draw.
|
|
734
|
+
let strokeRings = null;
|
|
735
|
+
if (style.strokeOpacity > 0 && style.strokeWidth !== 0) {
|
|
736
|
+
// When no fill was built (a polygon without a fill) the step cannot be received,
|
|
737
|
+
// so only in that case it is derived from the size of the feature
|
|
738
|
+
const ringStep = polygonStep ?? (terrainStep ? polygonTessellationStep(terrainStep, flatCoords) : null);
|
|
739
|
+
const strokeSource = ringStep ? tessellateRings(rings, ringStep) : rings;
|
|
740
|
+
const usable = strokeSource.filter((ring) => ring.length >= 3);
|
|
741
|
+
if (usable.length > 0) {
|
|
742
|
+
strokeRings = usable;
|
|
743
|
+
for (const ring of usable) {
|
|
744
|
+
// 4 vertices and 6 indices per segment
|
|
745
|
+
totalVertices += ring.length * 4;
|
|
746
|
+
totalIndices += ring.length * 6;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (!fillIndices && !strokeRings)
|
|
751
|
+
continue;
|
|
752
|
+
records.push({
|
|
753
|
+
fillCoords,
|
|
754
|
+
fillIndices,
|
|
755
|
+
strokeRings,
|
|
756
|
+
style,
|
|
757
|
+
createdZoom: polygon.createdZoom,
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
// Pass 2: write directly into the typed arrays
|
|
761
|
+
const vertexData = new Float32Array(totalVertices * VERTEX_STRIDE);
|
|
762
|
+
const indexData = new Uint32Array(totalIndices);
|
|
763
|
+
// Convert CSS pixels into physical pixels
|
|
764
|
+
//
|
|
765
|
+
// The ratio is chosen by the sign of the width (the "two ratios" of
|
|
766
|
+
// shared/utils/pixel-ratio.ts).
|
|
767
|
+
// Negative value = a width fixed in screen pixels, so the ratio that multiplies
|
|
768
|
+
// renderScale is used.
|
|
769
|
+
// Positive value = a width that the shader scales by 2^(u_zoom - createdZoom), so the
|
|
770
|
+
// ratio that does not multiply renderScale is used (multiplying it would apply the
|
|
771
|
+
// shrinking twice).
|
|
772
|
+
const screenDpr = resolvePixelRatio(this.pixelRatio);
|
|
773
|
+
const contentDpr = resolveContentPixelRatio(this.pixelRatio);
|
|
774
|
+
let base = 0;
|
|
775
|
+
let indexOffset = 0;
|
|
776
|
+
for (const record of records) {
|
|
777
|
+
const style = record.style;
|
|
778
|
+
// 1. Fill: each point of the rings becomes a vertex as is, and the earcut indices
|
|
779
|
+
// are shifted
|
|
780
|
+
if (record.fillCoords && record.fillIndices) {
|
|
781
|
+
const fillColor = [
|
|
782
|
+
style.fillColor[0],
|
|
783
|
+
style.fillColor[1],
|
|
784
|
+
style.fillColor[2],
|
|
785
|
+
style.fillColor[3] * style.fillOpacity,
|
|
786
|
+
];
|
|
787
|
+
const pointCount = record.fillCoords.length / 2;
|
|
788
|
+
for (let i = 0; i < pointCount; i++) {
|
|
789
|
+
// Compute the offset from the center at 64-bit precision
|
|
790
|
+
const offset = calculateLngLatOffset([record.fillCoords[i * 2], record.fillCoords[i * 2 + 1]], centerLngLat);
|
|
791
|
+
const at = (base + i) * VERTEX_STRIDE;
|
|
792
|
+
vertexData[at] = offset[0];
|
|
793
|
+
vertexData[at + 1] = offset[1];
|
|
794
|
+
vertexData[at + 2] = fillColor[0];
|
|
795
|
+
vertexData[at + 3] = fillColor[1];
|
|
796
|
+
vertexData[at + 4] = fillColor[2];
|
|
797
|
+
vertexData[at + 5] = fillColor[3];
|
|
798
|
+
// type = fill(0), and prev/next/side/extra stay 0
|
|
799
|
+
}
|
|
800
|
+
for (let i = 0; i < record.fillIndices.length; i++) {
|
|
801
|
+
indexData[indexOffset + i] = record.fillIndices[i] + base;
|
|
802
|
+
}
|
|
803
|
+
base += pointCount;
|
|
804
|
+
indexOffset += record.fillIndices.length;
|
|
805
|
+
}
|
|
806
|
+
// 2. Stroke: a quad per edge (4 vertices, 2 triangles)
|
|
807
|
+
if (record.strokeRings) {
|
|
808
|
+
const strokeColor = [
|
|
809
|
+
style.strokeColor[0],
|
|
810
|
+
style.strokeColor[1],
|
|
811
|
+
style.strokeColor[2],
|
|
812
|
+
style.strokeColor[3] * style.strokeOpacity,
|
|
813
|
+
];
|
|
814
|
+
const strokeWidth = style.strokeWidth * (style.strokeWidth < 0 ? screenDpr : contentDpr);
|
|
815
|
+
for (const ring of record.strokeRings) {
|
|
816
|
+
const n = ring.length;
|
|
817
|
+
for (let i = 0; i < n; i++) {
|
|
818
|
+
const curr = ring[i];
|
|
819
|
+
const next = ring[(i + 1) % n];
|
|
820
|
+
const prev = ring[(i - 1 + n) % n];
|
|
821
|
+
const nextNext = ring[(i + 2) % n];
|
|
822
|
+
// The left and right of the start point (curr)
|
|
823
|
+
this.writeStrokeVertex(vertexData, base * VERTEX_STRIDE, curr, strokeColor, prev, next, 1, 0, strokeWidth, record.createdZoom, centerLngLat);
|
|
824
|
+
this.writeStrokeVertex(vertexData, (base + 1) * VERTEX_STRIDE, curr, strokeColor, prev, next, -1, 0, strokeWidth, record.createdZoom, centerLngLat);
|
|
825
|
+
// The left and right of the end point (next)
|
|
826
|
+
this.writeStrokeVertex(vertexData, (base + 2) * VERTEX_STRIDE, next, strokeColor, curr, nextNext, 1, 1, strokeWidth, record.createdZoom, centerLngLat);
|
|
827
|
+
this.writeStrokeVertex(vertexData, (base + 3) * VERTEX_STRIDE, next, strokeColor, curr, nextNext, -1, 1, strokeWidth, record.createdZoom, centerLngLat);
|
|
828
|
+
// Triangle 1: start left, start right, end left / Triangle 2: end left, start
|
|
829
|
+
// right, end right
|
|
830
|
+
indexData[indexOffset] = base;
|
|
831
|
+
indexData[indexOffset + 1] = base + 1;
|
|
832
|
+
indexData[indexOffset + 2] = base + 2;
|
|
833
|
+
indexData[indexOffset + 3] = base + 2;
|
|
834
|
+
indexData[indexOffset + 4] = base + 1;
|
|
835
|
+
indexData[indexOffset + 5] = base + 3;
|
|
836
|
+
base += 4;
|
|
837
|
+
indexOffset += 6;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return { vertexData, indexData };
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Triangulates a polygon (making use of the cache)
|
|
846
|
+
*
|
|
847
|
+
* When a supplier is injected, the work is delegated to it. While the triangulation has
|
|
848
|
+
* not finished yet, null is returned and the fill of that polygon is omitted (the
|
|
849
|
+
* outline is still drawn).
|
|
850
|
+
*/
|
|
851
|
+
triangulate(polygon, flatCoords, holeIndices, useEarcutCache, triangulator) {
|
|
852
|
+
if (triangulator) {
|
|
853
|
+
return triangulator.triangulate({
|
|
854
|
+
featureId: polygon.featureId,
|
|
855
|
+
partIndex: polygon.partIndex ?? 0,
|
|
856
|
+
flatCoords,
|
|
857
|
+
holeIndices,
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
if (useEarcutCache && polygon.featureId) {
|
|
861
|
+
// Try to get it from the cache
|
|
862
|
+
const partIndex = polygon.partIndex ?? 0;
|
|
863
|
+
const cached = this.earcutCache.get(polygon.featureId, partIndex);
|
|
864
|
+
if (cached)
|
|
865
|
+
return cached;
|
|
866
|
+
const indices = earcut(flatCoords, holeIndices);
|
|
867
|
+
this.earcutCache.set(polygon.featureId, indices, partIndex);
|
|
868
|
+
return indices;
|
|
869
|
+
}
|
|
870
|
+
// When there is no featureId, run it without the cache
|
|
871
|
+
return earcut(flatCoords, holeIndices);
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Writes a stroke vertex directly into the vertex array (relative coordinates)
|
|
875
|
+
*/
|
|
876
|
+
writeStrokeVertex(target, at, pos, color, prev, next, side, t, strokeWidth, createdZoom, centerLngLat) {
|
|
877
|
+
// Compute the offset from the center at 64-bit precision
|
|
878
|
+
const posOffset = calculateLngLatOffset(pos, centerLngLat);
|
|
879
|
+
const prevOffset = calculateLngLatOffset(prev, centerLngLat);
|
|
880
|
+
const nextOffset = calculateLngLatOffset(next, centerLngLat);
|
|
881
|
+
target[at] = posOffset[0];
|
|
882
|
+
target[at + 1] = posOffset[1];
|
|
883
|
+
target[at + 2] = color[0];
|
|
884
|
+
target[at + 3] = color[1];
|
|
885
|
+
target[at + 4] = color[2];
|
|
886
|
+
target[at + 5] = color[3];
|
|
887
|
+
target[at + 6] = 1; // type = stroke
|
|
888
|
+
target[at + 7] = prevOffset[0];
|
|
889
|
+
target[at + 8] = prevOffset[1];
|
|
890
|
+
target[at + 9] = nextOffset[0];
|
|
891
|
+
target[at + 10] = nextOffset[1];
|
|
892
|
+
target[at + 11] = side;
|
|
893
|
+
target[at + 12] = t;
|
|
894
|
+
target[at + 13] = strokeWidth;
|
|
895
|
+
target[at + 14] = createdZoom;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Disposes of the resources
|
|
899
|
+
*/
|
|
900
|
+
dispose() {
|
|
901
|
+
const gl = this.gl;
|
|
902
|
+
if (this.program) {
|
|
903
|
+
gl.deleteProgram(this.program);
|
|
904
|
+
this.program = null;
|
|
905
|
+
}
|
|
906
|
+
if (this.vertexBuffer) {
|
|
907
|
+
gl.deleteBuffer(this.vertexBuffer);
|
|
908
|
+
this.vertexBuffer = null;
|
|
909
|
+
}
|
|
910
|
+
if (this.indexBuffer) {
|
|
911
|
+
gl.deleteBuffer(this.indexBuffer);
|
|
912
|
+
this.indexBuffer = null;
|
|
913
|
+
}
|
|
914
|
+
if (this.vao) {
|
|
915
|
+
gl.deleteVertexArray(this.vao);
|
|
916
|
+
this.vao = null;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|