@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,919 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * SDFPolygonRenderer
5
+ *
6
+ * A renderer that draws the fill and stroke of a polygon in a single draw call.
7
+ * - fill: filled with a triangulation (earcut)
8
+ * - stroke: high quality line rendering with the HHAA (Half-plane Anti-Aliasing) method
9
+ *
10
+ * Batching is possible while preserving the z-order.
11
+ */
12
+ import earcut from 'earcut';
13
+ import { RENDERING_DEFAULTS } from '../../../shared/math/index.js';
14
+ import { resolveContentPixelRatio, resolvePixelRatio } from '../../../shared/utils/pixel-ratio.js';
15
+ import { EarcutCache } from '../../cache/earcut.js';
16
+ import { getSurfaceTessellationStep, tessellateSurfaceFill } from '../../globe-subdivision.js';
17
+ import { getRenderFrame } from '../../shaders/frame.js';
18
+ import { calculateLngLatOffset, calculateOffsetUniforms, createProgram, getProjectionTransitionUniform, OFFSET_MODE_GLSL, } from '../../shaders/helpers.js';
19
+ import { ProjectionUniformManager } from '../../shaders/projection.js';
20
+ import { TERRAIN_SHADE_FRAGMENT_GLSL, TERRAIN_SHADE_VERTEX_GLSL, } from '../../shaders/terrain-shade.js';
21
+ import { TerrainContext } from '../../terrain/context.js';
22
+ import { TERRAIN_MAX_TILED_COARSEN } from '../../terrain/metrics.js';
23
+ import { batchTessellationFactor, polygonTessellationStep, ringBoundingCells, tessellateRings, } from '../../terrain/polygon.js';
24
+ import { reportTerrainCoarsening } from '../../terrain/state.js';
25
+ import { NEUTRAL_DRAW_FACTORS } from '../draw-factors.js';
26
+ import { buildEarcutInput } from './earcut-input.js';
27
+ import { drawFillWithTerrainCull } from './terrain-cull.js';
28
+ /** Floats per vertex: pos(2) + color(4) + type(1) + prev(2) + next(2) + side(1) + extra(3) */
29
+ const VERTEX_STRIDE = 15;
30
+ /**
31
+ * Rounds the origin of the relative coordinates to Float32
32
+ */
33
+ function normalizeOrigin(origin) {
34
+ return [Math.fround(origin[0]), Math.fround(origin[1])];
35
+ }
36
+ /**
37
+ * The default origin of a polygon batch (the first coordinate of the outer ring of the
38
+ * first polygon)
39
+ */
40
+ function defaultPolygonOrigin(polygons) {
41
+ const first = polygons[0]?.coordinates[0]?.[0];
42
+ return first ? [first[0], first[1]] : [0, 0];
43
+ }
44
+ /**
45
+ * SDFPolygonRenderer
46
+ *
47
+ * @internal
48
+ */
49
+ export class SDFPolygonRenderer {
50
+ constructor(gl, pixelRatio, scope = {}) {
51
+ Object.defineProperty(this, "gl", {
52
+ enumerable: true,
53
+ configurable: true,
54
+ writable: true,
55
+ value: void 0
56
+ });
57
+ Object.defineProperty(this, "program", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: null
62
+ });
63
+ Object.defineProperty(this, "variantName", {
64
+ enumerable: true,
65
+ configurable: true,
66
+ writable: true,
67
+ value: ''
68
+ });
69
+ // Projection uniform management
70
+ Object.defineProperty(this, "projectionUniformManager", {
71
+ enumerable: true,
72
+ configurable: true,
73
+ writable: true,
74
+ value: void 0
75
+ });
76
+ // Uniform locations (renderer specific)
77
+ Object.defineProperty(this, "viewportLoc", {
78
+ enumerable: true,
79
+ configurable: true,
80
+ writable: true,
81
+ value: null
82
+ });
83
+ Object.defineProperty(this, "zoomLoc", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: null
88
+ });
89
+ Object.defineProperty(this, "miterLimitLoc", {
90
+ enumerable: true,
91
+ configurable: true,
92
+ writable: true,
93
+ value: null
94
+ });
95
+ Object.defineProperty(this, "sizeScaleLoc", {
96
+ enumerable: true,
97
+ configurable: true,
98
+ writable: true,
99
+ value: null
100
+ });
101
+ Object.defineProperty(this, "opacityLoc", {
102
+ enumerable: true,
103
+ configurable: true,
104
+ writable: true,
105
+ value: null
106
+ });
107
+ // A record of the renderer specific uniforms written last (for memoization within a frame)
108
+ //
109
+ // Retained mode passes through here once per chunk, but neither the viewport nor the
110
+ // miter limit changes within a frame. Writes of the same value are skipped, and they
111
+ // are rewritten once the frame changes (see shaders/frame.ts).
112
+ Object.defineProperty(this, "memoFrame", {
113
+ enumerable: true,
114
+ configurable: true,
115
+ writable: true,
116
+ value: -1
117
+ });
118
+ Object.defineProperty(this, "memoViewportWidth", {
119
+ enumerable: true,
120
+ configurable: true,
121
+ writable: true,
122
+ value: Number.NaN
123
+ });
124
+ Object.defineProperty(this, "memoViewportHeight", {
125
+ enumerable: true,
126
+ configurable: true,
127
+ writable: true,
128
+ value: Number.NaN
129
+ });
130
+ Object.defineProperty(this, "memoZoom", {
131
+ enumerable: true,
132
+ configurable: true,
133
+ writable: true,
134
+ value: Number.NaN
135
+ });
136
+ Object.defineProperty(this, "memoMiterLimit", {
137
+ enumerable: true,
138
+ configurable: true,
139
+ writable: true,
140
+ value: Number.NaN
141
+ });
142
+ Object.defineProperty(this, "memoFactorsFrame", {
143
+ enumerable: true,
144
+ configurable: true,
145
+ writable: true,
146
+ value: -1
147
+ });
148
+ Object.defineProperty(this, "memoSizeScale", {
149
+ enumerable: true,
150
+ configurable: true,
151
+ writable: true,
152
+ value: Number.NaN
153
+ });
154
+ Object.defineProperty(this, "memoOpacity", {
155
+ enumerable: true,
156
+ configurable: true,
157
+ writable: true,
158
+ value: Number.NaN
159
+ });
160
+ // Stores the offset uniforms
161
+ Object.defineProperty(this, "offsetUniforms", {
162
+ enumerable: true,
163
+ configurable: true,
164
+ writable: true,
165
+ value: null
166
+ });
167
+ // Buffers
168
+ Object.defineProperty(this, "vertexBuffer", {
169
+ enumerable: true,
170
+ configurable: true,
171
+ writable: true,
172
+ value: null
173
+ });
174
+ Object.defineProperty(this, "indexBuffer", {
175
+ enumerable: true,
176
+ configurable: true,
177
+ writable: true,
178
+ value: null
179
+ });
180
+ Object.defineProperty(this, "vao", {
181
+ enumerable: true,
182
+ configurable: true,
183
+ writable: true,
184
+ value: null
185
+ });
186
+ /** The injected pixel ratio (when not injected it is read from window each time) */
187
+ Object.defineProperty(this, "pixelRatio", {
188
+ enumerable: true,
189
+ configurable: true,
190
+ writable: true,
191
+ value: void 0
192
+ });
193
+ /** The terrain state of the draw instance */
194
+ Object.defineProperty(this, "terrain", {
195
+ enumerable: true,
196
+ configurable: true,
197
+ writable: true,
198
+ value: void 0
199
+ });
200
+ /** Triangulation results of the draw instance, keyed by feature id */
201
+ Object.defineProperty(this, "earcutCache", {
202
+ enumerable: true,
203
+ configurable: true,
204
+ writable: true,
205
+ value: void 0
206
+ });
207
+ this.gl = gl;
208
+ this.pixelRatio = pixelRatio;
209
+ this.terrain = scope.terrain ?? new TerrainContext();
210
+ this.earcutCache = scope.earcut ?? new EarcutCache();
211
+ this.projectionUniformManager = new ProjectionUniformManager(gl, {
212
+ surface: true,
213
+ terrain: this.terrain,
214
+ });
215
+ this.vertexBuffer = gl.createBuffer();
216
+ this.indexBuffer = gl.createBuffer();
217
+ this.vao = gl.createVertexArray();
218
+ }
219
+ /**
220
+ * Ensures the shader (recreating it when necessary)
221
+ */
222
+ ensureShader(shaderData) {
223
+ if (this.variantName !== shaderData.variantName) {
224
+ if (this.program) {
225
+ this.gl.deleteProgram(this.program);
226
+ }
227
+ this.program = this.createShaderProgram(shaderData.vertexShaderPrelude, shaderData.define);
228
+ this.variantName = shaderData.variantName;
229
+ // Get the projection uniform locations
230
+ this.projectionUniformManager.getLocations(this.program);
231
+ // Get the renderer specific uniform locations
232
+ this.viewportLoc = this.gl.getUniformLocation(this.program, 'u_viewport');
233
+ this.zoomLoc = this.gl.getUniformLocation(this.program, 'u_zoom');
234
+ this.miterLimitLoc = this.gl.getUniformLocation(this.program, 'u_miterLimit');
235
+ this.sizeScaleLoc = this.gl.getUniformLocation(this.program, 'u_size_scale');
236
+ this.opacityLoc = this.gl.getUniformLocation(this.program, 'u_opacity');
237
+ // A recreated program also resets its uniforms to their initial values, so the
238
+ // record is discarded
239
+ this.resetUniformMemo();
240
+ // Set up the VAO
241
+ this.setupVAO();
242
+ }
243
+ }
244
+ /**
245
+ * Sets the uniforms for offset mode
246
+ */
247
+ setOffsetUniforms(uniforms) {
248
+ this.offsetUniforms = uniforms;
249
+ }
250
+ /**
251
+ * Discards the record of the values written last
252
+ */
253
+ resetUniformMemo() {
254
+ this.memoFrame = -1;
255
+ this.memoViewportWidth = Number.NaN;
256
+ this.memoViewportHeight = Number.NaN;
257
+ this.memoZoom = Number.NaN;
258
+ this.memoMiterLimit = Number.NaN;
259
+ this.memoFactorsFrame = -1;
260
+ this.memoSizeScale = Number.NaN;
261
+ this.memoOpacity = Number.NaN;
262
+ }
263
+ /**
264
+ * Writes the viewport, zoom and miter limit (shared by immediate mode and retained mode)
265
+ *
266
+ * If the value is the same it is not rewritten. Once the frame changes the whole set is
267
+ * rewritten.
268
+ */
269
+ setShapeUniforms(viewport, zoomValue) {
270
+ const gl = this.gl;
271
+ const frame = getRenderFrame();
272
+ const staleFrame = this.memoFrame !== frame;
273
+ if (this.viewportLoc &&
274
+ (staleFrame ||
275
+ this.memoViewportWidth !== viewport[0] ||
276
+ this.memoViewportHeight !== viewport[1])) {
277
+ gl.uniform2f(this.viewportLoc, viewport[0], viewport[1]);
278
+ this.memoViewportWidth = viewport[0];
279
+ this.memoViewportHeight = viewport[1];
280
+ }
281
+ if (this.zoomLoc && (staleFrame || this.memoZoom !== zoomValue)) {
282
+ gl.uniform1f(this.zoomLoc, zoomValue);
283
+ this.memoZoom = zoomValue;
284
+ }
285
+ if (this.miterLimitLoc &&
286
+ (staleFrame || this.memoMiterLimit !== RENDERING_DEFAULTS.MITER_LIMIT)) {
287
+ gl.uniform1f(this.miterLimitLoc, RENDERING_DEFAULTS.MITER_LIMIT);
288
+ this.memoMiterLimit = RENDERING_DEFAULTS.MITER_LIMIT;
289
+ }
290
+ this.memoFrame = frame;
291
+ }
292
+ /**
293
+ * Creates the shader program
294
+ */
295
+ createShaderProgram(prelude, define) {
296
+ const projTransitionUniform = getProjectionTransitionUniform(prelude);
297
+ // Vertex shader
298
+ // a_type: 0=fill, 1=stroke
299
+ // fill: uses only a_pos and a_color
300
+ // stroke: uses a_pos, a_color, a_prev, a_next, a_side and a_extra
301
+ const vertexSource = `#version 300 es
302
+ ${prelude}
303
+ ${define}
304
+ ${projTransitionUniform}${OFFSET_MODE_GLSL}${TERRAIN_SHADE_VERTEX_GLSL}
305
+
306
+ layout(location = 0) in vec2 a_pos; // current position (relative, 64-bit on CPU)
307
+ layout(location = 1) in vec4 a_color; // color (RGBA)
308
+ layout(location = 2) in float a_type; // 0=fill, 1=stroke
309
+ layout(location = 3) in vec2 a_prev; // previous vertex (relative coords, for stroke)
310
+ layout(location = 4) in vec2 a_next; // next vertex (relative coords, for stroke)
311
+ layout(location = 5) in float a_side; // left or right (for stroke: 1=left, -1=right)
312
+ layout(location = 6) in vec3 a_extra; // x=t(0-1), y=strokeWidth, z=createdZoom
313
+
314
+ uniform vec2 u_viewport;
315
+ uniform float u_zoom;
316
+ uniform float u_miterLimit;
317
+ uniform float u_size_scale; // the size factor at draw time (default 1)
318
+
319
+ out vec4 v_color;
320
+ out float v_type;
321
+ out float v_dist; // the SDF distance (for stroke)
322
+ out float v_halfWidth; // the half width of the line (for stroke)
323
+
324
+ void main() {
325
+ // The shading sample position is passed in both the fill and the outline branch (so
326
+ // that no undefined varying is left; only the fill fragment actually reads it)
327
+ emitShadeOffset(a_pos);
328
+
329
+ if (a_type < 0.5) {
330
+ // Fill: high precision version (uses relative coords computed at 64-bit precision on CPU)
331
+ gl_Position = project_position_to_clipspace_from_offset(a_pos, u_projection_matrix);
332
+ v_color = a_color;
333
+ v_type = 0.0;
334
+ v_dist = 0.0;
335
+ v_halfWidth = 0.0;
336
+ } else {
337
+ // Stroke: line rendering with the HHAA method (high precision version)
338
+ // Compute the clip coordinates (uses the relative coords already computed on the CPU side)
339
+ vec4 clipPos = project_position_to_clipspace_from_offset(a_pos, u_projection_matrix);
340
+ vec4 clipPrev = project_position_to_clipspace_from_offset(a_prev, u_projection_matrix);
341
+ vec4 clipNext = project_position_to_clipspace_from_offset(a_next, u_projection_matrix);
342
+
343
+ // NDC coordinates
344
+ vec2 ndcPos = clipPos.xy / clipPos.w;
345
+ vec2 ndcPrev = clipPrev.xy / clipPrev.w;
346
+ vec2 ndcNext = clipNext.xy / clipNext.w;
347
+
348
+ // Screen coordinates
349
+ vec2 screenPos = (ndcPos * 0.5 + 0.5) * u_viewport;
350
+ vec2 screenPrev = (ndcPrev * 0.5 + 0.5) * u_viewport;
351
+ vec2 screenNext = (ndcNext * 0.5 + 0.5) * u_viewport;
352
+
353
+ // Direction vectors
354
+ vec2 dirPrev = normalize(screenPos - screenPrev);
355
+ vec2 dirNext = normalize(screenNext - screenPos);
356
+
357
+ // Normals (the left side is positive)
358
+ vec2 normalPrev = vec2(-dirPrev.y, dirPrev.x);
359
+ vec2 normalNext = vec2(-dirNext.y, dirNext.x);
360
+
361
+ // Miter normal
362
+ vec2 miterNormal = normalize(normalPrev + normalNext);
363
+
364
+ // Miter scale
365
+ float cosHalfAngle = dot(miterNormal, normalPrev);
366
+ float miterScale = 1.0 / max(cosHalfAngle, 0.1);
367
+ miterScale = min(miterScale, u_miterLimit);
368
+
369
+ // Line width computation that takes createdZoom into account
370
+ // strokeWidth < 0 means "a fixed width of -strokeWidth pixels (zoom independent)".
371
+ // It is a convention for drawing features that have no createdZoom mixed into the
372
+ // same batch (= the same u_zoom) as features with a variable width.
373
+ float strokeWidth = a_extra.y;
374
+ float createdZoom = a_extra.z;
375
+ // u_size_scale is the size factor at draw time (default 1). It is multiplied
376
+ // outside the branch so that it takes effect whichever branch the data goes through.
377
+ float lineWidth = (strokeWidth >= 0.0
378
+ ? strokeWidth * pow(2.0, u_zoom - createdZoom)
379
+ : -strokeWidth) * u_size_scale;
380
+ float halfWidth = lineWidth / 2.0;
381
+
382
+ // Expand by 1 pixel for HHAA
383
+ float expandedHalfWidth = halfWidth + 1.0;
384
+
385
+ // Screen space offset
386
+ vec2 screenOffset = miterNormal * a_side * expandedHalfWidth * miterScale;
387
+ vec2 finalScreenPos = screenPos + screenOffset;
388
+
389
+ // Back to NDC
390
+ vec2 finalNdc = (finalScreenPos / u_viewport) * 2.0 - 1.0;
391
+ gl_Position = vec4(finalNdc * clipPos.w, clipPos.z, clipPos.w);
392
+
393
+ v_color = a_color;
394
+ v_type = 1.0;
395
+ v_dist = a_side * expandedHalfWidth;
396
+ v_halfWidth = halfWidth;
397
+ }
398
+ }`;
399
+ // Fragment shader
400
+ const fragmentSource = `#version 300 es
401
+ precision highp float;
402
+
403
+ in vec4 v_color;
404
+ in float v_type;
405
+ in float v_dist;
406
+ in float v_halfWidth;
407
+
408
+ uniform float u_opacity; // the opacity factor at draw time (default 1)
409
+
410
+ out vec4 fragColor;
411
+ ${TERRAIN_SHADE_FRAGMENT_GLSL}
412
+ void main() {
413
+ // Blending is non-premultiplied, so the factor is applied to the alpha only
414
+ if (v_type < 0.5) {
415
+ // Fill: output with the same terrain shading as the ground applied to the brightness
416
+ // (1.0 when there is no terrain). It is not applied to the outline (lines, points,
417
+ // labels and handles are by convention unshaded)
418
+ fragColor = vec4(v_color.rgb * terrainFillShade(), v_color.a * u_opacity);
419
+ } else {
420
+ // Stroke: anti-aliasing with the HHAA method
421
+ float d = abs(v_dist) - v_halfWidth;
422
+ float alpha = 1.0 - smoothstep(-1.0, 1.0, d);
423
+
424
+ if (alpha < 0.01) discard;
425
+
426
+ fragColor = vec4(v_color.rgb, v_color.a * alpha * u_opacity);
427
+ }
428
+ }`;
429
+ return createProgram(this.gl, vertexSource, fragmentSource);
430
+ }
431
+ /**
432
+ * Sets up the VAO
433
+ */
434
+ setupVAO() {
435
+ const gl = this.gl;
436
+ gl.bindVertexArray(this.vao);
437
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
438
+ this.setupVertexAttribs();
439
+ // The ELEMENT_ARRAY_BUFFER binding is part of the VAO state
440
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
441
+ gl.bindVertexArray(null);
442
+ }
443
+ /**
444
+ * Sets up the vertex attributes (called while the vertex buffer is bound to ARRAY_BUFFER)
445
+ *
446
+ * The same layout is used by immediate mode and retained mode.
447
+ */
448
+ setupVertexAttribs() {
449
+ const gl = this.gl;
450
+ // stride: pos(2) + color(4) + type(1) + prev(2) + next(2) + side(1) + extra(3) = 15 floats = 60 bytes
451
+ const stride = 60;
452
+ // a_pos: location 0
453
+ gl.enableVertexAttribArray(0);
454
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, 0);
455
+ // a_color: location 1
456
+ gl.enableVertexAttribArray(1);
457
+ gl.vertexAttribPointer(1, 4, gl.FLOAT, false, stride, 8);
458
+ // a_type: location 2
459
+ gl.enableVertexAttribArray(2);
460
+ gl.vertexAttribPointer(2, 1, gl.FLOAT, false, stride, 24);
461
+ // a_prev: location 3
462
+ gl.enableVertexAttribArray(3);
463
+ gl.vertexAttribPointer(3, 2, gl.FLOAT, false, stride, 28);
464
+ // a_next: location 4
465
+ gl.enableVertexAttribArray(4);
466
+ gl.vertexAttribPointer(4, 2, gl.FLOAT, false, stride, 36);
467
+ // a_side: location 5
468
+ gl.enableVertexAttribArray(5);
469
+ gl.vertexAttribPointer(5, 1, gl.FLOAT, false, stride, 44);
470
+ // a_extra: location 6
471
+ gl.enableVertexAttribArray(6);
472
+ gl.vertexAttribPointer(6, 3, gl.FLOAT, false, stride, 48);
473
+ }
474
+ /**
475
+ * Sets the projection uniforms (supporting offset mode + globe mode)
476
+ * @param projectionData MapLibre's ProjectionData
477
+ * @param zoom The current zoom level (used for switching offset mode)
478
+ */
479
+ setProjectionUniforms(projectionData, zoom) {
480
+ this.projectionUniformManager.setUniforms(projectionData, zoom, this.offsetUniforms);
481
+ }
482
+ /**
483
+ * Batch-draws multiple polygons
484
+ *
485
+ * Draws the fill and stroke of each polygon in a single draw call.
486
+ * The z-order is preserved by the order of the array.
487
+ *
488
+ * @param factors The factors used at draw time (the opacity of the layer being drawn; scale 1
489
+ * and opacity 1 when omitted)
490
+ * @returns The number of indices drawn (for debugging)
491
+ */
492
+ drawBatch(polygons, projectionData, zoom, viewport, factors = NEUTRAL_DRAW_FACTORS) {
493
+ if (!this.program || polygons.length === 0)
494
+ return 0;
495
+ const gl = this.gl;
496
+ // Compute relative coordinates on the CPU side (offset mode: computed at 64-bit precision)
497
+ const centerLngLat = this.offsetUniforms?.centerLngLat ?? [0, 0];
498
+ const { vertexData, indexData } = this.buildGeometry(polygons, centerLngLat, true);
499
+ if (indexData.length === 0)
500
+ return 0;
501
+ // Transfer the data to the buffer
502
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
503
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.DYNAMIC_DRAW);
504
+ // Draw
505
+ gl.useProgram(this.program);
506
+ this.setProjectionUniforms(projectionData, zoom);
507
+ this.setShapeUniforms(viewport, zoom);
508
+ // Always written (1 when the caller has none) so that no factor of an earlier draw is left
509
+ this.setDrawFactors(factors);
510
+ gl.bindVertexArray(this.vao);
511
+ // The ELEMENT_ARRAY_BUFFER binding is VAO state, so the transfer is done after
512
+ // binding the VAO
513
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.DYNAMIC_DRAW);
514
+ drawFillWithTerrainCull(gl, this.terrain, () => {
515
+ gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_INT, 0);
516
+ });
517
+ gl.bindVertexArray(null);
518
+ return indexData.length;
519
+ }
520
+ /**
521
+ * Writes the factors used at draw time
522
+ *
523
+ * Uniforms are residual state per program, so they are always reset to 1 even on paths
524
+ * that do not use the factors (immediate mode, the retained drawing of the Store). If
525
+ * the value already written is the same, it is not rewritten.
526
+ */
527
+ setDrawFactors(factors) {
528
+ const gl = this.gl;
529
+ const frame = getRenderFrame();
530
+ const staleFrame = this.memoFactorsFrame !== frame;
531
+ if (this.sizeScaleLoc && (staleFrame || this.memoSizeScale !== factors.scale)) {
532
+ gl.uniform1f(this.sizeScaleLoc, factors.scale);
533
+ this.memoSizeScale = factors.scale;
534
+ }
535
+ if (this.opacityLoc && (staleFrame || this.memoOpacity !== factors.opacity)) {
536
+ gl.uniform1f(this.opacityLoc, factors.opacity);
537
+ this.memoOpacity = factors.opacity;
538
+ }
539
+ this.memoFactorsFrame = frame;
540
+ }
541
+ /**
542
+ * Builds a retained-mode polygon batch
543
+ *
544
+ * earcut and the construction of the vertex array are finished here, so that in
545
+ * subsequent frames drawing takes only the bind + uniforms + draw call of
546
+ * `drawRetained`. The vertex data does not depend on the camera (the projection is done
547
+ * with per-frame uniforms).
548
+ *
549
+ * The earcut result is not put into the shared cache (the build happens only once, and
550
+ * the cache used by the drawing of the Store must not be polluted with the features
551
+ * of datasets). However, when options.triangulator is passed, both the caching and the
552
+ * time slicing of the triangulation become its responsibility
553
+ * (display/triangulation.ts).
554
+ *
555
+ * @returns The built batch. null when the shader is not initialized or there are no
556
+ * vertices
557
+ */
558
+ buildRetained(polygons, options = {}) {
559
+ if (!this.program || polygons.length === 0)
560
+ return null;
561
+ const gl = this.gl;
562
+ // The origin of the relative coordinates is fixed per batch (it is not made to depend
563
+ // on the camera center)
564
+ const origin = normalizeOrigin(options.origin ?? defaultPolygonOrigin(polygons));
565
+ const { vertexData, indexData } = this.buildGeometry(polygons, origin, false, options.triangulator);
566
+ if (indexData.length === 0)
567
+ return null;
568
+ const vao = gl.createVertexArray();
569
+ gl.bindVertexArray(vao);
570
+ const vertexBuffer = gl.createBuffer();
571
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
572
+ gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
573
+ this.setupVertexAttribs();
574
+ // The ELEMENT_ARRAY_BUFFER binding is part of the VAO state
575
+ const indexBuffer = gl.createBuffer();
576
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
577
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
578
+ gl.bindVertexArray(null);
579
+ return {
580
+ vao,
581
+ vertexBuffer,
582
+ indexBuffer,
583
+ indexCount: indexData.length,
584
+ origin,
585
+ widthZoom: options.widthZoom ?? null,
586
+ };
587
+ }
588
+ /**
589
+ * Draws a retained-mode polygon batch
590
+ *
591
+ * Neither earcut nor bufferData is performed. The projection uniforms are recomputed
592
+ * each frame from the origin of the batch (the vertex data is not rebuilt).
593
+ *
594
+ * @param factors The factors used at draw time (when omitted, scale 1 and opacity 1, as
595
+ * before)
596
+ */
597
+ drawRetained(batch, zoom, projectionData, viewport, factors = NEUTRAL_DRAW_FACTORS) {
598
+ if (!this.program || batch.indexCount === 0)
599
+ return;
600
+ const gl = this.gl;
601
+ gl.useProgram(this.program);
602
+ // The center of the linearization is aligned to the camera center (if it were
603
+ // linearized around the origin of the batch, the residual of the Mercator
604
+ // approximation would become a displacement of several pixels at vertices far from
605
+ // the center). The vertices are relative to the origin, so that difference is passed
606
+ // via u_origin_shift
607
+ const cameraUniforms = this.offsetUniforms;
608
+ if (cameraUniforms) {
609
+ this.projectionUniformManager.setUniforms(projectionData, zoom, cameraUniforms, [
610
+ batch.origin[0] - cameraUniforms.centerLngLat[0],
611
+ batch.origin[1] - cameraUniforms.centerLngLat[1],
612
+ ]);
613
+ }
614
+ else {
615
+ // Fallback (normally custom-layer has already called setOffsetUniforms each frame)
616
+ this.projectionUniformManager.setUniforms(projectionData, zoom, calculateOffsetUniforms(batch.origin, projectionData.mainMatrix));
617
+ }
618
+ this.setShapeUniforms(viewport, batch.widthZoom ?? zoom);
619
+ this.setDrawFactors(factors);
620
+ gl.bindVertexArray(batch.vao);
621
+ drawFillWithTerrainCull(gl, this.terrain, () => {
622
+ gl.drawElements(gl.TRIANGLES, batch.indexCount, gl.UNSIGNED_INT, 0);
623
+ });
624
+ gl.bindVertexArray(null);
625
+ }
626
+ /**
627
+ * Disposes of a retained-mode polygon batch
628
+ */
629
+ disposeRetained(batch) {
630
+ const gl = this.gl;
631
+ gl.deleteVertexArray(batch.vao);
632
+ gl.deleteBuffer(batch.vertexBuffer);
633
+ gl.deleteBuffer(batch.indexBuffer);
634
+ }
635
+ /**
636
+ * Decides the subdivision step used for this batch (null on a flat map without terrain)
637
+ *
638
+ * The step is the terrain's, or on the globe the cell of its fills (`globe-subdivision.ts`).
639
+ *
640
+ * A batch whose total cell count exceeds the budget drops every feature uniformly onto
641
+ * a coarser grid. The per-feature cap (TERRAIN_MAX_SUBDIVISION_POINTS) is insurance
642
+ * against "one huge polygon" and does not help against "thousands of small polygons".
643
+ * With 8,172 administrative boundaries, even at a few hundred cells each (far below the
644
+ * cap) the total reached 1.7 million cells, and a single build took 34 seconds
645
+ * (measured).
646
+ */
647
+ batchTerrainStep(polygons) {
648
+ const base = getSurfaceTessellationStep(this.terrain, 'fill');
649
+ if (!base)
650
+ return null;
651
+ let totalCells = 0;
652
+ for (const polygon of polygons) {
653
+ // Only the outer ring is looked at (an inner ring is inside the outer ring, so it
654
+ // does not change the total)
655
+ const outer = polygon.coordinates[0];
656
+ if (outer)
657
+ totalCells += ringBoundingCells(outer, base.grid, base.region);
658
+ }
659
+ const factor = batchTessellationFactor(totalCells);
660
+ // A coarsely subdivided polygon sinks into the depth easily. This is reported so that
661
+ // the bias can be matched
662
+ reportTerrainCoarsening(this.terrain, factor);
663
+ if (factor <= 1)
664
+ return base;
665
+ // While subdividing in alignment with the actual tile mesh, the coarsening is kept to
666
+ // a few steps of powers of 2 (it keeps riding on a subset of the mesh nodes, so
667
+ // valley floors do not sink)
668
+ if (base.tiling) {
669
+ return { ...base, coarsen: Math.min(factor, TERRAIN_MAX_TILED_COARSEN) };
670
+ }
671
+ return { grid: base.grid * factor, maxPoints: base.maxPoints, region: base.region };
672
+ }
673
+ /**
674
+ * Builds the vertex array and index array of the batch (shared by immediate mode and
675
+ * retained mode)
676
+ *
677
+ * The indices are laid out in the order "fill of polygon 0 -> outline of polygon 0 ->
678
+ * fill of polygon 1 -> ...", so the z-order is preserved even with a single
679
+ * drawElements.
680
+ *
681
+ * @param centerLngLat The origin of the relative coordinates
682
+ * @param useEarcutCache Whether to put the triangulation result into the draw instance's cache
683
+ * @param triangulator The supplier of triangulations (earcut is called on the spot when
684
+ * omitted)
685
+ */
686
+ buildGeometry(polygons, centerLngLat, useEarcutCache, triangulator) {
687
+ // Pass 1: collect the triangulations and the rings, and count the required array lengths
688
+ const records = [];
689
+ let totalVertices = 0;
690
+ let totalIndices = 0;
691
+ // Subdivide on a grid only while terrain is active or the globe is drawn (on a flat map
692
+ // without terrain it passes through as null). The total cell count of the whole batch is
693
+ // estimated first, and if it exceeds the budget everything is coarsened uniformly. A
694
+ // per-feature cap alone cannot stop a batch with thousands of features (a
695
+ // dataset). The factor is made single for the whole batch (if it varied per feature,
696
+ // adjacent features would ride on different grids and disagree at their shared boundary).
697
+ const terrainStep = this.batchTerrainStep(polygons);
698
+ for (const polygon of polygons) {
699
+ const style = polygon.style;
700
+ // Flatten all rings to build the earcut input (inner rings are treated as holes)
701
+ const { flatCoords, holeIndices, rings } = buildEarcutInput(polygon.coordinates);
702
+ if (rings.length === 0)
703
+ continue;
704
+ // The step actually used for this feature. It is received from the result of
705
+ // subdividing the fill and the same value is used for the outline as well. If the
706
+ // fill were coarsened because the budget ran out while the outline stayed fine, the
707
+ // two would ride on different grids and diverge in a wedge shape.
708
+ let polygonStep = null;
709
+ // 1. Fill
710
+ let fillCoords = null;
711
+ let fillIndices = null;
712
+ if (style.fillOpacity > 0) {
713
+ const indices = this.triangulate(polygon, flatCoords, holeIndices, useEarcutCache, triangulator);
714
+ if (indices && indices.length > 0) {
715
+ // Subdivision points are placed inside the triangles too. Subdividing only the
716
+ // edges still lets the center of a triangle pierce the terrain
717
+ if (terrainStep) {
718
+ const tessellated = tessellateSurfaceFill(this.terrain, polygon.featureId, polygon.partIndex ?? 0, flatCoords, indices, terrainStep);
719
+ polygonStep = tessellated.step;
720
+ fillCoords = tessellated.flatCoords;
721
+ fillIndices = tessellated.indices;
722
+ }
723
+ else {
724
+ fillCoords = flatCoords;
725
+ fillIndices = indices;
726
+ }
727
+ totalVertices += fillCoords.length / 2;
728
+ totalIndices += fillIndices.length;
729
+ }
730
+ }
731
+ // 2. Stroke (the outer ring and each inner ring are drawn as their own closed path)
732
+ // A width of 0 means "no outline". A negative width is the fixed-width convention,
733
+ // so it is included among the things to draw.
734
+ let strokeRings = null;
735
+ if (style.strokeOpacity > 0 && style.strokeWidth !== 0) {
736
+ // When no fill was built (a polygon without a fill) the step cannot be received,
737
+ // so only in that case it is derived from the size of the feature
738
+ const ringStep = polygonStep ?? (terrainStep ? polygonTessellationStep(terrainStep, flatCoords) : null);
739
+ const strokeSource = ringStep ? tessellateRings(rings, ringStep) : rings;
740
+ const usable = strokeSource.filter((ring) => ring.length >= 3);
741
+ if (usable.length > 0) {
742
+ strokeRings = usable;
743
+ for (const ring of usable) {
744
+ // 4 vertices and 6 indices per segment
745
+ totalVertices += ring.length * 4;
746
+ totalIndices += ring.length * 6;
747
+ }
748
+ }
749
+ }
750
+ if (!fillIndices && !strokeRings)
751
+ continue;
752
+ records.push({
753
+ fillCoords,
754
+ fillIndices,
755
+ strokeRings,
756
+ style,
757
+ createdZoom: polygon.createdZoom,
758
+ });
759
+ }
760
+ // Pass 2: write directly into the typed arrays
761
+ const vertexData = new Float32Array(totalVertices * VERTEX_STRIDE);
762
+ const indexData = new Uint32Array(totalIndices);
763
+ // Convert CSS pixels into physical pixels
764
+ //
765
+ // The ratio is chosen by the sign of the width (the "two ratios" of
766
+ // shared/utils/pixel-ratio.ts).
767
+ // Negative value = a width fixed in screen pixels, so the ratio that multiplies
768
+ // renderScale is used.
769
+ // Positive value = a width that the shader scales by 2^(u_zoom - createdZoom), so the
770
+ // ratio that does not multiply renderScale is used (multiplying it would apply the
771
+ // shrinking twice).
772
+ const screenDpr = resolvePixelRatio(this.pixelRatio);
773
+ const contentDpr = resolveContentPixelRatio(this.pixelRatio);
774
+ let base = 0;
775
+ let indexOffset = 0;
776
+ for (const record of records) {
777
+ const style = record.style;
778
+ // 1. Fill: each point of the rings becomes a vertex as is, and the earcut indices
779
+ // are shifted
780
+ if (record.fillCoords && record.fillIndices) {
781
+ const fillColor = [
782
+ style.fillColor[0],
783
+ style.fillColor[1],
784
+ style.fillColor[2],
785
+ style.fillColor[3] * style.fillOpacity,
786
+ ];
787
+ const pointCount = record.fillCoords.length / 2;
788
+ for (let i = 0; i < pointCount; i++) {
789
+ // Compute the offset from the center at 64-bit precision
790
+ const offset = calculateLngLatOffset([record.fillCoords[i * 2], record.fillCoords[i * 2 + 1]], centerLngLat);
791
+ const at = (base + i) * VERTEX_STRIDE;
792
+ vertexData[at] = offset[0];
793
+ vertexData[at + 1] = offset[1];
794
+ vertexData[at + 2] = fillColor[0];
795
+ vertexData[at + 3] = fillColor[1];
796
+ vertexData[at + 4] = fillColor[2];
797
+ vertexData[at + 5] = fillColor[3];
798
+ // type = fill(0), and prev/next/side/extra stay 0
799
+ }
800
+ for (let i = 0; i < record.fillIndices.length; i++) {
801
+ indexData[indexOffset + i] = record.fillIndices[i] + base;
802
+ }
803
+ base += pointCount;
804
+ indexOffset += record.fillIndices.length;
805
+ }
806
+ // 2. Stroke: a quad per edge (4 vertices, 2 triangles)
807
+ if (record.strokeRings) {
808
+ const strokeColor = [
809
+ style.strokeColor[0],
810
+ style.strokeColor[1],
811
+ style.strokeColor[2],
812
+ style.strokeColor[3] * style.strokeOpacity,
813
+ ];
814
+ const strokeWidth = style.strokeWidth * (style.strokeWidth < 0 ? screenDpr : contentDpr);
815
+ for (const ring of record.strokeRings) {
816
+ const n = ring.length;
817
+ for (let i = 0; i < n; i++) {
818
+ const curr = ring[i];
819
+ const next = ring[(i + 1) % n];
820
+ const prev = ring[(i - 1 + n) % n];
821
+ const nextNext = ring[(i + 2) % n];
822
+ // The left and right of the start point (curr)
823
+ this.writeStrokeVertex(vertexData, base * VERTEX_STRIDE, curr, strokeColor, prev, next, 1, 0, strokeWidth, record.createdZoom, centerLngLat);
824
+ this.writeStrokeVertex(vertexData, (base + 1) * VERTEX_STRIDE, curr, strokeColor, prev, next, -1, 0, strokeWidth, record.createdZoom, centerLngLat);
825
+ // The left and right of the end point (next)
826
+ this.writeStrokeVertex(vertexData, (base + 2) * VERTEX_STRIDE, next, strokeColor, curr, nextNext, 1, 1, strokeWidth, record.createdZoom, centerLngLat);
827
+ this.writeStrokeVertex(vertexData, (base + 3) * VERTEX_STRIDE, next, strokeColor, curr, nextNext, -1, 1, strokeWidth, record.createdZoom, centerLngLat);
828
+ // Triangle 1: start left, start right, end left / Triangle 2: end left, start
829
+ // right, end right
830
+ indexData[indexOffset] = base;
831
+ indexData[indexOffset + 1] = base + 1;
832
+ indexData[indexOffset + 2] = base + 2;
833
+ indexData[indexOffset + 3] = base + 2;
834
+ indexData[indexOffset + 4] = base + 1;
835
+ indexData[indexOffset + 5] = base + 3;
836
+ base += 4;
837
+ indexOffset += 6;
838
+ }
839
+ }
840
+ }
841
+ }
842
+ return { vertexData, indexData };
843
+ }
844
+ /**
845
+ * Triangulates a polygon (making use of the cache)
846
+ *
847
+ * When a supplier is injected, the work is delegated to it. While the triangulation has
848
+ * not finished yet, null is returned and the fill of that polygon is omitted (the
849
+ * outline is still drawn).
850
+ */
851
+ triangulate(polygon, flatCoords, holeIndices, useEarcutCache, triangulator) {
852
+ if (triangulator) {
853
+ return triangulator.triangulate({
854
+ featureId: polygon.featureId,
855
+ partIndex: polygon.partIndex ?? 0,
856
+ flatCoords,
857
+ holeIndices,
858
+ });
859
+ }
860
+ if (useEarcutCache && polygon.featureId) {
861
+ // Try to get it from the cache
862
+ const partIndex = polygon.partIndex ?? 0;
863
+ const cached = this.earcutCache.get(polygon.featureId, partIndex);
864
+ if (cached)
865
+ return cached;
866
+ const indices = earcut(flatCoords, holeIndices);
867
+ this.earcutCache.set(polygon.featureId, indices, partIndex);
868
+ return indices;
869
+ }
870
+ // When there is no featureId, run it without the cache
871
+ return earcut(flatCoords, holeIndices);
872
+ }
873
+ /**
874
+ * Writes a stroke vertex directly into the vertex array (relative coordinates)
875
+ */
876
+ writeStrokeVertex(target, at, pos, color, prev, next, side, t, strokeWidth, createdZoom, centerLngLat) {
877
+ // Compute the offset from the center at 64-bit precision
878
+ const posOffset = calculateLngLatOffset(pos, centerLngLat);
879
+ const prevOffset = calculateLngLatOffset(prev, centerLngLat);
880
+ const nextOffset = calculateLngLatOffset(next, centerLngLat);
881
+ target[at] = posOffset[0];
882
+ target[at + 1] = posOffset[1];
883
+ target[at + 2] = color[0];
884
+ target[at + 3] = color[1];
885
+ target[at + 4] = color[2];
886
+ target[at + 5] = color[3];
887
+ target[at + 6] = 1; // type = stroke
888
+ target[at + 7] = prevOffset[0];
889
+ target[at + 8] = prevOffset[1];
890
+ target[at + 9] = nextOffset[0];
891
+ target[at + 10] = nextOffset[1];
892
+ target[at + 11] = side;
893
+ target[at + 12] = t;
894
+ target[at + 13] = strokeWidth;
895
+ target[at + 14] = createdZoom;
896
+ }
897
+ /**
898
+ * Disposes of the resources
899
+ */
900
+ dispose() {
901
+ const gl = this.gl;
902
+ if (this.program) {
903
+ gl.deleteProgram(this.program);
904
+ this.program = null;
905
+ }
906
+ if (this.vertexBuffer) {
907
+ gl.deleteBuffer(this.vertexBuffer);
908
+ this.vertexBuffer = null;
909
+ }
910
+ if (this.indexBuffer) {
911
+ gl.deleteBuffer(this.indexBuffer);
912
+ this.indexBuffer = null;
913
+ }
914
+ if (this.vao) {
915
+ gl.deleteVertexArray(this.vao);
916
+ this.vao = null;
917
+ }
918
+ }
919
+ }