@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,1569 @@
1
+ // Copyright 2005 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/s2polygon.h"
19
+
20
+ #include <algorithm>
21
+ #include <array>
22
+ #include <cmath>
23
+ #include <cstddef>
24
+ #include <set>
25
+ #include <stack>
26
+ #include <utility>
27
+ #include <vector>
28
+
29
+
30
+ #include "s2/base/casts.h"
31
+ #include "s2/base/commandlineflags.h"
32
+ #include "s2/base/logging.h"
33
+ #include "s2/mutable_s2shape_index.h"
34
+ #include "s2/s1angle.h"
35
+ #include "s2/s1interval.h"
36
+ #include "s2/s2boolean_operation.h"
37
+ #include "s2/s2builder.h"
38
+ #include "s2/s2builderutil_s2polygon_layer.h"
39
+ #include "s2/s2builderutil_s2polyline_layer.h"
40
+ #include "s2/s2builderutil_s2polyline_vector_layer.h"
41
+ #include "s2/s2builderutil_snap_functions.h"
42
+ #include "s2/s2cap.h"
43
+ #include "s2/s2cell.h"
44
+ #include "s2/s2cell_id.h"
45
+ #include "s2/s2cell_union.h"
46
+ #include "s2/s2closest_edge_query.h"
47
+ #include "s2/s2contains_point_query.h"
48
+ #include "s2/s2coords.h"
49
+ #include "s2/s2crossing_edge_query.h"
50
+ #include "s2/s2debug.h"
51
+ #include "s2/s2edge_clipping.h"
52
+ #include "s2/s2edge_crosser.h"
53
+ #include "s2/s2edge_crossings.h"
54
+ #include "s2/s2error.h"
55
+ #include "s2/s2latlng.h"
56
+ #include "s2/s2latlng_rect.h"
57
+ #include "s2/s2latlng_rect_bounder.h"
58
+ #include "s2/s2loop.h"
59
+ #include "s2/s2measures.h"
60
+ #include "s2/s2metrics.h"
61
+ #include "s2/s2point_compression.h"
62
+ #include "s2/s2polyline.h"
63
+ #include "s2/s2predicates.h"
64
+ #include "s2/s2shape_index.h"
65
+ #include "s2/s2shape_index_region.h"
66
+ #include "s2/s2shapeutil_visit_crossing_edge_pairs.h"
67
+ #include "s2/third_party/absl/container/fixed_array.h"
68
+ #include "s2/third_party/absl/container/inlined_vector.h"
69
+ #include "s2/third_party/absl/memory/memory.h"
70
+ #include "s2/util/coding/coder.h"
71
+
72
+ using absl::make_unique;
73
+ using s2builderutil::IdentitySnapFunction;
74
+ using s2builderutil::S2PolygonLayer;
75
+ using s2builderutil::S2PolylineLayer;
76
+ using s2builderutil::S2PolylineVectorLayer;
77
+ using s2builderutil::S2CellIdSnapFunction;
78
+ using std::fabs;
79
+ using std::max;
80
+ using std::min;
81
+ using std::pair;
82
+ using std::set;
83
+ using std::sqrt;
84
+ using std::unique_ptr;
85
+ using std::vector;
86
+
87
+ S2_DEFINE_bool(
88
+ s2polygon_lazy_indexing, true,
89
+ "Build the S2ShapeIndex only when it is first needed. This can save "
90
+ "significant amounts of memory and time when geometry is constructed but "
91
+ "never queried, for example when converting from one format to another.");
92
+
93
+ // The maximum number of loops we'll allow when decoding a polygon.
94
+ // The default value of 10 million is 200x bigger than the number of
95
+ S2_DEFINE_int32(
96
+ s2polygon_decode_max_num_loops, 10000000,
97
+ "The upper limit on the number of loops that are allowed by the "
98
+ "S2Polygon::Decode method.");
99
+
100
+ // When adding a new encoding, be aware that old binaries will not
101
+ // be able to decode it.
102
+ static const unsigned char kCurrentUncompressedEncodingVersionNumber = 1;
103
+ static const unsigned char kCurrentCompressedEncodingVersionNumber = 4;
104
+
105
+ S2Polygon::S2Polygon()
106
+ : s2debug_override_(S2Debug::ALLOW),
107
+ error_inconsistent_loop_orientations_(false),
108
+ num_vertices_(0),
109
+ unindexed_contains_calls_(0) {
110
+ }
111
+
112
+ S2Polygon::S2Polygon(vector<unique_ptr<S2Loop>> loops, S2Debug override)
113
+ : s2debug_override_(override) {
114
+ InitNested(std::move(loops));
115
+ }
116
+
117
+ S2Polygon::S2Polygon(unique_ptr<S2Loop> loop, S2Debug override)
118
+ : s2debug_override_(override) {
119
+ Init(std::move(loop));
120
+ }
121
+
122
+ S2Polygon::S2Polygon(const S2Cell& cell)
123
+ : s2debug_override_(S2Debug::ALLOW) {
124
+ Init(make_unique<S2Loop>(cell));
125
+ }
126
+
127
+ void S2Polygon::set_s2debug_override(S2Debug override) {
128
+ s2debug_override_ = override;
129
+ }
130
+
131
+ S2Debug S2Polygon::s2debug_override() const {
132
+ return s2debug_override_;
133
+ }
134
+
135
+ void S2Polygon::Copy(const S2Polygon* src) {
136
+ ClearLoops();
137
+ for (int i = 0; i < src->num_loops(); ++i) {
138
+ loops_.emplace_back(src->loop(i)->Clone());
139
+ }
140
+ s2debug_override_ = src->s2debug_override_;
141
+ // Don't copy error_inconsistent_loop_orientations_, since this is not a
142
+ // property of the polygon but only of the way the polygon was constructed.
143
+ num_vertices_ = src->num_vertices();
144
+ unindexed_contains_calls_.store(0, std::memory_order_relaxed);
145
+ bound_ = src->bound_;
146
+ subregion_bound_ = src->subregion_bound_;
147
+ InitIndex(); // TODO(ericv): Copy the index efficiently.
148
+ }
149
+
150
+ S2Polygon* S2Polygon::Clone() const {
151
+ S2Polygon* result = new S2Polygon;
152
+ result->Copy(this);
153
+ return result;
154
+ }
155
+
156
+ vector<unique_ptr<S2Loop>> S2Polygon::Release() {
157
+ // Reset the polygon to be empty.
158
+ vector<unique_ptr<S2Loop>> loops;
159
+ loops.swap(loops_);
160
+ ClearLoops();
161
+ num_vertices_ = 0;
162
+ bound_ = S2LatLngRect::Empty();
163
+ subregion_bound_ = S2LatLngRect::Empty();
164
+ return loops;
165
+ }
166
+
167
+ void S2Polygon::ClearLoops() {
168
+ ClearIndex();
169
+ loops_.clear();
170
+ error_inconsistent_loop_orientations_ = false;
171
+ }
172
+
173
+ S2Polygon::~S2Polygon() {
174
+ ClearLoops();
175
+ }
176
+
177
+ bool S2Polygon::IsValid() const {
178
+ S2Error error;
179
+ if (FindValidationError(&error)) {
180
+ S2_LOG_IF(ERROR, FLAGS_s2debug) << error;
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+
186
+ bool S2Polygon::FindValidationError(S2Error* error) const {
187
+ for (int i = 0; i < num_loops(); ++i) {
188
+ // Check for loop errors that don't require building an S2ShapeIndex.
189
+ if (loop(i)->FindValidationErrorNoIndex(error)) {
190
+ error->Init(error->code(),
191
+ "Loop %d: %s", i, error->text().c_str());
192
+ return true;
193
+ }
194
+ // Check that no loop is empty, and that the full loop only appears in the
195
+ // full polygon.
196
+ if (loop(i)->is_empty()) {
197
+ error->Init(S2Error::POLYGON_EMPTY_LOOP,
198
+ "Loop %d: empty loops are not allowed", i);
199
+ return true;
200
+ }
201
+ if (loop(i)->is_full() && num_loops() > 1) {
202
+ error->Init(S2Error::POLYGON_EXCESS_FULL_LOOP,
203
+ "Loop %d: full loop appears in non-full polygon", i);
204
+ return true;
205
+ }
206
+ }
207
+
208
+ // Check for loop self-intersections and loop pairs that cross
209
+ // (including duplicate edges and vertices).
210
+ if (s2shapeutil::FindSelfIntersection(index_, error)) return true;
211
+
212
+ // Check whether InitOriented detected inconsistent loop orientations.
213
+ if (error_inconsistent_loop_orientations_) {
214
+ error->Init(S2Error::POLYGON_INCONSISTENT_LOOP_ORIENTATIONS,
215
+ "Inconsistent loop orientations detected");
216
+ return true;
217
+ }
218
+
219
+ // Finally, verify the loop nesting hierarchy.
220
+ return FindLoopNestingError(error);
221
+ }
222
+
223
+ bool S2Polygon::FindLoopNestingError(S2Error* error) const {
224
+ // First check that the loop depths make sense.
225
+ for (int last_depth = -1, i = 0; i < num_loops(); ++i) {
226
+ int depth = loop(i)->depth();
227
+ if (depth < 0 || depth > last_depth + 1) {
228
+ error->Init(S2Error::POLYGON_INVALID_LOOP_DEPTH,
229
+ "Loop %d: invalid loop depth (%d)", i, depth);
230
+ return true;
231
+ }
232
+ last_depth = depth;
233
+ }
234
+ // Then check that they correspond to the actual loop nesting. This test
235
+ // is quadratic in the number of loops but the cost per iteration is small.
236
+ for (int i = 0; i < num_loops(); ++i) {
237
+ int last = GetLastDescendant(i);
238
+ for (int j = 0; j < num_loops(); ++j) {
239
+ if (i == j) continue;
240
+ bool nested = (j >= i + 1) && (j <= last);
241
+ const bool reverse_b = false;
242
+ if (loop(i)->ContainsNonCrossingBoundary(loop(j), reverse_b) != nested) {
243
+ error->Init(S2Error::POLYGON_INVALID_LOOP_NESTING,
244
+ "Invalid nesting: loop %d should %scontain loop %d",
245
+ i, nested ? "" : "not ", j);
246
+ return true;
247
+ }
248
+ }
249
+ }
250
+ return false;
251
+ }
252
+
253
+ void S2Polygon::InsertLoop(S2Loop* new_loop, S2Loop* parent,
254
+ LoopMap* loop_map) {
255
+ vector<S2Loop*>* children;
256
+ for (bool done = false; !done; ) {
257
+ children = &(*loop_map)[parent];
258
+ done = true;
259
+ for (S2Loop* child : *children) {
260
+ if (child->ContainsNested(new_loop)) {
261
+ parent = child;
262
+ done = false;
263
+ break;
264
+ }
265
+ }
266
+ }
267
+
268
+ // Some of the children of the parent loop may now be children of
269
+ // the new loop.
270
+ vector<S2Loop*>* new_children = &(*loop_map)[new_loop];
271
+ for (int i = 0; i < children->size();) {
272
+ S2Loop* child = (*children)[i];
273
+ if (new_loop->ContainsNested(child)) {
274
+ new_children->push_back(child);
275
+ children->erase(children->begin() + i);
276
+ } else {
277
+ ++i;
278
+ }
279
+ }
280
+ children->push_back(new_loop);
281
+ }
282
+
283
+ void S2Polygon::InitLoops(LoopMap* loop_map) {
284
+ std::stack<S2Loop*> loop_stack({nullptr});
285
+ int depth = -1;
286
+ while (!loop_stack.empty()) {
287
+ S2Loop* loop = loop_stack.top();
288
+ loop_stack.pop();
289
+ if (loop != nullptr) {
290
+ depth = loop->depth();
291
+ loops_.emplace_back(loop);
292
+ }
293
+ const vector<S2Loop*>& children = (*loop_map)[loop];
294
+ for (int i = children.size() - 1; i >= 0; --i) {
295
+ S2Loop* child = children[i];
296
+ S2_DCHECK(child != nullptr);
297
+ child->set_depth(depth + 1);
298
+ loop_stack.push(child);
299
+ }
300
+ }
301
+ }
302
+
303
+ void S2Polygon::InitIndex() {
304
+ S2_DCHECK_EQ(0, index_.num_shape_ids());
305
+ index_.Add(make_unique<Shape>(this));
306
+ if (!FLAGS_s2polygon_lazy_indexing) {
307
+ index_.ForceBuild();
308
+ }
309
+ if (FLAGS_s2debug && s2debug_override_ == S2Debug::ALLOW) {
310
+ // Note that FLAGS_s2debug is false in optimized builds (by default).
311
+ S2_CHECK(IsValid());
312
+ }
313
+ }
314
+
315
+ void S2Polygon::ClearIndex() {
316
+ unindexed_contains_calls_.store(0, std::memory_order_relaxed);
317
+ index_.Clear();
318
+ }
319
+
320
+ void S2Polygon::InitNested(vector<unique_ptr<S2Loop>> loops) {
321
+ ClearLoops();
322
+ loops_.swap(loops);
323
+
324
+ if (num_loops() == 1) {
325
+ InitOneLoop();
326
+ return;
327
+ }
328
+ LoopMap loop_map;
329
+ for (int i = 0; i < num_loops(); ++i) {
330
+ InsertLoop(loop(i), nullptr, &loop_map);
331
+ }
332
+ // Reorder the loops in depth-first traversal order.
333
+ // Loops are now owned by loop_map, don't let them be
334
+ // deleted by clear().
335
+ for (auto& loop : loops_) loop.release();
336
+ loops_.clear();
337
+ InitLoops(&loop_map);
338
+
339
+ // Compute num_vertices_, bound_, subregion_bound_.
340
+ InitLoopProperties();
341
+ }
342
+
343
+ void S2Polygon::Init(unique_ptr<S2Loop> loop) {
344
+ // We don't allow empty loops in the other Init() methods because deleting
345
+ // them changes the number of loops, which is awkward to handle.
346
+ ClearLoops();
347
+ if (loop->is_empty()) {
348
+ InitLoopProperties();
349
+ } else {
350
+ loops_.push_back(std::move(loop));
351
+ InitOneLoop();
352
+ }
353
+ }
354
+
355
+ // This is an internal method that expects that loops_ has already been
356
+ // initialized with a single non-empty loop.
357
+ void S2Polygon::InitOneLoop() {
358
+ S2_DCHECK_EQ(1, num_loops());
359
+ S2Loop* loop = loops_[0].get();
360
+ loop->set_depth(0);
361
+ error_inconsistent_loop_orientations_ = false;
362
+ num_vertices_ = loop->num_vertices();
363
+ bound_ = loop->GetRectBound();
364
+ subregion_bound_ = S2LatLngRectBounder::ExpandForSubregions(bound_);
365
+ InitIndex();
366
+ }
367
+
368
+ void S2Polygon::InitOriented(vector<unique_ptr<S2Loop>> loops) {
369
+ // Here is the algorithm:
370
+ //
371
+ // 1. Remember which of the given loops contain S2::Origin().
372
+ //
373
+ // 2. Invert loops as necessary to ensure that they are nestable (i.e., no
374
+ // loop contains the complement of any other loop). This may result in a
375
+ // set of loops corresponding to the complement of the given polygon, but
376
+ // we will fix that problem later.
377
+ //
378
+ // We make the loops nestable by first normalizing all the loops (i.e.,
379
+ // inverting any loops whose curvature is negative). This handles
380
+ // all loops except those whose curvature is very close to zero
381
+ // (within the maximum error tolerance). Any such loops are inverted if
382
+ // and only if they contain S2::Origin(). (In theory this step is only
383
+ // necessary if there are at least two such loops.) The resulting set of
384
+ // loops is guaranteed to be nestable.
385
+ //
386
+ // 3. Build the polygon. This yields either the desired polygon or its
387
+ // complement.
388
+ //
389
+ // 4. If there is at least one loop, we find a loop L that is adjacent to
390
+ // S2::Origin() (where "adjacent" means that there exists a path
391
+ // connecting S2::Origin() to some vertex of L such that the path does
392
+ // not cross any loop). There may be a single such adjacent loop, or
393
+ // there may be several (in which case they should all have the same
394
+ // contains_origin() value). We choose L to be the loop containing the
395
+ // origin whose depth is greatest, or loop(0) (a top-level shell) if no
396
+ // such loop exists.
397
+ //
398
+ // 5. If (L originally contained origin) != (polygon contains origin), we
399
+ // invert the polygon. This is done by inverting a top-level shell whose
400
+ // curvature is minimal and then fixing the nesting hierarchy. Note
401
+ // that because we normalized all the loops initially, this step is only
402
+ // necessary if the polygon requires at least one non-normalized loop to
403
+ // represent it.
404
+
405
+ set<const S2Loop*> contained_origin;
406
+ for (int i = 0; i < loops.size(); ++i) {
407
+ S2Loop* loop = loops[i].get();
408
+ if (loop->contains_origin()) {
409
+ contained_origin.insert(loop);
410
+ }
411
+ double angle = loop->GetCurvature();
412
+ if (fabs(angle) > loop->GetCurvatureMaxError()) {
413
+ // Normalize the loop.
414
+ if (angle < 0) loop->Invert();
415
+ } else {
416
+ // Ensure that the loop does not contain the origin.
417
+ if (loop->contains_origin()) loop->Invert();
418
+ }
419
+ }
420
+ InitNested(std::move(loops));
421
+ if (num_loops() > 0) {
422
+ S2Loop* origin_loop = loop(0);
423
+ bool polygon_contains_origin = false;
424
+ for (int i = 0; i < num_loops(); ++i) {
425
+ if (loop(i)->contains_origin()) {
426
+ polygon_contains_origin ^= true;
427
+ origin_loop = loop(i);
428
+ }
429
+ }
430
+ if (contained_origin.count(origin_loop) != polygon_contains_origin) {
431
+ Invert();
432
+ }
433
+ }
434
+ // Verify that the original loops had consistent shell/hole orientations.
435
+ // Each original loop L should have been inverted if and only if it now
436
+ // represents a hole.
437
+ for (int i = 0; i < loops_.size(); ++i) {
438
+ if ((contained_origin.count(loop(i)) != loop(i)->contains_origin()) !=
439
+ loop(i)->is_hole()) {
440
+ // There is no point in saving the loop index, because the error is a
441
+ // property of the entire set of loops. In general there is no way to
442
+ // determine which ones are incorrect.
443
+ error_inconsistent_loop_orientations_ = true;
444
+ if (FLAGS_s2debug && s2debug_override_ == S2Debug::ALLOW) {
445
+ // The FLAGS_s2debug validity checking usually happens in InitIndex(),
446
+ // but this error is detected too late for that.
447
+ S2_CHECK(IsValid()); // Always fails.
448
+ }
449
+ }
450
+ }
451
+ }
452
+
453
+ void S2Polygon::InitLoopProperties() {
454
+ num_vertices_ = 0;
455
+ bound_ = S2LatLngRect::Empty();
456
+ for (int i = 0; i < num_loops(); ++i) {
457
+ if (loop(i)->depth() == 0) {
458
+ bound_ = bound_.Union(loop(i)->GetRectBound());
459
+ }
460
+ num_vertices_ += loop(i)->num_vertices();
461
+ }
462
+ subregion_bound_ = S2LatLngRectBounder::ExpandForSubregions(bound_);
463
+ InitIndex();
464
+ }
465
+
466
+ int S2Polygon::GetParent(int k) const {
467
+ int depth = loop(k)->depth();
468
+ if (depth == 0) return -1; // Optimization.
469
+ while (--k >= 0 && loop(k)->depth() >= depth) continue;
470
+ return k;
471
+ }
472
+
473
+ int S2Polygon::GetLastDescendant(int k) const {
474
+ if (k < 0) return num_loops() - 1;
475
+ int depth = loop(k)->depth();
476
+ while (++k < num_loops() && loop(k)->depth() > depth) continue;
477
+ return k - 1;
478
+ }
479
+
480
+ double S2Polygon::GetArea() const {
481
+ double area = 0;
482
+ for (int i = 0; i < num_loops(); ++i) {
483
+ area += loop(i)->sign() * loop(i)->GetArea();
484
+ }
485
+ return area;
486
+ }
487
+
488
+ S2Point S2Polygon::GetCentroid() const {
489
+ S2Point centroid;
490
+ for (int i = 0; i < num_loops(); ++i) {
491
+ centroid += loop(i)->sign() * loop(i)->GetCentroid();
492
+ }
493
+ return centroid;
494
+ }
495
+
496
+ int S2Polygon::GetSnapLevel() const {
497
+ int snap_level = -1;
498
+ for (const unique_ptr<S2Loop>& child : loops_) {
499
+ for (int j = 0; j < child->num_vertices(); ++j) {
500
+ int face;
501
+ unsigned int si, ti;
502
+ int level = S2::XYZtoFaceSiTi(child->vertex(j), &face, &si, &ti);
503
+ if (level < 0) return level; // Vertex is not a cell center.
504
+ if (level != snap_level) {
505
+ if (snap_level < 0) {
506
+ snap_level = level; // First vertex.
507
+ } else {
508
+ return -1; // Vertices at more than one cell level.
509
+ }
510
+ }
511
+ }
512
+ }
513
+ return snap_level;
514
+ }
515
+
516
+ S1Angle S2Polygon::GetDistance(const S2Point& x) const {
517
+ // Note that S2Polygon::Contains(S2Point) is slightly more efficient than
518
+ // the generic version used by S2ClosestEdgeQuery.
519
+ if (Contains(x)) return S1Angle::Zero();
520
+ return GetDistanceToBoundary(x);
521
+ }
522
+
523
+ S1Angle S2Polygon::GetDistanceToBoundary(const S2Point& x) const {
524
+ S2ClosestEdgeQuery::Options options;
525
+ options.set_include_interiors(false);
526
+ S2ClosestEdgeQuery::PointTarget t(x);
527
+ return S2ClosestEdgeQuery(&index_, options).GetDistance(&t).ToAngle();
528
+ }
529
+
530
+ /*static*/ pair<double, double> S2Polygon::GetOverlapFractions(
531
+ const S2Polygon* a, const S2Polygon* b) {
532
+ S2Polygon intersection;
533
+ intersection.InitToIntersection(a, b);
534
+ double intersection_area = intersection.GetArea();
535
+ double a_area = a->GetArea();
536
+ double b_area = b->GetArea();
537
+ return std::make_pair(
538
+ intersection_area >= a_area ? 1 : intersection_area / a_area,
539
+ intersection_area >= b_area ? 1 : intersection_area / b_area);
540
+ }
541
+
542
+ S2Point S2Polygon::Project(const S2Point& x) const {
543
+ if (Contains(x)) return x;
544
+ return ProjectToBoundary(x);
545
+ }
546
+
547
+ S2Point S2Polygon::ProjectToBoundary(const S2Point& x) const {
548
+ S2ClosestEdgeQuery::Options options;
549
+ options.set_include_interiors(false);
550
+ S2ClosestEdgeQuery q(&index_, options);
551
+ S2ClosestEdgeQuery::PointTarget target(x);
552
+ S2ClosestEdgeQuery::Result edge = q.FindClosestEdge(&target);
553
+ return q.Project(x, edge);
554
+ }
555
+
556
+ bool S2Polygon::Contains(const S2Polygon* b) const {
557
+ // It's worth checking bounding rectangles, since they are precomputed.
558
+ // Note that the first bound has been expanded to account for possible
559
+ // numerical errors in the second bound.
560
+ if (!subregion_bound_.Contains(b->bound_)) {
561
+ // It is possible that A contains B even though Bound(A) does not contain
562
+ // Bound(B). This can only happen when polygon B has at least two outer
563
+ // shells and the union of the two bounds spans all longitudes. For
564
+ // example, suppose that B consists of two shells with a longitude gap
565
+ // between them, while A consists of one shell that surrounds both shells
566
+ // of B but goes the other way around the sphere (so that it does not
567
+ // intersect the longitude gap).
568
+ //
569
+ // For convenience we just check whether B has at least two loops rather
570
+ // than two outer shells.
571
+ if (b->num_loops() == 1 || !bound_.lng().Union(b->bound_.lng()).is_full()) {
572
+ return false;
573
+ }
574
+ }
575
+
576
+ // The following case is not handled by S2BooleanOperation because it only
577
+ // determines whether the boundary of the result is empty (which does not
578
+ // distinguish between the full and empty polygons).
579
+ if (is_empty() && b->is_full()) return false;
580
+
581
+ return S2BooleanOperation::Contains(index_, b->index_);
582
+ }
583
+
584
+ bool S2Polygon::Intersects(const S2Polygon* b) const {
585
+ // It's worth checking bounding rectangles, since they are precomputed.
586
+ if (!bound_.Intersects(b->bound_)) return false;
587
+
588
+ // The following case is not handled by S2BooleanOperation because it only
589
+ // determines whether the boundary of the result is empty (which does not
590
+ // distinguish between the full and empty polygons).
591
+ if (is_full() && b->is_full()) return true;
592
+
593
+ return S2BooleanOperation::Intersects(index_, b->index_);
594
+ }
595
+
596
+ S2Cap S2Polygon::GetCapBound() const {
597
+ return bound_.GetCapBound();
598
+ }
599
+
600
+ void S2Polygon::GetCellUnionBound(vector<S2CellId> *cell_ids) const {
601
+ return MakeS2ShapeIndexRegion(&index_).GetCellUnionBound(cell_ids);
602
+ }
603
+
604
+ bool S2Polygon::Contains(const S2Cell& target) const {
605
+ return MakeS2ShapeIndexRegion(&index_).Contains(target);
606
+ }
607
+
608
+ bool S2Polygon::ApproxContains(const S2Polygon* b, S1Angle tolerance) const {
609
+ S2Polygon difference;
610
+ difference.InitToApproxDifference(b, this, tolerance);
611
+ return difference.is_empty();
612
+ }
613
+
614
+ bool S2Polygon::ApproxDisjoint(const S2Polygon* b, S1Angle tolerance) const {
615
+ S2Polygon intersection;
616
+ intersection.InitToApproxIntersection(b, this, tolerance);
617
+ return intersection.is_empty();
618
+ }
619
+
620
+ bool S2Polygon::ApproxEquals(const S2Polygon* b, S1Angle tolerance) const {
621
+ // TODO(ericv): This can be implemented more cheaply with S2Builder, by
622
+ // simply adding all the edges from one polygon, adding the reversed edge
623
+ // from the other polygon, and turning on the options to split edges and
624
+ // discard sibling pairs. Then the polygons are approximately equal if the
625
+ // output graph has no edges.
626
+ S2Polygon symmetric_difference;
627
+ symmetric_difference.InitToApproxSymmetricDifference(b, this, tolerance);
628
+ return symmetric_difference.is_empty();
629
+ }
630
+
631
+ bool S2Polygon::MayIntersect(const S2Cell& target) const {
632
+ return MakeS2ShapeIndexRegion(&index_).MayIntersect(target);
633
+ }
634
+
635
+ bool S2Polygon::Contains(const S2Point& p) const {
636
+ // NOTE(ericv): A bounds check slows down this function by about 50%. It is
637
+ // worthwhile only when it might allow us to delay building the index.
638
+ if (!index_.is_fresh() && !bound_.Contains(p)) return false;
639
+
640
+ // For small polygons it is faster to just check all the crossings.
641
+ // Otherwise we keep track of the number of calls to Contains() and only
642
+ // build the index once enough calls have been made so that we think it is
643
+ // worth the effort. See S2Loop::Contains(S2Point) for detailed comments.
644
+ static const int kMaxBruteForceVertices = 32;
645
+ static const int kMaxUnindexedContainsCalls = 20;
646
+ if (num_vertices() <= kMaxBruteForceVertices ||
647
+ (!index_.is_fresh() &&
648
+ ++unindexed_contains_calls_ != kMaxUnindexedContainsCalls)) {
649
+ bool inside = false;
650
+ for (int i = 0; i < num_loops(); ++i) {
651
+ // Use brute force to avoid building the loop's S2ShapeIndex.
652
+ inside ^= loop(i)->BruteForceContains(p);
653
+ }
654
+ return inside;
655
+ }
656
+ // Otherwise we look up the S2ShapeIndex cell containing this point.
657
+ return MakeS2ContainsPointQuery(&index_).Contains(p);
658
+ }
659
+
660
+ void S2Polygon::Encode(Encoder* const encoder) const {
661
+ if (num_vertices_ == 0) {
662
+ EncodeCompressed(encoder, nullptr, S2::kMaxCellLevel);
663
+ return;
664
+ }
665
+ // Converts all the polygon vertices to S2XYZFaceSiTi format.
666
+ absl::FixedArray<S2XYZFaceSiTi> all_vertices(num_vertices_);
667
+ S2XYZFaceSiTi* current_loop_vertices = all_vertices.data();
668
+ for (const unique_ptr<S2Loop>& loop : loops_) {
669
+ loop->GetXYZFaceSiTiVertices(current_loop_vertices);
670
+ current_loop_vertices += loop->num_vertices();
671
+ }
672
+ // Computes a histogram of the cell levels at which the vertices are snapped.
673
+ // cell_level is -1 for unsnapped, or 0 through kMaxCellLevel if snapped,
674
+ // so we add one to it to get a non-negative index. (histogram[0] is the
675
+ // number of unsnapped vertices, histogram[i] the number of vertices
676
+ // snapped at level i-1).
677
+ std::array<int, S2::kMaxCellLevel + 2> histogram;
678
+ histogram.fill(0);
679
+ for (const auto& v : all_vertices) {
680
+ histogram[v.cell_level + 1] += 1;
681
+ }
682
+ // Compute the level at which most of the vertices are snapped.
683
+ // If multiple levels have the same maximum number of vertices
684
+ // snapped to it, the first one (lowest level number / largest
685
+ // area / smallest encoding length) will be chosen, so this
686
+ // is desired. Start with histogram[1] since histogram[0] is
687
+ // the number of unsnapped vertices, which we don't care about.
688
+ const auto max_iter =
689
+ std::max_element(histogram.begin() + 1, histogram.end());
690
+ // snap_level will be at position histogram[snap_level + 1], see above.
691
+ const int snap_level = max_iter - (histogram.begin() + 1);
692
+ const int num_snapped = *max_iter;
693
+ // Choose an encoding format based on the number of unsnapped vertices and a
694
+ // rough estimate of the encoded sizes.
695
+
696
+ // The compressed encoding requires approximately 4 bytes per vertex plus
697
+ // "exact_point_size" for each unsnapped vertex (encoded as an S2Point plus
698
+ // the index at which it is located).
699
+ int exact_point_size = sizeof(S2Point) + 2;
700
+ int num_unsnapped = num_vertices_ - num_snapped;
701
+ int compressed_size = 4 * num_vertices_ + exact_point_size * num_unsnapped;
702
+ int lossless_size = sizeof(S2Point) * num_vertices_;
703
+ if (compressed_size < lossless_size) {
704
+ EncodeCompressed(encoder, all_vertices.data(), snap_level);
705
+ } else {
706
+ EncodeUncompressed(encoder);
707
+ }
708
+ }
709
+
710
+ void S2Polygon::EncodeUncompressed(Encoder* const encoder) const {
711
+ encoder->Ensure(10); // Sufficient
712
+ encoder->put8(kCurrentUncompressedEncodingVersionNumber);
713
+ // This code used to write "owns_loops_", so write "true" for compatibility.
714
+ encoder->put8(true);
715
+ // Encode obsolete "has_holes_" field for backwards compatibility.
716
+ bool has_holes = false;
717
+ for (int i = 0; i < num_loops(); ++i) {
718
+ if (loop(i)->is_hole()) has_holes = true;
719
+ }
720
+ encoder->put8(has_holes);
721
+ encoder->put32(loops_.size());
722
+ S2_DCHECK_GE(encoder->avail(), 0);
723
+
724
+ for (int i = 0; i < num_loops(); ++i) {
725
+ loop(i)->Encode(encoder);
726
+ }
727
+ bound_.Encode(encoder);
728
+ }
729
+
730
+ bool S2Polygon::Decode(Decoder* const decoder) {
731
+ if (decoder->avail() < sizeof(unsigned char)) return false;
732
+ unsigned char version = decoder->get8();
733
+ switch (version) {
734
+ case kCurrentUncompressedEncodingVersionNumber:
735
+ return DecodeUncompressed(decoder, false);
736
+ case kCurrentCompressedEncodingVersionNumber:
737
+ return DecodeCompressed(decoder);
738
+ }
739
+ return false;
740
+ }
741
+
742
+ bool S2Polygon::DecodeWithinScope(Decoder* const decoder) {
743
+ if (decoder->avail() < sizeof(unsigned char)) return false;
744
+ unsigned char version = decoder->get8();
745
+ switch (version) {
746
+ case kCurrentUncompressedEncodingVersionNumber:
747
+ return DecodeUncompressed(decoder, true);
748
+ case kCurrentCompressedEncodingVersionNumber:
749
+ return DecodeCompressed(decoder);
750
+ }
751
+ return false;
752
+ }
753
+
754
+ bool S2Polygon::DecodeUncompressed(Decoder* const decoder, bool within_scope) {
755
+ if (decoder->avail() < 2 * sizeof(uint8) + sizeof(uint32)) return false;
756
+ ClearLoops();
757
+ decoder->get8(); // Ignore irrelevant serialized owns_loops_ value.
758
+ decoder->get8(); // Ignore irrelevant serialized has_holes_ value.
759
+ // Polygons with no loops are explicitly allowed here: a newly created
760
+ // polygon has zero loops and such polygons encode and decode properly.
761
+ const uint32 num_loops = decoder->get32();
762
+ if (num_loops > FLAGS_s2polygon_decode_max_num_loops) return false;
763
+ loops_.reserve(num_loops);
764
+ num_vertices_ = 0;
765
+ for (int i = 0; i < num_loops; ++i) {
766
+ loops_.push_back(make_unique<S2Loop>());
767
+ loops_.back()->set_s2debug_override(s2debug_override());
768
+ if (within_scope) {
769
+ if (!loops_.back()->DecodeWithinScope(decoder)) return false;
770
+ } else {
771
+ if (!loops_.back()->Decode(decoder)) return false;
772
+ }
773
+ num_vertices_ += loops_.back()->num_vertices();
774
+ }
775
+ if (!bound_.Decode(decoder)) return false;
776
+ subregion_bound_ = S2LatLngRectBounder::ExpandForSubregions(bound_);
777
+ InitIndex();
778
+ return true;
779
+ }
780
+
781
+ // TODO(ericv): Consider adding this to the S2Loop API. (May also want an
782
+ // undirected version (CompareDirected vs CompareUndirected); should they
783
+ // return a sign, or have separate "<" and "==" methods?)
784
+ int S2Polygon::CompareLoops(const S2Loop* a, const S2Loop* b) {
785
+ if (a->num_vertices() != b->num_vertices()) {
786
+ return a->num_vertices() - b->num_vertices();
787
+ }
788
+ S2::LoopOrder ao = a->GetCanonicalLoopOrder();
789
+ S2::LoopOrder bo = b->GetCanonicalLoopOrder();
790
+ if (ao.dir != bo.dir) return ao.dir - bo.dir;
791
+ for (int n = a->num_vertices(), ai = ao.first, bi = bo.first;
792
+ --n >= 0; ai += ao.dir, bi += bo.dir) {
793
+ if (a->vertex(ai) < b->vertex(bi)) return -1;
794
+ if (a->vertex(ai) > b->vertex(bi)) return 1;
795
+ }
796
+ return 0;
797
+ }
798
+
799
+ void S2Polygon::Invert() {
800
+ // Inverting any one loop will invert the polygon. The best loop to invert
801
+ // is the one whose area is largest, since this yields the smallest area
802
+ // after inversion. The loop with the largest area is always at depth 0.
803
+ // The descendents of this loop all have their depth reduced by 1, while the
804
+ // former siblings of this loop all have their depth increased by 1.
805
+
806
+ // The empty and full polygons are handled specially.
807
+ if (is_empty()) {
808
+ loops_.push_back(make_unique<S2Loop>(S2Loop::kFull()));
809
+ } else if (is_full()) {
810
+ ClearLoops();
811
+ } else {
812
+ // Find the loop whose area is largest (i.e., whose curvature is
813
+ // smallest), minimizing calls to GetCurvature(). In particular, for
814
+ // polygons with a single shell at level 0 there is not need to call
815
+ // GetCurvature() at all. (This method is relatively expensive.)
816
+ int best = 0;
817
+ const double kNone = 10.0; // Flag that means "not computed yet"
818
+ double best_angle = kNone;
819
+ for (int i = 1; i < num_loops(); ++i) {
820
+ if (loop(i)->depth() == 0) {
821
+ // We defer computing the curvature of loop 0 until we discover
822
+ // that the polygon has another top-level shell.
823
+ if (best_angle == kNone) best_angle = loop(best)->GetCurvature();
824
+ double angle = loop(i)->GetCurvature();
825
+ // We break ties deterministically in order to avoid having the output
826
+ // depend on the input order of the loops.
827
+ if (angle < best_angle ||
828
+ (angle == best_angle && CompareLoops(loop(i), loop(best)) < 0)) {
829
+ best = i;
830
+ best_angle = angle;
831
+ }
832
+ }
833
+ }
834
+ // Build the new loops vector, starting with the inverted loop.
835
+ loop(best)->Invert();
836
+ vector<unique_ptr<S2Loop>> new_loops;
837
+ new_loops.reserve(num_loops());
838
+ // Add the former siblings of this loop as descendants.
839
+ int last_best = GetLastDescendant(best);
840
+ new_loops.push_back(std::move(loops_[best]));
841
+ for (int i = 0; i < num_loops(); ++i) {
842
+ if (i < best || i > last_best) {
843
+ loop(i)->set_depth(loop(i)->depth() + 1);
844
+ new_loops.push_back(std::move(loops_[i]));
845
+ }
846
+ }
847
+ // Add the former children of this loop as siblings.
848
+ for (int i = 0; i < num_loops(); ++i) {
849
+ if (i > best && i <= last_best) {
850
+ loop(i)->set_depth(loop(i)->depth() - 1);
851
+ new_loops.push_back(std::move(loops_[i]));
852
+ }
853
+ }
854
+ loops_.swap(new_loops);
855
+ S2_DCHECK_EQ(new_loops.size(), num_loops());
856
+ }
857
+ ClearIndex();
858
+ InitLoopProperties();
859
+ }
860
+
861
+ void S2Polygon::InitToComplement(const S2Polygon* a) {
862
+ Copy(a);
863
+ Invert();
864
+ }
865
+
866
+ bool S2Polygon::InitToOperation(S2BooleanOperation::OpType op_type,
867
+ const S2Builder::SnapFunction& snap_function,
868
+ const S2Polygon& a, const S2Polygon& b,
869
+ S2Error* error) {
870
+ S2BooleanOperation::Options options;
871
+ options.set_snap_function(snap_function);
872
+ S2BooleanOperation op(op_type, make_unique<S2PolygonLayer>(this),
873
+ options);
874
+ return op.Build(a.index_, b.index_, error);
875
+ }
876
+
877
+ void S2Polygon::InitToOperation(S2BooleanOperation::OpType op_type,
878
+ const S2Builder::SnapFunction& snap_function,
879
+ const S2Polygon& a, const S2Polygon& b) {
880
+ S2Error error;
881
+ if (!InitToOperation(op_type, snap_function, a, b, &error)) {
882
+ S2_LOG(DFATAL) << S2BooleanOperation::OpTypeToString(op_type)
883
+ << " operation failed: " << error;
884
+ }
885
+ }
886
+
887
+ void S2Polygon::InitToIntersection(const S2Polygon* a, const S2Polygon* b) {
888
+ InitToApproxIntersection(a, b, S2::kIntersectionMergeRadius);
889
+ }
890
+
891
+ void S2Polygon::InitToApproxIntersection(const S2Polygon* a, const S2Polygon* b,
892
+ S1Angle snap_radius) {
893
+ InitToIntersection(*a, *b, IdentitySnapFunction(snap_radius));
894
+ }
895
+
896
+ void S2Polygon::InitToIntersection(
897
+ const S2Polygon& a, const S2Polygon& b,
898
+ const S2Builder::SnapFunction& snap_function) {
899
+ if (!a.bound_.Intersects(b.bound_)) return;
900
+ InitToOperation(S2BooleanOperation::OpType::INTERSECTION,
901
+ snap_function, a, b);
902
+ }
903
+
904
+ bool S2Polygon::InitToIntersection(
905
+ const S2Polygon& a, const S2Polygon& b,
906
+ const S2Builder::SnapFunction& snap_function, S2Error* error) {
907
+ if (!a.bound_.Intersects(b.bound_)) return true; // Success.
908
+ return InitToOperation(S2BooleanOperation::OpType::INTERSECTION,
909
+ snap_function, a, b, error);
910
+ }
911
+
912
+ void S2Polygon::InitToUnion(const S2Polygon* a, const S2Polygon* b) {
913
+ InitToApproxUnion(a, b, S2::kIntersectionMergeRadius);
914
+ }
915
+
916
+ void S2Polygon::InitToApproxUnion(const S2Polygon* a, const S2Polygon* b,
917
+ S1Angle snap_radius) {
918
+ InitToUnion(*a, *b, IdentitySnapFunction(snap_radius));
919
+ }
920
+
921
+ void S2Polygon::InitToUnion(
922
+ const S2Polygon& a, const S2Polygon& b,
923
+ const S2Builder::SnapFunction& snap_function) {
924
+ InitToOperation(S2BooleanOperation::OpType::UNION, snap_function, a, b);
925
+ }
926
+
927
+ bool S2Polygon::InitToUnion(
928
+ const S2Polygon& a, const S2Polygon& b,
929
+ const S2Builder::SnapFunction& snap_function, S2Error* error) {
930
+ return InitToOperation(S2BooleanOperation::OpType::UNION,
931
+ snap_function, a, b, error);
932
+ }
933
+
934
+ void S2Polygon::InitToDifference(const S2Polygon* a, const S2Polygon* b) {
935
+ InitToApproxDifference(a, b, S2::kIntersectionMergeRadius);
936
+ }
937
+
938
+ void S2Polygon::InitToApproxDifference(const S2Polygon* a, const S2Polygon* b,
939
+ S1Angle snap_radius) {
940
+ InitToDifference(*a, *b, IdentitySnapFunction(snap_radius));
941
+ }
942
+
943
+ void S2Polygon::InitToDifference(
944
+ const S2Polygon& a, const S2Polygon& b,
945
+ const S2Builder::SnapFunction& snap_function) {
946
+ InitToOperation(S2BooleanOperation::OpType::DIFFERENCE, snap_function, a, b);
947
+ }
948
+
949
+ bool S2Polygon::InitToDifference(
950
+ const S2Polygon& a, const S2Polygon& b,
951
+ const S2Builder::SnapFunction& snap_function, S2Error* error) {
952
+ return InitToOperation(S2BooleanOperation::OpType::DIFFERENCE,
953
+ snap_function, a, b, error);
954
+ }
955
+
956
+ void S2Polygon::InitToSymmetricDifference(const S2Polygon* a,
957
+ const S2Polygon* b) {
958
+ InitToApproxSymmetricDifference(a, b, S2::kIntersectionMergeRadius);
959
+ }
960
+
961
+ void S2Polygon::InitToApproxSymmetricDifference(const S2Polygon* a,
962
+ const S2Polygon* b,
963
+ S1Angle snap_radius) {
964
+ InitToSymmetricDifference(*a, *b, IdentitySnapFunction(snap_radius));
965
+ }
966
+
967
+ void S2Polygon::InitToSymmetricDifference(
968
+ const S2Polygon& a, const S2Polygon& b,
969
+ const S2Builder::SnapFunction& snap_function) {
970
+ InitToOperation(S2BooleanOperation::OpType::SYMMETRIC_DIFFERENCE,
971
+ snap_function, a, b);
972
+ }
973
+
974
+ bool S2Polygon::InitToSymmetricDifference(
975
+ const S2Polygon& a, const S2Polygon& b,
976
+ const S2Builder::SnapFunction& snap_function, S2Error* error) {
977
+ return InitToOperation(S2BooleanOperation::OpType::SYMMETRIC_DIFFERENCE,
978
+ snap_function, a, b, error);
979
+ }
980
+
981
+ void S2Polygon::InitFromBuilder(const S2Polygon& a, S2Builder* builder) {
982
+ builder->StartLayer(make_unique<S2PolygonLayer>(this));
983
+ builder->AddPolygon(a);
984
+ S2Error error;
985
+ if (!builder->Build(&error)) {
986
+ S2_LOG(DFATAL) << "Could not build polygon: " << error;
987
+ }
988
+ // If there are no loops, check whether the result should be the full
989
+ // polygon rather than the empty one. (See InitToApproxIntersection.)
990
+ if (num_loops() == 0) {
991
+ if (a.bound_.Area() > 2 * M_PI && a.GetArea() > 2 * M_PI) Invert();
992
+ }
993
+ }
994
+
995
+ void S2Polygon::InitToSnapped(const S2Polygon& polygon,
996
+ const S2Builder::SnapFunction& snap_function) {
997
+ S2Builder builder{S2Builder::Options(snap_function)};
998
+ InitFromBuilder(polygon, &builder);
999
+ }
1000
+
1001
+ void S2Polygon::InitToSnapped(const S2Polygon* a, int snap_level) {
1002
+ InitToSnapped(*a, S2CellIdSnapFunction(snap_level));
1003
+ }
1004
+
1005
+ void S2Polygon::InitToSimplified(const S2Polygon& a,
1006
+ const S2Builder::SnapFunction& snap_function) {
1007
+ S2Builder::Options options(snap_function);
1008
+ options.set_simplify_edge_chains(true);
1009
+ S2Builder builder(options);
1010
+ InitFromBuilder(a, &builder);
1011
+ }
1012
+
1013
+ // Given a point "p" inside an S2Cell or on its boundary, return a mask
1014
+ // indicating which of the S2Cell edges the point lies on. All boundary
1015
+ // comparisons are to within a maximum "u" or "v" error of "tolerance_uv".
1016
+ // Bit "i" in the result is set if and only "p" is incident to the edge
1017
+ // corresponding to S2Cell::edge(i).
1018
+ uint8 GetCellEdgeIncidenceMask(const S2Cell& cell, const S2Point& p,
1019
+ double tolerance_uv) {
1020
+ uint8 mask = 0;
1021
+ R2Point uv;
1022
+ if (S2::FaceXYZtoUV(cell.face(), p, &uv)) {
1023
+ R2Rect bound = cell.GetBoundUV();
1024
+ if (FLAGS_s2debug) S2_DCHECK(bound.Expanded(tolerance_uv).Contains(uv));
1025
+ if (fabs(uv[1] - bound[1][0]) <= tolerance_uv) mask |= 1;
1026
+ if (fabs(uv[0] - bound[0][1]) <= tolerance_uv) mask |= 2;
1027
+ if (fabs(uv[1] - bound[1][1]) <= tolerance_uv) mask |= 4;
1028
+ if (fabs(uv[0] - bound[0][0]) <= tolerance_uv) mask |= 8;
1029
+ }
1030
+ return mask;
1031
+ }
1032
+
1033
+ void S2Polygon::InitToSimplifiedInCell(
1034
+ const S2Polygon* a, const S2Cell& cell,
1035
+ S1Angle snap_radius, S1Angle boundary_tolerance) {
1036
+ // The polygon to be simplified consists of "boundary edges" that follow the
1037
+ // cell boundary and "interior edges" that do not. We want to simplify the
1038
+ // interior edges while leaving the boundary edges unchanged. It's not
1039
+ // sufficient to call S2Builder::ForceVertex() on all boundary vertices.
1040
+ // For example, suppose the polygon includes a triangle ABC where all three
1041
+ // vertices are on the cell boundary and B is a cell corner. Then if
1042
+ // interior edge AC snaps to vertex B, this loop would become degenerate and
1043
+ // be removed. Similarly, we don't want boundary edges to snap to interior
1044
+ // vertices, since this also would cause portions of the polygon along the
1045
+ // boundary to be removed.
1046
+ //
1047
+ // Instead we use a two-pass algorithm. In the first pass, we simplify
1048
+ // *only* the interior edges, using ForceVertex() to ensure that any edge
1049
+ // endpoints on the cell boundary do not move. In the second pass, we add
1050
+ // the boundary edges (which are guaranteed to still form loops with the
1051
+ // interior edges) and build the output polygon.
1052
+ //
1053
+ // Note that in theory, simplifying the interior edges could create an
1054
+ // intersection with one of the boundary edges, since if two interior edges
1055
+ // intersect very near the boundary then the intersection point could be
1056
+ // slightly outside the cell (by at most S2::kIntersectionError).
1057
+ // This is the *only* way that a self-intersection can be created, and it is
1058
+ // expected to be extremely rare. Nevertheless we use a small snap radius
1059
+ // in the second pass in order to eliminate any such self-intersections.
1060
+ //
1061
+ // We also want to preserve the cyclic vertex order of loops, so that the
1062
+ // original polygon can be reconstructed when no simplification is possible
1063
+ // (i.e., idempotency). In order to do this, we group the input edges into
1064
+ // a sequence of polylines. Each polyline contains only one type of edge
1065
+ // (interior or boundary). We use S2Builder to simplify the interior
1066
+ // polylines, while the boundary polylines are passed through unchanged.
1067
+ // Each interior polyline is in its own S2Builder layer in order to keep the
1068
+ // edges in sequence. This lets us ensure that in the second pass, the
1069
+ // edges are added in their original order so that S2PolygonLayer can
1070
+ // reconstruct the original loops.
1071
+
1072
+ // We want an upper bound on how much "u" or "v" can change when a point on
1073
+ // the boundary of the S2Cell is moved away by up to "boundary_tolerance".
1074
+ // Inverting this, instead we could compute a lower bound on how far a point
1075
+ // can move away from an S2Cell edge when "u" or "v" is changed by a given
1076
+ // amount. The latter quantity is simply (S2::kMinWidth.deriv() / 2)
1077
+ // under the S2_LINEAR_PROJECTION model, where we divide by 2 because we
1078
+ // want the bound in terms of (u = 2 * s - 1) rather than "s" itself.
1079
+ // Consulting s2metrics.cc, this value is sqrt(2/3)/2 = sqrt(1/6).
1080
+ // Going back to the original problem, this gives:
1081
+ double boundary_tolerance_uv = sqrt(6) * boundary_tolerance.radians();
1082
+
1083
+ // The first pass yields a collection of simplified polylines that preserve
1084
+ // the original cyclic vertex order.
1085
+ auto polylines = SimplifyEdgesInCell(*a, cell, boundary_tolerance_uv,
1086
+ snap_radius);
1087
+
1088
+ // The second pass eliminates any intersections between interior edges and
1089
+ // boundary edges, and then assembles the edges into a polygon.
1090
+ S2Builder::Options options(
1091
+ (IdentitySnapFunction(S2::kIntersectionError)));
1092
+ options.set_idempotent(false); // Force snapping up to the given radius
1093
+ S2Builder builder(options);
1094
+ builder.StartLayer(make_unique<S2PolygonLayer>(this));
1095
+ for (const auto& polyline : polylines) {
1096
+ builder.AddPolyline(*polyline);
1097
+ }
1098
+ S2Error error;
1099
+ if (!builder.Build(&error)) {
1100
+ S2_LOG(DFATAL) << "Could not build polygon: " << error;
1101
+ return;
1102
+ }
1103
+ // If there are no loops, check whether the result should be the full
1104
+ // polygon rather than the empty one. (See InitToApproxIntersection.)
1105
+ if (num_loops() == 0) {
1106
+ if (a->bound_.Area() > 2 * M_PI && a->GetArea() > 2 * M_PI) Invert();
1107
+ }
1108
+ }
1109
+
1110
+ // See comments in InitToSimplifiedInCell.
1111
+ vector<unique_ptr<S2Polyline>> S2Polygon::SimplifyEdgesInCell(
1112
+ const S2Polygon& a, const S2Cell& cell,
1113
+ double tolerance_uv, S1Angle snap_radius) {
1114
+ S2Builder::Options options((IdentitySnapFunction(snap_radius)));
1115
+ options.set_simplify_edge_chains(true);
1116
+ S2Builder builder(options);
1117
+ // The output consists of a sequence of polylines. Polylines consisting of
1118
+ // interior edges are simplified using S2Builder, while polylines consisting
1119
+ // of boundary edges are returned unchanged.
1120
+ vector<unique_ptr<S2Polyline>> polylines;
1121
+ for (int i = 0; i < a.num_loops(); ++i) {
1122
+ const S2Loop& a_loop = *a.loop(i);
1123
+ const S2Point* v0 = &a_loop.oriented_vertex(0);
1124
+ uint8 mask0 = GetCellEdgeIncidenceMask(cell, *v0, tolerance_uv);
1125
+ bool in_interior = false; // Was the last edge an interior edge?
1126
+ for (int j = 1; j <= a_loop.num_vertices(); ++j) {
1127
+ const S2Point* v1 = &a_loop.oriented_vertex(j);
1128
+ uint8 mask1 = GetCellEdgeIncidenceMask(cell, *v1, tolerance_uv);
1129
+ if ((mask0 & mask1) != 0) {
1130
+ // This is an edge along the cell boundary. Such edges do not get
1131
+ // simplified; we add them directly to the output. (We create a
1132
+ // separate polyline for each edge to keep things simple.) We call
1133
+ // ForceVertex on all boundary vertices to ensure that they don't
1134
+ // move, and so that nearby interior edges are snapped to them.
1135
+ S2_DCHECK(!in_interior);
1136
+ builder.ForceVertex(*v1);
1137
+ polylines.emplace_back(new S2Polyline(vector<S2Point>{*v0, *v1}));
1138
+ } else {
1139
+ // This is an interior edge. If this is the first edge of an interior
1140
+ // chain, then start a new S2Builder layer. Also ensure that any
1141
+ // polyline vertices on the boundary do not move, so that they will
1142
+ // still connect with any boundary edge(s) there.
1143
+ if (!in_interior) {
1144
+ S2Polyline* polyline = new S2Polyline;
1145
+ builder.StartLayer(make_unique<S2PolylineLayer>(polyline));
1146
+ polylines.emplace_back(polyline);
1147
+ in_interior = true;
1148
+ }
1149
+ builder.AddEdge(*v0, *v1);
1150
+ if (mask1 != 0) {
1151
+ builder.ForceVertex(*v1);
1152
+ in_interior = false; // Terminate this polyline.
1153
+ }
1154
+ }
1155
+ v0 = v1;
1156
+ mask0 = mask1;
1157
+ }
1158
+ }
1159
+ S2Error error;
1160
+ if (!builder.Build(&error)) {
1161
+ S2_LOG(DFATAL) << "InitToSimplifiedInCell failed: " << error;
1162
+ }
1163
+ return polylines;
1164
+ }
1165
+
1166
+ vector<unique_ptr<S2Polyline>> S2Polygon::OperationWithPolyline(
1167
+ S2BooleanOperation::OpType op_type,
1168
+ const S2Builder::SnapFunction& snap_function,
1169
+ const S2Polyline& a) const {
1170
+ S2BooleanOperation::Options options;
1171
+ options.set_snap_function(snap_function);
1172
+ vector<unique_ptr<S2Polyline>> result;
1173
+ S2PolylineVectorLayer::Options layer_options;
1174
+ layer_options.set_polyline_type(
1175
+ S2PolylineVectorLayer::Options::PolylineType::WALK);
1176
+ S2BooleanOperation op(
1177
+ op_type, make_unique<S2PolylineVectorLayer>(&result, layer_options),
1178
+ options);
1179
+ MutableS2ShapeIndex a_index;
1180
+ a_index.Add(make_unique<S2Polyline::Shape>(&a));
1181
+ S2Error error;
1182
+ if (!op.Build(a_index, index_, &error)) {
1183
+ S2_LOG(DFATAL) << "Polyline " << S2BooleanOperation::OpTypeToString(op_type)
1184
+ << " operation failed: " << error;
1185
+ }
1186
+ return result;
1187
+ }
1188
+
1189
+ vector<unique_ptr<S2Polyline>> S2Polygon::IntersectWithPolyline(
1190
+ const S2Polyline& a) const {
1191
+ return ApproxIntersectWithPolyline(a, S2::kIntersectionMergeRadius);
1192
+ }
1193
+
1194
+ vector<unique_ptr<S2Polyline>> S2Polygon::ApproxIntersectWithPolyline(
1195
+ const S2Polyline& a, S1Angle snap_radius) const {
1196
+ return IntersectWithPolyline(a, IdentitySnapFunction(snap_radius));
1197
+ }
1198
+
1199
+ vector<unique_ptr<S2Polyline>> S2Polygon::IntersectWithPolyline(
1200
+ const S2Polyline& a, const S2Builder::SnapFunction& snap_function) const {
1201
+ return OperationWithPolyline(S2BooleanOperation::OpType::INTERSECTION,
1202
+ snap_function, a);
1203
+ }
1204
+
1205
+ vector<unique_ptr<S2Polyline>> S2Polygon::SubtractFromPolyline(
1206
+ const S2Polyline& a) const {
1207
+ return ApproxSubtractFromPolyline(a, S2::kIntersectionMergeRadius);
1208
+ }
1209
+
1210
+ vector<unique_ptr<S2Polyline>> S2Polygon::ApproxSubtractFromPolyline(
1211
+ const S2Polyline& a, S1Angle snap_radius) const {
1212
+ return SubtractFromPolyline(a, IdentitySnapFunction(snap_radius));
1213
+ }
1214
+
1215
+ vector<unique_ptr<S2Polyline>> S2Polygon::SubtractFromPolyline(
1216
+ const S2Polyline& a, const S2Builder::SnapFunction& snap_function) const {
1217
+ return OperationWithPolyline(S2BooleanOperation::OpType::DIFFERENCE,
1218
+ snap_function, a);
1219
+ }
1220
+
1221
+ bool S2Polygon::Contains(const S2Polyline& b) const {
1222
+ return ApproxContains(b, S2::kIntersectionMergeRadius);
1223
+ }
1224
+
1225
+ bool S2Polygon::ApproxContains(const S2Polyline& b, S1Angle tolerance) const {
1226
+ auto difference = ApproxSubtractFromPolyline(b, tolerance);
1227
+ return difference.empty();
1228
+ }
1229
+
1230
+ bool S2Polygon::Intersects(const S2Polyline& b) const {
1231
+ return !ApproxDisjoint(b, S2::kIntersectionMergeRadius);
1232
+ }
1233
+
1234
+ bool S2Polygon::ApproxDisjoint(const S2Polyline& b, S1Angle tolerance) const {
1235
+ auto intersection = ApproxIntersectWithPolyline(b, tolerance);
1236
+ return intersection.empty();
1237
+ }
1238
+
1239
+ unique_ptr<S2Polygon> S2Polygon::DestructiveUnion(
1240
+ vector<unique_ptr<S2Polygon>> polygons) {
1241
+ return DestructiveApproxUnion(std::move(polygons),
1242
+ S2::kIntersectionMergeRadius);
1243
+ }
1244
+
1245
+ unique_ptr<S2Polygon> S2Polygon::DestructiveApproxUnion(
1246
+ vector<unique_ptr<S2Polygon>> polygons, S1Angle snap_radius) {
1247
+ // Effectively create a priority queue of polygons in order of number of
1248
+ // vertices. Repeatedly union the two smallest polygons and add the result
1249
+ // to the queue until we have a single polygon to return.
1250
+ using QueueType = std::multimap<int, unique_ptr<S2Polygon>>;
1251
+ QueueType queue; // Map from # of vertices to polygon.
1252
+ for (auto& polygon : polygons)
1253
+ queue.insert(std::make_pair(polygon->num_vertices(), std::move(polygon)));
1254
+
1255
+ while (queue.size() > 1) {
1256
+ // Pop two simplest polygons from queue.
1257
+ QueueType::iterator smallest_it = queue.begin();
1258
+ int a_size = smallest_it->first;
1259
+ unique_ptr<S2Polygon> a_polygon(std::move(smallest_it->second));
1260
+ queue.erase(smallest_it);
1261
+ smallest_it = queue.begin();
1262
+ int b_size = smallest_it->first;
1263
+ unique_ptr<S2Polygon> b_polygon(std::move(smallest_it->second));
1264
+ queue.erase(smallest_it);
1265
+
1266
+ // Union and add result back to queue.
1267
+ auto union_polygon = make_unique<S2Polygon>();
1268
+ union_polygon->InitToApproxUnion(a_polygon.get(), b_polygon.get(),
1269
+ snap_radius);
1270
+ queue.insert(std::make_pair(a_size + b_size, std::move(union_polygon)));
1271
+ // We assume that the number of vertices in the union polygon is the
1272
+ // sum of the number of vertices in the original polygons, which is not
1273
+ // always true, but will almost always be a decent approximation, and
1274
+ // faster than recomputing.
1275
+ }
1276
+
1277
+ if (queue.empty())
1278
+ return make_unique<S2Polygon>();
1279
+ else
1280
+ return std::move(queue.begin()->second);
1281
+ }
1282
+
1283
+ void S2Polygon::InitToCellUnionBorder(const S2CellUnion& cells) {
1284
+ // We use S2Builder to compute the union. Due to rounding errors, we can't
1285
+ // compute an exact union - when a small cell is adjacent to a larger cell,
1286
+ // the shared edges can fail to line up exactly. Two cell edges cannot come
1287
+ // closer then kMinWidth, so if we have S2Builder snap edges within half
1288
+ // that distance, then we should always merge shared edges without merging
1289
+ // different edges.
1290
+ double snap_radius = 0.5 * S2::kMinWidth.GetValue(S2CellId::kMaxLevel);
1291
+ S2Builder builder{S2Builder::Options(
1292
+ IdentitySnapFunction(S1Angle::Radians(snap_radius)))};
1293
+ builder.StartLayer(make_unique<S2PolygonLayer>(this));
1294
+ for (S2CellId id : cells) {
1295
+ builder.AddLoop(S2Loop{S2Cell{id}});
1296
+ }
1297
+ S2Error error;
1298
+ if (!builder.Build(&error)) {
1299
+ S2_LOG(DFATAL) << "InitToCellUnionBorder failed: " << error;
1300
+ }
1301
+ // If there are no loops, check whether the result should be the full
1302
+ // polygon rather than the empty one. There are only two ways that this can
1303
+ // happen: either the cell union is empty, or it consists of all six faces.
1304
+ if (num_loops() == 0) {
1305
+ if (cells.empty()) return;
1306
+ S2_DCHECK_EQ(uint64{6} << (2 * S2CellId::kMaxLevel),
1307
+ cells.LeafCellsCovered());
1308
+ Invert();
1309
+ }
1310
+ }
1311
+
1312
+ bool S2Polygon::IsNormalized() const {
1313
+ // TODO(ericv): The condition tested here is insufficient. The correct
1314
+ // condition is that each *connected component* of child loops can share at
1315
+ // most one vertex with their parent loop. Example: suppose loop A has
1316
+ // children B, C, D, and the following pairs are connected: AB, BC, CD, DA.
1317
+ // Then the polygon is not normalized.
1318
+ set<S2Point> vertices;
1319
+ const S2Loop* last_parent = nullptr;
1320
+ for (int i = 0; i < num_loops(); ++i) {
1321
+ const S2Loop* child = loop(i);
1322
+ if (child->depth() == 0) continue;
1323
+ const S2Loop* parent = loop(GetParent(i));
1324
+ if (parent != last_parent) {
1325
+ vertices.clear();
1326
+ for (int j = 0; j < parent->num_vertices(); ++j) {
1327
+ vertices.insert(parent->vertex(j));
1328
+ }
1329
+ last_parent = parent;
1330
+ }
1331
+ int count = 0;
1332
+ for (int j = 0; j < child->num_vertices(); ++j) {
1333
+ if (vertices.count(child->vertex(j)) > 0) ++count;
1334
+ }
1335
+ if (count > 1) return false;
1336
+ }
1337
+ return true;
1338
+ }
1339
+
1340
+ bool S2Polygon::Equals(const S2Polygon* b) const {
1341
+ if (num_loops() != b->num_loops()) return false;
1342
+ for (int i = 0; i < num_loops(); ++i) {
1343
+ const S2Loop* a_loop = loop(i);
1344
+ const S2Loop* b_loop = b->loop(i);
1345
+ if ((b_loop->depth() != a_loop->depth()) || !b_loop->Equals(a_loop)) {
1346
+ return false;
1347
+ }
1348
+ }
1349
+ return true;
1350
+ }
1351
+
1352
+ bool S2Polygon::BoundaryEquals(const S2Polygon* b) const {
1353
+ if (num_loops() != b->num_loops()) return false;
1354
+
1355
+ for (int i = 0; i < num_loops(); ++i) {
1356
+ const S2Loop* a_loop = loop(i);
1357
+ bool success = false;
1358
+ for (int j = 0; j < num_loops(); ++j) {
1359
+ const S2Loop* b_loop = b->loop(j);
1360
+ if ((b_loop->depth() == a_loop->depth()) &&
1361
+ b_loop->BoundaryEquals(a_loop)) {
1362
+ success = true;
1363
+ break;
1364
+ }
1365
+ }
1366
+ if (!success) return false;
1367
+ }
1368
+ return true;
1369
+ }
1370
+
1371
+ bool S2Polygon::BoundaryApproxEquals(const S2Polygon& b,
1372
+ S1Angle max_error) const {
1373
+ if (num_loops() != b.num_loops()) return false;
1374
+
1375
+ // For now, we assume that there is at most one candidate match for each
1376
+ // loop. (So far this method is just used for testing.)
1377
+
1378
+ for (int i = 0; i < num_loops(); ++i) {
1379
+ const S2Loop& a_loop = *loop(i);
1380
+ bool success = false;
1381
+ for (int j = 0; j < num_loops(); ++j) {
1382
+ const S2Loop& b_loop = *b.loop(j);
1383
+ if (b_loop.depth() == a_loop.depth() &&
1384
+ b_loop.BoundaryApproxEquals(a_loop, max_error)) {
1385
+ success = true;
1386
+ break;
1387
+ }
1388
+ }
1389
+ if (!success) return false;
1390
+ }
1391
+ return true;
1392
+ }
1393
+
1394
+ bool S2Polygon::BoundaryNear(const S2Polygon& b, S1Angle max_error) const {
1395
+ if (num_loops() != b.num_loops()) return false;
1396
+
1397
+ // For now, we assume that there is at most one candidate match for each
1398
+ // loop. (So far this method is just used for testing.)
1399
+
1400
+ for (int i = 0; i < num_loops(); ++i) {
1401
+ const S2Loop& a_loop = *loop(i);
1402
+ bool success = false;
1403
+ for (int j = 0; j < num_loops(); ++j) {
1404
+ const S2Loop& b_loop = *b.loop(j);
1405
+ if (b_loop.depth() == a_loop.depth() &&
1406
+ b_loop.BoundaryNear(a_loop, max_error)) {
1407
+ success = true;
1408
+ break;
1409
+ }
1410
+ }
1411
+ if (!success) return false;
1412
+ }
1413
+ return true;
1414
+ }
1415
+
1416
+ void S2Polygon::EncodeCompressed(Encoder* encoder,
1417
+ const S2XYZFaceSiTi* all_vertices,
1418
+ int snap_level) const {
1419
+ S2_CHECK_GE(snap_level, 0);
1420
+ // Sufficient for what we write. Typically enough for a 4 vertex polygon.
1421
+ encoder->Ensure(40);
1422
+ encoder->put8(kCurrentCompressedEncodingVersionNumber);
1423
+ encoder->put8(snap_level);
1424
+ encoder->put_varint32(num_loops());
1425
+ S2_DCHECK_GE(encoder->avail(), 0);
1426
+ const S2XYZFaceSiTi* current_loop_vertices = all_vertices;
1427
+ for (int i = 0; i < num_loops(); ++i) {
1428
+ loops_[i]->EncodeCompressed(encoder, current_loop_vertices, snap_level);
1429
+ current_loop_vertices += loops_[i]->num_vertices();
1430
+ }
1431
+ // Do not write the bound or num_vertices as they can be cheaply recomputed
1432
+ // by DecodeCompressed. Microbenchmarks show the speed difference is
1433
+ // inconsequential.
1434
+ }
1435
+
1436
+ bool S2Polygon::DecodeCompressed(Decoder* decoder) {
1437
+ if (decoder->avail() < sizeof(uint8)) return false;
1438
+ ClearLoops();
1439
+ int snap_level = decoder->get8();
1440
+ if (snap_level > S2CellId::kMaxLevel) return false;
1441
+ // Polygons with no loops are explicitly allowed here: a newly created
1442
+ // polygon has zero loops and such polygons encode and decode properly.
1443
+ uint32 num_loops;
1444
+ if (!decoder->get_varint32(&num_loops)) return false;
1445
+ if (num_loops > FLAGS_s2polygon_decode_max_num_loops) return false;
1446
+ loops_.reserve(num_loops);
1447
+ for (int i = 0; i < num_loops; ++i) {
1448
+ auto loop = make_unique<S2Loop>();
1449
+ loop->set_s2debug_override(s2debug_override());
1450
+ if (!loop->DecodeCompressed(decoder, snap_level)) {
1451
+ return false;
1452
+ }
1453
+ loops_.push_back(std::move(loop));
1454
+ }
1455
+ InitLoopProperties();
1456
+ return true;
1457
+ }
1458
+
1459
+ S2Polygon::Shape::Shape(const S2Polygon* polygon)
1460
+ : cumulative_edges_(nullptr) {
1461
+ Init(polygon);
1462
+ }
1463
+
1464
+ void S2Polygon::Shape::Init(const S2Polygon* polygon) {
1465
+ polygon_ = polygon;
1466
+ delete[] cumulative_edges_;
1467
+ cumulative_edges_ = nullptr;
1468
+ num_edges_ = 0;
1469
+ if (!polygon->is_full()) {
1470
+ const int kMaxLinearSearchLoops = 12; // From benchmarks.
1471
+ int num_loops = polygon->num_loops();
1472
+ if (num_loops > kMaxLinearSearchLoops) {
1473
+ cumulative_edges_ = new int[num_loops];
1474
+ }
1475
+ for (int i = 0; i < num_loops; ++i) {
1476
+ if (cumulative_edges_) cumulative_edges_[i] = num_edges_;
1477
+ num_edges_ += polygon->loop(i)->num_vertices();
1478
+ }
1479
+ }
1480
+ }
1481
+
1482
+ S2Polygon::Shape::~Shape() {
1483
+ delete[] cumulative_edges_;
1484
+ }
1485
+
1486
+ S2Shape::Edge S2Polygon::Shape::edge(int e) const {
1487
+ S2_DCHECK_LT(e, num_edges());
1488
+ const S2Polygon* p = polygon();
1489
+ int i;
1490
+ if (cumulative_edges_) {
1491
+ // "upper_bound" finds the loop just beyond the one we want.
1492
+ int* start = std::upper_bound(cumulative_edges_,
1493
+ cumulative_edges_ + p->num_loops(), e) - 1;
1494
+ i = start - cumulative_edges_;
1495
+ e -= *start;
1496
+ } else {
1497
+ // When the number of loops is small, linear search is faster. Most often
1498
+ // there is exactly one loop and the code below executes zero times.
1499
+ for (i = 0; e >= p->loop(i)->num_vertices(); ++i) {
1500
+ e -= p->loop(i)->num_vertices();
1501
+ }
1502
+ }
1503
+ return Edge(p->loop(i)->oriented_vertex(e),
1504
+ p->loop(i)->oriented_vertex(e + 1));
1505
+ }
1506
+
1507
+ S2Shape::ReferencePoint S2Polygon::Shape::GetReferencePoint() const {
1508
+ const S2Polygon* p = polygon();
1509
+ bool contains_origin = false;
1510
+ for (int i = 0; i < p->num_loops(); ++i) {
1511
+ contains_origin ^= p->loop(i)->contains_origin();
1512
+ }
1513
+ return ReferencePoint(S2::Origin(), contains_origin);
1514
+ }
1515
+
1516
+ int S2Polygon::Shape::num_chains() const {
1517
+ return polygon_->num_loops();
1518
+ }
1519
+
1520
+ S2Shape::Chain S2Polygon::Shape::chain(int i) const {
1521
+ S2_DCHECK_LT(i, Shape::num_chains());
1522
+ if (cumulative_edges_) {
1523
+ return Chain(cumulative_edges_[i], polygon_->loop(i)->num_vertices());
1524
+ } else {
1525
+ int e = 0;
1526
+ for (int j = 0; j < i; ++j) e += polygon_->loop(j)->num_vertices();
1527
+ // S2Polygon represents a full loop as a loop with one vertex, while
1528
+ // S2Shape represents a full loop as a chain with no vertices.
1529
+ int num_vertices = polygon_->loop(i)->num_vertices();
1530
+ return Chain(e, (num_vertices == 1) ? 0 : num_vertices);
1531
+ }
1532
+ }
1533
+
1534
+ S2Shape::Edge S2Polygon::Shape::chain_edge(int i, int j) const {
1535
+ S2_DCHECK_LT(i, Shape::num_chains());
1536
+ S2_DCHECK_LT(j, polygon_->loop(i)->num_vertices());
1537
+ return Edge(polygon()->loop(i)->oriented_vertex(j),
1538
+ polygon()->loop(i)->oriented_vertex(j + 1));
1539
+ }
1540
+
1541
+ S2Shape::ChainPosition S2Polygon::Shape::chain_position(int e) const {
1542
+ // TODO(ericv): Make inline to remove code duplication with GetEdge.
1543
+ S2_DCHECK_LT(e, num_edges());
1544
+ const S2Polygon* p = polygon();
1545
+ int i;
1546
+ if (cumulative_edges_) {
1547
+ // "upper_bound" finds the loop just beyond the one we want.
1548
+ int* start = std::upper_bound(cumulative_edges_,
1549
+ cumulative_edges_ + p->num_loops(), e) - 1;
1550
+ i = start - cumulative_edges_;
1551
+ e -= *start;
1552
+ } else {
1553
+ // When the number of loops is small, linear search is faster. Most often
1554
+ // there is exactly one loop and the code below executes zero times.
1555
+ for (i = 0; e >= p->loop(i)->num_vertices(); ++i) {
1556
+ e -= p->loop(i)->num_vertices();
1557
+ }
1558
+ }
1559
+ return ChainPosition(i, e);
1560
+ }
1561
+
1562
+ size_t S2Polygon::SpaceUsed() const {
1563
+ size_t size = sizeof(*this);
1564
+ for (int i = 0; i < num_loops(); ++i) {
1565
+ size += loop(i)->SpaceUsed();
1566
+ }
1567
+ size += index_.SpaceUsed() - sizeof(index_);
1568
+ return size;
1569
+ }