@mapwhit/tilerenderer 0.47.1
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/LICENSE.txt +87 -0
- package/README.md +25 -0
- package/build/min/.dir +0 -0
- package/build/min/package.json +3 -0
- package/build/min/src/shaders/_prelude.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/_prelude.vertex.glsl.txt +14 -0
- package/build/min/src/shaders/background.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/background.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/background_pattern.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/background_pattern.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/circle.fragment.glsl.txt +20 -0
- package/build/min/src/shaders/circle.vertex.glsl.txt +17 -0
- package/build/min/src/shaders/clipping_mask.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/clipping_mask.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/collision_box.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/collision_box.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/collision_circle.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/collision_circle.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/debug.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/debug.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/fill.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/fill.vertex.glsl.txt +7 -0
- package/build/min/src/shaders/fill_extrusion.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/fill_extrusion.vertex.glsl.txt +9 -0
- package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.txt +15 -0
- package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.txt +11 -0
- package/build/min/src/shaders/fill_outline.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/fill_outline.vertex.glsl.txt +7 -0
- package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.txt +9 -0
- package/build/min/src/shaders/fill_pattern.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/fill_pattern.vertex.glsl.txt +9 -0
- package/build/min/src/shaders/heatmap.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/heatmap.vertex.glsl.txt +8 -0
- package/build/min/src/shaders/heatmap_texture.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/heatmap_texture.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/hillshade.fragment.glsl.txt +7 -0
- package/build/min/src/shaders/hillshade.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/hillshade_prepare.fragment.glsl.txt +8 -0
- package/build/min/src/shaders/hillshade_prepare.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/line.fragment.glsl.txt +12 -0
- package/build/min/src/shaders/line.vertex.glsl.txt +17 -0
- package/build/min/src/shaders/line_gradient.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/line_gradient.vertex.glsl.txt +16 -0
- package/build/min/src/shaders/line_pattern.fragment.glsl.txt +15 -0
- package/build/min/src/shaders/line_pattern.vertex.glsl.txt +20 -0
- package/build/min/src/shaders/line_sdf.fragment.glsl.txt +17 -0
- package/build/min/src/shaders/line_sdf.vertex.glsl.txt +20 -0
- package/build/min/src/shaders/raster.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/raster.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/symbol_icon.fragment.glsl.txt +9 -0
- package/build/min/src/shaders/symbol_icon.vertex.glsl.txt +5 -0
- package/build/min/src/shaders/symbol_sdf.fragment.glsl.txt +19 -0
- package/build/min/src/shaders/symbol_sdf.vertex.glsl.txt +13 -0
- package/package.json +44 -0
- package/src/css/mapbox-gl.css +506 -0
- package/src/css/svg/mapboxgl-ctrl-attrib.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-compass.svg +4 -0
- package/src/css/svg/mapboxgl-ctrl-fullscreen.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-geolocate-background.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-geolocate.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-logo-compact.svg +2 -0
- package/src/css/svg/mapboxgl-ctrl-logo.svg +1 -0
- package/src/css/svg/mapboxgl-ctrl-shrink.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-zoom-in.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-zoom-out.svg +3 -0
- package/src/data/array_types.js +1138 -0
- package/src/data/bucket/circle_attributes.js +5 -0
- package/src/data/bucket/circle_bucket.js +118 -0
- package/src/data/bucket/fill_attributes.js +5 -0
- package/src/data/bucket/fill_bucket.js +166 -0
- package/src/data/bucket/fill_extrusion_attributes.js +11 -0
- package/src/data/bucket/fill_extrusion_bucket.js +247 -0
- package/src/data/bucket/heatmap_bucket.js +12 -0
- package/src/data/bucket/line_attributes.js +11 -0
- package/src/data/bucket/line_bucket.js +625 -0
- package/src/data/bucket/pattern_attributes.js +9 -0
- package/src/data/bucket/pattern_bucket_features.js +44 -0
- package/src/data/bucket/symbol_attributes.js +95 -0
- package/src/data/bucket/symbol_bucket.js +697 -0
- package/src/data/bucket.js +53 -0
- package/src/data/dem_data.js +126 -0
- package/src/data/extent.js +17 -0
- package/src/data/feature_index.js +254 -0
- package/src/data/index_array_type.js +14 -0
- package/src/data/load_geometry.js +42 -0
- package/src/data/pos_attributes.js +3 -0
- package/src/data/program_configuration.js +782 -0
- package/src/data/raster_bounds_attributes.js +6 -0
- package/src/data/segment.js +63 -0
- package/src/geo/coordinate.js +78 -0
- package/src/geo/lng_lat.js +129 -0
- package/src/geo/lng_lat_bounds.js +253 -0
- package/src/geo/transform.js +605 -0
- package/src/gl/color_mode.js +21 -0
- package/src/gl/context.js +193 -0
- package/src/gl/cull_face_mode.js +22 -0
- package/src/gl/depth_mode.js +18 -0
- package/src/gl/framebuffer.js +28 -0
- package/src/gl/index_buffer.js +52 -0
- package/src/gl/stencil_mode.js +17 -0
- package/src/gl/types.js +0 -0
- package/src/gl/value.js +676 -0
- package/src/gl/vertex_buffer.js +101 -0
- package/src/index.js +50 -0
- package/src/render/draw_background.js +60 -0
- package/src/render/draw_circle.js +55 -0
- package/src/render/draw_collision_debug.js +45 -0
- package/src/render/draw_debug.js +429 -0
- package/src/render/draw_fill.js +143 -0
- package/src/render/draw_fill_extrusion.js +101 -0
- package/src/render/draw_heatmap.js +159 -0
- package/src/render/draw_hillshade.js +144 -0
- package/src/render/draw_line.js +99 -0
- package/src/render/draw_raster.js +151 -0
- package/src/render/draw_symbol.js +231 -0
- package/src/render/glyph_atlas.js +55 -0
- package/src/render/glyph_manager.js +145 -0
- package/src/render/image_atlas.js +97 -0
- package/src/render/image_manager.js +183 -0
- package/src/render/line_atlas.js +139 -0
- package/src/render/painter.js +483 -0
- package/src/render/program/background_program.js +46 -0
- package/src/render/program/circle_program.js +40 -0
- package/src/render/program/clipping_mask_program.js +11 -0
- package/src/render/program/collision_program.js +28 -0
- package/src/render/program/debug_program.js +13 -0
- package/src/render/program/fill_extrusion_program.js +76 -0
- package/src/render/program/fill_program.js +60 -0
- package/src/render/program/heatmap_program.js +46 -0
- package/src/render/program/hillshade_program.js +77 -0
- package/src/render/program/line_program.js +119 -0
- package/src/render/program/pattern.js +57 -0
- package/src/render/program/program_uniforms.js +46 -0
- package/src/render/program/raster_program.js +50 -0
- package/src/render/program/symbol_program.js +112 -0
- package/src/render/program.js +133 -0
- package/src/render/texture.js +88 -0
- package/src/render/tile_mask.js +108 -0
- package/src/render/uniform_binding.js +129 -0
- package/src/render/vertex_array_object.js +155 -0
- package/src/shaders/README.md +42 -0
- package/src/shaders/_prelude.fragment.glsl +17 -0
- package/src/shaders/_prelude.vertex.glsl +73 -0
- package/src/shaders/background.fragment.glsl +10 -0
- package/src/shaders/background.vertex.glsl +7 -0
- package/src/shaders/background_pattern.fragment.glsl +28 -0
- package/src/shaders/background_pattern.vertex.glsl +20 -0
- package/src/shaders/circle.fragment.glsl +39 -0
- package/src/shaders/circle.vertex.glsl +63 -0
- package/src/shaders/clipping_mask.fragment.glsl +3 -0
- package/src/shaders/clipping_mask.vertex.glsl +7 -0
- package/src/shaders/collision_box.fragment.glsl +21 -0
- package/src/shaders/collision_box.vertex.glsl +26 -0
- package/src/shaders/collision_circle.fragment.glsl +34 -0
- package/src/shaders/collision_circle.vertex.glsl +36 -0
- package/src/shaders/debug.fragment.glsl +5 -0
- package/src/shaders/debug.vertex.glsl +7 -0
- package/src/shaders/encode_attribute.js +19 -0
- package/src/shaders/fill.fragment.glsl +13 -0
- package/src/shaders/fill.vertex.glsl +13 -0
- package/src/shaders/fill_extrusion.fragment.glsl +16 -0
- package/src/shaders/fill_extrusion.vertex.glsl +66 -0
- package/src/shaders/fill_extrusion_pattern.fragment.glsl +41 -0
- package/src/shaders/fill_extrusion_pattern.vertex.glsl +76 -0
- package/src/shaders/fill_outline.fragment.glsl +17 -0
- package/src/shaders/fill_outline.vertex.glsl +17 -0
- package/src/shaders/fill_outline_pattern.fragment.glsl +43 -0
- package/src/shaders/fill_outline_pattern.vertex.glsl +41 -0
- package/src/shaders/fill_pattern.fragment.glsl +36 -0
- package/src/shaders/fill_pattern.vertex.glsl +36 -0
- package/src/shaders/heatmap.fragment.glsl +21 -0
- package/src/shaders/heatmap.vertex.glsl +53 -0
- package/src/shaders/heatmap_texture.fragment.glsl +14 -0
- package/src/shaders/heatmap_texture.vertex.glsl +11 -0
- package/src/shaders/hillshade.fragment.glsl +52 -0
- package/src/shaders/hillshade.vertex.glsl +11 -0
- package/src/shaders/hillshade_prepare.fragment.glsl +72 -0
- package/src/shaders/hillshade_prepare.vertex.glsl +15 -0
- package/src/shaders/index.js +194 -0
- package/src/shaders/line.fragment.glsl +28 -0
- package/src/shaders/line.vertex.glsl +84 -0
- package/src/shaders/line_gradient.fragment.glsl +34 -0
- package/src/shaders/line_gradient.vertex.glsl +84 -0
- package/src/shaders/line_pattern.fragment.glsl +69 -0
- package/src/shaders/line_pattern.vertex.glsl +88 -0
- package/src/shaders/line_sdf.fragment.glsl +44 -0
- package/src/shaders/line_sdf.vertex.glsl +95 -0
- package/src/shaders/raster.fragment.glsl +52 -0
- package/src/shaders/raster.vertex.glsl +21 -0
- package/src/shaders/symbol_icon.fragment.glsl +17 -0
- package/src/shaders/symbol_icon.vertex.glsl +91 -0
- package/src/shaders/symbol_sdf.fragment.glsl +50 -0
- package/src/shaders/symbol_sdf.vertex.glsl +117 -0
- package/src/source/geojson_source.js +267 -0
- package/src/source/geojson_worker_source.js +210 -0
- package/src/source/geojson_wrapper.js +67 -0
- package/src/source/image_source.js +213 -0
- package/src/source/load_tilejson.js +40 -0
- package/src/source/pixels_to_tile_units.js +17 -0
- package/src/source/query_features.js +198 -0
- package/src/source/raster_dem_tile_source.js +140 -0
- package/src/source/raster_dem_tile_worker_source.js +26 -0
- package/src/source/raster_tile_source.js +126 -0
- package/src/source/rtl_text_plugin.js +63 -0
- package/src/source/source.js +75 -0
- package/src/source/source_cache.js +794 -0
- package/src/source/source_state.js +55 -0
- package/src/source/tile.js +332 -0
- package/src/source/tile_bounds.js +40 -0
- package/src/source/tile_cache.js +122 -0
- package/src/source/tile_id.js +150 -0
- package/src/source/vector_tile_source.js +144 -0
- package/src/source/vector_tile_worker_source.js +126 -0
- package/src/source/worker.js +175 -0
- package/src/source/worker_source.js +14 -0
- package/src/source/worker_tile.js +199 -0
- package/src/style/create_style_layer.js +25 -0
- package/src/style/evaluation_parameters.js +45 -0
- package/src/style/light.js +112 -0
- package/src/style/load_glyph_range.js +17 -0
- package/src/style/load_sprite.js +26 -0
- package/src/style/parse_glyph_pbf.js +45 -0
- package/src/style/pauseable_placement.js +88 -0
- package/src/style/properties.js +691 -0
- package/src/style/query_utils.js +39 -0
- package/src/style/style.js +955 -0
- package/src/style/style_layer/background_style_layer.js +11 -0
- package/src/style/style_layer/background_style_layer_properties.js +25 -0
- package/src/style/style_layer/circle_style_layer.js +93 -0
- package/src/style/style_layer/circle_style_layer_properties.js +76 -0
- package/src/style/style_layer/fill_extrusion_style_layer.js +194 -0
- package/src/style/style_layer/fill_extrusion_style_layer_properties.js +56 -0
- package/src/style/style_layer/fill_style_layer.js +46 -0
- package/src/style/style_layer/fill_style_layer_properties.js +45 -0
- package/src/style/style_layer/heatmap_style_layer.js +51 -0
- package/src/style/style_layer/heatmap_style_layer_properties.js +52 -0
- package/src/style/style_layer/hillshade_style_layer.js +15 -0
- package/src/style/style_layer/hillshade_style_layer_properties.js +43 -0
- package/src/style/style_layer/line_style_layer.js +129 -0
- package/src/style/style_layer/line_style_layer_properties.js +104 -0
- package/src/style/style_layer/raster_style_layer.js +11 -0
- package/src/style/style_layer/raster_style_layer_properties.js +55 -0
- package/src/style/style_layer/symbol_style_layer.js +66 -0
- package/src/style/style_layer/symbol_style_layer_properties.js +288 -0
- package/src/style/style_layer.js +183 -0
- package/src/style/style_layer_index.js +61 -0
- package/src/style/zoom_history.js +36 -0
- package/src/style-spec/deref.js +51 -0
- package/src/style-spec/error/parsing_error.js +8 -0
- package/src/style-spec/error/validation_error.js +10 -0
- package/src/style-spec/expression/compound_expression.js +118 -0
- package/src/style-spec/expression/definitions/array.js +82 -0
- package/src/style-spec/expression/definitions/assertion.js +69 -0
- package/src/style-spec/expression/definitions/at.js +57 -0
- package/src/style-spec/expression/definitions/case.js +73 -0
- package/src/style-spec/expression/definitions/coalesce.js +68 -0
- package/src/style-spec/expression/definitions/coercion.js +96 -0
- package/src/style-spec/expression/definitions/collator.js +102 -0
- package/src/style-spec/expression/definitions/equals.js +93 -0
- package/src/style-spec/expression/definitions/index.js +407 -0
- package/src/style-spec/expression/definitions/interpolate.js +235 -0
- package/src/style-spec/expression/definitions/length.js +54 -0
- package/src/style-spec/expression/definitions/let.js +60 -0
- package/src/style-spec/expression/definitions/literal.js +64 -0
- package/src/style-spec/expression/definitions/match.js +142 -0
- package/src/style-spec/expression/definitions/step.js +116 -0
- package/src/style-spec/expression/definitions/var.js +38 -0
- package/src/style-spec/expression/evaluation_context.js +35 -0
- package/src/style-spec/expression/index.js +329 -0
- package/src/style-spec/expression/is_constant.js +63 -0
- package/src/style-spec/expression/parsing_context.js +213 -0
- package/src/style-spec/expression/parsing_error.js +9 -0
- package/src/style-spec/expression/runtime_error.js +12 -0
- package/src/style-spec/expression/scope.js +34 -0
- package/src/style-spec/expression/stops.js +37 -0
- package/src/style-spec/expression/types.js +77 -0
- package/src/style-spec/expression/values.js +126 -0
- package/src/style-spec/feature_filter/README.md +55 -0
- package/src/style-spec/feature_filter/index.js +158 -0
- package/src/style-spec/function/convert.js +256 -0
- package/src/style-spec/function/index.js +299 -0
- package/src/style-spec/group_by_layout.js +68 -0
- package/src/style-spec/reference/v8.json +5356 -0
- package/src/style-spec/util/color.js +73 -0
- package/src/style-spec/util/color_spaces.js +128 -0
- package/src/style-spec/util/eval_support.js +8 -0
- package/src/style-spec/util/get_type.js +18 -0
- package/src/style-spec/util/interpolate.js +21 -0
- package/src/style-spec/util/properties.js +17 -0
- package/src/style-spec/util/ref_properties.js +1 -0
- package/src/style-spec/util/result.js +19 -0
- package/src/symbol/anchor.js +21 -0
- package/src/symbol/check_max_angle.js +75 -0
- package/src/symbol/clip_line.js +73 -0
- package/src/symbol/collision_feature.js +230 -0
- package/src/symbol/collision_index.js +379 -0
- package/src/symbol/cross_tile_symbol_index.js +270 -0
- package/src/symbol/get_anchors.js +177 -0
- package/src/symbol/grid_index.js +318 -0
- package/src/symbol/mergelines.js +75 -0
- package/src/symbol/opacity_state.js +21 -0
- package/src/symbol/placement.js +563 -0
- package/src/symbol/projection.js +601 -0
- package/src/symbol/quads.js +173 -0
- package/src/symbol/shaping.js +347 -0
- package/src/symbol/symbol_layout.js +519 -0
- package/src/symbol/symbol_size.js +110 -0
- package/src/symbol/transform_text.js +16 -0
- package/src/ui/anchor.js +24 -0
- package/src/ui/bind_handlers.js +199 -0
- package/src/ui/camera.js +954 -0
- package/src/ui/events.js +210 -0
- package/src/ui/handler/box_zoom.js +151 -0
- package/src/ui/handler/dblclick_zoom.js +91 -0
- package/src/ui/handler/drag_pan.js +285 -0
- package/src/ui/handler/drag_rotate.js +290 -0
- package/src/ui/handler/frame.js +28 -0
- package/src/ui/handler/inertia.js +45 -0
- package/src/ui/handler/keyboard.js +148 -0
- package/src/ui/handler/scroll_zoom.js +284 -0
- package/src/ui/handler/touch_zoom_rotate.js +263 -0
- package/src/ui/map.js +1645 -0
- package/src/util/actor.js +104 -0
- package/src/util/async.js +23 -0
- package/src/util/browser.js +61 -0
- package/src/util/callback.js +26 -0
- package/src/util/classify_rings.js +43 -0
- package/src/util/color_ramp.js +24 -0
- package/src/util/config.js +24 -0
- package/src/util/dictionary_coder.js +25 -0
- package/src/util/dispatcher.js +68 -0
- package/src/util/dom.js +102 -0
- package/src/util/evented.js +182 -0
- package/src/util/find_pole_of_inaccessibility.js +129 -0
- package/src/util/global_worker_pool.js +15 -0
- package/src/util/image.js +124 -0
- package/src/util/interpolate.js +5 -0
- package/src/util/intersection_tests.js +207 -0
- package/src/util/is_char_in_unicode_block.js +287 -0
- package/src/util/loader/image.js +32 -0
- package/src/util/object.js +178 -0
- package/src/util/script_detection.js +337 -0
- package/src/util/struct_array.js +197 -0
- package/src/util/task_queue.js +57 -0
- package/src/util/throttle.js +26 -0
- package/src/util/tile_cover.js +114 -0
- package/src/util/token.js +13 -0
- package/src/util/unique_id.js +12 -0
- package/src/util/util.js +192 -0
- package/src/util/vectortile_to_geojson.js +44 -0
- package/src/util/verticalize_punctuation.js +112 -0
- package/src/util/warn.js +21 -0
- package/src/util/web_worker.js +5 -0
- package/src/util/web_worker_transfer.js +228 -0
- package/src/util/worker_pool.js +41 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
const interpolate = require('../util/interpolate');
|
|
2
|
+
|
|
3
|
+
const Anchor = require('../symbol/anchor');
|
|
4
|
+
const checkMaxAngle = require('./check_max_angle');
|
|
5
|
+
|
|
6
|
+
module.exports = { getAnchors, getCenterAnchor };
|
|
7
|
+
|
|
8
|
+
function getLineLength(line) {
|
|
9
|
+
let lineLength = 0;
|
|
10
|
+
for (let k = 0; k < line.length - 1; k++) {
|
|
11
|
+
lineLength += line[k].dist(line[k + 1]);
|
|
12
|
+
}
|
|
13
|
+
return lineLength;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getAngleWindowSize(shapedText, glyphSize, boxScale) {
|
|
17
|
+
return shapedText ? (3 / 5) * glyphSize * boxScale : 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getLabelLength(shapedText, shapedIcon) {
|
|
21
|
+
return Math.max(
|
|
22
|
+
shapedText ? shapedText.right - shapedText.left : 0,
|
|
23
|
+
shapedIcon ? shapedIcon.right - shapedIcon.left : 0
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getCenterAnchor(line, maxAngle, shapedText, shapedIcon, glyphSize, boxScale) {
|
|
28
|
+
const angleWindowSize = getAngleWindowSize(shapedText, glyphSize, boxScale);
|
|
29
|
+
const labelLength = getLabelLength(shapedText, shapedIcon);
|
|
30
|
+
|
|
31
|
+
let prevDistance = 0;
|
|
32
|
+
const centerDistance = getLineLength(line) / 2;
|
|
33
|
+
|
|
34
|
+
for (let i = 0; i < line.length - 1; i++) {
|
|
35
|
+
const a = line[i];
|
|
36
|
+
const b = line[i + 1];
|
|
37
|
+
|
|
38
|
+
const segmentDistance = a.dist(b);
|
|
39
|
+
|
|
40
|
+
if (prevDistance + segmentDistance > centerDistance) {
|
|
41
|
+
// The center is on this segment
|
|
42
|
+
const t = (centerDistance - prevDistance) / segmentDistance;
|
|
43
|
+
const x = interpolate(a.x, b.x, t);
|
|
44
|
+
const y = interpolate(a.y, b.y, t);
|
|
45
|
+
|
|
46
|
+
const anchor = new Anchor(x, y, b.angleTo(a), i);
|
|
47
|
+
anchor._round();
|
|
48
|
+
if (angleWindowSize && !checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return anchor;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
prevDistance += segmentDistance;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getAnchors(line, spacing, maxAngle, shapedText, shapedIcon, glyphSize, boxScale, overscaling, tileExtent) {
|
|
60
|
+
// Resample a line to get anchor points for labels and check that each
|
|
61
|
+
// potential label passes text-max-angle check and has enough froom to fit
|
|
62
|
+
// on the line.
|
|
63
|
+
|
|
64
|
+
const angleWindowSize = getAngleWindowSize(shapedText, glyphSize, boxScale);
|
|
65
|
+
|
|
66
|
+
const labelLength = getLabelLength(shapedText, shapedIcon);
|
|
67
|
+
|
|
68
|
+
// Is the line continued from outside the tile boundary?
|
|
69
|
+
const isLineContinued = line[0].x === 0 || line[0].x === tileExtent || line[0].y === 0 || line[0].y === tileExtent;
|
|
70
|
+
|
|
71
|
+
// Is the label long, relative to the spacing?
|
|
72
|
+
// If so, adjust the spacing so there is always a minimum space of `spacing / 4` between label edges.
|
|
73
|
+
if (spacing - labelLength * boxScale < spacing / 4) {
|
|
74
|
+
spacing = labelLength * boxScale + spacing / 4;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Offset the first anchor by:
|
|
78
|
+
// Either half the label length plus a fixed extra offset if the line is not continued
|
|
79
|
+
// Or half the spacing if the line is continued.
|
|
80
|
+
|
|
81
|
+
// For non-continued lines, add a bit of fixed extra offset to avoid collisions at T intersections.
|
|
82
|
+
const fixedExtraOffset = glyphSize * 2;
|
|
83
|
+
|
|
84
|
+
const offset = !isLineContinued
|
|
85
|
+
? ((labelLength / 2 + fixedExtraOffset) * boxScale * overscaling) % spacing
|
|
86
|
+
: ((spacing / 2) * overscaling) % spacing;
|
|
87
|
+
|
|
88
|
+
return resample(
|
|
89
|
+
line,
|
|
90
|
+
offset,
|
|
91
|
+
spacing,
|
|
92
|
+
angleWindowSize,
|
|
93
|
+
maxAngle,
|
|
94
|
+
labelLength * boxScale,
|
|
95
|
+
isLineContinued,
|
|
96
|
+
false,
|
|
97
|
+
tileExtent
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function resample(
|
|
102
|
+
line,
|
|
103
|
+
offset,
|
|
104
|
+
spacing,
|
|
105
|
+
angleWindowSize,
|
|
106
|
+
maxAngle,
|
|
107
|
+
labelLength,
|
|
108
|
+
isLineContinued,
|
|
109
|
+
placeAtMiddle,
|
|
110
|
+
tileExtent
|
|
111
|
+
) {
|
|
112
|
+
const halfLabelLength = labelLength / 2;
|
|
113
|
+
const lineLength = getLineLength(line);
|
|
114
|
+
|
|
115
|
+
let distance = 0;
|
|
116
|
+
let markedDistance = offset - spacing;
|
|
117
|
+
|
|
118
|
+
let anchors = [];
|
|
119
|
+
|
|
120
|
+
for (let i = 0; i < line.length - 1; i++) {
|
|
121
|
+
const a = line[i];
|
|
122
|
+
const b = line[i + 1];
|
|
123
|
+
|
|
124
|
+
const segmentDist = a.dist(b);
|
|
125
|
+
const angle = b.angleTo(a);
|
|
126
|
+
|
|
127
|
+
while (markedDistance + spacing < distance + segmentDist) {
|
|
128
|
+
markedDistance += spacing;
|
|
129
|
+
|
|
130
|
+
const t = (markedDistance - distance) / segmentDist;
|
|
131
|
+
const x = interpolate(a.x, b.x, t);
|
|
132
|
+
const y = interpolate(a.y, b.y, t);
|
|
133
|
+
|
|
134
|
+
// Check that the point is within the tile boundaries and that
|
|
135
|
+
// the label would fit before the beginning and end of the line
|
|
136
|
+
// if placed at this point.
|
|
137
|
+
if (
|
|
138
|
+
x >= 0 &&
|
|
139
|
+
x < tileExtent &&
|
|
140
|
+
y >= 0 &&
|
|
141
|
+
y < tileExtent &&
|
|
142
|
+
markedDistance - halfLabelLength >= 0 &&
|
|
143
|
+
markedDistance + halfLabelLength <= lineLength
|
|
144
|
+
) {
|
|
145
|
+
const anchor = new Anchor(x, y, angle, i);
|
|
146
|
+
anchor._round();
|
|
147
|
+
|
|
148
|
+
if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) {
|
|
149
|
+
anchors.push(anchor);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
distance += segmentDist;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!placeAtMiddle && !anchors.length && !isLineContinued) {
|
|
158
|
+
// The first attempt at finding anchors at which labels can be placed failed.
|
|
159
|
+
// Try again, but this time just try placing one anchor at the middle of the line.
|
|
160
|
+
// This has the most effect for short lines in overscaled tiles, since the
|
|
161
|
+
// initial offset used in overscaled tiles is calculated to align labels with positions in
|
|
162
|
+
// parent tiles instead of placing the label as close to the beginning as possible.
|
|
163
|
+
anchors = resample(
|
|
164
|
+
line,
|
|
165
|
+
distance / 2,
|
|
166
|
+
spacing,
|
|
167
|
+
angleWindowSize,
|
|
168
|
+
maxAngle,
|
|
169
|
+
labelLength,
|
|
170
|
+
isLineContinued,
|
|
171
|
+
true,
|
|
172
|
+
tileExtent
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return anchors;
|
|
177
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GridIndex is a data structure for testing the intersection of
|
|
3
|
+
* circles and rectangles in a 2d plane.
|
|
4
|
+
* It is optimized for rapid insertion and querying.
|
|
5
|
+
* GridIndex splits the plane into a set of "cells" and keeps track
|
|
6
|
+
* of which geometries intersect with each cell. At query time,
|
|
7
|
+
* full geometry comparisons are only done for items that share
|
|
8
|
+
* at least one cell. As long as the geometries are relatively
|
|
9
|
+
* uniformly distributed across the plane, this greatly reduces
|
|
10
|
+
* the number of comparisons necessary.
|
|
11
|
+
*
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
class GridIndex {
|
|
15
|
+
constructor(width, height, cellSize) {
|
|
16
|
+
const boxCells = (this.boxCells = []);
|
|
17
|
+
const circleCells = (this.circleCells = []);
|
|
18
|
+
|
|
19
|
+
// More cells -> fewer geometries to check per cell, but items tend
|
|
20
|
+
// to be split across more cells.
|
|
21
|
+
// Sweet spot allows most small items to fit in one cell
|
|
22
|
+
this.xCellCount = Math.ceil(width / cellSize);
|
|
23
|
+
this.yCellCount = Math.ceil(height / cellSize);
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < this.xCellCount * this.yCellCount; i++) {
|
|
26
|
+
boxCells.push([]);
|
|
27
|
+
circleCells.push([]);
|
|
28
|
+
}
|
|
29
|
+
this.circleKeys = [];
|
|
30
|
+
this.boxKeys = [];
|
|
31
|
+
this.bboxes = [];
|
|
32
|
+
this.circles = [];
|
|
33
|
+
|
|
34
|
+
this.width = width;
|
|
35
|
+
this.height = height;
|
|
36
|
+
this.xScale = this.xCellCount / width;
|
|
37
|
+
this.yScale = this.yCellCount / height;
|
|
38
|
+
this.boxUid = 0;
|
|
39
|
+
this.circleUid = 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
keysLength() {
|
|
43
|
+
return this.boxKeys.length + this.circleKeys.length;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
insert(key, x1, y1, x2, y2) {
|
|
47
|
+
this._forEachCell(x1, y1, x2, y2, this._insertBoxCell, this.boxUid++);
|
|
48
|
+
this.boxKeys.push(key);
|
|
49
|
+
this.bboxes.push(x1);
|
|
50
|
+
this.bboxes.push(y1);
|
|
51
|
+
this.bboxes.push(x2);
|
|
52
|
+
this.bboxes.push(y2);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
insertCircle(key, x, y, radius) {
|
|
56
|
+
// Insert circle into grid for all cells in the circumscribing square
|
|
57
|
+
// It's more than necessary (by a factor of 4/PI), but fast to insert
|
|
58
|
+
this._forEachCell(x - radius, y - radius, x + radius, y + radius, this._insertCircleCell, this.circleUid++);
|
|
59
|
+
this.circleKeys.push(key);
|
|
60
|
+
this.circles.push(x);
|
|
61
|
+
this.circles.push(y);
|
|
62
|
+
this.circles.push(radius);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
_insertBoxCell(x1, y1, x2, y2, cellIndex, uid) {
|
|
66
|
+
this.boxCells[cellIndex].push(uid);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_insertCircleCell(x1, y1, x2, y2, cellIndex, uid) {
|
|
70
|
+
this.circleCells[cellIndex].push(uid);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_query(x1, y1, x2, y2, hitTest, predicate) {
|
|
74
|
+
if (x2 < 0 || x1 > this.width || y2 < 0 || y1 > this.height) {
|
|
75
|
+
return hitTest ? false : [];
|
|
76
|
+
}
|
|
77
|
+
const result = [];
|
|
78
|
+
if (x1 <= 0 && y1 <= 0 && this.width <= x2 && this.height <= y2) {
|
|
79
|
+
if (hitTest) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
for (let boxUid = 0; boxUid < this.boxKeys.length; boxUid++) {
|
|
83
|
+
result.push({
|
|
84
|
+
key: this.boxKeys[boxUid],
|
|
85
|
+
x1: this.bboxes[boxUid * 4],
|
|
86
|
+
y1: this.bboxes[boxUid * 4 + 1],
|
|
87
|
+
x2: this.bboxes[boxUid * 4 + 2],
|
|
88
|
+
y2: this.bboxes[boxUid * 4 + 3]
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
for (let circleUid = 0; circleUid < this.circleKeys.length; circleUid++) {
|
|
92
|
+
const x = this.circles[circleUid * 3];
|
|
93
|
+
const y = this.circles[circleUid * 3 + 1];
|
|
94
|
+
const radius = this.circles[circleUid * 3 + 2];
|
|
95
|
+
result.push({
|
|
96
|
+
key: this.circleKeys[circleUid],
|
|
97
|
+
x1: x - radius,
|
|
98
|
+
y1: y - radius,
|
|
99
|
+
x2: x + radius,
|
|
100
|
+
y2: y + radius
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return predicate ? result.filter(predicate) : result;
|
|
104
|
+
}
|
|
105
|
+
const queryArgs = {
|
|
106
|
+
hitTest,
|
|
107
|
+
seenUids: { box: {}, circle: {} }
|
|
108
|
+
};
|
|
109
|
+
this._forEachCell(x1, y1, x2, y2, this._queryCell, result, queryArgs, predicate);
|
|
110
|
+
return hitTest ? result.length > 0 : result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_queryCircle(x, y, radius, hitTest, predicate) {
|
|
114
|
+
// Insert circle into grid for all cells in the circumscribing square
|
|
115
|
+
// It's more than necessary (by a factor of 4/PI), but fast to insert
|
|
116
|
+
const x1 = x - radius;
|
|
117
|
+
const x2 = x + radius;
|
|
118
|
+
const y1 = y - radius;
|
|
119
|
+
const y2 = y + radius;
|
|
120
|
+
if (x2 < 0 || x1 > this.width || y2 < 0 || y1 > this.height) {
|
|
121
|
+
return hitTest ? false : [];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Box query early exits if the bounding box is larger than the grid, but we don't do
|
|
125
|
+
// the equivalent calculation for circle queries because early exit is less likely
|
|
126
|
+
// and the calculation is more expensive
|
|
127
|
+
const result = [];
|
|
128
|
+
const queryArgs = {
|
|
129
|
+
hitTest,
|
|
130
|
+
circle: { x: x, y: y, radius: radius },
|
|
131
|
+
seenUids: { box: {}, circle: {} }
|
|
132
|
+
};
|
|
133
|
+
this._forEachCell(x1, y1, x2, y2, this._queryCellCircle, result, queryArgs, predicate);
|
|
134
|
+
return hitTest ? result.length > 0 : result;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
query(x1, y1, x2, y2, predicate) {
|
|
138
|
+
return this._query(x1, y1, x2, y2, false, predicate);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
hitTest(x1, y1, x2, y2, predicate) {
|
|
142
|
+
return this._query(x1, y1, x2, y2, true, predicate);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
hitTestCircle(x, y, radius, predicate) {
|
|
146
|
+
return this._queryCircle(x, y, radius, true, predicate);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
_queryCell(x1, y1, x2, y2, cellIndex, result, queryArgs, predicate) {
|
|
150
|
+
const seenUids = queryArgs.seenUids;
|
|
151
|
+
const boxCell = this.boxCells[cellIndex];
|
|
152
|
+
if (boxCell !== null) {
|
|
153
|
+
const bboxes = this.bboxes;
|
|
154
|
+
for (const boxUid of boxCell) {
|
|
155
|
+
if (!seenUids.box[boxUid]) {
|
|
156
|
+
seenUids.box[boxUid] = true;
|
|
157
|
+
const offset = boxUid * 4;
|
|
158
|
+
if (
|
|
159
|
+
x1 <= bboxes[offset + 2] &&
|
|
160
|
+
y1 <= bboxes[offset + 3] &&
|
|
161
|
+
x2 >= bboxes[offset + 0] &&
|
|
162
|
+
y2 >= bboxes[offset + 1] &&
|
|
163
|
+
(!predicate || predicate(this.boxKeys[boxUid]))
|
|
164
|
+
) {
|
|
165
|
+
if (queryArgs.hitTest) {
|
|
166
|
+
result.push(true);
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
result.push({
|
|
170
|
+
key: this.boxKeys[boxUid],
|
|
171
|
+
x1: bboxes[offset],
|
|
172
|
+
y1: bboxes[offset + 1],
|
|
173
|
+
x2: bboxes[offset + 2],
|
|
174
|
+
y2: bboxes[offset + 3]
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const circleCell = this.circleCells[cellIndex];
|
|
181
|
+
if (circleCell !== null) {
|
|
182
|
+
const circles = this.circles;
|
|
183
|
+
for (const circleUid of circleCell) {
|
|
184
|
+
if (!seenUids.circle[circleUid]) {
|
|
185
|
+
seenUids.circle[circleUid] = true;
|
|
186
|
+
const offset = circleUid * 3;
|
|
187
|
+
if (
|
|
188
|
+
this._circleAndRectCollide(circles[offset], circles[offset + 1], circles[offset + 2], x1, y1, x2, y2) &&
|
|
189
|
+
(!predicate || predicate(this.circleKeys[circleUid]))
|
|
190
|
+
) {
|
|
191
|
+
if (queryArgs.hitTest) {
|
|
192
|
+
result.push(true);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
const x = circles[offset];
|
|
196
|
+
const y = circles[offset + 1];
|
|
197
|
+
const radius = circles[offset + 2];
|
|
198
|
+
result.push({
|
|
199
|
+
key: this.circleKeys[circleUid],
|
|
200
|
+
x1: x - radius,
|
|
201
|
+
y1: y - radius,
|
|
202
|
+
x2: x + radius,
|
|
203
|
+
y2: y + radius
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
_queryCellCircle(x1, y1, x2, y2, cellIndex, result, queryArgs, predicate) {
|
|
212
|
+
const circle = queryArgs.circle;
|
|
213
|
+
const seenUids = queryArgs.seenUids;
|
|
214
|
+
const boxCell = this.boxCells[cellIndex];
|
|
215
|
+
if (boxCell !== null) {
|
|
216
|
+
const bboxes = this.bboxes;
|
|
217
|
+
for (const boxUid of boxCell) {
|
|
218
|
+
if (!seenUids.box[boxUid]) {
|
|
219
|
+
seenUids.box[boxUid] = true;
|
|
220
|
+
const offset = boxUid * 4;
|
|
221
|
+
if (
|
|
222
|
+
this._circleAndRectCollide(
|
|
223
|
+
circle.x,
|
|
224
|
+
circle.y,
|
|
225
|
+
circle.radius,
|
|
226
|
+
bboxes[offset + 0],
|
|
227
|
+
bboxes[offset + 1],
|
|
228
|
+
bboxes[offset + 2],
|
|
229
|
+
bboxes[offset + 3]
|
|
230
|
+
) &&
|
|
231
|
+
(!predicate || predicate(this.boxKeys[boxUid]))
|
|
232
|
+
) {
|
|
233
|
+
result.push(true);
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const circleCell = this.circleCells[cellIndex];
|
|
241
|
+
if (circleCell !== null) {
|
|
242
|
+
const circles = this.circles;
|
|
243
|
+
for (const circleUid of circleCell) {
|
|
244
|
+
if (!seenUids.circle[circleUid]) {
|
|
245
|
+
seenUids.circle[circleUid] = true;
|
|
246
|
+
const offset = circleUid * 3;
|
|
247
|
+
if (
|
|
248
|
+
this._circlesCollide(
|
|
249
|
+
circles[offset],
|
|
250
|
+
circles[offset + 1],
|
|
251
|
+
circles[offset + 2],
|
|
252
|
+
circle.x,
|
|
253
|
+
circle.y,
|
|
254
|
+
circle.radius
|
|
255
|
+
) &&
|
|
256
|
+
(!predicate || predicate(this.circleKeys[circleUid]))
|
|
257
|
+
) {
|
|
258
|
+
result.push(true);
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
_forEachCell(x1, y1, x2, y2, fn, arg1, arg2, predicate) {
|
|
267
|
+
const cx1 = this._convertToXCellCoord(x1);
|
|
268
|
+
const cy1 = this._convertToYCellCoord(y1);
|
|
269
|
+
const cx2 = this._convertToXCellCoord(x2);
|
|
270
|
+
const cy2 = this._convertToYCellCoord(y2);
|
|
271
|
+
|
|
272
|
+
for (let x = cx1; x <= cx2; x++) {
|
|
273
|
+
for (let y = cy1; y <= cy2; y++) {
|
|
274
|
+
const cellIndex = this.xCellCount * y + x;
|
|
275
|
+
if (fn.call(this, x1, y1, x2, y2, cellIndex, arg1, arg2, predicate)) return;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
_convertToXCellCoord(x) {
|
|
281
|
+
return Math.max(0, Math.min(this.xCellCount - 1, Math.floor(x * this.xScale)));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
_convertToYCellCoord(y) {
|
|
285
|
+
return Math.max(0, Math.min(this.yCellCount - 1, Math.floor(y * this.yScale)));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
_circlesCollide(x1, y1, r1, x2, y2, r2) {
|
|
289
|
+
const dx = x2 - x1;
|
|
290
|
+
const dy = y2 - y1;
|
|
291
|
+
const bothRadii = r1 + r2;
|
|
292
|
+
return bothRadii * bothRadii > dx * dx + dy * dy;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
_circleAndRectCollide(circleX, circleY, radius, x1, y1, x2, y2) {
|
|
296
|
+
const halfRectWidth = (x2 - x1) / 2;
|
|
297
|
+
const distX = Math.abs(circleX - (x1 + halfRectWidth));
|
|
298
|
+
if (distX > halfRectWidth + radius) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const halfRectHeight = (y2 - y1) / 2;
|
|
303
|
+
const distY = Math.abs(circleY - (y1 + halfRectHeight));
|
|
304
|
+
if (distY > halfRectHeight + radius) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (distX <= halfRectWidth || distY <= halfRectHeight) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const dx = distX - halfRectWidth;
|
|
313
|
+
const dy = distY - halfRectHeight;
|
|
314
|
+
return dx * dx + dy * dy <= radius * radius;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
module.exports = GridIndex;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module.exports = function (features) {
|
|
2
|
+
const leftIndex = {};
|
|
3
|
+
const rightIndex = {};
|
|
4
|
+
const mergedFeatures = [];
|
|
5
|
+
let mergedIndex = 0;
|
|
6
|
+
|
|
7
|
+
function add(k) {
|
|
8
|
+
mergedFeatures.push(features[k]);
|
|
9
|
+
mergedIndex++;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function mergeFromRight(leftKey, rightKey, geom) {
|
|
13
|
+
const i = rightIndex[leftKey];
|
|
14
|
+
delete rightIndex[leftKey];
|
|
15
|
+
rightIndex[rightKey] = i;
|
|
16
|
+
|
|
17
|
+
mergedFeatures[i].geometry[0].pop();
|
|
18
|
+
mergedFeatures[i].geometry[0] = mergedFeatures[i].geometry[0].concat(geom[0]);
|
|
19
|
+
return i;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function mergeFromLeft(leftKey, rightKey, geom) {
|
|
23
|
+
const i = leftIndex[rightKey];
|
|
24
|
+
delete leftIndex[rightKey];
|
|
25
|
+
leftIndex[leftKey] = i;
|
|
26
|
+
|
|
27
|
+
mergedFeatures[i].geometry[0].shift();
|
|
28
|
+
mergedFeatures[i].geometry[0] = geom[0].concat(mergedFeatures[i].geometry[0]);
|
|
29
|
+
return i;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getKey(text, geom, onRight) {
|
|
33
|
+
const point = onRight ? geom[0][geom[0].length - 1] : geom[0][0];
|
|
34
|
+
return `${text}:${point.x}:${point.y}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (let k = 0; k < features.length; k++) {
|
|
38
|
+
const feature = features[k];
|
|
39
|
+
const geom = feature.geometry;
|
|
40
|
+
const text = feature.text;
|
|
41
|
+
|
|
42
|
+
if (!text) {
|
|
43
|
+
add(k);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const leftKey = getKey(text, geom);
|
|
48
|
+
const rightKey = getKey(text, geom, true);
|
|
49
|
+
|
|
50
|
+
if (leftKey in rightIndex && rightKey in leftIndex && rightIndex[leftKey] !== leftIndex[rightKey]) {
|
|
51
|
+
// found lines with the same text adjacent to both ends of the current line, merge all three
|
|
52
|
+
const j = mergeFromLeft(leftKey, rightKey, geom);
|
|
53
|
+
const i = mergeFromRight(leftKey, rightKey, mergedFeatures[j].geometry);
|
|
54
|
+
|
|
55
|
+
delete leftIndex[leftKey];
|
|
56
|
+
delete rightIndex[rightKey];
|
|
57
|
+
|
|
58
|
+
rightIndex[getKey(text, mergedFeatures[i].geometry, true)] = i;
|
|
59
|
+
mergedFeatures[j].geometry = null;
|
|
60
|
+
} else if (leftKey in rightIndex) {
|
|
61
|
+
// found mergeable line adjacent to the start of the current line, merge
|
|
62
|
+
mergeFromRight(leftKey, rightKey, geom);
|
|
63
|
+
} else if (rightKey in leftIndex) {
|
|
64
|
+
// found mergeable line adjacent to the end of the current line, merge
|
|
65
|
+
mergeFromLeft(leftKey, rightKey, geom);
|
|
66
|
+
} else {
|
|
67
|
+
// no adjacent lines, add as a new item
|
|
68
|
+
add(k);
|
|
69
|
+
leftIndex[leftKey] = mergedIndex - 1;
|
|
70
|
+
rightIndex[rightKey] = mergedIndex - 1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return mergedFeatures.filter(f => f.geometry);
|
|
75
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { register } = require('../util/web_worker_transfer');
|
|
2
|
+
|
|
3
|
+
class OpacityState {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.opacity = 0;
|
|
6
|
+
this.targetOpacity = 0;
|
|
7
|
+
this.time = 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
clone() {
|
|
11
|
+
const clone = new OpacityState();
|
|
12
|
+
clone.opacity = this.opacity;
|
|
13
|
+
clone.targetOpacity = this.targetOpacity;
|
|
14
|
+
clone.time = this.time;
|
|
15
|
+
return clone;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
register('OpacityState', OpacityState);
|
|
20
|
+
|
|
21
|
+
module.exports = OpacityState;
|