@johnmorrisdotca/kyogijo-stadiums 0.44.1 → 0.44.2

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.
@@ -0,0 +1,3 @@
1
+ import type { ContextArea } from "./context.ts";
2
+ /** Vancouver: water, green and trees round BC Place and Rogers Arena: 0 buildings, 0 street lines, 28 land cover outlines and 1370 trees within 450 metres of the middle, read 2026-10-22. */
3
+ export declare const VANCOUVER_NATURE: ContextArea;
@@ -0,0 +1,57 @@
1
+ /** Vancouver: water, green and trees round BC Place and Rogers Arena: 0 buildings, 0 street lines, 28 land cover outlines and 1370 trees within 450 metres of the middle, read 2026-10-22. */
2
+ export const VANCOUVER_NATURE = {
3
+ "key": "vancouver-nature",
4
+ "name": { "en": "Vancouver: water, green and trees round BC Place and Rogers Arena", "ja": "バンクーバー:BCプレイスとロジャース・アリーナ周辺の水面・緑地・樹木" },
5
+ "origin": [-123.11038, 49.277237],
6
+ "radius": 450,
7
+ "grid": 0.5,
8
+ "layers": {
9
+ "landCover": {
10
+ "source": "VoxCity 1.7.0 land cover from OpenStreetMap",
11
+ "read": "2026-10-22",
12
+ "licence": "ODbL 1.0 (OpenStreetMap); VoxCity is MIT",
13
+ "attribution": { "en": "Land cover made with VoxCity (MIT) from OpenStreetMap", "ja": "土地被覆:OpenStreetMap から VoxCity(MIT)で作成" },
14
+ /** Each outline: the class (0 water, 1 green, 2 wood), then the first point (east, north) and each step to the next, in grid steps from `origin`. A hole is an outline of its own (filled even-odd). */
15
+ "rows": [
16
+ [0, 1838, 1998, -80, -120, 80, -40],
17
+ [0, 1558, 1998, -479, -200, 479, 40],
18
+ [0, 1119, -1079, -1758, 40, 0, -280],
19
+ [0, -80, -1159, 120, 80, 0, -40],
20
+ [0, -679, -1358, -1319, 159, 0, -799],
21
+ [1, 799, 1878, -80, -120, 80, -40],
22
+ [1, 1079, 1758, -120, -120, 639, 160],
23
+ [1, -1319, 1358, -199, -39, 199, -40],
24
+ [1, -1478, 1239, -120, -240, 160, 160],
25
+ [1, 80, 1199, -160, -120, 160, -80],
26
+ [1, -1119, 440, -160, 0, 0, -80],
27
+ [1, 599, 479, -40, -279, 280, 200, 0, 40],
28
+ [1, 639, 400, 40, 40, 0, -40],
29
+ [1, 1998, 479, -40, -359, 40, 0],
30
+ [1, 1159, 519, -480, -359, 520, -40],
31
+ [1, 1918, 80, -120, -120, 160, -40],
32
+ [1, 599, -160, -40, -160, 120, 40],
33
+ [1, 1438, -320, -119, -159, 119, 0],
34
+ [1, 1119, -240, -120, -479, 160, -40],
35
+ [1, 1718, -519, -200, -400, 160, 0],
36
+ [1, -919, -959, 320, 0, -40, 120],
37
+ [1, 1159, -1159, -40, 80, -240, -80],
38
+ [1, -1598, -919, -200, -439, 240, 319],
39
+ [1, 959, -1279, -120, -239, 80, -40],
40
+ [1, 120, -1119, -240, -160, -40, -119, 280, -120],
41
+ [1, -40, -1358, 40, 39, 0, -39],
42
+ [1, -799, -1598, -160, -120, 200, 40],
43
+ [1, -1598, -1918, -200, -80, 240, 0],
44
+ ],
45
+ },
46
+ "trees": {
47
+ "source": "OpenStreetMap natural=tree and the City of Vancouver's Public trees: https://opendata.vancouver.ca/explore/dataset/public-trees/",
48
+ "read": "2026-10-22",
49
+ "licence": "ODbL 1.0 (OpenStreetMap) and the Open Government Licence - Vancouver",
50
+ "attribution": { "en": "Trees: City of Vancouver open data, Public trees, under the Open Government Licence - Vancouver; simplified and edited by Kyogijo Stadiums", "ja": "樹木:バンクーバー市オープンデータ「Public trees」(Open Government Licence - Vancouver);Kyogijo Stadiums が加工して作成" },
51
+ /** One row for all the trees: the first tree's east, north and crown radius, then each next tree's step in east and north from the one before and its crown radius, all in grid steps. */
52
+ "rows": [
53
+ [-343, -825, 5, 4, 3, 7, 5, 4, 6, 8, 6, 5, 27, 11, 4, -1, 1, 5, 7, 6, 5, -13, 1, 5, -131, 8, 5, 15, 2, 5, -16, 2, 4, 0, 8, 5, -4, 2, 5, 20, 1, 5, -22, 3, 5, 41, 8, 5, -17, 0, 5, 10, 0, 5, 11, 4, 5, 57, 1, 4, -2, 1, 5, -19, 0, 5, 76, 3, 5, -208, 1, 5, 314, 1, 5, -228, 1, 4, -13, 1, 5, -55, 1, 5, 75, 1, 5, 112, 2, 4, 118, 0, 5, -313, 1, 5, 25, 2, 5, 261, 3, 5, -221, 1, 5, 258, 1, 5, -249, 0, 5, -52, 0, 5, -7, 1, 4, -2, 1, 5, 131, 0, 5, -166, 2, 5, 321, 1, 5, 29, 0, 5, -168, 1, 4, -136, 2, 5, 280, 1, 5, -315, 2, 5, 320, 2, 5, -248, 0, 5, 5, 1, 5, -33, 1, 5, -33, 3, 5, 315, 0, 5, -274, 3, 5, 140, 0, 5, -12, 1, 5, -223, 1, 5, 65, 3, 5, -59, 8, 5, 106, 0, 5, -36, 0, 5, 42, 1, 4, 4, 5, 5, 5, 1, 4, 107, 0, 5, -147, 1, 5, -77, 1, 5, 213, 0, 5, 192, 3, 5, -281, 2, 5, 290, 3, 5, -324, 0, 5, 351, 1, 5, -340, 5, 5, 5, 2, 5, 119, 1, 5, -13, 1, 5, -101, 3, 5, -148, 1, 3, 152, 1, 4, -172, 0, 5, 4, 0, 3, 210, 2, 4, -1, 3, 5, 86, 2, 5, -76, 4, 5, -35, 0, 4, -2, 1, 5, -165, 1, 5, 293, 1, 5, -44, 0, 5, 11, 0, 5, 20, 3, 5, -67, 1, 5, 3, 1, 4, -43, 0, 5, 158, 0, 5, -151, 1, 4, 90, 3, 5, -209, 0, 5, 121, 1, 5, 40, 2, 5, -32, 1, 5, -1, 3, 5, -115, 2, 5, 174, 1, 5, -11, 0, 4, 23, 0, 5, -26, 1, 5, -31, 2, 5, -2, 1, 5, 71, 1, 5, -186, 3, 5, 129, 3, 5, -3, 1, 5, -113, 4, 5, 126, 2, 5, -1, 1, 5, 66, 4, 5, -178, 2, 5, -119, 6, 3, -6, 1, 5, 139, 1, 5, -206, 2, 5, 85, 4, 5, 135, 4, 5, 2, 0, 3, 87, 1, 5, -2, 1, 4, 30, 0, 5, -233, 0, 4, -3, 2, 5, 130, 2, 5, 68, 4, 5, -181, 3, 5, 128, 1, 5, 77, 2, 5, -73, 0, 3, 73, 1, 4, -186, 4, 5, 149, 1, 5, -26, 1, 5, 24, 1, 4, -21, 0, 3, 51, 1, 5, -161, 6, 5, 147, 8, 5, -126, 1, 4, 126, 0, 4, 448, 1, 5, -687, 0, 5, 109, 0, 5, -236, 0, 5, 58, 7, 5, 79, 2, 5, 127, 5, 4, -269, 1, 5, 264, 0, 5, 559, 6, 5, -429, 0, 5, -108, 4, 4, -4, 1, 5, -291, 0, 5, 74, 1, 5, 326, 2, 4, -177, 1, 5, 200, 4, 5, -12, 4, 4, 424, 3, 5, 84, 7, 5, -496, 2, 5, 450, 2, 5, -443, 3, 5, -80, 6, 5, 90, 2, 5, -469, 1, 4, 393, 6, 5, 3, 1, 4, 516, 1, 5, -13, 1, 5, -886, 6, 3, 395, 0, 5, 3, 1, 4, 82, 1, 5, -66, 8, 4, 451, 0, 5, -11, 0, 5, -443, 1, 5, -403, 0, 5, 486, 1, 5, 360, 5, 5, -448, 5, 5, 24, 1, 4, 436, 4, 5, -888, 0, 5, 878, 1, 5, -832, 0, 5, -41, 1, 7, 459, 3, 5, -18, 1, 5, 23, 1, 4, 15, 4, 4, -427, 4, 5, -38, 2, 7, 479, 3, 4, -62, 0, 5, 38, 0, 5, -452, 4, 5, 472, 0, 5, -5, 7, 5, 20, 3, 5, -477, 1, 5, 5, 3, 7, 467, 2, 5, -332, 3, 5, -131, 3, 5, 287, 3, 5, -157, 2, 5, 476, 1, 5, -14, 2, 5, -580, 2, 6, 338, 1, 5, -216, 2, 4, -5, 1, 5, 228, 4, 5, -14, 1, 5, -199, 2, 5, 182, 1, 5, 9, 0, 5, -204, 1, 5, -112, 1, 5, 108, 0, 5, 227, 1, 5, -327, 1, 6, 504, 2, 4, -189, 1, 5, -201, 0, 5, 491, 2, 5, -300, 1, 5, 196, 2, 5, -403, 0, 5, -94, 4, 5, 107, 1, 5, -12, 3, 4, 523, 2, 5, -527, 0, 5, 16, 2, 5, -89, 7, 7, 103, 1, 5, 425, 0, 4, 88, 3, 5, -89, 0, 5, -525, 2, 5, 97, 3, 5, -19, 3, 5, 140, 5, 5, 1283, 2, 5, -1296, 1, 5, 347, 0, 4, -478, 0, 5, 1419, 0, 5, -9, 2, 5, -935, 0, 5, 928, 0, 5, 33, 1, 5, -43, 0, 5, -26, 0, 5, -1334, 2, 5, 1306, 1, 5, -21, 0, 5, 112, 1, 5, -208, 0, 5, 107, 1, 5, -1156, 0, 5, -14, 2, 5, 329, 2, 5, 703, 1, 5, 239, 2, 5, -1279, 0, 5, -155, 0, 7, 1213, 3, 5, -711, 3, 5, -375, 0, 5, 918, 1, 5, 15, 0, 5, -1122, 5, 5, 72, 0, 4, 8, 0, 5, 1425, 2, 5, -854, 0, 5, -76, 0, 5, 685, 1, 5, -670, 5, 4, -396, 0, 5, -201, 3, 5, 192, 1, 5, 1316, 0, 5, -1506, 0, 4, 593, 0, 5, -506, 3, 5, 115, 0, 5, -380, 1, 5, 271, 0, 8, 1163, 1, 5, -649, 1, 4, -3, 3, 5, 115, 0, 5, -727, 2, 5, 200, 0, 5, 1317, 0, 5, -1414, 0, 7, 1198, 3, 5, -673, 0, 4, 54, 2, 5, 607, 0, 5, -1094, 0, 5, -354, 0, 5, 1423, 2, 5, -1155, 0, 5, -275, 2, 5, 208, 2, 3, -47, 1, 4, 44, 1, 5, -47, 0, 5, 631, 2, 5, -465, 1, 5, 488, 1, 4, -571, 1, 5, 3, 0, 4, 111, 1, 5, -332, 0, 5, 264, 1, 3, 582, 1, 5, -61, 2, 5, -795, 0, 5, 139, 1, 5, 49, 2, 5, 2, 2, 4, 1447, 1, 5, -1628, 3, 5, 122, 1, 5, 154, 1, 3, -40, 0, 3, -2, 1, 5, -272, 0, 5, 0, 2, 5, 856, 1, 4, -648, 6, 3, -57, 0, 5, 54, 1, 5, 118, 1, 5, 1123, 1, 5, -1113, 2, 5, 519, 1, 5, -565, 3, 5, -271, 1, 5, 47, 2, 5, 231, 1, 4, -155, 0, 5, 52, 0, 5, 4, 1, 3, 673, 2, 5, -838, 8, 5, 1427, 1, 5, -1327, 1, 4, -53, 0, 5, 104, 1, 5, -54, 1, 5, 758, 0, 5, -578, 1, 4, -1, 1, 5, -262, 4, 5, 41, 2, 5, -43, 0, 5, 127, 2, 4, -4, 2, 5, -108, 8, 5, -3, 1, 5, 1395, 1, 5, -1291, 1, 3, -4, 0, 5, 779, 2, 4, 66, 1, 5, -929, 6, 6, 860, 1, 5, -788, 0, 5, 807, 4, 4, 498, 3, 5, -503, 4, 5, -885, 3, 5, 907, 2, 4, -907, 6, 5, 903, 0, 5, -892, 3, 5, 913, 5, 4, -845, 2, 5, 772, 0, 5, -848, 2, 4, 919, 2, 5, -922, 0, 5, -10, 0, 5, 835, 2, 5, 48, 0, 5, -879, 5, 5, 941, 1, 5, -953, 0, 5, 10, 1, 5, 864, 6, 5, -883, 1, 5, 11, 1, 5, 242, 4, 5, -247, 1, 5, 1410, 0, 5, -1280, 0, 5, 767, 1, 5, -899, 1, 5, -8, 8, 5, -21, 2, 5, 19, 0, 5, 300, 1, 5, -143, 0, 3, 117, 0, 5, 630, 2, 5, 11, 1, 5, -23, 0, 5, 810, 4, 5, -1714, 3, 5, 181, 2, 3, 132, 2, 5, 610, 2, 5, 795, 0, 5, -810, 0, 5, -10, 1, 5, -920, 1, 5, 1726, 2, 5, -1387, 0, 5, -327, 1, 5, -3, 2, 5, -19, 5, 5, 958, 2, 5, 508, 0, 5, -1458, 4, 5, 1105, 2, 4, -1108, 1, 5, 1105, 1, 5, -870, 1, 3, 714, 2, 5, 179, 7, 4, -1141, 1, 5, -11, 0, 5, 344, 3, 5, -73, 0, 3, 897, 3, 4, -3, 1, 5, -827, 1, 5, 699, 7, 5, -709, 2, 5, -43, 0, 3, 632, 3, 5, -594, 2, 5, -5, 5, 5, 915, 0, 4, -5, 2, 5, -931, 3, 5, 730, 0, 5, -704, 1, 5, 926, 1, 5, -931, 4, 5, 699, 5, 5, -710, 1, 5, 623, 3, 5, -896, 1, 5, -1, 3, 5, 974, 9, 5, -676, 7, 5, -276, 1, 3, -4, 1, 5, -39, 0, 5, 3, 1, 3, 1451, 1, 5, -469, 2, 5, -34, 4, 5, -940, 2, 3, 1463, 0, 3, -1464, 0, 5, 40, 1, 5, 4, 1, 5, 903, 1, 5, 304, 0, 4, 197, 1, 3, -545, 1, 5, 50, 0, 5, 508, 2, 5, -213, 0, 5, -1234, 6, 5, 11, 11, 5, 38, 0, 5, -37, 1, 3, 1436, 0, 5, -16, 5, 5, -1371, 4, 5, 1177, 0, 4, -1179, 0, 5, 1175, 2, 5, 216, 1, 3, -16, 11, 5, 17, 3, 3, -213, 0, 4, -1194, 6, 5, 1191, 2, 5, -1181, 6, 5, 8, 8, 7, 1177, 3, 14, -856, 3, 5, -40, 1, 5, -22, 0, 5, -213, 1, 3, 216, 2, 7, -251, 2, 6, 278, 4, 5, -236, 0, 5, 2, 1, 5, 195, 3, 6, -227, 4, 6, 175, 1, 5, 103, 3, 4, 1, 1, 5, -52, 0, 5, -11, 3, 6, -4, 1, 5, -202, 1, 6, 322, 7, 5, 149, 0, 5, -266, 2, 5, -11, 0, 5, 1427, 2, 5, -1610, 0, 3, 479, 1, 5, 655, 2, 4, -1002, 3, 5, 1447, 1, 7, -1531, 1, 6, 1083, 0, 5, 466, 0, 5, -804, 1, 3, -788, 0, 5, 7, 2, 3, 1550, 0, 5, -938, 1, 5, -289, 2, 6, 1210, 1, 5, -999, 1, 5, 982, 2, 5, -1473, 0, 5, 449, 1, 5, -446, 0, 4, 58, 3, 5, 1499, 0, 5, -41, 0, 5, -64, 1, 5, 107, 0, 8, -39, 0, 7, 26, 0, 5, -1584, 2, 5, 322, 1, 5, -189, 1, 5, -2, 0, 4, 1415, 0, 6, -1219, 0, 3, 472, 1, 3, 316, 1, 4, 416, 1, 7, -73, 0, 5, -346, 3, 5, 327, 1, 5, 147, 1, 6, -42, 0, 5, -32, 2, 7, -1433, 0, 5, 1401, 0, 5, -1359, 1, 5, 1302, 0, 7, -3, 1, 5, 124, 0, 7, -66, 1, 7, -818, 1, 5, -15, 0, 5, 935, 0, 5, -764, 1, 3, 683, 0, 8, -93, 0, 7, -2, 1, 5, 63, 0, 7, -25, 1, 5, -1328, 0, 4, 0, 2, 5, 233, 4, 5, -41, 0, 6, 43, 0, 3, 1134, 1, 5, 6, 0, 6, -45, 1, 7, -667, 0, 5, -131, 1, 5, -616, 1, 3, 599, 2, 5, 832, 1, 5, -1148, 3, 5, 1149, 0, 6, 13, 3, 5, -682, 1, 5, 5, 0, 4, 612, 0, 5, 70, 1, 7, -845, 0, 5, 761, 0, 5, 18, 0, 7, -11, 1, 7, -1080, 1, 5, 292, 0, 5, 813, 0, 8, 19, 3, 7, -33, 6, 7, -99, 0, 7, 93, 0, 5, -1075, 1, 3, 482, 1, 4, -4, 0, 5, 577, 1, 5, -767, 0, 5, 947, 0, 7, -266, 1, 7, 220, 0, 7, -921, 1, 5, -223, 1, 5, 917, 0, 5, -1197, 1, 5, 1366, 0, 4, -1362, 0, 5, 1351, 1, 4, -27, 0, 8, -1399, 0, 5, 1463, 1, 5, -13, 0, 5, -41, 1, 7, -152, 0, 5, -1254, 1, 4, 1347, 0, 5, -89, 0, 9, 110, 1, 5, 159, 0, 9, -50, 1, 5, -74, 1, 5, -169, 0, 5, 220, 0, 6, -1099, 0, 5, 203, 2, 5, 241, 0, 5, -225, 0, 5, -256, 1, 3, 1059, 1, 5, 66, 1, 7, -12, 0, 5, -73, 1, 5, 162, 0, 5, -1439, 1, 5, 1404, 0, 5, -172, 0, 5, -1323, 1, 3, 1232, 0, 5, 296, 0, 7, -198, 2, 7, 46, 2, 5, 147, 0, 5, -967, 1, 5, 320, 0, 5, -307, 1, 5, -506, 1, 6, 763, 0, 5, 518, 1, 7, 113, 1, 5, -1075, 0, 5, 1028, 0, 5, -1420, 1, 3, 1228, 0, 5, -1114, 0, 5, 231, 1, 5, 1022, 0, 5, 27, 0, 5, -1354, 0, 6, 1331, 0, 7, -74, 1, 4, 218, 0, 5, -221, 1, 5, -1175, 0, 4, 779, 2, 5, 200, 0, 5, -198, 1, 4, 434, 0, 5, 69, 2, 5, 32, 0, 5, -215, 0, 4, -1231, 1, 5, 1394, 1, 5, -168, 0, 5, -1185, 1, 5, -41, 0, 8, 375, 0, 5, -9, 0, 5, 1030, 1, 7, -530, 0, 5, -767, 0, 6, 1325, 2, 5, -48, 1, 3, 83, 1, 5, 3, 0, 4, -1041, 0, 5, 799, 0, 4, -797, 1, 4, 974, 1, 6, -59, 1, 5, 96, 0, 5, 93, 1, 5, -312, 1, 5, -638, 0, 5, 833, 2, 5, -1383, 1, 5, 450, 0, 5, 966, 1, 5, -561, 0, 5, 530, 2, 7, -829, 0, 5, -428, 1, 3, 1051, 0, 4, -2, 1, 5, -649, 1, 5, 899, 1, 5, -129, 1, 6, 204, 1, 7, -1553, 1, 5, 614, 0, 5, -575, 1, 5, 450, 0, 5, -583, 1, 5, 1423, 0, 5, -743, 0, 5, -14, 1, 5, 644, 1, 5, -290, 1, 4, -2, 0, 5, -501, 0, 5, 197, 3, 5, 825, 2, 5, -1415, 0, 5, 563, 1, 5, -402, 0, 5, -39, 0, 5, 1378, 0, 5, -973, 1, 5, 649, 1, 5, 0, 0, 4, 135, 1, 6, 108, 1, 7, -1533, 0, 5, 1507, 0, 5, -794, 1, 5, 832, 0, 7, -34, 0, 5, -827, 1, 5, -679, 0, 6, 1618, 0, 5, -596, 1, 4, -744, 1, 5, 1346, 0, 4, -347, 1, 5, -649, 0, 5, -529, 0, 5, 616, 3, 5, 844, 0, 7, -1316, 1, 5, 1360, 0, 4, -1359, 0, 4, 1357, 1, 5, 28, 1, 5, -117, 1, 7, -5, 0, 5, 39, 1, 6, -926, 0, 5, 952, 0, 7, -160, 2, 6, 69, 0, 5, -759, 0, 5, -472, 0, 5, -237, 0, 4, 277, 1, 5, 1202, 1, 7, -1404, 0, 5, 732, 1, 5, 819, 1, 5, -244, 1, 6, 219, 0, 5, -20, 1, 5, -894, 0, 5, 966, 0, 7, -938, 1, 5, 851, 0, 5, -190, 0, 5, -1348, 0, 5, 1542, 1, 7, -29, 1, 4, -948, 0, 5, 887, 1, 5, -1470, 0, 6, 1459, 2, 5, 78, 0, 4, -751, 0, 5, -102, 1, 5, -631, 0, 5, 2, 1, 3, 658, 0, 5, 937, 1, 5, -1072, 0, 5, 1024, 0, 5, -155, 1, 5, 177, 0, 5, -231, 0, 4, 0, 2, 5, -703, 1, 5, -405, 0, 5, 530, 0, 5, -527, 0, 3, 215, 1, 3, -3, 0, 5, 877, 1, 5, -657, 1, 5, 852, 0, 5, -24, 0, 4, -177, 0, 5, -598, 2, 5, 679, 0, 5, 4, 0, 5, -1412, 1, 6, 1590, 0, 4, -459, 0, 5, 436, 0, 5, 21, 1, 5, -167, 1, 5, 127, 0, 7, 24, 0, 4, -27, 1, 5, -444, 1, 5, 269, 0, 5, -686, 1, 5, 74, 1, 5, 325, 0, 5, 268, 1, 5, 46, 1, 5, -5, 0, 5, -674, 2, 5, -179, 0, 5, 124, 1, 5, 888, 0, 7, -861, 0, 5, -250, 0, 5, 971, 1, 5, -1149, 1, 5, 1069, 0, 5, 247, 1, 5, -169, 0, 5, -46, 0, 5, -1141, 0, 5, 524, 3, 5, -32, 1, 5, -282, 1, 5, 264, 1, 5, 852, 0, 7, -145, 0, 5, -732, 1, 5, -165, 0, 5, 4, 2, 5, 828, 0, 5, 20, 1, 4, -23, 2, 5, 64, 0, 5, 189, 0, 5, -1086, 0, 5, 175, 1, 5, -253, 0, 5, 934, 1, 5, -622, 0, 5, -257, 1, 5, 1054, 0, 8, -162, 1, 4, -1094, 1, 5, -275, 0, 3, 240, 0, 4, -244, 0, 5, 1558, 1, 5, -1274, 0, 6, 1087, 0, 5, -854, 0, 5, 401, 1, 5, -677, 0, 5, 445, 1, 5, 502, 0, 5, 384, 0, 5, -1007, 1, 5, -78, 0, 5, -71, 1, 5, 771, 0, 5, 364, 1, 5, -171, 0, 5, -701, 0, 5, -209, 2, 5, 59, 1, 7, 865, 0, 4, -1139, 2, 4, 271, 1, 5, -274, 0, 5, 1227, 2, 5, -74, 1, 4, -58, 0, 6, -771, 0, 5, 909, 2, 8, -84, 0, 5, -926, 0, 5, 915, 0, 4, 163, 1, 6, -2, 0, 5, -821, 0, 5, -63, 1, 5, 235, 0, 5, -919, 1, 5, 1398, 0, 5, -35, 1, 5, -1321, 0, 3, 1374, 1, 4, 170, 1, 5, -1306, 0, 5, 135, 0, 5, 1, 3, 5, 995, 1, 5, -938, 0, 5, 200, 0, 5, 911, 1, 5, -1018, 1, 5, 192, 0, 5, -196, 0, 5, 46, 0, 5, 779, 1, 5, -1377, 0, 5, 1468, 0, 5, 93, 1, 5, -1282, 1, 5, 117, 1, 5, 1157, 0, 5, -172, 1, 7, -659, 0, 5, 829, 1, 5, 26, 0, 5, -131, 1, 5, 41, 1, 5, -832, 0, 5, 787, 0, 5, -550, 1, 5, 606, 1, 7, -1171, 0, 5, 432, 0, 5, 603, 1, 6, 110, 0, 5, -860, 0, 10, -2, 2, 5, -320, 0, 5, 1163, 1, 5, -722, 0, 5, -276, 0, 5, 1107, 0, 5, -1271, 0, 4, 93, 0, 5, 262, 3, 5, 738, 0, 5, 160, 0, 5, 4, 1, 5, -781, 0, 5, -714, 0, 5, 1383, 1, 5, -860, 0, 6, -128, 2, 5, 748, 0, 5, -859, 0, 5, 1024, 1, 5, 168, 0, 5, -1095, 0, 5, -58, 0, 6, 988, 1, 6, -789, 0, 5, 164, 0, 5, -301, 1, 5, 334, 0, 5, 744, 1, 5, -879, 1, 5, 878, 1, 5, 53, 1, 6, -1220, 0, 5, 1152, 0, 4, -4, 1, 5, -110, 1, 5, 2, 1, 5, -609, 0, 5, -432, 0, 5, -268, 0, 5, 667, 1, 5, 804, 0, 5, -84, 1, 5, 70, 2, 6, -63, 0, 7, -105, 0, 7, -1299, 1, 5, 1126, 1, 5, -1200, 0, 5, 1522, 0, 5, -1514, 1, 5, 751, 0, 5, -744, 1, 5, 778, 0, 5, 712, 1, 5, -1459, 2, 5, 372, 0, 5, -394, 1, 5, 1373, 1, 6, 89, 0, 8, -1390, 1, 5, 669, 1, 5, 713, 0, 5, -677, 0, 5, -378, 2, 5, 777, 0, 4, 178, 1, 7, -4, 0, 5, -1285, 1, 5, 1361, 0, 5, -250, 2, 5, 201, 1, 5, -628, 0, 5, -717, 1, 5, 350, 0, 5, -298, 0, 5, 35, 1, 5, 1325, 0, 5, -11, 1, 8, -839, 2, 5, 195, 0, 5, 640, 0, 5, -839, 0, 5, -203, 1, 5, -279, 1, 5, 1305, 0, 7, -19, 0, 5, -638, 2, 5, 643, 2, 5, -18, 1, 5, -1338, 0, 5, 1343, 1, 8, -1303, 1, 5, 1094, 0, 4, -412, 3, 5, 411, 2, 5, -870, 0, 6, 347, 0, 9, -600, 2, 5, 1449, 1, 6, -1397, 1, 5, 505, 2, 5, 162, 0, 5, 726, 0, 5, -1400, 4, 5, 564, 0, 3, 816, 0, 5, -301, 2, 4, -1114, 0, 5, 9, 0, 3, 222, 0, 5, 1, 1, 4, 485, 0, 5, -389, 1, 5, 1069, 0, 5, -582, 1, 3, 298, 1, 5, -556, 1, 5, -504, 0, 5, 1212, 2, 4, 115, 0, 5, -129, 3, 5, 111, 1, 5, -1352, 1, 5, 603, 0, 8, 626, 0, 5, -1186, 1, 3, 1061, 2, 5, -547, 0, 5, 776, 1, 5, -122, 2, 4, -876, 2, 5, -324, 1, 5, 188, 0, 5, 904, 1, 5, 89, 0, 4, -628, 1, 5, -500, 2, 5, 1113, 2, 5, -15, 3, 5, -585, 1, 7, -520, 0, 5, 1262, 1, 4, -1298, 0, 5, 603, 0, 9, -5, 1, 5, -43, 0, 5, 574, 1, 5, -800, 0, 5, 968, 0, 5, -1242, 0, 5, 1062, 1, 5, 115, 0, 3, -1068, 1, 5, -154, 5, 5, 38, 1, 5, -37, 0, 3, 39, 0, 3, 288, 1, 5, 869, 0, 5, -1142, 0, 5, 90, 2, 4, -3, 1, 5, 1031, 3, 5, -608, 1, 7, 662, 0, 5, -1178, 3, 5, 1103, 2, 5, -813, 0, 5, -208, 1, 5, 660, 0, 5, 504, 0, 5, -269, 1, 5, -891, 0, 4, 1124, 1, 5, -132, 1, 5, -500, 0, 10, 675, 1, 5, -1114, 0, 5, 817, 2, 5, -219, 0, 5, 487, 3, 3, -1149, 0, 3, -60, 1, 3, 57, 1, 5, 458, 0, 5, -517, 1, 5, 913, 1, 5, 293, 1, 5, -490, 1, 5, -491, 1, 5, 824, 1, 5, -434, 1, 3, -644, 2, 5, 558, 3, 5, -228, 1, 5, 231, 0, 5, -428, 2, 5, 130, 0, 5, 577, 3, 5, -12, 1, 5, 419, 1, 3, -266, 1, 5, -969, 1, 5, 1043, 1, 5, -89, 2, 5, -847, 3, 5, 1128, 1, 5, -296, 0, 5, 85, 1, 5, 30, 1, 5, 5, 1, 5, -31, 0, 5, -1017, 0, 3, 1253, 0, 4, -926, 0, 5, 698, 2, 5, -219, 1, 5, 9, 0, 5, 12, 2, 5, -742, 1, 5, 6, 0, 4, 173, 1, 5, 721, 4, 5, -166, 0, 5, -298, 1, 5, 11, 0, 5, 452, 1, 5, 274, 3, 4, -245, 0, 5, 218, 3, 5, -215, 0, 5, -241, 3, 5, -268, 4, 5, -220, 2, 5, 298, 5, 5, 427, 1, 5, -451, 0, 5, -4, 1, 5, 460, 0, 5, -1021, 1, 5, 1239, 2, 5, 3, 1, 3, -740, 3, 4, -10, 3, 5, -499, 0, 3, 612, 1, 5, -296, 0, 5, 71, 0, 5, 168, 0, 5, 59, 1, 5, -617, 0, 5, 998, 1, 5, -402, 2, 5, 404, 1, 4, -421, 2, 5, 452, 1, 5, -4, 0, 5, -1035, 1, 3, 337, 1, 5, 72, 0, 5, -413, 1, 5, 561, 2, 5, -66, 1, 5, 147, 0, 5, -61, 1, 5, 38, 2, 5, -118, 1, 5, 509, 0, 5, -589, 2, 5, 270, 0, 4, 321, 1, 4, -522, 1, 4, -341, 2, 9, 393, 1, 5, 111, 1, 5, -105, 0, 5, 22, 2, 5, 472, 3, 5, -554, 0, 4, -381, 1, 4, 371, 0, 5, 561, 1, 5, -936, 1, 5, 57, 1, 9, 371, 1, 5, 29, 1, 5, 109, 6, 5, -127, 1, 5, -428, 1, 5, 55, 0, 9, 873, 0, 5, -594, 1, 5, 591, 0, 5, -579, 1, 5, 10, 2, 4, 47, 2, 5, -393, 0, 4, 886, 4, 5, 1, 1, 5, -885, 0, 5, 380, 5, 5, 536, 1, 5, -3, 2, 5, -530, 0, 5, -368, 7, 4, 264, 4, 5, 90, 3, 5, 544, 0, 5, -548, 2, 5, -255, 2, 5, 472, 0, 5, 301, 5, 5, 2, 3, 5, -793, 5, 7, 504, 1, 5, -494, 9, 9, 552, 2, 3, -5, 0, 5, -39, 2, 5, -238, 2, 5, 5, 0, 7, -266, 3, 8, 558, 9, 3, -5, 0, 5, 214, 1, 5, -545, 1, 5, -14, 2, 5, 72, 0, 6, 239, 1, 6, -313, 1, 5, 599, 7, 5, -238, 2, 5, -332, 0, 5, -93, 0, 5, 660, 0, 5, -27, 1, 4, -482, 1, 5, -100, 2, 5, 580, 3, 5, -526, 3, 5, 291, 1, 5, -409, 2, 5, 452, 0, 5, -454, 2, 6, -88, 0, 7, 505, 1, 5, 262, 1, 5, -4, 1, 5, -624, 0, 5, -56, 2, 5, 191, 3, 6, -265, 2, 6, 549, 1, 5, -431, 3, 5, 391, 1, 5, -280, 1, 5, 281, 0, 5, -449, 2, 6, -51, 2, 6, 214, 0, 5, 501, 4, 4, -767, 0, 4, 325, 3, 5, -263, 3, 6, 224, 0, 5, -142, 1, 5, 134, 2, 5, -136, 0, 5, -76, 1, 5, 506, 2, 5, -501, 3, 7, 505, 1, 5, -271, 5, 4, -175, 0, 3, 170, 0, 5, 316, 1, 5, -271, 0, 5, -2, 3, 5, 248, 6, 5, -472, 1, 5, 474, 1, 6, -477, 0, 5, 517, 2, 3, -277, 2, 5, -251, 7, 5, 502, 4, 3, -479, 0, 5, 519, 1, 4, -5, 1, 5, -51, 2, 5, -219, 2, 5, -27, 9, 4, -2, 1, 5, 240, 0, 5, -192, 5, 6, -2, 1, 5, -33, 8, 5],
54
+ ],
55
+ },
56
+ },
57
+ };
package/dist/context.js CHANGED
@@ -299,7 +299,9 @@ export function blockPlanes(b, prefix) {
299
299
  const ghost = (p) => (b.ghost ? { ...p, shy: [0, 0], fadeAt: -10, fadeTo: 0.16 } : p);
300
300
  // A see-through building: each wall gives way as the eye comes round to its side and looks in, to a trace of itself, and the roof is always nearly clear.
301
301
  const xray = b.xray;
302
- const wall1 = (p) => (xray === undefined ? ghost(p) : { ...shy(p, xray), fadeTo: 0.06, fadeSide: true });
302
+ // A wall of a solid building, nothing showing through it, is hidden by the nearer walls and the roof while it faces away: `cull` says which side of the plane is the building's outside (a wall's `u` x `v` points to the left of its walk, which is in when the ring is wound clockwise).
303
+ const outside = b.ghost || xray !== undefined || wound === 0 ? undefined : wound > 0 ? -1 : 1;
304
+ const wall1 = (p) => (xray === undefined ? (outside === undefined ? ghost(p) : { ...p, cull: outside }) : { ...shy(p, xray), fadeTo: 0.06, fadeSide: true });
303
305
  const roof1 = (p) => (xray === undefined ? ghost(p) : { ...p, shy: [0, 0], fadeAt: -10, fadeTo: 0.1 });
304
306
  b.ring.forEach((p, i) => {
305
307
  const q = b.ring[(i + 1) % b.ring.length];
@@ -181,11 +181,12 @@ export function fit(b, view, w, h, distance, pad = 0.03) {
181
181
  }
182
182
  /** Two matrices as one: `b` first, then `a`. */
183
183
  export function multiply(a, b) {
184
- const out = new Array(16).fill(0);
185
- for (let col = 0; col < 4; col += 1)
184
+ const out = new Array(16);
185
+ for (let col = 0; col < 16; col += 4) {
186
+ const [b0, b1, b2, b3] = [b[col], b[col + 1], b[col + 2], b[col + 3]];
186
187
  for (let row = 0; row < 4; row += 1)
187
- for (let k = 0; k < 4; k += 1)
188
- out[col * 4 + row] += a[k * 4 + row] * b[col * 4 + k];
188
+ out[col + row] = a[row] * b0 + a[4 + row] * b1 + a[8 + row] * b2 + a[12 + row] * b3;
189
+ }
189
190
  return out;
190
191
  }
191
192
  const translation = (x, y, z) => [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
@@ -213,11 +214,20 @@ export function cameraMatrix(view, at, distance) {
213
214
  * surface swelled and shrank in steps.
214
215
  */
215
216
  const num = (value) => {
216
- const text = value.toFixed(10).replace(/\.?0+$/, "");
217
- return text === "-0" || text === "" ? "0" : text;
217
+ if (value === 0)
218
+ return "0";
219
+ const text = value.toFixed(10);
220
+ // Without the zeros at the end, and the point if nothing is left after it: the same text as stripping them with a pattern, a good deal faster for the thousands of numbers a turn writes.
221
+ let end = text.length;
222
+ while (text.charCodeAt(end - 1) === 48)
223
+ end -= 1;
224
+ if (text.charCodeAt(end - 1) === 46)
225
+ end -= 1;
226
+ const out = end === text.length ? text : text.slice(0, end);
227
+ return out === "-0" ? "0" : out;
218
228
  };
219
229
  /** A matrix as the CSS `transform` that applies it. */
220
- export const matrix3d = (m) => `matrix3d(${m.map(num).join(",")})`;
230
+ export const matrix3d = (m) => `matrix3d(${num(m[0])},${num(m[1])},${num(m[2])},${num(m[3])},${num(m[4])},${num(m[5])},${num(m[6])},${num(m[7])},${num(m[8])},${num(m[9])},${num(m[10])},${num(m[11])},${num(m[12])},${num(m[13])},${num(m[14])},${num(m[15])})`;
221
231
  /** How far a point is from the eye's plane after the scene is turned and tipped, in pixels towards the eye: bigger is nearer. Planes are drawn far first. */
222
232
  export function depthOf(point, view, at) {
223
233
  const k = at.k * view.zoom;
package/dist/turn.dom.js CHANGED
@@ -103,11 +103,14 @@ export function mountTurn(host, options, settings, build) {
103
103
  let written = [];
104
104
  let stacked = [];
105
105
  let faded = [];
106
+ /** Which elements are left out of the view now (the faces of a solid that face away from the eye): they are not written to, and drawn at all, till the view turns them round. */
107
+ let gone = [];
106
108
  const gather = () => {
107
109
  elements = [...stage.querySelectorAll(".ky-turn-floor, .ky-up")];
108
110
  written = elements.map((one) => one.style.transform);
109
111
  stacked = elements.map((one) => one.style.zIndex);
110
112
  faded = elements.map((one) => one.style.opacity);
113
+ gone = elements.map(() => false);
111
114
  };
112
115
  gather();
113
116
  // The crowd outside, a canvas on the floor (the floor's matrix carries it), painted again only when its level, its detail or its colour changes.
@@ -135,9 +138,18 @@ export function mountTurn(host, options, settings, build) {
135
138
  const paint = (now) => {
136
139
  const width = stage.clientWidth || 960;
137
140
  const height = stage.clientHeight || 600;
138
- const layout = layoutOf(model, now, width, height, settings.lens);
141
+ const layout = layoutOf(model, now, width, height, settings.lens, true);
139
142
  outside?.zoom(now.zoom);
143
+ const culled = layout.culled;
140
144
  elements.forEach((one, i) => {
145
+ // A face turned away from the eye is hidden by the solid it belongs to: it is taken out of the page's drawing, not written to.
146
+ const away = culled?.[i] === true;
147
+ if (away !== gone[i]) {
148
+ one.style.display = away ? "none" : "";
149
+ gone[i] = away;
150
+ }
151
+ if (away)
152
+ return;
141
153
  if (written[i] !== layout.transforms[i])
142
154
  one.style.transform = written[i] = layout.transforms[i];
143
155
  const z = String(layout.stack[i]);
@@ -40,6 +40,11 @@ export interface Plane {
40
40
  * (a raised room is seen through every wall between it and the eye, at a low angle and from straight above alike).
41
41
  */
42
42
  fadeSide?: boolean;
43
+ /**
44
+ * A face of a closed solid that nothing shows through (a building's wall, drawn opaque): the side of it that is the solid's outside, as the way its `u` x `v` points, 1 out of the solid and -1 into it. While the face is turned away
45
+ * from the eye it is hidden by the solid's own near faces, so a page that asks for it (`layoutOf`'s `cull`) leaves it out of the view until the view turns it round, and spends nothing on it.
46
+ */
47
+ cull?: 1 | -1;
43
48
  /** A plate the other planes of its building stand on (a floor of a building picked out): it is placed by its farthest corner, so that it is drawn under everything on it, whatever way the view turns. */
44
49
  under?: boolean;
45
50
  /**
@@ -17,15 +17,20 @@ export declare function groupRanks(groups: readonly {
17
17
  /** Where everything is for a view in a container: the placement, the matrix of each element and its place in the stack. */
18
18
  export interface Layout {
19
19
  at: Placement;
20
- /** The floor, then the planes in the model's order. */
20
+ /** The floor, then the planes in the model's order. A plane that `cull` says is turned away has `""` here. */
21
21
  transforms: string[];
22
22
  /** The stack of each: 0 for the ground of a hall, 1 for the floor, then the planes far to near from 2. */
23
23
  stack: number[];
24
24
  /** How much of each is left: 1 for all but the walls that are between the eye and the surface, which are cut away as the view is low and on their side (`fadeOf`). */
25
25
  fade: number[];
26
+ /** Which elements are not drawn at this view, by their place in `transforms`: the faces of a closed solid that are turned away from the eye (`Plane.cull`). Only when `layoutOf` was asked to leave them out. */
27
+ culled?: boolean[];
26
28
  }
27
- /** Work a view out in a container `width` by `height` pixels. */
28
- export declare function layoutOf(model: TurnModel, view: TurnView, width: number, height: number, lens?: number): Layout;
29
+ /**
30
+ * Work a view out in a container `width` by `height` pixels. With `cull`, the faces of a closed solid that are turned away from the eye (`Plane.cull`) are left out: they have no transform and no place in the stack, and `culled` says
31
+ * which, so that a page need not write them at all; without it every plane is laid out, as a still picture needs.
32
+ */
33
+ export declare function layoutOf(model: TurnModel, view: TurnView, width: number, height: number, lens?: number, cull?: boolean): Layout;
29
34
  /** One plane as an element: its box in pixels and the SVG drawn on it in feet. */
30
35
  export declare function planeMarkup(p: Plane, scale: number, transform: string, stack: number, fade?: number): string;
31
36
  /**
@@ -53,20 +53,78 @@ export function groupRanks(groups, yaw) {
53
53
  }));
54
54
  return rank;
55
55
  }
56
- /** Work a view out in a container `width` by `height` pixels. */
57
- export function layoutOf(model, view, width, height, lens) {
56
+ const RAD = Math.PI / 180;
57
+ const prepared = new WeakMap();
58
+ function prepare(model) {
59
+ const known = prepared.get(model.planes);
60
+ if (known !== undefined && known.scale === model.scale && known.centre[0] === model.centre[0] && known.centre[1] === model.centre[1])
61
+ return known;
62
+ const s = model.scale;
63
+ const centre = model.centre;
64
+ const base = [];
65
+ const mid = [];
66
+ for (const p of model.planes) {
67
+ if (p.billboard === true) {
68
+ base.push(undefined);
69
+ mid.push(undefined);
70
+ continue;
71
+ }
72
+ base.push(planeMatrix(p, s, centre));
73
+ if (p.under === true) {
74
+ mid.push(undefined);
75
+ continue;
76
+ }
77
+ const zs = [p.o[2], p.o[2] + p.u[2], p.o[2] + p.v[2], p.o[2] + p.u[2] + p.v[2]];
78
+ mid.push([(p.o[0] + (p.u[0] + p.v[0]) / 2 - centre[0]) * s, (p.o[1] + (p.u[1] + p.v[1]) / 2 - centre[1]) * s, (p.o[2] + (p.u[2] + p.v[2]) / 2) * s, Math.min(...zs) * s, Math.max(...zs) * s]);
79
+ }
80
+ const made = { planes: model.planes, scale: s, centre, base, mid };
81
+ prepared.set(model.planes, made);
82
+ return made;
83
+ }
84
+ /**
85
+ * Whether a plane is turned away from the eye, given its matrix: the sign of the determinant of the 3 by 3 map from the plane's own x and y to the screen says which side of it faces the eye (positive: the side that its `u` x `v`
86
+ * points out of), and `Plane.cull` says which side is the solid's outside. A plane edge-on to the eye has no area to draw.
87
+ */
88
+ const turnedAway = (m, side) => side * (m[0] * (m[5] * m[15] - m[13] * m[7]) - m[4] * (m[1] * m[15] - m[13] * m[3]) + m[12] * (m[1] * m[7] - m[5] * m[3])) <= 0;
89
+ /**
90
+ * Work a view out in a container `width` by `height` pixels. With `cull`, the faces of a closed solid that are turned away from the eye (`Plane.cull`) are left out: they have no transform and no place in the stack, and `culled` says
91
+ * which, so that a page need not write them at all; without it every plane is laid out, as a still picture needs.
92
+ */
93
+ export function layoutOf(model, view, width, height, lens, cull = false) {
58
94
  const distance = eyeDistance(width, height, lens ?? model.lens);
59
95
  const at = fit(model.box, { ...view, zoom: 1 }, width, height, distance);
60
96
  const camera = cameraMatrix(view, at, distance);
61
97
  const s = model.scale;
62
98
  const centre = model.centre;
99
+ const known = prepare(model);
63
100
  const floor = { id: "floor", kind: "ground", o: [model.viewBox.x, model.viewBox.y, model.uprights.lift], u: [model.viewBox.w, 0, 0], v: [0, model.viewBox.h, 0], svg: "" };
101
+ const count = model.planes.length;
102
+ const transforms = new Array(count + 1);
103
+ const culled = cull ? new Array(count + 1).fill(false) : undefined;
64
104
  // A billboard faces the eye at this view.
65
- const planes = model.planes.map((p) => facing(p, view.yaw, view.pitch));
66
- const transforms = [floor, ...planes].map((p) => matrix3d(multiply(camera, planeMatrix(p, s, centre))));
105
+ const planes = new Array(count);
106
+ for (let i = 0; i < count; i += 1)
107
+ planes[i] = facing(model.planes[i], view.yaw, view.pitch);
108
+ transforms[0] = matrix3d(multiply(camera, planeMatrix(floor, s, centre)));
109
+ for (let i = 0; i < count; i += 1) {
110
+ const m = multiply(camera, known.base[i] ?? planeMatrix(planes[i], s, centre));
111
+ const side = planes[i].cull;
112
+ if (culled !== undefined && side !== undefined && turnedAway(m, side)) {
113
+ culled[i + 1] = true;
114
+ transforms[i + 1] = "";
115
+ }
116
+ else
117
+ transforms[i + 1] = matrix3d(m);
118
+ }
67
119
  // Far to near: a plane's depth is that of its middle. The ground of a hall is under everything. The floor is next, unless it stands raised on something (a table tennis table's top, on its legs): then it is
68
120
  // sorted with the rest, by its middle, so that the legs and the skirt on the far side are drawn under it and the ones on the near side over it, and nothing under the top shows through it.
69
- const depth = (p) => {
121
+ const [sinYaw, cosYaw, sinPitch, cosPitch] = [Math.sin(view.yaw * RAD), Math.cos(view.yaw * RAD), Math.sin(view.pitch * RAD), Math.cos(view.pitch * RAD)];
122
+ const k = at.k * view.zoom;
123
+ const depthAt = (x, y, z) => (x * k * sinYaw + y * k * cosYaw) * sinPitch + z * k * cosPitch;
124
+ const depth = (p, i) => {
125
+ const pre = i < 0 ? undefined : known.mid[i];
126
+ if (pre !== undefined)
127
+ return depthAt(pre[0], pre[1], p.fadeSide === true ? (fadeOf(p, view.yaw, view.pitch) >= 1 ? pre[3] : pre[4]) : pre[2]);
70
128
  // A see-through building's wall is a tall plane round what stands in it: a far wall is behind all of it and a near one in front of all of it, however high its middle is, so a far wall is placed by its foot and a near one by its top.
71
129
  const zs = [p.o[2], p.o[2] + p.u[2], p.o[2] + p.v[2], p.o[2] + p.u[2] + p.v[2]];
72
130
  const z = p.fadeSide === true ? (fadeOf(p, view.yaw, view.pitch) >= 1 ? Math.min(...zs) : Math.max(...zs)) : (p.o[2] + (p.u[2] + p.v[2]) / 2);
@@ -75,7 +133,12 @@ export function layoutOf(model, view, width, height, lens) {
75
133
  return depthOf([(p.o[0] + (p.u[0] + p.v[0]) / 2 - centre[0]) * s, (p.o[1] + (p.u[1] + p.v[1]) / 2 - centre[1]) * s, z * s], view, at);
76
134
  };
77
135
  const raised = model.uprights.lift > 0;
78
- const order = [...planes.map((p, i) => ({ i: i + 1, ground: p.kind === "ground", depth: depth(p), group: p.group })), ...(raised ? [{ i: 0, ground: false, depth: depth(floor), group: undefined }] : [])].filter((one) => !one.ground);
136
+ const order = [];
137
+ for (let i = 0; i < count; i += 1)
138
+ if (planes[i].kind !== "ground" && culled?.[i + 1] !== true)
139
+ order.push({ i: i + 1, depth: depth(planes[i], i), group: planes[i].group });
140
+ if (raised)
141
+ order.push({ i: 0, depth: depth(floor, -1), group: undefined });
79
142
  // Buildings that stand apart are drawn one after another, the far one first; a plane of none (the floor) goes by its depth alone.
80
143
  const rank = model.groups === undefined ? undefined : groupRanks(model.groups, view.yaw);
81
144
  // The planes of the blocks that stand round the buildings (`APART`) are stacked by depth among themselves and then woven into the buildings' by depth, each list keeping its own order.
@@ -84,13 +147,16 @@ export function layoutOf(model, view, width, height, lens) {
84
147
  order.length = 0;
85
148
  for (let i = 0, j = 0; i < own.length || j < apart.length;)
86
149
  order.push(j >= apart.length || (i < own.length && own[i].depth <= apart[j].depth) ? own[i++] : apart[j++]);
87
- const stack = new Array(model.planes.length + 1).fill(0);
150
+ const stack = new Array(count + 1).fill(0);
88
151
  stack[0] = 1;
89
152
  order.forEach((one, rank) => {
90
153
  stack[one.i] = rank + 2;
91
154
  });
92
- const fade = [1, ...model.planes.map((p) => fadeOf(p, view.yaw, view.pitch))];
93
- return { at, transforms, stack, fade };
155
+ const fade = new Array(count + 1);
156
+ fade[0] = 1;
157
+ for (let i = 0; i < count; i += 1)
158
+ fade[i + 1] = fadeOf(model.planes[i], view.yaw, view.pitch);
159
+ return { at, transforms, stack, fade, ...(culled === undefined ? {} : { culled }) };
94
160
  }
95
161
  /** One plane as an element: its box in pixels and the SVG drawn on it in feet. */
96
162
  export function planeMarkup(p, scale, transform, stack, fade = 1) {
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** The package's version: the same as package.json's, and a test holds them to each other. */
2
- export declare const VERSION = "0.44.1";
2
+ export declare const VERSION = "0.44.2";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** The package's version: the same as package.json's, and a test holds them to each other. */
2
- export const VERSION = "0.44.1";
2
+ export const VERSION = "0.44.2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnmorrisdotca/kyogijo-stadiums",
3
- "version": "0.44.1",
3
+ "version": "0.44.2",
4
4
  "description": "Kyogijo Stadiums 競技場, 40 sports' surfaces as SVG, drawn to scale from the rulebooks: NFL, CFL and IFAF football fields, an NHL rink, an NBA court, MLB ballparks, soccer pitches, curling sheets, athletics stadiums, speed skating, short track and figure skating rinks, swimming pools, water polo fields, diving wells, artistic swimming areas, and the courts and fields of tennis, volleyball (indoor, beach and sitting), badminton, pickleball, table tennis, padel, squash, racquetball, sepak takraw, teqball, roundnet, netball, lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey and handball, and the budo of judo, karate, kendo, sumo and kyudo with a dojo of tatami laid as real units, the MMA cage, with each team's name and logo on its side and the score in the middle, stands and a crowd, a pageant of flags, and a 3D view. Light and dark, accessible, a compact badge for lists, a helper for React and a custom element. Zero dependencies.",
5
5
  "keywords": [
6
6
  "sports",
@@ -153,6 +153,11 @@
153
153
  "import": "./dist/cityctx-entry.js",
154
154
  "default": "./dist/cityctx-entry.js"
155
155
  },
156
+ "./areas": {
157
+ "types": "./dist/areas-entry.d.ts",
158
+ "import": "./dist/areas-entry.js",
159
+ "default": "./dist/areas-entry.js"
160
+ },
156
161
  "./osm": {
157
162
  "types": "./dist/osm-entry.d.ts",
158
163
  "import": "./dist/osm-entry.js",