@sakuzu/maplibre-gl-draw 1.0.0

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 (636) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +661 -0
  3. package/README.ja.md +248 -0
  4. package/README.md +255 -0
  5. package/THIRD_PARTY_NOTICES.md +275 -0
  6. package/dist/api/api.d.ts +1259 -0
  7. package/dist/api/api.js +86 -0
  8. package/dist/api/context.d.ts +173 -0
  9. package/dist/api/context.js +193 -0
  10. package/dist/api/display-api.d.ts +1 -0
  11. package/dist/api/display-api.js +23 -0
  12. package/dist/api/event-api.d.ts +13 -0
  13. package/dist/api/event-api.js +17 -0
  14. package/dist/api/extension-api.d.ts +46 -0
  15. package/dist/api/extension-api.js +85 -0
  16. package/dist/api/feature-api.d.ts +11 -0
  17. package/dist/api/feature-api.js +101 -0
  18. package/dist/api/geometry/apply.d.ts +51 -0
  19. package/dist/api/geometry/apply.js +114 -0
  20. package/dist/api/geometry/boolean.d.ts +28 -0
  21. package/dist/api/geometry/boolean.js +65 -0
  22. package/dist/api/geometry/buffer.d.ts +11 -0
  23. package/dist/api/geometry/buffer.js +105 -0
  24. package/dist/api/geometry/split.d.ts +16 -0
  25. package/dist/api/geometry/split.js +75 -0
  26. package/dist/api/geometry/targets.d.ts +76 -0
  27. package/dist/api/geometry/targets.js +158 -0
  28. package/dist/api/geometry/types.d.ts +31 -0
  29. package/dist/api/geometry/types.js +3 -0
  30. package/dist/api/geometry-operations.d.ts +162 -0
  31. package/dist/api/geometry-operations.js +94 -0
  32. package/dist/api/group-api.d.ts +10 -0
  33. package/dist/api/group-api.js +78 -0
  34. package/dist/api/import-export/constants.d.ts +29 -0
  35. package/dist/api/import-export/constants.js +40 -0
  36. package/dist/api/import-export/embedded-file.d.ts +13 -0
  37. package/dist/api/import-export/embedded-file.js +31 -0
  38. package/dist/api/import-export/file-name.d.ts +10 -0
  39. package/dist/api/import-export/file-name.js +20 -0
  40. package/dist/api/import-export/format-detection.d.ts +12 -0
  41. package/dist/api/import-export/format-detection.js +29 -0
  42. package/dist/api/import-export/geojson-export.d.ts +19 -0
  43. package/dist/api/import-export/geojson-export.js +262 -0
  44. package/dist/api/import-export/geojson-import.d.ts +34 -0
  45. package/dist/api/import-export/geojson-import.js +538 -0
  46. package/dist/api/import-export/geometry-validation.d.ts +20 -0
  47. package/dist/api/import-export/geometry-validation.js +107 -0
  48. package/dist/api/import-export/image-import.d.ts +12 -0
  49. package/dist/api/import-export/image-import.js +53 -0
  50. package/dist/api/import-export/index.d.ts +9 -0
  51. package/dist/api/import-export/index.js +107 -0
  52. package/dist/api/import-export/native-format.d.ts +15 -0
  53. package/dist/api/import-export/native-format.js +126 -0
  54. package/dist/api/import-export/native-validation.d.ts +28 -0
  55. package/dist/api/import-export/native-validation.js +212 -0
  56. package/dist/api/import-export/own-property.d.ts +10 -0
  57. package/dist/api/import-export/own-property.js +19 -0
  58. package/dist/api/import-export/style-validation.d.ts +27 -0
  59. package/dist/api/import-export/style-validation.js +49 -0
  60. package/dist/api/import-export/types.d.ts +26 -0
  61. package/dist/api/import-export/types.js +3 -0
  62. package/dist/api/index.d.ts +15 -0
  63. package/dist/api/index.js +3 -0
  64. package/dist/api/input-api.d.ts +158 -0
  65. package/dist/api/input-api.js +144 -0
  66. package/dist/api/instance-api.d.ts +38 -0
  67. package/dist/api/instance-api.js +136 -0
  68. package/dist/api/layer-api.d.ts +12 -0
  69. package/dist/api/layer-api.js +62 -0
  70. package/dist/api/selection-api.d.ts +7 -0
  71. package/dist/api/selection-api.js +78 -0
  72. package/dist/api/snapping-api.d.ts +125 -0
  73. package/dist/api/snapping-api.js +50 -0
  74. package/dist/api/topology-api.d.ts +30 -0
  75. package/dist/api/topology-api.js +16 -0
  76. package/dist/api/tracing-api.d.ts +31 -0
  77. package/dist/api/tracing-api.js +16 -0
  78. package/dist/dispatcher/hit-test/box-strategies.d.ts +19 -0
  79. package/dist/dispatcher/hit-test/box-strategies.js +275 -0
  80. package/dist/dispatcher/hit-test/box-strategy.d.ts +59 -0
  81. package/dist/dispatcher/hit-test/box-strategy.js +37 -0
  82. package/dist/dispatcher/hit-test/globe-shape.d.ts +46 -0
  83. package/dist/dispatcher/hit-test/globe-shape.js +70 -0
  84. package/dist/dispatcher/hit-test/index.d.ts +14 -0
  85. package/dist/dispatcher/hit-test/index.js +9 -0
  86. package/dist/dispatcher/hit-test/local-frame.d.ts +77 -0
  87. package/dist/dispatcher/hit-test/local-frame.js +112 -0
  88. package/dist/dispatcher/hit-test/segment-grid.d.ts +32 -0
  89. package/dist/dispatcher/hit-test/segment-grid.js +79 -0
  90. package/dist/dispatcher/hit-test/service.d.ts +120 -0
  91. package/dist/dispatcher/hit-test/service.js +333 -0
  92. package/dist/dispatcher/hit-test/strategies/base.d.ts +136 -0
  93. package/dist/dispatcher/hit-test/strategies/base.js +66 -0
  94. package/dist/dispatcher/hit-test/strategies/circle.d.ts +10 -0
  95. package/dist/dispatcher/hit-test/strategies/circle.js +56 -0
  96. package/dist/dispatcher/hit-test/strategies/image.d.ts +22 -0
  97. package/dist/dispatcher/hit-test/strategies/image.js +115 -0
  98. package/dist/dispatcher/hit-test/strategies/index.d.ts +11 -0
  99. package/dist/dispatcher/hit-test/strategies/index.js +10 -0
  100. package/dist/dispatcher/hit-test/strategies/line.d.ts +17 -0
  101. package/dist/dispatcher/hit-test/strategies/line.js +30 -0
  102. package/dist/dispatcher/hit-test/strategies/multi.d.ts +44 -0
  103. package/dist/dispatcher/hit-test/strategies/multi.js +141 -0
  104. package/dist/dispatcher/hit-test/strategies/point.d.ts +20 -0
  105. package/dist/dispatcher/hit-test/strategies/point.js +29 -0
  106. package/dist/dispatcher/hit-test/strategies/polygon.d.ts +52 -0
  107. package/dist/dispatcher/hit-test/strategies/polygon.js +138 -0
  108. package/dist/dispatcher/hit-test/topmost.d.ts +48 -0
  109. package/dist/dispatcher/hit-test/topmost.js +157 -0
  110. package/dist/dispatcher/hit-test/visibility-lookup.d.ts +23 -0
  111. package/dist/dispatcher/hit-test/visibility-lookup.js +40 -0
  112. package/dist/dispatcher/index.d.ts +15 -0
  113. package/dist/dispatcher/index.js +3 -0
  114. package/dist/dispatcher/input-router.d.ts +1 -0
  115. package/dist/dispatcher/input-router.js +288 -0
  116. package/dist/dispatcher/normalizer.d.ts +1 -0
  117. package/dist/dispatcher/normalizer.js +513 -0
  118. package/dist/dispatcher/types.d.ts +144 -0
  119. package/dist/dispatcher/types.js +15 -0
  120. package/dist/display/chunk-set.d.ts +24 -0
  121. package/dist/display/chunk-set.js +533 -0
  122. package/dist/display/chunk.d.ts +1 -0
  123. package/dist/display/chunk.js +104 -0
  124. package/dist/display/columnar/index.d.ts +12 -0
  125. package/dist/display/columnar/index.js +13 -0
  126. package/dist/display/columnar/prepare.d.ts +42 -0
  127. package/dist/display/columnar/prepare.js +116 -0
  128. package/dist/display/columnar/source.d.ts +1 -0
  129. package/dist/display/columnar/source.js +531 -0
  130. package/dist/display/columnar/table.d.ts +1 -0
  131. package/dist/display/columnar/table.js +471 -0
  132. package/dist/display/columnar/types.d.ts +223 -0
  133. package/dist/display/columnar/types.js +3 -0
  134. package/dist/display/dataset.d.ts +2 -0
  135. package/dist/display/dataset.js +891 -0
  136. package/dist/display/index.d.ts +13 -0
  137. package/dist/display/index.js +3 -0
  138. package/dist/display/interaction.d.ts +1 -0
  139. package/dist/display/interaction.js +90 -0
  140. package/dist/display/manager.d.ts +1 -0
  141. package/dist/display/manager.js +440 -0
  142. package/dist/display/packed-rtree.d.ts +1 -0
  143. package/dist/display/packed-rtree.js +244 -0
  144. package/dist/display/partition.d.ts +1 -0
  145. package/dist/display/partition.js +226 -0
  146. package/dist/display/provider.d.ts +1 -0
  147. package/dist/display/provider.js +342 -0
  148. package/dist/display/retained.d.ts +40 -0
  149. package/dist/display/retained.js +898 -0
  150. package/dist/display/selection.d.ts +13 -0
  151. package/dist/display/selection.js +226 -0
  152. package/dist/display/source.d.ts +1 -0
  153. package/dist/display/source.js +119 -0
  154. package/dist/display/spatial.d.ts +1 -0
  155. package/dist/display/spatial.js +71 -0
  156. package/dist/display/style.d.ts +1 -0
  157. package/dist/display/style.js +126 -0
  158. package/dist/display/thinning.d.ts +65 -0
  159. package/dist/display/thinning.js +910 -0
  160. package/dist/display/triangulation.d.ts +1 -0
  161. package/dist/display/triangulation.js +0 -0
  162. package/dist/display/types.d.ts +561 -0
  163. package/dist/display/types.js +43 -0
  164. package/dist/extension/feature-handler.d.ts +182 -0
  165. package/dist/extension/feature-handler.js +3 -0
  166. package/dist/extension/index.d.ts +9 -0
  167. package/dist/extension/index.js +3 -0
  168. package/dist/extension/renderers.d.ts +208 -0
  169. package/dist/extension/renderers.js +3 -0
  170. package/dist/geometry/angle.d.ts +47 -0
  171. package/dist/geometry/angle.js +44 -0
  172. package/dist/geometry/bbox.d.ts +48 -0
  173. package/dist/geometry/bbox.js +83 -0
  174. package/dist/geometry/boolean.d.ts +162 -0
  175. package/dist/geometry/boolean.js +331 -0
  176. package/dist/geometry/buffer.d.ts +72 -0
  177. package/dist/geometry/buffer.js +218 -0
  178. package/dist/geometry/circle.d.ts +55 -0
  179. package/dist/geometry/circle.js +107 -0
  180. package/dist/geometry/coords.d.ts +97 -0
  181. package/dist/geometry/coords.js +149 -0
  182. package/dist/geometry/distance.d.ts +79 -0
  183. package/dist/geometry/distance.js +111 -0
  184. package/dist/geometry/errors.d.ts +74 -0
  185. package/dist/geometry/errors.js +104 -0
  186. package/dist/geometry/index.d.ts +28 -0
  187. package/dist/geometry/index.js +38 -0
  188. package/dist/geometry/measure.d.ts +81 -0
  189. package/dist/geometry/measure.js +236 -0
  190. package/dist/geometry/predicates.d.ts +62 -0
  191. package/dist/geometry/predicates.js +132 -0
  192. package/dist/geometry/simplify.d.ts +74 -0
  193. package/dist/geometry/simplify.js +159 -0
  194. package/dist/geometry/split.d.ts +68 -0
  195. package/dist/geometry/split.js +430 -0
  196. package/dist/geometry/types.d.ts +95 -0
  197. package/dist/geometry/types.js +3 -0
  198. package/dist/geometry/units.d.ts +35 -0
  199. package/dist/geometry/units.js +41 -0
  200. package/dist/index.d.ts +72 -0
  201. package/dist/index.js +20 -0
  202. package/dist/maplibre-gl-draw.d.ts +47 -0
  203. package/dist/maplibre-gl-draw.js +407 -0
  204. package/dist/messages.d.ts +64 -0
  205. package/dist/messages.js +36 -0
  206. package/dist/modes/cursor.d.ts +1 -0
  207. package/dist/modes/cursor.js +72 -0
  208. package/dist/modes/draw/circle.d.ts +1 -0
  209. package/dist/modes/draw/circle.js +222 -0
  210. package/dist/modes/draw/commit-layer.d.ts +26 -0
  211. package/dist/modes/draw/commit-layer.js +31 -0
  212. package/dist/modes/draw/freehand.d.ts +1 -0
  213. package/dist/modes/draw/freehand.js +264 -0
  214. package/dist/modes/draw/image.d.ts +1 -0
  215. package/dist/modes/draw/image.js +60 -0
  216. package/dist/modes/draw/index.d.ts +9 -0
  217. package/dist/modes/draw/index.js +11 -0
  218. package/dist/modes/draw/line.d.ts +1 -0
  219. package/dist/modes/draw/line.js +363 -0
  220. package/dist/modes/draw/point.d.ts +1 -0
  221. package/dist/modes/draw/point.js +87 -0
  222. package/dist/modes/draw/polygon.d.ts +1 -0
  223. package/dist/modes/draw/polygon.js +378 -0
  224. package/dist/modes/draw/trace-support.d.ts +79 -0
  225. package/dist/modes/draw/trace-support.js +161 -0
  226. package/dist/modes/handler.d.ts +285 -0
  227. package/dist/modes/handler.js +3 -0
  228. package/dist/modes/index.d.ts +7 -0
  229. package/dist/modes/index.js +3 -0
  230. package/dist/modes/manager.d.ts +15 -0
  231. package/dist/modes/manager.js +196 -0
  232. package/dist/modes/select/box-selection.d.ts +52 -0
  233. package/dist/modes/select/box-selection.js +140 -0
  234. package/dist/modes/select/click-handler.d.ts +32 -0
  235. package/dist/modes/select/click-handler.js +166 -0
  236. package/dist/modes/select/cursor-handler.d.ts +15 -0
  237. package/dist/modes/select/cursor-handler.js +59 -0
  238. package/dist/modes/select/drag/auxiliary.d.ts +26 -0
  239. package/dist/modes/select/drag/auxiliary.js +56 -0
  240. package/dist/modes/select/drag/intermediate-writes.d.ts +1 -0
  241. package/dist/modes/select/drag/intermediate-writes.js +171 -0
  242. package/dist/modes/select/drag/move.d.ts +24 -0
  243. package/dist/modes/select/drag/move.js +59 -0
  244. package/dist/modes/select/drag/operation.d.ts +30 -0
  245. package/dist/modes/select/drag/operation.js +18 -0
  246. package/dist/modes/select/drag/radius.d.ts +15 -0
  247. package/dist/modes/select/drag/radius.js +49 -0
  248. package/dist/modes/select/drag/transform.d.ts +17 -0
  249. package/dist/modes/select/drag/transform.js +155 -0
  250. package/dist/modes/select/drag/vertex.d.ts +17 -0
  251. package/dist/modes/select/drag/vertex.js +163 -0
  252. package/dist/modes/select/drag-handler.d.ts +1 -0
  253. package/dist/modes/select/drag-handler.js +254 -0
  254. package/dist/modes/select/hit-helpers.d.ts +40 -0
  255. package/dist/modes/select/hit-helpers.js +51 -0
  256. package/dist/modes/select/mode.d.ts +1 -0
  257. package/dist/modes/select/mode.js +397 -0
  258. package/dist/modes/select/shortcut-handler.d.ts +40 -0
  259. package/dist/modes/select/shortcut-handler.js +128 -0
  260. package/dist/operations/index.d.ts +9 -0
  261. package/dist/operations/index.js +3 -0
  262. package/dist/operations/layer-operations.d.ts +1 -0
  263. package/dist/operations/layer-operations.js +350 -0
  264. package/dist/operations/resize.d.ts +71 -0
  265. package/dist/operations/resize.js +252 -0
  266. package/dist/operations/rotate.d.ts +17 -0
  267. package/dist/operations/rotate.js +166 -0
  268. package/dist/operations/selection-operations.d.ts +20 -0
  269. package/dist/operations/selection-operations.js +159 -0
  270. package/dist/operations/shared-vertex.d.ts +1 -0
  271. package/dist/operations/shared-vertex.js +210 -0
  272. package/dist/operations/trace-graph.d.ts +96 -0
  273. package/dist/operations/trace-graph.js +283 -0
  274. package/dist/operations/vertex.d.ts +1 -0
  275. package/dist/operations/vertex.js +538 -0
  276. package/dist/plugins/index.d.ts +10 -0
  277. package/dist/plugins/index.js +3 -0
  278. package/dist/plugins/mutation-hooks.d.ts +28 -0
  279. package/dist/plugins/mutation-hooks.js +84 -0
  280. package/dist/plugins/plugin-context.d.ts +1 -0
  281. package/dist/plugins/plugin-context.js +367 -0
  282. package/dist/plugins/plugin-manager.d.ts +103 -0
  283. package/dist/plugins/plugin-manager.js +316 -0
  284. package/dist/plugins/plugin.d.ts +529 -0
  285. package/dist/plugins/plugin.js +3 -0
  286. package/dist/shared/config/constants.d.ts +66 -0
  287. package/dist/shared/config/constants.js +60 -0
  288. package/dist/shared/config/feature-style.d.ts +155 -0
  289. package/dist/shared/config/feature-style.js +154 -0
  290. package/dist/shared/config/index.d.ts +17 -0
  291. package/dist/shared/config/index.js +8 -0
  292. package/dist/shared/config/rendering.d.ts +107 -0
  293. package/dist/shared/config/rendering.js +33 -0
  294. package/dist/shared/config/selection-highlight.d.ts +29 -0
  295. package/dist/shared/config/selection-highlight.js +35 -0
  296. package/dist/shared/config/selection.d.ts +273 -0
  297. package/dist/shared/config/selection.js +266 -0
  298. package/dist/shared/config/topology.d.ts +33 -0
  299. package/dist/shared/config/topology.js +17 -0
  300. package/dist/shared/config/trace.d.ts +40 -0
  301. package/dist/shared/config/trace.js +17 -0
  302. package/dist/shared/math/angle.d.ts +21 -0
  303. package/dist/shared/math/angle.js +34 -0
  304. package/dist/shared/math/circle.d.ts +6 -0
  305. package/dist/shared/math/circle.js +10 -0
  306. package/dist/shared/math/constants.d.ts +48 -0
  307. package/dist/shared/math/constants.js +59 -0
  308. package/dist/shared/math/distance.d.ts +78 -0
  309. package/dist/shared/math/distance.js +147 -0
  310. package/dist/shared/math/globe-subdivision.d.ts +62 -0
  311. package/dist/shared/math/globe-subdivision.js +99 -0
  312. package/dist/shared/math/index.d.ts +17 -0
  313. package/dist/shared/math/index.js +21 -0
  314. package/dist/shared/math/intersection.d.ts +63 -0
  315. package/dist/shared/math/intersection.js +236 -0
  316. package/dist/shared/math/longitude.d.ts +20 -0
  317. package/dist/shared/math/longitude.js +31 -0
  318. package/dist/shared/math/mercator-plane.d.ts +27 -0
  319. package/dist/shared/math/mercator-plane.js +26 -0
  320. package/dist/shared/math/obb.d.ts +65 -0
  321. package/dist/shared/math/obb.js +107 -0
  322. package/dist/shared/math/rotation.d.ts +93 -0
  323. package/dist/shared/math/rotation.js +186 -0
  324. package/dist/shared/math/segment-grid.d.ts +69 -0
  325. package/dist/shared/math/segment-grid.js +159 -0
  326. package/dist/shared/math/transform.d.ts +140 -0
  327. package/dist/shared/math/transform.js +189 -0
  328. package/dist/shared/types/events.d.ts +128 -0
  329. package/dist/shared/types/events.js +3 -0
  330. package/dist/shared/types/model.d.ts +950 -0
  331. package/dist/shared/types/model.js +3 -0
  332. package/dist/shared/types/selection-box.d.ts +23 -0
  333. package/dist/shared/types/selection-box.js +3 -0
  334. package/dist/shared/types/style.d.ts +68 -0
  335. package/dist/shared/types/style.js +3 -0
  336. package/dist/shared/utils/color.d.ts +49 -0
  337. package/dist/shared/utils/color.js +180 -0
  338. package/dist/shared/utils/coordinates.d.ts +52 -0
  339. package/dist/shared/utils/coordinates.js +75 -0
  340. package/dist/shared/utils/embedded-image.d.ts +34 -0
  341. package/dist/shared/utils/embedded-image.js +161 -0
  342. package/dist/shared/utils/event-emitter.d.ts +262 -0
  343. package/dist/shared/utils/event-emitter.js +44 -0
  344. package/dist/shared/utils/feature-bbox.d.ts +8 -0
  345. package/dist/shared/utils/feature-bbox.js +207 -0
  346. package/dist/shared/utils/feature-segments.d.ts +23 -0
  347. package/dist/shared/utils/feature-segments.js +179 -0
  348. package/dist/shared/utils/id.d.ts +1 -0
  349. package/dist/shared/utils/id.js +35 -0
  350. package/dist/shared/utils/image.d.ts +34 -0
  351. package/dist/shared/utils/image.js +106 -0
  352. package/dist/shared/utils/index.d.ts +15 -0
  353. package/dist/shared/utils/index.js +24 -0
  354. package/dist/shared/utils/map.d.ts +26 -0
  355. package/dist/shared/utils/map.js +35 -0
  356. package/dist/shared/utils/name-generator.d.ts +197 -0
  357. package/dist/shared/utils/name-generator.js +337 -0
  358. package/dist/shared/utils/pixel-ratio.d.ts +111 -0
  359. package/dist/shared/utils/pixel-ratio.js +85 -0
  360. package/dist/shared/utils/property.d.ts +88 -0
  361. package/dist/shared/utils/property.js +140 -0
  362. package/dist/shared/utils/vertex-ref.d.ts +23 -0
  363. package/dist/shared/utils/vertex-ref.js +20 -0
  364. package/dist/snapping/custom-targets.d.ts +1 -0
  365. package/dist/snapping/custom-targets.js +21 -0
  366. package/dist/snapping/geometry.d.ts +1 -0
  367. package/dist/snapping/geometry.js +61 -0
  368. package/dist/snapping/index.d.ts +14 -0
  369. package/dist/snapping/index.js +4 -0
  370. package/dist/snapping/indicator.d.ts +19 -0
  371. package/dist/snapping/indicator.js +145 -0
  372. package/dist/snapping/providers/display.d.ts +72 -0
  373. package/dist/snapping/providers/display.js +268 -0
  374. package/dist/snapping/providers/guide.d.ts +69 -0
  375. package/dist/snapping/providers/guide.js +187 -0
  376. package/dist/snapping/providers/intersection.d.ts +1 -0
  377. package/dist/snapping/providers/intersection.js +92 -0
  378. package/dist/snapping/providers/shared.d.ts +39 -0
  379. package/dist/snapping/providers/shared.js +146 -0
  380. package/dist/snapping/providers/store.d.ts +1 -0
  381. package/dist/snapping/providers/store.js +132 -0
  382. package/dist/snapping/service.d.ts +1 -0
  383. package/dist/snapping/service.js +272 -0
  384. package/dist/snapping/types.d.ts +267 -0
  385. package/dist/snapping/types.js +66 -0
  386. package/dist/store/change-merger.d.ts +1 -0
  387. package/dist/store/change-merger.js +102 -0
  388. package/dist/store/draw-store.d.ts +1 -0
  389. package/dist/store/draw-store.js +396 -0
  390. package/dist/store/event-bridge.d.ts +1 -0
  391. package/dist/store/event-bridge.js +161 -0
  392. package/dist/store/index.d.ts +12 -0
  393. package/dist/store/index.js +4 -0
  394. package/dist/store/local-visibility.d.ts +21 -0
  395. package/dist/store/local-visibility.js +27 -0
  396. package/dist/store/lock.d.ts +67 -0
  397. package/dist/store/lock.js +54 -0
  398. package/dist/store/memory/change-bus.d.ts +60 -0
  399. package/dist/store/memory/change-bus.js +232 -0
  400. package/dist/store/memory/file-store.d.ts +15 -0
  401. package/dist/store/memory/file-store.js +33 -0
  402. package/dist/store/memory/frozen.d.ts +21 -0
  403. package/dist/store/memory/frozen.js +51 -0
  404. package/dist/store/memory/ui-state.d.ts +51 -0
  405. package/dist/store/memory/ui-state.js +223 -0
  406. package/dist/store/memory.d.ts +26 -0
  407. package/dist/store/memory.js +708 -0
  408. package/dist/store/spatial/index.d.ts +6 -0
  409. package/dist/store/spatial/index.js +4 -0
  410. package/dist/store/spatial/spatial-index.d.ts +90 -0
  411. package/dist/store/spatial/spatial-index.js +148 -0
  412. package/dist/store/spatial/store-spatial-index.d.ts +60 -0
  413. package/dist/store/spatial/store-spatial-index.js +125 -0
  414. package/dist/store/store.d.ts +417 -0
  415. package/dist/store/store.js +3 -0
  416. package/dist/store/types.d.ts +8 -0
  417. package/dist/store/types.js +3 -0
  418. package/dist/store/writable-layer.d.ts +35 -0
  419. package/dist/store/writable-layer.js +20 -0
  420. package/dist/view/cache/buffer.d.ts +28 -0
  421. package/dist/view/cache/buffer.js +176 -0
  422. package/dist/view/cache/earcut.d.ts +1 -0
  423. package/dist/view/cache/earcut.js +122 -0
  424. package/dist/view/cache/style-rule.d.ts +1 -0
  425. package/dist/view/cache/style-rule.js +97 -0
  426. package/dist/view/cache/terrain-fill.d.ts +30 -0
  427. package/dist/view/cache/terrain-fill.js +60 -0
  428. package/dist/view/cache/texture.d.ts +14 -0
  429. package/dist/view/cache/texture.js +292 -0
  430. package/dist/view/coordinator.d.ts +27 -0
  431. package/dist/view/coordinator.js +72 -0
  432. package/dist/view/feature-companion.d.ts +173 -0
  433. package/dist/view/feature-companion.js +108 -0
  434. package/dist/view/globe-subdivision.d.ts +78 -0
  435. package/dist/view/globe-subdivision.js +128 -0
  436. package/dist/view/index.d.ts +47 -0
  437. package/dist/view/index.js +20 -0
  438. package/dist/view/layer/attach.d.ts +20 -0
  439. package/dist/view/layer/attach.js +47 -0
  440. package/dist/view/layer/blend.d.ts +57 -0
  441. package/dist/view/layer/blend.js +14 -0
  442. package/dist/view/layer/custom-layer.d.ts +1 -0
  443. package/dist/view/layer/custom-layer.js +509 -0
  444. package/dist/view/layer/depth-state.d.ts +14 -0
  445. package/dist/view/layer/depth-state.js +44 -0
  446. package/dist/view/layer/display-list.d.ts +1 -0
  447. package/dist/view/layer/display-list.js +111 -0
  448. package/dist/view/layer/drape-planner.d.ts +139 -0
  449. package/dist/view/layer/drape-planner.js +726 -0
  450. package/dist/view/layer/frame-render.d.ts +57 -0
  451. package/dist/view/layer/frame-render.js +209 -0
  452. package/dist/view/layer/frame-state.d.ts +147 -0
  453. package/dist/view/layer/frame-state.js +484 -0
  454. package/dist/view/layer/gl-state.d.ts +77 -0
  455. package/dist/view/layer/gl-state.js +132 -0
  456. package/dist/view/layer/index.d.ts +6 -0
  457. package/dist/view/layer/index.js +5 -0
  458. package/dist/view/layer/render-scope.d.ts +30 -0
  459. package/dist/view/layer/render-scope.js +28 -0
  460. package/dist/view/layer/render.d.ts +87 -0
  461. package/dist/view/layer/render.js +187 -0
  462. package/dist/view/layer/renderers.d.ts +81 -0
  463. package/dist/view/layer/renderers.js +142 -0
  464. package/dist/view/layer/slot-manager.d.ts +26 -0
  465. package/dist/view/layer/slot-manager.js +133 -0
  466. package/dist/view/layer/slots.d.ts +33 -0
  467. package/dist/view/layer/slots.js +50 -0
  468. package/dist/view/layer/store-retained-bbox.d.ts +36 -0
  469. package/dist/view/layer/store-retained-bbox.js +188 -0
  470. package/dist/view/layer/store-retained-chunk.d.ts +97 -0
  471. package/dist/view/layer/store-retained-chunk.js +94 -0
  472. package/dist/view/layer/store-retained-classify.d.ts +34 -0
  473. package/dist/view/layer/store-retained-classify.js +88 -0
  474. package/dist/view/layer/store-retained-collect.d.ts +24 -0
  475. package/dist/view/layer/store-retained-collect.js +121 -0
  476. package/dist/view/layer/store-retained-coord-patch.d.ts +119 -0
  477. package/dist/view/layer/store-retained-coord-patch.js +168 -0
  478. package/dist/view/layer/store-retained-immediate.d.ts +63 -0
  479. package/dist/view/layer/store-retained-immediate.js +49 -0
  480. package/dist/view/layer/store-retained-invalidation.d.ts +96 -0
  481. package/dist/view/layer/store-retained-invalidation.js +192 -0
  482. package/dist/view/layer/store-retained.d.ts +198 -0
  483. package/dist/view/layer/store-retained.js +430 -0
  484. package/dist/view/layer/terrain-resolver.d.ts +1 -0
  485. package/dist/view/layer/terrain-resolver.js +174 -0
  486. package/dist/view/renderers/batch-manager.d.ts +61 -0
  487. package/dist/view/renderers/batch-manager.js +718 -0
  488. package/dist/view/renderers/draw-factors.d.ts +60 -0
  489. package/dist/view/renderers/draw-factors.js +35 -0
  490. package/dist/view/renderers/drawer.d.ts +1 -0
  491. package/dist/view/renderers/drawer.js +346 -0
  492. package/dist/view/renderers/image.d.ts +1 -0
  493. package/dist/view/renderers/image.js +255 -0
  494. package/dist/view/renderers/line/dash.d.ts +31 -0
  495. package/dist/view/renderers/line/dash.js +152 -0
  496. package/dist/view/renderers/line/line-geometry.d.ts +39 -0
  497. package/dist/view/renderers/line/line-geometry.js +460 -0
  498. package/dist/view/renderers/line/line-gl.d.ts +1 -0
  499. package/dist/view/renderers/line/line-gl.js +236 -0
  500. package/dist/view/renderers/line/line-shader.d.ts +1 -0
  501. package/dist/view/renderers/line/line-shader.js +364 -0
  502. package/dist/view/renderers/line/line-types.d.ts +43 -0
  503. package/dist/view/renderers/line/line-types.js +3 -0
  504. package/dist/view/renderers/line/line-uniforms.d.ts +1 -0
  505. package/dist/view/renderers/line/line-uniforms.js +390 -0
  506. package/dist/view/renderers/line/sdf-line.d.ts +92 -0
  507. package/dist/view/renderers/line/sdf-line.js +567 -0
  508. package/dist/view/renderers/point/billboard-depth.d.ts +10 -0
  509. package/dist/view/renderers/point/billboard-depth.js +56 -0
  510. package/dist/view/renderers/point/point-instance.d.ts +124 -0
  511. package/dist/view/renderers/point/point-instance.js +738 -0
  512. package/dist/view/renderers/point/point-sdf.d.ts +58 -0
  513. package/dist/view/renderers/point/point-sdf.js +170 -0
  514. package/dist/view/renderers/point/point-shape.d.ts +99 -0
  515. package/dist/view/renderers/point/point-shape.js +504 -0
  516. package/dist/view/renderers/point/point-style.d.ts +1 -0
  517. package/dist/view/renderers/point/point-style.js +46 -0
  518. package/dist/view/renderers/polygon/batch.d.ts +26 -0
  519. package/dist/view/renderers/polygon/batch.js +336 -0
  520. package/dist/view/renderers/polygon/earcut-input.d.ts +37 -0
  521. package/dist/view/renderers/polygon/earcut-input.js +55 -0
  522. package/dist/view/renderers/polygon/earcut-sliced.d.ts +69 -0
  523. package/dist/view/renderers/polygon/earcut-sliced.js +960 -0
  524. package/dist/view/renderers/polygon/fill.d.ts +74 -0
  525. package/dist/view/renderers/polygon/fill.js +251 -0
  526. package/dist/view/renderers/polygon/sdf-polygon.d.ts +62 -0
  527. package/dist/view/renderers/polygon/sdf-polygon.js +919 -0
  528. package/dist/view/renderers/polygon/terrain-cull.d.ts +3 -0
  529. package/dist/view/renderers/polygon/terrain-cull.js +14 -0
  530. package/dist/view/renderers/polygon/triangulator.d.ts +41 -0
  531. package/dist/view/renderers/polygon/triangulator.js +3 -0
  532. package/dist/view/renderers/retained.d.ts +43 -0
  533. package/dist/view/renderers/retained.js +3 -0
  534. package/dist/view/renderers/stroke.d.ts +121 -0
  535. package/dist/view/renderers/stroke.js +621 -0
  536. package/dist/view/shaders/frame.d.ts +8 -0
  537. package/dist/view/shaders/frame.js +37 -0
  538. package/dist/view/shaders/helpers.d.ts +238 -0
  539. package/dist/view/shaders/helpers.js +611 -0
  540. package/dist/view/shaders/initializer.d.ts +27 -0
  541. package/dist/view/shaders/initializer.js +125 -0
  542. package/dist/view/shaders/projection.d.ts +123 -0
  543. package/dist/view/shaders/projection.js +299 -0
  544. package/dist/view/shaders/quad-grid.d.ts +77 -0
  545. package/dist/view/shaders/quad-grid.js +128 -0
  546. package/dist/view/shaders/quad.d.ts +189 -0
  547. package/dist/view/shaders/quad.js +582 -0
  548. package/dist/view/shaders/retained-origin.d.ts +50 -0
  549. package/dist/view/shaders/retained-origin.js +67 -0
  550. package/dist/view/shaders/terrain-shade.d.ts +23 -0
  551. package/dist/view/shaders/terrain-shade.js +93 -0
  552. package/dist/view/style-rule.d.ts +166 -0
  553. package/dist/view/style-rule.js +300 -0
  554. package/dist/view/terrain/anchor.d.ts +135 -0
  555. package/dist/view/terrain/anchor.js +226 -0
  556. package/dist/view/terrain/context.d.ts +132 -0
  557. package/dist/view/terrain/context.js +437 -0
  558. package/dist/view/terrain/dem-atlas.d.ts +97 -0
  559. package/dist/view/terrain/dem-atlas.js +534 -0
  560. package/dist/view/terrain/detect.d.ts +126 -0
  561. package/dist/view/terrain/detect.js +198 -0
  562. package/dist/view/terrain/drape/bin-store.d.ts +179 -0
  563. package/dist/view/terrain/drape/bin-store.js +529 -0
  564. package/dist/view/terrain/drape/binning.d.ts +259 -0
  565. package/dist/view/terrain/drape/binning.js +604 -0
  566. package/dist/view/terrain/drape/edge-constrain.d.ts +37 -0
  567. package/dist/view/terrain/drape/edge-constrain.js +175 -0
  568. package/dist/view/terrain/drape/geometry.d.ts +95 -0
  569. package/dist/view/terrain/drape/geometry.js +260 -0
  570. package/dist/view/terrain/drape/mesh.d.ts +50 -0
  571. package/dist/view/terrain/drape/mesh.js +86 -0
  572. package/dist/view/terrain/drape/pass.d.ts +122 -0
  573. package/dist/view/terrain/drape/pass.js +379 -0
  574. package/dist/view/terrain/drape/quad-glyphs.d.ts +64 -0
  575. package/dist/view/terrain/drape/quad-glyphs.js +117 -0
  576. package/dist/view/terrain/drape/quad.d.ts +249 -0
  577. package/dist/view/terrain/drape/quad.js +835 -0
  578. package/dist/view/terrain/drape/renderer.d.ts +184 -0
  579. package/dist/view/terrain/drape/renderer.js +706 -0
  580. package/dist/view/terrain/drape/shared.d.ts +80 -0
  581. package/dist/view/terrain/drape/shared.js +173 -0
  582. package/dist/view/terrain/drape/stitch.d.ts +155 -0
  583. package/dist/view/terrain/drape/stitch.js +228 -0
  584. package/dist/view/terrain/ground.d.ts +72 -0
  585. package/dist/view/terrain/ground.js +151 -0
  586. package/dist/view/terrain/metrics.d.ts +180 -0
  587. package/dist/view/terrain/metrics.js +231 -0
  588. package/dist/view/terrain/occlusion.d.ts +11 -0
  589. package/dist/view/terrain/occlusion.js +129 -0
  590. package/dist/view/terrain/polygon.d.ts +86 -0
  591. package/dist/view/terrain/polygon.js +301 -0
  592. package/dist/view/terrain/shade.d.ts +48 -0
  593. package/dist/view/terrain/shade.js +45 -0
  594. package/dist/view/terrain/state.d.ts +99 -0
  595. package/dist/view/terrain/state.js +186 -0
  596. package/dist/view/terrain/tessellation.d.ts +265 -0
  597. package/dist/view/terrain/tessellation.js +924 -0
  598. package/dist/view/terrain/tiling.d.ts +56 -0
  599. package/dist/view/terrain/tiling.js +155 -0
  600. package/dist/view/terrain/upstream-terrain.d.ts +82 -0
  601. package/dist/view/terrain/upstream-terrain.js +116 -0
  602. package/dist/view/ui/auxiliary-handles.d.ts +151 -0
  603. package/dist/view/ui/auxiliary-handles.js +22 -0
  604. package/dist/view/ui/bounds.d.ts +53 -0
  605. package/dist/view/ui/bounds.js +149 -0
  606. package/dist/view/ui/box-selection.d.ts +1 -0
  607. package/dist/view/ui/box-selection.js +83 -0
  608. package/dist/view/ui/handle-test.d.ts +1 -0
  609. package/dist/view/ui/handle-test.js +437 -0
  610. package/dist/view/ui/handle-thinning.d.ts +122 -0
  611. package/dist/view/ui/handle-thinning.js +430 -0
  612. package/dist/view/ui/handles.d.ts +25 -0
  613. package/dist/view/ui/handles.js +673 -0
  614. package/dist/view/ui/helper.d.ts +19 -0
  615. package/dist/view/ui/helper.js +76 -0
  616. package/dist/view/ui/index.d.ts +15 -0
  617. package/dist/view/ui/index.js +15 -0
  618. package/dist/view/ui/selection-scope.d.ts +25 -0
  619. package/dist/view/ui/selection-scope.js +34 -0
  620. package/dist/view/ui/selection-ui/bounding-box.d.ts +44 -0
  621. package/dist/view/ui/selection-ui/bounding-box.js +240 -0
  622. package/dist/view/ui/selection-ui/extension-registry.d.ts +76 -0
  623. package/dist/view/ui/selection-ui/extension-registry.js +78 -0
  624. package/dist/view/ui/selection-ui/index.d.ts +12 -0
  625. package/dist/view/ui/selection-ui/index.js +12 -0
  626. package/dist/view/ui/selection-ui/renderer.d.ts +29 -0
  627. package/dist/view/ui/selection-ui/renderer.js +227 -0
  628. package/dist/view/ui/selection-ui/types.d.ts +55 -0
  629. package/dist/view/ui/selection-ui/types.js +3 -0
  630. package/dist/view/ui/selection-ui-drawer.d.ts +52 -0
  631. package/dist/view/ui/selection-ui-drawer.js +329 -0
  632. package/dist/view/ui/tentative.d.ts +1 -0
  633. package/dist/view/ui/tentative.js +320 -0
  634. package/dist/view/viewport.d.ts +119 -0
  635. package/dist/view/viewport.js +254 -0
  636. package/package.json +113 -0
@@ -0,0 +1,960 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only AND ISC
3
+ /**
4
+ * The number of ear clipping loop iterations run in a single step
5
+ *
6
+ * The caller checks the clock at this granularity, so this determines "how far the
7
+ * budget can be overrun". The measurements on a million-vertex water body are as
8
+ * follows.
9
+ *
10
+ * | slice | average per step | p99 | max | total CPU of the triangulation |
11
+ * | --- | --- | --- | --- | --- |
12
+ * | 16 | 0.14ms | 5.1ms | 23ms | 15.0s |
13
+ * | 32 | 0.28ms | 10.3ms | 35ms | 15.3s |
14
+ * | 64 | 0.52ms | 19.5ms | 55ms | 14.2s |
15
+ *
16
+ * Since the total hardly changes even when the slice is made finer (the cost of slicing
17
+ * is negligible), 16 is adopted because it keeps within the budget. A long step appears
18
+ * rarely because the recovery performed when no more ears can be found (the full sweep
19
+ * of filterPoints) runs within a single iteration.
20
+ */
21
+ export const EARCUT_SLICE_ITERATIONS = 16;
22
+ // === The following is upstream's mutable scratch state (alive only within one step) ===
23
+ /**
24
+ * The "single-vertex holes" (steiner points) that filterPoints stores
25
+ *
26
+ * Because the triangulation stops partway through, this set has to be swapped per job
27
+ * (it is swapped to the one of the job in question at the entrance of step).
28
+ */
29
+ let steiners = new Set();
30
+ /** The empty set steiners points at while no job is running (avoids allocating each time) */
31
+ const EMPTY_STEINERS = new Set();
32
+ // set by filterPoints whenever it removes at least one node; read by the ear clipping
33
+ // loop's stall handler to decide whether another clip pass is worth attempting
34
+ let filteredOut = false;
35
+ // true only while eliminateHoles merges holes, so removeNode keeps the block index live
36
+ let indexActive = false;
37
+ /**
38
+ * Time-sliceable earcut
39
+ *
40
+ * If `step()` is called repeatedly until completion (true), `triangles` ends up holding
41
+ * the same index sequence as the `earcut(data, holeIndices, dim)` dependency.
42
+ */
43
+ export class SlicedEarcut {
44
+ constructor(data, holeIndices, dim = 2) {
45
+ Object.defineProperty(this, "data", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ value: void 0
50
+ });
51
+ Object.defineProperty(this, "holeIndices", {
52
+ enumerable: true,
53
+ configurable: true,
54
+ writable: true,
55
+ value: void 0
56
+ });
57
+ Object.defineProperty(this, "dim", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: void 0
62
+ });
63
+ /** The triangulation result (partial progress until it finishes) */
64
+ Object.defineProperty(this, "triangles", {
65
+ enumerable: true,
66
+ configurable: true,
67
+ writable: true,
68
+ value: []
69
+ });
70
+ Object.defineProperty(this, "phase", {
71
+ enumerable: true,
72
+ configurable: true,
73
+ writable: true,
74
+ value: 'setup'
75
+ });
76
+ // State of the ear clipping loop (carried over across steps)
77
+ Object.defineProperty(this, "ear", {
78
+ enumerable: true,
79
+ configurable: true,
80
+ writable: true,
81
+ value: null
82
+ });
83
+ Object.defineProperty(this, "stop", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: null
88
+ });
89
+ Object.defineProperty(this, "cured", {
90
+ enumerable: true,
91
+ configurable: true,
92
+ writable: true,
93
+ value: false
94
+ });
95
+ Object.defineProperty(this, "minX", {
96
+ enumerable: true,
97
+ configurable: true,
98
+ writable: true,
99
+ value: 0
100
+ });
101
+ Object.defineProperty(this, "minY", {
102
+ enumerable: true,
103
+ configurable: true,
104
+ writable: true,
105
+ value: 0
106
+ });
107
+ Object.defineProperty(this, "invSize", {
108
+ enumerable: true,
109
+ configurable: true,
110
+ writable: true,
111
+ value: 0
112
+ });
113
+ /** The steiner points of this job (swapped into the module variable at step's entrance) */
114
+ Object.defineProperty(this, "ownSteiners", {
115
+ enumerable: true,
116
+ configurable: true,
117
+ writable: true,
118
+ value: new Set()
119
+ });
120
+ /** The filteredOut of this job (same as above) */
121
+ Object.defineProperty(this, "ownFilteredOut", {
122
+ enumerable: true,
123
+ configurable: true,
124
+ writable: true,
125
+ value: false
126
+ });
127
+ this.data = data;
128
+ this.holeIndices = holeIndices ?? null;
129
+ this.dim = dim;
130
+ }
131
+ /** Whether it has finished */
132
+ get done() {
133
+ return this.phase === 'done';
134
+ }
135
+ /**
136
+ * Advances the triangulation a little
137
+ *
138
+ * @param iterations The upper bound on ear clipping loop iterations (the default slice
139
+ * when omitted)
140
+ * @returns true once it has finished
141
+ */
142
+ step(iterations = EARCUT_SLICE_ITERATIONS) {
143
+ if (this.done)
144
+ return true;
145
+ // Swap the module scratch state to this job's (so that even if another job runs
146
+ // while this triangulation is partway through, they do not break each other's state)
147
+ steiners = this.ownSteiners;
148
+ filteredOut = this.ownFilteredOut;
149
+ try {
150
+ if (this.phase === 'setup') {
151
+ this.runSetup();
152
+ }
153
+ if (this.phase === 'clip') {
154
+ this.runClip(iterations);
155
+ }
156
+ }
157
+ finally {
158
+ this.ownFilteredOut = filteredOut;
159
+ steiners = EMPTY_STEINERS;
160
+ }
161
+ return this.done;
162
+ }
163
+ /**
164
+ * Preprocessing (building the linked list, bridging the holes, bbox, z-order indexing)
165
+ *
166
+ * This part is not sliced. It takes only tens of milliseconds even at a million
167
+ * vertices, so fidelity to the port is preferred over the value of slicing it.
168
+ */
169
+ runSetup() {
170
+ const data = this.data;
171
+ const holeIndices = this.holeIndices;
172
+ const dim = this.dim;
173
+ const hasHoles = holeIndices !== null && holeIndices.length > 0;
174
+ const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
175
+ if (steiners.size)
176
+ steiners.clear();
177
+ let outerNode = linkedList(data, 0, outerLen, dim, true);
178
+ if (!outerNode || outerNode.next === outerNode.prev) {
179
+ this.phase = 'done';
180
+ return;
181
+ }
182
+ if (hasHoles)
183
+ outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
184
+ // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
185
+ if (data.length > 80 * dim) {
186
+ let minX = data[0];
187
+ let minY = data[1];
188
+ let maxX = minX;
189
+ let maxY = minY;
190
+ for (let i = dim; i < outerLen; i += dim) {
191
+ const x = data[i];
192
+ const y = data[i + 1];
193
+ if (x < minX)
194
+ minX = x;
195
+ if (y < minY)
196
+ minY = y;
197
+ if (x > maxX)
198
+ maxX = x;
199
+ if (y > maxY)
200
+ maxY = y;
201
+ }
202
+ // minX, minY and invSize are later used to transform coords into integers for z-order
203
+ let invSize = Math.max(maxX - minX, maxY - minY);
204
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
205
+ this.minX = minX;
206
+ this.minY = minY;
207
+ this.invSize = invSize;
208
+ }
209
+ // interlink polygon nodes in z-order
210
+ if (this.invSize)
211
+ indexCurve(outerNode, this.minX, this.minY, this.invSize);
212
+ this.ear = outerNode;
213
+ this.stop = outerNode;
214
+ this.cured = false;
215
+ this.phase = 'clip';
216
+ }
217
+ /**
218
+ * The main ear clipping loop (identical to upstream's earcutLinked; breaks out on the
219
+ * iteration count)
220
+ *
221
+ * splitEarcut, the last resort, is recursive, so it is not sliced (it is a path that
222
+ * runs only once against the remaining polygon and is not taken for ordinary inputs).
223
+ */
224
+ runClip(iterations) {
225
+ const { triangles, minX, minY, invSize } = this;
226
+ let ear = this.ear;
227
+ let stop = this.stop;
228
+ let cured = this.cured;
229
+ let remaining = iterations;
230
+ // iterate through ears, slicing them one by one
231
+ while (ear.prev !== ear.next) {
232
+ if (remaining-- <= 0) {
233
+ this.ear = ear;
234
+ this.stop = stop;
235
+ this.cured = cured;
236
+ return;
237
+ }
238
+ const prev = ear.prev;
239
+ const next = ear.next;
240
+ if (area(prev, ear, next) < 0 &&
241
+ (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear))) {
242
+ triangles.push(prev.i, ear.i, next.i); // cut off the triangle
243
+ removeNode(ear);
244
+ ear = next;
245
+ stop = next;
246
+ continue;
247
+ }
248
+ ear = next;
249
+ // if we looped through the whole remaining polygon and can't find any more ears
250
+ if (ear === stop) {
251
+ // try filtering collinear/coincident points and slicing again — repeat as long as
252
+ // filtering actually removes nodes, since each removal can expose new ears
253
+ filteredOut = false;
254
+ ear = filterPoints(ear);
255
+ if (filteredOut) {
256
+ stop = ear;
257
+ continue;
258
+ }
259
+ // filtering is exhausted: cure small local self-intersections once, then retry
260
+ if (!cured) {
261
+ ear = cureLocalIntersections(ear, triangles);
262
+ stop = ear;
263
+ cured = true;
264
+ continue;
265
+ }
266
+ // as a last resort, try splitting the remaining polygon into two
267
+ splitEarcut(ear, triangles, minX, minY, invSize);
268
+ break;
269
+ }
270
+ }
271
+ this.ear = ear;
272
+ this.stop = stop;
273
+ this.cured = cured;
274
+ this.phase = 'done';
275
+ }
276
+ }
277
+ // === The following is the port of upstream earcut (the algorithm is unmodified) ===
278
+ // create a circular doubly linked list from polygon points in the specified winding order
279
+ function linkedList(data, start, end, dim, clockwise) {
280
+ let last = null;
281
+ if (clockwise === signedArea(data, start, end, dim) > 0) {
282
+ for (let i = start; i < end; i += dim)
283
+ last = insertNode((i / dim) | 0, data[i], data[i + 1], last);
284
+ }
285
+ else {
286
+ for (let i = end - dim; i >= start; i -= dim)
287
+ last = insertNode((i / dim) | 0, data[i], data[i + 1], last);
288
+ }
289
+ if (last && equals(last, last.next)) {
290
+ removeNode(last);
291
+ last = last.next;
292
+ }
293
+ return last;
294
+ }
295
+ // Remove collinear or coincident points; removability depends only on a node's immediate
296
+ // neighbors, so we sweep forward and re-check the predecessor after each removal. With no `end`
297
+ // we sweep the whole ring, lapping until nothing is removable (the fixpoint the clipper needs).
298
+ // With an explicit `end` we heal only the dirty window around a bridge/diagonal cut, stopping at
299
+ // `end` rather than lapping — O(window) instead of O(ring).
300
+ function filterPoints(start, end = start) {
301
+ const full = end === start;
302
+ let p = start;
303
+ let again;
304
+ do {
305
+ again = false;
306
+ if (p !== p.next &&
307
+ (steiners.size === 0 || !steiners.has(p)) &&
308
+ (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
309
+ if (full || p === end)
310
+ end = p.prev; // pull the stop bound back past the removal
311
+ filteredOut = true;
312
+ removeNode(p);
313
+ p = p.prev; // re-check the predecessor
314
+ again = true;
315
+ }
316
+ else if (full || p !== end) {
317
+ p = p.next;
318
+ again = !full; // local heal: keep looping until the sweep reaches end
319
+ }
320
+ } while (again || p !== end);
321
+ return end;
322
+ }
323
+ // main ear slicing loop which triangulates a polygon (given as a linked list)
324
+ //
325
+ // This has the same content as SlicedEarcut.runClip. It is left as upstream for the path
326
+ // that runs through in one go without slicing (the recursion of splitEarcut).
327
+ function earcutLinked(ear, triangles, minX, minY, invSize) {
328
+ // interlink polygon nodes in z-order
329
+ if (invSize)
330
+ indexCurve(ear, minX, minY, invSize);
331
+ let stop = ear;
332
+ let cured = false;
333
+ // iterate through ears, slicing them one by one
334
+ while (ear.prev !== ear.next) {
335
+ const prev = ear.prev;
336
+ const next = ear.next;
337
+ if (area(prev, ear, next) < 0 &&
338
+ (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear))) {
339
+ triangles.push(prev.i, ear.i, next.i); // cut off the triangle
340
+ removeNode(ear);
341
+ ear = next;
342
+ stop = next;
343
+ continue;
344
+ }
345
+ ear = next;
346
+ // if we looped through the whole remaining polygon and can't find any more ears
347
+ if (ear === stop) {
348
+ filteredOut = false;
349
+ ear = filterPoints(ear);
350
+ if (filteredOut) {
351
+ stop = ear;
352
+ continue;
353
+ }
354
+ if (!cured) {
355
+ ear = cureLocalIntersections(ear, triangles);
356
+ stop = ear;
357
+ cured = true;
358
+ continue;
359
+ }
360
+ splitEarcut(ear, triangles, minX, minY, invSize);
361
+ break;
362
+ }
363
+ }
364
+ }
365
+ // check whether a polygon node forms a valid ear with adjacent nodes
366
+ function isEar(ear) {
367
+ // reflex check (area(a, b, c) >= 0) is hoisted into the caller
368
+ const a = ear.prev;
369
+ const b = ear;
370
+ const c = ear.next;
371
+ const ax = a.x;
372
+ const bx = b.x;
373
+ const cx = c.x;
374
+ const ay = a.y;
375
+ const by = b.y;
376
+ const cy = c.y;
377
+ const x0 = Math.min(ax, bx, cx); // triangle bbox
378
+ const y0 = Math.min(ay, by, cy);
379
+ const x1 = Math.max(ax, bx, cx);
380
+ const y1 = Math.max(ay, by, cy);
381
+ // make sure we don't have other points inside the potential ear
382
+ let p = c.next;
383
+ while (p !== a) {
384
+ if (p.x >= x0 &&
385
+ p.x <= x1 &&
386
+ p.y >= y0 &&
387
+ p.y <= y1 &&
388
+ !(ax === p.x && ay === p.y) &&
389
+ pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) &&
390
+ area(p.prev, p, p.next) >= 0)
391
+ return false;
392
+ p = p.next;
393
+ }
394
+ return true;
395
+ }
396
+ function isEarHashed(ear, minX, minY, invSize) {
397
+ // reflex check is hoisted into the caller (see isEar)
398
+ const a = ear.prev;
399
+ const b = ear;
400
+ const c = ear.next;
401
+ const ax = a.x;
402
+ const bx = b.x;
403
+ const cx = c.x;
404
+ const ay = a.y;
405
+ const by = b.y;
406
+ const cy = c.y;
407
+ const x0 = Math.min(ax, bx, cx); // triangle bbox
408
+ const y0 = Math.min(ay, by, cy);
409
+ const x1 = Math.max(ax, bx, cx);
410
+ const y1 = Math.max(ay, by, cy);
411
+ // z-order range for the current triangle bbox
412
+ const minZ = zOrder(x0, y0, minX, minY, invSize);
413
+ const maxZ = zOrder(x1, y1, minX, minY, invSize);
414
+ let p = ear.prevZ;
415
+ while (p && p.z >= minZ) {
416
+ // look for points inside the triangle in decreasing z-order
417
+ if (p.x >= x0 &&
418
+ p.x <= x1 &&
419
+ p.y >= y0 &&
420
+ p.y <= y1 &&
421
+ p !== c &&
422
+ !(ax === p.x && ay === p.y) &&
423
+ pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) &&
424
+ area(p.prev, p, p.next) >= 0)
425
+ return false;
426
+ p = p.prevZ;
427
+ }
428
+ let n = ear.nextZ;
429
+ while (n && n.z <= maxZ) {
430
+ // look for points in increasing z-order
431
+ if (n.x >= x0 &&
432
+ n.x <= x1 &&
433
+ n.y >= y0 &&
434
+ n.y <= y1 &&
435
+ n !== c &&
436
+ !(ax === n.x && ay === n.y) &&
437
+ pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) &&
438
+ area(n.prev, n, n.next) >= 0)
439
+ return false;
440
+ n = n.nextZ;
441
+ }
442
+ return true;
443
+ }
444
+ // go through all polygon nodes and cure small local self-intersections
445
+ function cureLocalIntersections(start, triangles) {
446
+ let p = start;
447
+ let cured = false;
448
+ do {
449
+ const a = p.prev;
450
+ const b = p.next.next;
451
+ if (intersects(a, p, p.next, b, false) && locallyInside(a, b) && locallyInside(b, a)) {
452
+ triangles.push(a.i, p.i, b.i);
453
+ // remove two nodes involved
454
+ removeNode(p);
455
+ removeNode(p.next);
456
+ p = b;
457
+ start = b;
458
+ cured = true;
459
+ }
460
+ p = p.next;
461
+ } while (p !== start);
462
+ return cured ? filterPoints(p) : p;
463
+ }
464
+ // try splitting polygon into two and triangulate them independently
465
+ function splitEarcut(start, triangles, minX, minY, invSize) {
466
+ // look for a valid diagonal that divides the polygon into two
467
+ let a = start;
468
+ do {
469
+ let b = a.next.next;
470
+ while (b !== a.prev) {
471
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
472
+ // split the polygon in two by the diagonal
473
+ let c = splitPolygon(a, b);
474
+ // filter colinear points around the cuts
475
+ a = filterPoints(a, a.next);
476
+ c = filterPoints(c, c.next);
477
+ // run earcut on each half
478
+ earcutLinked(a, triangles, minX, minY, invSize);
479
+ earcutLinked(c, triangles, minX, minY, invSize);
480
+ return;
481
+ }
482
+ b = b.next;
483
+ }
484
+ a = a.next;
485
+ } while (a !== start);
486
+ }
487
+ // link every hole into the outer loop, producing a single-ring polygon without holes
488
+ function eliminateHoles(data, holeIndices, outerNode, dim) {
489
+ const queue = [];
490
+ for (let i = 0, len = holeIndices.length; i < len; i++) {
491
+ const start = holeIndices[i] * dim;
492
+ const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
493
+ const list = linkedList(data, start, end, dim, false);
494
+ if (list === list.next)
495
+ steiners.add(list);
496
+ queue.push(getLeftmost(list));
497
+ }
498
+ queue.sort(compareXYSlope);
499
+ // block-bbox index for findHoleBridge, grown append-only as holes merge
500
+ buildBlockIndex(data.length / dim, holeIndices.length);
501
+ indexSegment(outerNode, outerNode);
502
+ // process holes from left to right
503
+ indexActive = true;
504
+ for (let i = 0; i < queue.length; i++) {
505
+ outerNode = eliminateHole(queue[i], outerNode);
506
+ }
507
+ indexActive = false;
508
+ // collapse collinear/coincident points across the whole merged ring once before clipping
509
+ return filterPoints(outerNode);
510
+ }
511
+ function compareXYSlope(a, b) {
512
+ // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that
513
+ // when we find the bridge to the outer shell it is always the point that they meet at.
514
+ return (a.x - b.x ||
515
+ a.y - b.y ||
516
+ (a.next.y - a.y) / (a.next.x - a.x) - (b.next.y - b.y) / (b.next.x - b.x));
517
+ }
518
+ // find a bridge between vertices that connects hole with an outer ring and link it
519
+ function eliminateHole(hole, outerNode) {
520
+ const bridge = findHoleBridge(hole, outerNode);
521
+ if (!bridge) {
522
+ return outerNode;
523
+ }
524
+ const bridgeReverse = splitPolygon(bridge, hole);
525
+ // index the merged-in segment before filtering
526
+ const bridge2 = bridgeReverse.next;
527
+ indexSegment(bridge, bridge2.next);
528
+ // heal collinear/coincident points around the two new slit edges
529
+ filterPoints(bridgeReverse, bridgeReverse.next);
530
+ return filterPoints(bridge, bridge.next);
531
+ }
532
+ // Block-bbox index for findHoleBridge: one [minX,minY,maxX,maxY] bbox per K consecutive ring
533
+ // edges, in a flat Float64Array, so the leftward-ray scan can skip whole blocks in O(1).
534
+ const K = 16; // edges per block
535
+ let blockBBox = new Float64Array(0); // [minX,minY,maxX,maxY] per block
536
+ let numBlocks = 0;
537
+ const blockHead = []; // first node of each block's segment
538
+ const blockStop = []; // node just past each block's segment
539
+ function buildBlockIndex(maxNodes, numHoles) {
540
+ // upper bound: every input node indexed once, +2 bridge nodes per hole, plus a partial
541
+ // trailing block per appended segment (outer ring + one per hole)
542
+ const maxBlocks = Math.ceil((maxNodes + 2 * numHoles) / K) + numHoles + 2;
543
+ if (blockBBox.length < maxBlocks * 4)
544
+ blockBBox = new Float64Array(maxBlocks * 4);
545
+ numBlocks = 0;
546
+ }
547
+ // index the ring run head..stop (exclusive) as ceil(len / K) blocks; head === stop means
548
+ // the whole ring. each block's bbox covers both endpoints of every edge it owns.
549
+ function indexSegment(head, stop) {
550
+ let p = head;
551
+ do {
552
+ const b = numBlocks++;
553
+ blockHead[b] = p;
554
+ let minX = Number.POSITIVE_INFINITY;
555
+ let minY = Number.POSITIVE_INFINITY;
556
+ let maxX = Number.NEGATIVE_INFINITY;
557
+ let maxY = Number.NEGATIVE_INFINITY;
558
+ let k = 0;
559
+ do {
560
+ const c = p.next; // edge p->c; bbox must bound both endpoints
561
+ p.z = b; // reuse z as the owning block during eliminateHoles (see growBlock)
562
+ if (p.x < minX)
563
+ minX = p.x;
564
+ if (p.x > maxX)
565
+ maxX = p.x;
566
+ if (p.y < minY)
567
+ minY = p.y;
568
+ if (p.y > maxY)
569
+ maxY = p.y;
570
+ if (c.x < minX)
571
+ minX = c.x;
572
+ if (c.x > maxX)
573
+ maxX = c.x;
574
+ if (c.y < minY)
575
+ minY = c.y;
576
+ if (c.y > maxY)
577
+ maxY = c.y;
578
+ p = c;
579
+ } while (++k < K && p !== stop);
580
+ blockStop[b] = p;
581
+ const g = b * 4;
582
+ blockBBox[g] = minX;
583
+ blockBBox[g + 1] = minY;
584
+ blockBBox[g + 2] = maxX;
585
+ blockBBox[g + 3] = maxY;
586
+ } while (p !== stop);
587
+ }
588
+ // when filterPoints heals an edge head->tail, grow head's block bbox to cover tail so the
589
+ // leftward-ray prune can't false-skip it.
590
+ function growBlock(head, tail) {
591
+ const g = head.z * 4;
592
+ if (tail.x < blockBBox[g])
593
+ blockBBox[g] = tail.x;
594
+ if (tail.y < blockBBox[g + 1])
595
+ blockBBox[g + 1] = tail.y;
596
+ if (tail.x > blockBBox[g + 2])
597
+ blockBBox[g + 2] = tail.x;
598
+ if (tail.y > blockBBox[g + 3])
599
+ blockBBox[g + 3] = tail.y;
600
+ }
601
+ function liveBlockStop(b) {
602
+ let stop = blockStop[b];
603
+ while (stop.prev.next !== stop)
604
+ stop = stop.next;
605
+ blockStop[b] = stop;
606
+ return stop;
607
+ }
608
+ // the block's head node can be removed by filterPoints during merges; advance it to the next
609
+ // live node so the walk doesn't start on (and immediately terminate at) a dead node.
610
+ function liveBlockHead(b) {
611
+ let head = blockHead[b];
612
+ while (head.prev.next !== head)
613
+ head = head.next;
614
+ blockHead[b] = head;
615
+ return head;
616
+ }
617
+ // David Eberly's algorithm for finding a bridge between hole and outer polygon
618
+ function findHoleBridge(hole, outerNode) {
619
+ let p = outerNode;
620
+ const hx = hole.x;
621
+ const hy = hole.y;
622
+ let qx = Number.NEGATIVE_INFINITY;
623
+ let m;
624
+ // find a segment intersected by a ray from the hole's leftmost point to the left;
625
+ // segment's endpoint with lesser x will be potential connection point
626
+ // unless they intersect at a vertex, then choose the vertex
627
+ if (equals(hole, p))
628
+ return p;
629
+ // scan blocks; skip any whose bbox can't hold a crossing that beats qx and lies left of hx
630
+ for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {
631
+ if (hy < blockBBox[g + 1] ||
632
+ hy > blockBBox[g + 3] ||
633
+ blockBBox[g] > hx ||
634
+ blockBBox[g + 2] <= qx)
635
+ continue;
636
+ // ensure the walk's exclusive bound is live so we don't overrun into other blocks
637
+ const stop = liveBlockStop(b);
638
+ p = liveBlockHead(b);
639
+ do {
640
+ if (p.prev.next === p) {
641
+ // skip nodes removed by filterPoints (stale in the index)
642
+ if (equals(hole, p.next))
643
+ return p.next;
644
+ if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
645
+ const x = p.x + ((hy - p.y) * (p.next.x - p.x)) / (p.next.y - p.y);
646
+ if (x <= hx && x > qx) {
647
+ qx = x;
648
+ m = p.x < p.next.x ? p : p.next;
649
+ if (x === hx)
650
+ return m; // hole touches outer segment; pick leftmost endpoint
651
+ }
652
+ }
653
+ }
654
+ p = p.next;
655
+ } while (p !== stop);
656
+ }
657
+ if (!m)
658
+ return null;
659
+ // look for points inside the triangle of hole point, segment intersection and endpoint;
660
+ // if there are no points found, we have a valid connection;
661
+ // otherwise choose the point of the minimum angle with the ray as connection point
662
+ const mx = m.x;
663
+ const my = m.y;
664
+ const tminY = Math.min(hy, my); // the triangle's y span; x span is [mx, hx]
665
+ const tmaxY = Math.max(hy, my);
666
+ let tanMin = Number.POSITIVE_INFINITY;
667
+ // scan the same blocks; skip any whose bbox can't overlap the triangle's box
668
+ for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {
669
+ if (blockBBox[g + 2] < mx ||
670
+ blockBBox[g] > hx ||
671
+ blockBBox[g + 3] < tminY ||
672
+ blockBBox[g + 1] > tmaxY)
673
+ continue;
674
+ const stop = liveBlockStop(b);
675
+ p = liveBlockHead(b);
676
+ do {
677
+ if (p.prev.next === p &&
678
+ hx >= p.x &&
679
+ p.x >= mx &&
680
+ hx !== p.x && // skip dead nodes
681
+ pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
682
+ const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
683
+ // if hole point sits on p's horizontal edge (T-junction touch): the bridge runs
684
+ // along that edge — locallyInside rejects it as collinear, but it's valid
685
+ if ((locallyInside(p, hole) || (p.y === hy && p.next.y === hy && p.next.x > hx)) &&
686
+ (tan < tanMin ||
687
+ (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
688
+ m = p;
689
+ tanMin = tan;
690
+ }
691
+ }
692
+ p = p.next;
693
+ } while (p !== stop);
694
+ }
695
+ return m;
696
+ }
697
+ // whether sector in vertex m contains sector in vertex p in the same coordinates
698
+ function sectorContainsSector(m, p) {
699
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
700
+ }
701
+ // scratch buffers reused across calls and grown on demand
702
+ const sortArr = [];
703
+ let sortBuf = [];
704
+ let zArr = new Uint32Array(0);
705
+ let zBuf = new Uint32Array(0);
706
+ const counts = new Uint32Array(256);
707
+ // interlink polygon nodes in z-order: collect into an array, sort by z, relink
708
+ function indexCurve(start, minX, minY, invSize) {
709
+ let p = start;
710
+ let n = 0;
711
+ do {
712
+ // always (re)compute: z may still hold a block index left over from eliminateHoles
713
+ p.z = zOrder(p.x, p.y, minX, minY, invSize);
714
+ sortArr[n++] = p;
715
+ p = p.next;
716
+ } while (p !== start);
717
+ sortNodes(n);
718
+ let prev = null;
719
+ for (let i = 0; i < n; i++) {
720
+ const node = sortArr[i];
721
+ node.prevZ = prev;
722
+ if (prev)
723
+ prev.nextZ = node;
724
+ prev = node;
725
+ }
726
+ prev.nextZ = null;
727
+ }
728
+ // sort the first n nodes of sortArr by z, in place: insertion sort for small n, else LSD radix
729
+ function sortNodes(n) {
730
+ if (n <= 32) {
731
+ for (let i = 1; i < n; i++) {
732
+ const node = sortArr[i];
733
+ const z = node.z;
734
+ let j = i - 1;
735
+ while (j >= 0 && sortArr[j].z > z) {
736
+ sortArr[j + 1] = sortArr[j];
737
+ j--;
738
+ }
739
+ sortArr[j + 1] = node;
740
+ }
741
+ return;
742
+ }
743
+ if (zArr.length < n) {
744
+ zArr = new Uint32Array(n);
745
+ zBuf = new Uint32Array(n);
746
+ sortBuf = new Array(n);
747
+ }
748
+ for (let i = 0; i < n; i++)
749
+ zArr[i] = sortArr[i].z;
750
+ // even pass count lands the sorted result back in sortArr
751
+ radixPass(n, sortArr, zArr, sortBuf, zBuf, 0);
752
+ radixPass(n, sortBuf, zBuf, sortArr, zArr, 8);
753
+ radixPass(n, sortArr, zArr, sortBuf, zBuf, 16);
754
+ radixPass(n, sortBuf, zBuf, sortArr, zArr, 24);
755
+ }
756
+ // one LSD radix pass: stably scatter the first n nodes (and their z) from src to dst
757
+ function radixPass(n, src, srcZ, dst, dstZ, shift) {
758
+ counts.fill(0);
759
+ for (let i = 0; i < n; i++)
760
+ counts[(srcZ[i] >>> shift) & 0xff]++;
761
+ // turn per-bucket counts into start offsets (prefix sum)
762
+ let sum = 0;
763
+ for (let b = 0; b < 256; b++) {
764
+ const c = counts[b];
765
+ counts[b] = sum;
766
+ sum += c;
767
+ }
768
+ for (let i = 0; i < n; i++) {
769
+ const z = srcZ[i];
770
+ const pos = counts[(z >>> shift) & 0xff]++;
771
+ dst[pos] = src[i];
772
+ dstZ[pos] = z;
773
+ }
774
+ }
775
+ // z-order of a point given coords and inverse of the longer side of data bbox
776
+ function zOrder(x, y, minX, minY, invSize) {
777
+ // coords are transformed into non-negative 15-bit integer range
778
+ x = ((x - minX) * invSize) | 0;
779
+ y = ((y - minY) * invSize) | 0;
780
+ x = (x | (x << 8)) & 0x00ff00ff;
781
+ x = (x | (x << 4)) & 0x0f0f0f0f;
782
+ x = (x | (x << 2)) & 0x33333333;
783
+ x = (x | (x << 1)) & 0x55555555;
784
+ y = (y | (y << 8)) & 0x00ff00ff;
785
+ y = (y | (y << 4)) & 0x0f0f0f0f;
786
+ y = (y | (y << 2)) & 0x33333333;
787
+ y = (y | (y << 1)) & 0x55555555;
788
+ return x | (y << 1);
789
+ }
790
+ // find the leftmost node of a polygon ring
791
+ function getLeftmost(start) {
792
+ let p = start;
793
+ let leftmost = start;
794
+ do {
795
+ if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y))
796
+ leftmost = p;
797
+ p = p.next;
798
+ } while (p !== start);
799
+ return leftmost;
800
+ }
801
+ // check if a point lies within a convex triangle
802
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
803
+ return ((cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
804
+ (ax - px) * (by - py) >= (bx - px) * (ay - py) &&
805
+ (bx - px) * (cy - py) >= (cx - px) * (by - py));
806
+ }
807
+ // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
808
+ function isValidDiagonal(a, b) {
809
+ // degenerate case
810
+ const zeroLength = equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0;
811
+ return (a.next.i !== b.i &&
812
+ (zeroLength ||
813
+ (locallyInside(a, b) && // locally visible
814
+ locallyInside(b, a) &&
815
+ (area(a.prev, a, b.prev) !== 0 || area(a, b.prev, b) !== 0))) && // no opposite-facing sectors
816
+ !intersectsPolygon(a, b) &&
817
+ (zeroLength || middleInside(a, b)));
818
+ }
819
+ // signed area of a triangle
820
+ function area(p, q, r) {
821
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
822
+ }
823
+ // check if two points are equal
824
+ function equals(p1, p2) {
825
+ return p1.x === p2.x && p1.y === p2.y;
826
+ }
827
+ // check if two segments intersect; by default includes collinear boundary touches
828
+ function intersects(p1, q1, p2, q2, includeBoundary = true) {
829
+ const o1 = area(p1, q1, p2);
830
+ const o2 = area(p1, q1, q2);
831
+ const o3 = area(p2, q2, p1);
832
+ const o4 = area(p2, q2, q1);
833
+ if (((o1 > 0 && o2 < 0) || (o1 < 0 && o2 > 0)) && ((o3 > 0 && o4 < 0) || (o3 < 0 && o4 > 0)))
834
+ return true;
835
+ if (!includeBoundary)
836
+ return false;
837
+ if (o1 === 0 && onSegment(p1, p2, q1))
838
+ return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
839
+ if (o2 === 0 && onSegment(p1, q2, q1))
840
+ return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
841
+ if (o3 === 0 && onSegment(p2, p1, q2))
842
+ return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
843
+ if (o4 === 0 && onSegment(p2, q1, q2))
844
+ return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
845
+ return false;
846
+ }
847
+ // for collinear points p, q, r, check if point q lies on segment pr
848
+ function onSegment(p, q, r) {
849
+ return (q.x <= Math.max(p.x, r.x) &&
850
+ q.x >= Math.min(p.x, r.x) &&
851
+ q.y <= Math.max(p.y, r.y) &&
852
+ q.y >= Math.min(p.y, r.y));
853
+ }
854
+ // check if a polygon diagonal intersects any polygon segments
855
+ function intersectsPolygon(a, b) {
856
+ // diagonal bbox; an edge whose bbox can't overlap it can't intersect it
857
+ const minX = Math.min(a.x, b.x);
858
+ const maxX = Math.max(a.x, b.x);
859
+ const minY = Math.min(a.y, b.y);
860
+ const maxY = Math.max(a.y, b.y);
861
+ let p = a;
862
+ do {
863
+ const n = p.next;
864
+ if ((p.x > maxX && n.x > maxX) ||
865
+ (p.x < minX && n.x < minX) ||
866
+ (p.y > maxY && n.y > maxY) ||
867
+ (p.y < minY && n.y < minY)) {
868
+ p = n;
869
+ continue;
870
+ }
871
+ if (p.i !== a.i && n.i !== a.i && p.i !== b.i && n.i !== b.i && intersects(p, n, a, b))
872
+ return true;
873
+ p = n;
874
+ } while (p !== a);
875
+ return false;
876
+ }
877
+ // check if a polygon diagonal is locally inside the polygon
878
+ function locallyInside(a, b) {
879
+ return area(a.prev, a, a.next) < 0
880
+ ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0
881
+ : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
882
+ }
883
+ // check if the middle point of a polygon diagonal is inside the polygon
884
+ function middleInside(a, b) {
885
+ let p = a;
886
+ let inside = false;
887
+ const px = (a.x + b.x) / 2;
888
+ const py = (a.y + b.y) / 2;
889
+ do {
890
+ const n = p.next;
891
+ if (p.y > py !== n.y > py && px < ((n.x - p.x) * (py - p.y)) / (n.y - p.y) + p.x)
892
+ inside = !inside;
893
+ p = n;
894
+ } while (p !== a);
895
+ return inside;
896
+ }
897
+ // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits
898
+ // polygon into two; if one belongs to the outer ring and another to a hole, it merges it
899
+ function splitPolygon(a, b) {
900
+ const a2 = createNode(a.i, a.x, a.y);
901
+ const b2 = createNode(b.i, b.x, b.y);
902
+ const an = a.next;
903
+ const bp = b.prev;
904
+ a.next = b;
905
+ b.prev = a;
906
+ a2.next = an;
907
+ an.prev = a2;
908
+ b2.next = a2;
909
+ a2.prev = b2;
910
+ bp.next = b2;
911
+ b2.prev = bp;
912
+ return b2;
913
+ }
914
+ // create a node and optionally link it with previous one (in a circular doubly linked list)
915
+ function insertNode(i, x, y, last) {
916
+ const p = createNode(i, x, y);
917
+ if (!last) {
918
+ p.prev = p;
919
+ p.next = p;
920
+ }
921
+ else {
922
+ p.next = last.next;
923
+ p.prev = last;
924
+ last.next.prev = p;
925
+ last.next = p;
926
+ }
927
+ return p;
928
+ }
929
+ function removeNode(p) {
930
+ p.next.prev = p.prev;
931
+ p.prev.next = p.next;
932
+ if (p.prevZ)
933
+ p.prevZ.nextZ = p.nextZ;
934
+ if (p.nextZ)
935
+ p.nextZ.prevZ = p.prevZ;
936
+ // keep the hole-bridge index's block bboxes covering the healed prev->next edge
937
+ if (indexActive)
938
+ growBlock(p.prev, p.next);
939
+ }
940
+ function createNode(i, x, y) {
941
+ // prev/next are assigned by the caller before any read
942
+ return {
943
+ i, // vertex index in coordinates array
944
+ x,
945
+ y, // vertex coordinates
946
+ prev: null, // previous and next vertex nodes in a polygon ring
947
+ next: null,
948
+ z: 0, // z-order curve value; doubles as owning block in the hole-bridge index
949
+ prevZ: null, // previous and next nodes in z-order
950
+ nextZ: null,
951
+ };
952
+ }
953
+ function signedArea(data, start, end, dim) {
954
+ let sum = 0;
955
+ for (let i = start, j = end - dim; i < end; i += dim) {
956
+ sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
957
+ j = i;
958
+ }
959
+ return sum;
960
+ }