@tileflow/core 0.1.0-alpha.41 → 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 +51 -69
- 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 +337 -34
- package/dist/browser.d.ts +119 -7
- package/dist/browser.js +754 -61
- package/dist/build.d.ts +8 -4
- package/dist/build.js +284 -4
- package/dist/config-reference.json +4005 -2284
- package/dist/{icon-composition-HUh_Lj8Z.d.ts → icon-composition-Bbw9umUA.d.ts} +46 -3
- package/dist/index.d.ts +22 -5
- package/dist/index.js +254 -6
- package/dist/{manifest-types-DnhSJjCM.d.ts → manifest-types-CwjHd4qc.d.ts} +10 -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.d.ts +87 -1
- package/dist/native.js +980 -460
- 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 -217
- package/docs/buildings-3d.md +0 -608
- 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 -210
- 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,8 +6441,12 @@ 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) },
|
|
6447
|
+
...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
|
|
6448
|
+
...entry.ambientOcclusion === void 0 ? {} : { ambientOcclusion: bounded(entry.ambientOcclusion, 0, 1, 1) },
|
|
6449
|
+
...entry.partColorMix === void 0 ? {} : { partColorMix: bounded(entry.partColorMix, 0, 1, 1) },
|
|
6389
6450
|
...readRoleColorVariation(entry.colorVariation),
|
|
6390
6451
|
emissiveHeight: Array.isArray(gradient) && gradient.length === 5 && gradient.every(
|
|
6391
6452
|
(v2, i2) => typeof v2 === "number" && Number.isFinite(v2) && v2 <= 1 && v2 >= (i2 === 4 ? -1 : 0)
|
|
@@ -6482,6 +6543,8 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
|
6482
6543
|
windows: false,
|
|
6483
6544
|
shadows: true,
|
|
6484
6545
|
occlusion: true,
|
|
6546
|
+
groundOcclusion: 0.16,
|
|
6547
|
+
groundOcclusionRadius: 3,
|
|
6485
6548
|
modelOcclusion: 0.75
|
|
6486
6549
|
});
|
|
6487
6550
|
function readTileflowBuildings3D(metadata) {
|
|
@@ -6505,7 +6568,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6505
6568
|
},
|
|
6506
6569
|
color,
|
|
6507
6570
|
edges: within(value.edges, 1, 0),
|
|
6508
|
-
edgeRadius: within(value.edgeRadius, 1, defaults.edgeRadius),
|
|
6571
|
+
edgeRadius: within(value.edgeRadius, 1.5, defaults.edgeRadius),
|
|
6509
6572
|
lighting: value.lighting === "style" ? "style" : defaults.lighting,
|
|
6510
6573
|
colorVariation: within(value.colorVariation, 1, 0),
|
|
6511
6574
|
verticalGradient: value.verticalGradient !== false,
|
|
@@ -6518,7 +6581,12 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6518
6581
|
...readTileflowBuildingsEntrance(value.entrance),
|
|
6519
6582
|
shadows: typeof value.shadows === "boolean" ? value.shadows : defaults.shadows,
|
|
6520
6583
|
occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults.occlusion,
|
|
6584
|
+
groundOcclusion: within(value.groundOcclusion, 1, defaults.groundOcclusion),
|
|
6585
|
+
groundOcclusionRadius: within(value.groundOcclusionRadius, 20, defaults.groundOcclusionRadius),
|
|
6521
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 } : {},
|
|
6522
6590
|
...modelsOf(value.models),
|
|
6523
6591
|
...modelColorsOf(value.modelColors),
|
|
6524
6592
|
...landmarksOf(value.landmarks)
|
|
@@ -7525,7 +7593,7 @@ function meshTileflowBuildings(layer, options) {
|
|
|
7525
7593
|
const scale = tileflowBuildingExtent / layer.extent;
|
|
7526
7594
|
const metresPerUnit = options.tileMetres / tileflowBuildingExtent;
|
|
7527
7595
|
const fallback = options.defaultHeight ?? 5;
|
|
7528
|
-
const edgeRadius = Number.isFinite(options.edgeRadius) ? Math.max(0, Math.min(1, options.edgeRadius)) / metresPerUnit : 0;
|
|
7596
|
+
const edgeRadius = Number.isFinite(options.edgeRadius) ? Math.max(0, Math.min(1.5, options.edgeRadius)) / metresPerUnit : 0;
|
|
7529
7597
|
const vertices = new VertexWriter();
|
|
7530
7598
|
const roofs = new IndexWriter();
|
|
7531
7599
|
const walls = new IndexWriter();
|
|
@@ -9745,6 +9813,9 @@ function readTileflowVegetation3D(metadata) {
|
|
|
9745
9813
|
{
|
|
9746
9814
|
heightScale: scale(own.heightScale),
|
|
9747
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]) } : {},
|
|
9748
9819
|
...drawn.length > 0 ? { models: drawn } : {}
|
|
9749
9820
|
}
|
|
9750
9821
|
]
|
|
@@ -10064,7 +10135,7 @@ function browserWorker() {
|
|
|
10064
10135
|
if (typeof Worker === "undefined" || false)
|
|
10065
10136
|
return;
|
|
10066
10137
|
const url = URL.createObjectURL(
|
|
10067
|
-
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,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" })
|
|
10068
10139
|
);
|
|
10069
10140
|
try {
|
|
10070
10141
|
return new Worker(url, { name: "tileflow-tiles" });
|
|
@@ -11054,7 +11125,7 @@ var protocolPrefix = `${tileflowPmtilesProtocol}://`;
|
|
|
11054
11125
|
function registerTileflowPmtilesProtocol(registry, options = {}) {
|
|
11055
11126
|
if (registeredPmtilesProtocols.has(registry.addProtocol)) return;
|
|
11056
11127
|
const maximumDirectoryDepth = normalizeMaximumDirectoryDepth(options.maximumDirectoryDepth);
|
|
11057
|
-
const protocol2 = new TileflowPmtilesProtocol(maximumDirectoryDepth);
|
|
11128
|
+
const protocol2 = new TileflowPmtilesProtocol(maximumDirectoryDepth, options.transformArchiveUrl);
|
|
11058
11129
|
sharedProtocol ??= protocol2;
|
|
11059
11130
|
registry.addProtocol(tileflowPmtilesProtocol, protocol2.tile);
|
|
11060
11131
|
registeredPmtilesProtocols.add(registry.addProtocol);
|
|
@@ -11076,10 +11147,12 @@ function isTileflowPmtilesUrl(url) {
|
|
|
11076
11147
|
return url.startsWith(protocolPrefix);
|
|
11077
11148
|
}
|
|
11078
11149
|
var TileflowPmtilesProtocol = class {
|
|
11079
|
-
constructor(maximumDirectoryDepth) {
|
|
11150
|
+
constructor(maximumDirectoryDepth, transformArchiveUrl = (url) => url) {
|
|
11080
11151
|
this.maximumDirectoryDepth = maximumDirectoryDepth;
|
|
11152
|
+
this.transformArchiveUrl = transformArchiveUrl;
|
|
11081
11153
|
}
|
|
11082
11154
|
maximumDirectoryDepth;
|
|
11155
|
+
transformArchiveUrl;
|
|
11083
11156
|
#archives = /* @__PURE__ */ new Map();
|
|
11084
11157
|
tilev4 = async (request, abortController) => {
|
|
11085
11158
|
if (request.type === "json") {
|
|
@@ -11112,7 +11185,10 @@ var TileflowPmtilesProtocol = class {
|
|
|
11112
11185
|
#archive(target) {
|
|
11113
11186
|
let archive = this.#archives.get(target);
|
|
11114
11187
|
if (!archive) {
|
|
11115
|
-
archive = new TileflowPmtilesArchive(
|
|
11188
|
+
archive = new TileflowPmtilesArchive(
|
|
11189
|
+
this.transformArchiveUrl(target),
|
|
11190
|
+
this.maximumDirectoryDepth
|
|
11191
|
+
);
|
|
11116
11192
|
this.#archives.set(target, archive);
|
|
11117
11193
|
}
|
|
11118
11194
|
return archive;
|
|
@@ -11569,7 +11645,7 @@ function createCameraTiles(options) {
|
|
|
11569
11645
|
}
|
|
11570
11646
|
entry.used = now;
|
|
11571
11647
|
entry.distance = distance;
|
|
11572
|
-
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)
|
|
11573
11649
|
load(source, key, entry, chosen.tileMetres);
|
|
11574
11650
|
}
|
|
11575
11651
|
evict();
|
|
@@ -11585,6 +11661,8 @@ function createCameraTiles(options) {
|
|
|
11585
11661
|
).then((tile) => {
|
|
11586
11662
|
if (disposed || tiles.get(key) !== entry || entry.loading !== controller) return;
|
|
11587
11663
|
if (!tile) {
|
|
11664
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11665
|
+
entry.pending = void 0;
|
|
11588
11666
|
if (entry.value && entry.value !== options.empty) options.release(entry.value);
|
|
11589
11667
|
entry.value = options.empty;
|
|
11590
11668
|
entry.loading = void 0;
|
|
@@ -11633,10 +11711,11 @@ function createCameraTiles(options) {
|
|
|
11633
11711
|
if (value !== options.empty) options.release(value);
|
|
11634
11712
|
continue;
|
|
11635
11713
|
}
|
|
11636
|
-
|
|
11637
|
-
|
|
11714
|
+
if (entry.pending && entry.pending !== options.empty && entry.pending !== value)
|
|
11715
|
+
options.release(entry.pending);
|
|
11716
|
+
entry.pending = value;
|
|
11638
11717
|
entry.loading = void 0;
|
|
11639
|
-
|
|
11718
|
+
commit(entry);
|
|
11640
11719
|
built = true;
|
|
11641
11720
|
}
|
|
11642
11721
|
if (built && !disposed) {
|
|
@@ -11653,12 +11732,24 @@ function createCameraTiles(options) {
|
|
|
11653
11732
|
void step();
|
|
11654
11733
|
});
|
|
11655
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
|
+
}
|
|
11656
11746
|
function evict() {
|
|
11657
11747
|
const keep = new Set(wanted);
|
|
11658
11748
|
const spare = [...tiles.entries()].filter(([key]) => !keep.has(key)).sort((a, b2) => b2[1].used - a[1].used);
|
|
11659
11749
|
for (const [key, entry] of spare.slice(options.maxTiles)) {
|
|
11660
11750
|
entry.loading?.abort();
|
|
11661
11751
|
if (entry.value && entry.value !== options.empty) options.release(entry.value);
|
|
11752
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11662
11753
|
tiles.delete(key);
|
|
11663
11754
|
options.changed();
|
|
11664
11755
|
}
|
|
@@ -11684,11 +11775,19 @@ function createCameraTiles(options) {
|
|
|
11684
11775
|
const list = [];
|
|
11685
11776
|
for (const key of wanted) {
|
|
11686
11777
|
const entry = tiles.get(key);
|
|
11778
|
+
if (entry) commit(entry);
|
|
11687
11779
|
if (entry?.value && entry.value !== options.empty)
|
|
11688
11780
|
list.push(entry);
|
|
11689
11781
|
}
|
|
11690
11782
|
return list;
|
|
11691
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
|
+
},
|
|
11692
11791
|
coverage: () => covered,
|
|
11693
11792
|
ring: () => ring,
|
|
11694
11793
|
all: () => tiles.values(),
|
|
@@ -11710,6 +11809,8 @@ function createCameraTiles(options) {
|
|
|
11710
11809
|
for (const [key, entry] of tiles) {
|
|
11711
11810
|
if (!which(entry)) continue;
|
|
11712
11811
|
entry.loading?.abort();
|
|
11812
|
+
if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
|
|
11813
|
+
entry.pending = void 0;
|
|
11713
11814
|
entry.retryAt = void 0;
|
|
11714
11815
|
const latitude = Math.atan(Math.sinh(Math.PI * (1 - 2 * (entry.y + 0.5) / 2 ** zoom))) * 180 / Math.PI;
|
|
11715
11816
|
load(source, key, entry, earth * Math.cos(latitude * Math.PI / 180) / 2 ** zoom);
|
|
@@ -11722,7 +11823,10 @@ function createCameraTiles(options) {
|
|
|
11722
11823
|
map.off("sourcedata", onSource);
|
|
11723
11824
|
map.off("move", onMove);
|
|
11724
11825
|
map.off("moveend", onMoveEnd);
|
|
11725
|
-
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
|
+
}
|
|
11726
11830
|
tiles.clear();
|
|
11727
11831
|
queue.length = 0;
|
|
11728
11832
|
reader?.clear();
|
|
@@ -12449,7 +12553,9 @@ function tileflowModelCameraDistance(model, view) {
|
|
|
12449
12553
|
function tileflowModelLevel(model, view, previous) {
|
|
12450
12554
|
const thresholds = tileflowModelLevelDistancesOf(model.bounds);
|
|
12451
12555
|
const last = Math.max(0, Math.min(model.levels, thresholds.length + 1) - 1);
|
|
12452
|
-
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;
|
|
12453
12559
|
if (!Number.isFinite(distance)) return 0;
|
|
12454
12560
|
const margin = previous === void 0 ? 1 : tileflowModelLevelHysteresis;
|
|
12455
12561
|
let level = Math.max(0, Math.min(last, previous ?? 0));
|
|
@@ -12741,6 +12847,7 @@ uniform bool u_unlit;
|
|
|
12741
12847
|
uniform vec4 u_parts[${tileflowModelLimits.parts}];
|
|
12742
12848
|
uniform vec4 u_role_colour[7];
|
|
12743
12849
|
uniform vec4 u_role_material[7]; // metallic, roughness, their respective override weights
|
|
12850
|
+
uniform vec3 u_role_appearance[7]; // map shading share, ambient occlusion multiplier, part colour share
|
|
12744
12851
|
|
|
12745
12852
|
vec3 fromSRGB(vec3 colour) {
|
|
12746
12853
|
return pow(max(colour, vec3(0.0)), vec3(2.2));
|
|
@@ -12771,7 +12878,7 @@ vec3 materialBase(int role) {
|
|
|
12771
12878
|
vec4 own = u_role_colour[role];
|
|
12772
12879
|
vec3 factor = mix(u_base_colour.rgb, fromSRGB(own.rgb), own.a);
|
|
12773
12880
|
vec4 part = u_parts[v_part];
|
|
12774
|
-
factor = mix(factor, fromSRGB(part.rgb), part.a);
|
|
12881
|
+
factor = mix(factor, fromSRGB(part.rgb), part.a * u_role_appearance[role].z);
|
|
12775
12882
|
return factor * v_rgba.rgb * fromSRGB(materialTexture(0).rgb);
|
|
12776
12883
|
}
|
|
12777
12884
|
|
|
@@ -12808,7 +12915,7 @@ vec3 physicalLight(vec3 base, vec3 normal, float lit, int role) {
|
|
|
12808
12915
|
float exposure = (0.96 + 0.04 * clamp(normal.z, -1.0, 1.0)) *
|
|
12809
12916
|
(1.0 - 0.3 * min(directional, 1.0) * max(-dot(normal, u_sun_dir), 0.0));
|
|
12810
12917
|
float ao = mix(1.0, v_light * mix(1.0, materialTexture(3).r, u_occlusion_strength),
|
|
12811
|
-
u_ambient_occlusion);
|
|
12918
|
+
u_ambient_occlusion * u_role_appearance[role].y);
|
|
12812
12919
|
vec3 ambient = (diffuse + reflectedSky) * u_sky_light * exposure * ao;
|
|
12813
12920
|
return ambient + min(direct, vec3(1.0));
|
|
12814
12921
|
}
|
|
@@ -12901,6 +13008,7 @@ out vec3 v_shadow;
|
|
|
12901
13008
|
out float v_light;
|
|
12902
13009
|
flat out int v_lighting_role;
|
|
12903
13010
|
out float v_height;
|
|
13011
|
+
out float v_ground_height;
|
|
12904
13012
|
out vec4 v_uv;
|
|
12905
13013
|
out vec4 v_rgba;
|
|
12906
13014
|
out vec3 v_position;
|
|
@@ -12929,6 +13037,7 @@ void main() {
|
|
|
12929
13037
|
v_light = a_paint.z / 255.0;
|
|
12930
13038
|
v_lighting_role = clamp(int(a_lighting_role + 0.5), 0, 6);
|
|
12931
13039
|
v_height = (m.z - u_model_height.x) / max(u_model_height.y, 0.001);
|
|
13040
|
+
v_ground_height = m.z;
|
|
12932
13041
|
}`;
|
|
12933
13042
|
var tileflowModelFragment = `#version 300 es
|
|
12934
13043
|
precision highp float;
|
|
@@ -12938,6 +13047,9 @@ in vec3 v_shadow;
|
|
|
12938
13047
|
in float v_light;
|
|
12939
13048
|
flat in int v_lighting_role;
|
|
12940
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];
|
|
12941
13053
|
uniform vec3 u_sun_dir;
|
|
12942
13054
|
uniform vec3 u_sun_light;
|
|
12943
13055
|
uniform vec3 u_sky_light;
|
|
@@ -12956,15 +13068,25 @@ ${modelPhysicalLighting}
|
|
|
12956
13068
|
|
|
12957
13069
|
// The buildings' light: a sunlit roof keeps its colour, a face turned to a low sun glows, and shade
|
|
12958
13070
|
// takes the sky's colour; a face that looks down sees little sky.
|
|
12959
|
-
vec3 shade(vec3 normal, float lit) {
|
|
13071
|
+
vec3 shade(vec3 normal, float lit, float occlusion) {
|
|
12960
13072
|
float facing = dot(normal, u_sun_dir);
|
|
12961
13073
|
vec3 sky = u_sky_light * mix(mix(0.8, 0.5, u_night), 1.0, max(normal.z, -0.4));
|
|
12962
|
-
sky *= mix(1.0, v_light, u_ambient_occlusion);
|
|
13074
|
+
sky *= mix(1.0, v_light, u_ambient_occlusion * occlusion);
|
|
12963
13075
|
vec3 light = sky + u_sun_light * max(facing, 0.0) * (1.0 - u_shadow * (1.0 - lit));
|
|
12964
13076
|
vec3 roof = u_sky_light + u_sun_light * max(u_sun_dir.z, 0.0);
|
|
12965
13077
|
return min(pow(light / max(roof, vec3(1e-4)), vec3(1.0 / 2.2)), vec3(1.7));
|
|
12966
13078
|
}
|
|
12967
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
|
+
|
|
12968
13090
|
void main() {
|
|
12969
13091
|
vec3 normal = normalize(gl_FrontFacing ? v_normal : -v_normal);
|
|
12970
13092
|
if (u_physical) normal = materialNormal(normal);
|
|
@@ -12979,15 +13101,24 @@ void main() {
|
|
|
12979
13101
|
float emission = clamp(u_role_emission[role] * multiplier, 0.0, 1.0);
|
|
12980
13102
|
if (u_physical) {
|
|
12981
13103
|
float alpha = materialAlpha();
|
|
12982
|
-
vec3 base = materialBase(role);
|
|
12983
|
-
|
|
13104
|
+
vec3 base = materialBase(role) * fromSRGB(vec3(u_role_color_scale[role]));
|
|
13105
|
+
float mapShare = u_role_appearance[role].x;
|
|
13106
|
+
vec3 radiance;
|
|
13107
|
+
if (mapShare >= 1.0) {
|
|
13108
|
+
radiance = base * fromSRGB(shade(normal, lit, u_role_appearance[role].y));
|
|
13109
|
+
} else {
|
|
13110
|
+
radiance = physicalLight(base, normal, lit, role);
|
|
13111
|
+
if (mapShare > 0.0)
|
|
13112
|
+
radiance = mix(radiance, base * fromSRGB(shade(normal, lit, u_role_appearance[role].y)), mapShare);
|
|
13113
|
+
}
|
|
13114
|
+
radiance *= fromSRGB(vec3(facadeShade(normal, role)));
|
|
12984
13115
|
radiance += u_emissive * fromSRGB(materialTexture(4).rgb);
|
|
12985
13116
|
vec4 own = u_role_emission_colour[role];
|
|
12986
13117
|
radiance = mix(radiance, mix(base, fromSRGB(own.rgb), own.a), emission);
|
|
12987
13118
|
fragColor = vec4(hazed(toSRGB(radiance)), alpha * u_opacity);
|
|
12988
13119
|
return;
|
|
12989
13120
|
}
|
|
12990
|
-
vec3 colour = v_colour * shade(normal, lit);
|
|
13121
|
+
vec3 colour = v_colour * u_role_color_scale[role] * shade(normal, lit, u_role_appearance[role].y) * facadeShade(normal, role);
|
|
12991
13122
|
if (emission > 0.0) {
|
|
12992
13123
|
vec4 own = u_role_emission_colour[role];
|
|
12993
13124
|
vec3 target = mix(v_colour, own.rgb, own.a);
|
|
@@ -13779,7 +13910,7 @@ function sampleModelRole(profile, identity) {
|
|
|
13779
13910
|
};
|
|
13780
13911
|
const variation = profile?.colorVariation;
|
|
13781
13912
|
let color = profile?.color ? tileflowColourChannels(profile.color)?.slice(0, 3) : void 0;
|
|
13782
|
-
if (variation) {
|
|
13913
|
+
if (variation && !color) {
|
|
13783
13914
|
const hsl = [variation.hue, variation.saturation, variation.lightness].map(
|
|
13784
13915
|
([low, high], channel) => low + (high - low) * random(channel + 1)
|
|
13785
13916
|
);
|
|
@@ -13845,7 +13976,7 @@ function createTileflowBuildings3D(options) {
|
|
|
13845
13976
|
let ahead = [0, -1];
|
|
13846
13977
|
const scene = tileflowScene3D(map);
|
|
13847
13978
|
let generation = 0;
|
|
13848
|
-
let
|
|
13979
|
+
let registered2 = false;
|
|
13849
13980
|
let unregister = () => {
|
|
13850
13981
|
};
|
|
13851
13982
|
const models = createTileflowPlacedModels({
|
|
@@ -13894,7 +14025,7 @@ function createTileflowBuildings3D(options) {
|
|
|
13894
14025
|
if (program) context.deleteProgram(program.program);
|
|
13895
14026
|
for (const entry of linking ?? []) context.deleteProgram(entry.program);
|
|
13896
14027
|
unregister();
|
|
13897
|
-
|
|
14028
|
+
registered2 = false;
|
|
13898
14029
|
scene.setReach(void 0);
|
|
13899
14030
|
scene.release(context);
|
|
13900
14031
|
if (ground) {
|
|
@@ -13925,12 +14056,12 @@ function createTileflowBuildings3D(options) {
|
|
|
13925
14056
|
drawMasks(context, args);
|
|
13926
14057
|
if (!programs.depth) return;
|
|
13927
14058
|
if (!design().shadows || visibleScale() <= 0 && modelScale() <= 0) {
|
|
13928
|
-
if (
|
|
13929
|
-
|
|
14059
|
+
if (registered2) unregister();
|
|
14060
|
+
registered2 = false;
|
|
13930
14061
|
return;
|
|
13931
14062
|
}
|
|
13932
|
-
if (!
|
|
13933
|
-
|
|
14063
|
+
if (!registered2) unregister = scene.register(caster);
|
|
14064
|
+
registered2 = true;
|
|
13934
14065
|
scene.prepare(context, lighting(), camera.metres);
|
|
13935
14066
|
},
|
|
13936
14067
|
render(context, args) {
|
|
@@ -13987,6 +14118,7 @@ function createTileflowBuildings3D(options) {
|
|
|
13987
14118
|
return prepared ? { mesh: prepared.mesh, data: prepared.data } : emptyTile;
|
|
13988
14119
|
},
|
|
13989
14120
|
empty: emptyTile,
|
|
14121
|
+
isReady: (value) => value === emptyTile || value.gl !== void 0,
|
|
13990
14122
|
release(value) {
|
|
13991
14123
|
if (gl) release(gl, value);
|
|
13992
14124
|
},
|
|
@@ -14047,7 +14179,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14047
14179
|
models.upload(context);
|
|
14048
14180
|
if (modelKey !== models.key()) map.triggerRepaint();
|
|
14049
14181
|
let budget = 2;
|
|
14050
|
-
for (const { value: entry } of camera.
|
|
14182
|
+
for (const { value: entry } of camera.built()) {
|
|
14051
14183
|
if (entry.gl || !entry.data) continue;
|
|
14052
14184
|
if (budget-- <= 0) {
|
|
14053
14185
|
map.triggerRepaint();
|
|
@@ -14290,7 +14422,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14290
14422
|
for (const { x: x3, y: y2, value } of shown > 0 ? drawn() : []) {
|
|
14291
14423
|
const offset = frame.offsetOf({ x: x3, y: y2 }, camera.zoom);
|
|
14292
14424
|
const ring = ringIn(x3, y2);
|
|
14293
|
-
if (!
|
|
14425
|
+
if (!insideRing2(ring, 0, 0, tileflowBuildingExtent, tileflowBuildingExtent)) continue;
|
|
14294
14426
|
if (!buildingBoxVisible(frame.light.matrix, [
|
|
14295
14427
|
(offset[0] - 1) * frame.metres,
|
|
14296
14428
|
-(offset[1] + tileflowBuildingExtent + 1) * frame.metres,
|
|
@@ -14302,7 +14434,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14302
14434
|
continue;
|
|
14303
14435
|
const ranges = buildingDrawRanges(
|
|
14304
14436
|
value.mesh,
|
|
14305
|
-
({ bounds: [left, top, right, bottom, height] }) =>
|
|
14437
|
+
({ bounds: [left, top, right, bottom, height] }) => insideRing2(ring, left, top, right, bottom) && buildingBoxVisible(frame.light.matrix, [
|
|
14306
14438
|
(left + offset[0]) * frame.metres,
|
|
14307
14439
|
-(bottom + offset[1]) * frame.metres,
|
|
14308
14440
|
0,
|
|
@@ -14383,7 +14515,10 @@ function createTileflowBuildings3D(options) {
|
|
|
14383
14515
|
return [ax - reach, ay - reach, Math.min(0, low), ax + reach, ay + reach, high + 0.1];
|
|
14384
14516
|
}
|
|
14385
14517
|
function modelView(model) {
|
|
14386
|
-
return {
|
|
14518
|
+
return {
|
|
14519
|
+
camera: modelCamera(model),
|
|
14520
|
+
verticalFieldOfView: map.getVerticalFieldOfView?.()
|
|
14521
|
+
};
|
|
14387
14522
|
}
|
|
14388
14523
|
function levelOf(model) {
|
|
14389
14524
|
return models.levelOf(model, modelView(model));
|
|
@@ -14505,11 +14640,17 @@ function createTileflowBuildings3D(options) {
|
|
|
14505
14640
|
const gradients = new Float32Array(28);
|
|
14506
14641
|
const powers = new Float32Array(7);
|
|
14507
14642
|
const materialColours = new Float32Array(28);
|
|
14643
|
+
const colorScales = new Float32Array(7);
|
|
14508
14644
|
const materials = new Float32Array(28);
|
|
14645
|
+
const appearance = new Float32Array(21);
|
|
14509
14646
|
for (const [role, id] of Object.entries(tileflowModelLightingRoles)) {
|
|
14510
14647
|
const from = themes[lower].modelLighting?.[role], to = themes[upper].modelLighting?.[role];
|
|
14511
14648
|
const sampledFrom = sampleModelRole(from, `${identity}:${role}`);
|
|
14512
14649
|
const sampledTo = sampleModelRole(to, `${identity}:${role}`);
|
|
14650
|
+
colorScales[id] = (from?.colorScale ?? 1) * (1 - mix2) + (to?.colorScale ?? 1) * mix2;
|
|
14651
|
+
appearance[id * 3] = (from?.shading === "map" ? 1 - mix2 : 0) + (to?.shading === "map" ? mix2 : 0);
|
|
14652
|
+
appearance[id * 3 + 1] = (from?.ambientOcclusion ?? 1) * (1 - mix2) + (to?.ambientOcclusion ?? 1) * mix2;
|
|
14653
|
+
appearance[id * 3 + 2] = (from?.partColorMix ?? 1) * (1 - mix2) + (to?.partColorMix ?? 1) * mix2;
|
|
14513
14654
|
strengths[id] = sampledFrom.strength * (1 - mix2) + sampledTo.strength * mix2;
|
|
14514
14655
|
const ca = sampledFrom.color, cb = sampledTo.color;
|
|
14515
14656
|
for (let channel = 0; channel < 3; channel++)
|
|
@@ -14529,7 +14670,16 @@ function createTileflowBuildings3D(options) {
|
|
|
14529
14670
|
gradients[id * 4 + component] = first[component] * (1 - mix2) + second[component] * mix2;
|
|
14530
14671
|
powers[id] = first[4] * (1 - mix2) + second[4] * mix2;
|
|
14531
14672
|
}
|
|
14532
|
-
const result = {
|
|
14673
|
+
const result = {
|
|
14674
|
+
strengths,
|
|
14675
|
+
colours,
|
|
14676
|
+
gradients,
|
|
14677
|
+
powers,
|
|
14678
|
+
materialColours,
|
|
14679
|
+
colorScales,
|
|
14680
|
+
materials,
|
|
14681
|
+
appearance
|
|
14682
|
+
};
|
|
14533
14683
|
if (modelLightingCache.size >= 1024)
|
|
14534
14684
|
modelLightingCache.delete(modelLightingCache.keys().next().value);
|
|
14535
14685
|
modelLightingCache.set(identity, result);
|
|
@@ -14598,7 +14748,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14598
14748
|
const bearing = map.getBearing() * Math.PI / 180;
|
|
14599
14749
|
return [Math.sin(bearing), -Math.cos(bearing)];
|
|
14600
14750
|
}
|
|
14601
|
-
function
|
|
14751
|
+
function insideRing2(ring, left, top, right, bottom) {
|
|
14602
14752
|
const radius = ring[3];
|
|
14603
14753
|
if (!(radius > 0)) return true;
|
|
14604
14754
|
const cx = ring[0];
|
|
@@ -14617,7 +14767,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14617
14767
|
const reach = margin / camera.metres + 1;
|
|
14618
14768
|
const ring = ringIn(tile.x, tile.y);
|
|
14619
14769
|
const hazed = mercator && hazeDepth < Infinity;
|
|
14620
|
-
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);
|
|
14621
14771
|
const extent5 = tileflowBuildingExtent + reach;
|
|
14622
14772
|
if (!shows([-reach, -reach, 0, extent5, extent5, tile.value.mesh.top + 0.1])) return [];
|
|
14623
14773
|
return buildingDrawRanges(
|
|
@@ -14664,20 +14814,21 @@ function createTileflowBuildings3D(options) {
|
|
|
14664
14814
|
masks = {};
|
|
14665
14815
|
const shown = visibleScale();
|
|
14666
14816
|
const entries = variant === args.shaderData.variantName && shown > 0 && ground ? drawn() : [];
|
|
14667
|
-
|
|
14817
|
+
const contactRadius = mixed2((entry) => entry.groundOcclusionRadius ?? tileflowBuildingOcclusion.ground);
|
|
14818
|
+
if (design().occlusion && contactRadius > 0 && entries.length > 0) {
|
|
14668
14819
|
const program = programs.contact;
|
|
14669
14820
|
masks.contact = contactMask.render(context, () => {
|
|
14670
14821
|
context.useProgram(program.program);
|
|
14671
14822
|
context.uniform1f(program.uniforms.u_scale, shown);
|
|
14672
14823
|
context.uniform1f(program.uniforms.u_metres, camera.metres);
|
|
14673
|
-
context.uniform1f(program.uniforms.u_band,
|
|
14824
|
+
context.uniform1f(program.uniforms.u_band, contactRadius);
|
|
14674
14825
|
context.uniform1f(
|
|
14675
14826
|
program.uniforms.u_band_strength,
|
|
14676
|
-
tileflowBuildingOcclusion.groundStrength * visibleOpacity()
|
|
14827
|
+
mixed2((entry) => entry.groundOcclusion ?? tileflowBuildingOcclusion.groundStrength) * visibleOpacity()
|
|
14677
14828
|
);
|
|
14678
14829
|
for (const tile of entries) {
|
|
14679
14830
|
const { x: x3, y: y2, value } = tile;
|
|
14680
|
-
const ranges = viewRanges(args, tile,
|
|
14831
|
+
const ranges = viewRanges(args, tile, contactRadius, true);
|
|
14681
14832
|
if (!ranges.length) continue;
|
|
14682
14833
|
const { contact } = value.gl;
|
|
14683
14834
|
project(context, program, args, x3, y2);
|
|
@@ -14885,6 +15036,12 @@ function createTileflowBuildings3D(options) {
|
|
|
14885
15036
|
context.uniform3fv(m.u_sun_light, light.sunLight);
|
|
14886
15037
|
context.uniform3fv(m.u_sky_light, light.skyLight);
|
|
14887
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
|
+
);
|
|
14888
15045
|
context.uniform1f(
|
|
14889
15046
|
m.u_ambient_occlusion,
|
|
14890
15047
|
occlusionOn ? mixed2((entry) => entry.modelOcclusion ?? 0.75) : 0
|
|
@@ -14901,7 +15058,9 @@ function createTileflowBuildings3D(options) {
|
|
|
14901
15058
|
context.uniform4fv(m.u_role_emission_gradient, emission.gradients);
|
|
14902
15059
|
context.uniform1fv(m.u_role_emission_power, emission.powers);
|
|
14903
15060
|
context.uniform4fv(m.u_role_colour, emission.materialColours);
|
|
15061
|
+
context.uniform1fv(m.u_role_color_scale, emission.colorScales);
|
|
14904
15062
|
context.uniform4fv(m.u_role_material, emission.materials);
|
|
15063
|
+
context.uniform3fv(m.u_role_appearance, emission.appearance);
|
|
14905
15064
|
const at = placed2(stand.tileX, stand.tileY);
|
|
14906
15065
|
context.uniform2f(m.u_offset, ...at.offset);
|
|
14907
15066
|
context.uniform1f(m.u_metres, at.metres);
|
|
@@ -15039,7 +15198,7 @@ function createTileflowBuildings3D(options) {
|
|
|
15039
15198
|
if (strength <= 0) continue;
|
|
15040
15199
|
const own = lighting2.colours.subarray(role * 4, role * 4 + 4);
|
|
15041
15200
|
const tint = lighting2.materialColours.subarray(role * 4, role * 4 + 4);
|
|
15042
|
-
const tintWeight = tint[3] * (1 - part[3]);
|
|
15201
|
+
const tintWeight = tint[3] * (1 - part[3] * lighting2.appearance[role * 3 + 2]);
|
|
15043
15202
|
const colour = [0, 1, 2].map(
|
|
15044
15203
|
(channel) => own[3] > 0 ? own[channel] : part[channel] * (1 - tintWeight) + tint[channel] * tintWeight
|
|
15045
15204
|
);
|
|
@@ -16452,6 +16611,7 @@ uniform float u_metres; // metres per tile unit
|
|
|
16452
16611
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
16453
16612
|
uniform float u_minimum_height; // optional visual height floor, in metres
|
|
16454
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
|
|
16455
16615
|
uniform float u_round; // how far normals turn from the facets to the round shape, by finish
|
|
16456
16616
|
|
|
16457
16617
|
float growthOf() {
|
|
@@ -16468,7 +16628,14 @@ vec2 turned(vec2 v) {
|
|
|
16468
16628
|
|
|
16469
16629
|
vec2 displaySize() {
|
|
16470
16630
|
vec2 size = a_tree_size * 0.1 * u_size_scale;
|
|
16471
|
-
|
|
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;
|
|
16472
16639
|
}
|
|
16473
16640
|
|
|
16474
16641
|
vec3 standing(float growth) {
|
|
@@ -16749,7 +16916,7 @@ function createTileflowTrees3D(options) {
|
|
|
16749
16916
|
let disposed = false;
|
|
16750
16917
|
let drawnLast = 0;
|
|
16751
16918
|
let generation = 0;
|
|
16752
|
-
let
|
|
16919
|
+
let registered2 = false;
|
|
16753
16920
|
let unregister = () => {
|
|
16754
16921
|
};
|
|
16755
16922
|
const scene = tileflowScene3D(map);
|
|
@@ -17014,7 +17181,9 @@ function createTileflowTrees3D(options) {
|
|
|
17014
17181
|
forms: tileflowTreeForms.map((form) => [
|
|
17015
17182
|
theme?.forms[form]?.heightScale ?? 1,
|
|
17016
17183
|
theme?.forms[form]?.crownScale ?? 1,
|
|
17017
|
-
|
|
17184
|
+
theme?.forms[form]?.sizeAnchor ?? 8.5,
|
|
17185
|
+
theme?.forms[form]?.crownAnchor ?? 5,
|
|
17186
|
+
theme?.forms[form]?.sizeCompression ?? 0
|
|
17018
17187
|
]),
|
|
17019
17188
|
edges: [[theme?.edges ?? 0, 0, 0]],
|
|
17020
17189
|
edgeColor: [[...rgb(theme?.edgeColor ?? "#000000") ?? [0, 0, 0]]],
|
|
@@ -17039,6 +17208,12 @@ function createTileflowTrees3D(options) {
|
|
|
17039
17208
|
[size[0] * forms[index][0], size[1] * forms[index][1]]
|
|
17040
17209
|
])
|
|
17041
17210
|
),
|
|
17211
|
+
compressions: Object.fromEntries(
|
|
17212
|
+
tileflowTreeForms.map((form, index) => [
|
|
17213
|
+
form,
|
|
17214
|
+
[forms[index][2], forms[index][3], forms[index][4]]
|
|
17215
|
+
])
|
|
17216
|
+
),
|
|
17042
17217
|
finish: (t < 0.5 ? a : b2)?.finish ?? "faceted",
|
|
17043
17218
|
edges: mixList(x3.edges, y2.edges)[0][0],
|
|
17044
17219
|
edgeColor: mixList(x3.edgeColor, y2.edgeColor)[0],
|
|
@@ -17075,17 +17250,21 @@ function createTileflowTrees3D(options) {
|
|
|
17075
17250
|
tallest = Math.max(tallest, value.placement.tallest);
|
|
17076
17251
|
}
|
|
17077
17252
|
if (!Number.isFinite(left)) return void 0;
|
|
17078
|
-
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];
|
|
17079
17258
|
return {
|
|
17080
17259
|
zoom: preferredZoom3,
|
|
17081
17260
|
tiles: [left, top, right, bottom],
|
|
17082
|
-
tallest: Math.max(tallest *
|
|
17261
|
+
tallest: Math.max(tallest * maximumScale, palette2.minimumHeight) * maximumGrowth * shown
|
|
17083
17262
|
};
|
|
17084
17263
|
},
|
|
17085
17264
|
// Camera-dependent density, detail and fading also change the trees casting shadows.
|
|
17086
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(
|
|
17087
17266
|
colours().sizes
|
|
17088
|
-
).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(";")}`,
|
|
17089
17268
|
drawDepth(context, frame) {
|
|
17090
17269
|
const program = programs.depth;
|
|
17091
17270
|
if (!program || !meshes) return;
|
|
@@ -17095,6 +17274,7 @@ function createTileflowTrees3D(options) {
|
|
|
17095
17274
|
context.uniform1f(u.u_metres, frame.metres);
|
|
17096
17275
|
context.uniformMatrix4fv(u.u_light_matrix, false, frame.light.matrix);
|
|
17097
17276
|
const sizes = colours().sizes;
|
|
17277
|
+
const compressions = colours().compressions;
|
|
17098
17278
|
const minimumHeight = colours().minimumHeight;
|
|
17099
17279
|
const camera = view();
|
|
17100
17280
|
context.uniform1f(u.u_fade, 1);
|
|
@@ -17115,12 +17295,14 @@ function createTileflowTrees3D(options) {
|
|
|
17115
17295
|
const drawing = value.gl.vaos.get(`${form}:${model}:${selection.level}`);
|
|
17116
17296
|
if (instances === 0 || !drawing) return;
|
|
17117
17297
|
context.uniform2f(u.u_size_scale, sizes[form][0], sizes[form][1] * drawing.crown);
|
|
17298
|
+
context.uniform3f(u.u_size_compression, ...compressions[form]);
|
|
17118
17299
|
context.bindVertexArray(drawing.vao);
|
|
17119
17300
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
17120
17301
|
});
|
|
17121
17302
|
const hedge = value.gl.hedge;
|
|
17122
17303
|
if (hedge) {
|
|
17123
17304
|
context.uniform1f(u.u_minimum_height, 0);
|
|
17305
|
+
context.uniform3f(u.u_size_compression, 1, 1, 0);
|
|
17124
17306
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
17125
17307
|
context.bindVertexArray(hedge.vao);
|
|
17126
17308
|
context.drawArraysInstanced(
|
|
@@ -17206,6 +17388,7 @@ function createTileflowTrees3D(options) {
|
|
|
17206
17388
|
];
|
|
17207
17389
|
context.uniform1f(u.u_minimum_height, palette2.minimumHeight);
|
|
17208
17390
|
context.uniform2f(u.u_size_scale, ...size);
|
|
17391
|
+
context.uniform3f(u.u_size_compression, ...palette2.compressions[form]);
|
|
17209
17392
|
context.bindVertexArray(drawing.vao);
|
|
17210
17393
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
17211
17394
|
count += instances;
|
|
@@ -17216,6 +17399,7 @@ function createTileflowTrees3D(options) {
|
|
|
17216
17399
|
leaves,
|
|
17217
17400
|
size,
|
|
17218
17401
|
minimumHeight: palette2.minimumHeight,
|
|
17402
|
+
compression: palette2.compressions[form],
|
|
17219
17403
|
instances,
|
|
17220
17404
|
drawing
|
|
17221
17405
|
});
|
|
@@ -17226,6 +17410,7 @@ function createTileflowTrees3D(options) {
|
|
|
17226
17410
|
const instances = value.placement.hedges.length / tileflowTreeBytes;
|
|
17227
17411
|
context.uniform3fv(u.u_leaves, palette2.hedge.flat());
|
|
17228
17412
|
context.uniform1f(u.u_minimum_height, 0);
|
|
17413
|
+
context.uniform3f(u.u_size_compression, 1, 1, 0);
|
|
17229
17414
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
17230
17415
|
context.bindVertexArray(hedge.vao);
|
|
17231
17416
|
context.drawArraysInstanced(context.TRIANGLES, 0, hedge.count, instances);
|
|
@@ -17236,6 +17421,7 @@ function createTileflowTrees3D(options) {
|
|
|
17236
17421
|
leaves: palette2.hedge,
|
|
17237
17422
|
size: [1, 1],
|
|
17238
17423
|
minimumHeight: 0,
|
|
17424
|
+
compression: [1, 1, 0],
|
|
17239
17425
|
instances,
|
|
17240
17426
|
drawing: hedge
|
|
17241
17427
|
});
|
|
@@ -17278,6 +17464,7 @@ function createTileflowTrees3D(options) {
|
|
|
17278
17464
|
);
|
|
17279
17465
|
context.uniform1f(e.u_minimum_height, draw2.minimumHeight);
|
|
17280
17466
|
context.uniform2f(e.u_size_scale, ...draw2.size);
|
|
17467
|
+
context.uniform3f(e.u_size_compression, ...draw2.compression);
|
|
17281
17468
|
context.bindVertexArray(draw2.drawing.vao);
|
|
17282
17469
|
context.drawArraysInstanced(context.TRIANGLES, 0, draw2.drawing.count, draw2.instances);
|
|
17283
17470
|
}
|
|
@@ -17466,7 +17653,7 @@ ${shaderData.define}`;
|
|
|
17466
17653
|
context.deleteBuffer(ground.vbo);
|
|
17467
17654
|
}
|
|
17468
17655
|
unregister();
|
|
17469
|
-
|
|
17656
|
+
registered2 = false;
|
|
17470
17657
|
scene.release(context);
|
|
17471
17658
|
programs = {};
|
|
17472
17659
|
meshes = void 0;
|
|
@@ -17479,8 +17666,8 @@ ${shaderData.define}`;
|
|
|
17479
17666
|
if (!isWebGL23(context)) return;
|
|
17480
17667
|
ensureTiles();
|
|
17481
17668
|
if (!programs.depth) return;
|
|
17482
|
-
if (!
|
|
17483
|
-
|
|
17669
|
+
if (!registered2) unregister = scene.register(caster);
|
|
17670
|
+
registered2 = true;
|
|
17484
17671
|
const metres = tiles[0]?.metres ?? 1;
|
|
17485
17672
|
scene.prepare(context, tileflowSceneLight(sunNow()), metres);
|
|
17486
17673
|
},
|
|
@@ -19612,6 +19799,320 @@ function createChannel() {
|
|
|
19612
19799
|
return `bridge_${Date.now().toString(36)}_${channelSequence.toString(36)}`;
|
|
19613
19800
|
}
|
|
19614
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
|
+
|
|
19615
20116
|
// src/terrain/contour-protocol.ts
|
|
19616
20117
|
var tileflowContourProtocol = "tileflow-contour";
|
|
19617
20118
|
var tileflowContourSourceLayer = "contours";
|
|
@@ -19808,12 +20309,13 @@ var registeredContourProtocols = /* @__PURE__ */ new WeakSet();
|
|
|
19808
20309
|
function registerTileflowContourProtocol(registry, options = {}) {
|
|
19809
20310
|
if (registeredContourProtocols.has(registry.addProtocol)) return;
|
|
19810
20311
|
const handler = createTileflowContourProtocolHandler(
|
|
19811
|
-
options.loadMaplibreContour ?? loadPinnedMaplibreContour
|
|
20312
|
+
options.loadMaplibreContour ?? loadPinnedMaplibreContour,
|
|
20313
|
+
options.transformDemUrl
|
|
19812
20314
|
);
|
|
19813
20315
|
registry.addProtocol(tileflowContourProtocol, handler);
|
|
19814
20316
|
registeredContourProtocols.add(registry.addProtocol);
|
|
19815
20317
|
}
|
|
19816
|
-
function createTileflowContourProtocolHandler(loadModule) {
|
|
20318
|
+
function createTileflowContourProtocolHandler(loadModule, transformDemUrl = (url) => url) {
|
|
19817
20319
|
let library;
|
|
19818
20320
|
const sources = /* @__PURE__ */ new Map();
|
|
19819
20321
|
return async (request, abortController) => {
|
|
@@ -19828,7 +20330,7 @@ function createTileflowContourProtocolHandler(loadModule) {
|
|
|
19828
20330
|
(module) => new module.DemSource({
|
|
19829
20331
|
encoding: config.encoding,
|
|
19830
20332
|
maxzoom: config.demMaxzoom,
|
|
19831
|
-
url: config.demUrl,
|
|
20333
|
+
url: transformDemUrl(config.demUrl),
|
|
19832
20334
|
// Upstream workers use a generated `blob:` URL. The main-thread manager keeps the
|
|
19833
20335
|
// protocol usable in strict-CSP applications and deterministic local captures.
|
|
19834
20336
|
worker: false
|
|
@@ -20001,6 +20503,130 @@ function createTileflowVegetation(options) {
|
|
|
20001
20503
|
};
|
|
20002
20504
|
}
|
|
20003
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
|
+
|
|
20004
20630
|
// src/map-3d-attach-browser.ts
|
|
20005
20631
|
var tileflowMap3DMetadataKeys = Object.freeze([
|
|
20006
20632
|
tileflowBuildingsMetadataKey,
|
|
@@ -20026,6 +20652,7 @@ function attachTileflowMap3D(options) {
|
|
|
20026
20652
|
const { map, load, onError, ...sceneOptions } = options;
|
|
20027
20653
|
let viewMode = options.viewMode ?? "3d";
|
|
20028
20654
|
let vegetation = options.vegetation;
|
|
20655
|
+
let adaptivePerspective = options.camera?.adaptivePerspective;
|
|
20029
20656
|
let scene;
|
|
20030
20657
|
let loading = false;
|
|
20031
20658
|
let disposed = false;
|
|
@@ -20041,7 +20668,13 @@ function attachTileflowMap3D(options) {
|
|
|
20041
20668
|
stopWatching();
|
|
20042
20669
|
load().then(({ createTileflowMap3D: createTileflowMap3D2 }) => {
|
|
20043
20670
|
if (disposed) return;
|
|
20044
|
-
scene = createTileflowMap3D2({
|
|
20671
|
+
scene = createTileflowMap3D2({
|
|
20672
|
+
...sceneOptions,
|
|
20673
|
+
map,
|
|
20674
|
+
viewMode,
|
|
20675
|
+
vegetation,
|
|
20676
|
+
camera: { adaptivePerspective }
|
|
20677
|
+
});
|
|
20045
20678
|
}).catch((error) => {
|
|
20046
20679
|
if (!disposed) onError?.(error);
|
|
20047
20680
|
});
|
|
@@ -20059,28 +20692,36 @@ function attachTileflowMap3D(options) {
|
|
|
20059
20692
|
if (disposed) return;
|
|
20060
20693
|
disposed = true;
|
|
20061
20694
|
stopWatching();
|
|
20062
|
-
map.off("remove",
|
|
20695
|
+
map.off("remove", onRemove);
|
|
20063
20696
|
scene?.dispose();
|
|
20064
20697
|
scene = void 0;
|
|
20065
20698
|
}
|
|
20699
|
+
function onRemove() {
|
|
20700
|
+
scene = void 0;
|
|
20701
|
+
dispose();
|
|
20702
|
+
}
|
|
20066
20703
|
map.on("styledata", restyle);
|
|
20067
20704
|
map.on("style.load", restyle);
|
|
20068
20705
|
map.on("idle", check);
|
|
20069
|
-
map.on("remove",
|
|
20706
|
+
map.on("remove", onRemove);
|
|
20070
20707
|
check();
|
|
20071
20708
|
return {
|
|
20072
20709
|
get scene() {
|
|
20073
20710
|
return scene;
|
|
20074
20711
|
},
|
|
20075
|
-
setViewMode(mode) {
|
|
20712
|
+
setViewMode(mode, change) {
|
|
20076
20713
|
if (mode === viewMode) return;
|
|
20077
20714
|
viewMode = mode;
|
|
20078
|
-
if (scene) void (mode === "3d" ? scene.show() : scene.hide());
|
|
20715
|
+
if (scene) void (mode === "3d" ? scene.show(change) : scene.hide(change));
|
|
20079
20716
|
},
|
|
20080
20717
|
setVegetation(visible) {
|
|
20081
20718
|
vegetation = visible;
|
|
20082
20719
|
scene?.setVegetation(visible);
|
|
20083
20720
|
},
|
|
20721
|
+
setAdaptivePerspective(enabled) {
|
|
20722
|
+
adaptivePerspective = enabled;
|
|
20723
|
+
scene?.setAdaptivePerspective(enabled);
|
|
20724
|
+
},
|
|
20084
20725
|
dispose
|
|
20085
20726
|
};
|
|
20086
20727
|
}
|
|
@@ -20090,9 +20731,15 @@ function createTileflowMap3D(options) {
|
|
|
20090
20731
|
const { map, controller, transformRequest } = options;
|
|
20091
20732
|
let viewMode = options.viewMode ?? "3d";
|
|
20092
20733
|
let vegetationVisible = options.vegetation;
|
|
20734
|
+
let adaptivePerspective = options.camera?.adaptivePerspective;
|
|
20735
|
+
const camera = createTileflowAdaptiveCamera(map);
|
|
20736
|
+
let authoredPerspective;
|
|
20093
20737
|
let buildings;
|
|
20094
20738
|
let vegetation;
|
|
20095
20739
|
let streetLights;
|
|
20740
|
+
const flatBuildings = createBuildingFlatLayers(map);
|
|
20741
|
+
let footprintLayers;
|
|
20742
|
+
let footprintZoom = 15.3;
|
|
20096
20743
|
let disposed = false;
|
|
20097
20744
|
let syncing = false;
|
|
20098
20745
|
const shared4 = {
|
|
@@ -20107,6 +20754,19 @@ function createTileflowMap3D(options) {
|
|
|
20107
20754
|
syncing = true;
|
|
20108
20755
|
try {
|
|
20109
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));
|
|
20110
20770
|
const declared = declarations ??= tileflowMap3DDeclarations({
|
|
20111
20771
|
map,
|
|
20112
20772
|
...controller ? { controller } : {}
|
|
@@ -20120,6 +20780,7 @@ function createTileflowMap3D(options) {
|
|
|
20120
20780
|
}
|
|
20121
20781
|
if (!vegetation && (declares(tileflowVegetationMetadataKey) || declares(tileflowVegetationDisplayMetadataKey)))
|
|
20122
20782
|
vegetation = createTileflowVegetation({ ...shared4, visible: vegetationVisible, viewMode });
|
|
20783
|
+
syncFlatBuildings();
|
|
20123
20784
|
if (shown && declares(tileflowStreetLightsMetadataKey))
|
|
20124
20785
|
streetLights ??= createTileflowStreetLights(shared4);
|
|
20125
20786
|
else if (streetLights) {
|
|
@@ -20130,9 +20791,22 @@ function createTileflowMap3D(options) {
|
|
|
20130
20791
|
syncing = false;
|
|
20131
20792
|
}
|
|
20132
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
|
+
}
|
|
20133
20806
|
function change(next, transition) {
|
|
20134
20807
|
if (disposed) return Promise.resolve();
|
|
20135
20808
|
viewMode = next;
|
|
20809
|
+
camera.setEnabled(next === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
|
|
20136
20810
|
vegetation?.setViewMode(next);
|
|
20137
20811
|
if (next === "3d") {
|
|
20138
20812
|
const existing = buildings;
|
|
@@ -20148,10 +20822,13 @@ function createTileflowMap3D(options) {
|
|
|
20148
20822
|
function dispose() {
|
|
20149
20823
|
if (disposed) return;
|
|
20150
20824
|
disposed = true;
|
|
20825
|
+
flatBuildings.restore();
|
|
20826
|
+
camera.dispose();
|
|
20151
20827
|
map.off("styledata", restyle);
|
|
20152
20828
|
map.off("style.load", restyle);
|
|
20153
20829
|
map.off("idle", sync);
|
|
20154
|
-
map.off("remove",
|
|
20830
|
+
map.off("remove", onRemove);
|
|
20831
|
+
map.off("move", syncFlatBuildings);
|
|
20155
20832
|
streetLights?.dispose();
|
|
20156
20833
|
buildings?.dispose();
|
|
20157
20834
|
vegetation?.dispose();
|
|
@@ -20160,13 +20837,21 @@ function createTileflowMap3D(options) {
|
|
|
20160
20837
|
vegetation = void 0;
|
|
20161
20838
|
}
|
|
20162
20839
|
function restyle() {
|
|
20840
|
+
if (syncing) return;
|
|
20841
|
+
footprintLayers = void 0;
|
|
20163
20842
|
declarations = void 0;
|
|
20843
|
+
authoredPerspective = void 0;
|
|
20164
20844
|
sync();
|
|
20165
20845
|
}
|
|
20846
|
+
function onRemove() {
|
|
20847
|
+
flatBuildings.forget();
|
|
20848
|
+
dispose();
|
|
20849
|
+
}
|
|
20166
20850
|
map.on("styledata", restyle);
|
|
20167
20851
|
map.on("style.load", restyle);
|
|
20168
20852
|
map.on("idle", sync);
|
|
20169
|
-
map.on("remove",
|
|
20853
|
+
map.on("remove", onRemove);
|
|
20854
|
+
map.on("move", syncFlatBuildings);
|
|
20170
20855
|
sync();
|
|
20171
20856
|
return {
|
|
20172
20857
|
show: (transition) => change("3d", transition),
|
|
@@ -20178,6 +20863,11 @@ function createTileflowMap3D(options) {
|
|
|
20178
20863
|
vegetationVisible = visible;
|
|
20179
20864
|
vegetation?.setVisible(visible);
|
|
20180
20865
|
},
|
|
20866
|
+
setAdaptivePerspective(enabled) {
|
|
20867
|
+
adaptivePerspective = enabled;
|
|
20868
|
+
camera.setEnabled(viewMode === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
|
|
20869
|
+
sync();
|
|
20870
|
+
},
|
|
20181
20871
|
get buildings() {
|
|
20182
20872
|
return buildings;
|
|
20183
20873
|
},
|
|
@@ -21706,6 +22396,7 @@ function isPromiseLike(value) {
|
|
|
21706
22396
|
export {
|
|
21707
22397
|
attachTileflowAtmosphere,
|
|
21708
22398
|
attachTileflowFairUseNotice,
|
|
22399
|
+
attachTileflowHorizonQueries,
|
|
21709
22400
|
attachTileflowLabelPlacement,
|
|
21710
22401
|
attachTileflowMap3D,
|
|
21711
22402
|
attachTileflowMapLifecycle,
|
|
@@ -21747,6 +22438,7 @@ export {
|
|
|
21747
22438
|
readTileflowVegetation3D,
|
|
21748
22439
|
readTileflowVegetationDisplay,
|
|
21749
22440
|
registerTileflowContourProtocol,
|
|
22441
|
+
registerTileflowPathGroundProtocol,
|
|
21750
22442
|
registerTileflowPmtilesProtocol,
|
|
21751
22443
|
registerTileflowWorldRequestBridge,
|
|
21752
22444
|
resolveTileflowSun,
|
|
@@ -21763,6 +22455,7 @@ export {
|
|
|
21763
22455
|
tileflowDepthMarkerPlacement,
|
|
21764
22456
|
tileflowFairUseNoticeMessage,
|
|
21765
22457
|
tileflowGroundBeforeId,
|
|
22458
|
+
tileflowHorizonScaleFactor,
|
|
21766
22459
|
tileflowLayerDomainMetadataKey,
|
|
21767
22460
|
tileflowLightRhythm,
|
|
21768
22461
|
tileflowLightRhythmConventions,
|