@tileflow/core 0.1.0-alpha.39 → 0.1.0-alpha.40
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 +11 -10
- package/dist/{3d-BkaJjwfk.d.ts → 3d-CzLTD0RK.d.ts} +10 -1
- package/dist/3d.d.ts +1 -1
- package/dist/3d.js +199 -16
- package/dist/browser.d.ts +87 -11
- package/dist/browser.js +754 -178
- package/dist/build.d.ts +3 -3
- package/dist/build.js +3714 -3346
- package/dist/config-reference.json +4418 -2280
- package/dist/{icon-composition-Ivgoxz8d.d.ts → icon-composition-CcSHApUm.d.ts} +49 -2
- package/dist/index.d.ts +7 -5
- package/dist/index.js +5110 -4733
- package/dist/{manifest-types-DRy2980g.d.ts → manifest-types-DnhSJjCM.d.ts} +14 -3
- package/dist/manifest.d.ts +2 -2
- package/dist/native.js +3 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/worker/camera-tile-worker.global.js +2 -2
- package/docs/buildings-3d.md +33 -1
- package/docs/cartographic-defaults.md +69 -1
- package/docs/data-is-separate-from-design.md +5 -2
- package/docs/globe-atmosphere.md +46 -19
- package/docs/street-sky.md +3 -0
- package/docs/theme-transitions-and-blends.md +27 -20
- package/docs/trees-3d.md +7 -0
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -325,6 +325,9 @@ function assertSameStructure(styles, base) {
|
|
|
325
325
|
throw new TileflowThemeBlendError("Blended themes must use the same sources.");
|
|
326
326
|
if (!same(style.sprite, base.sprite) || !same(style.glyphs, base.glyphs))
|
|
327
327
|
throw new TileflowThemeBlendError("Blended themes must use the same sprite and glyphs.");
|
|
328
|
+
for (const key of ["projection", "terrain"])
|
|
329
|
+
if (!same(style[key], base[key]))
|
|
330
|
+
throw new TileflowThemeBlendError(`Blended themes must use the same ${key}.`);
|
|
328
331
|
for (const [index, layer] of style.layers.entries()) {
|
|
329
332
|
const other = base.layers[index];
|
|
330
333
|
for (const key of ["type", "source", "source-layer", "filter", "minzoom", "maxzoom"])
|
|
@@ -3707,6 +3710,74 @@ function getTileflowLocationOrigin() {
|
|
|
3707
3710
|
return window.location.origin;
|
|
3708
3711
|
}
|
|
3709
3712
|
|
|
3713
|
+
// src/sky.ts
|
|
3714
|
+
init_theme_blend();
|
|
3715
|
+
var tileflowSkyMetadataKey = "tileflow:sky";
|
|
3716
|
+
var hexColour = /^#[0-9a-f]{6}$/iu;
|
|
3717
|
+
var unit = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
|
|
3718
|
+
function readColours(value) {
|
|
3719
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3720
|
+
const record3 = value;
|
|
3721
|
+
if (Object.keys(record3).length !== 4) return void 0;
|
|
3722
|
+
const { color, horizonColor, horizonBlend, glowColor } = record3;
|
|
3723
|
+
if (typeof color !== "string" || !hexColour.test(color) || typeof horizonColor !== "string" || !hexColour.test(horizonColor) || typeof glowColor !== "string" || !hexColour.test(glowColor) || !unit(horizonBlend))
|
|
3724
|
+
return void 0;
|
|
3725
|
+
return { color, horizonColor, horizonBlend, glowColor };
|
|
3726
|
+
}
|
|
3727
|
+
function readTileflowSky(value) {
|
|
3728
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
3729
|
+
const record3 = value;
|
|
3730
|
+
const keys = Object.keys(record3);
|
|
3731
|
+
if (record3.version !== 1 || keys.length !== (record3.timesOfDay === void 0 ? 3 : 4))
|
|
3732
|
+
return void 0;
|
|
3733
|
+
const { starIntensity, glowColor, timesOfDay } = record3;
|
|
3734
|
+
if (!unit(starIntensity) || typeof glowColor !== "string" || !hexColour.test(glowColor))
|
|
3735
|
+
return void 0;
|
|
3736
|
+
if (timesOfDay === void 0) return { version: 1, starIntensity, glowColor };
|
|
3737
|
+
if (!timesOfDay || typeof timesOfDay !== "object" || Array.isArray(timesOfDay)) return void 0;
|
|
3738
|
+
const times = timesOfDay;
|
|
3739
|
+
if (Object.keys(times).length !== 4) return void 0;
|
|
3740
|
+
const day = readColours(times.day);
|
|
3741
|
+
const dawn = readColours(times.dawn);
|
|
3742
|
+
const dusk = readColours(times.dusk);
|
|
3743
|
+
const night = readColours(times.night);
|
|
3744
|
+
if (!day || !dawn || !dusk || !night) return void 0;
|
|
3745
|
+
return { version: 1, starIntensity, glowColor, timesOfDay: { day, dawn, dusk, night } };
|
|
3746
|
+
}
|
|
3747
|
+
function tileflowSkyStarVisibility(channels) {
|
|
3748
|
+
const linear = channels.map(
|
|
3749
|
+
(channel) => channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4
|
|
3750
|
+
);
|
|
3751
|
+
const luminance2 = 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];
|
|
3752
|
+
const progress = Math.min(1, Math.max(0, (0.06 - luminance2) / (0.06 - 0.015)));
|
|
3753
|
+
return progress * progress * (3 - 2 * progress);
|
|
3754
|
+
}
|
|
3755
|
+
var smooth = (from, to, value) => {
|
|
3756
|
+
const t = Math.min(1, Math.max(0, (value - from) / (to - from)));
|
|
3757
|
+
return t * t * (3 - 2 * t);
|
|
3758
|
+
};
|
|
3759
|
+
function tileflowSkyGlowStrength(altitude) {
|
|
3760
|
+
return smooth(-9, -1, altitude) * (1 - smooth(6, 24, altitude));
|
|
3761
|
+
}
|
|
3762
|
+
function mixColours(from, to, t) {
|
|
3763
|
+
if (t <= 0) return from;
|
|
3764
|
+
if (t >= 1) return to;
|
|
3765
|
+
return {
|
|
3766
|
+
color: mixTileflowColours(from.color, to.color, t) ?? to.color,
|
|
3767
|
+
horizonColor: mixTileflowColours(from.horizonColor, to.horizonColor, t) ?? to.horizonColor,
|
|
3768
|
+
horizonBlend: from.horizonBlend + (to.horizonBlend - from.horizonBlend) * t,
|
|
3769
|
+
glowColor: mixTileflowColours(from.glowColor, to.glowColor, t) ?? to.glowColor
|
|
3770
|
+
};
|
|
3771
|
+
}
|
|
3772
|
+
function tileflowSkyAtSun(times, sun) {
|
|
3773
|
+
const azimuth = (sun.azimuth % 360 + 360) % 360;
|
|
3774
|
+
const twilight = azimuth < 180 ? times.dawn : times.dusk;
|
|
3775
|
+
if (sun.altitude >= 2) return mixColours(twilight, times.day, smooth(2, 14, sun.altitude));
|
|
3776
|
+
if (sun.altitude >= -2) return twilight;
|
|
3777
|
+
return mixColours(times.night, twilight, smooth(-10, -2, sun.altitude));
|
|
3778
|
+
}
|
|
3779
|
+
var tileflowSkySunKey = /* @__PURE__ */ Symbol.for("tileflow.skySun");
|
|
3780
|
+
|
|
3710
3781
|
// src/browser.ts
|
|
3711
3782
|
init_sun();
|
|
3712
3783
|
init_theme_blend();
|
|
@@ -3823,7 +3894,7 @@ function emphasizeTileflowValue(target, value, options) {
|
|
|
3823
3894
|
if (amount <= 0) return value;
|
|
3824
3895
|
if (target.kind === "fade") return scaleOpacity(value, 1 - amount);
|
|
3825
3896
|
if (options.ground === void 0) return value;
|
|
3826
|
-
return
|
|
3897
|
+
return mixColours2(value, options.ground, amount);
|
|
3827
3898
|
}
|
|
3828
3899
|
function tileflowEmphasisGround(layers) {
|
|
3829
3900
|
for (const layer of layers) {
|
|
@@ -3845,11 +3916,11 @@ function firstColour(value) {
|
|
|
3845
3916
|
}
|
|
3846
3917
|
return void 0;
|
|
3847
3918
|
}
|
|
3848
|
-
function
|
|
3919
|
+
function mixColours2(value, toward, amount) {
|
|
3849
3920
|
if (typeof value === "string") return mixTileflowColours(value, toward, amount) ?? value;
|
|
3850
3921
|
if (Array.isArray(value)) {
|
|
3851
3922
|
if (value[0] === "literal") return value;
|
|
3852
|
-
return value.map((item, index) => index === 0 ? item :
|
|
3923
|
+
return value.map((item, index) => index === 0 ? item : mixColours2(item, toward, amount));
|
|
3853
3924
|
}
|
|
3854
3925
|
return value;
|
|
3855
3926
|
}
|
|
@@ -3939,30 +4010,14 @@ function beginTileflowStyleCrossfade(input, duration) {
|
|
|
3939
4010
|
snapshot.setAttribute("aria-hidden", "true");
|
|
3940
4011
|
snapshot.dataset.tileflowThemeCrossfade = "";
|
|
3941
4012
|
canvas.after(snapshot);
|
|
3942
|
-
const corners = [
|
|
3943
|
-
[width * 0.1, height * 0.45],
|
|
3944
|
-
[width * 0.9, height * 0.45],
|
|
3945
|
-
[width * 0.9, height * 0.9],
|
|
3946
|
-
[width * 0.1, height * 0.9]
|
|
3947
|
-
];
|
|
3948
|
-
const anchors = corners.map((corner) => map.unproject(corner));
|
|
3949
|
-
const follow = () => {
|
|
3950
|
-
const to = anchors.map((anchor) => map.project(anchor));
|
|
3951
|
-
if (to.some((point) => !Number.isFinite(point.x) || !Number.isFinite(point.y))) return;
|
|
3952
|
-
const matrix = homography(
|
|
3953
|
-
corners,
|
|
3954
|
-
to.map((point) => [point.x, point.y])
|
|
3955
|
-
);
|
|
3956
|
-
if (matrix) snapshot.style.transform = matrix3d(matrix);
|
|
3957
|
-
};
|
|
3958
|
-
map.on("move", follow);
|
|
3959
4013
|
let removed = false;
|
|
3960
4014
|
const remove = () => {
|
|
3961
4015
|
if (removed) return;
|
|
3962
4016
|
removed = true;
|
|
3963
|
-
map.off("move",
|
|
4017
|
+
map.off("move", remove);
|
|
3964
4018
|
snapshot.remove();
|
|
3965
4019
|
};
|
|
4020
|
+
map.on("move", remove);
|
|
3966
4021
|
const frame = (callback) => {
|
|
3967
4022
|
if (typeof view.requestAnimationFrame === "function") view.requestAnimationFrame(callback);
|
|
3968
4023
|
else view.setTimeout(callback, 16);
|
|
@@ -4225,7 +4280,7 @@ function relayoutPositions(plan) {
|
|
|
4225
4280
|
return positions;
|
|
4226
4281
|
}
|
|
4227
4282
|
function isCrossfadeMap(map) {
|
|
4228
|
-
return typeof map.getCanvas === "function" && typeof map.redraw === "function" && typeof map.
|
|
4283
|
+
return typeof map.getCanvas === "function" && typeof map.redraw === "function" && typeof map.isStyleLoaded === "function" && typeof map.areTilesLoaded === "function";
|
|
4229
4284
|
}
|
|
4230
4285
|
function viewOf(map) {
|
|
4231
4286
|
if (typeof map.getCanvas !== "function") return void 0;
|
|
@@ -4245,124 +4300,114 @@ function prefersReducedMotion(view) {
|
|
|
4245
4300
|
function tileflowThemeMotionView(map) {
|
|
4246
4301
|
return viewOf(map);
|
|
4247
4302
|
}
|
|
4248
|
-
function homography(from, to) {
|
|
4249
|
-
const rows = [];
|
|
4250
|
-
for (let index = 0; index < 4; index += 1) {
|
|
4251
|
-
const [x3, y2] = from[index];
|
|
4252
|
-
const [u, v2] = to[index];
|
|
4253
|
-
rows.push([x3, y2, 1, 0, 0, 0, -u * x3, -u * y2, u]);
|
|
4254
|
-
rows.push([0, 0, 0, x3, y2, 1, -v2 * x3, -v2 * y2, v2]);
|
|
4255
|
-
}
|
|
4256
|
-
for (let column = 0; column < 8; column += 1) {
|
|
4257
|
-
let pivot = column;
|
|
4258
|
-
for (let row = column + 1; row < 8; row += 1)
|
|
4259
|
-
if (Math.abs(rows[row][column]) > Math.abs(rows[pivot][column])) pivot = row;
|
|
4260
|
-
if (Math.abs(rows[pivot][column]) < 1e-12) return void 0;
|
|
4261
|
-
[rows[column], rows[pivot]] = [rows[pivot], rows[column]];
|
|
4262
|
-
for (let row = 0; row < 8; row += 1) {
|
|
4263
|
-
if (row === column) continue;
|
|
4264
|
-
const factor = rows[row][column] / rows[column][column];
|
|
4265
|
-
for (let k = column; k <= 8; k += 1) rows[row][k] -= factor * rows[column][k];
|
|
4266
|
-
}
|
|
4267
|
-
}
|
|
4268
|
-
return [...rows.map((row, index) => row[8] / row[index]), 1];
|
|
4269
|
-
}
|
|
4270
|
-
function matrix3d(matrix) {
|
|
4271
|
-
const [a, b2, c, d2, e, f, g, h2, i2] = matrix.map(
|
|
4272
|
-
(value) => Math.abs(value) < 1e-12 ? 0 : Number(value.toPrecision(10))
|
|
4273
|
-
);
|
|
4274
|
-
return `matrix3d(${a},${d2},0,${g},${b2},${e},0,${h2},0,0,1,0,${c},${f},0,${i2})`;
|
|
4275
|
-
}
|
|
4276
4303
|
|
|
4277
|
-
// src/
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
if (typeof color !== "string" || !hexColour.test(color) || typeof horizonColor !== "string" || !hexColour.test(horizonColor) || typeof glowColor !== "string" || !hexColour.test(glowColor) || !unit(horizonBlend))
|
|
4288
|
-
return void 0;
|
|
4289
|
-
return { color, horizonColor, horizonBlend, glowColor };
|
|
4290
|
-
}
|
|
4291
|
-
function readTileflowSky(value) {
|
|
4292
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
4293
|
-
const record2 = value;
|
|
4294
|
-
const keys = Object.keys(record2);
|
|
4295
|
-
if (record2.version !== 1 || keys.length !== (record2.timesOfDay === void 0 ? 3 : 4))
|
|
4296
|
-
return void 0;
|
|
4297
|
-
const { starIntensity, glowColor, timesOfDay } = record2;
|
|
4298
|
-
if (!unit(starIntensity) || typeof glowColor !== "string" || !hexColour.test(glowColor))
|
|
4299
|
-
return void 0;
|
|
4300
|
-
if (timesOfDay === void 0) return { version: 1, starIntensity, glowColor };
|
|
4301
|
-
if (!timesOfDay || typeof timesOfDay !== "object" || Array.isArray(timesOfDay)) return void 0;
|
|
4302
|
-
const times = timesOfDay;
|
|
4303
|
-
if (Object.keys(times).length !== 4) return void 0;
|
|
4304
|
-
const day = readColours(times.day);
|
|
4305
|
-
const dawn = readColours(times.dawn);
|
|
4306
|
-
const dusk = readColours(times.dusk);
|
|
4307
|
-
const night = readColours(times.night);
|
|
4308
|
-
if (!day || !dawn || !dusk || !night) return void 0;
|
|
4309
|
-
return { version: 1, starIntensity, glowColor, timesOfDay: { day, dawn, dusk, night } };
|
|
4310
|
-
}
|
|
4311
|
-
function tileflowSkyStarVisibility(channels) {
|
|
4312
|
-
const linear = channels.map(
|
|
4313
|
-
(channel) => channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4
|
|
4314
|
-
);
|
|
4315
|
-
const luminance2 = 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];
|
|
4316
|
-
const progress = Math.min(1, Math.max(0, (0.06 - luminance2) / (0.06 - 0.015)));
|
|
4317
|
-
return progress * progress * (3 - 2 * progress);
|
|
4318
|
-
}
|
|
4319
|
-
var smooth = (from, to, value) => {
|
|
4320
|
-
const t = Math.min(1, Math.max(0, (value - from) / (to - from)));
|
|
4321
|
-
return t * t * (3 - 2 * t);
|
|
4304
|
+
// src/theme-preparation-browser.ts
|
|
4305
|
+
var opacities = {
|
|
4306
|
+
background: ["background-opacity"],
|
|
4307
|
+
circle: ["circle-opacity", "circle-stroke-opacity"],
|
|
4308
|
+
fill: ["fill-opacity"],
|
|
4309
|
+
"fill-extrusion": ["fill-extrusion-opacity"],
|
|
4310
|
+
heatmap: ["heatmap-opacity"],
|
|
4311
|
+
line: ["line-opacity"],
|
|
4312
|
+
raster: ["raster-opacity"],
|
|
4313
|
+
symbol: ["text-opacity", "icon-opacity"]
|
|
4322
4314
|
};
|
|
4323
|
-
function
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4315
|
+
function prepareTileflowThemeGeometry(from, to) {
|
|
4316
|
+
const existing = new Set(from.layers.map((layer) => layer.id));
|
|
4317
|
+
const added = to.layers.filter((layer) => !existing.has(layer.id));
|
|
4318
|
+
if (!added.length || added.some((layer) => !opacities[String(layer.type)])) return void 0;
|
|
4319
|
+
const style = {
|
|
4320
|
+
...from,
|
|
4321
|
+
layers: [
|
|
4322
|
+
...from.layers,
|
|
4323
|
+
...added.map((layer) => ({
|
|
4324
|
+
...layer,
|
|
4325
|
+
paint: {
|
|
4326
|
+
...layer.paint,
|
|
4327
|
+
...Object.fromEntries(
|
|
4328
|
+
opacities[String(layer.type)].flatMap((property) => [
|
|
4329
|
+
[property, 0],
|
|
4330
|
+
[`${property}-transition`, { duration: 0, delay: 0 }]
|
|
4331
|
+
])
|
|
4332
|
+
)
|
|
4333
|
+
}
|
|
4334
|
+
}))
|
|
4335
|
+
]
|
|
4336
|
+
};
|
|
4329
4337
|
return {
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4338
|
+
style,
|
|
4339
|
+
reveal(map) {
|
|
4340
|
+
const set = map.setPaintProperty;
|
|
4341
|
+
for (const layer of added)
|
|
4342
|
+
for (const property of opacities[String(layer.type)])
|
|
4343
|
+
set.call(
|
|
4344
|
+
map,
|
|
4345
|
+
String(layer.id),
|
|
4346
|
+
property,
|
|
4347
|
+
layer.paint?.[property] ?? 1
|
|
4348
|
+
);
|
|
4349
|
+
}
|
|
4334
4350
|
};
|
|
4335
4351
|
}
|
|
4336
|
-
function
|
|
4337
|
-
const
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4352
|
+
function waitForTileflowThemeGeometry(map, timeoutMs, stop) {
|
|
4353
|
+
const view = tileflowThemeMotionView(map);
|
|
4354
|
+
if (!view || typeof map.isStyleLoaded !== "function" || typeof map.areTilesLoaded !== "function")
|
|
4355
|
+
return Promise.resolve(!stop());
|
|
4356
|
+
const loaded = map.isStyleLoaded;
|
|
4357
|
+
const tiles = map.areTilesLoaded;
|
|
4358
|
+
return new Promise((resolve, reject) => {
|
|
4359
|
+
const now = () => view.performance?.now?.() ?? Date.now();
|
|
4360
|
+
const started = now();
|
|
4361
|
+
let readyFrames = 0;
|
|
4362
|
+
const step = () => {
|
|
4363
|
+
if (stop()) return resolve(false);
|
|
4364
|
+
readyFrames = loaded.call(map) && tiles.call(map) ? readyFrames + 1 : 0;
|
|
4365
|
+
if (readyFrames >= 2) return resolve(true);
|
|
4366
|
+
if (now() - started >= timeoutMs)
|
|
4367
|
+
return reject(new Error("Tileflow theme geometry did not finish loading."));
|
|
4368
|
+
if (view.requestAnimationFrame) view.requestAnimationFrame(step);
|
|
4369
|
+
else view.setTimeout(step, 16);
|
|
4370
|
+
};
|
|
4371
|
+
if (view.requestAnimationFrame) view.requestAnimationFrame(step);
|
|
4372
|
+
else view.setTimeout(step, 16);
|
|
4373
|
+
});
|
|
4342
4374
|
}
|
|
4343
|
-
var tileflowSkySunKey = /* @__PURE__ */ Symbol.for("tileflow.skySun");
|
|
4344
4375
|
|
|
4345
4376
|
// src/atmosphere.ts
|
|
4346
4377
|
var tileflowAtmosphereMetadataKey = "tileflow:atmosphere";
|
|
4378
|
+
var tileflowAtmosphereMetadataVersion = 2;
|
|
4379
|
+
var defaultAtmosphereStars = {
|
|
4380
|
+
starColor: "#e0ebff",
|
|
4381
|
+
starCount: 1100,
|
|
4382
|
+
starSize: 1
|
|
4383
|
+
};
|
|
4347
4384
|
function readTileflowAtmosphere(value) {
|
|
4348
4385
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
4349
|
-
const
|
|
4350
|
-
|
|
4386
|
+
const record3 = value;
|
|
4387
|
+
const legacy = record3.version === 1;
|
|
4388
|
+
if (!legacy && record3.version !== tileflowAtmosphereMetadataVersion || Object.keys(record3).length !== (legacy ? 7 : 10))
|
|
4389
|
+
return void 0;
|
|
4351
4390
|
for (const key of ["skyColor", "horizonColor", "fogColor", "spaceColor"]) {
|
|
4352
|
-
if (typeof
|
|
4391
|
+
if (typeof record3[key] !== "string" || !/^#[0-9a-f]{6}$/i.test(record3[key])) return void 0;
|
|
4353
4392
|
}
|
|
4354
4393
|
for (const key of ["starIntensity", "starParallax"]) {
|
|
4355
|
-
const number =
|
|
4394
|
+
const number = record3[key];
|
|
4356
4395
|
if (typeof number !== "number" || !Number.isFinite(number) || number < 0 || number > 1)
|
|
4357
4396
|
return void 0;
|
|
4358
4397
|
}
|
|
4398
|
+
const stars = legacy ? defaultAtmosphereStars : record3;
|
|
4399
|
+
if (typeof stars.starColor !== "string" || !/^#[0-9a-f]{6}$/i.test(stars.starColor) || typeof stars.starCount !== "number" || !Number.isInteger(stars.starCount) || stars.starCount < 0 || stars.starCount > 4096 || typeof stars.starSize !== "number" || !Number.isFinite(stars.starSize) || stars.starSize < 0 || stars.starSize > 4)
|
|
4400
|
+
return void 0;
|
|
4359
4401
|
return {
|
|
4360
|
-
skyColor:
|
|
4361
|
-
horizonColor:
|
|
4362
|
-
fogColor:
|
|
4363
|
-
spaceColor:
|
|
4364
|
-
|
|
4365
|
-
|
|
4402
|
+
skyColor: record3.skyColor,
|
|
4403
|
+
horizonColor: record3.horizonColor,
|
|
4404
|
+
fogColor: record3.fogColor,
|
|
4405
|
+
spaceColor: record3.spaceColor,
|
|
4406
|
+
starColor: stars.starColor,
|
|
4407
|
+
starCount: stars.starCount,
|
|
4408
|
+
starSize: stars.starSize,
|
|
4409
|
+
starIntensity: record3.starIntensity,
|
|
4410
|
+
starParallax: record3.starParallax
|
|
4366
4411
|
};
|
|
4367
4412
|
}
|
|
4368
4413
|
function atmosphereSpaceOpacity(zoom) {
|
|
@@ -4389,6 +4434,162 @@ function createAtmosphereStars(count = 650) {
|
|
|
4389
4434
|
}));
|
|
4390
4435
|
}
|
|
4391
4436
|
|
|
4437
|
+
// src/atmosphere-rim-browser.ts
|
|
4438
|
+
var tileflowAtmosphereRimLayerId = "tileflow-atmosphere-rim";
|
|
4439
|
+
function atmosphereRimEllipse(matrix, width, height) {
|
|
4440
|
+
const x3 = [0, 4, 8, 12].map((i2) => (matrix[i2] + matrix[i2 + 3]) * width / 2);
|
|
4441
|
+
const y2 = [1, 5, 9, 13].map((i2) => (matrix[i2 + 2] - matrix[i2]) * height / 2);
|
|
4442
|
+
const w2 = [3, 7, 11, 15].map((i2) => matrix[i2]);
|
|
4443
|
+
const dot3 = (a2, b3) => a2[0] * b3[0] + a2[1] * b3[1] + a2[2] * b3[2] - a2[3] * b3[3];
|
|
4444
|
+
const xx = dot3(x3, x3), xy = dot3(x3, y2), xw = dot3(x3, w2);
|
|
4445
|
+
const yy = dot3(y2, y2), yw = dot3(y2, w2), ww = dot3(w2, w2);
|
|
4446
|
+
const a = yy * ww - yw * yw, b2 = xw * yw - xy * ww, c = xx * ww - xw * xw;
|
|
4447
|
+
const d2 = xy * yw - xw * yy, e = xy * xw - xx * yw, f = xx * yy - xy * xy;
|
|
4448
|
+
const determinant = a * c - b2 * b2;
|
|
4449
|
+
if (!Number.isFinite(determinant) || determinant <= 0) return void 0;
|
|
4450
|
+
const centerX = (b2 * e - c * d2) / determinant;
|
|
4451
|
+
const centerY = (b2 * d2 - a * e) / determinant;
|
|
4452
|
+
const level = -(f + d2 * centerX + e * centerY);
|
|
4453
|
+
const middle = (a + c) / 2;
|
|
4454
|
+
const spread = Math.hypot((a - c) / 2, b2);
|
|
4455
|
+
const radiusX = Math.sqrt(level / (middle + spread));
|
|
4456
|
+
const radiusY = Math.sqrt(level / (middle - spread));
|
|
4457
|
+
if (![centerX, centerY, radiusX, radiusY].every(Number.isFinite) || Math.min(radiusX, radiusY) <= 0)
|
|
4458
|
+
return void 0;
|
|
4459
|
+
return { centerX, centerY, radiusX, radiusY, rotation: Math.atan2(2 * b2, a - c) / 2 };
|
|
4460
|
+
}
|
|
4461
|
+
function attachTileflowAtmosphereRim(map) {
|
|
4462
|
+
const container = map.getContainer();
|
|
4463
|
+
const document2 = container.ownerDocument;
|
|
4464
|
+
const browser = document2.defaultView;
|
|
4465
|
+
if (!browser) return () => {
|
|
4466
|
+
};
|
|
4467
|
+
let disposed = false;
|
|
4468
|
+
let canvas;
|
|
4469
|
+
let context = null;
|
|
4470
|
+
let lastDraw = "";
|
|
4471
|
+
let atmosphere;
|
|
4472
|
+
function removeCanvas() {
|
|
4473
|
+
canvas?.remove();
|
|
4474
|
+
canvas = void 0;
|
|
4475
|
+
context = null;
|
|
4476
|
+
lastDraw = "";
|
|
4477
|
+
}
|
|
4478
|
+
const layer = {
|
|
4479
|
+
id: tileflowAtmosphereRimLayerId,
|
|
4480
|
+
type: "custom",
|
|
4481
|
+
// Keep projection reads out of terrain's offscreen ground textures.
|
|
4482
|
+
renderingMode: "3d",
|
|
4483
|
+
render(_gl, input) {
|
|
4484
|
+
if (!atmosphere || !canvas || !context) return;
|
|
4485
|
+
const { mainMatrix, projectionTransition } = input.defaultProjectionData;
|
|
4486
|
+
const width = container.clientWidth, height = container.clientHeight;
|
|
4487
|
+
if (!width || !height) return;
|
|
4488
|
+
const pixelRatio2 = Math.min(browser.devicePixelRatio || 1, 2);
|
|
4489
|
+
const transition = Math.max(0, Math.min(1, (projectionTransition - 0.98) / 0.02));
|
|
4490
|
+
const opacity = atmosphereSpaceOpacity(map.getZoom()) * transition * transition * (3 - 2 * transition);
|
|
4491
|
+
const key = JSON.stringify([
|
|
4492
|
+
Array.from(mainMatrix),
|
|
4493
|
+
width,
|
|
4494
|
+
height,
|
|
4495
|
+
pixelRatio2,
|
|
4496
|
+
opacity,
|
|
4497
|
+
atmosphere.horizonColor
|
|
4498
|
+
]);
|
|
4499
|
+
if (key === lastDraw) return;
|
|
4500
|
+
lastDraw = key;
|
|
4501
|
+
canvas.style.opacity = String(opacity);
|
|
4502
|
+
if (!opacity) return;
|
|
4503
|
+
const ellipse = atmosphereRimEllipse(mainMatrix, width, height);
|
|
4504
|
+
if (!ellipse) return;
|
|
4505
|
+
const physicalWidth = Math.round(width * pixelRatio2), physicalHeight = Math.round(height * pixelRatio2);
|
|
4506
|
+
if (canvas.width !== physicalWidth || canvas.height !== physicalHeight) {
|
|
4507
|
+
canvas.width = physicalWidth;
|
|
4508
|
+
canvas.height = physicalHeight;
|
|
4509
|
+
}
|
|
4510
|
+
context.setTransform(pixelRatio2, 0, 0, pixelRatio2, 0, 0);
|
|
4511
|
+
context.clearRect(0, 0, width, height);
|
|
4512
|
+
context.save();
|
|
4513
|
+
context.translate(ellipse.centerX, ellipse.centerY);
|
|
4514
|
+
context.rotate(ellipse.rotation);
|
|
4515
|
+
context.scale(ellipse.radiusX, ellipse.radiusY);
|
|
4516
|
+
const radius = Math.min(ellipse.radiusX, ellipse.radiusY);
|
|
4517
|
+
const extent5 = 1 + 120 / radius;
|
|
4518
|
+
const gradient = context.createRadialGradient(0, 0, 0, 0, 0, extent5);
|
|
4519
|
+
gradient.addColorStop(0, "transparent");
|
|
4520
|
+
gradient.addColorStop(Math.max(0, 1 - 0.5 / radius) / extent5, "transparent");
|
|
4521
|
+
const colour = Number.parseInt(atmosphere.horizonColor.slice(1), 16);
|
|
4522
|
+
const outer = [(colour >> 16) * 0.35, (colour >> 8 & 255) * 0.6, colour & 255];
|
|
4523
|
+
const white = [245, 250, 255];
|
|
4524
|
+
for (const distance of [0, 1, 2, 3, 5, 8, 12, 18, 26, 36, 50, 70, 96, 120]) {
|
|
4525
|
+
const tint = Math.exp(-distance / 7);
|
|
4526
|
+
const channels = outer.map(
|
|
4527
|
+
(channel, index) => Math.round(channel + (white[index] - channel) * tint)
|
|
4528
|
+
);
|
|
4529
|
+
const alpha = distance === 120 ? 0 : Math.min(1, 0.85 * Math.exp(-distance / 3) + 0.55 * Math.exp(-distance / 24));
|
|
4530
|
+
gradient.addColorStop(
|
|
4531
|
+
(1 + distance / radius) / extent5,
|
|
4532
|
+
`rgba(${channels.join(", ")}, ${alpha})`
|
|
4533
|
+
);
|
|
4534
|
+
}
|
|
4535
|
+
context.fillStyle = gradient;
|
|
4536
|
+
context.fillRect(-extent5, -extent5, extent5 * 2, extent5 * 2);
|
|
4537
|
+
context.restore();
|
|
4538
|
+
}
|
|
4539
|
+
};
|
|
4540
|
+
function sync(styleLoaded2 = false) {
|
|
4541
|
+
if (disposed) return;
|
|
4542
|
+
const style = map.getStyle();
|
|
4543
|
+
if (!style) return;
|
|
4544
|
+
atmosphere = style.projection?.type === "globe" ? readTileflowAtmosphere(
|
|
4545
|
+
style.metadata?.[tileflowAtmosphereMetadataKey]
|
|
4546
|
+
) : void 0;
|
|
4547
|
+
try {
|
|
4548
|
+
const present = Boolean(map.getLayer(layer.id));
|
|
4549
|
+
if (!atmosphere) {
|
|
4550
|
+
if (present) map.removeLayer(layer.id);
|
|
4551
|
+
removeCanvas();
|
|
4552
|
+
return;
|
|
4553
|
+
}
|
|
4554
|
+
if (!canvas) {
|
|
4555
|
+
canvas = document2.createElement("canvas");
|
|
4556
|
+
canvas.setAttribute("aria-hidden", "true");
|
|
4557
|
+
canvas.setAttribute("data-tileflow-atmosphere-rim", "");
|
|
4558
|
+
Object.assign(canvas.style, {
|
|
4559
|
+
position: "absolute",
|
|
4560
|
+
inset: "0",
|
|
4561
|
+
width: "100%",
|
|
4562
|
+
height: "100%",
|
|
4563
|
+
pointerEvents: "none"
|
|
4564
|
+
});
|
|
4565
|
+
context = canvas.getContext("2d");
|
|
4566
|
+
container.insertBefore(canvas, container.firstChild);
|
|
4567
|
+
}
|
|
4568
|
+
if (present || !styleLoaded2 && !map.isStyleLoaded()) return;
|
|
4569
|
+
map.addLayer(layer);
|
|
4570
|
+
} catch {
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
const styleLoaded = () => sync(true);
|
|
4574
|
+
const styleData = () => sync();
|
|
4575
|
+
map.on("style.load", styleLoaded);
|
|
4576
|
+
map.on("styledata", styleData);
|
|
4577
|
+
map.on("idle", styleData);
|
|
4578
|
+
sync();
|
|
4579
|
+
return () => {
|
|
4580
|
+
if (disposed) return;
|
|
4581
|
+
disposed = true;
|
|
4582
|
+
map.off("style.load", styleLoaded);
|
|
4583
|
+
map.off("styledata", styleData);
|
|
4584
|
+
map.off("idle", styleData);
|
|
4585
|
+
removeCanvas();
|
|
4586
|
+
try {
|
|
4587
|
+
if (map.getLayer(layer.id)) map.removeLayer(layer.id);
|
|
4588
|
+
} catch {
|
|
4589
|
+
}
|
|
4590
|
+
};
|
|
4591
|
+
}
|
|
4592
|
+
|
|
4392
4593
|
// src/sky-browser.ts
|
|
4393
4594
|
init_sun();
|
|
4394
4595
|
init_theme_blend();
|
|
@@ -5289,10 +5490,10 @@ function attachTileflowSkyHaze(map) {
|
|
|
5289
5490
|
}
|
|
5290
5491
|
function sync() {
|
|
5291
5492
|
if (disposed) return;
|
|
5292
|
-
const sky = map.getSky?.();
|
|
5293
|
-
const wanted = typeof sky?.["horizon-color"] === "string";
|
|
5294
|
-
const present = Boolean(map.getLayer(tileflowSkyHazeLayerId));
|
|
5295
5493
|
try {
|
|
5494
|
+
const sky = map.getSky?.();
|
|
5495
|
+
const wanted = typeof sky?.["horizon-color"] === "string";
|
|
5496
|
+
const present = Boolean(map.getLayer(tileflowSkyHazeLayerId));
|
|
5296
5497
|
if (!wanted) {
|
|
5297
5498
|
if (present) map.removeLayer(tileflowSkyHazeLayerId);
|
|
5298
5499
|
return;
|
|
@@ -5377,7 +5578,10 @@ function createProgram(gl) {
|
|
|
5377
5578
|
}
|
|
5378
5579
|
|
|
5379
5580
|
// src/atmosphere-browser.ts
|
|
5380
|
-
function attachTileflowAtmosphere(map) {
|
|
5581
|
+
function attachTileflowAtmosphere(map, runtimeOptions = {}) {
|
|
5582
|
+
const starParallaxScale = runtimeOptions.starParallaxScale ?? 1;
|
|
5583
|
+
if (!Number.isFinite(starParallaxScale))
|
|
5584
|
+
throw new RangeError("starParallaxScale must be a finite number.");
|
|
5381
5585
|
const container = map.getContainer();
|
|
5382
5586
|
const document2 = container.ownerDocument;
|
|
5383
5587
|
const browser = document2.defaultView;
|
|
@@ -5388,16 +5592,15 @@ function attachTileflowAtmosphere(map) {
|
|
|
5388
5592
|
};
|
|
5389
5593
|
const detachHaze = layered ? attachTileflowSkyHaze(map) : () => {
|
|
5390
5594
|
};
|
|
5391
|
-
const
|
|
5392
|
-
|
|
5595
|
+
const detachRim = layered ? attachTileflowAtmosphereRim(map) : () => {
|
|
5596
|
+
};
|
|
5393
5597
|
const reducedMotion = browser.matchMedia("(prefers-reduced-motion: reduce)");
|
|
5394
|
-
|
|
5598
|
+
let stars = [];
|
|
5395
5599
|
let options;
|
|
5396
5600
|
let canvas;
|
|
5397
5601
|
let context = null;
|
|
5398
5602
|
let frame;
|
|
5399
5603
|
let disposed = false;
|
|
5400
|
-
let appliedFilter;
|
|
5401
5604
|
let width = 0;
|
|
5402
5605
|
let height = 0;
|
|
5403
5606
|
let pixelRatio2 = 0;
|
|
@@ -5405,17 +5608,11 @@ function attachTileflowAtmosphere(map) {
|
|
|
5405
5608
|
let previousBearing = map.getBearing();
|
|
5406
5609
|
let longitude = previousLongitude;
|
|
5407
5610
|
let bearing = previousBearing;
|
|
5408
|
-
function restoreFilter() {
|
|
5409
|
-
if (appliedFilter !== void 0 && mapCanvas.style.filter === appliedFilter)
|
|
5410
|
-
mapCanvas.style.filter = previousFilter;
|
|
5411
|
-
appliedFilter = void 0;
|
|
5412
|
-
}
|
|
5413
5611
|
function removeCanvas() {
|
|
5414
5612
|
canvas?.remove();
|
|
5415
5613
|
canvas = void 0;
|
|
5416
5614
|
context = null;
|
|
5417
5615
|
width = height = pixelRatio2 = 0;
|
|
5418
|
-
restoreFilter();
|
|
5419
5616
|
}
|
|
5420
5617
|
function syncStyle() {
|
|
5421
5618
|
if (disposed) return;
|
|
@@ -5430,6 +5627,7 @@ function attachTileflowAtmosphere(map) {
|
|
|
5430
5627
|
removeCanvas();
|
|
5431
5628
|
return;
|
|
5432
5629
|
}
|
|
5630
|
+
if (stars.length !== options.starCount) stars = createAtmosphereStars(options.starCount);
|
|
5433
5631
|
if (!canvas) {
|
|
5434
5632
|
canvas = document2.createElement("canvas");
|
|
5435
5633
|
canvas.setAttribute("aria-hidden", "true");
|
|
@@ -5458,13 +5656,7 @@ function attachTileflowAtmosphere(map) {
|
|
|
5458
5656
|
previousBearing = map.getBearing();
|
|
5459
5657
|
const opacity = atmosphereSpaceOpacity(map.getZoom());
|
|
5460
5658
|
canvas.style.opacity = String(opacity);
|
|
5461
|
-
if (opacity === 0)
|
|
5462
|
-
restoreFilter();
|
|
5463
|
-
return;
|
|
5464
|
-
}
|
|
5465
|
-
const baseFilter = previousFilter && previousFilter !== "none" ? `${previousFilter} ` : "";
|
|
5466
|
-
mapCanvas.style.filter = `${baseFilter}drop-shadow(0 0 2px ${withAlpha(options.horizonColor, opacity * 0.65)}) drop-shadow(0 0 12px ${withAlpha(options.horizonColor, opacity * 0.4)})`;
|
|
5467
|
-
appliedFilter = mapCanvas.style.filter;
|
|
5659
|
+
if (opacity === 0) return;
|
|
5468
5660
|
if (!context) return;
|
|
5469
5661
|
const nextWidth = container.clientWidth;
|
|
5470
5662
|
const nextHeight = container.clientHeight;
|
|
@@ -5479,30 +5671,34 @@ function attachTileflowAtmosphere(map) {
|
|
|
5479
5671
|
context.setTransform(pixelRatio2, 0, 0, pixelRatio2, 0, 0);
|
|
5480
5672
|
}
|
|
5481
5673
|
context.clearRect(0, 0, width, height);
|
|
5482
|
-
if (options.starIntensity === 0) return;
|
|
5483
|
-
const motion = reducedMotion.matches ? 0 : options.starParallax / 0.4;
|
|
5674
|
+
if (options.starIntensity === 0 || options.starSize === 0) return;
|
|
5675
|
+
const motion = reducedMotion.matches ? 0 : options.starParallax / 0.4 * starParallaxScale;
|
|
5484
5676
|
const xOffset = motion * (-longitude * 0.8 - bearing * 0.35);
|
|
5485
5677
|
const yOffset = motion * (center.lat * 0.6 + map.getPitch() * 0.4);
|
|
5486
5678
|
const intensity = options.starIntensity / 0.6;
|
|
5487
5679
|
const fieldWidth = 1600;
|
|
5488
5680
|
const fieldHeight = 1e3;
|
|
5489
5681
|
for (const star of stars) {
|
|
5682
|
+
const radius = (star.radius + 0.25) * options.starSize;
|
|
5683
|
+
const margin = star.radius > 0.95 ? radius * 2.5 : radius;
|
|
5684
|
+
const alpha = Math.min(1, star.alpha * 1.35 * intensity);
|
|
5490
5685
|
const x3 = wrapAtmosphereStar(star.x * fieldWidth + xOffset, fieldWidth);
|
|
5491
5686
|
const y2 = wrapAtmosphereStar(star.y * fieldHeight + yOffset, fieldHeight);
|
|
5492
5687
|
for (let tileX = -1; tileX * fieldWidth < width; tileX++) {
|
|
5493
5688
|
for (let tileY = -1; tileY * fieldHeight < height; tileY++) {
|
|
5494
5689
|
const screenX = x3 + tileX * fieldWidth;
|
|
5495
5690
|
const screenY = y2 + tileY * fieldHeight;
|
|
5496
|
-
if (screenX < -
|
|
5691
|
+
if (screenX < -margin || screenX > width + margin || screenY < -margin || screenY > height + margin)
|
|
5692
|
+
continue;
|
|
5497
5693
|
if (star.radius > 0.95) {
|
|
5498
|
-
context.fillStyle = withAlpha(options.horizonColor,
|
|
5694
|
+
context.fillStyle = withAlpha(options.horizonColor, alpha * 0.1);
|
|
5499
5695
|
context.beginPath();
|
|
5500
|
-
context.arc(screenX, screenY,
|
|
5696
|
+
context.arc(screenX, screenY, radius * 2.5, 0, Math.PI * 2);
|
|
5501
5697
|
context.fill();
|
|
5502
5698
|
}
|
|
5503
|
-
context.fillStyle =
|
|
5699
|
+
context.fillStyle = withAlpha(options.starColor, alpha);
|
|
5504
5700
|
context.beginPath();
|
|
5505
|
-
context.arc(screenX, screenY,
|
|
5701
|
+
context.arc(screenX, screenY, radius, 0, Math.PI * 2);
|
|
5506
5702
|
context.fill();
|
|
5507
5703
|
}
|
|
5508
5704
|
}
|
|
@@ -5516,6 +5712,7 @@ function attachTileflowAtmosphere(map) {
|
|
|
5516
5712
|
disposed = true;
|
|
5517
5713
|
detachSky();
|
|
5518
5714
|
detachHaze();
|
|
5715
|
+
detachRim();
|
|
5519
5716
|
if (frame !== void 0) browser.cancelAnimationFrame(frame);
|
|
5520
5717
|
map.off("move", schedule);
|
|
5521
5718
|
map.off("resize", schedule);
|
|
@@ -5698,6 +5895,95 @@ function promotedKey(map, source) {
|
|
|
5698
5895
|
return value === "ref" ? "ref" : void 0;
|
|
5699
5896
|
}
|
|
5700
5897
|
|
|
5898
|
+
// src/cartography/label-placement.ts
|
|
5899
|
+
var roadLabelPlacementKey = "tileflow:road-label-placement";
|
|
5900
|
+
var groundRoadLabelMetadata = { [roadLabelPlacementKey]: { version: 1, mode: "ground" } };
|
|
5901
|
+
function isGroundRoadLabel(layer) {
|
|
5902
|
+
const policy = layer.metadata?.[roadLabelPlacementKey];
|
|
5903
|
+
return policy?.version === 1 && policy.mode === "ground";
|
|
5904
|
+
}
|
|
5905
|
+
|
|
5906
|
+
// src/label-placement-browser.ts
|
|
5907
|
+
function attachTileflowLabelPlacement(map) {
|
|
5908
|
+
let disposed = false;
|
|
5909
|
+
let targets = [];
|
|
5910
|
+
let ordering = false;
|
|
5911
|
+
let flatOrder = map.getPitch() < 30;
|
|
5912
|
+
function orderRoads(restore = false) {
|
|
5913
|
+
if (ordering || !map.moveLayer || !targets.length) return;
|
|
5914
|
+
const style = map.getStyle();
|
|
5915
|
+
const layers = (map.getLayersOrder?.() ?? style?.layers?.map((layer) => layer.id) ?? []).map(
|
|
5916
|
+
(id) => {
|
|
5917
|
+
const layer = map.getLayer(id);
|
|
5918
|
+
return {
|
|
5919
|
+
id,
|
|
5920
|
+
type: layer?.type,
|
|
5921
|
+
renderingMode: layer?.implementation?.renderingMode ?? layer?.renderingMode,
|
|
5922
|
+
vegetation: (layer?.implementation?.metadata ?? layer?.metadata)?.["tileflow:scene-kind"] === "vegetation"
|
|
5923
|
+
};
|
|
5924
|
+
}
|
|
5925
|
+
);
|
|
5926
|
+
const roads = new Set(targets);
|
|
5927
|
+
const anchors = style?.metadata?.["tileflow:overlay-placement-manifest"];
|
|
5928
|
+
const ceiling = layers.findIndex((layer) => layer.id === anchors?.anchors?.["above-buildings"]);
|
|
5929
|
+
const scene = layers.filter(
|
|
5930
|
+
(layer, index) => (ceiling < 0 || index < ceiling) && (layer.type === "fill-extrusion" || layer.type === "custom" && layer.renderingMode === "3d")
|
|
5931
|
+
);
|
|
5932
|
+
if (!scene.length) return;
|
|
5933
|
+
const solidScene = scene.filter((layer) => !layer.vegetation);
|
|
5934
|
+
const flat = !restore && map.getPitch() < 30;
|
|
5935
|
+
const boundary = flat || !restore && !solidScene.length ? layers.slice(layers.indexOf(scene.at(-1)) + 1).find((layer) => !roads.has(layer.id))?.id : (restore ? scene[0] : solidScene[0]).id;
|
|
5936
|
+
const order = layers.map((layer) => layer.id);
|
|
5937
|
+
const names = order.filter((id) => roads.has(id));
|
|
5938
|
+
const above = flat || !restore && !solidScene.length ? scene.at(-1) : !restore ? scene.filter(
|
|
5939
|
+
(layer) => layer.vegetation && layers.indexOf(layer) < layers.indexOf(solidScene[0])
|
|
5940
|
+
).at(-1) : void 0;
|
|
5941
|
+
const below = flat || !restore && !solidScene.length ? void 0 : boundary;
|
|
5942
|
+
if (names.every(
|
|
5943
|
+
(id) => (!above || order.indexOf(id) > order.indexOf(above.id)) && (!below || order.indexOf(id) < order.indexOf(below))
|
|
5944
|
+
))
|
|
5945
|
+
return;
|
|
5946
|
+
ordering = true;
|
|
5947
|
+
try {
|
|
5948
|
+
for (const id of names) map.moveLayer(id, boundary);
|
|
5949
|
+
} finally {
|
|
5950
|
+
ordering = false;
|
|
5951
|
+
}
|
|
5952
|
+
}
|
|
5953
|
+
function syncStyle() {
|
|
5954
|
+
if (disposed || ordering) return;
|
|
5955
|
+
targets = (map.getStyle()?.layers ?? []).filter(isGroundRoadLabel).map(({ id }) => id);
|
|
5956
|
+
flatOrder = map.getPitch() < 30;
|
|
5957
|
+
orderRoads();
|
|
5958
|
+
}
|
|
5959
|
+
function pitch() {
|
|
5960
|
+
if (disposed) return;
|
|
5961
|
+
const flat = map.getPitch() < 30;
|
|
5962
|
+
if (flat === flatOrder) return;
|
|
5963
|
+
flatOrder = flat;
|
|
5964
|
+
orderRoads();
|
|
5965
|
+
}
|
|
5966
|
+
function release(restore) {
|
|
5967
|
+
if (disposed) return;
|
|
5968
|
+
disposed = true;
|
|
5969
|
+
map.off("pitch", pitch);
|
|
5970
|
+
map.off("moveend", pitch);
|
|
5971
|
+
map.off("style.load", syncStyle);
|
|
5972
|
+
map.off("styledata", syncStyle);
|
|
5973
|
+
map.off("remove", removed);
|
|
5974
|
+
if (restore) orderRoads(true);
|
|
5975
|
+
targets = [];
|
|
5976
|
+
}
|
|
5977
|
+
const removed = () => release(false);
|
|
5978
|
+
map.on("pitch", pitch);
|
|
5979
|
+
map.on("moveend", pitch);
|
|
5980
|
+
map.on("style.load", syncStyle);
|
|
5981
|
+
map.on("styledata", syncStyle);
|
|
5982
|
+
map.on("remove", removed);
|
|
5983
|
+
syncStyle();
|
|
5984
|
+
return () => release(true);
|
|
5985
|
+
}
|
|
5986
|
+
|
|
5701
5987
|
// src/line-progress.ts
|
|
5702
5988
|
var epsilon = 5e-4;
|
|
5703
5989
|
var transparent = "rgba(0, 0, 0, 0)";
|
|
@@ -6120,6 +6406,50 @@ function record(value) {
|
|
|
6120
6406
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6121
6407
|
}
|
|
6122
6408
|
|
|
6409
|
+
// src/buildings-3d-surfaces.ts
|
|
6410
|
+
function readTileflowBuildingSurfaces(value) {
|
|
6411
|
+
if (!record2(value)) return void 0;
|
|
6412
|
+
const number = (value2, min, max2, fallback) => typeof value2 === "number" && Number.isFinite(value2) && value2 >= min && value2 <= max2 ? value2 : fallback;
|
|
6413
|
+
const result = {};
|
|
6414
|
+
if (record2(value.walls) && value.walls.kind === "brick") {
|
|
6415
|
+
const size = Array.isArray(value.walls.size) ? value.walls.size : [];
|
|
6416
|
+
const width = number(size[0], 0.5, 100, 6);
|
|
6417
|
+
const height = number(size[1], 0.5, 100, 3);
|
|
6418
|
+
result.walls = {
|
|
6419
|
+
kind: "brick",
|
|
6420
|
+
size: [width, height],
|
|
6421
|
+
jointWidth: Math.min(
|
|
6422
|
+
number(value.walls.jointWidth, 0.01, 2, 0.12),
|
|
6423
|
+
Math.min(width, height) * 0.25
|
|
6424
|
+
),
|
|
6425
|
+
contrast: number(value.walls.contrast, 0, 1, 0.2)
|
|
6426
|
+
};
|
|
6427
|
+
}
|
|
6428
|
+
if (record2(value.roof) && value.roof.kind === "tiles") {
|
|
6429
|
+
const size = number(value.roof.size, 0.5, 100, 8);
|
|
6430
|
+
result.roof = {
|
|
6431
|
+
kind: "tiles",
|
|
6432
|
+
size,
|
|
6433
|
+
jointWidth: Math.min(number(value.roof.jointWidth, 0.01, 2, 0.12), size * 0.25),
|
|
6434
|
+
contrast: number(value.roof.contrast, 0, 1, 0.1)
|
|
6435
|
+
};
|
|
6436
|
+
}
|
|
6437
|
+
if (record2(value.cornice))
|
|
6438
|
+
result.cornice = {
|
|
6439
|
+
height: number(value.cornice.height, 0.05, 5, 0.6),
|
|
6440
|
+
contrast: number(value.cornice.contrast, 0, 1, 0.2)
|
|
6441
|
+
};
|
|
6442
|
+
return Object.keys(result).length ? result : void 0;
|
|
6443
|
+
}
|
|
6444
|
+
function tileflowBuildingSurfaceTile(x3, y2, zoom, size) {
|
|
6445
|
+
const span = 4007501668557849e-8 / 2 ** zoom;
|
|
6446
|
+
const phase = (value) => (value % size + size) % size;
|
|
6447
|
+
return [phase(x3 * span), phase(y2 * span), span / 8192];
|
|
6448
|
+
}
|
|
6449
|
+
function record2(value) {
|
|
6450
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6451
|
+
}
|
|
6452
|
+
|
|
6123
6453
|
// src/buildings-3d-design.ts
|
|
6124
6454
|
var tileflowBuildingsMetadataKey = "tileflow:buildings";
|
|
6125
6455
|
var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
@@ -6147,6 +6477,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6147
6477
|
if (typeof color !== "string" && !Array.isArray(color)) return void 0;
|
|
6148
6478
|
const within = (number, high, fallback) => typeof number === "number" && number >= 0 && number <= high ? number : fallback;
|
|
6149
6479
|
const defaults = tileflowDefaultBuildings3DDesign;
|
|
6480
|
+
const surfaces = readTileflowBuildingSurfaces(value.surfaces);
|
|
6150
6481
|
const floodLight = readBuildingFloodLight(value.floodLight);
|
|
6151
6482
|
const modelLighting = readModelRoleLighting(value.modelLighting);
|
|
6152
6483
|
return {
|
|
@@ -6166,6 +6497,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
6166
6497
|
...floodLight ? { floodLight } : {},
|
|
6167
6498
|
...modelLighting ? { modelLighting } : {},
|
|
6168
6499
|
windows: value.windows === true,
|
|
6500
|
+
...surfaces ? { surfaces } : {},
|
|
6169
6501
|
...readTileflowBuildingsEntrance(value.entrance),
|
|
6170
6502
|
shadows: typeof value.shadows === "boolean" ? value.shadows : defaults.shadows,
|
|
6171
6503
|
occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults.occlusion,
|
|
@@ -8097,7 +8429,9 @@ uniform vec2 u_palette_rows; // rows per theme; texels per row
|
|
|
8097
8429
|
uniform vec2 u_palette_themes; // the themes either side of the blend position
|
|
8098
8430
|
uniform float u_palette_mix;
|
|
8099
8431
|
uniform float u_variation; // how far buildings' brightness strays from their colour, either way
|
|
8432
|
+
uniform vec3 u_surface_tile; // repeating projected-metre phase and metres per tile unit
|
|
8100
8433
|
${growth}
|
|
8434
|
+
out vec2 v_surface;
|
|
8101
8435
|
out vec3 v_colour;
|
|
8102
8436
|
out float v_base;
|
|
8103
8437
|
out vec3 v_facade; // metres along the wall, metres up as built, the building's top
|
|
@@ -8142,6 +8476,7 @@ void main() {
|
|
|
8142
8476
|
// Neighbours of one colour stay apart: each building a little lighter or darker than its colour.
|
|
8143
8477
|
v_colour *= 1.0 + (a_wave.x - 0.5) * 2.0 * u_variation;
|
|
8144
8478
|
v_base = base;
|
|
8479
|
+
v_surface = a_pos * u_surface_tile.z + u_surface_tile.xy;
|
|
8145
8480
|
v_edge = wall > 0.5 ? vec3(a_edge.x, 0.0, 0.0) : vec3(equal(vec3(a_edge.x), vec3(0.0, 1.0, 2.0)));
|
|
8146
8481
|
v_outline = a_edge.y;
|
|
8147
8482
|
v_facade = vec3(a_along * 0.1, own, top);
|
|
@@ -8152,6 +8487,10 @@ var tileflowBuildingFragment = `#version 300 es
|
|
|
8152
8487
|
precision highp float;
|
|
8153
8488
|
in vec3 v_colour;
|
|
8154
8489
|
in float v_base;
|
|
8490
|
+
in vec2 v_surface;
|
|
8491
|
+
uniform vec4 u_surface_walls; // width, course height, joint width, contrast
|
|
8492
|
+
uniform vec3 u_surface_roof; // square size, joint width, contrast
|
|
8493
|
+
uniform vec2 u_surface_cornice; // band height, contrast
|
|
8155
8494
|
uniform vec3 u_style_light_position;
|
|
8156
8495
|
uniform vec3 u_style_light_colour;
|
|
8157
8496
|
uniform float u_style_light_intensity;
|
|
@@ -8256,6 +8595,62 @@ float edgeOf() {
|
|
|
8256
8595
|
return 1.0 - smoothstep(u_edge_width - 0.75, u_edge_width + 0.25, near);
|
|
8257
8596
|
}
|
|
8258
8597
|
|
|
8598
|
+
// A filtered joint between large, softly shaded blocks. Derivatives are taken before the
|
|
8599
|
+
// stagger/periodic wrap, so row boundaries do not create false level-of-detail transitions.
|
|
8600
|
+
float surfaceBlocks(vec2 position, vec2 size, float joint, float contrast, float stagger) {
|
|
8601
|
+
vec2 footprint = max(fwidth(position), vec2(0.0001));
|
|
8602
|
+
float visible = smoothstep(2.0, 7.0, min(size.x / footprint.x, size.y / footprint.y));
|
|
8603
|
+
vec2 uv = position / size;
|
|
8604
|
+
uv.x += mod(floor(uv.y), 2.0) * stagger;
|
|
8605
|
+
vec2 cell = fract(uv) * size;
|
|
8606
|
+
vec2 distance = min(cell, size - cell);
|
|
8607
|
+
vec2 aa = footprint * 0.65;
|
|
8608
|
+
vec2 seam = 1.0 - smoothstep(vec2(joint * 0.5) - aa, vec2(joint * 0.5) + aa, distance);
|
|
8609
|
+
float groove = max(seam.x, seam.y);
|
|
8610
|
+
// A quiet bevel on the upper and left edges makes the painted blocks catch light.
|
|
8611
|
+
vec2 bevel = (1.0 - smoothstep(vec2(joint), vec2(joint + 0.35) + aa, cell)) * (1.0 - seam);
|
|
8612
|
+
return 1.0 + contrast * visible * (max(bevel.x, bevel.y) * 0.3 - groove * 0.65);
|
|
8613
|
+
}
|
|
8614
|
+
|
|
8615
|
+
// Distance to the actual roof outline in the roof's projected-metre plane. The triangle's
|
|
8616
|
+
// barycentric gradient ignores internal triangulation and tile cuts, including around patios.
|
|
8617
|
+
float roofOutlineDistance() {
|
|
8618
|
+
vec2 dx = dFdx(v_surface), dy = dFdy(v_surface);
|
|
8619
|
+
float determinant = dx.x * dy.y - dx.y * dy.x;
|
|
8620
|
+
if (abs(determinant) < 1e-10) return 1e6;
|
|
8621
|
+
vec3 bx = dFdx(v_edge), by = dFdy(v_edge);
|
|
8622
|
+
vec3 gx = (bx * dy.y - by * dx.y) / determinant;
|
|
8623
|
+
vec3 gy = (by * dx.x - bx * dy.x) / determinant;
|
|
8624
|
+
vec3 distance = v_edge / max(sqrt(gx * gx + gy * gy), vec3(1e-7));
|
|
8625
|
+
int sides = int(v_outline + 0.5);
|
|
8626
|
+
float nearest = 1e6;
|
|
8627
|
+
if ((sides & 1) != 0) nearest = min(nearest, distance.x);
|
|
8628
|
+
if ((sides & 2) != 0) nearest = min(nearest, distance.y);
|
|
8629
|
+
if ((sides & 4) != 0) nearest = min(nearest, distance.z);
|
|
8630
|
+
return nearest;
|
|
8631
|
+
}
|
|
8632
|
+
|
|
8633
|
+
vec3 surfaceColour() {
|
|
8634
|
+
vec3 colour = v_colour;
|
|
8635
|
+
bool wall = v_building.z > 0.5;
|
|
8636
|
+
float pattern = 1.0;
|
|
8637
|
+
if (wall && u_surface_walls.w > 0.0)
|
|
8638
|
+
pattern = surfaceBlocks(v_facade.xy, u_surface_walls.xy, u_surface_walls.z, u_surface_walls.w, 0.5);
|
|
8639
|
+
if (!wall && u_surface_roof.z > 0.0)
|
|
8640
|
+
pattern = surfaceBlocks(v_surface, vec2(u_surface_roof.x), u_surface_roof.y, u_surface_roof.z, 0.0);
|
|
8641
|
+
float band = 0.0, seam = 0.0;
|
|
8642
|
+
if (u_surface_cornice.y > 0.0) {
|
|
8643
|
+
float distance = wall ? v_facade.z - v_facade.y : roofOutlineDistance();
|
|
8644
|
+
float width = wall ? min(u_surface_cornice.x, (v_facade.z - v_base) * 0.2) : u_surface_cornice.x;
|
|
8645
|
+
float pixel = max(fwidth(distance), 0.001);
|
|
8646
|
+
float visible = smoothstep(0.4, 1.5, width / pixel);
|
|
8647
|
+
band = (1.0 - smoothstep(width - pixel * 0.5, width + pixel * 0.5, distance)) * visible;
|
|
8648
|
+
seam = (1.0 - smoothstep(0.0, pixel + width * 0.15, abs(distance - width))) * visible;
|
|
8649
|
+
}
|
|
8650
|
+
colour *= mix(pattern, 1.0, band) * (1.0 - seam * u_surface_cornice.y * 0.25);
|
|
8651
|
+
return mix(colour, mix(colour, vec3(1.0), u_surface_cornice.y * 0.45), band);
|
|
8652
|
+
}
|
|
8653
|
+
|
|
8259
8654
|
void main() {
|
|
8260
8655
|
vec3 normal = normalize(v_normal);
|
|
8261
8656
|
// A narrow lighting transition softens the roof/wall junction without moving the roof
|
|
@@ -8266,8 +8661,9 @@ void main() {
|
|
|
8266
8661
|
normal = normalize(mix(normal, vec3(0.0, 0.0, 1.0), rim));
|
|
8267
8662
|
}
|
|
8268
8663
|
float lit = dot(normal, u_sun_dir) > 0.0 ? visibility(v_shadow, 0.3) : 0.0;
|
|
8269
|
-
vec3
|
|
8270
|
-
|
|
8664
|
+
vec3 surface = surfaceColour();
|
|
8665
|
+
vec3 colour = mix(styleColour(surface, normal) * (1.0 - u_shadow * (1.0 - lit)),
|
|
8666
|
+
surface * shade(normal, lit), u_sun_lighting);
|
|
8271
8667
|
colour *= facadeShade();
|
|
8272
8668
|
// Roof outlines and outer corners catch the light, so where one building ends and the next starts
|
|
8273
8669
|
// stays legible, at night most of all.
|
|
@@ -9360,6 +9756,8 @@ function readTileflowVegetation3D(metadata) {
|
|
|
9360
9756
|
colors: { bark: colors.bark, broadleaf, conifer, palm, hedge },
|
|
9361
9757
|
heightScale: scale(heightScale),
|
|
9362
9758
|
crownScale: scale(crownScale),
|
|
9759
|
+
minimumHeight: typeof value.minimumHeight === "number" && Number.isFinite(value.minimumHeight) ? clamp(value.minimumHeight, [0, 20]) : 0,
|
|
9760
|
+
materialVariation: typeof value.materialVariation === "number" && Number.isFinite(value.materialVariation) ? clamp(value.materialVariation, [0, 1]) : 0,
|
|
9363
9761
|
forms,
|
|
9364
9762
|
models,
|
|
9365
9763
|
finish: finish2,
|
|
@@ -9649,7 +10047,7 @@ function browserWorker() {
|
|
|
9649
10047
|
if (typeof Worker === "undefined" || false)
|
|
9650
10048
|
return;
|
|
9651
10049
|
const url = URL.createObjectURL(
|
|
9652
|
-
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" })
|
|
10050
|
+
new Blob(['"use strict";(()=>{var Be=new Set,ln=!1;function Pe(e,n,t=2){let i=n&&n.length,o=i?n[0]*t:e.length;Be.size&&Be.clear();let r=zn(e,0,o,t,!0),s=[];if(!r||r.next===r.prev)return s;let a=0,l=0,u=0;if(i&&(r=xt(e,n,r,t)),e.length>80*t){a=e[0],l=e[1];let c=a,f=l;for(let d=t;d<o;d+=t){let g=e[d],m=e[d+1];g<a&&(a=g),m<l&&(l=m),g>c&&(c=g),m>f&&(f=m)}u=Math.max(c-a,f-l),u=u!==0?32767/u:0}return un(r,s,a,l,u),s}function zn(e,n,t,i,o){let r=null;if(o===Ut(e,n,t,i)>0)for(let s=n;s<t;s+=i)r=In(s/i|0,e[s],e[s+1],r);else for(let s=t-i;s>=n;s-=i)r=In(s/i|0,e[s],e[s+1],r);return r&&Oe(r,r.next)&&(Ce(r),r=r.next),r}function ge(e,n=e){let t=n===e,i=e,o;do o=!1,i!==i.next&&(Be.size===0||!Be.has(i))&&(Oe(i,i.next)||Q(i.prev,i,i.next)===0)?((t||i===n)&&(n=i.prev),ln=!0,Ce(i),i=i.prev,o=!0):(t||i!==n)&&(i=i.next,o=!t);while(o||i!==n);return n}function un(e,n,t,i,o){o&&Ft(e,t,i,o);let r=e,s=!1;for(;e.prev!==e.next;){let a=e.prev,l=e.next;if(Q(a,e,l)<0&&(o?bt(e,t,i,o):yt(e))){n.push(a.i,e.i,l.i),Ce(e),e=l,r=l;continue}if(e=l,e===r){if(ln=!1,e=ge(e),ln){r=e;continue}if(!s){e=gt(e,n),r=e,s=!0;continue}wt(e,n,t,i,o);break}}}function yt(e){let n=e.prev,t=e,i=e.next,o=n.x,r=t.x,s=i.x,a=n.y,l=t.y,u=i.y,c=Math.min(o,r,s),f=Math.min(a,l,u),d=Math.max(o,r,s),g=Math.max(a,l,u),m=i.next;for(;m!==n;){if(m.x>=c&&m.x<=d&&m.y>=f&&m.y<=g&&!(o===m.x&&a===m.y)&&Ke(o,a,r,l,s,u,m.x,m.y)&&Q(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function bt(e,n,t,i){let o=e.prev,r=e,s=e.next,a=o.x,l=r.x,u=s.x,c=o.y,f=r.y,d=s.y,g=Math.min(a,l,u),m=Math.min(c,f,d),p=Math.max(a,l,u),h=Math.max(c,f,d),_=mn(g,m,n,t,i),F=mn(p,h,n,t,i),k=e.prevZ;for(;k&&k.z>=_;){if(k.x>=g&&k.x<=p&&k.y>=m&&k.y<=h&&k!==s&&!(a===k.x&&c===k.y)&&Ke(a,c,l,f,u,d,k.x,k.y)&&Q(k.prev,k,k.next)>=0)return!1;k=k.prevZ}let M=e.nextZ;for(;M&&M.z<=F;){if(M.x>=g&&M.x<=p&&M.y>=m&&M.y<=h&&M!==s&&!(a===M.x&&c===M.y)&&Ke(a,c,l,f,u,d,M.x,M.y)&&Q(M.prev,M,M.next)>=0)return!1;M=M.nextZ}return!0}function gt(e,n){let t=e,i=!1;do{let o=t.prev,r=t.next.next;Nn(o,t,t.next,r,!1)&&Ue(o,r)&&Ue(r,o)&&(n.push(o.i,t.i,r.i),Ce(t),Ce(t.next),t=e=r,i=!0),t=t.next}while(t!==e);return i?ge(t):t}function wt(e,n,t,i,o){let r=e;do{let s=r.next.next;for(;s!==r.prev;){if(r.i!==s.i&&Lt(r,s)){let a=Vn(r,s);r=ge(r,r.next),a=ge(a,a.next),un(r,n,t,i,o),un(a,n,t,i,o);return}s=s.next}r=r.next}while(r!==e)}var cn=!1;function xt(e,n,t,i){let o=[];for(let r=0,s=n.length;r<s;r++){let a=n[r]*i,l=r<s-1?n[r+1]*i:e.length,u=zn(e,a,l,i,!1);u===u.next&&Be.add(u),o.push(St(u))}o.sort(Tt),kt(e.length/i,n.length),Dn(t,t),cn=!0;for(let r=0;r<o.length;r++)t=Mt(o[r],t);return cn=!1,ge(t)}function Tt(e,n){return e.x-n.x||e.y-n.y||(e.next.y-e.y)/(e.next.x-e.x)-(n.next.y-n.y)/(n.next.x-n.x)}function Mt(e,n){let t=Rt(e,n);if(!t)return n;let i=Vn(t,e),o=i.next;return Dn(t,o.next),ge(i,i.next),ge(t,t.next)}var jn=16,X=new Float64Array(0),Je=0,fn=[],dn=[];function kt(e,n){let t=Math.ceil((e+2*n)/jn)+n+2;X.length<t*4&&(X=new Float64Array(t*4)),Je=0}function Dn(e,n){let t=e;do{let i=Je++;fn[i]=t;let o=t.x,r=t.y,s=t.x,a=t.y,l=0;do{let c=t.next;t.z=i,c.x<o&&(o=c.x),c.x>s&&(s=c.x),c.y<r&&(r=c.y),c.y>a&&(a=c.y),t=c}while(++l<jn&&t!==n);dn[i]=t;let u=i*4;X[u]=o,X[u+1]=r,X[u+2]=s,X[u+3]=a}while(t!==n)}function vt(e,n){let t=e.z*4;n.x<X[t]&&(X[t]=n.x),n.y<X[t+1]&&(X[t+1]=n.y),n.x>X[t+2]&&(X[t+2]=n.x),n.y>X[t+3]&&(X[t+3]=n.y)}function Pn(e){let n=dn[e];for(;n.prev.next!==n;)n=n.next;return dn[e]=n,n}function En(e){let n=fn[e];for(;n.prev.next!==n;)n=n.next;return fn[e]=n,n}function Rt(e,n){let t=n,i=e.x,o=e.y,r=-1/0,s;if(Oe(e,t))return t;for(let d=0,g=0;d<Je;d++,g+=4){if(o<X[g+1]||o>X[g+3]||X[g]>i||X[g+2]<=r)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t){if(Oe(e,t.next))return t.next;if(o<=t.y&&o>=t.next.y&&t.next.y!==t.y){let p=t.x+(o-t.y)*(t.next.x-t.x)/(t.next.y-t.y);if(p<=i&&p>r&&(r=p,s=t.x<t.next.x?t:t.next,p===i))return s}}t=t.next}while(t!==m)}if(!s)return null;let a=s.x,l=s.y,u=Math.min(o,l),c=Math.max(o,l),f=1/0;for(let d=0,g=0;d<Je;d++,g+=4){if(X[g+2]<a||X[g]>i||X[g+3]<u||X[g+1]>c)continue;let m=Pn(d);t=En(d);do{if(t.prev.next===t&&i>=t.x&&t.x>=a&&i!==t.x&&Ke(o<l?i:r,o,a,l,o<l?r:i,o,t.x,t.y)){let p=Math.abs(o-t.y)/(i-t.x);(Ue(t,e)||t.y===o&&t.next.y===o&&t.next.x>i)&&(p<f||p===f&&(t.x>s.x||t.x===s.x&&_t(s,t)))&&(s=t,f=p)}t=t.next}while(t!==m)}return s}function _t(e,n){return Q(e.prev,e,n.prev)<0&&Q(n.next,e,e.next)<0}var ie=[],ve=[],be=new Uint32Array(0),Se=new Uint32Array(0),Le=new Uint32Array(256);function Ft(e,n,t,i){let o=e,r=0;do o.z=mn(o.x,o.y,n,t,i),ie[r++]=o,o=o.next;while(o!==e);At(r);let s=null;for(let a=0;a<r;a++){let l=ie[a];l.prevZ=s,s&&(s.nextZ=l),s=l}s.nextZ=null,ie.fill(null,0,r),ve.fill(null,0,r)}function At(e){if(e<=32){for(let n=1;n<e;n++){let t=ie[n],i=t.z,o=n-1;for(;o>=0&&ie[o].z>i;)ie[o+1]=ie[o],o--;ie[o+1]=t}return}be.length<e&&(be=new Uint32Array(e),Se=new Uint32Array(e),ve=new Array(e));for(let n=0;n<e;n++)be[n]=ie[n].z;Xe(e,ie,be,ve,Se,0),Xe(e,ve,Se,ie,be,8),Xe(e,ie,be,ve,Se,16),Xe(e,ve,Se,ie,be,24)}function Xe(e,n,t,i,o,r){Le.fill(0);for(let a=0;a<e;a++)Le[t[a]>>>r&255]++;let s=0;for(let a=0;a<256;a++){let l=Le[a];Le[a]=s,s+=l}for(let a=0;a<e;a++){let l=t[a],u=Le[l>>>r&255]++;i[u]=n[a],o[u]=l}}function mn(e,n,t,i,o){return e=(e-t)*o|0,n=(n-i)*o|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,n=(n|n<<8)&16711935,n=(n|n<<4)&252645135,n=(n|n<<2)&858993459,n=(n|n<<1)&1431655765,e|n<<1}function St(e){let n=e,t=e;do(n.x<t.x||n.x===t.x&&n.y<t.y)&&(t=n),n=n.next;while(n!==e);return t}function Ke(e,n,t,i,o,r,s,a){return(o-s)*(n-a)>=(e-s)*(r-a)&&(e-s)*(i-a)>=(t-s)*(n-a)&&(t-s)*(r-a)>=(o-s)*(i-a)}function Lt(e,n){let t=Oe(e,n)&&Q(e.prev,e,e.next)>0&&Q(n.prev,n,n.next)>0;return e.next.i!==n.i&&(t||Ue(e,n)&&Ue(n,e)&&(Q(e.prev,e,n.prev)!==0||Q(e,n.prev,n)!==0))&&!Bt(e,n)&&(t||Ot(e,n))}function Q(e,n,t){return(n.y-e.y)*(t.x-n.x)-(n.x-e.x)*(t.y-n.y)}function Oe(e,n){return e.x===n.x&&e.y===n.y}function Nn(e,n,t,i,o=!0){let r=Q(e,n,t),s=Q(e,n,i),a=Q(t,i,e),l=Q(t,i,n);return(r>0&&s<0||r<0&&s>0)&&(a>0&&l<0||a<0&&l>0)?!0:o?!!(r===0&&Ye(e,t,n)||s===0&&Ye(e,i,n)||a===0&&Ye(t,e,i)||l===0&&Ye(t,n,i)):!1}function Ye(e,n,t){return n.x<=Math.max(e.x,t.x)&&n.x>=Math.min(e.x,t.x)&&n.y<=Math.max(e.y,t.y)&&n.y>=Math.min(e.y,t.y)}function Bt(e,n){let t=Math.min(e.x,n.x),i=Math.max(e.x,n.x),o=Math.min(e.y,n.y),r=Math.max(e.y,n.y),s=e;do{let a=s.next;if(s.x>i&&a.x>i||s.x<t&&a.x<t||s.y>r&&a.y>r||s.y<o&&a.y<o){s=a;continue}if(s.i!==e.i&&a.i!==e.i&&s.i!==n.i&&a.i!==n.i&&Nn(s,a,e,n))return!0;s=a}while(s!==e);return!1}function Ue(e,n){return Q(e.prev,e,e.next)<0?Q(e,n,e.next)>=0&&Q(e,e.prev,n)>=0:Q(e,n,e.prev)<0||Q(e,e.next,n)<0}function Ot(e,n){let t=e,i=!1,o=(e.x+n.x)/2,r=(e.y+n.y)/2;do{let s=t.next;t.y>r!=s.y>r&&o<(s.x-t.x)*(r-t.y)/(s.y-t.y)+t.x&&(i=!i),t=s}while(t!==e);return i}function Vn(e,n){let t=hn(e.i,e.x,e.y),i=hn(n.i,n.x,n.y),o=e.next,r=n.prev;return e.next=n,n.prev=e,t.next=o,o.prev=t,i.next=t,t.prev=i,r.next=i,i.prev=r,i}function In(e,n,t,i){let o=hn(e,n,t);return i?(o.next=i.next,o.prev=i,i.next.prev=o,i.next=o):(o.prev=o,o.next=o),o}function Ce(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ),cn&&vt(e.prev,e.next)}function hn(e,n,t){return{i:e,x:n,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null}}function Ut(e,n,t,i){let o=0;for(let r=n,s=t-i;r<t;r+=i)o+=(e[s]-e[r])*(e[r+1]+e[s+1]),s=r;return o}var Ct=.7,Pt=Math.tan(Math.PI/6),Et=Math.tan(35*Math.PI/180),It=Math.tan(Math.PI/18),Ee=.65,Ie=.4;function Zn(e,n,t,i,o,r,s){let a=String(t.roof_shape??"");if(!a||a==="flat"||a==="sawtooth"||Vt(e,s))return;let l=Dt(e);if(!l||Math.abs(pn(e))<Ct*4*l.halfU*l.halfV)return;let u=l.u,c=l.v,f=l.halfU*r,d=l.halfV*r;f<d&&([u,c,f,d]=[c,u,d,f]);let g=Gn(t.roof_direction),m=g===void 0?void 0:[Math.sin(g*Math.PI/180),-Math.cos(g*Math.PI/180)];(m!==void 0?Math.abs(m[0]*u[0]+m[1]*u[1])>Math.abs(m[0]*c[0]+m[1]*c[1]):t.roof_orientation==="across")&&a!=="skillion"&&([u,c,f,d]=[c,u,d,f]);let h=jt(a,f,d,m&&[$n(m,u),$n(m,c)]);if(!h)return;let _=Math.max(0,o-i),F=Gn(t.roof_height),k,M;if(F!==void 0&&F>0)M=o,k=Math.max(i+Math.min(2,_/2),o-F);else{let y=Math.min(zt(a,d),_*.6,30);t.height_source==="height"?(M=o,k=o-y):(k=o,M=o+y)}let B=M-k;if(!(B>=.3))return;let[U,E]=l.centre,C=(y,b)=>{let x=(y-U)*r,T=(b-E)*r;return[x*u[0]+T*u[1],x*c[0]+T*c[1]]},I=(y,b)=>[U+(y*u[0]+b*c[0])/r,E+(y*u[1]+b*c[1])/r],N=(y,b)=>{let x=1/0;for(let[T,A,v]of h)x=Math.min(x,T*y+A*b+v);return Math.max(0,x)},K=(y,b)=>k+B*N(...C(y,b)),$=[];for(let y=0;y+1<n.length;y+=2)$.push(...C(n[y],n[y+1]));pn($)<0&&Ht($);let D=1.01,Y=[-f*D,-d*D,f*D,-d*D,f*D,d*D,-f*D,d*D],w=[];for(let[y,b]of h.entries()){let x=Y;for(let[P,Z]of h.entries()){if(P===y)continue;let j=b[0]-Z[0],G=b[1]-Z[1],W=b[2]-Z[2];if(Math.abs(j)+Math.abs(G)+Math.abs(W)<1e-9){P<y&&(x=[]);continue}if(x=Hn(x,j,G,W),x.length<6)break}if(x.length<6)continue;let T=$,A=x.length/2;for(let P=0;P<A&&T.length>=6;P+=1){let[Z,j]=[x[P*2],x[P*2+1]],[G,W]=[x[(P+1)%A*2],x[(P+1)%A*2+1]];T=Hn(T,W-j,Z-G,-(W-j)*Z-(Z-G)*j)}if(T.length<6||Math.abs(pn(T))<1e-6)continue;let v=[];for(let P=0;P<T.length;P+=2)v.push(...I(T[P],T[P+1]));let L=Pe(v);if(L.length===0)continue;let O=B*b[0],V=B*b[1],R=O*u[0]+V*c[0],S=O*u[1]+V*c[1],z=Math.hypot(R,S,1);w.push({ring:v,triangles:L,normal:[-R/z,-S/z]})}if(w.length!==0)return{eaves:k,ridge:M,faces:w,heightAt:K,breaks(y,b,x,T){let[A,v]=C(y,b),[L,O]=C(x,T),V=[];for(let R=0;R<h.length;R+=1)for(let S=R+1;S<h.length;S+=1){let z=(ae,H)=>(h[R][0]-h[S][0])*ae+(h[R][1]-h[S][1])*H+(h[R][2]-h[S][2]),P=z(A,v),Z=z(L,O);if(P===Z||P*Z>0)continue;let j=P/(P-Z);if(j<=1e-4||j>=1-1e-4)continue;let G=A+(L-A)*j,W=v+(O-v)*j;h[R][0]*G+h[R][1]*W+h[R][2]<=N(G,W)+1e-6&&V.push(j)}return[...new Set(V.map(R=>Math.round(R*1e6)/1e6))].sort((R,S)=>R-S)}}}function zt(e,n){switch(e){case"skillion":return 2*n*It;case"pyramidal":return n*Et;case"gambrel":case"mansard":return n*.8;case"dome":case"onion":case"round":return n;default:return n*Pt}}function jt(e,n,t,i){let o=n,r=t,s=[[0,-1/r,1],[0,1/r,1]],a=u=>u.flatMap(c=>[1,-1].flatMap(f=>{let d=c==="v"?r:o,g=Ee/(Ie*r)*f,m=(1-Ee)/((1-Ie)*r)*f,p=h=>c==="v"?[0,-h]:[-h,0];return[[...p(g),Ee/(Ie*r)*d],[...p(m),Ee+(1-Ee)/((1-Ie)*r)*(d-Ie*r)]]})),l=[.99,.8,.5,.2];switch(e){case"gabled":return s;case"saltbox":{let u=r/3;return[[0,-1/(r-u),1+u/(r-u)],[0,1/(r+u),1-u/(r+u)]]}case"hipped":return[...s,[-1/r,0,o/r],[1/r,0,o/r]];case"half_hipped":return[...s,[-1/r,0,.5+o/r],[1/r,0,.5+o/r]];case"pyramidal":return[...s,[-1/o,0,1],[1/o,0,1]];case"gambrel":return a(["v"]);case"mansard":return a(["v","u"]);case"skillion":{let[u,c]=i??[0,1],f=Math.abs(u)*o+Math.abs(c)*r;return f>0?[[-u/(2*f),-c/(2*f),.5]]:void 0}case"round":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return[1,-1].map(f=>[0,-f*u/(r*c),1/c])})];case"dome":case"onion":return[[0,0,1],...l.flatMap(u=>{let c=Math.sqrt(1-u*u);return Array.from({length:12},(f,d)=>{let g=d*Math.PI/6;return[-u*Math.cos(g)/(o*c),-u*Math.sin(g)/(r*c),1/c]})})];default:return}}function Hn(e,n,t,i){let o=e.length/2,r=[];for(let s=0;s<o;s+=1){let a=e[s*2],l=e[s*2+1],u=e[(s+1)%o*2],c=e[(s+1)%o*2+1],f=n*a+t*l+i,d=n*u+t*c+i;if(f<=0&&r.push(a,l),f<0&&d>0||f>0&&d<0){let g=f/(f-d);r.push(a+(u-a)*g,l+(c-l)*g)}}return r}function Dt(e){let n=Nt(e);if(n.length<3)return;let t,i=1/0;for(let o=0;o<n.length;o+=1){let[r,s]=n[o],[a,l]=n[(o+1)%n.length],u=Math.hypot(a-r,l-s);if(u===0)continue;let c=[(a-r)/u,(l-s)/u],f=[-c[1],c[0]],[d,g,m,p]=[1/0,-1/0,1/0,-1/0];for(let[_,F]of n){let k=_*c[0]+F*c[1],M=_*f[0]+F*f[1];d=Math.min(d,k),g=Math.max(g,k),m=Math.min(m,M),p=Math.max(p,M)}let h=(g-d)*(p-m);if(h<i){i=h;let _=(d+g)/2,F=(m+p)/2;t={centre:[_*c[0]+F*f[0],_*c[1]+F*f[1]],u:c,v:f,halfU:(g-d)/2,halfV:(p-m)/2}}}return t&&t.halfU>0&&t.halfV>0?t:void 0}function Nt(e){let n=[];for(let r=0;r+1<e.length;r+=2)n.push([e[r],e[r+1]]);n.sort((r,s)=>r[0]-s[0]||r[1]-s[1]);let t=(r,s,a)=>(s[0]-r[0])*(a[1]-r[1])-(s[1]-r[1])*(a[0]-r[0]),i=[];for(let r of n){for(;i.length>=2&&t(i.at(-2),i.at(-1),r)<=0;)i.pop();i.push(r)}let o=[];for(let r of n.reverse()){for(;o.length>=2&&t(o.at(-2),o.at(-1),r)<=0;)o.pop();o.push(r)}return[...i.slice(0,-1),...o.slice(0,-1)]}function Vt(e,n){let[t,i,o,r]=[1/0,-1/0,1/0,-1/0];for(let a=0;a+1<e.length;a+=2)t=Math.min(t,e[a]),i=Math.max(i,e[a]),o=Math.min(o,e[a+1]),r=Math.max(r,e[a+1]);let s=e.length/2;for(let a=0;a<s;a+=1){let l=e[a*2],u=e[a*2+1],c=e[(a+1)%s*2],f=e[(a+1)%s*2+1];if(t<0&&l===t&&c===t||i>n&&l===i&&c===i||o<0&&u===o&&f===o||r>n&&u===r&&f===r)return!0}return!1}function pn(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n/2}function Ht(e){let n=[];for(let t=0;t<e.length;t+=2)n.push([e[t],e[t+1]]);n.reverse(),e.splice(0,e.length,...n.flat())}function $n(e,n){return e[0]*n[0]+e[1]*n[1]}function Gn(e){let n=typeof e=="string"?Number(e):e;return typeof n=="number"&&Number.isFinite(n)?n:void 0}var jr=Object.freeze({surface:0,secondary:1,glass:2,accent:3,roof:4}),Dr=Object.freeze({unclassified:0,wall:1,door:2,roof:3,window:4,lamp:5,logo:6}),Nr=Object.freeze([1,1,4,1,3]),Vr=Object.freeze({levels:3,vertices:2e5,triangles:2e5,footprintPoints:4096,radius:2e3,height:1e3,models:512,bytes:16*1024*1024});function yn(e,n,t){for(let i of e){let o=!1;for(let r=0,s=i.length-2;r<i.length;s=r,r+=2){let a=i[r],l=i[r+1],u=i[s],c=i[s+1];l>t!=c>t&&n<(u-a)*(t-l)/(c-l)+a&&(o=!o)}if(o)return!0}return!1}function Yn(e,n,t){for(let i of n){let[o,r,s,a]=Xn(i);for(let l of e){let[u,c,f,d]=Xn(l);if(!(u>s-t||f<o+t||c>a-t||d<r+t)&&(Wn(l,i,t)||Wn(i,l,t)))return!0}}return!1}function Wn(e,n,t){let i=(o,r)=>yn([n],o,r)&&Gt(n,o,r)>t;for(let o=0;o+1<e.length;o+=2)if(i(e[o],e[o+1]))return!0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=[0,1];for(let f=0,d=n.length-2;f<n.length;d=f,f+=2){let g=$t(s,a,l,u,n[d],n[d+1],n[f],n[f+1]);g!==void 0&&c.push(g)}if(c.length!==2){c.sort((f,d)=>f-d);for(let f=1;f<c.length;f+=1){let d=(c[f-1]+c[f])/2;if(i(s+(l-s)*d,a+(u-a)*d))return!0}}}return!1}function $t(e,n,t,i,o,r,s,a){let l=t-e,u=i-n,c=s-o,f=a-r,d=l*f-u*c;if(d===0)return;let g=((o-e)*f-(r-n)*c)/d,m=((o-e)*u-(r-n)*l)/d;return g>0&&g<1&&m>=0&&m<=1?g:void 0}function Gt(e,n,t){let i=1/0;for(let o=0,r=e.length-2;o<e.length;r=o,o+=2){let[s,a,l,u]=[e[r],e[r+1],e[o],e[o+1]],c=(l-s)**2+(u-a)**2,f=c>0?Math.max(0,Math.min(1,((n-s)*(l-s)+(t-a)*(u-a))/c)):0;i=Math.min(i,Math.hypot(n-(s+(l-s)*f),t-(a+(u-a)*f)))}return i}function Xn(e){let[n,t,i,o]=[1/0,1/0,-1/0,-1/0];for(let r=0;r+1<e.length;r+=2)n=Math.min(n,e[r]),i=Math.max(i,e[r]),t=Math.min(t,e[r+1]),o=Math.max(o,e[r+1]);return[n,t,i,o]}var ue=8192,pe=28,Zt={commercial:1,active:2,destination:3},Wt={residential:1,...Object.fromEntries(["civic","commercial","education","entertainment","medical","transportation"].map(e=>[e,2])),...Object.fromEntries(["agricultural","industrial","military","outbuilding","religious","service"].map(e=>[e,3]))},Xt={dining:1,entertainment:2,nightlife:3},bn={...Object.fromEntries(["alcoholic_beverage_venue","bar","beer","biergarten","brewery","casino","cocktail_bar","dance_club","karaoke","lounge","music_venue","night_club","nightclub","pub","wine_bar"].map(e=>[e,3])),...Object.fromEntries(["arts_centre","bowling_alley","cinema","comedy_club","concert_hall","movie_theater","opera","performing_arts_venue","theater","theatre","theatre_venue"].map(e=>[e,2])),...Object.fromEntries(["casual_eatery","fast_food","fast_food_restaurant","food_court","restaurant"].map(e=>[e,1]))},Yt=6,Jt=.5,Kt=.5;function Kn(e,n){let t=ue/e.extent,i=n.tileMetres/ue,o=n.defaultHeight??5,r=Number.isFinite(n.edgeRadius)?Math.max(0,Math.min(1,n.edgeRadius))/i:0,s=new wn,a=new Qe,l=new Qe,u=[],c=[],f=0,d=nr(e,n);for(let[M,B]of e.features.entries()){if(B.type!=="Polygon"||u.length>=65535)continue;let U=B.properties,E=U.hide_3d;if(E===!0||E===1||E==="1"||E==="true")continue;let C=Math.min(6e3,Jn(U.render_height)??o),I=Math.min(C,Jn(U.render_min_height)??0),N=Zt[String(U.building_tone??"")]??0,K=Wt[String(U.class??"")]??0,$=d.get(M)??0,D=u.length,Y=!1;for(let w of tr(B.geometry,t)){let y=w.map(or).filter(S=>S.length>=6);if(y.length===0||qe(y[0])===0)continue;let[b,x]=rr(y[0]);if(n.masks?.length&&(yn(n.masks,b,x)||Yn(y,n.masks,Kt/i)))continue;let T={cell:Math.min(7,Math.max(0,Math.floor(x/1024)))*8+Math.min(7,Math.max(0,Math.floor(b/1024))),bounds:[1/0,1/0,-1/0,-1/0,C+.1],roofsFrom:a.length,roofsCount:0,wallsFrom:l.length,wallsCount:0};for(let S of y)for(let z=0;z<S.length;z+=2)T.bounds[0]=Math.min(T.bounds[0],S[z]-1),T.bounds[1]=Math.min(T.bounds[1],S[z+1]-1),T.bounds[2]=Math.max(T.bounds[2],S[z]+1),T.bounds[3]=Math.max(T.bounds[3],S[z+1]+1);Y=!0,f=Math.max(f,C);let A=Number.isSafeInteger(B.id),v=gn(A?B.id*.0731:b*.0731+x*.19137+D*1.618),L=!A&&y[0].some(S=>S<=0||S>=ue)?gn(C*7.31+I*3.17+N):v,O={base:I,top:C,jitter:L,seed:v,tone:N,group:K,use:$,cx:b,cy:x,index:D},V=y.map((S,z)=>er(S,z,r,n.cornerAngle));y=V.map(({ring:S})=>S);let R=w.length===1&&y.length===1?Zn(w[0],y[0],U,I,C,i,ue):void 0;R?(f=Math.max(f,R.ridge),T.bounds[4]=Math.max(T.bounds[4],R.ridge+.1),qt(R,O,s,a)):Qt(y,O,s,a);for(let[S,z]of y.entries()){let P=qe(z)>0,Z=S===0?P?-1:1:P?1:-1,j=z.length/2,G=H=>{let J=(H%j+j)%j;return[z[J*2],z[J*2+1]]},W=H=>{let[J,re]=G(H-1),[ne,te]=G(H),[le,de]=G(H+1);if(we(J,re,ne,te)||we(ne,te,le,de))return!1;let me=Math.hypot(ne-J,te-re),ce=Math.hypot(le-ne,de-te);if(!me||!ce)return!1;let je=-(te-re)/me*Z,De=(ne-J)/me*Z;return(je*(le-ne)+De*(de-te))/ce>Jt},se=(H,J)=>R?R.heightAt(H,J):C,ae=0;for(let H=0;H<j;H+=1){let[J,re]=G(H),[ne,te]=G(H+1),le=Math.hypot(ne-J,te-re);if(le===0||we(J,re,ne,te))continue;let de=-(te-re)/le*Z,me=(ne-J)/le*Z,ce=V[S].normals[H]??[de,me],je=V[S].normals[(H+1)%j]??[de,me],De=oe=>{let _e=ce[0]+(je[0]-ce[0])*oe,Fe=ce[1]+(je[1]-ce[1])*oe,ye=Math.hypot(_e,Fe)||1;return[_e/ye,Fe/ye]},he=[0,...R?R.breaks(J,re,ne,te):[],1];for(let oe=0;oe+1<he.length;oe+=1){let _e=oe===0,Fe=oe+2===he.length,ye=J+(ne-J)*he[oe],Ne=re+(te-re)*he[oe],Ve=J+(ne-J)*he[oe+1],He=re+(te-re)*he[oe+1],Ae=Math.hypot(Ve-ye,He-Ne)/ue*n.tileMetres,$e=(_e&&W(H)?1:0)|(Fe&&W(H+1)?2:0)|(S>0?4:0),Ge=(_e&&xn(J,re)?1:0)|(Fe&&xn(ne,te)?2:0),an=ae+Ae,Ze=De(he[oe]),We=De(he[oe+1]),Un=se(ye,Ne),Cn=se(Ve,He),ke=s.write(O,ye,Ne,0,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un);s.write(O,Ve,He,0,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),s.write(O,ye,Ne,1,Ze[0],Ze[1],1,ae,$e,Ae,0,Ge,Un),s.write(O,Ve,He,1,We[0],We[1],1,an,$e,Ae,1,Ge,Cn),l.push(ke,ke+1,ke+2,ke+1,ke+3,ke+2),ae=an}}}T.roofsCount=a.length-T.roofsFrom,T.wallsCount=l.length-T.wallsFrom,c.push(T)}Y&&u.push(U)}if(s.count===0)return;let g=new Uint32Array(a.length+l.length),m=[],p=0,h=a.length,_=a.values(),F=l.values();c.sort((M,B)=>M.cell-B.cell);let k=-1;for(let M of c){M.cell!==k&&(k=M.cell,m.push({bounds:[...M.bounds],roofsFrom:p,roofsCount:0,wallsFrom:h,wallsCount:0}));let B=m.at(-1);for(let U=0;U<5;U+=1)B.bounds[U]=U<2?Math.min(B.bounds[U],M.bounds[U]):Math.max(B.bounds[U],M.bounds[U]);g.set(_.subarray(M.roofsFrom,M.roofsFrom+M.roofsCount),p),g.set(F.subarray(M.wallsFrom,M.wallsFrom+M.wallsCount),h),p+=M.roofsCount,h+=M.wallsCount,B.roofsCount+=M.roofsCount,B.wallsCount+=M.wallsCount}return{groups:m,vertices:s.bytes(),indices:g,wallsFrom:a.length,top:f,features:u}}function Qt(e,n,t,i){let o=[],r=[];for(let l of e)r.push(o.length/2),o.push(...l);r.push(o.length/2);let s=(l,u)=>{let c=r.findIndex((p,h)=>l>=p&&l<r[h+1]),[f,d]=[r[c],r[c+1]-1];if(u<f||u>d)return!1;let[g,m]=l<u?[l,u]:[u,l];return m-g!==1&&!(g===f&&m===d)?!1:!we(o[l*2],o[l*2+1],o[u*2],o[u*2+1])},a=Pe(o,r.slice(1,-1),2);for(let l=0;l+2<a.length;l+=3){let u=[a[l],a[l+1],a[l+2]],c=0;for(let f=0;f<3;f+=1)s(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries())i.push(t.write(n,o[d*2],o[d*2+1],1,0,0,0,0,0,0,f,c))}}function qt(e,n,t,i){for(let o of e.faces){let r=o.ring,s=r.length/2,a=(l,u)=>{let[c,f]=l<u?[l,u]:[u,l];return f-c!==1&&!(c===0&&f===s-1)?!1:!we(r[l*2],r[l*2+1],r[u*2],r[u*2+1])};for(let l=0;l+2<o.triangles.length;l+=3){let u=[o.triangles[l],o.triangles[l+1],o.triangles[l+2]],c=0;for(let f=0;f<3;f+=1)a(u[(f+1)%3],u[(f+2)%3])&&(c|=1<<f);for(let[f,d]of u.entries()){let g=r[d*2],m=r[d*2+1];i.push(t.write(n,g,m,1,o.normal[0],o.normal[1],0,0,0,0,f,c,e.heightAt(g,m)))}}}}function er(e,n,t,i=Math.PI/6){if(t<1)return{ring:e,normals:[]};let o=e.length/2,r=qe(e)>0,s=n===0?r?-1:1:r?1:-1,a=[],l=[],u=(c,f,d)=>{c=Re(c),f=Re(f),!(a.at(-2)===c&&a.at(-1)===f)&&(a.push(c,f),l.push(d))};for(let c=0;c<o;c+=1){let f=(c+o-1)%o,d=(c+1)%o,[g,m]=[e[f*2],e[f*2+1]],[p,h]=[e[c*2],e[c*2+1]],[_,F]=[e[d*2],e[d*2+1]],k=Math.hypot(p-g,h-m),M=Math.hypot(_-p,F-h);if(!k||!M||xn(p,h)||we(g,m,p,h)||we(p,h,_,F)){u(p,h);continue}let[B,U]=[(p-g)/k,(h-m)/k],[E,C]=[(_-p)/M,(F-h)/M],I=Math.atan2(B*C-U*E,B*E+U*C);if(I*s>=-.08||Math.abs(I)>Math.PI*.85){u(p,h);continue}let N=Math.tan(Math.abs(I)/2),K=Math.min(t*N,k*.2,M*.2),$=K/N;if($<1){u(p,h);continue}let[D,Y]=[-U*s,B*s],[w,y]=[p-B*K-D*$,h-U*K-Y*$],b=Math.atan2(Y,D),x=Math.max(i<=Math.PI/6?2:1,Math.ceil(Math.abs(I)/Math.max(Math.PI/6,Math.min(Math.PI/3,i))));for(let T=0;T<=x;T+=1){let A=b+I*T/x,v=[Math.cos(A),Math.sin(A)];u(w+v[0]*$,y+v[1]*$,v)}}return a[0]===a.at(-2)&&a[1]===a.at(-1)&&(a.splice(-2),l.pop()),a.length>=6?{ring:a,normals:l}:{ring:e,normals:[]}}var wn=class{#e=new ArrayBuffer(4096*pe);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s,a,l,u,c,f=0,d=0,g=n.top){let m=pe;if((this.count+1)*m>this.#e.byteLength){let _=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(_).set(new Uint8Array(this.#e)),this.#e=_,this.#n=new DataView(_)}let p=this.#n,h=this.count*m;return p.setUint16(h,Re(t),!0),p.setUint16(h+2,Re(i),!0),p.setUint16(h+4,Math.min(65535,Math.round(n.base*10)),!0),p.setUint16(h+6,Math.min(65535,Math.max(0,Math.round(g*10))),!0),p.setInt8(h+8,Math.round(r*127)),p.setInt8(h+9,Math.round(s*127)),p.setUint8(h+10,o),p.setUint8(h+11,a),p.setUint16(h+12,Math.round(l*10)%65536,!0),p.setUint8(h+14,Math.round(n.jitter*255)),p.setUint8(h+15,Math.round(n.seed*255)),p.setUint16(h+16,Re(n.cx),!0),p.setUint16(h+18,Re(n.cy),!0),p.setUint8(h+20,n.tone+4*n.group),p.setUint8(h+21,n.use),p.setUint8(h+22,u),p.setUint8(h+23,Math.min(255,Math.round(c))),p.setUint16(h+24,n.index,!0),p.setUint8(h+26,f),p.setUint8(h+27,d),this.count+=1,this.count-1}bytes(){return new Uint8Array(this.#e.slice(0,this.count*pe))}},Qe=class{#e=new Uint32Array(8192);length=0;push(...n){if(this.length+n.length>this.#e.length){let t=new Uint32Array(Math.max(this.length+n.length,this.#e.length*2));t.set(this.#e),this.#e=t}for(let t of n)this.#e[this.length++]=t}values(){return this.#e.subarray(0,this.length)}};function nr(e,n){let t=new Map;if(e.features.some(a=>a.properties.night_use!==void 0)){for(let[a,l]of e.features.entries()){let u=Xt[String(l.properties.night_use??"")];u&&t.set(a,u)}return t}let i=n.places;if(!i||i.features.length===0)return t;let o=Yt/n.tileMetres*e.extent,r=[];for(let[a,l]of e.features.entries()){if(l.type!=="Polygon")continue;let u=l.properties.hide_3d;if(u===!0||u===1||u==="1"||u==="true")continue;let c=[1/0,1/0,-1/0,-1/0];for(let f of l.geometry)for(let d=0;d+1<f.length;d+=2)c[0]=Math.min(c[0],f[d]),c[1]=Math.min(c[1],f[d+1]),c[2]=Math.max(c[2],f[d]),c[3]=Math.max(c[3],f[d+1]);r.push({index:a,rings:l.geometry,box:c})}let s=e.extent/i.extent;for(let a of i.features){if(a.type!=="Point")continue;let l=a.properties,u=bn[String(l.type??"")]??bn[String(l.subclass??"")]??bn[String(l.class??"")];if(u)for(let c of a.geometry)for(let f=0;f+1<c.length;f+=2){let d=c[f]*s,g=c[f+1]*s,m,p,h=o;for(let F of r){let[k,M,B,U]=F.box;if(d<k-o||d>B+o||g<M-o||g>U+o)continue;let E=!1;for(let C of F.rings)for(let I=0,N=C.length-2;I+1<C.length;N=I,I+=2){let K=C[N],$=C[N+1],D=C[I],Y=C[I+1];Y>g!=$>g&&d<(K-D)*(g-Y)/($-Y)+D&&(E=!E);let w=D-K,y=Y-$,b=w*w+y*y,x=b?Math.min(1,Math.max(0,((d-K)*w+(g-$)*y)/b)):0,T=Math.hypot(d-K-x*w,g-$-x*y);T<h&&(h=T,p=F.index)}if(E){m=F.index;break}}let _=m??p;_!==void 0&&t.set(_,Math.max(t.get(_)??0,u))}}return t}function Re(e){return Math.min(ue,Math.max(0,Math.round(e)))}function Jn(e){let n=Number(e);return Number.isFinite(n)&&n>0?n:void 0}function tr(e,n){let t=[],i;for(let o of e){let r=[];for(let a=0;a+1<o.length;a+=2){let l=o[a]*n,u=o[a+1]*n;r.length&&l===r.at(-2)&&u===r.at(-1)||r.push(l,u)}if(r.length>=6&&r[0]===r.at(-2)&&r[1]===r.at(-1)&&(r.length-=2),r.length<6)continue;let s=Math.sign(qe(r));s&&(i??=s,s===i||t.length===0?t.push([r]):t.at(-1).push(r))}return t}function qe(e){let n=0,t=e.length/2;for(let i=0;i<t;i+=1){let o=(i+1)%t;n+=e[i*2]*e[o*2+1]-e[o*2]*e[i*2+1]}return n}function rr(e){let n=0,t=0,i=e.length/2;for(let o=0;o<i;o+=1)n+=e[o*2],t+=e[o*2+1];return[n/i,t/i]}function xn(e,n){return e<=0||n<=0||e>=ue||n>=ue}function we(e,n,t,i){let o=ue;return e<=0&&t<=0||e>=o&&t>=o||n<=0&&i<=0||n>=o&&i>=o}function or(e){let n=ue,t=[...e],i=[[0,0,o=>o>=0],[0,n,o=>o<=n],[1,0,o=>o>=0],[1,n,o=>o<=n]];for(let[o,r,s]of i){let a=[],l=t.length/2;for(let u=0;u<l;u+=1){let c=[t[u*2],t[u*2+1]],f=[t[(u+1)%l*2],t[(u+1)%l*2+1]],d=s(c[o]),g=s(f[o]);if(d&&a.push(c[0],c[1]),d!==g){let m=(r-c[o])/(f[o]-c[o]);a.push(c[0]+(f[0]-c[0])*m,c[1]+(f[1]-c[1])*m)}}if(t=a,t.length<6)return[]}return t}function gn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var Qn=`\nin float v_haze_depth;\nuniform vec3 u_haze_colour;\nuniform vec3 u_haze; // strength; the view depths where the haze starts and is complete\n\nfloat hazeOf() {\n return u_haze.x > 0.0 ? u_haze.x * smoothstep(u_haze.y, u_haze.z, v_haze_depth) : 0.0;\n}\n\nvec3 hazed(vec3 colour) {\n return mix(colour, u_haze_colour, hazeOf());\n}`;function qn(e){let n=(e.indices.length-e.wallsFrom)/6,t=new Uint8Array(n*16);for(let i=0;i<n;i+=1){let o=e.wallsFrom+i*6,r=e.indices[o]*pe,s=e.indices[o+1]*pe;t.set(e.vertices.subarray(r,r+4),i*16),t.set(e.vertices.subarray(s,s+4),i*16+4),t.set(e.vertices.subarray(r+4,r+8),i*16+8),t[i*16+12]=e.vertices[r+14],t[i*16+13]=e.vertices[r+27]}return t}var Kr=`#version 300 es\nprecision highp float;\nuniform highp sampler2D u_contact;\n${Qn}\nout vec4 fragColor;\nvoid main() {\n float shade = mix(texelFetch(u_contact, ivec2(gl_FragCoord.xy), 0).r, 1.0, hazeOf());\n fragColor = vec4(vec3(shade), 1.0);\n}`;function et(e){let n=e.vertices.length/pe;return{mesh:{...e.groups?{groups:e.groups}:{},wallsFrom:e.wallsFrom,top:e.top,features:e.features,vertexCount:n,indexCount:e.indices.length},data:{vertices:e.vertices,indices:n<=65536?Uint16Array.from(e.indices):e.indices,contact:qn(e)}}}function nt({data:e}){return[e.vertices.buffer,e.indices.buffer,e.contact.buffer]}function Tn(e){let n=ir(e);return n?[Math.min(1,Math.max(0,n[0]/255)),Math.min(1,Math.max(0,n[1]/255)),Math.min(1,Math.max(0,n[2]/255)),Math.min(1,Math.max(0,n[3]))]:null}function ir(e){let n=e.trim().toLowerCase(),t=/^#([\\da-f]{3,8})$/u.exec(n)?.[1];if(t&&[3,4,6,8].includes(t.length)){let _=(t.length<=4?[...t].map(F=>F+F).join(""):t).match(/../gu).map(F=>Number.parseInt(F,16));return[_[0],_[1],_[2],_.length>3?_[3]/255:1]}let i=/^(rgba?|hsla?)\\(([^)]+)\\)$/u.exec(n);if(!i)return null;let o=i[2].split(/[\\s,/]+/u).filter(Boolean);if(o.length<3||o.length>4)return null;let r=o[3]===void 0?1:en(o[3],1);if(i[1].startsWith("rgb")){let[h,_,F]=o.slice(0,3).map(k=>en(k,255));return[h,_,F,r].some(k=>k===null)?null:[h,_,F,r]}let s=Number.parseFloat(o[0]),a=en(o[1],1),l=en(o[2],1);if(!Number.isFinite(s)||a===null||l===null||r===null)return null;let u=(1-Math.abs(2*l-1))*a,c=(s%360+360)%360/60,f=u*(1-Math.abs(c%2-1)),[d,g,m]=c<1?[u,f,0]:c<2?[f,u,0]:c<3?[0,u,f]:c<4?[0,f,u]:c<5?[f,0,u]:[u,0,f],p=l-u/2;return[(d+p)*255,(g+p)*255,(m+p)*255,r]}function en(e,n){let t=e.endsWith("%"),i=Number.parseFloat(e);return Number.isFinite(i)?t?i/100*n:i:null}var fe=8192,Mn=12,sr={primary:{spacing:30,kerb:10},secondary:{spacing:32,kerb:8.5},tertiary:{spacing:34,kerb:7},minor:{spacing:36,kerb:5.5},pedestrian:{spacing:26,kerb:3}},ar={motorway:{spacing:45,kerb:14},trunk:{spacing:40,kerb:12},service:{spacing:38,kerb:4},path:{spacing:28,kerb:1.5},track:{spacing:40,kerb:2.5}},lr={spacing:30,kerb:0},ur=12,cr=18,fr=9,dr={sodium:"#ffa64d",high_pressure_sodium:"#ffa64d",low_pressure_sodium:"#ff9326",led:"#fff1db",mercury:"#e3ecff",metal_halide:"#f4f4ff",fluorescent:"#eef9ff",electric:"#ffd59a",incandescent:"#ffd59a",halogen:"#ffe3b0",gas:"#ffd28a",gaslight:"#ffd28a"},mr={orange:"#ffa64d",yellow:"#ffd27a",warm_white:"#ffe2b8",white:"#fff4e6",cool_white:"#eef4ff",neutral_white:"#fff8f0",blue:"#b8d0ff",green:"#c4ffd0",red:"#ff9a8a"},hr=new Set(["wall","wall_mounted","wall_bracket"]),pr=new Set(["suspended","cable","catenary","wire"]);function it(e,n){let t=n.estimate??"lit",i=new vn,o=new nn(cr),r=new nn(fr),s=e.streetFurniture;if(s){let m=fe/s.extent;for(let p of s.features){let h=p.properties;if(p.type!=="Point"||h.subclass!=="street_lamp")continue;let _=yr(h),F=br(h),k=Math.max(1,Math.min(4,Number(h.light_count)||1)),M=Math.min(24,Math.max(5,_*1.7*(k>1?1.15:1)));for(let B of p.geometry)for(let U=0;U+1<B.length;U+=2){let E=B[U]*m,C=B[U+1]*m;if(!rt(E,C))continue;i.write(E,C,_,M,!0,F);let I=ot(E,C,n.tileMetres);o.add(...I),r.add(...I)}}}let a=i.count;if(t==="none")return i.done(a);let l=e.transportation,u=0;if(l){let m=n.tileMetres/l.extent;for(let p of l.features)if(!(p.type!=="LineString"||!tt(p.properties,"streets")))for(let h of p.geometry)u+=gr(h,l.extent)*m}let c=u>0&&a/(u/1e3)>=ur,f=t==="streets"&&!c?"streets":"lit",d=(m,p,h,_)=>{let F=fe/m.extent,k=[];for(let N=0;N+1<p.length;N+=2)k.push(p[N]*F,p[N+1]*F);let M=n.tileMetres/fe,B=h.kerb*.45/M,U=Rn(k[0]*.013+k[1]*.029+_)*h.spacing,E=0,C=U,I=Rn(k[0]+k[1]*3.1)<.5?1:-1;for(let N=2;N<k.length;N+=2){let K=k[N-2],$=k[N-1],D=k[N],Y=k[N+1],w=Math.hypot(D-K,Y-$)*M;if(w!==0){for(;C<=E+w;){let y=(C-E)/w,b=-(Y-$)/(w/M)*I,x=(D-K)/(w/M)*I,T=K+(D-K)*y+b*B,A=$+(Y-$)*y+x*B;if(C+=h.kerb>0?h.spacing/2:h.spacing,h.kerb>0&&(I=-I),!rt(T,A))continue;let v=ot(T,A,n.tileMetres);o.near(...v)||r.near(...v)||(r.add(...v),i.write(T,A,7,15,!1))}E+=w}}};if(l)for(let m of l.features){if(m.type!=="LineString")continue;let p=tt(m.properties,f);if(p)for(let h of m.geometry)d(l,h,p,1)}let g=e.sidewalks;if(g){for(let m of g.features)if(!(m.type==="Point"||!kn(m.properties.lit)))for(let p of m.geometry)d(g,p,lr,2)}return i.done(a)}function tt(e,n){if(e.brunnel==="tunnel"||e.covered===!0)return;let t=e.lit;if(t===!1||t==="no")return;let i=String(e.class??""),o=String(e.subclass??""),r=i==="path"&&(o==="pedestrian"||o==="living_street")?"pedestrian":i,s=sr[r];if(s&&(n==="streets"||kn(t)))return s;let a=ar[r];if(a&&kn(t))return a}function kn(e){return e===!0||e==="yes"||e===1||e==="1"||e==="true"}function yr(e){let n=Number(e.height);if(Number.isFinite(n)&&n>=.5&&n<=40)return n;let t=String(e.lamp_mount??"").toLowerCase();return hr.has(t)?4.5:pr.has(t)?7.5:7}function br(e){let n=e.light_colour??e["light:colour"];if(typeof n=="string"&&n){let r=n.toLowerCase().replaceAll(" ","_"),s=Tn(mr[r]??n);if(s)return[s[0],s[1],s[2]]}let t=String(e.lamp_type??"").toLowerCase().replaceAll("-","_").replaceAll(" ","_"),i=dr[t];if(!i)return;let o=Tn(i);return[o[0],o[1],o[2]]}function rt(e,n){return e>=0&&n>=0&&e<fe&&n<fe}function ot(e,n,t){return[e/fe*t,n/fe*t]}function gr(e,n){let t=0;for(let i=2;i+1<e.length;i+=2){let o=(e[i-2]+e[i])/2,r=(e[i-1]+e[i+1])/2;o<0||r<0||o>=n||r>=n||(t+=Math.hypot(e[i]-e[i-2],e[i+1]-e[i-1]))}return t}var nn=class{constructor(n){this.size=n}size;#e=new Map;add(n,t){let i=`${Math.floor(n/this.size)}/${Math.floor(t/this.size)}`,o=this.#e.get(i);o?o.push([n,t]):this.#e.set(i,[[n,t]])}near(n,t){let i=Math.floor(n/this.size),o=Math.floor(t/this.size);for(let r=-1;r<=1;r+=1)for(let s=-1;s<=1;s+=1)for(let[a,l]of this.#e.get(`${i+r}/${o+s}`)??[])if(Math.hypot(a-n,l-t)<this.size)return!0;return!1}},vn=class{#e=new ArrayBuffer(256*Mn);#n=new DataView(this.#e);count=0;write(n,t,i,o,r,s){let a=Mn;if((this.count+1)*a>this.#e.byteLength){let c=new ArrayBuffer(this.#e.byteLength*2);new Uint8Array(c).set(new Uint8Array(this.#e)),this.#e=c,this.#n=new DataView(c)}let l=this.#n,u=this.count*a;l.setUint16(u,Math.min(fe,Math.max(0,Math.round(n))),!0),l.setUint16(u+2,Math.min(fe,Math.max(0,Math.round(t))),!0),l.setUint16(u+4,Math.min(65535,Math.round(i*10)),!0),l.setUint8(u+6,Math.min(255,Math.round(o))),l.setUint8(u+7,(r?1:0)|(s?2:0)),l.setUint8(u+8,Math.round((s?.[0]??0)*255)),l.setUint8(u+9,Math.round((s?.[1]??0)*255)),l.setUint8(u+10,Math.round((s?.[2]??0)*255)),l.setUint8(u+11,Math.round(Rn(n*.0731+t*.19137)*255)),this.count+=1}done(n){if(this.count!==0)return{lamps:new Uint8Array(this.#e.slice(0,this.count*Mn)),mapped:n,estimated:this.count-n}}};function Rn(e){let n=Math.sin(e*12.9898+78.233)*43758.5453;return n-Math.floor(n)}var oo=Object.freeze({source:"tileflow",layers:Object.freeze({streetFurniture:"street_furniture",transportation:"transportation",sidewalk:"sidewalk"}),estimate:"lit",color:"#ffcf8f",intensity:1});var Me=["round","open","tall","conifer","columnar","palm"];var ut=Object.freeze({height:"height",diameterCrown:"diameter_crown",circumference:"circumference",genus:"genus",species:"species",leafType:"leaf_type",taxon:"taxon",canopyRank:"rank",canopyClearance:"clearance_px_z15",canopyCover:"cover_pct",canopyHeight:"height_m",subclass:"subclass",hedge:"hedge"}),Sn=Object.freeze({round:1,open:1,tall:1}),tn=16,q=8192,rn=16,st={round:{height:[6,12],crown:[.66,.9]},open:{height:[5,10],crown:[.8,1.05]},tall:{height:[9,17],crown:[.48,.68]},conifer:{height:[7,16],crown:[.46,.66]},columnar:{height:[9,18],crown:[.22,.36]},palm:{height:[12,20],crown:[.42,.55]}};var on=[2,45],_n=[1,25],wr=1.2,xr=1.5,Tr=1.3,Mr=1,kr=[.3,10],vr=new Set(["acoelorrhaphe","adonidia","archontophoenix","areca","arecastrum","bismarckia","brahea","butia","caryota","chamaedorea","chamaerops","coccothrinax","cocos","dypsis","elaeis","howea","jubaea","licuala","livistona","phoenix","pritchardia","ptychosperma","rhapis","roystonea","sabal","serenoa","syagrus","thrinax","trachycarpus","veitchia","washingtonia","wodyetia"]),Rr=new Set(["cupressus","calocedrus","thuja"]),_r=new Set(["abies","araucaria","cedrus","cryptomeria","juniperus","larix","metasequoia","picea","pinus","pseudotsuga","sequoia","sequoiadendron","taxodium","taxus","tsuga"]),at=Object.freeze({...Object.fromEntries(["acacia","albizia","arbutus","bursera","ceratonia","delonix","ficus","gleditsia","jacaranda","olea","quercus","robinia","schinus","sophora","styphnolobium","tamarix"].map(e=>[e,"open"])),...Object.fromEntries(["betula","celtis","fraxinus","ginkgo","liquidambar","liriodendron","magnolia","platanus","populus","pyrus","ulmus","zelkova"].map(e=>[e,"tall"])),...Object.fromEntries(["acer","aesculus","carpinus","castanea","catalpa","cercis","citrus","fagus","lagerstroemia","malus","melia","morus","prunus","sorbus","tilia"].map(e=>[e,"round"]))});function lt(e,n={}){let t={...ut,...n},i=String(e[t.leafType]??"").toLowerCase(),o=String(e[t.taxon]??"").toLowerCase(),r=Fn(e[t.genus])??Fn(e[t.species])??(o.endsWith("aceae")?void 0:Fn(e[t.taxon]));if(i.includes("palm")||o.includes("arecaceae")||r&&vr.has(r))return"palm";if(o.includes("cupressaceae")&&!r||o.includes("pinaceae"))return"conifer";if(r&&Rr.has(r))return"columnar";if(i.includes("needle")||r&&_r.has(r))return"conifer";if(r&&at[r])return at[r];if(i.includes("broad"))return"broadleaf"}function Fn(e){return typeof e!="string"?void 0:e.trim().split(/\\s+/u)[0]?.toLowerCase()||void 0}function ct(e,n){let t={...ut,...n.fields},i=n.unknownForms??Sn,o=n.regions??[],{tile:r,tileMetres:s}=n,a=s/2**(15-r.z)/512,l=[],u=0,c=0,f=(w,y)=>{if(o.length===0)return i;let[b,x]=Ar(r,w/q,y/q);for(let T of o){let[A,v,L,O]=T.bounds;if(x>=v&&x<=O&&(A<=L?b>=A&&b<=L:b>=A||b<=L))return T.unknownForms}return i},d=(w,y,b,x)=>{let T=st[w],A=An(T.crown,ee(y,2)),v=b,L=x;return v===void 0&&L===void 0&&(v=An(T.height,ee(y,1))),v===void 0&&(v=L/A),L===void 0&&(L=v*A),{height:Te(v,on),crown:Te(L,_n)}},g=(w,y,b,x,T,A)=>{let v=ze(r.x*q+w,r.y*q+y,7),L=b===void 0?sn(f(w,y),ee(v,3)):b==="broadleaf"?sn(Fr(f(w,y)),ee(v,3)):b,O=x===void 0&&T===void 0&&A!==void 0?d(L,v,An(st[L].height,Te(A/3,[0,1]))):d(L,v,x,T);l.push({x:w,y,...O,turn:ee(v,4),shade:ee(v,5),form:Me.indexOf(L),rank:Math.floor(ee(v,6)*rn),seed:ee(v,7),canopy:0}),u+=1},m=e.trees;if(m){let w=q/m.extent;for(let y of m.features){if(y.type!=="Point")continue;let b=y.properties,x=lt(b,t),T=xe(b[t.height],on),A=xe(b[t.diameterCrown],_n),v=xe(b[t.circumference],[.1,12]);for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];V<0||R<0||V>=m.extent||R>=m.extent||g(V*w,R*w,x,T,A,v)}}}let p=e.trees;if(p){let w=q/p.extent,y=(n.rowSpacing??8)/(s/p.extent);for(let b of p.features){if(b.type!=="LineString")continue;let x=b.properties,T=lt(x,t),A=xe(x[t.height],on),v=xe(x[t.diameterCrown],_n);for(let L of b.geometry){let O=y/2,V=0;for(let R=0;R+3<L.length;R+=2){let[S,z,P,Z]=[L[R],L[R+1],L[R+2],L[R+3]],j=Math.hypot(P-S,Z-z);for(;O<=V+j;){let G=j>0?(O-V)/j:0,W=S+(P-S)*G,se=z+(Z-z)*G;W>=0&&se>=0&&W<p.extent&&se<p.extent&&g(W*w,se*w,T,A,v,void 0),O+=y}V+=j}}}}let h=e.canopy;if(h){let w=q/h.extent;for(let y of h.features){if(y.type!=="Point")continue;let b=y.properties,x=Te(Math.floor(Number(b[t.canopyRank]??8)),[0,rn-1]),T=Math.max(4,Number(b[t.canopyClearance]??8))*a,A=Number(b[t.canopyCover]??30),v=A>=60?3:A>=30?2:1;for(let L of y.geometry)for(let O=0;O+1<L.length;O+=2){let V=L[O],R=L[O+1];if(V<0||R<0||V>=h.extent||R>=h.extent)continue;let S=V*w,z=R*w,P=ze(r.x*q+S,r.y*q+z,11),Z=f(S,z),j=xe(b[t.canopyHeight],on),G=Te(Math.min(T*(v===1?1.3:.95),11)*(.85+ee(P,1)*.25),[3,12]),W=Math.max(0,Math.min(G*.5,T-G/2)),se=ee(P,2)*Math.PI*2;for(let ae=0;ae<v;ae+=1){let H=ze(P,ae,13),J=se+ae*Math.PI*2/v,re=v===1?W*.3*ee(H,1):W,ne=S+Math.cos(J)*re/(s/q),te=z+Math.sin(J)*re/(s/q);if(ne<0||te<0||ne>=q||te>=q)continue;let le=sn(Z,ee(H,3)),de=G*(.85+ee(H,2)*.3),me=j===void 0?void 0:j*(.85+ee(H,6)*.25),ce=d(le,H,me,le==="palm"?void 0:de);l.push({x:ne,y:te,...ce,turn:ee(H,4),shade:ee(H,5),form:Me.indexOf(le),rank:x,seed:ee(H,7),canopy:1}),c+=1}}}}let _=[],F=e.hedges;if(F){let w=q/F.extent,y=wr/(s/F.extent);for(let b of F.features){if(b.type==="Point"||b.properties[t.subclass]!=="hedge")continue;let x=b.properties[t.hedge]==="hedge_bank"?Mr:0,T=(xe(b.properties[t.height],kr)??Tr)+x;for(let A of b.geometry){let v=y/2,L=0;for(let O=0;O+3<A.length;O+=2){let[V,R,S,z]=[A[O],A[O+1],A[O+2],A[O+3]],P=Math.hypot(S-V,z-R),Z=(Math.atan2(R-z,S-V)/(Math.PI*2)+1)%1;for(;v<=L+P;){let j=P>0?(v-L)/P:0,G=V+(S-V)*j,W=R+(z-R)*j;if(G>=0&&W>=0&&G<F.extent&&W<F.extent){let se=ze(r.x*q+G*w,r.y*q+W*w,17);_.push({x:G*w,y:W*w,height:T,turn:Z,shade:ee(se,5),seed:ee(se,7)})}v+=y}L+=P}}}}let k=w=>Te(Math.floor(n.variants?.[Me[w]]??1),[1,4]),M=w=>Math.min(k(w.form)-1,Math.floor(ee(Math.floor(w.seed*256),9)*k(w.form))),B=l.map(M),U=l.map((w,y)=>y);U.sort((w,y)=>l[w].form-l[y].form||B[w]-B[y]||l[w].rank-l[y].rank);let E=new Uint8Array(l.length*tn),C=new DataView(E.buffer),I=0,N=()=>({start:0,count:0,upTo:new Array(rn).fill(0)}),K=Object.fromEntries(Me.map((w,y)=>[w,{...N(),variants:Array.from({length:k(y)},N)}])),$=(w,y,b)=>{w.count===0&&(w.start=y),w.count+=1;for(let x=b;x<rn;x+=1)w.upTo[x]+=1};U.forEach((w,y)=>{let b=l[w],x=y*tn;C.setUint16(x,Math.min(q-1,Math.round(b.x)),!0),C.setUint16(x+2,Math.min(q-1,Math.round(b.y)),!0),C.setUint16(x+4,Math.round(b.height*10),!0),C.setUint16(x+6,Math.round(b.crown*10),!0),E[x+8]=Math.floor(b.turn*256)&255,E[x+9]=Math.floor(b.shade*256)&255,E[x+10]=b.form,E[x+11]=b.rank,E[x+12]=Math.floor(b.seed*256)&255,E[x+13]=b.canopy,E[x+14]=B[w],I=Math.max(I,b.height);let T=K[Me[b.form]];$(T,y,b.rank),$(T.variants[B[w]],y,b.rank)});let D=new Uint8Array(_.length*tn),Y=new DataView(D.buffer);return _.forEach((w,y)=>{let b=y*tn;Y.setUint16(b,Math.min(q-1,Math.round(w.x)),!0),Y.setUint16(b+2,Math.min(q-1,Math.round(w.y)),!0),Y.setUint16(b+4,Math.round(w.height*10),!0),Y.setUint16(b+6,Math.round(xr*10),!0),D[b+8]=Math.round(w.turn*256)&255,D[b+9]=Math.floor(w.shade*256)&255,D[b+12]=Math.floor(w.seed*256)&255,I=Math.max(I,w.height)}),{trees:E,forms:K,hedges:D,tallest:I,mapped:u,canopy:c}}function Fr(e){let n={round:e.round??0,open:e.open??0,tall:e.tall??0};return n.round+n.open+n.tall>0?n:Sn}function sn(e,n){let t=0;for(let o of Me)t+=Math.max(0,e[o]??0);if(t<=0)return sn(Sn,n);let i=n*t;for(let o of Me){let r=Math.max(0,e[o]??0);if(i<r)return o;i-=r}return"round"}function xe(e,n){let t=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):NaN;return Number.isFinite(t)&&t>0?Te(t,n):void 0}function Te(e,[n,t]){return Math.min(t,Math.max(n,e))}function An([e,n],t){return e+(n-e)*t}function Ar(e,n,t){let i=2**e.z,o=(e.x+n)/i*360-180,r=Math.atan(Math.sinh(Math.PI*(1-2*(e.y+t)/i)))*180/Math.PI;return[o,r]}function ze(e,n,t){let i=(Math.imul(Math.floor(e)|0,668265261)^Math.imul(Math.floor(n)|0,374761393)^Math.imul(t,2654435761))>>>0;return i=Math.imul(i^i>>>15,2246822507)>>>0,i=Math.imul(i^i>>>13,3266489909)>>>0,(i^i>>>16)>>>0}function ee(e,n){return ze(e,n,20973)/4294967296}var Sr=[void 0,"Point","LineString","Polygon"];function ft(e,n={}){let t=n.layers?new Set(n.layers):void 0,i={},o=new Bn(e,0,e.length);for(;o.more();){let[r,s]=o.tag();if(r!==3){o.skip(s);continue}let a=o.message(),l=Lr(a,t);l&&!(l.name in i)&&(i[l.name]=l.layer)}return i}function Lr(e,n){let t,i=4096,o=[],r=[],s=[];for(;e.more();){let[a,l]=e.tag();if(a===1?t=e.string():a===2?s.push(e.message()):a===3?o.push(e.string()):a===4?r.push(Ur(e.message())):a===5?i=e.varint():e.skip(l),t!==void 0&&n&&!n.has(t))return}if(!(t===void 0||n&&!n.has(t)))return{name:t,layer:Object.freeze({extent:i,features:Object.freeze(s.flatMap(a=>{let l=Br(a,o,r);return l?[l]:[]}))})}}function Br(e,n,t){let i,o,r={},s=[];for(;e.more();){let[a,l]=e.tag();if(a===1)i=e.varint();else if(a===2){let u=e.packed();for(let c=0;c+1<u.length;c+=2){let f=n[u[c]],d=t[u[c+1]];f!==void 0&&d!==void 0&&(r[f]=d)}}else a===3?o=Sr[e.varint()]:a===4?s=e.packed():e.skip(l)}if(o)return Object.freeze({...i===void 0?{}:{id:i},type:o,properties:Object.freeze(r),geometry:Object.freeze(Or(s,o))})}function Or(e,n){let t=[],i,o=0,r=0,s=0;for(;s<e.length;){let a=e[s++],l=a&7,u=a>>>3;if(l===7){i&&i.length>=2&&i.push(i[0],i[1]);continue}if(l!==1&&l!==2)throw new Error(`Unknown geometry command ${l} in vector tile.`);if(s+u*2>e.length)throw new Error("Truncated vector tile geometry.");for(let c=0;c<u;c+=1){if(o+=Ln(e[s++]),r+=Ln(e[s++]),l===1&&(n!=="Point"||c===0)&&t.push(i=[]),!i)throw new Error("Vector tile geometry draws a line before moving to its start.");i.push(o,r)}}return t}var Ln=e=>e%2===1?-(e+1)/2:e/2;function Ur(e){let n="";for(;e.more();){let[t,i]=e.tag();t===1?n=e.string():t===2?n=e.float():t===3?n=e.double():t===4?n=e.varint(!0):t===5?n=e.varint():t===6?n=Ln(e.varint()):t===7?n=e.varint()!==0:e.skip(i)}return n}var Cr=new TextDecoder,Bn=class e{constructor(n,t,i){this.bytes=n;this.end=i;this.position=t,this.view=new DataView(n.buffer,n.byteOffset,n.byteLength)}bytes;end;position;view;more(){return this.position<this.end}tag(){let n=this.varint();return[Math.floor(n/8),n&7]}varint(n=!1){let t=0,i=0;for(let o=0;o<10;o+=1){if(this.position>=this.end)throw new Error("Truncated vector tile.");let r=this.bytes[this.position++];if(o<4?t|=(r&127)<<o*7:o===4?(t|=(r&15)<<28,i=(r&112)>>4):o<9?i|=(r&127)<<(o-5)*7+3:i|=(r&1)<<31,r<128)return n?i*4294967296+(t>>>0):(i>>>0)*4294967296+(t>>>0)}throw new Error("Invalid varint in vector tile.")}span(){let n=this.varint(),t=this.position;if(t+n>this.end)throw new Error("Truncated vector tile.");return this.position=t+n,[t,t+n]}message(){let[n,t]=this.span();return new e(this.bytes,n,t)}string(){let[n,t]=this.span();return Cr.decode(this.bytes.subarray(n,t))}packed(){let[n,t]=this.span(),i=new e(this.bytes,n,t),o=[];for(;i.more();)o.push(i.varint());return o}float(){if(this.position+4>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat32(this.position,!0);return this.position+=4,n}double(){if(this.position+8>this.end)throw new Error("Truncated vector tile.");let n=this.view.getFloat64(this.position,!0);return this.position+=8,n}skip(n){if(n===0)this.varint();else if(n===1)this.position+=8;else if(n===2)this.span();else if(n===5)this.position+=4;else throw new Error(`Unsupported protocol buffer wire type ${n} in vector tile.`);if(this.position>this.end)throw new Error("Truncated vector tile.")}};function dt(e){return Object.values(e.layers).filter(n=>typeof n=="string")}function mt(e,n){if(e.kind==="buildings"){let r=n(e.layers.building);if(!r)return;let s=n(e.layers.places),a=Kn(r,{...e.options,...s?{places:s}:{}});return a&&et(a)}if(e.kind==="trees"){let r=n(e.layers.tree),s=n(e.layers.canopy),a=n(e.layers.hedge);if(!r&&!s&&!a)return;let l=ct({...r?{trees:r}:{},...s?{canopy:s}:{},...a?{hedges:a}:{}},e.options);return l.trees.length>0||l.hedges.length>0?l:void 0}let t=n(e.layers.streetFurniture),i=n(e.layers.transportation),o=n(e.layers.sidewalk);return it({...t?{streetFurniture:t}:{},...i?{transportation:i}:{},...o?{sidewalks:o}:{}},e.options)}function ht(e,n){if(!n)return[];if(e==="buildings")return nt(n);if(e==="trees"){let{trees:t,hedges:i}=n;return[t.buffer,i.buffer].filter((o,r,s)=>s.indexOf(o)===r)}return[n.lamps.buffer]}function pt(e=16){let n=new Map;return{read(t,i,o){let r=n.get(t);for(n.delete(t),r??={bytes:i,layers:new Map},n.set(t,r);n.size>e;)n.delete(n.keys().next().value);let s=o.filter(l=>!r.layers.has(l));if(s.length>0){let l=ft(r.bytes,{layers:s});for(let u of s)r.layers.set(u,l[u])}let a=r.layers;return l=>l===void 0?void 0:a.get(l)}}}var On=globalThis,Pr=pt();On.onmessage=({data:{url:e,bytes:n,task:t}})=>{try{let i=mt(t,Pr.read(e,n,dt(t)));On.postMessage({result:i},ht(t.kind,i))}catch(i){On.postMessage({error:String(i)})}};})();\n'], { type: "text/javascript" })
|
|
9653
10051
|
);
|
|
9654
10052
|
try {
|
|
9655
10053
|
return new Worker(url, { name: "tileflow-tiles" });
|
|
@@ -14185,6 +14583,7 @@ function createTileflowBuildings3D(options) {
|
|
|
14185
14583
|
const nightLight2 = mixed2((entry) => entry.nightLight);
|
|
14186
14584
|
const architectural = floodLightNow();
|
|
14187
14585
|
const edges = mixed2((entry) => entry.edges);
|
|
14586
|
+
const surfaces = design().surfaces;
|
|
14188
14587
|
const { occlusion: occlusionOn, windows: windowsOn } = design();
|
|
14189
14588
|
const now = performance.now();
|
|
14190
14589
|
const appearing = standing.filter((entry) => appearanceOf(entry, now) < 1);
|
|
@@ -14210,6 +14609,24 @@ function createTileflowBuildings3D(options) {
|
|
|
14210
14609
|
context.uniform1f(u.u_corner, tileflowBuildingOcclusion.corner);
|
|
14211
14610
|
context.uniform1f(u.u_night, light.night);
|
|
14212
14611
|
context.uniform1f(u.u_windows, windowsOn ? 1 : 0);
|
|
14612
|
+
context.uniform4f(
|
|
14613
|
+
u.u_surface_walls,
|
|
14614
|
+
surfaces?.walls?.size[0] ?? 6,
|
|
14615
|
+
surfaces?.walls?.size[1] ?? 3,
|
|
14616
|
+
surfaces?.walls?.jointWidth ?? 0.12,
|
|
14617
|
+
mixed2((entry) => entry.surfaces?.walls?.contrast ?? 0)
|
|
14618
|
+
);
|
|
14619
|
+
context.uniform3f(
|
|
14620
|
+
u.u_surface_roof,
|
|
14621
|
+
surfaces?.roof?.size ?? 8,
|
|
14622
|
+
surfaces?.roof?.jointWidth ?? 0.12,
|
|
14623
|
+
mixed2((entry) => entry.surfaces?.roof?.contrast ?? 0)
|
|
14624
|
+
);
|
|
14625
|
+
context.uniform2f(
|
|
14626
|
+
u.u_surface_cornice,
|
|
14627
|
+
surfaces?.cornice?.height ?? 0.6,
|
|
14628
|
+
mixed2((entry) => entry.surfaces?.cornice?.contrast ?? 0)
|
|
14629
|
+
);
|
|
14213
14630
|
context.uniform1f(u.u_flood, light.night * nightLight2);
|
|
14214
14631
|
context.uniform3fv(u.u_flood_colour, flood.colour);
|
|
14215
14632
|
context.uniform1f(u.u_architectural_intensity, architectural.intensity);
|
|
@@ -14252,6 +14669,10 @@ function createTileflowBuildings3D(options) {
|
|
|
14252
14669
|
if (!ranges.length) continue;
|
|
14253
14670
|
project(context, buildings, args, x3, y2);
|
|
14254
14671
|
context.uniform2f(u.u_offset, ...placed2(x3, y2).offset);
|
|
14672
|
+
context.uniform3f(
|
|
14673
|
+
u.u_surface_tile,
|
|
14674
|
+
...tileflowBuildingSurfaceTile(x3, y2, camera.zoom, surfaces?.roof?.size ?? 8)
|
|
14675
|
+
);
|
|
14255
14676
|
context.uniform4f(u.u_ring ?? null, ...ringIn(x3, y2));
|
|
14256
14677
|
context.uniform2f(u.u_ring_ahead ?? null, ...ahead);
|
|
14257
14678
|
const palette = themes ? paletteOf(context, entry, themes.themes) : void 0;
|
|
@@ -15883,6 +16304,7 @@ var placement2 = `
|
|
|
15883
16304
|
uniform float u_scale;
|
|
15884
16305
|
uniform float u_metres; // metres per tile unit
|
|
15885
16306
|
uniform vec2 u_offset; // this tile's corner from the scene's origin, in tile units
|
|
16307
|
+
uniform float u_minimum_height; // optional visual height floor, in metres
|
|
15886
16308
|
uniform vec2 u_size_scale; // the map's height and crown scales, for this form
|
|
15887
16309
|
uniform float u_round; // how far normals turn from the facets to the round shape, by finish
|
|
15888
16310
|
|
|
@@ -15898,17 +16320,20 @@ vec2 turned(vec2 v) {
|
|
|
15898
16320
|
return vec2(v.x * c - v.y * s, v.x * s + v.y * c);
|
|
15899
16321
|
}
|
|
15900
16322
|
|
|
16323
|
+
vec2 displaySize() {
|
|
16324
|
+
vec2 size = a_tree_size * 0.1 * u_size_scale;
|
|
16325
|
+
return size * max(1.0, u_minimum_height / max(size.x, 0.001));
|
|
16326
|
+
}
|
|
16327
|
+
|
|
15901
16328
|
vec3 standing(float growth) {
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
return vec3(turned(a_vertex.xy * crown), a_vertex.z * height) * growth;
|
|
16329
|
+
vec2 size = displaySize();
|
|
16330
|
+
return vec3(turned(a_vertex.xy * size.y), a_vertex.z * size.x) * growth;
|
|
15905
16331
|
}
|
|
15906
16332
|
|
|
15907
16333
|
vec3 normalOf() {
|
|
15908
|
-
|
|
15909
|
-
float crown = max(a_tree_size.y * 0.1 * u_size_scale.y, 0.1);
|
|
16334
|
+
vec2 size = max(displaySize(), vec2(0.1));
|
|
15910
16335
|
vec3 blended = normalize(mix(a_normal, a_round, u_round));
|
|
15911
|
-
vec3 n = normalize(vec3(blended.xy /
|
|
16336
|
+
vec3 n = normalize(vec3(blended.xy / size.y, blended.z / size.x));
|
|
15912
16337
|
return vec3(turned(n.xy), n.z);
|
|
15913
16338
|
}
|
|
15914
16339
|
|
|
@@ -15998,6 +16423,7 @@ uniform float u_night;
|
|
|
15998
16423
|
uniform float u_fade; // how far the layer has faded in, from 0 to 1
|
|
15999
16424
|
uniform float u_toon; // 1 for light in bands, as a drawing has it
|
|
16000
16425
|
uniform vec3 u_bark;
|
|
16426
|
+
uniform float u_material_variation;
|
|
16001
16427
|
uniform vec3 u_leaves[4]; // the form's colours, sunlit
|
|
16002
16428
|
uniform float u_leaf_count;
|
|
16003
16429
|
out vec4 fragColor;
|
|
@@ -16008,7 +16434,7 @@ ${treeDither}
|
|
|
16008
16434
|
|
|
16009
16435
|
vec3 leafColour() {
|
|
16010
16436
|
float count = max(u_leaf_count, 1.0);
|
|
16011
|
-
float at = v_shade * (count - 1.0);
|
|
16437
|
+
float at = clamp(v_shade + v_look.y * 0.45 * u_material_variation, 0.0, 1.0) * (count - 1.0);
|
|
16012
16438
|
int low = int(floor(at));
|
|
16013
16439
|
int high = min(low + 1, int(count) - 1);
|
|
16014
16440
|
vec3 a = u_leaves[0];
|
|
@@ -16030,7 +16456,7 @@ void main() {
|
|
|
16030
16456
|
// A palm's stem is paler than bark, ringed light and dark by its leaf scars.
|
|
16031
16457
|
vec3 base = stem
|
|
16032
16458
|
? min(u_bark * 1.45 + 0.06, vec3(1.0)) * (1.0 + v_look.y * 0.12)
|
|
16033
|
-
: bark ? u_bark : leafColour() * (1.0 + v_look.y * 0.09);
|
|
16459
|
+
: bark ? u_bark * (1.0 + ((v_shade - 0.5) * 0.32 + v_look.y * 0.08) * u_material_variation) : leafColour() * (1.0 + v_look.y * 0.09);
|
|
16034
16460
|
float facing = dot(normal, u_sun_dir);
|
|
16035
16461
|
// Leaves let light round and through them: wrapped light on the lit side, a glow against a low sun.
|
|
16036
16462
|
float direct = bark ? max(facing, 0.0) : fronds ? abs(facing) * 0.85 : max((facing + 0.35) / 1.35, 0.0);
|
|
@@ -16438,6 +16864,7 @@ function createTileflowTrees3D(options) {
|
|
|
16438
16864
|
palm: slots(theme?.colors.palm ?? ["#7fa45f"]),
|
|
16439
16865
|
hedge: slots(theme?.colors.hedge ?? ["#5f8a55"]),
|
|
16440
16866
|
size: [[theme?.heightScale ?? 1, theme?.crownScale ?? 1, 0]],
|
|
16867
|
+
materials: [[theme?.minimumHeight ?? 0, theme?.materialVariation ?? 0, 0]],
|
|
16441
16868
|
forms: tileflowTreeForms.map((form) => [
|
|
16442
16869
|
theme?.forms[form]?.heightScale ?? 1,
|
|
16443
16870
|
theme?.forms[form]?.crownScale ?? 1,
|
|
@@ -16457,6 +16884,8 @@ function createTileflowTrees3D(options) {
|
|
|
16457
16884
|
palm: mixList(x3.palm, y2.palm),
|
|
16458
16885
|
hedge: mixList(x3.hedge, y2.hedge),
|
|
16459
16886
|
size,
|
|
16887
|
+
minimumHeight: mixList(x3.materials, y2.materials)[0][0],
|
|
16888
|
+
materialVariation: mixList(x3.materials, y2.materials)[0][1],
|
|
16460
16889
|
/** Each form's height and crown scale: the map's times the form's own. */
|
|
16461
16890
|
sizes: Object.fromEntries(
|
|
16462
16891
|
tileflowTreeForms.map((form, index) => [
|
|
@@ -16504,11 +16933,11 @@ function createTileflowTrees3D(options) {
|
|
|
16504
16933
|
return {
|
|
16505
16934
|
zoom: preferredZoom3,
|
|
16506
16935
|
tiles: [left, top, right, bottom],
|
|
16507
|
-
tallest: tallest *
|
|
16936
|
+
tallest: Math.max(tallest * size[0], colours().minimumHeight) * shown
|
|
16508
16937
|
};
|
|
16509
16938
|
},
|
|
16510
16939
|
// Camera-dependent density, detail and fading also change the trees casting shadows.
|
|
16511
|
-
key: () => `trees:${map.isMoving?.() ? view().movingKey : view().key}:${fadeIn().toFixed(4)}:${visibleScale().toFixed(4)}:${generation}:${programs.depth ? 1 : 0}:${Object.values(
|
|
16940
|
+
key: () => `trees:${colours().minimumHeight.toFixed(3)}:${map.isMoving?.() ? view().movingKey : view().key}:${fadeIn().toFixed(4)}:${visibleScale().toFixed(4)}:${generation}:${programs.depth ? 1 : 0}:${Object.values(
|
|
16512
16941
|
colours().sizes
|
|
16513
16942
|
).flat().map((value) => value.toFixed(3)).join()}:${drawn().map(({ x: x3, y: y2 }) => `${x3}/${y2}`).join(";")}`,
|
|
16514
16943
|
drawDepth(context, frame) {
|
|
@@ -16520,12 +16949,14 @@ function createTileflowTrees3D(options) {
|
|
|
16520
16949
|
context.uniform1f(u.u_metres, frame.metres);
|
|
16521
16950
|
context.uniformMatrix4fv(u.u_light_matrix, false, frame.light.matrix);
|
|
16522
16951
|
const sizes = colours().sizes;
|
|
16952
|
+
const minimumHeight = colours().minimumHeight;
|
|
16523
16953
|
const camera = view();
|
|
16524
16954
|
context.uniform1f(u.u_fade, 1);
|
|
16525
16955
|
context.uniform2fv(u.u_reach, [...camera.reach]);
|
|
16526
16956
|
for (const { x: x3, y: y2, set, value } of drawn()) {
|
|
16527
16957
|
const selection = camera.tile(x3, y2);
|
|
16528
16958
|
if (!selection) continue;
|
|
16959
|
+
context.uniform1f(u.u_minimum_height, minimumHeight);
|
|
16529
16960
|
context.uniform2f(u.u_offset, ...frame.offsetOf({ x: x3, y: y2 }, set.zoom));
|
|
16530
16961
|
context.uniform2f(
|
|
16531
16962
|
u.u_centre,
|
|
@@ -16543,6 +16974,7 @@ function createTileflowTrees3D(options) {
|
|
|
16543
16974
|
});
|
|
16544
16975
|
const hedge = value.gl.hedge;
|
|
16545
16976
|
if (hedge) {
|
|
16977
|
+
context.uniform1f(u.u_minimum_height, 0);
|
|
16546
16978
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
16547
16979
|
context.bindVertexArray(hedge.vao);
|
|
16548
16980
|
context.drawArraysInstanced(
|
|
@@ -16589,6 +17021,7 @@ function createTileflowTrees3D(options) {
|
|
|
16589
17021
|
context.uniform1f(u.u_scale, visibleScale());
|
|
16590
17022
|
context.uniform1f(u.u_metres, metres);
|
|
16591
17023
|
context.uniform1f(u.u_round, finishes[palette2.finish].round);
|
|
17024
|
+
context.uniform1f(u.u_material_variation, palette2.materialVariation);
|
|
16592
17025
|
context.uniform1f(u.u_toon, palette2.finish === "toon" ? 1 : 0);
|
|
16593
17026
|
context.uniform3fv(u.u_sun_dir, [...light.direction]);
|
|
16594
17027
|
context.uniform3fv(u.u_shadow_dir, light.shadowDirection);
|
|
@@ -16625,21 +17058,41 @@ function createTileflowTrees3D(options) {
|
|
|
16625
17058
|
palette2.sizes[form][0],
|
|
16626
17059
|
palette2.sizes[form][1] * drawing.crown
|
|
16627
17060
|
];
|
|
17061
|
+
context.uniform1f(u.u_minimum_height, palette2.minimumHeight);
|
|
16628
17062
|
context.uniform2f(u.u_size_scale, ...size);
|
|
16629
17063
|
context.bindVertexArray(drawing.vao);
|
|
16630
17064
|
context.drawArraysInstanced(context.TRIANGLES, 0, drawing.count, instances);
|
|
16631
17065
|
count += instances;
|
|
16632
|
-
draws.push({
|
|
17066
|
+
draws.push({
|
|
17067
|
+
x: x3,
|
|
17068
|
+
y: y2,
|
|
17069
|
+
offset,
|
|
17070
|
+
leaves,
|
|
17071
|
+
size,
|
|
17072
|
+
minimumHeight: palette2.minimumHeight,
|
|
17073
|
+
instances,
|
|
17074
|
+
drawing
|
|
17075
|
+
});
|
|
16633
17076
|
});
|
|
16634
17077
|
}
|
|
16635
17078
|
const hedge = value.gl.hedge;
|
|
16636
17079
|
if (hedge) {
|
|
16637
17080
|
const instances = value.placement.hedges.length / tileflowTreeBytes;
|
|
16638
17081
|
context.uniform3fv(u.u_leaves, palette2.hedge.flat());
|
|
17082
|
+
context.uniform1f(u.u_minimum_height, 0);
|
|
16639
17083
|
context.uniform2f(u.u_size_scale, 1, 1);
|
|
16640
17084
|
context.bindVertexArray(hedge.vao);
|
|
16641
17085
|
context.drawArraysInstanced(context.TRIANGLES, 0, hedge.count, instances);
|
|
16642
|
-
draws.push({
|
|
17086
|
+
draws.push({
|
|
17087
|
+
x: x3,
|
|
17088
|
+
y: y2,
|
|
17089
|
+
offset,
|
|
17090
|
+
leaves: palette2.hedge,
|
|
17091
|
+
size: [1, 1],
|
|
17092
|
+
minimumHeight: 0,
|
|
17093
|
+
instances,
|
|
17094
|
+
drawing: hedge
|
|
17095
|
+
});
|
|
16643
17096
|
}
|
|
16644
17097
|
}
|
|
16645
17098
|
drawnLast = count;
|
|
@@ -16677,6 +17130,7 @@ function createTileflowTrees3D(options) {
|
|
|
16677
17130
|
(channel) => palette2.edgeColor[channel] * own + draw2.leaves[0][channel] * 0.4 * (1 - own)
|
|
16678
17131
|
)
|
|
16679
17132
|
);
|
|
17133
|
+
context.uniform1f(e.u_minimum_height, draw2.minimumHeight);
|
|
16680
17134
|
context.uniform2f(e.u_size_scale, ...draw2.size);
|
|
16681
17135
|
context.bindVertexArray(draw2.drawing.vao);
|
|
16682
17136
|
context.drawArraysInstanced(context.TRIANGLES, 0, draw2.drawing.count, draw2.instances);
|
|
@@ -16841,6 +17295,7 @@ ${shaderData.define}`;
|
|
|
16841
17295
|
}
|
|
16842
17296
|
const layer = {
|
|
16843
17297
|
id: tileflowTrees3DLayerId,
|
|
17298
|
+
metadata: { "tileflow:scene-kind": "vegetation" },
|
|
16844
17299
|
type: "custom",
|
|
16845
17300
|
renderingMode: "3d",
|
|
16846
17301
|
onAdd(_2, context) {
|
|
@@ -16931,8 +17386,14 @@ ${args.shaderData.define}`;
|
|
|
16931
17386
|
}
|
|
16932
17387
|
function beforeId() {
|
|
16933
17388
|
if (options.beforeId) return map.getLayer(options.beforeId) ? options.beforeId : void 0;
|
|
16934
|
-
if (map.getLayer(streetLightsLayerId2)) return streetLightsLayerId2;
|
|
16935
17389
|
const style = map.getStyle();
|
|
17390
|
+
if (style?.layers?.some(isGroundRoadLabel)) {
|
|
17391
|
+
const boundary = style.layers.find(
|
|
17392
|
+
(entry) => isGroundRoadLabel(entry) || entry.type === "fill-extrusion"
|
|
17393
|
+
);
|
|
17394
|
+
if (boundary) return boundary.id;
|
|
17395
|
+
}
|
|
17396
|
+
if (map.getLayer(streetLightsLayerId2)) return streetLightsLayerId2;
|
|
16936
17397
|
const anchors = style?.metadata?.["tileflow:overlay-placement-manifest"]?.anchors;
|
|
16937
17398
|
const anchor = anchors?.["above-buildings"];
|
|
16938
17399
|
if (typeof anchor === "string" && map.getLayer(anchor)) return anchor;
|
|
@@ -19632,6 +20093,7 @@ function validateTileflowBrowserThemeBlendSelection(value) {
|
|
|
19632
20093
|
}
|
|
19633
20094
|
var maximumBlendThemes = 8;
|
|
19634
20095
|
var maximumTransitionMs = 5e3;
|
|
20096
|
+
var defaultThemeTransitionMs = 450;
|
|
19635
20097
|
var blendLabelFadeMs = 450;
|
|
19636
20098
|
var maximumTileflowBlendStyleBytes = 16 * 1024 * 1024;
|
|
19637
20099
|
function validateStyleState(name, value) {
|
|
@@ -19647,6 +20109,10 @@ function createTileflowThemeController(options) {
|
|
|
19647
20109
|
const loadStyle = options.loadStyle ?? loadTileflowBlendStyle;
|
|
19648
20110
|
const timeoutMs = normalizeThemeTransitionTimeout(options.timeoutMs);
|
|
19649
20111
|
const defaultTransition3 = normalizeThemeTransitionDuration(options.transition);
|
|
20112
|
+
const defaultThemeTransition = normalizeThemeTransitionDuration(
|
|
20113
|
+
options.transition,
|
|
20114
|
+
defaultThemeTransitionMs
|
|
20115
|
+
);
|
|
19650
20116
|
const styleIdentities = /* @__PURE__ */ new WeakMap();
|
|
19651
20117
|
const blendRouteInks = /* @__PURE__ */ new WeakMap();
|
|
19652
20118
|
const blendMetadata = /* @__PURE__ */ new WeakMap();
|
|
@@ -19668,6 +20134,7 @@ function createTileflowThemeController(options) {
|
|
|
19668
20134
|
let shown = { style: options.initial.style };
|
|
19669
20135
|
let activeBlend;
|
|
19670
20136
|
let pendingBlend;
|
|
20137
|
+
let stopThemeMotion;
|
|
19671
20138
|
let disposed = false;
|
|
19672
20139
|
let requestId = 0;
|
|
19673
20140
|
let applyQueue = Promise.resolve();
|
|
@@ -19712,6 +20179,7 @@ function createTileflowThemeController(options) {
|
|
|
19712
20179
|
return {
|
|
19713
20180
|
dispose() {
|
|
19714
20181
|
disposed = true;
|
|
20182
|
+
stopThemeMotion?.();
|
|
19715
20183
|
releaseMetadata();
|
|
19716
20184
|
images?.dispose();
|
|
19717
20185
|
requestId += 1;
|
|
@@ -19811,9 +20279,10 @@ function createTileflowThemeController(options) {
|
|
|
19811
20279
|
const invalid = validateBlendRequest(request);
|
|
19812
20280
|
if (invalid) return Promise.resolve({ error: invalid, status: "failed", theme: targetTheme });
|
|
19813
20281
|
if (disposed) return Promise.resolve(disposedResult(targetTheme));
|
|
19814
|
-
const transition = transitionOf(changeOptions);
|
|
20282
|
+
const transition = transitionOf(changeOptions, defaultThemeTransition);
|
|
19815
20283
|
if (transition instanceof TypeError)
|
|
19816
20284
|
return Promise.resolve({ error: transition, status: "failed", theme: targetTheme });
|
|
20285
|
+
stopThemeMotion?.();
|
|
19817
20286
|
const key = blendKey(request.themes);
|
|
19818
20287
|
if (activeBlend?.key === key) {
|
|
19819
20288
|
requestId += 1;
|
|
@@ -19851,9 +20320,10 @@ function createTileflowThemeController(options) {
|
|
|
19851
20320
|
return Promise.resolve({ error: invalidTheme, status: "failed", theme: style.theme });
|
|
19852
20321
|
}
|
|
19853
20322
|
if (disposed) return Promise.resolve(disposedResult(style.theme));
|
|
19854
|
-
const transition = transitionOf(changeOptions);
|
|
20323
|
+
const transition = transitionOf(changeOptions, defaultThemeTransition);
|
|
19855
20324
|
if (transition instanceof TypeError)
|
|
19856
20325
|
return Promise.resolve({ error: transition, status: "failed", theme: style.theme });
|
|
20326
|
+
stopThemeMotion?.();
|
|
19857
20327
|
const runId = ++requestId;
|
|
19858
20328
|
pendingBlend = void 0;
|
|
19859
20329
|
options.onTransition?.({
|
|
@@ -19873,10 +20343,10 @@ function createTileflowThemeController(options) {
|
|
|
19873
20343
|
);
|
|
19874
20344
|
}
|
|
19875
20345
|
};
|
|
19876
|
-
function transitionOf(changeOptions) {
|
|
19877
|
-
if (changeOptions?.transition === void 0) return
|
|
20346
|
+
function transitionOf(changeOptions, defaultDuration = defaultTransition3) {
|
|
20347
|
+
if (changeOptions?.transition === void 0) return defaultDuration;
|
|
19878
20348
|
try {
|
|
19879
|
-
return normalizeThemeTransitionDuration(changeOptions.transition);
|
|
20349
|
+
return normalizeThemeTransitionDuration(changeOptions.transition, defaultDuration);
|
|
19880
20350
|
} catch (error) {
|
|
19881
20351
|
return error;
|
|
19882
20352
|
}
|
|
@@ -19955,11 +20425,55 @@ function createTileflowThemeController(options) {
|
|
|
19955
20425
|
if (disposed || runId !== requestId) return { status: "superseded", theme: targetTheme };
|
|
19956
20426
|
const previous = { current, shown };
|
|
19957
20427
|
options.onTransition?.({ currentTheme: previous.current.theme, phase: "applying", targetTheme });
|
|
19958
|
-
|
|
19959
|
-
activeBlend?.blender.dispose();
|
|
19960
|
-
activeBlend = void 0;
|
|
20428
|
+
let cover;
|
|
19961
20429
|
const styleInput = target.kind === "theme" ? target.style.style : target.plan.styleAt(target.position());
|
|
19962
20430
|
try {
|
|
20431
|
+
let liveTransition = false;
|
|
20432
|
+
if (target.kind === "theme" && !activeBlend && target.transition > 0 && !reducedMotion() && tileflowThemeMotionView(options.map) && canBlendTileflowThemes(options.map)) {
|
|
20433
|
+
const themes = [previous.current, target.style];
|
|
20434
|
+
let plan;
|
|
20435
|
+
try {
|
|
20436
|
+
plan = await prepareBlend(themes);
|
|
20437
|
+
} catch {
|
|
20438
|
+
}
|
|
20439
|
+
if (disposed || runId !== requestId) return { status: "superseded", theme: targetTheme };
|
|
20440
|
+
if (plan) {
|
|
20441
|
+
liveTransition = true;
|
|
20442
|
+
const style = { ...plan.styleAt(0), transition: { duration: 0, delay: 0 } };
|
|
20443
|
+
const from = typeof previous.shown.style === "string" ? await loadStyle(previous.shown.style) : previous.shown.style;
|
|
20444
|
+
if (!await prepareGeometry(from, style, runId)) {
|
|
20445
|
+
if (!disposed) await restore(previous);
|
|
20446
|
+
return { status: "superseded", theme: targetTheme };
|
|
20447
|
+
}
|
|
20448
|
+
await applyMapStyle(options.map, style, timeoutMs);
|
|
20449
|
+
if (disposed) return { status: "superseded", theme: targetTheme };
|
|
20450
|
+
const blender = createBlender(plan, 0, true);
|
|
20451
|
+
activeBlend = { blender, key: "", plan, themes };
|
|
20452
|
+
shown = { blend: activeBlend, style };
|
|
20453
|
+
shownLayers = style.layers;
|
|
20454
|
+
resetEmphasis();
|
|
20455
|
+
resetStates();
|
|
20456
|
+
resetSun(void 0);
|
|
20457
|
+
await animateTheme(blender, themes, target.transition, runId);
|
|
20458
|
+
if (!disposed && runId === requestId) {
|
|
20459
|
+
const destination = typeof styleInput === "string" ? await loadStyle(styleInput) : styleInput;
|
|
20460
|
+
const finalBlendStyle = { ...plan.styleAt(1), transition: { duration: 0, delay: 0 } };
|
|
20461
|
+
await prepareGeometry(finalBlendStyle, destination, runId);
|
|
20462
|
+
}
|
|
20463
|
+
blender.dispose();
|
|
20464
|
+
activeBlend = void 0;
|
|
20465
|
+
if (disposed) return { status: "superseded", theme: targetTheme };
|
|
20466
|
+
if (runId !== requestId) {
|
|
20467
|
+
await restore(previous);
|
|
20468
|
+
return { status: "superseded", theme: targetTheme };
|
|
20469
|
+
}
|
|
20470
|
+
}
|
|
20471
|
+
}
|
|
20472
|
+
if (!liveTransition) {
|
|
20473
|
+
cover = beginTileflowStyleCrossfade(options.map, target.transition);
|
|
20474
|
+
}
|
|
20475
|
+
activeBlend?.blender.dispose();
|
|
20476
|
+
activeBlend = void 0;
|
|
19963
20477
|
if (target.kind === "blend") images?.assertBlend(target.plan.images);
|
|
19964
20478
|
invalidateMetadata();
|
|
19965
20479
|
await applyMapStyle(options.map, styleInput, timeoutMs);
|
|
@@ -20000,6 +20514,8 @@ function createTileflowThemeController(options) {
|
|
|
20000
20514
|
return { status: "applied", theme: current.theme };
|
|
20001
20515
|
} catch (error) {
|
|
20002
20516
|
cover?.cancel();
|
|
20517
|
+
activeBlend?.blender.dispose();
|
|
20518
|
+
activeBlend = void 0;
|
|
20003
20519
|
const normalized = normalizeThemeTransitionError(error, "Tileflow theme change failed.");
|
|
20004
20520
|
try {
|
|
20005
20521
|
await restore(previous);
|
|
@@ -20015,14 +20531,66 @@ function createTileflowThemeController(options) {
|
|
|
20015
20531
|
return { error: normalized, status: "failed", theme: targetTheme };
|
|
20016
20532
|
}
|
|
20017
20533
|
}
|
|
20018
|
-
function
|
|
20534
|
+
async function prepareGeometry(from, to, runId) {
|
|
20535
|
+
const getStyle = options.map.getStyle;
|
|
20536
|
+
const displayed = typeof getStyle === "function" ? getStyle.call(options.map) : void 0;
|
|
20537
|
+
const preparation = prepareTileflowThemeGeometry(displayed ?? from, to);
|
|
20538
|
+
if (!preparation) return !disposed && runId === requestId;
|
|
20539
|
+
await applyMapStyle(options.map, preparation.style, timeoutMs);
|
|
20540
|
+
const ready = await waitForTileflowThemeGeometry(
|
|
20541
|
+
options.map,
|
|
20542
|
+
timeoutMs,
|
|
20543
|
+
() => disposed || runId !== requestId
|
|
20544
|
+
);
|
|
20545
|
+
if (ready) preparation.reveal(options.map);
|
|
20546
|
+
return ready;
|
|
20547
|
+
}
|
|
20548
|
+
function animateTheme(blender, themes, duration, runId) {
|
|
20549
|
+
const view = tileflowThemeMotionView(options.map);
|
|
20550
|
+
return new Promise((resolve, reject) => {
|
|
20551
|
+
const now = () => view.performance?.now?.() ?? Date.now();
|
|
20552
|
+
const started = now();
|
|
20553
|
+
let frame;
|
|
20554
|
+
let settled = false;
|
|
20555
|
+
const finish2 = (error) => {
|
|
20556
|
+
if (settled) return;
|
|
20557
|
+
settled = true;
|
|
20558
|
+
if (frame !== void 0) {
|
|
20559
|
+
view.cancelAnimationFrame?.(frame);
|
|
20560
|
+
view.clearTimeout(frame);
|
|
20561
|
+
}
|
|
20562
|
+
if (stopThemeMotion === cancel) stopThemeMotion = void 0;
|
|
20563
|
+
if (error) reject(error);
|
|
20564
|
+
else resolve();
|
|
20565
|
+
};
|
|
20566
|
+
const cancel = () => finish2();
|
|
20567
|
+
const step = () => {
|
|
20568
|
+
frame = void 0;
|
|
20569
|
+
if (disposed || runId !== requestId) return finish2();
|
|
20570
|
+
try {
|
|
20571
|
+
const t = Math.min(1, (now() - started) / duration);
|
|
20572
|
+
blender.set(t * t * (3 - 2 * t));
|
|
20573
|
+
current = themes[blender.dominant];
|
|
20574
|
+
images?.invalidate();
|
|
20575
|
+
if (t >= 1) finish2();
|
|
20576
|
+
else frame = view.requestAnimationFrame?.(step) ?? view.setTimeout(step, 16);
|
|
20577
|
+
} catch (error) {
|
|
20578
|
+
finish2(error);
|
|
20579
|
+
}
|
|
20580
|
+
};
|
|
20581
|
+
stopThemeMotion = cancel;
|
|
20582
|
+
step();
|
|
20583
|
+
});
|
|
20584
|
+
}
|
|
20585
|
+
function createBlender(plan, position, liveTransition = false) {
|
|
20019
20586
|
return createTileflowThemeBlender(options.map, plan, {
|
|
20020
20587
|
cover(change) {
|
|
20588
|
+
if (liveTransition) return change();
|
|
20021
20589
|
const fade = beginTileflowStyleCrossfade(options.map, blendLabelFadeMs);
|
|
20022
20590
|
change();
|
|
20023
20591
|
void fade?.finish();
|
|
20024
20592
|
},
|
|
20025
|
-
labelFadeMs: reducedMotion() ? 0 : blendLabelFadeMs,
|
|
20593
|
+
labelFadeMs: liveTransition || reducedMotion() ? 0 : blendLabelFadeMs,
|
|
20026
20594
|
// The ground colour moves with the blend, and colours that recede follow it.
|
|
20027
20595
|
onPosition: () => {
|
|
20028
20596
|
if (emphasisShown) writeEmphasis(false);
|
|
@@ -20550,8 +21118,8 @@ function validateBlendRequest(request) {
|
|
|
20550
21118
|
}
|
|
20551
21119
|
return void 0;
|
|
20552
21120
|
}
|
|
20553
|
-
function normalizeThemeTransitionDuration(transition) {
|
|
20554
|
-
const duration = transition?.duration ??
|
|
21121
|
+
function normalizeThemeTransitionDuration(transition, defaultDuration = 0) {
|
|
21122
|
+
const duration = transition?.duration ?? defaultDuration;
|
|
20555
21123
|
if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0 || duration > maximumTransitionMs) {
|
|
20556
21124
|
throw new TypeError(
|
|
20557
21125
|
`A Tileflow theme transition duration must be a number of milliseconds from 0 to ${maximumTransitionMs}.`
|
|
@@ -20613,6 +21181,7 @@ function applyMapStyle(map, style, timeoutMs) {
|
|
|
20613
21181
|
const cleanup = () => {
|
|
20614
21182
|
clearTimeout(timeout);
|
|
20615
21183
|
map.off("style.load", handleLoad);
|
|
21184
|
+
map.off("render", handleRenderedStyle);
|
|
20616
21185
|
map.off("error", handleError);
|
|
20617
21186
|
};
|
|
20618
21187
|
const settle = (error) => {
|
|
@@ -20623,6 +21192,10 @@ function applyMapStyle(map, style, timeoutMs) {
|
|
|
20623
21192
|
else resolve();
|
|
20624
21193
|
};
|
|
20625
21194
|
const handleLoad = () => settle();
|
|
21195
|
+
const handleRenderedStyle = () => {
|
|
21196
|
+
const isStyleLoaded = map.isStyleLoaded;
|
|
21197
|
+
if (typeof isStyleLoaded === "function" && isStyleLoaded.call(map) === true) settle();
|
|
21198
|
+
};
|
|
20626
21199
|
const handleError = (event) => settle(
|
|
20627
21200
|
normalizeThemeTransitionError(
|
|
20628
21201
|
isRecordWithError(event) ? event.error : event,
|
|
@@ -20634,6 +21207,7 @@ function applyMapStyle(map, style, timeoutMs) {
|
|
|
20634
21207
|
timeoutMs
|
|
20635
21208
|
);
|
|
20636
21209
|
map.on("style.load", handleLoad);
|
|
21210
|
+
map.on("render", handleRenderedStyle);
|
|
20637
21211
|
map.on("error", handleError);
|
|
20638
21212
|
try {
|
|
20639
21213
|
if (typeof map.setStyle !== "function") {
|
|
@@ -20641,6 +21215,7 @@ function applyMapStyle(map, style, timeoutMs) {
|
|
|
20641
21215
|
}
|
|
20642
21216
|
const setStyle = map.setStyle;
|
|
20643
21217
|
setStyle.call(map, style, { diff: true, validate: false });
|
|
21218
|
+
handleRenderedStyle();
|
|
20644
21219
|
} catch (error) {
|
|
20645
21220
|
settle(normalizeThemeTransitionError(error, "MapLibre rejected the Tileflow theme."));
|
|
20646
21221
|
}
|
|
@@ -20985,6 +21560,7 @@ function isPromiseLike(value) {
|
|
|
20985
21560
|
export {
|
|
20986
21561
|
attachTileflowAtmosphere,
|
|
20987
21562
|
attachTileflowFairUseNotice,
|
|
21563
|
+
attachTileflowLabelPlacement,
|
|
20988
21564
|
attachTileflowMap3D,
|
|
20989
21565
|
attachTileflowMapLifecycle,
|
|
20990
21566
|
attachTileflowNauticalLights,
|