@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,838 @@
|
|
|
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
|
+
#include "s2/encoded_s2point_vector.h"
|
|
19
|
+
|
|
20
|
+
#include "s2/third_party/absl/base/internal/unaligned_access.h"
|
|
21
|
+
#include "s2/util/bits/bits.h"
|
|
22
|
+
#include "s2/s2cell_id.h"
|
|
23
|
+
#include "s2/s2coords.h"
|
|
24
|
+
|
|
25
|
+
using absl::MakeSpan;
|
|
26
|
+
using absl::Span;
|
|
27
|
+
using std::max;
|
|
28
|
+
using std::min;
|
|
29
|
+
using std::vector;
|
|
30
|
+
|
|
31
|
+
namespace s2coding {
|
|
32
|
+
|
|
33
|
+
// Like util_bits::InterleaveUint32, but interleaves bit pairs rather than
|
|
34
|
+
// individual bits. This format is faster to decode than the fully interleaved
|
|
35
|
+
// format, and produces the same results for our use case.
|
|
36
|
+
inline uint64 InterleaveUint32BitPairs(const uint32 val0, const uint32 val1) {
|
|
37
|
+
uint64 v0 = val0, v1 = val1;
|
|
38
|
+
v0 = (v0 | (v0 << 16)) & 0x0000ffff0000ffff;
|
|
39
|
+
v1 = (v1 | (v1 << 16)) & 0x0000ffff0000ffff;
|
|
40
|
+
v0 = (v0 | (v0 << 8)) & 0x00ff00ff00ff00ff;
|
|
41
|
+
v1 = (v1 | (v1 << 8)) & 0x00ff00ff00ff00ff;
|
|
42
|
+
v0 = (v0 | (v0 << 4)) & 0x0f0f0f0f0f0f0f0f;
|
|
43
|
+
v1 = (v1 | (v1 << 4)) & 0x0f0f0f0f0f0f0f0f;
|
|
44
|
+
v0 = (v0 | (v0 << 2)) & 0x3333333333333333;
|
|
45
|
+
v1 = (v1 | (v1 << 2)) & 0x3333333333333333;
|
|
46
|
+
return v0 | (v1 << 2);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// This code is about 50% faster than util_bits::DeinterleaveUint32, which
|
|
50
|
+
// uses a lookup table. The speed advantage is expected to be even larger in
|
|
51
|
+
// code that mixes bit interleaving with other significant operations since it
|
|
52
|
+
// doesn't require keeping a 256-byte lookup table in the L1 data cache.
|
|
53
|
+
inline void DeinterleaveUint32BitPairs(uint64 code,
|
|
54
|
+
uint32 *val0, uint32 *val1) {
|
|
55
|
+
uint64 v0 = code, v1 = code >> 2;
|
|
56
|
+
v0 &= 0x3333333333333333;
|
|
57
|
+
v0 |= v0 >> 2;
|
|
58
|
+
v1 &= 0x3333333333333333;
|
|
59
|
+
v1 |= v1 >> 2;
|
|
60
|
+
v0 &= 0x0f0f0f0f0f0f0f0f;
|
|
61
|
+
v0 |= v0 >> 4;
|
|
62
|
+
v1 &= 0x0f0f0f0f0f0f0f0f;
|
|
63
|
+
v1 |= v1 >> 4;
|
|
64
|
+
v0 &= 0x00ff00ff00ff00ff;
|
|
65
|
+
v0 |= v0 >> 8;
|
|
66
|
+
v1 &= 0x00ff00ff00ff00ff;
|
|
67
|
+
v1 |= v1 >> 8;
|
|
68
|
+
v0 &= 0x0000ffff0000ffff;
|
|
69
|
+
v0 |= v0 >> 16;
|
|
70
|
+
v1 &= 0x0000ffff0000ffff;
|
|
71
|
+
v1 |= v1 >> 16;
|
|
72
|
+
*val0 = v0;
|
|
73
|
+
*val1 = v1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Forward declarations.
|
|
77
|
+
void EncodeS2PointVectorFast(Span<const S2Point> points, Encoder* encoder);
|
|
78
|
+
void EncodeS2PointVectorCompact(Span<const S2Point> points, Encoder* encoder);
|
|
79
|
+
|
|
80
|
+
// To save space (especially for vectors of length 0, 1, and 2), the encoding
|
|
81
|
+
// format is encoded in the low-order 3 bits of the vector size. Up to 7
|
|
82
|
+
// encoding formats are supported (only 2 are currently defined). Additional
|
|
83
|
+
// formats could be supported by using "7" as an overflow indicator and
|
|
84
|
+
// encoding the actual format separately, but it seems unlikely we will ever
|
|
85
|
+
// need to do that.
|
|
86
|
+
static const int kEncodingFormatBits = 3;
|
|
87
|
+
static const uint8 kEncodingFormatMask = (1 << kEncodingFormatBits) - 1;
|
|
88
|
+
|
|
89
|
+
void EncodeS2PointVector(Span<const S2Point> points, CodingHint hint,
|
|
90
|
+
Encoder* encoder) {
|
|
91
|
+
switch (hint) {
|
|
92
|
+
case CodingHint::FAST:
|
|
93
|
+
return EncodeS2PointVectorFast(points, encoder);
|
|
94
|
+
|
|
95
|
+
case CodingHint::COMPACT:
|
|
96
|
+
return EncodeS2PointVectorCompact(points, encoder);
|
|
97
|
+
|
|
98
|
+
default:
|
|
99
|
+
S2_LOG(DFATAL) << "Unknown CodingHint: " << static_cast<int>(hint);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
bool EncodedS2PointVector::Init(Decoder* decoder) {
|
|
104
|
+
if (decoder->avail() < 1) return false;
|
|
105
|
+
|
|
106
|
+
// Peek at the format but don't advance the decoder; the format-specific
|
|
107
|
+
// Init functions will do that.
|
|
108
|
+
format_ = static_cast<Format>(*decoder->ptr() & kEncodingFormatMask);
|
|
109
|
+
switch (format_) {
|
|
110
|
+
case UNCOMPRESSED:
|
|
111
|
+
return InitUncompressedFormat(decoder);
|
|
112
|
+
|
|
113
|
+
case CELL_IDS:
|
|
114
|
+
return InitCellIdsFormat(decoder);
|
|
115
|
+
|
|
116
|
+
default:
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
vector<S2Point> EncodedS2PointVector::Decode() const {
|
|
122
|
+
vector<S2Point> points;
|
|
123
|
+
points.reserve(size_);
|
|
124
|
+
for (int i = 0; i < size_; ++i) {
|
|
125
|
+
points.push_back((*this)[i]);
|
|
126
|
+
}
|
|
127
|
+
return points;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
132
|
+
// UNCOMPRESSED Encoding Format
|
|
133
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
134
|
+
|
|
135
|
+
// Encodes a vector of points, optimizing for (encoding and decoding) speed.
|
|
136
|
+
void EncodeS2PointVectorFast(Span<const S2Point> points, Encoder* encoder) {
|
|
137
|
+
#ifndef IS_LITTLE_ENDIAN
|
|
138
|
+
S2_LOG(FATAL) << "Not implemented on big-endian architectures";
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
// This function always uses the UNCOMPRESSED encoding. The header consists
|
|
142
|
+
// of a varint64 in the following format:
|
|
143
|
+
//
|
|
144
|
+
// bits 0-2: encoding format (UNCOMPRESSED)
|
|
145
|
+
// bits 3-63: vector size
|
|
146
|
+
//
|
|
147
|
+
// This is followed by an array of S2Points in little-endian order.
|
|
148
|
+
encoder->Ensure(Varint::kMax64 + points.size() * sizeof(S2Point));
|
|
149
|
+
uint64 size_format = (points.size() << kEncodingFormatBits |
|
|
150
|
+
EncodedS2PointVector::UNCOMPRESSED);
|
|
151
|
+
encoder->put_varint64(size_format);
|
|
152
|
+
encoder->putn(points.data(), points.size() * sizeof(S2Point));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
bool EncodedS2PointVector::InitUncompressedFormat(Decoder* decoder) {
|
|
156
|
+
#if !defined(IS_LITTLE_ENDIAN) || defined(__arm__) || \
|
|
157
|
+
defined(ABSL_INTERNAL_NEED_ALIGNED_LOADS)
|
|
158
|
+
// TODO(ericv): Make this work on platforms that don't support unaligned
|
|
159
|
+
// 64-bit little-endian reads, e.g. by falling back to
|
|
160
|
+
//
|
|
161
|
+
// bit_cast<double>(little_endian::Load64()).
|
|
162
|
+
//
|
|
163
|
+
// Maybe the compiler is smart enough that we can do this all the time,
|
|
164
|
+
// but more likely we will need two cases using the #ifdef above.
|
|
165
|
+
// (Note that even ARMv7 does not support unaligned 64-bit loads.)
|
|
166
|
+
S2_LOG(DFATAL) << "Needs architecture with 64-bit little-endian unaligned loads";
|
|
167
|
+
return false;
|
|
168
|
+
#endif
|
|
169
|
+
|
|
170
|
+
uint64 size;
|
|
171
|
+
if (!decoder->get_varint64(&size)) return false;
|
|
172
|
+
size >>= kEncodingFormatBits;
|
|
173
|
+
|
|
174
|
+
// Note that the encoding format supports up to 2**59 vertices, but we
|
|
175
|
+
// currently only support decoding up to 2**32 vertices.
|
|
176
|
+
if (size > std::numeric_limits<uint32>::max()) return false;
|
|
177
|
+
size_ = size;
|
|
178
|
+
|
|
179
|
+
size_t bytes = size_t{size_} * sizeof(S2Point);
|
|
180
|
+
if (decoder->avail() < bytes) return false;
|
|
181
|
+
|
|
182
|
+
uncompressed_.points = reinterpret_cast<const S2Point*>(decoder->ptr());
|
|
183
|
+
decoder->skip(bytes);
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
189
|
+
// CELL_IDS Encoding Format
|
|
190
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
191
|
+
|
|
192
|
+
// Represents a point that can be encoded as an S2CellId center.
|
|
193
|
+
// (If such an encoding is not possible then level < 0.)
|
|
194
|
+
struct CellPoint {
|
|
195
|
+
// Constructor necessary in order to narrow "int" arguments to "int8".
|
|
196
|
+
CellPoint(int level, int face, uint32 si, uint32 ti)
|
|
197
|
+
: level(level), face(face), si(si), ti(ti) {}
|
|
198
|
+
|
|
199
|
+
int8 level, face;
|
|
200
|
+
uint32 si, ti;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// S2CellIds are represented in a special 64-bit format and are encoded in
|
|
204
|
+
// fixed-size blocks. kBlockSize represents the number of values per block.
|
|
205
|
+
// Block sizes of 4, 8, 16, and 32 were tested and kBlockSize == 16 seems to
|
|
206
|
+
// offer the best compression. (Note that kBlockSize == 32 requires some code
|
|
207
|
+
// modifications which have since been removed.)
|
|
208
|
+
constexpr int kBlockShift = 4;
|
|
209
|
+
constexpr size_t kBlockSize = 1 << kBlockShift;
|
|
210
|
+
|
|
211
|
+
// Used to indicate that a point must be encoded as an exception (a 24-byte
|
|
212
|
+
// S2Point) rather than as an S2CellId.
|
|
213
|
+
constexpr uint64 kException = ~0ULL;
|
|
214
|
+
|
|
215
|
+
// Represents the encoding parameters to be used for a given block (consisting
|
|
216
|
+
// of kBlockSize encodable 64-bit values). See below.
|
|
217
|
+
struct BlockCode {
|
|
218
|
+
int delta_bits; // Delta length in bits (multiple of 4)
|
|
219
|
+
int offset_bits; // Offset length in bits (multiple of 8)
|
|
220
|
+
int overlap_bits; // {Delta, Offset} overlap in bits (0 or 4)
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
// Returns a bit mask with "n" low-order 1 bits, for 0 <= n <= 64.
|
|
224
|
+
inline uint64 BitMask(int n) {
|
|
225
|
+
return (n == 0) ? 0 : (~0ULL >> (64 - n));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Returns the maximum number of bits per value at the given S2CellId level.
|
|
229
|
+
inline int MaxBitsForLevel(int level) {
|
|
230
|
+
return 2 * level + 3;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Returns the number of bits that "base" should be right-shifted in order to
|
|
234
|
+
// encode only its leading "base_bits" bits, assuming that all points are
|
|
235
|
+
// encoded at the given S2CellId level.
|
|
236
|
+
inline int BaseShift(int level, int base_bits) {
|
|
237
|
+
return max(0, MaxBitsForLevel(level) - base_bits);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Forward declarations.
|
|
241
|
+
int ChooseBestLevel(Span<const S2Point> points, vector<CellPoint>* cell_points);
|
|
242
|
+
vector<uint64> ConvertCellsToValues(const vector<CellPoint>& cell_points,
|
|
243
|
+
int level, bool* have_exceptions);
|
|
244
|
+
uint64 ChooseBase(const vector<uint64>& values, int level, bool have_exceptions,
|
|
245
|
+
int* base_bits);
|
|
246
|
+
BlockCode GetBlockCode(Span<const uint64> values, uint64 base,
|
|
247
|
+
bool have_exceptions);
|
|
248
|
+
|
|
249
|
+
// Encodes a vector of points, optimizing for space.
|
|
250
|
+
void EncodeS2PointVectorCompact(Span<const S2Point> points, Encoder* encoder) {
|
|
251
|
+
// OVERVIEW
|
|
252
|
+
// --------
|
|
253
|
+
//
|
|
254
|
+
// We attempt to represent each S2Point as the center of an S2CellId. All
|
|
255
|
+
// S2CellIds must be at the same level. Any points that cannot be encoded
|
|
256
|
+
// exactly as S2CellId centers are stored as exceptions using 24 bytes each.
|
|
257
|
+
// If there are so many exceptions that the CELL_IDS encoding does not save
|
|
258
|
+
// significant space, we give up and use the uncompressed encoding.
|
|
259
|
+
//
|
|
260
|
+
// The first step is to choose the best S2CellId level. This requires
|
|
261
|
+
// converting each point to (face, si, ti) coordinates and checking whether
|
|
262
|
+
// the point can be represented exactly as an S2CellId center at some level.
|
|
263
|
+
// We then build a histogram of S2CellId levels (just like the similar code
|
|
264
|
+
// in S2Polygon::Encode) and choose the best level (or give up, if there are
|
|
265
|
+
// not enough S2CellId-encodable points).
|
|
266
|
+
//
|
|
267
|
+
// The simplest approach would then be to take all the S2CellIds and
|
|
268
|
+
// right-shift them to remove all the constant bits at the chosen level.
|
|
269
|
+
// This would give the best spatial locality and hence the smallest deltas.
|
|
270
|
+
// However instead we give up some spatial locality and use the similar but
|
|
271
|
+
// faster transformation described below.
|
|
272
|
+
//
|
|
273
|
+
// Each encodable point is first converted to the (sj, tj) representation
|
|
274
|
+
// defined below:
|
|
275
|
+
//
|
|
276
|
+
// sj = (((face & 3) << 30) | (si >> 1)) >> (30 - level);
|
|
277
|
+
// tj = (((face & 4) << 29) | ti) >> (31 - level);
|
|
278
|
+
//
|
|
279
|
+
// These two values encode the (face, si, ti) tuple using (2 * level + 3)
|
|
280
|
+
// bits. To see this, recall that "si" and "ti" are 31-bit values that all
|
|
281
|
+
// share a common suffix consisting of a "1" bit followed by (30 - level)
|
|
282
|
+
// "0" bits. The code above right-shifts these values to remove the
|
|
283
|
+
// constant bits and then prepends the bits for "face", yielding a total of
|
|
284
|
+
// (level + 2) bits for "sj" and (level + 1) bits for "tj".
|
|
285
|
+
//
|
|
286
|
+
// We then combine (sj, tj) into one 64-bit value by interleaving bit pairs:
|
|
287
|
+
//
|
|
288
|
+
// v = InterleaveBitPairs(sj, tj);
|
|
289
|
+
//
|
|
290
|
+
// (We could also interleave individual bits, but it is faster this way.)
|
|
291
|
+
// The result is similar to right-shifting an S2CellId by (61 - 2 * level),
|
|
292
|
+
// except that it is faster to decode and the spatial locality is not quite
|
|
293
|
+
// as good.
|
|
294
|
+
//
|
|
295
|
+
// The 64-bit values are divided into blocks of size 8, and then each value is
|
|
296
|
+
// encoded as the sum of a base value, a per-block offset, and a per-value
|
|
297
|
+
// delta within that block:
|
|
298
|
+
//
|
|
299
|
+
// v[i,j] = base + offset[i] + delta[i, j]
|
|
300
|
+
//
|
|
301
|
+
// where "i" represents a block and "j" represents an entry in that block.
|
|
302
|
+
//
|
|
303
|
+
// The deltas for each block are encoded using a fixed number of 4-bit nibbles
|
|
304
|
+
// (1-16 nibbles per delta). This allows any delta to be accessed in constant
|
|
305
|
+
// time.
|
|
306
|
+
//
|
|
307
|
+
// The "offset" for each block is a 64-bit value encoded in 0-8 bytes. The
|
|
308
|
+
// offset is left-shifted such that it overlaps the deltas by a configurable
|
|
309
|
+
// number of bits (either 0 or 4), called the "overlap". The overlap and
|
|
310
|
+
// offset length (0-8 bytes) are specified per block. The reason for the
|
|
311
|
+
// overlap is that it allows fewer delta bits to be used in some cases. For
|
|
312
|
+
// example if base == 0 and the range within a block is 0xf0 to 0x110, then
|
|
313
|
+
// rather than using 12-bits deltas with an offset of 0, the overlap lets us
|
|
314
|
+
// use 8-bits deltas with an offset of 0xf0 (saving 7 bytes per block).
|
|
315
|
+
//
|
|
316
|
+
// The global minimum value "base" is encoded using 0-7 bytes starting with
|
|
317
|
+
// the most-significant non-zero bit possible for the chosen level. For
|
|
318
|
+
// example, if (level == 7) then the encoded values have at most 17 bits, so
|
|
319
|
+
// if "base" is encoded in 1 byte then it is shifted to occupy bits 9-16.
|
|
320
|
+
//
|
|
321
|
+
// Example: at level == 15, there are at most 33 non-zero value bits. The
|
|
322
|
+
// following shows the bit positions covered by "base", "offset", and "delta"
|
|
323
|
+
// assuming that "base" and "offset" are encoded in 2 bytes each, deltas are
|
|
324
|
+
// encoded in 2 nibbles (1 byte) each, and "overlap" is 4 bits:
|
|
325
|
+
//
|
|
326
|
+
// Base: 1111111100000000-----------------
|
|
327
|
+
// Offset: -------------1111111100000000----
|
|
328
|
+
// Delta: -------------------------00000000
|
|
329
|
+
// Overlap: ^^^^
|
|
330
|
+
//
|
|
331
|
+
// The numbers (0 or 1) in this diagram denote the byte number of the encoded
|
|
332
|
+
// value. Notice that "base" is shifted so that it starts at the leftmost
|
|
333
|
+
// possible bit, "delta" always starts at the rightmost possible bit (bit 0),
|
|
334
|
+
// and "offset" is shifted so that it overlaps "delta" by the chosen "overlap"
|
|
335
|
+
// (either 0 or 4 bits). Also note that all of these values are summed, and
|
|
336
|
+
// therefore each value can affect higher-order bits due to carries.
|
|
337
|
+
//
|
|
338
|
+
// NOTE(ericv): Encoding deltas in 4-bit rather than 8-bit length increments
|
|
339
|
+
// reduces encoded sizes by about 7%. Allowing a 4-bit overlap between the
|
|
340
|
+
// offset and deltas reduces encoded sizes by about 1%. Both optimizations
|
|
341
|
+
// make the code more complex but don't affect running times significantly.
|
|
342
|
+
//
|
|
343
|
+
// ENCODING DETAILS
|
|
344
|
+
// ----------------
|
|
345
|
+
//
|
|
346
|
+
// Now we can move on to the actual encodings. First, there is a 2 byte
|
|
347
|
+
// header encoded as follows:
|
|
348
|
+
//
|
|
349
|
+
// Byte 0, bits 0-2: encoding_format (CELL_IDS)
|
|
350
|
+
// Byte 0, bit 3: have_exceptions
|
|
351
|
+
// Byte 0, bits 4-7: (last_block_size - 1)
|
|
352
|
+
// Byte 1, bits 0-2: base_bytes
|
|
353
|
+
// Byte 1, bits 3-7: level (0-30)
|
|
354
|
+
//
|
|
355
|
+
// This is followed by an EncodedStringVector containing the encoded blocks.
|
|
356
|
+
// Each block contains kBlockSize (8) values. The total size of the
|
|
357
|
+
// EncodeS2PointVector is not stored explicity, but instead is calculated as
|
|
358
|
+
//
|
|
359
|
+
// num_values == kBlockSize * (num_blocks - 1) + last_block_size .
|
|
360
|
+
//
|
|
361
|
+
// (An empty vector has num_blocks == 0 and last_block_size == kBlockSize.)
|
|
362
|
+
//
|
|
363
|
+
// Each block starts with a 1 byte header containing the following:
|
|
364
|
+
//
|
|
365
|
+
// Byte 0, bits 0-2: (offset_bytes - overlap_nibbles)
|
|
366
|
+
// Byte 0, bit 3: overlap_nibbles
|
|
367
|
+
// Byte 0, bits 4-7: (delta_nibbles - 1)
|
|
368
|
+
//
|
|
369
|
+
// "overlap_nibbles" is either 0 or 1 (indicating an overlap of 0 or 4 bits),
|
|
370
|
+
// while "offset_bytes" is in the range 0-8 (indicating the number of bytes
|
|
371
|
+
// used to encode the offset for this block). Note that some combinations
|
|
372
|
+
// cannot be encoded: in particular, offset_bytes == 0 can only be encoded
|
|
373
|
+
// with an overlap of 0 bits, and offset_bytes == 8 can only be encoded with
|
|
374
|
+
// an overlap of 4 bits. This allows us to encode offset lengths of 0-8
|
|
375
|
+
// rather than just 0-7 without using an extra bit. (Note that the
|
|
376
|
+
// combinations that can't be encoded are not useful anyway.)
|
|
377
|
+
//
|
|
378
|
+
// The header is followed by "offset_bytes" bytes for the offset, and then
|
|
379
|
+
// (4 * delta_nibbles) bytes for the deltas.
|
|
380
|
+
//
|
|
381
|
+
// If there are any points that could not be represented as S2CellIds, then
|
|
382
|
+
// "have_exceptions" in the header is true. In that case the delta values
|
|
383
|
+
// within each block are encoded as (delta + 8), and values 0-7 are used to
|
|
384
|
+
// represent exceptions. If a block has exceptions, they are encoded
|
|
385
|
+
// immediately following the array of deltas, and are referenced by encoding
|
|
386
|
+
// the corresponding exception index (0-7) as the delta.
|
|
387
|
+
//
|
|
388
|
+
// TODO(ericv): A vector containing a single leaf cell is currently encoded as
|
|
389
|
+
// 13 bytes (2 byte header, 7 byte base, 1 byte block count, 1 byte block
|
|
390
|
+
// length, 1 byte block header, 1 byte delta). However if this case occurs
|
|
391
|
+
// often, a better solution would be implement a separate format that encodes
|
|
392
|
+
// the leading k bytes of an S2CellId. It would have a one-byte header
|
|
393
|
+
// consisting of the encoding format (3 bits) and the number of bytes encoded
|
|
394
|
+
// (3 bits), followed by the S2CellId bytes. The extra 2 header bits could be
|
|
395
|
+
// used to store single points using other encodings, e.g. E7.
|
|
396
|
+
//
|
|
397
|
+
// If we wind up using 8-value blocks, we could also use the extra bit in the
|
|
398
|
+
// first byte of the header to indicate that there is only one value, and
|
|
399
|
+
// then skip the 2nd byte of header and the EncodedStringVector. But this
|
|
400
|
+
// would be messy because it also requires special cases while decoding.
|
|
401
|
+
// Essentially this would be a sub-format within the CELL_IDS format.
|
|
402
|
+
|
|
403
|
+
// 1. Compute (level, face, si, ti) for each point, build a histogram of
|
|
404
|
+
// levels, and determine the optimal level to use for encoding (if any).
|
|
405
|
+
vector<CellPoint> cell_points;
|
|
406
|
+
int level = ChooseBestLevel(points, &cell_points);
|
|
407
|
+
if (level < 0) {
|
|
408
|
+
return EncodeS2PointVectorFast(points, encoder);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// 2. Convert the points into encodable 64-bit values. We don't use the
|
|
412
|
+
// S2CellId itself because it requires a somewhat more complicated bit
|
|
413
|
+
// interleaving operation.
|
|
414
|
+
//
|
|
415
|
+
// TODO(ericv): Benchmark using shifted S2CellIds instead.
|
|
416
|
+
bool have_exceptions;
|
|
417
|
+
vector<uint64> values = ConvertCellsToValues(cell_points, level,
|
|
418
|
+
&have_exceptions);
|
|
419
|
+
|
|
420
|
+
// 3. Choose the global encoding parameter "base" (consisting of the bit
|
|
421
|
+
// prefix shared by all values to be encoded).
|
|
422
|
+
int base_bits;
|
|
423
|
+
uint64 base = ChooseBase(values, level, have_exceptions, &base_bits);
|
|
424
|
+
|
|
425
|
+
// Now encode the output, starting with the 2-byte header (see above).
|
|
426
|
+
int num_blocks = (values.size() + kBlockSize - 1) >> kBlockShift;
|
|
427
|
+
int base_bytes = base_bits >> 3;
|
|
428
|
+
encoder->Ensure(2 + base_bytes);
|
|
429
|
+
int last_block_count = values.size() - kBlockSize * (num_blocks - 1);
|
|
430
|
+
S2_DCHECK_GE(last_block_count, 0);
|
|
431
|
+
S2_DCHECK_LE(last_block_count, kBlockSize);
|
|
432
|
+
S2_DCHECK_LE(base_bytes, 7);
|
|
433
|
+
S2_DCHECK_LE(level, 30);
|
|
434
|
+
encoder->put8(EncodedS2PointVector::CELL_IDS |
|
|
435
|
+
(have_exceptions << 3) |
|
|
436
|
+
((last_block_count - 1) << 4));
|
|
437
|
+
encoder->put8(base_bytes | (level << 3));
|
|
438
|
+
|
|
439
|
+
// Next we encode 0-7 bytes of "base".
|
|
440
|
+
int base_shift = BaseShift(level, base_bits);
|
|
441
|
+
EncodeUintWithLength(base >> base_shift, base_bytes, encoder);
|
|
442
|
+
|
|
443
|
+
// Now we encode the contents of each block.
|
|
444
|
+
StringVectorEncoder blocks;
|
|
445
|
+
vector<S2Point> exceptions;
|
|
446
|
+
uint64 offset_bytes_sum = 0;
|
|
447
|
+
uint64 delta_nibbles_sum = 0;
|
|
448
|
+
uint64 exceptions_sum = 0;
|
|
449
|
+
for (int i = 0; i < values.size(); i += kBlockSize) {
|
|
450
|
+
int block_size = min(kBlockSize, values.size() - i);
|
|
451
|
+
BlockCode code = GetBlockCode(MakeSpan(&values[i], block_size),
|
|
452
|
+
base, have_exceptions);
|
|
453
|
+
|
|
454
|
+
// Encode the one-byte block header (see above).
|
|
455
|
+
Encoder* block = blocks.AddViaEncoder();
|
|
456
|
+
int offset_bytes = code.offset_bits >> 3;
|
|
457
|
+
int delta_nibbles = code.delta_bits >> 2;
|
|
458
|
+
int overlap_nibbles = code.overlap_bits >> 2;
|
|
459
|
+
block->Ensure(1 + offset_bytes + (kBlockSize / 2) * delta_nibbles);
|
|
460
|
+
S2_DCHECK_LE(offset_bytes - overlap_nibbles, 7);
|
|
461
|
+
S2_DCHECK_LE(overlap_nibbles, 1);
|
|
462
|
+
S2_DCHECK_LE(delta_nibbles, 16);
|
|
463
|
+
block->put8((offset_bytes - overlap_nibbles) |
|
|
464
|
+
(overlap_nibbles << 3) | (delta_nibbles - 1) << 4);
|
|
465
|
+
|
|
466
|
+
// Determine the offset for this block, and whether there are exceptions.
|
|
467
|
+
uint64 offset = ~0ULL;
|
|
468
|
+
int num_exceptions = 0;
|
|
469
|
+
for (int j = 0; j < block_size; ++j) {
|
|
470
|
+
if (values[i + j] == kException) {
|
|
471
|
+
num_exceptions += 1;
|
|
472
|
+
} else {
|
|
473
|
+
S2_DCHECK_GE(values[i + j], base);
|
|
474
|
+
offset = min(offset, values[i + j] - base);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
if (num_exceptions == block_size) offset = 0;
|
|
478
|
+
|
|
479
|
+
// Encode the offset.
|
|
480
|
+
int offset_shift = code.delta_bits - code.overlap_bits;
|
|
481
|
+
offset &= ~BitMask(offset_shift);
|
|
482
|
+
S2_DCHECK_EQ(offset == 0, offset_bytes == 0);
|
|
483
|
+
if (offset > 0) {
|
|
484
|
+
EncodeUintWithLength(offset >> offset_shift, offset_bytes, block);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Encode the deltas, and also gather any exceptions present.
|
|
488
|
+
int delta_bytes = (delta_nibbles + 1) >> 1;
|
|
489
|
+
exceptions.clear();
|
|
490
|
+
for (int j = 0; j < block_size; ++j) {
|
|
491
|
+
uint64 delta;
|
|
492
|
+
if (values[i + j] == kException) {
|
|
493
|
+
delta = exceptions.size();
|
|
494
|
+
exceptions.push_back(points[i + j]);
|
|
495
|
+
} else {
|
|
496
|
+
S2_DCHECK_GE(values[i + j], offset + base);
|
|
497
|
+
delta = values[i + j] - (offset + base);
|
|
498
|
+
if (have_exceptions) {
|
|
499
|
+
S2_DCHECK_LE(delta, ~0ULL - kBlockSize);
|
|
500
|
+
delta += kBlockSize;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
S2_DCHECK_LE(delta, BitMask(code.delta_bits));
|
|
504
|
+
if ((delta_nibbles & 1) && (j & 1)) {
|
|
505
|
+
// Combine this delta with the high-order 4 bits of the previous delta.
|
|
506
|
+
uint8 last_byte = *(block->base() + block->length() - 1);
|
|
507
|
+
block->RemoveLast(1);
|
|
508
|
+
delta = (delta << 4) | (last_byte & 0xf);
|
|
509
|
+
}
|
|
510
|
+
EncodeUintWithLength(delta, delta_bytes, block);
|
|
511
|
+
}
|
|
512
|
+
// Append any exceptions to the end of the block.
|
|
513
|
+
if (num_exceptions > 0) {
|
|
514
|
+
int exceptions_bytes = exceptions.size() * sizeof(S2Point);
|
|
515
|
+
block->Ensure(exceptions_bytes);
|
|
516
|
+
block->putn(exceptions.data(), exceptions_bytes);
|
|
517
|
+
}
|
|
518
|
+
offset_bytes_sum += offset_bytes;
|
|
519
|
+
delta_nibbles_sum += delta_nibbles;
|
|
520
|
+
exceptions_sum += num_exceptions;
|
|
521
|
+
}
|
|
522
|
+
blocks.Encode(encoder);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Returns the S2CellId level for which the greatest number of the given points
|
|
526
|
+
// can be represented as the center of an S2CellId. Initializes "cell_points"
|
|
527
|
+
// to contain the S2CellId representation of each point (if any). Returns -1
|
|
528
|
+
// if there is no S2CellId that would result in significant space savings.
|
|
529
|
+
int ChooseBestLevel(Span<const S2Point> points,
|
|
530
|
+
vector<CellPoint>* cell_points) {
|
|
531
|
+
cell_points->clear();
|
|
532
|
+
cell_points->reserve(points.size());
|
|
533
|
+
|
|
534
|
+
// Count the number of points at each level.
|
|
535
|
+
int level_counts[S2CellId::kMaxLevel + 1] = { 0 };
|
|
536
|
+
for (const S2Point& point : points) {
|
|
537
|
+
int face;
|
|
538
|
+
uint32 si, ti;
|
|
539
|
+
int level = S2::XYZtoFaceSiTi(point, &face, &si, &ti);
|
|
540
|
+
cell_points->push_back(CellPoint(level, face, si, ti));
|
|
541
|
+
if (level >= 0) ++level_counts[level];
|
|
542
|
+
}
|
|
543
|
+
// Choose the level for which the most points can be encoded.
|
|
544
|
+
int best_level = 0;
|
|
545
|
+
for (int level = 1; level <= S2CellId::kMaxLevel; ++level) {
|
|
546
|
+
if (level_counts[level] > level_counts[best_level]) {
|
|
547
|
+
best_level = level;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
// The uncompressed encoding is smaller *and* faster when very few of the
|
|
551
|
+
// points are encodable as S2CellIds. The CELL_IDS encoding uses about 1
|
|
552
|
+
// extra byte per point in this case, consisting of up to a 3 byte
|
|
553
|
+
// EncodedStringVector offset for each block, a 1 byte block header, and 4
|
|
554
|
+
// bits per delta (encoding an exception number from 0-7), for a total of 8
|
|
555
|
+
// bytes per block. This represents a space overhead of about 4%, so we
|
|
556
|
+
// require that at least 5% of the input points should be encodable as
|
|
557
|
+
// S2CellIds in order for the CELL_IDS format to be worthwhile.
|
|
558
|
+
constexpr double kMinEncodableFraction = 0.05;
|
|
559
|
+
if (level_counts[best_level] <= kMinEncodableFraction * points.size()) {
|
|
560
|
+
return -1;
|
|
561
|
+
}
|
|
562
|
+
return best_level;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Given a vector of points in CellPoint format and an S2CellId level that has
|
|
566
|
+
// been chosen for encoding, returns a vector of 64-bit values that should be
|
|
567
|
+
// encoded in order to represent these points. Points that cannot be
|
|
568
|
+
// represented losslessly as the center of an S2CellId at the chosen level are
|
|
569
|
+
// indicated by the value "kException". "have_exceptions" is set to indicate
|
|
570
|
+
// whether any exceptions were present.
|
|
571
|
+
vector<uint64> ConvertCellsToValues(const vector<CellPoint>& cell_points,
|
|
572
|
+
int level, bool* have_exceptions) {
|
|
573
|
+
vector<uint64> values;
|
|
574
|
+
values.reserve(cell_points.size());
|
|
575
|
+
*have_exceptions = false;
|
|
576
|
+
int shift = S2CellId::kMaxLevel - level;
|
|
577
|
+
for (CellPoint cp : cell_points) {
|
|
578
|
+
if (cp.level != level) {
|
|
579
|
+
values.push_back(kException);
|
|
580
|
+
*have_exceptions = true;
|
|
581
|
+
} else {
|
|
582
|
+
// Note that bit 31 of tj is always zero, and that bits are interleaved in
|
|
583
|
+
// such a way that bit 63 of the result is always zero.
|
|
584
|
+
//
|
|
585
|
+
// The S2CellId version of the following code is:
|
|
586
|
+
// uint64 v = S2CellId::FromFaceIJ(cp.face, cp.si >> 1, cp.ti >> 1).
|
|
587
|
+
// parent(level).id() >> (2 * shift + 1);
|
|
588
|
+
uint32 sj = (((cp.face & 3) << 30) | (cp.si >> 1)) >> shift;
|
|
589
|
+
uint32 tj = (((cp.face & 4) << 29) | cp.ti) >> (shift + 1);
|
|
590
|
+
uint64 v = InterleaveUint32BitPairs(sj, tj);
|
|
591
|
+
S2_DCHECK_LE(v, BitMask(MaxBitsForLevel(level)));
|
|
592
|
+
values.push_back(v);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return values;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
uint64 ChooseBase(const vector<uint64>& values, int level, bool have_exceptions,
|
|
599
|
+
int* base_bits) {
|
|
600
|
+
// Find the minimum and maximum non-exception values to be represented.
|
|
601
|
+
uint64 v_min = kException, v_max = 0;
|
|
602
|
+
for (auto v : values) {
|
|
603
|
+
if (v != kException) {
|
|
604
|
+
v_min = min(v_min, v);
|
|
605
|
+
v_max = max(v_max, v);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if (v_min == kException) return 0;
|
|
609
|
+
|
|
610
|
+
// Generally "base" is chosen as the bit prefix shared by v_min and v_max.
|
|
611
|
+
// However there are a few adjustments we need to make.
|
|
612
|
+
//
|
|
613
|
+
// 1. Encodings are usually smaller if the bits represented by "base" and
|
|
614
|
+
// "delta" do not overlap. Usually the shared prefix rule does this
|
|
615
|
+
// automatically, but if v_min == v_max or there are special circumstances
|
|
616
|
+
// that increase delta_bits (such as values.size() == 1) then we need to
|
|
617
|
+
// make an adjustment.
|
|
618
|
+
//
|
|
619
|
+
// 2. The format only allows us to represent up to 7 bytes (56 bits) of
|
|
620
|
+
// "base", so we need to ensure that "base" conforms to this requirement.
|
|
621
|
+
int min_delta_bits = (have_exceptions || values.size() == 1) ? 8 : 4;
|
|
622
|
+
int excluded_bits = max(Bits::Log2Floor64(v_min ^ v_max) + 1,
|
|
623
|
+
max(min_delta_bits, BaseShift(level, 56)));
|
|
624
|
+
uint64 base = v_min & ~BitMask(excluded_bits);
|
|
625
|
+
|
|
626
|
+
// Determine how many bytes are needed to represent this prefix.
|
|
627
|
+
if (base == 0) {
|
|
628
|
+
*base_bits = 0;
|
|
629
|
+
} else {
|
|
630
|
+
int low_bit = Bits::FindLSBSetNonZero64(base);
|
|
631
|
+
*base_bits = (MaxBitsForLevel(level) - low_bit + 7) & ~7;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Since base_bits has been rounded up to a multiple of 8, we may now be
|
|
635
|
+
// able to represent additional bits of v_min. In general this reduces the
|
|
636
|
+
// final encoded size.
|
|
637
|
+
//
|
|
638
|
+
// NOTE(ericv): A different strategy for choosing "base" is to encode all
|
|
639
|
+
// blocks under the assumption that "base" equals v_min exactly, and then
|
|
640
|
+
// set base equal to the minimum-length prefix of "v_min" that allows these
|
|
641
|
+
// encodings to be used. This strategy reduces the encoded sizes by
|
|
642
|
+
// about 0.2% relative to the strategy here, but is more complicated.
|
|
643
|
+
return v_min & ~BitMask(BaseShift(level, *base_bits));
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Returns true if the range of values [d_min, d_max] can be encoded using the
|
|
647
|
+
// specified parameters (delta_bits, overlap_bits, and have_exceptions).
|
|
648
|
+
bool CanEncode(uint64 d_min, uint64 d_max, int delta_bits,
|
|
649
|
+
int overlap_bits, bool have_exceptions) {
|
|
650
|
+
// "offset" can't represent the lowest (delta_bits - overlap_bits) of d_min.
|
|
651
|
+
d_min &= ~BitMask(delta_bits - overlap_bits);
|
|
652
|
+
|
|
653
|
+
// The maximum delta is reduced by kBlockSize if any exceptions exist, since
|
|
654
|
+
// deltas 0..kBlockSize-1 are used to indicate exceptions.
|
|
655
|
+
uint64 max_delta = BitMask(delta_bits);
|
|
656
|
+
if (have_exceptions) {
|
|
657
|
+
if (max_delta < kBlockSize) return false;
|
|
658
|
+
max_delta -= kBlockSize;
|
|
659
|
+
}
|
|
660
|
+
// The first test below is necessary to avoid 64-bit overflow.
|
|
661
|
+
return (d_min > ~max_delta) || (d_min + max_delta >= d_max);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Given a vector of 64-bit values to be encoded and an S2CellId level, returns
|
|
665
|
+
// the optimal encoding parameters that should be used to encode each block.
|
|
666
|
+
// Also returns the global minimum value "base" and the number of bits that
|
|
667
|
+
// should be used to encode it ("base_bits").
|
|
668
|
+
BlockCode GetBlockCode(Span<const uint64> values, uint64 base,
|
|
669
|
+
bool have_exceptions) {
|
|
670
|
+
// "b_min" and "b_max"n are the minimum and maximum values within this block.
|
|
671
|
+
uint64 b_min = kException, b_max = 0;
|
|
672
|
+
for (uint64 v : values) {
|
|
673
|
+
if (v != kException) {
|
|
674
|
+
b_min = min(b_min, v);
|
|
675
|
+
b_max = max(b_max, v);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
if (b_min == kException) {
|
|
679
|
+
// All values in this block are exceptions.
|
|
680
|
+
return BlockCode{4, 0, 0};
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// Adjust the min/max values so that they are relative to "base".
|
|
684
|
+
b_min -= base;
|
|
685
|
+
b_max -= base;
|
|
686
|
+
|
|
687
|
+
// Determine the minimum possible delta length and overlap that can be used
|
|
688
|
+
// to encode this block. The block will usually be encodable using the
|
|
689
|
+
// number of bits in (b_max - b_min) rounded up to a multiple of 4. If this
|
|
690
|
+
// is not possible, the preferred solution is to shift "offset" so that the
|
|
691
|
+
// delta and offset values overlap by 4 bits (since this only costs an
|
|
692
|
+
// average of 4 extra bits per block). Otherwise we increase the delta size
|
|
693
|
+
// by 4 bits. Certain cases require that both of these techniques are used.
|
|
694
|
+
//
|
|
695
|
+
// Example 1: b_min = 0x72, b_max = 0x7e. The range is 0x0c. This can be
|
|
696
|
+
// encoded using delta_bits = 4 and overlap_bits = 0, which allows us to
|
|
697
|
+
// represent an offset of 0x70 and a maximum delta of 0x0f, so that we can
|
|
698
|
+
// encode values up to 0x7f.
|
|
699
|
+
//
|
|
700
|
+
// Example 2: b_min = 0x78, b_max = 0x84. The range is 0x0c, but in this
|
|
701
|
+
// case it is not sufficient to use delta_bits = 4 and overlap_bits = 0
|
|
702
|
+
// because we can again only represent an offset of 0x70, so the maximum
|
|
703
|
+
// delta of 0x0f only lets us encode values up to 0x7f. However if we
|
|
704
|
+
// increase the overlap to 4 bits then we can represent an offset of 0x78,
|
|
705
|
+
// which lets us encode values up to 0x78 + 0x0f = 0x87.
|
|
706
|
+
//
|
|
707
|
+
// Example 3: b_min = 0x08, b_max = 0x104. The range is 0xfc, so we should
|
|
708
|
+
// be able to use 8-bit deltas. But even with a 4-bit overlap, we can still
|
|
709
|
+
// only encode offset = 0 and a maximum value of 0xff. (We don't allow
|
|
710
|
+
// bigger overlaps because statistically they are not worthwhile.) Instead
|
|
711
|
+
// we increase the delta size to 12 bits, which handles this case easily.
|
|
712
|
+
//
|
|
713
|
+
// Example 4: b_min = 0xf08, b_max = 0x1004. The range is 0xfc, so we
|
|
714
|
+
// should be able to use 8-bit deltas. With 8-bit deltas and no overlap, we
|
|
715
|
+
// have offset = 0xf00 and a maximum encodable value of 0xfff. With 8-bit
|
|
716
|
+
// deltas and a 4-bit overlap, we still have offset = 0xf00 and a maximum
|
|
717
|
+
// encodable value of 0xfff. Even with 12-bit deltas, we have offset = 0
|
|
718
|
+
// and we can still only represent 0xfff. However with delta_bits = 12 and
|
|
719
|
+
// overlap_bits = 4, we can represent offset = 0xf00 and a maximum encodable
|
|
720
|
+
// value of 0xf00 + 0xfff = 0x1eff.
|
|
721
|
+
//
|
|
722
|
+
// It is possible to show that this last example is the worst case, i.e. we
|
|
723
|
+
// do not need to consider increasing delta_bits or overlap_bits further.
|
|
724
|
+
int delta_bits = (max(1, Bits::Log2Floor64(b_max - b_min)) + 3) & ~3;
|
|
725
|
+
int overlap_bits = 0;
|
|
726
|
+
if (!CanEncode(b_min, b_max, delta_bits, 0, have_exceptions)) {
|
|
727
|
+
if (CanEncode(b_min, b_max, delta_bits, 4, have_exceptions)) {
|
|
728
|
+
overlap_bits = 4;
|
|
729
|
+
} else {
|
|
730
|
+
S2_DCHECK_LE(delta_bits, 60);
|
|
731
|
+
delta_bits += 4;
|
|
732
|
+
if (!CanEncode(b_min, b_max, delta_bits, 0, have_exceptions)) {
|
|
733
|
+
S2_DCHECK(CanEncode(b_min, b_max, delta_bits, 4, have_exceptions));
|
|
734
|
+
overlap_bits = 4;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// Avoid wasting 4 bits of delta when the block size is 1. This reduces the
|
|
740
|
+
// encoding size for single leaf cells by one byte.
|
|
741
|
+
if (values.size() == 1) {
|
|
742
|
+
S2_DCHECK(delta_bits == 4 && overlap_bits == 0);
|
|
743
|
+
delta_bits = 8;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Now determine the number of bytes needed to encode "offset", given the
|
|
747
|
+
// chosen delta length.
|
|
748
|
+
uint64 max_delta = BitMask(delta_bits) - (have_exceptions ? kBlockSize : 0);
|
|
749
|
+
int offset_bits = 0;
|
|
750
|
+
if (b_max > max_delta) {
|
|
751
|
+
// At least one byte of offset is required. Round up the minimum offset
|
|
752
|
+
// to the next encodable value, and determine how many bits it has.
|
|
753
|
+
int offset_shift = delta_bits - overlap_bits;
|
|
754
|
+
uint64 mask = BitMask(offset_shift);
|
|
755
|
+
uint64 min_offset = (b_max - max_delta + mask) & ~mask;
|
|
756
|
+
S2_DCHECK_GT(min_offset, 0);
|
|
757
|
+
offset_bits =
|
|
758
|
+
(Bits::FindMSBSetNonZero64(min_offset) + 1 - offset_shift + 7) & ~7;
|
|
759
|
+
// A 64-bit offset can only be encoded with an overlap of 4 bits.
|
|
760
|
+
if (offset_bits == 64) overlap_bits = 4;
|
|
761
|
+
}
|
|
762
|
+
return BlockCode{delta_bits, offset_bits, overlap_bits};
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
bool EncodedS2PointVector::InitCellIdsFormat(Decoder* decoder) {
|
|
766
|
+
// This function inverts the encodings documented above.
|
|
767
|
+
// First we decode the two-byte header.
|
|
768
|
+
if (decoder->avail() < 2) return false;
|
|
769
|
+
uint8 header1 = decoder->get8();
|
|
770
|
+
uint8 header2 = decoder->get8();
|
|
771
|
+
S2_DCHECK_EQ(header1 & 7, CELL_IDS);
|
|
772
|
+
int last_block_count, base_bytes;
|
|
773
|
+
cell_ids_.have_exceptions = (header1 & 8) != 0;
|
|
774
|
+
last_block_count = (header1 >> 4) + 1;
|
|
775
|
+
base_bytes = header2 & 7;
|
|
776
|
+
cell_ids_.level = header2 >> 3;
|
|
777
|
+
|
|
778
|
+
// Decode the base value (if any).
|
|
779
|
+
uint64 base;
|
|
780
|
+
if (!DecodeUintWithLength(base_bytes, decoder, &base)) return false;
|
|
781
|
+
cell_ids_.base = base << BaseShift(cell_ids_.level, base_bytes << 3);
|
|
782
|
+
|
|
783
|
+
// Initialize the vector of encoded blocks.
|
|
784
|
+
if (!cell_ids_.blocks.Init(decoder)) return false;
|
|
785
|
+
size_ = kBlockSize * (cell_ids_.blocks.size() - 1) + last_block_count;
|
|
786
|
+
return true;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
S2Point EncodedS2PointVector::DecodeCellIdsFormat(int i) const {
|
|
790
|
+
// This function inverts the encodings documented above.
|
|
791
|
+
|
|
792
|
+
// First we decode the block header.
|
|
793
|
+
const char* ptr = cell_ids_.blocks.GetStart(i >> kBlockShift);
|
|
794
|
+
uint8 header = *ptr++;
|
|
795
|
+
int overlap_nibbles = (header >> 3) & 1;
|
|
796
|
+
int offset_bytes = (header & 7) + overlap_nibbles;
|
|
797
|
+
int delta_nibbles = (header >> 4) + 1;
|
|
798
|
+
|
|
799
|
+
// Decode the offset for this block.
|
|
800
|
+
int offset_shift = (delta_nibbles - overlap_nibbles) << 2;
|
|
801
|
+
uint64 offset = GetUintWithLength<uint64>(ptr, offset_bytes) << offset_shift;
|
|
802
|
+
ptr += offset_bytes;
|
|
803
|
+
|
|
804
|
+
// Decode the delta for the requested value.
|
|
805
|
+
int delta_nibble_offset = (i & (kBlockSize - 1)) * delta_nibbles;
|
|
806
|
+
int delta_bytes = (delta_nibbles + 1) >> 1;
|
|
807
|
+
const char* delta_ptr = ptr + (delta_nibble_offset >> 1);
|
|
808
|
+
uint64 delta = GetUintWithLength<uint64>(delta_ptr, delta_bytes);
|
|
809
|
+
delta >>= (delta_nibble_offset & 1) << 2;
|
|
810
|
+
delta &= BitMask(delta_nibbles << 2);
|
|
811
|
+
|
|
812
|
+
// Test whether this point is encoded as an exception.
|
|
813
|
+
if (cell_ids_.have_exceptions) {
|
|
814
|
+
if (delta < kBlockSize) {
|
|
815
|
+
int block_size = min(kBlockSize, size_ - (i & ~(kBlockSize - 1)));
|
|
816
|
+
ptr += (block_size * delta_nibbles + 1) >> 1;
|
|
817
|
+
ptr += delta * sizeof(S2Point);
|
|
818
|
+
return *reinterpret_cast<const S2Point*>(ptr);
|
|
819
|
+
}
|
|
820
|
+
delta -= kBlockSize;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Otherwise convert the 64-bit value back to an S2Point.
|
|
824
|
+
uint64 value = cell_ids_.base + offset + delta;
|
|
825
|
+
int shift = S2CellId::kMaxLevel - cell_ids_.level;
|
|
826
|
+
|
|
827
|
+
// The S2CellId version of the following code is:
|
|
828
|
+
// return S2CellId(((value << 1) | 1) << (2 * shift)).ToPoint();
|
|
829
|
+
uint32 sj, tj;
|
|
830
|
+
DeinterleaveUint32BitPairs(value, &sj, &tj);
|
|
831
|
+
int si = (((sj << 1) | 1) << shift) & 0x7fffffff;
|
|
832
|
+
int ti = (((tj << 1) | 1) << shift) & 0x7fffffff;
|
|
833
|
+
int face = ((sj << shift) >> 30) | (((tj << (shift + 1)) >> 29) & 4);
|
|
834
|
+
return S2::FaceUVtoXYZ(face, S2::STtoUV(S2::SiTitoST(si)),
|
|
835
|
+
S2::STtoUV(S2::SiTitoST(ti))).Normalize();
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
} // namespace s2coding
|