@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,1486 @@
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
+ #include "s2/s2predicates.h"
19
+ #include "s2/s2predicates_internal.h"
20
+
21
+ #include <algorithm>
22
+ #include <cfloat>
23
+ #include <cmath>
24
+ #include <ostream>
25
+ #include "s2/s1chord_angle.h"
26
+ #include "s2/util/math/exactfloat/exactfloat.h"
27
+ #include "s2/util/math/vector.h"
28
+
29
+ using std::fabs;
30
+ using std::max;
31
+ using std::min;
32
+ using std::sqrt;
33
+
34
+ namespace s2pred {
35
+
36
+ // All error bounds in this file are expressed in terms of the maximum
37
+ // rounding error for a floating-point type. The rounding error is half of
38
+ // the numeric_limits<T>::epsilon() value.
39
+ constexpr double DBL_ERR = rounding_epsilon<double>();
40
+ constexpr long double LD_ERR = rounding_epsilon<long double>();
41
+
42
+ // A predefined S1ChordAngle representing (approximately) 45 degrees.
43
+ static const S1ChordAngle k45Degrees = S1ChordAngle::FromLength2(2 - M_SQRT2);
44
+
45
+ int Sign(const S2Point& a, const S2Point& b, const S2Point& c) {
46
+ // We don't need RobustCrossProd() here because Sign() does its own
47
+ // error estimation and calls ExpensiveSign() if there is any uncertainty
48
+ // about the result.
49
+ return Sign(a, b, c, a.CrossProd(b));
50
+ }
51
+
52
+ // Compute the determinant in a numerically stable way. Unlike TriageSign(),
53
+ // this method can usually compute the correct determinant sign even when all
54
+ // three points are as collinear as possible. For example if three points are
55
+ // spaced 1km apart along a random line on the Earth's surface using the
56
+ // nearest representable points, there is only a 0.4% chance that this method
57
+ // will not be able to find the determinant sign. The probability of failure
58
+ // decreases as the points get closer together; if the collinear points are
59
+ // 1 meter apart, the failure rate drops to 0.0004%.
60
+ //
61
+ // This method could be extended to also handle nearly-antipodal points (and
62
+ // in fact an earlier version of this code did exactly that), but antipodal
63
+ // points are rare in practice so it seems better to simply fall back to
64
+ // exact arithmetic in that case.
65
+ int StableSign(const S2Point& a, const S2Point& b, const S2Point& c) {
66
+ Vector3_d ab = b - a;
67
+ Vector3_d bc = c - b;
68
+ Vector3_d ca = a - c;
69
+ double ab2 = ab.Norm2();
70
+ double bc2 = bc.Norm2();
71
+ double ca2 = ca.Norm2();
72
+
73
+ // Now compute the determinant ((A-C)x(B-C)).C, where the vertices have been
74
+ // cyclically permuted if necessary so that AB is the longest edge. (This
75
+ // minimizes the magnitude of cross product.) At the same time we also
76
+ // compute the maximum error in the determinant. Using a similar technique
77
+ // to the one used for kMaxDetError, the error is at most
78
+ //
79
+ // |d| <= (3 + 6/sqrt(3)) * |A-C| * |B-C| * e
80
+ //
81
+ // where e = 0.5 * DBL_EPSILON. If the determinant magnitude is larger than
82
+ // this value then we know its sign with certainty.
83
+ const double kDetErrorMultiplier = 3.2321 * DBL_EPSILON; // see above
84
+ double det, max_error;
85
+ if (ab2 >= bc2 && ab2 >= ca2) {
86
+ // AB is the longest edge, so compute (A-C)x(B-C).C.
87
+ det = -(ca.CrossProd(bc).DotProd(c));
88
+ max_error = kDetErrorMultiplier * sqrt(ca2 * bc2);
89
+ } else if (bc2 >= ca2) {
90
+ // BC is the longest edge, so compute (B-A)x(C-A).A.
91
+ det = -(ab.CrossProd(ca).DotProd(a));
92
+ max_error = kDetErrorMultiplier * sqrt(ab2 * ca2);
93
+ } else {
94
+ // CA is the longest edge, so compute (C-B)x(A-B).B.
95
+ det = -(bc.CrossProd(ab).DotProd(b));
96
+ max_error = kDetErrorMultiplier * sqrt(bc2 * ab2);
97
+ }
98
+ return (fabs(det) <= max_error) ? 0 : (det > 0) ? 1 : -1;
99
+ }
100
+
101
+ // The following function returns the sign of the determinant of three points
102
+ // A, B, C under a model where every possible S2Point is slightly perturbed by
103
+ // a unique infinitesmal amount such that no three perturbed points are
104
+ // collinear and no four points are coplanar. The perturbations are so small
105
+ // that they do not change the sign of any determinant that was non-zero
106
+ // before the perturbations, and therefore can be safely ignored unless the
107
+ // determinant of three points is exactly zero (using multiple-precision
108
+ // arithmetic).
109
+ //
110
+ // Since the symbolic perturbation of a given point is fixed (i.e., the
111
+ // perturbation is the same for all calls to this method and does not depend
112
+ // on the other two arguments), the results of this method are always
113
+ // self-consistent. It will never return results that would correspond to an
114
+ // "impossible" configuration of non-degenerate points.
115
+ //
116
+ // Requirements:
117
+ // The 3x3 determinant of A, B, C must be exactly zero.
118
+ // The points must be distinct, with A < B < C in lexicographic order.
119
+ //
120
+ // Returns:
121
+ // +1 or -1 according to the sign of the determinant after the symbolic
122
+ // perturbations are taken into account.
123
+ //
124
+ // Reference:
125
+ // "Simulation of Simplicity" (Edelsbrunner and Muecke, ACM Transactions on
126
+ // Graphics, 1990).
127
+ //
128
+ int SymbolicallyPerturbedSign(
129
+ const Vector3_xf& a, const Vector3_xf& b,
130
+ const Vector3_xf& c, const Vector3_xf& b_cross_c) {
131
+ // This method requires that the points are sorted in lexicographically
132
+ // increasing order. This is because every possible S2Point has its own
133
+ // symbolic perturbation such that if A < B then the symbolic perturbation
134
+ // for A is much larger than the perturbation for B.
135
+ //
136
+ // Alternatively, we could sort the points in this method and keep track of
137
+ // the sign of the permutation, but it is more efficient to do this before
138
+ // converting the inputs to the multi-precision representation, and this
139
+ // also lets us re-use the result of the cross product B x C.
140
+ S2_DCHECK(a < b && b < c);
141
+
142
+ // Every input coordinate x[i] is assigned a symbolic perturbation dx[i].
143
+ // We then compute the sign of the determinant of the perturbed points,
144
+ // i.e.
145
+ // | a[0]+da[0] a[1]+da[1] a[2]+da[2] |
146
+ // | b[0]+db[0] b[1]+db[1] b[2]+db[2] |
147
+ // | c[0]+dc[0] c[1]+dc[1] c[2]+dc[2] |
148
+ //
149
+ // The perturbations are chosen such that
150
+ //
151
+ // da[2] > da[1] > da[0] > db[2] > db[1] > db[0] > dc[2] > dc[1] > dc[0]
152
+ //
153
+ // where each perturbation is so much smaller than the previous one that we
154
+ // don't even need to consider it unless the coefficients of all previous
155
+ // perturbations are zero. In fact, it is so small that we don't need to
156
+ // consider it unless the coefficient of all products of the previous
157
+ // perturbations are zero. For example, we don't need to consider the
158
+ // coefficient of db[1] unless the coefficient of db[2]*da[0] is zero.
159
+ //
160
+ // The follow code simply enumerates the coefficients of the perturbations
161
+ // (and products of perturbations) that appear in the determinant above, in
162
+ // order of decreasing perturbation magnitude. The first non-zero
163
+ // coefficient determines the sign of the result. The easiest way to
164
+ // enumerate the coefficients in the correct order is to pretend that each
165
+ // perturbation is some tiny value "eps" raised to a power of two:
166
+ //
167
+ // eps** 1 2 4 8 16 32 64 128 256
168
+ // da[2] da[1] da[0] db[2] db[1] db[0] dc[2] dc[1] dc[0]
169
+ //
170
+ // Essentially we can then just count in binary and test the corresponding
171
+ // subset of perturbations at each step. So for example, we must test the
172
+ // coefficient of db[2]*da[0] before db[1] because eps**12 > eps**16.
173
+ //
174
+ // Of course, not all products of these perturbations appear in the
175
+ // determinant above, since the determinant only contains the products of
176
+ // elements in distinct rows and columns. Thus we don't need to consider
177
+ // da[2]*da[1], db[1]*da[1], etc. Furthermore, sometimes different pairs of
178
+ // perturbations have the same coefficient in the determinant; for example,
179
+ // da[1]*db[0] and db[1]*da[0] have the same coefficient (c[2]). Therefore
180
+ // we only need to test this coefficient the first time we encounter it in
181
+ // the binary order above (which will be db[1]*da[0]).
182
+ //
183
+ // The sequence of tests below also appears in Table 4-ii of the paper
184
+ // referenced above, if you just want to look it up, with the following
185
+ // translations: [a,b,c] -> [i,j,k] and [0,1,2] -> [1,2,3]. Also note that
186
+ // some of the signs are different because the opposite cross product is
187
+ // used (e.g., B x C rather than C x B).
188
+
189
+ int det_sign = b_cross_c[2].sgn(); // da[2]
190
+ if (det_sign != 0) return det_sign;
191
+ det_sign = b_cross_c[1].sgn(); // da[1]
192
+ if (det_sign != 0) return det_sign;
193
+ det_sign = b_cross_c[0].sgn(); // da[0]
194
+ if (det_sign != 0) return det_sign;
195
+
196
+ det_sign = (c[0]*a[1] - c[1]*a[0]).sgn(); // db[2]
197
+ if (det_sign != 0) return det_sign;
198
+ det_sign = c[0].sgn(); // db[2] * da[1]
199
+ if (det_sign != 0) return det_sign;
200
+ det_sign = -(c[1].sgn()); // db[2] * da[0]
201
+ if (det_sign != 0) return det_sign;
202
+ det_sign = (c[2]*a[0] - c[0]*a[2]).sgn(); // db[1]
203
+ if (det_sign != 0) return det_sign;
204
+ det_sign = c[2].sgn(); // db[1] * da[0]
205
+ if (det_sign != 0) return det_sign;
206
+ // The following test is listed in the paper, but it is redundant because
207
+ // the previous tests guarantee that C == (0, 0, 0).
208
+ S2_DCHECK_EQ(0, (c[1]*a[2] - c[2]*a[1]).sgn()); // db[0]
209
+
210
+ det_sign = (a[0]*b[1] - a[1]*b[0]).sgn(); // dc[2]
211
+ if (det_sign != 0) return det_sign;
212
+ det_sign = -(b[0].sgn()); // dc[2] * da[1]
213
+ if (det_sign != 0) return det_sign;
214
+ det_sign = b[1].sgn(); // dc[2] * da[0]
215
+ if (det_sign != 0) return det_sign;
216
+ det_sign = a[0].sgn(); // dc[2] * db[1]
217
+ if (det_sign != 0) return det_sign;
218
+ return 1; // dc[2] * db[1] * da[0]
219
+ }
220
+
221
+ // Compute the determinant using exact arithmetic and/or symbolic
222
+ // permutations. Requires that the three points are distinct.
223
+ int ExactSign(const S2Point& a, const S2Point& b, const S2Point& c,
224
+ bool perturb) {
225
+ S2_DCHECK(a != b && b != c && c != a);
226
+
227
+ // Sort the three points in lexicographic order, keeping track of the sign
228
+ // of the permutation. (Each exchange inverts the sign of the determinant.)
229
+ int perm_sign = 1;
230
+ const S2Point *pa = &a, *pb = &b, *pc = &c;
231
+ using std::swap;
232
+ if (*pa > *pb) { swap(pa, pb); perm_sign = -perm_sign; }
233
+ if (*pb > *pc) { swap(pb, pc); perm_sign = -perm_sign; }
234
+ if (*pa > *pb) { swap(pa, pb); perm_sign = -perm_sign; }
235
+ S2_DCHECK(*pa < *pb && *pb < *pc);
236
+
237
+ // Construct multiple-precision versions of the sorted points and compute
238
+ // their exact 3x3 determinant.
239
+ Vector3_xf xa = Vector3_xf::Cast(*pa);
240
+ Vector3_xf xb = Vector3_xf::Cast(*pb);
241
+ Vector3_xf xc = Vector3_xf::Cast(*pc);
242
+ Vector3_xf xb_cross_xc = xb.CrossProd(xc);
243
+ ExactFloat det = xa.DotProd(xb_cross_xc);
244
+
245
+ // The precision of ExactFloat is high enough that the result should always
246
+ // be exact (no rounding was performed).
247
+ S2_DCHECK(!det.is_nan());
248
+ S2_DCHECK_LT(det.prec(), det.max_prec());
249
+
250
+ // If the exact determinant is non-zero, we're done.
251
+ int det_sign = det.sgn();
252
+ if (det_sign == 0 && perturb) {
253
+ // Otherwise, we need to resort to symbolic perturbations to resolve the
254
+ // sign of the determinant.
255
+ det_sign = SymbolicallyPerturbedSign(xa, xb, xc, xb_cross_xc);
256
+ S2_DCHECK_NE(0, det_sign);
257
+ }
258
+ return perm_sign * det_sign;
259
+ }
260
+
261
+ // ExpensiveSign() uses arbitrary-precision arithmetic and the "simulation of
262
+ // simplicity" technique in order to be completely robust (i.e., to return
263
+ // consistent results for all possible inputs).
264
+ //
265
+ // Below we define a floating-point type with enough precision so that it can
266
+ // represent the exact determinant of any 3x3 matrix of floating-point
267
+ // numbers. It uses ExactFloat, which is based on the OpenSSL Bignum library
268
+ // and therefore has a permissive BSD-style license. (At one time we also
269
+ // supported an option based on MPFR, but that has an LGPL license and is
270
+ // therefore not suited for some applications.)
271
+
272
+ using Vector3_xf = Vector3<ExactFloat>;
273
+
274
+ int ExpensiveSign(const S2Point& a, const S2Point& b, const S2Point& c,
275
+ bool perturb) {
276
+ // Return zero if and only if two points are the same. This ensures (1).
277
+ if (a == b || b == c || c == a) return 0;
278
+
279
+ // Next we try recomputing the determinant still using floating-point
280
+ // arithmetic but in a more precise way. This is more expensive than the
281
+ // simple calculation done by TriageSign(), but it is still *much* cheaper
282
+ // than using arbitrary-precision arithmetic. This optimization is able to
283
+ // compute the correct determinant sign in virtually all cases except when
284
+ // the three points are truly collinear (e.g., three points on the equator).
285
+ int det_sign = StableSign(a, b, c);
286
+ if (det_sign != 0) return det_sign;
287
+
288
+ // TODO(ericv): Create a templated version of StableSign so that we can
289
+ // retry in "long double" precision before falling back to ExactFloat.
290
+
291
+ // TODO(ericv): Optimize ExactFloat so that it stores up to 32 bytes of
292
+ // mantissa inline (without requiring memory allocation).
293
+
294
+ // Otherwise fall back to exact arithmetic and symbolic permutations.
295
+ return ExactSign(a, b, c, perturb);
296
+ }
297
+
298
+ bool OrderedCCW(const S2Point& a, const S2Point& b, const S2Point& c,
299
+ const S2Point& o) {
300
+ // The last inequality below is ">" rather than ">=" so that we return true
301
+ // if A == B or B == C, and otherwise false if A == C. Recall that
302
+ // Sign(x,y,z) == -Sign(z,y,x) for all x,y,z.
303
+
304
+ int sum = 0;
305
+ if (Sign(b, o, a) >= 0) ++sum;
306
+ if (Sign(c, o, b) >= 0) ++sum;
307
+ if (Sign(a, o, c) > 0) ++sum;
308
+ return sum >= 2;
309
+ }
310
+
311
+ // Returns cos(XY), and sets "error" to the maximum error in the result.
312
+ // REQUIRES: "x" and "y" satisfy S2::IsNormalized().
313
+ inline double GetCosDistance(const S2Point& x, const S2Point& y,
314
+ double* error) {
315
+ double c = x.DotProd(y);
316
+ *error = 9.5 * DBL_ERR * fabs(c) + 1.5 * DBL_ERR;
317
+ return c;
318
+ }
319
+
320
+ // A high precision "long double" version of the function above.
321
+ inline long double GetCosDistance(const Vector3_ld& x, const Vector3_ld& y,
322
+ long double* error) {
323
+ // With "long double" precision it is worthwhile to compensate for length
324
+ // errors in "x" and "y", since they are only unit length to within the
325
+ // precision of "double". (This would also reduce the error constant
326
+ // slightly in the method above but is not worth the additional effort.)
327
+ long double c = x.DotProd(y) / sqrt(x.Norm2() * y.Norm2());
328
+ *error = 7 * LD_ERR * fabs(c) + 1.5 * LD_ERR;
329
+ return c;
330
+ }
331
+
332
+ // Returns sin**2(XY), where XY is the angle between X and Y, and sets "error"
333
+ // to the maximum error in the result.
334
+ //
335
+ // REQUIRES: "x" and "y" satisfy S2::IsNormalized().
336
+ inline double GetSin2Distance(const S2Point& x, const S2Point& y,
337
+ double* error) {
338
+ // The (x-y).CrossProd(x+y) trick eliminates almost all of error due to "x"
339
+ // and "y" being not quite unit length. This method is extremely accurate
340
+ // for small distances; the *relative* error in the result is O(DBL_ERR) for
341
+ // distances as small as DBL_ERR.
342
+ S2Point n = (x - y).CrossProd(x + y);
343
+ double d2 = 0.25 * n.Norm2();
344
+ *error = ((21 + 4 * sqrt(3)) * DBL_ERR * d2 +
345
+ 32 * sqrt(3) * DBL_ERR * DBL_ERR * sqrt(d2) +
346
+ 768 * DBL_ERR * DBL_ERR * DBL_ERR * DBL_ERR);
347
+ return d2;
348
+ }
349
+
350
+ // A high precision "long double" version of the function above.
351
+ inline long double GetSin2Distance(const Vector3_ld& x, const Vector3_ld& y,
352
+ long double* error) {
353
+ // In "long double" precision it is worthwhile to compensate for length
354
+ // errors in "x" and "y", since they are only unit length to within the
355
+ // precision of "double". Otherwise the "d2" error coefficient below would
356
+ // be (16 * DBL_ERR + (5 + 4 * sqrt(3)) * LD_ERR), which is much larger.
357
+ // (Dividing by the squared norms of "x" and "y" would also reduce the error
358
+ // constant slightly in the double-precision version, but this is not worth
359
+ // the additional effort.)
360
+ Vector3_ld n = (x - y).CrossProd(x + y);
361
+ long double d2 = 0.25 * n.Norm2() / (x.Norm2() * y.Norm2());
362
+ *error = ((13 + 4 * sqrt(3)) * LD_ERR * d2 +
363
+ 32 * sqrt(3) * DBL_ERR * LD_ERR * sqrt(d2) +
364
+ 768 * DBL_ERR * DBL_ERR * LD_ERR * LD_ERR);
365
+ return d2;
366
+ }
367
+
368
+ template <class T>
369
+ int TriageCompareCosDistances(const Vector3<T>& x,
370
+ const Vector3<T>& a, const Vector3<T>& b) {
371
+ T cos_ax_error, cos_bx_error;
372
+ T cos_ax = GetCosDistance(a, x, &cos_ax_error);
373
+ T cos_bx = GetCosDistance(b, x, &cos_bx_error);
374
+ T diff = cos_ax - cos_bx;
375
+ T error = cos_ax_error + cos_bx_error;
376
+ return (diff > error) ? -1 : (diff < -error) ? 1 : 0;
377
+ }
378
+
379
+ template <class T>
380
+ int TriageCompareSin2Distances(const Vector3<T>& x,
381
+ const Vector3<T>& a, const Vector3<T>& b) {
382
+ T sin2_ax_error, sin2_bx_error;
383
+ T sin2_ax = GetSin2Distance(a, x, &sin2_ax_error);
384
+ T sin2_bx = GetSin2Distance(b, x, &sin2_bx_error);
385
+ T diff = sin2_ax - sin2_bx;
386
+ T error = sin2_ax_error + sin2_bx_error;
387
+ return (diff > error) ? 1 : (diff < -error) ? -1 : 0;
388
+ }
389
+
390
+ int ExactCompareDistances(const Vector3_xf& x,
391
+ const Vector3_xf& a, const Vector3_xf& b) {
392
+ // This code produces the same result as though all points were reprojected
393
+ // to lie exactly on the surface of the unit sphere. It is based on testing
394
+ // whether x.DotProd(a.Normalize()) < x.DotProd(b.Normalize()), reformulated
395
+ // so that it can be evaluated using exact arithmetic.
396
+ ExactFloat cos_ax = x.DotProd(a);
397
+ ExactFloat cos_bx = x.DotProd(b);
398
+ // If the two values have different signs, we need to handle that case now
399
+ // before squaring them below.
400
+ int a_sign = cos_ax.sgn(), b_sign = cos_bx.sgn();
401
+ if (a_sign != b_sign) {
402
+ return (a_sign > b_sign) ? -1 : 1; // If cos(AX) > cos(BX), then AX < BX.
403
+ }
404
+ ExactFloat cmp = cos_bx * cos_bx * a.Norm2() - cos_ax * cos_ax * b.Norm2();
405
+ return a_sign * cmp.sgn();
406
+ }
407
+
408
+ // Given three points such that AX == BX (exactly), returns -1, 0, or +1
409
+ // according whether AX < BX, AX == BX, or AX > BX after symbolic
410
+ // perturbations are taken into account.
411
+ int SymbolicCompareDistances(const S2Point& x,
412
+ const S2Point& a, const S2Point& b) {
413
+ // Our symbolic perturbation strategy is based on the following model.
414
+ // Similar to "simulation of simplicity", we assign a perturbation to every
415
+ // point such that if A < B, then the symbolic perturbation for A is much,
416
+ // much larger than the symbolic perturbation for B. We imagine that
417
+ // rather than projecting every point to lie exactly on the unit sphere,
418
+ // instead each point is positioned on its own tiny pedestal that raises it
419
+ // just off the surface of the unit sphere. This means that the distance AX
420
+ // is actually the true distance AX plus the (symbolic) heights of the
421
+ // pedestals for A and X. The pedestals are infinitesmally thin, so they do
422
+ // not affect distance measurements except at the two endpoints. If several
423
+ // points project to exactly the same point on the unit sphere, we imagine
424
+ // that they are placed on separate pedestals placed close together, where
425
+ // the distance between pedestals is much, much less than the height of any
426
+ // pedestal. (There are a finite number of S2Points, and therefore a finite
427
+ // number of pedestals, so this is possible.)
428
+ //
429
+ // If A < B, then A is on a higher pedestal than B, and therefore AX > BX.
430
+ return (a < b) ? 1 : (a > b) ? -1 : 0;
431
+ }
432
+
433
+ static int CompareSin2Distances(const S2Point& x,
434
+ const S2Point& a, const S2Point& b) {
435
+ int sign = TriageCompareSin2Distances(x, a, b);
436
+ if (sign != 0) return sign;
437
+ return TriageCompareSin2Distances(ToLD(x), ToLD(a), ToLD(b));
438
+ }
439
+
440
+ int CompareDistances(const S2Point& x, const S2Point& a, const S2Point& b) {
441
+ // We start by comparing distances using dot products (i.e., cosine of the
442
+ // angle), because (1) this is the cheapest technique, and (2) it is valid
443
+ // over the entire range of possible angles. (We can only use the sin^2
444
+ // technique if both angles are less than 90 degrees or both angles are
445
+ // greater than 90 degrees.)
446
+ int sign = TriageCompareCosDistances(x, a, b);
447
+ if (sign != 0) return sign;
448
+
449
+ // Optimization for (a == b) to avoid falling back to exact arithmetic.
450
+ if (a == b) return 0;
451
+
452
+ // It is much better numerically to compare distances using cos(angle) if
453
+ // the distances are near 90 degrees and sin^2(angle) if the distances are
454
+ // near 0 or 180 degrees. We only need to check one of the two angles when
455
+ // making this decision because the fact that the test above failed means
456
+ // that angles "a" and "b" are very close together.
457
+ double cos_ax = a.DotProd(x);
458
+ if (cos_ax > M_SQRT1_2) {
459
+ // Angles < 45 degrees.
460
+ sign = CompareSin2Distances(x, a, b);
461
+ } else if (cos_ax < -M_SQRT1_2) {
462
+ // Angles > 135 degrees. sin^2(angle) is decreasing in this range.
463
+ sign = -CompareSin2Distances(x, a, b);
464
+ } else {
465
+ // We've already tried double precision, so continue with "long double".
466
+ sign = TriageCompareCosDistances(ToLD(x), ToLD(a), ToLD(b));
467
+ }
468
+ if (sign != 0) return sign;
469
+ sign = ExactCompareDistances(ToExact(x), ToExact(a), ToExact(b));
470
+ if (sign != 0) return sign;
471
+ return SymbolicCompareDistances(x, a, b);
472
+ }
473
+
474
+ template <class T>
475
+ int TriageCompareCosDistance(const Vector3<T>& x, const Vector3<T>& y, T r2) {
476
+ constexpr T T_ERR = rounding_epsilon<T>();
477
+ T cos_xy_error;
478
+ T cos_xy = GetCosDistance(x, y, &cos_xy_error);
479
+ T cos_r = 1 - 0.5 * r2;
480
+ T cos_r_error = 2 * T_ERR * cos_r;
481
+ T diff = cos_xy - cos_r;
482
+ T error = cos_xy_error + cos_r_error;
483
+ return (diff > error) ? -1 : (diff < -error) ? 1 : 0;
484
+ }
485
+
486
+ template <class T>
487
+ int TriageCompareSin2Distance(const Vector3<T>& x, const Vector3<T>& y, T r2) {
488
+ S2_DCHECK_LT(r2, 2.0); // Only valid for distance limits < 90 degrees.
489
+
490
+ constexpr T T_ERR = rounding_epsilon<T>();
491
+ T sin2_xy_error;
492
+ T sin2_xy = GetSin2Distance(x, y, &sin2_xy_error);
493
+ T sin2_r = r2 * (1 - 0.25 * r2);
494
+ T sin2_r_error = 3 * T_ERR * sin2_r;
495
+ T diff = sin2_xy - sin2_r;
496
+ T error = sin2_xy_error + sin2_r_error;
497
+ return (diff > error) ? 1 : (diff < -error) ? -1 : 0;
498
+ }
499
+
500
+ int ExactCompareDistance(const Vector3_xf& x, const Vector3_xf& y,
501
+ const ExactFloat& r2) {
502
+ // This code produces the same result as though all points were reprojected
503
+ // to lie exactly on the surface of the unit sphere. It is based on
504
+ // comparing the cosine of the angle XY (when both points are projected to
505
+ // lie exactly on the sphere) to the given threshold.
506
+ ExactFloat cos_xy = x.DotProd(y);
507
+ ExactFloat cos_r = 1 - 0.5 * r2;
508
+ // If the two values have different signs, we need to handle that case now
509
+ // before squaring them below.
510
+ int xy_sign = cos_xy.sgn(), r_sign = cos_r.sgn();
511
+ if (xy_sign != r_sign) {
512
+ return (xy_sign > r_sign) ? -1 : 1; // If cos(XY) > cos(r), then XY < r.
513
+ }
514
+ ExactFloat cmp = cos_r * cos_r * x.Norm2() * y.Norm2() - cos_xy * cos_xy;
515
+ return xy_sign * cmp.sgn();
516
+ }
517
+
518
+ int CompareDistance(const S2Point& x, const S2Point& y, S1ChordAngle r) {
519
+ // As with CompareDistances(), we start by comparing dot products because
520
+ // the sin^2 method is only valid when the distance XY and the limit "r" are
521
+ // both less than 90 degrees.
522
+ int sign = TriageCompareCosDistance(x, y, r.length2());
523
+ if (sign != 0) return sign;
524
+
525
+ // Unlike with CompareDistances(), it's not worth using the sin^2 method
526
+ // when the distance limit is near 180 degrees because the S1ChordAngle
527
+ // representation itself has has a rounding error of up to 2e-8 radians for
528
+ // distances near 180 degrees.
529
+ if (r < k45Degrees) {
530
+ sign = TriageCompareSin2Distance(x, y, r.length2());
531
+ if (sign != 0) return sign;
532
+ sign = TriageCompareSin2Distance(ToLD(x), ToLD(y), ToLD(r.length2()));
533
+ } else {
534
+ sign = TriageCompareCosDistance(ToLD(x), ToLD(y), ToLD(r.length2()));
535
+ }
536
+ if (sign != 0) return sign;
537
+ return ExactCompareDistance(ToExact(x), ToExact(y), r.length2());
538
+ }
539
+
540
+ // Helper function that compares the distance XY against the squared chord
541
+ // distance "r2" using the given precision "T".
542
+ template <class T>
543
+ int TriageCompareDistance(const Vector3<T>& x, const Vector3<T>& y, T r2) {
544
+ // The Sin2 method is much more accurate for small distances, but it is only
545
+ // valid when the actual distance and the distance limit are both less than
546
+ // 90 degrees. So we always start with the Cos method.
547
+ int sign = TriageCompareCosDistance(x, y, r2);
548
+ if (sign == 0 && r2 < k45Degrees.length2()) {
549
+ sign = TriageCompareSin2Distance(x, y, r2);
550
+ }
551
+ return sign;
552
+ }
553
+
554
+ // Helper function that returns "a0" or "a1", whichever is closer to "x".
555
+ // Also returns the squared distance from the returned point to "x" in "ax2".
556
+ template <class T>
557
+ inline Vector3<T> GetClosestVertex(const Vector3<T>& x, const Vector3<T>& a0,
558
+ const Vector3<T>& a1, T* ax2) {
559
+ T a0x2 = (a0 - x).Norm2();
560
+ T a1x2 = (a1 - x).Norm2();
561
+ if (a0x2 < a1x2 || (a0x2 == a1x2 && a0 < a1)) {
562
+ *ax2 = a0x2;
563
+ return a0;
564
+ } else {
565
+ *ax2 = a1x2;
566
+ return a1;
567
+ }
568
+ }
569
+
570
+ // Helper function that returns -1, 0, or +1 according to whether the distance
571
+ // from "x" to the great circle through (a0, a1) is less than, equal to, or
572
+ // greater than the given squared chord length "r2". This method computes the
573
+ // squared sines of the distances involved, which is more accurate when the
574
+ // distances are small (less than 45 degrees).
575
+ //
576
+ // The remaining parameters are functions of (a0, a1) and are passed in
577
+ // because they have already been computed: n = (a0 - a1) x (a0 + a1),
578
+ // n1 = n.Norm(), and n2 = n.Norm2().
579
+ template <class T>
580
+ int TriageCompareLineSin2Distance(const Vector3<T>& x, const Vector3<T>& a0,
581
+ const Vector3<T>& a1, T r2,
582
+ const Vector3<T>& n, T n1, T n2) {
583
+ constexpr T T_ERR = rounding_epsilon<T>();
584
+
585
+ // The minimum distance is to a point on the edge interior. Since the true
586
+ // distance to the edge is always less than 90 degrees, we can return
587
+ // immediately if the limit is 90 degrees or larger.
588
+ if (r2 >= 2.0) return -1; // distance < limit
589
+
590
+ // Otherwise we compute sin^2(distance to edge) to get the best accuracy
591
+ // when the distance limit is small (e.g., S2::kIntersectionError).
592
+ T n2sin2_r = n2 * r2 * (1 - 0.25 * r2);
593
+ T n2sin2_r_error = 6 * T_ERR * n2sin2_r;
594
+ T ax2, xDn = (x - GetClosestVertex(x, a0, a1, &ax2)).DotProd(n);
595
+ T xDn2 = xDn * xDn;
596
+ const T c1 = (((3.5 + 2 * sqrt(3)) * n1 + 32 * sqrt(3) * DBL_ERR) *
597
+ T_ERR * sqrt(ax2));
598
+ T xDn2_error = 4 * T_ERR * xDn2 + (2 * fabs(xDn) + c1) * c1;
599
+
600
+ // If we are using extended precision, then it is worthwhile to recompute
601
+ // the length of X more accurately. Otherwise we use the fact that X is
602
+ // guaranteed to be unit length to with a tolerance of 4 * DBL_ERR.
603
+ if (T_ERR < DBL_ERR) {
604
+ n2sin2_r *= x.Norm2();
605
+ n2sin2_r_error += 4 * T_ERR * n2sin2_r;
606
+ } else {
607
+ n2sin2_r_error += 8 * DBL_ERR * n2sin2_r;
608
+ }
609
+ T diff = xDn2 - n2sin2_r;
610
+ T error = xDn2_error + n2sin2_r_error;
611
+ return (diff > error) ? 1 : (diff < -error) ? -1 : 0;
612
+ }
613
+
614
+ // Like TriageCompareLineSin2Distance, but this method computes the squared
615
+ // cosines of the distances involved. It is more accurate when the distances
616
+ // are large (greater than 45 degrees).
617
+ template <class T>
618
+ int TriageCompareLineCos2Distance(const Vector3<T>& x, const Vector3<T>& a0,
619
+ const Vector3<T>& a1, T r2,
620
+ const Vector3<T>& n, T n1, T n2) {
621
+ constexpr T T_ERR = rounding_epsilon<T>();
622
+
623
+ // The minimum distance is to a point on the edge interior. Since the true
624
+ // distance to the edge is always less than 90 degrees, we can return
625
+ // immediately if the limit is 90 degrees or larger.
626
+ if (r2 >= 2.0) return -1; // distance < limit
627
+
628
+ // Otherwise we compute cos^2(distance to edge).
629
+ T cos_r = 1 - 0.5 * r2;
630
+ T n2cos2_r = n2 * cos_r * cos_r;
631
+ T n2cos2_r_error = 7 * T_ERR * n2cos2_r;
632
+
633
+ // The length of M = X.CrossProd(N) is the cosine of the distance.
634
+ T m2 = x.CrossProd(n).Norm2();
635
+ T m1 = sqrt(m2);
636
+ T m1_error = ((1 + 8 / sqrt(3)) * n1 + 32 * sqrt(3) * DBL_ERR) * T_ERR;
637
+ T m2_error = 3 * T_ERR * m2 + (2 * m1 + m1_error) * m1_error;
638
+
639
+ // If we are using extended precision, then it is worthwhile to recompute
640
+ // the length of X more accurately. Otherwise we use the fact that X is
641
+ // guaranteed to be unit length to within a tolerance of 4 * DBL_ERR.
642
+ if (T_ERR < DBL_ERR) {
643
+ n2cos2_r *= x.Norm2();
644
+ n2cos2_r_error += 4 * T_ERR * n2cos2_r;
645
+ } else {
646
+ n2cos2_r_error += 8 * DBL_ERR * n2cos2_r;
647
+ }
648
+ T diff = m2 - n2cos2_r;
649
+ T error = m2_error + n2cos2_r_error;
650
+ return (diff > error) ? -1 : (diff < -error) ? 1 : 0;
651
+ }
652
+
653
+ template <class T>
654
+ inline int TriageCompareLineDistance(const Vector3<T>& x, const Vector3<T>& a0,
655
+ const Vector3<T>& a1, T r2,
656
+ const Vector3<T>& n, T n1, T n2) {
657
+ if (r2 < k45Degrees.length2()) {
658
+ return TriageCompareLineSin2Distance(x, a0, a1, r2, n, n1, n2);
659
+ } else {
660
+ return TriageCompareLineCos2Distance(x, a0, a1, r2, n, n1, n2);
661
+ }
662
+ }
663
+
664
+ template <class T>
665
+ int TriageCompareEdgeDistance(const Vector3<T>& x, const Vector3<T>& a0,
666
+ const Vector3<T>& a1, T r2) {
667
+ constexpr T T_ERR = rounding_epsilon<T>();
668
+
669
+ // First we need to decide whether the closest point is an edge endpoint or
670
+ // somewhere in the interior. To determine this we compute a plane
671
+ // perpendicular to (a0, a1) that passes through X. Letting M be the normal
672
+ // to this plane, the closest point is in the edge interior if and only if
673
+ // a0.M < 0 and a1.M > 0. Note that we can use "<" rather than "<=" because
674
+ // if a0.M or a1.M is zero exactly then it doesn't matter which code path we
675
+ // follow (since the distance to an endpoint and the distance to the edge
676
+ // interior are exactly the same in this case).
677
+ Vector3<T> n = (a0 - a1).CrossProd(a0 + a1);
678
+ Vector3<T> m = n.CrossProd(x);
679
+ // For better accuracy when the edge (a0,a1) is very short, we subtract "x"
680
+ // before computing the dot products with M.
681
+ Vector3<T> a0_dir = a0 - x;
682
+ Vector3<T> a1_dir = a1 - x;
683
+ T a0_sign = a0_dir.DotProd(m);
684
+ T a1_sign = a1_dir.DotProd(m);
685
+ T n2 = n.Norm2();
686
+ T n1 = sqrt(n2);
687
+ T n1_error = ((3.5 + 8 / sqrt(3)) * n1 + 32 * sqrt(3) * DBL_ERR) * T_ERR;
688
+ T a0_sign_error = n1_error * a0_dir.Norm();
689
+ T a1_sign_error = n1_error * a1_dir.Norm();
690
+ if (fabs(a0_sign) < a0_sign_error || fabs(a1_sign) < a1_sign_error) {
691
+ // It is uncertain whether minimum distance is to an edge vertex or to the
692
+ // edge interior. We handle this by computing both distances and checking
693
+ // whether they yield the same result.
694
+ int vertex_sign = min(TriageCompareDistance(x, a0, r2),
695
+ TriageCompareDistance(x, a1, r2));
696
+ int line_sign = TriageCompareLineDistance(x, a0, a1, r2, n, n1, n2);
697
+ return (vertex_sign == line_sign) ? line_sign : 0;
698
+ }
699
+ if (a0_sign >= 0 || a1_sign <= 0) {
700
+ // The minimum distance is to an edge endpoint.
701
+ return min(TriageCompareDistance(x, a0, r2),
702
+ TriageCompareDistance(x, a1, r2));
703
+ } else {
704
+ // The minimum distance is to the edge interior.
705
+ return TriageCompareLineDistance(x, a0, a1, r2, n, n1, n2);
706
+ }
707
+ }
708
+
709
+ // REQUIRES: the closest point to "x" is in the interior of edge (a0, a1).
710
+ int ExactCompareLineDistance(const Vector3_xf& x, const Vector3_xf& a0,
711
+ const Vector3_xf& a1, const ExactFloat& r2) {
712
+ // Since we are given that the closest point is in the edge interior, the
713
+ // true distance is always less than 90 degrees (which corresponds to a
714
+ // squared chord length of 2.0).
715
+ if (r2 >= 2.0) return -1; // distance < limit
716
+
717
+ // Otherwise compute the edge normal
718
+ Vector3_xf n = a0.CrossProd(a1);
719
+ ExactFloat sin_d = x.DotProd(n);
720
+ ExactFloat sin2_r = r2 * (1 - 0.25 * r2);
721
+ ExactFloat cmp = sin_d * sin_d - sin2_r * x.Norm2() * n.Norm2();
722
+ return cmp.sgn();
723
+ }
724
+
725
+ int ExactCompareEdgeDistance(const S2Point& x, const S2Point& a0,
726
+ const S2Point& a1, S1ChordAngle r) {
727
+ // Even if previous calculations were uncertain, we might not need to do
728
+ // *all* the calculations in exact arithmetic here. For example it may be
729
+ // easy to determine whether "x" is closer to an endpoint or the edge
730
+ // interior. The only calculation where we always use exact arithmetic is
731
+ // when measuring the distance to the extended line (great circle) through
732
+ // "a0" and "a1", since it is virtually certain that the previous floating
733
+ // point calculations failed in that case.
734
+ //
735
+ // CompareEdgeDirections also checks that no edge has antipodal endpoints.
736
+ if (CompareEdgeDirections(a0, a1, a0, x) > 0 &&
737
+ CompareEdgeDirections(a0, a1, x, a1) > 0) {
738
+ // The closest point to "x" is along the interior of the edge.
739
+ return ExactCompareLineDistance(ToExact(x), ToExact(a0), ToExact(a1),
740
+ r.length2());
741
+ } else {
742
+ // The closest point to "x" is one of the edge endpoints.
743
+ return min(CompareDistance(x, a0, r), CompareDistance(x, a1, r));
744
+ }
745
+ }
746
+
747
+ int CompareEdgeDistance(const S2Point& x, const S2Point& a0, const S2Point& a1,
748
+ S1ChordAngle r) {
749
+ // Check that the edge does not consist of antipodal points. (This catches
750
+ // the most common case -- the full test is in ExactCompareEdgeDistance.)
751
+ S2_DCHECK_NE(a0, -a1);
752
+
753
+ int sign = TriageCompareEdgeDistance(x, a0, a1, r.length2());
754
+ if (sign != 0) return sign;
755
+
756
+ // Optimization for the case where the edge is degenerate.
757
+ if (a0 == a1) return CompareDistance(x, a0, r);
758
+
759
+ sign = TriageCompareEdgeDistance(ToLD(x), ToLD(a0), ToLD(a1),
760
+ ToLD(r.length2()));
761
+ if (sign != 0) return sign;
762
+ return ExactCompareEdgeDistance(x, a0, a1, r);
763
+ }
764
+
765
+ template <class T>
766
+ int TriageCompareEdgeDirections(
767
+ const Vector3<T>& a0, const Vector3<T>& a1,
768
+ const Vector3<T>& b0, const Vector3<T>& b1) {
769
+ constexpr T T_ERR = rounding_epsilon<T>();
770
+ Vector3<T> na = (a0 - a1).CrossProd(a0 + a1);
771
+ Vector3<T> nb = (b0 - b1).CrossProd(b0 + b1);
772
+ T na_len = na.Norm(), nb_len = nb.Norm();
773
+ T cos_ab = na.DotProd(nb);
774
+ T cos_ab_error = ((5 + 4 * sqrt(3)) * na_len * nb_len +
775
+ 32 * sqrt(3) * DBL_ERR * (na_len + nb_len)) * T_ERR;
776
+ return (cos_ab > cos_ab_error) ? 1 : (cos_ab < -cos_ab_error) ? -1 : 0;
777
+ }
778
+
779
+ bool ArePointsLinearlyDependent(const Vector3_xf& x, const Vector3_xf& y) {
780
+ Vector3_xf n = x.CrossProd(y);
781
+ return n[0].sgn() == 0 && n[1].sgn() == 0 && n[2].sgn() == 0;
782
+ }
783
+
784
+ bool ArePointsAntipodal(const Vector3_xf& x, const Vector3_xf& y) {
785
+ return ArePointsLinearlyDependent(x, y) && x.DotProd(y).sgn() < 0;
786
+ }
787
+
788
+ int ExactCompareEdgeDirections(const Vector3_xf& a0, const Vector3_xf& a1,
789
+ const Vector3_xf& b0, const Vector3_xf& b1) {
790
+ S2_DCHECK(!ArePointsAntipodal(a0, a1));
791
+ S2_DCHECK(!ArePointsAntipodal(b0, b1));
792
+ return a0.CrossProd(a1).DotProd(b0.CrossProd(b1)).sgn();
793
+ }
794
+
795
+ int CompareEdgeDirections(const S2Point& a0, const S2Point& a1,
796
+ const S2Point& b0, const S2Point& b1) {
797
+ // Check that no edge consists of antipodal points. (This catches the most
798
+ // common case -- the full test is in ExactCompareEdgeDirections.)
799
+ S2_DCHECK_NE(a0, -a1);
800
+ S2_DCHECK_NE(b0, -b1);
801
+
802
+ int sign = TriageCompareEdgeDirections(a0, a1, b0, b1);
803
+ if (sign != 0) return sign;
804
+
805
+ // Optimization for the case where either edge is degenerate.
806
+ if (a0 == a1 || b0 == b1) return 0;
807
+
808
+ sign = TriageCompareEdgeDirections(ToLD(a0), ToLD(a1), ToLD(b0), ToLD(b1));
809
+ if (sign != 0) return sign;
810
+ return ExactCompareEdgeDirections(ToExact(a0), ToExact(a1),
811
+ ToExact(b0), ToExact(b1));
812
+ }
813
+
814
+ // If triangle ABC has positive sign, returns its circumcenter. If ABC has
815
+ // negative sign, returns the negated circumcenter.
816
+ template <class T>
817
+ Vector3<T> GetCircumcenter(const Vector3<T>& a, const Vector3<T>& b,
818
+ const Vector3<T>& c, T* error) {
819
+ constexpr T T_ERR = rounding_epsilon<T>();
820
+
821
+ // We compute the circumcenter using the intersection of the perpendicular
822
+ // bisectors of AB and BC. The formula is essentially
823
+ //
824
+ // Z = ((A x B) x (A + B)) x ((B x C) x (B + C)),
825
+ //
826
+ // except that we compute the cross product (A x B) as (A - B) x (A + B)
827
+ // (and similarly for B x C) since this is much more stable when the inputs
828
+ // are unit vectors.
829
+ Vector3<T> ab_diff = a - b, ab_sum = a + b;
830
+ Vector3<T> bc_diff = b - c, bc_sum = b + c;
831
+ Vector3<T> nab = ab_diff.CrossProd(ab_sum);
832
+ T nab_len = nab.Norm();
833
+ T ab_len = ab_diff.Norm();
834
+ Vector3<T> nbc = bc_diff.CrossProd(bc_sum);
835
+ T nbc_len = nbc.Norm();
836
+ T bc_len = bc_diff.Norm();
837
+ Vector3<T> mab = nab.CrossProd(ab_sum);
838
+ Vector3<T> mbc = nbc.CrossProd(bc_sum);
839
+ *error = (((16 + 24 * sqrt(3)) * T_ERR +
840
+ 8 * DBL_ERR * (ab_len + bc_len)) * nab_len * nbc_len +
841
+ 128 * sqrt(3) * DBL_ERR * T_ERR * (nab_len + nbc_len) +
842
+ 3 * 4096 * DBL_ERR * DBL_ERR * T_ERR * T_ERR);
843
+ return mab.CrossProd(mbc);
844
+ }
845
+
846
+ template <class T>
847
+ int TriageEdgeCircumcenterSign(const Vector3<T>& x0, const Vector3<T>& x1,
848
+ const Vector3<T>& a, const Vector3<T>& b,
849
+ const Vector3<T>& c, int abc_sign) {
850
+ constexpr T T_ERR = rounding_epsilon<T>();
851
+
852
+ // Compute the circumcenter Z of triangle ABC, and then test which side of
853
+ // edge X it lies on.
854
+ T z_error;
855
+ Vector3<T> z = GetCircumcenter(a, b, c, &z_error);
856
+ Vector3<T> nx = (x0 - x1).CrossProd(x0 + x1);
857
+ // If the sign of triangle ABC is negative, then we have computed -Z and the
858
+ // result should be negated.
859
+ T result = abc_sign * nx.DotProd(z);
860
+
861
+ T z_len = z.Norm();
862
+ T nx_len = nx.Norm();
863
+ T nx_error = ((1 + 2 * sqrt(3)) * nx_len + 32 * sqrt(3) * DBL_ERR) * T_ERR;
864
+ T result_error = ((3 * T_ERR * nx_len + nx_error) * z_len + z_error * nx_len);
865
+ return (result > result_error) ? 1 : (result < -result_error) ? -1 : 0;
866
+ }
867
+
868
+ int ExactEdgeCircumcenterSign(const Vector3_xf& x0, const Vector3_xf& x1,
869
+ const Vector3_xf& a, const Vector3_xf& b,
870
+ const Vector3_xf& c, int abc_sign) {
871
+ // Return zero if the edge X is degenerate. (Also see the comments in
872
+ // SymbolicEdgeCircumcenterSign.)
873
+ if (ArePointsLinearlyDependent(x0, x1)) {
874
+ S2_DCHECK_GT(x0.DotProd(x1), 0); // Antipodal edges not allowed.
875
+ return 0;
876
+ }
877
+ // The simplest predicate for testing whether the sign is positive is
878
+ //
879
+ // (1) (X0 x X1) . (|C|(A x B) + |A|(B x C) + |B|(C x A)) > 0
880
+ //
881
+ // where |A| denotes A.Norm() and the expression after the "." represents
882
+ // the circumcenter of triangle ABC. (This predicate is terrible from a
883
+ // numerical accuracy point of view, but that doesn't matter since we are
884
+ // going to use exact arithmetic.) This predicate also assumes that
885
+ // triangle ABC is CCW (positive sign); we correct for that below.
886
+ //
887
+ // The only problem with evaluating this inequality is that computing |A|,
888
+ // |B| and |C| requires square roots. To avoid this problem we use the
889
+ // standard technique of rearranging the inequality to isolate at least one
890
+ // square root and then squaring both sides. We need to repeat this process
891
+ // twice in order to eliminate all the square roots, which leads to a
892
+ // polynomial predicate of degree 20 in the input arguments.
893
+ //
894
+ // Rearranging (1) we get
895
+ //
896
+ // (X0 x X1) . (|C|(A x B) + |A|(B x C)) > |B|(X0 x X1) . (A x C)
897
+ //
898
+ // Before squaring we need to check the sign of each side. If the signs are
899
+ // different then we know the result without squaring, and if the signs are
900
+ // both negative then after squaring both sides we need to invert the
901
+ // result. Define
902
+ //
903
+ // dAB = (X0 x X1) . (A x B)
904
+ // dBC = (X0 x X1) . (B x C)
905
+ // dCA = (X0 x X1) . (C x A)
906
+ //
907
+ // Then we can now write the inequality above as
908
+ //
909
+ // (2) |C| dAB + |A| dBC > -|B| dCA
910
+ //
911
+ // The RHS of (2) is positive if dCA < 0, and the LHS of (2) is positive if
912
+ // (|C| dAB + |A| dBC) > 0. Since the LHS has square roots, we need to
913
+ // eliminate them using the same process. Rewriting the LHS as
914
+ //
915
+ // (3) |C| dAB > -|A| dBC
916
+ //
917
+ // we again need to check the signs of both sides. Let's start with that.
918
+ // We also precompute the following values because they are used repeatedly
919
+ // when squaring various expressions below:
920
+ //
921
+ // abc2 = |A|^2 dBC^2
922
+ // bca2 = |B|^2 dCA^2
923
+ // cab2 = |C|^2 dAB^2
924
+ Vector3_xf nx = x0.CrossProd(x1);
925
+ ExactFloat dab = nx.DotProd(a.CrossProd(b));
926
+ ExactFloat dbc = nx.DotProd(b.CrossProd(c));
927
+ ExactFloat dca = nx.DotProd(c.CrossProd(a));
928
+ ExactFloat abc2 = a.Norm2() * (dbc * dbc);
929
+ ExactFloat bca2 = b.Norm2() * (dca * dca);
930
+ ExactFloat cab2 = c.Norm2() * (dab * dab);
931
+
932
+ // If the two sides of (3) have different signs (including the case where
933
+ // one side is zero) then we know the result. Also, if both sides are zero
934
+ // then we know the result. The following logic encodes this.
935
+ int lhs3_sgn = dab.sgn(), rhs3_sgn = -dbc.sgn();
936
+ int lhs2_sgn = max(-1, min(1, lhs3_sgn - rhs3_sgn));
937
+ if (lhs2_sgn == 0 && lhs3_sgn != 0) {
938
+ // Both sides of (3) have the same non-zero sign, so square both sides.
939
+ // If both sides were negative then invert the result.
940
+ lhs2_sgn = (cab2 - abc2).sgn() * lhs3_sgn;
941
+ }
942
+ // Now if the two sides of (2) have different signs then we know the result
943
+ // of this entire function.
944
+ int rhs2_sgn = -dca.sgn();
945
+ int result = max(-1, min(1, lhs2_sgn - rhs2_sgn));
946
+ if (result == 0 && lhs2_sgn != 0) {
947
+ // Both sides of (2) have the same non-zero sign, so square both sides.
948
+ // (If both sides were negative then we invert the result below.)
949
+ // This gives
950
+ //
951
+ // |C|^2 dAB^2 + |A|^2 dBC^2 + 2 |A| |C| dAB dBC > |B|^2 dCA^2
952
+ //
953
+ // This expression still has square roots (|A| and |C|), so we rewrite as
954
+ //
955
+ // (4) 2 |A| |C| dAB dBC > |B|^2 dCA^2 - |C|^2 dAB^2 - |A|^2 dBC^2 .
956
+ //
957
+ // Again, if the two sides have different signs then we know the result.
958
+ int lhs4_sgn = dab.sgn() * dbc.sgn();
959
+ ExactFloat rhs4 = bca2 - cab2 - abc2;
960
+ result = max(-1, min(1, lhs4_sgn - rhs4.sgn()));
961
+ if (result == 0 && lhs4_sgn != 0) {
962
+ // Both sides of (4) have the same non-zero sign, so square both sides.
963
+ // If both sides were negative then invert the result.
964
+ result = (4 * abc2 * cab2 - rhs4 * rhs4).sgn() * lhs4_sgn;
965
+ }
966
+ // Correct the sign if both sides of (2) were negative.
967
+ result *= lhs2_sgn;
968
+ }
969
+ // If the sign of triangle ABC is negative, then we have computed -Z and the
970
+ // result should be negated.
971
+ return abc_sign * result;
972
+ }
973
+
974
+ // Like Sign, except this method does not use symbolic perturbations when
975
+ // the input points are exactly coplanar with the origin (i.e., linearly
976
+ // dependent). Clients should never use this method, but it is useful here in
977
+ // order to implement the combined pedestal/axis-aligned perturbation scheme
978
+ // used by some methods (such as EdgeCircumcenterSign).
979
+ int UnperturbedSign(const S2Point& a, const S2Point& b, const S2Point& c) {
980
+ int sign = TriageSign(a, b, c, a.CrossProd(b));
981
+ if (sign == 0) sign = ExpensiveSign(a, b, c, false /*perturb*/);
982
+ return sign;
983
+ }
984
+
985
+ // Given arguments such that ExactEdgeCircumcenterSign(x0, x1, a, b, c) == 0,
986
+ // returns the value of Sign(X0, X1, Z) (where Z is the circumcenter of
987
+ // triangle ABC) after symbolic perturbations are taken into account. The
988
+ // result is zero only if X0 == X1, A == B, B == C, or C == A. (It is nonzero
989
+ // if these pairs are exactly proportional to each other but not equal.)
990
+ int SymbolicEdgeCircumcenterSign(
991
+ const S2Point& x0, const S2Point& x1,
992
+ const S2Point& a_arg, const S2Point& b_arg, const S2Point& c_arg) {
993
+ // We use the same perturbation strategy as SymbolicCompareDistances. Note
994
+ // that pedestal perturbations of X0 and X1 do not affect the result,
995
+ // because Sign(X0, X1, Z) does not change when its arguments are scaled
996
+ // by a positive factor. Therefore we only need to consider A, B, C.
997
+ // Suppose that A is the smallest lexicographically and therefore has the
998
+ // largest perturbation. This has the effect of perturbing the circumcenter
999
+ // of ABC slightly towards A, and since the circumcenter Z was previously
1000
+ // exactly collinear with edge X, this implies that after the perturbation
1001
+ // Sign(X0, X1, Z) == UnperturbedSign(X0, X1, A). (We want the result
1002
+ // to be zero if X0, X1, and A are linearly dependent, rather than using
1003
+ // symbolic perturbations, because these perturbations are defined to be
1004
+ // much, much smaller than the pedestal perturbation of B and C that are
1005
+ // considered below.)
1006
+ //
1007
+ // If A is also exactly collinear with edge X, then we move on to the next
1008
+ // smallest point lexicographically out of {B, C}. It is easy to see that
1009
+ // as long as A, B, C are all distinct, one of these three Sign calls
1010
+ // will be nonzero, because if A, B, C are all distinct and collinear with
1011
+ // edge X then their circumcenter Z coincides with the normal of X, and
1012
+ // therefore Sign(X0, X1, Z) is nonzero.
1013
+ //
1014
+ // This function could be extended to handle the case where X0 and X1 are
1015
+ // linearly dependent as follows. First, suppose that every point has both
1016
+ // a pedestal peturbation as described above, and also the three
1017
+ // axis-aligned perturbations described in the "Simulation of Simplicity"
1018
+ // paper, where all pedestal perturbations are defined to be much, much
1019
+ // larger than any axis-aligned perturbation. Note that since pedestal
1020
+ // perturbations have no effect on Sign, we can use this model for *all*
1021
+ // the S2 predicates, which ensures that all the various predicates are
1022
+ // fully consistent with each other.
1023
+ //
1024
+ // With this model, the strategy described above yields the correct result
1025
+ // unless X0 and X1 are exactly linearly dependent. When that happens, then
1026
+ // no perturbation (pedestal or axis-aligned) of A,B,C affects the result,
1027
+ // and no pedestal perturbation of X0 or X1 affects the result, therefore we
1028
+ // need to consider the smallest axis-aligned perturbation of X0 or X1. The
1029
+ // first perturbation that makes X0 and X1 linearly independent yields the
1030
+ // result. Supposing that X0 < X1, this is the perturbation of X0[2] unless
1031
+ // both points are multiples of [0, 0, 1], in which case it is the
1032
+ // perturbation of X0[1]. The sign test can be implemented by computing the
1033
+ // perturbed cross product of X0 and X1 and taking the dot product with the
1034
+ // exact value of Z. For example if X0[2] is perturbed, the perturbed cross
1035
+ // product is proportional to (0, 0, 1) x X1 = (-X1[1], x1[0], 0). Note
1036
+ // that if the dot product with Z is exactly zero, then it is still
1037
+ // necessary to fall back to pedestal perturbations of A, B, C, but one of
1038
+ // these perturbations is now guaranteed to succeed.
1039
+
1040
+ // If any two triangle vertices are equal, the result is zero.
1041
+ if (a_arg == b_arg || b_arg == c_arg || c_arg == a_arg) return 0;
1042
+
1043
+ // Sort A, B, C in lexicographic order.
1044
+ const S2Point *a = &a_arg, *b = &b_arg, *c = &c_arg;
1045
+ if (*b < *a) std::swap(a, b);
1046
+ if (*c < *b) std::swap(b, c);
1047
+ if (*b < *a) std::swap(a, b);
1048
+
1049
+ // Now consider the perturbations in decreasing order of size.
1050
+ int sign = UnperturbedSign(x0, x1, *a);
1051
+ if (sign != 0) return sign;
1052
+ sign = UnperturbedSign(x0, x1, *b);
1053
+ if (sign != 0) return sign;
1054
+ return UnperturbedSign(x0, x1, *c);
1055
+ }
1056
+
1057
+ int EdgeCircumcenterSign(const S2Point& x0, const S2Point& x1,
1058
+ const S2Point& a, const S2Point& b,
1059
+ const S2Point& c) {
1060
+ // Check that the edge does not consist of antipodal points. (This catches
1061
+ // the most common case -- the full test is in ExactEdgeCircumcenterSign.)
1062
+ S2_DCHECK_NE(x0, -x1);
1063
+
1064
+ int abc_sign = Sign(a, b, c);
1065
+ int sign = TriageEdgeCircumcenterSign(x0, x1, a, b, c, abc_sign);
1066
+ if (sign != 0) return sign;
1067
+
1068
+ // Optimization for the cases that are going to return zero anyway, in order
1069
+ // to avoid falling back to exact arithmetic.
1070
+ if (x0 == x1 || a == b || b == c || c == a) return 0;
1071
+
1072
+ sign = TriageEdgeCircumcenterSign(
1073
+ ToLD(x0), ToLD(x1), ToLD(a), ToLD(b), ToLD(c), abc_sign);
1074
+ if (sign != 0) return sign;
1075
+ sign = ExactEdgeCircumcenterSign(
1076
+ ToExact(x0), ToExact(x1), ToExact(a), ToExact(b), ToExact(c), abc_sign);
1077
+ if (sign != 0) return sign;
1078
+
1079
+ // Unlike the other methods, SymbolicEdgeCircumcenterSign does not depend
1080
+ // on the sign of triangle ABC.
1081
+ return SymbolicEdgeCircumcenterSign(x0, x1, a, b, c);
1082
+ }
1083
+
1084
+ template <class T>
1085
+ Excluded TriageVoronoiSiteExclusion(const Vector3<T>& a, const Vector3<T>& b,
1086
+ const Vector3<T>& x0, const Vector3<T>& x1,
1087
+ T r2) {
1088
+ constexpr T T_ERR = rounding_epsilon<T>();
1089
+
1090
+ // Define the "coverage disc" of a site S to be the disc centered at S with
1091
+ // radius r (i.e., squared chord angle length r2). Similarly, define the
1092
+ // "coverage interval" of S along an edge X to be the intersection of X with
1093
+ // the coverage disc of S. The coverage interval can be represented as the
1094
+ // point at the center of the interval and an angle that measures the
1095
+ // semi-width or "radius" of the interval.
1096
+ //
1097
+ // To test whether site A excludes site B along the input edge X, we test
1098
+ // whether the coverage interval of A contains the coverage interval of B.
1099
+ // Let "ra" and "rb" be the radii (semi-widths) of the two intervals, and
1100
+ // let "d" be the angle between their center points. Then "a" properly
1101
+ // contains "b" if (ra - rb > d), and "b" contains "a" if (rb - ra > d).
1102
+ // Note that only one of these conditions can be true. Therefore we can
1103
+ // determine whether one site excludes the other by checking whether
1104
+ //
1105
+ // (1) |rb - ra| > d
1106
+ //
1107
+ // and use the sign of (rb - ra) to determine which site is excluded.
1108
+ //
1109
+ // The actual code is based on the following. Let A1 and B1 be the unit
1110
+ // vectors A and B scaled by cos(r) (these points are inside the sphere).
1111
+ // The planes perpendicular to OA1 and OA2 cut off two discs of radius r
1112
+ // around A and B. Now consider the two lines (inside the sphere) where
1113
+ // these planes intersect the plane containing the input edge X, and let A2
1114
+ // and B2 be the points on these lines that are closest to A and B. The
1115
+ // coverage intervals of A and B can be represented as an interval along
1116
+ // each of these lines, centered at A2 and B2. Let P1 and P2 be the
1117
+ // endpoints of the coverage interval for A, and let Q1 and Q2 be the
1118
+ // endpoints of the coverage interval for B. We can view each coverage
1119
+ // interval as either a chord through the sphere's interior, or as a segment
1120
+ // of the original edge X (by projecting the chord onto the sphere's
1121
+ // surface).
1122
+ //
1123
+ // To check whether B's interval is contained by A's interval, we test
1124
+ // whether both endpoints of B's interval (Q1 and Q2) are contained by A's
1125
+ // interval. E.g., we could test whether Qi.DotProd(A2) > A2.Norm2().
1126
+ //
1127
+ // However rather than constructing the actual points A1, A2, and so on, it
1128
+ // turns out to be more efficient to compute the sines and cosines
1129
+ // ("components") of the various angles and then use trigonometric
1130
+ // identities. Predicate (1) can be expressed as
1131
+ //
1132
+ // |sin(rb - ra)| > sin(d)
1133
+ //
1134
+ // provided that |d| <= Pi/2 (which must be checked), and then expanded to
1135
+ //
1136
+ // (2) |sin(rb) cos(ra) - sin(ra) cos(rb)| > sin(d) .
1137
+ //
1138
+ // The components of the various angles can be expressed using dot and cross
1139
+ // products based on the construction above:
1140
+ //
1141
+ // sin(ra) = sqrt(sin^2(r) |a|^2 |n|^2 - |a.n|^2) / |aXn|
1142
+ // cos(ra) = cos(r) |a| |n| / |aXn|
1143
+ // sin(rb) = sqrt(sin^2(r) |b|^2 |n|^2 - |b.n|^2) / |bXn|
1144
+ // cos(rb) = cos(r) |b| |n| / |bXn|
1145
+ // sin(d) = (aXb).n |n| / (|aXn| |bXn|)
1146
+ // cos(d) = (aXn).(bXn) / (|aXn| |bXn|)
1147
+ //
1148
+ // Also, the squared chord length r2 is equal to 4 * sin^2(r / 2), which
1149
+ // yields the following relationships:
1150
+ //
1151
+ // sin(r) = sqrt(r2 (1 - r2 / 4))
1152
+ // cos(r) = 1 - r2 / 2
1153
+ //
1154
+ // We then scale both sides of (2) by |aXn| |bXn| / |n| (in order to
1155
+ // minimize the number of calculations and to avoid divisions), which gives:
1156
+ //
1157
+ // cos(r) ||a| sqrt(sin^2(r) |b|^2 |n|^2 - |b.n|^2) -
1158
+ // |b| sqrt(sin^2(r) |a|^2 |n|^2 - |a.n|^2)| > (aXb).n
1159
+ //
1160
+ // Furthermore we can substitute |a| = |b| = 1 (as long as this is taken
1161
+ // into account in the error bounds), yielding
1162
+ //
1163
+ // (3) cos(r) |sqrt(sin^2(r) |n|^2 - |b.n|^2) -
1164
+ // sqrt(sin^2(r) |n|^2 - |a.n|^2)| > (aXb).n
1165
+ //
1166
+ // The code below is more complicated than this because many expressions
1167
+ // have been modified for better numerical stability. For example, dot
1168
+ // products between unit vectors are computed using (x - y).DotProd(x + y),
1169
+ // and the dot product between a point P and the normal N of an edge X is
1170
+ // measured using (P - Xi).DotProd(N) where Xi is the endpoint of X that is
1171
+ // closer to P.
1172
+
1173
+ Vector3<T> n = (x0 - x1).CrossProd(x0 + x1); // 2 * x0.CrossProd(x1)
1174
+ T n2 = n.Norm2();
1175
+ T n1 = sqrt(n2);
1176
+ // This factor is used in the error terms of dot products with "n" below.
1177
+ T Dn_error = ((3.5 + 2 * sqrt(3)) * n1 + 32 * sqrt(3) * DBL_ERR) * T_ERR;
1178
+
1179
+ T cos_r = 1 - 0.5 * r2;
1180
+ T sin2_r = r2 * (1 - 0.25 * r2);
1181
+ T n2sin2_r = n2 * sin2_r;
1182
+
1183
+ // "ra" and "rb" denote sin(ra) and sin(rb) after the scaling above.
1184
+ T ax2, aDn = (a - GetClosestVertex(a, x0, x1, &ax2)).DotProd(n);
1185
+ T aDn2 = aDn * aDn;
1186
+ T aDn_error = Dn_error * sqrt(ax2);
1187
+ T ra2 = n2sin2_r - aDn2;
1188
+ T ra2_error = (8 * DBL_ERR + 4 * T_ERR) * aDn2 +
1189
+ (2 * fabs(aDn) + aDn_error) * aDn_error + 6 * T_ERR * n2sin2_r;
1190
+ // This is the minimum possible value of ra2, which is used to bound the
1191
+ // derivative of sqrt(ra2) in computing ra_error below.
1192
+ T min_ra2 = ra2 - ra2_error;
1193
+ if (min_ra2 < 0) return Excluded::UNCERTAIN;
1194
+ T ra = sqrt(ra2);
1195
+ // Includes the ra2 subtraction error above.
1196
+ T ra_error = 1.5 * T_ERR * ra + 0.5 * ra2_error / sqrt(min_ra2);
1197
+
1198
+ T bx2, bDn = (b - GetClosestVertex(b, x0, x1, &bx2)).DotProd(n);
1199
+ T bDn2 = bDn * bDn;
1200
+ T bDn_error = Dn_error * sqrt(bx2);
1201
+ T rb2 = n2sin2_r - bDn2;
1202
+ T rb2_error = (8 * DBL_ERR + 4 * T_ERR) * bDn2 +
1203
+ (2 * fabs(bDn) + bDn_error) * bDn_error + 6 * T_ERR * n2sin2_r;
1204
+ T min_rb2 = rb2 - rb2_error;
1205
+ if (min_rb2 < 0) return Excluded::UNCERTAIN;
1206
+ T rb = sqrt(rb2);
1207
+ // Includes the rb2 subtraction error above.
1208
+ T rb_error = 1.5 * T_ERR * rb + 0.5 * rb2_error / sqrt(min_rb2);
1209
+
1210
+ // The sign of LHS(3) determines which site may be excluded by the other.
1211
+ T lhs3 = cos_r * (rb - ra);
1212
+ T abs_lhs3 = fabs(lhs3);
1213
+ T lhs3_error = cos_r * (ra_error + rb_error) + 3 * T_ERR * abs_lhs3;
1214
+
1215
+ // Now we evaluate the RHS of (3), which is proportional to sin(d).
1216
+ Vector3<T> aXb = (a - b).CrossProd(a + b); // 2 * a.CrossProd(b)
1217
+ T aXb1 = aXb.Norm();
1218
+ T sin_d = 0.5 * aXb.DotProd(n);
1219
+ T sin_d_error = (4 * DBL_ERR + (2.5 + 2 * sqrt(3)) * T_ERR) * aXb1 * n1 +
1220
+ 16 * sqrt(3) * DBL_ERR * T_ERR * (aXb1 + n1);
1221
+
1222
+ // If LHS(3) is definitely less than RHS(3), neither site excludes the other.
1223
+ T result = abs_lhs3 - sin_d;
1224
+ T result_error = lhs3_error + sin_d_error;
1225
+ if (result < -result_error) return Excluded::NEITHER;
1226
+
1227
+ // Otherwise, before proceeding further we need to check that |d| <= Pi/2.
1228
+ // In fact, |d| < Pi/2 is enough because of the requirement that r < Pi/2.
1229
+ // The following expression represents cos(d) after scaling; it is
1230
+ // equivalent to (aXn).(bXn) but has about 30% less error.
1231
+ T cos_d = a.DotProd(b) * n2 - aDn * bDn;
1232
+ T cos_d_error =
1233
+ ((8 * DBL_ERR + 5 * T_ERR) * fabs(aDn) + aDn_error) * fabs(bDn) +
1234
+ (fabs(aDn) + aDn_error) * bDn_error + (8 * DBL_ERR + 8 * T_ERR) * n2;
1235
+ if (cos_d <= -cos_d_error) return Excluded::NEITHER;
1236
+
1237
+ // Potential optimization: if the sign of cos(d) is uncertain, then instead
1238
+ // we could check whether cos(d) >= cos(r). Unfortunately this is fairly
1239
+ // expensive since it requires computing denominator |aXn||bXn| of cos(d)
1240
+ // and the associated error bounds. In any case this case is relatively
1241
+ // rare so it seems better to punt.
1242
+ if (cos_d < cos_d_error) return Excluded::UNCERTAIN;
1243
+
1244
+ // Normally we have d > 0 because the sites are sorted so that A is closer
1245
+ // to X0 and B is closer to X1. However if the edge X is longer than Pi/2,
1246
+ // and the sites A and B are beyond its endpoints, then AB can wrap around
1247
+ // the sphere in the opposite direction from X. In this situation d < 0 but
1248
+ // each site is closest to one endpoint of X, so neither excludes the other.
1249
+ //
1250
+ // It turns out that this can happen only when the site that is further away
1251
+ // from edge X is less than 90 degrees away from whichever endpoint of X it
1252
+ // is closer to. It is provable that if this distance is less than 90
1253
+ // degrees, then it is also less than r2, and therefore the Voronoi regions
1254
+ // of both sites intersect the edge.
1255
+ if (sin_d < -sin_d_error) {
1256
+ T r90 = S1ChordAngle::Right().length2();
1257
+ // "ca" is negative if Voronoi region A definitely intersects edge X.
1258
+ int ca = (lhs3 < -lhs3_error) ? -1 : TriageCompareCosDistance(a, x0, r90);
1259
+ int cb = (lhs3 > lhs3_error) ? -1 : TriageCompareCosDistance(b, x1, r90);
1260
+ if (ca < 0 && cb < 0) return Excluded::NEITHER;
1261
+ if (ca <= 0 && cb <= 0) return Excluded::UNCERTAIN;
1262
+ if (abs_lhs3 <= lhs3_error) return Excluded::UNCERTAIN;
1263
+ } else if (sin_d <= sin_d_error) {
1264
+ return Excluded::UNCERTAIN;
1265
+ }
1266
+ // Now we can finish checking the results of predicate (3).
1267
+ if (result <= result_error) return Excluded::UNCERTAIN;
1268
+ S2_DCHECK_GT(abs_lhs3, lhs3_error);
1269
+ return (lhs3 > 0) ? Excluded::FIRST : Excluded::SECOND;
1270
+ }
1271
+
1272
+ Excluded ExactVoronoiSiteExclusion(const Vector3_xf& a, const Vector3_xf& b,
1273
+ const Vector3_xf& x0, const Vector3_xf& x1,
1274
+ const ExactFloat& r2) {
1275
+ S2_DCHECK(!ArePointsAntipodal(x0, x1));
1276
+
1277
+ // Recall that one site excludes the other if
1278
+ //
1279
+ // (1) |sin(rb - ra)| > sin(d)
1280
+ //
1281
+ // and that the sign of (rb - ra) determines which site is excluded (see the
1282
+ // comments in TriageVoronoiSiteExclusion). To evaluate this using exact
1283
+ // arithmetic, we expand this to the same predicate as before:
1284
+ //
1285
+ // (2) cos(r) ||a| sqrt(sin^2(r) |b|^2 |n|^2 - |b.n|^2) -
1286
+ // |b| sqrt(sin^2(r) |a|^2 |n|^2 - |a.n|^2)| > (aXb).n
1287
+ //
1288
+ // We also need to verify that d <= Pi/2, which is implemented by checking
1289
+ // that sin(d) >= 0 and cos(d) >= 0.
1290
+ //
1291
+ // To eliminate the square roots we use the standard technique of
1292
+ // rearranging the inequality to isolate at least one square root and then
1293
+ // squaring both sides. We need to repeat this process twice in order to
1294
+ // eliminate all the square roots, which leads to a polynomial predicate of
1295
+ // degree 20 in the input arguments (i.e., degree 4 in each of "a", "b",
1296
+ // "x0", "x1", and "r2").
1297
+ //
1298
+ // Before squaring we need to check the sign of each side. We also check
1299
+ // the condition that cos(d) >= 0. Given what else we need to compute, it
1300
+ // is cheaper use the identity (aXn).(bXn) = (a.b) |n|^2 - (a.n)(b.n) .
1301
+ Vector3_xf n = x0.CrossProd(x1);
1302
+ ExactFloat n2 = n.Norm2();
1303
+ ExactFloat aDn = a.DotProd(n);
1304
+ ExactFloat bDn = b.DotProd(n);
1305
+ ExactFloat cos_d = a.DotProd(b) * n2 - aDn * bDn;
1306
+ if (cos_d.sgn() < 0) return Excluded::NEITHER;
1307
+
1308
+ // Otherwise we continue evaluating the LHS of (2), defining
1309
+ // sa = |b| sqrt(sin^2(r) |a|^2 |n|^2 - |a.n|^2)
1310
+ // sb = |a| sqrt(sin^2(r) |b|^2 |n|^2 - |b.n|^2) .
1311
+ // The sign of the LHS of (2) (before taking the absolute value) determines
1312
+ // which coverage interval is larger and therefore which site is potentially
1313
+ // being excluded.
1314
+ ExactFloat a2 = a.Norm2();
1315
+ ExactFloat b2 = b.Norm2();
1316
+ ExactFloat n2sin2_r = r2 * (1 - 0.25 * r2) * n2;
1317
+ ExactFloat sa2 = b2 * (n2sin2_r * a2 - aDn * aDn);
1318
+ ExactFloat sb2 = a2 * (n2sin2_r * b2 - bDn * bDn);
1319
+ int lhs2_sgn = (sb2 - sa2).sgn();
1320
+
1321
+ // If the RHS of (2) is negative (corresponding to sin(d) < 0), then we need
1322
+ // to consider the possibility that the edge AB wraps around the sphere in
1323
+ // the opposite direction from edge X, with the result that neither site
1324
+ // excludes the other (see TriageVoronoiSiteExclusion).
1325
+ ExactFloat rhs2 = a.CrossProd(b).DotProd(n);
1326
+ int rhs2_sgn = rhs2.sgn();
1327
+ if (rhs2_sgn < 0) {
1328
+ ExactFloat r90 = S1ChordAngle::Right().length2();
1329
+ int ca = (lhs2_sgn < 0) ? -1 : ExactCompareDistance(a, x0, r90);
1330
+ int cb = (lhs2_sgn > 0) ? -1 : ExactCompareDistance(b, x1, r90);
1331
+ if (ca <= 0 && cb <= 0) return Excluded::NEITHER;
1332
+ S2_DCHECK(ca != 1 || cb != 1);
1333
+ return ca == 1 ? Excluded::FIRST : Excluded::SECOND;
1334
+ }
1335
+ if (lhs2_sgn == 0) {
1336
+ // If the RHS of (2) is zero as well (i.e., d == 0) then both sites are
1337
+ // equidistant from every point on edge X. This case requires symbolic
1338
+ // perturbations, but it should already have been handled in
1339
+ // GetVoronoiSiteExclusion() (see the call to CompareDistances).
1340
+ S2_DCHECK_GT(rhs2_sgn, 0);
1341
+ return Excluded::NEITHER;
1342
+ }
1343
+ // Next we square both sides of (2), yielding
1344
+ //
1345
+ // cos^2(r) (sb^2 + sa^2 - 2 sa sb) > (aXb.n)^2
1346
+ //
1347
+ // which can be rearranged to give
1348
+ //
1349
+ // (3) cos^2(r) (sb^2 + sa^2) - (aXb.n)^2 > 2 cos^2(r) sa sb .
1350
+ //
1351
+ // The RHS of (3) is always non-negative, but we still need to check the
1352
+ // sign of the LHS.
1353
+ ExactFloat cos_r = 1 - 0.5 * r2;
1354
+ ExactFloat cos2_r = cos_r * cos_r;
1355
+ ExactFloat lhs3 = cos2_r * (sa2 + sb2) - rhs2 * rhs2;
1356
+ if (lhs3.sgn() < 0) return Excluded::NEITHER;
1357
+
1358
+ // Otherwise we square both sides of (3) to obtain:
1359
+ //
1360
+ // (4) LHS(3)^2 > 4 cos^4(r) sa^2 sb^2
1361
+ ExactFloat lhs4 = lhs3 * lhs3;
1362
+ ExactFloat rhs4 = 4 * cos2_r * cos2_r * sa2 * sb2;
1363
+ int result = (lhs4 - rhs4).sgn();
1364
+ if (result < 0) return Excluded::NEITHER;
1365
+ if (result == 0) {
1366
+ // We have |rb - ra| = d and d > 0. This implies that one coverage
1367
+ // interval contains the other, but not properly: the two intervals share
1368
+ // a common endpoint. The distance from each site to that point is
1369
+ // exactly "r", therefore we need to use symbolic perturbations. Recall
1370
+ // that site A is considered closer to an equidistant point if and only if
1371
+ // A > B. Therefore if (rb > ra && A > B) or (ra > rb && B > A) then each
1372
+ // site is closer to at least one point and neither site is excluded.
1373
+ //
1374
+ // Ideally this logic would be in a separate SymbolicVoronoiSiteExclusion
1375
+ // method for better testing, but this is not convenient because it needs
1376
+ // lhs_sgn (which requires exact arithmetic to compute).
1377
+ if ((lhs2_sgn > 0) == (a > b)) return Excluded::NEITHER;
1378
+ }
1379
+ // At this point we know that one of the two sites is excluded. The sign of
1380
+ // the LHS of (2) (before the absolute value) determines which one.
1381
+ return (lhs2_sgn > 0) ? Excluded::FIRST : Excluded::SECOND;
1382
+ }
1383
+
1384
+ Excluded GetVoronoiSiteExclusion(const S2Point& a, const S2Point& b,
1385
+ const S2Point& x0, const S2Point& x1,
1386
+ S1ChordAngle r) {
1387
+ S2_DCHECK_LT(r, S1ChordAngle::Right());
1388
+ S2_DCHECK_LT(s2pred::CompareDistances(x0, a, b), 0); // (implies a != b)
1389
+ S2_DCHECK_LE(s2pred::CompareEdgeDistance(a, x0, x1, r), 0);
1390
+ S2_DCHECK_LE(s2pred::CompareEdgeDistance(b, x0, x1, r), 0);
1391
+ // Check that the edge does not consist of antipodal points. (This catches
1392
+ // the most common case -- the full test is in ExactVoronoiSiteExclusion.)
1393
+ S2_DCHECK_NE(x0, -x1);
1394
+
1395
+ // If one site is closer than the other to both endpoints of X, then it is
1396
+ // closer to every point on X. Note that this also handles the case where A
1397
+ // and B are equidistant from every point on X (i.e., X is the perpendicular
1398
+ // bisector of AB), because CompareDistances uses symbolic perturbations to
1399
+ // ensure that either A or B is considered closer (in a consistent way).
1400
+ // This also ensures that the choice of A or B does not depend on the
1401
+ // direction of X.
1402
+ if (s2pred::CompareDistances(x1, a, b) < 0) {
1403
+ return Excluded::SECOND; // Site A is closer to every point on X.
1404
+ }
1405
+
1406
+ Excluded result = TriageVoronoiSiteExclusion(a, b, x0, x1, r.length2());
1407
+ if (result != Excluded::UNCERTAIN) return result;
1408
+
1409
+ result = TriageVoronoiSiteExclusion(ToLD(a), ToLD(b), ToLD(x0), ToLD(x1),
1410
+ ToLD(r.length2()));
1411
+ if (result != Excluded::UNCERTAIN) return result;
1412
+
1413
+ return ExactVoronoiSiteExclusion(ToExact(a), ToExact(b), ToExact(x0),
1414
+ ToExact(x1), r.length2());
1415
+ }
1416
+
1417
+ std::ostream& operator<<(std::ostream& os, Excluded excluded) {
1418
+ switch (excluded) {
1419
+ case Excluded::FIRST: return os << "FIRST";
1420
+ case Excluded::SECOND: return os << "SECOND";
1421
+ case Excluded::NEITHER: return os << "NEITHER";
1422
+ case Excluded::UNCERTAIN: return os << "UNCERTAIN";
1423
+ default: return os << "Unknown enum value";
1424
+ }
1425
+ }
1426
+
1427
+ // Explicitly instantiate all of the template functions above so that the
1428
+ // tests can use them without putting all the definitions in a header file.
1429
+
1430
+ template int TriageCompareCosDistances<double>(
1431
+ const S2Point&, const S2Point&, const S2Point&);
1432
+
1433
+ template int TriageCompareCosDistances<long double>(
1434
+ const Vector3_ld&, const Vector3_ld&, const Vector3_ld&);
1435
+
1436
+ template int TriageCompareSin2Distances<double>(
1437
+ const S2Point&, const S2Point&, const S2Point&);
1438
+
1439
+ template int TriageCompareSin2Distances<long double>(
1440
+ const Vector3_ld&, const Vector3_ld&, const Vector3_ld&);
1441
+
1442
+ template int TriageCompareCosDistance<double>(
1443
+ const S2Point&, const S2Point&, double r2);
1444
+
1445
+ template int TriageCompareCosDistance<long double>(
1446
+ const Vector3_ld&, const Vector3_ld&, long double r2);
1447
+
1448
+ template int TriageCompareSin2Distance<double>(
1449
+ const S2Point&, const S2Point&, double r2);
1450
+
1451
+ template int TriageCompareSin2Distance<long double>(
1452
+ const Vector3_ld&, const Vector3_ld&, long double r2);
1453
+
1454
+ template int TriageCompareEdgeDistance<double>(
1455
+ const S2Point& x, const S2Point& a0, const S2Point& a1, double r2);
1456
+
1457
+ template int TriageCompareEdgeDistance<long double>(
1458
+ const Vector3_ld& x, const Vector3_ld& a0, const Vector3_ld& a1,
1459
+ long double r2);
1460
+
1461
+ template int TriageCompareEdgeDirections<double>(
1462
+ const S2Point& a0, const S2Point& a1,
1463
+ const S2Point& b0, const S2Point& b1);
1464
+
1465
+ template int TriageCompareEdgeDirections<long double>(
1466
+ const Vector3_ld& a0, const Vector3_ld& a1,
1467
+ const Vector3_ld& b0, const Vector3_ld& b1);
1468
+
1469
+ template int TriageEdgeCircumcenterSign<double>(
1470
+ const S2Point& x0, const S2Point& x1,
1471
+ const S2Point& a, const S2Point& b, const S2Point& c, int abc_sign);
1472
+
1473
+ template int TriageEdgeCircumcenterSign<long double>(
1474
+ const Vector3_ld& x0, const Vector3_ld& x1,
1475
+ const Vector3_ld& a, const Vector3_ld& b, const Vector3_ld& c,
1476
+ int abc_sign);
1477
+
1478
+ template Excluded TriageVoronoiSiteExclusion(
1479
+ const S2Point& a, const S2Point& b,
1480
+ const S2Point& x0, const S2Point& x1, double r2);
1481
+
1482
+ template Excluded TriageVoronoiSiteExclusion(
1483
+ const Vector3_ld& a, const Vector3_ld& b,
1484
+ const Vector3_ld& x0, const Vector3_ld& x1, long double r2);
1485
+
1486
+ } // namespace s2pred