@tileflow/core 0.1.0-alpha.40 → 0.1.0-alpha.42
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 +2 -2
- package/dist/3d.js +280 -110
- package/dist/browser.d.ts +38 -19
- package/dist/browser.js +288 -117
- package/dist/build.d.ts +3 -3
- package/dist/build.js +52 -11
- package/dist/config-reference.json +1062 -669
- package/dist/{icon-composition-CcSHApUm.d.ts → icon-composition-B1A2udKb.d.ts} +66 -20
- package/dist/index.d.ts +26 -19
- package/dist/index.js +189 -62
- package/dist/{manifest-types-DnhSJjCM.d.ts → manifest-types-B0lQjabX.d.ts} +2 -0
- package/dist/manifest.d.ts +2 -2
- package/dist/native.d.ts +87 -1
- package/dist/native.js +193 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/worker/camera-tile-worker.global.js +2 -2
- package/docs/boundary-areas-and-choropleths.md +24 -11
- package/docs/buildings-3d.md +51 -21
- package/docs/cartographic-defaults.md +4 -0
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -5285,7 +5285,7 @@ function tileflowSunLightMatrix(direction, box, view = {}) {
|
|
|
5285
5285
|
];
|
|
5286
5286
|
const matrix = new Float32Array(16);
|
|
5287
5287
|
for (let row = 0; row < 4; row += 1)
|
|
5288
|
-
for (let
|
|
5288
|
+
for (let column2 = 0; column2 < 4; column2 += 1) matrix[column2 * 4 + row] = rows[row][column2];
|
|
5289
5289
|
return {
|
|
5290
5290
|
matrix,
|
|
5291
5291
|
depth: hd * 2,
|
|
@@ -6197,6 +6197,12 @@ var tileflowModelParts = Object.freeze({
|
|
|
6197
6197
|
accent: 3,
|
|
6198
6198
|
roof: 4
|
|
6199
6199
|
});
|
|
6200
|
+
var tileflowModelArchitecturalPartNames = Object.freeze(
|
|
6201
|
+
Object.keys(tileflowModelParts)
|
|
6202
|
+
);
|
|
6203
|
+
function isTileflowModelPartName(value) {
|
|
6204
|
+
return typeof value === "string" && value.length <= 32 && /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/u.test(value);
|
|
6205
|
+
}
|
|
6200
6206
|
var tileflowModelLightingRoles = Object.freeze({
|
|
6201
6207
|
unclassified: 0,
|
|
6202
6208
|
wall: 1,
|
|
@@ -6206,7 +6212,16 @@ var tileflowModelLightingRoles = Object.freeze({
|
|
|
6206
6212
|
lamp: 5,
|
|
6207
6213
|
logo: 6
|
|
6208
6214
|
});
|
|
6209
|
-
var
|
|
6215
|
+
var architecturalRoles = {
|
|
6216
|
+
surface: 1,
|
|
6217
|
+
secondary: 1,
|
|
6218
|
+
glass: 4,
|
|
6219
|
+
accent: 1,
|
|
6220
|
+
roof: 3
|
|
6221
|
+
};
|
|
6222
|
+
function tileflowModelDefaultLightingRole(part) {
|
|
6223
|
+
return Object.hasOwn(architecturalRoles, part) ? architecturalRoles[part] : tileflowModelLightingRoles.unclassified;
|
|
6224
|
+
}
|
|
6210
6225
|
var tileflowModelLimits = Object.freeze({
|
|
6211
6226
|
/** Levels of detail, nearest first. */
|
|
6212
6227
|
levels: 3,
|
|
@@ -6223,7 +6238,9 @@ var tileflowModelLimits = Object.freeze({
|
|
|
6223
6238
|
/** Models in one prepared file, as a landmark tile holds them. */
|
|
6224
6239
|
models: 512,
|
|
6225
6240
|
/** Bytes of one prepared file. */
|
|
6226
|
-
bytes: 16 * 1024 * 1024
|
|
6241
|
+
bytes: 16 * 1024 * 1024,
|
|
6242
|
+
/** Differently named parts of one level. */
|
|
6243
|
+
parts: 16
|
|
6227
6244
|
});
|
|
6228
6245
|
var tileflowModelVertexBytes = 16;
|
|
6229
6246
|
function tileflowModelFootprintInTile(footprint, placement3, tile, extent5) {
|
|
@@ -6369,6 +6386,9 @@ function readModelRoleLighting(value) {
|
|
|
6369
6386
|
...entry.colorMix === void 0 ? {} : { colorMix: bounded(entry.colorMix, 0, 1, 1) },
|
|
6370
6387
|
...entry.metallic === void 0 ? {} : { metallic: bounded(entry.metallic, 0, 1, 0) },
|
|
6371
6388
|
...entry.roughness === void 0 ? {} : { roughness: bounded(entry.roughness, 0, 1, 1) },
|
|
6389
|
+
...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
|
|
6390
|
+
...entry.ambientOcclusion === void 0 ? {} : { ambientOcclusion: bounded(entry.ambientOcclusion, 0, 1, 1) },
|
|
6391
|
+
...entry.partColorMix === void 0 ? {} : { partColorMix: bounded(entry.partColorMix, 0, 1, 1) },
|
|
6372
6392
|
...readRoleColorVariation(entry.colorVariation),
|
|
6373
6393
|
emissiveHeight: Array.isArray(gradient) && gradient.length === 5 && gradient.every(
|
|
6374
6394
|
(v2, i2) => typeof v2 === "number" && Number.isFinite(v2) && v2 <= 1 && v2 >= (i2 === 4 ? -1 : 0)
|
|
@@ -6465,6 +6485,7 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
|
6465
6485
|
windows: false,
|
|
6466
6486
|
shadows: true,
|
|
6467
6487
|
occlusion: true,
|
|
6488
|
+
groundOcclusion: 0.16,
|
|
6468
6489
|
modelOcclusion: 0.75
|
|
6469
6490
|
});
|
|
6470
6491
|
function readTileflowBuildings3D(metadata) {
|
|
@@ -6488,7 +6509,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6488
6509
|
},
|
|
6489
6510
|
color,
|
|
6490
6511
|
edges: within(value.edges, 1, 0),
|
|
6491
|
-
edgeRadius: within(value.edgeRadius, 1, defaults.edgeRadius),
|
|
6512
|
+
edgeRadius: within(value.edgeRadius, 1.5, defaults.edgeRadius),
|
|
6492
6513
|
lighting: value.lighting === "style" ? "style" : defaults.lighting,
|
|
6493
6514
|
colorVariation: within(value.colorVariation, 1, 0),
|
|
6494
6515
|
verticalGradient: value.verticalGradient !== false,
|
|
@@ -6501,6 +6522,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6501
6522
|
...readTileflowBuildingsEntrance(value.entrance),
|
|
6502
6523
|
shadows: typeof value.shadows === "boolean" ? value.shadows : defaults.shadows,
|
|
6503
6524
|
occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults.occlusion,
|
|
6525
|
+
groundOcclusion: within(value.groundOcclusion, 1, defaults.groundOcclusion),
|
|
6504
6526
|
modelOcclusion: within(value.modelOcclusion, 1, defaults.modelOcclusion),
|
|
6505
6527
|
...modelsOf(value.models),
|
|
6506
6528
|
...modelColorsOf(value.modelColors),
|
|
@@ -6547,8 +6569,8 @@ function modelsOf(value) {
|
|
|
6547
6569
|
function modelColorsOf(value) {
|
|
6548
6570
|
if (!isRecord6(value)) return {};
|
|
6549
6571
|
const colors = {};
|
|
6550
|
-
for (const part of Object.
|
|
6551
|
-
if (typeof
|
|
6572
|
+
for (const [part, color] of Object.entries(value))
|
|
6573
|
+
if (isTileflowModelPartName(part) && typeof color === "string") colors[part] = color;
|
|
6552
6574
|
return Object.keys(colors).length > 0 ? { modelColors: colors } : {};
|
|
6553
6575
|
}
|
|
6554
6576
|
function landmarksOf(value) {
|
|
@@ -7508,7 +7530,7 @@ function meshTileflowBuildings(layer, options) {
|
|
|
7508
7530
|
const scale = tileflowBuildingExtent / layer.extent;
|
|
7509
7531
|
const metresPerUnit = options.tileMetres / tileflowBuildingExtent;
|
|
7510
7532
|
const fallback = options.defaultHeight ?? 5;
|
|
7511
|
-
const edgeRadius = Number.isFinite(options.edgeRadius) ? Math.max(0, Math.min(1, options.edgeRadius)) / metresPerUnit : 0;
|
|
7533
|
+
const edgeRadius = Number.isFinite(options.edgeRadius) ? Math.max(0, Math.min(1.5, options.edgeRadius)) / metresPerUnit : 0;
|
|
7512
7534
|
const vertices = new VertexWriter();
|
|
7513
7535
|
const roofs = new IndexWriter();
|
|
7514
7536
|
const walls = new IndexWriter();
|
|
@@ -10047,7 +10069,7 @@ function browserWorker() {
|
|
|
10047
10069
|
if (typeof Worker === "undefined" || false)
|
|
10048
10070
|
return;
|
|
10049
10071
|
const url = URL.createObjectURL(
|
|
10050
|
-
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;Nn(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),Dn(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 Dn(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 Dn(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 Nn(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&&Nn(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=Dt(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],N=(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*N(...C(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...C(n[y],n[y+1]));pn($)<0&&Ht($);let D=1.01,Y=[-f*D,-d*D,f*D,-d*D,f*D,d*D,-f*D,d*D],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]<=N(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 Dt(e){let n=Nt(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 Nt(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 jr=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6}),Nr=Object.freeze([1,1,4,1,3]),Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024});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)&&Gt(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=$t(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 $t(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 Gt(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,Zt={commercial:1,active:2,destination:3},Wt={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]))},Xt={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]))},Yt=6,Jt=.5,Kt=.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=nr(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),N=Zt[String(U.building_tone??"")]??0,K=Wt[String(U.class??"")]??0,$=d.get(M)??0,D=u.length,Y=!1;for(let w of tr(B.geometry,t)){let y=w.map(or).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=rr(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Kt/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+D*1.618),L=!A&&y[0].some(S=>S<=0||S>=ue)?gn(C*7.31+I*3.17+N):v,O={base:I,top:C,jitter:L,seed:v,tone:N,group:K,use:$,cx:b,cy:x,index:D},V=y.map((S,z)=>er(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),qt(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,De=(ne-J)/me*Z;return(je*(le-ne)+De*(de-te))/ce>Jt},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],De=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],Ne=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-Ne)/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=De(he[oe]),We=De(he[oe+1]),Un=se(ye,Ne),Cn=se(Ve,He),ke=s.write(O,ye,Ne,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,Ne,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 qt(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 er(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 N=Math.tan(Math.abs(I)/2),K=Math.min(t*N,k*.2,M*.2),$=K/N;if($<1){u(p,h);continue}let[D,Y]=[-U*s,B*s],[w,y]=[p-B*K-D*$,h-U*K-Y*$],b=Math.atan2(Y,D),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 nr(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=Xt[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=Yt/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,N=C.length-2;I+1<C.length;N=I,I+=2){let K=C[N],$=C[N+1],D=C[I],Y=C[I+1];Y>g!=$>g&&d<(K-D)*(g-Y)/($-Y)+D&&(E=!E);let w=D-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 tr(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 rr(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 or(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=ir(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 ir(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,sr={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}},ar={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}},lr={spacing:30,kerb:0},ur=12,cr=18,fr=9,dr={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"},mr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},hr=new Set(["wall","wall_mounted","wall_bracket"]),pr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(cr),r=new nn(fr),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 _=yr(h),F=br(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+=gr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=ur,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,_)=>{let F=fe/m.extent,k=[];for(let N=0;N+1<p.length;N+=2)k.push(p[N]*F,p[N+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 N=2;N<k.length;N+=2){let K=k[N-2],$=k[N-1],D=k[N],Y=k[N+1],w=Math.hypot(D-K,Y-$)*M;if(w!==0){for(;C<=E+w;){let y=(C-E)/w,b=-(Y-$)/(w/M)*I,x=(D-K)/(w/M)*I,T=K+(D-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,lr,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=sr[r];if(s&&(n==="streets"||kn(t)))return s;let a=ar[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function yr(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return hr.has(t)?4.5:pr.has(t)?7.5:7}function br(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(mr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=dr[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 gr(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],wr=1.2,xr=1.5,Tr=1.3,Mr=1,kr=[.3,10],vr=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"]),Rr=new Set(["cupressus","calocedrus","thuja"]),_r=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&&vr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&Rr.has(r))return"columnar";if(i.includes("needle")||r&&_r.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]=Ar(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(Fr(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=wr/(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"?Mr:0,T=(xe(b.properties[t.height],kr)??Tr)+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,N=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...N(),variants:Array.from({length:k(y)},N)}])),$=(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 D=new Uint8Array(_.length*tn),Y=new DataView(D.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(xr*10),!0),D[b+8]=Math.round(w.turn*256)&255,D[b+9]=Math.floor(w.shade*256)&255,D[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:D,tallest:I,mapped:u,canopy:c}}function Fr(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 Ar(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 Sr=[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=Lr(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Lr(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=Br(a,o,r);return l?[l]:[]}))})}}function Br(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=Sr[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(Or(s,o))})}function Or(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 Cr=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 Cr.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,Pr=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,Pr.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
10072
|
+
new Blob(['"use strict";(()=>{var Be=new Set,ln=!1;function Pe(e,n,t=2){let i=n&&n.length,o=i?n[0]*t:e.length;Be.size&&Be.clear();let r=zn(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=xt(e,n,r,t)),e.length>80*t){a=e[0],l=e[1];let c=a,f=l;for(let d=t;d<o;d+=t){let g=e[d],m=e[d+1];g<a&&(a=g),m<l&&(l=m),g>c&&(c=g),m>f&&(f=m)}u=Math.max(c-a,f-l),u=u!==0?32767/u:0}return un(r,s,a,l,u),s}function zn(e,n,t,i,o){let r=null;if(o===Ut(e,n,t,i)>0)for(let s=n;s<t;s+=i)r=In(s/i|0,e[s],e[s+1],r);else for(let s=t-i;s>=n;s-=i)r=In(s/i|0,e[s],e[s+1],r);return r&&Oe(r,r.next)&&(Ce(r),r=r.next),r}function ge(e,n=e){let t=n===e,i=e,o;do o=!1,i!==i.next&&(Be.size===0||!Be.has(i))&&(Oe(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Ce(i),i=i.prev,o=!0):(t||i!==n)&&(i=i.next,o=!t);while(o||i!==n);return n}function un(e,n,t,i,o){o&&Ft(e,t,i,o);let r=e,s=!1;for(;e.prev!==e.next;){let a=e.prev,l=e.next;if(Q(a,e,l)<0&&(o?bt(e,t,i,o):yt(e))){n.push(a.i,e.i,l.i),Ce(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=gt(e,n),r=e,s=!0;continue}wt(e,n,t,i,o);break}}}function yt(e){let n=e.prev,t=e,i=e.next,o=n.x,r=t.x,s=i.x,a=n.y,l=t.y,u=i.y,c=Math.min(o,r,s),f=Math.min(a,l,u),d=Math.max(o,r,s),g=Math.max(a,l,u),m=i.next;for(;m!==n;){if(m.x>=c&&m.x<=d&&m.y>=f&&m.y<=g&&!(o===m.x&&a===m.y)&&Ke(o,a,r,l,s,u,m.x,m.y)&&Q(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function bt(e,n,t,i){let o=e.prev,r=e,s=e.next,a=o.x,l=r.x,u=s.x,c=o.y,f=r.y,d=s.y,g=Math.min(a,l,u),m=Math.min(c,f,d),p=Math.max(a,l,u),h=Math.max(c,f,d),_=mn(g,m,n,t,i),F=mn(p,h,n,t,i),k=e.prevZ;for(;k&&k.z>=_;){if(k.x>=g&&k.x<=p&&k.y>=m&&k.y<=h&&k!==s&&!(a===k.x&&c===k.y)&&Ke(a,c,l,f,u,d,k.x,k.y)&&Q(k.prev,k,k.next)>=0)return!1;k=k.prevZ}let M=e.nextZ;for(;M&&M.z<=F;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Dn(o,t,t.next,r,!1)&&Ue(o,r)&&Ue(r,o)&&(n.push(o.i,t.i,r.i),Ce(t),Ce(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=zn(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Nn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Nn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Nn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function En(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ue(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&_t(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function _t(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function Ft(e,n,t,i){let o=e,r=0;do o.z=mn(o.x,o.y,n,t,i),ie[r++]=o,o=o.next;while(o!==e);At(r);let s=null;for(let a=0;a<r;a++){let l=ie[a];l.prevZ=s,s&&(s.nextZ=l),s=l}s.nextZ=null,ie.fill(null,0,r),ve.fill(null,0,r)}function At(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ue(e,n)&&Ue(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Dn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Dn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ue(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function In(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ce(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ut(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ct=.7,Pt=Math.tan(Math.PI/6),Et=Math.tan(35*Math.PI/180),It=Math.tan(Math.PI/18),Ee=.65,Ie=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Nt(e);if(!l||Math.abs(pn(e))<Ct*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let _=Math.max(0,o-i),F=Gn(t.roof_height),k,M;if(F!==void 0&&F>0)M=o,k=Math.max(i+Math.min(2,_/2),o-F);else{let y=Math.min(zt(a,d),_*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[U,E]=l.centre,C=(y,b)=>{let x=(y-U)*r,T=(b-E)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},I=(y,b)=>[U+(y*u[0]+b*c[0])/r,E+(y*u[1]+b*c[1])/r],D=(y,b)=>{let x=1/0;for(let[T,A,v]of h)x=Math.min(x,T*y+A*b+v);return Math.max(0,x)},K=(y,b)=>k+B*D(...C(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...C(n[y],n[y+1]));pn($)<0&&Ht($);let N=1.01,Y=[-f*N,-d*N,f*N,-d*N,f*N,d*N,-f*N,d*N],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,A=x.length/2;for(let P=0;P<A&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%A*2],x[(P+1)%A*2+1]];T=Hn(T,W-j,Z-G,-(W-j)*Z-(Z-G)*j)}if(T.length<6||Math.abs(pn(T))<1e-6)continue;let v=[];for(let P=0;P<T.length;P+=2)v.push(...I(T[P],T[P+1]));let L=Pe(v);if(L.length===0)continue;let O=B*b[0],V=B*b[1],R=O*u[0]+V*c[0],S=O*u[1]+V*c[1],z=Math.hypot(R,S,1);w.push({ring:v,triangles:L,normal:[-R/z,-S/z]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[A,v]=C(y,b),[L,O]=C(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let S=R+1;S<h.length;S+=1){let z=(ae,H)=>(h[R][0]-h[S][0])*ae+(h[R][1]-h[S][1])*H+(h[R][2]-h[S][2]),P=z(A,v),Z=z(L,O);if(P===Z||P*Z>0)continue;let j=P/(P-Z);if(j<=1e-4||j>=1-1e-4)continue;let G=A+(L-A)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=D(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function zt(e,n){switch(e){case"skillion":return 2*n*It;case"pyramidal":return n*Et;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=Ee/(Ie*r)*f,m=(1-Ee)/((1-Ie)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),Ee/(Ie*r)*d],[...p(m),Ee+(1-Ee)/((1-Ie)*r)*(d-Ie*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Nt(e){let n=Dt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[_,F]of n){let k=_*c[0]+F*c[1],M=_*f[0]+F*f[1];d=Math.min(d,k),g=Math.max(g,k),m=Math.min(m,M),p=Math.max(p,M)}let h=(g-d)*(p-m);if(h<i){i=h;let _=(d+g)/2,F=(m+p)/2;t={centre:[_*c[0]+F*f[0],_*c[1]+F*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Dt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var $t=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Nr=Object.freeze(Object.keys($t));var Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6});var Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024,parts:16});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Zt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=Gt(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function Gt(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Zt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Wt={commercial:1,active:2,destination:3},Xt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Yt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Jt=6,Kt=.5,Qt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1.5,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=tr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let U=B.properties,E=U.hide_3d;if(E===!0||E===1||E==="1"||E==="true")continue;let C=Math.min(6e3,Jn(U.render_height)??o),I=Math.min(C,Jn(U.render_min_height)??0),D=Wt[String(U.building_tone??"")]??0,K=Xt[String(U.class??"")]??0,$=d.get(M)??0,N=u.length,Y=!1;for(let w of rr(B.geometry,t)){let y=w.map(ir).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=or(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Qt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,C+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let z=0;z<S.length;z+=2)T.bounds[0]=Math.min(T.bounds[0],S[z]-1),T.bounds[1]=Math.min(T.bounds[1],S[z+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[z]+1),T.bounds[3]=Math.max(T.bounds[3],S[z+1]+1);Y=!0,f=Math.max(f,C);let A=Number.isSafeInteger(B.id),v=gn(A?B.id*.0731:b*.0731+x*.19137+N*1.618),L=!A&&y[0].some(S=>S<=0||S>=ue)?gn(C*7.31+I*3.17+D):v,O={base:I,top:C,jitter:L,seed:v,tone:D,group:K,use:$,cx:b,cy:x,index:N},V=y.map((S,z)=>nr(S,z,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],U,I,C,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),er(R,O,s,a)):qt(y,O,s,a);for(let[S,z]of y.entries()){let P=qe(z)>0,Z=S===0?P?-1:1:P?1:-1,j=z.length/2,G=H=>{let J=(H%j+j)%j;return[z[J*2],z[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,Ne=(ne-J)/me*Z;return(je*(le-ne)+Ne*(de-te))/ce>Kt},se=(H,J)=>R?R.heightAt(H,J):C,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],Ne=oe=>{let _e=ce[0]+(je[0]-ce[0])*oe,Fe=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(_e,Fe)||1;return[_e/ye,Fe/ye]},he=[0,...R?R.breaks(J,re,ne,te):[],1];for(let oe=0;oe+1<he.length;oe+=1){let _e=oe===0,Fe=oe+2===he.length,ye=J+(ne-J)*he[oe],De=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],Ae=Math.hypot(Ve-ye,He-De)/ue*n.tileMetres,$e=(_e&&W(H)?1:0)|(Fe&&W(H+1)?2:0)|(S>0?4:0),Ge=(_e&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+Ae,Ze=Ne(he[oe]),We=Ne(he[oe+1]),Un=se(ye,De),Cn=se(Ve,He),ke=s.write(O,ye,De,0,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),s.write(O,ye,De,1,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),l.push(ke,ke+1,ke+2,ke+1,ke+3,ke+2),ae=an}}}T.roofsCount=a.length-T.roofsFrom,T.wallsCount=l.length-T.wallsFrom,c.push(T)}Y&&u.push(U)}if(s.count===0)return;let g=new Uint32Array(a.length+l.length),m=[],p=0,h=a.length,_=a.values(),F=l.values();c.sort((M,B)=>M.cell-B.cell);let k=-1;for(let M of c){M.cell!==k&&(k=M.cell,m.push({bounds:[...M.bounds],roofsFrom:p,roofsCount:0,wallsFrom:h,wallsCount:0}));let B=m.at(-1);for(let U=0;U<5;U+=1)B.bounds[U]=U<2?Math.min(B.bounds[U],M.bounds[U]):Math.max(B.bounds[U],M.bounds[U]);g.set(_.subarray(M.roofsFrom,M.roofsFrom+M.roofsCount),p),g.set(F.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function er(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function nr(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[_,F]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(_-p,F-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,_,F)){u(p,h);continue}let[B,U]=[(p-g)/k,(h-m)/k],[E,C]=[(_-p)/M,(F-h)/M],I=Math.atan2(B*C-U*E,B*E+U*C);if(I*s>=-.08||Math.abs(I)>Math.PI*.85){u(p,h);continue}let D=Math.tan(Math.abs(I)/2),K=Math.min(t*D,k*.2,M*.2),$=K/D;if($<1){u(p,h);continue}let[N,Y]=[-U*s,B*s],[w,y]=[p-B*K-N*$,h-U*K-Y*$],b=Math.atan2(Y,N),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(I)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let A=b+I*T/x,v=[Math.cos(A),Math.sin(A)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let _=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(_).set(new Uint8Array(this.#e)),this.#e=_,this.#n=new DataView(_)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function tr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Yt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Jt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let F of r){let[k,M,B,U]=F.box;if(d<k-o||d>B+o||g<M-o||g>U+o)continue;let E=!1;for(let C of F.rings)for(let I=0,D=C.length-2;I+1<C.length;D=I,I+=2){let K=C[D],$=C[D+1],N=C[I],Y=C[I+1];Y>g!=$>g&&d<(K-N)*(g-Y)/($-Y)+N&&(E=!E);let w=N-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=F.index)}if(E){m=F.index;break}}let _=m??p;_!==void 0&&t.set(_,Math.max(t.get(_)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function rr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function or(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function ir(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=sr(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function sr(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let _=(t.length<=4?[...t].map(F=>F+F).join(""):t).match(/../gu).map(F=>Number.parseInt(F,16));return[_[0],_[1],_[2],_.length>3?_[3]/255:1]}let i=/^(rgba?|hsla?)\\(([^)]+)\\)$/u.exec(n);if(!i)return null;let o=i[2].split(/[\\s,/]+/u).filter(Boolean);if(o.length<3||o.length>4)return null;let r=o[3]===void 0?1:en(o[3],1);if(i[1].startsWith("rgb")){let[h,_,F]=o.slice(0,3).map(k=>en(k,255));return[h,_,F,r].some(k=>k===null)?null:[h,_,F,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,ar={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},lr={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},ur={spacing:30,kerb:0},cr=12,fr=18,dr=9,mr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},hr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},pr=new Set(["wall","wall_mounted","wall_bracket"]),yr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(fr),r=new nn(dr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let _=br(h),F=gr(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,_*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let U=0;U+1<B.length;U+=2){let E=B[U]*m,C=B[U+1]*m;if(!rt(E,C))continue;i.write(E,C,_,M,!0,F);let I=ot(E,C,n.tileMetres);o.add(...I),r.add(...I)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=wr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=cr,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,_)=>{let F=fe/m.extent,k=[];for(let D=0;D+1<p.length;D+=2)k.push(p[D]*F,p[D+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,U=Rn(k[0]*.013+k[1]*.029+_)*h.spacing,E=0,C=U,I=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let D=2;D<k.length;D+=2){let K=k[D-2],$=k[D-1],N=k[D],Y=k[D+1],w=Math.hypot(N-K,Y-$)*M;if(w!==0){for(;C<=E+w;){let y=(C-E)/w,b=-(Y-$)/(w/M)*I,x=(N-K)/(w/M)*I,T=K+(N-K)*y+b*B,A=$+(Y-$)*y+x*B;if(C+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(I=-I),!rt(T,A))continue;let v=ot(T,A,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,A,7,15,!1))}E+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,ur,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=ar[r];if(s&&(n==="streets"||kn(t)))return s;let a=lr[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function br(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return pr.has(t)?4.5:yr.has(t)?7.5:7}function gr(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(hr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=mr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function wr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],_n=[1,25],xr=1.2,Tr=1.5,Mr=1.3,kr=1,vr=[.3,10],Rr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),_r=new Set(["cupressus","calocedrus","thuja"]),Fr=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=Fn(e[t.genus])??Fn(e[t.species])??(o.endsWith("aceae")?void 0:Fn(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&Rr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&_r.has(r))return"columnar";if(i.includes("needle")||r&&Fr.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function Fn(e){return typeof e!="string"?void 0:e.trim().split(/\\s+/u)[0]?.toLowerCase()||void 0}function ct(e,n){let t={...ut,...n.fields},i=n.unknownForms??Sn,o=n.regions??[],{tile:r,tileMetres:s}=n,a=s/2**(15-r.z)/512,l=[],u=0,c=0,f=(w,y)=>{if(o.length===0)return i;let[b,x]=Sr(r,w/q,y/q);for(let T of o){let[A,v,L,O]=T.bounds;if(x>=v&&x<=O&&(A<=L?b>=A&&b<=L:b>=A||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],A=An(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=An(T.height,ee(y,1))),v===void 0&&(v=L/A),L===void 0&&(L=v*A),{height:Te(v,on),crown:Te(L,_n)}},g=(w,y,b,x,T,A)=>{let v=ze(r.x*q+w,r.y*q+y,7),L=b===void 0?sn(f(w,y),ee(v,3)):b==="broadleaf"?sn(Ar(f(w,y)),ee(v,3)):b,O=x===void 0&&T===void 0&&A!==void 0?d(L,v,An(st[L].height,Te(A/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...O,turn:ee(v,4),shade:ee(v,5),form:Me.indexOf(L),rank:Math.floor(ee(v,6)*rn),seed:ee(v,7),canopy:0}),u+=1},m=e.trees;if(m){let w=q/m.extent;for(let y of m.features){if(y.type!=="Point")continue;let b=y.properties,x=lt(b,t),T=xe(b[t.height],on),A=xe(b[t.diameterCrown],_n),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,A,v)}}}let p=e.trees;if(p){let w=q/p.extent,y=(n.rowSpacing??8)/(s/p.extent);for(let b of p.features){if(b.type!=="LineString")continue;let x=b.properties,T=lt(x,t),A=xe(x[t.height],on),v=xe(x[t.diameterCrown],_n);for(let L of b.geometry){let O=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[S,z,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],j=Math.hypot(P-S,Z-z);for(;O<=V+j;){let G=j>0?(O-V)/j:0,W=S+(P-S)*G,se=z+(Z-z)*G;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,A,v,void 0),O+=y}V+=j}}}}let h=e.canopy;if(h){let w=q/h.extent;for(let y of h.features){if(y.type!=="Point")continue;let b=y.properties,x=Te(Math.floor(Number(b[t.canopyRank]??8)),[0,rn-1]),T=Math.max(4,Number(b[t.canopyClearance]??8))*a,A=Number(b[t.canopyCover]??30),v=A>=60?3:A>=30?2:1;for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let S=V*w,z=R*w,P=ze(r.x*q+S,r.y*q+z,11),Z=f(S,z),j=xe(b[t.canopyHeight],on),G=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(G*.5,T-G/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let H=ze(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee(H,1):W,ne=S+Math.cos(J)*re/(s/q),te=z+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee(H,3)),de=G*(.85+ee(H,2)*.3),me=j===void 0?void 0:j*(.85+ee(H,6)*.25),ce=d(le,H,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee(H,4),shade:ee(H,5),form:Me.indexOf(le),rank:x,seed:ee(H,7),canopy:1}),c+=1}}}}let _=[],F=e.hedges;if(F){let w=q/F.extent,y=xr/(s/F.extent);for(let b of F.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?kr:0,T=(xe(b.properties[t.height],vr)??Mr)+x;for(let A of b.geometry){let v=y/2,L=0;for(let O=0;O+3<A.length;O+=2){let[V,R,S,z]=[A[O],A[O+1],A[O+2],A[O+3]],P=Math.hypot(S-V,z-R),Z=(Math.atan2(R-z,S-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let j=P>0?(v-L)/P:0,G=V+(S-V)*j,W=R+(z-R)*j;if(G>=0&&W>=0&&G<F.extent&&W<F.extent){let se=ze(r.x*q+G*w,r.y*q+W*w,17);_.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),U=l.map((w,y)=>y);U.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let E=new Uint8Array(l.length*tn),C=new DataView(E.buffer),I=0,D=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...D(),variants:Array.from({length:k(y)},D)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};U.forEach((w,y)=>{let b=l[w],x=y*tn;C.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),C.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),C.setUint16(x+4,Math.round(b.height*10),!0),C.setUint16(x+6,Math.round(b.crown*10),!0),E[x+8]=Math.floor(b.turn*256)&255,E[x+9]=Math.floor(b.shade*256)&255,E[x+10]=b.form,E[x+11]=b.rank,E[x+12]=Math.floor(b.seed*256)&255,E[x+13]=b.canopy,E[x+14]=B[w],I=Math.max(I,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let N=new Uint8Array(_.length*tn),Y=new DataView(N.buffer);return _.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(Tr*10),!0),N[b+8]=Math.round(w.turn*256)&255,N[b+9]=Math.floor(w.shade*256)&255,N[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:N,tallest:I,mapped:u,canopy:c}}function Ar(e){let n={round:e.round??0,open:e.open??0,tall:e.tall??0};return n.round+n.open+n.tall>0?n:Sn}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(Sn,n);let i=n*t;for(let o of Me){let r=Math.max(0,e[o]??0);if(i<r)return o;i-=r}return"round"}function xe(e,n){let t=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):NaN;return Number.isFinite(t)&&t>0?Te(t,n):void 0}function Te(e,[n,t]){return Math.min(t,Math.max(n,e))}function An([e,n],t){return e+(n-e)*t}function Sr(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function ze(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return ze(e,n,20973)/4294967296}var Lr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Br(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Br(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Cr(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Or(a,o,r);return l?[l]:[]}))})}}function Or(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Lr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Ur(s,o))})}function Ur(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Cr(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Pr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Pr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,Er=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,Er.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
10051
10073
|
);
|
|
10052
10074
|
try {
|
|
10053
10075
|
return new Worker(url, { name: "tileflow-tiles" });
|
|
@@ -11037,7 +11059,7 @@ var protocolPrefix = `${tileflowPmtilesProtocol}://`;
|
|
|
11037
11059
|
function registerTileflowPmtilesProtocol(registry, options = {}) {
|
|
11038
11060
|
if (registeredPmtilesProtocols.has(registry.addProtocol)) return;
|
|
11039
11061
|
const maximumDirectoryDepth = normalizeMaximumDirectoryDepth(options.maximumDirectoryDepth);
|
|
11040
|
-
const protocol2 = new TileflowPmtilesProtocol(maximumDirectoryDepth);
|
|
11062
|
+
const protocol2 = new TileflowPmtilesProtocol(maximumDirectoryDepth, options.transformArchiveUrl);
|
|
11041
11063
|
sharedProtocol ??= protocol2;
|
|
11042
11064
|
registry.addProtocol(tileflowPmtilesProtocol, protocol2.tile);
|
|
11043
11065
|
registeredPmtilesProtocols.add(registry.addProtocol);
|
|
@@ -11059,10 +11081,12 @@ function isTileflowPmtilesUrl(url) {
|
|
|
11059
11081
|
return url.startsWith(protocolPrefix);
|
|
11060
11082
|
}
|
|
11061
11083
|
var TileflowPmtilesProtocol = class {
|
|
11062
|
-
constructor(maximumDirectoryDepth) {
|
|
11084
|
+
constructor(maximumDirectoryDepth, transformArchiveUrl = (url) => url) {
|
|
11063
11085
|
this.maximumDirectoryDepth = maximumDirectoryDepth;
|
|
11086
|
+
this.transformArchiveUrl = transformArchiveUrl;
|
|
11064
11087
|
}
|
|
11065
11088
|
maximumDirectoryDepth;
|
|
11089
|
+
transformArchiveUrl;
|
|
11066
11090
|
#archives = /* @__PURE__ */ new Map();
|
|
11067
11091
|
tilev4 = async (request, abortController) => {
|
|
11068
11092
|
if (request.type === "json") {
|
|
@@ -11095,7 +11119,10 @@ var TileflowPmtilesProtocol = class {
|
|
|
11095
11119
|
#archive(target) {
|
|
11096
11120
|
let archive = this.#archives.get(target);
|
|
11097
11121
|
if (!archive) {
|
|
11098
|
-
archive = new TileflowPmtilesArchive(
|
|
11122
|
+
archive = new TileflowPmtilesArchive(
|
|
11123
|
+
this.transformArchiveUrl(target),
|
|
11124
|
+
this.maximumDirectoryDepth
|
|
11125
|
+
);
|
|
11099
11126
|
this.#archives.set(target, archive);
|
|
11100
11127
|
}
|
|
11101
11128
|
return archive;
|
|
@@ -11239,7 +11266,7 @@ function tileflowTilesForBounds(bounds, zoom) {
|
|
|
11239
11266
|
throw new RangeError("Tile bounds are [west, south, east, north] in degrees.");
|
|
11240
11267
|
const z2 = Math.max(0, Math.round(zoom));
|
|
11241
11268
|
const count = 2 ** z2;
|
|
11242
|
-
const
|
|
11269
|
+
const column2 = (lng) => Math.min(count - 1, Math.max(0, Math.floor((lng + 180) / 360 * count)));
|
|
11243
11270
|
const row = (lat) => {
|
|
11244
11271
|
const clamped = Math.min(earthLatitudeLimit, Math.max(-earthLatitudeLimit, lat));
|
|
11245
11272
|
const radians2 = clamped * Math.PI / 180;
|
|
@@ -11247,8 +11274,8 @@ function tileflowTilesForBounds(bounds, zoom) {
|
|
|
11247
11274
|
return Math.min(count - 1, Math.max(0, Math.floor(y2 * count)));
|
|
11248
11275
|
};
|
|
11249
11276
|
const columns2 = [];
|
|
11250
|
-
const first =
|
|
11251
|
-
const last =
|
|
11277
|
+
const first = column2(west);
|
|
11278
|
+
const last = column2(east);
|
|
11252
11279
|
if (west <= east) for (let x3 = first; x3 <= last; x3 += 1) columns2.push(x3);
|
|
11253
11280
|
else {
|
|
11254
11281
|
for (let x3 = first; x3 < count; x3 += 1) columns2.push(x3);
|
|
@@ -12004,6 +12031,7 @@ function checkTileflowModelSurface(surface, vertices, indices) {
|
|
|
12004
12031
|
const value = attributes4[i2];
|
|
12005
12032
|
if (!Number.isFinite(value) || Math.abs(value) > 65536) fail("unbounded vertex attributes");
|
|
12006
12033
|
if (i2 % 8 >= 4 && (value < 0 || value > 1)) fail("vertex RGBA must be zero to one");
|
|
12034
|
+
if ((i2 % 8 === 2 || i2 % 8 === 3) && (value < 0 || value > 1)) fail("UV1 must be zero to one");
|
|
12007
12035
|
}
|
|
12008
12036
|
if (!Array.isArray(materials) || materials.length < 1 || materials.length > tileflowModelSurfaceLimits.materials)
|
|
12009
12037
|
fail("material count exceeds the limit");
|
|
@@ -12085,7 +12113,7 @@ function checkTileflowModelSurface(surface, vertices, indices) {
|
|
|
12085
12113
|
fail("emitter count exceeds the limit");
|
|
12086
12114
|
for (const emitter of emitters) {
|
|
12087
12115
|
if (!emitter || typeof emitter !== "object") fail("invalid area emitter");
|
|
12088
|
-
if (!tuple(emitter.start, 3, -2e3, 2e3) || !tuple(emitter.end, 3, -2e3, 2e3) || !number(emitter.height, 0.01, 1e3) || emitter.depth !== void 0 && !number(emitter.depth, 0, 100) || !Object.hasOwn(tileflowModelLightingRoles, emitter.role) || !
|
|
12116
|
+
if (!tuple(emitter.start, 3, -2e3, 2e3) || !tuple(emitter.end, 3, -2e3, 2e3) || !number(emitter.height, 0.01, 1e3) || emitter.depth !== void 0 && !number(emitter.depth, 0, 100) || !Object.hasOwn(tileflowModelLightingRoles, emitter.role) || !isTileflowModelPartName(emitter.part))
|
|
12089
12117
|
fail("invalid area emitter");
|
|
12090
12118
|
if (Math.hypot(emitter.end[0] - emitter.start[0], emitter.end[1] - emitter.start[1]) < 1e-3 || Math.abs(emitter.end[2] - emitter.start[2]) > 0.01)
|
|
12091
12119
|
fail("an area emitter needs a horizontal lower edge");
|
|
@@ -12126,7 +12154,6 @@ function tileflowModelImageSize(bytes, mimeType) {
|
|
|
12126
12154
|
var levelNames = ["near", "mid", "far"];
|
|
12127
12155
|
var meshopt = "EXT_meshopt_compression";
|
|
12128
12156
|
var quantisation = "KHR_mesh_quantization";
|
|
12129
|
-
var partCount = Object.keys(tileflowModelParts).length;
|
|
12130
12157
|
var roleCount = Object.keys(tileflowModelLightingRoles).length;
|
|
12131
12158
|
var modelId2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
12132
12159
|
var [glbMagic, jsonChunk, binChunk] = [1179937895, 1313821514, 5130562];
|
|
@@ -12163,7 +12190,7 @@ async function decodeTileflowModels(buffer, decompressor) {
|
|
|
12163
12190
|
if (source !== 0 || byteStride !== stride || count * byteStride !== length)
|
|
12164
12191
|
throw new Error();
|
|
12165
12192
|
if (filter !== void 0 && filter !== "NONE") throw new Error();
|
|
12166
|
-
if (mode !== (
|
|
12193
|
+
if (mode !== (view.target === 34963 ? "TRIANGLES" : "ATTRIBUTES")) throw new Error();
|
|
12167
12194
|
out = new Uint8Array(length);
|
|
12168
12195
|
decoder.decodeGltfBuffer(out, count, byteStride, slice(bin, byteOffset, byteLength), mode);
|
|
12169
12196
|
} else {
|
|
@@ -12202,6 +12229,7 @@ async function decodeTileflowModels(buffer, decompressor) {
|
|
|
12202
12229
|
}
|
|
12203
12230
|
levels.push({
|
|
12204
12231
|
vertices: level.vertices,
|
|
12232
|
+
partNames: level.partNames,
|
|
12205
12233
|
indices: level.indices,
|
|
12206
12234
|
centre: level.centre,
|
|
12207
12235
|
step: level.step,
|
|
@@ -12290,6 +12318,9 @@ function readLevelNode(json, node, name, viewBytes, hasLightingRoles) {
|
|
|
12290
12318
|
const indexCount = index?.count;
|
|
12291
12319
|
if (!width || index.type !== "SCALAR" || (index.byteOffset ?? 0) !== 0 || !Number.isInteger(indexCount) || indexCount < 3 || indexCount % 3 !== 0 || indexCount / 3 > tileflowModelLimits.triangles)
|
|
12292
12320
|
throw new Error();
|
|
12321
|
+
const own = node.extras?.tileflow?.parts;
|
|
12322
|
+
const partNames = own === void 0 ? tileflowModelArchitecturalPartNames : own;
|
|
12323
|
+
if (!isPartNames(partNames)) throw new Error();
|
|
12293
12324
|
const vertices = viewBytes(
|
|
12294
12325
|
position.bufferView,
|
|
12295
12326
|
tileflowModelVertexBytes,
|
|
@@ -12298,8 +12329,8 @@ function readLevelNode(json, node, name, viewBytes, hasLightingRoles) {
|
|
|
12298
12329
|
for (let vertex = 0; vertex < count; vertex += 1) {
|
|
12299
12330
|
const at = vertex * tileflowModelVertexBytes;
|
|
12300
12331
|
const part = vertices[at + 12];
|
|
12301
|
-
if (part >=
|
|
12302
|
-
if (!hasLightingRoles) vertices[at + 15] =
|
|
12332
|
+
if (part >= partNames.length) throw new Error();
|
|
12333
|
+
if (!hasLightingRoles) vertices[at + 15] = tileflowModelDefaultLightingRole(partNames[part]);
|
|
12303
12334
|
else if (vertices[at + 15] >= roleCount) throw new Error();
|
|
12304
12335
|
}
|
|
12305
12336
|
const indexBytes = viewBytes(index.bufferView, width, indexCount * width);
|
|
@@ -12308,18 +12339,30 @@ function readLevelNode(json, node, name, viewBytes, hasLightingRoles) {
|
|
|
12308
12339
|
const physical = node.extras?.tileflow?.surface;
|
|
12309
12340
|
let surface;
|
|
12310
12341
|
if (physical !== void 0) {
|
|
12311
|
-
if (physical?.version !==
|
|
12342
|
+
if (physical?.version !== 2 || !Array.isArray(physical.attributes) || physical.attributes.length !== 3)
|
|
12312
12343
|
throw new Error();
|
|
12313
|
-
const uv =
|
|
12314
|
-
|
|
12315
|
-
if (!uv || !colour || (uv.byteOffset ?? 0) !== 0 || colour.byteOffset !== 16 || uv.bufferView !== colour.bufferView || [uv, colour].some(
|
|
12316
|
-
(value) => value.componentType !== 5126 || value.type !== "VEC4" || value.count !== count || value.normalized === true
|
|
12317
|
-
))
|
|
12344
|
+
const [uv, lightmap, colour] = physical.attributes.map(accessor);
|
|
12345
|
+
if (!uv || !lightmap || !colour || (uv.byteOffset ?? 0) !== 0 || colour.byteOffset !== 8 || (lightmap.byteOffset ?? 0) !== 0 || uv.bufferView !== colour.bufferView || uv.bufferView === lightmap.bufferView || uv.componentType !== 5126 || uv.type !== "VEC2" || colour.componentType !== 5126 || colour.type !== "VEC4" || lightmap.componentType !== 5123 || lightmap.type !== "VEC2" || lightmap.normalized !== true || [uv, lightmap, colour].some((value) => value.count !== count))
|
|
12318
12346
|
throw new Error();
|
|
12319
|
-
const
|
|
12347
|
+
const restBytes = viewBytes(uv.bufferView, 24, count * 24);
|
|
12348
|
+
const lightmapBytes = viewBytes(lightmap.bufferView, 4, count * 4);
|
|
12349
|
+
const rest = new Float32Array(
|
|
12350
|
+
restBytes.buffer.slice(restBytes.byteOffset, restBytes.byteOffset + count * 24)
|
|
12351
|
+
);
|
|
12352
|
+
const second = new Uint16Array(
|
|
12353
|
+
lightmapBytes.buffer.slice(lightmapBytes.byteOffset, lightmapBytes.byteOffset + count * 4)
|
|
12354
|
+
);
|
|
12355
|
+
const attributes4 = new Float32Array(count * 8);
|
|
12356
|
+
for (let vertex = 0; vertex < count; vertex++) {
|
|
12357
|
+
const at = vertex * 8;
|
|
12358
|
+
attributes4[at] = rest[vertex * 6];
|
|
12359
|
+
attributes4[at + 1] = rest[vertex * 6 + 1];
|
|
12360
|
+
attributes4[at + 2] = second[vertex * 2] / 65535;
|
|
12361
|
+
attributes4[at + 3] = second[vertex * 2 + 1] / 65535;
|
|
12362
|
+
attributes4.set(rest.subarray(vertex * 6 + 2, vertex * 6 + 6), at + 4);
|
|
12363
|
+
}
|
|
12320
12364
|
if (!Array.isArray(physical.textures) || physical.textures.length > 32) throw new Error();
|
|
12321
|
-
|
|
12322
|
-
attributes: new Float32Array(attributeBytes.buffer, attributeBytes.byteOffset, count * 8),
|
|
12365
|
+
const read = {
|
|
12323
12366
|
materials: physical.materials,
|
|
12324
12367
|
ranges: physical.ranges,
|
|
12325
12368
|
textures: physical.textures.map((texture) => {
|
|
@@ -12330,10 +12373,12 @@ function readLevelNode(json, node, name, viewBytes, hasLightingRoles) {
|
|
|
12330
12373
|
}),
|
|
12331
12374
|
...physical.emitters === void 0 ? {} : { emitters: physical.emitters }
|
|
12332
12375
|
};
|
|
12333
|
-
checkTileflowModelSurface(
|
|
12376
|
+
checkTileflowModelSurface({ ...read, attributes: attributes4 }, count, indexCount);
|
|
12377
|
+
surface = { ...read, uv: column(attributes4, 0), rgba: column(attributes4, 4) };
|
|
12334
12378
|
}
|
|
12335
12379
|
return {
|
|
12336
12380
|
vertices,
|
|
12381
|
+
partNames: [...partNames],
|
|
12337
12382
|
indices,
|
|
12338
12383
|
centre: [centre[0], centre[1], centre[2]],
|
|
12339
12384
|
step: scale[0],
|
|
@@ -12342,6 +12387,21 @@ function readLevelNode(json, node, name, viewBytes, hasLightingRoles) {
|
|
|
12342
12387
|
surface
|
|
12343
12388
|
};
|
|
12344
12389
|
}
|
|
12390
|
+
function column(attributes4, first) {
|
|
12391
|
+
const out = attributes4.slice(first, first + 4);
|
|
12392
|
+
for (let at = 8 + first; at < attributes4.length; at += 8)
|
|
12393
|
+
for (let component = 0; component < 4; component += 1)
|
|
12394
|
+
if (attributes4[at + component] !== out[component]) {
|
|
12395
|
+
const all = new Float32Array(attributes4.length / 2);
|
|
12396
|
+
for (let vertex = 0; vertex < all.length / 4; vertex += 1)
|
|
12397
|
+
all.set(attributes4.subarray(vertex * 8 + first, vertex * 8 + first + 4), vertex * 4);
|
|
12398
|
+
return all;
|
|
12399
|
+
}
|
|
12400
|
+
return out;
|
|
12401
|
+
}
|
|
12402
|
+
function isPartNames(names) {
|
|
12403
|
+
return Array.isArray(names) && names.length >= 1 && names.length <= tileflowModelLimits.parts && names.every(isTileflowModelPartName) && new Set(names).size === names.length;
|
|
12404
|
+
}
|
|
12345
12405
|
function readGlb(bytes) {
|
|
12346
12406
|
if (bytes.byteLength < 20 || bytes.byteLength > tileflowModelLimits.bytes) throw new Error();
|
|
12347
12407
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
@@ -12375,6 +12435,42 @@ function placed(at) {
|
|
|
12375
12435
|
return typeof longitude === "number" && typeof latitude === "number" && longitude >= -180 && longitude <= 180 && latitude >= -85 && latitude <= 85;
|
|
12376
12436
|
}
|
|
12377
12437
|
|
|
12438
|
+
// src/models-3d-levels.ts
|
|
12439
|
+
var tileflowModelLevelDistances = Object.freeze({
|
|
12440
|
+
tall: Object.freeze([2e3, 5e3]),
|
|
12441
|
+
wide: Object.freeze([1500, 3500]),
|
|
12442
|
+
small: Object.freeze([1e3, 2500])
|
|
12443
|
+
});
|
|
12444
|
+
var tileflowModelLevelHysteresis = 1.1;
|
|
12445
|
+
function tileflowModelLevelDistancesOf(bounds) {
|
|
12446
|
+
const [minX, minY, , maxX, maxY, maxZ] = bounds;
|
|
12447
|
+
if (maxZ >= 30) return tileflowModelLevelDistances.tall;
|
|
12448
|
+
if (Math.max(maxX - minX, maxY - minY) >= 80) return tileflowModelLevelDistances.wide;
|
|
12449
|
+
return tileflowModelLevelDistances.small;
|
|
12450
|
+
}
|
|
12451
|
+
function tileflowModelCameraDistance(model, view) {
|
|
12452
|
+
const [minX, minY, minZ, maxX, maxY, maxZ] = model.bounds;
|
|
12453
|
+
const [x3, y2, z2] = [(minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2];
|
|
12454
|
+
const turn = model.heading * Math.PI / 180;
|
|
12455
|
+
const east = x3 * Math.cos(turn) + y2 * Math.sin(turn);
|
|
12456
|
+
const north = -x3 * Math.sin(turn) + y2 * Math.cos(turn);
|
|
12457
|
+
return Math.hypot(view.camera[0] - east, view.camera[1] - north, view.camera[2] - z2);
|
|
12458
|
+
}
|
|
12459
|
+
function tileflowModelLevel(model, view, previous) {
|
|
12460
|
+
const thresholds = tileflowModelLevelDistancesOf(model.bounds);
|
|
12461
|
+
const last = Math.max(0, Math.min(model.levels, thresholds.length + 1) - 1);
|
|
12462
|
+
const distance = tileflowModelCameraDistance(model, view);
|
|
12463
|
+
if (!Number.isFinite(distance)) return 0;
|
|
12464
|
+
const margin = previous === void 0 ? 1 : tileflowModelLevelHysteresis;
|
|
12465
|
+
let level = Math.max(0, Math.min(last, previous ?? 0));
|
|
12466
|
+
while (level < last && distance >= thresholds[level] * margin) level += 1;
|
|
12467
|
+
while (level > 0 && distance < thresholds[level - 1] / margin) level -= 1;
|
|
12468
|
+
return level;
|
|
12469
|
+
}
|
|
12470
|
+
function tileflowModelShadowLevel(level, levels) {
|
|
12471
|
+
return Math.max(0, Math.min(level + 1, levels - 1));
|
|
12472
|
+
}
|
|
12473
|
+
|
|
12378
12474
|
// src/models-3d-landmarks.ts
|
|
12379
12475
|
var tileflowLandmarkTileZoom = 14;
|
|
12380
12476
|
var tileflowLandmarkRegionZoom = 6;
|
|
@@ -12408,8 +12504,7 @@ function validFootprint(footprint) {
|
|
|
12408
12504
|
}
|
|
12409
12505
|
function readTileflowLandmarkRegion(json) {
|
|
12410
12506
|
if (!isRecord9(json)) return void 0;
|
|
12411
|
-
|
|
12412
|
-
if (!named && json.format !== "tileflow-landmark-region-v1") return void 0;
|
|
12507
|
+
if (json.format !== "tileflow-landmark-region-v2") return void 0;
|
|
12413
12508
|
const region = json.region;
|
|
12414
12509
|
if (json.zoom !== tileflowLandmarkTileZoom || !Array.isArray(region) || region.length !== 3 || region[0] !== tileflowLandmarkRegionZoom || !Array.isArray(json.tiles))
|
|
12415
12510
|
return void 0;
|
|
@@ -12417,17 +12512,13 @@ function readTileflowLandmarkRegion(json) {
|
|
|
12417
12512
|
if (!Number.isInteger(x3) || !Number.isInteger(y2)) return void 0;
|
|
12418
12513
|
const tiles = [];
|
|
12419
12514
|
for (const tile of json.tiles) {
|
|
12420
|
-
if (!Array.isArray(tile) || tile.length !==
|
|
12515
|
+
if (!Array.isArray(tile) || tile.length !== 4) return void 0;
|
|
12421
12516
|
const [tx, ty, hash4, listed] = tile;
|
|
12422
12517
|
if (!Number.isInteger(tx) || !Number.isInteger(ty) || typeof hash4 !== "string")
|
|
12423
12518
|
return void 0;
|
|
12424
12519
|
if (!sha256.test(hash4)) return void 0;
|
|
12425
12520
|
const [rx, ry] = tileflowLandmarkRegionOf([tx, ty]);
|
|
12426
12521
|
if (rx !== x3 || ry !== y2) return void 0;
|
|
12427
|
-
if (!named) {
|
|
12428
|
-
tiles.push([tx, ty, hash4]);
|
|
12429
|
-
continue;
|
|
12430
|
-
}
|
|
12431
12522
|
const landmarks = readLandmarks(listed, tx, ty);
|
|
12432
12523
|
if (!landmarks) return void 0;
|
|
12433
12524
|
tiles.push([tx, ty, hash4, landmarks]);
|
|
@@ -12656,10 +12747,11 @@ uniform vec3 u_emissive;
|
|
|
12656
12747
|
uniform float u_normal_strength;
|
|
12657
12748
|
uniform float u_occlusion_strength;
|
|
12658
12749
|
uniform bool u_unlit;
|
|
12659
|
-
|
|
12660
|
-
uniform
|
|
12750
|
+
// Each part's colour, and how far the map's colour replaces the material's own.
|
|
12751
|
+
uniform vec4 u_parts[${tileflowModelLimits.parts}];
|
|
12661
12752
|
uniform vec4 u_role_colour[7];
|
|
12662
12753
|
uniform vec4 u_role_material[7]; // metallic, roughness, their respective override weights
|
|
12754
|
+
uniform vec3 u_role_appearance[7]; // map shading share, ambient occlusion multiplier, part colour share
|
|
12663
12755
|
|
|
12664
12756
|
vec3 fromSRGB(vec3 colour) {
|
|
12665
12757
|
return pow(max(colour, vec3(0.0)), vec3(2.2));
|
|
@@ -12689,7 +12781,8 @@ vec3 materialNormal(vec3 normal) {
|
|
|
12689
12781
|
vec3 materialBase(int role) {
|
|
12690
12782
|
vec4 own = u_role_colour[role];
|
|
12691
12783
|
vec3 factor = mix(u_base_colour.rgb, fromSRGB(own.rgb), own.a);
|
|
12692
|
-
|
|
12784
|
+
vec4 part = u_parts[v_part];
|
|
12785
|
+
factor = mix(factor, fromSRGB(part.rgb), part.a * u_role_appearance[role].z);
|
|
12693
12786
|
return factor * v_rgba.rgb * fromSRGB(materialTexture(0).rgb);
|
|
12694
12787
|
}
|
|
12695
12788
|
|
|
@@ -12726,7 +12819,7 @@ vec3 physicalLight(vec3 base, vec3 normal, float lit, int role) {
|
|
|
12726
12819
|
float exposure = (0.96 + 0.04 * clamp(normal.z, -1.0, 1.0)) *
|
|
12727
12820
|
(1.0 - 0.3 * min(directional, 1.0) * max(-dot(normal, u_sun_dir), 0.0));
|
|
12728
12821
|
float ao = mix(1.0, v_light * mix(1.0, materialTexture(3).r, u_occlusion_strength),
|
|
12729
|
-
u_ambient_occlusion);
|
|
12822
|
+
u_ambient_occlusion * u_role_appearance[role].y);
|
|
12730
12823
|
vec3 ambient = (diffuse + reflectedSky) * u_sky_light * exposure * ao;
|
|
12731
12824
|
return ambient + min(direct, vec3(1.0));
|
|
12732
12825
|
}
|
|
@@ -12739,10 +12832,7 @@ var tileflowModelAttributes = [
|
|
|
12739
12832
|
["a_paint", 3, "UNSIGNED_BYTE", false, 12],
|
|
12740
12833
|
["a_lighting_role", 1, "UNSIGNED_BYTE", false, 15]
|
|
12741
12834
|
];
|
|
12742
|
-
var tileflowModelSurfaceAttributes = [
|
|
12743
|
-
["a_uv", 4, "FLOAT", false, 0],
|
|
12744
|
-
["a_rgba", 4, "FLOAT", false, 16]
|
|
12745
|
-
];
|
|
12835
|
+
var tileflowModelSurfaceAttributes = ["a_uv", "a_rgba"];
|
|
12746
12836
|
var attributes2 = `
|
|
12747
12837
|
in vec3 a_position; // whole steps from the level's centre, in glTF's axes
|
|
12748
12838
|
in vec3 a_normal; // in glTF's axes
|
|
@@ -12813,7 +12903,7 @@ ${attributes2}
|
|
|
12813
12903
|
uniform mat4 u_light_matrix;
|
|
12814
12904
|
uniform vec3 u_shadow_dir;
|
|
12815
12905
|
uniform float u_normal_offset;
|
|
12816
|
-
uniform
|
|
12906
|
+
uniform vec4 u_parts[${tileflowModelLimits.parts}];
|
|
12817
12907
|
uniform vec2 u_model_height;
|
|
12818
12908
|
${placement}
|
|
12819
12909
|
out vec3 v_colour;
|
|
@@ -12840,11 +12930,11 @@ void main() {
|
|
|
12840
12930
|
v_shadow = shadow.xyz * 0.5 + 0.5;
|
|
12841
12931
|
v_normal = normal;
|
|
12842
12932
|
int part = int(a_paint.x + 0.5);
|
|
12843
|
-
v_part = clamp(part, 0,
|
|
12933
|
+
v_part = clamp(part, 0, ${tileflowModelLimits.parts - 1});
|
|
12844
12934
|
v_uv = a_uv;
|
|
12845
12935
|
v_rgba = a_rgba;
|
|
12846
12936
|
v_position = vec3(m.xy, z);
|
|
12847
|
-
vec3 colour =
|
|
12937
|
+
vec3 colour = u_parts[v_part].rgb;
|
|
12848
12938
|
// A material lighter or darker than mid-grey makes its part lighter or darker.
|
|
12849
12939
|
v_colour = colour * (0.55 + 0.45 * (a_paint.y / 255.0) * 2.0);
|
|
12850
12940
|
v_light = a_paint.z / 255.0;
|
|
@@ -12877,10 +12967,10 @@ ${modelPhysicalLighting}
|
|
|
12877
12967
|
|
|
12878
12968
|
// The buildings' light: a sunlit roof keeps its colour, a face turned to a low sun glows, and shade
|
|
12879
12969
|
// takes the sky's colour; a face that looks down sees little sky.
|
|
12880
|
-
vec3 shade(vec3 normal, float lit) {
|
|
12970
|
+
vec3 shade(vec3 normal, float lit, float occlusion) {
|
|
12881
12971
|
float facing = dot(normal, u_sun_dir);
|
|
12882
12972
|
vec3 sky = u_sky_light * mix(mix(0.8, 0.5, u_night), 1.0, max(normal.z, -0.4));
|
|
12883
|
-
sky *= mix(1.0, v_light, u_ambient_occlusion);
|
|
12973
|
+
sky *= mix(1.0, v_light, u_ambient_occlusion * occlusion);
|
|
12884
12974
|
vec3 light = sky + u_sun_light * max(facing, 0.0) * (1.0 - u_shadow * (1.0 - lit));
|
|
12885
12975
|
vec3 roof = u_sky_light + u_sun_light * max(u_sun_dir.z, 0.0);
|
|
12886
12976
|
return min(pow(light / max(roof, vec3(1e-4)), vec3(1.0 / 2.2)), vec3(1.7));
|
|
@@ -12901,14 +12991,22 @@ void main() {
|
|
|
12901
12991
|
if (u_physical) {
|
|
12902
12992
|
float alpha = materialAlpha();
|
|
12903
12993
|
vec3 base = materialBase(role);
|
|
12904
|
-
|
|
12994
|
+
float mapShare = u_role_appearance[role].x;
|
|
12995
|
+
vec3 radiance;
|
|
12996
|
+
if (mapShare >= 1.0) {
|
|
12997
|
+
radiance = base * fromSRGB(shade(normal, lit, u_role_appearance[role].y));
|
|
12998
|
+
} else {
|
|
12999
|
+
radiance = physicalLight(base, normal, lit, role);
|
|
13000
|
+
if (mapShare > 0.0)
|
|
13001
|
+
radiance = mix(radiance, base * fromSRGB(shade(normal, lit, u_role_appearance[role].y)), mapShare);
|
|
13002
|
+
}
|
|
12905
13003
|
radiance += u_emissive * fromSRGB(materialTexture(4).rgb);
|
|
12906
13004
|
vec4 own = u_role_emission_colour[role];
|
|
12907
13005
|
radiance = mix(radiance, mix(base, fromSRGB(own.rgb), own.a), emission);
|
|
12908
13006
|
fragColor = vec4(hazed(toSRGB(radiance)), alpha * u_opacity);
|
|
12909
13007
|
return;
|
|
12910
13008
|
}
|
|
12911
|
-
vec3 colour = v_colour * shade(normal, lit);
|
|
13009
|
+
vec3 colour = v_colour * shade(normal, lit, u_role_appearance[role].y);
|
|
12912
13010
|
if (emission > 0.0) {
|
|
12913
13011
|
vec4 own = u_role_emission_colour[role];
|
|
12914
13012
|
vec3 target = mix(v_colour, own.rgb, own.a);
|
|
@@ -12958,21 +13056,39 @@ function closeModelImages(images) {
|
|
|
12958
13056
|
}
|
|
12959
13057
|
function uploadModelSurface(gl, level, images) {
|
|
12960
13058
|
if (!level.surface) return void 0;
|
|
12961
|
-
const
|
|
12962
|
-
|
|
12963
|
-
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
13059
|
+
const streams = [level.surface.uv, level.surface.rgba];
|
|
13060
|
+
const shared4 = streams.map((stream) => stream.length === 4 ? stream : void 0);
|
|
13061
|
+
const bytes = streams.reduce(
|
|
13062
|
+
(sum2, stream) => sum2 + (stream.length > 4 ? stream.byteLength : 0),
|
|
13063
|
+
0
|
|
13064
|
+
);
|
|
13065
|
+
let vbo;
|
|
13066
|
+
if (bytes > 0) {
|
|
13067
|
+
vbo = gl.createBuffer();
|
|
13068
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
13069
|
+
gl.bufferData(gl.ARRAY_BUFFER, bytes, gl.STATIC_DRAW);
|
|
13070
|
+
}
|
|
13071
|
+
let offset = 0;
|
|
13072
|
+
for (const [index, stream] of streams.entries()) {
|
|
12968
13073
|
const location = index + tileflowModelAttributes.length;
|
|
13074
|
+
if (stream.length === 4) {
|
|
13075
|
+
gl.disableVertexAttribArray(location);
|
|
13076
|
+
continue;
|
|
13077
|
+
}
|
|
13078
|
+
gl.bufferSubData(gl.ARRAY_BUFFER, offset, stream);
|
|
12969
13079
|
gl.enableVertexAttribArray(location);
|
|
12970
|
-
gl.vertexAttribPointer(location,
|
|
13080
|
+
gl.vertexAttribPointer(location, 4, gl.FLOAT, false, 16, offset);
|
|
13081
|
+
offset += stream.byteLength;
|
|
12971
13082
|
}
|
|
12972
13083
|
const flip = gl.getParameter(gl.UNPACK_FLIP_Y_WEBGL);
|
|
12973
13084
|
const premultiply = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL);
|
|
12974
13085
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
12975
13086
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
13087
|
+
const coloured = /* @__PURE__ */ new Set();
|
|
13088
|
+
for (const material of level.surface.materials)
|
|
13089
|
+
for (const channel of tileflowModelTextureChannels)
|
|
13090
|
+
if (channel !== "occlusionTexture" && material[channel])
|
|
13091
|
+
coloured.add(material[channel].texture);
|
|
12976
13092
|
try {
|
|
12977
13093
|
const textures = level.surface.textures.map((source, index) => {
|
|
12978
13094
|
const texture = gl.createTexture();
|
|
@@ -12982,7 +13098,9 @@ function uploadModelSurface(gl, level, images) {
|
|
|
12982
13098
|
const min = source.minFilter ?? gl.LINEAR_MIPMAP_LINEAR;
|
|
12983
13099
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, min);
|
|
12984
13100
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, source.magFilter ?? gl.LINEAR);
|
|
12985
|
-
|
|
13101
|
+
if (coloured.has(index))
|
|
13102
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE, images[index]);
|
|
13103
|
+
else gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, gl.RED, gl.UNSIGNED_BYTE, images[index]);
|
|
12986
13104
|
if (min >= gl.NEAREST_MIPMAP_NEAREST) gl.generateMipmap(gl.TEXTURE_2D);
|
|
12987
13105
|
return texture;
|
|
12988
13106
|
});
|
|
@@ -13003,7 +13121,8 @@ function uploadModelSurface(gl, level, images) {
|
|
|
13003
13121
|
);
|
|
13004
13122
|
}
|
|
13005
13123
|
return {
|
|
13006
|
-
vbo,
|
|
13124
|
+
...vbo ? { vbo } : {},
|
|
13125
|
+
shared: shared4,
|
|
13007
13126
|
textures,
|
|
13008
13127
|
centres,
|
|
13009
13128
|
emitters: (level.surface.emitters ?? []).map(modelEmitterGeometry)
|
|
@@ -13013,6 +13132,10 @@ function uploadModelSurface(gl, level, images) {
|
|
|
13013
13132
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiply);
|
|
13014
13133
|
}
|
|
13015
13134
|
}
|
|
13135
|
+
function bindModelSurfaceShared(gl, buffers) {
|
|
13136
|
+
for (const [index, value] of buffers.shared.entries())
|
|
13137
|
+
if (value) gl.vertexAttrib4fv(index + tileflowModelAttributes.length, value);
|
|
13138
|
+
}
|
|
13016
13139
|
function bindModelMaterial(gl, uniforms, material, buffers, blank) {
|
|
13017
13140
|
const at = (name) => uniforms[name] ?? null;
|
|
13018
13141
|
gl.uniform1i(at("u_physical"), material ? 1 : 0);
|
|
@@ -13059,7 +13182,6 @@ var keptModels = 12;
|
|
|
13059
13182
|
var keptLandmarkTiles = 9;
|
|
13060
13183
|
var keptLandmarkRegions = 8;
|
|
13061
13184
|
var reachTiles = 1;
|
|
13062
|
-
var levelDistances = [900, 2600];
|
|
13063
13185
|
var retryAfter = 3e4;
|
|
13064
13186
|
var tilesetRetryAfter = 3e5;
|
|
13065
13187
|
var landmarkHold = 3e3;
|
|
@@ -13187,7 +13309,7 @@ function createTileflowPlacedModels(options) {
|
|
|
13187
13309
|
const tiles = new Map(
|
|
13188
13310
|
region.tiles.map((tile) => [
|
|
13189
13311
|
`${tile[0]}/${tile[1]}`,
|
|
13190
|
-
{ hash: tile[2],
|
|
13312
|
+
{ hash: tile[2], landmarks: tile[3] }
|
|
13191
13313
|
])
|
|
13192
13314
|
);
|
|
13193
13315
|
regions.set(regionKey, { tiles, used: performance.now() });
|
|
@@ -13430,7 +13552,7 @@ function createTileflowPlacedModels(options) {
|
|
|
13430
13552
|
else {
|
|
13431
13553
|
const failing = (tileFailed.get(hash4) ?? 0) > now;
|
|
13432
13554
|
if (!tileLoading.has(hash4) && !failing) loadTile(hash4);
|
|
13433
|
-
if (
|
|
13555
|
+
if (!failing) onTheirWay.set(hash4, named.landmarks);
|
|
13434
13556
|
}
|
|
13435
13557
|
}
|
|
13436
13558
|
if (nearHashes.size !== wantedTiles.size || [...nearHashes].some((hash4) => !wantedTiles.has(hash4))) {
|
|
@@ -13476,6 +13598,7 @@ function createTileflowPlacedModels(options) {
|
|
|
13476
13598
|
for (const entry of next)
|
|
13477
13599
|
if (!before.delete(entry)) {
|
|
13478
13600
|
entry.standingSince = now;
|
|
13601
|
+
entry.level = void 0;
|
|
13479
13602
|
changed.push(...reach(entry));
|
|
13480
13603
|
}
|
|
13481
13604
|
for (const entry of before.keys()) {
|
|
@@ -13586,13 +13709,17 @@ function createTileflowPlacedModels(options) {
|
|
|
13586
13709
|
version2 += 1;
|
|
13587
13710
|
}
|
|
13588
13711
|
},
|
|
13589
|
-
levelOf(model,
|
|
13590
|
-
|
|
13591
|
-
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13595
|
-
|
|
13712
|
+
levelOf(model, view) {
|
|
13713
|
+
model.level = tileflowModelLevel(
|
|
13714
|
+
{
|
|
13715
|
+
bounds: model.model.bounds,
|
|
13716
|
+
heading: model.placement.heading,
|
|
13717
|
+
levels: model.model.levels.length
|
|
13718
|
+
},
|
|
13719
|
+
view,
|
|
13720
|
+
model.level
|
|
13721
|
+
);
|
|
13722
|
+
return model.level;
|
|
13596
13723
|
},
|
|
13597
13724
|
key: () => String(version2),
|
|
13598
13725
|
release(context) {
|
|
@@ -13651,7 +13778,7 @@ function releaseBuffers(context, entry) {
|
|
|
13651
13778
|
context.deleteBuffer(level.vbo);
|
|
13652
13779
|
context.deleteBuffer(level.ibo);
|
|
13653
13780
|
if (level.surface) {
|
|
13654
|
-
context.deleteBuffer(level.surface.vbo);
|
|
13781
|
+
if (level.surface.vbo) context.deleteBuffer(level.surface.vbo);
|
|
13655
13782
|
for (const texture of level.surface.textures) context.deleteTexture(texture);
|
|
13656
13783
|
}
|
|
13657
13784
|
}
|
|
@@ -13671,7 +13798,7 @@ function sampleModelRole(profile, identity) {
|
|
|
13671
13798
|
};
|
|
13672
13799
|
const variation = profile?.colorVariation;
|
|
13673
13800
|
let color = profile?.color ? tileflowColourChannels(profile.color)?.slice(0, 3) : void 0;
|
|
13674
|
-
if (variation) {
|
|
13801
|
+
if (variation && !color) {
|
|
13675
13802
|
const hsl = [variation.hue, variation.saturation, variation.lightness].map(
|
|
13676
13803
|
([low, high], channel) => low + (high - low) * random(channel + 1)
|
|
13677
13804
|
);
|
|
@@ -14170,7 +14297,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14170
14297
|
}
|
|
14171
14298
|
return { zoom: camera.zoom, tiles: [left, top, right, bottom], tallest };
|
|
14172
14299
|
},
|
|
14173
|
-
key: () => `buildings:${visibleScale().toFixed(4)}:${modelScale().toFixed(4)}:${generation}:${models.key()}:${programs.depth ? 1 : 0}`,
|
|
14300
|
+
key: () => `buildings:${visibleScale().toFixed(4)}:${modelScale().toFixed(4)}:${generation}:${models.key()}:${programs.depth ? 1 : 0}:${(modelScale() > 0 ? modelsDrawn() : []).map(shadowLevelOf).join("")}`,
|
|
14174
14301
|
drawDepth(context, frame) {
|
|
14175
14302
|
const program = programs.depth;
|
|
14176
14303
|
if (!program) return;
|
|
@@ -14224,15 +14351,22 @@ function createTileflowBuildings3D(options) {
|
|
|
14224
14351
|
const modelsShown = modelScale();
|
|
14225
14352
|
context.uniform1f(modelDepth.uniforms.u_scale, modelsShown);
|
|
14226
14353
|
context.uniform1f(modelDepth.uniforms.u_metres, frame.metres);
|
|
14227
|
-
const centre = map.getCenter();
|
|
14228
14354
|
for (const model of modelsShown > 0 ? modelsDrawn() : []) {
|
|
14229
14355
|
const stand = standOf(model);
|
|
14356
|
+
const offset = frame.offsetOf({ x: stand.tileX, y: stand.tileY }, camera.zoom);
|
|
14357
|
+
const [left, top, low, right, bottom, high] = modelBox(model, stand);
|
|
14358
|
+
if (!buildingBoxVisible(frame.light.matrix, [
|
|
14359
|
+
(left + offset[0]) * frame.metres,
|
|
14360
|
+
-(bottom + offset[1]) * frame.metres,
|
|
14361
|
+
low,
|
|
14362
|
+
(right + offset[0]) * frame.metres,
|
|
14363
|
+
-(top + offset[1]) * frame.metres,
|
|
14364
|
+
high
|
|
14365
|
+
]))
|
|
14366
|
+
continue;
|
|
14230
14367
|
setPlacement(context, modelDepth, model, stand);
|
|
14231
|
-
context.uniform2f(
|
|
14232
|
-
|
|
14233
|
-
...frame.offsetOf({ x: stand.tileX, y: stand.tileY }, camera.zoom)
|
|
14234
|
-
);
|
|
14235
|
-
drawModel(context, modelDepth, model, models.levelOf(model, centre), "depth");
|
|
14368
|
+
context.uniform2f(modelDepth.uniforms.u_offset, ...offset);
|
|
14369
|
+
drawModel(context, modelDepth, model, shadowLevelOf(model), "depth");
|
|
14236
14370
|
}
|
|
14237
14371
|
}
|
|
14238
14372
|
};
|
|
@@ -14261,6 +14395,21 @@ function createTileflowBuildings3D(options) {
|
|
|
14261
14395
|
reach: Math.hypot(Math.max(-minX, maxX), Math.max(-minY, maxY)) / tileMetres
|
|
14262
14396
|
};
|
|
14263
14397
|
}
|
|
14398
|
+
function modelBox(model, stand) {
|
|
14399
|
+
const reach = stand.reach * tileflowBuildingExtent;
|
|
14400
|
+
const [ax, ay] = stand.anchor;
|
|
14401
|
+
const [, , low, , , high] = model.model.bounds;
|
|
14402
|
+
return [ax - reach, ay - reach, Math.min(0, low), ax + reach, ay + reach, high + 0.1];
|
|
14403
|
+
}
|
|
14404
|
+
function modelView(model) {
|
|
14405
|
+
return { camera: modelCamera(model) };
|
|
14406
|
+
}
|
|
14407
|
+
function levelOf(model) {
|
|
14408
|
+
return models.levelOf(model, modelView(model));
|
|
14409
|
+
}
|
|
14410
|
+
function shadowLevelOf(model) {
|
|
14411
|
+
return tileflowModelShadowLevel(levelOf(model), model.model.levels.length);
|
|
14412
|
+
}
|
|
14264
14413
|
function setPlacement(context, program, model, stand) {
|
|
14265
14414
|
const u = program.uniforms;
|
|
14266
14415
|
const turn = model.placement.heading * Math.PI / 180;
|
|
@@ -14279,6 +14428,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14279
14428
|
model.model.bounds[5] - model.model.bounds[2]
|
|
14280
14429
|
);
|
|
14281
14430
|
context.bindVertexArray(buffers.vao);
|
|
14431
|
+
if (buffers.surface) bindModelSurfaceShared(context, buffers.surface);
|
|
14282
14432
|
if (!mesh.surface) {
|
|
14283
14433
|
if (pass === "blend") return;
|
|
14284
14434
|
bindModelMaterial(context, program.uniforms, void 0, void 0, blank);
|
|
@@ -14321,23 +14471,27 @@ function createTileflowBuildings3D(options) {
|
|
|
14321
14471
|
function partColoursNow() {
|
|
14322
14472
|
const { themes, lower, upper, mix: mix2 } = designsOnScreen();
|
|
14323
14473
|
const base = themeColour();
|
|
14324
|
-
const
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14474
|
+
const named = (index, part) => {
|
|
14475
|
+
const colours = themes[index].modelColors;
|
|
14476
|
+
return colours && Object.hasOwn(colours, part) ? rgbOf2(colours[part]) : void 0;
|
|
14477
|
+
};
|
|
14478
|
+
return (part) => {
|
|
14479
|
+
const derived = Object.hasOwn(derivedParts, part) ? derivedParts[part](base) : base;
|
|
14480
|
+
const below = named(lower, part);
|
|
14481
|
+
const above = named(upper, part);
|
|
14482
|
+
const [from, to] = [below ?? derived, above ?? derived];
|
|
14483
|
+
return [
|
|
14484
|
+
from[0] + (to[0] - from[0]) * mix2,
|
|
14485
|
+
from[1] + (to[1] - from[1]) * mix2,
|
|
14486
|
+
from[2] + (to[2] - from[2]) * mix2,
|
|
14487
|
+
(below ? 1 - mix2 : 0) + (above ? mix2 : 0)
|
|
14488
|
+
];
|
|
14489
|
+
};
|
|
14333
14490
|
}
|
|
14334
|
-
function
|
|
14335
|
-
const
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
(part) => (themes[lower].modelColors?.[part] ? 1 - mix2 : 0) + (themes[upper].modelColors?.[part] ? mix2 : 0)
|
|
14339
|
-
)
|
|
14340
|
-
);
|
|
14491
|
+
function partPalette(names, colourOf2) {
|
|
14492
|
+
const out = new Float32Array(tileflowModelLimits.parts * 4);
|
|
14493
|
+
for (const [index, name] of names.entries()) out.set(colourOf2(name), index * 4);
|
|
14494
|
+
return out;
|
|
14341
14495
|
}
|
|
14342
14496
|
function modelCamera(model) {
|
|
14343
14497
|
const zoom = map.getZoom();
|
|
@@ -14371,10 +14525,14 @@ function createTileflowBuildings3D(options) {
|
|
|
14371
14525
|
const powers = new Float32Array(7);
|
|
14372
14526
|
const materialColours = new Float32Array(28);
|
|
14373
14527
|
const materials = new Float32Array(28);
|
|
14528
|
+
const appearance = new Float32Array(21);
|
|
14374
14529
|
for (const [role, id] of Object.entries(tileflowModelLightingRoles)) {
|
|
14375
14530
|
const from = themes[lower].modelLighting?.[role], to = themes[upper].modelLighting?.[role];
|
|
14376
14531
|
const sampledFrom = sampleModelRole(from, `${identity}:${role}`);
|
|
14377
14532
|
const sampledTo = sampleModelRole(to, `${identity}:${role}`);
|
|
14533
|
+
appearance[id * 3] = (from?.shading === "map" ? 1 - mix2 : 0) + (to?.shading === "map" ? mix2 : 0);
|
|
14534
|
+
appearance[id * 3 + 1] = (from?.ambientOcclusion ?? 1) * (1 - mix2) + (to?.ambientOcclusion ?? 1) * mix2;
|
|
14535
|
+
appearance[id * 3 + 2] = (from?.partColorMix ?? 1) * (1 - mix2) + (to?.partColorMix ?? 1) * mix2;
|
|
14378
14536
|
strengths[id] = sampledFrom.strength * (1 - mix2) + sampledTo.strength * mix2;
|
|
14379
14537
|
const ca = sampledFrom.color, cb = sampledTo.color;
|
|
14380
14538
|
for (let channel = 0; channel < 3; channel++)
|
|
@@ -14394,7 +14552,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14394
14552
|
gradients[id * 4 + component] = first[component] * (1 - mix2) + second[component] * mix2;
|
|
14395
14553
|
powers[id] = first[4] * (1 - mix2) + second[4] * mix2;
|
|
14396
14554
|
}
|
|
14397
|
-
const result = { strengths, colours, gradients, powers, materialColours, materials };
|
|
14555
|
+
const result = { strengths, colours, gradients, powers, materialColours, materials, appearance };
|
|
14398
14556
|
if (modelLightingCache.size >= 1024)
|
|
14399
14557
|
modelLightingCache.delete(modelLightingCache.keys().next().value);
|
|
14400
14558
|
modelLightingCache.set(identity, result);
|
|
@@ -14431,6 +14589,11 @@ function createTileflowBuildings3D(options) {
|
|
|
14431
14589
|
context.uniform4fv(uniforms.u_projection_clipping_plane, data.clippingPlane);
|
|
14432
14590
|
context.uniform1f(uniforms.u_projection_transition, data.projectionTransition);
|
|
14433
14591
|
context.uniformMatrix4fv(uniforms.u_projection_fallback_matrix, false, data.fallbackMatrix);
|
|
14592
|
+
return data;
|
|
14593
|
+
}
|
|
14594
|
+
function modelInView(args, data, box) {
|
|
14595
|
+
if (args.shaderData.variantName !== "mercator") return true;
|
|
14596
|
+
return buildingBoxVisible(data.mainMatrix, box) && (hazeDepth === Infinity || buildingBoxDepth(data.mainMatrix, box) < hazeDepth);
|
|
14434
14597
|
}
|
|
14435
14598
|
function reachNow() {
|
|
14436
14599
|
const ring = camera.ring();
|
|
@@ -14533,7 +14696,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14533
14696
|
context.uniform1f(program.uniforms.u_band, tileflowBuildingOcclusion.ground);
|
|
14534
14697
|
context.uniform1f(
|
|
14535
14698
|
program.uniforms.u_band_strength,
|
|
14536
|
-
tileflowBuildingOcclusion.groundStrength * visibleOpacity()
|
|
14699
|
+
mixed2((entry) => entry.groundOcclusion ?? tileflowBuildingOcclusion.groundStrength) * visibleOpacity()
|
|
14537
14700
|
);
|
|
14538
14701
|
for (const tile of entries) {
|
|
14539
14702
|
const { x: x3, y: y2, value } = tile;
|
|
@@ -14749,11 +14912,12 @@ function createTileflowBuildings3D(options) {
|
|
|
14749
14912
|
m.u_ambient_occlusion,
|
|
14750
14913
|
occlusionOn ? mixed2((entry) => entry.modelOcclusion ?? 0.75) : 0
|
|
14751
14914
|
);
|
|
14752
|
-
|
|
14753
|
-
context.uniform1fv(m.u_part_mix, partMixNow());
|
|
14915
|
+
const colourOf2 = partColoursNow();
|
|
14754
14916
|
scene.bindShadow(context, m, light.strength);
|
|
14755
|
-
const centre = map.getCenter();
|
|
14756
14917
|
for (const entry of list) {
|
|
14918
|
+
const stand = standOf(entry);
|
|
14919
|
+
const data = project(context, model, args, stand.tileX, stand.tileY);
|
|
14920
|
+
if (!modelInView(args, data, modelBox(entry, stand))) continue;
|
|
14757
14921
|
const emission = modelLightingNow(entry.model.id);
|
|
14758
14922
|
context.uniform1fv(m.u_role_emission, emission.strengths);
|
|
14759
14923
|
context.uniform4fv(m.u_role_emission_colour, emission.colours);
|
|
@@ -14761,8 +14925,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14761
14925
|
context.uniform1fv(m.u_role_emission_power, emission.powers);
|
|
14762
14926
|
context.uniform4fv(m.u_role_colour, emission.materialColours);
|
|
14763
14927
|
context.uniform4fv(m.u_role_material, emission.materials);
|
|
14764
|
-
|
|
14765
|
-
project(context, model, args, stand.tileX, stand.tileY);
|
|
14928
|
+
context.uniform3fv(m.u_role_appearance, emission.appearance);
|
|
14766
14929
|
const at = placed2(stand.tileX, stand.tileY);
|
|
14767
14930
|
context.uniform2f(m.u_offset, ...at.offset);
|
|
14768
14931
|
context.uniform1f(m.u_metres, at.metres);
|
|
@@ -14772,7 +14935,12 @@ function createTileflowBuildings3D(options) {
|
|
|
14772
14935
|
m.u_opacity,
|
|
14773
14936
|
pass === "blend" ? modelsOpacity * appearanceOf(entry, now) : 1
|
|
14774
14937
|
);
|
|
14775
|
-
|
|
14938
|
+
const level = levelOf(entry);
|
|
14939
|
+
context.uniform4fv(
|
|
14940
|
+
m.u_parts,
|
|
14941
|
+
partPalette(entry.model.levels[level].partNames, colourOf2)
|
|
14942
|
+
);
|
|
14943
|
+
drawModel(context, model, entry, level, pass);
|
|
14776
14944
|
}
|
|
14777
14945
|
}
|
|
14778
14946
|
}
|
|
@@ -14874,10 +15042,9 @@ function createTileflowBuildings3D(options) {
|
|
|
14874
15042
|
);
|
|
14875
15043
|
context.bindVertexArray(null);
|
|
14876
15044
|
context.uniform1f(u.u_scale, modelsShown);
|
|
14877
|
-
const
|
|
14878
|
-
const paletteMix = partMixNow();
|
|
15045
|
+
const colourOf2 = partColoursNow();
|
|
14879
15046
|
for (const entry of standing) {
|
|
14880
|
-
const level =
|
|
15047
|
+
const level = levelOf(entry);
|
|
14881
15048
|
const surface = entry.model.levels[level].surface;
|
|
14882
15049
|
if (!surface?.emitters?.length) continue;
|
|
14883
15050
|
const stand = standOf(entry), lighting2 = modelLightingNow(entry.model.id);
|
|
@@ -14885,7 +15052,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14885
15052
|
setPlacement(context, emitterProgram, entry, stand);
|
|
14886
15053
|
context.uniform1f(u.u_opacity, modelsOpacity * appearanceOf(entry, now));
|
|
14887
15054
|
for (const [index, emitter] of surface.emitters.entries()) {
|
|
14888
|
-
const role = tileflowModelLightingRoles[emitter.role], part =
|
|
15055
|
+
const role = tileflowModelLightingRoles[emitter.role], part = colourOf2(emitter.part);
|
|
14889
15056
|
const geometry2 = entry.gl[level].surface.emitters[index];
|
|
14890
15057
|
const gradient = lighting2.gradients.subarray(role * 4, role * 4 + 4);
|
|
14891
15058
|
const bounds = entry.model.bounds;
|
|
@@ -14896,9 +15063,9 @@ function createTileflowBuildings3D(options) {
|
|
|
14896
15063
|
if (strength <= 0) continue;
|
|
14897
15064
|
const own = lighting2.colours.subarray(role * 4, role * 4 + 4);
|
|
14898
15065
|
const tint = lighting2.materialColours.subarray(role * 4, role * 4 + 4);
|
|
14899
|
-
const tintWeight = tint[3] * (1 -
|
|
15066
|
+
const tintWeight = tint[3] * (1 - part[3] * lighting2.appearance[role * 3 + 2]);
|
|
14900
15067
|
const colour = [0, 1, 2].map(
|
|
14901
|
-
(channel) => own[3] > 0 ? own[channel] :
|
|
15068
|
+
(channel) => own[3] > 0 ? own[channel] : part[channel] * (1 - tintWeight) + tint[channel] * tintWeight
|
|
14902
15069
|
);
|
|
14903
15070
|
context.uniform3fv(u.u_emitter_positions, geometry2.positions);
|
|
14904
15071
|
context.uniform4fv(u.u_emitter_coordinates, geometry2.coordinates);
|
|
@@ -14948,8 +15115,11 @@ ${shaderData.define}`;
|
|
|
14948
15115
|
const fragment = shader(context.FRAGMENT_SHADER, fragmentText);
|
|
14949
15116
|
context.attachShader(program, vertex);
|
|
14950
15117
|
context.attachShader(program, fragment);
|
|
14951
|
-
const bound = name === "model" || name === "modelDepth" ? [
|
|
14952
|
-
|
|
15118
|
+
const bound = name === "model" || name === "modelDepth" ? [
|
|
15119
|
+
...tileflowModelAttributes.map(([attribute]) => attribute),
|
|
15120
|
+
...tileflowModelSurfaceAttributes
|
|
15121
|
+
] : tileflowBuildingAttributes.map(([attribute]) => attribute);
|
|
15122
|
+
for (const [index, attribute] of bound.entries())
|
|
14953
15123
|
context.bindAttribLocation(program, index, attribute);
|
|
14954
15124
|
context.linkProgram(program);
|
|
14955
15125
|
return { name, program, vertex, fragment, variant: shaderData.variantName };
|
|
@@ -16231,7 +16401,7 @@ var version = 1;
|
|
|
16231
16401
|
var headerBytes = 16;
|
|
16232
16402
|
var vertexBytes = 12;
|
|
16233
16403
|
var positionRange = 2;
|
|
16234
|
-
var
|
|
16404
|
+
var partCount = Object.keys(tileflowTreeParts).length;
|
|
16235
16405
|
function decodeTileflowTreeModel(text2, level) {
|
|
16236
16406
|
if (typeof text2 !== "string" || text2.length > 2e5) return void 0;
|
|
16237
16407
|
let bytes;
|
|
@@ -16262,7 +16432,7 @@ function decodeTileflowTreeModel(text2, level) {
|
|
|
16262
16432
|
positions.push(view.getInt16(at + axis * 2, true) / 32767 * positionRange);
|
|
16263
16433
|
normals.push(view.getInt8(at + 6 + axis) / 127);
|
|
16264
16434
|
}
|
|
16265
|
-
if (bytes[at + 9] >=
|
|
16435
|
+
if (bytes[at + 9] >= partCount) return void 0;
|
|
16266
16436
|
parts.push(bytes[at + 9]);
|
|
16267
16437
|
shades.push(bytes[at + 10] / 255 * 2 - 1);
|
|
16268
16438
|
occlusion.push(bytes[at + 11] / 255);
|
|
@@ -19662,12 +19832,13 @@ var registeredContourProtocols = /* @__PURE__ */ new WeakSet();
|
|
|
19662
19832
|
function registerTileflowContourProtocol(registry, options = {}) {
|
|
19663
19833
|
if (registeredContourProtocols.has(registry.addProtocol)) return;
|
|
19664
19834
|
const handler = createTileflowContourProtocolHandler(
|
|
19665
|
-
options.loadMaplibreContour ?? loadPinnedMaplibreContour
|
|
19835
|
+
options.loadMaplibreContour ?? loadPinnedMaplibreContour,
|
|
19836
|
+
options.transformDemUrl
|
|
19666
19837
|
);
|
|
19667
19838
|
registry.addProtocol(tileflowContourProtocol, handler);
|
|
19668
19839
|
registeredContourProtocols.add(registry.addProtocol);
|
|
19669
19840
|
}
|
|
19670
|
-
function createTileflowContourProtocolHandler(loadModule) {
|
|
19841
|
+
function createTileflowContourProtocolHandler(loadModule, transformDemUrl = (url) => url) {
|
|
19671
19842
|
let library;
|
|
19672
19843
|
const sources = /* @__PURE__ */ new Map();
|
|
19673
19844
|
return async (request, abortController) => {
|
|
@@ -19682,7 +19853,7 @@ function createTileflowContourProtocolHandler(loadModule) {
|
|
|
19682
19853
|
(module) => new module.DemSource({
|
|
19683
19854
|
encoding: config.encoding,
|
|
19684
19855
|
maxzoom: config.demMaxzoom,
|
|
19685
|
-
url: config.demUrl,
|
|
19856
|
+
url: transformDemUrl(config.demUrl),
|
|
19686
19857
|
// Upstream workers use a generated `blob:` URL. The main-thread manager keeps the
|
|
19687
19858
|
// protocol usable in strict-CSP applications and deterministic local captures.
|
|
19688
19859
|
worker: false
|