@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,122 @@
1
+ import type { Coordinate, Feature, VertexRef } from '../../store/types.js';
2
+ /**
3
+ * The set of handles to display
4
+ *
5
+ * It holds no coordinates. Because the set can be reused as is even after the vertices
6
+ * move, the number of handles does not change while dragging.
7
+ */
8
+ export interface VisibleHandleSet {
9
+ /** Vertices to display (same VertexRef semantics as computeVertexHandles) */
10
+ vertexRefs: VertexRef[];
11
+ /** Midpoints to display (same VertexRef semantics as computeMidpointHandles) */
12
+ midpointRefs: VertexRef[];
13
+ }
14
+ /**
15
+ * Viewport used for the pre-filtering of the thinning
16
+ */
17
+ export interface ThinningViewport {
18
+ /** lngLat rectangle. When null, pre-filtering is skipped (all vertices are candidates) */
19
+ bounds: {
20
+ minLng: number;
21
+ minLat: number;
22
+ maxLng: number;
23
+ maxLat: number;
24
+ } | null;
25
+ }
26
+ /**
27
+ * Counts the total number of handles (vertices + midpoints) without enumerating them all
28
+ *
29
+ * It matches computeVertexHandles(feature).length +
30
+ * computeMidpointHandles(feature).length exactly. Because it is used to decide whether the
31
+ * thinning kicks in and whether the cache is invalidated, it only scans the number of rings
32
+ * and parts.
33
+ */
34
+ export declare function countPotentialHandles(feature: Feature): number;
35
+ /**
36
+ * Whether the handles of this feature are thinned
37
+ */
38
+ export declare function shouldThinHandles(feature: Feature): boolean;
39
+ /**
40
+ * Computes the set of handles to display (pure function)
41
+ *
42
+ * Vertices are chosen with a greedy algorithm that takes only those whose screen distance
43
+ * from the previously adopted vertex is at least MIN_HANDLE_SPACING_PX. Midpoints are
44
+ * emitted only when both end vertices have been adopted and the screen length of the edge
45
+ * is at least MIDPOINT_MIN_EDGE_PX.
46
+ *
47
+ * @param project Function that projects a longitude/latitude to screen coordinates
48
+ * @param viewport Rectangle for pre-filtering (off-screen vertices are not even projected)
49
+ */
50
+ export declare function computeVisibleHandleSet(feature: Feature, project: (coord: Coordinate) => {
51
+ x: number;
52
+ y: number;
53
+ }, viewport: ThinningViewport): VisibleHandleSet;
54
+ /**
55
+ * Returns the set with the vertex references it does not contain added on the vertex side
56
+ *
57
+ * A rendering-only supplement that prevents a recomputation from hiding the selected or
58
+ * in-operation vertices and producing "it disappeared even though I selected it". The hit
59
+ * testing side does not apply this supplement (the principle that only what is visible can
60
+ * be grabbed is not bent for a single supplemented point; a selected vertex is being
61
+ * dragged, so it need not be grabbed again, which makes this a harmless simplification).
62
+ */
63
+ export declare function includeRequiredVertexRefs(set: VisibleHandleSet, required: readonly VertexRef[]): VisibleHandleSet;
64
+ /**
65
+ * Looks up the coordinate of a vertex handle
66
+ *
67
+ * index is the vertex number excluding the closing point, but it matches the number counted
68
+ * from the head of the raw coordinate sequence (the closing point only ever sits at the
69
+ * end), so it can be used as an index as is.
70
+ */
71
+ export declare function resolveVertexCoordinate(feature: Feature, ref: VertexRef): Coordinate | null;
72
+ /**
73
+ * Looks up the coordinate of a midpoint handle
74
+ *
75
+ * The midpoint of edge i is the midpoint on the Mercator plane of the raw coordinates i and
76
+ * i+1, the point halfway along the edge as drawn (the same formula as computeMidpointHandles;
77
+ * `mercatorMidpoint`). For the last edge of a closed ring no wrap-around is needed either,
78
+ * because the trailing closing point has the same coordinate as the first.
79
+ */
80
+ export declare function resolveMidpointCoordinate(feature: Feature, ref: VertexRef): Coordinate | null;
81
+ /**
82
+ * Cache of the thinned sets
83
+ *
84
+ * Rendering (selection-ui-drawer) and hit testing (handle-test) have to look at the same
85
+ * set. One cache belongs to one draw instance (it is part of the SelectionScope that both the
86
+ * CustomLayer and the modes receive), so two instances holding a feature with the same id
87
+ * (a duplicated document, for instance) never share a set or a refresh timer.
88
+ */
89
+ export declare class HandleThinningCache {
90
+ private entries;
91
+ private refreshTimer;
92
+ /**
93
+ * Gets the set from the rendering path (building it if there is none)
94
+ *
95
+ * While the camera is moving the stale set is returned, and it is rebuilt once the camera
96
+ * has been still for THINNING_REFRESH_DEBOUNCE_MS. Only when the vertex count changes is
97
+ * it rebuilt immediately.
98
+ *
99
+ * @param now Current time (passed by the caller for testability)
100
+ * @param compute Function that computes the set
101
+ * @param onNeedsRefresh Hook that triggers a redraw after the camera settles, called when
102
+ * a stale set was returned
103
+ */
104
+ ensureSet(feature: Feature, cameraSig: string, now: number, compute: () => VisibleHandleSet, onNeedsRefresh?: () => void): VisibleHandleSet;
105
+ /**
106
+ * Gets "the set currently displayed" from the hit testing path
107
+ *
108
+ * The camera signature is not consulted. The stale set used while moving is precisely the
109
+ * one being displayed, and matching it is the source of truth for hit testing. For a
110
+ * feature that is not thinned it returns null, and the caller tests by full enumeration
111
+ * as before.
112
+ */
113
+ getDisplayedSet(feature: Feature): VisibleHandleSet | null;
114
+ /**
115
+ * Discards the cache (all entries when featureId is omitted)
116
+ */
117
+ clear(featureId?: string): void;
118
+ /** Stores an entry (discarding the oldest one when the upper bound is exceeded) */
119
+ private store;
120
+ /** Re-arms the timer that triggers a redraw (only one is held at a time) */
121
+ private scheduleRefresh;
122
+ }
@@ -0,0 +1,430 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Screen-density thinning of the editing handles
5
+ *
6
+ * When a LineString / Polygon (including the Multi types) with thousands to tens of
7
+ * thousands of vertices is selected, the vertex handles and midpoint handles are thinned by
8
+ * screen density to build "the set of vertex references to display". Only the display is
9
+ * thinned; the doc (the coordinate sequence) is never touched.
10
+ *
11
+ * What is visible is the source of truth for what can be manipulated, so hit testing
12
+ * (handle-test.ts) also covers only the set built here. Grabbing a place with no handle
13
+ * still moves the feature itself as before, so moving a dense line as a whole still works.
14
+ */
15
+ import { HANDLE_THINNING_THRESHOLD, MIDPOINT_MIN_EDGE_PX, MIN_HANDLE_SPACING_PX, THINNING_REFRESH_DEBOUNCE_MS, } from '../../shared/config/selection.js';
16
+ import { mercatorMidpoint } from '../../shared/math/globe-subdivision.js';
17
+ import { supportsVertexEditing } from '../../shared/utils/coordinates.js';
18
+ import { isSameVertexRef } from '../../shared/utils/vertex-ref.js';
19
+ /**
20
+ * Decomposes a feature into scan units
21
+ *
22
+ * They are ordered so that the scan order of the vertices is exactly the same as in
23
+ * computeVertexHandles and the scan order of the edges exactly the same as in
24
+ * computeMidpointHandles.
25
+ */
26
+ function collectHandleRuns(feature) {
27
+ const runs = [];
28
+ if (feature.type === 'LineString') {
29
+ pushLineRun(runs, feature.coordinates);
30
+ }
31
+ else if (feature.type === 'Polygon') {
32
+ pushPolygonRuns(runs, feature.coordinates);
33
+ }
34
+ else if (feature.type === 'MultiPoint') {
35
+ // Splitting a MultiPoint per part would adopt every point and defeat the thinning, so
36
+ // all parts are scanned as a single sequence
37
+ const points = feature.coordinates;
38
+ runs.push({
39
+ coords: points,
40
+ vertexCount: points.length,
41
+ hasEdges: false,
42
+ forceLast: false,
43
+ makeRef: (index) => ({ part: index, ring: 0, index: 0 }),
44
+ });
45
+ }
46
+ else if (feature.type === 'MultiLineString') {
47
+ const parts = feature.coordinates;
48
+ for (let part = 0; part < parts.length; part++) {
49
+ pushLineRun(runs, parts[part], part);
50
+ }
51
+ }
52
+ else if (feature.type === 'MultiPolygon') {
53
+ const parts = feature.coordinates;
54
+ for (let part = 0; part < parts.length; part++) {
55
+ pushPolygonRuns(runs, parts[part], part);
56
+ }
57
+ }
58
+ return runs;
59
+ }
60
+ /**
61
+ * Adds a line (a single coordinate sequence) as a scan unit
62
+ */
63
+ function pushLineRun(runs, coords, part) {
64
+ runs.push({
65
+ coords,
66
+ vertexCount: coords.length,
67
+ hasEdges: true,
68
+ forceLast: true,
69
+ makeRef: (index) => (part === undefined ? { ring: 0, index } : { part, ring: 0, index }),
70
+ });
71
+ }
72
+ /**
73
+ * Adds a polygon (an array of rings) as scan units
74
+ */
75
+ function pushPolygonRuns(runs, rings, part) {
76
+ for (let ring = 0; ring < rings.length; ring++) {
77
+ const coords = rings[ring];
78
+ if (coords.length === 0)
79
+ continue;
80
+ runs.push({
81
+ coords,
82
+ vertexCount: countRingVertices(coords),
83
+ hasEdges: true,
84
+ // A closed ring has no endpoints, and in an open ring the edges also end at the last
85
+ // vertex, so nothing is force-adopted
86
+ forceLast: false,
87
+ makeRef: (index) => (part === undefined ? { ring, index } : { part, ring, index }),
88
+ });
89
+ }
90
+ }
91
+ /**
92
+ * Number of vertex handles of a ring (the vertex count excluding the closing point)
93
+ *
94
+ * The closing-point test is identical to collectPolygonVertexHandles (the first and the
95
+ * last coordinates match).
96
+ */
97
+ function countRingVertices(ring) {
98
+ if (ring.length === 0)
99
+ return 0;
100
+ const isClosed = ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1];
101
+ return isClosed ? ring.length - 1 : ring.length;
102
+ }
103
+ /**
104
+ * Counts the total number of handles (vertices + midpoints) without enumerating them all
105
+ *
106
+ * It matches computeVertexHandles(feature).length +
107
+ * computeMidpointHandles(feature).length exactly. Because it is used to decide whether the
108
+ * thinning kicks in and whether the cache is invalidated, it only scans the number of rings
109
+ * and parts.
110
+ */
111
+ export function countPotentialHandles(feature) {
112
+ if (feature.type === 'Point')
113
+ return 1;
114
+ if (feature.type === 'LineString') {
115
+ return countLineHandles(feature.coordinates.length);
116
+ }
117
+ if (feature.type === 'Polygon') {
118
+ return countPolygonHandles(feature.coordinates);
119
+ }
120
+ if (feature.type === 'MultiPoint') {
121
+ // Each coordinate is the vertex handle of one part. There are no edges
122
+ return feature.coordinates.length;
123
+ }
124
+ if (feature.type === 'MultiLineString') {
125
+ let total = 0;
126
+ for (const part of feature.coordinates) {
127
+ total += countLineHandles(part.length);
128
+ }
129
+ return total;
130
+ }
131
+ if (feature.type === 'MultiPolygon') {
132
+ let total = 0;
133
+ for (const part of feature.coordinates) {
134
+ total += countPolygonHandles(part);
135
+ }
136
+ return total;
137
+ }
138
+ // Circle / Freehand / Image / custom features have no vertex handles
139
+ return 0;
140
+ }
141
+ /** Number of handles of a single line (n vertices + n-1 edges) */
142
+ function countLineHandles(length) {
143
+ return length + Math.max(0, length - 1);
144
+ }
145
+ /** Number of handles of a single polygon (the sum of vertices + edges over the rings) */
146
+ function countPolygonHandles(rings) {
147
+ let total = 0;
148
+ for (const ring of rings) {
149
+ if (ring.length === 0)
150
+ continue;
151
+ total += countRingVertices(ring) + Math.max(0, ring.length - 1);
152
+ }
153
+ return total;
154
+ }
155
+ /**
156
+ * Whether the handles of this feature are thinned
157
+ */
158
+ export function shouldThinHandles(feature) {
159
+ return (supportsVertexEditing(feature.type) &&
160
+ countPotentialHandles(feature) > HANDLE_THINNING_THRESHOLD);
161
+ }
162
+ /**
163
+ * Whether the coordinate falls inside the viewport rectangle (always true if bounds is null)
164
+ */
165
+ function isInBounds(coord, bounds) {
166
+ if (!bounds)
167
+ return true;
168
+ return (coord[0] >= bounds.minLng &&
169
+ coord[0] <= bounds.maxLng &&
170
+ coord[1] >= bounds.minLat &&
171
+ coord[1] <= bounds.maxLat);
172
+ }
173
+ /**
174
+ * Computes the set of handles to display (pure function)
175
+ *
176
+ * Vertices are chosen with a greedy algorithm that takes only those whose screen distance
177
+ * from the previously adopted vertex is at least MIN_HANDLE_SPACING_PX. Midpoints are
178
+ * emitted only when both end vertices have been adopted and the screen length of the edge
179
+ * is at least MIDPOINT_MIN_EDGE_PX.
180
+ *
181
+ * @param project Function that projects a longitude/latitude to screen coordinates
182
+ * @param viewport Rectangle for pre-filtering (off-screen vertices are not even projected)
183
+ */
184
+ export function computeVisibleHandleSet(feature, project, viewport) {
185
+ const vertexRefs = [];
186
+ const midpointRefs = [];
187
+ const minSpacingSq = MIN_HANDLE_SPACING_PX * MIN_HANDLE_SPACING_PX;
188
+ const minEdgeSq = MIDPOINT_MIN_EDGE_PX * MIDPOINT_MIN_EDGE_PX;
189
+ for (const run of collectHandleRuns(feature)) {
190
+ // Screen positions of the adopted vertices (kept so the midpoint test need not reproject)
191
+ const adopted = new Map();
192
+ let last = null;
193
+ for (let i = 0; i < run.vertexCount; i++) {
194
+ // Off-screen vertices are skipped without being projected (and "the previously
195
+ // adopted point" is not updated either)
196
+ if (!isInBounds(run.coords[i], viewport.bounds))
197
+ continue;
198
+ const screen = project(run.coords[i]);
199
+ const isLastVertex = run.forceLast && i === run.vertexCount - 1;
200
+ if (last !== null && !isLastVertex && distanceSq(screen, last) < minSpacingSq) {
201
+ continue;
202
+ }
203
+ vertexRefs.push(run.makeRef(i));
204
+ adopted.set(i, screen);
205
+ last = screen;
206
+ }
207
+ if (!run.hasEdges)
208
+ continue;
209
+ // The edges are enumerated as in computeMidpointHandles (i = 0..len-2 over the raw
210
+ // coordinates)
211
+ for (let i = 0; i < run.coords.length - 1; i++) {
212
+ const start = adopted.get(i);
213
+ // The last edge of a closed ring wraps back to vertex 0, not to the closing point
214
+ const endIndex = i + 1 < run.vertexCount ? i + 1 : 0;
215
+ const end = adopted.get(endIndex);
216
+ if (!start || !end)
217
+ continue;
218
+ if (distanceSq(start, end) < minEdgeSq)
219
+ continue;
220
+ midpointRefs.push(run.makeRef(i));
221
+ }
222
+ }
223
+ return { vertexRefs, midpointRefs };
224
+ }
225
+ /** The square of the screen distance between two points */
226
+ function distanceSq(a, b) {
227
+ const dx = a.x - b.x;
228
+ const dy = a.y - b.y;
229
+ return dx * dx + dy * dy;
230
+ }
231
+ /**
232
+ * Returns the set with the vertex references it does not contain added on the vertex side
233
+ *
234
+ * A rendering-only supplement that prevents a recomputation from hiding the selected or
235
+ * in-operation vertices and producing "it disappeared even though I selected it". The hit
236
+ * testing side does not apply this supplement (the principle that only what is visible can
237
+ * be grabbed is not bent for a single supplemented point; a selected vertex is being
238
+ * dragged, so it need not be grabbed again, which makes this a harmless simplification).
239
+ */
240
+ export function includeRequiredVertexRefs(set, required) {
241
+ if (required.length === 0)
242
+ return set;
243
+ const missing = required.filter((ref) => !set.vertexRefs.some((r) => isSameVertexRef(r, ref)));
244
+ if (missing.length === 0)
245
+ return set;
246
+ return {
247
+ vertexRefs: [...set.vertexRefs, ...missing],
248
+ midpointRefs: set.midpointRefs,
249
+ };
250
+ }
251
+ /**
252
+ * Extracts the raw coordinate sequence (one line / one ring) the vertex reference belongs to
253
+ */
254
+ function getRefCoords(feature, ref) {
255
+ const part = ref.part ?? 0;
256
+ if (feature.type === 'Point') {
257
+ return [feature.coordinates];
258
+ }
259
+ if (feature.type === 'LineString') {
260
+ return feature.coordinates;
261
+ }
262
+ if (feature.type === 'Polygon') {
263
+ return feature.coordinates[ref.ring] ?? null;
264
+ }
265
+ if (feature.type === 'MultiPoint') {
266
+ const point = feature.coordinates[part];
267
+ return point ? [point] : null;
268
+ }
269
+ if (feature.type === 'MultiLineString') {
270
+ return feature.coordinates[part] ?? null;
271
+ }
272
+ if (feature.type === 'MultiPolygon') {
273
+ return feature.coordinates[part]?.[ref.ring] ?? null;
274
+ }
275
+ return null;
276
+ }
277
+ /**
278
+ * Looks up the coordinate of a vertex handle
279
+ *
280
+ * index is the vertex number excluding the closing point, but it matches the number counted
281
+ * from the head of the raw coordinate sequence (the closing point only ever sits at the
282
+ * end), so it can be used as an index as is.
283
+ */
284
+ export function resolveVertexCoordinate(feature, ref) {
285
+ const coords = getRefCoords(feature, ref);
286
+ return coords?.[ref.index] ?? null;
287
+ }
288
+ /**
289
+ * Looks up the coordinate of a midpoint handle
290
+ *
291
+ * The midpoint of edge i is the midpoint on the Mercator plane of the raw coordinates i and
292
+ * i+1, the point halfway along the edge as drawn (the same formula as computeMidpointHandles;
293
+ * `mercatorMidpoint`). For the last edge of a closed ring no wrap-around is needed either,
294
+ * because the trailing closing point has the same coordinate as the first.
295
+ */
296
+ export function resolveMidpointCoordinate(feature, ref) {
297
+ const coords = getRefCoords(feature, ref);
298
+ const start = coords?.[ref.index];
299
+ const end = coords?.[ref.index + 1];
300
+ if (!start || !end)
301
+ return null;
302
+ return mercatorMidpoint(start, end);
303
+ }
304
+ /**
305
+ * Upper bound on the number of cache entries (the selection is effectively single, so 4 is
306
+ * enough)
307
+ */
308
+ const MAX_CACHE_ENTRIES = 4;
309
+ /** Slack of the timer that triggers a redraw (fires reliably after the debounce expires) */
310
+ const REFRESH_TIMER_MARGIN_MS = 20;
311
+ /**
312
+ * Cache of the thinned sets
313
+ *
314
+ * Rendering (selection-ui-drawer) and hit testing (handle-test) have to look at the same
315
+ * set. One cache belongs to one draw instance (it is part of the SelectionScope that both the
316
+ * CustomLayer and the modes receive), so two instances holding a feature with the same id
317
+ * (a duplicated document, for instance) never share a set or a refresh timer.
318
+ */
319
+ export class HandleThinningCache {
320
+ constructor() {
321
+ Object.defineProperty(this, "entries", {
322
+ enumerable: true,
323
+ configurable: true,
324
+ writable: true,
325
+ value: new Map()
326
+ });
327
+ Object.defineProperty(this, "refreshTimer", {
328
+ enumerable: true,
329
+ configurable: true,
330
+ writable: true,
331
+ value: null
332
+ });
333
+ }
334
+ /**
335
+ * Gets the set from the rendering path (building it if there is none)
336
+ *
337
+ * While the camera is moving the stale set is returned, and it is rebuilt once the camera
338
+ * has been still for THINNING_REFRESH_DEBOUNCE_MS. Only when the vertex count changes is
339
+ * it rebuilt immediately.
340
+ *
341
+ * @param now Current time (passed by the caller for testability)
342
+ * @param compute Function that computes the set
343
+ * @param onNeedsRefresh Hook that triggers a redraw after the camera settles, called when
344
+ * a stale set was returned
345
+ */
346
+ ensureSet(feature, cameraSig, now, compute, onNeedsRefresh) {
347
+ const handleCount = countPotentialHandles(feature);
348
+ const entry = this.entries.get(feature.id);
349
+ // No entry / the vertex count changed -> rebuild immediately
350
+ if (!entry || entry.handleCount !== handleCount) {
351
+ const set = compute();
352
+ this.store(feature.id, { handleCount, cameraSig, set });
353
+ return set;
354
+ }
355
+ if (entry.cameraSig === cameraSig) {
356
+ entry.pendingSig = undefined;
357
+ entry.pendingSince = undefined;
358
+ return entry.set;
359
+ }
360
+ if (entry.pendingSig !== cameraSig) {
361
+ // A new camera position was seen. The debounce is counted from here
362
+ entry.pendingSig = cameraSig;
363
+ entry.pendingSince = now;
364
+ }
365
+ else if (now - (entry.pendingSince ?? now) >= THINNING_REFRESH_DEBOUNCE_MS) {
366
+ const set = compute();
367
+ entry.set = set;
368
+ entry.cameraSig = cameraSig;
369
+ entry.pendingSig = undefined;
370
+ entry.pendingSince = undefined;
371
+ return set;
372
+ }
373
+ // Return the stale set. The timer that triggers a redraw is re-armed so that the
374
+ // recomputation runs even if no rendering frame arrives after the camera settles
375
+ this.scheduleRefresh(onNeedsRefresh);
376
+ return entry.set;
377
+ }
378
+ /**
379
+ * Gets "the set currently displayed" from the hit testing path
380
+ *
381
+ * The camera signature is not consulted. The stale set used while moving is precisely the
382
+ * one being displayed, and matching it is the source of truth for hit testing. For a
383
+ * feature that is not thinned it returns null, and the caller tests by full enumeration
384
+ * as before.
385
+ */
386
+ getDisplayedSet(feature) {
387
+ const entry = this.entries.get(feature.id);
388
+ if (!entry)
389
+ return null;
390
+ if (entry.handleCount !== countPotentialHandles(feature))
391
+ return null;
392
+ return entry.set;
393
+ }
394
+ /**
395
+ * Discards the cache (all entries when featureId is omitted)
396
+ */
397
+ clear(featureId) {
398
+ if (featureId === undefined) {
399
+ this.entries.clear();
400
+ if (this.refreshTimer !== null) {
401
+ clearTimeout(this.refreshTimer);
402
+ this.refreshTimer = null;
403
+ }
404
+ return;
405
+ }
406
+ this.entries.delete(featureId);
407
+ }
408
+ /** Stores an entry (discarding the oldest one when the upper bound is exceeded) */
409
+ store(featureId, entry) {
410
+ this.entries.delete(featureId);
411
+ while (this.entries.size >= MAX_CACHE_ENTRIES) {
412
+ const oldest = this.entries.keys().next();
413
+ if (oldest.done)
414
+ break;
415
+ this.entries.delete(oldest.value);
416
+ }
417
+ this.entries.set(featureId, entry);
418
+ }
419
+ /** Re-arms the timer that triggers a redraw (only one is held at a time) */
420
+ scheduleRefresh(onNeedsRefresh) {
421
+ if (!onNeedsRefresh)
422
+ return;
423
+ if (this.refreshTimer !== null)
424
+ clearTimeout(this.refreshTimer);
425
+ this.refreshTimer = setTimeout(() => {
426
+ this.refreshTimer = null;
427
+ onNeedsRefresh();
428
+ }, THINNING_REFRESH_DEBOUNCE_MS + REFRESH_TIMER_MARGIN_MS);
429
+ }
430
+ }
@@ -0,0 +1,25 @@
1
+ import type { HandleType } from '../../shared/config/constants.js';
2
+ import type { Coordinate, Feature, VertexRef } from '../../store/types.js';
3
+ /**
4
+ * A handle of the selection UI: its kind and its position.
5
+ */
6
+ export interface HandleInfo {
7
+ /** The kind of handle (a resize corner, a vertex, a midpoint, a rotation handle...) */
8
+ type: HandleType;
9
+ /** The position of the handle, `[lng, lat]` in degrees */
10
+ position: Coordinate;
11
+ /** Vertex reference for vertex/midpoint handles (part number + ring number + vertex index) */
12
+ vertexRef?: VertexRef;
13
+ }
14
+ export { supportsVertexEditing } from '../../shared/utils/coordinates.js';
15
+ /**
16
+ * Computes the position of the radius handle for a Circle
17
+ *
18
+ * The handle is laid out with the same geodesic direct problem as the circle's outline, so it
19
+ * sits on the outline at any latitude and radius.
20
+ */
21
+ export declare function computeCircleRadiusHandle(feature: Feature): HandleInfo | null;
22
+ /**
23
+ * Computes the position of the center marker for a Circle
24
+ */
25
+ export declare function computeCircleCenterHandle(feature: Feature): HandleInfo | null;