@tileflow/core 0.1.0-alpha.38 → 0.1.0-alpha.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/{3d-D9c3i78O.d.ts → 3d-BkaJjwfk.d.ts} +3 -0
- package/dist/3d.d.ts +1 -1
- package/dist/3d.js +325 -76
- package/dist/browser.d.ts +341 -12
- package/dist/browser.js +9412 -7855
- package/dist/build.d.ts +4 -3
- package/dist/build.js +854 -117
- package/dist/capture.js +4 -1
- package/dist/config-reference.json +417 -159
- package/dist/{icon-composition-Br4Bd2bY.d.ts → icon-composition-Ivgoxz8d.d.ts} +156 -5
- package/dist/index.d.ts +165 -5
- package/dist/index.js +1508 -260
- package/dist/{manifest-types-jrBdBrES.d.ts → manifest-types-DRy2980g.d.ts} +5 -2
- package/dist/manifest.d.ts +2 -2
- package/dist/manifest.js +4 -1
- package/dist/native-profile.d.ts +4 -0
- package/dist/native-profile.js +2 -0
- package/dist/native.js +11 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +11 -1
- package/dist/worker/camera-tile-worker.global.js +20 -1
- package/docs/globe-atmosphere.md +3 -0
- package/docs/native-artifact-profile.md +2 -2
- package/docs/nautical-marks.md +147 -39
- package/docs/public-api-and-browser-subpath.md +3 -2
- package/docs/street-sky.md +153 -0
- package/docs/sun-and-light.md +4 -2
- package/package.json +1 -1
package/dist/3d.js
CHANGED
|
@@ -655,15 +655,15 @@ function tileflowBuildingStyleLight(value, bearing) {
|
|
|
655
655
|
const light = typeof value === "object" && value !== null ? value : {};
|
|
656
656
|
const position = Array.isArray(light.position) && light.position.length === 3 && light.position.every((part) => typeof part === "number" && Number.isFinite(part)) ? light.position : [1.15, 210, 30];
|
|
657
657
|
const [radius, azimuth, polar] = position;
|
|
658
|
-
const
|
|
659
|
-
const angle = (azimuth + 90 + (light.anchor === "map" ? 0 : bearing)) *
|
|
660
|
-
const horizontal = radius * Math.sin(polar *
|
|
658
|
+
const radians2 = Math.PI / 180;
|
|
659
|
+
const angle = (azimuth + 90 + (light.anchor === "map" ? 0 : bearing)) * radians2;
|
|
660
|
+
const horizontal = radius * Math.sin(polar * radians2);
|
|
661
661
|
const colour = typeof light.color === "string" ? tileflowColourChannels(light.color) : null;
|
|
662
662
|
return {
|
|
663
663
|
position: [
|
|
664
664
|
horizontal * Math.cos(angle),
|
|
665
665
|
horizontal * Math.sin(angle),
|
|
666
|
-
radius * Math.cos(polar *
|
|
666
|
+
radius * Math.cos(polar * radians2)
|
|
667
667
|
],
|
|
668
668
|
colour: colour ? colour.slice(0, 3) : [1, 1, 1],
|
|
669
669
|
intensity: typeof light.intensity === "number" && Number.isFinite(light.intensity) ? Math.max(0, Math.min(1, light.intensity)) : 0.5
|
|
@@ -2187,6 +2187,35 @@ function hash(value) {
|
|
|
2187
2187
|
return s - Math.floor(s);
|
|
2188
2188
|
}
|
|
2189
2189
|
|
|
2190
|
+
// src/scene-3d-shaders.ts
|
|
2191
|
+
var tileflowShadowLookup = `
|
|
2192
|
+
uniform highp sampler2DShadow u_shadow_map;
|
|
2193
|
+
uniform float u_shadow;
|
|
2194
|
+
uniform float u_depth_unit;
|
|
2195
|
+
|
|
2196
|
+
float visibility(vec3 c, float bias) {
|
|
2197
|
+
if (u_shadow <= 0.0 || c.x <= 0.0 || c.y <= 0.0 || c.x >= 1.0 || c.y >= 1.0 || c.z >= 1.0)
|
|
2198
|
+
return 1.0;
|
|
2199
|
+
float z = c.z - bias * u_depth_unit;
|
|
2200
|
+
// The depth texture uses LINEAR comparison; an extra multi-tap kernel would
|
|
2201
|
+
// spread distant texels into metres of soft shadow.
|
|
2202
|
+
return texture(u_shadow_map, vec3(c.xy, z));
|
|
2203
|
+
}`;
|
|
2204
|
+
var tileflowHazeVertex = `
|
|
2205
|
+
out float v_haze_depth;`;
|
|
2206
|
+
var tileflowHazeFragment = `
|
|
2207
|
+
in float v_haze_depth;
|
|
2208
|
+
uniform vec3 u_haze_colour;
|
|
2209
|
+
uniform vec3 u_haze; // strength; the view depths where the haze starts and is complete
|
|
2210
|
+
|
|
2211
|
+
float hazeOf() {
|
|
2212
|
+
return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
vec3 hazed(vec3 colour) {
|
|
2216
|
+
return mix(colour, u_haze_colour, hazeOf());
|
|
2217
|
+
}`;
|
|
2218
|
+
|
|
2190
2219
|
// src/buildings-3d-occlusion.ts
|
|
2191
2220
|
var tileflowBuildingOcclusion = {
|
|
2192
2221
|
ground: 3,
|
|
@@ -2282,9 +2311,10 @@ void main() {
|
|
|
2282
2311
|
var buildingContactCompositeFragment = `#version 300 es
|
|
2283
2312
|
precision highp float;
|
|
2284
2313
|
uniform highp sampler2D u_contact;
|
|
2314
|
+
${tileflowHazeFragment}
|
|
2285
2315
|
out vec4 fragColor;
|
|
2286
2316
|
void main() {
|
|
2287
|
-
float shade = texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r;
|
|
2317
|
+
float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());
|
|
2288
2318
|
fragColor = vec4(vec3(shade), 1.0);
|
|
2289
2319
|
}`;
|
|
2290
2320
|
function createBuildingContactMask() {
|
|
@@ -2371,21 +2401,6 @@ function drawBuildingOpacity(gl, opacity, draw) {
|
|
|
2371
2401
|
}
|
|
2372
2402
|
}
|
|
2373
2403
|
|
|
2374
|
-
// src/scene-3d-shaders.ts
|
|
2375
|
-
var tileflowShadowLookup = `
|
|
2376
|
-
uniform highp sampler2DShadow u_shadow_map;
|
|
2377
|
-
uniform float u_shadow;
|
|
2378
|
-
uniform float u_depth_unit;
|
|
2379
|
-
|
|
2380
|
-
float visibility(vec3 c, float bias) {
|
|
2381
|
-
if (u_shadow <= 0.0 || c.x <= 0.0 || c.y <= 0.0 || c.x >= 1.0 || c.y >= 1.0 || c.z >= 1.0)
|
|
2382
|
-
return 1.0;
|
|
2383
|
-
float z = c.z - bias * u_depth_unit;
|
|
2384
|
-
// The depth texture uses LINEAR comparison; an extra multi-tap kernel would
|
|
2385
|
-
// spread distant texels into metres of soft shadow.
|
|
2386
|
-
return texture(u_shadow_map, vec3(c.xy, z));
|
|
2387
|
-
}`;
|
|
2388
|
-
|
|
2389
2404
|
// src/buildings-3d-shaders.ts
|
|
2390
2405
|
var tileflowBuildingAttributes = [
|
|
2391
2406
|
["a_pos", 2, "UNSIGNED_SHORT", false, 0],
|
|
@@ -2417,6 +2432,11 @@ var growth = `
|
|
|
2417
2432
|
uniform float u_scale;
|
|
2418
2433
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
2419
2434
|
uniform float u_metres; // metres per tile unit
|
|
2435
|
+
// The disc the city's tiles cover whole, in this tile's units: its centre, where heights start to
|
|
2436
|
+
// ease down and where they are gone; none while its radius is 0. And the view's direction along the
|
|
2437
|
+
// ground, in this tile's axes.
|
|
2438
|
+
uniform vec4 u_ring;
|
|
2439
|
+
uniform vec2 u_ring_ahead;
|
|
2420
2440
|
|
|
2421
2441
|
float progressOf() {
|
|
2422
2442
|
return clamp(u_scale * 1.25 - a_wave.x * 0.25, 0.0, 1.0);
|
|
@@ -2427,6 +2447,16 @@ float elevationOf(float own, float top, float p) {
|
|
|
2427
2447
|
return max(0.0, own - (1.0 - eased) * top);
|
|
2428
2448
|
}
|
|
2429
2449
|
|
|
2450
|
+
// Buildings sink into the ground over the last stretch of the city's reach, so it ends without an
|
|
2451
|
+
// edge of cut-off blocks. Only its far side does: where the tile limit holds the ring short, the
|
|
2452
|
+
// buildings round the camera, nearer than its centre, keep standing.
|
|
2453
|
+
float reachOf(vec2 position) {
|
|
2454
|
+
if (u_ring.w <= 0.0) return 1.0;
|
|
2455
|
+
vec2 from = position - u_ring.xy;
|
|
2456
|
+
float far = smoothstep(0.0, u_ring.w - u_ring.z, dot(from, u_ring_ahead));
|
|
2457
|
+
return 1.0 - smoothstep(u_ring.z, u_ring.w, length(from)) * far;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2430
2460
|
vec3 localOf(vec2 position, float elevation) {
|
|
2431
2461
|
return vec3((position + u_offset) * u_metres * vec2(1.0, -1.0), elevation);
|
|
2432
2462
|
}
|
|
@@ -2470,7 +2500,7 @@ void main() {
|
|
|
2470
2500
|
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
2471
2501
|
return;
|
|
2472
2502
|
}
|
|
2473
|
-
float elevation = elevationOf(a_flags.x > 0.5 ? top : base, top, p);
|
|
2503
|
+
float elevation = elevationOf(a_flags.x > 0.5 ? top : base, top, p) * reachOf(a_pos);
|
|
2474
2504
|
gl_Position = u_light_matrix * vec4(localOf(a_pos, elevation), 1.0);
|
|
2475
2505
|
}`;
|
|
2476
2506
|
var tileflowBuildingDepthFragment = `#version 300 es
|
|
@@ -2499,6 +2529,7 @@ out vec3 v_shadow;
|
|
|
2499
2529
|
flat out vec3 v_wall; // where the wall starts along its ring, its tight corners, its length
|
|
2500
2530
|
out vec3 v_edge; // a roof triangle's corner weights; on a wall, from 0 at its start to 1 at its end
|
|
2501
2531
|
flat out float v_outline; // a roof triangle's sides on the outline; a wall's ends on the tile's edge
|
|
2532
|
+
${tileflowHazeVertex}
|
|
2502
2533
|
|
|
2503
2534
|
vec3 paletteColour(float theme) {
|
|
2504
2535
|
float row = theme * u_palette_rows.x + floor(a_feature / u_palette_rows.y);
|
|
@@ -2515,8 +2546,9 @@ void main() {
|
|
|
2515
2546
|
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
2516
2547
|
return;
|
|
2517
2548
|
}
|
|
2518
|
-
float elevation = elevationOf(own, top, p);
|
|
2549
|
+
float elevation = elevationOf(own, top, p) * reachOf(a_pos);
|
|
2519
2550
|
gl_Position = projectTileFor3D(a_pos, elevation);
|
|
2551
|
+
v_haze_depth = gl_Position.w;
|
|
2520
2552
|
float wall = a_flags.y;
|
|
2521
2553
|
// A wall faces out level; a roof faces up, tilted by its slope.
|
|
2522
2554
|
vec3 normal = wall > 0.5 ? vec3(a_normal.x, -a_normal.y, 0.0)
|
|
@@ -2573,6 +2605,7 @@ uniform vec3 u_edge_colour; // the application's colour for them
|
|
|
2573
2605
|
uniform float u_edge_own; // how much of them takes the application's colour, from 0 to 1
|
|
2574
2606
|
${nightLight}
|
|
2575
2607
|
${tileflowShadowLookup}
|
|
2608
|
+
${tileflowHazeFragment}
|
|
2576
2609
|
out vec4 fragColor;
|
|
2577
2610
|
|
|
2578
2611
|
float hash(vec2 p) {
|
|
@@ -2736,7 +2769,7 @@ void main() {
|
|
|
2736
2769
|
colour = mix(colour, shopOf(v_building.w, seed) * u_flood + colour * 0.15, across * rows * 0.6 * min(u_flood, 1.0));
|
|
2737
2770
|
}
|
|
2738
2771
|
}
|
|
2739
|
-
fragColor = vec4(colour, 1.0);
|
|
2772
|
+
fragColor = vec4(hazed(colour), 1.0);
|
|
2740
2773
|
}`;
|
|
2741
2774
|
var tileflowBuildingGroundVertex = (projected) => `#version 300 es
|
|
2742
2775
|
${projected}
|
|
@@ -2745,8 +2778,10 @@ uniform mat4 u_light_matrix;
|
|
|
2745
2778
|
uniform vec2 u_offset;
|
|
2746
2779
|
uniform float u_metres;
|
|
2747
2780
|
out vec3 v_shadow;
|
|
2781
|
+
${tileflowHazeVertex}
|
|
2748
2782
|
void main() {
|
|
2749
2783
|
gl_Position = projectTileFor3D(a_pos, 0.0);
|
|
2784
|
+
v_haze_depth = gl_Position.w;
|
|
2750
2785
|
vec4 shadow = u_light_matrix * vec4((a_pos + u_offset) * u_metres * vec2(1.0, -1.0), 0.0, 1.0);
|
|
2751
2786
|
v_shadow = shadow.xyz * 0.5 + 0.5;
|
|
2752
2787
|
}`;
|
|
@@ -2755,9 +2790,11 @@ precision highp float;
|
|
|
2755
2790
|
in vec3 v_shadow;
|
|
2756
2791
|
uniform vec3 u_ground_shadow;
|
|
2757
2792
|
${tileflowShadowLookup}
|
|
2793
|
+
${tileflowHazeFragment}
|
|
2758
2794
|
out vec4 fragColor;
|
|
2759
2795
|
void main() {
|
|
2760
|
-
|
|
2796
|
+
// Far shadows fade into the haze the flat map has already taken.
|
|
2797
|
+
float shaded = u_shadow * (1.0 - visibility(v_shadow, 0.15)) * (1.0 - hazeOf());
|
|
2761
2798
|
fragColor = vec4(mix(vec3(1.0), u_ground_shadow, shaded), 1.0);
|
|
2762
2799
|
}`;
|
|
2763
2800
|
var tileflowBuildingBandVertex = (projected) => `#version 300 es
|
|
@@ -2770,6 +2807,7 @@ out float v_out;
|
|
|
2770
2807
|
out float v_strength;
|
|
2771
2808
|
out vec3 v_flood;
|
|
2772
2809
|
out vec3 v_shop;
|
|
2810
|
+
${tileflowHazeVertex}
|
|
2773
2811
|
void main() {
|
|
2774
2812
|
float base = a_height.x * 0.1;
|
|
2775
2813
|
float top = a_height.y * 0.1;
|
|
@@ -2783,6 +2821,7 @@ void main() {
|
|
|
2783
2821
|
return;
|
|
2784
2822
|
}
|
|
2785
2823
|
gl_Position = projectTileFor3D(a_pos + a_normal * (u_band / u_metres) * a_flags.x, 0.0);
|
|
2824
|
+
v_haze_depth = gl_Position.w;
|
|
2786
2825
|
v_out = a_flags.x;
|
|
2787
2826
|
v_strength = p;
|
|
2788
2827
|
}`;
|
|
@@ -2793,11 +2832,13 @@ in float v_strength;
|
|
|
2793
2832
|
in vec3 v_flood;
|
|
2794
2833
|
in vec3 v_shop;
|
|
2795
2834
|
uniform float u_flood;
|
|
2835
|
+
${tileflowHazeFragment}
|
|
2796
2836
|
out vec4 fragColor;
|
|
2797
2837
|
void main() {
|
|
2798
2838
|
float near = 1.0 - v_out;
|
|
2799
2839
|
float close = near * near * near * near * near * near;
|
|
2800
|
-
fragColor = vec4((v_flood * 0.35 * near * near + v_shop * 0.12 * close) * u_flood * v_strength
|
|
2840
|
+
fragColor = vec4((v_flood * 0.35 * near * near + v_shop * 0.12 * close) * u_flood * v_strength *
|
|
2841
|
+
(1.0 - hazeOf()), 0.0);
|
|
2801
2842
|
}`;
|
|
2802
2843
|
var buildingArchitecturalFloodVertex = (projected) => `#version 300 es
|
|
2803
2844
|
${projected}
|
|
@@ -2828,10 +2869,11 @@ var buildingArchitecturalFloodComposite = `#version 300 es
|
|
|
2828
2869
|
precision highp float;
|
|
2829
2870
|
uniform sampler2D u_mask;
|
|
2830
2871
|
uniform vec3 u_colour;
|
|
2872
|
+
${tileflowHazeFragment}
|
|
2831
2873
|
out vec4 fragColor;
|
|
2832
2874
|
void main() {
|
|
2833
2875
|
float light = 1.0 - texelFetch(u_mask, ivec2(gl_FragCoord.xy), 0).r;
|
|
2834
|
-
fragColor = vec4(u_colour, light);
|
|
2876
|
+
fragColor = vec4(u_colour, light * (1.0 - hazeOf()));
|
|
2835
2877
|
}`;
|
|
2836
2878
|
|
|
2837
2879
|
// src/buildings-3d-view.ts
|
|
@@ -2877,6 +2919,10 @@ function buildingCornerDetail(zoom, latitude = 40.42, radius = 0.8, pitch = 0, p
|
|
|
2877
2919
|
if (previous === 2 && pixels >= 2.7) return 2;
|
|
2878
2920
|
return pixels < 0.6 ? 0 : pixels < 3 ? 1 : 2;
|
|
2879
2921
|
}
|
|
2922
|
+
function buildingBoxDepth(matrix, bounds) {
|
|
2923
|
+
const depth = Math.min(matrix[3] * bounds[0], matrix[3] * bounds[3]) + Math.min(matrix[7] * bounds[1], matrix[7] * bounds[4]) + Math.min(matrix[11] * bounds[2], matrix[11] * bounds[5]) + matrix[15];
|
|
2924
|
+
return Number.isFinite(depth) ? depth : -Infinity;
|
|
2925
|
+
}
|
|
2880
2926
|
|
|
2881
2927
|
// src/buildings-3d-tile.ts
|
|
2882
2928
|
function prepareBuildingTile(mesh) {
|
|
@@ -4024,7 +4070,7 @@ function browserWorker() {
|
|
|
4024
4070
|
if (typeof Worker === "undefined" || false)
|
|
4025
4071
|
return;
|
|
4026
4072
|
const url = URL.createObjectURL(
|
|
4027
|
-
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=jn(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=wt(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 jn(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&&Ue(r,r.next)&&(Oe(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))&&(Ue(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Oe(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&&At(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?yt(e,t,i,o):pt(e))){n.push(a.i,e.i,l.i),Oe(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=bt(e,n),r=e,s=!0;continue}gt(e,n,t,i,o);break}}}function pt(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 yt(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 bt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Nn(o,t,t.next,r,!1)&&Ce(o,r)&&Ce(r,o)&&(n.push(o.i,t.i,r.i),Oe(t),Oe(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function gt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&_t(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 wt(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=jn(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(xt),Mt(e.length/i,n.length),zn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Tt(o[r],t);return cn=!1,ge(t)}function xt(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 Tt(e,n){let t=vt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return zn(t,o.next),ge(i,i.next),ge(t,t.next)}var Dn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function Mt(e,n){let t=Math.ceil((e+2*n)/Dn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function zn(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<Dn&&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 kt(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 vt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Ue(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(Ue(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);(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&&Rt(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function Rt(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),_e=new Uint32Array(0),Le=new Uint32Array(256);function At(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);Ft(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 Ft(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),_e=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,_e,0),Xe(e,ve,_e,ie,be,8),Xe(e,ie,be,ve,_e,16),Xe(e,ve,_e,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 _t(e,n){let t=Ue(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))&&!Lt(e,n)&&(t||Bt(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 Ue(e,n){return e.x===n.x&&e.y===n.y}function Nn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Lt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Nn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function 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 Bt(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 Oe(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&&kt(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,Ot=Math.tan(Math.PI/6),Pt=Math.tan(35*Math.PI/180),Et=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"||Nt(e,s))return;let l=Dt(e);if(!l||Math.abs(pn(e))<Ct*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Hn(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&&[Gn(m,u),Gn(m,c)]);if(!h)return;let A=Math.max(0,o-i),F=Hn(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,E]=l.centre,O=(y,b)=>{let x=(y-C)*r,T=(b-E)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},I=(y,b)=>[C+(y*u[0]+b*c[0])/r,E+(y*u[1]+b*c[1])/r],N=(y,b)=>{let x=1/0;for(let[T,S,v]of h)x=Math.min(x,T*y+S*b+v);return Math.max(0,x)},K=(y,b)=>k+B*N(...O(y,b)),G=[];for(let y=0;y+1<n.length;y+=2)G.push(...O(n[y],n[y+1]));pn(G)<0&&Vt(G);let z=1.01,Y=[-f*z,-d*z,f*z,-d*z,f*z,d*z,-f*z,d*z],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let D=b[0]-Z[0],H=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(D)+Math.abs(H)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=$n(x,D,H,W),x.length<6)break}if(x.length<6)continue;let T=G,S=x.length/2;for(let P=0;P<S&&T.length>=6;P+=1){let[Z,D]=[x[P*2],x[P*2+1]],[H,W]=[x[(P+1)%S*2],x[(P+1)%S*2+1]];T=$n(T,W-D,Z-H,-(W-D)*Z-(Z-H)*D)}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 U=B*b[0],V=B*b[1],R=U*u[0]+V*c[0],_=U*u[1]+V*c[1],j=Math.hypot(R,_,1);w.push({ring:v,triangles:L,normal:[-R/j,-_/j]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[S,v]=O(y,b),[L,U]=O(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let _=R+1;_<h.length;_+=1){let j=(ae,$)=>(h[R][0]-h[_][0])*ae+(h[R][1]-h[_][1])*$+(h[R][2]-h[_][2]),P=j(S,v),Z=j(L,U);if(P===Z||P*Z>0)continue;let D=P/(P-Z);if(D<=1e-4||D>=1-1e-4)continue;let H=S+(L-S)*D,W=v+(U-v)*D;h[R][0]*H+h[R][1]*W+h[R][2]<=N(H,W)+1e-6&&V.push(D)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,_)=>R-_)}}}function It(e,n){switch(e){case"skillion":return 2*n*Et;case"pyramidal":return n*Pt;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Ot}}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 $n(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Dt(e){let n=zt(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 zt(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 Nt(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 Vt(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 Gn(e,n){return e[0]*n[0]+e[1]*n[1]}function Hn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var jr=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6}),zr=Object.freeze([1,1,4,1,3]),Nr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Gt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=$t(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function $t(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Gt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Ht={commercial:1,active:2,destination:3},Zt={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]))},Wt={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]))},Xt=6,Yt=.5,Jt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=er(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let C=B.properties,E=C.hide_3d;if(E===!0||E===1||E==="1"||E==="true")continue;let O=Math.min(6e3,Jn(C.render_height)??o),I=Math.min(O,Jn(C.render_min_height)??0),N=Ht[String(C.building_tone??"")]??0,K=Zt[String(C.class??"")]??0,G=d.get(M)??0,z=u.length,Y=!1;for(let w of nr(B.geometry,t)){let y=w.map(rr).filter(_=>_.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=tr(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Jt/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,O+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let _ of y)for(let j=0;j<_.length;j+=2)T.bounds[0]=Math.min(T.bounds[0],_[j]-1),T.bounds[1]=Math.min(T.bounds[1],_[j+1]-1),T.bounds[2]=Math.max(T.bounds[2],_[j]+1),T.bounds[3]=Math.max(T.bounds[3],_[j+1]+1);Y=!0,f=Math.max(f,O);let S=Number.isSafeInteger(B.id),v=gn(S?B.id*.0731:b*.0731+x*.19137+z*1.618),L=!S&&y[0].some(_=>_<=0||_>=ue)?gn(O*7.31+I*3.17+N):v,U={base:I,top:O,jitter:L,seed:v,tone:N,group:K,use:G,cx:b,cy:x,index:z},V=y.map((_,j)=>qt(_,j,r,n.cornerAngle));y=V.map(({ring:_})=>_);let R=w.length===1&&y.length===1?Zn(w[0],y[0],C,I,O,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),Qt(R,U,s,a)):Kt(y,U,s,a);for(let[_,j]of y.entries()){let P=qe(j)>0,Z=_===0?P?-1:1:P?1:-1,D=j.length/2,H=$=>{let J=($%D+D)%D;return[j[J*2],j[J*2+1]]},W=$=>{let[J,re]=H($-1),[ne,te]=H($),[le,de]=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 De=-(te-re)/me*Z,ze=(ne-J)/me*Z;return(De*(le-ne)+ze*(de-te))/ce>Yt},se=($,J)=>R?R.heightAt($,J):O,ae=0;for(let $=0;$<D;$+=1){let[J,re]=H($),[ne,te]=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[_].normals[$]??[de,me],De=V[_].normals[($+1)%D]??[de,me],ze=oe=>{let Ae=ce[0]+(De[0]-ce[0])*oe,Fe=ce[1]+(De[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],Ne=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],$e=re+(te-re)*he[oe+1],Se=Math.hypot(Ve-ye,$e-Ne)/ue*n.tileMetres,Ge=(Ae&&W($)?1:0)|(Fe&&W($+1)?2:0)|(_>0?4:0),He=(Ae&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+Se,Ze=ze(he[oe]),We=ze(he[oe+1]),Cn=se(ye,Ne),On=se(Ve,$e),ke=s.write(U,ye,Ne,0,Ze[0],Ze[1],1,ae,Ge,Se,0,He,Cn);s.write(U,Ve,$e,0,We[0],We[1],1,an,Ge,Se,1,He,On),s.write(U,ye,Ne,1,Ze[0],Ze[1],1,ae,Ge,Se,0,He,Cn),s.write(U,Ve,$e,1,We[0],We[1],1,an,Ge,Se,1,He,On),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 Kt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function Qt(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function qt(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],[E,O]=[(A-p)/M,(F-h)/M],I=Math.atan2(B*O-C*E,B*E+C*O);if(I*s>=-.08||Math.abs(I)>Math.PI*.85){u(p,h);continue}let N=Math.tan(Math.abs(I)/2),K=Math.min(t*N,k*.2,M*.2),G=K/N;if(G<1){u(p,h);continue}let[z,Y]=[-C*s,B*s],[w,y]=[p-B*K-z*G,h-C*K-Y*G],b=Math.atan2(Y,z),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 S=b+I*T/x,v=[Math.cos(S),Math.sin(S)];u(w+v[0]*G,y+v[1]*G,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 er(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=Wt[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=Xt/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 E=!1;for(let O of F.rings)for(let I=0,N=O.length-2;I+1<O.length;N=I,I+=2){let K=O[N],G=O[N+1],z=O[I],Y=O[I+1];Y>g!=G>g&&d<(K-z)*(g-Y)/(G-Y)+z&&(E=!E);let w=z-K,y=Y-G,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-G)*y)/b)):0,T=Math.hypot(d-K-x*w,g-G-x*y);T<h&&(h=T,p=F.index)}if(E){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 nr(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 tr(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 rr(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)}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}function qn(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 et({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=or(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 or(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,ir={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}},sr={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}},ar={spacing:30,kerb:0},lr=12,ur=18,cr=9,fr={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"},dr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},mr=new Set(["wall","wall_mounted","wall_bracket"]),hr=new Set(["suspended","cable","catenary","wire"]);function ot(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(ur),r=new nn(cr),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=pr(h),F=yr(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 E=B[C]*m,O=B[C+1]*m;if(!tt(E,O))continue;i.write(E,O,A,M,!0,F);let I=rt(E,O,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"||!nt(p.properties,"streets")))for(let h of p.geometry)u+=br(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=lr,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,A)=>{let F=fe/m.extent,k=[];for(let N=0;N+1<p.length;N+=2)k.push(p[N]*F,p[N+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,C=Rn(k[0]*.013+k[1]*.029+A)*h.spacing,E=0,O=C,I=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let N=2;N<k.length;N+=2){let K=k[N-2],G=k[N-1],z=k[N],Y=k[N+1],w=Math.hypot(z-K,Y-G)*M;if(w!==0){for(;O<=E+w;){let y=(O-E)/w,b=-(Y-G)/(w/M)*I,x=(z-K)/(w/M)*I,T=K+(z-K)*y+b*B,S=G+(Y-G)*y+x*B;if(O+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(I=-I),!tt(T,S))continue;let v=rt(T,S,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,S,7,15,!1))}E+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=nt(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,ar,2)}return i.done(a)}function nt(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=ir[r];if(s&&(n==="streets"||kn(t)))return s;let a=sr[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function pr(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return mr.has(t)?4.5:hr.has(t)?7.5:7}function yr(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(dr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=fr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function tt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function rt(e,n,t){return[e/fe*t,n/fe*t]}function br(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 eo=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 lt=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"}),_n=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,it={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],gr=1.2,wr=1.5,xr=1.3,Tr=1,Mr=[.3,10],kr=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"]),vr=new Set(["cupressus","calocedrus","thuja"]),Rr=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),st=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 at(e,n={}){let t={...lt,...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&&kr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&vr.has(r))return"columnar";if(i.includes("needle")||r&&Rr.has(r))return"conifer";if(r&&st[r])return st[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 ut(e,n){let t={...lt,...n.fields},i=n.unknownForms??_n,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]=Fr(r,w/q,y/q);for(let T of o){let[S,v,L,U]=T.bounds;if(x>=v&&x<=U&&(S<=L?b>=S&&b<=L:b>=S||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=it[w],S=Sn(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=Sn(T.height,ee(y,1))),v===void 0&&(v=L/S),L===void 0&&(L=v*S),{height:Te(v,on),crown:Te(L,An)}},g=(w,y,b,x,T,S)=>{let v=je(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,U=x===void 0&&T===void 0&&S!==void 0?d(L,v,Sn(it[L].height,Te(S/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...U,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=at(b,t),T=xe(b[t.height],on),S=xe(b[t.diameterCrown],An),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let U=0;U+1<L.length;U+=2){let V=L[U],R=L[U+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,S,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=at(x,t),S=xe(x[t.height],on),v=xe(x[t.diameterCrown],An);for(let L of b.geometry){let U=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[_,j,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],D=Math.hypot(P-_,Z-j);for(;U<=V+D;){let H=D>0?(U-V)/D:0,W=_+(P-_)*H,se=j+(Z-j)*H;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,S,v,void 0),U+=y}V+=D}}}}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,S=Number(b[t.canopyCover]??30),v=S>=60?3:S>=30?2:1;for(let L of y.geometry)for(let U=0;U+1<L.length;U+=2){let V=L[U],R=L[U+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let _=V*w,j=R*w,P=je(r.x*q+_,r.y*q+j,11),Z=f(_,j),D=xe(b[t.canopyHeight],on),H=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(H*.5,T-H/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let $=je(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee($,1):W,ne=_+Math.cos(J)*re/(s/q),te=j+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee($,3)),de=H*(.85+ee($,2)*.3),me=D===void 0?void 0:D*(.85+ee($,6)*.25),ce=d(le,$,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee($,4),shade:ee($,5),form:Me.indexOf(le),rank:x,seed:ee($,7),canopy:1}),c+=1}}}}let A=[],F=e.hedges;if(F){let w=q/F.extent,y=gr/(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"?Tr:0,T=(xe(b.properties[t.height],Mr)??xr)+x;for(let S of b.geometry){let v=y/2,L=0;for(let U=0;U+3<S.length;U+=2){let[V,R,_,j]=[S[U],S[U+1],S[U+2],S[U+3]],P=Math.hypot(_-V,j-R),Z=(Math.atan2(R-j,_-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let D=P>0?(v-L)/P:0,H=V+(_-V)*D,W=R+(j-R)*D;if(H>=0&&W>=0&&H<F.extent&&W<F.extent){let se=je(r.x*q+H*w,r.y*q+W*w,17);A.push({x:H*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 E=new Uint8Array(l.length*tn),O=new DataView(E.buffer),I=0,N=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...N(),variants:Array.from({length:k(y)},N)}])),G=(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;O.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),O.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),O.setUint16(x+4,Math.round(b.height*10),!0),O.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]];G(T,y,b.rank),G(T.variants[B[w]],y,b.rank)});let z=new Uint8Array(A.length*tn),Y=new DataView(z.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(wr*10),!0),z[b+8]=Math.round(w.turn*256)&255,z[b+9]=Math.floor(w.shade*256)&255,z[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:z,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:_n}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(_n,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 Sn([e,n],t){return e+(n-e)*t}function Fr(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 je(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 je(e,n,20973)/4294967296}var Sr=[void 0,"Point","LineString","Polygon"];function ct(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=_r(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function _r(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=Lr(a,o,r);return l?[l]:[]}))})}}function Lr(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Sr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Br(s,o))})}function Br(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Ur(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Cr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Cr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function ft(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function dt(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&&qn(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=ut({...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 ot({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function mt(e,n){if(!n)return[];if(e==="buildings")return et(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 ht(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=ct(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 Un=globalThis,Or=ht();Un.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=dt(t,Or.read(e,n,ft(t)));Un.postMessage({result:i},mt(t.kind,i))}catch(i){Un.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
4073
|
+
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&&At(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),A=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<=A;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Nn(o,t,t.next,r,!1)&&Ue(o,r)&&Ue(r,o)&&(n.push(o.i,t.i,r.i),Ce(t),Ce(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=zn(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Dn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Dn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Dn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function En(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ue(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&_t(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function _t(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function At(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);Ft(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 Ft(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ue(e,n)&&Ue(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Nn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Nn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ue(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function In(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ce(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ut(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ct=.7,Pt=Math.tan(Math.PI/6),Et=Math.tan(35*Math.PI/180),It=Math.tan(Math.PI/18),Ee=.65,Ie=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Dt(e);if(!l||Math.abs(pn(e))<Ct*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let _=Math.max(0,o-i),A=Gn(t.roof_height),k,M;if(A!==void 0&&A>0)M=o,k=Math.max(i+Math.min(2,_/2),o-A);else{let y=Math.min(zt(a,d),_*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[U,E]=l.centre,C=(y,b)=>{let x=(y-U)*r,T=(b-E)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},I=(y,b)=>[U+(y*u[0]+b*c[0])/r,E+(y*u[1]+b*c[1])/r],N=(y,b)=>{let x=1/0;for(let[T,F,v]of h)x=Math.min(x,T*y+F*b+v);return Math.max(0,x)},K=(y,b)=>k+B*N(...C(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...C(n[y],n[y+1]));pn($)<0&&Ht($);let D=1.01,Y=[-f*D,-d*D,f*D,-d*D,f*D,d*D,-f*D,d*D],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,F=x.length/2;for(let P=0;P<F&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%F*2],x[(P+1)%F*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[F,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(F,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=F+(L-F)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=N(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function zt(e,n){switch(e){case"skillion":return 2*n*It;case"pyramidal":return n*Et;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=Ee/(Ie*r)*f,m=(1-Ee)/((1-Ie)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),Ee/(Ie*r)*d],[...p(m),Ee+(1-Ee)/((1-Ie)*r)*(d-Ie*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Dt(e){let n=Nt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[_,A]of n){let k=_*c[0]+A*c[1],M=_*f[0]+A*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,A=(m+p)/2;t={centre:[_*c[0]+A*f[0],_*c[1]+A*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Nt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var jr=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6}),Nr=Object.freeze([1,1,4,1,3]),Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Gt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=$t(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function $t(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Gt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Zt={commercial:1,active:2,destination:3},Wt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Xt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Yt=6,Jt=.5,Kt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=nr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let U=B.properties,E=U.hide_3d;if(E===!0||E===1||E==="1"||E==="true")continue;let C=Math.min(6e3,Jn(U.render_height)??o),I=Math.min(C,Jn(U.render_min_height)??0),N=Zt[String(U.building_tone??"")]??0,K=Wt[String(U.class??"")]??0,$=d.get(M)??0,D=u.length,Y=!1;for(let w of tr(B.geometry,t)){let y=w.map(or).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=rr(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Kt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,C+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let z=0;z<S.length;z+=2)T.bounds[0]=Math.min(T.bounds[0],S[z]-1),T.bounds[1]=Math.min(T.bounds[1],S[z+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[z]+1),T.bounds[3]=Math.max(T.bounds[3],S[z+1]+1);Y=!0,f=Math.max(f,C);let F=Number.isSafeInteger(B.id),v=gn(F?B.id*.0731:b*.0731+x*.19137+D*1.618),L=!F&&y[0].some(S=>S<=0||S>=ue)?gn(C*7.31+I*3.17+N):v,O={base:I,top:C,jitter:L,seed:v,tone:N,group:K,use:$,cx:b,cy:x,index:D},V=y.map((S,z)=>er(S,z,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],U,I,C,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),qt(R,O,s,a)):Qt(y,O,s,a);for(let[S,z]of y.entries()){let P=qe(z)>0,Z=S===0?P?-1:1:P?1:-1,j=z.length/2,G=H=>{let J=(H%j+j)%j;return[z[J*2],z[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,De=(ne-J)/me*Z;return(je*(le-ne)+De*(de-te))/ce>Jt},se=(H,J)=>R?R.heightAt(H,J):C,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],De=oe=>{let _e=ce[0]+(je[0]-ce[0])*oe,Ae=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(_e,Ae)||1;return[_e/ye,Ae/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,Ae=oe+2===he.length,ye=J+(ne-J)*he[oe],Ne=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],Fe=Math.hypot(Ve-ye,He-Ne)/ue*n.tileMetres,$e=(_e&&W(H)?1:0)|(Ae&&W(H+1)?2:0)|(S>0?4:0),Ge=(_e&&xn(J,re)?1:0)|(Ae&&xn(ne,te)?2:0),an=ae+Fe,Ze=De(he[oe]),We=De(he[oe+1]),Un=se(ye,Ne),Cn=se(Ve,He),ke=s.write(O,ye,Ne,0,Ze[0],Ze[1],1,ae,$e,Fe,0,Ge,Un);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,Fe,1,Ge,Cn),s.write(O,ye,Ne,1,Ze[0],Ze[1],1,ae,$e,Fe,0,Ge,Un),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,Fe,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(),A=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(A.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function Qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function qt(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function er(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[_,A]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(_-p,A-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,_,A)){u(p,h);continue}let[B,U]=[(p-g)/k,(h-m)/k],[E,C]=[(_-p)/M,(A-h)/M],I=Math.atan2(B*C-U*E,B*E+U*C);if(I*s>=-.08||Math.abs(I)>Math.PI*.85){u(p,h);continue}let N=Math.tan(Math.abs(I)/2),K=Math.min(t*N,k*.2,M*.2),$=K/N;if($<1){u(p,h);continue}let[D,Y]=[-U*s,B*s],[w,y]=[p-B*K-D*$,h-U*K-Y*$],b=Math.atan2(Y,D),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(I)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let F=b+I*T/x,v=[Math.cos(F),Math.sin(F)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let _=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(_).set(new Uint8Array(this.#e)),this.#e=_,this.#n=new DataView(_)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function nr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Xt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Yt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let A of r){let[k,M,B,U]=A.box;if(d<k-o||d>B+o||g<M-o||g>U+o)continue;let E=!1;for(let C of A.rings)for(let I=0,N=C.length-2;I+1<C.length;N=I,I+=2){let K=C[N],$=C[N+1],D=C[I],Y=C[I+1];Y>g!=$>g&&d<(K-D)*(g-Y)/($-Y)+D&&(E=!E);let w=D-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=A.index)}if(E){m=A.index;break}}let _=m??p;_!==void 0&&t.set(_,Math.max(t.get(_)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function tr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function rr(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function or(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=ir(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function ir(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let _=(t.length<=4?[...t].map(A=>A+A).join(""):t).match(/../gu).map(A=>Number.parseInt(A,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,_,A]=o.slice(0,3).map(k=>en(k,255));return[h,_,A,r].some(k=>k===null)?null:[h,_,A,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,sr={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},ar={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},lr={spacing:30,kerb:0},ur=12,cr=18,fr=9,dr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},mr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},hr=new Set(["wall","wall_mounted","wall_bracket"]),pr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(cr),r=new nn(fr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let _=yr(h),A=br(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,_*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let U=0;U+1<B.length;U+=2){let E=B[U]*m,C=B[U+1]*m;if(!rt(E,C))continue;i.write(E,C,_,M,!0,A);let I=ot(E,C,n.tileMetres);o.add(...I),r.add(...I)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=gr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=ur,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,_)=>{let A=fe/m.extent,k=[];for(let N=0;N+1<p.length;N+=2)k.push(p[N]*A,p[N+1]*A);let M=n.tileMetres/fe,B=h.kerb*.45/M,U=Rn(k[0]*.013+k[1]*.029+_)*h.spacing,E=0,C=U,I=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let N=2;N<k.length;N+=2){let K=k[N-2],$=k[N-1],D=k[N],Y=k[N+1],w=Math.hypot(D-K,Y-$)*M;if(w!==0){for(;C<=E+w;){let y=(C-E)/w,b=-(Y-$)/(w/M)*I,x=(D-K)/(w/M)*I,T=K+(D-K)*y+b*B,F=$+(Y-$)*y+x*B;if(C+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(I=-I),!rt(T,F))continue;let v=ot(T,F,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,F,7,15,!1))}E+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,lr,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=sr[r];if(s&&(n==="streets"||kn(t)))return s;let a=ar[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function yr(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return hr.has(t)?4.5:pr.has(t)?7.5:7}function br(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(mr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=dr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function gr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],_n=[1,25],wr=1.2,xr=1.5,Tr=1.3,Mr=1,kr=[.3,10],vr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),Rr=new Set(["cupressus","calocedrus","thuja"]),_r=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=An(e[t.genus])??An(e[t.species])??(o.endsWith("aceae")?void 0:An(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&vr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&Rr.has(r))return"columnar";if(i.includes("needle")||r&&_r.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function An(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]=Fr(r,w/q,y/q);for(let T of o){let[F,v,L,O]=T.bounds;if(x>=v&&x<=O&&(F<=L?b>=F&&b<=L:b>=F||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],F=Fn(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=Fn(T.height,ee(y,1))),v===void 0&&(v=L/F),L===void 0&&(L=v*F),{height:Te(v,on),crown:Te(L,_n)}},g=(w,y,b,x,T,F)=>{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&&F!==void 0?d(L,v,Fn(st[L].height,Te(F/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),F=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,F,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),F=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,F,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,F=Number(b[t.canopyCover]??30),v=F>=60?3:F>=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 _=[],A=e.hedges;if(A){let w=q/A.extent,y=wr/(s/A.extent);for(let b of A.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?Mr:0,T=(xe(b.properties[t.height],kr)??Tr)+x;for(let F of b.geometry){let v=y/2,L=0;for(let O=0;O+3<F.length;O+=2){let[V,R,S,z]=[F[O],F[O+1],F[O+2],F[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<A.extent&&W<A.extent){let se=ze(r.x*q+G*w,r.y*q+W*w,17);_.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),U=l.map((w,y)=>y);U.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let E=new Uint8Array(l.length*tn),C=new DataView(E.buffer),I=0,N=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...N(),variants:Array.from({length:k(y)},N)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};U.forEach((w,y)=>{let b=l[w],x=y*tn;C.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),C.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),C.setUint16(x+4,Math.round(b.height*10),!0),C.setUint16(x+6,Math.round(b.crown*10),!0),E[x+8]=Math.floor(b.turn*256)&255,E[x+9]=Math.floor(b.shade*256)&255,E[x+10]=b.form,E[x+11]=b.rank,E[x+12]=Math.floor(b.seed*256)&255,E[x+13]=b.canopy,E[x+14]=B[w],I=Math.max(I,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let D=new Uint8Array(_.length*tn),Y=new DataView(D.buffer);return _.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(xr*10),!0),D[b+8]=Math.round(w.turn*256)&255,D[b+9]=Math.floor(w.shade*256)&255,D[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:D,tallest:I,mapped:u,canopy:c}}function 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 Fn([e,n],t){return e+(n-e)*t}function Fr(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function ze(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return ze(e,n,20973)/4294967296}var Sr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Lr(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Lr(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Ur(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Br(a,o,r);return l?[l]:[]}))})}}function Br(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Sr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Or(s,o))})}function Or(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Ur(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Cr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Cr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,Pr=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,Pr.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
4028
4074
|
);
|
|
4029
4075
|
try {
|
|
4030
4076
|
return new Worker(url, { name: "tileflow-tiles" });
|
|
@@ -5392,6 +5438,7 @@ function createCameraTiles(options) {
|
|
|
5392
5438
|
const queue = [];
|
|
5393
5439
|
let wanted = [];
|
|
5394
5440
|
let covered = [];
|
|
5441
|
+
let ring;
|
|
5395
5442
|
let reader;
|
|
5396
5443
|
let zoom = options.zoom;
|
|
5397
5444
|
let origin = [0, 0];
|
|
@@ -5420,30 +5467,14 @@ function createCameraTiles(options) {
|
|
|
5420
5467
|
if (currentZoom < options.minzoom - 1 || !options.active()) return;
|
|
5421
5468
|
const source = ensureReader();
|
|
5422
5469
|
const centre = map.getCenter();
|
|
5423
|
-
const
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
const span = Math.ceil(reach / tileMetres);
|
|
5432
|
-
const candidates = [];
|
|
5433
|
-
for (let dx = -span; dx <= span; dx += 1)
|
|
5434
|
-
for (let dy = -span; dy <= span; dy += 1) {
|
|
5435
|
-
const x3 = Math.floor(cx) + dx;
|
|
5436
|
-
const y2 = Math.floor(cy) + dy;
|
|
5437
|
-
const distance = Math.hypot(
|
|
5438
|
-
Math.max(x3, Math.min(cx, x3 + 1)) - cx,
|
|
5439
|
-
Math.max(y2, Math.min(cy, y2 + 1)) - cy
|
|
5440
|
-
);
|
|
5441
|
-
if (distance * tileMetres <= reach) candidates.push({ x: x3, y: y2, distance });
|
|
5442
|
-
}
|
|
5443
|
-
candidates.sort((a, b2) => a.distance - b2.distance);
|
|
5444
|
-
const chosen = candidates.slice(0, options.maxTiles);
|
|
5445
|
-
wanted = chosen.map(({ x: x3, y: y2 }) => `${x3}/${y2}`);
|
|
5446
|
-
covered = chosen.map(({ x: x3, y: y2 }) => ({ x: x3, y: y2 }));
|
|
5470
|
+
const chosen = cameraTileRing(
|
|
5471
|
+
{ ...centre, zoom: currentZoom, pitch: map.getPitch(), bearing: map.getBearing() },
|
|
5472
|
+
zoom,
|
|
5473
|
+
options.maxTiles
|
|
5474
|
+
);
|
|
5475
|
+
ring = chosen;
|
|
5476
|
+
wanted = chosen.tiles.map(({ x: x3, y: y2 }) => `${x3}/${y2}`);
|
|
5477
|
+
covered = chosen.tiles.map(({ x: x3, y: y2 }) => ({ x: x3, y: y2 }));
|
|
5447
5478
|
origin = cameraTileAt(centre.lng, centre.lat, zoom);
|
|
5448
5479
|
metres = earth * Math.cos(centre.lat * Math.PI / 180) / 2 ** zoom / extent3;
|
|
5449
5480
|
if (!source) {
|
|
@@ -5451,7 +5482,7 @@ function createCameraTiles(options) {
|
|
|
5451
5482
|
return;
|
|
5452
5483
|
}
|
|
5453
5484
|
const now = performance.now();
|
|
5454
|
-
for (const { x: x3, y: y2, distance } of chosen) {
|
|
5485
|
+
for (const { x: x3, y: y2, distance } of chosen.tiles) {
|
|
5455
5486
|
const key = `${x3}/${y2}`;
|
|
5456
5487
|
let entry = tiles.get(key);
|
|
5457
5488
|
if (!entry) {
|
|
@@ -5461,7 +5492,7 @@ function createCameraTiles(options) {
|
|
|
5461
5492
|
entry.used = now;
|
|
5462
5493
|
entry.distance = distance;
|
|
5463
5494
|
if ((!entry.value || entry.retryAt !== void 0) && !entry.loading && (entry.retryAt ?? 0) <= now)
|
|
5464
|
-
load(source, key, entry, tileMetres);
|
|
5495
|
+
load(source, key, entry, chosen.tileMetres);
|
|
5465
5496
|
}
|
|
5466
5497
|
evict();
|
|
5467
5498
|
map.triggerRepaint();
|
|
@@ -5581,6 +5612,7 @@ function createCameraTiles(options) {
|
|
|
5581
5612
|
return list;
|
|
5582
5613
|
},
|
|
5583
5614
|
coverage: () => covered,
|
|
5615
|
+
ring: () => ring,
|
|
5584
5616
|
all: () => tiles.values(),
|
|
5585
5617
|
get zoom() {
|
|
5586
5618
|
return zoom;
|
|
@@ -5676,6 +5708,34 @@ function cameraFrame(callback) {
|
|
|
5676
5708
|
if (typeof requestAnimationFrame === "function") requestAnimationFrame(callback);
|
|
5677
5709
|
else setTimeout(callback, 16);
|
|
5678
5710
|
}
|
|
5711
|
+
function cameraTileRing(camera, tileZoom, maxTiles) {
|
|
5712
|
+
const reach = Math.min(
|
|
5713
|
+
5e3,
|
|
5714
|
+
Math.max(800, 1600 * 2 ** (16 - camera.zoom) * (1 + camera.pitch / 60))
|
|
5715
|
+
);
|
|
5716
|
+
const bearing = camera.bearing * Math.PI / 180;
|
|
5717
|
+
const ahead = reach * 0.35 * Math.min(1, camera.pitch / 60);
|
|
5718
|
+
const latitude = camera.lat + Math.cos(bearing) * ahead / 111320;
|
|
5719
|
+
const longitude = camera.lng + Math.sin(bearing) * ahead / (111320 * Math.cos(camera.lat * Math.PI / 180));
|
|
5720
|
+
const [cx, cy] = cameraTileAt(longitude, latitude, tileZoom);
|
|
5721
|
+
const tileMetres = earth * Math.cos(latitude * Math.PI / 180) / 2 ** tileZoom;
|
|
5722
|
+
const span = Math.ceil(reach / tileMetres);
|
|
5723
|
+
const candidates = [];
|
|
5724
|
+
for (let dx = -span; dx <= span; dx += 1)
|
|
5725
|
+
for (let dy = -span; dy <= span; dy += 1) {
|
|
5726
|
+
const x3 = Math.floor(cx) + dx;
|
|
5727
|
+
const y2 = Math.floor(cy) + dy;
|
|
5728
|
+
const distance = Math.hypot(
|
|
5729
|
+
Math.max(x3, Math.min(cx, x3 + 1)) - cx,
|
|
5730
|
+
Math.max(y2, Math.min(cy, y2 + 1)) - cy
|
|
5731
|
+
);
|
|
5732
|
+
if (distance * tileMetres <= reach) candidates.push({ x: x3, y: y2, distance });
|
|
5733
|
+
}
|
|
5734
|
+
candidates.sort((a, b2) => a.distance - b2.distance);
|
|
5735
|
+
const tiles = candidates.slice(0, maxTiles);
|
|
5736
|
+
const radius = Math.min(reach / tileMetres, candidates[tiles.length]?.distance ?? Infinity);
|
|
5737
|
+
return { tiles, centre: [cx, cy], radius, tileMetres };
|
|
5738
|
+
}
|
|
5679
5739
|
function cameraTileAt(longitude, latitude, zoom) {
|
|
5680
5740
|
const phi = Math.min(85.05, Math.max(-85.05, latitude)) * Math.PI / 180;
|
|
5681
5741
|
return [
|
|
@@ -6451,6 +6511,7 @@ uniform vec2 u_anchor;
|
|
|
6451
6511
|
uniform float u_model_metres;
|
|
6452
6512
|
uniform float u_scale;
|
|
6453
6513
|
out vec4 v_light_coordinates;
|
|
6514
|
+
${tileflowHazeVertex}
|
|
6454
6515
|
void main() {
|
|
6455
6516
|
const int indices[12] = int[12](0, 1, 2, 2, 1, 3, 4, 6, 8, 5, 9, 7);
|
|
6456
6517
|
int index = indices[gl_VertexID];
|
|
@@ -6460,6 +6521,7 @@ void main() {
|
|
|
6460
6521
|
float growth = clamp(u_scale, 0.0, 1.0);
|
|
6461
6522
|
gl_Position = projectTileFor3D(u_anchor + turned * vec2(1.0, -1.0) / u_model_metres,
|
|
6462
6523
|
position.z * growth * growth * (3.0 - 2.0 * growth));
|
|
6524
|
+
v_haze_depth = gl_Position.w;
|
|
6463
6525
|
v_light_coordinates = u_emitter_coordinates[index];
|
|
6464
6526
|
}`;
|
|
6465
6527
|
var modelEmitterFragment = `#version 300 es
|
|
@@ -6468,6 +6530,7 @@ in vec4 v_light_coordinates;
|
|
|
6468
6530
|
uniform vec3 u_emitter_colour;
|
|
6469
6531
|
uniform float u_emitter_strength;
|
|
6470
6532
|
uniform float u_opacity;
|
|
6533
|
+
${tileflowHazeFragment}
|
|
6471
6534
|
out vec4 fragColor;
|
|
6472
6535
|
void main() {
|
|
6473
6536
|
if (u_emitter_strength <= 0.0) discard;
|
|
@@ -6476,7 +6539,7 @@ void main() {
|
|
|
6476
6539
|
float distance = length(vec2(across, light.y)) +
|
|
6477
6540
|
0.5 * (1.0 - clamp(u_emitter_strength - 1.0, 0.0, 1.0));
|
|
6478
6541
|
float alpha = clamp((1.0 - distance * distance) * light.w, 0.0, 1.0);
|
|
6479
|
-
fragColor = vec4(u_emitter_colour, alpha * min(1.0, u_emitter_strength) * u_opacity);
|
|
6542
|
+
fragColor = vec4(hazed(u_emitter_colour), alpha * min(1.0, u_emitter_strength) * u_opacity);
|
|
6480
6543
|
}`;
|
|
6481
6544
|
|
|
6482
6545
|
// src/models-3d-material-shaders.ts
|
|
@@ -6702,12 +6765,14 @@ out vec4 v_uv;
|
|
|
6702
6765
|
out vec4 v_rgba;
|
|
6703
6766
|
out vec3 v_position;
|
|
6704
6767
|
flat out int v_part;
|
|
6768
|
+
${tileflowHazeVertex}
|
|
6705
6769
|
|
|
6706
6770
|
void main() {
|
|
6707
6771
|
vec3 m = turned(metresOf());
|
|
6708
6772
|
vec2 tile = tileOf(m);
|
|
6709
6773
|
float z = grown(m.z);
|
|
6710
6774
|
gl_Position = projectTileFor3D(tile, z);
|
|
6775
|
+
v_haze_depth = gl_Position.w;
|
|
6711
6776
|
vec3 normal = normalize(turned(upright(a_normal)) + vec3(0.0, 0.0, 1e-5));
|
|
6712
6777
|
float facing = clamp(dot(normal, u_shadow_dir), 0.0, 1.0);
|
|
6713
6778
|
vec4 shadow = u_light_matrix * vec4(sceneOf(tile, z) + normal * u_normal_offset * mix(1.0, 0.5, facing), 1.0);
|
|
@@ -6745,6 +6810,7 @@ uniform float u_role_emission_power[7];
|
|
|
6745
6810
|
uniform float u_opacity;
|
|
6746
6811
|
out vec4 fragColor;
|
|
6747
6812
|
${tileflowShadowLookup}
|
|
6813
|
+
${tileflowHazeFragment}
|
|
6748
6814
|
${modelMaterialSampling}
|
|
6749
6815
|
${modelPhysicalLighting}
|
|
6750
6816
|
|
|
@@ -6778,7 +6844,7 @@ void main() {
|
|
|
6778
6844
|
radiance += u_emissive * fromSRGB(materialTexture(4).rgb);
|
|
6779
6845
|
vec4 own = u_role_emission_colour[role];
|
|
6780
6846
|
radiance = mix(radiance, mix(base, fromSRGB(own.rgb), own.a), emission);
|
|
6781
|
-
fragColor = vec4(toSRGB(radiance), alpha * u_opacity);
|
|
6847
|
+
fragColor = vec4(hazed(toSRGB(radiance)), alpha * u_opacity);
|
|
6782
6848
|
return;
|
|
6783
6849
|
}
|
|
6784
6850
|
vec3 colour = v_colour * shade(normal, lit);
|
|
@@ -6788,7 +6854,7 @@ void main() {
|
|
|
6788
6854
|
colour = pow(mix(pow(max(colour, vec3(0.0)), vec3(2.2)),
|
|
6789
6855
|
pow(max(target, vec3(0.0)), vec3(2.2)), emission), vec3(1.0 / 2.2));
|
|
6790
6856
|
}
|
|
6791
|
-
fragColor = vec4(colour, 1.0);
|
|
6857
|
+
fragColor = vec4(hazed(colour), 1.0);
|
|
6792
6858
|
}`;
|
|
6793
6859
|
|
|
6794
6860
|
// src/models-3d-materials-browser.ts
|
|
@@ -7588,6 +7654,10 @@ function tileflowSceneLight(sun, shadows = true) {
|
|
|
7588
7654
|
};
|
|
7589
7655
|
}
|
|
7590
7656
|
var sceneRegistry = /* @__PURE__ */ Symbol.for("tileflow.scene-3d");
|
|
7657
|
+
function tileflowSceneReach(map) {
|
|
7658
|
+
const global = globalThis;
|
|
7659
|
+
return global[sceneRegistry]?.get(map)?.reach();
|
|
7660
|
+
}
|
|
7591
7661
|
function tileflowScene3D(map) {
|
|
7592
7662
|
const global = globalThis;
|
|
7593
7663
|
const scenes = global[sceneRegistry] ??= /* @__PURE__ */ new WeakMap();
|
|
@@ -7604,6 +7674,7 @@ function createScene(map) {
|
|
|
7604
7674
|
let key;
|
|
7605
7675
|
let frame;
|
|
7606
7676
|
let fitted;
|
|
7677
|
+
let reach;
|
|
7607
7678
|
function ensureTarget(context) {
|
|
7608
7679
|
if (target && target.context === context) return target;
|
|
7609
7680
|
const size = Math.min(4096, context.getParameter(context.MAX_TEXTURE_SIZE));
|
|
@@ -7739,6 +7810,10 @@ function createScene(map) {
|
|
|
7739
7810
|
}
|
|
7740
7811
|
}
|
|
7741
7812
|
return {
|
|
7813
|
+
reach: () => reach,
|
|
7814
|
+
setReach(next) {
|
|
7815
|
+
reach = next;
|
|
7816
|
+
},
|
|
7742
7817
|
register(caster) {
|
|
7743
7818
|
casters.add(caster);
|
|
7744
7819
|
key = void 0;
|
|
@@ -8064,6 +8139,123 @@ function isColour(value) {
|
|
|
8064
8139
|
return typeof value === "string" && tileflowColourChannels(value) !== null;
|
|
8065
8140
|
}
|
|
8066
8141
|
|
|
8142
|
+
// src/sky-haze.ts
|
|
8143
|
+
var tileflowSkyHazePitch = [45, 60];
|
|
8144
|
+
var tileflowSkyHazeStart = 1;
|
|
8145
|
+
var horizonShare = 0.85;
|
|
8146
|
+
var horizonLimit = 89.25;
|
|
8147
|
+
var radians = (degrees2) => degrees2 * Math.PI / 180;
|
|
8148
|
+
var smoothstep2 = (from, to, value) => {
|
|
8149
|
+
const t = Math.min(1, Math.max(0, (value - from) / (to - from)));
|
|
8150
|
+
return t * t * (3 - 2 * t);
|
|
8151
|
+
};
|
|
8152
|
+
function tileflowSkyHorizon(pitch) {
|
|
8153
|
+
return Math.min(
|
|
8154
|
+
Math.tan(radians(90 - pitch)) * horizonShare,
|
|
8155
|
+
Math.tan(radians(horizonLimit - pitch))
|
|
8156
|
+
);
|
|
8157
|
+
}
|
|
8158
|
+
function tileflowSkyGroundDepth(pitch, rise) {
|
|
8159
|
+
const cos = Math.cos(radians(pitch));
|
|
8160
|
+
const below = cos - Math.sin(radians(pitch)) * rise;
|
|
8161
|
+
return below > 0 ? cos / below : Number.POSITIVE_INFINITY;
|
|
8162
|
+
}
|
|
8163
|
+
var tileflowSkyHazeReachFloor = 3;
|
|
8164
|
+
var nineTenths = 0.8042;
|
|
8165
|
+
function tileflowSkyReachDepth(view, reach) {
|
|
8166
|
+
const sin = Math.sin(radians(view.pitch));
|
|
8167
|
+
const cos = Math.cos(radians(view.pitch));
|
|
8168
|
+
const back = -sin;
|
|
8169
|
+
const across = Math.atan(view.aspect * Math.tan(view.fov / 2));
|
|
8170
|
+
let nearest;
|
|
8171
|
+
for (let step = -4; step <= 4; step += 1) {
|
|
8172
|
+
const angle = across * step / 4;
|
|
8173
|
+
const [x3, y2] = [Math.sin(angle), Math.cos(angle)];
|
|
8174
|
+
const [dx, dy] = [-reach.across, back - reach.ahead];
|
|
8175
|
+
const b2 = x3 * dx + y2 * dy;
|
|
8176
|
+
const c = dx * dx + dy * dy - reach.radius * reach.radius;
|
|
8177
|
+
const disc = b2 * b2 - c;
|
|
8178
|
+
if (disc < 0) continue;
|
|
8179
|
+
const along = -b2 + Math.sqrt(disc);
|
|
8180
|
+
if (along <= 0) continue;
|
|
8181
|
+
const depth = along * y2 * sin + cos * cos;
|
|
8182
|
+
nearest = nearest === void 0 ? depth : Math.min(nearest, depth);
|
|
8183
|
+
}
|
|
8184
|
+
return nearest;
|
|
8185
|
+
}
|
|
8186
|
+
function tileflowSkyHaze(view) {
|
|
8187
|
+
if (typeof view.horizonColor !== "string") return void 0;
|
|
8188
|
+
const channels = tileflowColourChannels(view.horizonColor);
|
|
8189
|
+
if (!channels || channels[3] < 1) return void 0;
|
|
8190
|
+
const strength = smoothstep2(tileflowSkyHazePitch[0], tileflowSkyHazePitch[1], view.pitch) * (1 - Math.min(1, Math.max(0, view.globe ?? 0)));
|
|
8191
|
+
if (!(strength > 0) || !(view.fov > 0) || !(view.height > 0)) return void 0;
|
|
8192
|
+
const horizon = tileflowSkyHorizon(view.pitch);
|
|
8193
|
+
const ground = tileflowSkyGroundDepth(view.pitch, horizon);
|
|
8194
|
+
if (!Number.isFinite(ground) || ground <= tileflowSkyHazeStart) return void 0;
|
|
8195
|
+
const edge = view.reach && view.aspect ? tileflowSkyReachDepth({ ...view, aspect: view.aspect }, view.reach) : void 0;
|
|
8196
|
+
const fitted = edge === void 0 ? Infinity : tileflowSkyHazeStart + (Math.max(tileflowSkyHazeReachFloor, edge) - tileflowSkyHazeStart) / nineTenths;
|
|
8197
|
+
const end = Math.min(ground, fitted);
|
|
8198
|
+
return {
|
|
8199
|
+
colour: [channels[0], channels[1], channels[2]],
|
|
8200
|
+
strength,
|
|
8201
|
+
distance: view.height / 2 / Math.tan(view.fov / 2),
|
|
8202
|
+
start: tileflowSkyHazeStart,
|
|
8203
|
+
end,
|
|
8204
|
+
horizon
|
|
8205
|
+
};
|
|
8206
|
+
}
|
|
8207
|
+
|
|
8208
|
+
// src/sky-haze-browser.ts
|
|
8209
|
+
function tileflowSkyHazeOf(map, args, context) {
|
|
8210
|
+
const sky = map.getSky?.();
|
|
8211
|
+
if (!sky) return void 0;
|
|
8212
|
+
const pixelRatio2 = globalThis.devicePixelRatio || 1;
|
|
8213
|
+
const height = map.getCanvas?.().clientHeight || (context ? context.drawingBufferHeight / pixelRatio2 : 0);
|
|
8214
|
+
const fov = fovOf(map, args);
|
|
8215
|
+
const aspect = context ? context.drawingBufferWidth / context.drawingBufferHeight : void 0;
|
|
8216
|
+
const reach = reachOf(map, height / 2 / Math.tan(fov / 2));
|
|
8217
|
+
return tileflowSkyHaze({
|
|
8218
|
+
horizonColor: sky["horizon-color"],
|
|
8219
|
+
pitch: map.getPitch(),
|
|
8220
|
+
fov,
|
|
8221
|
+
height,
|
|
8222
|
+
globe: args?.defaultProjectionData?.projectionTransition ?? 0,
|
|
8223
|
+
...reach && aspect ? { reach, aspect } : {}
|
|
8224
|
+
});
|
|
8225
|
+
}
|
|
8226
|
+
function reachOf(map, distance) {
|
|
8227
|
+
const reach = tileflowSceneReach(map);
|
|
8228
|
+
const centre = map.getCenter?.();
|
|
8229
|
+
const zoom = map.getZoom?.();
|
|
8230
|
+
if (!reach || !centre || zoom === void 0 || !(distance > 0)) return void 0;
|
|
8231
|
+
const cos = Math.cos(centre.lat * Math.PI / 180);
|
|
8232
|
+
const metres = distance * 40075016686e-3 * cos / (512 * 2 ** zoom);
|
|
8233
|
+
const east = (reach.lng - centre.lng) * 111320 * cos;
|
|
8234
|
+
const north = (reach.lat - centre.lat) * 111320;
|
|
8235
|
+
const bearing = (map.getBearing?.() ?? 0) * Math.PI / 180;
|
|
8236
|
+
return {
|
|
8237
|
+
ahead: (east * Math.sin(bearing) + north * Math.cos(bearing)) / metres,
|
|
8238
|
+
across: (east * Math.cos(bearing) - north * Math.sin(bearing)) / metres,
|
|
8239
|
+
radius: reach.radius / metres
|
|
8240
|
+
};
|
|
8241
|
+
}
|
|
8242
|
+
function fovOf(map, args) {
|
|
8243
|
+
return args?.fov ?? (map.getVerticalFieldOfView?.() ?? 36.87) * Math.PI / 180;
|
|
8244
|
+
}
|
|
8245
|
+
function bindTileflowSkyHaze(context, uniforms, haze) {
|
|
8246
|
+
if (!haze) {
|
|
8247
|
+
context.uniform3f(uniforms.u_haze ?? null, 0, 0, 1);
|
|
8248
|
+
return;
|
|
8249
|
+
}
|
|
8250
|
+
context.uniform3fv(uniforms.u_haze_colour ?? null, haze.colour);
|
|
8251
|
+
context.uniform3f(
|
|
8252
|
+
uniforms.u_haze ?? null,
|
|
8253
|
+
haze.strength,
|
|
8254
|
+
haze.start * haze.distance,
|
|
8255
|
+
haze.end * haze.distance
|
|
8256
|
+
);
|
|
8257
|
+
}
|
|
8258
|
+
|
|
8067
8259
|
// src/buildings-3d-browser.ts
|
|
8068
8260
|
var tileflowBuildings3DLayerId = "tileflow-buildings-3d";
|
|
8069
8261
|
var preferredZoom = 15;
|
|
@@ -8104,6 +8296,8 @@ function createTileflowBuildings3D(options) {
|
|
|
8104
8296
|
const floodMask = createBuildingContactMask();
|
|
8105
8297
|
let masks = {};
|
|
8106
8298
|
let disposed = false;
|
|
8299
|
+
let hazeDepth = Infinity;
|
|
8300
|
+
let ahead = [0, -1];
|
|
8107
8301
|
const scene = tileflowScene3D(map);
|
|
8108
8302
|
let generation = 0;
|
|
8109
8303
|
let registered = false;
|
|
@@ -8156,6 +8350,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8156
8350
|
for (const entry of linking ?? []) context.deleteProgram(entry.program);
|
|
8157
8351
|
unregister();
|
|
8158
8352
|
registered = false;
|
|
8353
|
+
scene.setReach(void 0);
|
|
8159
8354
|
scene.release(context);
|
|
8160
8355
|
if (ground) {
|
|
8161
8356
|
context.deleteVertexArray(ground.vao);
|
|
@@ -8172,6 +8367,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8172
8367
|
},
|
|
8173
8368
|
prerender(context, args) {
|
|
8174
8369
|
if (!isWebGL2(context)) return;
|
|
8370
|
+
ahead = aheadNow();
|
|
8175
8371
|
ensureCamera();
|
|
8176
8372
|
if (target > 0 || scale > 0)
|
|
8177
8373
|
models.update(
|
|
@@ -8205,6 +8401,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8205
8401
|
return;
|
|
8206
8402
|
}
|
|
8207
8403
|
if (target > 0 || scale > 0) upload(context);
|
|
8404
|
+
scene.setReach(visibleScale() > 0 ? reachNow() : void 0);
|
|
8208
8405
|
if (visibleScale() <= 0 && modelScale() <= 0) return;
|
|
8209
8406
|
draw(context, args);
|
|
8210
8407
|
}
|
|
@@ -8547,6 +8744,8 @@ function createTileflowBuildings3D(options) {
|
|
|
8547
8744
|
context.uniformMatrix4fv(program.uniforms.u_light_matrix, false, frame.light.matrix);
|
|
8548
8745
|
for (const { x: x3, y: y2, value } of shown > 0 ? drawn() : []) {
|
|
8549
8746
|
const offset = frame.offsetOf({ x: x3, y: y2 }, camera.zoom);
|
|
8747
|
+
const ring = ringIn(x3, y2);
|
|
8748
|
+
if (!insideRing(ring, 0, 0, tileflowBuildingExtent, tileflowBuildingExtent)) continue;
|
|
8550
8749
|
if (!buildingBoxVisible(frame.light.matrix, [
|
|
8551
8750
|
(offset[0] - 1) * frame.metres,
|
|
8552
8751
|
-(offset[1] + tileflowBuildingExtent + 1) * frame.metres,
|
|
@@ -8558,7 +8757,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8558
8757
|
continue;
|
|
8559
8758
|
const ranges = buildingDrawRanges(
|
|
8560
8759
|
value.mesh,
|
|
8561
|
-
({ bounds: [left, top, right, bottom, height] }) => buildingBoxVisible(frame.light.matrix, [
|
|
8760
|
+
({ bounds: [left, top, right, bottom, height] }) => insideRing(ring, left, top, right, bottom) && buildingBoxVisible(frame.light.matrix, [
|
|
8562
8761
|
(left + offset[0]) * frame.metres,
|
|
8563
8762
|
-(bottom + offset[1]) * frame.metres,
|
|
8564
8763
|
0,
|
|
@@ -8569,6 +8768,8 @@ function createTileflowBuildings3D(options) {
|
|
|
8569
8768
|
);
|
|
8570
8769
|
if (!ranges.length) continue;
|
|
8571
8770
|
context.uniform2f(program.uniforms.u_offset, ...offset);
|
|
8771
|
+
context.uniform4f(program.uniforms.u_ring ?? null, ...ring);
|
|
8772
|
+
context.uniform2f(program.uniforms.u_ring_ahead ?? null, ...ahead);
|
|
8572
8773
|
const buffers = value.gl;
|
|
8573
8774
|
context.bindVertexArray(buffers.vao);
|
|
8574
8775
|
for (const range of ranges)
|
|
@@ -8794,31 +8995,57 @@ function createTileflowBuildings3D(options) {
|
|
|
8794
8995
|
context.uniform1f(uniforms.u_projection_transition, data.projectionTransition);
|
|
8795
8996
|
context.uniformMatrix4fv(uniforms.u_projection_fallback_matrix, false, data.fallbackMatrix);
|
|
8796
8997
|
}
|
|
8998
|
+
function reachNow() {
|
|
8999
|
+
const ring = camera.ring();
|
|
9000
|
+
if (!ring) return void 0;
|
|
9001
|
+
const n = 2 ** camera.zoom;
|
|
9002
|
+
return {
|
|
9003
|
+
lng: ring.centre[0] / n * 360 - 180,
|
|
9004
|
+
lat: Math.atan(Math.sinh(Math.PI * (1 - 2 * ring.centre[1] / n))) * 180 / Math.PI,
|
|
9005
|
+
radius: ring.radius * ring.tileMetres
|
|
9006
|
+
};
|
|
9007
|
+
}
|
|
9008
|
+
function ringIn(x3, y2) {
|
|
9009
|
+
const ring = camera.ring();
|
|
9010
|
+
if (!ring) return [0, 0, 0, 0];
|
|
9011
|
+
const extent4 = tileflowBuildingExtent;
|
|
9012
|
+
const cx = (ring.centre[0] - x3) * extent4;
|
|
9013
|
+
const cy = (ring.centre[1] - y2) * extent4;
|
|
9014
|
+
const inner = ring.radius * extent4 * 0.8;
|
|
9015
|
+
const dx = Math.max(Math.abs(cx), Math.abs(extent4 - cx));
|
|
9016
|
+
const dy = Math.max(Math.abs(cy), Math.abs(extent4 - cy));
|
|
9017
|
+
if (dx * dx + dy * dy <= inner * inner) return [0, 0, 0, 0];
|
|
9018
|
+
return [cx, cy, inner, ring.radius * extent4];
|
|
9019
|
+
}
|
|
9020
|
+
function aheadNow() {
|
|
9021
|
+
const bearing = map.getBearing() * Math.PI / 180;
|
|
9022
|
+
return [Math.sin(bearing), -Math.cos(bearing)];
|
|
9023
|
+
}
|
|
9024
|
+
function insideRing(ring, left, top, right, bottom) {
|
|
9025
|
+
const radius = ring[3];
|
|
9026
|
+
if (!(radius > 0)) return true;
|
|
9027
|
+
const cx = ring[0];
|
|
9028
|
+
const cy = ring[1];
|
|
9029
|
+
const dx = Math.max(left - cx, 0, cx - right);
|
|
9030
|
+
const dy = Math.max(top - cy, 0, cy - bottom);
|
|
9031
|
+
if (dx * dx + dy * dy < radius * radius) return true;
|
|
9032
|
+
const along = Math.min(ahead[0] * (left - cx), ahead[0] * (right - cx)) + Math.min(ahead[1] * (top - cy), ahead[1] * (bottom - cy));
|
|
9033
|
+
return along < radius - ring[2];
|
|
9034
|
+
}
|
|
8797
9035
|
function viewRanges(args, tile, margin = 0, wallsOnly = false) {
|
|
8798
9036
|
const data = args.getProjectionData({
|
|
8799
9037
|
tileID: { canonical: { x: tile.x, y: tile.y, z: camera.zoom }, wrap: 0 }
|
|
8800
9038
|
});
|
|
8801
9039
|
const mercator = args.shaderData.variantName === "mercator";
|
|
8802
9040
|
const reach = margin / camera.metres + 1;
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
tileflowBuildingExtent + reach,
|
|
8809
|
-
tile.value.mesh.top + 0.1
|
|
8810
|
-
]))
|
|
8811
|
-
return [];
|
|
9041
|
+
const ring = ringIn(tile.x, tile.y);
|
|
9042
|
+
const hazed = mercator && hazeDepth < Infinity;
|
|
9043
|
+
const shows = (box) => (!mercator || buildingBoxVisible(data.mainMatrix, box)) && insideRing(ring, box[0], box[1], box[3], box[4]) && (!hazed || buildingBoxDepth(data.mainMatrix, box) < hazeDepth);
|
|
9044
|
+
const extent4 = tileflowBuildingExtent + reach;
|
|
9045
|
+
if (!shows([-reach, -reach, 0, extent4, extent4, tile.value.mesh.top + 0.1])) return [];
|
|
8812
9046
|
return buildingDrawRanges(
|
|
8813
9047
|
tile.value.mesh,
|
|
8814
|
-
({ bounds: [left, top, right, bottom, height] }) =>
|
|
8815
|
-
left - reach,
|
|
8816
|
-
top - reach,
|
|
8817
|
-
0,
|
|
8818
|
-
right + reach,
|
|
8819
|
-
bottom + reach,
|
|
8820
|
-
height
|
|
8821
|
-
]),
|
|
9048
|
+
({ bounds: [left, top, right, bottom, height] }) => shows([left - reach, top - reach, 0, right + reach, bottom + reach, height]),
|
|
8822
9049
|
wallsOnly
|
|
8823
9050
|
);
|
|
8824
9051
|
}
|
|
@@ -8907,6 +9134,8 @@ function createTileflowBuildings3D(options) {
|
|
|
8907
9134
|
} else floodMask.release(context);
|
|
8908
9135
|
}
|
|
8909
9136
|
function draw(context, args) {
|
|
9137
|
+
const haze = tileflowSkyHazeOf(map, args, context);
|
|
9138
|
+
hazeDepth = haze && haze.strength >= 0.999 ? haze.end * haze.distance : Infinity;
|
|
8910
9139
|
const shown = visibleScale();
|
|
8911
9140
|
const modelsShown = modelScale();
|
|
8912
9141
|
const entries = shown > 0 ? drawn() : [];
|
|
@@ -8929,6 +9158,7 @@ function createTileflowBuildings3D(options) {
|
|
|
8929
9158
|
const buildings = programs.buildings;
|
|
8930
9159
|
const u = buildings.uniforms;
|
|
8931
9160
|
context.useProgram(buildings.program);
|
|
9161
|
+
bindTileflowSkyHaze(context, buildings.uniforms, haze);
|
|
8932
9162
|
context.uniform1f(u.u_scale, shown);
|
|
8933
9163
|
context.uniform1f(u.u_metres, placed2(0, 0).metres);
|
|
8934
9164
|
context.uniform3fv(u.u_colour, themeColour());
|
|
@@ -8983,6 +9213,8 @@ function createTileflowBuildings3D(options) {
|
|
|
8983
9213
|
if (!ranges.length) continue;
|
|
8984
9214
|
project(context, buildings, args, x3, y2);
|
|
8985
9215
|
context.uniform2f(u.u_offset, ...placed2(x3, y2).offset);
|
|
9216
|
+
context.uniform4f(u.u_ring ?? null, ...ringIn(x3, y2));
|
|
9217
|
+
context.uniform2f(u.u_ring_ahead ?? null, ...ahead);
|
|
8986
9218
|
const palette = themes ? paletteOf(context, entry, themes.themes) : void 0;
|
|
8987
9219
|
context.uniform1f(u.u_palette_on, palette ? 1 : 0);
|
|
8988
9220
|
context.activeTexture(context.TEXTURE1);
|
|
@@ -9045,6 +9277,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9045
9277
|
if (model && list.length > 0) {
|
|
9046
9278
|
const m = model.uniforms;
|
|
9047
9279
|
context.useProgram(model.program);
|
|
9280
|
+
bindTileflowSkyHaze(context, model.uniforms, haze);
|
|
9048
9281
|
context.disable(context.CULL_FACE);
|
|
9049
9282
|
context.uniform1f(m.u_scale, modelsShown);
|
|
9050
9283
|
context.uniform3fv(m.u_sun_dir, [...light.direction]);
|
|
@@ -9090,6 +9323,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9090
9323
|
if (light.strength > 0 && frame && frame.zoom === camera.zoom && ground && scene.drawsGround(caster)) {
|
|
9091
9324
|
const program = programs.ground;
|
|
9092
9325
|
context.useProgram(program.program);
|
|
9326
|
+
bindTileflowSkyHaze(context, program.uniforms, haze);
|
|
9093
9327
|
context.uniform1f(program.uniforms.u_metres, frame.metres);
|
|
9094
9328
|
context.uniform3fv(program.uniforms.u_ground_shadow, light.groundShadow);
|
|
9095
9329
|
scene.bindShadow(context, program.uniforms, light.strength);
|
|
@@ -9115,6 +9349,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9115
9349
|
if (masks.contact && entries.length > 0 && ground) {
|
|
9116
9350
|
const composite = programs.contactComposite;
|
|
9117
9351
|
context.useProgram(composite.program);
|
|
9352
|
+
bindTileflowSkyHaze(context, composite.uniforms, haze);
|
|
9118
9353
|
context.activeTexture(context.TEXTURE2);
|
|
9119
9354
|
context.bindTexture(context.TEXTURE_2D, masks.contact);
|
|
9120
9355
|
context.uniform1i(composite.uniforms.u_contact, 2);
|
|
@@ -9132,6 +9367,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9132
9367
|
if (nightLight2 > 0 && light.night > 0.01) {
|
|
9133
9368
|
const program = programs.flood;
|
|
9134
9369
|
context.useProgram(program.program);
|
|
9370
|
+
bindTileflowSkyHaze(context, program.uniforms, haze);
|
|
9135
9371
|
context.blendFuncSeparate(context.ONE, context.ONE, context.ZERO, context.ONE);
|
|
9136
9372
|
context.uniform1f(program.uniforms.u_scale, shown);
|
|
9137
9373
|
context.uniform1f(program.uniforms.u_metres, camera.metres);
|
|
@@ -9143,6 +9379,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9143
9379
|
if (masks.flood && entries.length > 0 && ground) {
|
|
9144
9380
|
const composite = programs.architecturalFloodComposite;
|
|
9145
9381
|
context.useProgram(composite.program);
|
|
9382
|
+
bindTileflowSkyHaze(context, composite.uniforms, haze);
|
|
9146
9383
|
context.activeTexture(context.TEXTURE2);
|
|
9147
9384
|
context.bindTexture(context.TEXTURE_2D, masks.flood);
|
|
9148
9385
|
context.uniform1i(composite.uniforms.u_mask, 2);
|
|
@@ -9167,6 +9404,7 @@ function createTileflowBuildings3D(options) {
|
|
|
9167
9404
|
if (emitterProgram) {
|
|
9168
9405
|
const u = emitterProgram.uniforms;
|
|
9169
9406
|
context.useProgram(emitterProgram.program);
|
|
9407
|
+
bindTileflowSkyHaze(context, emitterProgram.uniforms, haze);
|
|
9170
9408
|
context.disable(context.CULL_FACE);
|
|
9171
9409
|
context.blendFuncSeparate(
|
|
9172
9410
|
context.SRC_ALPHA,
|
|
@@ -9455,6 +9693,7 @@ ${shaderData.define}`;
|
|
|
9455
9693
|
map.off("styledata", onStyle);
|
|
9456
9694
|
map.off("idle", attach);
|
|
9457
9695
|
unregister();
|
|
9696
|
+
scene.setReach(void 0);
|
|
9458
9697
|
models.dispose();
|
|
9459
9698
|
try {
|
|
9460
9699
|
if (map.getLayer(tileflowBuildings3DLayerId)) map.removeLayer(tileflowBuildings3DLayerId);
|
|
@@ -10727,6 +10966,7 @@ out vec3 v_shadow;
|
|
|
10727
10966
|
out vec3 v_look; // part, lobe shade, occlusion
|
|
10728
10967
|
out float v_shade; // the tree's shade among the theme's colours
|
|
10729
10968
|
out float v_fade;
|
|
10969
|
+
${tileflowHazeVertex}
|
|
10730
10970
|
void main() {
|
|
10731
10971
|
float growth = growthOf();
|
|
10732
10972
|
if (growth <= 0.0) {
|
|
@@ -10735,6 +10975,7 @@ void main() {
|
|
|
10735
10975
|
}
|
|
10736
10976
|
vec3 local = standing(growth);
|
|
10737
10977
|
gl_Position = projectTileFor3D(a_tree_pos + local.xy / u_metres * vec2(1.0, -1.0), local.z);
|
|
10978
|
+
v_haze_depth = gl_Position.w;
|
|
10738
10979
|
vec3 normal = normalOf();
|
|
10739
10980
|
float facing = clamp(dot(normal, u_shadow_dir), 0.0, 1.0);
|
|
10740
10981
|
vec4 shadow = u_light_matrix *
|
|
@@ -10764,6 +11005,7 @@ uniform vec3 u_leaves[4]; // the form's colours, sunlit
|
|
|
10764
11005
|
uniform float u_leaf_count;
|
|
10765
11006
|
out vec4 fragColor;
|
|
10766
11007
|
${tileflowShadowLookup}
|
|
11008
|
+
${tileflowHazeFragment}
|
|
10767
11009
|
|
|
10768
11010
|
${treeDither}
|
|
10769
11011
|
|
|
@@ -10813,7 +11055,7 @@ void main() {
|
|
|
10813
11055
|
// and scene illumination, so a grey tree in neutral light stays grey.
|
|
10814
11056
|
float crownTop = bark ? 0.0 : smoothstep(0.1, 0.9, normal.z);
|
|
10815
11057
|
colour = mix(colour, base * 0.95 + vec3(0.03), u_night * 0.45 * crownTop);
|
|
10816
|
-
fragColor = vec4(colour, 1.0);
|
|
11058
|
+
fragColor = vec4(hazed(colour), 1.0);
|
|
10817
11059
|
}`;
|
|
10818
11060
|
var tileflowTreeEdgeVertex = (projected) => `#version 300 es
|
|
10819
11061
|
${projected}
|
|
@@ -10824,6 +11066,7 @@ uniform vec2 u_viewport; // the drawing buffer's size, in pixels
|
|
|
10824
11066
|
uniform float u_edge_width; // the outline's width, in the drawing buffer's pixels
|
|
10825
11067
|
${placement2}
|
|
10826
11068
|
out float v_fade;
|
|
11069
|
+
${tileflowHazeVertex}
|
|
10827
11070
|
void main() {
|
|
10828
11071
|
float growth = growthOf();
|
|
10829
11072
|
// Fronds are seen from both sides: they keep no outline.
|
|
@@ -10841,6 +11084,7 @@ void main() {
|
|
|
10841
11084
|
vec2 push = length(screen) > 1e-6 ? normalize(screen) : vec2(0.0);
|
|
10842
11085
|
at.xy += push * u_edge_width * 2.0 / u_viewport * at.w;
|
|
10843
11086
|
gl_Position = at;
|
|
11087
|
+
v_haze_depth = at.w;
|
|
10844
11088
|
float distance = length((a_tree_pos - u_centre) * u_metres);
|
|
10845
11089
|
v_fade = 1.0 - smoothstep(u_reach.x, u_reach.y, distance);
|
|
10846
11090
|
}`;
|
|
@@ -10849,6 +11093,7 @@ precision highp float;
|
|
|
10849
11093
|
in float v_fade;
|
|
10850
11094
|
uniform float u_fade;
|
|
10851
11095
|
uniform vec3 u_edge_colour;
|
|
11096
|
+
${tileflowHazeFragment}
|
|
10852
11097
|
out vec4 fragColor;
|
|
10853
11098
|
|
|
10854
11099
|
float dither(vec2 p) {
|
|
@@ -10860,7 +11105,7 @@ float dither(vec2 p) {
|
|
|
10860
11105
|
|
|
10861
11106
|
void main() {
|
|
10862
11107
|
if (v_fade * u_fade < dither(gl_FragCoord.xy)) discard;
|
|
10863
|
-
fragColor = vec4(u_edge_colour, 1.0);
|
|
11108
|
+
fragColor = vec4(hazed(u_edge_colour), 1.0);
|
|
10864
11109
|
}`;
|
|
10865
11110
|
|
|
10866
11111
|
// src/trees-3d-view.ts
|
|
@@ -11323,6 +11568,7 @@ function createTileflowTrees3D(options) {
|
|
|
11323
11568
|
context.uniformMatrix4fv(uniforms.u_projection_fallback_matrix, false, data.fallbackMatrix);
|
|
11324
11569
|
}
|
|
11325
11570
|
function draw(context, args) {
|
|
11571
|
+
const haze = tileflowSkyHazeOf(map, args, context);
|
|
11326
11572
|
const entries = drawn();
|
|
11327
11573
|
drawnLast = 0;
|
|
11328
11574
|
if (entries.length === 0 || !meshes || !programs.trees) return;
|
|
@@ -11337,6 +11583,7 @@ function createTileflowTrees3D(options) {
|
|
|
11337
11583
|
const program = programs.trees;
|
|
11338
11584
|
const u = program.uniforms;
|
|
11339
11585
|
context.useProgram(program.program);
|
|
11586
|
+
bindTileflowSkyHaze(context, program.uniforms, haze);
|
|
11340
11587
|
context.enable(context.DEPTH_TEST);
|
|
11341
11588
|
context.depthFunc(context.LEQUAL);
|
|
11342
11589
|
context.depthMask(true);
|
|
@@ -11404,6 +11651,7 @@ function createTileflowTrees3D(options) {
|
|
|
11404
11651
|
const edgeProgram = programs.edges;
|
|
11405
11652
|
const e = edgeProgram.uniforms;
|
|
11406
11653
|
context.useProgram(edgeProgram.program);
|
|
11654
|
+
bindTileflowSkyHaze(context, edgeProgram.uniforms, haze);
|
|
11407
11655
|
context.enable(context.CULL_FACE);
|
|
11408
11656
|
context.cullFace(context.FRONT);
|
|
11409
11657
|
context.uniform1f(e.u_scale, visibleScale());
|
|
@@ -11444,6 +11692,7 @@ function createTileflowTrees3D(options) {
|
|
|
11444
11692
|
context.enable(context.BLEND);
|
|
11445
11693
|
context.blendFuncSeparate(context.DST_COLOR, context.ZERO, context.ZERO, context.ONE);
|
|
11446
11694
|
context.useProgram(shadowProgram.program);
|
|
11695
|
+
bindTileflowSkyHaze(context, shadowProgram.uniforms, haze);
|
|
11447
11696
|
context.uniform1f(shadowProgram.uniforms.u_metres, frame.metres);
|
|
11448
11697
|
context.uniform3fv(shadowProgram.uniforms.u_ground_shadow, light.groundShadow);
|
|
11449
11698
|
scene.bindShadow(context, shadowProgram.uniforms, light.strength);
|