maplibre-gl 6.3.0 → 6.4.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 (56) hide show
  1. package/dist/maplibre-gl-dev.mjs +590 -208
  2. package/dist/maplibre-gl-dev.mjs.map +1 -1
  3. package/dist/maplibre-gl-shared-dev.mjs +258 -235
  4. package/dist/maplibre-gl-shared-dev.mjs.map +1 -1
  5. package/dist/maplibre-gl-shared.mjs +2 -2
  6. package/dist/maplibre-gl-shared.mjs.map +1 -1
  7. package/dist/maplibre-gl-worker-dev.mjs +2 -2
  8. package/dist/maplibre-gl-worker.mjs +2 -2
  9. package/dist/maplibre-gl-worker.mjs.map +1 -1
  10. package/dist/maplibre-gl.d.ts +258 -97
  11. package/dist/maplibre-gl.mjs +18 -18
  12. package/dist/maplibre-gl.mjs.map +1 -1
  13. package/package.json +7 -7
  14. package/src/data/bucket/fill_extrusion_bucket.ts +1 -13
  15. package/src/data/bucket/round_polygon_corners.test.ts +84 -36
  16. package/src/data/bucket/round_polygon_corners.ts +90 -39
  17. package/src/data/extent_bounds.ts +28 -1
  18. package/src/geo/projection/globe_transform.test.ts +129 -1
  19. package/src/geo/projection/globe_utils.ts +189 -2
  20. package/src/geo/projection/vertical_perspective_camera_helper.test.ts +24 -0
  21. package/src/geo/projection/vertical_perspective_camera_helper.ts +11 -10
  22. package/src/render/image_atlas.test.ts +110 -2
  23. package/src/render/image_atlas.ts +35 -4
  24. package/src/render/image_manager.test.ts +66 -1
  25. package/src/render/image_manager.ts +136 -144
  26. package/src/render/painter.ts +5 -2
  27. package/src/render/pattern_atlas.test.ts +131 -0
  28. package/src/render/pattern_atlas.ts +144 -0
  29. package/src/shaders/glsl/_prelude.vertex.glsl +8 -8
  30. package/src/shaders/glsl/_prelude.vertex.glsl.g.ts +1 -1
  31. package/src/shaders/glsl/color_relief.fragment.glsl +1 -2
  32. package/src/shaders/glsl/color_relief.fragment.glsl.g.ts +1 -1
  33. package/src/shaders/glsl/hillshade_prepare.fragment.glsl +12 -12
  34. package/src/shaders/glsl/hillshade_prepare.fragment.glsl.g.ts +1 -1
  35. package/src/source/image_source.test.ts +41 -31
  36. package/src/source/image_source.ts +14 -15
  37. package/src/source/raster_dem_tile_source.test.ts +37 -3
  38. package/src/source/raster_dem_tile_source.ts +1 -2
  39. package/src/source/raster_tile_source.test.ts +5 -26
  40. package/src/source/raster_tile_source.ts +4 -3
  41. package/src/style/style.test.ts +64 -0
  42. package/src/style/style.ts +37 -64
  43. package/src/symbol/cross_tile_symbol_index.test.ts +31 -0
  44. package/src/symbol/cross_tile_symbol_index.ts +67 -37
  45. package/src/tile/tile_manager.test.ts +69 -1
  46. package/src/tile/tile_manager.ts +14 -9
  47. package/src/ui/handler/two_fingers_touch.test.ts +14 -3
  48. package/src/ui/handler_inertia.test.ts +91 -0
  49. package/src/ui/handler_inertia.ts +65 -14
  50. package/src/ui/map_tests/map_images.test.ts +26 -0
  51. package/src/ui/map_tests/map_webgl.test.ts +2 -1
  52. package/src/ui/marker.test.ts +151 -0
  53. package/src/ui/marker.ts +120 -10
  54. package/src/util/image_request.ts +31 -1
  55. package/src/webgl/draw/draw_background.ts +1 -1
  56. package/src/webgl/program/pattern.ts +3 -3
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * MapLibre GL JS
3
- * @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.3.0/LICENSE.txt
3
+ * @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.4.0/LICENSE.txt
4
4
  */
5
5
  //#region \0rolldown/runtime.js
6
6
  var __create = Object.create;
@@ -1443,6 +1443,23 @@ function create$3() {
1443
1443
  return out;
1444
1444
  }
1445
1445
  /**
1446
+ * Creates a new vec4 initialized with the given values
1447
+ *
1448
+ * @param {Number} x X component
1449
+ * @param {Number} y Y component
1450
+ * @param {Number} z Z component
1451
+ * @param {Number} w W component
1452
+ * @returns {vec4} a new 4D vector
1453
+ */
1454
+ function fromValues$3(x, y, z, w) {
1455
+ var out = new ARRAY_TYPE(4);
1456
+ out[0] = x;
1457
+ out[1] = y;
1458
+ out[2] = z;
1459
+ out[3] = w;
1460
+ return out;
1461
+ }
1462
+ /**
1446
1463
  * Multiplies two vec4's
1447
1464
  *
1448
1465
  * @param {vec4} out the receiving vector
@@ -1573,6 +1590,23 @@ function setAxisAngle(out, axis, rad) {
1573
1590
  return out;
1574
1591
  }
1575
1592
  /**
1593
+ * Multiplies two quat's
1594
+ *
1595
+ * @param {quat} out the receiving quaternion
1596
+ * @param {ReadonlyQuat} a the first operand
1597
+ * @param {ReadonlyQuat} b the second operand
1598
+ * @returns {quat} out
1599
+ */
1600
+ function multiply$2(out, a, b) {
1601
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3];
1602
+ var bx = b[0], by = b[1], bz = b[2], bw = b[3];
1603
+ out[0] = ax * bw + aw * bx + ay * bz - az * by;
1604
+ out[1] = ay * bw + aw * by + az * bx - ax * bz;
1605
+ out[2] = az * bw + aw * bz + ax * by - ay * bx;
1606
+ out[3] = aw * bw - ax * bx - ay * by - az * bz;
1607
+ return out;
1608
+ }
1609
+ /**
1576
1610
  * Performs a spherical linear interpolation between two quat
1577
1611
  *
1578
1612
  * @param {quat} out the receiving quaternion
@@ -1708,6 +1742,17 @@ function fromEuler(out, x, y, z) {
1708
1742
  return out;
1709
1743
  }
1710
1744
  /**
1745
+ * Creates a new quat initialized with the given values
1746
+ *
1747
+ * @param {Number} x X component
1748
+ * @param {Number} y Y component
1749
+ * @param {Number} z Z component
1750
+ * @param {Number} w W component
1751
+ * @returns {quat} a new quaternion
1752
+ * @function
1753
+ */
1754
+ var fromValues$2 = fromValues$3;
1755
+ /**
1711
1756
  * Normalize a quat
1712
1757
  *
1713
1758
  * @param {quat} out the receiving quaternion
@@ -1787,18 +1832,6 @@ function create() {
1787
1832
  return out;
1788
1833
  }
1789
1834
  /**
1790
- * Creates a new vec2 initialized with values from an existing vector
1791
- *
1792
- * @param {ReadonlyVec2} a vector to clone
1793
- * @returns {vec2} a new 2D vector
1794
- */
1795
- function clone$1(a) {
1796
- var out = new ARRAY_TYPE(2);
1797
- out[0] = a[0];
1798
- out[1] = a[1];
1799
- return out;
1800
- }
1801
- /**
1802
1835
  * Creates a new vec2 initialized with the given values
1803
1836
  *
1804
1837
  * @param {Number} x X component
@@ -1812,32 +1845,6 @@ function fromValues(x, y) {
1812
1845
  return out;
1813
1846
  }
1814
1847
  /**
1815
- * Adds two vec2's
1816
- *
1817
- * @param {vec2} out the receiving vector
1818
- * @param {ReadonlyVec2} a the first operand
1819
- * @param {ReadonlyVec2} b the second operand
1820
- * @returns {vec2} out
1821
- */
1822
- function add(out, a, b) {
1823
- out[0] = a[0] + b[0];
1824
- out[1] = a[1] + b[1];
1825
- return out;
1826
- }
1827
- /**
1828
- * Subtracts vector b from vector a
1829
- *
1830
- * @param {vec2} out the receiving vector
1831
- * @param {ReadonlyVec2} a the first operand
1832
- * @param {ReadonlyVec2} b the second operand
1833
- * @returns {vec2} out
1834
- */
1835
- function subtract(out, a, b) {
1836
- out[0] = a[0] - b[0];
1837
- out[1] = a[1] - b[1];
1838
- return out;
1839
- }
1840
- /**
1841
1848
  * Scales a vec2 by a scalar number
1842
1849
  *
1843
1850
  * @param {vec2} out the receiving vector
@@ -1851,20 +1858,6 @@ function scale(out, a, b) {
1851
1858
  return out;
1852
1859
  }
1853
1860
  /**
1854
- * Adds two vec2's after scaling the second operand by a scalar value
1855
- *
1856
- * @param {vec2} out the receiving vector
1857
- * @param {ReadonlyVec2} a the first operand
1858
- * @param {ReadonlyVec2} b the second operand
1859
- * @param {Number} scale the amount to scale b by before adding
1860
- * @returns {vec2} out
1861
- */
1862
- function scaleAndAdd(out, a, b, scale) {
1863
- out[0] = a[0] + b[0] * scale;
1864
- out[1] = a[1] + b[1] * scale;
1865
- return out;
1866
- }
1867
- /**
1868
1861
  * Calculates the length of a vec2
1869
1862
  *
1870
1863
  * @param {ReadonlyVec2} a vector to calculate length of
@@ -1885,21 +1878,6 @@ function squaredLength(a) {
1885
1878
  return x * x + y * y;
1886
1879
  }
1887
1880
  /**
1888
- * Normalize a vec2
1889
- *
1890
- * @param {vec2} out the receiving vector
1891
- * @param {ReadonlyVec2} a vector to normalize
1892
- * @returns {vec2} out
1893
- */
1894
- function normalize(out, a) {
1895
- var x = a[0], y = a[1];
1896
- var len = x * x + y * y;
1897
- if (len > 0) len = 1 / Math.sqrt(len);
1898
- out[0] = a[0] * len;
1899
- out[1] = a[1] * len;
1900
- return out;
1901
- }
1902
- /**
1903
1881
  * Calculates the dot product of two vec2's
1904
1882
  *
1905
1883
  * @param {ReadonlyVec2} a the first operand
@@ -1910,30 +1888,6 @@ function dot$1(a, b) {
1910
1888
  return a[0] * b[0] + a[1] * b[1];
1911
1889
  }
1912
1890
  /**
1913
- * Rotate a 2D vector
1914
- * @param {vec2} out The receiving vec2
1915
- * @param {ReadonlyVec2} a The vec2 point to rotate
1916
- * @param {ReadonlyVec2} b The origin of the rotation
1917
- * @param {Number} rad The angle of rotation in radians
1918
- * @returns {vec2} out
1919
- */
1920
- function rotate(out, a, b, rad) {
1921
- var p0 = a[0] - b[0], p1 = a[1] - b[1], sinC = Math.sin(rad), cosC = Math.cos(rad);
1922
- out[0] = p0 * cosC - p1 * sinC + b[0];
1923
- out[1] = p0 * sinC + p1 * cosC + b[1];
1924
- return out;
1925
- }
1926
- /**
1927
- * Get the smallest angle between two 2D vectors
1928
- * @param {ReadonlyVec2} a The first operand
1929
- * @param {ReadonlyVec2} b The second operand
1930
- * @returns {Number} The angle in radians
1931
- */
1932
- function angle(a, b) {
1933
- var ax = a[0], ay = a[1], bx = b[0], by = b[1];
1934
- return Math.abs(Math.atan2(ay * bx - ax * by, ax * bx + ay * by));
1935
- }
1936
- /**
1937
1891
  * Set the components of a vec2 to zero
1938
1892
  *
1939
1893
  * @param {vec2} out the receiving vector
@@ -1945,11 +1899,6 @@ function zero(out) {
1945
1899
  return out;
1946
1900
  }
1947
1901
  /**
1948
- * Alias for {@link vec2.subtract}
1949
- * @function
1950
- */
1951
- var sub = subtract;
1952
- /**
1953
1902
  * Alias for {@link vec2.squaredLength}
1954
1903
  * @function
1955
1904
  */
@@ -18754,6 +18703,128 @@ const members$2 = layout$3.members;
18754
18703
  layout$3.size;
18755
18704
  layout$3.alignment;
18756
18705
  //#endregion
18706
+ //#region src/geo/bounds.ts
18707
+ /** A 2-d bounding box covering an X and Y range. */
18708
+ var Bounds = class Bounds {
18709
+ constructor() {
18710
+ this.minX = Infinity;
18711
+ this.maxX = -Infinity;
18712
+ this.minY = Infinity;
18713
+ this.maxY = -Infinity;
18714
+ }
18715
+ /**
18716
+ * Expands this bounding box to include point.
18717
+ *
18718
+ * @param point - The point to include in this bounding box
18719
+ * @returns This mutated bounding box
18720
+ */
18721
+ extend(point) {
18722
+ this.minX = Math.min(this.minX, point.x);
18723
+ this.minY = Math.min(this.minY, point.y);
18724
+ this.maxX = Math.max(this.maxX, point.x);
18725
+ this.maxY = Math.max(this.maxY, point.y);
18726
+ return this;
18727
+ }
18728
+ /**
18729
+ * Expands this bounding box by a fixed amount in each direction.
18730
+ *
18731
+ * @param amount - The amount to expand the box by, or contract if negative
18732
+ * @returns This mutated bounding box
18733
+ */
18734
+ expandBy(amount) {
18735
+ this.minX -= amount;
18736
+ this.minY -= amount;
18737
+ this.maxX += amount;
18738
+ this.maxY += amount;
18739
+ if (this.minX > this.maxX || this.minY > this.maxY) {
18740
+ this.minX = Infinity;
18741
+ this.maxX = -Infinity;
18742
+ this.minY = Infinity;
18743
+ this.maxY = -Infinity;
18744
+ }
18745
+ return this;
18746
+ }
18747
+ /**
18748
+ * Shrinks this bounding box by a fixed amount in each direction.
18749
+ *
18750
+ * @param amount - The amount to shrink the box by
18751
+ * @returns This mutated bounding box
18752
+ */
18753
+ shrinkBy(amount) {
18754
+ return this.expandBy(-amount);
18755
+ }
18756
+ /**
18757
+ * Returns a new bounding box that contains all of the corners of this bounding
18758
+ * box with a transform applied. Does not modify this bounding box.
18759
+ *
18760
+ * @param fn - The function to apply to each corner
18761
+ * @returns A new bounding box containing all of the mapped points.
18762
+ */
18763
+ map(fn) {
18764
+ const result = new Bounds();
18765
+ result.extend(fn(new Point(this.minX, this.minY)));
18766
+ result.extend(fn(new Point(this.maxX, this.minY)));
18767
+ result.extend(fn(new Point(this.minX, this.maxY)));
18768
+ result.extend(fn(new Point(this.maxX, this.maxY)));
18769
+ return result;
18770
+ }
18771
+ /**
18772
+ * Creates a new bounding box that includes all points provided.
18773
+ *
18774
+ * @param points - The points to include inside the bounding box
18775
+ * @returns The new bounding box
18776
+ */
18777
+ static fromPoints(points) {
18778
+ const result = new Bounds();
18779
+ for (const p of points) result.extend(p);
18780
+ return result;
18781
+ }
18782
+ contains(point) {
18783
+ return point.x >= this.minX && point.x <= this.maxX && point.y >= this.minY && point.y <= this.maxY;
18784
+ }
18785
+ empty() {
18786
+ return this.minX > this.maxX;
18787
+ }
18788
+ width() {
18789
+ return this.maxX - this.minX;
18790
+ }
18791
+ height() {
18792
+ return this.maxY - this.minY;
18793
+ }
18794
+ covers(other) {
18795
+ return !this.empty() && !other.empty() && other.minX >= this.minX && other.maxX <= this.maxX && other.minY >= this.minY && other.maxY <= this.maxY;
18796
+ }
18797
+ intersects(other) {
18798
+ return !this.empty() && !other.empty() && other.minX <= this.maxX && other.maxX >= this.minX && other.minY <= this.maxY && other.maxY >= this.minY;
18799
+ }
18800
+ };
18801
+ //#endregion
18802
+ //#region src/data/extent_bounds.ts
18803
+ /**
18804
+ * The bounding box covering the entire extent of a tile.
18805
+ */
18806
+ const EXTENT_BOUNDS = Bounds.fromPoints([new Point(0, 0), new Point(EXTENT$1, EXTENT$1)]);
18807
+ /**
18808
+ * Whether an edge runs along one of the lines the tile was cut out of the world at. Clipping happens
18809
+ * on the buffer rectangle, outside the tile, so an axis parallel edge out there belongs to the cut
18810
+ * rather than to the feature. Such an edge is shared with the neighbouring tile, which cuts the same
18811
+ * feature somewhere else, so geometry derived from it has to stay identical in both tiles.
18812
+ * @param p1 - First vertex of the edge
18813
+ * @param p2 - Second vertex of the edge
18814
+ * @returns True when the edge lies on a clip line.
18815
+ */
18816
+ function isBoundaryEdge(p1, p2) {
18817
+ return p1.x === p2.x && (p1.x < 0 || p1.x > 8192) || p1.y === p2.y && (p1.y < 0 || p1.y > 8192);
18818
+ }
18819
+ /**
18820
+ * Whether a ring lies completely off one side of the tile, and so cannot contribute a visible pixel.
18821
+ * @param ring - Ring to test
18822
+ * @returns True when every vertex is beyond the same edge of the tile.
18823
+ */
18824
+ function isEntirelyOutside(ring) {
18825
+ return ring.every((p) => p.x < 0) || ring.every((p) => p.x > 8192) || ring.every((p) => p.y < 0) || ring.every((p) => p.y > 8192);
18826
+ }
18827
+ //#endregion
18757
18828
  //#region node_modules/@mapbox/vector-tile/index.js
18758
18829
  /** @import {PbfReader} from 'pbf' */
18759
18830
  /** @import {Feature} from 'geojson' */
@@ -19390,55 +19461,90 @@ function getTileUnitsForMeters(distanceInMeters, canonical) {
19390
19461
  const tileUnitsPerMercator = (1 << canonical.z) * EXTENT$1;
19391
19462
  return distanceInMeters * meterInMercator * tileUnitsPerMercator;
19392
19463
  }
19464
+ /**
19465
+ * Rounds the corners of a single ring.
19466
+ *
19467
+ * Corners that tile clipping created are left sharp: they belong to the cut rather than to the
19468
+ * feature, and the neighbouring tile cuts the same feature elsewhere, so rounding them would leave
19469
+ * the two halves out of step. Every vertex ends up on the integer tile grid, because triangulation,
19470
+ * subdivision and the vertex buffers snap and deduplicate vertices there - arcs finer than a tile
19471
+ * unit would otherwise be merged only after they were triangulated, turning the mesh into spikes.
19472
+ *
19473
+ * A ring that collapses into fewer than three distinct vertices is returned unchanged.
19474
+ * @param ring - Ring to round, closed or open
19475
+ * @param distanceInTileUnits - Corner rounding distance, already converted to tile units
19476
+ */
19393
19477
  function roundRing(ring, distanceInTileUnits) {
19394
19478
  if (!ring || ring.length < 3) return ring;
19395
19479
  const isClosed = ring[0].x === ring[ring.length - 1].x && ring[0].y === ring[ring.length - 1].y;
19396
19480
  const vertexCount = isClosed ? ring.length - 1 : ring.length;
19397
19481
  if (vertexCount < 3) return ring;
19398
- const vertices = ring.map((p) => fromValues(p.x, p.y));
19399
19482
  const newRing = [];
19400
19483
  for (let i = 0; i < vertexCount; i++) {
19401
- const prev = vertices[(i - 1 + vertexCount) % vertexCount];
19402
- const current = vertices[i];
19403
- const next = vertices[(i + 1) % vertexCount];
19404
- appendRoundCorner(newRing, prev, current, next, distanceInTileUnits);
19484
+ const previous = ring[(i - 1 + vertexCount) % vertexCount];
19485
+ const current = ring[i];
19486
+ const next = ring[(i + 1) % vertexCount];
19487
+ if (isBoundaryEdge(previous, current) || isBoundaryEdge(current, next)) {
19488
+ newRing.push(current.clone());
19489
+ continue;
19490
+ }
19491
+ appendRoundCorner(newRing, previous, current, next, distanceInTileUnits);
19405
19492
  }
19406
- if (isClosed && newRing.length > 0) newRing.push(clone$1(newRing[0]));
19407
- return newRing.map((p) => new Point(p[0], p[1]));
19493
+ const snapped = snapToIntegerGrid(newRing);
19494
+ if (snapped.length < 3) return ring;
19495
+ if (isClosed) snapped.push(snapped[0].clone());
19496
+ return snapped;
19408
19497
  }
19498
+ /**
19499
+ * Rounds every vertex to the integer tile grid, dropping vertices that collapse onto their neighbour.
19500
+ * The ring is treated as closed, so the wrap-around duplicate is dropped as well.
19501
+ * @param ring - Ring to snap
19502
+ */
19503
+ function snapToIntegerGrid(ring) {
19504
+ const snapped = [];
19505
+ for (const p of ring) {
19506
+ const point = p.round();
19507
+ const previous = snapped[snapped.length - 1];
19508
+ if (previous?.x === point.x && previous?.y === point.y) continue;
19509
+ snapped.push(point);
19510
+ }
19511
+ while (snapped.length > 1 && snapped[0].x === snapped[snapped.length - 1].x && snapped[0].y === snapped[snapped.length - 1].y) snapped.pop();
19512
+ return snapped;
19513
+ }
19514
+ /**
19515
+ * Appends the arc that replaces one corner, or the corner itself when it is too shallow or too sharp
19516
+ * to round.
19517
+ * @param newRing - Ring being built, the arc points are appended to it
19518
+ * @param prev - Vertex before the corner
19519
+ * @param current - The corner
19520
+ * @param next - Vertex after the corner
19521
+ * @param distanceInTileUnits - Corner rounding distance, already converted to tile units
19522
+ */
19409
19523
  function appendRoundCorner(newRing, prev, current, next, distanceInTileUnits) {
19410
- const ua = sub(create(), prev, current);
19411
- const ub = sub(create(), next, current);
19412
- const lenA = length(ua);
19413
- const lenB = length(ub);
19524
+ const ua = prev.sub(current);
19525
+ const ub = next.sub(current);
19526
+ const lenA = ua.mag();
19527
+ const lenB = ub.mag();
19414
19528
  if (lenA < 1e-6 || lenB < 1e-6) {
19415
- newRing.push(clone$1(current));
19529
+ newRing.push(current.clone());
19416
19530
  return;
19417
19531
  }
19418
- scale(ua, ua, 1 / lenA);
19419
- scale(ub, ub, 1 / lenB);
19420
- const dot = dot$1(ua, ub);
19532
+ ua._div(lenA);
19533
+ ub._div(lenB);
19534
+ const dot = ua.x * ub.x + ua.y * ub.y;
19421
19535
  if (Math.abs(dot) > Math.cos(5 * Math.PI / 180)) {
19422
- newRing.push(clone$1(current));
19536
+ newRing.push(current.clone());
19423
19537
  return;
19424
19538
  }
19425
19539
  const maxEdgeLenPercent = .2;
19426
19540
  const r = Math.min(distanceInTileUnits, lenA * maxEdgeLenPercent, lenB * maxEdgeLenPercent);
19427
- const tangentA = scaleAndAdd(create(), current, ua, r);
19428
- const tangentB = scaleAndAdd(create(), current, ub, r);
19429
- const bisector = add(create(), ua, ub);
19430
- normalize(bisector, bisector);
19541
+ const tangentA = current.add(ua.mult(r));
19542
+ const tangentB = current.add(ub.mult(r));
19431
19543
  const cosHalfTheta = Math.sqrt((1 + dot) / 2);
19432
- const center = scaleAndAdd(create(), current, bisector, r / cosHalfTheta);
19433
- const radiusA = sub(create(), tangentA, center);
19434
- const radiusB = sub(create(), tangentB, center);
19435
- const sweepAngle = angle(radiusA, radiusB);
19436
- const direction = Math.sign(radiusA[0] * radiusB[1] - radiusA[1] * radiusB[0]);
19437
- const numSegments = Math.max(2, Math.ceil(sweepAngle / (Math.PI / 6) - 1e-6));
19438
- for (let s = 0; s <= numSegments; s++) {
19439
- const angle = direction * sweepAngle * (s / numSegments);
19440
- newRing.push(rotate(create(), tangentA, center, angle));
19441
- }
19544
+ const center = current.add(ua.add(ub)._unit()._mult(r / cosHalfTheta));
19545
+ const sweepAngle = tangentA.sub(center).angleWith(tangentB.sub(center));
19546
+ const numSegments = Math.max(2, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 6) - 1e-6));
19547
+ for (let s = 0; s <= numSegments; s++) newRing.push(tangentA.rotateAround(sweepAngle * (s / numSegments), center));
19442
19548
  }
19443
19549
  //#endregion
19444
19550
  //#region src/data/bucket/fill_extrusion_bucket.ts
@@ -19606,12 +19712,6 @@ function accumulatePointsToCentroid(centroid, geometry) {
19606
19712
  }
19607
19713
  }
19608
19714
  register("FillExtrusionBucket", FillExtrusionBucket, { omit: ["layers", "features"] });
19609
- function isBoundaryEdge(p1, p2) {
19610
- return p1.x === p2.x && (p1.x < 0 || p1.x > 8192) || p1.y === p2.y && (p1.y < 0 || p1.y > 8192);
19611
- }
19612
- function isEntirelyOutside(ring) {
19613
- return ring.every((p) => p.x < 0) || ring.every((p) => p.x > 8192) || ring.every((p) => p.y < 0) || ring.every((p) => p.y > 8192);
19614
- }
19615
19715
  //#endregion
19616
19716
  //#region src/style/style_layer/fill_extrusion_style_layer_properties.g.ts
19617
19717
  let layout$2;
@@ -23787,12 +23887,17 @@ var ImagePosition = class {
23787
23887
  }
23788
23888
  };
23789
23889
  /**
23790
- * A class holding all the images
23890
+ * A single tile's packed copy of the icons and patterns its features reference, built in the
23891
+ * worker so that the symbol layout can bake the positions within it straight into the vertex
23892
+ * buffers. Each tile owns one, along with the texture it is uploaded to - as opposed to
23893
+ * {@link ImageManager}, which owns the images of the whole style.
23894
+ * @internal
23791
23895
  */
23792
23896
  var ImageAtlas = class {
23793
23897
  constructor(icons, patterns) {
23794
23898
  const iconPositions = {}, patternPositions = {};
23795
23899
  this.haveRenderCallbacks = [];
23900
+ this.patchedUpdateVersion = -1;
23796
23901
  const bins = [];
23797
23902
  this.addImages(icons, iconPositions, bins);
23798
23903
  this.addImages(patterns, patternPositions, bins);
@@ -23883,12 +23988,26 @@ var ImageAtlas = class {
23883
23988
  if (src.hasRenderCallback) this.haveRenderCallbacks.push(id);
23884
23989
  }
23885
23990
  }
23991
+ /**
23992
+ * Brings this atlas' texture back in sync with the images it was built from, re-uploading the
23993
+ * ones that were replaced in the meantime.
23994
+ *
23995
+ * This runs for every in-view tile on every frame, so the common case of nothing having
23996
+ * changed has to cost nothing: a single comparison against {@link ImageManager.updateVersion}
23997
+ * ends the call. When something did change, only the images this atlas actually holds are
23998
+ * looked at - a handful per tile - and {@link ImageAtlas.patchUpdatedImage} then skips the
23999
+ * ones whose version still matches, leaving just the genuinely stale ones to upload.
24000
+ *
24001
+ * The render callbacks are dispatched first because they may update images themselves, and
24002
+ * those updates have to be part of the version this call catches up with - otherwise an
24003
+ * animated image would always be uploaded a frame late.
24004
+ */
23886
24005
  patchUpdatedImages(imageManager, texture) {
23887
24006
  imageManager.dispatchRenderCallbacks(this.haveRenderCallbacks);
23888
- for (const name in imageManager.updatedImages) {
23889
- this.patchUpdatedImage(this.iconPositions[name], imageManager.getImage(name), texture);
23890
- this.patchUpdatedImage(this.patternPositions[name], imageManager.getImage(name), texture);
23891
- }
24007
+ if (this.patchedUpdateVersion === imageManager.updateVersion) return;
24008
+ this.patchedUpdateVersion = imageManager.updateVersion;
24009
+ for (const name in this.iconPositions) this.patchUpdatedImage(this.iconPositions[name], imageManager.getImage(name), texture);
24010
+ for (const name in this.patternPositions) this.patchUpdatedImage(this.patternPositions[name], imageManager.getImage(name), texture);
23892
24011
  }
23893
24012
  patchUpdatedImage(position, image, texture) {
23894
24013
  if (!position || !image) return;
@@ -25580,102 +25699,6 @@ function compareTileId(a, b) {
25580
25699
  register("CanonicalTileID", CanonicalTileID);
25581
25700
  register("OverscaledTileID", OverscaledTileID, { omit: ["terrainRttPosMatrix32f"] });
25582
25701
  //#endregion
25583
- //#region src/geo/bounds.ts
25584
- /** A 2-d bounding box covering an X and Y range. */
25585
- var Bounds = class Bounds {
25586
- constructor() {
25587
- this.minX = Infinity;
25588
- this.maxX = -Infinity;
25589
- this.minY = Infinity;
25590
- this.maxY = -Infinity;
25591
- }
25592
- /**
25593
- * Expands this bounding box to include point.
25594
- *
25595
- * @param point - The point to include in this bounding box
25596
- * @returns This mutated bounding box
25597
- */
25598
- extend(point) {
25599
- this.minX = Math.min(this.minX, point.x);
25600
- this.minY = Math.min(this.minY, point.y);
25601
- this.maxX = Math.max(this.maxX, point.x);
25602
- this.maxY = Math.max(this.maxY, point.y);
25603
- return this;
25604
- }
25605
- /**
25606
- * Expands this bounding box by a fixed amount in each direction.
25607
- *
25608
- * @param amount - The amount to expand the box by, or contract if negative
25609
- * @returns This mutated bounding box
25610
- */
25611
- expandBy(amount) {
25612
- this.minX -= amount;
25613
- this.minY -= amount;
25614
- this.maxX += amount;
25615
- this.maxY += amount;
25616
- if (this.minX > this.maxX || this.minY > this.maxY) {
25617
- this.minX = Infinity;
25618
- this.maxX = -Infinity;
25619
- this.minY = Infinity;
25620
- this.maxY = -Infinity;
25621
- }
25622
- return this;
25623
- }
25624
- /**
25625
- * Shrinks this bounding box by a fixed amount in each direction.
25626
- *
25627
- * @param amount - The amount to shrink the box by
25628
- * @returns This mutated bounding box
25629
- */
25630
- shrinkBy(amount) {
25631
- return this.expandBy(-amount);
25632
- }
25633
- /**
25634
- * Returns a new bounding box that contains all of the corners of this bounding
25635
- * box with a transform applied. Does not modify this bounding box.
25636
- *
25637
- * @param fn - The function to apply to each corner
25638
- * @returns A new bounding box containing all of the mapped points.
25639
- */
25640
- map(fn) {
25641
- const result = new Bounds();
25642
- result.extend(fn(new Point(this.minX, this.minY)));
25643
- result.extend(fn(new Point(this.maxX, this.minY)));
25644
- result.extend(fn(new Point(this.minX, this.maxY)));
25645
- result.extend(fn(new Point(this.maxX, this.maxY)));
25646
- return result;
25647
- }
25648
- /**
25649
- * Creates a new bounding box that includes all points provided.
25650
- *
25651
- * @param points - The points to include inside the bounding box
25652
- * @returns The new bounding box
25653
- */
25654
- static fromPoints(points) {
25655
- const result = new Bounds();
25656
- for (const p of points) result.extend(p);
25657
- return result;
25658
- }
25659
- contains(point) {
25660
- return point.x >= this.minX && point.x <= this.maxX && point.y >= this.minY && point.y <= this.maxY;
25661
- }
25662
- empty() {
25663
- return this.minX > this.maxX;
25664
- }
25665
- width() {
25666
- return this.maxX - this.minX;
25667
- }
25668
- height() {
25669
- return this.maxY - this.minY;
25670
- }
25671
- covers(other) {
25672
- return !this.empty() && !other.empty() && other.minX >= this.minX && other.maxX <= this.maxX && other.minY >= this.minY && other.maxY <= this.maxY;
25673
- }
25674
- intersects(other) {
25675
- return !this.empty() && !other.empty() && other.minX <= this.maxX && other.maxX >= this.minX && other.minY <= this.maxY && other.maxY >= this.minY;
25676
- }
25677
- };
25678
- //#endregion
25679
25702
  //#region node_modules/@maplibre/vt-pbf/dist/index.es.js
25680
25703
  var FeatureWrapper = class {
25681
25704
  constructor(feature, extent) {
@@ -31448,6 +31471,6 @@ function anchorIsTooClose(bucket, text, repeatDistance, anchor) {
31448
31471
  return false;
31449
31472
  }
31450
31473
  //#endregion
31451
- export { projectToWorldCoordinates as $, defaultEasing as $n, add$4 as $r, Transitionable as $t, getOverlapMode as A, rotateZ$3 as Ai, makeRequest as An, rollPitchBearingEqual as Ar, Uniform1f as At, parseGlyphPbf as B, offscreenCanvasSupported as Bi, MAX_VALID_LATITUDE as Bn, zoomScale as Br, CollisionBoxArray as Bt, createStyleLayer as C, identity$2 as Ci, Evented as Cn, parseCacheControl as Cr, isHeatmapStyleLayer as Ct, isSymbolStyleLayer as D, perspective as Di, getJSON as Dn, rayPlaneIntersection as Dr, isCircleStyleLayer as Dt, isBackgroundStyleLayer as E, ortho as Ei, getArrayBuffer as En, radiansToDegrees as Er, RGBAImage as Et, ImageAtlas as F, create$8 as Fi, config as Fn, threePlaneIntersection as Fr, UniformColor as Ft, GeoJSONVT as G, clamp$2 as Gn, scale as Gr, QuadTriangleArray as Gt, collisionCircleLayout as H, arrayBufferToImage as Hn, EXTENT$1 as Hr, LineStripIndexArray as Ht, ImagePosition as I, determinant$3 as Ii, AbortError as In, translatePosition as Ir, UniformColorArray as It, calculateTileMatrix as J, createIdentityMat4f64 as Jn, fromEuler as Jr, createLayout as Jt, isFillExtrusionStyleLayer as K, clone as Kn, sqrLen as Kr, RasterBoundsArray as Kt, potpack as L, invert$5 as Li, isAbortError as Ln, uniqueId as Lr, UniformFloatArray as Lt, evaluateSizeForZoom as M, translate$2 as Mi, addProtocol as Mn, scaleZoom as Mr, Uniform2f as Mt, WritingMode as N, create$6 as Ni, getProtocol as Nn, sphericalToCartesian as Nr, Uniform3f as Nt, SymbolBucket as O, rotateX$3 as Oi, getReferrer as On, readImageUsingVideoFrame as Or, polygonIntersectsPolygon as Ot, getAnchorAlignment as P, fromRotation$2 as Pi, removeProtocol as Pn, subscribe as Pr, Uniform4f as Pt, maxMercatorHorizonAngle as Q, deepEqual$1 as Qn, transformMat4$1 as Qr, TRANSITION_SUFFIX as Qt, isStyleImageWebGLData as R, rotate$4 as Ri, throwIfAborted as Rn, warnOnce as Rr, UniformMatrix4f as Rt, Actor as S, fromScaling as Si, Event as Sn, nextPowerOfTwo as Sr, HEATMAP_FULL_RENDER_FBO_KEY as St, validateCustomStyleLayer as T, multiply$5 as Ti, GLOBAL_DISPATCHER_ID as Tn, pointPlaneSignedDistance as Tr, AlphaImage as Tt, isLineStyleLayer as U, arrayBufferToImageBitmap as Un, create as Ur, Pos3dArray as Ut, PbfReader as V, Point as Vi, angleToRotateBetweenVectors2D as Vn, pixelsToTileUnits as Vr, CollisionCircleLayoutArray as Vt, LineBucket as W, bezier as Wn, length as Wr, PosArray as Wt, cameraMercatorCoordinateFromCenterAndRotation as X, createVec3f64 as Xn, mul$3 as Xr, DataConstantProperty as Xt, cameraDirectionFromPitchBearing as Y, createMat4f64 as Yn, slerp as Yr, isRasterStyleLayer as Yt, getMercatorHorizon as Z, createVec4f64 as Zn, scale$3 as Zr, Properties as Zt, OverscaledTileID as _, clone$6 as _i, featureFilter as _n, isTouchableOrPointableType as _r, SubdivisionGranularitySetting as _t, clipLine as a, negate$2 as ai, SPEC_SOURCE_TYPES as an, extend as ar, lngFromMercatorX as at, compareTileId as b, equals$6 as bi, latest as bn, mapObject as br, Texture as bt, FeatureIndex as c, rotateY$2 as ci, validateStyle as cn, getAABB as cr, mercatorZfromAltitude as ct, DictionaryCoder as d, scaleAndAdd$2 as di, ProjectionDefinition as dn, getImageData as dr, VectorTile as dt, clone$5 as ei, EvaluationParameters as en, degreesToRadians as er, tileCoordinatesToMercatorCoordinates as et, GEOJSON_TILE_LAYER_NAME as f, sub$2 as fi, ValidationError as fn, getRollPitchBearing as fr, isFillStyleLayer as ft, CanonicalTileID as g, zero$2 as gi, emptyStyle as gn, isTouchableEvent as gr, SubdivisionGranularityExpression as gt, Bounds as h, transformQuat$1 as hi, diff as hn, isSafari as hr, SOUTH_POLE_Y as ht, clipGeometry as i, length$4 as ii, register as in, evaluateZoomSnap as ir, latFromMercatorY as it, evaluateSizeForFeature as j, scale$5 as ji, sameOrigin as jn, rollPitchBearingToQuat as jr, Uniform1i as jt, addDynamicAttributes as k, rotateY$3 as ki, getVideo as kn, remapSaturate as kr, toEvaluationFeature as kt, MLTVectorTile as l, rotateZ$2 as li, validateStyleAndEmit as ln, getAngleDelta as lr, LngLat as lt, fromVectorTileJs as m, transformMat4$2 as mi, derefLayers as mn, isPointableEvent as mr, NORTH_POLE_Y as mt, performSymbolLayout as n, dot$5 as ni, codePointUsesLocalIdeographFontFamily as nn, distanceOfAnglesRadians as nr, MercatorCoordinate as nt, BoundedLRUCache as o, normalize$4 as oi, emitValidationErrors as on, filterObject as or, mercatorXfromLng as ot, GeoJSONWrapper as p, transformMat3$1 as pi, createExpression as pn, isImageBitmap as pr, FillBucket as pt, FillExtrusionBucket as q, createIdentityMat4f32 as qn, zero as qr, TriangleIndexArray as qt, TextAnchorEnum as r, len$4 as ri, ZoomHistory as rn, ensureError as rr, altitudeFromMercatorZ as rt, TileCache as s, rotateX$2 as si, validateAndEmit as sn, findLineIntersection as sr, mercatorYfromLat as st, getAnchorJustification as t, cross$2 as ti, rtlWorkerPlugin as tn, differenceOfAnglesDegrees as tr, unprojectFromWorldCoordinates as tt, GeoJSONFeature as u, scale$4 as ui, Color as un, getEdgeTiles as ur, earthRadius as ut, UnwrappedTileID as v, copy$5 as vi, groupByLayout as vn, isWorker as vr, isColorReliefStyleLayer as vt, isCustomStyleLayer as w, invert$2 as wi, AJAXError as wn, pick as wr, renderColorRamp as wt, isInBoundsForZoomLngLat as x, exactEquals$5 as xi, ErrorEvent as xn, mod as xr, isHillshadeStyleLayer as xt, calculateTileKey as y, create$5 as yi, interpolateFactory as yn, lerp as yr, DEMData as yt, renderStyleImage as z, isOffscreenCanvasDistorted as zi, JSON_PREFIX as zn, wrap$1 as zr, SegmentVector as zt };
31474
+ export { tileCoordinatesToMercatorCoordinates as $, deepEqual$1 as $n, mul$3 as $r, TRANSITION_SUFFIX as $t, evaluateSizeForFeature as A, perspective as Ai, getVideo as An, remapSaturate as Ar, toEvaluationFeature as At, PbfReader as B, invert$5 as Bi, JSON_PREFIX as Bn, wrap$1 as Br, SegmentVector as Bt, isCustomStyleLayer as C, equals$6 as Ci, Event as Cn, nextPowerOfTwo as Cr, HEATMAP_FULL_RENDER_FBO_KEY as Ct, SymbolBucket as D, invert$2 as Di, getArrayBuffer as Dn, radiansToDegrees as Dr, RGBAImage as Dt, isSymbolStyleLayer as E, identity$2 as Ei, GLOBAL_DISPATCHER_ID as En, pointPlaneSignedDistance as Er, AlphaImage as Et, ImagePosition as F, translate$2 as Fi, removeProtocol as Fn, subscribe as Fr, Uniform4f as Ft, isFillExtrusionStyleLayer as G, bezier as Gn, length as Gr, PosArray as Gt, isLineStyleLayer as H, isOffscreenCanvasDistorted as Hi, angleToRotateBetweenVectors2D as Hn, pixelsToTileUnits as Hr, CollisionCircleLayoutArray as Ht, potpack as I, create$6 as Ii, config as In, threePlaneIntersection as Ir, UniformColor as It, cameraDirectionFromPitchBearing as J, createIdentityMat4f32 as Jn, zero as Jr, TriangleIndexArray as Jt, FillExtrusionBucket as K, clamp$2 as Kn, scale as Kr, QuadTriangleArray as Kt, isStyleImageWebGLData as L, fromRotation$2 as Li, AbortError as Ln, translatePosition as Lr, UniformColorArray as Lt, WritingMode as M, rotateY$3 as Mi, sameOrigin as Mn, rollPitchBearingToQuat as Mr, Uniform1i as Mt, getAnchorAlignment as N, rotateZ$3 as Ni, addProtocol as Nn, scaleZoom as Nr, Uniform2f as Nt, addDynamicAttributes as O, multiply$5 as Oi, getJSON as On, rayPlaneIntersection as Or, isCircleStyleLayer as Ot, ImageAtlas as P, scale$5 as Pi, getProtocol as Pn, sphericalToCartesian as Pr, Uniform3f as Pt, projectToWorldCoordinates as Q, createVec4f64 as Qn, slerp as Qr, Properties as Qt, renderStyleImage as R, create$8 as Ri, isAbortError as Rn, uniqueId as Rr, UniformFloatArray as Rt, createStyleLayer as S, create$5 as Si, ErrorEvent as Sn, mod as Sr, isHillshadeStyleLayer as St, isBackgroundStyleLayer as T, fromScaling as Ti, AJAXError as Tn, pick as Tr, renderColorRamp as Tt, LineBucket as U, offscreenCanvasSupported as Ui, arrayBufferToImage as Un, EXTENT$1 as Ur, LineStripIndexArray as Ut, collisionCircleLayout as V, rotate$4 as Vi, MAX_VALID_LATITUDE as Vn, zoomScale as Vr, CollisionBoxArray as Vt, GeoJSONVT as W, Point as Wi, arrayBufferToImageBitmap as Wn, create as Wr, Pos3dArray as Wt, getMercatorHorizon as X, createMat4f64 as Xn, fromValues$2 as Xr, isRasterStyleLayer as Xt, cameraMercatorCoordinateFromCenterAndRotation as Y, createIdentityMat4f64 as Yn, fromEuler as Yr, createLayout as Yt, maxMercatorHorizonAngle as Z, createVec3f64 as Zn, multiply$2 as Zr, DataConstantProperty as Zt, UnwrappedTileID as _, transformMat4$2 as _i, emptyStyle as _n, isTouchableEvent as _r, SubdivisionGranularityExpression as _t, clipLine as a, dot$5 as ai, register as an, evaluateZoomSnap as ar, mercatorXfromLng as at, isInBoundsForZoomLngLat as b, clone$6 as bi, interpolateFactory as bn, lerp as br, DEMData as bt, FeatureIndex as c, negate$2 as ci, validateAndEmit as cn, findLineIntersection as cr, LngLat as ct, DictionaryCoder as d, rotateY$2 as di, Color as dn, getEdgeTiles as dr, EXTENT_BOUNDS as dt, scale$3 as ei, Transitionable as en, defaultEasing as er, unprojectFromWorldCoordinates as et, GEOJSON_TILE_LAYER_NAME as f, rotateZ$2 as fi, ProjectionDefinition as fn, getImageData as fr, Bounds as ft, OverscaledTileID as g, transformMat3$1 as gi, diff as gn, isSafari as gr, SOUTH_POLE_Y as gt, CanonicalTileID as h, sub$2 as hi, derefLayers as hn, isPointableEvent as hr, NORTH_POLE_Y as ht, clipGeometry as i, cross$2 as ii, ZoomHistory as in, ensureError as ir, lngFromMercatorX as it, evaluateSizeForZoom as j, rotateX$3 as ji, makeRequest as jn, rollPitchBearingEqual as jr, Uniform1f as jt, getOverlapMode as k, ortho as ki, getReferrer as kn, readImageUsingVideoFrame as kr, polygonIntersectsPolygon as kt, MLTVectorTile as l, normalize$4 as li, validateStyle as ln, getAABB as lr, earthRadius as lt, fromVectorTileJs as m, scaleAndAdd$2 as mi, createExpression as mn, isImageBitmap as mr, FillBucket as mt, performSymbolLayout as n, add$4 as ni, rtlWorkerPlugin as nn, differenceOfAnglesDegrees as nr, altitudeFromMercatorZ as nt, BoundedLRUCache as o, len$4 as oi, SPEC_SOURCE_TYPES as on, extend as or, mercatorYfromLat as ot, GeoJSONWrapper as p, scale$4 as pi, ValidationError as pn, getRollPitchBearing as pr, isFillStyleLayer as pt, calculateTileMatrix as q, clone as qn, sqrLen as qr, RasterBoundsArray as qt, TextAnchorEnum as r, clone$5 as ri, codePointUsesLocalIdeographFontFamily as rn, distanceOfAnglesRadians as rr, latFromMercatorY as rt, TileCache as s, length$4 as si, emitValidationErrors as sn, filterObject as sr, mercatorZfromAltitude as st, getAnchorJustification as t, transformMat4$1 as ti, EvaluationParameters as tn, degreesToRadians as tr, MercatorCoordinate as tt, GeoJSONFeature as u, rotateX$2 as ui, validateStyleAndEmit as un, getAngleDelta as ur, VectorTile as ut, calculateTileKey as v, transformQuat$1 as vi, featureFilter as vn, isTouchableOrPointableType as vr, SubdivisionGranularitySetting as vt, validateCustomStyleLayer as w, exactEquals$5 as wi, Evented as wn, parseCacheControl as wr, isHeatmapStyleLayer as wt, Actor as x, copy$5 as xi, latest as xn, mapObject as xr, Texture as xt, compareTileId as y, zero$2 as yi, groupByLayout as yn, isWorker as yr, isColorReliefStyleLayer as yt, parseGlyphPbf as z, determinant$3 as zi, throwIfAborted as zn, warnOnce as zr, UniformMatrix4f as zt };
31452
31475
 
31453
31476
  //# sourceMappingURL=maplibre-gl-shared-dev.mjs.map