@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.
Files changed (471) hide show
  1. package/.circleci/config.yml +45 -0
  2. package/.dockerignore +1 -0
  3. package/.gitmodules +3 -0
  4. package/CHANGELOG.md +33 -0
  5. package/LICENSE +201 -0
  6. package/README.md +147 -0
  7. package/binding.gyp +170 -0
  8. package/docker/Dockerfile.node20.test +8 -0
  9. package/docker/Dockerfile.node22.test +8 -0
  10. package/docker/Dockerfile.node24.test +8 -0
  11. package/index.d.ts +117 -0
  12. package/index.js +6 -0
  13. package/jest.config.js +184 -0
  14. package/package.json +43 -0
  15. package/publish-linux.sh +18 -0
  16. package/publish-osx.sh +19 -0
  17. package/src/builder.cc +84 -0
  18. package/src/builder.h +29 -0
  19. package/src/cell.cc +71 -0
  20. package/src/cell.h +26 -0
  21. package/src/cell_id.cc +210 -0
  22. package/src/cell_id.h +44 -0
  23. package/src/cell_union.cc +237 -0
  24. package/src/cell_union.h +34 -0
  25. package/src/earth.cc +185 -0
  26. package/src/earth.h +33 -0
  27. package/src/latlng.cc +132 -0
  28. package/src/latlng.h +28 -0
  29. package/src/loop.cc +51 -0
  30. package/src/loop.h +21 -0
  31. package/src/point.cc +69 -0
  32. package/src/point.h +23 -0
  33. package/src/polygon.cc +36 -0
  34. package/src/polygon.h +20 -0
  35. package/src/polyline.cc +186 -0
  36. package/src/polyline.h +34 -0
  37. package/src/region_coverer.cc +450 -0
  38. package/src/region_coverer.h +56 -0
  39. package/src/s2.cc +27 -0
  40. package/test/Cell.test.js +37 -0
  41. package/test/CellId.test.js +135 -0
  42. package/test/CellUnion.test.js +150 -0
  43. package/test/Earth.test.js +62 -0
  44. package/test/LatLng.test.js +45 -0
  45. package/test/Point.test.js +14 -0
  46. package/test/Polyline.test.js +78 -0
  47. package/test/RegionCoverer.test.js +301 -0
  48. package/test.sh +16 -0
  49. package/third_party/s2geometry/.travis.yml +163 -0
  50. package/third_party/s2geometry/AUTHORS +13 -0
  51. package/third_party/s2geometry/CONTRIBUTING.md +65 -0
  52. package/third_party/s2geometry/CONTRIBUTORS +30 -0
  53. package/third_party/s2geometry/LICENSE +202 -0
  54. package/third_party/s2geometry/NOTICE +5 -0
  55. package/third_party/s2geometry/README.md +127 -0
  56. package/third_party/s2geometry/doc/examples/point_index.cc +44 -0
  57. package/third_party/s2geometry/doc/examples/term_index.cc +99 -0
  58. package/third_party/s2geometry/doc/examples/term_index.py +101 -0
  59. package/third_party/s2geometry/src/python/coder.i +125 -0
  60. package/third_party/s2geometry/src/python/pywraps2_test.py +786 -0
  61. package/third_party/s2geometry/src/python/s2.i +37 -0
  62. package/third_party/s2geometry/src/python/s2_common.i +756 -0
  63. package/third_party/s2geometry/src/s2/_fp_contract_off.h +60 -0
  64. package/third_party/s2geometry/src/s2/base/casts.h +318 -0
  65. package/third_party/s2geometry/src/s2/base/commandlineflags.h +67 -0
  66. package/third_party/s2geometry/src/s2/base/integral_types.h +31 -0
  67. package/third_party/s2geometry/src/s2/base/log_severity.h +40 -0
  68. package/third_party/s2geometry/src/s2/base/logging.h +173 -0
  69. package/third_party/s2geometry/src/s2/base/mutex.h +61 -0
  70. package/third_party/s2geometry/src/s2/base/port.h +999 -0
  71. package/third_party/s2geometry/src/s2/base/spinlock.h +60 -0
  72. package/third_party/s2geometry/src/s2/base/stringprintf.cc +107 -0
  73. package/third_party/s2geometry/src/s2/base/stringprintf.h +53 -0
  74. package/third_party/s2geometry/src/s2/base/strtoint.cc +65 -0
  75. package/third_party/s2geometry/src/s2/base/strtoint.h +106 -0
  76. package/third_party/s2geometry/src/s2/base/timer.h +50 -0
  77. package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector.cc +164 -0
  78. package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector.h +110 -0
  79. package/third_party/s2geometry/src/s2/encoded_s2cell_id_vector_test.cc +232 -0
  80. package/third_party/s2geometry/src/s2/encoded_s2point_vector.cc +838 -0
  81. package/third_party/s2geometry/src/s2/encoded_s2point_vector.h +140 -0
  82. package/third_party/s2geometry/src/s2/encoded_s2point_vector_test.cc +344 -0
  83. package/third_party/s2geometry/src/s2/encoded_s2shape_index.cc +181 -0
  84. package/third_party/s2geometry/src/s2/encoded_s2shape_index.h +276 -0
  85. package/third_party/s2geometry/src/s2/encoded_s2shape_index_test.cc +244 -0
  86. package/third_party/s2geometry/src/s2/encoded_string_vector.cc +66 -0
  87. package/third_party/s2geometry/src/s2/encoded_string_vector.h +164 -0
  88. package/third_party/s2geometry/src/s2/encoded_string_vector_test.cc +69 -0
  89. package/third_party/s2geometry/src/s2/encoded_uint_vector.h +299 -0
  90. package/third_party/s2geometry/src/s2/encoded_uint_vector_test.cc +124 -0
  91. package/third_party/s2geometry/src/s2/id_set_lexicon.cc +81 -0
  92. package/third_party/s2geometry/src/s2/id_set_lexicon.h +199 -0
  93. package/third_party/s2geometry/src/s2/id_set_lexicon_test.cc +70 -0
  94. package/third_party/s2geometry/src/s2/mutable_s2shape_index.cc +1585 -0
  95. package/third_party/s2geometry/src/s2/mutable_s2shape_index.h +600 -0
  96. package/third_party/s2geometry/src/s2/mutable_s2shape_index_test.cc +589 -0
  97. package/third_party/s2geometry/src/s2/r1interval.h +220 -0
  98. package/third_party/s2geometry/src/s2/r1interval_test.cc +185 -0
  99. package/third_party/s2geometry/src/s2/r2.h +26 -0
  100. package/third_party/s2geometry/src/s2/r2rect.cc +93 -0
  101. package/third_party/s2geometry/src/s2/r2rect.h +234 -0
  102. package/third_party/s2geometry/src/s2/r2rect_test.cc +228 -0
  103. package/third_party/s2geometry/src/s2/s1angle.cc +54 -0
  104. package/third_party/s2geometry/src/s2/s1angle.h +336 -0
  105. package/third_party/s2geometry/src/s2/s1angle_test.cc +185 -0
  106. package/third_party/s2geometry/src/s2/s1chord_angle.cc +159 -0
  107. package/third_party/s2geometry/src/s2/s1chord_angle.h +369 -0
  108. package/third_party/s2geometry/src/s2/s1chord_angle_test.cc +207 -0
  109. package/third_party/s2geometry/src/s2/s1interval.cc +296 -0
  110. package/third_party/s2geometry/src/s2/s1interval.h +266 -0
  111. package/third_party/s2geometry/src/s2/s1interval_test.cc +469 -0
  112. package/third_party/s2geometry/src/s2/s2boolean_operation.cc +2391 -0
  113. package/third_party/s2geometry/src/s2/s2boolean_operation.h +501 -0
  114. package/third_party/s2geometry/src/s2/s2boolean_operation_test.cc +1400 -0
  115. package/third_party/s2geometry/src/s2/s2builder.cc +1828 -0
  116. package/third_party/s2geometry/src/s2/s2builder.h +1057 -0
  117. package/third_party/s2geometry/src/s2/s2builder_graph.cc +1084 -0
  118. package/third_party/s2geometry/src/s2/s2builder_graph.h +799 -0
  119. package/third_party/s2geometry/src/s2/s2builder_graph_test.cc +462 -0
  120. package/third_party/s2geometry/src/s2/s2builder_layer.h +50 -0
  121. package/third_party/s2geometry/src/s2/s2builder_test.cc +1329 -0
  122. package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer.cc +313 -0
  123. package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer.h +221 -0
  124. package/third_party/s2geometry/src/s2/s2builderutil_closed_set_normalizer_test.cc +261 -0
  125. package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies.cc +392 -0
  126. package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies.h +86 -0
  127. package/third_party/s2geometry/src/s2/s2builderutil_find_polygon_degeneracies_test.cc +182 -0
  128. package/third_party/s2geometry/src/s2/s2builderutil_graph_shape.h +57 -0
  129. package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer.cc +212 -0
  130. package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer.h +218 -0
  131. package/third_party/s2geometry/src/s2/s2builderutil_lax_polygon_layer_test.cc +367 -0
  132. package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer.cc +74 -0
  133. package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer.h +122 -0
  134. package/third_party/s2geometry/src/s2/s2builderutil_s2point_vector_layer_test.cc +167 -0
  135. package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer.cc +191 -0
  136. package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer.h +211 -0
  137. package/third_party/s2geometry/src/s2/s2builderutil_s2polygon_layer_test.cc +312 -0
  138. package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer.cc +105 -0
  139. package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer.h +174 -0
  140. package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_layer_test.cc +220 -0
  141. package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer.cc +98 -0
  142. package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer.h +292 -0
  143. package/third_party/s2geometry/src/s2/s2builderutil_s2polyline_vector_layer_test.cc +233 -0
  144. package/third_party/s2geometry/src/s2/s2builderutil_snap_functions.cc +354 -0
  145. package/third_party/s2geometry/src/s2/s2builderutil_snap_functions.h +239 -0
  146. package/third_party/s2geometry/src/s2/s2builderutil_snap_functions_test.cc +716 -0
  147. package/third_party/s2geometry/src/s2/s2builderutil_testing.cc +37 -0
  148. package/third_party/s2geometry/src/s2/s2builderutil_testing.h +100 -0
  149. package/third_party/s2geometry/src/s2/s2builderutil_testing_test.cc +85 -0
  150. package/third_party/s2geometry/src/s2/s2cap.cc +347 -0
  151. package/third_party/s2geometry/src/s2/s2cap.h +286 -0
  152. package/third_party/s2geometry/src/s2/s2cap_test.cc +379 -0
  153. package/third_party/s2geometry/src/s2/s2cell.cc +552 -0
  154. package/third_party/s2geometry/src/s2/s2cell.h +249 -0
  155. package/third_party/s2geometry/src/s2/s2cell_id.cc +619 -0
  156. package/third_party/s2geometry/src/s2/s2cell_id.h +705 -0
  157. package/third_party/s2geometry/src/s2/s2cell_id_test.cc +633 -0
  158. package/third_party/s2geometry/src/s2/s2cell_index.cc +149 -0
  159. package/third_party/s2geometry/src/s2/s2cell_index.h +660 -0
  160. package/third_party/s2geometry/src/s2/s2cell_index_test.cc +411 -0
  161. package/third_party/s2geometry/src/s2/s2cell_test.cc +687 -0
  162. package/third_party/s2geometry/src/s2/s2cell_union.cc +515 -0
  163. package/third_party/s2geometry/src/s2/s2cell_union.h +399 -0
  164. package/third_party/s2geometry/src/s2/s2cell_union_test.cc +598 -0
  165. package/third_party/s2geometry/src/s2/s2centroids.cc +84 -0
  166. package/third_party/s2geometry/src/s2/s2centroids.h +87 -0
  167. package/third_party/s2geometry/src/s2/s2centroids_test.cc +82 -0
  168. package/third_party/s2geometry/src/s2/s2closest_cell_query.cc +123 -0
  169. package/third_party/s2geometry/src/s2/s2closest_cell_query.h +385 -0
  170. package/third_party/s2geometry/src/s2/s2closest_cell_query_base.h +841 -0
  171. package/third_party/s2geometry/src/s2/s2closest_cell_query_base_test.cc +63 -0
  172. package/third_party/s2geometry/src/s2/s2closest_cell_query_test.cc +412 -0
  173. package/third_party/s2geometry/src/s2/s2closest_edge_query.cc +106 -0
  174. package/third_party/s2geometry/src/s2/s2closest_edge_query.h +421 -0
  175. package/third_party/s2geometry/src/s2/s2closest_edge_query_base.h +946 -0
  176. package/third_party/s2geometry/src/s2/s2closest_edge_query_base_test.cc +59 -0
  177. package/third_party/s2geometry/src/s2/s2closest_edge_query_test.cc +505 -0
  178. package/third_party/s2geometry/src/s2/s2closest_edge_query_testing.h +91 -0
  179. package/third_party/s2geometry/src/s2/s2closest_point_query.cc +66 -0
  180. package/third_party/s2geometry/src/s2/s2closest_point_query.h +465 -0
  181. package/third_party/s2geometry/src/s2/s2closest_point_query_base.h +767 -0
  182. package/third_party/s2geometry/src/s2/s2closest_point_query_base_test.cc +63 -0
  183. package/third_party/s2geometry/src/s2/s2closest_point_query_test.cc +312 -0
  184. package/third_party/s2geometry/src/s2/s2contains_point_query.h +328 -0
  185. package/third_party/s2geometry/src/s2/s2contains_point_query_test.cc +159 -0
  186. package/third_party/s2geometry/src/s2/s2contains_vertex_query.cc +39 -0
  187. package/third_party/s2geometry/src/s2/s2contains_vertex_query.h +66 -0
  188. package/third_party/s2geometry/src/s2/s2contains_vertex_query_test.cc +67 -0
  189. package/third_party/s2geometry/src/s2/s2convex_hull_query.cc +198 -0
  190. package/third_party/s2geometry/src/s2/s2convex_hull_query.h +110 -0
  191. package/third_party/s2geometry/src/s2/s2convex_hull_query_test.cc +208 -0
  192. package/third_party/s2geometry/src/s2/s2coords.cc +146 -0
  193. package/third_party/s2geometry/src/s2/s2coords.h +459 -0
  194. package/third_party/s2geometry/src/s2/s2coords_internal.h +71 -0
  195. package/third_party/s2geometry/src/s2/s2coords_test.cc +218 -0
  196. package/third_party/s2geometry/src/s2/s2crossing_edge_query.cc +380 -0
  197. package/third_party/s2geometry/src/s2/s2crossing_edge_query.h +220 -0
  198. package/third_party/s2geometry/src/s2/s2crossing_edge_query_test.cc +382 -0
  199. package/third_party/s2geometry/src/s2/s2debug.cc +23 -0
  200. package/third_party/s2geometry/src/s2/s2debug.h +69 -0
  201. package/third_party/s2geometry/src/s2/s2distance_target.h +165 -0
  202. package/third_party/s2geometry/src/s2/s2earth.cc +52 -0
  203. package/third_party/s2geometry/src/s2/s2earth.h +268 -0
  204. package/third_party/s2geometry/src/s2/s2earth_test.cc +146 -0
  205. package/third_party/s2geometry/src/s2/s2edge_clipping.cc +462 -0
  206. package/third_party/s2geometry/src/s2/s2edge_clipping.h +183 -0
  207. package/third_party/s2geometry/src/s2/s2edge_clipping_test.cc +335 -0
  208. package/third_party/s2geometry/src/s2/s2edge_crosser.cc +85 -0
  209. package/third_party/s2geometry/src/s2/s2edge_crosser.h +343 -0
  210. package/third_party/s2geometry/src/s2/s2edge_crosser_test.cc +264 -0
  211. package/third_party/s2geometry/src/s2/s2edge_crossings.cc +515 -0
  212. package/third_party/s2geometry/src/s2/s2edge_crossings.h +138 -0
  213. package/third_party/s2geometry/src/s2/s2edge_crossings_internal.h +59 -0
  214. package/third_party/s2geometry/src/s2/s2edge_crossings_test.cc +246 -0
  215. package/third_party/s2geometry/src/s2/s2edge_distances.cc +419 -0
  216. package/third_party/s2geometry/src/s2/s2edge_distances.h +192 -0
  217. package/third_party/s2geometry/src/s2/s2edge_distances_test.cc +539 -0
  218. package/third_party/s2geometry/src/s2/s2edge_tessellator.cc +276 -0
  219. package/third_party/s2geometry/src/s2/s2edge_tessellator.h +101 -0
  220. package/third_party/s2geometry/src/s2/s2edge_tessellator_test.cc +492 -0
  221. package/third_party/s2geometry/src/s2/s2edge_vector_shape.h +85 -0
  222. package/third_party/s2geometry/src/s2/s2edge_vector_shape_test.cc +66 -0
  223. package/third_party/s2geometry/src/s2/s2error.cc +29 -0
  224. package/third_party/s2geometry/src/s2/s2error.h +147 -0
  225. package/third_party/s2geometry/src/s2/s2error_test.cc +31 -0
  226. package/third_party/s2geometry/src/s2/s2furthest_edge_query.cc +117 -0
  227. package/third_party/s2geometry/src/s2/s2furthest_edge_query.h +439 -0
  228. package/third_party/s2geometry/src/s2/s2furthest_edge_query_test.cc +487 -0
  229. package/third_party/s2geometry/src/s2/s2latlng.cc +90 -0
  230. package/third_party/s2geometry/src/s2/s2latlng.h +234 -0
  231. package/third_party/s2geometry/src/s2/s2latlng_rect.cc +727 -0
  232. package/third_party/s2geometry/src/s2/s2latlng_rect.h +434 -0
  233. package/third_party/s2geometry/src/s2/s2latlng_rect_bounder.cc +344 -0
  234. package/third_party/s2geometry/src/s2/s2latlng_rect_bounder.h +89 -0
  235. package/third_party/s2geometry/src/s2/s2latlng_rect_bounder_test.cc +306 -0
  236. package/third_party/s2geometry/src/s2/s2latlng_rect_test.cc +1030 -0
  237. package/third_party/s2geometry/src/s2/s2latlng_test.cc +165 -0
  238. package/third_party/s2geometry/src/s2/s2lax_loop_shape.cc +104 -0
  239. package/third_party/s2geometry/src/s2/s2lax_loop_shape.h +153 -0
  240. package/third_party/s2geometry/src/s2/s2lax_loop_shape_test.cc +101 -0
  241. package/third_party/s2geometry/src/s2/s2lax_polygon_shape.cc +348 -0
  242. package/third_party/s2geometry/src/s2/s2lax_polygon_shape.h +183 -0
  243. package/third_party/s2geometry/src/s2/s2lax_polygon_shape_test.cc +234 -0
  244. package/third_party/s2geometry/src/s2/s2lax_polyline_shape.cc +118 -0
  245. package/third_party/s2geometry/src/s2/s2lax_polyline_shape.h +124 -0
  246. package/third_party/s2geometry/src/s2/s2lax_polyline_shape_test.cc +62 -0
  247. package/third_party/s2geometry/src/s2/s2loop.cc +1509 -0
  248. package/third_party/s2geometry/src/s2/s2loop.h +711 -0
  249. package/third_party/s2geometry/src/s2/s2loop_measures.cc +313 -0
  250. package/third_party/s2geometry/src/s2/s2loop_measures.h +280 -0
  251. package/third_party/s2geometry/src/s2/s2loop_measures_test.cc +367 -0
  252. package/third_party/s2geometry/src/s2/s2loop_test.cc +1371 -0
  253. package/third_party/s2geometry/src/s2/s2max_distance_targets.cc +265 -0
  254. package/third_party/s2geometry/src/s2/s2max_distance_targets.h +241 -0
  255. package/third_party/s2geometry/src/s2/s2max_distance_targets_test.cc +367 -0
  256. package/third_party/s2geometry/src/s2/s2measures.cc +128 -0
  257. package/third_party/s2geometry/src/s2/s2measures.h +78 -0
  258. package/third_party/s2geometry/src/s2/s2measures_test.cc +135 -0
  259. package/third_party/s2geometry/src/s2/s2metrics.cc +122 -0
  260. package/third_party/s2geometry/src/s2/s2metrics.h +199 -0
  261. package/third_party/s2geometry/src/s2/s2metrics_test.cc +127 -0
  262. package/third_party/s2geometry/src/s2/s2min_distance_targets.cc +295 -0
  263. package/third_party/s2geometry/src/s2/s2min_distance_targets.h +273 -0
  264. package/third_party/s2geometry/src/s2/s2min_distance_targets_test.cc +239 -0
  265. package/third_party/s2geometry/src/s2/s2padded_cell.cc +162 -0
  266. package/third_party/s2geometry/src/s2/s2padded_cell.h +108 -0
  267. package/third_party/s2geometry/src/s2/s2padded_cell_test.cc +138 -0
  268. package/third_party/s2geometry/src/s2/s2point.h +38 -0
  269. package/third_party/s2geometry/src/s2/s2point_compression.cc +388 -0
  270. package/third_party/s2geometry/src/s2/s2point_compression.h +78 -0
  271. package/third_party/s2geometry/src/s2/s2point_compression_test.cc +305 -0
  272. package/third_party/s2geometry/src/s2/s2point_index.h +345 -0
  273. package/third_party/s2geometry/src/s2/s2point_index_test.cc +147 -0
  274. package/third_party/s2geometry/src/s2/s2point_region.cc +72 -0
  275. package/third_party/s2geometry/src/s2/s2point_region.h +76 -0
  276. package/third_party/s2geometry/src/s2/s2point_region_test.cc +100 -0
  277. package/third_party/s2geometry/src/s2/s2point_span.h +57 -0
  278. package/third_party/s2geometry/src/s2/s2point_test.cc +47 -0
  279. package/third_party/s2geometry/src/s2/s2point_vector_shape.h +127 -0
  280. package/third_party/s2geometry/src/s2/s2point_vector_shape_test.cc +59 -0
  281. package/third_party/s2geometry/src/s2/s2pointutil.cc +131 -0
  282. package/third_party/s2geometry/src/s2/s2pointutil.h +138 -0
  283. package/third_party/s2geometry/src/s2/s2pointutil_test.cc +157 -0
  284. package/third_party/s2geometry/src/s2/s2polygon.cc +1569 -0
  285. package/third_party/s2geometry/src/s2/s2polygon.h +934 -0
  286. package/third_party/s2geometry/src/s2/s2polygon_test.cc +3025 -0
  287. package/third_party/s2geometry/src/s2/s2polyline.cc +645 -0
  288. package/third_party/s2geometry/src/s2/s2polyline.h +379 -0
  289. package/third_party/s2geometry/src/s2/s2polyline_alignment.cc +414 -0
  290. package/third_party/s2geometry/src/s2/s2polyline_alignment.h +245 -0
  291. package/third_party/s2geometry/src/s2/s2polyline_alignment_internal.h +158 -0
  292. package/third_party/s2geometry/src/s2/s2polyline_alignment_test.cc +610 -0
  293. package/third_party/s2geometry/src/s2/s2polyline_measures.cc +42 -0
  294. package/third_party/s2geometry/src/s2/s2polyline_measures.h +53 -0
  295. package/third_party/s2geometry/src/s2/s2polyline_measures_test.cc +57 -0
  296. package/third_party/s2geometry/src/s2/s2polyline_simplifier.cc +187 -0
  297. package/third_party/s2geometry/src/s2/s2polyline_simplifier.h +109 -0
  298. package/third_party/s2geometry/src/s2/s2polyline_simplifier_test.cc +165 -0
  299. package/third_party/s2geometry/src/s2/s2polyline_test.cc +554 -0
  300. package/third_party/s2geometry/src/s2/s2predicates.cc +1486 -0
  301. package/third_party/s2geometry/src/s2/s2predicates.h +282 -0
  302. package/third_party/s2geometry/src/s2/s2predicates_internal.h +135 -0
  303. package/third_party/s2geometry/src/s2/s2predicates_test.cc +1427 -0
  304. package/third_party/s2geometry/src/s2/s2projections.cc +109 -0
  305. package/third_party/s2geometry/src/s2/s2projections.h +161 -0
  306. package/third_party/s2geometry/src/s2/s2projections_test.cc +78 -0
  307. package/third_party/s2geometry/src/s2/s2r2rect.cc +88 -0
  308. package/third_party/s2geometry/src/s2/s2r2rect.h +292 -0
  309. package/third_party/s2geometry/src/s2/s2r2rect_test.cc +312 -0
  310. package/third_party/s2geometry/src/s2/s2region.cc +26 -0
  311. package/third_party/s2geometry/src/s2/s2region.h +142 -0
  312. package/third_party/s2geometry/src/s2/s2region_coverer.cc +514 -0
  313. package/third_party/s2geometry/src/s2/s2region_coverer.h +356 -0
  314. package/third_party/s2geometry/src/s2/s2region_coverer_test.cc +509 -0
  315. package/third_party/s2geometry/src/s2/s2region_intersection.cc +84 -0
  316. package/third_party/s2geometry/src/s2/s2region_intersection.h +79 -0
  317. package/third_party/s2geometry/src/s2/s2region_term_indexer.cc +270 -0
  318. package/third_party/s2geometry/src/s2/s2region_term_indexer.h +299 -0
  319. package/third_party/s2geometry/src/s2/s2region_term_indexer_test.cc +209 -0
  320. package/third_party/s2geometry/src/s2/s2region_test.cc +370 -0
  321. package/third_party/s2geometry/src/s2/s2region_union.cc +90 -0
  322. package/third_party/s2geometry/src/s2/s2region_union.h +83 -0
  323. package/third_party/s2geometry/src/s2/s2region_union_test.cc +89 -0
  324. package/third_party/s2geometry/src/s2/s2shape.h +283 -0
  325. package/third_party/s2geometry/src/s2/s2shape_index.cc +321 -0
  326. package/third_party/s2geometry/src/s2/s2shape_index.h +781 -0
  327. package/third_party/s2geometry/src/s2/s2shape_index_buffered_region.cc +113 -0
  328. package/third_party/s2geometry/src/s2/s2shape_index_buffered_region.h +135 -0
  329. package/third_party/s2geometry/src/s2/s2shape_index_buffered_region_test.cc +162 -0
  330. package/third_party/s2geometry/src/s2/s2shape_index_measures.cc +92 -0
  331. package/third_party/s2geometry/src/s2/s2shape_index_measures.h +100 -0
  332. package/third_party/s2geometry/src/s2/s2shape_index_measures_test.cc +136 -0
  333. package/third_party/s2geometry/src/s2/s2shape_index_region.h +350 -0
  334. package/third_party/s2geometry/src/s2/s2shape_index_region_test.cc +161 -0
  335. package/third_party/s2geometry/src/s2/s2shape_index_test.cc +24 -0
  336. package/third_party/s2geometry/src/s2/s2shape_measures.cc +138 -0
  337. package/third_party/s2geometry/src/s2/s2shape_measures.h +95 -0
  338. package/third_party/s2geometry/src/s2/s2shape_measures_test.cc +139 -0
  339. package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries.cc +120 -0
  340. package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries.h +66 -0
  341. package/third_party/s2geometry/src/s2/s2shapeutil_build_polygon_boundaries_test.cc +170 -0
  342. package/third_party/s2geometry/src/s2/s2shapeutil_coding.cc +253 -0
  343. package/third_party/s2geometry/src/s2/s2shapeutil_coding.h +283 -0
  344. package/third_party/s2geometry/src/s2/s2shapeutil_coding_test.cc +54 -0
  345. package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force.cc +40 -0
  346. package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force.h +41 -0
  347. package/third_party/s2geometry/src/s2/s2shapeutil_contains_brute_force_test.cc +55 -0
  348. package/third_party/s2geometry/src/s2/s2shapeutil_count_edges.h +57 -0
  349. package/third_party/s2geometry/src/s2/s2shapeutil_count_edges_test.cc +43 -0
  350. package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator.cc +45 -0
  351. package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator.h +72 -0
  352. package/third_party/s2geometry/src/s2/s2shapeutil_edge_iterator_test.cc +116 -0
  353. package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point.cc +107 -0
  354. package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point.h +48 -0
  355. package/third_party/s2geometry/src/s2/s2shapeutil_get_reference_point_test.cc +104 -0
  356. package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator.cc +58 -0
  357. package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator.h +65 -0
  358. package/third_party/s2geometry/src/s2/s2shapeutil_range_iterator_test.cc +61 -0
  359. package/third_party/s2geometry/src/s2/s2shapeutil_shape_edge.h +58 -0
  360. package/third_party/s2geometry/src/s2/s2shapeutil_shape_edge_id.h +97 -0
  361. package/third_party/s2geometry/src/s2/s2shapeutil_testing.cc +104 -0
  362. package/third_party/s2geometry/src/s2/s2shapeutil_testing.h +36 -0
  363. package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs.cc +440 -0
  364. package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs.h +72 -0
  365. package/third_party/s2geometry/src/s2/s2shapeutil_visit_crossing_edge_pairs_test.cc +184 -0
  366. package/third_party/s2geometry/src/s2/s2testing.cc +464 -0
  367. package/third_party/s2geometry/src/s2/s2testing.h +385 -0
  368. package/third_party/s2geometry/src/s2/s2testing_test.cc +166 -0
  369. package/third_party/s2geometry/src/s2/s2text_format.cc +506 -0
  370. package/third_party/s2geometry/src/s2/s2text_format.h +289 -0
  371. package/third_party/s2geometry/src/s2/s2text_format_test.cc +417 -0
  372. package/third_party/s2geometry/src/s2/s2wedge_relations.cc +80 -0
  373. package/third_party/s2geometry/src/s2/s2wedge_relations.h +64 -0
  374. package/third_party/s2geometry/src/s2/s2wedge_relations_test.cc +89 -0
  375. package/third_party/s2geometry/src/s2/sequence_lexicon.h +296 -0
  376. package/third_party/s2geometry/src/s2/sequence_lexicon_test.cc +113 -0
  377. package/third_party/s2geometry/src/s2/strings/ostringstream.cc +35 -0
  378. package/third_party/s2geometry/src/s2/strings/ostringstream.h +105 -0
  379. package/third_party/s2geometry/src/s2/strings/serialize.cc +46 -0
  380. package/third_party/s2geometry/src/s2/strings/serialize.h +40 -0
  381. package/third_party/s2geometry/src/s2/third_party/absl/algorithm/algorithm.h +187 -0
  382. package/third_party/s2geometry/src/s2/third_party/absl/base/attributes.h +666 -0
  383. package/third_party/s2geometry/src/s2/third_party/absl/base/casts.h +189 -0
  384. package/third_party/s2geometry/src/s2/third_party/absl/base/config.h +462 -0
  385. package/third_party/s2geometry/src/s2/third_party/absl/base/dynamic_annotations.cc +129 -0
  386. package/third_party/s2geometry/src/s2/third_party/absl/base/dynamic_annotations.h +394 -0
  387. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/atomic_hook.h +168 -0
  388. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/identity.h +33 -0
  389. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/inline_variable.h +117 -0
  390. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/invoke.h +188 -0
  391. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/raw_logging.cc +254 -0
  392. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/raw_logging.h +205 -0
  393. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/throw_delegate.cc +106 -0
  394. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/throw_delegate.h +71 -0
  395. package/third_party/s2geometry/src/s2/third_party/absl/base/internal/unaligned_access.h +322 -0
  396. package/third_party/s2geometry/src/s2/third_party/absl/base/log_severity.h +77 -0
  397. package/third_party/s2geometry/src/s2/third_party/absl/base/macros.h +236 -0
  398. package/third_party/s2geometry/src/s2/third_party/absl/base/optimization.h +177 -0
  399. package/third_party/s2geometry/src/s2/third_party/absl/base/policy_checks.h +124 -0
  400. package/third_party/s2geometry/src/s2/third_party/absl/base/port.h +97 -0
  401. package/third_party/s2geometry/src/s2/third_party/absl/base/thread_annotations.h +277 -0
  402. package/third_party/s2geometry/src/s2/third_party/absl/container/fixed_array.h +523 -0
  403. package/third_party/s2geometry/src/s2/third_party/absl/container/inlined_vector.h +1453 -0
  404. package/third_party/s2geometry/src/s2/third_party/absl/container/internal/compressed_tuple.h +191 -0
  405. package/third_party/s2geometry/src/s2/third_party/absl/container/internal/container_memory.h +424 -0
  406. package/third_party/s2geometry/src/s2/third_party/absl/container/internal/layout.h +739 -0
  407. package/third_party/s2geometry/src/s2/third_party/absl/memory/memory.h +755 -0
  408. package/third_party/s2geometry/src/s2/third_party/absl/meta/type_traits.h +436 -0
  409. package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128.cc +232 -0
  410. package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128.h +656 -0
  411. package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128_have_intrinsic.inc +3 -0
  412. package/third_party/s2geometry/src/s2/third_party/absl/numeric/int128_no_intrinsic.inc +3 -0
  413. package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii.cc +198 -0
  414. package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii.h +239 -0
  415. package/third_party/s2geometry/src/s2/third_party/absl/strings/ascii_ctype.h +66 -0
  416. package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/bits.h +53 -0
  417. package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/memutil.cc +110 -0
  418. package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/memutil.h +146 -0
  419. package/third_party/s2geometry/src/s2/third_party/absl/strings/internal/resize_uninitialized.h +72 -0
  420. package/third_party/s2geometry/src/s2/third_party/absl/strings/match.cc +38 -0
  421. package/third_party/s2geometry/src/s2/third_party/absl/strings/match.h +89 -0
  422. package/third_party/s2geometry/src/s2/third_party/absl/strings/numbers.cc +909 -0
  423. package/third_party/s2geometry/src/s2/third_party/absl/strings/numbers.h +187 -0
  424. package/third_party/s2geometry/src/s2/third_party/absl/strings/str_cat.cc +240 -0
  425. package/third_party/s2geometry/src/s2/third_party/absl/strings/str_cat.h +398 -0
  426. package/third_party/s2geometry/src/s2/third_party/absl/strings/str_join.h +22 -0
  427. package/third_party/s2geometry/src/s2/third_party/absl/strings/str_split.cc +47 -0
  428. package/third_party/s2geometry/src/s2/third_party/absl/strings/str_split.h +43 -0
  429. package/third_party/s2geometry/src/s2/third_party/absl/strings/string_view.cc +245 -0
  430. package/third_party/s2geometry/src/s2/third_party/absl/strings/string_view.h +602 -0
  431. package/third_party/s2geometry/src/s2/third_party/absl/strings/strip.cc +42 -0
  432. package/third_party/s2geometry/src/s2/third_party/absl/strings/strip.h +130 -0
  433. package/third_party/s2geometry/src/s2/third_party/absl/types/span.h +793 -0
  434. package/third_party/s2geometry/src/s2/third_party/absl/utility/utility.h +299 -0
  435. package/third_party/s2geometry/src/s2/util/bits/bit-interleave.cc +274 -0
  436. package/third_party/s2geometry/src/s2/util/bits/bit-interleave.h +53 -0
  437. package/third_party/s2geometry/src/s2/util/bits/bits.cc +155 -0
  438. package/third_party/s2geometry/src/s2/util/bits/bits.h +745 -0
  439. package/third_party/s2geometry/src/s2/util/coding/coder.cc +83 -0
  440. package/third_party/s2geometry/src/s2/util/coding/coder.h +553 -0
  441. package/third_party/s2geometry/src/s2/util/coding/nth-derivative.h +134 -0
  442. package/third_party/s2geometry/src/s2/util/coding/transforms.h +62 -0
  443. package/third_party/s2geometry/src/s2/util/coding/varint.cc +289 -0
  444. package/third_party/s2geometry/src/s2/util/coding/varint.h +476 -0
  445. package/third_party/s2geometry/src/s2/util/endian/endian.h +859 -0
  446. package/third_party/s2geometry/src/s2/util/gtl/btree.h +2471 -0
  447. package/third_party/s2geometry/src/s2/util/gtl/btree_container.h +411 -0
  448. package/third_party/s2geometry/src/s2/util/gtl/btree_map.h +79 -0
  449. package/third_party/s2geometry/src/s2/util/gtl/btree_set.h +73 -0
  450. package/third_party/s2geometry/src/s2/util/gtl/compact_array.h +653 -0
  451. package/third_party/s2geometry/src/s2/util/gtl/container_logging.h +291 -0
  452. package/third_party/s2geometry/src/s2/util/gtl/dense_hash_set.h +358 -0
  453. package/third_party/s2geometry/src/s2/util/gtl/densehashtable.h +1493 -0
  454. package/third_party/s2geometry/src/s2/util/gtl/hashtable_common.h +253 -0
  455. package/third_party/s2geometry/src/s2/util/gtl/layout.h +28 -0
  456. package/third_party/s2geometry/src/s2/util/gtl/legacy_random_shuffle.h +77 -0
  457. package/third_party/s2geometry/src/s2/util/hash/mix.h +76 -0
  458. package/third_party/s2geometry/src/s2/util/math/exactfloat/exactfloat.cc +832 -0
  459. package/third_party/s2geometry/src/s2/util/math/exactfloat/exactfloat.h +646 -0
  460. package/third_party/s2geometry/src/s2/util/math/mathutil.cc +75 -0
  461. package/third_party/s2geometry/src/s2/util/math/mathutil.h +189 -0
  462. package/third_party/s2geometry/src/s2/util/math/matrix3x3.h +574 -0
  463. package/third_party/s2geometry/src/s2/util/math/vector.h +569 -0
  464. package/third_party/s2geometry/src/s2/util/math/vector3_hash.h +54 -0
  465. package/third_party/s2geometry/src/s2/util/units/length-units.cc +21 -0
  466. package/third_party/s2geometry/src/s2/util/units/length-units.h +135 -0
  467. package/third_party/s2geometry/src/s2/util/units/physical-units.h +313 -0
  468. package/third_party/s2geometry/src/s2/value_lexicon.h +234 -0
  469. package/third_party/s2geometry/src/s2/value_lexicon_test.cc +121 -0
  470. package/third_party/s2geometry/third_party/cmake/FindGFlags.cmake +48 -0
  471. 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_