@tangram.gl/tangram-renderer 0.0.0-stage → 0.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 (321) hide show
  1. package/README.md +59 -2
  2. package/dist/core.js +36923 -0
  3. package/dist/core.js.map +6 -0
  4. package/dist/index.js +32 -0
  5. package/dist/loaders-gl-worker.js +82 -0
  6. package/dist/loaders-gl-worker.js.map +6 -0
  7. package/dist/map-logic.js +2 -0
  8. package/dist/map-logic.js.map +6 -0
  9. package/dist/projected-basemaps-worker.js +3 -0
  10. package/dist/projected-basemaps-worker.js.map +6 -0
  11. package/dist/shader-modules.js +141 -0
  12. package/dist/shader-modules.js.map +6 -0
  13. package/dist/style-schema.js +126 -0
  14. package/dist/style-schema.js.map +6 -0
  15. package/dist/tangram-style.schema.json +882 -0
  16. package/dist/tangram.debug.mjs +37139 -0
  17. package/dist/tangram.debug.mjs.map +6 -0
  18. package/dist/tangram.min.mjs +4950 -0
  19. package/dist/types/builders/earcut.d.ts +15 -0
  20. package/dist/types/core.d.ts +29 -0
  21. package/dist/types/gl/constants.d.ts +2 -0
  22. package/dist/types/gl/globe_mesh.d.ts +48 -0
  23. package/dist/types/gl/glsl.d.ts +17 -0
  24. package/dist/types/gl/vertex-constants.d.ts +4 -0
  25. package/dist/types/gl/vertex-types.d.ts +34 -0
  26. package/dist/types/gl/vertex_data.d.ts +32 -0
  27. package/dist/types/gl/vertex_elements.d.ts +8 -0
  28. package/dist/types/gl/vertex_layout.d.ts +32 -0
  29. package/dist/types/glsl.d.ts +14 -0
  30. package/dist/types/gpu/luma_device_renderer.d.ts +66 -0
  31. package/dist/types/gpu/resource_lifecycle.d.ts +4 -0
  32. package/dist/types/gpu/tangram_gpu_backend.d.ts +151 -0
  33. package/dist/types/index.d.ts +155 -0
  34. package/dist/types/lights/light-definitions.d.ts +121 -0
  35. package/dist/types/map-logic/draped-terrain-bounds.d.ts +41 -0
  36. package/dist/types/map-logic/globe-terrain-preparation.d.ts +85 -0
  37. package/dist/types/map-logic/globe-terrain.d.ts +54 -0
  38. package/dist/types/map-logic/index.d.ts +33 -0
  39. package/dist/types/map-logic/label-identity.d.ts +22 -0
  40. package/dist/types/map-logic/label-placement.d.ts +32 -0
  41. package/dist/types/map-logic/screen-bounds.d.ts +15 -0
  42. package/dist/types/map-logic/terrain-data.d.ts +55 -0
  43. package/dist/types/map-logic/terrain-error.d.ts +51 -0
  44. package/dist/types/map-logic/terrain-ground-topology.d.ts +26 -0
  45. package/dist/types/map-logic/terrain-height-field.d.ts +59 -0
  46. package/dist/types/map-logic/terrain-navigation.d.ts +27 -0
  47. package/dist/types/map-logic/terrain-neighborhood.d.ts +5 -0
  48. package/dist/types/map-logic/terrain-query.d.ts +33 -0
  49. package/dist/types/map-logic/terrain-resource-budget.d.ts +51 -0
  50. package/dist/types/map-logic/terrain-transition-topology.d.ts +23 -0
  51. package/dist/types/map-logic/tile-build-queue.d.ts +51 -0
  52. package/dist/types/map-logic/tile-cache-policy.d.ts +46 -0
  53. package/dist/types/map-logic/tile-residency.d.ts +17 -0
  54. package/dist/types/map-logic/triangle-query-index.d.ts +87 -0
  55. package/dist/types/procedures/js-yaml.d.ts +15 -0
  56. package/dist/types/procedures/mesh-projector.d.ts +107 -0
  57. package/dist/types/procedures/mvt-dependencies.d.ts +20 -0
  58. package/dist/types/procedures/projected-coordinate-transform.d.ts +27 -0
  59. package/dist/types/procedures/projection-batch-executor.d.ts +53 -0
  60. package/dist/types/procedures/scene-yaml-legacy.d.ts +6 -0
  61. package/dist/types/procedures/terrain-draping.d.ts +165 -0
  62. package/dist/types/procedures/terrain-globe.d.ts +6 -0
  63. package/dist/types/procedures/terrain-styled-topology.d.ts +34 -0
  64. package/dist/types/procedures/web-mercator-legacy.d.ts +4 -0
  65. package/dist/types/procedures/web-mercator-math.d.ts +4 -0
  66. package/dist/types/scene/globals.d.ts +11 -0
  67. package/dist/types/scene/ground_footprint.d.ts +16 -0
  68. package/dist/types/scene/host_frame.d.ts +54 -0
  69. package/dist/types/scene/projection_math.d.ts +52 -0
  70. package/dist/types/scene/scene-resource-types.d.ts +177 -0
  71. package/dist/types/scene/scene_bundle.d.ts +69 -0
  72. package/dist/types/scene/visibility_adapter.d.ts +106 -0
  73. package/dist/types/selection/draped-terrain-surface.d.ts +78 -0
  74. package/dist/types/selection/terrain_surface.d.ts +149 -0
  75. package/dist/types/shader-modules/globe-horizon.d.ts +15 -0
  76. package/dist/types/shader-modules/height-decode.d.ts +13 -0
  77. package/dist/types/shader-modules/hillshade.d.ts +13 -0
  78. package/dist/types/shader-modules/index.d.ts +6 -0
  79. package/dist/types/shader-modules/planar.d.ts +12 -0
  80. package/dist/types/shader-modules/sphere-map.d.ts +13 -0
  81. package/dist/types/shader-modules/triplanar.d.ts +15 -0
  82. package/dist/types/sources/decoded_tile_store.d.ts +95 -0
  83. package/dist/types/sources/tile_source_metadata.d.ts +32 -0
  84. package/dist/types/styles/text/fontfaceobserver.d.ts +10 -0
  85. package/dist/types/tile/tile_id.d.ts +37 -0
  86. package/dist/types/tile/tile_traversal_adapter.d.ts +63 -0
  87. package/dist/types/types.d.ts +293 -0
  88. package/dist/types/utils/geo.d.ts +57 -0
  89. package/dist/types/utils/hash.d.ts +1 -0
  90. package/dist/types/utils/log.d.ts +27 -0
  91. package/dist/types/utils/props.d.ts +6 -0
  92. package/dist/types/utils/subscribe.d.ts +10 -0
  93. package/dist/types/utils/thread.d.ts +6 -0
  94. package/dist/types/utils/urls.d.ts +26 -0
  95. package/dist/types/utils/utils.d.ts +26 -0
  96. package/dist/types/utils/version.d.ts +2 -0
  97. package/dist/types/utils/worker-types.d.ts +68 -0
  98. package/dist/types/utils/worker_broker.d.ts +3 -0
  99. package/package.json +103 -3
  100. package/src/builders/common.ts +41 -0
  101. package/src/builders/earcut.d.ts +15 -0
  102. package/src/builders/geometry-types.ts +60 -0
  103. package/src/builders/points.ts +115 -0
  104. package/src/builders/polygons.ts +225 -0
  105. package/src/builders/polylines.ts +682 -0
  106. package/src/builders/wireframe.ts +31 -0
  107. package/src/core.d.ts +29 -0
  108. package/src/core.ts +33 -0
  109. package/src/experimental/loaders-gl-worker.ts +19 -0
  110. package/src/experimental/projected-basemaps-worker.ts +13 -0
  111. package/src/experimental/projected-mesh-cache.ts +137 -0
  112. package/src/experimental/projected-mesh-domain.ts +110 -0
  113. package/src/experimental/projected-mesh-refinement.ts +193 -0
  114. package/src/experimental/projected-mesh.ts +399 -0
  115. package/src/experimental/projected-normal.ts +26 -0
  116. package/src/experimental/projected-symbol-mesh.ts +74 -0
  117. package/src/gl/constants.ts +18 -0
  118. package/src/gl/context.ts +103 -0
  119. package/src/gl/extensions.ts +30 -0
  120. package/src/gl/globe_mesh.ts +285 -0
  121. package/src/gl/glsl.ts +257 -0
  122. package/src/gl/mesh-types.ts +56 -0
  123. package/src/gl/render_state.ts +111 -0
  124. package/src/gl/shader_program.ts +1310 -0
  125. package/src/gl/texture.ts +814 -0
  126. package/src/gl/uniform_buffer.ts +340 -0
  127. package/src/gl/vao.ts +154 -0
  128. package/src/gl/vbo_mesh.ts +349 -0
  129. package/src/gl/vertex-constants.ts +19 -0
  130. package/src/gl/vertex-types.ts +35 -0
  131. package/src/gl/vertex_data.ts +126 -0
  132. package/src/gl/vertex_elements.ts +54 -0
  133. package/src/gl/vertex_layout.ts +241 -0
  134. package/src/glsl.d.ts +14 -0
  135. package/src/gpu/luma_device_renderer.ts +579 -0
  136. package/src/gpu/pixel_readback.ts +51 -0
  137. package/src/gpu/resource_lifecycle.ts +32 -0
  138. package/src/gpu/tangram_gpu_backend.ts +195 -0
  139. package/src/index.d.ts +155 -0
  140. package/src/index.ts +105 -0
  141. package/src/labels/collision-types.ts +94 -0
  142. package/src/labels/collision.ts +273 -0
  143. package/src/labels/collision_grid.ts +61 -0
  144. package/src/labels/intersect.ts +30 -0
  145. package/src/labels/label-types.ts +91 -0
  146. package/src/labels/label.ts +207 -0
  147. package/src/labels/label_line.ts +801 -0
  148. package/src/labels/label_point.ts +131 -0
  149. package/src/labels/main-pass-types.ts +73 -0
  150. package/src/labels/main_pass.ts +221 -0
  151. package/src/labels/point_anchor.ts +100 -0
  152. package/src/labels/point_placement.ts +150 -0
  153. package/src/labels/projected-pass.ts +259 -0
  154. package/src/labels/repeat_group.ts +72 -0
  155. package/src/lights/ambient_light.glsl +18 -0
  156. package/src/lights/directional_light.glsl +39 -0
  157. package/src/lights/geographic-lights.ts +21 -0
  158. package/src/lights/light-definitions.ts +285 -0
  159. package/src/lights/light.ts +590 -0
  160. package/src/lights/lighting-uniforms.ts +80 -0
  161. package/src/lights/lighting-wgsl.ts +116 -0
  162. package/src/lights/material.glsl +237 -0
  163. package/src/lights/material.ts +145 -0
  164. package/src/lights/native-falloff.ts +37 -0
  165. package/src/lights/point_light.glsl +96 -0
  166. package/src/lights/spot_light.glsl +111 -0
  167. package/src/map-logic/draped-terrain-bounds.ts +71 -0
  168. package/src/map-logic/globe-terrain-preparation.ts +217 -0
  169. package/src/map-logic/globe-terrain.ts +296 -0
  170. package/src/map-logic/index.ts +37 -0
  171. package/src/map-logic/label-identity.ts +36 -0
  172. package/src/map-logic/label-placement.ts +117 -0
  173. package/src/map-logic/screen-bounds.ts +34 -0
  174. package/src/map-logic/terrain-data.ts +107 -0
  175. package/src/map-logic/terrain-error.ts +134 -0
  176. package/src/map-logic/terrain-ground-topology.ts +164 -0
  177. package/src/map-logic/terrain-height-field.ts +254 -0
  178. package/src/map-logic/terrain-navigation.ts +50 -0
  179. package/src/map-logic/terrain-neighborhood.ts +43 -0
  180. package/src/map-logic/terrain-query.ts +51 -0
  181. package/src/map-logic/terrain-resource-budget.ts +124 -0
  182. package/src/map-logic/terrain-transition-topology.ts +164 -0
  183. package/src/map-logic/tile-build-queue.ts +110 -0
  184. package/src/map-logic/tile-cache-policy.ts +89 -0
  185. package/src/map-logic/tile-residency.ts +50 -0
  186. package/src/map-logic/triangle-query-index.ts +265 -0
  187. package/src/procedures/js-yaml.d.ts +15 -0
  188. package/src/procedures/mesh-projector.ts +191 -0
  189. package/src/procedures/mlt-loaders.ts +55 -0
  190. package/src/procedures/mvt-dependencies.d.ts +20 -0
  191. package/src/procedures/mvt-legacy.ts +150 -0
  192. package/src/procedures/mvt-loaders.ts +53 -0
  193. package/src/procedures/mvt-parser.ts +48 -0
  194. package/src/procedures/mvt-properties.ts +36 -0
  195. package/src/procedures/mvt-tile-provider.ts +72 -0
  196. package/src/procedures/pmtiles-loader.ts +75 -0
  197. package/src/procedures/projected-coordinate-transform.ts +79 -0
  198. package/src/procedures/projection-batch-executor.ts +140 -0
  199. package/src/procedures/scene-yaml-legacy.ts +16 -0
  200. package/src/procedures/scene-yaml-loaders.ts +10 -0
  201. package/src/procedures/terrain-draping.ts +713 -0
  202. package/src/procedures/terrain-globe.ts +32 -0
  203. package/src/procedures/terrain-styled-topology.ts +184 -0
  204. package/src/procedures/web-mercator-legacy.ts +24 -0
  205. package/src/procedures/web-mercator-math.ts +50 -0
  206. package/src/scene/camera.ts +298 -0
  207. package/src/scene/camera_base.ts +116 -0
  208. package/src/scene/classic_scene.ts +20 -0
  209. package/src/scene/external_camera.ts +101 -0
  210. package/src/scene/globals.ts +120 -0
  211. package/src/scene/ground_footprint.ts +139 -0
  212. package/src/scene/host_frame.ts +326 -0
  213. package/src/scene/projected_tile_lod.ts +125 -0
  214. package/src/scene/projection_math.ts +142 -0
  215. package/src/scene/projection_shaders.ts +183 -0
  216. package/src/scene/renderer.ts +516 -0
  217. package/src/scene/scene-resource-types.ts +174 -0
  218. package/src/scene/scene.ts +2378 -0
  219. package/src/scene/scene_bundle.ts +304 -0
  220. package/src/scene/scene_debug.ts +129 -0
  221. package/src/scene/scene_loader.ts +402 -0
  222. package/src/scene/scene_worker.ts +528 -0
  223. package/src/scene/view.ts +683 -0
  224. package/src/scene/visibility_adapter.ts +319 -0
  225. package/src/scene/worker_url.ts +15 -0
  226. package/src/selection/draped-terrain-surface.ts +377 -0
  227. package/src/selection/selection-types.ts +79 -0
  228. package/src/selection/selection.ts +542 -0
  229. package/src/selection/selection_fragment.glsl +18 -0
  230. package/src/selection/selection_globals.glsl +9 -0
  231. package/src/selection/selection_pixels.ts +59 -0
  232. package/src/selection/selection_vertex.glsl +15 -0
  233. package/src/selection/terrain_surface.ts +298 -0
  234. package/src/shader-modules/globe-horizon.ts +52 -0
  235. package/src/shader-modules/height-decode.ts +41 -0
  236. package/src/shader-modules/hillshade.ts +70 -0
  237. package/src/shader-modules/index.ts +10 -0
  238. package/src/shader-modules/planar.ts +24 -0
  239. package/src/shader-modules/sphere-map.ts +38 -0
  240. package/src/shader-modules/triplanar.ts +45 -0
  241. package/src/sources/aligned_tile_source.ts +122 -0
  242. package/src/sources/data_source.ts +655 -0
  243. package/src/sources/decoded_tile_store.ts +245 -0
  244. package/src/sources/geojson.ts +300 -0
  245. package/src/sources/mvt.ts +247 -0
  246. package/src/sources/raster.ts +341 -0
  247. package/src/sources/shared_tile_source_adapter.ts +117 -0
  248. package/src/sources/sources.ts +10 -0
  249. package/src/sources/tile_source_adapter.ts +84 -0
  250. package/src/sources/tile_source_metadata.ts +65 -0
  251. package/src/sources/tile_source_state.ts +112 -0
  252. package/src/sources/topojson.ts +90 -0
  253. package/src/styles/feature_annotations.ts +16 -0
  254. package/src/styles/filter.ts +190 -0
  255. package/src/styles/geometry-style-types.ts +209 -0
  256. package/src/styles/globe_visibility_wgsl.ts +22 -0
  257. package/src/styles/layer-types.ts +45 -0
  258. package/src/styles/layer.ts +586 -0
  259. package/src/styles/lines/dasharray.ts +49 -0
  260. package/src/styles/lines/lines.ts +707 -0
  261. package/src/styles/lines/lines_wgsl.ts +224 -0
  262. package/src/styles/points/point-runtime-types.ts +125 -0
  263. package/src/styles/points/points.ts +1079 -0
  264. package/src/styles/points/points_fragment.glsl +126 -0
  265. package/src/styles/points/points_vertex.glsl +230 -0
  266. package/src/styles/points/points_wgsl.ts +189 -0
  267. package/src/styles/polygons/polygons.ts +268 -0
  268. package/src/styles/polygons/polygons_fragment.glsl +173 -0
  269. package/src/styles/polygons/polygons_vertex.glsl +213 -0
  270. package/src/styles/polygons/polygons_wgsl.ts +127 -0
  271. package/src/styles/property-types.ts +125 -0
  272. package/src/styles/raster/raster.ts +33 -0
  273. package/src/styles/raster/raster_globals.glsl +46 -0
  274. package/src/styles/style-mixing-types.ts +101 -0
  275. package/src/styles/style-runtime-types.ts +220 -0
  276. package/src/styles/style-schema.ts +133 -0
  277. package/src/styles/style.ts +1033 -0
  278. package/src/styles/style_globals.glsl +69 -0
  279. package/src/styles/style_manager.ts +464 -0
  280. package/src/styles/style_parser.ts +620 -0
  281. package/src/styles/text/font_manager.ts +180 -0
  282. package/src/styles/text/fontfaceobserver.d.ts +10 -0
  283. package/src/styles/text/text-types.ts +220 -0
  284. package/src/styles/text/text.ts +378 -0
  285. package/src/styles/text/text_canvas.ts +773 -0
  286. package/src/styles/text/text_labels.ts +436 -0
  287. package/src/styles/text/text_segments.ts +142 -0
  288. package/src/styles/text/text_settings.ts +228 -0
  289. package/src/styles/text/text_wgsl.ts +159 -0
  290. package/src/styles/text/text_wrap.ts +194 -0
  291. package/src/tile/globe_tile_preload.ts +40 -0
  292. package/src/tile/tangram_tileset_2d.ts +108 -0
  293. package/src/tile/tile-build-types.ts +155 -0
  294. package/src/tile/tile.ts +807 -0
  295. package/src/tile/tile_id.ts +172 -0
  296. package/src/tile/tile_manager.ts +889 -0
  297. package/src/tile/tile_pyramid.ts +119 -0
  298. package/src/tile/tile_resource_cache.ts +91 -0
  299. package/src/tile/tile_traversal_adapter.ts +132 -0
  300. package/src/types.ts +332 -0
  301. package/src/utils/debounce.ts +17 -0
  302. package/src/utils/debug_settings.ts +43 -0
  303. package/src/utils/errors.ts +12 -0
  304. package/src/utils/functions.ts +95 -0
  305. package/src/utils/geo.ts +364 -0
  306. package/src/utils/hash.ts +14 -0
  307. package/src/utils/log.ts +108 -0
  308. package/src/utils/media_capture.ts +193 -0
  309. package/src/utils/merge.ts +44 -0
  310. package/src/utils/obb.ts +134 -0
  311. package/src/utils/props.ts +43 -0
  312. package/src/utils/slice.ts +14 -0
  313. package/src/utils/subscribe.ts +58 -0
  314. package/src/utils/task.ts +154 -0
  315. package/src/utils/thread.ts +26 -0
  316. package/src/utils/urls.ts +223 -0
  317. package/src/utils/utils.ts +310 -0
  318. package/src/utils/vector.ts +197 -0
  319. package/src/utils/version.ts +8 -0
  320. package/src/utils/worker-types.ts +79 -0
  321. package/src/utils/worker_broker.ts +523 -0
@@ -0,0 +1,682 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+ // Copyright (c) 2026 vis.gl contributors
5
+
6
+ // Geometry building functions
7
+
8
+ import type {GeometryLine, GeometryCoordinate, GeometryVertexData, PolylineStyle, PolylineVertexIndices, PolylineBuildContext} from './geometry-types';
9
+ import Vector from '../utils/vector';
10
+ import Geo from '../utils/geo';
11
+ import {outsideTile, isCoordOutsideTile} from './common';
12
+
13
+ const zero_vec2 = [0, 0];
14
+
15
+ // Build tessellated triangles for a polyline
16
+ const CAP_TYPE = {
17
+ butt: 0,
18
+ square: 1,
19
+ round: 2
20
+ };
21
+
22
+ const JOIN_TYPE = {
23
+ miter: 0,
24
+ bevel: 1,
25
+ round: 2
26
+ };
27
+
28
+ const DEFAULT_MITER_LIMIT = 3;
29
+ const MIN_FAN_WIDTH = 5; // Width of line in tile units to place 1 triangle per fan
30
+ const TEXCOORD_NORMALIZE = 65535; // Scaling factor for UV attribute values
31
+
32
+ // Scaling factor to add precision to line texture V coordinate packed as normalized short
33
+ const V_SCALE_ADJUST = Geo.tile_scale;
34
+ const zero_v = [0, 0], one_v = [1, 0], mid_v = [0.5, 0]; // reusable instances, updated with V coordinate
35
+
36
+ export function buildPolylines (
37
+ lines: GeometryLine[],
38
+ style: PolylineStyle,
39
+ vertex_data: GeometryVertexData,
40
+ vertex_template: number[],
41
+ vindex: PolylineVertexIndices,
42
+ closed_polygon: boolean | undefined,
43
+ remove_tile_edges: boolean | undefined,
44
+ tile_edge_tolerance: number): number {
45
+
46
+ var cap_type = style.cap ? CAP_TYPE[style.cap] : CAP_TYPE.butt;
47
+ var join_type = style.join ? JOIN_TYPE[style.join] : JOIN_TYPE.miter;
48
+
49
+ // Configure miter limit
50
+ if (join_type === JOIN_TYPE.miter) {
51
+ const miter_limit = style.miter_limit || DEFAULT_MITER_LIMIT; // default miter limit
52
+ var miter_len_sq: number | undefined = miter_limit * miter_limit;
53
+ }
54
+
55
+ // Texture Variables
56
+ var v_scale;
57
+ if (vindex.a_texcoord) {
58
+ v_scale = 1 / (style.texcoord_width * V_SCALE_ADJUST); // scales line texture as a ratio of the line's width
59
+ }
60
+
61
+ // Values that are constant for each line and are passed to helper functions
62
+ var context: PolylineBuildContext = {
63
+ closed_polygon,
64
+ remove_tile_edges,
65
+ tile_edge_tolerance,
66
+ miter_len_sq,
67
+ join_type,
68
+ cap_type,
69
+ vertex_data,
70
+ vertex_template,
71
+ half_width: style.width / 2,
72
+ extrude_index: vindex.a_extrude,
73
+ offset_index: vindex.a_offset,
74
+ v_scale,
75
+ texcoord_index: vindex.a_texcoord,
76
+ texcoord_width: style.texcoord_width,
77
+ offset: style.offset,
78
+ projected_normals_index: vindex.a_projected_normals,
79
+ projected_widths_index: vindex.a_projected_widths,
80
+ geom_count: 0
81
+ };
82
+
83
+ // Process lines
84
+ for (let i = 0; i < lines.length; i++) {
85
+ buildPolyline(lines[i], context);
86
+ }
87
+
88
+ // Process extra lines (which are created above if lines need to be mutated for easier processing)
89
+ if (context.extra_lines) {
90
+ for (let i = 0; i < context.extra_lines.length; i++) {
91
+ buildPolyline(context.extra_lines[i], context);
92
+ }
93
+ }
94
+
95
+ return context.geom_count;
96
+ }
97
+
98
+ function buildPolyline(line: GeometryLine, context: PolylineBuildContext): void {
99
+ // Skip if line is not valid
100
+ if (line.length < 2) {
101
+ return;
102
+ }
103
+
104
+ var coordCurr: GeometryCoordinate, coordNext: GeometryCoordinate, normPrev: number[], normNext: number[];
105
+ var {join_type, cap_type, closed_polygon, remove_tile_edges, tile_edge_tolerance, v_scale, miter_len_sq} = context;
106
+ var has_texcoord = (context.texcoord_index != null);
107
+ var v = 0; // Texture v-coordinate
108
+
109
+ // Loop backwards through line to a tile boundary if found
110
+ // since you need to draw lines that are only partially inside the tile,
111
+ // so we start at the first index where it is safe to loop through to the last index within the tile
112
+ if (closed_polygon && join_type === JOIN_TYPE.miter) {
113
+ var boundaryIndex = getTileBoundaryIndex(line);
114
+ if (boundaryIndex !== 0) {
115
+ // create new line that is a cyclic permutation of the original
116
+ var permutedLine = permuteLine(line, boundaryIndex);
117
+ context.extra_lines = context.extra_lines || [];
118
+ context.extra_lines.push(permutedLine);
119
+ return;
120
+ }
121
+ }
122
+
123
+ var index_start = 0;
124
+ var index_end = line.length - 1;
125
+ var ignored_indices_count = 0;
126
+
127
+ // FIRST POINT
128
+ // loop through beginning points if duplicates
129
+ coordCurr = line[index_start];
130
+ coordNext = line[index_start + 1];
131
+ while (Vector.isEqual(coordCurr, coordNext)) {
132
+ index_start++;
133
+ coordCurr = coordNext;
134
+ coordNext = line[index_start + 1];
135
+ ignored_indices_count++;
136
+ if (index_start === line.length - 1) {
137
+ return;
138
+ }
139
+ }
140
+
141
+ // loop through ending points to check for duplicates
142
+ while (Vector.isEqual(line[index_end], line[index_end - 1])) {
143
+ index_end--;
144
+ ignored_indices_count++;
145
+ if (index_end === 0) {
146
+ return;
147
+ }
148
+ }
149
+
150
+ if (line.length < 2 + ignored_indices_count) {
151
+ return;
152
+ }
153
+
154
+ normNext = Vector.normalize(Vector.perp(coordCurr, coordNext));
155
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normNext, ...normNext];
156
+
157
+ // Skip tile boundary lines and append a new line if needed
158
+ if (remove_tile_edges && outsideTile(coordCurr, coordNext, tile_edge_tolerance)) {
159
+ var nonBoundarySegment = getNextNonBoundarySegment(line, index_start, tile_edge_tolerance);
160
+ if (nonBoundarySegment) {
161
+ context.extra_lines = context.extra_lines || [];
162
+ context.extra_lines.push(nonBoundarySegment);
163
+ }
164
+ return;
165
+ }
166
+
167
+ if (closed_polygon){
168
+ // Begin the polygon with a join (connecting the first and last segments)
169
+ normPrev = Vector.normalize(Vector.perp(line[index_end - 1], coordCurr));
170
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normPrev, ...normNext];
171
+ startPolygon(coordCurr, normPrev, normNext, join_type, context);
172
+ }
173
+ else {
174
+ // If line begins at edge, don't add a cap
175
+ if (!isCoordOutsideTile(coordCurr)) {
176
+ addCap(coordCurr, v, normNext, cap_type, true, context);
177
+ if (has_texcoord && cap_type !== CAP_TYPE.butt) {
178
+ v += 0.5 * v_scale! * context.texcoord_width;
179
+ }
180
+ }
181
+
182
+ // Add first pair of points for the line strip
183
+ addVertex(coordCurr, normNext, normNext, 1, v, context, 1);
184
+ addVertex(coordCurr, normNext, normNext, 0, v, context, -1);
185
+ }
186
+
187
+ // INTERMEDIARY POINTS
188
+ if (has_texcoord) {
189
+ v += v_scale! * Vector.length(Vector.sub(coordNext, coordCurr));
190
+ }
191
+
192
+ for (var i = index_start + 1; i < index_end; i++) {
193
+ var currIndex = i;
194
+ var nextIndex = i + 1;
195
+ coordCurr = line[currIndex];
196
+ coordNext = line[nextIndex];
197
+
198
+ // Skip redundant vertices
199
+ if (Vector.isEqual(coordCurr, coordNext)) {
200
+ continue;
201
+ }
202
+
203
+ // Remove tile boundaries
204
+ if (remove_tile_edges && outsideTile(coordCurr, coordNext, tile_edge_tolerance)) {
205
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normNext, ...normNext];
206
+ addVertex(coordCurr, normNext, normNext, 1, v, context, 1);
207
+ addVertex(coordCurr, normNext, normNext, 0, v, context, -1);
208
+
209
+ indexPairs(1, context);
210
+
211
+ var nonBoundaryLines = getNextNonBoundarySegment(line, currIndex + 1, tile_edge_tolerance);
212
+ if (nonBoundaryLines) {
213
+ context.extra_lines = context.extra_lines || [];
214
+ context.extra_lines.push(nonBoundaryLines);
215
+ }
216
+ return;
217
+ }
218
+
219
+ normPrev = normNext;
220
+ normNext = Vector.normalize(Vector.perp(coordCurr, coordNext));
221
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normPrev, ...normNext];
222
+
223
+ // Add join
224
+ if (join_type === JOIN_TYPE.miter) {
225
+ addMiter(v, coordCurr, normPrev, normNext, miter_len_sq!, false, context);
226
+ }
227
+ else {
228
+ addJoin(join_type, v, coordCurr, normPrev, normNext, false, context);
229
+ }
230
+
231
+ if (has_texcoord) {
232
+ v += v_scale! * Vector.length(Vector.sub(coordNext, coordCurr));
233
+ }
234
+ }
235
+
236
+ // LAST POINT
237
+ coordCurr = coordNext;
238
+ normPrev = normNext;
239
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normPrev, ...normPrev];
240
+
241
+ if (closed_polygon) {
242
+ // Close the polygon with a miter joint or butt cap if on a tile boundary
243
+ normNext = Vector.normalize(Vector.perp(coordCurr, line[1]));
244
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normPrev, ...normNext];
245
+ endPolygon(coordCurr, normPrev, normNext, join_type, v, context);
246
+ }
247
+ else {
248
+ // Finish the line strip
249
+ addVertex(coordCurr, normPrev, normNext, 1, v, context, 1);
250
+ addVertex(coordCurr, normPrev, normNext, 0, v, context, -1);
251
+
252
+ indexPairs(1, context);
253
+
254
+ // If line ends at edge, don't add a cap
255
+ if (!isCoordOutsideTile(coordCurr)) {
256
+ addCap(coordCurr, v, normPrev, cap_type, false, context);
257
+ }
258
+ }
259
+
260
+ }
261
+
262
+ function getTileBoundaryIndex(line: GeometryLine): number {
263
+ if (isCoordOutsideTile(line[0])) {
264
+ return 0;
265
+ }
266
+
267
+ for (var backIndex = 0; backIndex < line.length; backIndex++) {
268
+ var coordCurr = line[line.length - 1 - backIndex];
269
+ if (isCoordOutsideTile(coordCurr)) {
270
+ return line.length - 1 - backIndex;
271
+ }
272
+ }
273
+
274
+ return 0;
275
+ }
276
+
277
+ // Iterate through line from startIndex to find a segment not on a tile boundary, if any.
278
+ function getNextNonBoundarySegment (line: GeometryLine, startIndex: number, tolerance: number): GeometryLine | false {
279
+ var endIndex = startIndex;
280
+ while (line[endIndex + 1] && outsideTile(line[endIndex], line[endIndex + 1], tolerance)) {
281
+ endIndex++;
282
+ }
283
+
284
+ // If there is a line segment remaining that is within the tile, push it to the lines array
285
+ return (line.length - endIndex >= 2) ? line.slice(endIndex) : false;
286
+ }
287
+
288
+ // Begin a polygon with a join connecting to the last segment (if valid join-type specified)
289
+ function startPolygon(coordCurr: GeometryCoordinate, normPrev: number[], normNext: number[], join_type: number | undefined, context: PolylineBuildContext): void {
290
+ // If polygon starts on a tile boundary, don't add a join
291
+ if (join_type === undefined || isCoordOutsideTile(coordCurr)) {
292
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normNext, ...normNext];
293
+ addVertex(coordCurr, normNext, normNext, 1, 0, context, 1);
294
+ addVertex(coordCurr, normNext, normNext, 0, 0, context, -1);
295
+ }
296
+ else {
297
+ // If polygon starts within a tile, add a join
298
+ var v = 0;
299
+ if (join_type === JOIN_TYPE.miter) {
300
+ addMiter(v, coordCurr, normPrev, normNext, context.miter_len_sq!, true, context);
301
+ }
302
+ else {
303
+ addJoin(join_type, v, coordCurr, normPrev, normNext, true, context);
304
+ }
305
+ }
306
+ }
307
+
308
+ // End a polygon appropriately
309
+ function endPolygon(coordCurr: GeometryCoordinate, normPrev: number[], normNext: number[], join_type: number, v: number, context: PolylineBuildContext): void {
310
+ // If polygon ends on a tile boundary, don't add a join
311
+ if (isCoordOutsideTile(coordCurr)) {
312
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normPrev, ...normPrev];
313
+ addVertex(coordCurr, normPrev, normPrev, 1, v, context, 1);
314
+ addVertex(coordCurr, normPrev, normPrev, 0, v, context, -1);
315
+ indexPairs(1, context);
316
+ }
317
+ else {
318
+ // If polygon ends within a tile, add Miter or no joint (join added on startPolygon)
319
+ var miterVec = createMiterVec(normPrev, normNext);
320
+
321
+ if (join_type === JOIN_TYPE.miter && Vector.lengthSq(miterVec) > context.miter_len_sq!) {
322
+ join_type = JOIN_TYPE.bevel; // switch to bevel
323
+ }
324
+
325
+ if (join_type === JOIN_TYPE.miter) {
326
+ addVertex(coordCurr, miterVec, normPrev, 1, v, context, 1);
327
+ addVertex(coordCurr, miterVec, normPrev, 0, v, context, -1);
328
+ indexPairs(1, context);
329
+ }
330
+ else {
331
+ if (context.projected_normals_index !== undefined) context.projected_normals = [...normPrev, ...normPrev];
332
+ addVertex(coordCurr, normPrev, normPrev, 1, v, context, 1);
333
+ addVertex(coordCurr, normPrev, normPrev, 0, v, context, -1);
334
+ indexPairs(1, context);
335
+ }
336
+ }
337
+ }
338
+
339
+ function createMiterVec(normPrev: number[], normNext: number[]): number[] {
340
+ var miterVec = Vector.normalize(Vector.add(normPrev, normNext));
341
+ var scale = 2 / (1 + Math.abs(Vector.dot(normPrev, miterVec)));
342
+ return Vector.mult(miterVec, scale * scale);
343
+ }
344
+
345
+ // Add a miter vector or a join if the miter is too sharp
346
+ function addMiter (v: number, coordCurr: GeometryCoordinate, normPrev: number[], normNext: number[], miter_len_sq: number, isBeginning: boolean, context: PolylineBuildContext): void {
347
+ var miterVec = createMiterVec(normPrev, normNext);
348
+
349
+ // Miter limit: if miter join is too sharp, convert to bevel instead
350
+ if (Vector.lengthSq(miterVec) > miter_len_sq) {
351
+ addJoin(JOIN_TYPE.bevel, v, coordCurr, normPrev, normNext, isBeginning, context);
352
+ }
353
+ else {
354
+ addVertex(coordCurr, miterVec, miterVec, 1, v, context, 1);
355
+ addVertex(coordCurr, miterVec, miterVec, 0, v, context, -1);
356
+ if (!isBeginning) {
357
+ indexPairs(1, context);
358
+ }
359
+ }
360
+ }
361
+
362
+ // Add a bevel or round join
363
+ function addJoin(join_type: number, v: number, coordCurr: GeometryCoordinate, normPrev: number[], normNext: number[], isBeginning: boolean, context: PolylineBuildContext): void {
364
+ var miterVec = createMiterVec(normPrev, normNext);
365
+ var isClockwise = (normNext[0] * normPrev[1] - normNext[1] * normPrev[0] > 0);
366
+
367
+ if (context.texcoord_index != null) {
368
+ zero_v[1] = v;
369
+ one_v[1] = v;
370
+ }
371
+
372
+ if (isClockwise){
373
+ addVertex(coordCurr, miterVec, miterVec, 1, v, context, 1);
374
+ addVertex(coordCurr, normPrev, miterVec, 0, v, context, -1);
375
+
376
+ if (!isBeginning) {
377
+ indexPairs(1, context);
378
+ }
379
+
380
+ addFan(coordCurr,
381
+ // extrusion vector of first vertex
382
+ Vector.neg(normPrev),
383
+ // controls extrude distance of pivot vertex
384
+ miterVec,
385
+ // extrusion vector of last vertex
386
+ Vector.neg(normNext),
387
+ // line normal (unused here)
388
+ miterVec,
389
+ // uv coordinates
390
+ zero_v, one_v, zero_v,
391
+ false, (join_type === JOIN_TYPE.bevel), context
392
+ );
393
+
394
+ addVertex(coordCurr, miterVec, miterVec, 1, v, context, 1);
395
+ addVertex(coordCurr, normNext, miterVec, 0, v, context, -1);
396
+ } else {
397
+ addVertex(coordCurr, normPrev, miterVec, 1, v, context, 1);
398
+ addVertex(coordCurr, miterVec, miterVec, 0, v, context, -1);
399
+
400
+ if (!isBeginning) {
401
+ indexPairs(1, context);
402
+ }
403
+
404
+ addFan(coordCurr,
405
+ // extrusion vector of first vertex
406
+ normPrev,
407
+ // extrusion vector of pivot vertex
408
+ Vector.neg(miterVec),
409
+ // extrusion vector of last vertex
410
+ normNext,
411
+ // line normal for offset
412
+ miterVec,
413
+ // uv coordinates
414
+ one_v, zero_v, one_v,
415
+ false, (join_type === JOIN_TYPE.bevel), context
416
+ );
417
+
418
+ addVertex(coordCurr, normNext, miterVec, 1, v, context, 1);
419
+ addVertex(coordCurr, miterVec, miterVec, 0, v, context, -1);
420
+ }
421
+ }
422
+
423
+ // Add indices to vertex_elements
424
+ function indexPairs(num_pairs: number, context: PolylineBuildContext): void {
425
+ var vertex_elements = context.vertex_data.vertex_elements;
426
+ var num_vertices = context.vertex_data.vertex_count;
427
+ var offset = num_vertices - 2 * num_pairs - 2;
428
+
429
+ for (var i = 0; i < num_pairs; i++){
430
+ vertex_elements.push(offset + 2 * i + 2);
431
+ vertex_elements.push(offset + 2 * i + 1);
432
+ vertex_elements.push(offset + 2 * i + 0);
433
+ vertex_elements.push(offset + 2 * i + 2);
434
+ vertex_elements.push(offset + 2 * i + 3);
435
+ vertex_elements.push(offset + 2 * i + 1);
436
+ context.geom_count += 2;
437
+ }
438
+ }
439
+
440
+ function addVertex(position: GeometryCoordinate, extrude: number[], normal: number[], u: number, v: number, context: PolylineBuildContext, flip: number): void {
441
+ var vertex_template = context.vertex_template;
442
+ var vertex_data = context.vertex_data;
443
+
444
+ // set vertex position
445
+ vertex_template[0] = position[0];
446
+ vertex_template[1] = position[1];
447
+
448
+ // set line extrusion vector
449
+ let len = context.half_width * flip;
450
+ vertex_template[context.extrude_index + 0] = extrude[0] * len;
451
+ vertex_template[context.extrude_index + 1] = extrude[1] * len;
452
+
453
+ if (context.projected_normals_index !== undefined && context.projected_normals) {
454
+ for (let component = 0; component < 4; component++) {
455
+ vertex_template[context.projected_normals_index + component] = context.projected_normals[component];
456
+ }
457
+ }
458
+ if (context.projected_widths_index !== undefined) {
459
+ vertex_template[context.projected_widths_index] = context.half_width;
460
+ vertex_template[context.projected_widths_index + 1] = context.offset;
461
+ }
462
+
463
+ // set line offset vector
464
+ if (context.offset) {
465
+ // Nonzero offsets select a packed offset attribute rather than a constant.
466
+ const offsetIndex = context.offset_index as number;
467
+ vertex_template[offsetIndex + 0] = normal[0] * context.offset;
468
+ vertex_template[offsetIndex + 1] = normal[1] * context.offset;
469
+ }
470
+
471
+ // set UVs
472
+ if (context.texcoord_index != null) {
473
+ vertex_template[context.texcoord_index + 0] = u * TEXCOORD_NORMALIZE;
474
+ vertex_template[context.texcoord_index + 1] = v * TEXCOORD_NORMALIZE;
475
+ }
476
+
477
+ vertex_data.addVertex(vertex_template);
478
+ }
479
+
480
+ // Tesselate a fan geometry between points A ----- B
481
+ // using their normals from a center p \ . . /
482
+ // and interpolating their UVs \ p /
483
+ // \./
484
+ // C
485
+ var uvCurr = [0, 0];
486
+
487
+ function addFan (coord: GeometryCoordinate, eA: number[], eC: number[], eB: number[], normal: number[], uvA: number[], uvC: number[], uvB: number[], isCap: boolean, isBevel: boolean, context: PolylineBuildContext): void {
488
+ // eA = extrusion vector of first outer vertex
489
+ // eC = extrusion vector of inner vertex
490
+ // eA, eC, eB = extrusion vectors
491
+ // normal = line normal for calculating cap offsets
492
+ // coord = center point p - vertex connecting two line segments
493
+
494
+ var cross = eA[0] * eB[1] - eA[1] * eB[0];
495
+ var dot = Vector.dot(eA, eB);
496
+
497
+ var angle = Math.atan2(cross, dot);
498
+ while (angle >= Math.PI) {
499
+ angle -= 2*Math.PI;
500
+ }
501
+
502
+ if (isBevel) {
503
+ numTriangles = 1;
504
+ } else {
505
+ // vary number of triangles in fan with angle (based on MIN_FAN_WIDTH)
506
+ var numTriangles = trianglesPerArc(angle, context.half_width);
507
+ if (numTriangles < 1) {
508
+ return;
509
+ }
510
+ }
511
+
512
+ var pivotIndex = context.vertex_data.vertex_count;
513
+ var vertex_elements = context.vertex_data.vertex_elements;
514
+ if (angle < 0) { // cw
515
+ addVertex(coord, eC, normal, uvC[0], uvC[1], context, 1);
516
+ addVertex(coord, eA, normal, uvA[0], uvA[1], context, 1);
517
+ } else { // ccw
518
+ addVertex(coord, eC, normal, uvC[0], uvC[1], context, 1);
519
+ addVertex(coord, eA, normal, uvA[0], uvA[1], context, 1);
520
+ }
521
+
522
+ var blade = eA;
523
+
524
+ var has_texcoord = (context.texcoord_index != null);
525
+ if (has_texcoord) {
526
+ if (isCap){
527
+ var affine_uvCurr = Vector.sub(uvA, uvC);
528
+ }
529
+ else {
530
+ uvCurr = Vector.copy(uvA);
531
+ var uv_delta = Vector.div(Vector.sub(uvB, uvA), numTriangles);
532
+ }
533
+ }
534
+
535
+ var angle_step = angle / numTriangles;
536
+ let flip = ((angle < 0) ? -1 : 1); // if angle < 0, is cw - set 'flip' flag
537
+
538
+ // add outside vertices in reverse order depending on sign of angle
539
+ let v1, v2;
540
+ if (cross > 0) {
541
+ v1 = 2;
542
+ v2 = 1;
543
+ }
544
+ else {
545
+ v1 = 1;
546
+ v2 = 2;
547
+ }
548
+
549
+ for (var i = 0; i < numTriangles; i++) {
550
+ if (i === 0 && angle < 0) {
551
+ // if ccw, flip the extrusion vector so offsets work properly
552
+ blade = Vector.neg(blade);
553
+ }
554
+
555
+ blade = Vector.rot(blade, angle_step);
556
+
557
+ if (has_texcoord) {
558
+ if (isCap){
559
+ // UV textures go "through" the cap
560
+ affine_uvCurr = Vector.rot(affine_uvCurr!, angle_step);
561
+ uvCurr[0] = affine_uvCurr[0] + uvC[0];
562
+ uvCurr[1] = affine_uvCurr[1] * context.texcoord_width * context.v_scale! + uvC[1]; // scale the v-coordinate
563
+ }
564
+ else {
565
+ // UV textures go "around" the join
566
+ uvCurr = Vector.add(uvCurr, uv_delta!);
567
+ }
568
+ }
569
+
570
+ addVertex(coord, blade, normal, uvCurr[0], uvCurr[1], context, flip);
571
+
572
+ vertex_elements.push(pivotIndex + i + v1);
573
+ vertex_elements.push(pivotIndex);
574
+ vertex_elements.push(pivotIndex + i + v2);
575
+ }
576
+ }
577
+
578
+ // Function to add the vertices needed for line caps,
579
+ // because to re-use the buffers they need to be at the end
580
+ function addCap (coord: GeometryCoordinate, v: number, normal: number[], type: number, isBeginning: boolean, context: PolylineBuildContext): void {
581
+ var neg_normal = Vector.neg(normal);
582
+ var has_texcoord = (context.texcoord_index != null);
583
+
584
+ switch (type){
585
+ case CAP_TYPE.square:
586
+ var tangent;
587
+ // first vertex on the lineString
588
+ if (isBeginning){
589
+ tangent = [normal[1], -normal[0]];
590
+
591
+ addVertex(coord, Vector.add(normal, tangent), normal, 1, v, context, 1);
592
+ addVertex(coord, Vector.add(neg_normal, tangent), normal, 0, v, context, 1);
593
+
594
+ if (has_texcoord) {
595
+ // Add length of square cap to texture coordinate
596
+ v += 0.5 * context.texcoord_width * context.v_scale!;
597
+ }
598
+
599
+ addVertex(coord, normal, normal, 1, v, context, 1);
600
+ addVertex(coord, neg_normal, normal, 0, v, context, 1);
601
+
602
+ }
603
+ // last vertex on the lineString
604
+ else {
605
+ tangent = [-normal[1], normal[0]];
606
+
607
+ addVertex(coord, normal, normal, 1, v, context, 1);
608
+ addVertex(coord, neg_normal, normal, 0, v, context, 1);
609
+
610
+ if (has_texcoord) {
611
+ // Add length of square cap to texture coordinate
612
+ v += 0.5 * context.texcoord_width * context.v_scale!;
613
+ }
614
+
615
+ addVertex(coord, Vector.add(normal, tangent), normal, 1, v, context, 1);
616
+ addVertex(coord, Vector.add(neg_normal, tangent), normal, 0, v, context, 1);
617
+ }
618
+
619
+ indexPairs(1, context);
620
+ break;
621
+ case CAP_TYPE.round:
622
+ // default for end cap, beginning cap will overwrite below (this way we're always passing a non-null value,
623
+ // even if texture coords are disabled)
624
+ var uvA = zero_v, uvB = one_v, uvC = mid_v;
625
+ var nA, nB;
626
+
627
+ // first vertex on the lineString
628
+ if (isBeginning) {
629
+ nA = normal;
630
+ nB = neg_normal;
631
+
632
+ if (has_texcoord){
633
+ v += 0.5 * context.texcoord_width * context.v_scale!;
634
+ uvA = one_v, uvB = zero_v, uvC = mid_v; // update cap UV order
635
+ }
636
+ }
637
+ // last vertex on the lineString - flip the direction of the cap
638
+ else {
639
+ nA = neg_normal;
640
+ nB = normal;
641
+ }
642
+
643
+ if (has_texcoord) {
644
+ zero_v[1] = v, one_v[1] = v, mid_v[1] = v; // update cap UV values
645
+ }
646
+
647
+ addFan(coord,
648
+ nA, zero_vec2, nB, // extrusion normal
649
+ normal, // line normal, for offsets
650
+ uvA, uvC, uvB, // texture coords (ignored if disabled)
651
+ true, false, context
652
+ );
653
+
654
+ break;
655
+ case CAP_TYPE.butt:
656
+ return;
657
+ }
658
+ }
659
+
660
+ // Calculate number of triangles for a fan given an angle and line width
661
+ function trianglesPerArc (angle: number, width: number): number {
662
+ if (angle < 0) {
663
+ angle = -angle;
664
+ }
665
+
666
+ var numTriangles = (width > 2 * MIN_FAN_WIDTH) ? Math.log2(width / MIN_FAN_WIDTH) : 1;
667
+ return Math.ceil(angle / Math.PI * numTriangles);
668
+ }
669
+
670
+ // Cyclically permute closed line starting at an index
671
+ function permuteLine(line: GeometryLine, startIndex: number): GeometryLine {
672
+ var newLine: GeometryLine = [];
673
+ for (let i = 0; i < line.length; i++){
674
+ var index = (i + startIndex) % line.length;
675
+ // skip the first (repeated) index
676
+ if (index !== 0) {
677
+ newLine.push(line[index]);
678
+ }
679
+ }
680
+ newLine.push(newLine[0]);
681
+ return newLine;
682
+ }