@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,716 @@
1
+ // Copyright 2016 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
+ // The bulk of this file consists of "tests" that attempt to construct worst
19
+ // cases for the various constants used in S2CellIdSnapFunction and
20
+ // IntLatLngSnapFunction implementations. For all of these constants I have
21
+ // done hand analysis of the planar configurations, but sometimes the
22
+ // spherical case is slightly better or worse because of the spherical
23
+ // distortion.
24
+
25
+ #include "s2/s2builderutil_snap_functions.h"
26
+
27
+ #include <algorithm>
28
+ #include <cinttypes>
29
+ #include <cmath>
30
+ #include <cstdint>
31
+ #include <cstdio>
32
+ #include <map>
33
+ #include <set>
34
+ #include <string>
35
+ #include <utility>
36
+ #include <vector>
37
+ #include "s2/base/integral_types.h"
38
+ #include "s2/base/logging.h"
39
+ #include <gtest/gtest.h>
40
+ #include "s2/r2.h"
41
+ #include "s2/s1angle.h"
42
+ #include "s2/s2cell.h"
43
+ #include "s2/s2cell_id.h"
44
+ #include "s2/s2edge_distances.h"
45
+ #include "s2/s2latlng.h"
46
+ #include "s2/s2measures.h"
47
+ #include "s2/s2metrics.h"
48
+ #include "s2/s2testing.h"
49
+ #include "s2/s2text_format.h"
50
+ #include "s2/util/math/mathutil.h"
51
+
52
+ using std::abs;
53
+ using std::fabs;
54
+ using std::make_pair;
55
+ using std::map;
56
+ using std::min;
57
+ using std::max;
58
+ using std::pair;
59
+ using std::set;
60
+ using std::vector;
61
+ using s2builderutil::S2CellIdSnapFunction;
62
+ using s2builderutil::IntLatLngSnapFunction;
63
+
64
+ TEST(S2CellIdSnapFunction, LevelToFromSnapRadius) {
65
+ for (int level = 0; level <= S2CellId::kMaxLevel; ++level) {
66
+ S1Angle radius = S2CellIdSnapFunction::MinSnapRadiusForLevel(level);
67
+ EXPECT_EQ(level, S2CellIdSnapFunction::LevelForMaxSnapRadius(radius));
68
+ EXPECT_EQ(min(level + 1, S2CellId::kMaxLevel),
69
+ S2CellIdSnapFunction::LevelForMaxSnapRadius(0.999 * radius));
70
+ }
71
+ EXPECT_EQ(0,
72
+ S2CellIdSnapFunction::LevelForMaxSnapRadius(
73
+ S1Angle::Radians(5)));
74
+ EXPECT_EQ(S2CellId::kMaxLevel,
75
+ S2CellIdSnapFunction::LevelForMaxSnapRadius(
76
+ S1Angle::Radians(1e-30)));
77
+ }
78
+
79
+ TEST(S2CellIdSnapFunction, SnapPoint) {
80
+ for (int iter = 0; iter < 1000; ++iter) {
81
+ for (int level = 0; level <= S2CellId::kMaxLevel; ++level) {
82
+ // This checks that points are snapped to the correct level, since
83
+ // S2CellId centers at different levels are always different.
84
+ S2CellIdSnapFunction f(level);
85
+ S2Point p = S2Testing::GetRandomCellId(level).ToPoint();
86
+ EXPECT_EQ(p, f.SnapPoint(p));
87
+ }
88
+ }
89
+ }
90
+
91
+ TEST(IntLatLngSnapFunction, ExponentToFromSnapRadius) {
92
+ for (int exponent = IntLatLngSnapFunction::kMinExponent;
93
+ exponent <= IntLatLngSnapFunction::kMaxExponent; ++exponent) {
94
+ S1Angle radius = IntLatLngSnapFunction::MinSnapRadiusForExponent(exponent);
95
+ EXPECT_EQ(exponent,
96
+ IntLatLngSnapFunction::ExponentForMaxSnapRadius(radius));
97
+ EXPECT_EQ(min(exponent + 1, IntLatLngSnapFunction::kMaxExponent),
98
+ IntLatLngSnapFunction::ExponentForMaxSnapRadius(0.999 * radius));
99
+ }
100
+ EXPECT_EQ(IntLatLngSnapFunction::kMinExponent,
101
+ IntLatLngSnapFunction::ExponentForMaxSnapRadius(
102
+ S1Angle::Radians(5)));
103
+ EXPECT_EQ(IntLatLngSnapFunction::kMaxExponent,
104
+ IntLatLngSnapFunction::ExponentForMaxSnapRadius(
105
+ S1Angle::Radians(1e-30)));
106
+ }
107
+
108
+ TEST(IntLatLngSnapFunction, SnapPoint) {
109
+ for (int iter = 0; iter < 1000; ++iter) {
110
+ // Test that IntLatLngSnapFunction does not modify points that were
111
+ // generated using the S2LatLng::From{E5,E6,E7} methods. This ensures
112
+ // that both functions are using bitwise-compatible conversion methods.
113
+ S2Point p = S2Testing::RandomPoint();
114
+ S2LatLng ll(p);
115
+ S2Point p5 = S2LatLng::FromE5(ll.lat().e5(), ll.lng().e5()).ToPoint();
116
+ EXPECT_EQ(p5, IntLatLngSnapFunction(5).SnapPoint(p5));
117
+ S2Point p6 = S2LatLng::FromE6(ll.lat().e6(), ll.lng().e6()).ToPoint();
118
+ EXPECT_EQ(p6, IntLatLngSnapFunction(6).SnapPoint(p6));
119
+ S2Point p7 = S2LatLng::FromE7(ll.lat().e7(), ll.lng().e7()).ToPoint();
120
+ EXPECT_EQ(p7, IntLatLngSnapFunction(7).SnapPoint(p7));
121
+
122
+ // Make sure that we're not snapping using some lower exponent.
123
+ S2Point p7not6 = S2LatLng::FromE7(10 * ll.lat().e6() + 1,
124
+ 10 * ll.lng().e6() + 1).ToPoint();
125
+ EXPECT_NE(p7not6, IntLatLngSnapFunction(6).SnapPoint(p7not6));
126
+ }
127
+ }
128
+
129
+ static S2CellId kSearchRootId = S2CellId::FromFace(0);
130
+ static S2CellId kSearchFocusId = S2CellId::FromFace(0).child(3);
131
+
132
+ static S1Angle GetMaxVertexDistance(const S2Point& p, S2CellId id) {
133
+ S2Cell cell(id);
134
+ return max(max(S1Angle(p, cell.GetVertex(0)),
135
+ S1Angle(p, cell.GetVertex(1))),
136
+ max(S1Angle(p, cell.GetVertex(2)),
137
+ S1Angle(p, cell.GetVertex(3))));
138
+ }
139
+
140
+ // Helper function that computes the vertex separation between "id0" and its
141
+ // neighbors.
142
+ static void UpdateS2CellIdMinVertexSeparation(
143
+ S2CellId id0, vector<pair<double, S2CellId>>* scores) {
144
+ S2Point site0 = id0.ToPoint();
145
+ vector<S2CellId> nbrs;
146
+ id0.AppendAllNeighbors(id0.level(), &nbrs);
147
+ for (S2CellId id1 : nbrs) {
148
+ S2Point site1 = id1.ToPoint();
149
+ S1Angle vertex_sep(site0, site1);
150
+ S1Angle max_snap_radius = GetMaxVertexDistance(site0, id1);
151
+ S2_DCHECK_GE(max_snap_radius,
152
+ S2CellIdSnapFunction::MinSnapRadiusForLevel(id0.level()));
153
+ double r = vertex_sep / max_snap_radius;
154
+ scores->push_back(make_pair(r, id0));
155
+ }
156
+ }
157
+
158
+ static double GetS2CellIdMinVertexSeparation(int level,
159
+ set<S2CellId>* best_cells) {
160
+ // The worst-case separation ratios always occur when the snap_radius is not
161
+ // much larger than the minimum, since this allows the site spacing to be
162
+ // reduced by as large a fraction as possible.
163
+ //
164
+ // For the minimum vertex separation ratio, we choose a site and one of its
165
+ // 8-way neighbors, then look at the ratio of the distance to the center of
166
+ // that neighbor to the distance to the furthest corner of that neighbor
167
+ // (which is the largest possible snap radius for this configuration).
168
+ vector<pair<double, S2CellId>> scores;
169
+ if (level == 0) {
170
+ UpdateS2CellIdMinVertexSeparation(kSearchRootId, &scores);
171
+ } else {
172
+ for (S2CellId parent : *best_cells) {
173
+ for (S2CellId id0 = parent.child_begin();
174
+ id0 != parent.child_end(); id0 = id0.next()) {
175
+ UpdateS2CellIdMinVertexSeparation(id0, &scores);
176
+ }
177
+ }
178
+ }
179
+ // Now sort the entries, print out the "num_to_print" best ones, and keep
180
+ // the best "num_to_keep" of them to seed the next round.
181
+ std::sort(scores.begin(), scores.end());
182
+ scores.erase(std::unique(scores.begin(), scores.end()), scores.end());
183
+ best_cells->clear();
184
+ int num_to_keep = 300;
185
+ int num_to_print = 1;
186
+ for (const auto& entry : scores) {
187
+ S2CellId id = entry.second;
188
+ if (--num_to_print >= 0) {
189
+ R2Point uv = id.GetCenterUV();
190
+ printf("Level %2d: min_vertex_sep_ratio = %.15f u=%.6f v=%.6f %s\n",
191
+ level, entry.first, uv[0], uv[1], id.ToToken().c_str());
192
+ }
193
+ if (kSearchFocusId.contains(id) || id.contains(kSearchFocusId)) {
194
+ if (best_cells->insert(id).second && --num_to_keep <= 0) break;
195
+ }
196
+ }
197
+ return scores[0].first;
198
+ }
199
+
200
+ TEST(S2CellIdSnapFunction, MinVertexSeparationSnapRadiusRatio) {
201
+ // The purpose of this "test" is to compute a lower bound to the fraction
202
+ // (min_vertex_separation() / snap_radius()). Essentially this involves
203
+ // searching for two adjacent cells A and B such when one of the corner
204
+ // vertices of B is snapped to the center of B, the distance to the center
205
+ // of A decreases as much as possible. In other words, we want the ratio
206
+ //
207
+ // distance(center(A), center(B)) / distance(center(A), vertex(B))
208
+ //
209
+ // to be as small as possible. We do this by considering one cell level at
210
+ // a time, and remembering the cells that had the lowest ratios. When we
211
+ // proceed from one level to the next, we consider all the children of those
212
+ // cells and keep the best ones.
213
+ //
214
+ // The reason we can restrict the search to children of cells at the
215
+ // previous level is that the ratio above is essentially a function of the
216
+ // local distortions created by projecting the S2 cube space onto the
217
+ // sphere. These distortions change smoothly over the sphere, so by keeping
218
+ // a fairly large number of candidates ("num_to_keep"), we are essentially
219
+ // keeping all the neighbors of the optimal cell as well.
220
+ double best_score = 1e10;
221
+ set<S2CellId> best_cells;
222
+ for (int level = 0; level <= S2CellId::kMaxLevel; ++level) {
223
+ double score = GetS2CellIdMinVertexSeparation(level, &best_cells);
224
+ best_score = min(best_score, score);
225
+ }
226
+ printf("min_vertex_sep / snap_radius ratio: %.15f\n", best_score);
227
+ }
228
+
229
+ static S1Angle GetCircumRadius(const S2Point& a, const S2Point& b,
230
+ const S2Point& c) {
231
+ // We return this value is the circumradius is very large.
232
+ S1Angle kTooBig = S1Angle::Radians(M_PI);
233
+ double turn_angle = S2::TurnAngle(a, b, c);
234
+ if (fabs(remainder(turn_angle, M_PI)) < 1e-2) return kTooBig;
235
+
236
+ long double a2 = (b - c).Norm2();
237
+ long double b2 = (c - a).Norm2();
238
+ long double c2 = (a - b).Norm2();
239
+ if (a2 > 2 || b2 > 2 || c2 > 2) return kTooBig;
240
+ long double ma = a2 * (b2 + c2 - a2);
241
+ long double mb = b2 * (c2 + a2 - b2);
242
+ long double mc = c2 * (a2 + b2 - c2);
243
+ S2Point p = (ma * a + mb * b + mc * c) / (ma + mb + mc);
244
+ return S1Angle(p, a);
245
+ }
246
+
247
+ static vector<S2CellId> GetNeighbors(S2CellId id) {
248
+ const int kNumLayers = 2;
249
+ vector<S2CellId> nbrs;
250
+ nbrs.push_back(id);
251
+ for (int layer = 0; layer < kNumLayers; ++layer) {
252
+ vector<S2CellId> new_nbrs;
253
+ for (S2CellId nbr : nbrs) {
254
+ nbr.AppendAllNeighbors(id.level(), &new_nbrs);
255
+ }
256
+ nbrs.insert(nbrs.end(), new_nbrs.begin(), new_nbrs.end());
257
+ nbrs.erase(std::remove(nbrs.begin(), nbrs.end(), id), nbrs.end());
258
+ std::sort(nbrs.begin(), nbrs.end());
259
+ nbrs.erase(std::unique(nbrs.begin(), nbrs.end()), nbrs.end());
260
+ }
261
+ return nbrs;
262
+ }
263
+
264
+ // S2CellIdMinEdgeSeparationFunction defines an objective function that will
265
+ // be optimized by GetS2CellIdMinEdgeSeparation() by finding worst-case
266
+ // configurations of S2CellIds. We use this to find the worst cases under
267
+ // various conditions (e.g., when the minimum snap radius at a given level is
268
+ // being used). The objective function is called for a specific configuration
269
+ // of vertices that are snapped at the given S2CellId level. "edge_sep" is
270
+ // the edge-vertex distance that is achieved by this configuration, and
271
+ // "min_snap_radius" and "max_snap_radius" are the minimum and maximum snap
272
+ // radii for which this configuration is valid (i.e., where the desired
273
+ // snapping will take place).
274
+ typedef double S2CellIdMinEdgeSeparationFunction(int level, S1Angle edge_sep,
275
+ S1Angle min_snap_radius,
276
+ S1Angle max_snap_radius);
277
+
278
+ // Returns the minimum value of the given objective function over sets of
279
+ // nearby vertices that are designed to minimize the edge-vertex separation
280
+ // when an edge is snapped.
281
+ static double GetS2CellIdMinEdgeSeparation(
282
+ const char* label, S2CellIdMinEdgeSeparationFunction objective,
283
+ int level, set<S2CellId>* best_cells) {
284
+ // To find minimum edge separations, we choose a cell ("id0") and two nearby
285
+ // cells ("id1" and "id2"), where "nearby" is defined by GetNeighbors().
286
+ // Let "site0", "site1", and "site2" be the centers of these cells. The
287
+ // idea is to consider an input edge E that intersects the Voronoi regions
288
+ // of "site1" and "site2" (and therefore snaps to an edge E' between these
289
+ // sites) but does not not intersect the Voronoi region of "site0" (and
290
+ // therefore can't be snapped to site0). The goal is to search for snapped
291
+ // edges E' that approach site0 as closely as possible.
292
+ //
293
+ // To do this, we first compute the circumradius of the three cell centers
294
+ // ("site0", "site1", and "site2"); this is the minimum snap radius in order
295
+ // for it to be possible to construct an edge E that snaps to "site1" and
296
+ // "site2" but not to "site0". We also compute the distance from "site0" to
297
+ // the snapped edge. Next we find the corner vertex of "id1" and "id2" that
298
+ // is furthest from "site0"; the smaller of these two distances is the
299
+ // maximum snap radius such that "site1" and "site2" can be chosen as
300
+ // sites after choosing "site0". If the maximum is less than the minimum,
301
+ // then this configuration is rejected; otherwise we evaluate the given
302
+ // objective function and keep the configurations that result in the
303
+ // smallest values.
304
+ //
305
+ // The optimization process works by keeping track of the set of S2CellIds
306
+ // that yielded the best results at the previous level, and exploring all
307
+ // the nearby neighbor combinations of the children of those cells at the
308
+ // next level. In order to get better coverage, we keep track of the best
309
+ // score and configuration (i.e. the two neighboring cells "id1" and "id2")
310
+ // for each initial cell "id0".
311
+ map<S2CellId, double> best_scores;
312
+ map<S2CellId, pair<S2CellId, S2CellId>> best_configs;
313
+ for (S2CellId parent : *best_cells) {
314
+ for (S2CellId id0 = parent.child_begin(level);
315
+ id0 != parent.child_end(level); id0 = id0.next()) {
316
+ S2Point site0 = id0.ToPoint();
317
+ vector<S2CellId> nbrs = GetNeighbors(id0);
318
+ for (S2CellId id1 : nbrs) {
319
+ S2Point site1 = id1.ToPoint();
320
+ S1Angle max_v1 = GetMaxVertexDistance(site0, id1);
321
+ for (S2CellId id2 : nbrs) {
322
+ if (id2 <= id1) continue;
323
+ S2Point site2 = id2.ToPoint();
324
+ S1Angle min_snap_radius = GetCircumRadius(site0, site1, site2);
325
+ if (min_snap_radius > S2Builder::SnapFunction::kMaxSnapRadius()) {
326
+ continue;
327
+ }
328
+ // Note that it is only the original points *before* snapping that
329
+ // need to be at least "snap_radius" away from "site0". The points
330
+ // after snapping ("site1" and "site2") may be closer.
331
+ S1Angle max_v2 = GetMaxVertexDistance(site0, id2);
332
+ S1Angle max_snap_radius = min(max_v1, max_v2);
333
+ if (min_snap_radius > max_snap_radius) continue;
334
+ S2_DCHECK_GE(max_snap_radius,
335
+ S2CellIdSnapFunction::MinSnapRadiusForLevel(level));
336
+
337
+ // This is a valid configuration, so evaluate it.
338
+ S1Angle edge_sep = S2::GetDistance(site0, site1, site2);
339
+ double score = objective(level, edge_sep,
340
+ min_snap_radius, max_snap_radius);
341
+ double& best_score = best_scores[id0];
342
+ if (best_score == 0 || best_score > score) {
343
+ best_score = score;
344
+ best_configs[id0] = make_pair(id1, id2);
345
+ }
346
+ }
347
+ }
348
+ }
349
+ }
350
+ // Now sort the entries, print out the "num_to_print" best ones, and
351
+ // generate a set of candidates for the next round by generating all the
352
+ // 8-way neighbors of the best candidates, and keeping up to"num_to_keep" of
353
+ // them. The results vary slightly according to how many candidates we
354
+ // keep, but the variations are much smaller than the conservative
355
+ // assumptions made by the S2CellIdSnapFunction implementation.
356
+ int num_to_keep = google::DEBUG_MODE ? 20 : 100;
357
+ int num_to_print = 3;
358
+ vector<pair<double, S2CellId>> sorted;
359
+ for (const auto& entry : best_scores) {
360
+ sorted.push_back(make_pair(entry.second, entry.first));
361
+ }
362
+ std::sort(sorted.begin(), sorted.end());
363
+ best_cells->clear();
364
+ printf("Level %d:\n", level);
365
+ for (const auto& entry : sorted) {
366
+ S2CellId id = entry.second;
367
+ if (--num_to_print >= 0) {
368
+ R2Point uv = id.GetCenterUV();
369
+ const pair<S2CellId, S2CellId>& nbrs = best_configs.find(id)->second;
370
+ printf(" %s = %.15f u=%7.4f v=%7.4f %s %s %s\n",
371
+ label, entry.first, uv[0], uv[1], id.ToToken().c_str(),
372
+ nbrs.first.ToToken().c_str(), nbrs.second.ToToken().c_str());
373
+ }
374
+ vector<S2CellId> nbrs(1, id);
375
+ id.AppendAllNeighbors(id.level(), &nbrs);
376
+ for (S2CellId nbr : nbrs) {
377
+ // The S2Cell hierarchy has many regions that are symmetrical. We can
378
+ // eliminate most of the "duplicates" by restricting the search to cells
379
+ // in kS2CellIdFocus.
380
+ if (kSearchFocusId.contains(nbr) || nbr.contains(kSearchFocusId)) {
381
+ if (best_cells->insert(nbr).second && --num_to_keep <= 0) {
382
+ return sorted[0].first;
383
+ }
384
+ }
385
+ }
386
+ }
387
+ return sorted[0].first;
388
+ }
389
+
390
+ static double GetS2CellIdMinEdgeSeparation(
391
+ const char* label, S2CellIdMinEdgeSeparationFunction objective) {
392
+ double best_score = 1e10;
393
+ set<S2CellId> best_cells;
394
+ best_cells.insert(kSearchRootId);
395
+ for (int level = 0; level <= S2CellId::kMaxLevel; ++level) {
396
+ double score = GetS2CellIdMinEdgeSeparation(label, objective, level,
397
+ &best_cells);
398
+ best_score = min(best_score, score);
399
+ }
400
+ return best_score;
401
+ }
402
+
403
+ TEST(S2CellIdSnapFunction, MinEdgeVertexSeparationForLevel) {
404
+ // Computes the minimum edge separation (as a fraction of kMinDiag) for any
405
+ // snap radius at each level.
406
+ double score = GetS2CellIdMinEdgeSeparation("min_sep_for_level",
407
+ [](int level, S1Angle edge_sep,
408
+ S1Angle min_snap_radius,
409
+ S1Angle max_snap_radius) {
410
+ return edge_sep.radians() / S2::kMinDiag.GetValue(level);
411
+ });
412
+ printf("min_edge_vertex_sep / kMinDiag ratio: %.15f\n", score);
413
+ }
414
+ TEST(S2CellIdSnapFunction, MinEdgeVertexSeparationAtMinSnapRadius) {
415
+ // Computes the minimum edge separation (as a fraction of kMinDiag) for the
416
+ // special case where the minimum snap radius is being used.
417
+ double score = GetS2CellIdMinEdgeSeparation("min_sep_at_min_radius",
418
+ [](int level, S1Angle edge_sep,
419
+ S1Angle min_snap_radius,
420
+ S1Angle max_snap_radius) {
421
+ double min_radius_at_level = S2::kMaxDiag.GetValue(level) / 2;
422
+ return (min_snap_radius.radians() <= (1 + 1e-10) * min_radius_at_level) ?
423
+ (edge_sep.radians() / S2::kMinDiag.GetValue(level)) : 100.0;
424
+ });
425
+ printf("min_edge_vertex_sep / kMinDiag at MinSnapRadiusForLevel: %.15f\n",
426
+ score);
427
+ }
428
+
429
+ TEST(S2CellIdSnapFunction, MinEdgeVertexSeparationSnapRadiusRatio) {
430
+ // Computes the minimum edge separation expressed as a fraction of the
431
+ // maximum snap radius that could yield that edge separation.
432
+ double score = GetS2CellIdMinEdgeSeparation("min_sep_snap_radius_ratio",
433
+ [](int level, S1Angle edge_sep,
434
+ S1Angle min_snap_radius,
435
+ S1Angle max_snap_radius) {
436
+ return edge_sep.radians() / max_snap_radius.radians();
437
+ });
438
+ printf("min_edge_vertex_sep / snap_radius ratio: %.15f\n", score);
439
+ }
440
+
441
+ // A scaled S2LatLng with integer coordinates, similar to E7 coordinates,
442
+ // except that the scale is variable (see LatLngConfig below).
443
+ using IntLatLng = Vector2<int64>;
444
+
445
+ static bool IsValid(const IntLatLng& ll, int64 scale) {
446
+ // A coordinate value of "scale" corresponds to 180 degrees.
447
+ return (abs(ll[0]) <= scale / 2 && abs(ll[1]) <= scale);
448
+ }
449
+
450
+ static bool HasValidVertices(const IntLatLng& ll, int64 scale) {
451
+ // Like IsValid, but excludes latitudes of 90 and longitudes of 180.
452
+ // A coordinate value of "scale" corresponds to 180 degrees.
453
+ return (abs(ll[0]) < scale / 2 && abs(ll[1]) < scale);
454
+ }
455
+
456
+ static IntLatLng Rescale(const IntLatLng&ll, double scale_factor) {
457
+ return IntLatLng(MathUtil::FastInt64Round(scale_factor * ll[0]),
458
+ MathUtil::FastInt64Round(scale_factor * ll[1]));
459
+ }
460
+
461
+ static S2Point ToPoint(const IntLatLng& ll, int64 scale) {
462
+ return S2LatLng::FromRadians(ll[0] * (M_PI / scale),
463
+ ll[1] * (M_PI / scale)).ToPoint();
464
+ }
465
+
466
+ static S2Point GetVertex(const IntLatLng& ll, int64 scale, int i) {
467
+ // Return the points in CCW order starting from the lower left.
468
+ int dlat = (i == 0 || i == 3) ? -1 : 1;
469
+ int dlng = (i == 0 || i == 1) ? -1 : 1;
470
+ return ToPoint(2 * ll + IntLatLng(dlat, dlng), 2 * scale);
471
+ }
472
+
473
+ static S1Angle GetMaxVertexDistance(const S2Point& p,
474
+ const IntLatLng& ll, int64 scale) {
475
+ return max(max(S1Angle(p, GetVertex(ll, scale, 0)),
476
+ S1Angle(p, GetVertex(ll, scale, 1))),
477
+ max(S1Angle(p, GetVertex(ll, scale, 2)),
478
+ S1Angle(p, GetVertex(ll, scale, 3))));
479
+ }
480
+
481
+ static double GetLatLngMinVertexSeparation(int64 old_scale, int64 scale,
482
+ set<IntLatLng>* best_configs) {
483
+ // The worst-case separation ratios always occur when the snap_radius is not
484
+ // much larger than the minimum, since this allows the site spacing to be
485
+ // reduced by as large a fraction as possible.
486
+ //
487
+ // For the minimum vertex separation ratio, we choose a site and one of its
488
+ // 8-way neighbors, then look at the ratio of the distance to the center of
489
+ // that neighbor to the distance to the furthest corner of that neighbor
490
+ // (which is the largest possible snap radius for this configuration).
491
+ S1Angle min_snap_radius_at_scale = S1Angle::Radians(M_SQRT1_2 * M_PI / scale);
492
+ vector<pair<double, IntLatLng>> scores;
493
+ double scale_factor = static_cast<double>(scale) / old_scale;
494
+ for (const IntLatLng& parent : *best_configs) {
495
+ IntLatLng new_parent = Rescale(parent, scale_factor);
496
+ for (int dlat0 = -7; dlat0 <= 7; ++dlat0) {
497
+ IntLatLng ll0 = new_parent + IntLatLng(dlat0, 0);
498
+ if (!IsValid(ll0, scale) || ll0[0] < 0) continue;
499
+ S2Point site0 = ToPoint(ll0, scale);
500
+ for (int dlat1 = 0; dlat1 <= 2; ++dlat1) {
501
+ for (int dlng1 = 0; dlng1 <= 5; ++dlng1) {
502
+ IntLatLng ll1 = ll0 + IntLatLng(dlat1, dlng1);
503
+ if (ll1 == ll0 || !HasValidVertices(ll1, scale)) continue;
504
+ S1Angle max_snap_radius = GetMaxVertexDistance(site0, ll1, scale);
505
+ if (max_snap_radius < min_snap_radius_at_scale) continue;
506
+ S2Point site1 = ToPoint(ll1, scale);
507
+ S1Angle vertex_sep(site0, site1);
508
+ double r = vertex_sep / max_snap_radius;
509
+ scores.push_back(make_pair(r, ll0));
510
+ }
511
+ }
512
+ }
513
+ }
514
+ // Now sort the entries, print out the "num_to_print" best ones, and keep
515
+ // the best "num_to_keep" of them to seed the next round.
516
+ std::sort(scores.begin(), scores.end());
517
+ scores.erase(std::unique(scores.begin(), scores.end()), scores.end());
518
+ best_configs->clear();
519
+ int num_to_keep = 100;
520
+ int num_to_print = 1;
521
+ for (const auto& entry : scores) {
522
+ if (--num_to_print >= 0) {
523
+ printf("Scale %14" PRId64 ": min_vertex_sep_ratio = %.15f, %s\n",
524
+ int64_t{scale}, entry.first,
525
+ s2textformat::ToString(ToPoint(entry.second, scale)).c_str());
526
+ }
527
+ if (best_configs->insert(entry.second).second && --num_to_keep <= 0) break;
528
+ }
529
+ return scores[0].first;
530
+ }
531
+
532
+ TEST(IntLatLngSnapFunction, MinVertexSeparationSnapRadiusRatio) {
533
+ double best_score = 1e10;
534
+ set<IntLatLng> best_configs;
535
+ int64 scale = 18;
536
+ for (int lat0 = 0; lat0 <= 9; ++lat0) {
537
+ best_configs.insert(IntLatLng(lat0, 0));
538
+ }
539
+ for (int exp = 0; exp <= 10; ++exp, scale *= 10) {
540
+ double score = GetLatLngMinVertexSeparation(scale, 10 * scale,
541
+ &best_configs);
542
+ best_score = min(best_score, score);
543
+ }
544
+ printf("min_vertex_sep / snap_radius ratio: %.15f\n", best_score);
545
+ }
546
+
547
+ // A triple of scaled S2LatLng coordinates. The coordinates are multiplied by
548
+ // (M_PI / scale) to convert them to radians.
549
+ struct LatLngConfig {
550
+ int64 scale;
551
+ IntLatLng ll0, ll1, ll2;
552
+
553
+ LatLngConfig(int64 _scale, const IntLatLng& _ll0,
554
+ const IntLatLng& _ll1, const IntLatLng& _ll2) :
555
+ scale(_scale), ll0(_ll0), ll1(_ll1), ll2(_ll2) {
556
+ }
557
+ bool operator<(const LatLngConfig& other) const {
558
+ S2_DCHECK_EQ(scale, other.scale);
559
+ return (make_pair(ll0, make_pair(ll1, ll2)) <
560
+ make_pair(other.ll0, make_pair(other.ll1, other.ll2)));
561
+ }
562
+ bool operator==(const LatLngConfig& other) const {
563
+ return (ll0 == other.ll0 && ll1 == other.ll1 && ll2 == other.ll2);
564
+ }
565
+ };
566
+
567
+ typedef double LatLngMinEdgeSeparationFunction(int64 scale, S1Angle edge_sep,
568
+ S1Angle max_snap_radius);
569
+
570
+ static double GetLatLngMinEdgeSeparation(
571
+ const char* label, LatLngMinEdgeSeparationFunction objective,
572
+ int64 scale, vector<LatLngConfig>* best_configs) {
573
+ S1Angle min_snap_radius_at_scale = S1Angle::Radians(M_SQRT1_2 * M_PI / scale);
574
+ vector<pair<double, LatLngConfig>> scores;
575
+ for (LatLngConfig parent : *best_configs) {
576
+ // To reduce duplicates, we require that site0 always has longitude 0.
577
+ S2_DCHECK_EQ(0, parent.ll0[1]);
578
+ double scale_factor = static_cast<double>(scale) / parent.scale;
579
+ parent.ll0 = Rescale(parent.ll0, scale_factor);
580
+ parent.ll1 = Rescale(parent.ll1, scale_factor);
581
+ parent.ll2 = Rescale(parent.ll2, scale_factor);
582
+ for (int dlat0 = -1; dlat0 <= 1; ++dlat0) {
583
+ IntLatLng ll0 = parent.ll0 + IntLatLng(dlat0, 0);
584
+ // To reduce duplicates, we require that site0.latitude >= 0.
585
+ if (!IsValid(ll0, scale) || ll0[0] < 0) continue;
586
+ S2Point site0 = ToPoint(ll0, scale);
587
+ for (int dlat1 = -1; dlat1 <= 1; ++dlat1) {
588
+ for (int dlng1 = -2; dlng1 <= 2; ++dlng1) {
589
+ IntLatLng ll1 = parent.ll1 + IntLatLng(dlat0 + dlat1, dlng1);
590
+ if (ll1 == ll0 || !HasValidVertices(ll1, scale)) continue;
591
+ // Only consider neighbors within 2 latitude units of site0.
592
+ if (abs(ll1[0] - ll0[0]) > 2) continue;
593
+
594
+ S2Point site1 = ToPoint(ll1, scale);
595
+ S1Angle max_v1 = GetMaxVertexDistance(site0, ll1, scale);
596
+ for (int dlat2 = -1; dlat2 <= 1; ++dlat2) {
597
+ for (int dlng2 = -2; dlng2 <= 2; ++dlng2) {
598
+ IntLatLng ll2 = parent.ll2 + IntLatLng(dlat0 + dlat2, dlng2);
599
+ if (!HasValidVertices(ll2, scale)) continue;
600
+ // Only consider neighbors within 2 latitude units of site0.
601
+ if (abs(ll2[0] - ll0[0]) > 2) continue;
602
+ // To reduce duplicates, we require ll1 < ll2 lexicographically
603
+ // and site2.longitude >= 0. (It's *not* okay to
604
+ // require site1.longitude >= 0, because then some configurations
605
+ // with site1.latitude == site2.latitude would be missed.)
606
+ if (ll2 <= ll1 || ll2[1] < 0) continue;
607
+
608
+ S2Point site2 = ToPoint(ll2, scale);
609
+ S1Angle min_snap_radius = GetCircumRadius(site0, site1, site2);
610
+ if (min_snap_radius > S2Builder::SnapFunction::kMaxSnapRadius()) {
611
+ continue;
612
+ }
613
+ // Only the original points *before* snapping that need to be at
614
+ // least "snap_radius" away from "site0". The points after
615
+ // snapping ("site1" and "site2") may be closer.
616
+ S1Angle max_v2 = GetMaxVertexDistance(site0, ll2, scale);
617
+ S1Angle max_snap_radius = min(max_v1, max_v2);
618
+ if (min_snap_radius > max_snap_radius) continue;
619
+ if (max_snap_radius < min_snap_radius_at_scale) continue;
620
+
621
+ // This is a valid configuration, so evaluate it.
622
+ S1Angle edge_sep = S2::GetDistance(site0, site1, site2);
623
+ double score = objective(scale, edge_sep, max_snap_radius);
624
+ LatLngConfig config(scale, ll0, ll1, ll2);
625
+ scores.push_back(make_pair(score, config));
626
+ }
627
+ }
628
+ }
629
+ }
630
+ }
631
+ }
632
+ // Now sort the entries, print out the "num_to_print" best ones, and keep
633
+ // the best "num_to_keep" of them to seed the next round.
634
+ std::sort(scores.begin(), scores.end());
635
+ scores.erase(std::unique(scores.begin(), scores.end()), scores.end());
636
+ best_configs->clear();
637
+ int num_to_keep = google::DEBUG_MODE ? 50 : 200;
638
+ int num_to_print = 3;
639
+ printf("Scale %" PRId64 ":\n", int64_t{scale});
640
+ for (const auto& entry : scores) {
641
+ const LatLngConfig& config = entry.second;
642
+ int64 scale = config.scale;
643
+ if (--num_to_print >= 0) {
644
+ printf(" %s = %.15f %s %s %s\n",
645
+ label, entry.first,
646
+ s2textformat::ToString(ToPoint(config.ll0, scale)).c_str(),
647
+ s2textformat::ToString(ToPoint(config.ll1, scale)).c_str(),
648
+ s2textformat::ToString(ToPoint(config.ll2, scale)).c_str());
649
+ }
650
+ // Optional: filter the candidates to concentrate on a specific region
651
+ // (e.g., the north pole).
652
+ best_configs->push_back(config);
653
+ if (--num_to_keep <= 0) break;
654
+ }
655
+ return scores[0].first;
656
+ }
657
+
658
+ static double GetLatLngMinEdgeSeparation(
659
+ const char* label, LatLngMinEdgeSeparationFunction objective) {
660
+ double best_score = 1e10;
661
+ vector<LatLngConfig> best_configs;
662
+ int64 scale = 6; // Initially points are 30 degrees apart.
663
+ int max_lng = scale;
664
+ int max_lat = scale / 2;
665
+ for (int lat0 = 0; lat0 <= max_lat; ++lat0) {
666
+ for (int lat1 = lat0 - 2; lat1 <= min(max_lat, lat0 + 2); ++lat1) {
667
+ for (int lng1 = 0; lng1 <= max_lng; ++lng1) {
668
+ for (int lat2 = lat1; lat2 <= min(max_lat, lat0 + 2); ++lat2) {
669
+ for (int lng2 = 0; lng2 <= max_lng; ++lng2) {
670
+ IntLatLng ll0(lat0, 0);
671
+ IntLatLng ll1(lat1, lng1);
672
+ IntLatLng ll2(lat2, lng2);
673
+ if (ll2 <= ll1) continue;
674
+ best_configs.push_back(LatLngConfig(scale, ll0, ll1, ll2));
675
+ }
676
+ }
677
+ }
678
+ }
679
+ }
680
+ S2_LOG(INFO) << "Starting with " << best_configs.size() << " configurations";
681
+ int64 target_scale = 180;
682
+ for (int exp = 0; exp <= 10; ++exp, target_scale *= 10) {
683
+ while (scale < target_scale) {
684
+ scale = min(static_cast<int64>(1.8 * scale), target_scale);
685
+ double score = GetLatLngMinEdgeSeparation(label, objective, scale,
686
+ &best_configs);
687
+ if (scale == target_scale) {
688
+ best_score = min(best_score, score);
689
+ }
690
+ }
691
+ }
692
+ return best_score;
693
+ }
694
+
695
+ TEST(IntLatLngSnapFunction, MinEdgeVertexSeparationForLevel) {
696
+ // Computes the minimum edge separation (as a fraction of kMinDiag) for any
697
+ // snap radius at each level.
698
+ double score = GetLatLngMinEdgeSeparation("min_sep_for_level",
699
+ [](int64 scale, S1Angle edge_sep,
700
+ S1Angle max_snap_radius) {
701
+ double e_unit = M_PI / scale;
702
+ return edge_sep.radians() / e_unit;
703
+ });
704
+ printf("min_edge_vertex_sep / e_unit ratio: %.15f\n", score);
705
+ }
706
+
707
+ TEST(IntLatLngSnapFunction, MinEdgeVertexSeparationSnapRadiusRatio) {
708
+ // Computes the minimum edge separation expressed as a fraction of the
709
+ // maximum snap radius that could yield that edge separation.
710
+ double score = GetLatLngMinEdgeSeparation("min_sep_snap_radius_ratio",
711
+ [](int64 scale, S1Angle edge_sep,
712
+ S1Angle max_snap_radius) {
713
+ return edge_sep.radians() / max_snap_radius.radians();
714
+ });
715
+ printf("min_edge_vertex_sep / snap_radius ratio: %.15f\n", score);
716
+ }