@sentryware/s2-node 0.0.6
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/.circleci/config.yml +45 -0
- package/.dockerignore +1 -0
- package/.gitmodules +3 -0
- package/CHANGELOG.md +33 -0
- package/LICENSE +201 -0
- package/README.md +147 -0
- package/binding.gyp +170 -0
- package/docker/Dockerfile.node20.test +8 -0
- package/docker/Dockerfile.node22.test +8 -0
- package/docker/Dockerfile.node24.test +8 -0
- package/index.d.ts +117 -0
- package/index.js +6 -0
- package/jest.config.js +184 -0
- package/package.json +43 -0
- package/publish-linux.sh +18 -0
- package/publish-osx.sh +19 -0
- package/src/builder.cc +84 -0
- package/src/builder.h +29 -0
- package/src/cell.cc +71 -0
- package/src/cell.h +26 -0
- package/src/cell_id.cc +210 -0
- package/src/cell_id.h +44 -0
- package/src/cell_union.cc +237 -0
- package/src/cell_union.h +34 -0
- package/src/earth.cc +185 -0
- package/src/earth.h +33 -0
- package/src/latlng.cc +132 -0
- package/src/latlng.h +28 -0
- package/src/loop.cc +51 -0
- package/src/loop.h +21 -0
- package/src/point.cc +69 -0
- package/src/point.h +23 -0
- package/src/polygon.cc +36 -0
- package/src/polygon.h +20 -0
- package/src/polyline.cc +186 -0
- package/src/polyline.h +34 -0
- package/src/region_coverer.cc +450 -0
- package/src/region_coverer.h +56 -0
- package/src/s2.cc +27 -0
- package/test/Cell.test.js +37 -0
- package/test/CellId.test.js +135 -0
- package/test/CellUnion.test.js +150 -0
- package/test/Earth.test.js +62 -0
- package/test/LatLng.test.js +45 -0
- package/test/Point.test.js +14 -0
- package/test/Polyline.test.js +78 -0
- package/test/RegionCoverer.test.js +301 -0
- package/test.sh +16 -0
- package/third_party/s2geometry/.travis.yml +163 -0
- package/third_party/s2geometry/AUTHORS +13 -0
- package/third_party/s2geometry/CONTRIBUTING.md +65 -0
- package/third_party/s2geometry/CONTRIBUTORS +30 -0
- package/third_party/s2geometry/LICENSE +202 -0
- package/third_party/s2geometry/NOTICE +5 -0
- package/third_party/s2geometry/README.md +127 -0
- package/third_party/s2geometry/doc/examples/point_index.cc +44 -0
- package/third_party/s2geometry/doc/examples/term_index.cc +99 -0
- package/third_party/s2geometry/doc/examples/term_index.py +101 -0
- package/third_party/s2geometry/src/python/coder.i +125 -0
- package/third_party/s2geometry/src/python/pywraps2_test.py +786 -0
- package/third_party/s2geometry/src/python/s2.i +37 -0
- package/third_party/s2geometry/src/python/s2_common.i +756 -0
- package/third_party/s2geometry/src/s2/_fp_contract_off.h +60 -0
- package/third_party/s2geometry/src/s2/base/casts.h +318 -0
- package/third_party/s2geometry/src/s2/base/commandlineflags.h +67 -0
- package/third_party/s2geometry/src/s2/base/integral_types.h +31 -0
- package/third_party/s2geometry/src/s2/base/log_severity.h +40 -0
- package/third_party/s2geometry/src/s2/base/logging.h +173 -0
- package/third_party/s2geometry/src/s2/base/mutex.h +61 -0
- package/third_party/s2geometry/src/s2/base/port.h +999 -0
- package/third_party/s2geometry/src/s2/base/spinlock.h +60 -0
- package/third_party/s2geometry/src/s2/base/stringprintf.cc +107 -0
- package/third_party/s2geometry/src/s2/base/stringprintf.h +53 -0
- package/third_party/s2geometry/src/s2/base/strtoint.cc +65 -0
- package/third_party/s2geometry/src/s2/base/strtoint.h +106 -0
- package/third_party/s2geometry/src/s2/base/timer.h +50 -0
- package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector.cc +164 -0
- package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector.h +110 -0
- package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector_test.cc +232 -0
- package/third_party/s2geometry/src/s2/encoded_s2point_vector.cc +838 -0
- package/third_party/s2geometry/src/s2/encoded_s2point_vector.h +140 -0
- package/third_party/s2geometry/src/s2/encoded_s2point_vector_test.cc +344 -0
- package/third_party/s2geometry/src/s2/encoded_s2shape_index.cc +181 -0
- package/third_party/s2geometry/src/s2/encoded_s2shape_index.h +276 -0
- package/third_party/s2geometry/src/s2/encoded_s2shape_index_test.cc +244 -0
- package/third_party/s2geometry/src/s2/encoded_string_vector.cc +66 -0
- package/third_party/s2geometry/src/s2/encoded_string_vector.h +164 -0
- package/third_party/s2geometry/src/s2/encoded_string_vector_test.cc +69 -0
- package/third_party/s2geometry/src/s2/encoded_uint_vector.h +299 -0
- package/third_party/s2geometry/src/s2/encoded_uint_vector_test.cc +124 -0
- package/third_party/s2geometry/src/s2/id_set_lexicon.cc +81 -0
- package/third_party/s2geometry/src/s2/id_set_lexicon.h +199 -0
- package/third_party/s2geometry/src/s2/id_set_lexicon_test.cc +70 -0
- package/third_party/s2geometry/src/s2/mutable_s2shape_index.cc +1585 -0
- package/third_party/s2geometry/src/s2/mutable_s2shape_index.h +600 -0
- package/third_party/s2geometry/src/s2/mutable_s2shape_index_test.cc +589 -0
- package/third_party/s2geometry/src/s2/r1interval.h +220 -0
- package/third_party/s2geometry/src/s2/r1interval_test.cc +185 -0
- package/third_party/s2geometry/src/s2/r2.h +26 -0
- package/third_party/s2geometry/src/s2/r2rect.cc +93 -0
- package/third_party/s2geometry/src/s2/r2rect.h +234 -0
- package/third_party/s2geometry/src/s2/r2rect_test.cc +228 -0
- package/third_party/s2geometry/src/s2/s1angle.cc +54 -0
- package/third_party/s2geometry/src/s2/s1angle.h +336 -0
- package/third_party/s2geometry/src/s2/s1angle_test.cc +185 -0
- package/third_party/s2geometry/src/s2/s1chord_angle.cc +159 -0
- package/third_party/s2geometry/src/s2/s1chord_angle.h +369 -0
- package/third_party/s2geometry/src/s2/s1chord_angle_test.cc +207 -0
- package/third_party/s2geometry/src/s2/s1interval.cc +296 -0
- package/third_party/s2geometry/src/s2/s1interval.h +266 -0
- package/third_party/s2geometry/src/s2/s1interval_test.cc +469 -0
- package/third_party/s2geometry/src/s2/s2boolean_operation.cc +2391 -0
- package/third_party/s2geometry/src/s2/s2boolean_operation.h +501 -0
- package/third_party/s2geometry/src/s2/s2boolean_operation_test.cc +1400 -0
- package/third_party/s2geometry/src/s2/s2builder.cc +1828 -0
- package/third_party/s2geometry/src/s2/s2builder.h +1057 -0
- package/third_party/s2geometry/src/s2/s2builder_graph.cc +1084 -0
- package/third_party/s2geometry/src/s2/s2builder_graph.h +799 -0
- package/third_party/s2geometry/src/s2/s2builder_graph_test.cc +462 -0
- package/third_party/s2geometry/src/s2/s2builder_layer.h +50 -0
- package/third_party/s2geometry/src/s2/s2builder_test.cc +1329 -0
- package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer.cc +313 -0
- package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer.h +221 -0
- package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer_test.cc +261 -0
- package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies.cc +392 -0
- package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies.h +86 -0
- package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies_test.cc +182 -0
- package/third_party/s2geometry/src/s2/s2builderutil_graph_shape.h +57 -0
- package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer.cc +212 -0
- package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer.h +218 -0
- package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer_test.cc +367 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer.cc +74 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer.h +122 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer_test.cc +167 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer.cc +191 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer.h +211 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer_test.cc +312 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer.cc +105 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer.h +174 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer_test.cc +220 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer.cc +98 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer.h +292 -0
- package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer_test.cc +233 -0
- package/third_party/s2geometry/src/s2/s2builderutil_snap_functions.cc +354 -0
- package/third_party/s2geometry/src/s2/s2builderutil_snap_functions.h +239 -0
- package/third_party/s2geometry/src/s2/s2builderutil_snap_functions_test.cc +716 -0
- package/third_party/s2geometry/src/s2/s2builderutil_testing.cc +37 -0
- package/third_party/s2geometry/src/s2/s2builderutil_testing.h +100 -0
- package/third_party/s2geometry/src/s2/s2builderutil_testing_test.cc +85 -0
- package/third_party/s2geometry/src/s2/s2cap.cc +347 -0
- package/third_party/s2geometry/src/s2/s2cap.h +286 -0
- package/third_party/s2geometry/src/s2/s2cap_test.cc +379 -0
- package/third_party/s2geometry/src/s2/s2cell.cc +552 -0
- package/third_party/s2geometry/src/s2/s2cell.h +249 -0
- package/third_party/s2geometry/src/s2/s2cell_id.cc +619 -0
- package/third_party/s2geometry/src/s2/s2cell_id.h +705 -0
- package/third_party/s2geometry/src/s2/s2cell_id_test.cc +633 -0
- package/third_party/s2geometry/src/s2/s2cell_index.cc +149 -0
- package/third_party/s2geometry/src/s2/s2cell_index.h +660 -0
- package/third_party/s2geometry/src/s2/s2cell_index_test.cc +411 -0
- package/third_party/s2geometry/src/s2/s2cell_test.cc +687 -0
- package/third_party/s2geometry/src/s2/s2cell_union.cc +515 -0
- package/third_party/s2geometry/src/s2/s2cell_union.h +399 -0
- package/third_party/s2geometry/src/s2/s2cell_union_test.cc +598 -0
- package/third_party/s2geometry/src/s2/s2centroids.cc +84 -0
- package/third_party/s2geometry/src/s2/s2centroids.h +87 -0
- package/third_party/s2geometry/src/s2/s2centroids_test.cc +82 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query.cc +123 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query.h +385 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query_base.h +841 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query_base_test.cc +63 -0
- package/third_party/s2geometry/src/s2/s2closest_cell_query_test.cc +412 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query.cc +106 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query.h +421 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_base.h +946 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_base_test.cc +59 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_test.cc +505 -0
- package/third_party/s2geometry/src/s2/s2closest_edge_query_testing.h +91 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query.cc +66 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query.h +465 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query_base.h +767 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query_base_test.cc +63 -0
- package/third_party/s2geometry/src/s2/s2closest_point_query_test.cc +312 -0
- package/third_party/s2geometry/src/s2/s2contains_point_query.h +328 -0
- package/third_party/s2geometry/src/s2/s2contains_point_query_test.cc +159 -0
- package/third_party/s2geometry/src/s2/s2contains_vertex_query.cc +39 -0
- package/third_party/s2geometry/src/s2/s2contains_vertex_query.h +66 -0
- package/third_party/s2geometry/src/s2/s2contains_vertex_query_test.cc +67 -0
- package/third_party/s2geometry/src/s2/s2convex_hull_query.cc +198 -0
- package/third_party/s2geometry/src/s2/s2convex_hull_query.h +110 -0
- package/third_party/s2geometry/src/s2/s2convex_hull_query_test.cc +208 -0
- package/third_party/s2geometry/src/s2/s2coords.cc +146 -0
- package/third_party/s2geometry/src/s2/s2coords.h +459 -0
- package/third_party/s2geometry/src/s2/s2coords_internal.h +71 -0
- package/third_party/s2geometry/src/s2/s2coords_test.cc +218 -0
- package/third_party/s2geometry/src/s2/s2crossing_edge_query.cc +380 -0
- package/third_party/s2geometry/src/s2/s2crossing_edge_query.h +220 -0
- package/third_party/s2geometry/src/s2/s2crossing_edge_query_test.cc +382 -0
- package/third_party/s2geometry/src/s2/s2debug.cc +23 -0
- package/third_party/s2geometry/src/s2/s2debug.h +69 -0
- package/third_party/s2geometry/src/s2/s2distance_target.h +165 -0
- package/third_party/s2geometry/src/s2/s2earth.cc +52 -0
- package/third_party/s2geometry/src/s2/s2earth.h +268 -0
- package/third_party/s2geometry/src/s2/s2earth_test.cc +146 -0
- package/third_party/s2geometry/src/s2/s2edge_clipping.cc +462 -0
- package/third_party/s2geometry/src/s2/s2edge_clipping.h +183 -0
- package/third_party/s2geometry/src/s2/s2edge_clipping_test.cc +335 -0
- package/third_party/s2geometry/src/s2/s2edge_crosser.cc +85 -0
- package/third_party/s2geometry/src/s2/s2edge_crosser.h +343 -0
- package/third_party/s2geometry/src/s2/s2edge_crosser_test.cc +264 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings.cc +515 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings.h +138 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings_internal.h +59 -0
- package/third_party/s2geometry/src/s2/s2edge_crossings_test.cc +246 -0
- package/third_party/s2geometry/src/s2/s2edge_distances.cc +419 -0
- package/third_party/s2geometry/src/s2/s2edge_distances.h +192 -0
- package/third_party/s2geometry/src/s2/s2edge_distances_test.cc +539 -0
- package/third_party/s2geometry/src/s2/s2edge_tessellator.cc +276 -0
- package/third_party/s2geometry/src/s2/s2edge_tessellator.h +101 -0
- package/third_party/s2geometry/src/s2/s2edge_tessellator_test.cc +492 -0
- package/third_party/s2geometry/src/s2/s2edge_vector_shape.h +85 -0
- package/third_party/s2geometry/src/s2/s2edge_vector_shape_test.cc +66 -0
- package/third_party/s2geometry/src/s2/s2error.cc +29 -0
- package/third_party/s2geometry/src/s2/s2error.h +147 -0
- package/third_party/s2geometry/src/s2/s2error_test.cc +31 -0
- package/third_party/s2geometry/src/s2/s2furthest_edge_query.cc +117 -0
- package/third_party/s2geometry/src/s2/s2furthest_edge_query.h +439 -0
- package/third_party/s2geometry/src/s2/s2furthest_edge_query_test.cc +487 -0
- package/third_party/s2geometry/src/s2/s2latlng.cc +90 -0
- package/third_party/s2geometry/src/s2/s2latlng.h +234 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect.cc +727 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect.h +434 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_bounder.cc +344 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_bounder.h +89 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_bounder_test.cc +306 -0
- package/third_party/s2geometry/src/s2/s2latlng_rect_test.cc +1030 -0
- package/third_party/s2geometry/src/s2/s2latlng_test.cc +165 -0
- package/third_party/s2geometry/src/s2/s2lax_loop_shape.cc +104 -0
- package/third_party/s2geometry/src/s2/s2lax_loop_shape.h +153 -0
- package/third_party/s2geometry/src/s2/s2lax_loop_shape_test.cc +101 -0
- package/third_party/s2geometry/src/s2/s2lax_polygon_shape.cc +348 -0
- package/third_party/s2geometry/src/s2/s2lax_polygon_shape.h +183 -0
- package/third_party/s2geometry/src/s2/s2lax_polygon_shape_test.cc +234 -0
- package/third_party/s2geometry/src/s2/s2lax_polyline_shape.cc +118 -0
- package/third_party/s2geometry/src/s2/s2lax_polyline_shape.h +124 -0
- package/third_party/s2geometry/src/s2/s2lax_polyline_shape_test.cc +62 -0
- package/third_party/s2geometry/src/s2/s2loop.cc +1509 -0
- package/third_party/s2geometry/src/s2/s2loop.h +711 -0
- package/third_party/s2geometry/src/s2/s2loop_measures.cc +313 -0
- package/third_party/s2geometry/src/s2/s2loop_measures.h +280 -0
- package/third_party/s2geometry/src/s2/s2loop_measures_test.cc +367 -0
- package/third_party/s2geometry/src/s2/s2loop_test.cc +1371 -0
- package/third_party/s2geometry/src/s2/s2max_distance_targets.cc +265 -0
- package/third_party/s2geometry/src/s2/s2max_distance_targets.h +241 -0
- package/third_party/s2geometry/src/s2/s2max_distance_targets_test.cc +367 -0
- package/third_party/s2geometry/src/s2/s2measures.cc +128 -0
- package/third_party/s2geometry/src/s2/s2measures.h +78 -0
- package/third_party/s2geometry/src/s2/s2measures_test.cc +135 -0
- package/third_party/s2geometry/src/s2/s2metrics.cc +122 -0
- package/third_party/s2geometry/src/s2/s2metrics.h +199 -0
- package/third_party/s2geometry/src/s2/s2metrics_test.cc +127 -0
- package/third_party/s2geometry/src/s2/s2min_distance_targets.cc +295 -0
- package/third_party/s2geometry/src/s2/s2min_distance_targets.h +273 -0
- package/third_party/s2geometry/src/s2/s2min_distance_targets_test.cc +239 -0
- package/third_party/s2geometry/src/s2/s2padded_cell.cc +162 -0
- package/third_party/s2geometry/src/s2/s2padded_cell.h +108 -0
- package/third_party/s2geometry/src/s2/s2padded_cell_test.cc +138 -0
- package/third_party/s2geometry/src/s2/s2point.h +38 -0
- package/third_party/s2geometry/src/s2/s2point_compression.cc +388 -0
- package/third_party/s2geometry/src/s2/s2point_compression.h +78 -0
- package/third_party/s2geometry/src/s2/s2point_compression_test.cc +305 -0
- package/third_party/s2geometry/src/s2/s2point_index.h +345 -0
- package/third_party/s2geometry/src/s2/s2point_index_test.cc +147 -0
- package/third_party/s2geometry/src/s2/s2point_region.cc +72 -0
- package/third_party/s2geometry/src/s2/s2point_region.h +76 -0
- package/third_party/s2geometry/src/s2/s2point_region_test.cc +100 -0
- package/third_party/s2geometry/src/s2/s2point_span.h +57 -0
- package/third_party/s2geometry/src/s2/s2point_test.cc +47 -0
- package/third_party/s2geometry/src/s2/s2point_vector_shape.h +127 -0
- package/third_party/s2geometry/src/s2/s2point_vector_shape_test.cc +59 -0
- package/third_party/s2geometry/src/s2/s2pointutil.cc +131 -0
- package/third_party/s2geometry/src/s2/s2pointutil.h +138 -0
- package/third_party/s2geometry/src/s2/s2pointutil_test.cc +157 -0
- package/third_party/s2geometry/src/s2/s2polygon.cc +1569 -0
- package/third_party/s2geometry/src/s2/s2polygon.h +934 -0
- package/third_party/s2geometry/src/s2/s2polygon_test.cc +3025 -0
- package/third_party/s2geometry/src/s2/s2polyline.cc +645 -0
- package/third_party/s2geometry/src/s2/s2polyline.h +379 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment.cc +414 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment.h +245 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment_internal.h +158 -0
- package/third_party/s2geometry/src/s2/s2polyline_alignment_test.cc +610 -0
- package/third_party/s2geometry/src/s2/s2polyline_measures.cc +42 -0
- package/third_party/s2geometry/src/s2/s2polyline_measures.h +53 -0
- package/third_party/s2geometry/src/s2/s2polyline_measures_test.cc +57 -0
- package/third_party/s2geometry/src/s2/s2polyline_simplifier.cc +187 -0
- package/third_party/s2geometry/src/s2/s2polyline_simplifier.h +109 -0
- package/third_party/s2geometry/src/s2/s2polyline_simplifier_test.cc +165 -0
- package/third_party/s2geometry/src/s2/s2polyline_test.cc +554 -0
- package/third_party/s2geometry/src/s2/s2predicates.cc +1486 -0
- package/third_party/s2geometry/src/s2/s2predicates.h +282 -0
- package/third_party/s2geometry/src/s2/s2predicates_internal.h +135 -0
- package/third_party/s2geometry/src/s2/s2predicates_test.cc +1427 -0
- package/third_party/s2geometry/src/s2/s2projections.cc +109 -0
- package/third_party/s2geometry/src/s2/s2projections.h +161 -0
- package/third_party/s2geometry/src/s2/s2projections_test.cc +78 -0
- package/third_party/s2geometry/src/s2/s2r2rect.cc +88 -0
- package/third_party/s2geometry/src/s2/s2r2rect.h +292 -0
- package/third_party/s2geometry/src/s2/s2r2rect_test.cc +312 -0
- package/third_party/s2geometry/src/s2/s2region.cc +26 -0
- package/third_party/s2geometry/src/s2/s2region.h +142 -0
- package/third_party/s2geometry/src/s2/s2region_coverer.cc +514 -0
- package/third_party/s2geometry/src/s2/s2region_coverer.h +356 -0
- package/third_party/s2geometry/src/s2/s2region_coverer_test.cc +509 -0
- package/third_party/s2geometry/src/s2/s2region_intersection.cc +84 -0
- package/third_party/s2geometry/src/s2/s2region_intersection.h +79 -0
- package/third_party/s2geometry/src/s2/s2region_term_indexer.cc +270 -0
- package/third_party/s2geometry/src/s2/s2region_term_indexer.h +299 -0
- package/third_party/s2geometry/src/s2/s2region_term_indexer_test.cc +209 -0
- package/third_party/s2geometry/src/s2/s2region_test.cc +370 -0
- package/third_party/s2geometry/src/s2/s2region_union.cc +90 -0
- package/third_party/s2geometry/src/s2/s2region_union.h +83 -0
- package/third_party/s2geometry/src/s2/s2region_union_test.cc +89 -0
- package/third_party/s2geometry/src/s2/s2shape.h +283 -0
- package/third_party/s2geometry/src/s2/s2shape_index.cc +321 -0
- package/third_party/s2geometry/src/s2/s2shape_index.h +781 -0
- package/third_party/s2geometry/src/s2/s2shape_index_buffered_region.cc +113 -0
- package/third_party/s2geometry/src/s2/s2shape_index_buffered_region.h +135 -0
- package/third_party/s2geometry/src/s2/s2shape_index_buffered_region_test.cc +162 -0
- package/third_party/s2geometry/src/s2/s2shape_index_measures.cc +92 -0
- package/third_party/s2geometry/src/s2/s2shape_index_measures.h +100 -0
- package/third_party/s2geometry/src/s2/s2shape_index_measures_test.cc +136 -0
- package/third_party/s2geometry/src/s2/s2shape_index_region.h +350 -0
- package/third_party/s2geometry/src/s2/s2shape_index_region_test.cc +161 -0
- package/third_party/s2geometry/src/s2/s2shape_index_test.cc +24 -0
- package/third_party/s2geometry/src/s2/s2shape_measures.cc +138 -0
- package/third_party/s2geometry/src/s2/s2shape_measures.h +95 -0
- package/third_party/s2geometry/src/s2/s2shape_measures_test.cc +139 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries.cc +120 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries.h +66 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries_test.cc +170 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_coding.cc +253 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_coding.h +283 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_coding_test.cc +54 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force.cc +40 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force.h +41 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force_test.cc +55 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_count_edges.h +57 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_count_edges_test.cc +43 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator.cc +45 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator.h +72 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator_test.cc +116 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point.cc +107 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point.h +48 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point_test.cc +104 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator.cc +58 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator.h +65 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator_test.cc +61 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_shape_edge.h +58 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_shape_edge_id.h +97 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_testing.cc +104 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_testing.h +36 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs.cc +440 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs.h +72 -0
- package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs_test.cc +184 -0
- package/third_party/s2geometry/src/s2/s2testing.cc +464 -0
- package/third_party/s2geometry/src/s2/s2testing.h +385 -0
- package/third_party/s2geometry/src/s2/s2testing_test.cc +166 -0
- package/third_party/s2geometry/src/s2/s2text_format.cc +506 -0
- package/third_party/s2geometry/src/s2/s2text_format.h +289 -0
- package/third_party/s2geometry/src/s2/s2text_format_test.cc +417 -0
- package/third_party/s2geometry/src/s2/s2wedge_relations.cc +80 -0
- package/third_party/s2geometry/src/s2/s2wedge_relations.h +64 -0
- package/third_party/s2geometry/src/s2/s2wedge_relations_test.cc +89 -0
- package/third_party/s2geometry/src/s2/sequence_lexicon.h +296 -0
- package/third_party/s2geometry/src/s2/sequence_lexicon_test.cc +113 -0
- package/third_party/s2geometry/src/s2/strings/ostringstream.cc +35 -0
- package/third_party/s2geometry/src/s2/strings/ostringstream.h +105 -0
- package/third_party/s2geometry/src/s2/strings/serialize.cc +46 -0
- package/third_party/s2geometry/src/s2/strings/serialize.h +40 -0
- package/third_party/s2geometry/src/s2/third_party/absl/algorithm/algorithm.h +187 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/attributes.h +666 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/casts.h +189 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/config.h +462 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/dynamic_annotations.cc +129 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/dynamic_annotations.h +394 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/atomic_hook.h +168 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/identity.h +33 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/inline_variable.h +117 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/invoke.h +188 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/raw_logging.cc +254 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/raw_logging.h +205 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/throw_delegate.cc +106 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/throw_delegate.h +71 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/internal/unaligned_access.h +322 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/log_severity.h +77 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/macros.h +236 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/optimization.h +177 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/policy_checks.h +124 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/port.h +97 -0
- package/third_party/s2geometry/src/s2/third_party/absl/base/thread_annotations.h +277 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/fixed_array.h +523 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/inlined_vector.h +1453 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/internal/compressed_tuple.h +191 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/internal/container_memory.h +424 -0
- package/third_party/s2geometry/src/s2/third_party/absl/container/internal/layout.h +739 -0
- package/third_party/s2geometry/src/s2/third_party/absl/memory/memory.h +755 -0
- package/third_party/s2geometry/src/s2/third_party/absl/meta/type_traits.h +436 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128.cc +232 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128.h +656 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128_have_intrinsic.inc +3 -0
- package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128_no_intrinsic.inc +3 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii.cc +198 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii.h +239 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii_ctype.h +66 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/bits.h +53 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/memutil.cc +110 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/memutil.h +146 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/resize_uninitialized.h +72 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/match.cc +38 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/match.h +89 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/numbers.cc +909 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/numbers.h +187 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_cat.cc +240 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_cat.h +398 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_join.h +22 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_split.cc +47 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/str_split.h +43 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/string_view.cc +245 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/string_view.h +602 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/strip.cc +42 -0
- package/third_party/s2geometry/src/s2/third_party/absl/strings/strip.h +130 -0
- package/third_party/s2geometry/src/s2/third_party/absl/types/span.h +793 -0
- package/third_party/s2geometry/src/s2/third_party/absl/utility/utility.h +299 -0
- package/third_party/s2geometry/src/s2/util/bits/bit-interleave.cc +274 -0
- package/third_party/s2geometry/src/s2/util/bits/bit-interleave.h +53 -0
- package/third_party/s2geometry/src/s2/util/bits/bits.cc +155 -0
- package/third_party/s2geometry/src/s2/util/bits/bits.h +745 -0
- package/third_party/s2geometry/src/s2/util/coding/coder.cc +83 -0
- package/third_party/s2geometry/src/s2/util/coding/coder.h +553 -0
- package/third_party/s2geometry/src/s2/util/coding/nth-derivative.h +134 -0
- package/third_party/s2geometry/src/s2/util/coding/transforms.h +62 -0
- package/third_party/s2geometry/src/s2/util/coding/varint.cc +289 -0
- package/third_party/s2geometry/src/s2/util/coding/varint.h +476 -0
- package/third_party/s2geometry/src/s2/util/endian/endian.h +859 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree.h +2471 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree_container.h +411 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree_map.h +79 -0
- package/third_party/s2geometry/src/s2/util/gtl/btree_set.h +73 -0
- package/third_party/s2geometry/src/s2/util/gtl/compact_array.h +653 -0
- package/third_party/s2geometry/src/s2/util/gtl/container_logging.h +291 -0
- package/third_party/s2geometry/src/s2/util/gtl/dense_hash_set.h +358 -0
- package/third_party/s2geometry/src/s2/util/gtl/densehashtable.h +1493 -0
- package/third_party/s2geometry/src/s2/util/gtl/hashtable_common.h +253 -0
- package/third_party/s2geometry/src/s2/util/gtl/layout.h +28 -0
- package/third_party/s2geometry/src/s2/util/gtl/legacy_random_shuffle.h +77 -0
- package/third_party/s2geometry/src/s2/util/hash/mix.h +76 -0
- package/third_party/s2geometry/src/s2/util/math/exactfloat/exactfloat.cc +832 -0
- package/third_party/s2geometry/src/s2/util/math/exactfloat/exactfloat.h +646 -0
- package/third_party/s2geometry/src/s2/util/math/mathutil.cc +75 -0
- package/third_party/s2geometry/src/s2/util/math/mathutil.h +189 -0
- package/third_party/s2geometry/src/s2/util/math/matrix3x3.h +574 -0
- package/third_party/s2geometry/src/s2/util/math/vector.h +569 -0
- package/third_party/s2geometry/src/s2/util/math/vector3_hash.h +54 -0
- package/third_party/s2geometry/src/s2/util/units/length-units.cc +21 -0
- package/third_party/s2geometry/src/s2/util/units/length-units.h +135 -0
- package/third_party/s2geometry/src/s2/util/units/physical-units.h +313 -0
- package/third_party/s2geometry/src/s2/value_lexicon.h +234 -0
- package/third_party/s2geometry/src/s2/value_lexicon_test.cc +121 -0
- package/third_party/s2geometry/third_party/cmake/FindGFlags.cmake +48 -0
- package/third_party/s2geometry/third_party/cmake/FindGlog.cmake +48 -0
|
@@ -0,0 +1,841 @@
|
|
|
1
|
+
// Copyright 2018 Google Inc. All Rights Reserved.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
//
|
|
15
|
+
|
|
16
|
+
// Author: ericv@google.com (Eric Veach)
|
|
17
|
+
//
|
|
18
|
+
// See S2ClosestCellQueryBase (defined below) for an overview.
|
|
19
|
+
|
|
20
|
+
#ifndef S2_S2CLOSEST_CELL_QUERY_BASE_H_
|
|
21
|
+
#define S2_S2CLOSEST_CELL_QUERY_BASE_H_
|
|
22
|
+
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "s2/base/logging.h"
|
|
26
|
+
#include "s2/util/gtl/btree_set.h"
|
|
27
|
+
#include "s2/third_party/absl/container/inlined_vector.h"
|
|
28
|
+
#include "s2/s1chord_angle.h"
|
|
29
|
+
#include "s2/s2cap.h"
|
|
30
|
+
#include "s2/s2cell_id.h"
|
|
31
|
+
#include "s2/s2cell_index.h"
|
|
32
|
+
#include "s2/s2cell_union.h"
|
|
33
|
+
#include "s2/s2distance_target.h"
|
|
34
|
+
#include "s2/s2region_coverer.h"
|
|
35
|
+
#include "s2/util/gtl/dense_hash_set.h"
|
|
36
|
+
#include "s2/util/hash/mix.h"
|
|
37
|
+
|
|
38
|
+
// S2ClosestCellQueryBase is a templatized class for finding the closest
|
|
39
|
+
// (cell_id, label) pairs in an S2CellIndex to a given target. It is not
|
|
40
|
+
// intended to be used directly, but rather to serve as the implementation of
|
|
41
|
+
// various specialized classes with more convenient APIs (such as
|
|
42
|
+
// S2ClosestCellQuery). It is flexible enough so that it can be adapted to
|
|
43
|
+
// compute maximum distances and even potentially Hausdorff distances.
|
|
44
|
+
//
|
|
45
|
+
// By using the appropriate options, this class can answer questions such as:
|
|
46
|
+
//
|
|
47
|
+
// - Find the minimum distance between a cell collection A and a target B.
|
|
48
|
+
// - Find all cells in collection A that are within a distance D of target B.
|
|
49
|
+
// - Find the k cells of collection A that are closest to a given point P.
|
|
50
|
+
//
|
|
51
|
+
// The target is any class that implements the S2DistanceTarget interface.
|
|
52
|
+
// There are predefined targets for points, edges, S2Cells, S2CellUnions, and
|
|
53
|
+
// S2ShapeIndexes (arbitrary collctions of points, polylines, and polygons).
|
|
54
|
+
//
|
|
55
|
+
// The Distance template argument is used to represent distances. Usually it
|
|
56
|
+
// is a thin wrapper around S1ChordAngle, but another distance type may be
|
|
57
|
+
// used as long as it implements the Distance concept described in
|
|
58
|
+
// s2distance_targets.h. For example this can be used to measure maximum
|
|
59
|
+
// distances, to get more accuracy, or to measure non-spheroidal distances.
|
|
60
|
+
template <class Distance>
|
|
61
|
+
class S2ClosestCellQueryBase {
|
|
62
|
+
public:
|
|
63
|
+
using Delta = typename Distance::Delta;
|
|
64
|
+
using Label = S2CellIndex::Label;
|
|
65
|
+
using LabelledCell = S2CellIndex::LabelledCell;
|
|
66
|
+
|
|
67
|
+
// Options that control the set of cells returned. Note that by default
|
|
68
|
+
// *all* cells are returned, so you will always want to set either the
|
|
69
|
+
// max_results() option or the max_distance() option (or both).
|
|
70
|
+
//
|
|
71
|
+
// This class is also available as S2ClosestCellQueryBase<Data>::Options.
|
|
72
|
+
//
|
|
73
|
+
// The Distance template argument is described below.
|
|
74
|
+
class Options {
|
|
75
|
+
public:
|
|
76
|
+
Options();
|
|
77
|
+
|
|
78
|
+
// Specifies that at most "max_results" cells should be returned.
|
|
79
|
+
//
|
|
80
|
+
// REQUIRES: max_results >= 1
|
|
81
|
+
// DEFAULT: kMaxMaxResults
|
|
82
|
+
int max_results() const;
|
|
83
|
+
void set_max_results(int max_results);
|
|
84
|
+
static constexpr int kMaxMaxResults = std::numeric_limits<int>::max();
|
|
85
|
+
|
|
86
|
+
// Specifies that only cells whose distance to the target is less than
|
|
87
|
+
// "max_distance" should be returned.
|
|
88
|
+
//
|
|
89
|
+
// Note that cells whose distance is exactly equal to "max_distance" are
|
|
90
|
+
// not returned. In most cases this doesn't matter (since distances are
|
|
91
|
+
// not computed exactly in the first place), but if such cells are needed
|
|
92
|
+
// then you can retrieve them by specifying "max_distance" as the next
|
|
93
|
+
// largest representable Distance. For example, if Distance is an
|
|
94
|
+
// S1ChordAngle then you can specify max_distance.Successor().
|
|
95
|
+
//
|
|
96
|
+
// DEFAULT: Distance::Infinity()
|
|
97
|
+
Distance max_distance() const;
|
|
98
|
+
void set_max_distance(Distance max_distance);
|
|
99
|
+
|
|
100
|
+
// Specifies that cells up to max_error() further away than the true
|
|
101
|
+
// closest cells may be substituted in the result set, as long as such
|
|
102
|
+
// cells satisfy all the remaining search criteria (such as max_distance).
|
|
103
|
+
// This option only has an effect if max_results() is also specified;
|
|
104
|
+
// otherwise all cells closer than max_distance() will always be returned.
|
|
105
|
+
//
|
|
106
|
+
// Note that this does not affect how the distance between cells is
|
|
107
|
+
// computed; it simply gives the algorithm permission to stop the search
|
|
108
|
+
// early as soon as the best possible improvement drops below max_error().
|
|
109
|
+
//
|
|
110
|
+
// This can be used to implement distance predicates efficiently. For
|
|
111
|
+
// example, to determine whether the minimum distance is less than D, the
|
|
112
|
+
// IsDistanceLess() method sets max_results() == 1 and max_distance() ==
|
|
113
|
+
// max_error() == D. This causes the algorithm to terminate as soon as it
|
|
114
|
+
// finds any cell whose distance is less than D, rather than continuing to
|
|
115
|
+
// search for a cell that is even closer.
|
|
116
|
+
//
|
|
117
|
+
// DEFAULT: Distance::Delta::Zero()
|
|
118
|
+
Delta max_error() const;
|
|
119
|
+
void set_max_error(Delta max_error);
|
|
120
|
+
|
|
121
|
+
// Specifies that cells must intersect the given S2Region. "region" is
|
|
122
|
+
// owned by the caller and must persist during the lifetime of this
|
|
123
|
+
// object. The value may be changed between calls to FindClosestPoints(),
|
|
124
|
+
// or reset by calling set_region(nullptr).
|
|
125
|
+
//
|
|
126
|
+
// Note that if you want to set the region to a disc around a target
|
|
127
|
+
// point, it is faster to use a PointTarget with set_max_distance()
|
|
128
|
+
// instead. You can also call both methods, e.g. to set a maximum
|
|
129
|
+
// distance and also require that cells lie within a given rectangle.
|
|
130
|
+
const S2Region* region() const;
|
|
131
|
+
void set_region(const S2Region* region);
|
|
132
|
+
|
|
133
|
+
// Specifies that distances should be computed by examining every cell
|
|
134
|
+
// rather than using the S2ShapeIndex. This is useful for testing,
|
|
135
|
+
// benchmarking, and debugging.
|
|
136
|
+
//
|
|
137
|
+
// DEFAULT: false
|
|
138
|
+
bool use_brute_force() const;
|
|
139
|
+
void set_use_brute_force(bool use_brute_force);
|
|
140
|
+
|
|
141
|
+
private:
|
|
142
|
+
Distance max_distance_ = Distance::Infinity();
|
|
143
|
+
Delta max_error_ = Delta::Zero();
|
|
144
|
+
const S2Region* region_ = nullptr;
|
|
145
|
+
int max_results_ = kMaxMaxResults;
|
|
146
|
+
bool use_brute_force_ = false;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// The Target class represents the geometry to which the distance is
|
|
150
|
+
// measured. For example, there can be subtypes for measuring the distance
|
|
151
|
+
// to a point, an edge, or to an S2ShapeIndex (an arbitrary collection of
|
|
152
|
+
// geometry).
|
|
153
|
+
//
|
|
154
|
+
// Implementations do *not* need to be thread-safe. They may cache data or
|
|
155
|
+
// allocate temporary data structures in order to improve performance.
|
|
156
|
+
using Target = S2DistanceTarget<Distance>;
|
|
157
|
+
|
|
158
|
+
// Each "Result" object represents a closest (cell_id, label) pair.
|
|
159
|
+
class Result {
|
|
160
|
+
public:
|
|
161
|
+
// The default constructor yields an empty result, with a distance() of
|
|
162
|
+
// Infinity() and invalid cell_id() and label() values.
|
|
163
|
+
Result() : distance_(Distance::Infinity()), cell_id_(S2CellId::None()),
|
|
164
|
+
label_(-1) {}
|
|
165
|
+
|
|
166
|
+
// Constructs a Result object for the given (cell_id, label) pair.
|
|
167
|
+
Result(Distance distance, S2CellId cell_id, Label label)
|
|
168
|
+
: distance_(distance), cell_id_(cell_id), label_(label) {}
|
|
169
|
+
|
|
170
|
+
// The distance from the target to this cell.
|
|
171
|
+
Distance distance() const { return distance_; }
|
|
172
|
+
|
|
173
|
+
// The cell itself.
|
|
174
|
+
S2CellId cell_id() const { return cell_id_; }
|
|
175
|
+
|
|
176
|
+
// The label associated with this S2CellId.
|
|
177
|
+
Label label() const { return label_; }
|
|
178
|
+
|
|
179
|
+
// Returns true if this Result object does not refer to any cell.
|
|
180
|
+
// (The only case where an empty Result is returned is when the
|
|
181
|
+
// FindClosestCell() method does not find any cells that meet the
|
|
182
|
+
// specified criteria.)
|
|
183
|
+
bool is_empty() const { return cell_id_ == S2CellId::None(); }
|
|
184
|
+
|
|
185
|
+
// Returns true if two Result objects are identical.
|
|
186
|
+
friend bool operator==(const Result& x, const Result& y) {
|
|
187
|
+
return (x.distance_ == y.distance_ &&
|
|
188
|
+
x.cell_id_ == y.cell_id_ &&
|
|
189
|
+
x.label_ == y.label_);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Compares two Result objects first by distance, then by cell_id and
|
|
193
|
+
// finally by label.
|
|
194
|
+
friend bool operator<(const Result& x, const Result& y) {
|
|
195
|
+
if (x.distance_ < y.distance_) return true;
|
|
196
|
+
if (y.distance_ < x.distance_) return false;
|
|
197
|
+
if (x.cell_id_ < y.cell_id_) return true;
|
|
198
|
+
if (y.cell_id_ < x.cell_id_) return false;
|
|
199
|
+
return x.label_ < y.label_;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Indicates that linear rather than binary search should be used when this
|
|
203
|
+
// type is used as the key in gtl::btree data structures.
|
|
204
|
+
using goog_btree_prefer_linear_node_search = std::true_type;
|
|
205
|
+
|
|
206
|
+
private:
|
|
207
|
+
Distance distance_;
|
|
208
|
+
S2CellId cell_id_;
|
|
209
|
+
Label label_;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// The minimum number of ranges that a cell must contain to enqueue it
|
|
213
|
+
// rather than processing its contents immediately.
|
|
214
|
+
static constexpr int kMinRangesToEnqueue = 6;
|
|
215
|
+
|
|
216
|
+
// Default constructor; requires Init() to be called.
|
|
217
|
+
S2ClosestCellQueryBase();
|
|
218
|
+
~S2ClosestCellQueryBase();
|
|
219
|
+
|
|
220
|
+
// Convenience constructor that calls Init().
|
|
221
|
+
explicit S2ClosestCellQueryBase(const S2CellIndex* index);
|
|
222
|
+
|
|
223
|
+
// S2ClosestCellQueryBase is not copyable.
|
|
224
|
+
S2ClosestCellQueryBase(const S2ClosestCellQueryBase&) = delete;
|
|
225
|
+
void operator=(const S2ClosestCellQueryBase&) = delete;
|
|
226
|
+
|
|
227
|
+
// Initializes the query.
|
|
228
|
+
// REQUIRES: ReInit() must be called if "index" is modified.
|
|
229
|
+
void Init(const S2CellIndex* index);
|
|
230
|
+
|
|
231
|
+
// Reinitializes the query. This method must be called whenever the
|
|
232
|
+
// underlying index is modified.
|
|
233
|
+
void ReInit();
|
|
234
|
+
|
|
235
|
+
// Return a reference to the underlying S2CellIndex.
|
|
236
|
+
const S2CellIndex& index() const;
|
|
237
|
+
|
|
238
|
+
// Returns the closest (cell_id, label) pairs to the given target that
|
|
239
|
+
// satisfy the given options. This method may be called multiple times.
|
|
240
|
+
std::vector<Result> FindClosestCells(Target* target, const Options& options);
|
|
241
|
+
|
|
242
|
+
// This version can be more efficient when this method is called many times,
|
|
243
|
+
// since it does not require allocating a new vector on each call.
|
|
244
|
+
void FindClosestCells(Target* target, const Options& options,
|
|
245
|
+
std::vector<Result>* results);
|
|
246
|
+
|
|
247
|
+
// Convenience method that returns exactly one (cell_id, label) pair. If no
|
|
248
|
+
// cells satisfy the given search criteria, then a Result with
|
|
249
|
+
// distance() == Infinity() and is_empty() == true is returned.
|
|
250
|
+
//
|
|
251
|
+
// REQUIRES: options.max_results() == 1
|
|
252
|
+
Result FindClosestCell(Target* target, const Options& options);
|
|
253
|
+
|
|
254
|
+
private:
|
|
255
|
+
using CellIterator = S2CellIndex::CellIterator;
|
|
256
|
+
using ContentsIterator = S2CellIndex::ContentsIterator;
|
|
257
|
+
using NonEmptyRangeIterator = S2CellIndex::NonEmptyRangeIterator;
|
|
258
|
+
using RangeIterator = S2CellIndex::RangeIterator;
|
|
259
|
+
|
|
260
|
+
const Options& options() const { return *options_; }
|
|
261
|
+
void FindClosestCellsInternal(Target* target, const Options& options);
|
|
262
|
+
void FindClosestCellsBruteForce();
|
|
263
|
+
void FindClosestCellsOptimized();
|
|
264
|
+
void InitQueue();
|
|
265
|
+
void InitCovering();
|
|
266
|
+
void AddInitialRange(S2CellId first_id, S2CellId last_id);
|
|
267
|
+
void MaybeAddResult(S2CellId cell_id, Label label);
|
|
268
|
+
bool ProcessOrEnqueue(S2CellId id, NonEmptyRangeIterator* iter, bool seek);
|
|
269
|
+
void AddRange(const RangeIterator& range);
|
|
270
|
+
|
|
271
|
+
const S2CellIndex* index_;
|
|
272
|
+
const Options* options_;
|
|
273
|
+
Target* target_;
|
|
274
|
+
|
|
275
|
+
// True if max_error() must be subtracted from priority queue cell distances
|
|
276
|
+
// in order to ensure that such distances are measured conservatively. This
|
|
277
|
+
// is true only if the target takes advantage of max_error() in order to
|
|
278
|
+
// return faster results, and 0 < max_error() < distance_limit_.
|
|
279
|
+
bool use_conservative_cell_distance_;
|
|
280
|
+
|
|
281
|
+
// For the optimized algorithm we precompute the top-level S2CellIds that
|
|
282
|
+
// will be added to the priority queue. There can be at most 6 of these
|
|
283
|
+
// cells. Essentially this is just a covering of the indexed cells.
|
|
284
|
+
std::vector<S2CellId> index_covering_;
|
|
285
|
+
|
|
286
|
+
// The distance beyond which we can safely ignore further candidate cells.
|
|
287
|
+
// (Candidates that are exactly at the limit are ignored; this is more
|
|
288
|
+
// efficient for UpdateMinDistance() and should not affect clients since
|
|
289
|
+
// distance measurements have a small amount of error anyway.)
|
|
290
|
+
//
|
|
291
|
+
// Initially this is the same as the maximum distance specified by the user,
|
|
292
|
+
// but it can also be updated by the algorithm (see MaybeAddResult).
|
|
293
|
+
Distance distance_limit_;
|
|
294
|
+
|
|
295
|
+
// The current result set is stored in one of three ways:
|
|
296
|
+
//
|
|
297
|
+
// - If max_results() == 1, the best result is kept in result_singleton_.
|
|
298
|
+
//
|
|
299
|
+
// - If max_results() == kMaxMaxResults, results are appended to
|
|
300
|
+
// result_vector_ and sorted/uniqued at the end.
|
|
301
|
+
//
|
|
302
|
+
// - Otherwise results are kept in a btree_set so that we can progressively
|
|
303
|
+
// reduce the distance limit once max_results() results have been found.
|
|
304
|
+
// (A priority queue is not sufficient because we need to be able to
|
|
305
|
+
// check whether a candidate cell is already in the result set.)
|
|
306
|
+
//
|
|
307
|
+
// TODO(ericv): Check whether it would be faster to use avoid_duplicates_
|
|
308
|
+
// when result_set_ is used so that we could use a priority queue instead.
|
|
309
|
+
Result result_singleton_;
|
|
310
|
+
std::vector<Result> result_vector_;
|
|
311
|
+
gtl::btree_set<Result> result_set_;
|
|
312
|
+
|
|
313
|
+
// When the results are stored in a btree_set (see above), usually
|
|
314
|
+
// duplicates can be removed simply by inserting candidate cells in the
|
|
315
|
+
// current result set. However this is not true if Options::max_error() > 0
|
|
316
|
+
// and the Target subtype takes advantage of this by returning suboptimal
|
|
317
|
+
// distances. This is because when UpdateMinDistance() is called with
|
|
318
|
+
// different "min_dist" parameters (i.e., the distance to beat), the
|
|
319
|
+
// implementation may return a different distance for the same cell. Since
|
|
320
|
+
// the btree_set is keyed by (distance, cell_id, label) this can create
|
|
321
|
+
// duplicate results.
|
|
322
|
+
//
|
|
323
|
+
// The flag below is true when duplicates must be avoided explicitly. This
|
|
324
|
+
// is achieved by maintaining a separate set keyed by (cell_id, label) only,
|
|
325
|
+
// and checking whether each edge is in that set before computing the
|
|
326
|
+
// distance to it.
|
|
327
|
+
//
|
|
328
|
+
// TODO(ericv): Check whether it is faster to avoid duplicates by default
|
|
329
|
+
// (even when Options::max_results() == 1), rather than just when we need to.
|
|
330
|
+
bool avoid_duplicates_;
|
|
331
|
+
struct LabelledCellHash {
|
|
332
|
+
size_t operator()(LabelledCell x) const {
|
|
333
|
+
HashMix mix(x.cell_id.id());
|
|
334
|
+
mix.Mix(x.label);
|
|
335
|
+
return mix.get();
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
gtl::dense_hash_set<LabelledCell, LabelledCellHash> tested_cells_;
|
|
339
|
+
|
|
340
|
+
// The algorithm maintains a priority queue of unprocessed S2CellIds, sorted
|
|
341
|
+
// in increasing order of distance from the target.
|
|
342
|
+
struct QueueEntry {
|
|
343
|
+
// A lower bound on the distance from the target to "id". This is the key
|
|
344
|
+
// of the priority queue.
|
|
345
|
+
Distance distance;
|
|
346
|
+
|
|
347
|
+
// The cell being queued.
|
|
348
|
+
S2CellId id;
|
|
349
|
+
|
|
350
|
+
QueueEntry(Distance _distance, S2CellId _id)
|
|
351
|
+
: distance(_distance), id(_id) {}
|
|
352
|
+
|
|
353
|
+
bool operator<(const QueueEntry& other) const {
|
|
354
|
+
// The priority queue returns the largest elements first, so we want the
|
|
355
|
+
// "largest" entry to have the smallest distance.
|
|
356
|
+
return other.distance < distance;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
using CellQueue =
|
|
360
|
+
std::priority_queue<QueueEntry, absl::InlinedVector<QueueEntry, 16>>;
|
|
361
|
+
CellQueue queue_;
|
|
362
|
+
|
|
363
|
+
// Used to iterate over the contents of an S2CellIndex range. It is defined
|
|
364
|
+
// here to take advantage of the fact that when multiple ranges are visited
|
|
365
|
+
// in increasing order, duplicates can automatically be eliminated.
|
|
366
|
+
S2CellIndex::ContentsIterator contents_it_;
|
|
367
|
+
|
|
368
|
+
// Temporaries, defined here to avoid multiple allocations / initializations.
|
|
369
|
+
|
|
370
|
+
std::vector<S2CellId> max_distance_covering_;
|
|
371
|
+
std::vector<S2CellId> intersection_with_max_distance_;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
////////////////// Implementation details follow ////////////////////
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
template <class Distance>
|
|
379
|
+
inline S2ClosestCellQueryBase<Distance>::Options::Options() {
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
template <class Distance>
|
|
383
|
+
inline int S2ClosestCellQueryBase<Distance>::Options::max_results() const {
|
|
384
|
+
return max_results_;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
template <class Distance>
|
|
388
|
+
inline void S2ClosestCellQueryBase<Distance>::Options::set_max_results(
|
|
389
|
+
int max_results) {
|
|
390
|
+
S2_DCHECK_GE(max_results, 1);
|
|
391
|
+
max_results_ = max_results;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
template <class Distance>
|
|
395
|
+
inline Distance S2ClosestCellQueryBase<Distance>::Options::max_distance()
|
|
396
|
+
const {
|
|
397
|
+
return max_distance_;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
template <class Distance>
|
|
401
|
+
inline void S2ClosestCellQueryBase<Distance>::Options::set_max_distance(
|
|
402
|
+
Distance max_distance) {
|
|
403
|
+
max_distance_ = max_distance;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
template <class Distance>
|
|
407
|
+
inline typename Distance::Delta
|
|
408
|
+
S2ClosestCellQueryBase<Distance>::Options::max_error() const {
|
|
409
|
+
return max_error_;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
template <class Distance>
|
|
413
|
+
inline void S2ClosestCellQueryBase<Distance>::Options::set_max_error(
|
|
414
|
+
Delta max_error) {
|
|
415
|
+
max_error_ = max_error;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
template <class Distance>
|
|
419
|
+
inline const S2Region* S2ClosestCellQueryBase<Distance>::Options::region()
|
|
420
|
+
const {
|
|
421
|
+
return region_;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
template <class Distance>
|
|
425
|
+
inline void S2ClosestCellQueryBase<Distance>::Options::set_region(
|
|
426
|
+
const S2Region* region) {
|
|
427
|
+
region_ = region;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
template <class Distance>
|
|
431
|
+
inline bool S2ClosestCellQueryBase<Distance>::Options::use_brute_force() const {
|
|
432
|
+
return use_brute_force_;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
template <class Distance>
|
|
436
|
+
inline void S2ClosestCellQueryBase<Distance>::Options::set_use_brute_force(
|
|
437
|
+
bool use_brute_force) {
|
|
438
|
+
use_brute_force_ = use_brute_force;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
template <class Distance>
|
|
442
|
+
S2ClosestCellQueryBase<Distance>::S2ClosestCellQueryBase()
|
|
443
|
+
: tested_cells_(1) /* expected_max_elements*/ {
|
|
444
|
+
tested_cells_.set_empty_key(LabelledCell(S2CellId::None(), -1));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
template <class Distance>
|
|
448
|
+
S2ClosestCellQueryBase<Distance>::~S2ClosestCellQueryBase() {
|
|
449
|
+
// Prevent inline destructor bloat by providing a definition.
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
template <class Distance>
|
|
453
|
+
inline S2ClosestCellQueryBase<Distance>::S2ClosestCellQueryBase(
|
|
454
|
+
const S2CellIndex* index) : S2ClosestCellQueryBase() {
|
|
455
|
+
Init(index);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
template <class Distance>
|
|
459
|
+
void S2ClosestCellQueryBase<Distance>::Init(
|
|
460
|
+
const S2CellIndex* index) {
|
|
461
|
+
index_ = index;
|
|
462
|
+
contents_it_.Init(index);
|
|
463
|
+
ReInit();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
template <class Distance>
|
|
467
|
+
void S2ClosestCellQueryBase<Distance>::ReInit() {
|
|
468
|
+
index_covering_.clear();
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
template <class Distance>
|
|
472
|
+
inline const S2CellIndex&
|
|
473
|
+
S2ClosestCellQueryBase<Distance>::index() const {
|
|
474
|
+
return *index_;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
template <class Distance>
|
|
478
|
+
inline std::vector<typename S2ClosestCellQueryBase<Distance>::Result>
|
|
479
|
+
S2ClosestCellQueryBase<Distance>::FindClosestCells(
|
|
480
|
+
Target* target, const Options& options) {
|
|
481
|
+
std::vector<Result> results;
|
|
482
|
+
FindClosestCells(target, options, &results);
|
|
483
|
+
return results;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
template <class Distance>
|
|
487
|
+
typename S2ClosestCellQueryBase<Distance>::Result
|
|
488
|
+
S2ClosestCellQueryBase<Distance>::FindClosestCell(
|
|
489
|
+
Target* target, const Options& options) {
|
|
490
|
+
S2_DCHECK_EQ(options.max_results(), 1);
|
|
491
|
+
FindClosestCellsInternal(target, options);
|
|
492
|
+
return result_singleton_;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
template <class Distance>
|
|
496
|
+
void S2ClosestCellQueryBase<Distance>::FindClosestCells(
|
|
497
|
+
Target* target, const Options& options, std::vector<Result>* results) {
|
|
498
|
+
FindClosestCellsInternal(target, options);
|
|
499
|
+
results->clear();
|
|
500
|
+
if (options.max_results() == 1) {
|
|
501
|
+
if (!result_singleton_.is_empty()) {
|
|
502
|
+
results->push_back(result_singleton_);
|
|
503
|
+
}
|
|
504
|
+
} else if (options.max_results() == Options::kMaxMaxResults) {
|
|
505
|
+
std::sort(result_vector_.begin(), result_vector_.end());
|
|
506
|
+
std::unique_copy(result_vector_.begin(), result_vector_.end(),
|
|
507
|
+
std::back_inserter(*results));
|
|
508
|
+
result_vector_.clear();
|
|
509
|
+
} else {
|
|
510
|
+
results->assign(result_set_.begin(), result_set_.end());
|
|
511
|
+
result_set_.clear();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
template <class Distance>
|
|
516
|
+
void S2ClosestCellQueryBase<Distance>::FindClosestCellsInternal(
|
|
517
|
+
Target* target, const Options& options) {
|
|
518
|
+
target_ = target;
|
|
519
|
+
options_ = &options;
|
|
520
|
+
|
|
521
|
+
tested_cells_.clear();
|
|
522
|
+
contents_it_.Clear();
|
|
523
|
+
distance_limit_ = options.max_distance();
|
|
524
|
+
result_singleton_ = Result();
|
|
525
|
+
S2_DCHECK(result_vector_.empty());
|
|
526
|
+
S2_DCHECK(result_set_.empty());
|
|
527
|
+
S2_DCHECK_GE(target->max_brute_force_index_size(), 0);
|
|
528
|
+
if (distance_limit_ == Distance::Zero()) return;
|
|
529
|
+
|
|
530
|
+
if (options.max_results() == Options::kMaxMaxResults &&
|
|
531
|
+
options.max_distance() == Distance::Infinity() &&
|
|
532
|
+
options.region() == nullptr) {
|
|
533
|
+
S2_LOG(WARNING) << "Returning all cells "
|
|
534
|
+
"(max_results/max_distance/region not set)";
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// If max_error() > 0 and the target takes advantage of this, then we may
|
|
538
|
+
// need to adjust the distance estimates to the priority queue cells to
|
|
539
|
+
// ensure that they are always a lower bound on the true distance. For
|
|
540
|
+
// example, suppose max_distance == 100, max_error == 30, and we compute the
|
|
541
|
+
// distance to the target from some cell C0 as d(C0) == 80. Then because
|
|
542
|
+
// the target takes advantage of max_error(), the true distance could be as
|
|
543
|
+
// low as 50. In order not to miss edges contained by such cells, we need
|
|
544
|
+
// to subtract max_error() from the distance estimates. This behavior is
|
|
545
|
+
// controlled by the use_conservative_cell_distance_ flag.
|
|
546
|
+
//
|
|
547
|
+
// However there is one important case where this adjustment is not
|
|
548
|
+
// necessary, namely when max_distance() < max_error(). This is because
|
|
549
|
+
// max_error() only affects the algorithm once at least max_edges() edges
|
|
550
|
+
// have been found that satisfy the given distance limit. At that point,
|
|
551
|
+
// max_error() is subtracted from distance_limit_ in order to ensure that
|
|
552
|
+
// any further matches are closer by at least that amount. But when
|
|
553
|
+
// max_distance() < max_error(), this reduces the distance limit to 0,
|
|
554
|
+
// i.e. all remaining candidate cells and edges can safely be discarded.
|
|
555
|
+
// (Note that this is how IsDistanceLess() and friends are implemented.)
|
|
556
|
+
//
|
|
557
|
+
// Note that Distance::Delta only supports operator==.
|
|
558
|
+
bool target_uses_max_error = (!(options.max_error() == Delta::Zero()) &&
|
|
559
|
+
target_->set_max_error(options.max_error()));
|
|
560
|
+
|
|
561
|
+
// Note that we can't compare max_error() and distance_limit_ directly
|
|
562
|
+
// because one is a Delta and one is a Distance. Instead we subtract them.
|
|
563
|
+
use_conservative_cell_distance_ = target_uses_max_error &&
|
|
564
|
+
(distance_limit_ == Distance::Infinity() ||
|
|
565
|
+
Distance::Zero() < distance_limit_ - options.max_error());
|
|
566
|
+
|
|
567
|
+
// Use the brute force algorithm if the index is small enough.
|
|
568
|
+
if (options.use_brute_force() ||
|
|
569
|
+
index_->num_cells() <= target_->max_brute_force_index_size()) {
|
|
570
|
+
avoid_duplicates_ = false;
|
|
571
|
+
FindClosestCellsBruteForce();
|
|
572
|
+
} else {
|
|
573
|
+
// If the target takes advantage of max_error() then we need to avoid
|
|
574
|
+
// duplicate edges explicitly. (Otherwise it happens automatically.)
|
|
575
|
+
avoid_duplicates_ = (target_uses_max_error && options.max_results() > 1);
|
|
576
|
+
FindClosestCellsOptimized();
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
template <class Distance>
|
|
581
|
+
void S2ClosestCellQueryBase<Distance>::FindClosestCellsBruteForce() {
|
|
582
|
+
for (CellIterator it(index_); !it.done(); it.Next()) {
|
|
583
|
+
MaybeAddResult(it.cell_id(), it.label());
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
template <class Distance>
|
|
588
|
+
void S2ClosestCellQueryBase<Distance>::FindClosestCellsOptimized() {
|
|
589
|
+
InitQueue();
|
|
590
|
+
while (!queue_.empty()) {
|
|
591
|
+
// We need to copy the top entry before removing it, and we need to remove
|
|
592
|
+
// it before adding any new entries to the queue.
|
|
593
|
+
QueueEntry entry = queue_.top();
|
|
594
|
+
queue_.pop();
|
|
595
|
+
// Work around weird parse error in gcc 4.9 by using a local variable for
|
|
596
|
+
// entry.distance.
|
|
597
|
+
Distance distance = entry.distance;
|
|
598
|
+
if (!(distance < distance_limit_)) {
|
|
599
|
+
queue_ = CellQueue(); // Clear any remaining entries.
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
S2CellId child = entry.id.child_begin();
|
|
603
|
+
// We already know that it has too many cells, so process its children.
|
|
604
|
+
// Each child may either be processed directly or enqueued again. The
|
|
605
|
+
// loop is optimized so that we don't seek unnecessarily.
|
|
606
|
+
bool seek = true;
|
|
607
|
+
NonEmptyRangeIterator range(index_);
|
|
608
|
+
for (int i = 0; i < 4; ++i, child = child.next()) {
|
|
609
|
+
seek = ProcessOrEnqueue(child, &range, seek);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
template <class Distance>
|
|
615
|
+
void S2ClosestCellQueryBase<Distance>::InitQueue() {
|
|
616
|
+
S2_DCHECK(queue_.empty());
|
|
617
|
+
|
|
618
|
+
// Optimization: rather than starting with the entire index, see if we can
|
|
619
|
+
// limit the search region to a small disc. Then we can find a covering for
|
|
620
|
+
// that disc and intersect it with the covering for the index. This can
|
|
621
|
+
// save a lot of work when the search region is small.
|
|
622
|
+
S2Cap cap = target_->GetCapBound();
|
|
623
|
+
if (cap.is_empty()) return; // Empty target.
|
|
624
|
+
if (options().max_results() == 1) {
|
|
625
|
+
// If the user is searching for just the closest cell, we can compute an
|
|
626
|
+
// upper bound on search radius by seeking to the center of the target's
|
|
627
|
+
// bounding cap and looking at the contents of that leaf cell range. If
|
|
628
|
+
// the range intersects any cells, then the distance is zero. Otherwise
|
|
629
|
+
// we can still look at the two neighboring ranges, and use the minimum
|
|
630
|
+
// distance to any cell in those ranges as an upper bound on the search
|
|
631
|
+
// radius. These cells may wind up being processed twice, but in general
|
|
632
|
+
// this is still faster.
|
|
633
|
+
//
|
|
634
|
+
// First check the range containing or immediately following "center".
|
|
635
|
+
NonEmptyRangeIterator range(index_);
|
|
636
|
+
S2CellId target(cap.center());
|
|
637
|
+
range.Seek(target);
|
|
638
|
+
AddRange(range);
|
|
639
|
+
if (distance_limit_ == Distance::Zero()) return;
|
|
640
|
+
|
|
641
|
+
// If the range immediately follows "center" (rather than containing it),
|
|
642
|
+
// then check the previous non-empty range as well.
|
|
643
|
+
if (range.start_id() > target && range.Prev()) {
|
|
644
|
+
AddRange(range);
|
|
645
|
+
if (distance_limit_ == Distance::Zero()) return;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// We start with a covering of the set of indexed cells, then intersect it
|
|
650
|
+
// with the maximum search radius disc (if any).
|
|
651
|
+
//
|
|
652
|
+
// Note that unlike S2ClosestPointQuery, we can't also intersect with the
|
|
653
|
+
// given region (if any). This is because the index cells in the result are
|
|
654
|
+
// only required to intersect the region. This means that an index cell that
|
|
655
|
+
// intersects the region's covering may be much closer to the target than the
|
|
656
|
+
// covering itself, which means that we cannot use the region's covering to
|
|
657
|
+
// restrict the search.
|
|
658
|
+
//
|
|
659
|
+
// TODO(ericv): If this feature becomes important, this could be fixed by
|
|
660
|
+
// (1) computing a covering of the region, (2) looking up any index cells
|
|
661
|
+
// that contain each covering cell by seeking to covering_cell.range_min(),
|
|
662
|
+
// (3) replacing each covering cell by the largest such cell (if any), and
|
|
663
|
+
// (4) normalizing the result.
|
|
664
|
+
if (index_covering_.empty()) InitCovering();
|
|
665
|
+
const std::vector<S2CellId>* initial_cells = &index_covering_;
|
|
666
|
+
if (distance_limit_ < Distance::Infinity()) {
|
|
667
|
+
S2RegionCoverer coverer;
|
|
668
|
+
coverer.mutable_options()->set_max_cells(4);
|
|
669
|
+
S1ChordAngle radius = cap.radius() + distance_limit_.GetChordAngleBound();
|
|
670
|
+
S2Cap search_cap(cap.center(), radius);
|
|
671
|
+
coverer.GetFastCovering(search_cap, &max_distance_covering_);
|
|
672
|
+
S2CellUnion::GetIntersection(*initial_cells, max_distance_covering_,
|
|
673
|
+
&intersection_with_max_distance_);
|
|
674
|
+
initial_cells = &intersection_with_max_distance_;
|
|
675
|
+
}
|
|
676
|
+
NonEmptyRangeIterator range(index_);
|
|
677
|
+
for (int i = 0; i < initial_cells->size(); ++i) {
|
|
678
|
+
S2CellId id = (*initial_cells)[i];
|
|
679
|
+
bool seek = (i == 0) || id.range_min() >= range.limit_id();
|
|
680
|
+
ProcessOrEnqueue(id, &range, seek);
|
|
681
|
+
if (range.done()) break;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
template <class Distance>
|
|
686
|
+
void S2ClosestCellQueryBase<Distance>::InitCovering() {
|
|
687
|
+
// Compute the "index covering", which is a small number of S2CellIds that
|
|
688
|
+
// cover the indexed cells. There are two cases:
|
|
689
|
+
//
|
|
690
|
+
// - If the index spans more than one face, then there is one covering cell
|
|
691
|
+
// per spanned face, just big enough to cover the indexed cells on that face.
|
|
692
|
+
//
|
|
693
|
+
// - If the index spans only one face, then we find the smallest cell "C"
|
|
694
|
+
// that covers the indexed cells on that face (just like the case above).
|
|
695
|
+
// Then for each of the 4 children of "C", if the child contains any index
|
|
696
|
+
// cells then we create a covering cell that is big enough to just fit
|
|
697
|
+
// those indexed cells (i.e., shrinking the child as much as possible to fit
|
|
698
|
+
// its contents). This essentially replicates what would happen if we
|
|
699
|
+
// started with "C" as the covering cell, since "C" would immediately be
|
|
700
|
+
// split, except that we take the time to prune the children further since
|
|
701
|
+
// this will save work on every subsequent query.
|
|
702
|
+
index_covering_.reserve(6);
|
|
703
|
+
NonEmptyRangeIterator it(index_), last(index_);
|
|
704
|
+
it.Begin();
|
|
705
|
+
last.Finish();
|
|
706
|
+
if (!last.Prev()) return; // Empty index.
|
|
707
|
+
S2CellId index_last_id = last.limit_id().prev();
|
|
708
|
+
if (it.start_id() != last.start_id()) {
|
|
709
|
+
// The index contains at least two distinct S2CellIds (because otherwise
|
|
710
|
+
// there would only be one non-empty range). Choose a level such that the
|
|
711
|
+
// entire index can be spanned with at most 6 cells (if the index spans
|
|
712
|
+
// multiple faces) or 4 cells (it the index spans a single face).
|
|
713
|
+
int level = it.start_id().GetCommonAncestorLevel(index_last_id) + 1;
|
|
714
|
+
|
|
715
|
+
// Visit each potential covering cell except the last (handled below).
|
|
716
|
+
S2CellId start_id = it.start_id().parent(level);
|
|
717
|
+
S2CellId last_id = index_last_id.parent(level);
|
|
718
|
+
for (S2CellId id = start_id; id != last_id; id = id.next()) {
|
|
719
|
+
// Skip any covering cells that don't contain an indexed range.
|
|
720
|
+
if (id.range_max() < it.start_id()) continue;
|
|
721
|
+
|
|
722
|
+
// Find the indexed range contained by this covering cell and then
|
|
723
|
+
// shrink the cell if necessary so that it just covers this range.
|
|
724
|
+
S2CellId cell_first_id = it.start_id();
|
|
725
|
+
it.Seek(id.range_max().next());
|
|
726
|
+
// Find the last leaf cell covered by the previous non-empty range.
|
|
727
|
+
last = it;
|
|
728
|
+
last.Prev();
|
|
729
|
+
AddInitialRange(cell_first_id, last.limit_id().prev());
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
AddInitialRange(it.start_id(), index_last_id);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Adds a cell to index_covering_ that covers the given inclusive range.
|
|
736
|
+
//
|
|
737
|
+
// REQUIRES: "first" and "last" have a common ancestor.
|
|
738
|
+
template <class Distance>
|
|
739
|
+
void S2ClosestCellQueryBase<Distance>::AddInitialRange(
|
|
740
|
+
S2CellId first_id, S2CellId last_id) {
|
|
741
|
+
// Add the lowest common ancestor of the given range.
|
|
742
|
+
int level = first_id.GetCommonAncestorLevel(last_id);
|
|
743
|
+
S2_DCHECK_GE(level, 0);
|
|
744
|
+
index_covering_.push_back(first_id.parent(level));
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// TODO(ericv): Consider having this method return false when distance_limit_
|
|
748
|
+
// is reduced to zero, and terminating any calling loops early.
|
|
749
|
+
template <class Distance>
|
|
750
|
+
void S2ClosestCellQueryBase<Distance>::MaybeAddResult(S2CellId cell_id,
|
|
751
|
+
Label label) {
|
|
752
|
+
if (avoid_duplicates_ &&
|
|
753
|
+
!tested_cells_.insert(LabelledCell(cell_id, label)).second) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// TODO(ericv): It may be relatively common to add the same S2CellId
|
|
758
|
+
// multiple times with different labels. This could be optimized by
|
|
759
|
+
// remembering the last "cell_id" argument and its distance. However this
|
|
760
|
+
// may not be beneficial when Options::max_results() == 1, for example.
|
|
761
|
+
S2Cell cell(cell_id);
|
|
762
|
+
Distance distance = distance_limit_;
|
|
763
|
+
if (!target_->UpdateMinDistance(cell, &distance)) return;
|
|
764
|
+
|
|
765
|
+
const S2Region* region = options().region();
|
|
766
|
+
if (region && !region->MayIntersect(cell)) return;
|
|
767
|
+
|
|
768
|
+
Result result(distance, cell_id, label);
|
|
769
|
+
if (options().max_results() == 1) {
|
|
770
|
+
// Optimization for the common case where only the closest cell is wanted.
|
|
771
|
+
result_singleton_ = result;
|
|
772
|
+
distance_limit_ = result.distance() - options().max_error();
|
|
773
|
+
} else if (options().max_results() == Options::kMaxMaxResults) {
|
|
774
|
+
result_vector_.push_back(result); // Sort/unique at end.
|
|
775
|
+
} else {
|
|
776
|
+
// Add this cell to result_set_. Note that even if we already have enough
|
|
777
|
+
// edges, we can't erase an element before insertion because the "new"
|
|
778
|
+
// edge might in fact be a duplicate.
|
|
779
|
+
result_set_.insert(result);
|
|
780
|
+
int size = result_set_.size();
|
|
781
|
+
if (size >= options().max_results()) {
|
|
782
|
+
if (size > options().max_results()) {
|
|
783
|
+
result_set_.erase(--result_set_.end());
|
|
784
|
+
}
|
|
785
|
+
distance_limit_ = (--result_set_.end())->distance() -
|
|
786
|
+
options().max_error();
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Either process the contents of the given cell immediately, or add it to the
|
|
792
|
+
// queue to be subdivided. If "seek" is false, then "iter" must be positioned
|
|
793
|
+
// at the first non-empty range (if any) with start_id() >= id.range_min().
|
|
794
|
+
//
|
|
795
|
+
// Returns "true" if the cell was added to the queue, and "false" if it was
|
|
796
|
+
// processed immediately, in which case "iter" is positioned at the first
|
|
797
|
+
// non-empty range (if any) with start_id() > id.range_max().
|
|
798
|
+
template <class Distance>
|
|
799
|
+
bool S2ClosestCellQueryBase<Distance>::ProcessOrEnqueue(
|
|
800
|
+
S2CellId id, NonEmptyRangeIterator* iter, bool seek) {
|
|
801
|
+
if (seek) iter->Seek(id.range_min());
|
|
802
|
+
S2CellId last = id.range_max();
|
|
803
|
+
if (iter->start_id() > last) {
|
|
804
|
+
return false; // No need to seek to next child.
|
|
805
|
+
}
|
|
806
|
+
// If this cell intersects at least "kMinRangesToEnqueue" leaf cell ranges
|
|
807
|
+
// (including ranges whose contents are empty), then enqueue it. We test
|
|
808
|
+
// this by advancing (n - 1) ranges and checking whether that range also
|
|
809
|
+
// intersects this cell.
|
|
810
|
+
RangeIterator max_it = *iter;
|
|
811
|
+
if (max_it.Advance(kMinRangesToEnqueue - 1) && max_it.start_id() <= last) {
|
|
812
|
+
// This cell intersects at least kMinRangesToEnqueue ranges, so enqueue it.
|
|
813
|
+
S2Cell cell(id);
|
|
814
|
+
Distance distance = distance_limit_;
|
|
815
|
+
// We check "region_" second because it may be relatively expensive.
|
|
816
|
+
if (target_->UpdateMinDistance(cell, &distance) &&
|
|
817
|
+
(!options().region() || options().region()->MayIntersect(cell))) {
|
|
818
|
+
if (use_conservative_cell_distance_) {
|
|
819
|
+
// Ensure that "distance" is a lower bound on distance to the cell.
|
|
820
|
+
distance = distance - options().max_error();
|
|
821
|
+
}
|
|
822
|
+
queue_.push(QueueEntry(distance, id));
|
|
823
|
+
}
|
|
824
|
+
return true; // Seek to next child.
|
|
825
|
+
}
|
|
826
|
+
// There were few enough ranges that we might as well process them now.
|
|
827
|
+
for (; iter->start_id() <= last; iter->Next()) {
|
|
828
|
+
AddRange(*iter);
|
|
829
|
+
}
|
|
830
|
+
return false; // No need to seek to next child.
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
template <class Distance>
|
|
834
|
+
void S2ClosestCellQueryBase<Distance>::AddRange(const RangeIterator& range) {
|
|
835
|
+
for (contents_it_.StartUnion(range);
|
|
836
|
+
!contents_it_.done(); contents_it_.Next()) {
|
|
837
|
+
MaybeAddResult(contents_it_.cell_id(), contents_it_.label());
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
#endif // S2_S2CLOSEST_CELL_QUERY_BASE_H_
|