@tangram.gl/tangram-renderer 0.0.0-stage → 0.0.1

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 +60 -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,17 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+
5
+ // Debounce a function
6
+ // https://davidwalsh.name/javascript-debounce-function
7
+ export default function debounce<ThisType, Arguments extends unknown[]>(
8
+ func: (this: ThisType, ...arguments_: Arguments) => void,
9
+ wait: number
10
+ ): (this: ThisType, ...arguments_: Arguments) => void {
11
+ let timeout: ReturnType<typeof setTimeout> | undefined;
12
+
13
+ return function debounced(this: ThisType, ...arguments_: Arguments): void {
14
+ clearTimeout(timeout);
15
+ timeout = setTimeout(() => func.apply(this, arguments_), wait);
16
+ };
17
+ }
@@ -0,0 +1,43 @@
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
+ export type DebugSettings = {
7
+ draw_label_collision_boxes: boolean;
8
+ draw_label_texture_boxes: boolean;
9
+ suppress_label_fade_in: boolean;
10
+ suppress_label_snap_animation: boolean;
11
+ show_hidden_labels: boolean;
12
+ layer_stats: boolean;
13
+ wireframe: boolean;
14
+ };
15
+
16
+ export const debugSettings: DebugSettings = {
17
+ // draws a blue rectangle border around the collision box of a label
18
+ draw_label_collision_boxes: false,
19
+
20
+ // draws a green rectangle border within the texture box of a label
21
+ draw_label_texture_boxes: false,
22
+
23
+ // suppresses fade-in of labels
24
+ suppress_label_fade_in: false,
25
+
26
+ // suppresses animation of label snap to pixel grid
27
+ suppress_label_snap_animation: false,
28
+
29
+ // show hidden labels for debugging
30
+ show_hidden_labels: false,
31
+
32
+ // collect feature/geometry stats on styling layers
33
+ layer_stats: false,
34
+
35
+ // draw scene in wireframe mode
36
+ wireframe: false
37
+ };
38
+
39
+ export default debugSettings;
40
+
41
+ export function mergeDebugSettings(settings: Partial<DebugSettings>): void {
42
+ Object.assign(debugSettings, settings);
43
+ }
@@ -0,0 +1,12 @@
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
+ export class MethodNotImplemented extends Error {
7
+ constructor(methodName: string) {
8
+ super();
9
+ this.name = 'MethodNotImplemented';
10
+ this.message = 'Method ' + methodName + ' must be implemented in subclass';
11
+ }
12
+ }
@@ -0,0 +1,95 @@
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
+ import hashString from './hash';
7
+
8
+ export type CompiledFunction = ((...arguments_: unknown[]) => unknown) & {source: string};
9
+ export type FunctionStringWrapper = (source: string) => string;
10
+ export type FunctionStringCache = {
11
+ functions: Record<number, CompiledFunction>;
12
+ num_functions: number;
13
+ num_cached: number;
14
+ };
15
+
16
+ // cache of functions, keyed by unique source
17
+ const cache: FunctionStringCache = {
18
+ functions: {},
19
+ num_functions: 0,
20
+ num_cached: 0
21
+ };
22
+
23
+ export { cache as functionStringCache };
24
+
25
+ export function clearFunctionStringCache(): void {
26
+ cache.functions = {};
27
+ cache.num_functions = 0;
28
+ cache.num_cached = 0;
29
+ }
30
+
31
+ // Recursively parse an object, compiling string properties that look like functions
32
+ export function compileFunctionStrings<Value extends object>(value: Value, wrap?: FunctionStringWrapper): Value;
33
+ export function compileFunctionStrings<Value>(value: Value, wrap?: FunctionStringWrapper): Value | CompiledFunction;
34
+ export function compileFunctionStrings<Value>(
35
+ value: Value,
36
+ wrap?: FunctionStringWrapper
37
+ ): Value | CompiledFunction {
38
+ // Convert string
39
+ if (typeof value === 'string') {
40
+ return compileFunctionString(value, wrap) as Value | CompiledFunction;
41
+ }
42
+ // Loop through object properties
43
+ if (value != null && typeof value === 'object') {
44
+ const record = value as Record<string, unknown>;
45
+ for (const property in record) {
46
+ record[property] = compileFunctionStrings(record[property], wrap);
47
+ }
48
+ }
49
+ return value;
50
+ }
51
+
52
+ // Compile a string that looks like a function
53
+ export function compileFunctionString<Value>(
54
+ value: Value,
55
+ wrap?: FunctionStringWrapper
56
+ ): Value | CompiledFunction {
57
+ // Parse function signature and body
58
+ const functionMatch =
59
+ typeof value === 'string' && value.match(/^\s*function[^(]*\(([^)]*)\)\s*?\{([\s\S]*)\}$/m);
60
+
61
+ if (functionMatch && functionMatch.length > 2) {
62
+ try {
63
+ // function body
64
+ const body = functionMatch[2];
65
+ const source = wrap ? wrap(body) : body;
66
+
67
+ // compile and cache by unique function source
68
+ const key = hashString(source);
69
+ if (cache.functions[key] === undefined) {
70
+ // function arguments extracted from signature
71
+ const parsedArguments = functionMatch[1]
72
+ .split(',')
73
+ .map(argument => argument.trim())
74
+ .filter(Boolean);
75
+ const functionArguments = parsedArguments.length > 0 ? parsedArguments : ['context'];
76
+
77
+ const compiledFunction = new Function(
78
+ functionArguments.toString(),
79
+ source
80
+ ) as CompiledFunction;
81
+ compiledFunction.source = body;
82
+ cache.functions[key] = compiledFunction;
83
+ cache.num_functions++;
84
+ } else {
85
+ cache.num_cached++;
86
+ }
87
+
88
+ return cache.functions[key];
89
+ } catch {
90
+ // fall back to original value if parsing failed
91
+ return value;
92
+ }
93
+ }
94
+ return value;
95
+ }
@@ -0,0 +1,364 @@
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
+ // Miscellaneous geo functions
7
+
8
+ import {
9
+ projectLngLatToMetersWithMath,
10
+ unprojectMetersToLngLatWithMath
11
+ } from '../procedures/web-mercator-math';
12
+ import {PROJECTION_CONSTANTS, getMercatorMetersPerPixel} from '../scene/projection_math';
13
+ import {PACKED_HEIGHT_SCALE} from '../gl/vertex-constants';
14
+
15
+ export type Coordinate = number[];
16
+ export type Meters = {x: number; y: number};
17
+ export type Tile = {x: number; y: number; z: number};
18
+ export type Bounds = {sw: Meters; ne: Meters};
19
+ export type Geometry = {type: string; coordinates: unknown};
20
+ export type Transform = (coordinate: Coordinate) => void;
21
+
22
+ interface GeoNamespace {
23
+ default_source_max_zoom: number;
24
+ default_view_max_zoom: number;
25
+ max_style_zoom: number;
26
+ tile_size: number;
27
+ half_circumference_meters: number;
28
+ circumference_meters: number;
29
+ min_zoom_meters_per_pixel: number;
30
+ tile_scale: number;
31
+ units_per_pixel: number;
32
+ height_scale: number;
33
+ metersPerPixel(z: number): number;
34
+ metersPerTile(z: number): number;
35
+ unitsPerMeter(z: number): number;
36
+ metersForTile(tile: Tile): Meters;
37
+ tileForMeters(coordinates: Coordinate, zoom: number): Tile;
38
+ wrapTile(tile: Tile, mask?: {x: boolean; y: boolean}): Tile;
39
+ metersToLatLng(coordinates: Coordinate): Coordinate;
40
+ latLngToMeters(coordinates: Coordinate): Coordinate;
41
+ tileSpaceToLatlng(geometry: Geometry, z: number, min: Meters): Geometry;
42
+ copyGeometry(geometry: Geometry | null): Geometry | undefined;
43
+ transformGeometry(geometry: Geometry | null, transform: Transform): void;
44
+ boxIntersect(first: Bounds, second: Bounds): boolean;
45
+ findBoundingBox(polygon: Coordinate[][]): [number, number, number, number];
46
+ geometryType(type: string): 'point' | 'line' | 'polygon' | undefined;
47
+ centroid(polygon: Coordinate[][], relative?: boolean): Coordinate | undefined;
48
+ multiCentroid(polygons: Coordinate[][][]): Coordinate | null;
49
+ signedPolygonRingAreaSum(ring: Coordinate[]): number;
50
+ polygonRingArea(ring: Coordinate[]): number;
51
+ polygonArea(polygon: Coordinate[][] | null): number | undefined;
52
+ multiPolygonArea(polygons: Coordinate[][][]): number;
53
+ ringWinding(ring: Coordinate[]): 'CW' | 'CCW' | undefined;
54
+ }
55
+
56
+ export const Geo = {} as GeoNamespace;
57
+ export default Geo;
58
+
59
+ // Projection constants
60
+ Geo.default_source_max_zoom = 18;
61
+ Geo.default_view_max_zoom = 20;
62
+ Geo.max_style_zoom = 25; // max zoom at which styles will be evaluated
63
+ Geo.tile_size = PROJECTION_CONSTANTS.tileSize;
64
+ Geo.half_circumference_meters = Math.PI * PROJECTION_CONSTANTS.mercatorRadius;
65
+ Geo.circumference_meters = Geo.half_circumference_meters * 2;
66
+ Geo.min_zoom_meters_per_pixel = Geo.circumference_meters / Geo.tile_size; // min zoom draws world as 2 tiles wide
67
+
68
+ const meters_per_pixel: number[] = [];
69
+ Geo.metersPerPixel = function (z: number): number {
70
+ meters_per_pixel[z] = meters_per_pixel[z] || getMercatorMetersPerPixel(z);
71
+ return meters_per_pixel[z];
72
+ };
73
+
74
+ const meters_per_tile: number[] = [];
75
+ Geo.metersPerTile = function (z: number): number {
76
+ meters_per_tile[z] = meters_per_tile[z] || Geo.circumference_meters / Math.pow(2, z);
77
+ return meters_per_tile[z];
78
+ };
79
+
80
+ // Conversion functions based on an defined tile scale
81
+ Geo.tile_scale = 4096; // coordinates are locally scaled to the range [0, tile_scale]
82
+ Geo.units_per_pixel = Geo.tile_scale / Geo.tile_size;
83
+ Geo.height_scale = PACKED_HEIGHT_SCALE; // provides sub-meter precision for height values (16ths of a meters)
84
+
85
+ const units_per_meter: number[] = [];
86
+ Geo.unitsPerMeter = function (z: number): number {
87
+ units_per_meter[z] = units_per_meter[z] || Geo.tile_scale / (Geo.tile_size * Geo.metersPerPixel(z));
88
+ return units_per_meter[z];
89
+ };
90
+
91
+ // Convert tile location to mercator meters - multiply by pixels per tile, then by meters per pixel, adjust for map origin
92
+ Geo.metersForTile = function (tile: Tile): Meters {
93
+ return {
94
+ x: tile.x * Geo.circumference_meters / Math.pow(2, tile.z) - Geo.half_circumference_meters,
95
+ y: -(tile.y * Geo.circumference_meters / Math.pow(2, tile.z) - Geo.half_circumference_meters)
96
+ };
97
+ };
98
+
99
+ /**
100
+ Given a point in mercator meters and a zoom level, return the tile X/Y/Z that the point lies in
101
+ */
102
+ Geo.tileForMeters = function ([x, y]: Coordinate, zoom: number): Tile {
103
+ return {
104
+ x: Math.floor((x + Geo.half_circumference_meters) / (Geo.circumference_meters / Math.pow(2, zoom))),
105
+ y: Math.floor((-y + Geo.half_circumference_meters) / (Geo.circumference_meters / Math.pow(2, zoom))),
106
+ z: zoom
107
+ };
108
+ };
109
+
110
+ // Wrap a tile to positive #s for zoom
111
+ // Optionally specify the axes to wrap
112
+ Geo.wrapTile = function({ x, y, z }: Tile, mask = { x: true, y: false }): Tile {
113
+ var m = (1 << z) - 1;
114
+ if (mask.x) {
115
+ x = x & m;
116
+ }
117
+ if (mask.y) {
118
+ y = y & m;
119
+ }
120
+ return { x, y, z };
121
+ };
122
+
123
+ /**
124
+ Convert mercator meters to lat-lng, in-place
125
+ */
126
+ Geo.metersToLatLng = function (c: Coordinate): Coordinate {
127
+ const converted = unprojectMetersToLngLatWithMath([c[0], c[1]]);
128
+ c[0] = converted[0];
129
+ c[1] = converted[1];
130
+ return c;
131
+ };
132
+
133
+ /**
134
+ Convert lat-lng to mercator meters, in-place
135
+ */
136
+ Geo.latLngToMeters = function (c: Coordinate): Coordinate {
137
+ const converted = projectLngLatToMetersWithMath([c[0], c[1]]);
138
+ c[0] = converted[0];
139
+ c[1] = converted[1];
140
+ return c;
141
+ };
142
+
143
+ // Transform from local tile coordinats to lat lng
144
+ Geo.tileSpaceToLatlng = function (geometry: Geometry, z: number, min: Meters): Geometry {
145
+ const units_per_meter = Geo.unitsPerMeter(z);
146
+ Geo.transformGeometry(geometry, (coord: Coordinate) => {
147
+ coord[0] = (coord[0] / units_per_meter) + min.x;
148
+ coord[1] = (coord[1] / units_per_meter) + min.y;
149
+ Geo.metersToLatLng(coord);
150
+ });
151
+ return geometry;
152
+ };
153
+
154
+ // Copy GeoJSON geometry
155
+ Geo.copyGeometry = function (geometry: Geometry | null): Geometry | undefined {
156
+ if (geometry == null) {
157
+ return; // skip if missing geometry (valid GeoJSON)
158
+ }
159
+
160
+ const sourceCoordinates = geometry.coordinates as any;
161
+ const copy: Geometry = { type: geometry.type, coordinates: undefined };
162
+
163
+ if (geometry.type === 'Point') {
164
+ copy.coordinates = [sourceCoordinates[0], sourceCoordinates[1]];
165
+ }
166
+ else if (geometry.type === 'LineString' || geometry.type === 'MultiPoint') {
167
+ copy.coordinates = sourceCoordinates.map((c: Coordinate) => [c[0], c[1]]);
168
+ }
169
+ else if (geometry.type === 'Polygon' || geometry.type === 'MultiLineString') {
170
+ copy.coordinates = sourceCoordinates.map((ring: Coordinate[]) => ring.map(c => [c[0], c[1]]));
171
+ }
172
+ else if (geometry.type === 'MultiPolygon') {
173
+ copy.coordinates = sourceCoordinates.map((polygon: Coordinate[][]) => {
174
+ return polygon.map(ring => ring.map(c => [c[0], c[1]]));
175
+ });
176
+ }
177
+ // TODO: support GeometryCollection
178
+ return copy;
179
+ };
180
+
181
+ // Run an in-place transform function on each cooordinate in a GeoJSON geometry
182
+ Geo.transformGeometry = function (geometry: Geometry | null, transform: Transform): void {
183
+ if (geometry == null) {
184
+ return; // skip if missing geometry (valid GeoJSON)
185
+ }
186
+
187
+ if (geometry.type === 'Point') {
188
+ transform(geometry.coordinates as Coordinate);
189
+ }
190
+ else if (geometry.type === 'LineString' || geometry.type === 'MultiPoint') {
191
+ (geometry.coordinates as Coordinate[]).forEach(transform);
192
+ }
193
+ else if (geometry.type === 'Polygon' || geometry.type === 'MultiLineString') {
194
+ (geometry.coordinates as Coordinate[][]).forEach(ring => ring.forEach(transform));
195
+ }
196
+ else if (geometry.type === 'MultiPolygon') {
197
+ (geometry.coordinates as Coordinate[][][]).forEach(polygon => {
198
+ polygon.forEach(ring => ring.forEach(transform));
199
+ });
200
+ }
201
+ // TODO: support GeometryCollection
202
+ };
203
+
204
+ Geo.boxIntersect = function (b1: Bounds, b2: Bounds): boolean {
205
+ return !(
206
+ b2.sw.x > b1.ne.x ||
207
+ b2.ne.x < b1.sw.x ||
208
+ b2.sw.y > b1.ne.y ||
209
+ b2.ne.y < b1.sw.y
210
+ );
211
+ };
212
+
213
+ // Finds the axis-aligned bounding box for a polygon
214
+ Geo.findBoundingBox = function (polygon: Coordinate[][]): [number, number, number, number] {
215
+ var min_x = Infinity,
216
+ max_x = -Infinity,
217
+ min_y = Infinity,
218
+ max_y = -Infinity;
219
+
220
+ // Only need to examine outer ring (polygon[0])
221
+ var num_coords = polygon[0].length;
222
+ for (var c=0; c < num_coords; c++) {
223
+ var coord = polygon[0][c];
224
+
225
+ if (coord[0] < min_x) {
226
+ min_x = coord[0];
227
+ }
228
+ if (coord[1] < min_y) {
229
+ min_y = coord[1];
230
+ }
231
+ if (coord[0] > max_x) {
232
+ max_x = coord[0];
233
+ }
234
+ if (coord[1] > max_y) {
235
+ max_y = coord[1];
236
+ }
237
+ }
238
+
239
+ return [min_x, min_y, max_x, max_y];
240
+ };
241
+
242
+ // Convert geometry type to one of: 'point', 'line', 'polygon'
243
+ Geo.geometryType = function(type: string): 'point' | 'line' | 'polygon' | undefined {
244
+ if (type === 'Polygon' || type === 'MultiPolygon') {
245
+ return 'polygon';
246
+ }
247
+ else if (type === 'LineString' || type === 'MultiLineString') {
248
+ return 'line';
249
+ }
250
+ if (type === 'Point' || type === 'MultiPoint') {
251
+ return 'point';
252
+ }
253
+ };
254
+
255
+ // Geometric / weighted centroid of polygon
256
+ // Adapted from https://github.com/Leaflet/Leaflet/blob/c10f405a112142b19785967ce0e142132a6095ad/src/layer/vector/Polygon.js#L57
257
+ Geo.centroid = function (polygon: Coordinate[][], relative = true): Coordinate | undefined {
258
+ if (!polygon || polygon.length === 0) {
259
+ return;
260
+ }
261
+
262
+ let x = 0, y = 0, area = 0;
263
+ let ring = polygon[0]; // only use first ring for now
264
+ let len = ring.length;
265
+
266
+ // optionally calculate relative to first coordinate to avoid precision issues w/small polygons
267
+ let origin: Coordinate | undefined;
268
+ if (relative) {
269
+ const originCoordinate = ring[0];
270
+ origin = originCoordinate;
271
+ ring = ring.map(v => [v[0] - originCoordinate[0], v[1] - originCoordinate[1]]);
272
+ }
273
+
274
+ for (let i = 0, j = len - 1; i < len; j = i, i++) {
275
+ let p0 = ring[i];
276
+ let p1 = ring[j];
277
+ let f = p0[1] * p1[0] - p1[1] * p0[0];
278
+
279
+ x += (p0[0] + p1[0]) * f;
280
+ y += (p0[1] + p1[1]) * f;
281
+ area += f * 3;
282
+ }
283
+
284
+ if (!area) {
285
+ return; // skip degenerate polygons
286
+ }
287
+
288
+ const c: Coordinate = [x / area, y / area];
289
+ if (relative) {
290
+ c[0] += origin![0];
291
+ c[1] += origin![1];
292
+ }
293
+ return c;
294
+ };
295
+
296
+ Geo.multiCentroid = function (polygons: Coordinate[][][]): Coordinate | null {
297
+ let n = 0;
298
+ let centroid: Coordinate | null = null;
299
+
300
+ for (let p=0; p < polygons.length; p++) {
301
+ let c = Geo.centroid(polygons[p]);
302
+ if (c) { // skip degenerate polygons
303
+ centroid = centroid || [0, 0];
304
+ centroid[0] += c[0];
305
+ centroid[1] += c[1];
306
+ n++;
307
+ }
308
+ }
309
+
310
+ if (n > 0) {
311
+ centroid![0] /= n;
312
+ centroid![1] /= n;
313
+ }
314
+
315
+ return centroid; // will return null if all polygons were degenerate
316
+ };
317
+
318
+ Geo.signedPolygonRingAreaSum = function (ring: Coordinate[]): number {
319
+ let area = 0;
320
+ let n = ring.length;
321
+
322
+ for (let i = 0; i < n - 1; i++) {
323
+ let p0 = ring[i];
324
+ let p1 = ring[i+1];
325
+
326
+ area += p0[0] * p1[1] - p1[0] * p0[1];
327
+ }
328
+
329
+ area += ring[n - 1][0] * ring[0][1] - ring[0][0] * ring[n - 1][1];
330
+ return area;
331
+ };
332
+
333
+ Geo.polygonRingArea = function (ring: Coordinate[]): number {
334
+ return Math.abs(Geo.signedPolygonRingAreaSum(ring)) / 2;
335
+ };
336
+
337
+ // TODO: subtract inner rings
338
+ Geo.polygonArea = function (polygon: Coordinate[][] | null): number | undefined {
339
+ if (!polygon) {
340
+ return;
341
+ }
342
+ return Geo.polygonRingArea(polygon[0]);
343
+ };
344
+
345
+ Geo.multiPolygonArea = function (polygons: Coordinate[][][]): number {
346
+ let area = 0;
347
+
348
+ for (let p=0; p < polygons.length; p++) {
349
+ area += Geo.polygonArea(polygons[p]) || 0;
350
+ }
351
+
352
+ return area;
353
+ };
354
+
355
+ Geo.ringWinding = function (ring: Coordinate[]): 'CW' | 'CCW' | undefined {
356
+ let area = Geo.signedPolygonRingAreaSum(ring);
357
+ if (area > 0) {
358
+ return 'CW';
359
+ }
360
+ else if (area < 0) {
361
+ return 'CCW';
362
+ }
363
+ // return undefined on zero area polygon
364
+ };
@@ -0,0 +1,14 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+
5
+ // http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
6
+ export default function hashString(string: string): number {
7
+ let hash = 0;
8
+
9
+ for (let index = 0; index < string.length; index++) {
10
+ hash = (hash << 5) - hash + string.charCodeAt(index);
11
+ hash |= 0;
12
+ }
13
+ return hash;
14
+ }
@@ -0,0 +1,108 @@
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
+ import version from './version';
7
+ import Thread from './thread';
8
+ import WorkerBroker from './worker_broker';
9
+
10
+ import type {BrokerWorker} from './worker-types';
11
+
12
+ const workerBroker = WorkerBroker;
13
+
14
+ const LEVELS = {
15
+ silent: -1,
16
+ error: 0,
17
+ warn: 1,
18
+ info: 2,
19
+ debug: 3,
20
+ trace: 4
21
+ } as const;
22
+
23
+ /** Supported renderer log levels. */
24
+ export type LogLevel = keyof typeof LEVELS;
25
+
26
+ /** Per-message renderer logging options. */
27
+ export type LogOptions = {level: LogLevel; once?: boolean};
28
+
29
+ type ConsoleMethod = (...messages: unknown[]) => void;
30
+
31
+ /** Renderer logger with shared level and worker controls. */
32
+ export interface Logger {
33
+ (options: LogLevel | LogOptions, ...messages: unknown[]): Promise<boolean>;
34
+ level: LogLevel;
35
+ workers: BrokerWorker[] | null;
36
+ setLevel(level: LogLevel): void;
37
+ setWorkers?(workers: BrokerWorker[] | null): void;
38
+ reset?(): void;
39
+ }
40
+
41
+ const methods: Partial<Record<LogLevel, ConsoleMethod>> = {};
42
+ let loggedOnce: Record<string, true> = {};
43
+
44
+ function getMethodForLevel(level: LogLevel): ConsoleMethod | undefined {
45
+ if (!methods[level]) {
46
+ const consoleMethods = console as unknown as Record<string, ConsoleMethod | undefined>;
47
+ methods[level] = (consoleMethods[level] || console.log).bind(console);
48
+ }
49
+ return methods[level];
50
+ }
51
+
52
+ const log = (async (
53
+ options: LogLevel | LogOptions,
54
+ ...messages: unknown[]
55
+ ): Promise<boolean> => {
56
+ const level = typeof options === 'object' ? options.level : options;
57
+ if (LEVELS[level] > LEVELS[log.level]) {
58
+ return false;
59
+ }
60
+
61
+ if (Thread.is_worker) {
62
+ return workerBroker.postMessage<boolean>(
63
+ {method: '_logProxy', stringify: true},
64
+ options,
65
+ ...messages
66
+ );
67
+ }
68
+
69
+ if (typeof options === 'object' && options.once === true) {
70
+ const key = JSON.stringify(messages);
71
+ if (loggedOnce[key]) {
72
+ return false;
73
+ }
74
+ loggedOnce[key] = true;
75
+ }
76
+
77
+ const logger = getMethodForLevel(level);
78
+ if (messages.length > 1) {
79
+ logger!(`Tangram ${version} [${level}]: ${messages[0]}`, ...messages.slice(1));
80
+ } else {
81
+ logger!(`Tangram ${version} [${level}]: ${messages[0]}`);
82
+ }
83
+ return true;
84
+ }) as Logger;
85
+
86
+ log.level = 'info';
87
+ log.workers = null;
88
+
89
+ log.setLevel = (level: LogLevel): void => {
90
+ log.level = level;
91
+ if (Thread.is_main && Array.isArray(log.workers)) {
92
+ workerBroker.postMessage(log.workers, '_logSetLevelProxy', level);
93
+ }
94
+ };
95
+
96
+ if (!Thread.is_worker) {
97
+ log.setWorkers = (workers: BrokerWorker[] | null): void => {
98
+ log.workers = workers;
99
+ };
100
+ log.reset = (): void => {
101
+ loggedOnce = {};
102
+ };
103
+ }
104
+
105
+ WorkerBroker.addTarget('_logProxy', log);
106
+ WorkerBroker.addTarget('_logSetLevelProxy', log.setLevel);
107
+
108
+ export default log;