@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,1084 @@
1
+ // Copyright 2016 Google Inc. All Rights Reserved.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS-IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+
16
+ // Author: ericv@google.com (Eric Veach)
17
+
18
+ #include "s2/s2builder_graph.h"
19
+
20
+ #include <algorithm>
21
+ #include <limits>
22
+ #include <memory>
23
+ #include <numeric>
24
+ #include <vector>
25
+ #include "s2/base/logging.h"
26
+ #include "s2/util/gtl/btree_map.h"
27
+ #include "s2/id_set_lexicon.h"
28
+ #include "s2/s2builder.h"
29
+ #include "s2/s2error.h"
30
+ #include "s2/s2predicates.h"
31
+
32
+ using std::make_pair;
33
+ using std::max;
34
+ using std::min;
35
+ using std::pair;
36
+ using std::vector;
37
+
38
+ using Graph = S2Builder::Graph;
39
+ using GraphOptions = S2Builder::GraphOptions;
40
+ using DegenerateEdges = GraphOptions::DegenerateEdges;
41
+ using DuplicateEdges = GraphOptions::DuplicateEdges;
42
+ using SiblingPairs = GraphOptions::SiblingPairs;
43
+
44
+ Graph::Graph(const GraphOptions& options,
45
+ const vector<S2Point>* vertices,
46
+ const vector<Edge>* edges,
47
+ const vector<InputEdgeIdSetId>* input_edge_id_set_ids,
48
+ const IdSetLexicon* input_edge_id_set_lexicon,
49
+ const vector<LabelSetId>* label_set_ids,
50
+ const IdSetLexicon* label_set_lexicon,
51
+ IsFullPolygonPredicate is_full_polygon_predicate)
52
+ : options_(options), num_vertices_(vertices->size()), vertices_(vertices),
53
+ edges_(edges), input_edge_id_set_ids_(input_edge_id_set_ids),
54
+ input_edge_id_set_lexicon_(input_edge_id_set_lexicon),
55
+ label_set_ids_(label_set_ids),
56
+ label_set_lexicon_(label_set_lexicon),
57
+ is_full_polygon_predicate_(std::move(is_full_polygon_predicate)) {
58
+ S2_DCHECK(std::is_sorted(edges->begin(), edges->end()));
59
+ S2_DCHECK_EQ(edges->size(), input_edge_id_set_ids->size());
60
+ }
61
+
62
+ vector<Graph::EdgeId> Graph::GetInEdgeIds() const {
63
+ vector<EdgeId> in_edge_ids(num_edges());
64
+ std::iota(in_edge_ids.begin(), in_edge_ids.end(), 0);
65
+ std::sort(in_edge_ids.begin(), in_edge_ids.end(),
66
+ [this](EdgeId ai, EdgeId bi) {
67
+ return StableLessThan(reverse(edge(ai)), reverse(edge(bi)), ai, bi);
68
+ });
69
+ return in_edge_ids;
70
+ }
71
+
72
+ vector<Graph::EdgeId> Graph::GetSiblingMap() const {
73
+ vector<EdgeId> in_edge_ids = GetInEdgeIds();
74
+ MakeSiblingMap(&in_edge_ids);
75
+ return in_edge_ids;
76
+ }
77
+
78
+ void Graph::MakeSiblingMap(vector<Graph::EdgeId>* in_edge_ids) const {
79
+ S2_DCHECK(options_.sibling_pairs() == SiblingPairs::REQUIRE ||
80
+ options_.sibling_pairs() == SiblingPairs::CREATE ||
81
+ options_.edge_type() == EdgeType::UNDIRECTED);
82
+ for (EdgeId e = 0; e < num_edges(); ++e) {
83
+ S2_DCHECK(edge(e) == reverse(edge((*in_edge_ids)[e])));
84
+ }
85
+ if (options_.edge_type() == EdgeType::DIRECTED) return;
86
+ if (options_.degenerate_edges() == DegenerateEdges::DISCARD) return;
87
+
88
+ for (EdgeId e = 0; e < num_edges(); ++e) {
89
+ VertexId v = edge(e).first;
90
+ if (edge(e).second == v) {
91
+ S2_DCHECK_LT(e + 1, num_edges());
92
+ S2_DCHECK_EQ(edge(e + 1).first, v);
93
+ S2_DCHECK_EQ(edge(e + 1).second, v);
94
+ S2_DCHECK_EQ((*in_edge_ids)[e], e);
95
+ S2_DCHECK_EQ((*in_edge_ids)[e + 1], e + 1);
96
+ (*in_edge_ids)[e] = e + 1;
97
+ (*in_edge_ids)[e + 1] = e;
98
+ ++e;
99
+ }
100
+ }
101
+ }
102
+
103
+ void Graph::VertexOutMap::Init(const Graph& g) {
104
+ edges_ = &g.edges();
105
+ edge_begins_.reserve(g.num_vertices() + 1);
106
+ EdgeId e = 0;
107
+ for (VertexId v = 0; v <= g.num_vertices(); ++v) {
108
+ while (e < g.num_edges() && g.edge(e).first < v) ++e;
109
+ edge_begins_.push_back(e);
110
+ }
111
+ }
112
+
113
+ void Graph::VertexInMap::Init(const Graph& g) {
114
+ in_edge_ids_ = g.GetInEdgeIds();
115
+ in_edge_begins_.reserve(g.num_vertices() + 1);
116
+ EdgeId e = 0;
117
+ for (VertexId v = 0; v <= g.num_vertices(); ++v) {
118
+ while (e < g.num_edges() && g.edge(in_edge_ids_[e]).second < v) ++e;
119
+ in_edge_begins_.push_back(e);
120
+ }
121
+ }
122
+
123
+ void Graph::LabelFetcher::Init(const Graph& g, S2Builder::EdgeType edge_type) {
124
+ g_ = &g;
125
+ edge_type_ = edge_type;
126
+ if (edge_type == EdgeType::UNDIRECTED) sibling_map_ = g.GetSiblingMap();
127
+ }
128
+
129
+ void Graph::LabelFetcher::Fetch(EdgeId e, vector<S2Builder::Label>* labels) {
130
+ labels->clear();
131
+ for (InputEdgeId input_edge_id : g_->input_edge_ids(e)) {
132
+ for (Label label : g_->labels(input_edge_id)) {
133
+ labels->push_back(label);
134
+ }
135
+ }
136
+ if (edge_type_ == EdgeType::UNDIRECTED) {
137
+ for (InputEdgeId input_edge_id : g_->input_edge_ids(sibling_map_[e])) {
138
+ for (Label label : g_->labels(input_edge_id)) {
139
+ labels->push_back(label);
140
+ }
141
+ }
142
+ }
143
+ if (labels->size() > 1) {
144
+ std::sort(labels->begin(), labels->end());
145
+ labels->erase(std::unique(labels->begin(), labels->end()), labels->end());
146
+ }
147
+ }
148
+
149
+ S2Builder::InputEdgeId Graph::min_input_edge_id(EdgeId e) const {
150
+ IdSetLexicon::IdSet id_set = input_edge_ids(e);
151
+ return (id_set.size() == 0) ? kNoInputEdgeId : *id_set.begin();
152
+ }
153
+
154
+ vector<S2Builder::InputEdgeId> Graph::GetMinInputEdgeIds() const {
155
+ vector<InputEdgeId> min_input_ids(num_edges());
156
+ for (EdgeId e = 0; e < num_edges(); ++e) {
157
+ min_input_ids[e] = min_input_edge_id(e);
158
+ }
159
+ return min_input_ids;
160
+ }
161
+
162
+ vector<Graph::EdgeId> Graph::GetInputEdgeOrder(
163
+ const vector<InputEdgeId>& input_ids) const {
164
+ vector<EdgeId> order(input_ids.size());
165
+ std::iota(order.begin(), order.end(), 0);
166
+ std::sort(order.begin(), order.end(), [&input_ids](EdgeId a, EdgeId b) {
167
+ // Comparison function ensures sort is stable.
168
+ return make_pair(input_ids[a], a) < make_pair(input_ids[b], b);
169
+ });
170
+ return order;
171
+ }
172
+
173
+ // A struct for sorting the incoming and outgoing edges around a vertex "v0".
174
+ struct VertexEdge {
175
+ VertexEdge(bool _incoming, Graph::EdgeId _index,
176
+ Graph::VertexId _endpoint, int32 _rank)
177
+ : incoming(_incoming), index(_index),
178
+ endpoint(_endpoint), rank(_rank) {
179
+ }
180
+ bool incoming; // Is this an incoming edge to "v0"?
181
+ Graph::EdgeId index; // Index of this edge in "edges_" or "in_edge_ids"
182
+ Graph::VertexId endpoint; // The other (not "v0") endpoint of this edge
183
+ int32 rank; // Secondary key for edges with the same endpoint
184
+ };
185
+
186
+ // Given a set of duplicate outgoing edges (v0, v1) and a set of duplicate
187
+ // incoming edges (v1, v0), this method assigns each edge an integer "rank" so
188
+ // that the edges are sorted in a consistent order with respect to their
189
+ // orderings around "v0" and "v1". Usually there is just one edge, in which
190
+ // case this is easy. Sometimes there is one edge in each direction, in which
191
+ // case the outgoing edge is always ordered before the incoming edge.
192
+ //
193
+ // In general, we allow any number of duplicate edges in each direction, in
194
+ // which case outgoing edges are interleaved with incoming edges so as to
195
+ // create as many degenerate (two-edge) loops as possible. In order to get a
196
+ // consistent ordering around "v0" and "v1", we move forwards through the list
197
+ // of outgoing edges and backwards through the list of incoming edges. If
198
+ // there are more incoming edges, they go at the beginning of the ordering,
199
+ // while if there are more outgoing edges then they go at the end.
200
+ //
201
+ // For example, suppose there are 2 edges "a,b" from "v0" to "v1", and 4 edges
202
+ // "w,x,y,z" from "v1" to "v0". Using lower/upper case letters to represent
203
+ // incoming/outgoing edges, the clockwise ordering around v0 would be zyAxBw,
204
+ // and the clockwise ordering around v1 would be WbXaYZ. (Try making a
205
+ // diagram with each edge as a separate arc.)
206
+ static void AddVertexEdges(Graph::EdgeId out_begin, Graph::EdgeId out_end,
207
+ Graph::EdgeId in_begin, Graph::EdgeId in_end,
208
+ Graph::VertexId v1, vector<VertexEdge>* v0_edges) {
209
+ int rank = 0;
210
+ // Any extra incoming edges go at the beginning of the ordering.
211
+ while (in_end - in_begin > out_end - out_begin) {
212
+ v0_edges->push_back(VertexEdge(true, --in_end, v1, rank++));
213
+ }
214
+ // Next we interleave as many outgoing and incoming edges as possible.
215
+ while (in_end > in_begin) {
216
+ v0_edges->push_back(VertexEdge(false, out_begin++, v1, rank++));
217
+ v0_edges->push_back(VertexEdge(true, --in_end, v1, rank++));
218
+ }
219
+ // Any extra outgoing edges to at the end of the ordering.
220
+ while (out_end > out_begin) {
221
+ v0_edges->push_back(VertexEdge(false, out_begin++, v1, rank++));
222
+ }
223
+ }
224
+
225
+ bool Graph::GetLeftTurnMap(const vector<EdgeId>& in_edge_ids,
226
+ vector<EdgeId>* left_turn_map,
227
+ S2Error* error) const {
228
+ left_turn_map->assign(num_edges(), -1);
229
+ if (num_edges() == 0) return true;
230
+
231
+ // Declare vectors outside the loop to avoid reallocating them each time.
232
+ vector<VertexEdge> v0_edges;
233
+ vector<EdgeId> e_in, e_out;
234
+
235
+ // Walk through the two sorted arrays of edges (outgoing and incoming) and
236
+ // gather all the edges incident to each vertex. Then we sort those edges
237
+ // and add an entry to the left turn map from each incoming edge to the
238
+ // immediately following outgoing edge in clockwise order.
239
+ int out = 0, in = 0;
240
+ const Edge* out_edge = &edge(out);
241
+ const Edge* in_edge = &edge(in_edge_ids[in]);
242
+ Edge sentinel(num_vertices(), num_vertices());
243
+ Edge min_edge = min(*out_edge, reverse(*in_edge));
244
+ while (min_edge != sentinel) {
245
+ // Gather all incoming and outgoing edges around vertex "v0".
246
+ VertexId v0 = min_edge.first;
247
+ for (; min_edge.first == v0; min_edge = min(*out_edge, reverse(*in_edge))) {
248
+ VertexId v1 = min_edge.second;
249
+ // Count the number of copies of "min_edge" in each direction.
250
+ int out_begin = out, in_begin = in;
251
+ while (*out_edge == min_edge) {
252
+ out_edge = (++out == num_edges()) ? &sentinel : &edge(out);
253
+ }
254
+ while (reverse(*in_edge) == min_edge) {
255
+ in_edge = (++in == num_edges()) ? &sentinel : &edge(in_edge_ids[in]);
256
+ }
257
+ if (v0 != v1) {
258
+ AddVertexEdges(out_begin, out, in_begin, in, v1, &v0_edges);
259
+ } else {
260
+ // Each degenerate edge becomes its own loop.
261
+ for (; in_begin < in; ++in_begin) {
262
+ (*left_turn_map)[in_begin] = in_begin;
263
+ }
264
+ }
265
+ }
266
+ if (v0_edges.empty()) continue;
267
+
268
+ // Sort the edges in clockwise order around "v0".
269
+ VertexId min_endpoint = v0_edges.front().endpoint;
270
+ std::sort(v0_edges.begin() + 1, v0_edges.end(),
271
+ [v0, min_endpoint, this](const VertexEdge& a,
272
+ const VertexEdge& b) {
273
+ if (a.endpoint == b.endpoint) return a.rank < b.rank;
274
+ if (a.endpoint == min_endpoint) return true;
275
+ if (b.endpoint == min_endpoint) return false;
276
+ return !s2pred::OrderedCCW(vertex(a.endpoint), vertex(b.endpoint),
277
+ vertex(min_endpoint), vertex(v0));
278
+ });
279
+ // Match incoming with outgoing edges. We do this by keeping a stack of
280
+ // unmatched incoming edges. We also keep a stack of outgoing edges with
281
+ // no previous incoming edge, and match these at the end by wrapping
282
+ // around circularly to the start of the edge ordering.
283
+ for (const VertexEdge& e : v0_edges) {
284
+ if (e.incoming) {
285
+ e_in.push_back(in_edge_ids[e.index]);
286
+ } else if (!e_in.empty()) {
287
+ (*left_turn_map)[e_in.back()] = e.index;
288
+ e_in.pop_back();
289
+ } else {
290
+ e_out.push_back(e.index); // Matched below.
291
+ }
292
+ }
293
+ // Pair up additional edges using the fact that the ordering is circular.
294
+ std::reverse(e_out.begin(), e_out.end());
295
+ for (; !e_out.empty() && !e_in.empty(); e_out.pop_back(), e_in.pop_back()) {
296
+ (*left_turn_map)[e_in.back()] = e_out.back();
297
+ }
298
+ // We only need to process unmatched incoming edges, since we are only
299
+ // responsible for creating left turn map entries for those edges.
300
+ if (!e_in.empty() && error->ok()) {
301
+ error->Init(S2Error::BUILDER_EDGES_DO_NOT_FORM_LOOPS,
302
+ "Given edges do not form loops (indegree != outdegree)");
303
+ }
304
+ e_in.clear();
305
+ e_out.clear();
306
+ v0_edges.clear();
307
+ }
308
+ return error->ok();
309
+ }
310
+
311
+ void Graph::CanonicalizeLoopOrder(const vector<InputEdgeId>& min_input_ids,
312
+ vector<EdgeId>* loop) {
313
+ if (loop->empty()) return;
314
+ // Find the position of the element with the highest input edge id. If
315
+ // there are multiple such elements together (i.e., the edge was split
316
+ // into several pieces by snapping it to several vertices), then we choose
317
+ // the last such position in cyclic order (this attempts to preserve the
318
+ // original loop order even when new vertices are added). For example, if
319
+ // the input edge id sequence is (7, 7, 4, 5, 6, 7) then we would rotate
320
+ // it to obtain (4, 5, 6, 7, 7, 7).
321
+
322
+ // The reason that we put the highest-numbered edge last, rather than the
323
+ // lowest-numbered edge first, is that S2Loop::Invert() reverses the loop
324
+ // edge order *except* for the last edge. For example, the loop ABCD (with
325
+ // edges AB, BC, CD, DA) becomes DCBA (with edges DC, CB, BA, AD). Note
326
+ // that the last edge is the same except for its direction (DA vs. AD).
327
+ // This has the advantage that if an undirected loop is assembled with the
328
+ // wrong orientation and later inverted (e.g. by S2Polygon::InitOriented),
329
+ // we still end up preserving the original cyclic vertex order.
330
+ int pos = 0;
331
+ bool saw_gap = false;
332
+ for (int i = 1; i < loop->size(); ++i) {
333
+ int cmp = min_input_ids[(*loop)[i]] - min_input_ids[(*loop)[pos]];
334
+ if (cmp < 0) {
335
+ saw_gap = true;
336
+ } else if (cmp > 0 || !saw_gap) {
337
+ pos = i;
338
+ saw_gap = false;
339
+ }
340
+ }
341
+ if (++pos == loop->size()) pos = 0; // Convert loop end to loop start.
342
+ std::rotate(loop->begin(), loop->begin() + pos, loop->end());
343
+ }
344
+
345
+ void Graph::CanonicalizeVectorOrder(const vector<InputEdgeId>& min_input_ids,
346
+ vector<vector<EdgeId>>* chains) {
347
+ std::sort(chains->begin(), chains->end(),
348
+ [&min_input_ids](const vector<EdgeId>& a, const vector<EdgeId>& b) {
349
+ return min_input_ids[a[0]] < min_input_ids[b[0]];
350
+ });
351
+ }
352
+
353
+ bool Graph::GetDirectedLoops(LoopType loop_type, vector<EdgeLoop>* loops,
354
+ S2Error* error) const {
355
+ S2_DCHECK(options_.degenerate_edges() == DegenerateEdges::DISCARD ||
356
+ options_.degenerate_edges() == DegenerateEdges::DISCARD_EXCESS);
357
+ S2_DCHECK(options_.edge_type() == EdgeType::DIRECTED);
358
+
359
+ vector<EdgeId> left_turn_map;
360
+ if (!GetLeftTurnMap(GetInEdgeIds(), &left_turn_map, error)) return false;
361
+ vector<InputEdgeId> min_input_ids = GetMinInputEdgeIds();
362
+
363
+ // If we are breaking loops at repeated vertices, we maintain a map from
364
+ // VertexId to its position in "path".
365
+ vector<int> path_index;
366
+ if (loop_type == LoopType::SIMPLE) path_index.assign(num_vertices(), -1);
367
+
368
+ // Visit edges in arbitrary order, and try to build a loop from each edge.
369
+ vector<EdgeId> path;
370
+ for (EdgeId start = 0; start < num_edges(); ++start) {
371
+ if (left_turn_map[start] < 0) continue;
372
+
373
+ // Build a loop by making left turns at each vertex until we return to
374
+ // "start". We use "left_turn_map" to keep track of which edges have
375
+ // already been visited by setting its entries to -1 as we go along. If
376
+ // we are building vertex cycles, then whenever we encounter a vertex that
377
+ // is already part of the path, we "peel off" a loop by removing those
378
+ // edges from the path so far.
379
+ for (EdgeId e = start, next; left_turn_map[e] >= 0; e = next) {
380
+ path.push_back(e);
381
+ next = left_turn_map[e];
382
+ left_turn_map[e] = -1;
383
+ if (loop_type == LoopType::SIMPLE) {
384
+ path_index[edge(e).first] = path.size() - 1;
385
+ int loop_start = path_index[edge(e).second];
386
+ if (loop_start < 0) continue;
387
+ // Peel off a loop from the path.
388
+ vector<EdgeId> loop(path.begin() + loop_start, path.end());
389
+ path.erase(path.begin() + loop_start, path.end());
390
+ for (EdgeId e2 : loop) path_index[edge(e2).first] = -1;
391
+ CanonicalizeLoopOrder(min_input_ids, &loop);
392
+ loops->push_back(std::move(loop));
393
+ }
394
+ }
395
+ if (loop_type == LoopType::SIMPLE) {
396
+ S2_DCHECK(path.empty()); // Invariant.
397
+ } else {
398
+ CanonicalizeLoopOrder(min_input_ids, &path);
399
+ loops->push_back(std::move(path));
400
+ path.clear();
401
+ }
402
+ }
403
+ CanonicalizeVectorOrder(min_input_ids, loops);
404
+ return true;
405
+ }
406
+
407
+ bool Graph::GetDirectedComponents(
408
+ DegenerateBoundaries degenerate_boundaries,
409
+ vector<DirectedComponent>* components, S2Error* error) const {
410
+ S2_DCHECK(options_.degenerate_edges() == DegenerateEdges::DISCARD ||
411
+ (options_.degenerate_edges() == DegenerateEdges::DISCARD_EXCESS &&
412
+ degenerate_boundaries == DegenerateBoundaries::KEEP));
413
+ S2_DCHECK(options_.sibling_pairs() == SiblingPairs::REQUIRE ||
414
+ options_.sibling_pairs() == SiblingPairs::CREATE);
415
+ S2_DCHECK(options_.edge_type() == EdgeType::DIRECTED); // Implied by above.
416
+
417
+ vector<EdgeId> sibling_map = GetInEdgeIds();
418
+ vector<EdgeId> left_turn_map;
419
+ if (!GetLeftTurnMap(sibling_map, &left_turn_map, error)) return false;
420
+ MakeSiblingMap(&sibling_map);
421
+ vector<InputEdgeId> min_input_ids = GetMinInputEdgeIds();
422
+ vector<EdgeId> frontier; // Unexplored sibling edges.
423
+
424
+ // A map from EdgeId to the position of that edge in "path". Only needed if
425
+ // degenerate boundaries are being discarded.
426
+ vector<int> path_index;
427
+ if (degenerate_boundaries == DegenerateBoundaries::DISCARD) {
428
+ path_index.assign(num_edges(), -1);
429
+ }
430
+ for (EdgeId min_start = 0; min_start < num_edges(); ++min_start) {
431
+ if (left_turn_map[min_start] < 0) continue; // Already used.
432
+
433
+ // Build a connected component by keeping a stack of unexplored siblings
434
+ // of the edges used so far.
435
+ DirectedComponent component;
436
+ frontier.push_back(min_start);
437
+ while (!frontier.empty()) {
438
+ EdgeId start = frontier.back();
439
+ frontier.pop_back();
440
+ if (left_turn_map[start] < 0) continue; // Already used.
441
+
442
+ // Build a path by making left turns at each vertex until we return to
443
+ // "start". Whenever we encounter an edge that is a sibling of an edge
444
+ // that is already on the path, we "peel off" a loop consisting of any
445
+ // edges that were between these two edges.
446
+ vector<EdgeId> path;
447
+ for (EdgeId e = start, next; left_turn_map[e] >= 0; e = next) {
448
+ path.push_back(e);
449
+ next = left_turn_map[e];
450
+ left_turn_map[e] = -1;
451
+ // If the sibling hasn't been visited yet, add it to the frontier.
452
+ EdgeId sibling = sibling_map[e];
453
+ if (left_turn_map[sibling] >= 0) {
454
+ frontier.push_back(sibling);
455
+ }
456
+ if (degenerate_boundaries == DegenerateBoundaries::DISCARD) {
457
+ path_index[e] = path.size() - 1;
458
+ int sibling_index = path_index[sibling];
459
+ if (sibling_index < 0) continue;
460
+
461
+ // Common special case: the edge and its sibling are adjacent, in
462
+ // which case we can simply remove them from the path and continue.
463
+ if (sibling_index == path.size() - 2) {
464
+ path.resize(sibling_index);
465
+ // We don't need to update "path_index" for these two edges
466
+ // because both edges of the sibling pair have now been used.
467
+ continue;
468
+ }
469
+ // Peel off a loop from the path.
470
+ vector<EdgeId> loop(path.begin() + sibling_index + 1, path.end() - 1);
471
+ path.erase(path.begin() + sibling_index, path.end());
472
+ // Mark the edges that are no longer part of the path.
473
+ for (EdgeId e2 : loop) path_index[e2] = -1;
474
+ CanonicalizeLoopOrder(min_input_ids, &loop);
475
+ component.push_back(std::move(loop));
476
+ }
477
+ }
478
+ // Mark the edges that are no longer part of the path.
479
+ if (degenerate_boundaries == DegenerateBoundaries::DISCARD) {
480
+ for (EdgeId e2 : path) path_index[e2] = -1;
481
+ }
482
+ CanonicalizeLoopOrder(min_input_ids, &path);
483
+ component.push_back(std::move(path));
484
+ }
485
+ CanonicalizeVectorOrder(min_input_ids, &component);
486
+ components->push_back(std::move(component));
487
+ }
488
+ // Sort the components to correspond to the input edge ordering.
489
+ std::sort(components->begin(), components->end(),
490
+ [&min_input_ids](const DirectedComponent& a,
491
+ const DirectedComponent& b) {
492
+ return min_input_ids[a[0][0]] < min_input_ids[b[0][0]];
493
+ });
494
+ return true;
495
+ }
496
+
497
+ // Encodes the index of one of the two complements of each component
498
+ // (a.k.a. the "slot", either 0 or 1) as a negative EdgeId.
499
+ inline static Graph::EdgeId MarkEdgeUsed(int slot) { return -1 - slot; }
500
+
501
+ bool Graph::GetUndirectedComponents(LoopType loop_type,
502
+ vector<UndirectedComponent>* components,
503
+ S2Error* error) const {
504
+ S2_DCHECK(options_.degenerate_edges() == DegenerateEdges::DISCARD ||
505
+ options_.degenerate_edges() == DegenerateEdges::DISCARD_EXCESS);
506
+ S2_DCHECK(options_.edge_type() == EdgeType::UNDIRECTED);
507
+
508
+ vector<EdgeId> sibling_map = GetInEdgeIds();
509
+ vector<EdgeId> left_turn_map;
510
+ if (!GetLeftTurnMap(sibling_map, &left_turn_map, error)) return false;
511
+ MakeSiblingMap(&sibling_map);
512
+ vector<InputEdgeId> min_input_ids = GetMinInputEdgeIds();
513
+
514
+ // A stack of unexplored sibling edges. Each sibling edge has a "slot"
515
+ // (0 or 1) that indicates which of the two complements it belongs to.
516
+ vector<pair<EdgeId, int>> frontier;
517
+
518
+ // If we are breaking loops at repeated vertices, we maintain a map from
519
+ // VertexId to its position in "path".
520
+ vector<int> path_index;
521
+ if (loop_type == LoopType::SIMPLE) path_index.assign(num_vertices(), -1);
522
+
523
+ for (EdgeId min_start = 0; min_start < num_edges(); ++min_start) {
524
+ if (left_turn_map[min_start] < 0) continue; // Already used.
525
+
526
+ // Build a connected component by keeping a stack of unexplored siblings
527
+ // of the edges used so far.
528
+ UndirectedComponent component;
529
+ frontier.push_back(make_pair(min_start, 0));
530
+ while (!frontier.empty()) {
531
+ EdgeId start = frontier.back().first;
532
+ int slot = frontier.back().second;
533
+ frontier.pop_back();
534
+ if (left_turn_map[start] < 0) continue; // Already used.
535
+
536
+ // Build a path by making left turns at each vertex until we return to
537
+ // "start". We use "left_turn_map" to keep track of which edges have
538
+ // already been visited, and which complement they were assigned to, by
539
+ // setting its entries to negative values as we go along.
540
+ vector<EdgeId> path;
541
+ for (EdgeId e = start, next; left_turn_map[e] >= 0; e = next) {
542
+ path.push_back(e);
543
+ next = left_turn_map[e];
544
+ left_turn_map[e] = MarkEdgeUsed(slot);
545
+ // If the sibling hasn't been visited yet, add it to the frontier.
546
+ EdgeId sibling = sibling_map[e];
547
+ if (left_turn_map[sibling] >= 0) {
548
+ frontier.push_back(make_pair(sibling, 1 - slot));
549
+ } else if (left_turn_map[sibling] != MarkEdgeUsed(1 - slot)) {
550
+ // Two siblings edges can only belong the same complement if the
551
+ // given undirected edges do not form loops.
552
+ error->Init(S2Error::BUILDER_EDGES_DO_NOT_FORM_LOOPS,
553
+ "Given undirected edges do not form loops");
554
+ return false;
555
+ }
556
+ if (loop_type == LoopType::SIMPLE) {
557
+ // Whenever we encounter a vertex that is already part of the path,
558
+ // we "peel off" a loop by removing those edges from the path.
559
+ path_index[edge(e).first] = path.size() - 1;
560
+ int loop_start = path_index[edge(e).second];
561
+ if (loop_start < 0) continue;
562
+ vector<EdgeId> loop(path.begin() + loop_start, path.end());
563
+ path.erase(path.begin() + loop_start, path.end());
564
+ // Mark the vertices that are no longer part of the path.
565
+ for (EdgeId e2 : loop) path_index[edge(e2).first] = -1;
566
+ CanonicalizeLoopOrder(min_input_ids, &loop);
567
+ component[slot].push_back(std::move(loop));
568
+ }
569
+ }
570
+ if (loop_type == LoopType::SIMPLE) {
571
+ S2_DCHECK(path.empty()); // Invariant.
572
+ } else {
573
+ CanonicalizeLoopOrder(min_input_ids, &path);
574
+ component[slot].push_back(std::move(path));
575
+ }
576
+ }
577
+ CanonicalizeVectorOrder(min_input_ids, &component[0]);
578
+ CanonicalizeVectorOrder(min_input_ids, &component[1]);
579
+ // To save some work in S2PolygonLayer, we swap the two loop sets of the
580
+ // component so that the loop set whose first loop most closely follows
581
+ // the input edge ordering is first. (If the input was a valid S2Polygon,
582
+ // then this component will contain normalized loops.)
583
+ if (min_input_ids[component[0][0][0]] > min_input_ids[component[1][0][0]]) {
584
+ component[0].swap(component[1]);
585
+ }
586
+ components->push_back(std::move(component));
587
+ }
588
+ // Sort the components to correspond to the input edge ordering.
589
+ std::sort(components->begin(), components->end(),
590
+ [&min_input_ids](const UndirectedComponent& a,
591
+ const UndirectedComponent& b) {
592
+ return min_input_ids[a[0][0][0]] < min_input_ids[b[0][0][0]];
593
+ });
594
+ return true;
595
+ }
596
+
597
+ class Graph::PolylineBuilder {
598
+ public:
599
+ explicit PolylineBuilder(const Graph& g);
600
+ vector<EdgePolyline> BuildPaths();
601
+ vector<EdgePolyline> BuildWalks();
602
+
603
+ private:
604
+ bool is_interior(VertexId v);
605
+ int excess_degree(VertexId v);
606
+ EdgePolyline BuildPath(EdgeId e);
607
+ EdgePolyline BuildWalk(VertexId v);
608
+ void MaximizeWalk(EdgePolyline* polyline);
609
+
610
+ const Graph& g_;
611
+ Graph::VertexInMap in_;
612
+ Graph::VertexOutMap out_;
613
+ vector<EdgeId> sibling_map_;
614
+ vector<InputEdgeId> min_input_ids_;
615
+ bool directed_;
616
+ int edges_left_;
617
+ vector<bool> used_;
618
+ // A map of (outdegree(v) - indegree(v)) considering used edges only.
619
+ gtl::btree_map<VertexId, int> excess_used_;
620
+ };
621
+
622
+ vector<Graph::EdgePolyline> Graph::GetPolylines(
623
+ PolylineType polyline_type) const {
624
+ S2_DCHECK(options_.sibling_pairs() == SiblingPairs::DISCARD ||
625
+ options_.sibling_pairs() == SiblingPairs::DISCARD_EXCESS ||
626
+ options_.sibling_pairs() == SiblingPairs::KEEP);
627
+ PolylineBuilder builder(*this);
628
+ if (polyline_type == PolylineType::PATH) {
629
+ return builder.BuildPaths();
630
+ } else {
631
+ return builder.BuildWalks();
632
+ }
633
+ }
634
+
635
+ Graph::PolylineBuilder::PolylineBuilder(const Graph& g)
636
+ : g_(g), in_(g), out_(g),
637
+ min_input_ids_(g.GetMinInputEdgeIds()),
638
+ directed_(g_.options().edge_type() == EdgeType::DIRECTED),
639
+ edges_left_(g.num_edges() / (directed_ ? 1 : 2)),
640
+ used_(g.num_edges(), false) {
641
+ if (!directed_) {
642
+ sibling_map_ = in_.in_edge_ids();
643
+ g.MakeSiblingMap(&sibling_map_);
644
+ }
645
+ }
646
+
647
+ inline bool Graph::PolylineBuilder::is_interior(VertexId v) {
648
+ if (directed_) {
649
+ return in_.degree(v) == 1 && out_.degree(v) == 1;
650
+ } else {
651
+ return out_.degree(v) == 2;
652
+ }
653
+ }
654
+
655
+ inline int Graph::PolylineBuilder::excess_degree(VertexId v) {
656
+ return directed_ ? out_.degree(v) - in_.degree(v) : out_.degree(v) % 2;
657
+ }
658
+
659
+ vector<Graph::EdgePolyline> Graph::PolylineBuilder::BuildPaths() {
660
+ // First build polylines starting at all the vertices that cannot be in the
661
+ // polyline interior (i.e., indegree != 1 or outdegree != 1 for directed
662
+ // edges, or degree != 2 for undirected edges). We consider the possible
663
+ // starting edges in input edge id order so that we preserve the input path
664
+ // direction even when undirected edges are used. (Undirected edges are
665
+ // represented by sibling pairs where only the edge in the input direction
666
+ // is labeled with an input edge id.)
667
+ vector<EdgePolyline> polylines;
668
+ vector<EdgeId> edges = g_.GetInputEdgeOrder(min_input_ids_);
669
+ for (EdgeId e : edges) {
670
+ if (!used_[e] && !is_interior(g_.edge(e).first)) {
671
+ polylines.push_back(BuildPath(e));
672
+ }
673
+ }
674
+ // If there are any edges left, they form non-intersecting loops. We build
675
+ // each loop and then canonicalize its edge order. We consider candidate
676
+ // starting edges in input edge id order in order to preserve the input
677
+ // direction of undirected loops. Even so, we still need to canonicalize
678
+ // the edge order to ensure that when an input edge is split into an edge
679
+ // chain, the loop does not start in the middle of such a chain.
680
+ for (EdgeId e : edges) {
681
+ if (edges_left_ == 0) break;
682
+ if (used_[e]) continue;
683
+ EdgePolyline polyline = BuildPath(e);
684
+ CanonicalizeLoopOrder(min_input_ids_, &polyline);
685
+ polylines.push_back(std::move(polyline));
686
+ }
687
+ S2_DCHECK_EQ(0, edges_left_);
688
+
689
+ // Sort the polylines to correspond to the input order (if possible).
690
+ CanonicalizeVectorOrder(min_input_ids_, &polylines);
691
+ return polylines;
692
+ }
693
+
694
+ Graph::EdgePolyline Graph::PolylineBuilder::BuildPath(EdgeId e) {
695
+ // We simply follow edges until either we reach a vertex where there is a
696
+ // choice about which way to go (where is_interior(v) is false), or we
697
+ // return to the starting vertex (if the polyline is actually a loop).
698
+ EdgePolyline polyline;
699
+ VertexId start = g_.edge(e).first;
700
+ for (;;) {
701
+ polyline.push_back(e);
702
+ S2_DCHECK(!used_[e]);
703
+ used_[e] = true;
704
+ if (!directed_) used_[sibling_map_[e]] = true;
705
+ --edges_left_;
706
+ VertexId v = g_.edge(e).second;
707
+ if (!is_interior(v) || v == start) break;
708
+ if (directed_) {
709
+ S2_DCHECK_EQ(1, out_.degree(v));
710
+ e = *out_.edge_ids(v).begin();
711
+ } else {
712
+ S2_DCHECK_EQ(2, out_.degree(v));
713
+ for (EdgeId e2 : out_.edge_ids(v)) if (!used_[e2]) e = e2;
714
+ }
715
+ }
716
+ return polyline;
717
+ }
718
+
719
+ vector<Graph::EdgePolyline> Graph::PolylineBuilder::BuildWalks() {
720
+ // Note that some of this code is worst-case quadratic in the maximum vertex
721
+ // degree. This could be fixed with a few extra arrays, but it should not
722
+ // be a problem in practice.
723
+
724
+ // First, build polylines from all vertices where outdegree > indegree (or
725
+ // for undirected edges, vertices whose degree is odd). We consider the
726
+ // possible starting edges in input edge id order, for idempotency in the
727
+ // case where multiple input polylines share vertices or edges.
728
+ vector<EdgePolyline> polylines;
729
+ vector<EdgeId> edges = g_.GetInputEdgeOrder(min_input_ids_);
730
+ for (EdgeId e : edges) {
731
+ if (used_[e]) continue;
732
+ VertexId v = g_.edge(e).first;
733
+ int excess = excess_degree(v);
734
+ if (excess <= 0) continue;
735
+ excess -= excess_used_[v];
736
+ if (directed_ ? (excess <= 0) : (excess % 2 == 0)) continue;
737
+ ++excess_used_[v];
738
+ polylines.push_back(BuildWalk(v));
739
+ --excess_used_[g_.edge(polylines.back().back()).second];
740
+ }
741
+ // Now all vertices have outdegree == indegree (or even degree if undirected
742
+ // edges are being used). Therefore all remaining edges can be assembled
743
+ // into loops. We first try to expand the existing polylines if possible by
744
+ // adding loops to them.
745
+ if (edges_left_ > 0) {
746
+ for (EdgePolyline& polyline : polylines) {
747
+ MaximizeWalk(&polyline);
748
+ }
749
+ }
750
+ // Finally, if there are still unused edges then we build loops. If the
751
+ // input is a polyline that forms a loop, then for idempotency we need to
752
+ // start from the edge with minimum input edge id. If the minimal input
753
+ // edge was split into several edges, then we start from the first edge of
754
+ // the chain.
755
+ for (int i = 0; i < edges.size() && edges_left_ > 0; ++i) {
756
+ EdgeId e = edges[i];
757
+ if (used_[e]) continue;
758
+
759
+ // Determine whether the origin of this edge is the start of an edge
760
+ // chain. To do this, we test whether (outdegree - indegree == 1) for the
761
+ // origin, considering only unused edges with the same minimum input edge
762
+ // id. (Undirected edges have input edge ids in one direction only.)
763
+ VertexId v = g_.edge(e).first;
764
+ InputEdgeId id = min_input_ids_[e];
765
+ int excess = 0;
766
+ for (int j = i; j < edges.size() && min_input_ids_[edges[j]] == id; ++j) {
767
+ EdgeId e2 = edges[j];
768
+ if (used_[e2]) continue;
769
+ if (g_.edge(e2).first == v) ++excess;
770
+ if (g_.edge(e2).second == v) --excess;
771
+ }
772
+ // It is also acceptable to start a polyline from any degenerate edge.
773
+ if (excess == 1 || g_.edge(e).second == v) {
774
+ EdgePolyline polyline = BuildWalk(v);
775
+ MaximizeWalk(&polyline);
776
+ polylines.push_back(std::move(polyline));
777
+ }
778
+ }
779
+ S2_DCHECK_EQ(0, edges_left_);
780
+
781
+ // Sort the polylines to correspond to the input order (if possible).
782
+ CanonicalizeVectorOrder(min_input_ids_, &polylines);
783
+ return polylines;
784
+ }
785
+
786
+ Graph::EdgePolyline Graph::PolylineBuilder::BuildWalk(VertexId v) {
787
+ EdgePolyline polyline;
788
+ for (;;) {
789
+ // Follow the edge with the smallest input edge id.
790
+ EdgeId best_edge = -1;
791
+ InputEdgeId best_out_id = std::numeric_limits<InputEdgeId>::max();
792
+ for (EdgeId e : out_.edge_ids(v)) {
793
+ if (used_[e] || min_input_ids_[e] >= best_out_id) continue;
794
+ best_out_id = min_input_ids_[e];
795
+ best_edge = e;
796
+ }
797
+ if (best_edge < 0) return polyline;
798
+ // For idempotency when there are multiple input polylines, we stop the
799
+ // walk early if "best_edge" might be a continuation of a different
800
+ // incoming edge.
801
+ int excess = excess_degree(v) - excess_used_[v];
802
+ if (directed_ ? (excess < 0) : (excess % 2) == 1) {
803
+ for (EdgeId e : in_.edge_ids(v)) {
804
+ if (!used_[e] && min_input_ids_[e] <= best_out_id) {
805
+ return polyline;
806
+ }
807
+ }
808
+ }
809
+ polyline.push_back(best_edge);
810
+ used_[best_edge] = true;
811
+ if (!directed_) used_[sibling_map_[best_edge]] = true;
812
+ --edges_left_;
813
+ v = g_.edge(best_edge).second;
814
+ }
815
+ }
816
+
817
+ void Graph::PolylineBuilder::MaximizeWalk(EdgePolyline* polyline) {
818
+ // Examine all vertices of the polyline and check whether there are any
819
+ // unused outgoing edges. If so, then build a loop starting at that vertex
820
+ // and insert it into the polyline. (The walk is guaranteed to be a loop
821
+ // because this method is only called when all vertices have equal numbers
822
+ // of unused incoming and outgoing edges.)
823
+ for (int i = 0; i <= polyline->size(); ++i) {
824
+ VertexId v = (i == 0 ? g_.edge((*polyline)[i]).first
825
+ : g_.edge((*polyline)[i - 1]).second);
826
+ for (EdgeId e : out_.edge_ids(v)) {
827
+ if (!used_[e]) {
828
+ EdgePolyline loop = BuildWalk(v);
829
+ S2_DCHECK_EQ(v, g_.edge(loop.back()).second);
830
+ polyline->insert(polyline->begin() + i, loop.begin(), loop.end());
831
+ S2_DCHECK(used_[e]); // All outgoing edges from "v" are now used.
832
+ break;
833
+ }
834
+ }
835
+ }
836
+ }
837
+
838
+ class Graph::EdgeProcessor {
839
+ public:
840
+ EdgeProcessor(const GraphOptions& options,
841
+ vector<Edge>* edges,
842
+ vector<InputEdgeIdSetId>* input_ids,
843
+ IdSetLexicon* id_set_lexicon);
844
+ void Run(S2Error* error);
845
+
846
+ private:
847
+ void AddEdge(const Edge& edge, InputEdgeIdSetId input_edge_id_set_id);
848
+ void AddEdges(int num_edges, const Edge& edge,
849
+ InputEdgeIdSetId input_edge_id_set_id);
850
+ void CopyEdges(int out_begin, int out_end);
851
+ InputEdgeIdSetId MergeInputIds(int out_begin, int out_end);
852
+
853
+ GraphOptions options_;
854
+ vector<Edge>& edges_;
855
+ vector<InputEdgeIdSetId>& input_ids_;
856
+ IdSetLexicon* id_set_lexicon_;
857
+ vector<EdgeId> out_edges_;
858
+ vector<EdgeId> in_edges_;
859
+
860
+ vector<Edge> new_edges_;
861
+ vector<InputEdgeIdSetId> new_input_ids_;
862
+
863
+ vector<InputEdgeId> tmp_ids_;
864
+ };
865
+
866
+ void Graph::ProcessEdges(
867
+ GraphOptions* options, std::vector<Edge>* edges,
868
+ std::vector<InputEdgeIdSetId>* input_ids, IdSetLexicon* id_set_lexicon,
869
+ S2Error* error) {
870
+ EdgeProcessor processor(*options, edges, input_ids, id_set_lexicon);
871
+ processor.Run(error);
872
+ // Certain values of sibling_pairs() discard half of the edges and change
873
+ // the edge_type() to DIRECTED (see the description of GraphOptions).
874
+ if (options->sibling_pairs() == SiblingPairs::REQUIRE ||
875
+ options->sibling_pairs() == SiblingPairs::CREATE) {
876
+ options->set_edge_type(EdgeType::DIRECTED);
877
+ }
878
+ }
879
+
880
+ Graph::EdgeProcessor::EdgeProcessor(const GraphOptions& options,
881
+ vector<Edge>* edges,
882
+ vector<InputEdgeIdSetId>* input_ids,
883
+ IdSetLexicon* id_set_lexicon)
884
+ : options_(options), edges_(*edges),
885
+ input_ids_(*input_ids), id_set_lexicon_(id_set_lexicon),
886
+ out_edges_(edges_.size()), in_edges_(edges_.size()) {
887
+ // Sort the outgoing and incoming edges in lexigraphic order. We use a
888
+ // stable sort to ensure that each undirected edge becomes a sibling pair,
889
+ // even if there are multiple identical input edges.
890
+ std::iota(out_edges_.begin(), out_edges_.end(), 0);
891
+ std::sort(out_edges_.begin(), out_edges_.end(), [this](EdgeId a, EdgeId b) {
892
+ return StableLessThan(edges_[a], edges_[b], a, b);
893
+ });
894
+ std::iota(in_edges_.begin(), in_edges_.end(), 0);
895
+ std::sort(in_edges_.begin(), in_edges_.end(), [this](EdgeId a, EdgeId b) {
896
+ return StableLessThan(reverse(edges_[a]), reverse(edges_[b]), a, b);
897
+ });
898
+ new_edges_.reserve(edges_.size());
899
+ new_input_ids_.reserve(edges_.size());
900
+ }
901
+
902
+ inline void Graph::EdgeProcessor::AddEdge(
903
+ const Edge& edge, InputEdgeIdSetId input_edge_id_set_id) {
904
+ new_edges_.push_back(edge);
905
+ new_input_ids_.push_back(input_edge_id_set_id);
906
+ }
907
+
908
+ void Graph::EdgeProcessor::AddEdges(int num_edges, const Edge& edge,
909
+ InputEdgeIdSetId input_edge_id_set_id) {
910
+ for (int i = 0; i < num_edges; ++i) {
911
+ AddEdge(edge, input_edge_id_set_id);
912
+ }
913
+ }
914
+
915
+ void Graph::EdgeProcessor::CopyEdges(int out_begin, int out_end) {
916
+ for (int i = out_begin; i < out_end; ++i) {
917
+ AddEdge(edges_[out_edges_[i]], input_ids_[out_edges_[i]]);
918
+ }
919
+ }
920
+
921
+ S2Builder::InputEdgeIdSetId Graph::EdgeProcessor::MergeInputIds(
922
+ int out_begin, int out_end) {
923
+ if (out_end - out_begin == 1) {
924
+ return input_ids_[out_edges_[out_begin]];
925
+ }
926
+ tmp_ids_.clear();
927
+ for (int i = out_begin; i < out_end; ++i) {
928
+ for (auto id : id_set_lexicon_->id_set(input_ids_[out_edges_[i]])) {
929
+ tmp_ids_.push_back(id);
930
+ }
931
+ }
932
+ return id_set_lexicon_->Add(tmp_ids_);
933
+ }
934
+
935
+ void Graph::EdgeProcessor::Run(S2Error* error) {
936
+ int num_edges = edges_.size();
937
+ if (num_edges == 0) return;
938
+
939
+ // Walk through the two sorted arrays performing a merge join. For each
940
+ // edge, gather all the duplicate copies of the edge in both directions
941
+ // (outgoing and incoming). Then decide what to do based on "options_" and
942
+ // how many copies of the edge there are in each direction.
943
+ int out = 0, in = 0;
944
+ const Edge* out_edge = &edges_[out_edges_[out]];
945
+ const Edge* in_edge = &edges_[in_edges_[in]];
946
+ Edge sentinel(std::numeric_limits<VertexId>::max(),
947
+ std::numeric_limits<VertexId>::max());
948
+ for (;;) {
949
+ Edge edge = min(*out_edge, reverse(*in_edge));
950
+ if (edge == sentinel) break;
951
+
952
+ int out_begin = out, in_begin = in;
953
+ while (*out_edge == edge) {
954
+ out_edge = (++out == num_edges) ? &sentinel : &edges_[out_edges_[out]];
955
+ }
956
+ while (reverse(*in_edge) == edge) {
957
+ in_edge = (++in == num_edges) ? &sentinel : &edges_[in_edges_[in]];
958
+ }
959
+ int n_out = out - out_begin;
960
+ int n_in = in - in_begin;
961
+ if (edge.first == edge.second) {
962
+ S2_DCHECK_EQ(n_out, n_in);
963
+ if (options_.degenerate_edges() == DegenerateEdges::DISCARD) {
964
+ continue;
965
+ }
966
+ if (options_.degenerate_edges() == DegenerateEdges::DISCARD_EXCESS &&
967
+ ((out_begin > 0 &&
968
+ edges_[out_edges_[out_begin - 1]].first == edge.first) ||
969
+ (out < num_edges && edges_[out_edges_[out]].first == edge.first) ||
970
+ (in_begin > 0 &&
971
+ edges_[in_edges_[in_begin - 1]].second == edge.first) ||
972
+ (in < num_edges && edges_[in_edges_[in]].second == edge.first))) {
973
+ continue; // There were non-degenerate incident edges, so discard.
974
+ }
975
+ if (options_.edge_type() == EdgeType::UNDIRECTED &&
976
+ (options_.sibling_pairs() == SiblingPairs::REQUIRE ||
977
+ options_.sibling_pairs() == SiblingPairs::CREATE)) {
978
+ // When we have undirected edges and are guaranteed to have siblings,
979
+ // we cut the number of edges in half (see s2builder.h).
980
+ S2_DCHECK_EQ(0, n_out & 1); // Number of edges is always even.
981
+ AddEdges(options_.duplicate_edges() == DuplicateEdges::MERGE ?
982
+ 1 : (n_out / 2), edge, MergeInputIds(out_begin, out));
983
+ } else if (options_.duplicate_edges() == DuplicateEdges::MERGE) {
984
+ AddEdges(options_.edge_type() == EdgeType::UNDIRECTED ? 2 : 1,
985
+ edge, MergeInputIds(out_begin, out));
986
+ } else if (options_.sibling_pairs() == SiblingPairs::DISCARD ||
987
+ options_.sibling_pairs() == SiblingPairs::DISCARD_EXCESS) {
988
+ // Any SiblingPair option that discards edges causes the labels of all
989
+ // duplicate edges to be merged together (see s2builder.h).
990
+ AddEdges(n_out, edge, MergeInputIds(out_begin, out));
991
+ } else {
992
+ CopyEdges(out_begin, out);
993
+ }
994
+ } else if (options_.sibling_pairs() == SiblingPairs::KEEP) {
995
+ if (n_out > 1 && options_.duplicate_edges() == DuplicateEdges::MERGE) {
996
+ AddEdge(edge, MergeInputIds(out_begin, out));
997
+ } else {
998
+ CopyEdges(out_begin, out);
999
+ }
1000
+ } else if (options_.sibling_pairs() == SiblingPairs::DISCARD) {
1001
+ if (options_.edge_type() == EdgeType::DIRECTED) {
1002
+ // If n_out == n_in: balanced sibling pairs
1003
+ // If n_out < n_in: unbalanced siblings, in the form AB, BA, BA
1004
+ // If n_out > n_in: unbalanced siblings, in the form AB, AB, BA
1005
+ if (n_out <= n_in) continue;
1006
+ // Any option that discards edges causes the labels of all duplicate
1007
+ // edges to be merged together (see s2builder.h).
1008
+ AddEdges(options_.duplicate_edges() == DuplicateEdges::MERGE ?
1009
+ 1 : (n_out - n_in), edge, MergeInputIds(out_begin, out));
1010
+ } else {
1011
+ if ((n_out & 1) == 0) continue;
1012
+ AddEdge(edge, MergeInputIds(out_begin, out));
1013
+ }
1014
+ } else if (options_.sibling_pairs() == SiblingPairs::DISCARD_EXCESS) {
1015
+ if (options_.edge_type() == EdgeType::DIRECTED) {
1016
+ // See comments above. The only difference is that if there are
1017
+ // balanced sibling pairs, we want to keep one such pair.
1018
+ if (n_out < n_in) continue;
1019
+ AddEdges(options_.duplicate_edges() == DuplicateEdges::MERGE ?
1020
+ 1 : max(1, n_out - n_in), edge, MergeInputIds(out_begin, out));
1021
+ } else {
1022
+ AddEdges((n_out & 1) ? 1 : 2, edge, MergeInputIds(out_begin, out));
1023
+ }
1024
+ } else {
1025
+ S2_DCHECK(options_.sibling_pairs() == SiblingPairs::REQUIRE ||
1026
+ options_.sibling_pairs() == SiblingPairs::CREATE);
1027
+ if (error->ok() && options_.sibling_pairs() == SiblingPairs::REQUIRE &&
1028
+ (options_.edge_type() == EdgeType::DIRECTED ? (n_out != n_in)
1029
+ : ((n_out & 1) != 0))) {
1030
+ error->Init(S2Error::BUILDER_MISSING_EXPECTED_SIBLING_EDGES,
1031
+ "Expected all input edges to have siblings, "
1032
+ "but some were missing");
1033
+ }
1034
+ if (options_.duplicate_edges() == DuplicateEdges::MERGE) {
1035
+ AddEdge(edge, MergeInputIds(out_begin, out));
1036
+ } else if (options_.edge_type() == EdgeType::UNDIRECTED) {
1037
+ // Convert graph to use directed edges instead (see documentation of
1038
+ // REQUIRE/CREATE for undirected edges).
1039
+ AddEdges((n_out + 1) / 2, edge, MergeInputIds(out_begin, out));
1040
+ } else {
1041
+ CopyEdges(out_begin, out);
1042
+ if (n_in > n_out) {
1043
+ // Automatically created edges have no input edge ids or labels.
1044
+ AddEdges(n_in - n_out, edge, IdSetLexicon::EmptySetId());
1045
+ }
1046
+ }
1047
+ }
1048
+ }
1049
+ edges_.swap(new_edges_);
1050
+ edges_.shrink_to_fit();
1051
+ input_ids_.swap(new_input_ids_);
1052
+ input_ids_.shrink_to_fit();
1053
+ }
1054
+
1055
+ vector<S2Point> Graph::FilterVertices(const vector<S2Point>& vertices,
1056
+ std::vector<Edge>* edges,
1057
+ vector<VertexId>* tmp) {
1058
+ // Gather the vertices that are actually used.
1059
+ vector<VertexId> used;
1060
+ used.reserve(2 * edges->size());
1061
+ for (const Edge& e : *edges) {
1062
+ used.push_back(e.first);
1063
+ used.push_back(e.second);
1064
+ }
1065
+ // Sort the vertices and find the distinct ones.
1066
+ std::sort(used.begin(), used.end());
1067
+ used.erase(std::unique(used.begin(), used.end()), used.end());
1068
+
1069
+ // Build the list of new vertices, and generate a map from old vertex id to
1070
+ // new vertex id.
1071
+ vector<VertexId>& vmap = *tmp;
1072
+ vmap.resize(vertices.size());
1073
+ vector<S2Point> new_vertices(used.size());
1074
+ for (int i = 0; i < used.size(); ++i) {
1075
+ new_vertices[i] = vertices[used[i]];
1076
+ vmap[used[i]] = i;
1077
+ }
1078
+ // Update the edges.
1079
+ for (Edge& e : *edges) {
1080
+ e.first = vmap[e.first];
1081
+ e.second = vmap[e.second];
1082
+ }
1083
+ return new_vertices;
1084
+ }