@tileflow/core 0.1.0-alpha.43 → 0.1.0-alpha.44
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.
- package/README.md +5 -0
- package/THIRD_PARTY_NOTICES.md +2 -2
- package/dist/3d.js +124 -28
- package/dist/browser.js +153 -56
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -267,6 +267,11 @@ under the camera, read chosen layers of a vector source for an area at a fixed z
|
|
|
267
267
|
Browser 3D scenes support `camera.adaptivePerspective`: caller override,
|
|
268
268
|
map default, then `false`. Streets enables it. Depth markers let buildings
|
|
269
269
|
occlude application markers.
|
|
270
|
+
Custom 3D layers load visible ground from the bottom of the viewport towards the horizon before
|
|
271
|
+
spending tiles offscreen. Buildings fade down at the far boundary, across the view's width, and
|
|
272
|
+
distance haze follows that boundary. Coverage follows the viewport and its projection on resize,
|
|
273
|
+
within each layer's `maxTiles` budget (25 by default); views exceeding that budget still have
|
|
274
|
+
bounded coverage, with the nearest ground taking priority.
|
|
270
275
|
Model roles use `modelLighting` for independent colours and materials. `colorScale` (0–1,
|
|
271
276
|
default 1) subtly darkens a role after recolouring. Map-shaded models share the buildings’
|
|
272
277
|
vertical/contact gradient; physical roles keep their own lighting. Model corner geometry is
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Third-party notices
|
|
2
2
|
|
|
3
|
-
`@tileflow/core/browser` embeds `maplibre-contour` 0.1.
|
|
3
|
+
`@tileflow/core/browser` embeds `maplibre-contour` 0.1.1, `PMTiles` 4.5.0, `fflate` 0.8.3, and
|
|
4
4
|
`earcut` 3.2.4 so contour, local archive, and 3D building rendering remain self-contained.
|
|
5
5
|
`@tileflow/core` and `@tileflow/core/browser` embed the decoder of `meshoptimizer` 1.3.0, loaded
|
|
6
6
|
only to read a compressed 3D model file. The complete upstream licenses follow.
|
|
7
7
|
|
|
8
|
-
## maplibre-contour 0.1.
|
|
8
|
+
## maplibre-contour 0.1.1
|
|
9
9
|
|
|
10
10
|
BSD 3-Clause License
|
|
11
11
|
|
package/dist/3d.js
CHANGED
|
@@ -2553,11 +2553,11 @@ var growth = `
|
|
|
2553
2553
|
uniform float u_scale;
|
|
2554
2554
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
2555
2555
|
uniform float u_metres; // metres per tile unit
|
|
2556
|
-
//
|
|
2557
|
-
//
|
|
2558
|
-
// ground, in this tile's axes.
|
|
2556
|
+
// In this tile's units: origin and start/end of the fade along the view, or centre and radii of the
|
|
2557
|
+
// fallback covered disc. The direction is along the ground in this tile's axes.
|
|
2559
2558
|
uniform vec4 u_ring;
|
|
2560
2559
|
uniform vec2 u_ring_ahead;
|
|
2560
|
+
uniform bool u_ring_directional;
|
|
2561
2561
|
|
|
2562
2562
|
float progressOf() {
|
|
2563
2563
|
return clamp(u_scale * 1.25 - a_wave.x * 0.25, 0.0, 1.0);
|
|
@@ -2569,9 +2569,11 @@ float elevationOf(float own, float top, float p) {
|
|
|
2569
2569
|
}
|
|
2570
2570
|
|
|
2571
2571
|
// Buildings sink into the ground over the last stretch of the city's reach, so it ends without an
|
|
2572
|
-
// edge of cut-off blocks.
|
|
2573
|
-
//
|
|
2572
|
+
// edge of cut-off blocks. The view-aligned fade leaves the entire near width standing; the legacy
|
|
2573
|
+
// disc fallback also exempts its near side.
|
|
2574
2574
|
float reachOf(vec2 position) {
|
|
2575
|
+
if (u_ring_directional)
|
|
2576
|
+
return 1.0 - smoothstep(u_ring.z, u_ring.w, dot(position - u_ring.xy, u_ring_ahead));
|
|
2575
2577
|
if (u_ring.w <= 0.0) return 1.0;
|
|
2576
2578
|
vec2 from = position - u_ring.xy;
|
|
2577
2579
|
float far = smoothstep(0.0, u_ring.w - u_ring.z, dot(from, u_ring_ahead));
|
|
@@ -5665,7 +5667,8 @@ function createCameraTiles(options) {
|
|
|
5665
5667
|
const chosen = cameraTileRing(
|
|
5666
5668
|
{ ...centre, zoom: currentZoom, pitch: map.getPitch(), bearing: map.getBearing() },
|
|
5667
5669
|
zoom,
|
|
5668
|
-
options.maxTiles
|
|
5670
|
+
options.maxTiles,
|
|
5671
|
+
cameraViewport(map, zoom)
|
|
5669
5672
|
);
|
|
5670
5673
|
ring = chosen;
|
|
5671
5674
|
wanted = chosen.tiles.map(({ x: x3, y: y2 }) => `${x3}/${y2}`);
|
|
@@ -5677,7 +5680,7 @@ function createCameraTiles(options) {
|
|
|
5677
5680
|
return;
|
|
5678
5681
|
}
|
|
5679
5682
|
const now = performance.now();
|
|
5680
|
-
for (const { x: x3, y: y2
|
|
5683
|
+
for (const [priority, { x: x3, y: y2 }] of chosen.tiles.entries()) {
|
|
5681
5684
|
const key = `${x3}/${y2}`;
|
|
5682
5685
|
let entry = tiles.get(key);
|
|
5683
5686
|
if (!entry) {
|
|
@@ -5685,7 +5688,7 @@ function createCameraTiles(options) {
|
|
|
5685
5688
|
tiles.set(key, entry);
|
|
5686
5689
|
}
|
|
5687
5690
|
entry.used = now;
|
|
5688
|
-
entry.
|
|
5691
|
+
entry.priority = priority;
|
|
5689
5692
|
if ((!entry.value && !entry.pending || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
5690
5693
|
load(source, key, entry, chosen.tileMetres);
|
|
5691
5694
|
}
|
|
@@ -5698,7 +5701,7 @@ function createCameraTiles(options) {
|
|
|
5698
5701
|
entry.retryAt = void 0;
|
|
5699
5702
|
source.read(
|
|
5700
5703
|
{ z: zoom, x: entry.x, y: entry.y },
|
|
5701
|
-
{ signal: controller.signal, priority: entry.
|
|
5704
|
+
{ signal: controller.signal, priority: entry.priority ?? 0 }
|
|
5702
5705
|
).then((tile) => {
|
|
5703
5706
|
if (disposed || tiles.get(key) !== entry || entry.loading !== controller) return;
|
|
5704
5707
|
if (!tile) {
|
|
@@ -5733,14 +5736,14 @@ function createCameraTiles(options) {
|
|
|
5733
5736
|
while (!disposed && queue.length && performance.now() - started < buildBudgetMs) {
|
|
5734
5737
|
let nearest = 0;
|
|
5735
5738
|
for (let at = 1; at < queue.length; at += 1)
|
|
5736
|
-
if ((queue[at].entry.
|
|
5739
|
+
if ((queue[at].entry.priority ?? 0) < (queue[nearest].entry.priority ?? 0))
|
|
5737
5740
|
nearest = at;
|
|
5738
5741
|
const { key, entry, controller, tile, metres: tileMetres } = queue.splice(nearest, 1)[0];
|
|
5739
5742
|
const current = () => !disposed && tiles.get(key) === entry && entry.loading === controller && !controller.signal.aborted;
|
|
5740
5743
|
if (!current()) continue;
|
|
5741
5744
|
let value;
|
|
5742
5745
|
try {
|
|
5743
|
-
value = await options.build(tile, tileMetres, controller.signal, entry.
|
|
5746
|
+
value = await options.build(tile, tileMetres, controller.signal, entry.priority ?? 0);
|
|
5744
5747
|
} catch {
|
|
5745
5748
|
if (current()) {
|
|
5746
5749
|
entry.loading = void 0;
|
|
@@ -5810,6 +5813,7 @@ function createCameraTiles(options) {
|
|
|
5810
5813
|
map.on("sourcedata", onSource);
|
|
5811
5814
|
map.on("move", onMove);
|
|
5812
5815
|
map.on("moveend", onMoveEnd);
|
|
5816
|
+
map.on("resize", onMoveEnd);
|
|
5813
5817
|
return {
|
|
5814
5818
|
update,
|
|
5815
5819
|
ready() {
|
|
@@ -5864,6 +5868,7 @@ function createCameraTiles(options) {
|
|
|
5864
5868
|
map.off("sourcedata", onSource);
|
|
5865
5869
|
map.off("move", onMove);
|
|
5866
5870
|
map.off("moveend", onMoveEnd);
|
|
5871
|
+
map.off("resize", onMoveEnd);
|
|
5867
5872
|
for (const entry of tiles.values()) {
|
|
5868
5873
|
entry.loading?.abort();
|
|
5869
5874
|
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
@@ -5931,33 +5936,110 @@ function cameraFrame(callback) {
|
|
|
5931
5936
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(callback);
|
|
5932
5937
|
else setTimeout(callback, 16);
|
|
5933
5938
|
}
|
|
5934
|
-
function cameraTileRing(camera, tileZoom, maxTiles) {
|
|
5939
|
+
function cameraTileRing(camera, tileZoom, maxTiles, viewport) {
|
|
5935
5940
|
const reach = Math.min(
|
|
5936
5941
|
5e3,
|
|
5937
5942
|
Math.max(800, 1600 * 2 ** (16 - camera.zoom) * (1 + camera.pitch / 60))
|
|
5938
5943
|
);
|
|
5939
5944
|
const bearing = camera.bearing * Math.PI / 180;
|
|
5945
|
+
const direction = [Math.sin(bearing), -Math.cos(bearing)];
|
|
5940
5946
|
const ahead = reach * 0.35 * Math.min(1, camera.pitch / 60);
|
|
5941
5947
|
const latitude = camera.lat + Math.cos(bearing) * ahead / 111320;
|
|
5942
5948
|
const longitude = camera.lng + Math.sin(bearing) * ahead / (111320 * Math.cos(camera.lat * Math.PI / 180));
|
|
5943
5949
|
const [cx, cy] = cameraTileAt(longitude, latitude, tileZoom);
|
|
5944
|
-
const
|
|
5950
|
+
const [ox, oy] = cameraTileAt(camera.lng, camera.lat, tileZoom);
|
|
5951
|
+
const tileMetres = earth * Math.cos(camera.lat * Math.PI / 180) / 2 ** tileZoom;
|
|
5952
|
+
const far = (reach + ahead) / tileMetres;
|
|
5953
|
+
const along = ([x3, y2]) => (x3 - ox) * direction[0] + (y2 - oy) * direction[1];
|
|
5954
|
+
const visible = viewport && clipGround(viewport, (point) => far - along(point));
|
|
5945
5955
|
const span = Math.ceil(reach / tileMetres);
|
|
5956
|
+
const left = Math.floor(Math.min(cx - span, ...visible?.map(([x3]) => x3) ?? []));
|
|
5957
|
+
const right = Math.floor(Math.max(cx + span, ...visible?.map(([x3]) => x3) ?? []));
|
|
5958
|
+
const top = Math.floor(Math.min(cy - span, ...visible?.map(([, y2]) => y2) ?? []));
|
|
5959
|
+
const bottom = Math.floor(Math.max(cy + span, ...visible?.map(([, y2]) => y2) ?? []));
|
|
5946
5960
|
const candidates = [];
|
|
5947
|
-
for (let
|
|
5948
|
-
for (let
|
|
5949
|
-
const
|
|
5950
|
-
|
|
5951
|
-
const
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5961
|
+
for (let x3 = left; x3 <= right; x3++)
|
|
5962
|
+
for (let y2 = top; y2 <= bottom; y2++) {
|
|
5963
|
+
const distance = Math.hypot(Math.max(x3 - cx, 0, cx - x3 - 1), Math.max(y2 - cy, 0, cy - y2 - 1));
|
|
5964
|
+
let intersection = visible ?? [];
|
|
5965
|
+
for (const boundary of [
|
|
5966
|
+
([px]) => px - x3,
|
|
5967
|
+
([px]) => x3 + 1 - px,
|
|
5968
|
+
([, py]) => py - y2,
|
|
5969
|
+
([, py]) => y2 + 1 - py
|
|
5970
|
+
])
|
|
5971
|
+
intersection = clipGround(intersection, boundary);
|
|
5972
|
+
const near2 = Math.min(...intersection.map(along));
|
|
5973
|
+
if (near2 < Infinity || distance * tileMetres <= reach)
|
|
5974
|
+
candidates.push({ x: x3, y: y2, distance, near: near2 });
|
|
5975
|
+
}
|
|
5976
|
+
candidates.sort((a, b2) => a.near - b2.near || a.distance - b2.distance);
|
|
5977
|
+
const tiles = candidates.slice(0, maxTiles).map(({ x: x3, y: y2, distance }) => ({ x: x3, y: y2, distance }));
|
|
5978
|
+
const omitted = candidates.slice(tiles.length);
|
|
5979
|
+
const radius = omitted.reduce(
|
|
5980
|
+
(radius2, tile) => Math.min(radius2, tile.distance),
|
|
5981
|
+
reach / tileMetres
|
|
5982
|
+
);
|
|
5983
|
+
const end = Math.min(far, ...omitted.map((tile) => tile.near));
|
|
5984
|
+
const near = visible?.length ? Math.min(...visible.map(along)) : end;
|
|
5985
|
+
return {
|
|
5986
|
+
tiles,
|
|
5987
|
+
centre: [cx, cy],
|
|
5988
|
+
radius,
|
|
5989
|
+
tileMetres,
|
|
5990
|
+
...visible?.length ? {
|
|
5991
|
+
fade: {
|
|
5992
|
+
origin: [ox, oy],
|
|
5993
|
+
start: end - Math.max(0.25, (end - near) * 0.2),
|
|
5994
|
+
end
|
|
5995
|
+
}
|
|
5996
|
+
} : {}
|
|
5997
|
+
};
|
|
5998
|
+
}
|
|
5999
|
+
function cameraViewport(map, zoom) {
|
|
6000
|
+
const canvas = map.getCanvas?.();
|
|
6001
|
+
const width = canvas?.clientWidth ?? 0;
|
|
6002
|
+
const height = canvas?.clientHeight ?? 0;
|
|
6003
|
+
if (!map.unproject || width <= 0 || height <= 0) return void 0;
|
|
6004
|
+
const origin = cameraTileAt(map.getCenter().lng, map.getCenter().lat, zoom)[0];
|
|
6005
|
+
const world = 2 ** zoom;
|
|
6006
|
+
const pointAt = (x3, y2) => {
|
|
6007
|
+
const location = map.unproject([x3, y2]);
|
|
6008
|
+
const [tx, ty] = cameraTileAt(location.lng, location.lat, zoom);
|
|
6009
|
+
return [tx + Math.round((origin - tx) / world) * world, ty];
|
|
6010
|
+
};
|
|
6011
|
+
const bearing = map.getBearing() * Math.PI / 180;
|
|
6012
|
+
const points = [];
|
|
6013
|
+
for (const x3 of [0, width]) {
|
|
6014
|
+
const bottom = pointAt(x3, height);
|
|
6015
|
+
const middle = pointAt(x3, height / 2);
|
|
6016
|
+
let top = pointAt(x3, 0);
|
|
6017
|
+
if ((top[0] - middle[0]) * Math.sin(bearing) - (top[1] - middle[1]) * Math.cos(bearing) <= 0) {
|
|
6018
|
+
const stretch = world / Math.hypot(middle[0] - bottom[0], middle[1] - bottom[1]);
|
|
6019
|
+
top = [
|
|
6020
|
+
middle[0] + (middle[0] - bottom[0]) * stretch,
|
|
6021
|
+
middle[1] + (middle[1] - bottom[1]) * stretch
|
|
6022
|
+
];
|
|
6023
|
+
}
|
|
6024
|
+
points.push(bottom, top);
|
|
6025
|
+
}
|
|
6026
|
+
if (points.some((point) => point.some((value) => !Number.isFinite(value)))) return void 0;
|
|
6027
|
+
return [points[0], points[1], points[3], points[2]];
|
|
6028
|
+
}
|
|
6029
|
+
function clipGround(points, distance) {
|
|
6030
|
+
const result = [];
|
|
6031
|
+
for (let i2 = 0; i2 < points.length; i2++) {
|
|
6032
|
+
const a = points[i2];
|
|
6033
|
+
const b2 = points[(i2 + 1) % points.length];
|
|
6034
|
+
const da = distance(a);
|
|
6035
|
+
const db = distance(b2);
|
|
6036
|
+
if (da >= 0) result.push([a[0], a[1]]);
|
|
6037
|
+
if (da < 0 !== db < 0) {
|
|
6038
|
+
const t = da / (da - db);
|
|
6039
|
+
result.push([a[0] + (b2[0] - a[0]) * t, a[1] + (b2[1] - a[1]) * t]);
|
|
5956
6040
|
}
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
const radius = Math.min(reach / tileMetres, candidates[tiles.length]?.distance ?? Infinity);
|
|
5960
|
-
return { tiles, centre: [cx, cy], radius, tileMetres };
|
|
6041
|
+
}
|
|
6042
|
+
return result;
|
|
5961
6043
|
}
|
|
5962
6044
|
function cameraTileAt(longitude, latitude, zoom) {
|
|
5963
6045
|
const phi = Math.min(85.05, Math.max(-85.05, latitude)) * Math.PI / 180;
|
|
@@ -8505,6 +8587,7 @@ var tileflowSkyHazeReachFloor = 3;
|
|
|
8505
8587
|
var nineTenths = 0.8042;
|
|
8506
8588
|
function tileflowSkyReachDepth(view, reach) {
|
|
8507
8589
|
const sin = Math.sin(radians(view.pitch));
|
|
8590
|
+
if (reach.forward !== void 0) return 1 + reach.forward * sin;
|
|
8508
8591
|
const cos = Math.cos(radians(view.pitch));
|
|
8509
8592
|
const back = -sin;
|
|
8510
8593
|
const across = Math.atan(view.aspect * Math.tan(view.fov / 2));
|
|
@@ -8577,7 +8660,8 @@ function reachOf(map, distance) {
|
|
|
8577
8660
|
return {
|
|
8578
8661
|
ahead: (east * Math.sin(bearing) + north * Math.cos(bearing)) / metres,
|
|
8579
8662
|
across: (east * Math.cos(bearing) - north * Math.sin(bearing)) / metres,
|
|
8580
|
-
radius: reach.radius / metres
|
|
8663
|
+
radius: reach.radius / metres,
|
|
8664
|
+
...reach.forward === void 0 ? {} : { forward: reach.forward / metres }
|
|
8581
8665
|
};
|
|
8582
8666
|
}
|
|
8583
8667
|
function fovOf(map, args) {
|
|
@@ -9112,6 +9196,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9112
9196
|
context.uniform2f(program.uniforms.u_offset, ...offset);
|
|
9113
9197
|
context.uniform4f(program.uniforms.u_ring ?? null, ...ring);
|
|
9114
9198
|
context.uniform2f(program.uniforms.u_ring_ahead ?? null, ...ahead);
|
|
9199
|
+
context.uniform1i(program.uniforms.u_ring_directional ?? null, camera.ring()?.fade ? 1 : 0);
|
|
9115
9200
|
const buffers = value.gl;
|
|
9116
9201
|
context.bindVertexArray(buffers.vao);
|
|
9117
9202
|
for (const range of ranges)
|
|
@@ -9394,13 +9479,21 @@ function createTileflowBuildings3D(options) {
|
|
|
9394
9479
|
return {
|
|
9395
9480
|
lng: ring.centre[0] / n * 360 - 180,
|
|
9396
9481
|
lat: Math.atan(Math.sinh(Math.PI * (1 - 2 * ring.centre[1] / n))) * 180 / Math.PI,
|
|
9397
|
-
radius: ring.radius * ring.tileMetres
|
|
9482
|
+
radius: ring.radius * ring.tileMetres,
|
|
9483
|
+
...ring.fade ? { forward: ring.fade.end * ring.tileMetres } : {}
|
|
9398
9484
|
};
|
|
9399
9485
|
}
|
|
9400
9486
|
function ringIn(x3, y2) {
|
|
9401
9487
|
const ring = camera.ring();
|
|
9402
9488
|
if (!ring) return [0, 0, 0, 0];
|
|
9403
9489
|
const extent4 = tileflowBuildingExtent;
|
|
9490
|
+
if (ring.fade)
|
|
9491
|
+
return [
|
|
9492
|
+
(ring.fade.origin[0] - x3) * extent4,
|
|
9493
|
+
(ring.fade.origin[1] - y2) * extent4,
|
|
9494
|
+
ring.fade.start * extent4,
|
|
9495
|
+
ring.fade.end * extent4
|
|
9496
|
+
];
|
|
9404
9497
|
const cx = (ring.centre[0] - x3) * extent4;
|
|
9405
9498
|
const cy = (ring.centre[1] - y2) * extent4;
|
|
9406
9499
|
const inner = ring.radius * extent4 * 0.8;
|
|
@@ -9414,6 +9507,8 @@ function createTileflowBuildings3D(options) {
|
|
|
9414
9507
|
return [Math.sin(bearing), -Math.cos(bearing)];
|
|
9415
9508
|
}
|
|
9416
9509
|
function insideRing(ring, left, top, right, bottom) {
|
|
9510
|
+
if (camera.ring()?.fade)
|
|
9511
|
+
return Math.min(ahead[0] * (left - ring[0]), ahead[0] * (right - ring[0])) + Math.min(ahead[1] * (top - ring[1]), ahead[1] * (bottom - ring[1])) < ring[3];
|
|
9417
9512
|
const radius = ring[3];
|
|
9418
9513
|
if (!(radius > 0)) return true;
|
|
9419
9514
|
const cx = ring[0];
|
|
@@ -9631,6 +9726,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9631
9726
|
);
|
|
9632
9727
|
context.uniform4f(u.u_ring ?? null, ...ringIn(x3, y2));
|
|
9633
9728
|
context.uniform2f(u.u_ring_ahead ?? null, ...ahead);
|
|
9729
|
+
context.uniform1i(u.u_ring_directional ?? null, camera.ring()?.fade ? 1 : 0);
|
|
9634
9730
|
const palette = themes ? paletteOf(context, entry, themes.themes) : void 0;
|
|
9635
9731
|
context.uniform1f(u.u_palette_on, palette ? 1 : 0);
|
|
9636
9732
|
context.activeTexture(context.TEXTURE1);
|
package/dist/browser.js
CHANGED
|
@@ -1224,7 +1224,7 @@ var init_meshopt_decoder = __esm({
|
|
|
1224
1224
|
}
|
|
1225
1225
|
});
|
|
1226
1226
|
|
|
1227
|
-
// ../../node_modules/.pnpm/maplibre-contour@0.1.
|
|
1227
|
+
// ../../node_modules/.pnpm/maplibre-contour@0.1.1/node_modules/maplibre-contour/dist/index.mjs
|
|
1228
1228
|
var dist_exports = {};
|
|
1229
1229
|
__export(dist_exports, {
|
|
1230
1230
|
default: () => mlcontour$1
|
|
@@ -1248,7 +1248,7 @@ function define(_2, chunk) {
|
|
|
1248
1248
|
}
|
|
1249
1249
|
var shared3, worker, mlcontour, mlcontour$1;
|
|
1250
1250
|
var init_dist = __esm({
|
|
1251
|
-
"../../node_modules/.pnpm/maplibre-contour@0.1.
|
|
1251
|
+
"../../node_modules/.pnpm/maplibre-contour@0.1.1/node_modules/maplibre-contour/dist/index.mjs"() {
|
|
1252
1252
|
"use strict";
|
|
1253
1253
|
define(["exports"], (function(exports) {
|
|
1254
1254
|
"use strict";
|
|
@@ -1596,13 +1596,10 @@ var init_dist = __esm({
|
|
|
1596
1596
|
});
|
|
1597
1597
|
}
|
|
1598
1598
|
function prepareContourTile(promise) {
|
|
1599
|
-
return promise.then(({ arrayBuffer }) => {
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
transferrables: [clone]
|
|
1604
|
-
};
|
|
1605
|
-
});
|
|
1599
|
+
return promise.then(({ arrayBuffer }) => ({
|
|
1600
|
+
arrayBuffer,
|
|
1601
|
+
transferrables: [arrayBuffer]
|
|
1602
|
+
}));
|
|
1606
1603
|
}
|
|
1607
1604
|
let supportsOffscreenCanvas = null;
|
|
1608
1605
|
function offscreenCanvasSupported() {
|
|
@@ -1665,6 +1662,10 @@ var init_dist = __esm({
|
|
|
1665
1662
|
var _a2;
|
|
1666
1663
|
return Boolean((_a2 = abortController === null || abortController === void 0 ? void 0 : abortController.signal) === null || _a2 === void 0 ? void 0 : _a2.aborted);
|
|
1667
1664
|
}
|
|
1665
|
+
function parseUrl(url) {
|
|
1666
|
+
const [, z2, x3, y2] = /\/\/(\d+)\/(\d+)\/(\d+)/.exec(url) || [];
|
|
1667
|
+
return [Number(z2), Number(x3), Number(y2)];
|
|
1668
|
+
}
|
|
1668
1669
|
let num = 0;
|
|
1669
1670
|
class AsyncCache {
|
|
1670
1671
|
constructor(maxSize = 100) {
|
|
@@ -2644,9 +2645,7 @@ var init_dist = __esm({
|
|
|
2644
2645
|
function writeLayer(layer, pbf) {
|
|
2645
2646
|
if (!pbf)
|
|
2646
2647
|
throw new Error("pbf undefined");
|
|
2647
|
-
pbf.writeVarintField(15, 2);
|
|
2648
2648
|
pbf.writeStringField(1, layer.id || "");
|
|
2649
|
-
pbf.writeVarintField(5, layer.extent || 4096);
|
|
2650
2649
|
const context = {
|
|
2651
2650
|
keys: [],
|
|
2652
2651
|
values: [],
|
|
@@ -2663,6 +2662,8 @@ var init_dist = __esm({
|
|
|
2663
2662
|
for (const value of context.values) {
|
|
2664
2663
|
pbf.writeMessage(4, writeValue, value);
|
|
2665
2664
|
}
|
|
2665
|
+
pbf.writeVarintField(5, layer.extent || 4096);
|
|
2666
|
+
pbf.writeVarintField(15, 2);
|
|
2666
2667
|
}
|
|
2667
2668
|
function writeFeature(context, pbf) {
|
|
2668
2669
|
const feature = context.feature;
|
|
@@ -2911,7 +2912,7 @@ var init_dist = __esm({
|
|
|
2911
2912
|
}
|
|
2912
2913
|
fetchDem(z2, x3, y2, options, abortController, timer) {
|
|
2913
2914
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2914
|
-
const zoom = Math.min(z2 - (options.overzoom || 0), this.maxzoom);
|
|
2915
|
+
const zoom = Math.max(0, Math.min(z2 - (options.overzoom || 0), this.maxzoom));
|
|
2915
2916
|
const subZ = z2 - zoom;
|
|
2916
2917
|
const div = 1 << subZ;
|
|
2917
2918
|
const newX = Math.floor(x3 / div);
|
|
@@ -2926,7 +2927,7 @@ var init_dist = __esm({
|
|
|
2926
2927
|
return Promise.resolve({ arrayBuffer: new ArrayBuffer(0) });
|
|
2927
2928
|
}
|
|
2928
2929
|
const key = [z2, x3, y2, encodeIndividualOptions(options)].join("/");
|
|
2929
|
-
|
|
2930
|
+
const cached = this.contourCache.get(key, (_2, childAbortController) => __awaiter(this, void 0, void 0, function* () {
|
|
2930
2931
|
const max2 = 1 << z2;
|
|
2931
2932
|
const neighborPromises = [];
|
|
2932
2933
|
for (let iy = y2 - 1; iy <= y2 + 1; iy++) {
|
|
@@ -2969,8 +2970,11 @@ var init_dist = __esm({
|
|
|
2969
2970
|
}
|
|
2970
2971
|
});
|
|
2971
2972
|
mark === null || mark === void 0 ? void 0 : mark();
|
|
2972
|
-
return { arrayBuffer: result.buffer };
|
|
2973
|
+
return { arrayBuffer: result.slice().buffer };
|
|
2973
2974
|
}), parentAbortController);
|
|
2975
|
+
return cached.then(({ arrayBuffer }) => ({
|
|
2976
|
+
arrayBuffer: copy(arrayBuffer)
|
|
2977
|
+
}));
|
|
2974
2978
|
}
|
|
2975
2979
|
}
|
|
2976
2980
|
let id = 0;
|
|
@@ -3054,13 +3058,14 @@ var init_dist = __esm({
|
|
|
3054
3058
|
exports.L = LocalDemManager;
|
|
3055
3059
|
exports.T = Timer;
|
|
3056
3060
|
exports._ = __awaiter;
|
|
3057
|
-
exports.a =
|
|
3058
|
-
exports.b =
|
|
3061
|
+
exports.a = parseUrl;
|
|
3062
|
+
exports.b = decodeOptions;
|
|
3059
3063
|
exports.c = decodeParsedImage;
|
|
3060
3064
|
exports.d = defaultDecoder;
|
|
3061
3065
|
exports.e = encodeOptions;
|
|
3062
|
-
exports.f =
|
|
3066
|
+
exports.f = generateIsolines;
|
|
3063
3067
|
exports.g = getOptionsForZoom;
|
|
3068
|
+
exports.h = prepareContourTile;
|
|
3064
3069
|
exports.p = prepareDemTile;
|
|
3065
3070
|
}));
|
|
3066
3071
|
define(["./shared"], (function(actor) {
|
|
@@ -3083,7 +3088,7 @@ var init_dist = __esm({
|
|
|
3083
3088
|
};
|
|
3084
3089
|
this.fetchContourTile = (managerId, z2, x3, y2, options, abortController, timer) => {
|
|
3085
3090
|
var _a2;
|
|
3086
|
-
return actor.
|
|
3091
|
+
return actor.h(((_a2 = this.managers[managerId]) === null || _a2 === void 0 ? void 0 : _a2.fetchContourTile(z2, x3, y2, options, abortController, timer)) || noManager(managerId));
|
|
3087
3092
|
};
|
|
3088
3093
|
}
|
|
3089
3094
|
}
|
|
@@ -3152,7 +3157,7 @@ var init_dist = __esm({
|
|
|
3152
3157
|
maplibre.addProtocol(this.contourProtocolId, this.contourProtocol);
|
|
3153
3158
|
};
|
|
3154
3159
|
this.sharedDemProtocolV4 = (request, abortController) => actor._(this, void 0, void 0, function* () {
|
|
3155
|
-
const [z2, x3, y2] =
|
|
3160
|
+
const [z2, x3, y2] = actor.a(request.url);
|
|
3156
3161
|
const timer = new actor.T("main");
|
|
3157
3162
|
let timing;
|
|
3158
3163
|
try {
|
|
@@ -3175,8 +3180,8 @@ var init_dist = __esm({
|
|
|
3175
3180
|
const timer = new actor.T("main");
|
|
3176
3181
|
let timing;
|
|
3177
3182
|
try {
|
|
3178
|
-
const [z2, x3, y2] =
|
|
3179
|
-
const options = actor.
|
|
3183
|
+
const [z2, x3, y2] = actor.a(request.url);
|
|
3184
|
+
const options = actor.b(request.url);
|
|
3180
3185
|
const data = yield this.manager.fetchContourTile(z2, x3, y2, actor.g(options, z2), abortController, timer);
|
|
3181
3186
|
timing = timer.finish(request.url);
|
|
3182
3187
|
return { data: data.arrayBuffer };
|
|
@@ -3213,13 +3218,9 @@ var init_dist = __esm({
|
|
|
3213
3218
|
getDemTile(z2, x3, y2, abortController) {
|
|
3214
3219
|
return this.manager.fetchAndParseTile(z2, x3, y2, abortController || new AbortController());
|
|
3215
3220
|
}
|
|
3216
|
-
parseUrl(url) {
|
|
3217
|
-
const [, z2, x3, y2] = /\/\/(\d+)\/(\d+)\/(\d+)/.exec(url) || [];
|
|
3218
|
-
return [Number(z2), Number(x3), Number(y2)];
|
|
3219
|
-
}
|
|
3220
3221
|
}
|
|
3221
3222
|
const exported = {
|
|
3222
|
-
generateIsolines: actor.
|
|
3223
|
+
generateIsolines: actor.f,
|
|
3223
3224
|
DemSource,
|
|
3224
3225
|
HeightTile: actor.H,
|
|
3225
3226
|
LocalDemManager: actor.L,
|
|
@@ -5324,6 +5325,7 @@ var tileflowSkyHazeReachFloor = 3;
|
|
|
5324
5325
|
var nineTenths = 0.8042;
|
|
5325
5326
|
function tileflowSkyReachDepth(view, reach) {
|
|
5326
5327
|
const sin = Math.sin(radians(view.pitch));
|
|
5328
|
+
if (reach.forward !== void 0) return 1 + reach.forward * sin;
|
|
5327
5329
|
const cos = Math.cos(radians(view.pitch));
|
|
5328
5330
|
const back = -sin;
|
|
5329
5331
|
const across = Math.atan(view.aspect * Math.tan(view.fov / 2));
|
|
@@ -5397,7 +5399,8 @@ function reachOf(map, distance) {
|
|
|
5397
5399
|
return {
|
|
5398
5400
|
ahead: (east * Math.sin(bearing) + north * Math.cos(bearing)) / metres,
|
|
5399
5401
|
across: (east * Math.cos(bearing) - north * Math.sin(bearing)) / metres,
|
|
5400
|
-
radius: reach.radius / metres
|
|
5402
|
+
radius: reach.radius / metres,
|
|
5403
|
+
...reach.forward === void 0 ? {} : { forward: reach.forward / metres }
|
|
5401
5404
|
};
|
|
5402
5405
|
}
|
|
5403
5406
|
function fovOf(map, args) {
|
|
@@ -8427,11 +8430,11 @@ var growth = `
|
|
|
8427
8430
|
uniform float u_scale;
|
|
8428
8431
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
8429
8432
|
uniform float u_metres; // metres per tile unit
|
|
8430
|
-
//
|
|
8431
|
-
//
|
|
8432
|
-
// ground, in this tile's axes.
|
|
8433
|
+
// In this tile's units: origin and start/end of the fade along the view, or centre and radii of the
|
|
8434
|
+
// fallback covered disc. The direction is along the ground in this tile's axes.
|
|
8433
8435
|
uniform vec4 u_ring;
|
|
8434
8436
|
uniform vec2 u_ring_ahead;
|
|
8437
|
+
uniform bool u_ring_directional;
|
|
8435
8438
|
|
|
8436
8439
|
float progressOf() {
|
|
8437
8440
|
return clamp(u_scale * 1.25 - a_wave.x * 0.25, 0.0, 1.0);
|
|
@@ -8443,9 +8446,11 @@ float elevationOf(float own, float top, float p) {
|
|
|
8443
8446
|
}
|
|
8444
8447
|
|
|
8445
8448
|
// Buildings sink into the ground over the last stretch of the city's reach, so it ends without an
|
|
8446
|
-
// edge of cut-off blocks.
|
|
8447
|
-
//
|
|
8449
|
+
// edge of cut-off blocks. The view-aligned fade leaves the entire near width standing; the legacy
|
|
8450
|
+
// disc fallback also exempts its near side.
|
|
8448
8451
|
float reachOf(vec2 position) {
|
|
8452
|
+
if (u_ring_directional)
|
|
8453
|
+
return 1.0 - smoothstep(u_ring.z, u_ring.w, dot(position - u_ring.xy, u_ring_ahead));
|
|
8449
8454
|
if (u_ring.w <= 0.0) return 1.0;
|
|
8450
8455
|
vec2 from = position - u_ring.xy;
|
|
8451
8456
|
float far = smoothstep(0.0, u_ring.w - u_ring.z, dot(from, u_ring_ahead));
|
|
@@ -11624,7 +11629,8 @@ function createCameraTiles(options) {
|
|
|
11624
11629
|
const chosen = cameraTileRing(
|
|
11625
11630
|
{ ...centre, zoom: currentZoom, pitch: map.getPitch(), bearing: map.getBearing() },
|
|
11626
11631
|
zoom,
|
|
11627
|
-
options.maxTiles
|
|
11632
|
+
options.maxTiles,
|
|
11633
|
+
cameraViewport(map, zoom)
|
|
11628
11634
|
);
|
|
11629
11635
|
ring = chosen;
|
|
11630
11636
|
wanted = chosen.tiles.map(({ x: x3, y: y2 }) => `${x3}/${y2}`);
|
|
@@ -11636,7 +11642,7 @@ function createCameraTiles(options) {
|
|
|
11636
11642
|
return;
|
|
11637
11643
|
}
|
|
11638
11644
|
const now = performance.now();
|
|
11639
|
-
for (const { x: x3, y: y2
|
|
11645
|
+
for (const [priority, { x: x3, y: y2 }] of chosen.tiles.entries()) {
|
|
11640
11646
|
const key = `${x3}/${y2}`;
|
|
11641
11647
|
let entry = tiles.get(key);
|
|
11642
11648
|
if (!entry) {
|
|
@@ -11644,7 +11650,7 @@ function createCameraTiles(options) {
|
|
|
11644
11650
|
tiles.set(key, entry);
|
|
11645
11651
|
}
|
|
11646
11652
|
entry.used = now;
|
|
11647
|
-
entry.
|
|
11653
|
+
entry.priority = priority;
|
|
11648
11654
|
if ((!entry.value && !entry.pending || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
11649
11655
|
load(source, key, entry, chosen.tileMetres);
|
|
11650
11656
|
}
|
|
@@ -11657,7 +11663,7 @@ function createCameraTiles(options) {
|
|
|
11657
11663
|
entry.retryAt = void 0;
|
|
11658
11664
|
source.read(
|
|
11659
11665
|
{ z: zoom, x: entry.x, y: entry.y },
|
|
11660
|
-
{ signal: controller.signal, priority: entry.
|
|
11666
|
+
{ signal: controller.signal, priority: entry.priority ?? 0 }
|
|
11661
11667
|
).then((tile) => {
|
|
11662
11668
|
if (disposed || tiles.get(key) !== entry || entry.loading !== controller) return;
|
|
11663
11669
|
if (!tile) {
|
|
@@ -11692,14 +11698,14 @@ function createCameraTiles(options) {
|
|
|
11692
11698
|
while (!disposed && queue.length && performance.now() - started < buildBudgetMs) {
|
|
11693
11699
|
let nearest = 0;
|
|
11694
11700
|
for (let at = 1; at < queue.length; at += 1)
|
|
11695
|
-
if ((queue[at].entry.
|
|
11701
|
+
if ((queue[at].entry.priority ?? 0) < (queue[nearest].entry.priority ?? 0))
|
|
11696
11702
|
nearest = at;
|
|
11697
11703
|
const { key, entry, controller, tile, metres: tileMetres } = queue.splice(nearest, 1)[0];
|
|
11698
11704
|
const current = () => !disposed && tiles.get(key) === entry && entry.loading === controller && !controller.signal.aborted;
|
|
11699
11705
|
if (!current()) continue;
|
|
11700
11706
|
let value;
|
|
11701
11707
|
try {
|
|
11702
|
-
value = await options.build(tile, tileMetres, controller.signal, entry.
|
|
11708
|
+
value = await options.build(tile, tileMetres, controller.signal, entry.priority ?? 0);
|
|
11703
11709
|
} catch {
|
|
11704
11710
|
if (current()) {
|
|
11705
11711
|
entry.loading = void 0;
|
|
@@ -11769,6 +11775,7 @@ function createCameraTiles(options) {
|
|
|
11769
11775
|
map.on("sourcedata", onSource);
|
|
11770
11776
|
map.on("move", onMove);
|
|
11771
11777
|
map.on("moveend", onMoveEnd);
|
|
11778
|
+
map.on("resize", onMoveEnd);
|
|
11772
11779
|
return {
|
|
11773
11780
|
update,
|
|
11774
11781
|
ready() {
|
|
@@ -11823,6 +11830,7 @@ function createCameraTiles(options) {
|
|
|
11823
11830
|
map.off("sourcedata", onSource);
|
|
11824
11831
|
map.off("move", onMove);
|
|
11825
11832
|
map.off("moveend", onMoveEnd);
|
|
11833
|
+
map.off("resize", onMoveEnd);
|
|
11826
11834
|
for (const entry of tiles.values()) {
|
|
11827
11835
|
entry.loading?.abort();
|
|
11828
11836
|
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
@@ -11890,33 +11898,110 @@ function cameraFrame(callback) {
|
|
|
11890
11898
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(callback);
|
|
11891
11899
|
else setTimeout(callback, 16);
|
|
11892
11900
|
}
|
|
11893
|
-
function cameraTileRing(camera, tileZoom, maxTiles) {
|
|
11901
|
+
function cameraTileRing(camera, tileZoom, maxTiles, viewport) {
|
|
11894
11902
|
const reach = Math.min(
|
|
11895
11903
|
5e3,
|
|
11896
11904
|
Math.max(800, 1600 * 2 ** (16 - camera.zoom) * (1 + camera.pitch / 60))
|
|
11897
11905
|
);
|
|
11898
11906
|
const bearing = camera.bearing * Math.PI / 180;
|
|
11907
|
+
const direction = [Math.sin(bearing), -Math.cos(bearing)];
|
|
11899
11908
|
const ahead = reach * 0.35 * Math.min(1, camera.pitch / 60);
|
|
11900
11909
|
const latitude = camera.lat + Math.cos(bearing) * ahead / 111320;
|
|
11901
11910
|
const longitude = camera.lng + Math.sin(bearing) * ahead / (111320 * Math.cos(camera.lat * Math.PI / 180));
|
|
11902
11911
|
const [cx, cy] = cameraTileAt(longitude, latitude, tileZoom);
|
|
11903
|
-
const
|
|
11912
|
+
const [ox, oy] = cameraTileAt(camera.lng, camera.lat, tileZoom);
|
|
11913
|
+
const tileMetres = earth * Math.cos(camera.lat * Math.PI / 180) / 2 ** tileZoom;
|
|
11914
|
+
const far = (reach + ahead) / tileMetres;
|
|
11915
|
+
const along = ([x3, y2]) => (x3 - ox) * direction[0] + (y2 - oy) * direction[1];
|
|
11916
|
+
const visible = viewport && clipGround(viewport, (point) => far - along(point));
|
|
11904
11917
|
const span = Math.ceil(reach / tileMetres);
|
|
11918
|
+
const left = Math.floor(Math.min(cx - span, ...visible?.map(([x3]) => x3) ?? []));
|
|
11919
|
+
const right = Math.floor(Math.max(cx + span, ...visible?.map(([x3]) => x3) ?? []));
|
|
11920
|
+
const top = Math.floor(Math.min(cy - span, ...visible?.map(([, y2]) => y2) ?? []));
|
|
11921
|
+
const bottom = Math.floor(Math.max(cy + span, ...visible?.map(([, y2]) => y2) ?? []));
|
|
11905
11922
|
const candidates = [];
|
|
11906
|
-
for (let
|
|
11907
|
-
for (let
|
|
11908
|
-
const
|
|
11909
|
-
|
|
11910
|
-
const
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11923
|
+
for (let x3 = left; x3 <= right; x3++)
|
|
11924
|
+
for (let y2 = top; y2 <= bottom; y2++) {
|
|
11925
|
+
const distance = Math.hypot(Math.max(x3 - cx, 0, cx - x3 - 1), Math.max(y2 - cy, 0, cy - y2 - 1));
|
|
11926
|
+
let intersection = visible ?? [];
|
|
11927
|
+
for (const boundary of [
|
|
11928
|
+
([px]) => px - x3,
|
|
11929
|
+
([px]) => x3 + 1 - px,
|
|
11930
|
+
([, py]) => py - y2,
|
|
11931
|
+
([, py]) => y2 + 1 - py
|
|
11932
|
+
])
|
|
11933
|
+
intersection = clipGround(intersection, boundary);
|
|
11934
|
+
const near2 = Math.min(...intersection.map(along));
|
|
11935
|
+
if (near2 < Infinity || distance * tileMetres <= reach)
|
|
11936
|
+
candidates.push({ x: x3, y: y2, distance, near: near2 });
|
|
11937
|
+
}
|
|
11938
|
+
candidates.sort((a, b2) => a.near - b2.near || a.distance - b2.distance);
|
|
11939
|
+
const tiles = candidates.slice(0, maxTiles).map(({ x: x3, y: y2, distance }) => ({ x: x3, y: y2, distance }));
|
|
11940
|
+
const omitted = candidates.slice(tiles.length);
|
|
11941
|
+
const radius = omitted.reduce(
|
|
11942
|
+
(radius2, tile) => Math.min(radius2, tile.distance),
|
|
11943
|
+
reach / tileMetres
|
|
11944
|
+
);
|
|
11945
|
+
const end = Math.min(far, ...omitted.map((tile) => tile.near));
|
|
11946
|
+
const near = visible?.length ? Math.min(...visible.map(along)) : end;
|
|
11947
|
+
return {
|
|
11948
|
+
tiles,
|
|
11949
|
+
centre: [cx, cy],
|
|
11950
|
+
radius,
|
|
11951
|
+
tileMetres,
|
|
11952
|
+
...visible?.length ? {
|
|
11953
|
+
fade: {
|
|
11954
|
+
origin: [ox, oy],
|
|
11955
|
+
start: end - Math.max(0.25, (end - near) * 0.2),
|
|
11956
|
+
end
|
|
11957
|
+
}
|
|
11958
|
+
} : {}
|
|
11959
|
+
};
|
|
11960
|
+
}
|
|
11961
|
+
function cameraViewport(map, zoom) {
|
|
11962
|
+
const canvas = map.getCanvas?.();
|
|
11963
|
+
const width = canvas?.clientWidth ?? 0;
|
|
11964
|
+
const height = canvas?.clientHeight ?? 0;
|
|
11965
|
+
if (!map.unproject || width <= 0 || height <= 0) return void 0;
|
|
11966
|
+
const origin = cameraTileAt(map.getCenter().lng, map.getCenter().lat, zoom)[0];
|
|
11967
|
+
const world = 2 ** zoom;
|
|
11968
|
+
const pointAt = (x3, y2) => {
|
|
11969
|
+
const location = map.unproject([x3, y2]);
|
|
11970
|
+
const [tx, ty] = cameraTileAt(location.lng, location.lat, zoom);
|
|
11971
|
+
return [tx + Math.round((origin - tx) / world) * world, ty];
|
|
11972
|
+
};
|
|
11973
|
+
const bearing = map.getBearing() * Math.PI / 180;
|
|
11974
|
+
const points = [];
|
|
11975
|
+
for (const x3 of [0, width]) {
|
|
11976
|
+
const bottom = pointAt(x3, height);
|
|
11977
|
+
const middle = pointAt(x3, height / 2);
|
|
11978
|
+
let top = pointAt(x3, 0);
|
|
11979
|
+
if ((top[0] - middle[0]) * Math.sin(bearing) - (top[1] - middle[1]) * Math.cos(bearing) <= 0) {
|
|
11980
|
+
const stretch = world / Math.hypot(middle[0] - bottom[0], middle[1] - bottom[1]);
|
|
11981
|
+
top = [
|
|
11982
|
+
middle[0] + (middle[0] - bottom[0]) * stretch,
|
|
11983
|
+
middle[1] + (middle[1] - bottom[1]) * stretch
|
|
11984
|
+
];
|
|
11985
|
+
}
|
|
11986
|
+
points.push(bottom, top);
|
|
11987
|
+
}
|
|
11988
|
+
if (points.some((point) => point.some((value) => !Number.isFinite(value)))) return void 0;
|
|
11989
|
+
return [points[0], points[1], points[3], points[2]];
|
|
11990
|
+
}
|
|
11991
|
+
function clipGround(points, distance) {
|
|
11992
|
+
const result = [];
|
|
11993
|
+
for (let i2 = 0; i2 < points.length; i2++) {
|
|
11994
|
+
const a = points[i2];
|
|
11995
|
+
const b2 = points[(i2 + 1) % points.length];
|
|
11996
|
+
const da = distance(a);
|
|
11997
|
+
const db = distance(b2);
|
|
11998
|
+
if (da >= 0) result.push([a[0], a[1]]);
|
|
11999
|
+
if (da < 0 !== db < 0) {
|
|
12000
|
+
const t = da / (da - db);
|
|
12001
|
+
result.push([a[0] + (b2[0] - a[0]) * t, a[1] + (b2[1] - a[1]) * t]);
|
|
11915
12002
|
}
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
const radius = Math.min(reach / tileMetres, candidates[tiles.length]?.distance ?? Infinity);
|
|
11919
|
-
return { tiles, centre: [cx, cy], radius, tileMetres };
|
|
12003
|
+
}
|
|
12004
|
+
return result;
|
|
11920
12005
|
}
|
|
11921
12006
|
function cameraTileAt(longitude, latitude, zoom) {
|
|
11922
12007
|
const phi = Math.min(85.05, Math.max(-85.05, latitude)) * Math.PI / 180;
|
|
@@ -14447,6 +14532,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14447
14532
|
context.uniform2f(program.uniforms.u_offset, ...offset);
|
|
14448
14533
|
context.uniform4f(program.uniforms.u_ring ?? null, ...ring);
|
|
14449
14534
|
context.uniform2f(program.uniforms.u_ring_ahead ?? null, ...ahead);
|
|
14535
|
+
context.uniform1i(program.uniforms.u_ring_directional ?? null, camera.ring()?.fade ? 1 : 0);
|
|
14450
14536
|
const buffers = value.gl;
|
|
14451
14537
|
context.bindVertexArray(buffers.vao);
|
|
14452
14538
|
for (const range of ranges)
|
|
@@ -14729,13 +14815,21 @@ function createTileflowBuildings3D(options) {
|
|
|
14729
14815
|
return {
|
|
14730
14816
|
lng: ring.centre[0] / n * 360 - 180,
|
|
14731
14817
|
lat: Math.atan(Math.sinh(Math.PI * (1 - 2 * ring.centre[1] / n))) * 180 / Math.PI,
|
|
14732
|
-
radius: ring.radius * ring.tileMetres
|
|
14818
|
+
radius: ring.radius * ring.tileMetres,
|
|
14819
|
+
...ring.fade ? { forward: ring.fade.end * ring.tileMetres } : {}
|
|
14733
14820
|
};
|
|
14734
14821
|
}
|
|
14735
14822
|
function ringIn(x3, y2) {
|
|
14736
14823
|
const ring = camera.ring();
|
|
14737
14824
|
if (!ring) return [0, 0, 0, 0];
|
|
14738
14825
|
const extent5 = tileflowBuildingExtent;
|
|
14826
|
+
if (ring.fade)
|
|
14827
|
+
return [
|
|
14828
|
+
(ring.fade.origin[0] - x3) * extent5,
|
|
14829
|
+
(ring.fade.origin[1] - y2) * extent5,
|
|
14830
|
+
ring.fade.start * extent5,
|
|
14831
|
+
ring.fade.end * extent5
|
|
14832
|
+
];
|
|
14739
14833
|
const cx = (ring.centre[0] - x3) * extent5;
|
|
14740
14834
|
const cy = (ring.centre[1] - y2) * extent5;
|
|
14741
14835
|
const inner = ring.radius * extent5 * 0.8;
|
|
@@ -14749,6 +14843,8 @@ function createTileflowBuildings3D(options) {
|
|
|
14749
14843
|
return [Math.sin(bearing), -Math.cos(bearing)];
|
|
14750
14844
|
}
|
|
14751
14845
|
function insideRing2(ring, left, top, right, bottom) {
|
|
14846
|
+
if (camera.ring()?.fade)
|
|
14847
|
+
return Math.min(ahead[0] * (left - ring[0]), ahead[0] * (right - ring[0])) + Math.min(ahead[1] * (top - ring[1]), ahead[1] * (bottom - ring[1])) < ring[3];
|
|
14752
14848
|
const radius = ring[3];
|
|
14753
14849
|
if (!(radius > 0)) return true;
|
|
14754
14850
|
const cx = ring[0];
|
|
@@ -14966,6 +15062,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14966
15062
|
);
|
|
14967
15063
|
context.uniform4f(u.u_ring ?? null, ...ringIn(x3, y2));
|
|
14968
15064
|
context.uniform2f(u.u_ring_ahead ?? null, ...ahead);
|
|
15065
|
+
context.uniform1i(u.u_ring_directional ?? null, camera.ring()?.fade ? 1 : 0);
|
|
14969
15066
|
const palette = themes ? paletteOf(context, entry, themes.themes) : void 0;
|
|
14970
15067
|
context.uniform1f(u.u_palette_on, palette ? 1 : 0);
|
|
14971
15068
|
context.activeTexture(context.TEXTURE1);
|
|
@@ -20361,11 +20458,11 @@ async function loadPinnedMaplibreContour() {
|
|
|
20361
20458
|
}
|
|
20362
20459
|
function resolveMaplibreContourLibrary(module) {
|
|
20363
20460
|
if (!module || typeof module !== "object") {
|
|
20364
|
-
throw new Error("maplibre-contour 0.1.
|
|
20461
|
+
throw new Error("maplibre-contour 0.1.1 did not expose its browser module.");
|
|
20365
20462
|
}
|
|
20366
20463
|
const library = module.default;
|
|
20367
20464
|
if (!library || typeof library !== "object" || typeof library.DemSource !== "function") {
|
|
20368
|
-
throw new Error("maplibre-contour 0.1.
|
|
20465
|
+
throw new Error("maplibre-contour 0.1.1 did not expose DemSource.");
|
|
20369
20466
|
}
|
|
20370
20467
|
return library;
|
|
20371
20468
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tileflow/core",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.44",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Typed Tileflow config and MapLibre style compiler.",
|
|
6
6
|
"type": "module",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@mapbox/vector-tile": "3.0.0",
|
|
89
89
|
"earcut": "3.2.4",
|
|
90
|
-
"maplibre-contour": "0.1.
|
|
90
|
+
"maplibre-contour": "0.1.1",
|
|
91
91
|
"meshoptimizer": "1.3.0",
|
|
92
92
|
"pbf": "5.1.2",
|
|
93
93
|
"pmtiles": "4.5.0",
|