@tileflow/core 0.1.0-alpha.42 → 0.1.0-alpha.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +50 -68
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/dist/{3d-CzLTD0RK.d.ts → 3d-CW5Ls0An.d.ts} +32 -2
  4. package/dist/3d.d.ts +1 -1
  5. package/dist/3d.js +301 -22
  6. package/dist/browser.d.ts +95 -5
  7. package/dist/browser.js +713 -45
  8. package/dist/build.d.ts +8 -4
  9. package/dist/build.js +250 -3
  10. package/dist/config-reference.json +3395 -2140
  11. package/dist/{icon-composition-B1A2udKb.d.ts → icon-composition-Bbw9umUA.d.ts} +37 -2
  12. package/dist/index.d.ts +13 -4
  13. package/dist/index.js +193 -3
  14. package/dist/{manifest-types-B0lQjabX.d.ts → manifest-types-CwjHd4qc.d.ts} +8 -0
  15. package/dist/manifest.d.ts +2 -2
  16. package/dist/native-profile.d.ts +4 -0
  17. package/dist/native-profile.js +2 -0
  18. package/dist/native.js +789 -462
  19. package/dist/runtime.d.ts +1 -1
  20. package/dist/worker/camera-tile-worker.global.js +2 -2
  21. package/package.json +4 -5
  22. package/docs/application-tile-reading.md +0 -86
  23. package/docs/authoring-model.md +0 -269
  24. package/docs/boundary-areas-and-choropleths.md +0 -230
  25. package/docs/buildings-3d.md +0 -624
  26. package/docs/camera-moves-and-tile-cache.md +0 -112
  27. package/docs/capture-scenes.md +0 -40
  28. package/docs/capture-shots.md +0 -173
  29. package/docs/cartographic-defaults.md +0 -214
  30. package/docs/compiled-style-performance.md +0 -286
  31. package/docs/data-is-separate-from-design.md +0 -610
  32. package/docs/depth-markers.md +0 -65
  33. package/docs/dynamic-style-images.md +0 -100
  34. package/docs/globe-atmosphere.md +0 -113
  35. package/docs/hosted-session-authorization.md +0 -106
  36. package/docs/map-and-terrain-examples.md +0 -156
  37. package/docs/map-emphasis.md +0 -89
  38. package/docs/native-artifact-profile.md +0 -152
  39. package/docs/native-resource-urls.md +0 -369
  40. package/docs/nautical-marks.md +0 -308
  41. package/docs/public-api-and-browser-subpath.md +0 -101
  42. package/docs/route-drawing.md +0 -191
  43. package/docs/shared-visual-primitives.md +0 -101
  44. package/docs/street-lights.md +0 -127
  45. package/docs/street-sky.md +0 -156
  46. package/docs/style-states.md +0 -73
  47. package/docs/sun-and-light.md +0 -167
  48. package/docs/theme-transitions-and-blends.md +0 -317
  49. package/docs/themes-and-module-styles.md +0 -156
  50. package/docs/trees-3d.md +0 -295
package/dist/browser.js CHANGED
@@ -2708,7 +2708,7 @@ var init_dist = __esm({
2708
2708
  function command(cmd, length) {
2709
2709
  return (length << 3) + (cmd & 7);
2710
2710
  }
2711
- function zigzag2(num2) {
2711
+ function zigzag3(num2) {
2712
2712
  return num2 << 1 ^ num2 >> 31;
2713
2713
  }
2714
2714
  function writeGeometry(feature, pbf) {
@@ -2732,8 +2732,8 @@ var init_dist = __esm({
2732
2732
  }
2733
2733
  const dx = ring[i2 * 2] - x3;
2734
2734
  const dy = ring[i2 * 2 + 1] - y2;
2735
- pbf.writeVarint(zigzag2(dx));
2736
- pbf.writeVarint(zigzag2(dy));
2735
+ pbf.writeVarint(zigzag3(dx));
2736
+ pbf.writeVarint(zigzag3(dy));
2737
2737
  x3 += dx;
2738
2738
  y2 += dy;
2739
2739
  }
@@ -3304,7 +3304,11 @@ function createTileflowDynamicImageRegistry(input, context, beforeRestore) {
3304
3304
  if (existing && existing !== entry.installed && !isRestoredCopy(existing, entry.recoveryImage)) {
3305
3305
  throw new Error(`Dynamic image "${entry.name}" conflicts with an existing image owner.`);
3306
3306
  }
3307
- if (!existing) map.addImage(entry.name, entry.pixels, { pixelRatio: entry.pixelRatio });
3307
+ if (!existing)
3308
+ map.addImage(entry.name, entry.pixels, {
3309
+ pixelRatio: entry.pixelRatio,
3310
+ ...entry.definition.sdf ? { sdf: true } : {}
3311
+ });
3308
3312
  else if (changed) map.updateImage(entry.name, entry.pixels);
3309
3313
  entry.installed = map.getImage(entry.name);
3310
3314
  entry.recoveryImage = void 0;
@@ -5737,6 +5741,59 @@ function withAlpha(color, alpha) {
5737
5741
  // src/browser.ts
5738
5742
  init_camera_limits();
5739
5743
 
5744
+ // src/horizon-queries-browser.ts
5745
+ var horizonShare2 = 0.85;
5746
+ var maximumHorizonAngle = 89.25 * Math.PI / 180;
5747
+ function tileflowHorizonScaleFactor(view) {
5748
+ const pitch = view.pitch * Math.PI / 180;
5749
+ const horizon = Math.min(
5750
+ Math.tan(Math.PI / 2 - pitch) * horizonShare2,
5751
+ Math.tan(maximumHorizonAngle - pitch)
5752
+ );
5753
+ const top = Math.min(view.centerY / view.cameraToCenterDistance, horizon);
5754
+ return 1 / (1 - Math.tan(pitch) * top);
5755
+ }
5756
+ function attachTileflowHorizonQueries(map) {
5757
+ const target = map;
5758
+ const query = target.queryRenderedFeatures;
5759
+ if (typeof query !== "function") return () => {
5760
+ };
5761
+ const own = Object.prototype.hasOwnProperty.call(target, "queryRenderedFeatures");
5762
+ const corrected = /* @__PURE__ */ new Map();
5763
+ const correct = (transform) => {
5764
+ const original = transform?.maxPitchScaleFactor;
5765
+ if (!transform || typeof original !== "function" || corrected.has(transform)) return;
5766
+ const own2 = Object.prototype.hasOwnProperty.call(transform, "maxPitchScaleFactor");
5767
+ corrected.set(transform, own2 ? original : void 0);
5768
+ transform.maxPitchScaleFactor = function() {
5769
+ const value = original.call(this);
5770
+ if (value > 0 && Number.isFinite(value)) return value;
5771
+ const fallback = tileflowHorizonScaleFactor({
5772
+ pitch: this.pitch,
5773
+ centerY: this.centerPoint.y,
5774
+ cameraToCenterDistance: this.cameraToCenterDistance
5775
+ });
5776
+ return fallback > 0 && Number.isFinite(fallback) ? fallback : value;
5777
+ };
5778
+ };
5779
+ const wrapped = function(...args) {
5780
+ correct(target._camera?.transform ?? target.transform);
5781
+ return query.apply(this, args);
5782
+ };
5783
+ target.queryRenderedFeatures = wrapped;
5784
+ return () => {
5785
+ if (target.queryRenderedFeatures === wrapped) {
5786
+ if (own) target.queryRenderedFeatures = query;
5787
+ else delete target.queryRenderedFeatures;
5788
+ }
5789
+ for (const [transform, original] of corrected) {
5790
+ if (original) transform.maxPitchScaleFactor = original;
5791
+ else delete transform.maxPitchScaleFactor;
5792
+ }
5793
+ corrected.clear();
5794
+ };
5795
+ }
5796
+
5740
5797
  // src/canvas-context-browser.ts
5741
5798
  function tileflowCanvasContextAttributes(attributes4) {
5742
5799
  return { antialias: true, ...attributes4 };
@@ -6384,6 +6441,7 @@ function readModelRoleLighting(value) {
6384
6441
  ...typeof entry.emissiveColor === "string" ? { emissiveColor: entry.emissiveColor } : {},
6385
6442
  ...typeof entry.color === "string" ? { color: entry.color } : {},
6386
6443
  ...entry.colorMix === void 0 ? {} : { colorMix: bounded(entry.colorMix, 0, 1, 1) },
6444
+ ...entry.colorScale === void 0 ? {} : { colorScale: bounded(entry.colorScale, 0, 1, 1) },
6387
6445
  ...entry.metallic === void 0 ? {} : { metallic: bounded(entry.metallic, 0, 1, 0) },
6388
6446
  ...entry.roughness === void 0 ? {} : { roughness: bounded(entry.roughness, 0, 1, 1) },
6389
6447
  ...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
@@ -6486,6 +6544,7 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
6486
6544
  shadows: true,
6487
6545
  occlusion: true,
6488
6546
  groundOcclusion: 0.16,
6547
+ groundOcclusionRadius: 3,
6489
6548
  modelOcclusion: 0.75
6490
6549
  });
6491
6550
  function readTileflowBuildings3D(metadata) {
@@ -6523,7 +6582,11 @@ function readTileflowBuildings3D(metadata) {
6523
6582
  shadows: typeof value.shadows === "boolean" ? value.shadows : defaults.shadows,
6524
6583
  occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults.occlusion,
6525
6584
  groundOcclusion: within(value.groundOcclusion, 1, defaults.groundOcclusion),
6585
+ groundOcclusionRadius: within(value.groundOcclusionRadius, 20, defaults.groundOcclusionRadius),
6526
6586
  modelOcclusion: within(value.modelOcclusion, 1, defaults.modelOcclusion),
6587
+ ...Array.isArray(value.flatLayers) && value.flatLayers.length <= 128 && value.flatLayers.every(
6588
+ (entry) => isRecord6(entry) && typeof entry.id === "string" && typeof entry.visible === "boolean"
6589
+ ) ? { flatLayers: value.flatLayers } : {},
6527
6590
  ...modelsOf(value.models),
6528
6591
  ...modelColorsOf(value.modelColors),
6529
6592
  ...landmarksOf(value.landmarks)
@@ -9750,6 +9813,9 @@ function readTileflowVegetation3D(metadata) {
9750
9813
  {
9751
9814
  heightScale: scale(own.heightScale),
9752
9815
  crownScale: scale(own.crownScale),
9816
+ ...typeof own.sizeAnchor === "number" && Number.isFinite(own.sizeAnchor) ? { sizeAnchor: clamp(own.sizeAnchor, [1, 45]) } : {},
9817
+ ...typeof own.crownAnchor === "number" && Number.isFinite(own.crownAnchor) ? { crownAnchor: clamp(own.crownAnchor, [1, 25]) } : {},
9818
+ ...typeof own.sizeCompression === "number" && Number.isFinite(own.sizeCompression) ? { sizeCompression: clamp(own.sizeCompression, [0, 1]) } : {},
9753
9819
  ...drawn.length > 0 ? { models: drawn } : {}
9754
9820
  }
9755
9821
  ]
@@ -10069,7 +10135,7 @@ function browserWorker() {
10069
10135
  if (typeof Worker === "undefined" || false)
10070
10136
  return;
10071
10137
  const url = URL.createObjectURL(
10072
- new Blob(['"use strict";(()=>{var Be=new Set,ln=!1;function Pe(e,n,t=2){let i=n&&n.length,o=i?n[0]*t:e.length;Be.size&&Be.clear();let r=zn(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=xt(e,n,r,t)),e.length>80*t){a=e[0],l=e[1];let c=a,f=l;for(let d=t;d<o;d+=t){let g=e[d],m=e[d+1];g<a&&(a=g),m<l&&(l=m),g>c&&(c=g),m>f&&(f=m)}u=Math.max(c-a,f-l),u=u!==0?32767/u:0}return un(r,s,a,l,u),s}function zn(e,n,t,i,o){let r=null;if(o===Ut(e,n,t,i)>0)for(let s=n;s<t;s+=i)r=In(s/i|0,e[s],e[s+1],r);else for(let s=t-i;s>=n;s-=i)r=In(s/i|0,e[s],e[s+1],r);return r&&Oe(r,r.next)&&(Ce(r),r=r.next),r}function ge(e,n=e){let t=n===e,i=e,o;do o=!1,i!==i.next&&(Be.size===0||!Be.has(i))&&(Oe(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Ce(i),i=i.prev,o=!0):(t||i!==n)&&(i=i.next,o=!t);while(o||i!==n);return n}function un(e,n,t,i,o){o&&Ft(e,t,i,o);let r=e,s=!1;for(;e.prev!==e.next;){let a=e.prev,l=e.next;if(Q(a,e,l)<0&&(o?bt(e,t,i,o):yt(e))){n.push(a.i,e.i,l.i),Ce(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=gt(e,n),r=e,s=!0;continue}wt(e,n,t,i,o);break}}}function yt(e){let n=e.prev,t=e,i=e.next,o=n.x,r=t.x,s=i.x,a=n.y,l=t.y,u=i.y,c=Math.min(o,r,s),f=Math.min(a,l,u),d=Math.max(o,r,s),g=Math.max(a,l,u),m=i.next;for(;m!==n;){if(m.x>=c&&m.x<=d&&m.y>=f&&m.y<=g&&!(o===m.x&&a===m.y)&&Ke(o,a,r,l,s,u,m.x,m.y)&&Q(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function bt(e,n,t,i){let o=e.prev,r=e,s=e.next,a=o.x,l=r.x,u=s.x,c=o.y,f=r.y,d=s.y,g=Math.min(a,l,u),m=Math.min(c,f,d),p=Math.max(a,l,u),h=Math.max(c,f,d),_=mn(g,m,n,t,i),F=mn(p,h,n,t,i),k=e.prevZ;for(;k&&k.z>=_;){if(k.x>=g&&k.x<=p&&k.y>=m&&k.y<=h&&k!==s&&!(a===k.x&&c===k.y)&&Ke(a,c,l,f,u,d,k.x,k.y)&&Q(k.prev,k,k.next)>=0)return!1;k=k.prevZ}let M=e.nextZ;for(;M&&M.z<=F;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Dn(o,t,t.next,r,!1)&&Ue(o,r)&&Ue(r,o)&&(n.push(o.i,t.i,r.i),Ce(t),Ce(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=zn(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Nn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Nn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Nn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function En(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ue(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&_t(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function _t(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function Ft(e,n,t,i){let o=e,r=0;do o.z=mn(o.x,o.y,n,t,i),ie[r++]=o,o=o.next;while(o!==e);At(r);let s=null;for(let a=0;a<r;a++){let l=ie[a];l.prevZ=s,s&&(s.nextZ=l),s=l}s.nextZ=null,ie.fill(null,0,r),ve.fill(null,0,r)}function At(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ue(e,n)&&Ue(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Dn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Dn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ue(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function In(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ce(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ut(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ct=.7,Pt=Math.tan(Math.PI/6),Et=Math.tan(35*Math.PI/180),It=Math.tan(Math.PI/18),Ee=.65,Ie=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Nt(e);if(!l||Math.abs(pn(e))<Ct*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let _=Math.max(0,o-i),F=Gn(t.roof_height),k,M;if(F!==void 0&&F>0)M=o,k=Math.max(i+Math.min(2,_/2),o-F);else{let y=Math.min(zt(a,d),_*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[U,E]=l.centre,C=(y,b)=>{let x=(y-U)*r,T=(b-E)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},I=(y,b)=>[U+(y*u[0]+b*c[0])/r,E+(y*u[1]+b*c[1])/r],D=(y,b)=>{let x=1/0;for(let[T,A,v]of h)x=Math.min(x,T*y+A*b+v);return Math.max(0,x)},K=(y,b)=>k+B*D(...C(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...C(n[y],n[y+1]));pn($)<0&&Ht($);let N=1.01,Y=[-f*N,-d*N,f*N,-d*N,f*N,d*N,-f*N,d*N],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,A=x.length/2;for(let P=0;P<A&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%A*2],x[(P+1)%A*2+1]];T=Hn(T,W-j,Z-G,-(W-j)*Z-(Z-G)*j)}if(T.length<6||Math.abs(pn(T))<1e-6)continue;let v=[];for(let P=0;P<T.length;P+=2)v.push(...I(T[P],T[P+1]));let L=Pe(v);if(L.length===0)continue;let O=B*b[0],V=B*b[1],R=O*u[0]+V*c[0],S=O*u[1]+V*c[1],z=Math.hypot(R,S,1);w.push({ring:v,triangles:L,normal:[-R/z,-S/z]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[A,v]=C(y,b),[L,O]=C(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let S=R+1;S<h.length;S+=1){let z=(ae,H)=>(h[R][0]-h[S][0])*ae+(h[R][1]-h[S][1])*H+(h[R][2]-h[S][2]),P=z(A,v),Z=z(L,O);if(P===Z||P*Z>0)continue;let j=P/(P-Z);if(j<=1e-4||j>=1-1e-4)continue;let G=A+(L-A)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=D(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function zt(e,n){switch(e){case"skillion":return 2*n*It;case"pyramidal":return n*Et;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=Ee/(Ie*r)*f,m=(1-Ee)/((1-Ie)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),Ee/(Ie*r)*d],[...p(m),Ee+(1-Ee)/((1-Ie)*r)*(d-Ie*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Nt(e){let n=Dt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[_,F]of n){let k=_*c[0]+F*c[1],M=_*f[0]+F*f[1];d=Math.min(d,k),g=Math.max(g,k),m=Math.min(m,M),p=Math.max(p,M)}let h=(g-d)*(p-m);if(h<i){i=h;let _=(d+g)/2,F=(m+p)/2;t={centre:[_*c[0]+F*f[0],_*c[1]+F*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Dt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var $t=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Nr=Object.freeze(Object.keys($t));var Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6});var Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024,parts:16});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Zt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=Gt(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function Gt(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Zt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Wt={commercial:1,active:2,destination:3},Xt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Yt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Jt=6,Kt=.5,Qt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1.5,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=tr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let U=B.properties,E=U.hide_3d;if(E===!0||E===1||E==="1"||E==="true")continue;let C=Math.min(6e3,Jn(U.render_height)??o),I=Math.min(C,Jn(U.render_min_height)??0),D=Wt[String(U.building_tone??"")]??0,K=Xt[String(U.class??"")]??0,$=d.get(M)??0,N=u.length,Y=!1;for(let w of rr(B.geometry,t)){let y=w.map(ir).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=or(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Qt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,C+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let z=0;z<S.length;z+=2)T.bounds[0]=Math.min(T.bounds[0],S[z]-1),T.bounds[1]=Math.min(T.bounds[1],S[z+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[z]+1),T.bounds[3]=Math.max(T.bounds[3],S[z+1]+1);Y=!0,f=Math.max(f,C);let A=Number.isSafeInteger(B.id),v=gn(A?B.id*.0731:b*.0731+x*.19137+N*1.618),L=!A&&y[0].some(S=>S<=0||S>=ue)?gn(C*7.31+I*3.17+D):v,O={base:I,top:C,jitter:L,seed:v,tone:D,group:K,use:$,cx:b,cy:x,index:N},V=y.map((S,z)=>nr(S,z,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],U,I,C,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),er(R,O,s,a)):qt(y,O,s,a);for(let[S,z]of y.entries()){let P=qe(z)>0,Z=S===0?P?-1:1:P?1:-1,j=z.length/2,G=H=>{let J=(H%j+j)%j;return[z[J*2],z[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,Ne=(ne-J)/me*Z;return(je*(le-ne)+Ne*(de-te))/ce>Kt},se=(H,J)=>R?R.heightAt(H,J):C,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],Ne=oe=>{let _e=ce[0]+(je[0]-ce[0])*oe,Fe=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(_e,Fe)||1;return[_e/ye,Fe/ye]},he=[0,...R?R.breaks(J,re,ne,te):[],1];for(let oe=0;oe+1<he.length;oe+=1){let _e=oe===0,Fe=oe+2===he.length,ye=J+(ne-J)*he[oe],De=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],Ae=Math.hypot(Ve-ye,He-De)/ue*n.tileMetres,$e=(_e&&W(H)?1:0)|(Fe&&W(H+1)?2:0)|(S>0?4:0),Ge=(_e&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+Ae,Ze=Ne(he[oe]),We=Ne(he[oe+1]),Un=se(ye,De),Cn=se(Ve,He),ke=s.write(O,ye,De,0,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),s.write(O,ye,De,1,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),l.push(ke,ke+1,ke+2,ke+1,ke+3,ke+2),ae=an}}}T.roofsCount=a.length-T.roofsFrom,T.wallsCount=l.length-T.wallsFrom,c.push(T)}Y&&u.push(U)}if(s.count===0)return;let g=new Uint32Array(a.length+l.length),m=[],p=0,h=a.length,_=a.values(),F=l.values();c.sort((M,B)=>M.cell-B.cell);let k=-1;for(let M of c){M.cell!==k&&(k=M.cell,m.push({bounds:[...M.bounds],roofsFrom:p,roofsCount:0,wallsFrom:h,wallsCount:0}));let B=m.at(-1);for(let U=0;U<5;U+=1)B.bounds[U]=U<2?Math.min(B.bounds[U],M.bounds[U]):Math.max(B.bounds[U],M.bounds[U]);g.set(_.subarray(M.roofsFrom,M.roofsFrom+M.roofsCount),p),g.set(F.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function er(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function nr(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[_,F]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(_-p,F-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,_,F)){u(p,h);continue}let[B,U]=[(p-g)/k,(h-m)/k],[E,C]=[(_-p)/M,(F-h)/M],I=Math.atan2(B*C-U*E,B*E+U*C);if(I*s>=-.08||Math.abs(I)>Math.PI*.85){u(p,h);continue}let D=Math.tan(Math.abs(I)/2),K=Math.min(t*D,k*.2,M*.2),$=K/D;if($<1){u(p,h);continue}let[N,Y]=[-U*s,B*s],[w,y]=[p-B*K-N*$,h-U*K-Y*$],b=Math.atan2(Y,N),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(I)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let A=b+I*T/x,v=[Math.cos(A),Math.sin(A)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let _=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(_).set(new Uint8Array(this.#e)),this.#e=_,this.#n=new DataView(_)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function tr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Yt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Jt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let F of r){let[k,M,B,U]=F.box;if(d<k-o||d>B+o||g<M-o||g>U+o)continue;let E=!1;for(let C of F.rings)for(let I=0,D=C.length-2;I+1<C.length;D=I,I+=2){let K=C[D],$=C[D+1],N=C[I],Y=C[I+1];Y>g!=$>g&&d<(K-N)*(g-Y)/($-Y)+N&&(E=!E);let w=N-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=F.index)}if(E){m=F.index;break}}let _=m??p;_!==void 0&&t.set(_,Math.max(t.get(_)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function rr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function or(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function ir(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=sr(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function sr(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let _=(t.length<=4?[...t].map(F=>F+F).join(""):t).match(/../gu).map(F=>Number.parseInt(F,16));return[_[0],_[1],_[2],_.length>3?_[3]/255:1]}let i=/^(rgba?|hsla?)\\(([^)]+)\\)$/u.exec(n);if(!i)return null;let o=i[2].split(/[\\s,/]+/u).filter(Boolean);if(o.length<3||o.length>4)return null;let r=o[3]===void 0?1:en(o[3],1);if(i[1].startsWith("rgb")){let[h,_,F]=o.slice(0,3).map(k=>en(k,255));return[h,_,F,r].some(k=>k===null)?null:[h,_,F,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,ar={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},lr={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},ur={spacing:30,kerb:0},cr=12,fr=18,dr=9,mr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},hr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},pr=new Set(["wall","wall_mounted","wall_bracket"]),yr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(fr),r=new nn(dr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let _=br(h),F=gr(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,_*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let U=0;U+1<B.length;U+=2){let E=B[U]*m,C=B[U+1]*m;if(!rt(E,C))continue;i.write(E,C,_,M,!0,F);let I=ot(E,C,n.tileMetres);o.add(...I),r.add(...I)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=wr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=cr,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,_)=>{let F=fe/m.extent,k=[];for(let D=0;D+1<p.length;D+=2)k.push(p[D]*F,p[D+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,U=Rn(k[0]*.013+k[1]*.029+_)*h.spacing,E=0,C=U,I=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let D=2;D<k.length;D+=2){let K=k[D-2],$=k[D-1],N=k[D],Y=k[D+1],w=Math.hypot(N-K,Y-$)*M;if(w!==0){for(;C<=E+w;){let y=(C-E)/w,b=-(Y-$)/(w/M)*I,x=(N-K)/(w/M)*I,T=K+(N-K)*y+b*B,A=$+(Y-$)*y+x*B;if(C+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(I=-I),!rt(T,A))continue;let v=ot(T,A,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,A,7,15,!1))}E+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,ur,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=ar[r];if(s&&(n==="streets"||kn(t)))return s;let a=lr[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function br(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return pr.has(t)?4.5:yr.has(t)?7.5:7}function gr(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(hr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=mr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function wr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],_n=[1,25],xr=1.2,Tr=1.5,Mr=1.3,kr=1,vr=[.3,10],Rr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),_r=new Set(["cupressus","calocedrus","thuja"]),Fr=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=Fn(e[t.genus])??Fn(e[t.species])??(o.endsWith("aceae")?void 0:Fn(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&Rr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&_r.has(r))return"columnar";if(i.includes("needle")||r&&Fr.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function Fn(e){return typeof e!="string"?void 0:e.trim().split(/\\s+/u)[0]?.toLowerCase()||void 0}function ct(e,n){let t={...ut,...n.fields},i=n.unknownForms??Sn,o=n.regions??[],{tile:r,tileMetres:s}=n,a=s/2**(15-r.z)/512,l=[],u=0,c=0,f=(w,y)=>{if(o.length===0)return i;let[b,x]=Sr(r,w/q,y/q);for(let T of o){let[A,v,L,O]=T.bounds;if(x>=v&&x<=O&&(A<=L?b>=A&&b<=L:b>=A||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],A=An(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=An(T.height,ee(y,1))),v===void 0&&(v=L/A),L===void 0&&(L=v*A),{height:Te(v,on),crown:Te(L,_n)}},g=(w,y,b,x,T,A)=>{let v=ze(r.x*q+w,r.y*q+y,7),L=b===void 0?sn(f(w,y),ee(v,3)):b==="broadleaf"?sn(Ar(f(w,y)),ee(v,3)):b,O=x===void 0&&T===void 0&&A!==void 0?d(L,v,An(st[L].height,Te(A/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...O,turn:ee(v,4),shade:ee(v,5),form:Me.indexOf(L),rank:Math.floor(ee(v,6)*rn),seed:ee(v,7),canopy:0}),u+=1},m=e.trees;if(m){let w=q/m.extent;for(let y of m.features){if(y.type!=="Point")continue;let b=y.properties,x=lt(b,t),T=xe(b[t.height],on),A=xe(b[t.diameterCrown],_n),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,A,v)}}}let p=e.trees;if(p){let w=q/p.extent,y=(n.rowSpacing??8)/(s/p.extent);for(let b of p.features){if(b.type!=="LineString")continue;let x=b.properties,T=lt(x,t),A=xe(x[t.height],on),v=xe(x[t.diameterCrown],_n);for(let L of b.geometry){let O=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[S,z,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],j=Math.hypot(P-S,Z-z);for(;O<=V+j;){let G=j>0?(O-V)/j:0,W=S+(P-S)*G,se=z+(Z-z)*G;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,A,v,void 0),O+=y}V+=j}}}}let h=e.canopy;if(h){let w=q/h.extent;for(let y of h.features){if(y.type!=="Point")continue;let b=y.properties,x=Te(Math.floor(Number(b[t.canopyRank]??8)),[0,rn-1]),T=Math.max(4,Number(b[t.canopyClearance]??8))*a,A=Number(b[t.canopyCover]??30),v=A>=60?3:A>=30?2:1;for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let S=V*w,z=R*w,P=ze(r.x*q+S,r.y*q+z,11),Z=f(S,z),j=xe(b[t.canopyHeight],on),G=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(G*.5,T-G/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let H=ze(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee(H,1):W,ne=S+Math.cos(J)*re/(s/q),te=z+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee(H,3)),de=G*(.85+ee(H,2)*.3),me=j===void 0?void 0:j*(.85+ee(H,6)*.25),ce=d(le,H,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee(H,4),shade:ee(H,5),form:Me.indexOf(le),rank:x,seed:ee(H,7),canopy:1}),c+=1}}}}let _=[],F=e.hedges;if(F){let w=q/F.extent,y=xr/(s/F.extent);for(let b of F.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?kr:0,T=(xe(b.properties[t.height],vr)??Mr)+x;for(let A of b.geometry){let v=y/2,L=0;for(let O=0;O+3<A.length;O+=2){let[V,R,S,z]=[A[O],A[O+1],A[O+2],A[O+3]],P=Math.hypot(S-V,z-R),Z=(Math.atan2(R-z,S-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let j=P>0?(v-L)/P:0,G=V+(S-V)*j,W=R+(z-R)*j;if(G>=0&&W>=0&&G<F.extent&&W<F.extent){let se=ze(r.x*q+G*w,r.y*q+W*w,17);_.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),U=l.map((w,y)=>y);U.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let E=new Uint8Array(l.length*tn),C=new DataView(E.buffer),I=0,D=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...D(),variants:Array.from({length:k(y)},D)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};U.forEach((w,y)=>{let b=l[w],x=y*tn;C.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),C.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),C.setUint16(x+4,Math.round(b.height*10),!0),C.setUint16(x+6,Math.round(b.crown*10),!0),E[x+8]=Math.floor(b.turn*256)&255,E[x+9]=Math.floor(b.shade*256)&255,E[x+10]=b.form,E[x+11]=b.rank,E[x+12]=Math.floor(b.seed*256)&255,E[x+13]=b.canopy,E[x+14]=B[w],I=Math.max(I,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let N=new Uint8Array(_.length*tn),Y=new DataView(N.buffer);return _.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(Tr*10),!0),N[b+8]=Math.round(w.turn*256)&255,N[b+9]=Math.floor(w.shade*256)&255,N[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:N,tallest:I,mapped:u,canopy:c}}function Ar(e){let n={round:e.round??0,open:e.open??0,tall:e.tall??0};return n.round+n.open+n.tall>0?n:Sn}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(Sn,n);let i=n*t;for(let o of Me){let r=Math.max(0,e[o]??0);if(i<r)return o;i-=r}return"round"}function xe(e,n){let t=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):NaN;return Number.isFinite(t)&&t>0?Te(t,n):void 0}function Te(e,[n,t]){return Math.min(t,Math.max(n,e))}function An([e,n],t){return e+(n-e)*t}function Sr(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function ze(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return ze(e,n,20973)/4294967296}var Lr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Br(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Br(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Cr(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Or(a,o,r);return l?[l]:[]}))})}}function Or(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Lr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Ur(s,o))})}function Ur(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Cr(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Pr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Pr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,Er=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,Er.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
10138
+ new Blob(['"use strict";(()=>{var Be=new Set,ln=!1;function Pe(e,n,t=2){let i=n&&n.length,o=i?n[0]*t:e.length;Be.size&&Be.clear();let r=In(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=xt(e,n,r,t)),e.length>80*t){a=e[0],l=e[1];let c=a,f=l;for(let d=t;d<o;d+=t){let g=e[d],m=e[d+1];g<a&&(a=g),m<l&&(l=m),g>c&&(c=g),m>f&&(f=m)}u=Math.max(c-a,f-l),u=u!==0?32767/u:0}return un(r,s,a,l,u),s}function In(e,n,t,i,o){let r=null;if(o===Ct(e,n,t,i)>0)for(let s=n;s<t;s+=i)r=En(s/i|0,e[s],e[s+1],r);else for(let s=t-i;s>=n;s-=i)r=En(s/i|0,e[s],e[s+1],r);return r&&Oe(r,r.next)&&(Ue(r),r=r.next),r}function ge(e,n=e){let t=n===e,i=e,o;do o=!1,i!==i.next&&(Be.size===0||!Be.has(i))&&(Oe(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Ue(i),i=i.prev,o=!0):(t||i!==n)&&(i=i.next,o=!t);while(o||i!==n);return n}function un(e,n,t,i,o){o&&Ft(e,t,i,o);let r=e,s=!1;for(;e.prev!==e.next;){let a=e.prev,l=e.next;if(Q(a,e,l)<0&&(o?bt(e,t,i,o):yt(e))){n.push(a.i,e.i,l.i),Ue(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=gt(e,n),r=e,s=!0;continue}wt(e,n,t,i,o);break}}}function yt(e){let n=e.prev,t=e,i=e.next,o=n.x,r=t.x,s=i.x,a=n.y,l=t.y,u=i.y,c=Math.min(o,r,s),f=Math.min(a,l,u),d=Math.max(o,r,s),g=Math.max(a,l,u),m=i.next;for(;m!==n;){if(m.x>=c&&m.x<=d&&m.y>=f&&m.y<=g&&!(o===m.x&&a===m.y)&&Ke(o,a,r,l,s,u,m.x,m.y)&&Q(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function bt(e,n,t,i){let o=e.prev,r=e,s=e.next,a=o.x,l=r.x,u=s.x,c=o.y,f=r.y,d=s.y,g=Math.min(a,l,u),m=Math.min(c,f,d),p=Math.max(a,l,u),h=Math.max(c,f,d),A=mn(g,m,n,t,i),F=mn(p,h,n,t,i),k=e.prevZ;for(;k&&k.z>=A;){if(k.x>=g&&k.x<=p&&k.y>=m&&k.y<=h&&k!==s&&!(a===k.x&&c===k.y)&&Ke(a,c,l,f,u,d,k.x,k.y)&&Q(k.prev,k,k.next)>=0)return!1;k=k.prevZ}let M=e.nextZ;for(;M&&M.z<=F;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Dn(o,t,t.next,r,!1)&&Ce(o,r)&&Ce(r,o)&&(n.push(o.i,t.i,r.i),Ue(t),Ue(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=In(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Nn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Nn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Nn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function zn(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=zn(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=zn(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ce(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&At(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function At(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function Ft(e,n,t,i){let o=e,r=0;do o.z=mn(o.x,o.y,n,t,i),ie[r++]=o,o=o.next;while(o!==e);_t(r);let s=null;for(let a=0;a<r;a++){let l=ie[a];l.prevZ=s,s&&(s.nextZ=l),s=l}s.nextZ=null,ie.fill(null,0,r),ve.fill(null,0,r)}function _t(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ce(e,n)&&Ce(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Dn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Dn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ce(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function En(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ue(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ct(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ut=.7,Pt=Math.tan(Math.PI/6),zt=Math.tan(35*Math.PI/180),Et=Math.tan(Math.PI/18),ze=.65,Ee=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Nt(e);if(!l||Math.abs(pn(e))<Ut*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let A=Math.max(0,o-i),F=Gn(t.roof_height),k,M;if(F!==void 0&&F>0)M=o,k=Math.max(i+Math.min(2,A/2),o-F);else{let y=Math.min(It(a,d),A*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[C,z]=l.centre,U=(y,b)=>{let x=(y-C)*r,T=(b-z)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},E=(y,b)=>[C+(y*u[0]+b*c[0])/r,z+(y*u[1]+b*c[1])/r],D=(y,b)=>{let x=1/0;for(let[T,_,v]of h)x=Math.min(x,T*y+_*b+v);return Math.max(0,x)},K=(y,b)=>k+B*D(...U(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...U(n[y],n[y+1]));pn($)<0&&Ht($);let N=1.01,Y=[-f*N,-d*N,f*N,-d*N,f*N,d*N,-f*N,d*N],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,_=x.length/2;for(let P=0;P<_&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%_*2],x[(P+1)%_*2+1]];T=Hn(T,W-j,Z-G,-(W-j)*Z-(Z-G)*j)}if(T.length<6||Math.abs(pn(T))<1e-6)continue;let v=[];for(let P=0;P<T.length;P+=2)v.push(...E(T[P],T[P+1]));let L=Pe(v);if(L.length===0)continue;let O=B*b[0],V=B*b[1],R=O*u[0]+V*c[0],S=O*u[1]+V*c[1],I=Math.hypot(R,S,1);w.push({ring:v,triangles:L,normal:[-R/I,-S/I]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[_,v]=U(y,b),[L,O]=U(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let S=R+1;S<h.length;S+=1){let I=(ae,H)=>(h[R][0]-h[S][0])*ae+(h[R][1]-h[S][1])*H+(h[R][2]-h[S][2]),P=I(_,v),Z=I(L,O);if(P===Z||P*Z>0)continue;let j=P/(P-Z);if(j<=1e-4||j>=1-1e-4)continue;let G=_+(L-_)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=D(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function It(e,n){switch(e){case"skillion":return 2*n*Et;case"pyramidal":return n*zt;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=ze/(Ee*r)*f,m=(1-ze)/((1-Ee)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),ze/(Ee*r)*d],[...p(m),ze+(1-ze)/((1-Ee)*r)*(d-Ee*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Nt(e){let n=Dt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[A,F]of n){let k=A*c[0]+F*c[1],M=A*f[0]+F*f[1];d=Math.min(d,k),g=Math.max(g,k),m=Math.min(m,M),p=Math.max(p,M)}let h=(g-d)*(p-m);if(h<i){i=h;let A=(d+g)/2,F=(m+p)/2;t={centre:[A*c[0]+F*f[0],A*c[1]+F*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Dt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var $t=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Nr=Object.freeze(Object.keys($t));var Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6});var Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024,parts:16});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Zt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=Gt(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function Gt(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Zt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Wt={commercial:1,active:2,destination:3},Xt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Yt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Jt=6,Kt=.5,Qt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1.5,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=tr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let C=B.properties,z=C.hide_3d;if(z===!0||z===1||z==="1"||z==="true")continue;let U=Math.min(6e3,Jn(C.render_height)??o),E=Math.min(U,Jn(C.render_min_height)??0),D=Wt[String(C.building_tone??"")]??0,K=Xt[String(C.class??"")]??0,$=d.get(M)??0,N=u.length,Y=!1;for(let w of rr(B.geometry,t)){let y=w.map(ir).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=or(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Qt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,U+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let I=0;I<S.length;I+=2)T.bounds[0]=Math.min(T.bounds[0],S[I]-1),T.bounds[1]=Math.min(T.bounds[1],S[I+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[I]+1),T.bounds[3]=Math.max(T.bounds[3],S[I+1]+1);Y=!0,f=Math.max(f,U);let _=Number.isSafeInteger(B.id),v=gn(_?B.id*.0731:b*.0731+x*.19137+N*1.618),L=!_&&y[0].some(S=>S<=0||S>=ue)?gn(U*7.31+E*3.17+D):v,O={base:E,top:U,jitter:L,seed:v,tone:D,group:K,use:$,cx:b,cy:x,index:N},V=y.map((S,I)=>nr(S,I,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],C,E,U,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),er(R,O,s,a)):qt(y,O,s,a);for(let[S,I]of y.entries()){let P=qe(I)>0,Z=S===0?P?-1:1:P?1:-1,j=I.length/2,G=H=>{let J=(H%j+j)%j;return[I[J*2],I[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,Ne=(ne-J)/me*Z;return(je*(le-ne)+Ne*(de-te))/ce>Kt},se=(H,J)=>R?R.heightAt(H,J):U,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],Ne=oe=>{let Ae=ce[0]+(je[0]-ce[0])*oe,Fe=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(Ae,Fe)||1;return[Ae/ye,Fe/ye]},he=[0,...R?R.breaks(J,re,ne,te):[],1];for(let oe=0;oe+1<he.length;oe+=1){let Ae=oe===0,Fe=oe+2===he.length,ye=J+(ne-J)*he[oe],De=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],_e=Math.hypot(Ve-ye,He-De)/ue*n.tileMetres,$e=(Ae&&W(H)?1:0)|(Fe&&W(H+1)?2:0)|(S>0?4:0),Ge=(Ae&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+_e,Ze=Ne(he[oe]),We=Ne(he[oe+1]),Cn=se(ye,De),Un=se(Ve,He),ke=s.write(O,ye,De,0,Ze[0],Ze[1],1,ae,$e,_e,0,Ge,Cn);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,_e,1,Ge,Un),s.write(O,ye,De,1,Ze[0],Ze[1],1,ae,$e,_e,0,Ge,Cn),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,_e,1,Ge,Un),l.push(ke,ke+1,ke+2,ke+1,ke+3,ke+2),ae=an}}}T.roofsCount=a.length-T.roofsFrom,T.wallsCount=l.length-T.wallsFrom,c.push(T)}Y&&u.push(C)}if(s.count===0)return;let g=new Uint32Array(a.length+l.length),m=[],p=0,h=a.length,A=a.values(),F=l.values();c.sort((M,B)=>M.cell-B.cell);let k=-1;for(let M of c){M.cell!==k&&(k=M.cell,m.push({bounds:[...M.bounds],roofsFrom:p,roofsCount:0,wallsFrom:h,wallsCount:0}));let B=m.at(-1);for(let C=0;C<5;C+=1)B.bounds[C]=C<2?Math.min(B.bounds[C],M.bounds[C]):Math.max(B.bounds[C],M.bounds[C]);g.set(A.subarray(M.roofsFrom,M.roofsFrom+M.roofsCount),p),g.set(F.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function er(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function nr(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[A,F]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(A-p,F-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,A,F)){u(p,h);continue}let[B,C]=[(p-g)/k,(h-m)/k],[z,U]=[(A-p)/M,(F-h)/M],E=Math.atan2(B*U-C*z,B*z+C*U);if(E*s>=-.08||Math.abs(E)>Math.PI*.85){u(p,h);continue}let D=Math.tan(Math.abs(E)/2),K=Math.min(t*D,k*.2,M*.2),$=K/D;if($<1){u(p,h);continue}let[N,Y]=[-C*s,B*s],[w,y]=[p-B*K-N*$,h-C*K-Y*$],b=Math.atan2(Y,N),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(E)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let _=b+E*T/x,v=[Math.cos(_),Math.sin(_)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let A=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(A).set(new Uint8Array(this.#e)),this.#e=A,this.#n=new DataView(A)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function tr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Yt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Jt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let F of r){let[k,M,B,C]=F.box;if(d<k-o||d>B+o||g<M-o||g>C+o)continue;let z=!1;for(let U of F.rings)for(let E=0,D=U.length-2;E+1<U.length;D=E,E+=2){let K=U[D],$=U[D+1],N=U[E],Y=U[E+1];Y>g!=$>g&&d<(K-N)*(g-Y)/($-Y)+N&&(z=!z);let w=N-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=F.index)}if(z){m=F.index;break}}let A=m??p;A!==void 0&&t.set(A,Math.max(t.get(A)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function rr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function or(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function ir(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=sr(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function sr(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let A=(t.length<=4?[...t].map(F=>F+F).join(""):t).match(/../gu).map(F=>Number.parseInt(F,16));return[A[0],A[1],A[2],A.length>3?A[3]/255:1]}let i=/^(rgba?|hsla?)\\(([^)]+)\\)$/u.exec(n);if(!i)return null;let o=i[2].split(/[\\s,/]+/u).filter(Boolean);if(o.length<3||o.length>4)return null;let r=o[3]===void 0?1:en(o[3],1);if(i[1].startsWith("rgb")){let[h,A,F]=o.slice(0,3).map(k=>en(k,255));return[h,A,F,r].some(k=>k===null)?null:[h,A,F,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,ar={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},lr={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},ur={spacing:30,kerb:0},cr=12,fr=18,dr=9,mr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},hr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},pr=new Set(["wall","wall_mounted","wall_bracket"]),yr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(fr),r=new nn(dr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let A=br(h),F=gr(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,A*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let C=0;C+1<B.length;C+=2){let z=B[C]*m,U=B[C+1]*m;if(!rt(z,U))continue;i.write(z,U,A,M,!0,F);let E=ot(z,U,n.tileMetres);o.add(...E),r.add(...E)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=wr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=cr,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,A)=>{let F=fe/m.extent,k=[];for(let D=0;D+1<p.length;D+=2)k.push(p[D]*F,p[D+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,C=Rn(k[0]*.013+k[1]*.029+A)*h.spacing,z=0,U=C,E=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let D=2;D<k.length;D+=2){let K=k[D-2],$=k[D-1],N=k[D],Y=k[D+1],w=Math.hypot(N-K,Y-$)*M;if(w!==0){for(;U<=z+w;){let y=(U-z)/w,b=-(Y-$)/(w/M)*E,x=(N-K)/(w/M)*E,T=K+(N-K)*y+b*B,_=$+(Y-$)*y+x*B;if(U+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(E=-E),!rt(T,_))continue;let v=ot(T,_,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,_,7,15,!1))}z+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,ur,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=ar[r];if(s&&(n==="streets"||kn(t)))return s;let a=lr[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function br(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return pr.has(t)?4.5:yr.has(t)?7.5:7}function gr(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(hr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=mr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function wr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],An=[1,25],xr=1.2,Tr=1.5,Mr=1.3,kr=1,vr=[.3,10],Rr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),Ar=new Set(["cupressus","calocedrus","thuja"]),Fr=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=Fn(e[t.genus])??Fn(e[t.species])??(o.endsWith("aceae")?void 0:Fn(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&Rr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&Ar.has(r))return"columnar";if(i.includes("needle")||r&&Fr.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function Fn(e){return typeof e!="string"?void 0:e.trim().split(/\\s+/u)[0]?.toLowerCase()||void 0}function ct(e,n){let t={...ut,...n.fields},i=n.unknownForms??Sn,o=n.regions??[],{tile:r,tileMetres:s}=n,a=s/2**(15-r.z)/512,l=[],u=0,c=0,f=(w,y)=>{if(o.length===0)return i;let[b,x]=Sr(r,w/q,y/q);for(let T of o){let[_,v,L,O]=T.bounds;if(x>=v&&x<=O&&(_<=L?b>=_&&b<=L:b>=_||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],_=_n(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=_n(T.height,ee(y,1))),v===void 0&&(v=L/_),L===void 0&&(L=v*_),{height:Te(v,on),crown:Te(L,An)}},g=(w,y,b,x,T,_)=>{let v=Ie(r.x*q+w,r.y*q+y,7),L=b===void 0?sn(f(w,y),ee(v,3)):b==="broadleaf"?sn(_r(f(w,y)),ee(v,3)):b,O=x===void 0&&T===void 0&&_!==void 0?d(L,v,_n(st[L].height,Te(_/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...O,turn:ee(v,4),shade:ee(v,5),form:Me.indexOf(L),rank:Math.floor(ee(v,6)*rn),seed:ee(v,7),canopy:0}),u+=1},m=e.trees;if(m){let w=q/m.extent;for(let y of m.features){if(y.type!=="Point")continue;let b=y.properties,x=lt(b,t),T=xe(b[t.height],on),_=xe(b[t.diameterCrown],An),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,_,v)}}}let p=e.trees;if(p){let w=q/p.extent,y=(n.rowSpacing??8)/(s/p.extent);for(let b of p.features){if(b.type!=="LineString")continue;let x=b.properties,T=lt(x,t),_=xe(x[t.height],on),v=xe(x[t.diameterCrown],An);for(let L of b.geometry){let O=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[S,I,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],j=Math.hypot(P-S,Z-I);for(;O<=V+j;){let G=j>0?(O-V)/j:0,W=S+(P-S)*G,se=I+(Z-I)*G;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,_,v,void 0),O+=y}V+=j}}}}let h=e.canopy;if(h){let w=q/h.extent;for(let y of h.features){if(y.type!=="Point")continue;let b=y.properties,x=Te(Math.floor(Number(b[t.canopyRank]??8)),[0,rn-1]),T=Math.max(4,Number(b[t.canopyClearance]??8))*a,_=Number(b[t.canopyCover]??30),v=_>=60?3:_>=30?2:1;for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let S=V*w,I=R*w,P=Ie(r.x*q+S,r.y*q+I,11),Z=f(S,I),j=xe(b[t.canopyHeight],on),G=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(G*.5,T-G/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let H=Ie(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee(H,1):W,ne=S+Math.cos(J)*re/(s/q),te=I+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee(H,3)),de=G*(.85+ee(H,2)*.3),me=j===void 0?void 0:j*(.85+ee(H,6)*.25),ce=d(le,H,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee(H,4),shade:ee(H,5),form:Me.indexOf(le),rank:x,seed:ee(H,7),canopy:1}),c+=1}}}}let A=[],F=e.hedges;if(F){let w=q/F.extent,y=xr/(s/F.extent);for(let b of F.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?kr:0,T=(xe(b.properties[t.height],vr)??Mr)+x;for(let _ of b.geometry){let v=y/2,L=0;for(let O=0;O+3<_.length;O+=2){let[V,R,S,I]=[_[O],_[O+1],_[O+2],_[O+3]],P=Math.hypot(S-V,I-R),Z=(Math.atan2(R-I,S-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let j=P>0?(v-L)/P:0,G=V+(S-V)*j,W=R+(I-R)*j;if(G>=0&&W>=0&&G<F.extent&&W<F.extent){let se=Ie(r.x*q+G*w,r.y*q+W*w,17);A.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),C=l.map((w,y)=>y);C.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let z=new Uint8Array(l.length*tn),U=new DataView(z.buffer),E=0,D=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...D(),variants:Array.from({length:k(y)},D)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};C.forEach((w,y)=>{let b=l[w],x=y*tn;U.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),U.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),U.setUint16(x+4,Math.round(b.height*10),!0),U.setUint16(x+6,Math.round(b.crown*10),!0),z[x+8]=Math.floor(b.turn*256)&255,z[x+9]=Math.floor(b.shade*256)&255,z[x+10]=b.form,z[x+11]=b.rank,z[x+12]=Math.floor(b.seed*256)&255,z[x+13]=b.canopy,z[x+14]=B[w],E=Math.max(E,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let N=new Uint8Array(A.length*tn),Y=new DataView(N.buffer);return A.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(Tr*10),!0),N[b+8]=Math.round(w.turn*256)&255,N[b+9]=Math.floor(w.shade*256)&255,N[b+12]=Math.floor(w.seed*256)&255,E=Math.max(E,w.height)}),{trees:z,forms:K,hedges:N,tallest:E,mapped:u,canopy:c}}function _r(e){let n={round:e.round??0,open:e.open??0,tall:e.tall??0};return n.round+n.open+n.tall>0?n:Sn}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(Sn,n);let i=n*t;for(let o of Me){let r=Math.max(0,e[o]??0);if(i<r)return o;i-=r}return"round"}function xe(e,n){let t=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):NaN;return Number.isFinite(t)&&t>0?Te(t,n):void 0}function Te(e,[n,t]){return Math.min(t,Math.max(n,e))}function _n([e,n],t){return e+(n-e)*t}function Sr(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function Ie(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return Ie(e,n,20973)/4294967296}var Lr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Br(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Br(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Ur(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Or(a,o,r);return l?[l]:[]}))})}}function Or(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Lr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Cr(s,o))})}function Cr(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Ur(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Pr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Pr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,zr=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,zr.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
10073
10139
  );
10074
10140
  try {
10075
10141
  return new Worker(url, { name: "tileflow-tiles" });
@@ -11579,7 +11645,7 @@ function createCameraTiles(options) {
11579
11645
  }
11580
11646
  entry.used = now;
11581
11647
  entry.distance = distance;
11582
- if ((!entry.value || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
11648
+ if ((!entry.value && !entry.pending || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
11583
11649
  load(source, key, entry, chosen.tileMetres);
11584
11650
  }
11585
11651
  evict();
@@ -11595,6 +11661,8 @@ function createCameraTiles(options) {
11595
11661
  ).then((tile) => {
11596
11662
  if (disposed || tiles.get(key) !== entry || entry.loading !== controller) return;
11597
11663
  if (!tile) {
11664
+ if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
11665
+ entry.pending = void 0;
11598
11666
  if (entry.value && entry.value !== options.empty) options.release(entry.value);
11599
11667
  entry.value = options.empty;
11600
11668
  entry.loading = void 0;
@@ -11643,10 +11711,11 @@ function createCameraTiles(options) {
11643
11711
  if (value !== options.empty) options.release(value);
11644
11712
  continue;
11645
11713
  }
11646
- const previous = entry.value;
11647
- entry.value = value;
11714
+ if (entry.pending && entry.pending !== options.empty && entry.pending !== value)
11715
+ options.release(entry.pending);
11716
+ entry.pending = value;
11648
11717
  entry.loading = void 0;
11649
- if (previous && previous !== options.empty && previous !== value) options.release(previous);
11718
+ commit(entry);
11650
11719
  built = true;
11651
11720
  }
11652
11721
  if (built && !disposed) {
@@ -11663,12 +11732,24 @@ function createCameraTiles(options) {
11663
11732
  void step();
11664
11733
  });
11665
11734
  }
11735
+ function commit(entry) {
11736
+ const value = entry.pending;
11737
+ if (value === void 0 || value !== options.empty && options.isReady && !options.isReady(value))
11738
+ return;
11739
+ const previous = entry.value;
11740
+ entry.value = value;
11741
+ entry.pending = void 0;
11742
+ if (previous && previous !== options.empty && previous !== value) options.release(previous);
11743
+ options.changed();
11744
+ map.triggerRepaint();
11745
+ }
11666
11746
  function evict() {
11667
11747
  const keep = new Set(wanted);
11668
11748
  const spare = [...tiles.entries()].filter(([key]) => !keep.has(key)).sort((a, b2) => b2[1].used - a[1].used);
11669
11749
  for (const [key, entry] of spare.slice(options.maxTiles)) {
11670
11750
  entry.loading?.abort();
11671
11751
  if (entry.value && entry.value !== options.empty) options.release(entry.value);
11752
+ if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
11672
11753
  tiles.delete(key);
11673
11754
  options.changed();
11674
11755
  }
@@ -11694,11 +11775,19 @@ function createCameraTiles(options) {
11694
11775
  const list = [];
11695
11776
  for (const key of wanted) {
11696
11777
  const entry = tiles.get(key);
11778
+ if (entry) commit(entry);
11697
11779
  if (entry?.value && entry.value !== options.empty)
11698
11780
  list.push(entry);
11699
11781
  }
11700
11782
  return list;
11701
11783
  },
11784
+ built() {
11785
+ return wanted.flatMap((key) => {
11786
+ const entry = tiles.get(key);
11787
+ const value = entry?.pending ?? entry?.value;
11788
+ return entry && value && value !== options.empty ? [{ ...entry, value }] : [];
11789
+ });
11790
+ },
11702
11791
  coverage: () => covered,
11703
11792
  ring: () => ring,
11704
11793
  all: () => tiles.values(),
@@ -11720,6 +11809,8 @@ function createCameraTiles(options) {
11720
11809
  for (const [key, entry] of tiles) {
11721
11810
  if (!which(entry)) continue;
11722
11811
  entry.loading?.abort();
11812
+ if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
11813
+ entry.pending = void 0;
11723
11814
  entry.retryAt = void 0;
11724
11815
  const latitude = Math.atan(Math.sinh(Math.PI * (1 - 2 * (entry.y + 0.5) / 2 ** zoom))) * 180 / Math.PI;
11725
11816
  load(source, key, entry, earth * Math.cos(latitude * Math.PI / 180) / 2 ** zoom);
@@ -11732,7 +11823,10 @@ function createCameraTiles(options) {
11732
11823
  map.off("sourcedata", onSource);
11733
11824
  map.off("move", onMove);
11734
11825
  map.off("moveend", onMoveEnd);
11735
- for (const entry of tiles.values()) entry.loading?.abort();
11826
+ for (const entry of tiles.values()) {
11827
+ entry.loading?.abort();
11828
+ if (entry.pending && entry.pending !== options.empty) options.release(entry.pending);
11829
+ }
11736
11830
  tiles.clear();
11737
11831
  queue.length = 0;
11738
11832
  reader?.clear();
@@ -12459,7 +12553,9 @@ function tileflowModelCameraDistance(model, view) {
12459
12553
  function tileflowModelLevel(model, view, previous) {
12460
12554
  const thresholds = tileflowModelLevelDistancesOf(model.bounds);
12461
12555
  const last = Math.max(0, Math.min(model.levels, thresholds.length + 1) - 1);
12462
- const distance = tileflowModelCameraDistance(model, view);
12556
+ const fov = view.verticalFieldOfView;
12557
+ const lens = fov !== void 0 && fov > 0 && fov < 180 ? Math.tan(fov * Math.PI / 360) * 3 : 1;
12558
+ const distance = tileflowModelCameraDistance(model, view) * lens;
12463
12559
  if (!Number.isFinite(distance)) return 0;
12464
12560
  const margin = previous === void 0 ? 1 : tileflowModelLevelHysteresis;
12465
12561
  let level = Math.max(0, Math.min(last, previous ?? 0));
@@ -12912,6 +13008,7 @@ out vec3 v_shadow;
12912
13008
  out float v_light;
12913
13009
  flat out int v_lighting_role;
12914
13010
  out float v_height;
13011
+ out float v_ground_height;
12915
13012
  out vec4 v_uv;
12916
13013
  out vec4 v_rgba;
12917
13014
  out vec3 v_position;
@@ -12940,6 +13037,7 @@ void main() {
12940
13037
  v_light = a_paint.z / 255.0;
12941
13038
  v_lighting_role = clamp(int(a_lighting_role + 0.5), 0, 6);
12942
13039
  v_height = (m.z - u_model_height.x) / max(u_model_height.y, 0.001);
13040
+ v_ground_height = m.z;
12943
13041
  }`;
12944
13042
  var tileflowModelFragment = `#version 300 es
12945
13043
  precision highp float;
@@ -12949,6 +13047,9 @@ in vec3 v_shadow;
12949
13047
  in float v_light;
12950
13048
  flat in int v_lighting_role;
12951
13049
  in float v_height;
13050
+ in float v_ground_height;
13051
+ uniform vec3 u_facade_shading; // vertical gradient, ground-contact strength and radius in metres
13052
+ uniform float u_role_color_scale[7];
12952
13053
  uniform vec3 u_sun_dir;
12953
13054
  uniform vec3 u_sun_light;
12954
13055
  uniform vec3 u_sky_light;
@@ -12976,6 +13077,16 @@ vec3 shade(vec3 normal, float lit, float occlusion) {
12976
13077
  return min(pow(light / max(roof, vec3(1e-4)), vec3(1.0 / 2.2)), vec3(1.7));
12977
13078
  }
12978
13079
 
13080
+ // Same quiet ground-to-facade transition as ordinary tile buildings, evaluated in metres.
13081
+ // Only map-shaded roles opt in; roofs and physical materials keep their own response.
13082
+ float facadeShade(vec3 normal, int role) {
13083
+ float wall = 1.0 - abs(normal.z);
13084
+ float up = max(v_ground_height, 0.0);
13085
+ float gradient = 0.1 * u_facade_shading.x * (1.0 - smoothstep(0.0, 3.0, up));
13086
+ float contact = u_facade_shading.y * exp(-up / max(u_facade_shading.z, 0.001));
13087
+ return 1.0 - max(gradient, contact) * wall * u_role_appearance[role].x;
13088
+ }
13089
+
12979
13090
  void main() {
12980
13091
  vec3 normal = normalize(gl_FrontFacing ? v_normal : -v_normal);
12981
13092
  if (u_physical) normal = materialNormal(normal);
@@ -12990,7 +13101,7 @@ void main() {
12990
13101
  float emission = clamp(u_role_emission[role] * multiplier, 0.0, 1.0);
12991
13102
  if (u_physical) {
12992
13103
  float alpha = materialAlpha();
12993
- vec3 base = materialBase(role);
13104
+ vec3 base = materialBase(role) * fromSRGB(vec3(u_role_color_scale[role]));
12994
13105
  float mapShare = u_role_appearance[role].x;
12995
13106
  vec3 radiance;
12996
13107
  if (mapShare >= 1.0) {
@@ -13000,13 +13111,14 @@ void main() {
13000
13111
  if (mapShare > 0.0)
13001
13112
  radiance = mix(radiance, base * fromSRGB(shade(normal, lit, u_role_appearance[role].y)), mapShare);
13002
13113
  }
13114
+ radiance *= fromSRGB(vec3(facadeShade(normal, role)));
13003
13115
  radiance += u_emissive * fromSRGB(materialTexture(4).rgb);
13004
13116
  vec4 own = u_role_emission_colour[role];
13005
13117
  radiance = mix(radiance, mix(base, fromSRGB(own.rgb), own.a), emission);
13006
13118
  fragColor = vec4(hazed(toSRGB(radiance)), alpha * u_opacity);
13007
13119
  return;
13008
13120
  }
13009
- vec3 colour = v_colour * shade(normal, lit, u_role_appearance[role].y);
13121
+ vec3 colour = v_colour * u_role_color_scale[role] * shade(normal, lit, u_role_appearance[role].y) * facadeShade(normal, role);
13010
13122
  if (emission > 0.0) {
13011
13123
  vec4 own = u_role_emission_colour[role];
13012
13124
  vec3 target = mix(v_colour, own.rgb, own.a);
@@ -13864,7 +13976,7 @@ function createTileflowBuildings3D(options) {
13864
13976
  let ahead = [0, -1];
13865
13977
  const scene = tileflowScene3D(map);
13866
13978
  let generation = 0;
13867
- let registered = false;
13979
+ let registered2 = false;
13868
13980
  let unregister = () => {
13869
13981
  };
13870
13982
  const models = createTileflowPlacedModels({
@@ -13913,7 +14025,7 @@ function createTileflowBuildings3D(options) {
13913
14025
  if (program) context.deleteProgram(program.program);
13914
14026
  for (const entry of linking ?? []) context.deleteProgram(entry.program);
13915
14027
  unregister();
13916
- registered = false;
14028
+ registered2 = false;
13917
14029
  scene.setReach(void 0);
13918
14030
  scene.release(context);
13919
14031
  if (ground) {
@@ -13944,12 +14056,12 @@ function createTileflowBuildings3D(options) {
13944
14056
  drawMasks(context, args);
13945
14057
  if (!programs.depth) return;
13946
14058
  if (!design().shadows || visibleScale() <= 0 && modelScale() <= 0) {
13947
- if (registered) unregister();
13948
- registered = false;
14059
+ if (registered2) unregister();
14060
+ registered2 = false;
13949
14061
  return;
13950
14062
  }
13951
- if (!registered) unregister = scene.register(caster);
13952
- registered = true;
14063
+ if (!registered2) unregister = scene.register(caster);
14064
+ registered2 = true;
13953
14065
  scene.prepare(context, lighting(), camera.metres);
13954
14066
  },
13955
14067
  render(context, args) {
@@ -14006,6 +14118,7 @@ function createTileflowBuildings3D(options) {
14006
14118
  return prepared ? { mesh: prepared.mesh, data: prepared.data } : emptyTile;
14007
14119
  },
14008
14120
  empty: emptyTile,
14121
+ isReady: (value) => value === emptyTile || value.gl !== void 0,
14009
14122
  release(value) {
14010
14123
  if (gl) release(gl, value);
14011
14124
  },
@@ -14066,7 +14179,7 @@ function createTileflowBuildings3D(options) {
14066
14179
  models.upload(context);
14067
14180
  if (modelKey !== models.key()) map.triggerRepaint();
14068
14181
  let budget = 2;
14069
- for (const { value: entry } of camera.ready()) {
14182
+ for (const { value: entry } of camera.built()) {
14070
14183
  if (entry.gl || !entry.data) continue;
14071
14184
  if (budget-- <= 0) {
14072
14185
  map.triggerRepaint();
@@ -14309,7 +14422,7 @@ function createTileflowBuildings3D(options) {
14309
14422
  for (const { x: x3, y: y2, value } of shown > 0 ? drawn() : []) {
14310
14423
  const offset = frame.offsetOf({ x: x3, y: y2 }, camera.zoom);
14311
14424
  const ring = ringIn(x3, y2);
14312
- if (!insideRing(ring, 0, 0, tileflowBuildingExtent, tileflowBuildingExtent)) continue;
14425
+ if (!insideRing2(ring, 0, 0, tileflowBuildingExtent, tileflowBuildingExtent)) continue;
14313
14426
  if (!buildingBoxVisible(frame.light.matrix, [
14314
14427
  (offset[0] - 1) * frame.metres,
14315
14428
  -(offset[1] + tileflowBuildingExtent + 1) * frame.metres,
@@ -14321,7 +14434,7 @@ function createTileflowBuildings3D(options) {
14321
14434
  continue;
14322
14435
  const ranges = buildingDrawRanges(
14323
14436
  value.mesh,
14324
- ({ bounds: [left, top, right, bottom, height] }) => insideRing(ring, left, top, right, bottom) && buildingBoxVisible(frame.light.matrix, [
14437
+ ({ bounds: [left, top, right, bottom, height] }) => insideRing2(ring, left, top, right, bottom) && buildingBoxVisible(frame.light.matrix, [
14325
14438
  (left + offset[0]) * frame.metres,
14326
14439
  -(bottom + offset[1]) * frame.metres,
14327
14440
  0,
@@ -14402,7 +14515,10 @@ function createTileflowBuildings3D(options) {
14402
14515
  return [ax - reach, ay - reach, Math.min(0, low), ax + reach, ay + reach, high + 0.1];
14403
14516
  }
14404
14517
  function modelView(model) {
14405
- return { camera: modelCamera(model) };
14518
+ return {
14519
+ camera: modelCamera(model),
14520
+ verticalFieldOfView: map.getVerticalFieldOfView?.()
14521
+ };
14406
14522
  }
14407
14523
  function levelOf(model) {
14408
14524
  return models.levelOf(model, modelView(model));
@@ -14524,12 +14640,14 @@ function createTileflowBuildings3D(options) {
14524
14640
  const gradients = new Float32Array(28);
14525
14641
  const powers = new Float32Array(7);
14526
14642
  const materialColours = new Float32Array(28);
14643
+ const colorScales = new Float32Array(7);
14527
14644
  const materials = new Float32Array(28);
14528
14645
  const appearance = new Float32Array(21);
14529
14646
  for (const [role, id] of Object.entries(tileflowModelLightingRoles)) {
14530
14647
  const from = themes[lower].modelLighting?.[role], to = themes[upper].modelLighting?.[role];
14531
14648
  const sampledFrom = sampleModelRole(from, `${identity}:${role}`);
14532
14649
  const sampledTo = sampleModelRole(to, `${identity}:${role}`);
14650
+ colorScales[id] = (from?.colorScale ?? 1) * (1 - mix2) + (to?.colorScale ?? 1) * mix2;
14533
14651
  appearance[id * 3] = (from?.shading === "map" ? 1 - mix2 : 0) + (to?.shading === "map" ? mix2 : 0);
14534
14652
  appearance[id * 3 + 1] = (from?.ambientOcclusion ?? 1) * (1 - mix2) + (to?.ambientOcclusion ?? 1) * mix2;
14535
14653
  appearance[id * 3 + 2] = (from?.partColorMix ?? 1) * (1 - mix2) + (to?.partColorMix ?? 1) * mix2;
@@ -14552,7 +14670,16 @@ function createTileflowBuildings3D(options) {
14552
14670
  gradients[id * 4 + component] = first[component] * (1 - mix2) + second[component] * mix2;
14553
14671
  powers[id] = first[4] * (1 - mix2) + second[4] * mix2;
14554
14672
  }
14555
- const result = { strengths, colours, gradients, powers, materialColours, materials, appearance };
14673
+ const result = {
14674
+ strengths,
14675
+ colours,
14676
+ gradients,
14677
+ powers,
14678
+ materialColours,
14679
+ colorScales,
14680
+ materials,
14681
+ appearance
14682
+ };
14556
14683
  if (modelLightingCache.size >= 1024)
14557
14684
  modelLightingCache.delete(modelLightingCache.keys().next().value);
14558
14685
  modelLightingCache.set(identity, result);
@@ -14621,7 +14748,7 @@ function createTileflowBuildings3D(options) {
14621
14748
  const bearing = map.getBearing() * Math.PI / 180;
14622
14749
  return [Math.sin(bearing), -Math.cos(bearing)];
14623
14750
  }
14624
- function insideRing(ring, left, top, right, bottom) {
14751
+ function insideRing2(ring, left, top, right, bottom) {
14625
14752
  const radius = ring[3];
14626
14753
  if (!(radius > 0)) return true;
14627
14754
  const cx = ring[0];
@@ -14640,7 +14767,7 @@ function createTileflowBuildings3D(options) {
14640
14767
  const reach = margin / camera.metres + 1;
14641
14768
  const ring = ringIn(tile.x, tile.y);
14642
14769
  const hazed = mercator && hazeDepth < Infinity;
14643
- const shows = (box) => (!mercator || buildingBoxVisible(data.mainMatrix, box)) && insideRing(ring, box[0], box[1], box[3], box[4]) && (!hazed || buildingBoxDepth(data.mainMatrix, box) < hazeDepth);
14770
+ const shows = (box) => (!mercator || buildingBoxVisible(data.mainMatrix, box)) && insideRing2(ring, box[0], box[1], box[3], box[4]) && (!hazed || buildingBoxDepth(data.mainMatrix, box) < hazeDepth);
14644
14771
  const extent5 = tileflowBuildingExtent + reach;
14645
14772
  if (!shows([-reach, -reach, 0, extent5, extent5, tile.value.mesh.top + 0.1])) return [];
14646
14773
  return buildingDrawRanges(
@@ -14687,20 +14814,21 @@ function createTileflowBuildings3D(options) {
14687
14814
  masks = {};
14688
14815
  const shown = visibleScale();
14689
14816
  const entries = variant === args.shaderData.variantName && shown > 0 && ground ? drawn() : [];
14690
- if (design().occlusion && entries.length > 0) {
14817
+ const contactRadius = mixed2((entry) => entry.groundOcclusionRadius ?? tileflowBuildingOcclusion.ground);
14818
+ if (design().occlusion && contactRadius > 0 && entries.length > 0) {
14691
14819
  const program = programs.contact;
14692
14820
  masks.contact = contactMask.render(context, () => {
14693
14821
  context.useProgram(program.program);
14694
14822
  context.uniform1f(program.uniforms.u_scale, shown);
14695
14823
  context.uniform1f(program.uniforms.u_metres, camera.metres);
14696
- context.uniform1f(program.uniforms.u_band, tileflowBuildingOcclusion.ground);
14824
+ context.uniform1f(program.uniforms.u_band, contactRadius);
14697
14825
  context.uniform1f(
14698
14826
  program.uniforms.u_band_strength,
14699
14827
  mixed2((entry) => entry.groundOcclusion ?? tileflowBuildingOcclusion.groundStrength) * visibleOpacity()
14700
14828
  );
14701
14829
  for (const tile of entries) {
14702
14830
  const { x: x3, y: y2, value } = tile;
14703
- const ranges = viewRanges(args, tile, tileflowBuildingOcclusion.ground, true);
14831
+ const ranges = viewRanges(args, tile, contactRadius, true);
14704
14832
  if (!ranges.length) continue;
14705
14833
  const { contact } = value.gl;
14706
14834
  project(context, program, args, x3, y2);
@@ -14908,6 +15036,12 @@ function createTileflowBuildings3D(options) {
14908
15036
  context.uniform3fv(m.u_sun_light, light.sunLight);
14909
15037
  context.uniform3fv(m.u_sky_light, light.skyLight);
14910
15038
  context.uniform1f(m.u_night, light.night);
15039
+ context.uniform3f(
15040
+ m.u_facade_shading,
15041
+ mixed2((entry) => entry.verticalGradient ? 1 : 0),
15042
+ occlusionOn ? mixed2((entry) => entry.groundOcclusion ?? 0.16) : 0,
15043
+ mixed2((entry) => entry.groundOcclusionRadius ?? 3)
15044
+ );
14911
15045
  context.uniform1f(
14912
15046
  m.u_ambient_occlusion,
14913
15047
  occlusionOn ? mixed2((entry) => entry.modelOcclusion ?? 0.75) : 0
@@ -14924,6 +15058,7 @@ function createTileflowBuildings3D(options) {
14924
15058
  context.uniform4fv(m.u_role_emission_gradient, emission.gradients);
14925
15059
  context.uniform1fv(m.u_role_emission_power, emission.powers);
14926
15060
  context.uniform4fv(m.u_role_colour, emission.materialColours);
15061
+ context.uniform1fv(m.u_role_color_scale, emission.colorScales);
14927
15062
  context.uniform4fv(m.u_role_material, emission.materials);
14928
15063
  context.uniform3fv(m.u_role_appearance, emission.appearance);
14929
15064
  const at = placed2(stand.tileX, stand.tileY);
@@ -16476,6 +16611,7 @@ uniform float u_metres; // metres per tile unit
16476
16611
  uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
16477
16612
  uniform float u_minimum_height; // optional visual height floor, in metres
16478
16613
  uniform vec2 u_size_scale; // the map's height and crown scales, for this form
16614
+ uniform vec3 u_size_compression; // reference height, reference crown, strength
16479
16615
  uniform float u_round; // how far normals turn from the facets to the round shape, by finish
16480
16616
 
16481
16617
  float growthOf() {
@@ -16492,7 +16628,14 @@ vec2 turned(vec2 v) {
16492
16628
 
16493
16629
  vec2 displaySize() {
16494
16630
  vec2 size = a_tree_size * 0.1 * u_size_scale;
16495
- return size * max(1.0, u_minimum_height / max(size.x, 0.001));
16631
+ size *= max(1.0, u_minimum_height / max(size.x, 0.001));
16632
+ // Scale the complete tree together to preserve crown, trunk and branch proportions.
16633
+ if (u_size_compression.z > 0.0) {
16634
+ vec2 relative = max(u_size_compression.xy, vec2(0.001)) / max(size, vec2(0.001));
16635
+ // Balance height and footprint, so a short but broad crown is not enlarged.
16636
+ size *= min(1.35, pow(relative.x * relative.y, u_size_compression.z * 0.5));
16637
+ }
16638
+ return size;
16496
16639
  }
16497
16640
 
16498
16641
  vec3 standing(float growth) {
@@ -16773,7 +16916,7 @@ function createTileflowTrees3D(options) {
16773
16916
  let disposed = false;
16774
16917
  let drawnLast = 0;
16775
16918
  let generation = 0;
16776
- let registered = false;
16919
+ let registered2 = false;
16777
16920
  let unregister = () => {
16778
16921
  };
16779
16922
  const scene = tileflowScene3D(map);
@@ -17038,7 +17181,9 @@ function createTileflowTrees3D(options) {
17038
17181
  forms: tileflowTreeForms.map((form) => [
17039
17182
  theme?.forms[form]?.heightScale ?? 1,
17040
17183
  theme?.forms[form]?.crownScale ?? 1,
17041
- 0
17184
+ theme?.forms[form]?.sizeAnchor ?? 8.5,
17185
+ theme?.forms[form]?.crownAnchor ?? 5,
17186
+ theme?.forms[form]?.sizeCompression ?? 0
17042
17187
  ]),
17043
17188
  edges: [[theme?.edges ?? 0, 0, 0]],
17044
17189
  edgeColor: [[...rgb(theme?.edgeColor ?? "#000000") ?? [0, 0, 0]]],
@@ -17063,6 +17208,12 @@ function createTileflowTrees3D(options) {
17063
17208
  [size[0] * forms[index][0], size[1] * forms[index][1]]
17064
17209
  ])
17065
17210
  ),
17211
+ compressions: Object.fromEntries(
17212
+ tileflowTreeForms.map((form, index) => [
17213
+ form,
17214
+ [forms[index][2], forms[index][3], forms[index][4]]
17215
+ ])
17216
+ ),
17066
17217
  finish: (t < 0.5 ? a : b2)?.finish ?? "faceted",
17067
17218
  edges: mixList(x3.edges, y2.edges)[0][0],
17068
17219
  edgeColor: mixList(x3.edgeColor, y2.edgeColor)[0],
@@ -17099,17 +17250,21 @@ function createTileflowTrees3D(options) {
17099
17250
  tallest = Math.max(tallest, value.placement.tallest);
17100
17251
  }
17101
17252
  if (!Number.isFinite(left)) return void 0;
17102
- const size = colours().size;
17253
+ const palette2 = colours();
17254
+ const maximumGrowth = Object.values(palette2.compressions).some(
17255
+ ([, , strength]) => strength > 0
17256
+ ) ? 1.35 : 1;
17257
+ const maximumScale = maximumGrowth > 1 ? Math.max(...Object.values(palette2.sizes).map((size) => size[0])) : palette2.size[0];
17103
17258
  return {
17104
17259
  zoom: preferredZoom3,
17105
17260
  tiles: [left, top, right, bottom],
17106
- tallest: Math.max(tallest * size[0], colours().minimumHeight) * shown
17261
+ tallest: Math.max(tallest * maximumScale, palette2.minimumHeight) * maximumGrowth * shown
17107
17262
  };
17108
17263
  },
17109
17264
  // Camera-dependent density, detail and fading also change the trees casting shadows.
17110
17265
  key: () => `trees:${colours().minimumHeight.toFixed(3)}:${map.isMoving?.() ? view().movingKey : view().key}:${fadeIn().toFixed(4)}:${visibleScale().toFixed(4)}:${generation}:${programs.depth ? 1 : 0}:${Object.values(
17111
17266
  colours().sizes
17112
- ).flat().map((value) => value.toFixed(3)).join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
17267
+ ).flat().map((value) => value.toFixed(3)).join()}:${Object.values(colours().compressions).flat().join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
17113
17268
  drawDepth(context, frame) {
17114
17269
  const program = programs.depth;
17115
17270
  if (!program || !meshes) return;
@@ -17119,6 +17274,7 @@ function createTileflowTrees3D(options) {
17119
17274
  context.uniform1f(u.u_metres, frame.metres);
17120
17275
  context.uniformMatrix4fv(u.u_light_matrix, false, frame.light.matrix);
17121
17276
  const sizes = colours().sizes;
17277
+ const compressions = colours().compressions;
17122
17278
  const minimumHeight = colours().minimumHeight;
17123
17279
  const camera = view();
17124
17280
  context.uniform1f(u.u_fade, 1);
@@ -17139,12 +17295,14 @@ function createTileflowTrees3D(options) {
17139
17295
  const drawing = value.gl.vaos.get(`${form}:${model}:${selection.level}`);
17140
17296
  if (instances === 0 || !drawing) return;
17141
17297
  context.uniform2f(u.u_size_scale, sizes[form][0], sizes[form][1] * drawing.crown);
17298
+ context.uniform3f(u.u_size_compression, ...compressions[form]);
17142
17299
  context.bindVertexArray(drawing.vao);
17143
17300
  context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
17144
17301
  });
17145
17302
  const hedge = value.gl.hedge;
17146
17303
  if (hedge) {
17147
17304
  context.uniform1f(u.u_minimum_height, 0);
17305
+ context.uniform3f(u.u_size_compression, 1, 1, 0);
17148
17306
  context.uniform2f(u.u_size_scale, 1, 1);
17149
17307
  context.bindVertexArray(hedge.vao);
17150
17308
  context.drawArraysInstanced(
@@ -17230,6 +17388,7 @@ function createTileflowTrees3D(options) {
17230
17388
  ];
17231
17389
  context.uniform1f(u.u_minimum_height, palette2.minimumHeight);
17232
17390
  context.uniform2f(u.u_size_scale, ...size);
17391
+ context.uniform3f(u.u_size_compression, ...palette2.compressions[form]);
17233
17392
  context.bindVertexArray(drawing.vao);
17234
17393
  context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
17235
17394
  count += instances;
@@ -17240,6 +17399,7 @@ function createTileflowTrees3D(options) {
17240
17399
  leaves,
17241
17400
  size,
17242
17401
  minimumHeight: palette2.minimumHeight,
17402
+ compression: palette2.compressions[form],
17243
17403
  instances,
17244
17404
  drawing
17245
17405
  });
@@ -17250,6 +17410,7 @@ function createTileflowTrees3D(options) {
17250
17410
  const instances = value.placement.hedges.length / tileflowTreeBytes;
17251
17411
  context.uniform3fv(u.u_leaves, palette2.hedge.flat());
17252
17412
  context.uniform1f(u.u_minimum_height, 0);
17413
+ context.uniform3f(u.u_size_compression, 1, 1, 0);
17253
17414
  context.uniform2f(u.u_size_scale, 1, 1);
17254
17415
  context.bindVertexArray(hedge.vao);
17255
17416
  context.drawArraysInstanced(context.TRIANGLES, 0, hedge.count, instances);
@@ -17260,6 +17421,7 @@ function createTileflowTrees3D(options) {
17260
17421
  leaves: palette2.hedge,
17261
17422
  size: [1, 1],
17262
17423
  minimumHeight: 0,
17424
+ compression: [1, 1, 0],
17263
17425
  instances,
17264
17426
  drawing: hedge
17265
17427
  });
@@ -17302,6 +17464,7 @@ function createTileflowTrees3D(options) {
17302
17464
  );
17303
17465
  context.uniform1f(e.u_minimum_height, draw2.minimumHeight);
17304
17466
  context.uniform2f(e.u_size_scale, ...draw2.size);
17467
+ context.uniform3f(e.u_size_compression, ...draw2.compression);
17305
17468
  context.bindVertexArray(draw2.drawing.vao);
17306
17469
  context.drawArraysInstanced(context.TRIANGLES, 0, draw2.drawing.count, draw2.instances);
17307
17470
  }
@@ -17490,7 +17653,7 @@ ${shaderData.define}`;
17490
17653
  context.deleteBuffer(ground.vbo);
17491
17654
  }
17492
17655
  unregister();
17493
- registered = false;
17656
+ registered2 = false;
17494
17657
  scene.release(context);
17495
17658
  programs = {};
17496
17659
  meshes = void 0;
@@ -17503,8 +17666,8 @@ ${shaderData.define}`;
17503
17666
  if (!isWebGL23(context)) return;
17504
17667
  ensureTiles();
17505
17668
  if (!programs.depth) return;
17506
- if (!registered) unregister = scene.register(caster);
17507
- registered = true;
17669
+ if (!registered2) unregister = scene.register(caster);
17670
+ registered2 = true;
17508
17671
  const metres = tiles[0]?.metres ?? 1;
17509
17672
  scene.prepare(context, tileflowSceneLight(sunNow()), metres);
17510
17673
  },
@@ -19636,6 +19799,320 @@ function createChannel() {
19636
19799
  return `bridge_${Date.now().toString(36)}_${channelSequence.toString(36)}`;
19637
19800
  }
19638
19801
 
19802
+ // src/path-ground-geometry.ts
19803
+ var coverClasses = /* @__PURE__ */ new Set(["grass", "wood", "forest", "wetland"]);
19804
+ var useClasses = /* @__PURE__ */ new Set(["cemetery", "pitch", "track", "playground", "zoo"]);
19805
+ var pathClasses = /* @__PURE__ */ new Set([
19806
+ "footway",
19807
+ "path",
19808
+ "bridleway",
19809
+ "corridor",
19810
+ "pedestrian",
19811
+ "steps",
19812
+ "cycleway"
19813
+ ]);
19814
+ function deriveTileflowGreenPaths(bytes, bindings) {
19815
+ const tile = decodeTileflowVectorTile(bytes, {
19816
+ layers: [bindings.road, bindings.landcover, bindings.landuse]
19817
+ });
19818
+ const road = tile[bindings.road];
19819
+ if (!road) return encodeLines(bindings.road, 4096, []);
19820
+ const polygons = [];
19821
+ for (const name of [bindings.landcover, bindings.landuse]) {
19822
+ const layer = tile[name];
19823
+ if (!layer) continue;
19824
+ for (const feature of layer.features) {
19825
+ const kind = String(feature.properties[bindings.class]);
19826
+ const subclass = String(feature.properties[bindings.subclass]);
19827
+ const green = name === bindings.landcover ? coverClasses.has(kind) || kind === "farmland" && ["orchard", "plant_nursery"].includes(subclass) : useClasses.has(kind);
19828
+ if (feature.type !== "Polygon" || !green) continue;
19829
+ let current;
19830
+ for (const raw of feature.geometry) {
19831
+ const ring = raw.map((n) => n * road.extent / layer.extent);
19832
+ if (signedArea2(ring) > 0 || !current) {
19833
+ current = [ring];
19834
+ polygons.push({ rings: current, bounds: boundsOf2(ring) });
19835
+ } else current.push(ring);
19836
+ }
19837
+ }
19838
+ }
19839
+ const features = [];
19840
+ for (const feature of road.features) {
19841
+ const p = feature.properties;
19842
+ if (feature.type !== "LineString" || !["path", "path_construction"].includes(String(p[bindings.class])) || !pathClasses.has(String(p[bindings.subclass])) || ["bridge", "tunnel"].includes(String(p[bindings.brunnel])))
19843
+ continue;
19844
+ const geometry2 = feature.geometry.flatMap((line) => clipLineToGreen(line, polygons));
19845
+ if (geometry2.length) features.push({ ...feature, geometry: geometry2 });
19846
+ }
19847
+ return encodeLines(bindings.road, road.extent, features);
19848
+ }
19849
+ function signedArea2(ring) {
19850
+ let area3 = 0;
19851
+ for (let i2 = 0, j2 = ring.length - 2; i2 < ring.length; j2 = i2, i2 += 2)
19852
+ area3 += ring[j2] * ring[i2 + 1] - ring[i2] * ring[j2 + 1];
19853
+ return area3 / 2;
19854
+ }
19855
+ function boundsOf2(line) {
19856
+ const box = [Infinity, Infinity, -Infinity, -Infinity];
19857
+ for (let i2 = 0; i2 < line.length; i2 += 2) {
19858
+ box[0] = Math.min(box[0], line[i2]);
19859
+ box[1] = Math.min(box[1], line[i2 + 1]);
19860
+ box[2] = Math.max(box[2], line[i2]);
19861
+ box[3] = Math.max(box[3], line[i2 + 1]);
19862
+ }
19863
+ return box;
19864
+ }
19865
+ function overlaps(a, b2) {
19866
+ return a[0] <= b2[2] && a[2] >= b2[0] && a[1] <= b2[3] && a[3] >= b2[1];
19867
+ }
19868
+ function insideRing(point, ring) {
19869
+ const [x3, y2] = point;
19870
+ let inside2 = false;
19871
+ for (let i2 = 0, j2 = ring.length - 2; i2 < ring.length; j2 = i2, i2 += 2) {
19872
+ const ax = ring[j2], ay = ring[j2 + 1], bx = ring[i2], by = ring[i2 + 1];
19873
+ const cross = (x3 - ax) * (by - ay) - (y2 - ay) * (bx - ax);
19874
+ if (Math.abs(cross) < 1e-7 && x3 >= Math.min(ax, bx) && x3 <= Math.max(ax, bx) && y2 >= Math.min(ay, by) && y2 <= Math.max(ay, by))
19875
+ return true;
19876
+ if (ay > y2 !== by > y2 && x3 < (bx - ax) * (y2 - ay) / (by - ay) + ax) inside2 = !inside2;
19877
+ }
19878
+ return inside2;
19879
+ }
19880
+ function clipLineToGreen(line, all) {
19881
+ const polygons = all.filter((polygon) => overlaps(boundsOf2(line), polygon.bounds));
19882
+ if (!polygons.length) return [];
19883
+ const output = [];
19884
+ let active;
19885
+ for (let i2 = 2; i2 < line.length; i2 += 2) {
19886
+ const ax = line[i2 - 2], ay = line[i2 - 1], dx = line[i2] - ax, dy = line[i2 + 1] - ay;
19887
+ if (dx === 0 && dy === 0) continue;
19888
+ const cuts = [0, 1];
19889
+ for (const polygon of polygons)
19890
+ for (const ring of polygon.rings)
19891
+ for (let k = 0, j2 = ring.length - 2; k < ring.length; j2 = k, k += 2) {
19892
+ const bx = ring[j2], by = ring[j2 + 1], ex = ring[k] - bx, ey = ring[k + 1] - by;
19893
+ const denominator = dx * ey - dy * ex;
19894
+ if (Math.abs(denominator) < 1e-10) continue;
19895
+ const t = ((bx - ax) * ey - (by - ay) * ex) / denominator;
19896
+ const u = ((bx - ax) * dy - (by - ay) * dx) / denominator;
19897
+ if (t > 0 && t < 1 && u >= 0 && u <= 1) cuts.push(t);
19898
+ }
19899
+ cuts.sort((a, b2) => a - b2);
19900
+ for (let k = 1; k < cuts.length; k++) {
19901
+ const lo = cuts[k - 1], hi = cuts[k];
19902
+ if (hi - lo < 1e-9) continue;
19903
+ const mid = (lo + hi) / 2;
19904
+ const point = [ax + dx * mid, ay + dy * mid];
19905
+ const inside2 = polygons.some(
19906
+ (p) => insideRing(point, p.rings[0]) && !p.rings.slice(1).some((hole) => insideRing(point, hole))
19907
+ );
19908
+ if (!inside2) {
19909
+ active = void 0;
19910
+ continue;
19911
+ }
19912
+ const start = [Math.round(ax + dx * lo), Math.round(ay + dy * lo)];
19913
+ const end = [Math.round(ax + dx * hi), Math.round(ay + dy * hi)];
19914
+ if (start[0] === end[0] && start[1] === end[1]) continue;
19915
+ if (!active || active.at(-2) !== start[0] || active.at(-1) !== start[1]) {
19916
+ active = [...start];
19917
+ output.push(active);
19918
+ }
19919
+ active.push(...end);
19920
+ }
19921
+ }
19922
+ return output;
19923
+ }
19924
+ var Writer = class {
19925
+ bytes = [];
19926
+ uint(n) {
19927
+ while (n > 127) {
19928
+ this.bytes.push(n % 128 | 128);
19929
+ n = Math.floor(n / 128);
19930
+ }
19931
+ this.bytes.push(n);
19932
+ }
19933
+ field(tag, value) {
19934
+ this.uint(tag * 8);
19935
+ this.uint(value);
19936
+ }
19937
+ message(tag, value) {
19938
+ this.uint(tag * 8 + 2);
19939
+ this.uint(value.length);
19940
+ for (const n of value) this.bytes.push(n);
19941
+ }
19942
+ text(tag, value) {
19943
+ this.message(tag, new TextEncoder().encode(value));
19944
+ }
19945
+ };
19946
+ function zigzag2(n) {
19947
+ return n < 0 ? -n * 2 - 1 : n * 2;
19948
+ }
19949
+ function encodeLines(name, extent5, features) {
19950
+ const layer = new Writer();
19951
+ layer.text(1, name);
19952
+ const keys = [];
19953
+ const values = [];
19954
+ const keyMap = /* @__PURE__ */ new Map(), valueMap = /* @__PURE__ */ new Map();
19955
+ for (const feature of features) {
19956
+ const message = new Writer(), tags = new Writer(), geometry2 = new Writer();
19957
+ if (feature.id !== void 0) message.field(1, feature.id);
19958
+ for (const [key, value] of Object.entries(feature.properties)) {
19959
+ if (!keyMap.has(key)) {
19960
+ keyMap.set(key, keys.length);
19961
+ keys.push(key);
19962
+ }
19963
+ const identity = typeof value + ":" + value;
19964
+ if (!valueMap.has(identity)) {
19965
+ valueMap.set(identity, values.length);
19966
+ values.push(value);
19967
+ }
19968
+ tags.uint(keyMap.get(key));
19969
+ tags.uint(valueMap.get(identity));
19970
+ }
19971
+ message.message(2, tags.bytes);
19972
+ message.field(3, feature.type === "Polygon" ? 3 : 2);
19973
+ let x3 = 0, y2 = 0;
19974
+ for (const raw of feature.geometry) {
19975
+ const points = feature.type === "Polygon" && raw[0] === raw.at(-2) && raw[1] === raw.at(-1) ? raw.slice(0, -2) : raw;
19976
+ if (points.length < 4) continue;
19977
+ geometry2.uint(9);
19978
+ geometry2.uint(zigzag2(Math.round(points[0]) - x3));
19979
+ geometry2.uint(zigzag2(Math.round(points[1]) - y2));
19980
+ x3 = Math.round(points[0]);
19981
+ y2 = Math.round(points[1]);
19982
+ geometry2.uint((points.length / 2 - 1) * 8 + 2);
19983
+ for (let i2 = 2; i2 < points.length; i2 += 2) {
19984
+ const nx = Math.round(points[i2]), ny = Math.round(points[i2 + 1]);
19985
+ geometry2.uint(zigzag2(nx - x3));
19986
+ geometry2.uint(zigzag2(ny - y2));
19987
+ x3 = nx;
19988
+ y2 = ny;
19989
+ }
19990
+ if (feature.type === "Polygon") geometry2.uint(15);
19991
+ }
19992
+ message.message(4, geometry2.bytes);
19993
+ layer.message(2, message.bytes);
19994
+ }
19995
+ for (const key of keys) layer.text(3, key);
19996
+ for (const value of values) {
19997
+ const message = new Writer();
19998
+ if (typeof value === "string") message.text(1, value);
19999
+ else if (typeof value === "boolean") message.field(7, value ? 1 : 0);
20000
+ else if (Number.isSafeInteger(value)) {
20001
+ message.field(value < 0 ? 6 : 4, value < 0 ? zigzag2(value) : value);
20002
+ } else {
20003
+ message.uint(25);
20004
+ const b2 = new Uint8Array(8);
20005
+ new DataView(b2.buffer).setFloat64(0, value, true);
20006
+ message.bytes.push(...b2);
20007
+ }
20008
+ layer.message(4, message.bytes);
20009
+ }
20010
+ layer.field(5, extent5);
20011
+ layer.field(15, 2);
20012
+ const tile = new Writer();
20013
+ tile.message(3, layer.bytes);
20014
+ return new Uint8Array(tile.bytes);
20015
+ }
20016
+
20017
+ // src/path-ground-protocol.ts
20018
+ var tileflowPathGroundProtocol = "tileflow-path-ground";
20019
+ function pathGroundProtocolUrl(source, tile = false) {
20020
+ return `${tileflowPathGroundProtocol}://source/${tile ? "{z}/{x}/{y}.pbf" : "index.json"}?source=${encodeURIComponent(JSON.stringify(source))}`;
20021
+ }
20022
+ function parsePathGroundRequest(value) {
20023
+ if (value.length > 16e3) throw new Error("Path context URL is too long");
20024
+ const url = new URL(value);
20025
+ if (url.protocol !== `${tileflowPathGroundProtocol}:` || url.hostname !== "source" || url.username || url.password || url.hash)
20026
+ throw new Error("Invalid path context URL");
20027
+ const source = JSON.parse(url.searchParams.get("source") ?? "null");
20028
+ if (!source || !["road", "landcover", "landuse", "class", "subclass", "brunnel"].every(
20029
+ (k) => typeof source[k] === "string"
20030
+ ))
20031
+ throw new Error("Invalid path context bindings");
20032
+ if (!source.url && !source.tiles?.length) throw new Error("Missing path context source");
20033
+ for (const endpoint of [source.url, ...source.tiles ?? []].filter((s) => !!s)) {
20034
+ const u = new URL(
20035
+ endpoint.replaceAll("{z}", "0").replaceAll("{x}", "0").replaceAll("{y}", "0")
20036
+ );
20037
+ if (!["https:", "http:"].includes(u.protocol) || u.username || u.password)
20038
+ throw new Error("Path context requires an HTTP(S) vector source");
20039
+ }
20040
+ if (url.pathname === "/index.json") return { source };
20041
+ const match = /^\/(\d{1,2})\/(\d+)\/(\d+)\.pbf$/.exec(url.pathname);
20042
+ if (!match) throw new Error("Invalid path context tile");
20043
+ const [z2, x3, y2] = match.slice(1).map(Number);
20044
+ if (z2 < 0 || z2 > 24 || x3 < 0 || y2 < 0 || x3 >= 2 ** z2 || y2 >= 2 ** z2)
20045
+ throw new Error("Invalid path context coordinates");
20046
+ return { source, tile: { z: z2, x: x3, y: y2 } };
20047
+ }
20048
+
20049
+ // src/path-ground-browser.ts
20050
+ var registered = /* @__PURE__ */ new WeakSet();
20051
+ function registerTileflowPathGroundProtocol(registry, options = {}) {
20052
+ if (registered.has(registry.addProtocol)) return;
20053
+ const request = options.fetch ?? globalThis.fetch;
20054
+ const transform = options.transformUrl ?? ((url) => url);
20055
+ const descriptions = /* @__PURE__ */ new Map();
20056
+ const tiles = /* @__PURE__ */ new Map();
20057
+ let cacheBytes = 0;
20058
+ async function description(source, signal) {
20059
+ if (!source.url)
20060
+ return { tiles: source.tiles, minzoom: source.minzoom, maxzoom: source.maxzoom };
20061
+ const previous = descriptions.get(source.url);
20062
+ if (previous) return previous;
20063
+ const response = await request(transform(source.url), { signal });
20064
+ if (!response.ok) throw new Error(`Path context TileJSON: HTTP ${response.status}`);
20065
+ const json = await response.json();
20066
+ if (!Array.isArray(json.tiles) || !json.tiles.length || json.tiles.some((url) => typeof url !== "string"))
20067
+ throw new Error("Path context TileJSON has no tile templates");
20068
+ const result = {
20069
+ ...json,
20070
+ tiles: json.tiles.map(
20071
+ (url) => new URL(url, source.url).href.replaceAll("%7B", "{").replaceAll("%7D", "}")
20072
+ )
20073
+ };
20074
+ if (descriptions.size >= 16) descriptions.delete(descriptions.keys().next().value);
20075
+ descriptions.set(source.url, result);
20076
+ return result;
20077
+ }
20078
+ registry.addProtocol(tileflowPathGroundProtocol, async (input, abort) => {
20079
+ const { source, tile } = parsePathGroundRequest(input.url);
20080
+ const signal = abort.signal;
20081
+ signal.throwIfAborted();
20082
+ const json = await description(source, signal);
20083
+ if (!tile)
20084
+ return {
20085
+ data: {
20086
+ tiles: [pathGroundProtocolUrl(source, true)],
20087
+ minzoom: Math.max(12, json.minzoom ?? 0),
20088
+ maxzoom: json.maxzoom ?? source.maxzoom ?? 15,
20089
+ ...json.attribution ? { attribution: json.attribution } : {}
20090
+ }
20091
+ };
20092
+ const cached = tiles.get(input.url);
20093
+ if (cached) return { data: cached.slice().buffer };
20094
+ const y2 = json.scheme === "tms" ? 2 ** tile.z - 1 - tile.y : tile.y;
20095
+ const url = json.tiles[0].replaceAll("{z}", String(tile.z)).replaceAll("{x}", String(tile.x)).replaceAll("{y}", String(y2));
20096
+ if (!/^https?:\/\//.test(url))
20097
+ throw new Error("Path context requires an HTTP(S) tile template");
20098
+ const response = await request(transform(url), { signal });
20099
+ if (!response.ok) throw new Error(`Path context tile: HTTP ${response.status}`);
20100
+ const bytes = new Uint8Array(await response.arrayBuffer());
20101
+ if (bytes.byteLength > 16 * 1024 * 1024) throw new Error("Path context tile exceeds 16 MiB");
20102
+ signal.throwIfAborted();
20103
+ const result = deriveTileflowGreenPaths(bytes, source);
20104
+ while (tiles.size && (tiles.size >= 64 || cacheBytes + result.byteLength > 16 * 1024 * 1024)) {
20105
+ const key = tiles.keys().next().value;
20106
+ cacheBytes -= tiles.get(key).byteLength;
20107
+ tiles.delete(key);
20108
+ }
20109
+ tiles.set(input.url, result);
20110
+ cacheBytes += result.byteLength;
20111
+ return { data: result.slice().buffer };
20112
+ });
20113
+ registered.add(registry.addProtocol);
20114
+ }
20115
+
19639
20116
  // src/terrain/contour-protocol.ts
19640
20117
  var tileflowContourProtocol = "tileflow-contour";
19641
20118
  var tileflowContourSourceLayer = "contours";
@@ -20026,6 +20503,130 @@ function createTileflowVegetation(options) {
20026
20503
  };
20027
20504
  }
20028
20505
 
20506
+ // src/building-flat-layers-browser.ts
20507
+ function createBuildingFlatLayers(map) {
20508
+ const saved = /* @__PURE__ */ new Map();
20509
+ let updating = false;
20510
+ function restore() {
20511
+ if (!map.setLayoutProperty || !map.getLayoutProperty || updating) return;
20512
+ updating = true;
20513
+ try {
20514
+ for (const [id, { visibility, layer }] of saved)
20515
+ if (map.getLayer(id) === layer && map.getLayoutProperty(id, "visibility") !== visibility)
20516
+ map.setLayoutProperty(id, "visibility", visibility);
20517
+ saved.clear();
20518
+ } finally {
20519
+ updating = false;
20520
+ }
20521
+ }
20522
+ return {
20523
+ update(layers, hidden) {
20524
+ if (updating || !map.setLayoutProperty || !map.getLayoutProperty) return;
20525
+ if (!hidden || layers.length === 0) {
20526
+ restore();
20527
+ return;
20528
+ }
20529
+ updating = true;
20530
+ try {
20531
+ const authored = new Map(layers.map((layer) => [layer.id, layer.visible]));
20532
+ const ids = map.getLayersOrder?.() ?? (map.getStyle()?.layers ?? []).map(({ id }) => id);
20533
+ for (const id of ids) {
20534
+ const visible = authored.get(id.split("::")[0]);
20535
+ if (visible === void 0 || !map.getLayer(id)) continue;
20536
+ const current = map.getLayoutProperty(id, "visibility") ?? "visible";
20537
+ if (!saved.has(id) || saved.get(id).layer !== map.getLayer(id))
20538
+ saved.set(id, { visibility: visible ? current : "none", layer: map.getLayer(id) });
20539
+ if (current !== "none") map.setLayoutProperty(id, "visibility", "none");
20540
+ }
20541
+ } finally {
20542
+ updating = false;
20543
+ }
20544
+ },
20545
+ restore,
20546
+ /** Removing a map must not write to its destroyed style. */
20547
+ forget() {
20548
+ saved.clear();
20549
+ }
20550
+ };
20551
+ }
20552
+
20553
+ // src/camera.ts
20554
+ var tileflowCameraMetadataKey = "tileflow:camera";
20555
+ function readTileflowCamera(metadata) {
20556
+ if (!metadata || typeof metadata !== "object") return {};
20557
+ const value = metadata[tileflowCameraMetadataKey];
20558
+ if (!value || typeof value !== "object") return {};
20559
+ const policy = value;
20560
+ return policy.version === 1 && typeof policy.adaptivePerspective === "boolean" ? { adaptivePerspective: policy.adaptivePerspective } : {};
20561
+ }
20562
+
20563
+ // src/camera-browser.ts
20564
+ function tileflowAdaptiveFieldOfView(pitch, zoom, height, normalFieldOfView) {
20565
+ if (pitch >= 15 || zoom <= 13 || height <= 0) return normalFieldOfView;
20566
+ const tangent = Math.tan(normalFieldOfView * Math.PI / 360);
20567
+ const distance = height / (2 * tangent);
20568
+ const mix2 = (Math.max(0, pitch) / 15) ** 5;
20569
+ const nearTangent = Math.max(
20570
+ Math.tan(Math.min(6, normalFieldOfView) * Math.PI / 360),
20571
+ height * mix2 / (2 * (1 - mix2 + mix2 * distance))
20572
+ );
20573
+ const t = Math.min(1, Math.max(0, (zoom - 13) / 2));
20574
+ const amount = t * t * (3 - 2 * t);
20575
+ return Math.atan(tangent + (nearTangent - tangent) * amount) * 360 / Math.PI;
20576
+ }
20577
+ function createTileflowAdaptiveCamera(map) {
20578
+ let normal;
20579
+ let applying = false;
20580
+ let disposed = false;
20581
+ const write = (next) => {
20582
+ if (applying || Math.abs((map.getVerticalFieldOfView?.() ?? next) - next) < 1e-6) return;
20583
+ applying = true;
20584
+ try {
20585
+ map.setVerticalFieldOfView?.(next);
20586
+ } finally {
20587
+ applying = false;
20588
+ }
20589
+ };
20590
+ const update = () => {
20591
+ if (disposed || applying || normal === void 0) return;
20592
+ write(
20593
+ tileflowAdaptiveFieldOfView(
20594
+ map.getPitch(),
20595
+ map.getZoom(),
20596
+ map.getCanvas().clientHeight,
20597
+ normal
20598
+ )
20599
+ );
20600
+ };
20601
+ const setEnabled = (enabled) => {
20602
+ if (disposed) return;
20603
+ if (enabled) {
20604
+ if (!map.getVerticalFieldOfView || !map.setVerticalFieldOfView || !map.getCanvas) return;
20605
+ normal ??= map.getVerticalFieldOfView();
20606
+ update();
20607
+ } else if (normal !== void 0) {
20608
+ const restore = normal;
20609
+ normal = void 0;
20610
+ write(restore);
20611
+ }
20612
+ };
20613
+ const onRemove = () => dispose(false);
20614
+ function dispose(restore = true) {
20615
+ if (disposed) return;
20616
+ if (restore) setEnabled(false);
20617
+ disposed = true;
20618
+ map.off("pitch", update);
20619
+ map.off("zoom", update);
20620
+ map.off("resize", update);
20621
+ map.off("remove", onRemove);
20622
+ }
20623
+ map.on("pitch", update);
20624
+ map.on("zoom", update);
20625
+ map.on("resize", update);
20626
+ map.on("remove", onRemove);
20627
+ return { setEnabled, dispose };
20628
+ }
20629
+
20029
20630
  // src/map-3d-attach-browser.ts
20030
20631
  var tileflowMap3DMetadataKeys = Object.freeze([
20031
20632
  tileflowBuildingsMetadataKey,
@@ -20051,6 +20652,7 @@ function attachTileflowMap3D(options) {
20051
20652
  const { map, load, onError, ...sceneOptions } = options;
20052
20653
  let viewMode = options.viewMode ?? "3d";
20053
20654
  let vegetation = options.vegetation;
20655
+ let adaptivePerspective = options.camera?.adaptivePerspective;
20054
20656
  let scene;
20055
20657
  let loading = false;
20056
20658
  let disposed = false;
@@ -20066,7 +20668,13 @@ function attachTileflowMap3D(options) {
20066
20668
  stopWatching();
20067
20669
  load().then(({ createTileflowMap3D: createTileflowMap3D2 }) => {
20068
20670
  if (disposed) return;
20069
- scene = createTileflowMap3D2({ ...sceneOptions, map, viewMode, vegetation });
20671
+ scene = createTileflowMap3D2({
20672
+ ...sceneOptions,
20673
+ map,
20674
+ viewMode,
20675
+ vegetation,
20676
+ camera: { adaptivePerspective }
20677
+ });
20070
20678
  }).catch((error) => {
20071
20679
  if (!disposed) onError?.(error);
20072
20680
  });
@@ -20084,28 +20692,36 @@ function attachTileflowMap3D(options) {
20084
20692
  if (disposed) return;
20085
20693
  disposed = true;
20086
20694
  stopWatching();
20087
- map.off("remove", dispose);
20695
+ map.off("remove", onRemove);
20088
20696
  scene?.dispose();
20089
20697
  scene = void 0;
20090
20698
  }
20699
+ function onRemove() {
20700
+ scene = void 0;
20701
+ dispose();
20702
+ }
20091
20703
  map.on("styledata", restyle);
20092
20704
  map.on("style.load", restyle);
20093
20705
  map.on("idle", check);
20094
- map.on("remove", dispose);
20706
+ map.on("remove", onRemove);
20095
20707
  check();
20096
20708
  return {
20097
20709
  get scene() {
20098
20710
  return scene;
20099
20711
  },
20100
- setViewMode(mode) {
20712
+ setViewMode(mode, change) {
20101
20713
  if (mode === viewMode) return;
20102
20714
  viewMode = mode;
20103
- if (scene) void (mode === "3d" ? scene.show() : scene.hide());
20715
+ if (scene) void (mode === "3d" ? scene.show(change) : scene.hide(change));
20104
20716
  },
20105
20717
  setVegetation(visible) {
20106
20718
  vegetation = visible;
20107
20719
  scene?.setVegetation(visible);
20108
20720
  },
20721
+ setAdaptivePerspective(enabled) {
20722
+ adaptivePerspective = enabled;
20723
+ scene?.setAdaptivePerspective(enabled);
20724
+ },
20109
20725
  dispose
20110
20726
  };
20111
20727
  }
@@ -20115,9 +20731,15 @@ function createTileflowMap3D(options) {
20115
20731
  const { map, controller, transformRequest } = options;
20116
20732
  let viewMode = options.viewMode ?? "3d";
20117
20733
  let vegetationVisible = options.vegetation;
20734
+ let adaptivePerspective = options.camera?.adaptivePerspective;
20735
+ const camera = createTileflowAdaptiveCamera(map);
20736
+ let authoredPerspective;
20118
20737
  let buildings;
20119
20738
  let vegetation;
20120
20739
  let streetLights;
20740
+ const flatBuildings = createBuildingFlatLayers(map);
20741
+ let footprintLayers;
20742
+ let footprintZoom = 15.3;
20121
20743
  let disposed = false;
20122
20744
  let syncing = false;
20123
20745
  const shared4 = {
@@ -20132,6 +20754,19 @@ function createTileflowMap3D(options) {
20132
20754
  syncing = true;
20133
20755
  try {
20134
20756
  const shown = viewMode === "3d";
20757
+ if (footprintLayers === void 0) {
20758
+ const themes = controller?.getThemeMetadata?.(tileflowBuildingsMetadataKey);
20759
+ const metadata = themes ? { [tileflowBuildingsMetadataKey]: themes.values[Math.round(themes.position)] } : map.getStyle()?.metadata;
20760
+ const design = readTileflowBuildings3D(metadata);
20761
+ footprintLayers = design?.flatLayers ?? [];
20762
+ footprintZoom = design?.entrance?.buildings?.[1] ?? 15.3;
20763
+ }
20764
+ if (authoredPerspective === void 0) {
20765
+ const themes = controller?.getThemeMetadata?.(tileflowCameraMetadataKey);
20766
+ const metadata = themes ? { [tileflowCameraMetadataKey]: themes.values[Math.round(themes.position)] } : map.getStyle()?.metadata;
20767
+ authoredPerspective = readTileflowCamera(metadata).adaptivePerspective ?? false;
20768
+ }
20769
+ camera.setEnabled(shown && (adaptivePerspective ?? authoredPerspective));
20135
20770
  const declared = declarations ??= tileflowMap3DDeclarations({
20136
20771
  map,
20137
20772
  ...controller ? { controller } : {}
@@ -20145,6 +20780,7 @@ function createTileflowMap3D(options) {
20145
20780
  }
20146
20781
  if (!vegetation && (declares(tileflowVegetationMetadataKey) || declares(tileflowVegetationDisplayMetadataKey)))
20147
20782
  vegetation = createTileflowVegetation({ ...shared4, visible: vegetationVisible, viewMode });
20783
+ syncFlatBuildings();
20148
20784
  if (shown && declares(tileflowStreetLightsMetadataKey))
20149
20785
  streetLights ??= createTileflowStreetLights(shared4);
20150
20786
  else if (streetLights) {
@@ -20155,9 +20791,22 @@ function createTileflowMap3D(options) {
20155
20791
  syncing = false;
20156
20792
  }
20157
20793
  }
20794
+ function syncFlatBuildings() {
20795
+ if (disposed) return;
20796
+ if (!footprintLayers?.length) {
20797
+ flatBuildings.restore();
20798
+ return;
20799
+ }
20800
+ const canvas = map.getCanvas?.();
20801
+ flatBuildings.update(
20802
+ footprintLayers,
20803
+ viewMode === "3d" && Boolean(buildings) && map.getZoom() >= footprintZoom && Boolean(canvas?.getContext?.("webgl2"))
20804
+ );
20805
+ }
20158
20806
  function change(next, transition) {
20159
20807
  if (disposed) return Promise.resolve();
20160
20808
  viewMode = next;
20809
+ camera.setEnabled(next === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
20161
20810
  vegetation?.setViewMode(next);
20162
20811
  if (next === "3d") {
20163
20812
  const existing = buildings;
@@ -20173,10 +20822,13 @@ function createTileflowMap3D(options) {
20173
20822
  function dispose() {
20174
20823
  if (disposed) return;
20175
20824
  disposed = true;
20825
+ flatBuildings.restore();
20826
+ camera.dispose();
20176
20827
  map.off("styledata", restyle);
20177
20828
  map.off("style.load", restyle);
20178
20829
  map.off("idle", sync);
20179
- map.off("remove", dispose);
20830
+ map.off("remove", onRemove);
20831
+ map.off("move", syncFlatBuildings);
20180
20832
  streetLights?.dispose();
20181
20833
  buildings?.dispose();
20182
20834
  vegetation?.dispose();
@@ -20185,13 +20837,21 @@ function createTileflowMap3D(options) {
20185
20837
  vegetation = void 0;
20186
20838
  }
20187
20839
  function restyle() {
20840
+ if (syncing) return;
20841
+ footprintLayers = void 0;
20188
20842
  declarations = void 0;
20843
+ authoredPerspective = void 0;
20189
20844
  sync();
20190
20845
  }
20846
+ function onRemove() {
20847
+ flatBuildings.forget();
20848
+ dispose();
20849
+ }
20191
20850
  map.on("styledata", restyle);
20192
20851
  map.on("style.load", restyle);
20193
20852
  map.on("idle", sync);
20194
- map.on("remove", dispose);
20853
+ map.on("remove", onRemove);
20854
+ map.on("move", syncFlatBuildings);
20195
20855
  sync();
20196
20856
  return {
20197
20857
  show: (transition) => change("3d", transition),
@@ -20203,6 +20863,11 @@ function createTileflowMap3D(options) {
20203
20863
  vegetationVisible = visible;
20204
20864
  vegetation?.setVisible(visible);
20205
20865
  },
20866
+ setAdaptivePerspective(enabled) {
20867
+ adaptivePerspective = enabled;
20868
+ camera.setEnabled(viewMode === "3d" && (adaptivePerspective ?? authoredPerspective ?? false));
20869
+ sync();
20870
+ },
20206
20871
  get buildings() {
20207
20872
  return buildings;
20208
20873
  },
@@ -21731,6 +22396,7 @@ function isPromiseLike(value) {
21731
22396
  export {
21732
22397
  attachTileflowAtmosphere,
21733
22398
  attachTileflowFairUseNotice,
22399
+ attachTileflowHorizonQueries,
21734
22400
  attachTileflowLabelPlacement,
21735
22401
  attachTileflowMap3D,
21736
22402
  attachTileflowMapLifecycle,
@@ -21772,6 +22438,7 @@ export {
21772
22438
  readTileflowVegetation3D,
21773
22439
  readTileflowVegetationDisplay,
21774
22440
  registerTileflowContourProtocol,
22441
+ registerTileflowPathGroundProtocol,
21775
22442
  registerTileflowPmtilesProtocol,
21776
22443
  registerTileflowWorldRequestBridge,
21777
22444
  resolveTileflowSun,
@@ -21788,6 +22455,7 @@ export {
21788
22455
  tileflowDepthMarkerPlacement,
21789
22456
  tileflowFairUseNoticeMessage,
21790
22457
  tileflowGroundBeforeId,
22458
+ tileflowHorizonScaleFactor,
21791
22459
  tileflowLayerDomainMetadataKey,
21792
22460
  tileflowLightRhythm,
21793
22461
  tileflowLightRhythmConventions,