@tileflow/core 0.1.0-alpha.42 → 0.1.0-alpha.43
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 +50 -68
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/{3d-CzLTD0RK.d.ts → 3d-CW5Ls0An.d.ts} +32 -2
- package/dist/3d.d.ts +1 -1
- package/dist/3d.js +301 -22
- package/dist/browser.d.ts +95 -5
- package/dist/browser.js +713 -45
- 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 +4 -5
- 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/browser.js
CHANGED
|
@@ -2708,7 +2708,7 @@ var init_dist = __esm({
|
|
|
2708
2708
|
function command(cmd, length) {
|
|
2709
2709
|
return (length << 3) + (cmd & 7);
|
|
2710
2710
|
}
|
|
2711
|
-
function
|
|
2711
|
+
function zigzag3(num2) {
|
|
2712
2712
|
return num2 << 1 ^ num2 >> 31;
|
|
2713
2713
|
}
|
|
2714
2714
|
function writeGeometry(feature, pbf) {
|
|
@@ -2732,8 +2732,8 @@ var init_dist = __esm({
|
|
|
2732
2732
|
}
|
|
2733
2733
|
const dx = ring[i2 * 2] - x3;
|
|
2734
2734
|
const dy = ring[i2 * 2 + 1] - y2;
|
|
2735
|
-
pbf.writeVarint(
|
|
2736
|
-
pbf.writeVarint(
|
|
2735
|
+
pbf.writeVarint(zigzag3(dx));
|
|
2736
|
+
pbf.writeVarint(zigzag3(dy));
|
|
2737
2737
|
x3 += dx;
|
|
2738
2738
|
y2 += dy;
|
|
2739
2739
|
}
|
|
@@ -3304,7 +3304,11 @@ function createTileflowDynamicImageRegistry(input, context, beforeRestore) {
|
|
|
3304
3304
|
if (existing && existing !== entry.installed && !isRestoredCopy(existing, entry.recoveryImage)) {
|
|
3305
3305
|
throw new Error(`Dynamic image "${entry.name}" conflicts with an existing image owner.`);
|
|
3306
3306
|
}
|
|
3307
|
-
if (!existing)
|
|
3307
|
+
if (!existing)
|
|
3308
|
+
map.addImage(entry.name, entry.pixels, {
|
|
3309
|
+
pixelRatio: entry.pixelRatio,
|
|
3310
|
+
...entry.definition.sdf ? { sdf: true } : {}
|
|
3311
|
+
});
|
|
3308
3312
|
else if (changed) map.updateImage(entry.name, entry.pixels);
|
|
3309
3313
|
entry.installed = map.getImage(entry.name);
|
|
3310
3314
|
entry.recoveryImage = void 0;
|
|
@@ -5737,6 +5741,59 @@ function withAlpha(color, alpha) {
|
|
|
5737
5741
|
// src/browser.ts
|
|
5738
5742
|
init_camera_limits();
|
|
5739
5743
|
|
|
5744
|
+
// src/horizon-queries-browser.ts
|
|
5745
|
+
var horizonShare2 = 0.85;
|
|
5746
|
+
var maximumHorizonAngle = 89.25 * Math.PI / 180;
|
|
5747
|
+
function tileflowHorizonScaleFactor(view) {
|
|
5748
|
+
const pitch = view.pitch * Math.PI / 180;
|
|
5749
|
+
const horizon = Math.min(
|
|
5750
|
+
Math.tan(Math.PI / 2 - pitch) * horizonShare2,
|
|
5751
|
+
Math.tan(maximumHorizonAngle - pitch)
|
|
5752
|
+
);
|
|
5753
|
+
const top = Math.min(view.centerY / view.cameraToCenterDistance, horizon);
|
|
5754
|
+
return 1 / (1 - Math.tan(pitch) * top);
|
|
5755
|
+
}
|
|
5756
|
+
function attachTileflowHorizonQueries(map) {
|
|
5757
|
+
const target = map;
|
|
5758
|
+
const query = target.queryRenderedFeatures;
|
|
5759
|
+
if (typeof query !== "function") return () => {
|
|
5760
|
+
};
|
|
5761
|
+
const own = Object.prototype.hasOwnProperty.call(target, "queryRenderedFeatures");
|
|
5762
|
+
const corrected = /* @__PURE__ */ new Map();
|
|
5763
|
+
const correct = (transform) => {
|
|
5764
|
+
const original = transform?.maxPitchScaleFactor;
|
|
5765
|
+
if (!transform || typeof original !== "function" || corrected.has(transform)) return;
|
|
5766
|
+
const own2 = Object.prototype.hasOwnProperty.call(transform, "maxPitchScaleFactor");
|
|
5767
|
+
corrected.set(transform, own2 ? original : void 0);
|
|
5768
|
+
transform.maxPitchScaleFactor = function() {
|
|
5769
|
+
const value = original.call(this);
|
|
5770
|
+
if (value > 0 && Number.isFinite(value)) return value;
|
|
5771
|
+
const fallback = tileflowHorizonScaleFactor({
|
|
5772
|
+
pitch: this.pitch,
|
|
5773
|
+
centerY: this.centerPoint.y,
|
|
5774
|
+
cameraToCenterDistance: this.cameraToCenterDistance
|
|
5775
|
+
});
|
|
5776
|
+
return fallback > 0 && Number.isFinite(fallback) ? fallback : value;
|
|
5777
|
+
};
|
|
5778
|
+
};
|
|
5779
|
+
const wrapped = function(...args) {
|
|
5780
|
+
correct(target._camera?.transform ?? target.transform);
|
|
5781
|
+
return query.apply(this, args);
|
|
5782
|
+
};
|
|
5783
|
+
target.queryRenderedFeatures = wrapped;
|
|
5784
|
+
return () => {
|
|
5785
|
+
if (target.queryRenderedFeatures === wrapped) {
|
|
5786
|
+
if (own) target.queryRenderedFeatures = query;
|
|
5787
|
+
else delete target.queryRenderedFeatures;
|
|
5788
|
+
}
|
|
5789
|
+
for (const [transform, original] of corrected) {
|
|
5790
|
+
if (original) transform.maxPitchScaleFactor = original;
|
|
5791
|
+
else delete transform.maxPitchScaleFactor;
|
|
5792
|
+
}
|
|
5793
|
+
corrected.clear();
|
|
5794
|
+
};
|
|
5795
|
+
}
|
|
5796
|
+
|
|
5740
5797
|
// src/canvas-context-browser.ts
|
|
5741
5798
|
function tileflowCanvasContextAttributes(attributes4) {
|
|
5742
5799
|
return { antialias: true, ...attributes4 };
|
|
@@ -6384,6 +6441,7 @@ function readModelRoleLighting(value) {
|
|
|
6384
6441
|
...typeof entry.emissiveColor === "string" ? { emissiveColor: entry.emissiveColor } : {},
|
|
6385
6442
|
...typeof entry.color === "string" ? { color: entry.color } : {},
|
|
6386
6443
|
...entry.colorMix === void 0 ? {} : { colorMix: bounded(entry.colorMix, 0, 1, 1) },
|
|
6444
|
+
...entry.colorScale === void 0 ? {} : { colorScale: bounded(entry.colorScale, 0, 1, 1) },
|
|
6387
6445
|
...entry.metallic === void 0 ? {} : { metallic: bounded(entry.metallic, 0, 1, 0) },
|
|
6388
6446
|
...entry.roughness === void 0 ? {} : { roughness: bounded(entry.roughness, 0, 1, 1) },
|
|
6389
6447
|
...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
|
|
@@ -6486,6 +6544,7 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
|
6486
6544
|
shadows: true,
|
|
6487
6545
|
occlusion: true,
|
|
6488
6546
|
groundOcclusion: 0.16,
|
|
6547
|
+
groundOcclusionRadius: 3,
|
|
6489
6548
|
modelOcclusion: 0.75
|
|
6490
6549
|
});
|
|
6491
6550
|
function readTileflowBuildings3D(metadata) {
|
|
@@ -6523,7 +6582,11 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6523
6582
|
shadows: typeof value.shadows === "boolean" ? value.shadows : defaults.shadows,
|
|
6524
6583
|
occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults.occlusion,
|
|
6525
6584
|
groundOcclusion: within(value.groundOcclusion, 1, defaults.groundOcclusion),
|
|
6585
|
+
groundOcclusionRadius: within(value.groundOcclusionRadius, 20, defaults.groundOcclusionRadius),
|
|
6526
6586
|
modelOcclusion: within(value.modelOcclusion, 1, defaults.modelOcclusion),
|
|
6587
|
+
...Array.isArray(value.flatLayers) && value.flatLayers.length <= 128 && value.flatLayers.every(
|
|
6588
|
+
(entry) => isRecord6(entry) && typeof entry.id === "string" && typeof entry.visible === "boolean"
|
|
6589
|
+
) ? { flatLayers: value.flatLayers } : {},
|
|
6527
6590
|
...modelsOf(value.models),
|
|
6528
6591
|
...modelColorsOf(value.modelColors),
|
|
6529
6592
|
...landmarksOf(value.landmarks)
|
|
@@ -9750,6 +9813,9 @@ function readTileflowVegetation3D(metadata) {
|
|
|
9750
9813
|
{
|
|
9751
9814
|
heightScale: scale(own.heightScale),
|
|
9752
9815
|
crownScale: scale(own.crownScale),
|
|
9816
|
+
...typeof own.sizeAnchor === "number" && Number.isFinite(own.sizeAnchor) ? { sizeAnchor: clamp(own.sizeAnchor, [1, 45]) } : {},
|
|
9817
|
+
...typeof own.crownAnchor === "number" && Number.isFinite(own.crownAnchor) ? { crownAnchor: clamp(own.crownAnchor, [1, 25]) } : {},
|
|
9818
|
+
...typeof own.sizeCompression === "number" && Number.isFinite(own.sizeCompression) ? { sizeCompression: clamp(own.sizeCompression, [0, 1]) } : {},
|
|
9753
9819
|
...drawn.length > 0 ? { models: drawn } : {}
|
|
9754
9820
|
}
|
|
9755
9821
|
]
|
|
@@ -10069,7 +10135,7 @@ function browserWorker() {
|
|
|
10069
10135
|
if (typeof Worker === "undefined" || false)
|
|
10070
10136
|
return;
|
|
10071
10137
|
const url = URL.createObjectURL(
|
|
10072
|
-
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" })
|
|
10138
|
+
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" })
|
|
10073
10139
|
);
|
|
10074
10140
|
try {
|
|
10075
10141
|
return new Worker(url, { name: "tileflow-tiles" });
|
|
@@ -11579,7 +11645,7 @@ function createCameraTiles(options) {
|
|
|
11579
11645
|
}
|
|
11580
11646
|
entry.used = now;
|
|
11581
11647
|
entry.distance = distance;
|
|
11582
|
-
if ((!entry.value || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
11648
|
+
if ((!entry.value && !entry.pending || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
11583
11649
|
load(source, key, entry, chosen.tileMetres);
|
|
11584
11650
|
}
|
|
11585
11651
|
evict();
|
|
@@ -11595,6 +11661,8 @@ function createCameraTiles(options) {
|
|
|
11595
11661
|
).then((tile) => {
|
|
11596
11662
|
if (disposed || tiles.get(key) !== entry || entry.loading !== controller) return;
|
|
11597
11663
|
if (!tile) {
|
|
11664
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11665
|
+
entry.pending = void 0;
|
|
11598
11666
|
if (entry.value && entry.value !== options.empty) options.release(entry.value);
|
|
11599
11667
|
entry.value = options.empty;
|
|
11600
11668
|
entry.loading = void 0;
|
|
@@ -11643,10 +11711,11 @@ function createCameraTiles(options) {
|
|
|
11643
11711
|
if (value !== options.empty) options.release(value);
|
|
11644
11712
|
continue;
|
|
11645
11713
|
}
|
|
11646
|
-
|
|
11647
|
-
|
|
11714
|
+
if (entry.pending && entry.pending !== options.empty && entry.pending !== value)
|
|
11715
|
+
options.release(entry.pending);
|
|
11716
|
+
entry.pending = value;
|
|
11648
11717
|
entry.loading = void 0;
|
|
11649
|
-
|
|
11718
|
+
commit(entry);
|
|
11650
11719
|
built = true;
|
|
11651
11720
|
}
|
|
11652
11721
|
if (built && !disposed) {
|
|
@@ -11663,12 +11732,24 @@ function createCameraTiles(options) {
|
|
|
11663
11732
|
void step();
|
|
11664
11733
|
});
|
|
11665
11734
|
}
|
|
11735
|
+
function commit(entry) {
|
|
11736
|
+
const value = entry.pending;
|
|
11737
|
+
if (value === void 0 || value !== options.empty && options.isReady && !options.isReady(value))
|
|
11738
|
+
return;
|
|
11739
|
+
const previous = entry.value;
|
|
11740
|
+
entry.value = value;
|
|
11741
|
+
entry.pending = void 0;
|
|
11742
|
+
if (previous && previous !== options.empty && previous !== value) options.release(previous);
|
|
11743
|
+
options.changed();
|
|
11744
|
+
map.triggerRepaint();
|
|
11745
|
+
}
|
|
11666
11746
|
function evict() {
|
|
11667
11747
|
const keep = new Set(wanted);
|
|
11668
11748
|
const spare = [...tiles.entries()].filter(([key]) => !keep.has(key)).sort((a, b2) => b2[1].used - a[1].used);
|
|
11669
11749
|
for (const [key, entry] of spare.slice(options.maxTiles)) {
|
|
11670
11750
|
entry.loading?.abort();
|
|
11671
11751
|
if (entry.value && entry.value !== options.empty) options.release(entry.value);
|
|
11752
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11672
11753
|
tiles.delete(key);
|
|
11673
11754
|
options.changed();
|
|
11674
11755
|
}
|
|
@@ -11694,11 +11775,19 @@ function createCameraTiles(options) {
|
|
|
11694
11775
|
const list = [];
|
|
11695
11776
|
for (const key of wanted) {
|
|
11696
11777
|
const entry = tiles.get(key);
|
|
11778
|
+
if (entry) commit(entry);
|
|
11697
11779
|
if (entry?.value && entry.value !== options.empty)
|
|
11698
11780
|
list.push(entry);
|
|
11699
11781
|
}
|
|
11700
11782
|
return list;
|
|
11701
11783
|
},
|
|
11784
|
+
built() {
|
|
11785
|
+
return wanted.flatMap((key) => {
|
|
11786
|
+
const entry = tiles.get(key);
|
|
11787
|
+
const value = entry?.pending ?? entry?.value;
|
|
11788
|
+
return entry && value && value !== options.empty ? [{ ...entry, value }] : [];
|
|
11789
|
+
});
|
|
11790
|
+
},
|
|
11702
11791
|
coverage: () => covered,
|
|
11703
11792
|
ring: () => ring,
|
|
11704
11793
|
all: () => tiles.values(),
|
|
@@ -11720,6 +11809,8 @@ function createCameraTiles(options) {
|
|
|
11720
11809
|
for (const [key, entry] of tiles) {
|
|
11721
11810
|
if (!which(entry)) continue;
|
|
11722
11811
|
entry.loading?.abort();
|
|
11812
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11813
|
+
entry.pending = void 0;
|
|
11723
11814
|
entry.retryAt = void 0;
|
|
11724
11815
|
const latitude = Math.atan(Math.sinh(Math.PI * (1 - 2 * (entry.y + 0.5) / 2 ** zoom))) * 180 / Math.PI;
|
|
11725
11816
|
load(source, key, entry, earth * Math.cos(latitude * Math.PI / 180) / 2 ** zoom);
|
|
@@ -11732,7 +11823,10 @@ function createCameraTiles(options) {
|
|
|
11732
11823
|
map.off("sourcedata", onSource);
|
|
11733
11824
|
map.off("move", onMove);
|
|
11734
11825
|
map.off("moveend", onMoveEnd);
|
|
11735
|
-
for (const entry of tiles.values())
|
|
11826
|
+
for (const entry of tiles.values()) {
|
|
11827
|
+
entry.loading?.abort();
|
|
11828
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11829
|
+
}
|
|
11736
11830
|
tiles.clear();
|
|
11737
11831
|
queue.length = 0;
|
|
11738
11832
|
reader?.clear();
|
|
@@ -12459,7 +12553,9 @@ function tileflowModelCameraDistance(model, view) {
|
|
|
12459
12553
|
function tileflowModelLevel(model, view, previous) {
|
|
12460
12554
|
const thresholds = tileflowModelLevelDistancesOf(model.bounds);
|
|
12461
12555
|
const last = Math.max(0, Math.min(model.levels, thresholds.length + 1) - 1);
|
|
12462
|
-
const
|
|
12556
|
+
const fov = view.verticalFieldOfView;
|
|
12557
|
+
const lens = fov !== void 0 && fov > 0 && fov < 180 ? Math.tan(fov * Math.PI / 360) * 3 : 1;
|
|
12558
|
+
const distance = tileflowModelCameraDistance(model, view) * lens;
|
|
12463
12559
|
if (!Number.isFinite(distance)) return 0;
|
|
12464
12560
|
const margin = previous === void 0 ? 1 : tileflowModelLevelHysteresis;
|
|
12465
12561
|
let level = Math.max(0, Math.min(last, previous ?? 0));
|
|
@@ -12912,6 +13008,7 @@ out vec3 v_shadow;
|
|
|
12912
13008
|
out float v_light;
|
|
12913
13009
|
flat out int v_lighting_role;
|
|
12914
13010
|
out float v_height;
|
|
13011
|
+
out float v_ground_height;
|
|
12915
13012
|
out vec4 v_uv;
|
|
12916
13013
|
out vec4 v_rgba;
|
|
12917
13014
|
out vec3 v_position;
|
|
@@ -12940,6 +13037,7 @@ void main() {
|
|
|
12940
13037
|
v_light = a_paint.z / 255.0;
|
|
12941
13038
|
v_lighting_role = clamp(int(a_lighting_role + 0.5), 0, 6);
|
|
12942
13039
|
v_height = (m.z - u_model_height.x) / max(u_model_height.y, 0.001);
|
|
13040
|
+
v_ground_height = m.z;
|
|
12943
13041
|
}`;
|
|
12944
13042
|
var tileflowModelFragment = `#version 300 es
|
|
12945
13043
|
precision highp float;
|
|
@@ -12949,6 +13047,9 @@ in vec3 v_shadow;
|
|
|
12949
13047
|
in float v_light;
|
|
12950
13048
|
flat in int v_lighting_role;
|
|
12951
13049
|
in float v_height;
|
|
13050
|
+
in float v_ground_height;
|
|
13051
|
+
uniform vec3 u_facade_shading; // vertical gradient, ground-contact strength and radius in metres
|
|
13052
|
+
uniform float u_role_color_scale[7];
|
|
12952
13053
|
uniform vec3 u_sun_dir;
|
|
12953
13054
|
uniform vec3 u_sun_light;
|
|
12954
13055
|
uniform vec3 u_sky_light;
|
|
@@ -12976,6 +13077,16 @@ vec3 shade(vec3 normal, float lit, float occlusion) {
|
|
|
12976
13077
|
return min(pow(light / max(roof, vec3(1e-4)), vec3(1.0 / 2.2)), vec3(1.7));
|
|
12977
13078
|
}
|
|
12978
13079
|
|
|
13080
|
+
// Same quiet ground-to-facade transition as ordinary tile buildings, evaluated in metres.
|
|
13081
|
+
// Only map-shaded roles opt in; roofs and physical materials keep their own response.
|
|
13082
|
+
float facadeShade(vec3 normal, int role) {
|
|
13083
|
+
float wall = 1.0 - abs(normal.z);
|
|
13084
|
+
float up = max(v_ground_height, 0.0);
|
|
13085
|
+
float gradient = 0.1 * u_facade_shading.x * (1.0 - smoothstep(0.0, 3.0, up));
|
|
13086
|
+
float contact = u_facade_shading.y * exp(-up / max(u_facade_shading.z, 0.001));
|
|
13087
|
+
return 1.0 - max(gradient, contact) * wall * u_role_appearance[role].x;
|
|
13088
|
+
}
|
|
13089
|
+
|
|
12979
13090
|
void main() {
|
|
12980
13091
|
vec3 normal = normalize(gl_FrontFacing ? v_normal : -v_normal);
|
|
12981
13092
|
if (u_physical) normal = materialNormal(normal);
|
|
@@ -12990,7 +13101,7 @@ void main() {
|
|
|
12990
13101
|
float emission = clamp(u_role_emission[role] * multiplier, 0.0, 1.0);
|
|
12991
13102
|
if (u_physical) {
|
|
12992
13103
|
float alpha = materialAlpha();
|
|
12993
|
-
vec3 base = materialBase(role);
|
|
13104
|
+
vec3 base = materialBase(role) * fromSRGB(vec3(u_role_color_scale[role]));
|
|
12994
13105
|
float mapShare = u_role_appearance[role].x;
|
|
12995
13106
|
vec3 radiance;
|
|
12996
13107
|
if (mapShare >= 1.0) {
|
|
@@ -13000,13 +13111,14 @@ void main() {
|
|
|
13000
13111
|
if (mapShare > 0.0)
|
|
13001
13112
|
radiance = mix(radiance, base * fromSRGB(shade(normal, lit, u_role_appearance[role].y)), mapShare);
|
|
13002
13113
|
}
|
|
13114
|
+
radiance *= fromSRGB(vec3(facadeShade(normal, role)));
|
|
13003
13115
|
radiance += u_emissive * fromSRGB(materialTexture(4).rgb);
|
|
13004
13116
|
vec4 own = u_role_emission_colour[role];
|
|
13005
13117
|
radiance = mix(radiance, mix(base, fromSRGB(own.rgb), own.a), emission);
|
|
13006
13118
|
fragColor = vec4(hazed(toSRGB(radiance)), alpha * u_opacity);
|
|
13007
13119
|
return;
|
|
13008
13120
|
}
|
|
13009
|
-
vec3 colour = v_colour * shade(normal, lit, u_role_appearance[role].y);
|
|
13121
|
+
vec3 colour = v_colour * u_role_color_scale[role] * shade(normal, lit, u_role_appearance[role].y) * facadeShade(normal, role);
|
|
13010
13122
|
if (emission > 0.0) {
|
|
13011
13123
|
vec4 own = u_role_emission_colour[role];
|
|
13012
13124
|
vec3 target = mix(v_colour, own.rgb, own.a);
|
|
@@ -13864,7 +13976,7 @@ function createTileflowBuildings3D(options) {
|
|
|
13864
13976
|
let ahead = [0, -1];
|
|
13865
13977
|
const scene = tileflowScene3D(map);
|
|
13866
13978
|
let generation = 0;
|
|
13867
|
-
let
|
|
13979
|
+
let registered2 = false;
|
|
13868
13980
|
let unregister = () => {
|
|
13869
13981
|
};
|
|
13870
13982
|
const models = createTileflowPlacedModels({
|
|
@@ -13913,7 +14025,7 @@ function createTileflowBuildings3D(options) {
|
|
|
13913
14025
|
if (program) context.deleteProgram(program.program);
|
|
13914
14026
|
for (const entry of linking ?? []) context.deleteProgram(entry.program);
|
|
13915
14027
|
unregister();
|
|
13916
|
-
|
|
14028
|
+
registered2 = false;
|
|
13917
14029
|
scene.setReach(void 0);
|
|
13918
14030
|
scene.release(context);
|
|
13919
14031
|
if (ground) {
|
|
@@ -13944,12 +14056,12 @@ function createTileflowBuildings3D(options) {
|
|
|
13944
14056
|
drawMasks(context, args);
|
|
13945
14057
|
if (!programs.depth) return;
|
|
13946
14058
|
if (!design().shadows || visibleScale() <= 0 && modelScale() <= 0) {
|
|
13947
|
-
if (
|
|
13948
|
-
|
|
14059
|
+
if (registered2) unregister();
|
|
14060
|
+
registered2 = false;
|
|
13949
14061
|
return;
|
|
13950
14062
|
}
|
|
13951
|
-
if (!
|
|
13952
|
-
|
|
14063
|
+
if (!registered2) unregister = scene.register(caster);
|
|
14064
|
+
registered2 = true;
|
|
13953
14065
|
scene.prepare(context, lighting(), camera.metres);
|
|
13954
14066
|
},
|
|
13955
14067
|
render(context, args) {
|
|
@@ -14006,6 +14118,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14006
14118
|
return prepared ? { mesh: prepared.mesh, data: prepared.data } : emptyTile;
|
|
14007
14119
|
},
|
|
14008
14120
|
empty: emptyTile,
|
|
14121
|
+
isReady: (value) => value === emptyTile || value.gl !== void 0,
|
|
14009
14122
|
release(value) {
|
|
14010
14123
|
if (gl) release(gl, value);
|
|
14011
14124
|
},
|
|
@@ -14066,7 +14179,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14066
14179
|
models.upload(context);
|
|
14067
14180
|
if (modelKey !== models.key()) map.triggerRepaint();
|
|
14068
14181
|
let budget = 2;
|
|
14069
|
-
for (const { value: entry } of camera.
|
|
14182
|
+
for (const { value: entry } of camera.built()) {
|
|
14070
14183
|
if (entry.gl || !entry.data) continue;
|
|
14071
14184
|
if (budget-- <= 0) {
|
|
14072
14185
|
map.triggerRepaint();
|
|
@@ -14309,7 +14422,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14309
14422
|
for (const { x: x3, y: y2, value } of shown > 0 ? drawn() : []) {
|
|
14310
14423
|
const offset = frame.offsetOf({ x: x3, y: y2 }, camera.zoom);
|
|
14311
14424
|
const ring = ringIn(x3, y2);
|
|
14312
|
-
if (!
|
|
14425
|
+
if (!insideRing2(ring, 0, 0, tileflowBuildingExtent, tileflowBuildingExtent)) continue;
|
|
14313
14426
|
if (!buildingBoxVisible(frame.light.matrix, [
|
|
14314
14427
|
(offset[0] - 1) * frame.metres,
|
|
14315
14428
|
-(offset[1] + tileflowBuildingExtent + 1) * frame.metres,
|
|
@@ -14321,7 +14434,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14321
14434
|
continue;
|
|
14322
14435
|
const ranges = buildingDrawRanges(
|
|
14323
14436
|
value.mesh,
|
|
14324
|
-
({ bounds: [left, top, right, bottom, height] }) =>
|
|
14437
|
+
({ bounds: [left, top, right, bottom, height] }) => insideRing2(ring, left, top, right, bottom) && buildingBoxVisible(frame.light.matrix, [
|
|
14325
14438
|
(left + offset[0]) * frame.metres,
|
|
14326
14439
|
-(bottom + offset[1]) * frame.metres,
|
|
14327
14440
|
0,
|
|
@@ -14402,7 +14515,10 @@ function createTileflowBuildings3D(options) {
|
|
|
14402
14515
|
return [ax - reach, ay - reach, Math.min(0, low), ax + reach, ay + reach, high + 0.1];
|
|
14403
14516
|
}
|
|
14404
14517
|
function modelView(model) {
|
|
14405
|
-
return {
|
|
14518
|
+
return {
|
|
14519
|
+
camera: modelCamera(model),
|
|
14520
|
+
verticalFieldOfView: map.getVerticalFieldOfView?.()
|
|
14521
|
+
};
|
|
14406
14522
|
}
|
|
14407
14523
|
function levelOf(model) {
|
|
14408
14524
|
return models.levelOf(model, modelView(model));
|
|
@@ -14524,12 +14640,14 @@ function createTileflowBuildings3D(options) {
|
|
|
14524
14640
|
const gradients = new Float32Array(28);
|
|
14525
14641
|
const powers = new Float32Array(7);
|
|
14526
14642
|
const materialColours = new Float32Array(28);
|
|
14643
|
+
const colorScales = new Float32Array(7);
|
|
14527
14644
|
const materials = new Float32Array(28);
|
|
14528
14645
|
const appearance = new Float32Array(21);
|
|
14529
14646
|
for (const [role, id] of Object.entries(tileflowModelLightingRoles)) {
|
|
14530
14647
|
const from = themes[lower].modelLighting?.[role], to = themes[upper].modelLighting?.[role];
|
|
14531
14648
|
const sampledFrom = sampleModelRole(from, `${identity}:${role}`);
|
|
14532
14649
|
const sampledTo = sampleModelRole(to, `${identity}:${role}`);
|
|
14650
|
+
colorScales[id] = (from?.colorScale ?? 1) * (1 - mix2) + (to?.colorScale ?? 1) * mix2;
|
|
14533
14651
|
appearance[id * 3] = (from?.shading === "map" ? 1 - mix2 : 0) + (to?.shading === "map" ? mix2 : 0);
|
|
14534
14652
|
appearance[id * 3 + 1] = (from?.ambientOcclusion ?? 1) * (1 - mix2) + (to?.ambientOcclusion ?? 1) * mix2;
|
|
14535
14653
|
appearance[id * 3 + 2] = (from?.partColorMix ?? 1) * (1 - mix2) + (to?.partColorMix ?? 1) * mix2;
|
|
@@ -14552,7 +14670,16 @@ function createTileflowBuildings3D(options) {
|
|
|
14552
14670
|
gradients[id * 4 + component] = first[component] * (1 - mix2) + second[component] * mix2;
|
|
14553
14671
|
powers[id] = first[4] * (1 - mix2) + second[4] * mix2;
|
|
14554
14672
|
}
|
|
14555
|
-
const result = {
|
|
14673
|
+
const result = {
|
|
14674
|
+
strengths,
|
|
14675
|
+
colours,
|
|
14676
|
+
gradients,
|
|
14677
|
+
powers,
|
|
14678
|
+
materialColours,
|
|
14679
|
+
colorScales,
|
|
14680
|
+
materials,
|
|
14681
|
+
appearance
|
|
14682
|
+
};
|
|
14556
14683
|
if (modelLightingCache.size >= 1024)
|
|
14557
14684
|
modelLightingCache.delete(modelLightingCache.keys().next().value);
|
|
14558
14685
|
modelLightingCache.set(identity, result);
|
|
@@ -14621,7 +14748,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14621
14748
|
const bearing = map.getBearing() * Math.PI / 180;
|
|
14622
14749
|
return [Math.sin(bearing), -Math.cos(bearing)];
|
|
14623
14750
|
}
|
|
14624
|
-
function
|
|
14751
|
+
function insideRing2(ring, left, top, right, bottom) {
|
|
14625
14752
|
const radius = ring[3];
|
|
14626
14753
|
if (!(radius > 0)) return true;
|
|
14627
14754
|
const cx = ring[0];
|
|
@@ -14640,7 +14767,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14640
14767
|
const reach = margin / camera.metres + 1;
|
|
14641
14768
|
const ring = ringIn(tile.x, tile.y);
|
|
14642
14769
|
const hazed = mercator && hazeDepth < Infinity;
|
|
14643
|
-
const shows = (box) => (!mercator || buildingBoxVisible(data.mainMatrix, box)) &&
|
|
14770
|
+
const shows = (box) => (!mercator || buildingBoxVisible(data.mainMatrix, box)) && insideRing2(ring, box[0], box[1], box[3], box[4]) && (!hazed || buildingBoxDepth(data.mainMatrix, box) < hazeDepth);
|
|
14644
14771
|
const extent5 = tileflowBuildingExtent + reach;
|
|
14645
14772
|
if (!shows([-reach, -reach, 0, extent5, extent5, tile.value.mesh.top + 0.1])) return [];
|
|
14646
14773
|
return buildingDrawRanges(
|
|
@@ -14687,20 +14814,21 @@ function createTileflowBuildings3D(options) {
|
|
|
14687
14814
|
masks = {};
|
|
14688
14815
|
const shown = visibleScale();
|
|
14689
14816
|
const entries = variant === args.shaderData.variantName && shown > 0 && ground ? drawn() : [];
|
|
14690
|
-
|
|
14817
|
+
const contactRadius = mixed2((entry) => entry.groundOcclusionRadius ?? tileflowBuildingOcclusion.ground);
|
|
14818
|
+
if (design().occlusion && contactRadius > 0 && entries.length > 0) {
|
|
14691
14819
|
const program = programs.contact;
|
|
14692
14820
|
masks.contact = contactMask.render(context, () => {
|
|
14693
14821
|
context.useProgram(program.program);
|
|
14694
14822
|
context.uniform1f(program.uniforms.u_scale, shown);
|
|
14695
14823
|
context.uniform1f(program.uniforms.u_metres, camera.metres);
|
|
14696
|
-
context.uniform1f(program.uniforms.u_band,
|
|
14824
|
+
context.uniform1f(program.uniforms.u_band, contactRadius);
|
|
14697
14825
|
context.uniform1f(
|
|
14698
14826
|
program.uniforms.u_band_strength,
|
|
14699
14827
|
mixed2((entry) => entry.groundOcclusion ?? tileflowBuildingOcclusion.groundStrength) * visibleOpacity()
|
|
14700
14828
|
);
|
|
14701
14829
|
for (const tile of entries) {
|
|
14702
14830
|
const { x: x3, y: y2, value } = tile;
|
|
14703
|
-
const ranges = viewRanges(args, tile,
|
|
14831
|
+
const ranges = viewRanges(args, tile, contactRadius, true);
|
|
14704
14832
|
if (!ranges.length) continue;
|
|
14705
14833
|
const { contact } = value.gl;
|
|
14706
14834
|
project(context, program, args, x3, y2);
|
|
@@ -14908,6 +15036,12 @@ function createTileflowBuildings3D(options) {
|
|
|
14908
15036
|
context.uniform3fv(m.u_sun_light, light.sunLight);
|
|
14909
15037
|
context.uniform3fv(m.u_sky_light, light.skyLight);
|
|
14910
15038
|
context.uniform1f(m.u_night, light.night);
|
|
15039
|
+
context.uniform3f(
|
|
15040
|
+
m.u_facade_shading,
|
|
15041
|
+
mixed2((entry) => entry.verticalGradient ? 1 : 0),
|
|
15042
|
+
occlusionOn ? mixed2((entry) => entry.groundOcclusion ?? 0.16) : 0,
|
|
15043
|
+
mixed2((entry) => entry.groundOcclusionRadius ?? 3)
|
|
15044
|
+
);
|
|
14911
15045
|
context.uniform1f(
|
|
14912
15046
|
m.u_ambient_occlusion,
|
|
14913
15047
|
occlusionOn ? mixed2((entry) => entry.modelOcclusion ?? 0.75) : 0
|
|
@@ -14924,6 +15058,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14924
15058
|
context.uniform4fv(m.u_role_emission_gradient, emission.gradients);
|
|
14925
15059
|
context.uniform1fv(m.u_role_emission_power, emission.powers);
|
|
14926
15060
|
context.uniform4fv(m.u_role_colour, emission.materialColours);
|
|
15061
|
+
context.uniform1fv(m.u_role_color_scale, emission.colorScales);
|
|
14927
15062
|
context.uniform4fv(m.u_role_material, emission.materials);
|
|
14928
15063
|
context.uniform3fv(m.u_role_appearance, emission.appearance);
|
|
14929
15064
|
const at = placed2(stand.tileX, stand.tileY);
|
|
@@ -16476,6 +16611,7 @@ uniform float u_metres; // metres per tile unit
|
|
|
16476
16611
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
16477
16612
|
uniform float u_minimum_height; // optional visual height floor, in metres
|
|
16478
16613
|
uniform vec2 u_size_scale; // the map's height and crown scales, for this form
|
|
16614
|
+
uniform vec3 u_size_compression; // reference height, reference crown, strength
|
|
16479
16615
|
uniform float u_round; // how far normals turn from the facets to the round shape, by finish
|
|
16480
16616
|
|
|
16481
16617
|
float growthOf() {
|
|
@@ -16492,7 +16628,14 @@ vec2 turned(vec2 v) {
|
|
|
16492
16628
|
|
|
16493
16629
|
vec2 displaySize() {
|
|
16494
16630
|
vec2 size = a_tree_size * 0.1 * u_size_scale;
|
|
16495
|
-
|
|
16631
|
+
size *= max(1.0, u_minimum_height / max(size.x, 0.001));
|
|
16632
|
+
// Scale the complete tree together to preserve crown, trunk and branch proportions.
|
|
16633
|
+
if (u_size_compression.z > 0.0) {
|
|
16634
|
+
vec2 relative = max(u_size_compression.xy, vec2(0.001)) / max(size, vec2(0.001));
|
|
16635
|
+
// Balance height and footprint, so a short but broad crown is not enlarged.
|
|
16636
|
+
size *= min(1.35, pow(relative.x * relative.y, u_size_compression.z * 0.5));
|
|
16637
|
+
}
|
|
16638
|
+
return size;
|
|
16496
16639
|
}
|
|
16497
16640
|
|
|
16498
16641
|
vec3 standing(float growth) {
|
|
@@ -16773,7 +16916,7 @@ function createTileflowTrees3D(options) {
|
|
|
16773
16916
|
let disposed = false;
|
|
16774
16917
|
let drawnLast = 0;
|
|
16775
16918
|
let generation = 0;
|
|
16776
|
-
let
|
|
16919
|
+
let registered2 = false;
|
|
16777
16920
|
let unregister = () => {
|
|
16778
16921
|
};
|
|
16779
16922
|
const scene = tileflowScene3D(map);
|
|
@@ -17038,7 +17181,9 @@ function createTileflowTrees3D(options) {
|
|
|
17038
17181
|
forms: tileflowTreeForms.map((form) => [
|
|
17039
17182
|
theme?.forms[form]?.heightScale ?? 1,
|
|
17040
17183
|
theme?.forms[form]?.crownScale ?? 1,
|
|
17041
|
-
|
|
17184
|
+
theme?.forms[form]?.sizeAnchor ?? 8.5,
|
|
17185
|
+
theme?.forms[form]?.crownAnchor ?? 5,
|
|
17186
|
+
theme?.forms[form]?.sizeCompression ?? 0
|
|
17042
17187
|
]),
|
|
17043
17188
|
edges: [[theme?.edges ?? 0, 0, 0]],
|
|
17044
17189
|
edgeColor: [[...rgb(theme?.edgeColor ?? "#000000") ?? [0, 0, 0]]],
|
|
@@ -17063,6 +17208,12 @@ function createTileflowTrees3D(options) {
|
|
|
17063
17208
|
[size[0] * forms[index][0], size[1] * forms[index][1]]
|
|
17064
17209
|
])
|
|
17065
17210
|
),
|
|
17211
|
+
compressions: Object.fromEntries(
|
|
17212
|
+
tileflowTreeForms.map((form, index) => [
|
|
17213
|
+
form,
|
|
17214
|
+
[forms[index][2], forms[index][3], forms[index][4]]
|
|
17215
|
+
])
|
|
17216
|
+
),
|
|
17066
17217
|
finish: (t < 0.5 ? a : b2)?.finish ?? "faceted",
|
|
17067
17218
|
edges: mixList(x3.edges, y2.edges)[0][0],
|
|
17068
17219
|
edgeColor: mixList(x3.edgeColor, y2.edgeColor)[0],
|
|
@@ -17099,17 +17250,21 @@ function createTileflowTrees3D(options) {
|
|
|
17099
17250
|
tallest = Math.max(tallest, value.placement.tallest);
|
|
17100
17251
|
}
|
|
17101
17252
|
if (!Number.isFinite(left)) return void 0;
|
|
17102
|
-
const
|
|
17253
|
+
const palette2 = colours();
|
|
17254
|
+
const maximumGrowth = Object.values(palette2.compressions).some(
|
|
17255
|
+
([, , strength]) => strength > 0
|
|
17256
|
+
) ? 1.35 : 1;
|
|
17257
|
+
const maximumScale = maximumGrowth > 1 ? Math.max(...Object.values(palette2.sizes).map((size) => size[0])) : palette2.size[0];
|
|
17103
17258
|
return {
|
|
17104
17259
|
zoom: preferredZoom3,
|
|
17105
17260
|
tiles: [left, top, right, bottom],
|
|
17106
|
-
tallest: Math.max(tallest *
|
|
17261
|
+
tallest: Math.max(tallest * maximumScale, palette2.minimumHeight) * maximumGrowth * shown
|
|
17107
17262
|
};
|
|
17108
17263
|
},
|
|
17109
17264
|
// Camera-dependent density, detail and fading also change the trees casting shadows.
|
|
17110
17265
|
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(
|
|
17111
17266
|
colours().sizes
|
|
17112
|
-
).flat().map((value) => value.toFixed(3)).join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
|
|
17267
|
+
).flat().map((value) => value.toFixed(3)).join()}:${Object.values(colours().compressions).flat().join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
|
|
17113
17268
|
drawDepth(context, frame) {
|
|
17114
17269
|
const program = programs.depth;
|
|
17115
17270
|
if (!program || !meshes) return;
|
|
@@ -17119,6 +17274,7 @@ function createTileflowTrees3D(options) {
|
|
|
17119
17274
|
context.uniform1f(u.u_metres, frame.metres);
|
|
17120
17275
|
context.uniformMatrix4fv(u.u_light_matrix, false, frame.light.matrix);
|
|
17121
17276
|
const sizes = colours().sizes;
|
|
17277
|
+
const compressions = colours().compressions;
|
|
17122
17278
|
const minimumHeight = colours().minimumHeight;
|
|
17123
17279
|
const camera = view();
|
|
17124
17280
|
context.uniform1f(u.u_fade, 1);
|
|
@@ -17139,12 +17295,14 @@ function createTileflowTrees3D(options) {
|
|
|
17139
17295
|
const drawing = value.gl.vaos.get(`${form}:${model}:${selection.level}`);
|
|
17140
17296
|
if (instances === 0 || !drawing) return;
|
|
17141
17297
|
context.uniform2f(u.u_size_scale, sizes[form][0], sizes[form][1] * drawing.crown);
|
|
17298
|
+
context.uniform3f(u.u_size_compression, ...compressions[form]);
|
|
17142
17299
|
context.bindVertexArray(drawing.vao);
|
|
17143
17300
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
17144
17301
|
});
|
|
17145
17302
|
const hedge = value.gl.hedge;
|
|
17146
17303
|
if (hedge) {
|
|
17147
17304
|
context.uniform1f(u.u_minimum_height, 0);
|
|
17305
|
+
context.uniform3f(u.u_size_compression, 1, 1, 0);
|
|
17148
17306
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
17149
17307
|
context.bindVertexArray(hedge.vao);
|
|
17150
17308
|
context.drawArraysInstanced(
|
|
@@ -17230,6 +17388,7 @@ function createTileflowTrees3D(options) {
|
|
|
17230
17388
|
];
|
|
17231
17389
|
context.uniform1f(u.u_minimum_height, palette2.minimumHeight);
|
|
17232
17390
|
context.uniform2f(u.u_size_scale, ...size);
|
|
17391
|
+
context.uniform3f(u.u_size_compression, ...palette2.compressions[form]);
|
|
17233
17392
|
context.bindVertexArray(drawing.vao);
|
|
17234
17393
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
17235
17394
|
count += instances;
|
|
@@ -17240,6 +17399,7 @@ function createTileflowTrees3D(options) {
|
|
|
17240
17399
|
leaves,
|
|
17241
17400
|
size,
|
|
17242
17401
|
minimumHeight: palette2.minimumHeight,
|
|
17402
|
+
compression: palette2.compressions[form],
|
|
17243
17403
|
instances,
|
|
17244
17404
|
drawing
|
|
17245
17405
|
});
|
|
@@ -17250,6 +17410,7 @@ function createTileflowTrees3D(options) {
|
|
|
17250
17410
|
const instances = value.placement.hedges.length / tileflowTreeBytes;
|
|
17251
17411
|
context.uniform3fv(u.u_leaves, palette2.hedge.flat());
|
|
17252
17412
|
context.uniform1f(u.u_minimum_height, 0);
|
|
17413
|
+
context.uniform3f(u.u_size_compression, 1, 1, 0);
|
|
17253
17414
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
17254
17415
|
context.bindVertexArray(hedge.vao);
|
|
17255
17416
|
context.drawArraysInstanced(context.TRIANGLES, 0, hedge.count, instances);
|
|
@@ -17260,6 +17421,7 @@ function createTileflowTrees3D(options) {
|
|
|
17260
17421
|
leaves: palette2.hedge,
|
|
17261
17422
|
size: [1, 1],
|
|
17262
17423
|
minimumHeight: 0,
|
|
17424
|
+
compression: [1, 1, 0],
|
|
17263
17425
|
instances,
|
|
17264
17426
|
drawing: hedge
|
|
17265
17427
|
});
|
|
@@ -17302,6 +17464,7 @@ function createTileflowTrees3D(options) {
|
|
|
17302
17464
|
);
|
|
17303
17465
|
context.uniform1f(e.u_minimum_height, draw2.minimumHeight);
|
|
17304
17466
|
context.uniform2f(e.u_size_scale, ...draw2.size);
|
|
17467
|
+
context.uniform3f(e.u_size_compression, ...draw2.compression);
|
|
17305
17468
|
context.bindVertexArray(draw2.drawing.vao);
|
|
17306
17469
|
context.drawArraysInstanced(context.TRIANGLES, 0, draw2.drawing.count, draw2.instances);
|
|
17307
17470
|
}
|
|
@@ -17490,7 +17653,7 @@ ${shaderData.define}`;
|
|
|
17490
17653
|
context.deleteBuffer(ground.vbo);
|
|
17491
17654
|
}
|
|
17492
17655
|
unregister();
|
|
17493
|
-
|
|
17656
|
+
registered2 = false;
|
|
17494
17657
|
scene.release(context);
|
|
17495
17658
|
programs = {};
|
|
17496
17659
|
meshes = void 0;
|
|
@@ -17503,8 +17666,8 @@ ${shaderData.define}`;
|
|
|
17503
17666
|
if (!isWebGL23(context)) return;
|
|
17504
17667
|
ensureTiles();
|
|
17505
17668
|
if (!programs.depth) return;
|
|
17506
|
-
if (!
|
|
17507
|
-
|
|
17669
|
+
if (!registered2) unregister = scene.register(caster);
|
|
17670
|
+
registered2 = true;
|
|
17508
17671
|
const metres = tiles[0]?.metres ?? 1;
|
|
17509
17672
|
scene.prepare(context, tileflowSceneLight(sunNow()), metres);
|
|
17510
17673
|
},
|
|
@@ -19636,6 +19799,320 @@ function createChannel() {
|
|
|
19636
19799
|
return `bridge_${Date.now().toString(36)}_${channelSequence.toString(36)}`;
|
|
19637
19800
|
}
|
|
19638
19801
|
|
|
19802
|
+
// src/path-ground-geometry.ts
|
|
19803
|
+
var coverClasses = /* @__PURE__ */ new Set(["grass", "wood", "forest", "wetland"]);
|
|
19804
|
+
var useClasses = /* @__PURE__ */ new Set(["cemetery", "pitch", "track", "playground", "zoo"]);
|
|
19805
|
+
var pathClasses = /* @__PURE__ */ new Set([
|
|
19806
|
+
"footway",
|
|
19807
|
+
"path",
|
|
19808
|
+
"bridleway",
|
|
19809
|
+
"corridor",
|
|
19810
|
+
"pedestrian",
|
|
19811
|
+
"steps",
|
|
19812
|
+
"cycleway"
|
|
19813
|
+
]);
|
|
19814
|
+
function deriveTileflowGreenPaths(bytes, bindings) {
|
|
19815
|
+
const tile = decodeTileflowVectorTile(bytes, {
|
|
19816
|
+
layers: [bindings.road, bindings.landcover, bindings.landuse]
|
|
19817
|
+
});
|
|
19818
|
+
const road = tile[bindings.road];
|
|
19819
|
+
if (!road) return encodeLines(bindings.road, 4096, []);
|
|
19820
|
+
const polygons = [];
|
|
19821
|
+
for (const name of [bindings.landcover, bindings.landuse]) {
|
|
19822
|
+
const layer = tile[name];
|
|
19823
|
+
if (!layer) continue;
|
|
19824
|
+
for (const feature of layer.features) {
|
|
19825
|
+
const kind = String(feature.properties[bindings.class]);
|
|
19826
|
+
const subclass = String(feature.properties[bindings.subclass]);
|
|
19827
|
+
const green = name === bindings.landcover ? coverClasses.has(kind) || kind === "farmland" && ["orchard", "plant_nursery"].includes(subclass) : useClasses.has(kind);
|
|
19828
|
+
if (feature.type !== "Polygon" || !green) continue;
|
|
19829
|
+
let current;
|
|
19830
|
+
for (const raw of feature.geometry) {
|
|
19831
|
+
const ring = raw.map((n) => n * road.extent / layer.extent);
|
|
19832
|
+
if (signedArea2(ring) > 0 || !current) {
|
|
19833
|
+
current = [ring];
|
|
19834
|
+
polygons.push({ rings: current, bounds: boundsOf2(ring) });
|
|
19835
|
+
} else current.push(ring);
|
|
19836
|
+
}
|
|
19837
|
+
}
|
|
19838
|
+
}
|
|
19839
|
+
const features = [];
|
|
19840
|
+
for (const feature of road.features) {
|
|
19841
|
+
const p = feature.properties;
|
|
19842
|
+
if (feature.type !== "LineString" || !["path", "path_construction"].includes(String(p[bindings.class])) || !pathClasses.has(String(p[bindings.subclass])) || ["bridge", "tunnel"].includes(String(p[bindings.brunnel])))
|
|
19843
|
+
continue;
|
|
19844
|
+
const geometry2 = feature.geometry.flatMap((line) => clipLineToGreen(line, polygons));
|
|
19845
|
+
if (geometry2.length) features.push({ ...feature, geometry: geometry2 });
|
|
19846
|
+
}
|
|
19847
|
+
return encodeLines(bindings.road, road.extent, features);
|
|
19848
|
+
}
|
|
19849
|
+
function signedArea2(ring) {
|
|
19850
|
+
let area3 = 0;
|
|
19851
|
+
for (let i2 = 0, j2 = ring.length - 2; i2 < ring.length; j2 = i2, i2 += 2)
|
|
19852
|
+
area3 += ring[j2] * ring[i2 + 1] - ring[i2] * ring[j2 + 1];
|
|
19853
|
+
return area3 / 2;
|
|
19854
|
+
}
|
|
19855
|
+
function boundsOf2(line) {
|
|
19856
|
+
const box = [Infinity, Infinity, -Infinity, -Infinity];
|
|
19857
|
+
for (let i2 = 0; i2 < line.length; i2 += 2) {
|
|
19858
|
+
box[0] = Math.min(box[0], line[i2]);
|
|
19859
|
+
box[1] = Math.min(box[1], line[i2 + 1]);
|
|
19860
|
+
box[2] = Math.max(box[2], line[i2]);
|
|
19861
|
+
box[3] = Math.max(box[3], line[i2 + 1]);
|
|
19862
|
+
}
|
|
19863
|
+
return box;
|
|
19864
|
+
}
|
|
19865
|
+
function overlaps(a, b2) {
|
|
19866
|
+
return a[0] <= b2[2] && a[2] >= b2[0] && a[1] <= b2[3] && a[3] >= b2[1];
|
|
19867
|
+
}
|
|
19868
|
+
function insideRing(point, ring) {
|
|
19869
|
+
const [x3, y2] = point;
|
|
19870
|
+
let inside2 = false;
|
|
19871
|
+
for (let i2 = 0, j2 = ring.length - 2; i2 < ring.length; j2 = i2, i2 += 2) {
|
|
19872
|
+
const ax = ring[j2], ay = ring[j2 + 1], bx = ring[i2], by = ring[i2 + 1];
|
|
19873
|
+
const cross = (x3 - ax) * (by - ay) - (y2 - ay) * (bx - ax);
|
|
19874
|
+
if (Math.abs(cross) < 1e-7 && x3 >= Math.min(ax, bx) && x3 <= Math.max(ax, bx) && y2 >= Math.min(ay, by) && y2 <= Math.max(ay, by))
|
|
19875
|
+
return true;
|
|
19876
|
+
if (ay > y2 !== by > y2 && x3 < (bx - ax) * (y2 - ay) / (by - ay) + ax) inside2 = !inside2;
|
|
19877
|
+
}
|
|
19878
|
+
return inside2;
|
|
19879
|
+
}
|
|
19880
|
+
function clipLineToGreen(line, all) {
|
|
19881
|
+
const polygons = all.filter((polygon) => overlaps(boundsOf2(line), polygon.bounds));
|
|
19882
|
+
if (!polygons.length) return [];
|
|
19883
|
+
const output = [];
|
|
19884
|
+
let active;
|
|
19885
|
+
for (let i2 = 2; i2 < line.length; i2 += 2) {
|
|
19886
|
+
const ax = line[i2 - 2], ay = line[i2 - 1], dx = line[i2] - ax, dy = line[i2 + 1] - ay;
|
|
19887
|
+
if (dx === 0 && dy === 0) continue;
|
|
19888
|
+
const cuts = [0, 1];
|
|
19889
|
+
for (const polygon of polygons)
|
|
19890
|
+
for (const ring of polygon.rings)
|
|
19891
|
+
for (let k = 0, j2 = ring.length - 2; k < ring.length; j2 = k, k += 2) {
|
|
19892
|
+
const bx = ring[j2], by = ring[j2 + 1], ex = ring[k] - bx, ey = ring[k + 1] - by;
|
|
19893
|
+
const denominator = dx * ey - dy * ex;
|
|
19894
|
+
if (Math.abs(denominator) < 1e-10) continue;
|
|
19895
|
+
const t = ((bx - ax) * ey - (by - ay) * ex) / denominator;
|
|
19896
|
+
const u = ((bx - ax) * dy - (by - ay) * dx) / denominator;
|
|
19897
|
+
if (t > 0 && t < 1 && u >= 0 && u <= 1) cuts.push(t);
|
|
19898
|
+
}
|
|
19899
|
+
cuts.sort((a, b2) => a - b2);
|
|
19900
|
+
for (let k = 1; k < cuts.length; k++) {
|
|
19901
|
+
const lo = cuts[k - 1], hi = cuts[k];
|
|
19902
|
+
if (hi - lo < 1e-9) continue;
|
|
19903
|
+
const mid = (lo + hi) / 2;
|
|
19904
|
+
const point = [ax + dx * mid, ay + dy * mid];
|
|
19905
|
+
const inside2 = polygons.some(
|
|
19906
|
+
(p) => insideRing(point, p.rings[0]) && !p.rings.slice(1).some((hole) => insideRing(point, hole))
|
|
19907
|
+
);
|
|
19908
|
+
if (!inside2) {
|
|
19909
|
+
active = void 0;
|
|
19910
|
+
continue;
|
|
19911
|
+
}
|
|
19912
|
+
const start = [Math.round(ax + dx * lo), Math.round(ay + dy * lo)];
|
|
19913
|
+
const end = [Math.round(ax + dx * hi), Math.round(ay + dy * hi)];
|
|
19914
|
+
if (start[0] === end[0] && start[1] === end[1]) continue;
|
|
19915
|
+
if (!active || active.at(-2) !== start[0] || active.at(-1) !== start[1]) {
|
|
19916
|
+
active = [...start];
|
|
19917
|
+
output.push(active);
|
|
19918
|
+
}
|
|
19919
|
+
active.push(...end);
|
|
19920
|
+
}
|
|
19921
|
+
}
|
|
19922
|
+
return output;
|
|
19923
|
+
}
|
|
19924
|
+
var Writer = class {
|
|
19925
|
+
bytes = [];
|
|
19926
|
+
uint(n) {
|
|
19927
|
+
while (n > 127) {
|
|
19928
|
+
this.bytes.push(n % 128 | 128);
|
|
19929
|
+
n = Math.floor(n / 128);
|
|
19930
|
+
}
|
|
19931
|
+
this.bytes.push(n);
|
|
19932
|
+
}
|
|
19933
|
+
field(tag, value) {
|
|
19934
|
+
this.uint(tag * 8);
|
|
19935
|
+
this.uint(value);
|
|
19936
|
+
}
|
|
19937
|
+
message(tag, value) {
|
|
19938
|
+
this.uint(tag * 8 + 2);
|
|
19939
|
+
this.uint(value.length);
|
|
19940
|
+
for (const n of value) this.bytes.push(n);
|
|
19941
|
+
}
|
|
19942
|
+
text(tag, value) {
|
|
19943
|
+
this.message(tag, new TextEncoder().encode(value));
|
|
19944
|
+
}
|
|
19945
|
+
};
|
|
19946
|
+
function zigzag2(n) {
|
|
19947
|
+
return n < 0 ? -n * 2 - 1 : n * 2;
|
|
19948
|
+
}
|
|
19949
|
+
function encodeLines(name, extent5, features) {
|
|
19950
|
+
const layer = new Writer();
|
|
19951
|
+
layer.text(1, name);
|
|
19952
|
+
const keys = [];
|
|
19953
|
+
const values = [];
|
|
19954
|
+
const keyMap = /* @__PURE__ */ new Map(), valueMap = /* @__PURE__ */ new Map();
|
|
19955
|
+
for (const feature of features) {
|
|
19956
|
+
const message = new Writer(), tags = new Writer(), geometry2 = new Writer();
|
|
19957
|
+
if (feature.id !== void 0) message.field(1, feature.id);
|
|
19958
|
+
for (const [key, value] of Object.entries(feature.properties)) {
|
|
19959
|
+
if (!keyMap.has(key)) {
|
|
19960
|
+
keyMap.set(key, keys.length);
|
|
19961
|
+
keys.push(key);
|
|
19962
|
+
}
|
|
19963
|
+
const identity = typeof value + ":" + value;
|
|
19964
|
+
if (!valueMap.has(identity)) {
|
|
19965
|
+
valueMap.set(identity, values.length);
|
|
19966
|
+
values.push(value);
|
|
19967
|
+
}
|
|
19968
|
+
tags.uint(keyMap.get(key));
|
|
19969
|
+
tags.uint(valueMap.get(identity));
|
|
19970
|
+
}
|
|
19971
|
+
message.message(2, tags.bytes);
|
|
19972
|
+
message.field(3, feature.type === "Polygon" ? 3 : 2);
|
|
19973
|
+
let x3 = 0, y2 = 0;
|
|
19974
|
+
for (const raw of feature.geometry) {
|
|
19975
|
+
const points = feature.type === "Polygon" && raw[0] === raw.at(-2) && raw[1] === raw.at(-1) ? raw.slice(0, -2) : raw;
|
|
19976
|
+
if (points.length < 4) continue;
|
|
19977
|
+
geometry2.uint(9);
|
|
19978
|
+
geometry2.uint(zigzag2(Math.round(points[0]) - x3));
|
|
19979
|
+
geometry2.uint(zigzag2(Math.round(points[1]) - y2));
|
|
19980
|
+
x3 = Math.round(points[0]);
|
|
19981
|
+
y2 = Math.round(points[1]);
|
|
19982
|
+
geometry2.uint((points.length / 2 - 1) * 8 + 2);
|
|
19983
|
+
for (let i2 = 2; i2 < points.length; i2 += 2) {
|
|
19984
|
+
const nx = Math.round(points[i2]), ny = Math.round(points[i2 + 1]);
|
|
19985
|
+
geometry2.uint(zigzag2(nx - x3));
|
|
19986
|
+
geometry2.uint(zigzag2(ny - y2));
|
|
19987
|
+
x3 = nx;
|
|
19988
|
+
y2 = ny;
|
|
19989
|
+
}
|
|
19990
|
+
if (feature.type === "Polygon") geometry2.uint(15);
|
|
19991
|
+
}
|
|
19992
|
+
message.message(4, geometry2.bytes);
|
|
19993
|
+
layer.message(2, message.bytes);
|
|
19994
|
+
}
|
|
19995
|
+
for (const key of keys) layer.text(3, key);
|
|
19996
|
+
for (const value of values) {
|
|
19997
|
+
const message = new Writer();
|
|
19998
|
+
if (typeof value === "string") message.text(1, value);
|
|
19999
|
+
else if (typeof value === "boolean") message.field(7, value ? 1 : 0);
|
|
20000
|
+
else if (Number.isSafeInteger(value)) {
|
|
20001
|
+
message.field(value < 0 ? 6 : 4, value < 0 ? zigzag2(value) : value);
|
|
20002
|
+
} else {
|
|
20003
|
+
message.uint(25);
|
|
20004
|
+
const b2 = new Uint8Array(8);
|
|
20005
|
+
new DataView(b2.buffer).setFloat64(0, value, true);
|
|
20006
|
+
message.bytes.push(...b2);
|
|
20007
|
+
}
|
|
20008
|
+
layer.message(4, message.bytes);
|
|
20009
|
+
}
|
|
20010
|
+
layer.field(5, extent5);
|
|
20011
|
+
layer.field(15, 2);
|
|
20012
|
+
const tile = new Writer();
|
|
20013
|
+
tile.message(3, layer.bytes);
|
|
20014
|
+
return new Uint8Array(tile.bytes);
|
|
20015
|
+
}
|
|
20016
|
+
|
|
20017
|
+
// src/path-ground-protocol.ts
|
|
20018
|
+
var tileflowPathGroundProtocol = "tileflow-path-ground";
|
|
20019
|
+
function pathGroundProtocolUrl(source, tile = false) {
|
|
20020
|
+
return `${tileflowPathGroundProtocol}://source/${tile ? "{z}/{x}/{y}.pbf" : "index.json"}?source=${encodeURIComponent(JSON.stringify(source))}`;
|
|
20021
|
+
}
|
|
20022
|
+
function parsePathGroundRequest(value) {
|
|
20023
|
+
if (value.length > 16e3) throw new Error("Path context URL is too long");
|
|
20024
|
+
const url = new URL(value);
|
|
20025
|
+
if (url.protocol !== `${tileflowPathGroundProtocol}:` || url.hostname !== "source" || url.username || url.password || url.hash)
|
|
20026
|
+
throw new Error("Invalid path context URL");
|
|
20027
|
+
const source = JSON.parse(url.searchParams.get("source") ?? "null");
|
|
20028
|
+
if (!source || !["road", "landcover", "landuse", "class", "subclass", "brunnel"].every(
|
|
20029
|
+
(k) => typeof source[k] === "string"
|
|
20030
|
+
))
|
|
20031
|
+
throw new Error("Invalid path context bindings");
|
|
20032
|
+
if (!source.url && !source.tiles?.length) throw new Error("Missing path context source");
|
|
20033
|
+
for (const endpoint of [source.url, ...source.tiles ?? []].filter((s) => !!s)) {
|
|
20034
|
+
const u = new URL(
|
|
20035
|
+
endpoint.replaceAll("{z}", "0").replaceAll("{x}", "0").replaceAll("{y}", "0")
|
|
20036
|
+
);
|
|
20037
|
+
if (!["https:", "http:"].includes(u.protocol) || u.username || u.password)
|
|
20038
|
+
throw new Error("Path context requires an HTTP(S) vector source");
|
|
20039
|
+
}
|
|
20040
|
+
if (url.pathname === "/index.json") return { source };
|
|
20041
|
+
const match = /^\/(\d{1,2})\/(\d+)\/(\d+)\.pbf$/.exec(url.pathname);
|
|
20042
|
+
if (!match) throw new Error("Invalid path context tile");
|
|
20043
|
+
const [z2, x3, y2] = match.slice(1).map(Number);
|
|
20044
|
+
if (z2 < 0 || z2 > 24 || x3 < 0 || y2 < 0 || x3 >= 2 ** z2 || y2 >= 2 ** z2)
|
|
20045
|
+
throw new Error("Invalid path context coordinates");
|
|
20046
|
+
return { source, tile: { z: z2, x: x3, y: y2 } };
|
|
20047
|
+
}
|
|
20048
|
+
|
|
20049
|
+
// src/path-ground-browser.ts
|
|
20050
|
+
var registered = /* @__PURE__ */ new WeakSet();
|
|
20051
|
+
function registerTileflowPathGroundProtocol(registry, options = {}) {
|
|
20052
|
+
if (registered.has(registry.addProtocol)) return;
|
|
20053
|
+
const request = options.fetch ?? globalThis.fetch;
|
|
20054
|
+
const transform = options.transformUrl ?? ((url) => url);
|
|
20055
|
+
const descriptions = /* @__PURE__ */ new Map();
|
|
20056
|
+
const tiles = /* @__PURE__ */ new Map();
|
|
20057
|
+
let cacheBytes = 0;
|
|
20058
|
+
async function description(source, signal) {
|
|
20059
|
+
if (!source.url)
|
|
20060
|
+
return { tiles: source.tiles, minzoom: source.minzoom, maxzoom: source.maxzoom };
|
|
20061
|
+
const previous = descriptions.get(source.url);
|
|
20062
|
+
if (previous) return previous;
|
|
20063
|
+
const response = await request(transform(source.url), { signal });
|
|
20064
|
+
if (!response.ok) throw new Error(`Path context TileJSON: HTTP ${response.status}`);
|
|
20065
|
+
const json = await response.json();
|
|
20066
|
+
if (!Array.isArray(json.tiles) || !json.tiles.length || json.tiles.some((url) => typeof url !== "string"))
|
|
20067
|
+
throw new Error("Path context TileJSON has no tile templates");
|
|
20068
|
+
const result = {
|
|
20069
|
+
...json,
|
|
20070
|
+
tiles: json.tiles.map(
|
|
20071
|
+
(url) => new URL(url, source.url).href.replaceAll("%7B", "{").replaceAll("%7D", "}")
|
|
20072
|
+
)
|
|
20073
|
+
};
|
|
20074
|
+
if (descriptions.size >= 16) descriptions.delete(descriptions.keys().next().value);
|
|
20075
|
+
descriptions.set(source.url, result);
|
|
20076
|
+
return result;
|
|
20077
|
+
}
|
|
20078
|
+
registry.addProtocol(tileflowPathGroundProtocol, async (input, abort) => {
|
|
20079
|
+
const { source, tile } = parsePathGroundRequest(input.url);
|
|
20080
|
+
const signal = abort.signal;
|
|
20081
|
+
signal.throwIfAborted();
|
|
20082
|
+
const json = await description(source, signal);
|
|
20083
|
+
if (!tile)
|
|
20084
|
+
return {
|
|
20085
|
+
data: {
|
|
20086
|
+
tiles: [pathGroundProtocolUrl(source, true)],
|
|
20087
|
+
minzoom: Math.max(12, json.minzoom ?? 0),
|
|
20088
|
+
maxzoom: json.maxzoom ?? source.maxzoom ?? 15,
|
|
20089
|
+
...json.attribution ? { attribution: json.attribution } : {}
|
|
20090
|
+
}
|
|
20091
|
+
};
|
|
20092
|
+
const cached = tiles.get(input.url);
|
|
20093
|
+
if (cached) return { data: cached.slice().buffer };
|
|
20094
|
+
const y2 = json.scheme === "tms" ? 2 ** tile.z - 1 - tile.y : tile.y;
|
|
20095
|
+
const url = json.tiles[0].replaceAll("{z}", String(tile.z)).replaceAll("{x}", String(tile.x)).replaceAll("{y}", String(y2));
|
|
20096
|
+
if (!/^https?:\/\//.test(url))
|
|
20097
|
+
throw new Error("Path context requires an HTTP(S) tile template");
|
|
20098
|
+
const response = await request(transform(url), { signal });
|
|
20099
|
+
if (!response.ok) throw new Error(`Path context tile: HTTP ${response.status}`);
|
|
20100
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
20101
|
+
if (bytes.byteLength > 16 * 1024 * 1024) throw new Error("Path context tile exceeds 16 MiB");
|
|
20102
|
+
signal.throwIfAborted();
|
|
20103
|
+
const result = deriveTileflowGreenPaths(bytes, source);
|
|
20104
|
+
while (tiles.size && (tiles.size >= 64 || cacheBytes + result.byteLength > 16 * 1024 * 1024)) {
|
|
20105
|
+
const key = tiles.keys().next().value;
|
|
20106
|
+
cacheBytes -= tiles.get(key).byteLength;
|
|
20107
|
+
tiles.delete(key);
|
|
20108
|
+
}
|
|
20109
|
+
tiles.set(input.url, result);
|
|
20110
|
+
cacheBytes += result.byteLength;
|
|
20111
|
+
return { data: result.slice().buffer };
|
|
20112
|
+
});
|
|
20113
|
+
registered.add(registry.addProtocol);
|
|
20114
|
+
}
|
|
20115
|
+
|
|
19639
20116
|
// src/terrain/contour-protocol.ts
|
|
19640
20117
|
var tileflowContourProtocol = "tileflow-contour";
|
|
19641
20118
|
var tileflowContourSourceLayer = "contours";
|
|
@@ -20026,6 +20503,130 @@ function createTileflowVegetation(options) {
|
|
|
20026
20503
|
};
|
|
20027
20504
|
}
|
|
20028
20505
|
|
|
20506
|
+
// src/building-flat-layers-browser.ts
|
|
20507
|
+
function createBuildingFlatLayers(map) {
|
|
20508
|
+
const saved = /* @__PURE__ */ new Map();
|
|
20509
|
+
let updating = false;
|
|
20510
|
+
function restore() {
|
|
20511
|
+
if (!map.setLayoutProperty || !map.getLayoutProperty || updating) return;
|
|
20512
|
+
updating = true;
|
|
20513
|
+
try {
|
|
20514
|
+
for (const [id, { visibility, layer }] of saved)
|
|
20515
|
+
if (map.getLayer(id) === layer && map.getLayoutProperty(id, "visibility") !== visibility)
|
|
20516
|
+
map.setLayoutProperty(id, "visibility", visibility);
|
|
20517
|
+
saved.clear();
|
|
20518
|
+
} finally {
|
|
20519
|
+
updating = false;
|
|
20520
|
+
}
|
|
20521
|
+
}
|
|
20522
|
+
return {
|
|
20523
|
+
update(layers, hidden) {
|
|
20524
|
+
if (updating || !map.setLayoutProperty || !map.getLayoutProperty) return;
|
|
20525
|
+
if (!hidden || layers.length === 0) {
|
|
20526
|
+
restore();
|
|
20527
|
+
return;
|
|
20528
|
+
}
|
|
20529
|
+
updating = true;
|
|
20530
|
+
try {
|
|
20531
|
+
const authored = new Map(layers.map((layer) => [layer.id, layer.visible]));
|
|
20532
|
+
const ids = map.getLayersOrder?.() ?? (map.getStyle()?.layers ?? []).map(({ id }) => id);
|
|
20533
|
+
for (const id of ids) {
|
|
20534
|
+
const visible = authored.get(id.split("::")[0]);
|
|
20535
|
+
if (visible === void 0 || !map.getLayer(id)) continue;
|
|
20536
|
+
const current = map.getLayoutProperty(id, "visibility") ?? "visible";
|
|
20537
|
+
if (!saved.has(id) || saved.get(id).layer !== map.getLayer(id))
|
|
20538
|
+
saved.set(id, { visibility: visible ? current : "none", layer: map.getLayer(id) });
|
|
20539
|
+
if (current !== "none") map.setLayoutProperty(id, "visibility", "none");
|
|
20540
|
+
}
|
|
20541
|
+
} finally {
|
|
20542
|
+
updating = false;
|
|
20543
|
+
}
|
|
20544
|
+
},
|
|
20545
|
+
restore,
|
|
20546
|
+
/** Removing a map must not write to its destroyed style. */
|
|
20547
|
+
forget() {
|
|
20548
|
+
saved.clear();
|
|
20549
|
+
}
|
|
20550
|
+
};
|
|
20551
|
+
}
|
|
20552
|
+
|
|
20553
|
+
// src/camera.ts
|
|
20554
|
+
var tileflowCameraMetadataKey = "tileflow:camera";
|
|
20555
|
+
function readTileflowCamera(metadata) {
|
|
20556
|
+
if (!metadata || typeof metadata !== "object") return {};
|
|
20557
|
+
const value = metadata[tileflowCameraMetadataKey];
|
|
20558
|
+
if (!value || typeof value !== "object") return {};
|
|
20559
|
+
const policy = value;
|
|
20560
|
+
return policy.version === 1 && typeof policy.adaptivePerspective === "boolean" ? { adaptivePerspective: policy.adaptivePerspective } : {};
|
|
20561
|
+
}
|
|
20562
|
+
|
|
20563
|
+
// src/camera-browser.ts
|
|
20564
|
+
function tileflowAdaptiveFieldOfView(pitch, zoom, height, normalFieldOfView) {
|
|
20565
|
+
if (pitch >= 15 || zoom <= 13 || height <= 0) return normalFieldOfView;
|
|
20566
|
+
const tangent = Math.tan(normalFieldOfView * Math.PI / 360);
|
|
20567
|
+
const distance = height / (2 * tangent);
|
|
20568
|
+
const mix2 = (Math.max(0, pitch) / 15) ** 5;
|
|
20569
|
+
const nearTangent = Math.max(
|
|
20570
|
+
Math.tan(Math.min(6, normalFieldOfView) * Math.PI / 360),
|
|
20571
|
+
height * mix2 / (2 * (1 - mix2 + mix2 * distance))
|
|
20572
|
+
);
|
|
20573
|
+
const t = Math.min(1, Math.max(0, (zoom - 13) / 2));
|
|
20574
|
+
const amount = t * t * (3 - 2 * t);
|
|
20575
|
+
return Math.atan(tangent + (nearTangent - tangent) * amount) * 360 / Math.PI;
|
|
20576
|
+
}
|
|
20577
|
+
function createTileflowAdaptiveCamera(map) {
|
|
20578
|
+
let normal;
|
|
20579
|
+
let applying = false;
|
|
20580
|
+
let disposed = false;
|
|
20581
|
+
const write = (next) => {
|
|
20582
|
+
if (applying || Math.abs((map.getVerticalFieldOfView?.() ?? next) - next) < 1e-6) return;
|
|
20583
|
+
applying = true;
|
|
20584
|
+
try {
|
|
20585
|
+
map.setVerticalFieldOfView?.(next);
|
|
20586
|
+
} finally {
|
|
20587
|
+
applying = false;
|
|
20588
|
+
}
|
|
20589
|
+
};
|
|
20590
|
+
const update = () => {
|
|
20591
|
+
if (disposed || applying || normal === void 0) return;
|
|
20592
|
+
write(
|
|
20593
|
+
tileflowAdaptiveFieldOfView(
|
|
20594
|
+
map.getPitch(),
|
|
20595
|
+
map.getZoom(),
|
|
20596
|
+
map.getCanvas().clientHeight,
|
|
20597
|
+
normal
|
|
20598
|
+
)
|
|
20599
|
+
);
|
|
20600
|
+
};
|
|
20601
|
+
const setEnabled = (enabled) => {
|
|
20602
|
+
if (disposed) return;
|
|
20603
|
+
if (enabled) {
|
|
20604
|
+
if (!map.getVerticalFieldOfView || !map.setVerticalFieldOfView || !map.getCanvas) return;
|
|
20605
|
+
normal ??= map.getVerticalFieldOfView();
|
|
20606
|
+
update();
|
|
20607
|
+
} else if (normal !== void 0) {
|
|
20608
|
+
const restore = normal;
|
|
20609
|
+
normal = void 0;
|
|
20610
|
+
write(restore);
|
|
20611
|
+
}
|
|
20612
|
+
};
|
|
20613
|
+
const onRemove = () => dispose(false);
|
|
20614
|
+
function dispose(restore = true) {
|
|
20615
|
+
if (disposed) return;
|
|
20616
|
+
if (restore) setEnabled(false);
|
|
20617
|
+
disposed = true;
|
|
20618
|
+
map.off("pitch", update);
|
|
20619
|
+
map.off("zoom", update);
|
|
20620
|
+
map.off("resize", update);
|
|
20621
|
+
map.off("remove", onRemove);
|
|
20622
|
+
}
|
|
20623
|
+
map.on("pitch", update);
|
|
20624
|
+
map.on("zoom", update);
|
|
20625
|
+
map.on("resize", update);
|
|
20626
|
+
map.on("remove", onRemove);
|
|
20627
|
+
return { setEnabled, dispose };
|
|
20628
|
+
}
|
|
20629
|
+
|
|
20029
20630
|
// src/map-3d-attach-browser.ts
|
|
20030
20631
|
var tileflowMap3DMetadataKeys = Object.freeze([
|
|
20031
20632
|
tileflowBuildingsMetadataKey,
|
|
@@ -20051,6 +20652,7 @@ function attachTileflowMap3D(options) {
|
|
|
20051
20652
|
const { map, load, onError, ...sceneOptions } = options;
|
|
20052
20653
|
let viewMode = options.viewMode ?? "3d";
|
|
20053
20654
|
let vegetation = options.vegetation;
|
|
20655
|
+
let adaptivePerspective = options.camera?.adaptivePerspective;
|
|
20054
20656
|
let scene;
|
|
20055
20657
|
let loading = false;
|
|
20056
20658
|
let disposed = false;
|
|
@@ -20066,7 +20668,13 @@ function attachTileflowMap3D(options) {
|
|
|
20066
20668
|
stopWatching();
|
|
20067
20669
|
load().then(({ createTileflowMap3D: createTileflowMap3D2 }) => {
|
|
20068
20670
|
if (disposed) return;
|
|
20069
|
-
scene = createTileflowMap3D2({
|
|
20671
|
+
scene = createTileflowMap3D2({
|
|
20672
|
+
...sceneOptions,
|
|
20673
|
+
map,
|
|
20674
|
+
viewMode,
|
|
20675
|
+
vegetation,
|
|
20676
|
+
camera: { adaptivePerspective }
|
|
20677
|
+
});
|
|
20070
20678
|
}).catch((error) => {
|
|
20071
20679
|
if (!disposed) onError?.(error);
|
|
20072
20680
|
});
|
|
@@ -20084,28 +20692,36 @@ function attachTileflowMap3D(options) {
|
|
|
20084
20692
|
if (disposed) return;
|
|
20085
20693
|
disposed = true;
|
|
20086
20694
|
stopWatching();
|
|
20087
|
-
map.off("remove",
|
|
20695
|
+
map.off("remove", onRemove);
|
|
20088
20696
|
scene?.dispose();
|
|
20089
20697
|
scene = void 0;
|
|
20090
20698
|
}
|
|
20699
|
+
function onRemove() {
|
|
20700
|
+
scene = void 0;
|
|
20701
|
+
dispose();
|
|
20702
|
+
}
|
|
20091
20703
|
map.on("styledata", restyle);
|
|
20092
20704
|
map.on("style.load", restyle);
|
|
20093
20705
|
map.on("idle", check);
|
|
20094
|
-
map.on("remove",
|
|
20706
|
+
map.on("remove", onRemove);
|
|
20095
20707
|
check();
|
|
20096
20708
|
return {
|
|
20097
20709
|
get scene() {
|
|
20098
20710
|
return scene;
|
|
20099
20711
|
},
|
|
20100
|
-
setViewMode(mode) {
|
|
20712
|
+
setViewMode(mode, change) {
|
|
20101
20713
|
if (mode === viewMode) return;
|
|
20102
20714
|
viewMode = mode;
|
|
20103
|
-
if (scene) void (mode === "3d" ? scene.show() : scene.hide());
|
|
20715
|
+
if (scene) void (mode === "3d" ? scene.show(change) : scene.hide(change));
|
|
20104
20716
|
},
|
|
20105
20717
|
setVegetation(visible) {
|
|
20106
20718
|
vegetation = visible;
|
|
20107
20719
|
scene?.setVegetation(visible);
|
|
20108
20720
|
},
|
|
20721
|
+
setAdaptivePerspective(enabled) {
|
|
20722
|
+
adaptivePerspective = enabled;
|
|
20723
|
+
scene?.setAdaptivePerspective(enabled);
|
|
20724
|
+
},
|
|
20109
20725
|
dispose
|
|
20110
20726
|
};
|
|
20111
20727
|
}
|
|
@@ -20115,9 +20731,15 @@ function createTileflowMap3D(options) {
|
|
|
20115
20731
|
const { map, controller, transformRequest } = options;
|
|
20116
20732
|
let viewMode = options.viewMode ?? "3d";
|
|
20117
20733
|
let vegetationVisible = options.vegetation;
|
|
20734
|
+
let adaptivePerspective = options.camera?.adaptivePerspective;
|
|
20735
|
+
const camera = createTileflowAdaptiveCamera(map);
|
|
20736
|
+
let authoredPerspective;
|
|
20118
20737
|
let buildings;
|
|
20119
20738
|
let vegetation;
|
|
20120
20739
|
let streetLights;
|
|
20740
|
+
const flatBuildings = createBuildingFlatLayers(map);
|
|
20741
|
+
let footprintLayers;
|
|
20742
|
+
let footprintZoom = 15.3;
|
|
20121
20743
|
let disposed = false;
|
|
20122
20744
|
let syncing = false;
|
|
20123
20745
|
const shared4 = {
|
|
@@ -20132,6 +20754,19 @@ function createTileflowMap3D(options) {
|
|
|
20132
20754
|
syncing = true;
|
|
20133
20755
|
try {
|
|
20134
20756
|
const shown = viewMode === "3d";
|
|
20757
|
+
if (footprintLayers === void 0) {
|
|
20758
|
+
const themes = controller?.getThemeMetadata?.(tileflowBuildingsMetadataKey);
|
|
20759
|
+
const metadata = themes ? { [tileflowBuildingsMetadataKey]: themes.values[Math.round(themes.position)] } : map.getStyle()?.metadata;
|
|
20760
|
+
const design = readTileflowBuildings3D(metadata);
|
|
20761
|
+
footprintLayers = design?.flatLayers ?? [];
|
|
20762
|
+
footprintZoom = design?.entrance?.buildings?.[1] ?? 15.3;
|
|
20763
|
+
}
|
|
20764
|
+
if (authoredPerspective === void 0) {
|
|
20765
|
+
const themes = controller?.getThemeMetadata?.(tileflowCameraMetadataKey);
|
|
20766
|
+
const metadata = themes ? { [tileflowCameraMetadataKey]: themes.values[Math.round(themes.position)] } : map.getStyle()?.metadata;
|
|
20767
|
+
authoredPerspective = readTileflowCamera(metadata).adaptivePerspective ?? false;
|
|
20768
|
+
}
|
|
20769
|
+
camera.setEnabled(shown && (adaptivePerspective ?? authoredPerspective));
|
|
20135
20770
|
const declared = declarations ??= tileflowMap3DDeclarations({
|
|
20136
20771
|
map,
|
|
20137
20772
|
...controller ? { controller } : {}
|
|
@@ -20145,6 +20780,7 @@ function createTileflowMap3D(options) {
|
|
|
20145
20780
|
}
|
|
20146
20781
|
if (!vegetation && (declares(tileflowVegetationMetadataKey) || declares(tileflowVegetationDisplayMetadataKey)))
|
|
20147
20782
|
vegetation = createTileflowVegetation({ ...shared4, visible: vegetationVisible, viewMode });
|
|
20783
|
+
syncFlatBuildings();
|
|
20148
20784
|
if (shown && declares(tileflowStreetLightsMetadataKey))
|
|
20149
20785
|
streetLights ??= createTileflowStreetLights(shared4);
|
|
20150
20786
|
else if (streetLights) {
|
|
@@ -20155,9 +20791,22 @@ function createTileflowMap3D(options) {
|
|
|
20155
20791
|
syncing = false;
|
|
20156
20792
|
}
|
|
20157
20793
|
}
|
|
20794
|
+
function syncFlatBuildings() {
|
|
20795
|
+
if (disposed) return;
|
|
20796
|
+
if (!footprintLayers?.length) {
|
|
20797
|
+
flatBuildings.restore();
|
|
20798
|
+
return;
|
|
20799
|
+
}
|
|
20800
|
+
const canvas = map.getCanvas?.();
|
|
20801
|
+
flatBuildings.update(
|
|
20802
|
+
footprintLayers,
|
|
20803
|
+
viewMode === "3d" && Boolean(buildings) && map.getZoom() >= footprintZoom && Boolean(canvas?.getContext?.("webgl2"))
|
|
20804
|
+
);
|
|
20805
|
+
}
|
|
20158
20806
|
function change(next, transition) {
|
|
20159
20807
|
if (disposed) return Promise.resolve();
|
|
20160
20808
|
viewMode = next;
|
|
20809
|
+
camera.setEnabled(next === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
|
|
20161
20810
|
vegetation?.setViewMode(next);
|
|
20162
20811
|
if (next === "3d") {
|
|
20163
20812
|
const existing = buildings;
|
|
@@ -20173,10 +20822,13 @@ function createTileflowMap3D(options) {
|
|
|
20173
20822
|
function dispose() {
|
|
20174
20823
|
if (disposed) return;
|
|
20175
20824
|
disposed = true;
|
|
20825
|
+
flatBuildings.restore();
|
|
20826
|
+
camera.dispose();
|
|
20176
20827
|
map.off("styledata", restyle);
|
|
20177
20828
|
map.off("style.load", restyle);
|
|
20178
20829
|
map.off("idle", sync);
|
|
20179
|
-
map.off("remove",
|
|
20830
|
+
map.off("remove", onRemove);
|
|
20831
|
+
map.off("move", syncFlatBuildings);
|
|
20180
20832
|
streetLights?.dispose();
|
|
20181
20833
|
buildings?.dispose();
|
|
20182
20834
|
vegetation?.dispose();
|
|
@@ -20185,13 +20837,21 @@ function createTileflowMap3D(options) {
|
|
|
20185
20837
|
vegetation = void 0;
|
|
20186
20838
|
}
|
|
20187
20839
|
function restyle() {
|
|
20840
|
+
if (syncing) return;
|
|
20841
|
+
footprintLayers = void 0;
|
|
20188
20842
|
declarations = void 0;
|
|
20843
|
+
authoredPerspective = void 0;
|
|
20189
20844
|
sync();
|
|
20190
20845
|
}
|
|
20846
|
+
function onRemove() {
|
|
20847
|
+
flatBuildings.forget();
|
|
20848
|
+
dispose();
|
|
20849
|
+
}
|
|
20191
20850
|
map.on("styledata", restyle);
|
|
20192
20851
|
map.on("style.load", restyle);
|
|
20193
20852
|
map.on("idle", sync);
|
|
20194
|
-
map.on("remove",
|
|
20853
|
+
map.on("remove", onRemove);
|
|
20854
|
+
map.on("move", syncFlatBuildings);
|
|
20195
20855
|
sync();
|
|
20196
20856
|
return {
|
|
20197
20857
|
show: (transition) => change("3d", transition),
|
|
@@ -20203,6 +20863,11 @@ function createTileflowMap3D(options) {
|
|
|
20203
20863
|
vegetationVisible = visible;
|
|
20204
20864
|
vegetation?.setVisible(visible);
|
|
20205
20865
|
},
|
|
20866
|
+
setAdaptivePerspective(enabled) {
|
|
20867
|
+
adaptivePerspective = enabled;
|
|
20868
|
+
camera.setEnabled(viewMode === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
|
|
20869
|
+
sync();
|
|
20870
|
+
},
|
|
20206
20871
|
get buildings() {
|
|
20207
20872
|
return buildings;
|
|
20208
20873
|
},
|
|
@@ -21731,6 +22396,7 @@ function isPromiseLike(value) {
|
|
|
21731
22396
|
export {
|
|
21732
22397
|
attachTileflowAtmosphere,
|
|
21733
22398
|
attachTileflowFairUseNotice,
|
|
22399
|
+
attachTileflowHorizonQueries,
|
|
21734
22400
|
attachTileflowLabelPlacement,
|
|
21735
22401
|
attachTileflowMap3D,
|
|
21736
22402
|
attachTileflowMapLifecycle,
|
|
@@ -21772,6 +22438,7 @@ export {
|
|
|
21772
22438
|
readTileflowVegetation3D,
|
|
21773
22439
|
readTileflowVegetationDisplay,
|
|
21774
22440
|
registerTileflowContourProtocol,
|
|
22441
|
+
registerTileflowPathGroundProtocol,
|
|
21775
22442
|
registerTileflowPmtilesProtocol,
|
|
21776
22443
|
registerTileflowWorldRequestBridge,
|
|
21777
22444
|
resolveTileflowSun,
|
|
@@ -21788,6 +22455,7 @@ export {
|
|
|
21788
22455
|
tileflowDepthMarkerPlacement,
|
|
21789
22456
|
tileflowFairUseNoticeMessage,
|
|
21790
22457
|
tileflowGroundBeforeId,
|
|
22458
|
+
tileflowHorizonScaleFactor,
|
|
21791
22459
|
tileflowLayerDomainMetadataKey,
|
|
21792
22460
|
tileflowLightRhythm,
|
|
21793
22461
|
tileflowLightRhythmConventions,
|