@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,946 @@
1
+ // Copyright 2017 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
+ #ifndef S2_S2CLOSEST_EDGE_QUERY_BASE_H_
19
+ #define S2_S2CLOSEST_EDGE_QUERY_BASE_H_
20
+
21
+ #include <memory>
22
+ #include <vector>
23
+
24
+ #include "s2/base/logging.h"
25
+ #include "s2/util/gtl/btree_set.h"
26
+ #include "s2/third_party/absl/container/inlined_vector.h"
27
+ #include "s2/_fp_contract_off.h"
28
+ #include "s2/s1angle.h"
29
+ #include "s2/s1chord_angle.h"
30
+ #include "s2/s2cap.h"
31
+ #include "s2/s2cell.h"
32
+ #include "s2/s2cell_id.h"
33
+ #include "s2/s2cell_union.h"
34
+ #include "s2/s2distance_target.h"
35
+ #include "s2/s2region_coverer.h"
36
+ #include "s2/s2shape_index.h"
37
+ #include "s2/s2shapeutil_count_edges.h"
38
+ #include "s2/s2shapeutil_shape_edge_id.h"
39
+ #include "s2/util/gtl/dense_hash_set.h"
40
+
41
+ // S2ClosestEdgeQueryBase is a templatized class for finding the closest
42
+ // edge(s) between two geometries. It is not intended to be used directly,
43
+ // but rather to serve as the implementation of various specialized classes
44
+ // with more convenient APIs (such as S2ClosestEdgeQuery). It is flexible
45
+ // enough so that it can be adapted to compute maximum distances and even
46
+ // potentially Hausdorff distances.
47
+ //
48
+ // By using the appropriate options, this class can answer questions such as:
49
+ //
50
+ // - Find the minimum distance between two geometries A and B.
51
+ // - Find all edges of geometry A that are within a distance D of geometry B.
52
+ // - Find the k edges of geometry A that are closest to a given point P.
53
+ //
54
+ // You can also specify whether polygons should include their interiors (i.e.,
55
+ // if a point is contained by a polygon, should the distance be zero or should
56
+ // it be measured to the polygon boundary?)
57
+ //
58
+ // The input geometries may consist of any number of points, polylines, and
59
+ // polygons (collectively referred to as "shapes"). Shapes do not need to be
60
+ // disjoint; they may overlap or intersect arbitrarily. The implementation is
61
+ // designed to be fast for both simple and complex geometries.
62
+ //
63
+ // The Distance template argument is used to represent distances. Usually it
64
+ // is a thin wrapper around S1ChordAngle, but another distance type may be
65
+ // used as long as it implements the Distance concept described in
66
+ // s2distance_targets.h. For example this can be used to measure maximum
67
+ // distances, to get more accuracy, or to measure non-spheroidal distances.
68
+ template <class Distance>
69
+ class S2ClosestEdgeQueryBase {
70
+ public:
71
+ using Delta = typename Distance::Delta;
72
+
73
+ // Options that control the set of edges returned. Note that by default
74
+ // *all* edges are returned, so you will always want to set either the
75
+ // max_results() option or the max_distance() option (or both).
76
+ class Options {
77
+ public:
78
+ Options();
79
+
80
+ // Specifies that at most "max_results" edges should be returned.
81
+ //
82
+ // REQUIRES: max_results >= 1
83
+ // DEFAULT: kMaxMaxResults
84
+ int max_results() const;
85
+ void set_max_results(int max_results);
86
+ static constexpr int kMaxMaxResults = std::numeric_limits<int>::max();
87
+
88
+ // Specifies that only edges whose distance to the target is less than
89
+ // "max_distance" should be returned.
90
+ //
91
+ // Note that edges whose distance is exactly equal to "max_distance" are
92
+ // not returned. In most cases this doesn't matter (since distances are
93
+ // not computed exactly in the first place), but if such edges are needed
94
+ // then you can retrieve them by specifying "max_distance" as the next
95
+ // largest representable Distance. For example, if Distance is an
96
+ // S1ChordAngle then you can specify max_distance.Successor().
97
+ //
98
+ // DEFAULT: Distance::Infinity()
99
+ Distance max_distance() const;
100
+ void set_max_distance(Distance max_distance);
101
+
102
+ // Specifies that edges up to max_error() further away than the true
103
+ // closest edges may be substituted in the result set, as long as such
104
+ // edges satisfy all the remaining search criteria (such as max_distance).
105
+ // This option only has an effect if max_results() is also specified;
106
+ // otherwise all edges closer than max_distance() will always be returned.
107
+ //
108
+ // Note that this does not affect how the distance between edges is
109
+ // computed; it simply gives the algorithm permission to stop the search
110
+ // early as soon as the best possible improvement drops below max_error().
111
+ //
112
+ // This can be used to implement distance predicates efficiently. For
113
+ // example, to determine whether the minimum distance is less than D, set
114
+ // max_results() == 1 and max_distance() == max_error() == D. This causes
115
+ // the algorithm to terminate as soon as it finds any edge whose distance
116
+ // is less than D, rather than continuing to search for an edge that is
117
+ // even closer.
118
+ //
119
+ // DEFAULT: Distance::Delta::Zero()
120
+ Delta max_error() const;
121
+ void set_max_error(Delta max_error);
122
+
123
+ // Specifies that polygon interiors should be included when measuring
124
+ // distances. In other words, polygons that contain the target should
125
+ // have a distance of zero. (For targets consisting of multiple connected
126
+ // components, the distance is zero if any component is contained.) This
127
+ // is indicated in the results by returning a (shape_id, edge_id) pair
128
+ // with edge_id == -1, i.e. this value denotes the polygons's interior.
129
+ //
130
+ // Note that for efficiency, any polygon that intersects the target may or
131
+ // may not have an (edge_id == -1) result. Such results are optional
132
+ // because in that case the distance to the polygon is already zero.
133
+ //
134
+ // DEFAULT: true
135
+ bool include_interiors() const;
136
+ void set_include_interiors(bool include_interiors);
137
+
138
+ // Specifies that distances should be computed by examining every edge
139
+ // rather than using the S2ShapeIndex. This is useful for testing,
140
+ // benchmarking, and debugging.
141
+ //
142
+ // DEFAULT: false
143
+ bool use_brute_force() const;
144
+ void set_use_brute_force(bool use_brute_force);
145
+
146
+ private:
147
+ Distance max_distance_ = Distance::Infinity();
148
+ Delta max_error_ = Delta::Zero();
149
+ int max_results_ = kMaxMaxResults;
150
+ bool include_interiors_ = true;
151
+ bool use_brute_force_ = false;
152
+ };
153
+
154
+ // The Target class represents the geometry to which the distance is
155
+ // measured. For example, there can be subtypes for measuring the distance
156
+ // to a point, an edge, or to an S2ShapeIndex (an arbitrary collection of
157
+ // geometry).
158
+ //
159
+ // Implementations do *not* need to be thread-safe. They may cache data or
160
+ // allocate temporary data structures in order to improve performance.
161
+ using Target = S2DistanceTarget<Distance>;
162
+
163
+ // Each "Result" object represents a closest edge. Note the following
164
+ // special cases:
165
+ //
166
+ // - (shape_id() >= 0) && (edge_id() < 0) represents the interior of a shape.
167
+ // Such results may be returned when options.include_interiors() is true.
168
+ // Such results can be identified using the is_interior() method.
169
+ //
170
+ // - (shape_id() < 0) && (edge_id() < 0) is returned by `FindClosestEdge`
171
+ // to indicate that no edge satisfies the given query options. Such
172
+ // results can be identified using is_empty() method.
173
+ class Result {
174
+ public:
175
+ // The default constructor yields an empty result, with a distance() of
176
+ // Infinity() and shape_id == edge_id == -1.
177
+ Result() : distance_(Distance::Infinity()), shape_id_(-1), edge_id_(-1) {}
178
+
179
+ // Constructs a Result object for the given arguments.
180
+ Result(Distance distance, int32 shape_id, int32 edge_id)
181
+ : distance_(distance), shape_id_(shape_id), edge_id_(edge_id) {}
182
+
183
+ // The distance from the target to this edge.
184
+ Distance distance() const { return distance_; }
185
+
186
+ // Identifies an indexed shape.
187
+ int32 shape_id() const { return shape_id_; }
188
+
189
+ // Identifies an edge within the shape.
190
+ int32 edge_id() const { return edge_id_; }
191
+
192
+ // Returns true if this Result object represents the interior of a shape.
193
+ // (Such results may be returned when options.include_interiors() is true.)
194
+ bool is_interior() const { return shape_id_ >= 0 && edge_id_ < 0; }
195
+
196
+ // Returns true if this Result object indicates that no edge satisfies the
197
+ // given query options. (This result is only returned in one special
198
+ // case, namely when FindClosestEdge() does not find any suitable edges.
199
+ // It is never returned by methods that return a vector of results.)
200
+ bool is_empty() const { return shape_id_ < 0; }
201
+
202
+ // Returns true if two Result objects are identical.
203
+ friend bool operator==(const Result& x, const Result& y) {
204
+ return (x.distance_ == y.distance_ &&
205
+ x.shape_id_ == y.shape_id_ &&
206
+ x.edge_id_ == y.edge_id_);
207
+ }
208
+
209
+ // Compares edges first by distance, then by (shape_id, edge_id).
210
+ friend bool operator<(const Result& x, const Result& y) {
211
+ if (x.distance_ < y.distance_) return true;
212
+ if (y.distance_ < x.distance_) return false;
213
+ if (x.shape_id_ < y.shape_id_) return true;
214
+ if (y.shape_id_ < x.shape_id_) return false;
215
+ return x.edge_id_ < y.edge_id_;
216
+ }
217
+
218
+ // Indicates that linear rather than binary search should be used when this
219
+ // type is used as the key in gtl::btree data structures.
220
+ using goog_btree_prefer_linear_node_search = std::true_type;
221
+
222
+ private:
223
+ Distance distance_; // The distance from the target to this edge.
224
+ int32 shape_id_; // Identifies an indexed shape.
225
+ int32 edge_id_; // Identifies an edge within the shape.
226
+ };
227
+
228
+ // Default constructor; requires Init() to be called.
229
+ S2ClosestEdgeQueryBase();
230
+ ~S2ClosestEdgeQueryBase();
231
+
232
+ // Convenience constructor that calls Init().
233
+ explicit S2ClosestEdgeQueryBase(const S2ShapeIndex* index);
234
+
235
+ // S2ClosestEdgeQueryBase is not copyable.
236
+ S2ClosestEdgeQueryBase(const S2ClosestEdgeQueryBase&) = delete;
237
+ void operator=(const S2ClosestEdgeQueryBase&) = delete;
238
+
239
+ // Initializes the query.
240
+ // REQUIRES: ReInit() must be called if "index" is modified.
241
+ void Init(const S2ShapeIndex* index);
242
+
243
+ // Reinitializes the query. This method must be called whenever the
244
+ // underlying index is modified.
245
+ void ReInit();
246
+
247
+ // Returns a reference to the underlying S2ShapeIndex.
248
+ const S2ShapeIndex& index() const;
249
+
250
+ // Returns the closest edges to the given target that satisfy the given
251
+ // options. This method may be called multiple times.
252
+ //
253
+ // Note that if options().include_interiors() is true, the result vector may
254
+ // include some entries with edge_id == -1. This indicates that the target
255
+ // intersects the indexed polygon with the given shape_id.
256
+ std::vector<Result> FindClosestEdges(Target* target, const Options& options);
257
+
258
+ // This version can be more efficient when this method is called many times,
259
+ // since it does not require allocating a new vector on each call.
260
+ void FindClosestEdges(Target* target, const Options& options,
261
+ std::vector<Result>* results);
262
+
263
+ // Convenience method that returns exactly one edge. If no edges satisfy
264
+ // the given search criteria, then a Result with distance == Infinity() and
265
+ // shape_id == edge_id == -1 is returned.
266
+ //
267
+ // Note that if options.include_interiors() is true, edge_id == -1 is also
268
+ // used to indicate that the target intersects an indexed polygon (but in
269
+ // that case distance == Zero() and shape_id >= 0).
270
+ //
271
+ // REQUIRES: options.max_results() == 1
272
+ Result FindClosestEdge(Target* target, const Options& options);
273
+
274
+ private:
275
+ struct QueueEntry;
276
+
277
+ const Options& options() const { return *options_; }
278
+ void FindClosestEdgesInternal(Target* target, const Options& options);
279
+ void FindClosestEdgesBruteForce();
280
+ void FindClosestEdgesOptimized();
281
+ void InitQueue();
282
+ void InitCovering();
283
+ void AddInitialRange(const S2ShapeIndex::Iterator& first,
284
+ const S2ShapeIndex::Iterator& last);
285
+ void MaybeAddResult(const S2Shape& shape, int edge_id);
286
+ void AddResult(const Result& result);
287
+ void ProcessEdges(const QueueEntry& entry);
288
+ void ProcessOrEnqueue(S2CellId id);
289
+ void ProcessOrEnqueue(S2CellId id, const S2ShapeIndexCell* index_cell);
290
+
291
+ const S2ShapeIndex* index_;
292
+ const Options* options_;
293
+ Target* target_;
294
+
295
+ // True if max_error() must be subtracted from priority queue cell distances
296
+ // in order to ensure that such distances are measured conservatively. This
297
+ // is true only if the target takes advantage of max_error() in order to
298
+ // return faster results, and 0 < max_error() < distance_limit_.
299
+ bool use_conservative_cell_distance_;
300
+
301
+ // For the optimized algorihm we precompute the top-level S2CellIds that
302
+ // will be added to the priority queue. There can be at most 6 of these
303
+ // cells. Essentially this is just a covering of the indexed edges, except
304
+ // that we also store pointers to the corresponding S2ShapeIndexCells to
305
+ // reduce the number of index seeks required.
306
+ //
307
+ // The covering needs to be stored in a std::vector so that we can use
308
+ // S2CellUnion::GetIntersection().
309
+ std::vector<S2CellId> index_covering_;
310
+ absl::InlinedVector<const S2ShapeIndexCell*, 6> index_cells_;
311
+
312
+ // The decision about whether to use the brute force algorithm is based on
313
+ // counting the total number of edges in the index. However if the index
314
+ // contains a large number of shapes, this in itself might take too long.
315
+ // So instead we only count edges up to (max_brute_force_index_size() + 1)
316
+ // for the current target type (stored as index_num_edges_limit_).
317
+ int index_num_edges_;
318
+ int index_num_edges_limit_;
319
+
320
+ // The distance beyond which we can safely ignore further candidate edges.
321
+ // (Candidates that are exactly at the limit are ignored; this is more
322
+ // efficient for UpdateMinDistance() and should not affect clients since
323
+ // distance measurements have a small amount of error anyway.)
324
+ //
325
+ // Initially this is the same as the maximum distance specified by the user,
326
+ // but it can also be updated by the algorithm (see MaybeAddResult).
327
+ Distance distance_limit_;
328
+
329
+ // The current result set is stored in one of three ways:
330
+ //
331
+ // - If max_results() == 1, the best result is kept in result_singleton_.
332
+ //
333
+ // - If max_results() == "infinity", results are appended to result_vector_
334
+ // and sorted/uniqued at the end.
335
+ //
336
+ // - Otherwise results are kept in a btree_set so that we can progressively
337
+ // reduce the distance limit once max_results() results have been found.
338
+ // (A priority queue is not sufficient because we need to be able to
339
+ // check whether a candidate edge is already in the result set.)
340
+ //
341
+ // TODO(ericv): Check whether it would be faster to use avoid_duplicates_
342
+ // when result_set_ is used so that we could use a priority queue instead.
343
+ Result result_singleton_;
344
+ std::vector<Result> result_vector_;
345
+ gtl::btree_set<Result> result_set_;
346
+
347
+ // When the result edges are stored in a btree_set (see above), usually
348
+ // duplicates can be removed simply by inserting candidate edges in the
349
+ // current set. However this is not true if Options::max_error() > 0 and
350
+ // the Target subtype takes advantage of this by returning suboptimal
351
+ // distances. This is because when UpdateMinDistance() is called with
352
+ // different "min_dist" parameters (i.e., the distance to beat), the
353
+ // implementation may return a different distance for the same edge. Since
354
+ // the btree_set is keyed by (distance, shape_id, edge_id) this can create
355
+ // duplicate edges in the results.
356
+ //
357
+ // The flag below is true when duplicates must be avoided explicitly. This
358
+ // is achieved by maintaining a separate set keyed by (shape_id, edge_id)
359
+ // only, and checking whether each edge is in that set before computing the
360
+ // distance to it.
361
+ //
362
+ // TODO(ericv): Check whether it is faster to avoid duplicates by default
363
+ // (even when Options::max_results() == 1), rather than just when we need to.
364
+ bool avoid_duplicates_;
365
+ using ShapeEdgeId = s2shapeutil::ShapeEdgeId;
366
+ gtl::dense_hash_set<ShapeEdgeId, s2shapeutil::ShapeEdgeIdHash> tested_edges_;
367
+
368
+ // The algorithm maintains a priority queue of unprocessed S2CellIds, sorted
369
+ // in increasing order of distance from the target.
370
+ struct QueueEntry {
371
+ // A lower bound on the distance from the target to "id". This is the key
372
+ // of the priority queue.
373
+ Distance distance;
374
+
375
+ // The cell being queued.
376
+ S2CellId id;
377
+
378
+ // If "id" belongs to the index, this field stores the corresponding
379
+ // S2ShapeIndexCell. Otherwise "id" is a proper ancestor of one or more
380
+ // S2ShapeIndexCells and this field stores nullptr. The purpose of this
381
+ // field is to avoid an extra Seek() when the queue entry is processed.
382
+ const S2ShapeIndexCell* index_cell;
383
+
384
+ QueueEntry(Distance _distance, S2CellId _id,
385
+ const S2ShapeIndexCell* _index_cell)
386
+ : distance(_distance), id(_id), index_cell(_index_cell) {
387
+ }
388
+ bool operator<(const QueueEntry& other) const {
389
+ // The priority queue returns the largest elements first, so we want the
390
+ // "largest" entry to have the smallest distance.
391
+ return other.distance < distance;
392
+ }
393
+ };
394
+ using CellQueue =
395
+ std::priority_queue<QueueEntry, absl::InlinedVector<QueueEntry, 16>>;
396
+ CellQueue queue_;
397
+
398
+ // Temporaries, defined here to avoid multiple allocations / initializations.
399
+
400
+ S2ShapeIndex::Iterator iter_;
401
+ std::vector<S2CellId> max_distance_covering_;
402
+ std::vector<S2CellId> initial_cells_;
403
+ };
404
+
405
+
406
+ ////////////////// Implementation details follow ////////////////////
407
+
408
+
409
+ template <class Distance>
410
+ inline S2ClosestEdgeQueryBase<Distance>::Options::Options() {
411
+ }
412
+
413
+ template <class Distance>
414
+ inline int S2ClosestEdgeQueryBase<Distance>::Options::max_results() const {
415
+ return max_results_;
416
+ }
417
+
418
+ template <class Distance>
419
+ inline void S2ClosestEdgeQueryBase<Distance>::Options::set_max_results(
420
+ int max_results) {
421
+ S2_DCHECK_GE(max_results, 1);
422
+ max_results_ = max_results;
423
+ }
424
+
425
+ template <class Distance>
426
+ inline Distance S2ClosestEdgeQueryBase<Distance>::Options::max_distance()
427
+ const {
428
+ return max_distance_;
429
+ }
430
+
431
+ template <class Distance>
432
+ inline void S2ClosestEdgeQueryBase<Distance>::Options::set_max_distance(
433
+ Distance max_distance) {
434
+ max_distance_ = max_distance;
435
+ }
436
+
437
+ template <class Distance>
438
+ inline typename Distance::Delta
439
+ S2ClosestEdgeQueryBase<Distance>::Options::max_error() const {
440
+ return max_error_;
441
+ }
442
+
443
+ template <class Distance>
444
+ inline void S2ClosestEdgeQueryBase<Distance>::Options::set_max_error(
445
+ Delta max_error) {
446
+ max_error_ = max_error;
447
+ }
448
+
449
+ template <class Distance>
450
+ inline bool S2ClosestEdgeQueryBase<Distance>::Options::include_interiors()
451
+ const {
452
+ return include_interiors_;
453
+ }
454
+
455
+ template <class Distance>
456
+ inline void S2ClosestEdgeQueryBase<Distance>::Options::set_include_interiors(
457
+ bool include_interiors) {
458
+ include_interiors_ = include_interiors;
459
+ }
460
+
461
+ template <class Distance>
462
+ inline bool S2ClosestEdgeQueryBase<Distance>::Options::use_brute_force() const {
463
+ return use_brute_force_;
464
+ }
465
+
466
+ template <class Distance>
467
+ inline void S2ClosestEdgeQueryBase<Distance>::Options::set_use_brute_force(
468
+ bool use_brute_force) {
469
+ use_brute_force_ = use_brute_force;
470
+ }
471
+
472
+ template <class Distance>
473
+ S2ClosestEdgeQueryBase<Distance>::S2ClosestEdgeQueryBase()
474
+ : tested_edges_(1) /* expected_max_elements*/ {
475
+ tested_edges_.set_empty_key(ShapeEdgeId(-1, -1));
476
+ }
477
+
478
+ template <class Distance>
479
+ S2ClosestEdgeQueryBase<Distance>::~S2ClosestEdgeQueryBase() {
480
+ // Prevent inline destructor bloat by providing a definition.
481
+ }
482
+
483
+ template <class Distance>
484
+ inline S2ClosestEdgeQueryBase<Distance>::S2ClosestEdgeQueryBase(
485
+ const S2ShapeIndex* index) : S2ClosestEdgeQueryBase() {
486
+ Init(index);
487
+ }
488
+
489
+ template <class Distance>
490
+ void S2ClosestEdgeQueryBase<Distance>::Init(const S2ShapeIndex* index) {
491
+ index_ = index;
492
+ ReInit();
493
+ }
494
+
495
+ template <class Distance>
496
+ void S2ClosestEdgeQueryBase<Distance>::ReInit() {
497
+ index_num_edges_ = 0;
498
+ index_num_edges_limit_ = 0;
499
+ index_covering_.clear();
500
+ index_cells_.clear();
501
+ // We don't initialize iter_ here to make queries on small indexes a bit
502
+ // faster (i.e., where brute force is used).
503
+ }
504
+
505
+ template <class Distance>
506
+ inline const S2ShapeIndex& S2ClosestEdgeQueryBase<Distance>::index() const {
507
+ return *index_;
508
+ }
509
+
510
+ template <class Distance>
511
+ inline std::vector<typename S2ClosestEdgeQueryBase<Distance>::Result>
512
+ S2ClosestEdgeQueryBase<Distance>::FindClosestEdges(Target* target,
513
+ const Options& options) {
514
+ std::vector<Result> results;
515
+ FindClosestEdges(target, options, &results);
516
+ return results;
517
+ }
518
+
519
+ template <class Distance>
520
+ typename S2ClosestEdgeQueryBase<Distance>::Result
521
+ S2ClosestEdgeQueryBase<Distance>::FindClosestEdge(Target* target,
522
+ const Options& options) {
523
+ S2_DCHECK_EQ(options.max_results(), 1);
524
+ FindClosestEdgesInternal(target, options);
525
+ return result_singleton_;
526
+ }
527
+
528
+ template <class Distance>
529
+ void S2ClosestEdgeQueryBase<Distance>::FindClosestEdges(
530
+ Target* target, const Options& options,
531
+ std::vector<Result>* results) {
532
+ FindClosestEdgesInternal(target, options);
533
+ results->clear();
534
+ if (options.max_results() == 1) {
535
+ if (result_singleton_.shape_id() >= 0) {
536
+ results->push_back(result_singleton_);
537
+ }
538
+ } else if (options.max_results() == Options::kMaxMaxResults) {
539
+ std::sort(result_vector_.begin(), result_vector_.end());
540
+ std::unique_copy(result_vector_.begin(), result_vector_.end(),
541
+ std::back_inserter(*results));
542
+ result_vector_.clear();
543
+ } else {
544
+ results->assign(result_set_.begin(), result_set_.end());
545
+ result_set_.clear();
546
+ }
547
+ }
548
+
549
+ template <class Distance>
550
+ void S2ClosestEdgeQueryBase<Distance>::FindClosestEdgesInternal(
551
+ Target* target, const Options& options) {
552
+ target_ = target;
553
+ options_ = &options;
554
+
555
+ tested_edges_.clear();
556
+ distance_limit_ = options.max_distance();
557
+ result_singleton_ = Result();
558
+ S2_DCHECK(result_vector_.empty());
559
+ S2_DCHECK(result_set_.empty());
560
+ S2_DCHECK_GE(target->max_brute_force_index_size(), 0);
561
+ if (distance_limit_ == Distance::Zero()) return;
562
+
563
+ if (options.max_results() == Options::kMaxMaxResults &&
564
+ options.max_distance() == Distance::Infinity()) {
565
+ S2_LOG(WARNING) << "Returning all edges (max_results/max_distance not set)";
566
+ }
567
+
568
+ if (options.include_interiors()) {
569
+ gtl::btree_set<int32> shape_ids;
570
+ (void) target->VisitContainingShapes(
571
+ *index_, [&shape_ids, &options](S2Shape* containing_shape,
572
+ const S2Point& target_point) {
573
+ shape_ids.insert(containing_shape->id());
574
+ return shape_ids.size() < options.max_results();
575
+ });
576
+ for (int shape_id : shape_ids) {
577
+ AddResult(Result(Distance::Zero(), shape_id, -1));
578
+ }
579
+ if (distance_limit_ == Distance::Zero()) return;
580
+ }
581
+
582
+ // If max_error() > 0 and the target takes advantage of this, then we may
583
+ // need to adjust the distance estimates to the priority queue cells to
584
+ // ensure that they are always a lower bound on the true distance. For
585
+ // example, suppose max_distance == 100, max_error == 30, and we compute the
586
+ // distance to the target from some cell C0 as d(C0) == 80. Then because
587
+ // the target takes advantage of max_error(), the true distance could be as
588
+ // low as 50. In order not to miss edges contained by such cells, we need
589
+ // to subtract max_error() from the distance estimates. This behavior is
590
+ // controlled by the use_conservative_cell_distance_ flag.
591
+ //
592
+ // However there is one important case where this adjustment is not
593
+ // necessary, namely when max_distance() < max_error(). This is because
594
+ // max_error() only affects the algorithm once at least max_results() edges
595
+ // have been found that satisfy the given distance limit. At that point,
596
+ // max_error() is subtracted from distance_limit_ in order to ensure that
597
+ // any further matches are closer by at least that amount. But when
598
+ // max_distance() < max_error(), this reduces the distance limit to 0,
599
+ // i.e. all remaining candidate cells and edges can safely be discarded.
600
+ // (Note that this is how IsDistanceLess() and friends are implemented.)
601
+ //
602
+ // Note that Distance::Delta only supports operator==.
603
+ bool target_uses_max_error = (!(options.max_error() == Delta::Zero()) &&
604
+ target_->set_max_error(options.max_error()));
605
+
606
+ // Note that we can't compare max_error() and distance_limit_ directly
607
+ // because one is a Delta and one is a Distance. Instead we subtract them.
608
+ use_conservative_cell_distance_ = target_uses_max_error &&
609
+ (distance_limit_ == Distance::Infinity() ||
610
+ Distance::Zero() < distance_limit_ - options.max_error());
611
+
612
+ // Use the brute force algorithm if the index is small enough. To avoid
613
+ // spending too much time counting edges when there are many shapes, we stop
614
+ // counting once there are too many edges. We may need to recount the edges
615
+ // if we later see a target with a larger brute force edge threshold.
616
+ int min_optimized_edges = target_->max_brute_force_index_size() + 1;
617
+ if (min_optimized_edges > index_num_edges_limit_ &&
618
+ index_num_edges_ >= index_num_edges_limit_) {
619
+ index_num_edges_ = s2shapeutil::CountEdgesUpTo(*index_,
620
+ min_optimized_edges);
621
+ index_num_edges_limit_ = min_optimized_edges;
622
+ }
623
+
624
+ if (options.use_brute_force() || index_num_edges_ < min_optimized_edges) {
625
+ // The brute force algorithm considers each edge exactly once.
626
+ avoid_duplicates_ = false;
627
+ FindClosestEdgesBruteForce();
628
+ } else {
629
+ // If the target takes advantage of max_error() then we need to avoid
630
+ // duplicate edges explicitly. (Otherwise it happens automatically.)
631
+ avoid_duplicates_ = (target_uses_max_error && options.max_results() > 1);
632
+ FindClosestEdgesOptimized();
633
+ }
634
+ }
635
+
636
+ template <class Distance>
637
+ void S2ClosestEdgeQueryBase<Distance>::FindClosestEdgesBruteForce() {
638
+ for (S2Shape* shape : *index_) {
639
+ if (shape == nullptr) continue;
640
+ int num_edges = shape->num_edges();
641
+ for (int e = 0; e < num_edges; ++e) {
642
+ MaybeAddResult(*shape, e);
643
+ }
644
+ }
645
+ }
646
+
647
+ template <class Distance>
648
+ void S2ClosestEdgeQueryBase<Distance>::FindClosestEdgesOptimized() {
649
+ InitQueue();
650
+ // Repeatedly find the closest S2Cell to "target" and either split it into
651
+ // its four children or process all of its edges.
652
+ while (!queue_.empty()) {
653
+ // We need to copy the top entry before removing it, and we need to
654
+ // remove it before adding any new entries to the queue.
655
+ QueueEntry entry = queue_.top();
656
+ queue_.pop();
657
+ // Work around weird parse error in gcc 4.9 by using a local variable for
658
+ // entry.distance.
659
+ Distance distance = entry.distance;
660
+ if (!(distance < distance_limit_)) {
661
+ queue_ = CellQueue(); // Clear any remaining entries.
662
+ break;
663
+ }
664
+ // If this is already known to be an index cell, just process it.
665
+ if (entry.index_cell != nullptr) {
666
+ ProcessEdges(entry);
667
+ continue;
668
+ }
669
+ // Otherwise split the cell into its four children. Before adding a
670
+ // child back to the queue, we first check whether it is empty. We do
671
+ // this in two seek operations rather than four by seeking to the key
672
+ // between children 0 and 1 and to the key between children 2 and 3.
673
+ S2CellId id = entry.id;
674
+ iter_.Seek(id.child(1).range_min());
675
+ if (!iter_.done() && iter_.id() <= id.child(1).range_max()) {
676
+ ProcessOrEnqueue(id.child(1));
677
+ }
678
+ if (iter_.Prev() && iter_.id() >= id.range_min()) {
679
+ ProcessOrEnqueue(id.child(0));
680
+ }
681
+ iter_.Seek(id.child(3).range_min());
682
+ if (!iter_.done() && iter_.id() <= id.range_max()) {
683
+ ProcessOrEnqueue(id.child(3));
684
+ }
685
+ if (iter_.Prev() && iter_.id() >= id.child(2).range_min()) {
686
+ ProcessOrEnqueue(id.child(2));
687
+ }
688
+ }
689
+ }
690
+
691
+ template <class Distance>
692
+ void S2ClosestEdgeQueryBase<Distance>::InitQueue() {
693
+ S2_DCHECK(queue_.empty());
694
+ if (index_covering_.empty()) {
695
+ // We delay iterator initialization until now to make queries on very
696
+ // small indexes a bit faster (i.e., where brute force is used).
697
+ iter_.Init(index_, S2ShapeIndex::UNPOSITIONED);
698
+ }
699
+
700
+ // Optimization: if the user is searching for just the closest edge, and the
701
+ // center of the target's bounding cap happens to intersect an index cell,
702
+ // then we try to limit the search region to a small disc by first
703
+ // processing the edges in that cell. This sets distance_limit_ based on
704
+ // the closest edge in that cell, which we can then use to limit the search
705
+ // area. This means that the cell containing "target" will be processed
706
+ // twice, but in general this is still faster.
707
+ //
708
+ // TODO(ericv): Even if the cap center is not contained, we could still
709
+ // process one or both of the adjacent index cells in S2CellId order,
710
+ // provided that those cells are closer than distance_limit_.
711
+ S2Cap cap = target_->GetCapBound();
712
+ if (cap.is_empty()) return; // Empty target.
713
+ if (options().max_results() == 1 && iter_.Locate(cap.center())) {
714
+ ProcessEdges(QueueEntry(Distance::Zero(), iter_.id(), &iter_.cell()));
715
+ // Skip the rest of the algorithm if we found an intersecting edge.
716
+ if (distance_limit_ == Distance::Zero()) return;
717
+ }
718
+ if (index_covering_.empty()) InitCovering();
719
+ if (distance_limit_ == Distance::Infinity()) {
720
+ // Start with the precomputed index covering.
721
+ for (int i = 0; i < index_covering_.size(); ++i) {
722
+ ProcessOrEnqueue(index_covering_[i], index_cells_[i]);
723
+ }
724
+ } else {
725
+ // Compute a covering of the search disc and intersect it with the
726
+ // precomputed index covering.
727
+ S2RegionCoverer coverer;
728
+ coverer.mutable_options()->set_max_cells(4);
729
+ S1ChordAngle radius = cap.radius() + distance_limit_.GetChordAngleBound();
730
+ S2Cap search_cap(cap.center(), radius);
731
+ coverer.GetFastCovering(search_cap, &max_distance_covering_);
732
+ S2CellUnion::GetIntersection(index_covering_, max_distance_covering_,
733
+ &initial_cells_);
734
+
735
+ // Now we need to clean up the initial cells to ensure that they all
736
+ // contain at least one cell of the S2ShapeIndex. (Some may not intersect
737
+ // the index at all, while other may be descendants of an index cell.)
738
+ for (int i = 0, j = 0; i < initial_cells_.size(); ) {
739
+ S2CellId id_i = initial_cells_[i];
740
+ // Find the top-level cell that contains this initial cell.
741
+ while (index_covering_[j].range_max() < id_i) ++j;
742
+ S2CellId id_j = index_covering_[j];
743
+ if (id_i == id_j) {
744
+ // This initial cell is one of the top-level cells. Use the
745
+ // precomputed S2ShapeIndexCell pointer to avoid an index seek.
746
+ ProcessOrEnqueue(id_j, index_cells_[j]);
747
+ ++i, ++j;
748
+ } else {
749
+ // This initial cell is a proper descendant of a top-level cell.
750
+ // Check how it is related to the cells of the S2ShapeIndex.
751
+ S2ShapeIndex::CellRelation r = iter_.Locate(id_i);
752
+ if (r == S2ShapeIndex::INDEXED) {
753
+ // This cell is a descendant of an index cell. Enqueue it and skip
754
+ // any other initial cells that are also descendants of this cell.
755
+ ProcessOrEnqueue(iter_.id(), &iter_.cell());
756
+ const S2CellId last_id = iter_.id().range_max();
757
+ while (++i < initial_cells_.size() && initial_cells_[i] <= last_id)
758
+ continue;
759
+ } else {
760
+ // Enqueue the cell only if it contains at least one index cell.
761
+ if (r == S2ShapeIndex::SUBDIVIDED) ProcessOrEnqueue(id_i, nullptr);
762
+ ++i;
763
+ }
764
+ }
765
+ }
766
+ }
767
+ }
768
+
769
+ template <class Distance>
770
+ void S2ClosestEdgeQueryBase<Distance>::InitCovering() {
771
+ // Find the range of S2Cells spanned by the index and choose a level such
772
+ // that the entire index can be covered with just a few cells. These are
773
+ // the "top-level" cells. There are two cases:
774
+ //
775
+ // - If the index spans more than one face, then there is one top-level cell
776
+ // per spanned face, just big enough to cover the index cells on that face.
777
+ //
778
+ // - If the index spans only one face, then we find the smallest cell "C"
779
+ // that covers the index cells on that face (just like the case above).
780
+ // Then for each of the 4 children of "C", if the child contains any index
781
+ // cells then we create a top-level cell that is big enough to just fit
782
+ // those index cells (i.e., shrinking the child as much as possible to fit
783
+ // its contents). This essentially replicates what would happen if we
784
+ // started with "C" as the top-level cell, since "C" would immediately be
785
+ // split, except that we take the time to prune the children further since
786
+ // this will save work on every subsequent query.
787
+
788
+ // Don't need to reserve index_cells_ since it is an InlinedVector.
789
+ index_covering_.reserve(6);
790
+
791
+ // TODO(ericv): Use a single iterator (iter_) below and save position
792
+ // information using pair<S2CellId, const S2ShapeIndexCell*> type.
793
+ S2ShapeIndex::Iterator next(index_, S2ShapeIndex::BEGIN);
794
+ S2ShapeIndex::Iterator last(index_, S2ShapeIndex::END);
795
+ last.Prev();
796
+ if (next.id() != last.id()) {
797
+ // The index has at least two cells. Choose a level such that the entire
798
+ // index can be spanned with at most 6 cells (if the index spans multiple
799
+ // faces) or 4 cells (it the index spans a single face).
800
+ int level = next.id().GetCommonAncestorLevel(last.id()) + 1;
801
+
802
+ // Visit each potential top-level cell except the last (handled below).
803
+ S2CellId last_id = last.id().parent(level);
804
+ for (S2CellId id = next.id().parent(level); id != last_id; id = id.next()) {
805
+ // Skip any top-level cells that don't contain any index cells.
806
+ if (id.range_max() < next.id()) continue;
807
+
808
+ // Find the range of index cells contained by this top-level cell and
809
+ // then shrink the cell if necessary so that it just covers them.
810
+ S2ShapeIndex::Iterator cell_first = next;
811
+ next.Seek(id.range_max().next());
812
+ S2ShapeIndex::Iterator cell_last = next;
813
+ cell_last.Prev();
814
+ AddInitialRange(cell_first, cell_last);
815
+ }
816
+ }
817
+ AddInitialRange(next, last);
818
+ }
819
+
820
+ // Add an entry to index_covering_ and index_cells_ that covers the given
821
+ // inclusive range of cells.
822
+ //
823
+ // REQUIRES: "first" and "last" have a common ancestor.
824
+ template <class Distance>
825
+ void S2ClosestEdgeQueryBase<Distance>::AddInitialRange(
826
+ const S2ShapeIndex::Iterator& first,
827
+ const S2ShapeIndex::Iterator& last) {
828
+ if (first.id() == last.id()) {
829
+ // The range consists of a single index cell.
830
+ index_covering_.push_back(first.id());
831
+ index_cells_.push_back(&first.cell());
832
+ } else {
833
+ // Add the lowest common ancestor of the given range.
834
+ int level = first.id().GetCommonAncestorLevel(last.id());
835
+ S2_DCHECK_GE(level, 0);
836
+ index_covering_.push_back(first.id().parent(level));
837
+ index_cells_.push_back(nullptr);
838
+ }
839
+ }
840
+
841
+ template <class Distance>
842
+ void S2ClosestEdgeQueryBase<Distance>::MaybeAddResult(
843
+ const S2Shape& shape, int edge_id) {
844
+ if (avoid_duplicates_ &&
845
+ !tested_edges_.insert(ShapeEdgeId(shape.id(), edge_id)).second) {
846
+ return;
847
+ }
848
+ auto edge = shape.edge(edge_id);
849
+ Distance distance = distance_limit_;
850
+ if (target_->UpdateMinDistance(edge.v0, edge.v1, &distance)) {
851
+ AddResult(Result(distance, shape.id(), edge_id));
852
+ }
853
+ }
854
+
855
+ template <class Distance>
856
+ void S2ClosestEdgeQueryBase<Distance>::AddResult(const Result& result) {
857
+ if (options().max_results() == 1) {
858
+ // Optimization for the common case where only the closest edge is wanted.
859
+ result_singleton_ = result;
860
+ distance_limit_ = result.distance() - options().max_error();
861
+ } else if (options().max_results() == Options::kMaxMaxResults) {
862
+ result_vector_.push_back(result); // Sort/unique at end.
863
+ } else {
864
+ // Add this edge to result_set_. Note that even if we already have enough
865
+ // edges, we can't erase an element before insertion because the "new"
866
+ // edge might in fact be a duplicate.
867
+ result_set_.insert(result);
868
+ int size = result_set_.size();
869
+ if (size >= options().max_results()) {
870
+ if (size > options().max_results()) {
871
+ result_set_.erase(--result_set_.end());
872
+ }
873
+ distance_limit_ = (--result_set_.end())->distance() -
874
+ options().max_error();
875
+ }
876
+ }
877
+ }
878
+
879
+ // Return the number of edges in the given index cell.
880
+ inline static int CountEdges(const S2ShapeIndexCell* cell) {
881
+ int count = 0;
882
+ for (int s = 0; s < cell->num_clipped(); ++s) {
883
+ count += cell->clipped(s).num_edges();
884
+ }
885
+ return count;
886
+ }
887
+
888
+ // Process all the edges of the given index cell.
889
+ template <class Distance>
890
+ void S2ClosestEdgeQueryBase<Distance>::ProcessEdges(const QueueEntry& entry) {
891
+ const S2ShapeIndexCell* index_cell = entry.index_cell;
892
+ for (int s = 0; s < index_cell->num_clipped(); ++s) {
893
+ const S2ClippedShape& clipped = index_cell->clipped(s);
894
+ const S2Shape* shape = index_->shape(clipped.shape_id());
895
+ for (int j = 0; j < clipped.num_edges(); ++j) {
896
+ MaybeAddResult(*shape, clipped.edge(j));
897
+ }
898
+ }
899
+ }
900
+
901
+ // Enqueue the given cell id.
902
+ // REQUIRES: iter_ is positioned at a cell contained by "id".
903
+ template <class Distance>
904
+ inline void S2ClosestEdgeQueryBase<Distance>::ProcessOrEnqueue(
905
+ S2CellId id) {
906
+ S2_DCHECK(id.contains(iter_.id()));
907
+ if (iter_.id() == id) {
908
+ ProcessOrEnqueue(id, &iter_.cell());
909
+ } else {
910
+ ProcessOrEnqueue(id, nullptr);
911
+ }
912
+ }
913
+
914
+ // Add the given cell id to the queue. "index_cell" is the corresponding
915
+ // S2ShapeIndexCell, or nullptr if "id" is not an index cell.
916
+ //
917
+ // This version is called directly only by InitQueue().
918
+ template <class Distance>
919
+ void S2ClosestEdgeQueryBase<Distance>::ProcessOrEnqueue(
920
+ S2CellId id, const S2ShapeIndexCell* index_cell) {
921
+ if (index_cell) {
922
+ // If this index cell has only a few edges, then it is faster to check
923
+ // them directly rather than computing the minimum distance to the S2Cell
924
+ // and inserting it into the queue.
925
+ static const int kMinEdgesToEnqueue = 10;
926
+ int num_edges = CountEdges(index_cell);
927
+ if (num_edges == 0) return;
928
+ if (num_edges < kMinEdgesToEnqueue) {
929
+ // Set "distance" to zero to avoid the expense of computing it.
930
+ ProcessEdges(QueueEntry(Distance::Zero(), id, index_cell));
931
+ return;
932
+ }
933
+ }
934
+ // Otherwise compute the minimum distance to any point in the cell and add
935
+ // it to the priority queue.
936
+ S2Cell cell(id);
937
+ Distance distance = distance_limit_;
938
+ if (!target_->UpdateMinDistance(cell, &distance)) return;
939
+ if (use_conservative_cell_distance_) {
940
+ // Ensure that "distance" is a lower bound on the true distance to the cell.
941
+ distance = distance - options().max_error(); // operator-=() not defined.
942
+ }
943
+ queue_.push(QueueEntry(distance, id, index_cell));
944
+ }
945
+
946
+ #endif // S2_S2CLOSEST_EDGE_QUERY_BASE_H_