@tileflow/core 0.1.0-alpha.42 → 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 +56 -69
- package/THIRD_PARTY_NOTICES.md +3 -3
- package/dist/{3d-CzLTD0RK.d.ts → 3d-CW5Ls0An.d.ts} +32 -2
- package/dist/3d.d.ts +1 -1
- package/dist/3d.js +425 -50
- package/dist/browser.d.ts +95 -5
- package/dist/browser.js +866 -101
- package/dist/build.d.ts +8 -4
- package/dist/build.js +250 -3
- package/dist/config-reference.json +3395 -2140
- package/dist/{icon-composition-B1A2udKb.d.ts → icon-composition-Bbw9umUA.d.ts} +37 -2
- package/dist/index.d.ts +13 -4
- package/dist/index.js +193 -3
- package/dist/{manifest-types-B0lQjabX.d.ts → manifest-types-CwjHd4qc.d.ts} +8 -0
- package/dist/manifest.d.ts +2 -2
- package/dist/native-profile.d.ts +4 -0
- package/dist/native-profile.js +2 -0
- package/dist/native.js +789 -462
- package/dist/runtime.d.ts +1 -1
- package/dist/worker/camera-tile-worker.global.js +2 -2
- package/package.json +5 -6
- package/docs/application-tile-reading.md +0 -86
- package/docs/authoring-model.md +0 -269
- package/docs/boundary-areas-and-choropleths.md +0 -230
- package/docs/buildings-3d.md +0 -624
- package/docs/camera-moves-and-tile-cache.md +0 -112
- package/docs/capture-scenes.md +0 -40
- package/docs/capture-shots.md +0 -173
- package/docs/cartographic-defaults.md +0 -214
- package/docs/compiled-style-performance.md +0 -286
- package/docs/data-is-separate-from-design.md +0 -610
- package/docs/depth-markers.md +0 -65
- package/docs/dynamic-style-images.md +0 -100
- package/docs/globe-atmosphere.md +0 -113
- package/docs/hosted-session-authorization.md +0 -106
- package/docs/map-and-terrain-examples.md +0 -156
- package/docs/map-emphasis.md +0 -89
- package/docs/native-artifact-profile.md +0 -152
- package/docs/native-resource-urls.md +0 -369
- package/docs/nautical-marks.md +0 -308
- package/docs/public-api-and-browser-subpath.md +0 -101
- package/docs/route-drawing.md +0 -191
- package/docs/shared-visual-primitives.md +0 -101
- package/docs/street-lights.md +0 -127
- package/docs/street-sky.md +0 -156
- package/docs/style-states.md +0 -73
- package/docs/sun-and-light.md +0 -167
- package/docs/theme-transitions-and-blends.md +0 -317
- package/docs/themes-and-module-styles.md +0 -156
- package/docs/trees-3d.md +0 -295
package/dist/3d.js
CHANGED
|
@@ -284,6 +284,53 @@ var init_meshopt_decoder = __esm({
|
|
|
284
284
|
}
|
|
285
285
|
});
|
|
286
286
|
|
|
287
|
+
// src/building-flat-layers-browser.ts
|
|
288
|
+
function createBuildingFlatLayers(map) {
|
|
289
|
+
const saved = /* @__PURE__ */ new Map();
|
|
290
|
+
let updating = false;
|
|
291
|
+
function restore() {
|
|
292
|
+
if (!map.setLayoutProperty || !map.getLayoutProperty || updating) return;
|
|
293
|
+
updating = true;
|
|
294
|
+
try {
|
|
295
|
+
for (const [id, { visibility, layer }] of saved)
|
|
296
|
+
if (map.getLayer(id) === layer && map.getLayoutProperty(id, "visibility") !== visibility)
|
|
297
|
+
map.setLayoutProperty(id, "visibility", visibility);
|
|
298
|
+
saved.clear();
|
|
299
|
+
} finally {
|
|
300
|
+
updating = false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
update(layers, hidden) {
|
|
305
|
+
if (updating || !map.setLayoutProperty || !map.getLayoutProperty) return;
|
|
306
|
+
if (!hidden || layers.length === 0) {
|
|
307
|
+
restore();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
updating = true;
|
|
311
|
+
try {
|
|
312
|
+
const authored = new Map(layers.map((layer) => [layer.id, layer.visible]));
|
|
313
|
+
const ids = map.getLayersOrder?.() ?? (map.getStyle()?.layers ?? []).map(({ id }) => id);
|
|
314
|
+
for (const id of ids) {
|
|
315
|
+
const visible = authored.get(id.split("::")[0]);
|
|
316
|
+
if (visible === void 0 || !map.getLayer(id)) continue;
|
|
317
|
+
const current = map.getLayoutProperty(id, "visibility") ?? "visible";
|
|
318
|
+
if (!saved.has(id) || saved.get(id).layer !== map.getLayer(id))
|
|
319
|
+
saved.set(id, { visibility: visible ? current : "none", layer: map.getLayer(id) });
|
|
320
|
+
if (current !== "none") map.setLayoutProperty(id, "visibility", "none");
|
|
321
|
+
}
|
|
322
|
+
} finally {
|
|
323
|
+
updating = false;
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
restore,
|
|
327
|
+
/** Removing a map must not write to its destroyed style. */
|
|
328
|
+
forget() {
|
|
329
|
+
saved.clear();
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
287
334
|
// src/models-3d-model.ts
|
|
288
335
|
var tileflowModelParts = Object.freeze({
|
|
289
336
|
surface: 0,
|
|
@@ -479,6 +526,7 @@ function readModelRoleLighting(value) {
|
|
|
479
526
|
...typeof entry.emissiveColor === "string" ? { emissiveColor: entry.emissiveColor } : {},
|
|
480
527
|
...typeof entry.color === "string" ? { color: entry.color } : {},
|
|
481
528
|
...entry.colorMix === void 0 ? {} : { colorMix: bounded(entry.colorMix, 0, 1, 1) },
|
|
529
|
+
...entry.colorScale === void 0 ? {} : { colorScale: bounded(entry.colorScale, 0, 1, 1) },
|
|
482
530
|
...entry.metallic === void 0 ? {} : { metallic: bounded(entry.metallic, 0, 1, 0) },
|
|
483
531
|
...entry.roughness === void 0 ? {} : { roughness: bounded(entry.roughness, 0, 1, 1) },
|
|
484
532
|
...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
|
|
@@ -581,6 +629,7 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
|
581
629
|
shadows: true,
|
|
582
630
|
occlusion: true,
|
|
583
631
|
groundOcclusion: 0.16,
|
|
632
|
+
groundOcclusionRadius: 3,
|
|
584
633
|
modelOcclusion: 0.75
|
|
585
634
|
});
|
|
586
635
|
function readTileflowBuildings3D(metadata) {
|
|
@@ -618,7 +667,11 @@ function readTileflowBuildings3D(metadata) {
|
|
|
618
667
|
shadows: typeof value.shadows === "boolean" ? value.shadows : defaults.shadows,
|
|
619
668
|
occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults.occlusion,
|
|
620
669
|
groundOcclusion: within(value.groundOcclusion, 1, defaults.groundOcclusion),
|
|
670
|
+
groundOcclusionRadius: within(value.groundOcclusionRadius, 20, defaults.groundOcclusionRadius),
|
|
621
671
|
modelOcclusion: within(value.modelOcclusion, 1, defaults.modelOcclusion),
|
|
672
|
+
...Array.isArray(value.flatLayers) && value.flatLayers.length <= 128 && value.flatLayers.every(
|
|
673
|
+
(entry) => isRecord(entry) && typeof entry.id === "string" && typeof entry.visible === "boolean"
|
|
674
|
+
) ? { flatLayers: value.flatLayers } : {},
|
|
622
675
|
...modelsOf(value.models),
|
|
623
676
|
...modelColorsOf(value.modelColors),
|
|
624
677
|
...landmarksOf(value.landmarks)
|
|
@@ -2500,11 +2553,11 @@ var growth = `
|
|
|
2500
2553
|
uniform float u_scale;
|
|
2501
2554
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
2502
2555
|
uniform float u_metres; // metres per tile unit
|
|
2503
|
-
//
|
|
2504
|
-
//
|
|
2505
|
-
// 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.
|
|
2506
2558
|
uniform vec4 u_ring;
|
|
2507
2559
|
uniform vec2 u_ring_ahead;
|
|
2560
|
+
uniform bool u_ring_directional;
|
|
2508
2561
|
|
|
2509
2562
|
float progressOf() {
|
|
2510
2563
|
return clamp(u_scale * 1.25 - a_wave.x * 0.25, 0.0, 1.0);
|
|
@@ -2516,9 +2569,11 @@ float elevationOf(float own, float top, float p) {
|
|
|
2516
2569
|
}
|
|
2517
2570
|
|
|
2518
2571
|
// Buildings sink into the ground over the last stretch of the city's reach, so it ends without an
|
|
2519
|
-
// edge of cut-off blocks.
|
|
2520
|
-
//
|
|
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.
|
|
2521
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));
|
|
2522
2577
|
if (u_ring.w <= 0.0) return 1.0;
|
|
2523
2578
|
vec2 from = position - u_ring.xy;
|
|
2524
2579
|
float far = smoothstep(0.0, u_ring.w - u_ring.z, dot(from, u_ring_ahead));
|
|
@@ -3885,6 +3940,9 @@ function readTileflowVegetation3D(metadata) {
|
|
|
3885
3940
|
{
|
|
3886
3941
|
heightScale: scale(own.heightScale),
|
|
3887
3942
|
crownScale: scale(own.crownScale),
|
|
3943
|
+
...typeof own.sizeAnchor === "number" && Number.isFinite(own.sizeAnchor) ? { sizeAnchor: clamp(own.sizeAnchor, [1, 45]) } : {},
|
|
3944
|
+
...typeof own.crownAnchor === "number" && Number.isFinite(own.crownAnchor) ? { crownAnchor: clamp(own.crownAnchor, [1, 25]) } : {},
|
|
3945
|
+
...typeof own.sizeCompression === "number" && Number.isFinite(own.sizeCompression) ? { sizeCompression: clamp(own.sizeCompression, [0, 1]) } : {},
|
|
3888
3946
|
...drawn.length > 0 ? { models: drawn } : {}
|
|
3889
3947
|
}
|
|
3890
3948
|
]
|
|
@@ -4204,7 +4262,7 @@ function browserWorker() {
|
|
|
4204
4262
|
if (typeof Worker === "undefined" || false)
|
|
4205
4263
|
return;
|
|
4206
4264
|
const url = URL.createObjectURL(
|
|
4207
|
-
new Blob(['"use strict";(()=>{var Be=new Set,ln=!1;function Pe(e,n,t=2){let i=n&&n.length,o=i?n[0]*t:e.length;Be.size&&Be.clear();let r=zn(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=xt(e,n,r,t)),e.length>80*t){a=e[0],l=e[1];let c=a,f=l;for(let d=t;d<o;d+=t){let g=e[d],m=e[d+1];g<a&&(a=g),m<l&&(l=m),g>c&&(c=g),m>f&&(f=m)}u=Math.max(c-a,f-l),u=u!==0?32767/u:0}return un(r,s,a,l,u),s}function zn(e,n,t,i,o){let r=null;if(o===Ut(e,n,t,i)>0)for(let s=n;s<t;s+=i)r=In(s/i|0,e[s],e[s+1],r);else for(let s=t-i;s>=n;s-=i)r=In(s/i|0,e[s],e[s+1],r);return r&&Oe(r,r.next)&&(Ce(r),r=r.next),r}function ge(e,n=e){let t=n===e,i=e,o;do o=!1,i!==i.next&&(Be.size===0||!Be.has(i))&&(Oe(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Ce(i),i=i.prev,o=!0):(t||i!==n)&&(i=i.next,o=!t);while(o||i!==n);return n}function un(e,n,t,i,o){o&&Ft(e,t,i,o);let r=e,s=!1;for(;e.prev!==e.next;){let a=e.prev,l=e.next;if(Q(a,e,l)<0&&(o?bt(e,t,i,o):yt(e))){n.push(a.i,e.i,l.i),Ce(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=gt(e,n),r=e,s=!0;continue}wt(e,n,t,i,o);break}}}function yt(e){let n=e.prev,t=e,i=e.next,o=n.x,r=t.x,s=i.x,a=n.y,l=t.y,u=i.y,c=Math.min(o,r,s),f=Math.min(a,l,u),d=Math.max(o,r,s),g=Math.max(a,l,u),m=i.next;for(;m!==n;){if(m.x>=c&&m.x<=d&&m.y>=f&&m.y<=g&&!(o===m.x&&a===m.y)&&Ke(o,a,r,l,s,u,m.x,m.y)&&Q(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function bt(e,n,t,i){let o=e.prev,r=e,s=e.next,a=o.x,l=r.x,u=s.x,c=o.y,f=r.y,d=s.y,g=Math.min(a,l,u),m=Math.min(c,f,d),p=Math.max(a,l,u),h=Math.max(c,f,d),_=mn(g,m,n,t,i),F=mn(p,h,n,t,i),k=e.prevZ;for(;k&&k.z>=_;){if(k.x>=g&&k.x<=p&&k.y>=m&&k.y<=h&&k!==s&&!(a===k.x&&c===k.y)&&Ke(a,c,l,f,u,d,k.x,k.y)&&Q(k.prev,k,k.next)>=0)return!1;k=k.prevZ}let M=e.nextZ;for(;M&&M.z<=F;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Dn(o,t,t.next,r,!1)&&Ue(o,r)&&Ue(r,o)&&(n.push(o.i,t.i,r.i),Ce(t),Ce(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=zn(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Nn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Nn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Nn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function En(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ue(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&_t(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function _t(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function Ft(e,n,t,i){let o=e,r=0;do o.z=mn(o.x,o.y,n,t,i),ie[r++]=o,o=o.next;while(o!==e);At(r);let s=null;for(let a=0;a<r;a++){let l=ie[a];l.prevZ=s,s&&(s.nextZ=l),s=l}s.nextZ=null,ie.fill(null,0,r),ve.fill(null,0,r)}function At(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ue(e,n)&&Ue(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Dn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Dn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ue(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function In(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ce(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ut(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ct=.7,Pt=Math.tan(Math.PI/6),Et=Math.tan(35*Math.PI/180),It=Math.tan(Math.PI/18),Ee=.65,Ie=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Nt(e);if(!l||Math.abs(pn(e))<Ct*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let _=Math.max(0,o-i),F=Gn(t.roof_height),k,M;if(F!==void 0&&F>0)M=o,k=Math.max(i+Math.min(2,_/2),o-F);else{let y=Math.min(zt(a,d),_*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[U,E]=l.centre,C=(y,b)=>{let x=(y-U)*r,T=(b-E)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},I=(y,b)=>[U+(y*u[0]+b*c[0])/r,E+(y*u[1]+b*c[1])/r],D=(y,b)=>{let x=1/0;for(let[T,A,v]of h)x=Math.min(x,T*y+A*b+v);return Math.max(0,x)},K=(y,b)=>k+B*D(...C(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...C(n[y],n[y+1]));pn($)<0&&Ht($);let N=1.01,Y=[-f*N,-d*N,f*N,-d*N,f*N,d*N,-f*N,d*N],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,A=x.length/2;for(let P=0;P<A&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%A*2],x[(P+1)%A*2+1]];T=Hn(T,W-j,Z-G,-(W-j)*Z-(Z-G)*j)}if(T.length<6||Math.abs(pn(T))<1e-6)continue;let v=[];for(let P=0;P<T.length;P+=2)v.push(...I(T[P],T[P+1]));let L=Pe(v);if(L.length===0)continue;let O=B*b[0],V=B*b[1],R=O*u[0]+V*c[0],S=O*u[1]+V*c[1],z=Math.hypot(R,S,1);w.push({ring:v,triangles:L,normal:[-R/z,-S/z]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[A,v]=C(y,b),[L,O]=C(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let S=R+1;S<h.length;S+=1){let z=(ae,H)=>(h[R][0]-h[S][0])*ae+(h[R][1]-h[S][1])*H+(h[R][2]-h[S][2]),P=z(A,v),Z=z(L,O);if(P===Z||P*Z>0)continue;let j=P/(P-Z);if(j<=1e-4||j>=1-1e-4)continue;let G=A+(L-A)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=D(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function zt(e,n){switch(e){case"skillion":return 2*n*It;case"pyramidal":return n*Et;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=Ee/(Ie*r)*f,m=(1-Ee)/((1-Ie)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),Ee/(Ie*r)*d],[...p(m),Ee+(1-Ee)/((1-Ie)*r)*(d-Ie*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Nt(e){let n=Dt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[_,F]of n){let k=_*c[0]+F*c[1],M=_*f[0]+F*f[1];d=Math.min(d,k),g=Math.max(g,k),m=Math.min(m,M),p=Math.max(p,M)}let h=(g-d)*(p-m);if(h<i){i=h;let _=(d+g)/2,F=(m+p)/2;t={centre:[_*c[0]+F*f[0],_*c[1]+F*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Dt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var $t=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Nr=Object.freeze(Object.keys($t));var Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6});var Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024,parts:16});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Zt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=Gt(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function Gt(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Zt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Wt={commercial:1,active:2,destination:3},Xt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Yt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Jt=6,Kt=.5,Qt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1.5,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=tr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let U=B.properties,E=U.hide_3d;if(E===!0||E===1||E==="1"||E==="true")continue;let C=Math.min(6e3,Jn(U.render_height)??o),I=Math.min(C,Jn(U.render_min_height)??0),D=Wt[String(U.building_tone??"")]??0,K=Xt[String(U.class??"")]??0,$=d.get(M)??0,N=u.length,Y=!1;for(let w of rr(B.geometry,t)){let y=w.map(ir).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=or(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Qt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,C+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let z=0;z<S.length;z+=2)T.bounds[0]=Math.min(T.bounds[0],S[z]-1),T.bounds[1]=Math.min(T.bounds[1],S[z+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[z]+1),T.bounds[3]=Math.max(T.bounds[3],S[z+1]+1);Y=!0,f=Math.max(f,C);let A=Number.isSafeInteger(B.id),v=gn(A?B.id*.0731:b*.0731+x*.19137+N*1.618),L=!A&&y[0].some(S=>S<=0||S>=ue)?gn(C*7.31+I*3.17+D):v,O={base:I,top:C,jitter:L,seed:v,tone:D,group:K,use:$,cx:b,cy:x,index:N},V=y.map((S,z)=>nr(S,z,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],U,I,C,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),er(R,O,s,a)):qt(y,O,s,a);for(let[S,z]of y.entries()){let P=qe(z)>0,Z=S===0?P?-1:1:P?1:-1,j=z.length/2,G=H=>{let J=(H%j+j)%j;return[z[J*2],z[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,Ne=(ne-J)/me*Z;return(je*(le-ne)+Ne*(de-te))/ce>Kt},se=(H,J)=>R?R.heightAt(H,J):C,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],Ne=oe=>{let _e=ce[0]+(je[0]-ce[0])*oe,Fe=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(_e,Fe)||1;return[_e/ye,Fe/ye]},he=[0,...R?R.breaks(J,re,ne,te):[],1];for(let oe=0;oe+1<he.length;oe+=1){let _e=oe===0,Fe=oe+2===he.length,ye=J+(ne-J)*he[oe],De=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],Ae=Math.hypot(Ve-ye,He-De)/ue*n.tileMetres,$e=(_e&&W(H)?1:0)|(Fe&&W(H+1)?2:0)|(S>0?4:0),Ge=(_e&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+Ae,Ze=Ne(he[oe]),We=Ne(he[oe+1]),Un=se(ye,De),Cn=se(Ve,He),ke=s.write(O,ye,De,0,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),s.write(O,ye,De,1,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),l.push(ke,ke+1,ke+2,ke+1,ke+3,ke+2),ae=an}}}T.roofsCount=a.length-T.roofsFrom,T.wallsCount=l.length-T.wallsFrom,c.push(T)}Y&&u.push(U)}if(s.count===0)return;let g=new Uint32Array(a.length+l.length),m=[],p=0,h=a.length,_=a.values(),F=l.values();c.sort((M,B)=>M.cell-B.cell);let k=-1;for(let M of c){M.cell!==k&&(k=M.cell,m.push({bounds:[...M.bounds],roofsFrom:p,roofsCount:0,wallsFrom:h,wallsCount:0}));let B=m.at(-1);for(let U=0;U<5;U+=1)B.bounds[U]=U<2?Math.min(B.bounds[U],M.bounds[U]):Math.max(B.bounds[U],M.bounds[U]);g.set(_.subarray(M.roofsFrom,M.roofsFrom+M.roofsCount),p),g.set(F.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function er(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function nr(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[_,F]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(_-p,F-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,_,F)){u(p,h);continue}let[B,U]=[(p-g)/k,(h-m)/k],[E,C]=[(_-p)/M,(F-h)/M],I=Math.atan2(B*C-U*E,B*E+U*C);if(I*s>=-.08||Math.abs(I)>Math.PI*.85){u(p,h);continue}let D=Math.tan(Math.abs(I)/2),K=Math.min(t*D,k*.2,M*.2),$=K/D;if($<1){u(p,h);continue}let[N,Y]=[-U*s,B*s],[w,y]=[p-B*K-N*$,h-U*K-Y*$],b=Math.atan2(Y,N),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(I)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let A=b+I*T/x,v=[Math.cos(A),Math.sin(A)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let _=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(_).set(new Uint8Array(this.#e)),this.#e=_,this.#n=new DataView(_)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function tr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Yt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Jt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let F of r){let[k,M,B,U]=F.box;if(d<k-o||d>B+o||g<M-o||g>U+o)continue;let E=!1;for(let C of F.rings)for(let I=0,D=C.length-2;I+1<C.length;D=I,I+=2){let K=C[D],$=C[D+1],N=C[I],Y=C[I+1];Y>g!=$>g&&d<(K-N)*(g-Y)/($-Y)+N&&(E=!E);let w=N-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=F.index)}if(E){m=F.index;break}}let _=m??p;_!==void 0&&t.set(_,Math.max(t.get(_)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function rr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function or(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function ir(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=sr(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function sr(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let _=(t.length<=4?[...t].map(F=>F+F).join(""):t).match(/../gu).map(F=>Number.parseInt(F,16));return[_[0],_[1],_[2],_.length>3?_[3]/255:1]}let i=/^(rgba?|hsla?)\\(([^)]+)\\)$/u.exec(n);if(!i)return null;let o=i[2].split(/[\\s,/]+/u).filter(Boolean);if(o.length<3||o.length>4)return null;let r=o[3]===void 0?1:en(o[3],1);if(i[1].startsWith("rgb")){let[h,_,F]=o.slice(0,3).map(k=>en(k,255));return[h,_,F,r].some(k=>k===null)?null:[h,_,F,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,ar={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},lr={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},ur={spacing:30,kerb:0},cr=12,fr=18,dr=9,mr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},hr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},pr=new Set(["wall","wall_mounted","wall_bracket"]),yr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(fr),r=new nn(dr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let _=br(h),F=gr(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,_*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let U=0;U+1<B.length;U+=2){let E=B[U]*m,C=B[U+1]*m;if(!rt(E,C))continue;i.write(E,C,_,M,!0,F);let I=ot(E,C,n.tileMetres);o.add(...I),r.add(...I)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=wr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=cr,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,_)=>{let F=fe/m.extent,k=[];for(let D=0;D+1<p.length;D+=2)k.push(p[D]*F,p[D+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,U=Rn(k[0]*.013+k[1]*.029+_)*h.spacing,E=0,C=U,I=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let D=2;D<k.length;D+=2){let K=k[D-2],$=k[D-1],N=k[D],Y=k[D+1],w=Math.hypot(N-K,Y-$)*M;if(w!==0){for(;C<=E+w;){let y=(C-E)/w,b=-(Y-$)/(w/M)*I,x=(N-K)/(w/M)*I,T=K+(N-K)*y+b*B,A=$+(Y-$)*y+x*B;if(C+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(I=-I),!rt(T,A))continue;let v=ot(T,A,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,A,7,15,!1))}E+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,ur,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=ar[r];if(s&&(n==="streets"||kn(t)))return s;let a=lr[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function br(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return pr.has(t)?4.5:yr.has(t)?7.5:7}function gr(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(hr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=mr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function wr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],_n=[1,25],xr=1.2,Tr=1.5,Mr=1.3,kr=1,vr=[.3,10],Rr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),_r=new Set(["cupressus","calocedrus","thuja"]),Fr=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=Fn(e[t.genus])??Fn(e[t.species])??(o.endsWith("aceae")?void 0:Fn(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&Rr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&_r.has(r))return"columnar";if(i.includes("needle")||r&&Fr.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function Fn(e){return typeof e!="string"?void 0:e.trim().split(/\\s+/u)[0]?.toLowerCase()||void 0}function ct(e,n){let t={...ut,...n.fields},i=n.unknownForms??Sn,o=n.regions??[],{tile:r,tileMetres:s}=n,a=s/2**(15-r.z)/512,l=[],u=0,c=0,f=(w,y)=>{if(o.length===0)return i;let[b,x]=Sr(r,w/q,y/q);for(let T of o){let[A,v,L,O]=T.bounds;if(x>=v&&x<=O&&(A<=L?b>=A&&b<=L:b>=A||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],A=An(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=An(T.height,ee(y,1))),v===void 0&&(v=L/A),L===void 0&&(L=v*A),{height:Te(v,on),crown:Te(L,_n)}},g=(w,y,b,x,T,A)=>{let v=ze(r.x*q+w,r.y*q+y,7),L=b===void 0?sn(f(w,y),ee(v,3)):b==="broadleaf"?sn(Ar(f(w,y)),ee(v,3)):b,O=x===void 0&&T===void 0&&A!==void 0?d(L,v,An(st[L].height,Te(A/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...O,turn:ee(v,4),shade:ee(v,5),form:Me.indexOf(L),rank:Math.floor(ee(v,6)*rn),seed:ee(v,7),canopy:0}),u+=1},m=e.trees;if(m){let w=q/m.extent;for(let y of m.features){if(y.type!=="Point")continue;let b=y.properties,x=lt(b,t),T=xe(b[t.height],on),A=xe(b[t.diameterCrown],_n),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,A,v)}}}let p=e.trees;if(p){let w=q/p.extent,y=(n.rowSpacing??8)/(s/p.extent);for(let b of p.features){if(b.type!=="LineString")continue;let x=b.properties,T=lt(x,t),A=xe(x[t.height],on),v=xe(x[t.diameterCrown],_n);for(let L of b.geometry){let O=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[S,z,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],j=Math.hypot(P-S,Z-z);for(;O<=V+j;){let G=j>0?(O-V)/j:0,W=S+(P-S)*G,se=z+(Z-z)*G;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,A,v,void 0),O+=y}V+=j}}}}let h=e.canopy;if(h){let w=q/h.extent;for(let y of h.features){if(y.type!=="Point")continue;let b=y.properties,x=Te(Math.floor(Number(b[t.canopyRank]??8)),[0,rn-1]),T=Math.max(4,Number(b[t.canopyClearance]??8))*a,A=Number(b[t.canopyCover]??30),v=A>=60?3:A>=30?2:1;for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let S=V*w,z=R*w,P=ze(r.x*q+S,r.y*q+z,11),Z=f(S,z),j=xe(b[t.canopyHeight],on),G=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(G*.5,T-G/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let H=ze(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee(H,1):W,ne=S+Math.cos(J)*re/(s/q),te=z+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee(H,3)),de=G*(.85+ee(H,2)*.3),me=j===void 0?void 0:j*(.85+ee(H,6)*.25),ce=d(le,H,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee(H,4),shade:ee(H,5),form:Me.indexOf(le),rank:x,seed:ee(H,7),canopy:1}),c+=1}}}}let _=[],F=e.hedges;if(F){let w=q/F.extent,y=xr/(s/F.extent);for(let b of F.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?kr:0,T=(xe(b.properties[t.height],vr)??Mr)+x;for(let A of b.geometry){let v=y/2,L=0;for(let O=0;O+3<A.length;O+=2){let[V,R,S,z]=[A[O],A[O+1],A[O+2],A[O+3]],P=Math.hypot(S-V,z-R),Z=(Math.atan2(R-z,S-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let j=P>0?(v-L)/P:0,G=V+(S-V)*j,W=R+(z-R)*j;if(G>=0&&W>=0&&G<F.extent&&W<F.extent){let se=ze(r.x*q+G*w,r.y*q+W*w,17);_.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),U=l.map((w,y)=>y);U.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let E=new Uint8Array(l.length*tn),C=new DataView(E.buffer),I=0,D=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...D(),variants:Array.from({length:k(y)},D)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};U.forEach((w,y)=>{let b=l[w],x=y*tn;C.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),C.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),C.setUint16(x+4,Math.round(b.height*10),!0),C.setUint16(x+6,Math.round(b.crown*10),!0),E[x+8]=Math.floor(b.turn*256)&255,E[x+9]=Math.floor(b.shade*256)&255,E[x+10]=b.form,E[x+11]=b.rank,E[x+12]=Math.floor(b.seed*256)&255,E[x+13]=b.canopy,E[x+14]=B[w],I=Math.max(I,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let N=new Uint8Array(_.length*tn),Y=new DataView(N.buffer);return _.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(Tr*10),!0),N[b+8]=Math.round(w.turn*256)&255,N[b+9]=Math.floor(w.shade*256)&255,N[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:N,tallest:I,mapped:u,canopy:c}}function Ar(e){let n={round:e.round??0,open:e.open??0,tall:e.tall??0};return n.round+n.open+n.tall>0?n:Sn}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(Sn,n);let i=n*t;for(let o of Me){let r=Math.max(0,e[o]??0);if(i<r)return o;i-=r}return"round"}function xe(e,n){let t=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):NaN;return Number.isFinite(t)&&t>0?Te(t,n):void 0}function Te(e,[n,t]){return Math.min(t,Math.max(n,e))}function An([e,n],t){return e+(n-e)*t}function Sr(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function ze(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return ze(e,n,20973)/4294967296}var Lr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Br(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Br(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Cr(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Or(a,o,r);return l?[l]:[]}))})}}function Or(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Lr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Ur(s,o))})}function Ur(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Cr(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Pr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Pr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,Er=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,Er.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
4265
|
+
new Blob(['"use strict";(()=>{var Be=new Set,ln=!1;function Pe(e,n,t=2){let i=n&&n.length,o=i?n[0]*t:e.length;Be.size&&Be.clear();let r=In(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=xt(e,n,r,t)),e.length>80*t){a=e[0],l=e[1];let c=a,f=l;for(let d=t;d<o;d+=t){let g=e[d],m=e[d+1];g<a&&(a=g),m<l&&(l=m),g>c&&(c=g),m>f&&(f=m)}u=Math.max(c-a,f-l),u=u!==0?32767/u:0}return un(r,s,a,l,u),s}function In(e,n,t,i,o){let r=null;if(o===Ct(e,n,t,i)>0)for(let s=n;s<t;s+=i)r=En(s/i|0,e[s],e[s+1],r);else for(let s=t-i;s>=n;s-=i)r=En(s/i|0,e[s],e[s+1],r);return r&&Oe(r,r.next)&&(Ue(r),r=r.next),r}function ge(e,n=e){let t=n===e,i=e,o;do o=!1,i!==i.next&&(Be.size===0||!Be.has(i))&&(Oe(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Ue(i),i=i.prev,o=!0):(t||i!==n)&&(i=i.next,o=!t);while(o||i!==n);return n}function un(e,n,t,i,o){o&&Ft(e,t,i,o);let r=e,s=!1;for(;e.prev!==e.next;){let a=e.prev,l=e.next;if(Q(a,e,l)<0&&(o?bt(e,t,i,o):yt(e))){n.push(a.i,e.i,l.i),Ue(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=gt(e,n),r=e,s=!0;continue}wt(e,n,t,i,o);break}}}function yt(e){let n=e.prev,t=e,i=e.next,o=n.x,r=t.x,s=i.x,a=n.y,l=t.y,u=i.y,c=Math.min(o,r,s),f=Math.min(a,l,u),d=Math.max(o,r,s),g=Math.max(a,l,u),m=i.next;for(;m!==n;){if(m.x>=c&&m.x<=d&&m.y>=f&&m.y<=g&&!(o===m.x&&a===m.y)&&Ke(o,a,r,l,s,u,m.x,m.y)&&Q(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function bt(e,n,t,i){let o=e.prev,r=e,s=e.next,a=o.x,l=r.x,u=s.x,c=o.y,f=r.y,d=s.y,g=Math.min(a,l,u),m=Math.min(c,f,d),p=Math.max(a,l,u),h=Math.max(c,f,d),A=mn(g,m,n,t,i),F=mn(p,h,n,t,i),k=e.prevZ;for(;k&&k.z>=A;){if(k.x>=g&&k.x<=p&&k.y>=m&&k.y<=h&&k!==s&&!(a===k.x&&c===k.y)&&Ke(a,c,l,f,u,d,k.x,k.y)&&Q(k.prev,k,k.next)>=0)return!1;k=k.prevZ}let M=e.nextZ;for(;M&&M.z<=F;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Dn(o,t,t.next,r,!1)&&Ce(o,r)&&Ce(r,o)&&(n.push(o.i,t.i,r.i),Ue(t),Ue(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=In(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Nn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Nn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Nn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function zn(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=zn(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=zn(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ce(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&At(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function At(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function Ft(e,n,t,i){let o=e,r=0;do o.z=mn(o.x,o.y,n,t,i),ie[r++]=o,o=o.next;while(o!==e);_t(r);let s=null;for(let a=0;a<r;a++){let l=ie[a];l.prevZ=s,s&&(s.nextZ=l),s=l}s.nextZ=null,ie.fill(null,0,r),ve.fill(null,0,r)}function _t(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ce(e,n)&&Ce(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Dn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Dn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ce(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function En(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ue(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ct(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ut=.7,Pt=Math.tan(Math.PI/6),zt=Math.tan(35*Math.PI/180),Et=Math.tan(Math.PI/18),ze=.65,Ee=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Nt(e);if(!l||Math.abs(pn(e))<Ut*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let A=Math.max(0,o-i),F=Gn(t.roof_height),k,M;if(F!==void 0&&F>0)M=o,k=Math.max(i+Math.min(2,A/2),o-F);else{let y=Math.min(It(a,d),A*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[C,z]=l.centre,U=(y,b)=>{let x=(y-C)*r,T=(b-z)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},E=(y,b)=>[C+(y*u[0]+b*c[0])/r,z+(y*u[1]+b*c[1])/r],D=(y,b)=>{let x=1/0;for(let[T,_,v]of h)x=Math.min(x,T*y+_*b+v);return Math.max(0,x)},K=(y,b)=>k+B*D(...U(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...U(n[y],n[y+1]));pn($)<0&&Ht($);let N=1.01,Y=[-f*N,-d*N,f*N,-d*N,f*N,d*N,-f*N,d*N],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,_=x.length/2;for(let P=0;P<_&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%_*2],x[(P+1)%_*2+1]];T=Hn(T,W-j,Z-G,-(W-j)*Z-(Z-G)*j)}if(T.length<6||Math.abs(pn(T))<1e-6)continue;let v=[];for(let P=0;P<T.length;P+=2)v.push(...E(T[P],T[P+1]));let L=Pe(v);if(L.length===0)continue;let O=B*b[0],V=B*b[1],R=O*u[0]+V*c[0],S=O*u[1]+V*c[1],I=Math.hypot(R,S,1);w.push({ring:v,triangles:L,normal:[-R/I,-S/I]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[_,v]=U(y,b),[L,O]=U(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let S=R+1;S<h.length;S+=1){let I=(ae,H)=>(h[R][0]-h[S][0])*ae+(h[R][1]-h[S][1])*H+(h[R][2]-h[S][2]),P=I(_,v),Z=I(L,O);if(P===Z||P*Z>0)continue;let j=P/(P-Z);if(j<=1e-4||j>=1-1e-4)continue;let G=_+(L-_)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=D(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function It(e,n){switch(e){case"skillion":return 2*n*Et;case"pyramidal":return n*zt;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=ze/(Ee*r)*f,m=(1-ze)/((1-Ee)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),ze/(Ee*r)*d],[...p(m),ze+(1-ze)/((1-Ee)*r)*(d-Ee*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Nt(e){let n=Dt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[A,F]of n){let k=A*c[0]+F*c[1],M=A*f[0]+F*f[1];d=Math.min(d,k),g=Math.max(g,k),m=Math.min(m,M),p=Math.max(p,M)}let h=(g-d)*(p-m);if(h<i){i=h;let A=(d+g)/2,F=(m+p)/2;t={centre:[A*c[0]+F*f[0],A*c[1]+F*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Dt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var $t=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Nr=Object.freeze(Object.keys($t));var Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6});var Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024,parts:16});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Zt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=Gt(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function Gt(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Zt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Wt={commercial:1,active:2,destination:3},Xt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Yt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Jt=6,Kt=.5,Qt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1.5,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=tr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let C=B.properties,z=C.hide_3d;if(z===!0||z===1||z==="1"||z==="true")continue;let U=Math.min(6e3,Jn(C.render_height)??o),E=Math.min(U,Jn(C.render_min_height)??0),D=Wt[String(C.building_tone??"")]??0,K=Xt[String(C.class??"")]??0,$=d.get(M)??0,N=u.length,Y=!1;for(let w of rr(B.geometry,t)){let y=w.map(ir).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=or(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Qt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,U+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let I=0;I<S.length;I+=2)T.bounds[0]=Math.min(T.bounds[0],S[I]-1),T.bounds[1]=Math.min(T.bounds[1],S[I+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[I]+1),T.bounds[3]=Math.max(T.bounds[3],S[I+1]+1);Y=!0,f=Math.max(f,U);let _=Number.isSafeInteger(B.id),v=gn(_?B.id*.0731:b*.0731+x*.19137+N*1.618),L=!_&&y[0].some(S=>S<=0||S>=ue)?gn(U*7.31+E*3.17+D):v,O={base:E,top:U,jitter:L,seed:v,tone:D,group:K,use:$,cx:b,cy:x,index:N},V=y.map((S,I)=>nr(S,I,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],C,E,U,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),er(R,O,s,a)):qt(y,O,s,a);for(let[S,I]of y.entries()){let P=qe(I)>0,Z=S===0?P?-1:1:P?1:-1,j=I.length/2,G=H=>{let J=(H%j+j)%j;return[I[J*2],I[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,Ne=(ne-J)/me*Z;return(je*(le-ne)+Ne*(de-te))/ce>Kt},se=(H,J)=>R?R.heightAt(H,J):U,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],Ne=oe=>{let Ae=ce[0]+(je[0]-ce[0])*oe,Fe=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(Ae,Fe)||1;return[Ae/ye,Fe/ye]},he=[0,...R?R.breaks(J,re,ne,te):[],1];for(let oe=0;oe+1<he.length;oe+=1){let Ae=oe===0,Fe=oe+2===he.length,ye=J+(ne-J)*he[oe],De=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],_e=Math.hypot(Ve-ye,He-De)/ue*n.tileMetres,$e=(Ae&&W(H)?1:0)|(Fe&&W(H+1)?2:0)|(S>0?4:0),Ge=(Ae&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+_e,Ze=Ne(he[oe]),We=Ne(he[oe+1]),Cn=se(ye,De),Un=se(Ve,He),ke=s.write(O,ye,De,0,Ze[0],Ze[1],1,ae,$e,_e,0,Ge,Cn);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,_e,1,Ge,Un),s.write(O,ye,De,1,Ze[0],Ze[1],1,ae,$e,_e,0,Ge,Cn),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,_e,1,Ge,Un),l.push(ke,ke+1,ke+2,ke+1,ke+3,ke+2),ae=an}}}T.roofsCount=a.length-T.roofsFrom,T.wallsCount=l.length-T.wallsFrom,c.push(T)}Y&&u.push(C)}if(s.count===0)return;let g=new Uint32Array(a.length+l.length),m=[],p=0,h=a.length,A=a.values(),F=l.values();c.sort((M,B)=>M.cell-B.cell);let k=-1;for(let M of c){M.cell!==k&&(k=M.cell,m.push({bounds:[...M.bounds],roofsFrom:p,roofsCount:0,wallsFrom:h,wallsCount:0}));let B=m.at(-1);for(let C=0;C<5;C+=1)B.bounds[C]=C<2?Math.min(B.bounds[C],M.bounds[C]):Math.max(B.bounds[C],M.bounds[C]);g.set(A.subarray(M.roofsFrom,M.roofsFrom+M.roofsCount),p),g.set(F.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function er(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function nr(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[A,F]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(A-p,F-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,A,F)){u(p,h);continue}let[B,C]=[(p-g)/k,(h-m)/k],[z,U]=[(A-p)/M,(F-h)/M],E=Math.atan2(B*U-C*z,B*z+C*U);if(E*s>=-.08||Math.abs(E)>Math.PI*.85){u(p,h);continue}let D=Math.tan(Math.abs(E)/2),K=Math.min(t*D,k*.2,M*.2),$=K/D;if($<1){u(p,h);continue}let[N,Y]=[-C*s,B*s],[w,y]=[p-B*K-N*$,h-C*K-Y*$],b=Math.atan2(Y,N),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(E)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let _=b+E*T/x,v=[Math.cos(_),Math.sin(_)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let A=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(A).set(new Uint8Array(this.#e)),this.#e=A,this.#n=new DataView(A)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function tr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Yt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Jt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let F of r){let[k,M,B,C]=F.box;if(d<k-o||d>B+o||g<M-o||g>C+o)continue;let z=!1;for(let U of F.rings)for(let E=0,D=U.length-2;E+1<U.length;D=E,E+=2){let K=U[D],$=U[D+1],N=U[E],Y=U[E+1];Y>g!=$>g&&d<(K-N)*(g-Y)/($-Y)+N&&(z=!z);let w=N-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=F.index)}if(z){m=F.index;break}}let A=m??p;A!==void 0&&t.set(A,Math.max(t.get(A)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function rr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function or(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function ir(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=sr(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function sr(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let A=(t.length<=4?[...t].map(F=>F+F).join(""):t).match(/../gu).map(F=>Number.parseInt(F,16));return[A[0],A[1],A[2],A.length>3?A[3]/255:1]}let i=/^(rgba?|hsla?)\\(([^)]+)\\)$/u.exec(n);if(!i)return null;let o=i[2].split(/[\\s,/]+/u).filter(Boolean);if(o.length<3||o.length>4)return null;let r=o[3]===void 0?1:en(o[3],1);if(i[1].startsWith("rgb")){let[h,A,F]=o.slice(0,3).map(k=>en(k,255));return[h,A,F,r].some(k=>k===null)?null:[h,A,F,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,ar={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},lr={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},ur={spacing:30,kerb:0},cr=12,fr=18,dr=9,mr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},hr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},pr=new Set(["wall","wall_mounted","wall_bracket"]),yr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(fr),r=new nn(dr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let A=br(h),F=gr(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,A*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let C=0;C+1<B.length;C+=2){let z=B[C]*m,U=B[C+1]*m;if(!rt(z,U))continue;i.write(z,U,A,M,!0,F);let E=ot(z,U,n.tileMetres);o.add(...E),r.add(...E)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=wr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=cr,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,A)=>{let F=fe/m.extent,k=[];for(let D=0;D+1<p.length;D+=2)k.push(p[D]*F,p[D+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,C=Rn(k[0]*.013+k[1]*.029+A)*h.spacing,z=0,U=C,E=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let D=2;D<k.length;D+=2){let K=k[D-2],$=k[D-1],N=k[D],Y=k[D+1],w=Math.hypot(N-K,Y-$)*M;if(w!==0){for(;U<=z+w;){let y=(U-z)/w,b=-(Y-$)/(w/M)*E,x=(N-K)/(w/M)*E,T=K+(N-K)*y+b*B,_=$+(Y-$)*y+x*B;if(U+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(E=-E),!rt(T,_))continue;let v=ot(T,_,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,_,7,15,!1))}z+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,ur,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=ar[r];if(s&&(n==="streets"||kn(t)))return s;let a=lr[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function br(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return pr.has(t)?4.5:yr.has(t)?7.5:7}function gr(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(hr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=mr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function wr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],An=[1,25],xr=1.2,Tr=1.5,Mr=1.3,kr=1,vr=[.3,10],Rr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),Ar=new Set(["cupressus","calocedrus","thuja"]),Fr=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=Fn(e[t.genus])??Fn(e[t.species])??(o.endsWith("aceae")?void 0:Fn(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&Rr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&Ar.has(r))return"columnar";if(i.includes("needle")||r&&Fr.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function Fn(e){return typeof e!="string"?void 0:e.trim().split(/\\s+/u)[0]?.toLowerCase()||void 0}function ct(e,n){let t={...ut,...n.fields},i=n.unknownForms??Sn,o=n.regions??[],{tile:r,tileMetres:s}=n,a=s/2**(15-r.z)/512,l=[],u=0,c=0,f=(w,y)=>{if(o.length===0)return i;let[b,x]=Sr(r,w/q,y/q);for(let T of o){let[_,v,L,O]=T.bounds;if(x>=v&&x<=O&&(_<=L?b>=_&&b<=L:b>=_||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],_=_n(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=_n(T.height,ee(y,1))),v===void 0&&(v=L/_),L===void 0&&(L=v*_),{height:Te(v,on),crown:Te(L,An)}},g=(w,y,b,x,T,_)=>{let v=Ie(r.x*q+w,r.y*q+y,7),L=b===void 0?sn(f(w,y),ee(v,3)):b==="broadleaf"?sn(_r(f(w,y)),ee(v,3)):b,O=x===void 0&&T===void 0&&_!==void 0?d(L,v,_n(st[L].height,Te(_/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...O,turn:ee(v,4),shade:ee(v,5),form:Me.indexOf(L),rank:Math.floor(ee(v,6)*rn),seed:ee(v,7),canopy:0}),u+=1},m=e.trees;if(m){let w=q/m.extent;for(let y of m.features){if(y.type!=="Point")continue;let b=y.properties,x=lt(b,t),T=xe(b[t.height],on),_=xe(b[t.diameterCrown],An),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,_,v)}}}let p=e.trees;if(p){let w=q/p.extent,y=(n.rowSpacing??8)/(s/p.extent);for(let b of p.features){if(b.type!=="LineString")continue;let x=b.properties,T=lt(x,t),_=xe(x[t.height],on),v=xe(x[t.diameterCrown],An);for(let L of b.geometry){let O=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[S,I,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],j=Math.hypot(P-S,Z-I);for(;O<=V+j;){let G=j>0?(O-V)/j:0,W=S+(P-S)*G,se=I+(Z-I)*G;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,_,v,void 0),O+=y}V+=j}}}}let h=e.canopy;if(h){let w=q/h.extent;for(let y of h.features){if(y.type!=="Point")continue;let b=y.properties,x=Te(Math.floor(Number(b[t.canopyRank]??8)),[0,rn-1]),T=Math.max(4,Number(b[t.canopyClearance]??8))*a,_=Number(b[t.canopyCover]??30),v=_>=60?3:_>=30?2:1;for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let S=V*w,I=R*w,P=Ie(r.x*q+S,r.y*q+I,11),Z=f(S,I),j=xe(b[t.canopyHeight],on),G=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(G*.5,T-G/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let H=Ie(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee(H,1):W,ne=S+Math.cos(J)*re/(s/q),te=I+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee(H,3)),de=G*(.85+ee(H,2)*.3),me=j===void 0?void 0:j*(.85+ee(H,6)*.25),ce=d(le,H,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee(H,4),shade:ee(H,5),form:Me.indexOf(le),rank:x,seed:ee(H,7),canopy:1}),c+=1}}}}let A=[],F=e.hedges;if(F){let w=q/F.extent,y=xr/(s/F.extent);for(let b of F.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?kr:0,T=(xe(b.properties[t.height],vr)??Mr)+x;for(let _ of b.geometry){let v=y/2,L=0;for(let O=0;O+3<_.length;O+=2){let[V,R,S,I]=[_[O],_[O+1],_[O+2],_[O+3]],P=Math.hypot(S-V,I-R),Z=(Math.atan2(R-I,S-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let j=P>0?(v-L)/P:0,G=V+(S-V)*j,W=R+(I-R)*j;if(G>=0&&W>=0&&G<F.extent&&W<F.extent){let se=Ie(r.x*q+G*w,r.y*q+W*w,17);A.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),C=l.map((w,y)=>y);C.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let z=new Uint8Array(l.length*tn),U=new DataView(z.buffer),E=0,D=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...D(),variants:Array.from({length:k(y)},D)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};C.forEach((w,y)=>{let b=l[w],x=y*tn;U.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),U.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),U.setUint16(x+4,Math.round(b.height*10),!0),U.setUint16(x+6,Math.round(b.crown*10),!0),z[x+8]=Math.floor(b.turn*256)&255,z[x+9]=Math.floor(b.shade*256)&255,z[x+10]=b.form,z[x+11]=b.rank,z[x+12]=Math.floor(b.seed*256)&255,z[x+13]=b.canopy,z[x+14]=B[w],E=Math.max(E,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let N=new Uint8Array(A.length*tn),Y=new DataView(N.buffer);return A.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(Tr*10),!0),N[b+8]=Math.round(w.turn*256)&255,N[b+9]=Math.floor(w.shade*256)&255,N[b+12]=Math.floor(w.seed*256)&255,E=Math.max(E,w.height)}),{trees:z,forms:K,hedges:N,tallest:E,mapped:u,canopy:c}}function _r(e){let n={round:e.round??0,open:e.open??0,tall:e.tall??0};return n.round+n.open+n.tall>0?n:Sn}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(Sn,n);let i=n*t;for(let o of Me){let r=Math.max(0,e[o]??0);if(i<r)return o;i-=r}return"round"}function xe(e,n){let t=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):NaN;return Number.isFinite(t)&&t>0?Te(t,n):void 0}function Te(e,[n,t]){return Math.min(t,Math.max(n,e))}function _n([e,n],t){return e+(n-e)*t}function Sr(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function Ie(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return Ie(e,n,20973)/4294967296}var Lr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Br(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Br(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Ur(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Or(a,o,r);return l?[l]:[]}))})}}function Or(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Lr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Cr(s,o))})}function Cr(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Ur(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Pr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Pr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,zr=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,zr.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
4208
4266
|
);
|
|
4209
4267
|
try {
|
|
4210
4268
|
return new Worker(url, { name: "tileflow-tiles" });
|
|
@@ -5609,7 +5667,8 @@ function createCameraTiles(options) {
|
|
|
5609
5667
|
const chosen = cameraTileRing(
|
|
5610
5668
|
{ ...centre, zoom: currentZoom, pitch: map.getPitch(), bearing: map.getBearing() },
|
|
5611
5669
|
zoom,
|
|
5612
|
-
options.maxTiles
|
|
5670
|
+
options.maxTiles,
|
|
5671
|
+
cameraViewport(map, zoom)
|
|
5613
5672
|
);
|
|
5614
5673
|
ring = chosen;
|
|
5615
5674
|
wanted = chosen.tiles.map(({ x: x3, y: y2 }) => `${x3}/${y2}`);
|
|
@@ -5621,7 +5680,7 @@ function createCameraTiles(options) {
|
|
|
5621
5680
|
return;
|
|
5622
5681
|
}
|
|
5623
5682
|
const now = performance.now();
|
|
5624
|
-
for (const { x: x3, y: y2
|
|
5683
|
+
for (const [priority, { x: x3, y: y2 }] of chosen.tiles.entries()) {
|
|
5625
5684
|
const key = `${x3}/${y2}`;
|
|
5626
5685
|
let entry = tiles.get(key);
|
|
5627
5686
|
if (!entry) {
|
|
@@ -5629,8 +5688,8 @@ function createCameraTiles(options) {
|
|
|
5629
5688
|
tiles.set(key, entry);
|
|
5630
5689
|
}
|
|
5631
5690
|
entry.used = now;
|
|
5632
|
-
entry.
|
|
5633
|
-
if ((!entry.value || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
5691
|
+
entry.priority = priority;
|
|
5692
|
+
if ((!entry.value && !entry.pending || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
5634
5693
|
load(source, key, entry, chosen.tileMetres);
|
|
5635
5694
|
}
|
|
5636
5695
|
evict();
|
|
@@ -5642,10 +5701,12 @@ function createCameraTiles(options) {
|
|
|
5642
5701
|
entry.retryAt = void 0;
|
|
5643
5702
|
source.read(
|
|
5644
5703
|
{ z: zoom, x: entry.x, y: entry.y },
|
|
5645
|
-
{ signal: controller.signal, priority: entry.
|
|
5704
|
+
{ signal: controller.signal, priority: entry.priority ?? 0 }
|
|
5646
5705
|
).then((tile) => {
|
|
5647
5706
|
if (disposed || tiles.get(key) !== entry || entry.loading !== controller) return;
|
|
5648
5707
|
if (!tile) {
|
|
5708
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
5709
|
+
entry.pending = void 0;
|
|
5649
5710
|
if (entry.value && entry.value !== options.empty) options.release(entry.value);
|
|
5650
5711
|
entry.value = options.empty;
|
|
5651
5712
|
entry.loading = void 0;
|
|
@@ -5675,14 +5736,14 @@ function createCameraTiles(options) {
|
|
|
5675
5736
|
while (!disposed && queue.length && performance.now() - started < buildBudgetMs) {
|
|
5676
5737
|
let nearest = 0;
|
|
5677
5738
|
for (let at = 1; at < queue.length; at += 1)
|
|
5678
|
-
if ((queue[at].entry.
|
|
5739
|
+
if ((queue[at].entry.priority ?? 0) < (queue[nearest].entry.priority ?? 0))
|
|
5679
5740
|
nearest = at;
|
|
5680
5741
|
const { key, entry, controller, tile, metres: tileMetres } = queue.splice(nearest, 1)[0];
|
|
5681
5742
|
const current = () => !disposed && tiles.get(key) === entry && entry.loading === controller && !controller.signal.aborted;
|
|
5682
5743
|
if (!current()) continue;
|
|
5683
5744
|
let value;
|
|
5684
5745
|
try {
|
|
5685
|
-
value = await options.build(tile, tileMetres, controller.signal, entry.
|
|
5746
|
+
value = await options.build(tile, tileMetres, controller.signal, entry.priority ?? 0);
|
|
5686
5747
|
} catch {
|
|
5687
5748
|
if (current()) {
|
|
5688
5749
|
entry.loading = void 0;
|
|
@@ -5694,10 +5755,11 @@ function createCameraTiles(options) {
|
|
|
5694
5755
|
if (value !== options.empty) options.release(value);
|
|
5695
5756
|
continue;
|
|
5696
5757
|
}
|
|
5697
|
-
|
|
5698
|
-
|
|
5758
|
+
if (entry.pending && entry.pending !== options.empty && entry.pending !== value)
|
|
5759
|
+
options.release(entry.pending);
|
|
5760
|
+
entry.pending = value;
|
|
5699
5761
|
entry.loading = void 0;
|
|
5700
|
-
|
|
5762
|
+
commit(entry);
|
|
5701
5763
|
built = true;
|
|
5702
5764
|
}
|
|
5703
5765
|
if (built && !disposed) {
|
|
@@ -5714,12 +5776,24 @@ function createCameraTiles(options) {
|
|
|
5714
5776
|
void step();
|
|
5715
5777
|
});
|
|
5716
5778
|
}
|
|
5779
|
+
function commit(entry) {
|
|
5780
|
+
const value = entry.pending;
|
|
5781
|
+
if (value === void 0 || value !== options.empty && options.isReady && !options.isReady(value))
|
|
5782
|
+
return;
|
|
5783
|
+
const previous = entry.value;
|
|
5784
|
+
entry.value = value;
|
|
5785
|
+
entry.pending = void 0;
|
|
5786
|
+
if (previous && previous !== options.empty && previous !== value) options.release(previous);
|
|
5787
|
+
options.changed();
|
|
5788
|
+
map.triggerRepaint();
|
|
5789
|
+
}
|
|
5717
5790
|
function evict() {
|
|
5718
5791
|
const keep = new Set(wanted);
|
|
5719
5792
|
const spare = [...tiles.entries()].filter(([key]) => !keep.has(key)).sort((a, b2) => b2[1].used - a[1].used);
|
|
5720
5793
|
for (const [key, entry] of spare.slice(options.maxTiles)) {
|
|
5721
5794
|
entry.loading?.abort();
|
|
5722
5795
|
if (entry.value && entry.value !== options.empty) options.release(entry.value);
|
|
5796
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
5723
5797
|
tiles.delete(key);
|
|
5724
5798
|
options.changed();
|
|
5725
5799
|
}
|
|
@@ -5739,17 +5813,26 @@ function createCameraTiles(options) {
|
|
|
5739
5813
|
map.on("sourcedata", onSource);
|
|
5740
5814
|
map.on("move", onMove);
|
|
5741
5815
|
map.on("moveend", onMoveEnd);
|
|
5816
|
+
map.on("resize", onMoveEnd);
|
|
5742
5817
|
return {
|
|
5743
5818
|
update,
|
|
5744
5819
|
ready() {
|
|
5745
5820
|
const list = [];
|
|
5746
5821
|
for (const key of wanted) {
|
|
5747
5822
|
const entry = tiles.get(key);
|
|
5823
|
+
if (entry) commit(entry);
|
|
5748
5824
|
if (entry?.value && entry.value !== options.empty)
|
|
5749
5825
|
list.push(entry);
|
|
5750
5826
|
}
|
|
5751
5827
|
return list;
|
|
5752
5828
|
},
|
|
5829
|
+
built() {
|
|
5830
|
+
return wanted.flatMap((key) => {
|
|
5831
|
+
const entry = tiles.get(key);
|
|
5832
|
+
const value = entry?.pending ?? entry?.value;
|
|
5833
|
+
return entry && value && value !== options.empty ? [{ ...entry, value }] : [];
|
|
5834
|
+
});
|
|
5835
|
+
},
|
|
5753
5836
|
coverage: () => covered,
|
|
5754
5837
|
ring: () => ring,
|
|
5755
5838
|
all: () => tiles.values(),
|
|
@@ -5771,6 +5854,8 @@ function createCameraTiles(options) {
|
|
|
5771
5854
|
for (const [key, entry] of tiles) {
|
|
5772
5855
|
if (!which(entry)) continue;
|
|
5773
5856
|
entry.loading?.abort();
|
|
5857
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
5858
|
+
entry.pending = void 0;
|
|
5774
5859
|
entry.retryAt = void 0;
|
|
5775
5860
|
const latitude = Math.atan(Math.sinh(Math.PI * (1 - 2 * (entry.y + 0.5) / 2 ** zoom))) * 180 / Math.PI;
|
|
5776
5861
|
load(source, key, entry, earth * Math.cos(latitude * Math.PI / 180) / 2 ** zoom);
|
|
@@ -5783,7 +5868,11 @@ function createCameraTiles(options) {
|
|
|
5783
5868
|
map.off("sourcedata", onSource);
|
|
5784
5869
|
map.off("move", onMove);
|
|
5785
5870
|
map.off("moveend", onMoveEnd);
|
|
5786
|
-
|
|
5871
|
+
map.off("resize", onMoveEnd);
|
|
5872
|
+
for (const entry of tiles.values()) {
|
|
5873
|
+
entry.loading?.abort();
|
|
5874
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
5875
|
+
}
|
|
5787
5876
|
tiles.clear();
|
|
5788
5877
|
queue.length = 0;
|
|
5789
5878
|
reader?.clear();
|
|
@@ -5847,33 +5936,110 @@ function cameraFrame(callback) {
|
|
|
5847
5936
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(callback);
|
|
5848
5937
|
else setTimeout(callback, 16);
|
|
5849
5938
|
}
|
|
5850
|
-
function cameraTileRing(camera, tileZoom, maxTiles) {
|
|
5939
|
+
function cameraTileRing(camera, tileZoom, maxTiles, viewport) {
|
|
5851
5940
|
const reach = Math.min(
|
|
5852
5941
|
5e3,
|
|
5853
5942
|
Math.max(800, 1600 * 2 ** (16 - camera.zoom) * (1 + camera.pitch / 60))
|
|
5854
5943
|
);
|
|
5855
5944
|
const bearing = camera.bearing * Math.PI / 180;
|
|
5945
|
+
const direction = [Math.sin(bearing), -Math.cos(bearing)];
|
|
5856
5946
|
const ahead = reach * 0.35 * Math.min(1, camera.pitch / 60);
|
|
5857
5947
|
const latitude = camera.lat + Math.cos(bearing) * ahead / 111320;
|
|
5858
5948
|
const longitude = camera.lng + Math.sin(bearing) * ahead / (111320 * Math.cos(camera.lat * Math.PI / 180));
|
|
5859
5949
|
const [cx, cy] = cameraTileAt(longitude, latitude, tileZoom);
|
|
5860
|
-
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));
|
|
5861
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) ?? []));
|
|
5862
5960
|
const candidates = [];
|
|
5863
|
-
for (let
|
|
5864
|
-
for (let
|
|
5865
|
-
const
|
|
5866
|
-
|
|
5867
|
-
const
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
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]);
|
|
5872
6040
|
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
const radius = Math.min(reach / tileMetres, candidates[tiles.length]?.distance ?? Infinity);
|
|
5876
|
-
return { tiles, centre: [cx, cy], radius, tileMetres };
|
|
6041
|
+
}
|
|
6042
|
+
return result;
|
|
5877
6043
|
}
|
|
5878
6044
|
function cameraTileAt(longitude, latitude, zoom) {
|
|
5879
6045
|
const phi = Math.min(85.05, Math.max(-85.05, latitude)) * Math.PI / 180;
|
|
@@ -6510,7 +6676,9 @@ function tileflowModelCameraDistance(model, view) {
|
|
|
6510
6676
|
function tileflowModelLevel(model, view, previous) {
|
|
6511
6677
|
const thresholds = tileflowModelLevelDistancesOf(model.bounds);
|
|
6512
6678
|
const last = Math.max(0, Math.min(model.levels, thresholds.length + 1) - 1);
|
|
6513
|
-
const
|
|
6679
|
+
const fov = view.verticalFieldOfView;
|
|
6680
|
+
const lens = fov !== void 0 && fov > 0 && fov < 180 ? Math.tan(fov * Math.PI / 360) * 3 : 1;
|
|
6681
|
+
const distance = tileflowModelCameraDistance(model, view) * lens;
|
|
6514
6682
|
if (!Number.isFinite(distance)) return 0;
|
|
6515
6683
|
const margin = previous === void 0 ? 1 : tileflowModelLevelHysteresis;
|
|
6516
6684
|
let level = Math.max(0, Math.min(last, previous ?? 0));
|
|
@@ -6963,6 +7131,7 @@ out vec3 v_shadow;
|
|
|
6963
7131
|
out float v_light;
|
|
6964
7132
|
flat out int v_lighting_role;
|
|
6965
7133
|
out float v_height;
|
|
7134
|
+
out float v_ground_height;
|
|
6966
7135
|
out vec4 v_uv;
|
|
6967
7136
|
out vec4 v_rgba;
|
|
6968
7137
|
out vec3 v_position;
|
|
@@ -6991,6 +7160,7 @@ void main() {
|
|
|
6991
7160
|
v_light = a_paint.z / 255.0;
|
|
6992
7161
|
v_lighting_role = clamp(int(a_lighting_role + 0.5), 0, 6);
|
|
6993
7162
|
v_height = (m.z - u_model_height.x) / max(u_model_height.y, 0.001);
|
|
7163
|
+
v_ground_height = m.z;
|
|
6994
7164
|
}`;
|
|
6995
7165
|
var tileflowModelFragment = `#version 300 es
|
|
6996
7166
|
precision highp float;
|
|
@@ -7000,6 +7170,9 @@ in vec3 v_shadow;
|
|
|
7000
7170
|
in float v_light;
|
|
7001
7171
|
flat in int v_lighting_role;
|
|
7002
7172
|
in float v_height;
|
|
7173
|
+
in float v_ground_height;
|
|
7174
|
+
uniform vec3 u_facade_shading; // vertical gradient, ground-contact strength and radius in metres
|
|
7175
|
+
uniform float u_role_color_scale[7];
|
|
7003
7176
|
uniform vec3 u_sun_dir;
|
|
7004
7177
|
uniform vec3 u_sun_light;
|
|
7005
7178
|
uniform vec3 u_sky_light;
|
|
@@ -7027,6 +7200,16 @@ vec3 shade(vec3 normal, float lit, float occlusion) {
|
|
|
7027
7200
|
return min(pow(light / max(roof, vec3(1e-4)), vec3(1.0 / 2.2)), vec3(1.7));
|
|
7028
7201
|
}
|
|
7029
7202
|
|
|
7203
|
+
// Same quiet ground-to-facade transition as ordinary tile buildings, evaluated in metres.
|
|
7204
|
+
// Only map-shaded roles opt in; roofs and physical materials keep their own response.
|
|
7205
|
+
float facadeShade(vec3 normal, int role) {
|
|
7206
|
+
float wall = 1.0 - abs(normal.z);
|
|
7207
|
+
float up = max(v_ground_height, 0.0);
|
|
7208
|
+
float gradient = 0.1 * u_facade_shading.x * (1.0 - smoothstep(0.0, 3.0, up));
|
|
7209
|
+
float contact = u_facade_shading.y * exp(-up / max(u_facade_shading.z, 0.001));
|
|
7210
|
+
return 1.0 - max(gradient, contact) * wall * u_role_appearance[role].x;
|
|
7211
|
+
}
|
|
7212
|
+
|
|
7030
7213
|
void main() {
|
|
7031
7214
|
vec3 normal = normalize(gl_FrontFacing ? v_normal : -v_normal);
|
|
7032
7215
|
if (u_physical) normal = materialNormal(normal);
|
|
@@ -7041,7 +7224,7 @@ void main() {
|
|
|
7041
7224
|
float emission = clamp(u_role_emission[role] * multiplier, 0.0, 1.0);
|
|
7042
7225
|
if (u_physical) {
|
|
7043
7226
|
float alpha = materialAlpha();
|
|
7044
|
-
vec3 base = materialBase(role);
|
|
7227
|
+
vec3 base = materialBase(role) * fromSRGB(vec3(u_role_color_scale[role]));
|
|
7045
7228
|
float mapShare = u_role_appearance[role].x;
|
|
7046
7229
|
vec3 radiance;
|
|
7047
7230
|
if (mapShare >= 1.0) {
|
|
@@ -7051,13 +7234,14 @@ void main() {
|
|
|
7051
7234
|
if (mapShare > 0.0)
|
|
7052
7235
|
radiance = mix(radiance, base * fromSRGB(shade(normal, lit, u_role_appearance[role].y)), mapShare);
|
|
7053
7236
|
}
|
|
7237
|
+
radiance *= fromSRGB(vec3(facadeShade(normal, role)));
|
|
7054
7238
|
radiance += u_emissive * fromSRGB(materialTexture(4).rgb);
|
|
7055
7239
|
vec4 own = u_role_emission_colour[role];
|
|
7056
7240
|
radiance = mix(radiance, mix(base, fromSRGB(own.rgb), own.a), emission);
|
|
7057
7241
|
fragColor = vec4(hazed(toSRGB(radiance)), alpha * u_opacity);
|
|
7058
7242
|
return;
|
|
7059
7243
|
}
|
|
7060
|
-
vec3 colour = v_colour * shade(normal, lit, u_role_appearance[role].y);
|
|
7244
|
+
vec3 colour = v_colour * u_role_color_scale[role] * shade(normal, lit, u_role_appearance[role].y) * facadeShade(normal, role);
|
|
7061
7245
|
if (emission > 0.0) {
|
|
7062
7246
|
vec4 own = u_role_emission_colour[role];
|
|
7063
7247
|
vec3 target = mix(v_colour, own.rgb, own.a);
|
|
@@ -8403,6 +8587,7 @@ var tileflowSkyHazeReachFloor = 3;
|
|
|
8403
8587
|
var nineTenths = 0.8042;
|
|
8404
8588
|
function tileflowSkyReachDepth(view, reach) {
|
|
8405
8589
|
const sin = Math.sin(radians(view.pitch));
|
|
8590
|
+
if (reach.forward !== void 0) return 1 + reach.forward * sin;
|
|
8406
8591
|
const cos = Math.cos(radians(view.pitch));
|
|
8407
8592
|
const back = -sin;
|
|
8408
8593
|
const across = Math.atan(view.aspect * Math.tan(view.fov / 2));
|
|
@@ -8475,7 +8660,8 @@ function reachOf(map, distance) {
|
|
|
8475
8660
|
return {
|
|
8476
8661
|
ahead: (east * Math.sin(bearing) + north * Math.cos(bearing)) / metres,
|
|
8477
8662
|
across: (east * Math.cos(bearing) - north * Math.sin(bearing)) / metres,
|
|
8478
|
-
radius: reach.radius / metres
|
|
8663
|
+
radius: reach.radius / metres,
|
|
8664
|
+
...reach.forward === void 0 ? {} : { forward: reach.forward / metres }
|
|
8479
8665
|
};
|
|
8480
8666
|
}
|
|
8481
8667
|
function fovOf(map, args) {
|
|
@@ -8681,6 +8867,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8681
8867
|
return prepared ? { mesh: prepared.mesh, data: prepared.data } : emptyTile;
|
|
8682
8868
|
},
|
|
8683
8869
|
empty: emptyTile,
|
|
8870
|
+
isReady: (value) => value === emptyTile || value.gl !== void 0,
|
|
8684
8871
|
release(value) {
|
|
8685
8872
|
if (gl) release(gl, value);
|
|
8686
8873
|
},
|
|
@@ -8741,7 +8928,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8741
8928
|
models.upload(context);
|
|
8742
8929
|
if (modelKey !== models.key()) map.triggerRepaint();
|
|
8743
8930
|
let budget = 2;
|
|
8744
|
-
for (const { value: entry } of camera.
|
|
8931
|
+
for (const { value: entry } of camera.built()) {
|
|
8745
8932
|
if (entry.gl || !entry.data) continue;
|
|
8746
8933
|
if (budget-- <= 0) {
|
|
8747
8934
|
map.triggerRepaint();
|
|
@@ -9009,6 +9196,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9009
9196
|
context.uniform2f(program.uniforms.u_offset, ...offset);
|
|
9010
9197
|
context.uniform4f(program.uniforms.u_ring ?? null, ...ring);
|
|
9011
9198
|
context.uniform2f(program.uniforms.u_ring_ahead ?? null, ...ahead);
|
|
9199
|
+
context.uniform1i(program.uniforms.u_ring_directional ?? null, camera.ring()?.fade ? 1 : 0);
|
|
9012
9200
|
const buffers = value.gl;
|
|
9013
9201
|
context.bindVertexArray(buffers.vao);
|
|
9014
9202
|
for (const range of ranges)
|
|
@@ -9077,7 +9265,10 @@ function createTileflowBuildings3D(options) {
|
|
|
9077
9265
|
return [ax - reach, ay - reach, Math.min(0, low), ax + reach, ay + reach, high + 0.1];
|
|
9078
9266
|
}
|
|
9079
9267
|
function modelView(model) {
|
|
9080
|
-
return {
|
|
9268
|
+
return {
|
|
9269
|
+
camera: modelCamera(model),
|
|
9270
|
+
verticalFieldOfView: map.getVerticalFieldOfView?.()
|
|
9271
|
+
};
|
|
9081
9272
|
}
|
|
9082
9273
|
function levelOf(model) {
|
|
9083
9274
|
return models.levelOf(model, modelView(model));
|
|
@@ -9199,12 +9390,14 @@ function createTileflowBuildings3D(options) {
|
|
|
9199
9390
|
const gradients = new Float32Array(28);
|
|
9200
9391
|
const powers = new Float32Array(7);
|
|
9201
9392
|
const materialColours = new Float32Array(28);
|
|
9393
|
+
const colorScales = new Float32Array(7);
|
|
9202
9394
|
const materials = new Float32Array(28);
|
|
9203
9395
|
const appearance = new Float32Array(21);
|
|
9204
9396
|
for (const [role, id] of Object.entries(tileflowModelLightingRoles)) {
|
|
9205
9397
|
const from = themes[lower].modelLighting?.[role], to = themes[upper].modelLighting?.[role];
|
|
9206
9398
|
const sampledFrom = sampleModelRole(from, `${identity}:${role}`);
|
|
9207
9399
|
const sampledTo = sampleModelRole(to, `${identity}:${role}`);
|
|
9400
|
+
colorScales[id] = (from?.colorScale ?? 1) * (1 - mix2) + (to?.colorScale ?? 1) * mix2;
|
|
9208
9401
|
appearance[id * 3] = (from?.shading === "map" ? 1 - mix2 : 0) + (to?.shading === "map" ? mix2 : 0);
|
|
9209
9402
|
appearance[id * 3 + 1] = (from?.ambientOcclusion ?? 1) * (1 - mix2) + (to?.ambientOcclusion ?? 1) * mix2;
|
|
9210
9403
|
appearance[id * 3 + 2] = (from?.partColorMix ?? 1) * (1 - mix2) + (to?.partColorMix ?? 1) * mix2;
|
|
@@ -9227,7 +9420,16 @@ function createTileflowBuildings3D(options) {
|
|
|
9227
9420
|
gradients[id * 4 + component] = first[component] * (1 - mix2) + second[component] * mix2;
|
|
9228
9421
|
powers[id] = first[4] * (1 - mix2) + second[4] * mix2;
|
|
9229
9422
|
}
|
|
9230
|
-
const result = {
|
|
9423
|
+
const result = {
|
|
9424
|
+
strengths,
|
|
9425
|
+
colours,
|
|
9426
|
+
gradients,
|
|
9427
|
+
powers,
|
|
9428
|
+
materialColours,
|
|
9429
|
+
colorScales,
|
|
9430
|
+
materials,
|
|
9431
|
+
appearance
|
|
9432
|
+
};
|
|
9231
9433
|
if (modelLightingCache.size >= 1024)
|
|
9232
9434
|
modelLightingCache.delete(modelLightingCache.keys().next().value);
|
|
9233
9435
|
modelLightingCache.set(identity, result);
|
|
@@ -9277,13 +9479,21 @@ function createTileflowBuildings3D(options) {
|
|
|
9277
9479
|
return {
|
|
9278
9480
|
lng: ring.centre[0] / n * 360 - 180,
|
|
9279
9481
|
lat: Math.atan(Math.sinh(Math.PI * (1 - 2 * ring.centre[1] / n))) * 180 / Math.PI,
|
|
9280
|
-
radius: ring.radius * ring.tileMetres
|
|
9482
|
+
radius: ring.radius * ring.tileMetres,
|
|
9483
|
+
...ring.fade ? { forward: ring.fade.end * ring.tileMetres } : {}
|
|
9281
9484
|
};
|
|
9282
9485
|
}
|
|
9283
9486
|
function ringIn(x3, y2) {
|
|
9284
9487
|
const ring = camera.ring();
|
|
9285
9488
|
if (!ring) return [0, 0, 0, 0];
|
|
9286
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
|
+
];
|
|
9287
9497
|
const cx = (ring.centre[0] - x3) * extent4;
|
|
9288
9498
|
const cy = (ring.centre[1] - y2) * extent4;
|
|
9289
9499
|
const inner = ring.radius * extent4 * 0.8;
|
|
@@ -9297,6 +9507,8 @@ function createTileflowBuildings3D(options) {
|
|
|
9297
9507
|
return [Math.sin(bearing), -Math.cos(bearing)];
|
|
9298
9508
|
}
|
|
9299
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];
|
|
9300
9512
|
const radius = ring[3];
|
|
9301
9513
|
if (!(radius > 0)) return true;
|
|
9302
9514
|
const cx = ring[0];
|
|
@@ -9362,20 +9574,21 @@ function createTileflowBuildings3D(options) {
|
|
|
9362
9574
|
masks = {};
|
|
9363
9575
|
const shown = visibleScale();
|
|
9364
9576
|
const entries = variant === args.shaderData.variantName && shown > 0 && ground ? drawn() : [];
|
|
9365
|
-
|
|
9577
|
+
const contactRadius = mixed2((entry) => entry.groundOcclusionRadius ?? tileflowBuildingOcclusion.ground);
|
|
9578
|
+
if (design().occlusion && contactRadius > 0 && entries.length > 0) {
|
|
9366
9579
|
const program = programs.contact;
|
|
9367
9580
|
masks.contact = contactMask.render(context, () => {
|
|
9368
9581
|
context.useProgram(program.program);
|
|
9369
9582
|
context.uniform1f(program.uniforms.u_scale, shown);
|
|
9370
9583
|
context.uniform1f(program.uniforms.u_metres, camera.metres);
|
|
9371
|
-
context.uniform1f(program.uniforms.u_band,
|
|
9584
|
+
context.uniform1f(program.uniforms.u_band, contactRadius);
|
|
9372
9585
|
context.uniform1f(
|
|
9373
9586
|
program.uniforms.u_band_strength,
|
|
9374
9587
|
mixed2((entry) => entry.groundOcclusion ?? tileflowBuildingOcclusion.groundStrength) * visibleOpacity()
|
|
9375
9588
|
);
|
|
9376
9589
|
for (const tile of entries) {
|
|
9377
9590
|
const { x: x3, y: y2, value } = tile;
|
|
9378
|
-
const ranges = viewRanges(args, tile,
|
|
9591
|
+
const ranges = viewRanges(args, tile, contactRadius, true);
|
|
9379
9592
|
if (!ranges.length) continue;
|
|
9380
9593
|
const { contact } = value.gl;
|
|
9381
9594
|
project(context, program, args, x3, y2);
|
|
@@ -9513,6 +9726,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9513
9726
|
);
|
|
9514
9727
|
context.uniform4f(u.u_ring ?? null, ...ringIn(x3, y2));
|
|
9515
9728
|
context.uniform2f(u.u_ring_ahead ?? null, ...ahead);
|
|
9729
|
+
context.uniform1i(u.u_ring_directional ?? null, camera.ring()?.fade ? 1 : 0);
|
|
9516
9730
|
const palette = themes ? paletteOf(context, entry, themes.themes) : void 0;
|
|
9517
9731
|
context.uniform1f(u.u_palette_on, palette ? 1 : 0);
|
|
9518
9732
|
context.activeTexture(context.TEXTURE1);
|
|
@@ -9583,6 +9797,12 @@ function createTileflowBuildings3D(options) {
|
|
|
9583
9797
|
context.uniform3fv(m.u_sun_light, light.sunLight);
|
|
9584
9798
|
context.uniform3fv(m.u_sky_light, light.skyLight);
|
|
9585
9799
|
context.uniform1f(m.u_night, light.night);
|
|
9800
|
+
context.uniform3f(
|
|
9801
|
+
m.u_facade_shading,
|
|
9802
|
+
mixed2((entry) => entry.verticalGradient ? 1 : 0),
|
|
9803
|
+
occlusionOn ? mixed2((entry) => entry.groundOcclusion ?? 0.16) : 0,
|
|
9804
|
+
mixed2((entry) => entry.groundOcclusionRadius ?? 3)
|
|
9805
|
+
);
|
|
9586
9806
|
context.uniform1f(
|
|
9587
9807
|
m.u_ambient_occlusion,
|
|
9588
9808
|
occlusionOn ? mixed2((entry) => entry.modelOcclusion ?? 0.75) : 0
|
|
@@ -9599,6 +9819,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9599
9819
|
context.uniform4fv(m.u_role_emission_gradient, emission.gradients);
|
|
9600
9820
|
context.uniform1fv(m.u_role_emission_power, emission.powers);
|
|
9601
9821
|
context.uniform4fv(m.u_role_colour, emission.materialColours);
|
|
9822
|
+
context.uniform1fv(m.u_role_color_scale, emission.colorScales);
|
|
9602
9823
|
context.uniform4fv(m.u_role_material, emission.materials);
|
|
9603
9824
|
context.uniform3fv(m.u_role_appearance, emission.appearance);
|
|
9604
9825
|
const at = placed2(stand.tileX, stand.tileY);
|
|
@@ -10020,6 +10241,83 @@ function isWebGL2(context) {
|
|
|
10020
10241
|
return typeof WebGL2RenderingContext !== "undefined" && context instanceof WebGL2RenderingContext;
|
|
10021
10242
|
}
|
|
10022
10243
|
|
|
10244
|
+
// src/camera.ts
|
|
10245
|
+
var tileflowCameraMetadataKey = "tileflow:camera";
|
|
10246
|
+
function readTileflowCamera(metadata) {
|
|
10247
|
+
if (!metadata || typeof metadata !== "object") return {};
|
|
10248
|
+
const value = metadata[tileflowCameraMetadataKey];
|
|
10249
|
+
if (!value || typeof value !== "object") return {};
|
|
10250
|
+
const policy = value;
|
|
10251
|
+
return policy.version === 1 && typeof policy.adaptivePerspective === "boolean" ? { adaptivePerspective: policy.adaptivePerspective } : {};
|
|
10252
|
+
}
|
|
10253
|
+
|
|
10254
|
+
// src/camera-browser.ts
|
|
10255
|
+
function tileflowAdaptiveFieldOfView(pitch, zoom, height, normalFieldOfView) {
|
|
10256
|
+
if (pitch >= 15 || zoom <= 13 || height <= 0) return normalFieldOfView;
|
|
10257
|
+
const tangent = Math.tan(normalFieldOfView * Math.PI / 360);
|
|
10258
|
+
const distance = height / (2 * tangent);
|
|
10259
|
+
const mix2 = (Math.max(0, pitch) / 15) ** 5;
|
|
10260
|
+
const nearTangent = Math.max(
|
|
10261
|
+
Math.tan(Math.min(6, normalFieldOfView) * Math.PI / 360),
|
|
10262
|
+
height * mix2 / (2 * (1 - mix2 + mix2 * distance))
|
|
10263
|
+
);
|
|
10264
|
+
const t = Math.min(1, Math.max(0, (zoom - 13) / 2));
|
|
10265
|
+
const amount = t * t * (3 - 2 * t);
|
|
10266
|
+
return Math.atan(tangent + (nearTangent - tangent) * amount) * 360 / Math.PI;
|
|
10267
|
+
}
|
|
10268
|
+
function createTileflowAdaptiveCamera(map) {
|
|
10269
|
+
let normal;
|
|
10270
|
+
let applying = false;
|
|
10271
|
+
let disposed = false;
|
|
10272
|
+
const write = (next) => {
|
|
10273
|
+
if (applying || Math.abs((map.getVerticalFieldOfView?.() ?? next) - next) < 1e-6) return;
|
|
10274
|
+
applying = true;
|
|
10275
|
+
try {
|
|
10276
|
+
map.setVerticalFieldOfView?.(next);
|
|
10277
|
+
} finally {
|
|
10278
|
+
applying = false;
|
|
10279
|
+
}
|
|
10280
|
+
};
|
|
10281
|
+
const update = () => {
|
|
10282
|
+
if (disposed || applying || normal === void 0) return;
|
|
10283
|
+
write(
|
|
10284
|
+
tileflowAdaptiveFieldOfView(
|
|
10285
|
+
map.getPitch(),
|
|
10286
|
+
map.getZoom(),
|
|
10287
|
+
map.getCanvas().clientHeight,
|
|
10288
|
+
normal
|
|
10289
|
+
)
|
|
10290
|
+
);
|
|
10291
|
+
};
|
|
10292
|
+
const setEnabled = (enabled) => {
|
|
10293
|
+
if (disposed) return;
|
|
10294
|
+
if (enabled) {
|
|
10295
|
+
if (!map.getVerticalFieldOfView || !map.setVerticalFieldOfView || !map.getCanvas) return;
|
|
10296
|
+
normal ??= map.getVerticalFieldOfView();
|
|
10297
|
+
update();
|
|
10298
|
+
} else if (normal !== void 0) {
|
|
10299
|
+
const restore = normal;
|
|
10300
|
+
normal = void 0;
|
|
10301
|
+
write(restore);
|
|
10302
|
+
}
|
|
10303
|
+
};
|
|
10304
|
+
const onRemove = () => dispose(false);
|
|
10305
|
+
function dispose(restore = true) {
|
|
10306
|
+
if (disposed) return;
|
|
10307
|
+
if (restore) setEnabled(false);
|
|
10308
|
+
disposed = true;
|
|
10309
|
+
map.off("pitch", update);
|
|
10310
|
+
map.off("zoom", update);
|
|
10311
|
+
map.off("resize", update);
|
|
10312
|
+
map.off("remove", onRemove);
|
|
10313
|
+
}
|
|
10314
|
+
map.on("pitch", update);
|
|
10315
|
+
map.on("zoom", update);
|
|
10316
|
+
map.on("resize", update);
|
|
10317
|
+
map.on("remove", onRemove);
|
|
10318
|
+
return { setEnabled, dispose };
|
|
10319
|
+
}
|
|
10320
|
+
|
|
10023
10321
|
// src/vegetation-display.ts
|
|
10024
10322
|
var tileflowVegetationDisplayMetadataKey = "tileflow:vegetation-display";
|
|
10025
10323
|
function readTileflowVegetationDisplay(metadata) {
|
|
@@ -11201,6 +11499,7 @@ uniform float u_metres; // metres per tile unit
|
|
|
11201
11499
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
11202
11500
|
uniform float u_minimum_height; // optional visual height floor, in metres
|
|
11203
11501
|
uniform vec2 u_size_scale; // the map's height and crown scales, for this form
|
|
11502
|
+
uniform vec3 u_size_compression; // reference height, reference crown, strength
|
|
11204
11503
|
uniform float u_round; // how far normals turn from the facets to the round shape, by finish
|
|
11205
11504
|
|
|
11206
11505
|
float growthOf() {
|
|
@@ -11217,7 +11516,14 @@ vec2 turned(vec2 v) {
|
|
|
11217
11516
|
|
|
11218
11517
|
vec2 displaySize() {
|
|
11219
11518
|
vec2 size = a_tree_size * 0.1 * u_size_scale;
|
|
11220
|
-
|
|
11519
|
+
size *= max(1.0, u_minimum_height / max(size.x, 0.001));
|
|
11520
|
+
// Scale the complete tree together to preserve crown, trunk and branch proportions.
|
|
11521
|
+
if (u_size_compression.z > 0.0) {
|
|
11522
|
+
vec2 relative = max(u_size_compression.xy, vec2(0.001)) / max(size, vec2(0.001));
|
|
11523
|
+
// Balance height and footprint, so a short but broad crown is not enlarged.
|
|
11524
|
+
size *= min(1.35, pow(relative.x * relative.y, u_size_compression.z * 0.5));
|
|
11525
|
+
}
|
|
11526
|
+
return size;
|
|
11221
11527
|
}
|
|
11222
11528
|
|
|
11223
11529
|
vec3 standing(float growth) {
|
|
@@ -11763,7 +12069,9 @@ function createTileflowTrees3D(options) {
|
|
|
11763
12069
|
forms: tileflowTreeForms.map((form) => [
|
|
11764
12070
|
theme?.forms[form]?.heightScale ?? 1,
|
|
11765
12071
|
theme?.forms[form]?.crownScale ?? 1,
|
|
11766
|
-
|
|
12072
|
+
theme?.forms[form]?.sizeAnchor ?? 8.5,
|
|
12073
|
+
theme?.forms[form]?.crownAnchor ?? 5,
|
|
12074
|
+
theme?.forms[form]?.sizeCompression ?? 0
|
|
11767
12075
|
]),
|
|
11768
12076
|
edges: [[theme?.edges ?? 0, 0, 0]],
|
|
11769
12077
|
edgeColor: [[...rgb(theme?.edgeColor ?? "#000000") ?? [0, 0, 0]]],
|
|
@@ -11788,6 +12096,12 @@ function createTileflowTrees3D(options) {
|
|
|
11788
12096
|
[size[0] * forms[index][0], size[1] * forms[index][1]]
|
|
11789
12097
|
])
|
|
11790
12098
|
),
|
|
12099
|
+
compressions: Object.fromEntries(
|
|
12100
|
+
tileflowTreeForms.map((form, index) => [
|
|
12101
|
+
form,
|
|
12102
|
+
[forms[index][2], forms[index][3], forms[index][4]]
|
|
12103
|
+
])
|
|
12104
|
+
),
|
|
11791
12105
|
finish: (t < 0.5 ? a : b2)?.finish ?? "faceted",
|
|
11792
12106
|
edges: mixList(x3.edges, y2.edges)[0][0],
|
|
11793
12107
|
edgeColor: mixList(x3.edgeColor, y2.edgeColor)[0],
|
|
@@ -11824,17 +12138,21 @@ function createTileflowTrees3D(options) {
|
|
|
11824
12138
|
tallest = Math.max(tallest, value.placement.tallest);
|
|
11825
12139
|
}
|
|
11826
12140
|
if (!Number.isFinite(left)) return void 0;
|
|
11827
|
-
const
|
|
12141
|
+
const palette2 = colours();
|
|
12142
|
+
const maximumGrowth = Object.values(palette2.compressions).some(
|
|
12143
|
+
([, , strength]) => strength > 0
|
|
12144
|
+
) ? 1.35 : 1;
|
|
12145
|
+
const maximumScale = maximumGrowth > 1 ? Math.max(...Object.values(palette2.sizes).map((size) => size[0])) : palette2.size[0];
|
|
11828
12146
|
return {
|
|
11829
12147
|
zoom: preferredZoom3,
|
|
11830
12148
|
tiles: [left, top, right, bottom],
|
|
11831
|
-
tallest: Math.max(tallest *
|
|
12149
|
+
tallest: Math.max(tallest * maximumScale, palette2.minimumHeight) * maximumGrowth * shown
|
|
11832
12150
|
};
|
|
11833
12151
|
},
|
|
11834
12152
|
// Camera-dependent density, detail and fading also change the trees casting shadows.
|
|
11835
12153
|
key: () => `trees:${colours().minimumHeight.toFixed(3)}:${map.isMoving?.() ? view().movingKey : view().key}:${fadeIn().toFixed(4)}:${visibleScale().toFixed(4)}:${generation}:${programs.depth ? 1 : 0}:${Object.values(
|
|
11836
12154
|
colours().sizes
|
|
11837
|
-
).flat().map((value) => value.toFixed(3)).join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
|
|
12155
|
+
).flat().map((value) => value.toFixed(3)).join()}:${Object.values(colours().compressions).flat().join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
|
|
11838
12156
|
drawDepth(context, frame) {
|
|
11839
12157
|
const program = programs.depth;
|
|
11840
12158
|
if (!program || !meshes) return;
|
|
@@ -11844,6 +12162,7 @@ function createTileflowTrees3D(options) {
|
|
|
11844
12162
|
context.uniform1f(u.u_metres, frame.metres);
|
|
11845
12163
|
context.uniformMatrix4fv(u.u_light_matrix, false, frame.light.matrix);
|
|
11846
12164
|
const sizes = colours().sizes;
|
|
12165
|
+
const compressions = colours().compressions;
|
|
11847
12166
|
const minimumHeight = colours().minimumHeight;
|
|
11848
12167
|
const camera = view();
|
|
11849
12168
|
context.uniform1f(u.u_fade, 1);
|
|
@@ -11864,12 +12183,14 @@ function createTileflowTrees3D(options) {
|
|
|
11864
12183
|
const drawing = value.gl.vaos.get(`${form}:${model}:${selection.level}`);
|
|
11865
12184
|
if (instances === 0 || !drawing) return;
|
|
11866
12185
|
context.uniform2f(u.u_size_scale, sizes[form][0], sizes[form][1] * drawing.crown);
|
|
12186
|
+
context.uniform3f(u.u_size_compression, ...compressions[form]);
|
|
11867
12187
|
context.bindVertexArray(drawing.vao);
|
|
11868
12188
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
11869
12189
|
});
|
|
11870
12190
|
const hedge = value.gl.hedge;
|
|
11871
12191
|
if (hedge) {
|
|
11872
12192
|
context.uniform1f(u.u_minimum_height, 0);
|
|
12193
|
+
context.uniform3f(u.u_size_compression, 1, 1, 0);
|
|
11873
12194
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
11874
12195
|
context.bindVertexArray(hedge.vao);
|
|
11875
12196
|
context.drawArraysInstanced(
|
|
@@ -11955,6 +12276,7 @@ function createTileflowTrees3D(options) {
|
|
|
11955
12276
|
];
|
|
11956
12277
|
context.uniform1f(u.u_minimum_height, palette2.minimumHeight);
|
|
11957
12278
|
context.uniform2f(u.u_size_scale, ...size);
|
|
12279
|
+
context.uniform3f(u.u_size_compression, ...palette2.compressions[form]);
|
|
11958
12280
|
context.bindVertexArray(drawing.vao);
|
|
11959
12281
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
11960
12282
|
count += instances;
|
|
@@ -11965,6 +12287,7 @@ function createTileflowTrees3D(options) {
|
|
|
11965
12287
|
leaves,
|
|
11966
12288
|
size,
|
|
11967
12289
|
minimumHeight: palette2.minimumHeight,
|
|
12290
|
+
compression: palette2.compressions[form],
|
|
11968
12291
|
instances,
|
|
11969
12292
|
drawing
|
|
11970
12293
|
});
|
|
@@ -11975,6 +12298,7 @@ function createTileflowTrees3D(options) {
|
|
|
11975
12298
|
const instances = value.placement.hedges.length / tileflowTreeBytes;
|
|
11976
12299
|
context.uniform3fv(u.u_leaves, palette2.hedge.flat());
|
|
11977
12300
|
context.uniform1f(u.u_minimum_height, 0);
|
|
12301
|
+
context.uniform3f(u.u_size_compression, 1, 1, 0);
|
|
11978
12302
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
11979
12303
|
context.bindVertexArray(hedge.vao);
|
|
11980
12304
|
context.drawArraysInstanced(context.TRIANGLES, 0, hedge.count, instances);
|
|
@@ -11985,6 +12309,7 @@ function createTileflowTrees3D(options) {
|
|
|
11985
12309
|
leaves: palette2.hedge,
|
|
11986
12310
|
size: [1, 1],
|
|
11987
12311
|
minimumHeight: 0,
|
|
12312
|
+
compression: [1, 1, 0],
|
|
11988
12313
|
instances,
|
|
11989
12314
|
drawing: hedge
|
|
11990
12315
|
});
|
|
@@ -12027,6 +12352,7 @@ function createTileflowTrees3D(options) {
|
|
|
12027
12352
|
);
|
|
12028
12353
|
context.uniform1f(e.u_minimum_height, draw2.minimumHeight);
|
|
12029
12354
|
context.uniform2f(e.u_size_scale, ...draw2.size);
|
|
12355
|
+
context.uniform3f(e.u_size_compression, ...draw2.compression);
|
|
12030
12356
|
context.bindVertexArray(draw2.drawing.vao);
|
|
12031
12357
|
context.drawArraysInstanced(context.TRIANGLES, 0, draw2.drawing.count, draw2.instances);
|
|
12032
12358
|
}
|
|
@@ -12579,9 +12905,15 @@ function createTileflowMap3D(options) {
|
|
|
12579
12905
|
const { map, controller, transformRequest } = options;
|
|
12580
12906
|
let viewMode = options.viewMode ?? "3d";
|
|
12581
12907
|
let vegetationVisible = options.vegetation;
|
|
12908
|
+
let adaptivePerspective = options.camera?.adaptivePerspective;
|
|
12909
|
+
const camera = createTileflowAdaptiveCamera(map);
|
|
12910
|
+
let authoredPerspective;
|
|
12582
12911
|
let buildings;
|
|
12583
12912
|
let vegetation;
|
|
12584
12913
|
let streetLights;
|
|
12914
|
+
const flatBuildings = createBuildingFlatLayers(map);
|
|
12915
|
+
let footprintLayers;
|
|
12916
|
+
let footprintZoom = 15.3;
|
|
12585
12917
|
let disposed = false;
|
|
12586
12918
|
let syncing = false;
|
|
12587
12919
|
const shared3 = {
|
|
@@ -12596,6 +12928,19 @@ function createTileflowMap3D(options) {
|
|
|
12596
12928
|
syncing = true;
|
|
12597
12929
|
try {
|
|
12598
12930
|
const shown = viewMode === "3d";
|
|
12931
|
+
if (footprintLayers === void 0) {
|
|
12932
|
+
const themes = controller?.getThemeMetadata?.(tileflowBuildingsMetadataKey);
|
|
12933
|
+
const metadata = themes ? { [tileflowBuildingsMetadataKey]: themes.values[Math.round(themes.position)] } : map.getStyle()?.metadata;
|
|
12934
|
+
const design = readTileflowBuildings3D(metadata);
|
|
12935
|
+
footprintLayers = design?.flatLayers ?? [];
|
|
12936
|
+
footprintZoom = design?.entrance?.buildings?.[1] ?? 15.3;
|
|
12937
|
+
}
|
|
12938
|
+
if (authoredPerspective === void 0) {
|
|
12939
|
+
const themes = controller?.getThemeMetadata?.(tileflowCameraMetadataKey);
|
|
12940
|
+
const metadata = themes ? { [tileflowCameraMetadataKey]: themes.values[Math.round(themes.position)] } : map.getStyle()?.metadata;
|
|
12941
|
+
authoredPerspective = readTileflowCamera(metadata).adaptivePerspective ?? false;
|
|
12942
|
+
}
|
|
12943
|
+
camera.setEnabled(shown && (adaptivePerspective ?? authoredPerspective));
|
|
12599
12944
|
const declared = declarations ??= tileflowMap3DDeclarations({
|
|
12600
12945
|
map,
|
|
12601
12946
|
...controller ? { controller } : {}
|
|
@@ -12609,6 +12954,7 @@ function createTileflowMap3D(options) {
|
|
|
12609
12954
|
}
|
|
12610
12955
|
if (!vegetation && (declares(tileflowVegetationMetadataKey) || declares(tileflowVegetationDisplayMetadataKey)))
|
|
12611
12956
|
vegetation = createTileflowVegetation({ ...shared3, visible: vegetationVisible, viewMode });
|
|
12957
|
+
syncFlatBuildings();
|
|
12612
12958
|
if (shown && declares(tileflowStreetLightsMetadataKey))
|
|
12613
12959
|
streetLights ??= createTileflowStreetLights(shared3);
|
|
12614
12960
|
else if (streetLights) {
|
|
@@ -12619,9 +12965,22 @@ function createTileflowMap3D(options) {
|
|
|
12619
12965
|
syncing = false;
|
|
12620
12966
|
}
|
|
12621
12967
|
}
|
|
12968
|
+
function syncFlatBuildings() {
|
|
12969
|
+
if (disposed) return;
|
|
12970
|
+
if (!footprintLayers?.length) {
|
|
12971
|
+
flatBuildings.restore();
|
|
12972
|
+
return;
|
|
12973
|
+
}
|
|
12974
|
+
const canvas = map.getCanvas?.();
|
|
12975
|
+
flatBuildings.update(
|
|
12976
|
+
footprintLayers,
|
|
12977
|
+
viewMode === "3d" && Boolean(buildings) && map.getZoom() >= footprintZoom && Boolean(canvas?.getContext?.("webgl2"))
|
|
12978
|
+
);
|
|
12979
|
+
}
|
|
12622
12980
|
function change(next, transition) {
|
|
12623
12981
|
if (disposed) return Promise.resolve();
|
|
12624
12982
|
viewMode = next;
|
|
12983
|
+
camera.setEnabled(next === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
|
|
12625
12984
|
vegetation?.setViewMode(next);
|
|
12626
12985
|
if (next === "3d") {
|
|
12627
12986
|
const existing = buildings;
|
|
@@ -12637,10 +12996,13 @@ function createTileflowMap3D(options) {
|
|
|
12637
12996
|
function dispose() {
|
|
12638
12997
|
if (disposed) return;
|
|
12639
12998
|
disposed = true;
|
|
12999
|
+
flatBuildings.restore();
|
|
13000
|
+
camera.dispose();
|
|
12640
13001
|
map.off("styledata", restyle);
|
|
12641
13002
|
map.off("style.load", restyle);
|
|
12642
13003
|
map.off("idle", sync);
|
|
12643
|
-
map.off("remove",
|
|
13004
|
+
map.off("remove", onRemove);
|
|
13005
|
+
map.off("move", syncFlatBuildings);
|
|
12644
13006
|
streetLights?.dispose();
|
|
12645
13007
|
buildings?.dispose();
|
|
12646
13008
|
vegetation?.dispose();
|
|
@@ -12649,13 +13011,21 @@ function createTileflowMap3D(options) {
|
|
|
12649
13011
|
vegetation = void 0;
|
|
12650
13012
|
}
|
|
12651
13013
|
function restyle() {
|
|
13014
|
+
if (syncing) return;
|
|
13015
|
+
footprintLayers = void 0;
|
|
12652
13016
|
declarations = void 0;
|
|
13017
|
+
authoredPerspective = void 0;
|
|
12653
13018
|
sync();
|
|
12654
13019
|
}
|
|
13020
|
+
function onRemove() {
|
|
13021
|
+
flatBuildings.forget();
|
|
13022
|
+
dispose();
|
|
13023
|
+
}
|
|
12655
13024
|
map.on("styledata", restyle);
|
|
12656
13025
|
map.on("style.load", restyle);
|
|
12657
13026
|
map.on("idle", sync);
|
|
12658
|
-
map.on("remove",
|
|
13027
|
+
map.on("remove", onRemove);
|
|
13028
|
+
map.on("move", syncFlatBuildings);
|
|
12659
13029
|
sync();
|
|
12660
13030
|
return {
|
|
12661
13031
|
show: (transition) => change("3d", transition),
|
|
@@ -12667,6 +13037,11 @@ function createTileflowMap3D(options) {
|
|
|
12667
13037
|
vegetationVisible = visible;
|
|
12668
13038
|
vegetation?.setVisible(visible);
|
|
12669
13039
|
},
|
|
13040
|
+
setAdaptivePerspective(enabled) {
|
|
13041
|
+
adaptivePerspective = enabled;
|
|
13042
|
+
camera.setEnabled(viewMode === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
|
|
13043
|
+
sync();
|
|
13044
|
+
},
|
|
12670
13045
|
get buildings() {
|
|
12671
13046
|
return buildings;
|
|
12672
13047
|
},
|