@johnmorrisdotca/kyogijo-stadiums 0.47.0 → 0.48.1
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/CHANGELOG.md +39 -0
- package/NOTICE.md +2 -0
- package/README.md +112 -474
- package/dist/crowd.d.ts +11 -0
- package/dist/turn.style.js +13 -3
- package/dist/venue.real.d.ts +1 -4
- package/dist/venue.real.js +18 -12
- package/dist/venue.saddle.d.ts +48 -0
- package/dist/venue.saddle.js +218 -0
- package/dist/venues/scotiabank-saddledome.data.js +2 -1
- package/dist/venues.d.ts +21 -2
- package/dist/venues.data.js +2 -1
- package/dist/venues.js +38 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
package/dist/crowd.d.ts
CHANGED
|
@@ -179,6 +179,17 @@ export interface RealShell {
|
|
|
179
179
|
};
|
|
180
180
|
/** The height of the roof's lowest edge above the surface, in feet. */
|
|
181
181
|
edge: number;
|
|
182
|
+
/**
|
|
183
|
+
* A `saddle` roof's measure, in the drawing's frame: the middle of its round plan and its radius, the unit direction of the line through its two high points, the height of those points (`high`) and of the low rim between them
|
|
184
|
+
* (`low`), in feet over the surface. The roof is the hyperbolic paraboloid through them (`venue.saddle.ts`), and the building round it is round.
|
|
185
|
+
*/
|
|
186
|
+
saddle?: {
|
|
187
|
+
centre: Pt;
|
|
188
|
+
radius: number;
|
|
189
|
+
axis: Pt;
|
|
190
|
+
low: number;
|
|
191
|
+
high: number;
|
|
192
|
+
};
|
|
182
193
|
/** Towers that stand apart from the bowl (Lumen Field's, at the open end), each a box on its outline in the drawing's frame, `height` feet high; `face` is the unit direction its scoreboard looks, towards the field. */
|
|
183
194
|
towers?: {
|
|
184
195
|
ring: Pt[];
|
package/dist/turn.style.js
CHANGED
|
@@ -5,9 +5,9 @@ import { KYOGIJO_TURN_BOARD_STYLE } from "./overlay.js";
|
|
|
5
5
|
* defaults are in `:where()`, which has no weight, so a page's own rule always wins; the colours are custom properties (`--ky-up-*`) a page can set.
|
|
6
6
|
*/
|
|
7
7
|
export const KYOGIJO_TURN_STYLE = `
|
|
8
|
-
:where(.ky-turn){--ky-left:#2f6db0;--ky-right:#b5452c;--ky-cr-home:#b5452c;--ky-cr-away:#2f6db0;--ky-cr-bed:#4a525d;--ky-cr-empty:#7d8794;--ky-cr-gap:#14181d;--ky-cr-conc:#8c929b;--ky-cr-dim:1;--ky-up-roof:rgba(214,218,212,.6);--ky-up-roofline:rgba(40,46,42,.55);--ky-up-fascia:#9aa09a;--ky-up-ivy:#5b8a45;--ky-up-brick:#a8604a;--ky-up-canopy:rgba(232,235,230,.9);--ky-up-door:#8a6a46;--ky-up-window:rgba(150,200,240,.55);--ky-up-sash:#f2f0e6;--ky-up-banner:#26211d;--ky-up-bannerline:#c8b88a;--ky-up-room:#efe8d6;--ky-up-roomback:#d6cdb9;--ky-up-ceiling:#dedcd5;--ky-up-railw:#fbfaf6;--ky-up-wainline:#6b4a2a;--ky-up-riser:#3f342c;--ky-up-slab:#d8cfba;--ky-up-slabedge:#c2b69c;--ky-up-seatc:#46342a;--ky-up-seatb:#2d211b;--ky-up-dais:#a0683a;--ky-up-dais-side:#6a4326;--ky-up-shrine:#c9b48f;--ky-up-shrine-side:#8f7a55;--ky-up-gal:#4d4037;--ky-up-aisle:#dcc196;--ky-up-panel:rgba(95,58,22,.3);--ky-up-alcove:#b58a52;--ky-up-purple:#5b2a6e;--ky-up-clock:#ffffff;--ky-up-rail:#3a2c1f;--ky-up-matedge:#2a2a26;--ky-up-sbframe:#1a1f1c;--ky-up-sbedge:#5b645e;--ky-up-sbline:#59615b;--ky-up-pole:#e9e7de;--ky-up-white:#f6f4ec;--ky-up-yellow:#f2c230;--ky-up-red:#c8372d;--ky-up-orange:#f26a1b;--ky-up-wood:#e3d4b4;--ky-up-leg:#474e49;--ky-up-pad:#2f6db0;--ky-up-cagepad:#2a2d32;--ky-up-table:#18243f;--ky-up-foot:rgba(0,0,0,.25);--ky-up-ground:#d9d5c7;--ky-up-wall:#2f4a36;--ky-up-clay:#a8703f;--ky-up-cap:#1d2a22;--ky-up-board:#ece9df;--ky-up-glass:rgba(138,190,232,.26);--ky-up-backboard:rgba(255,255,255,.88);--ky-up-outline:#f2f0e6;--ky-up-rim:#e8591a;--ky-up-mesh:rgba(24,30,27,.7);--ky-up-netfill:rgba(255,255,255,.2);--ky-up-tape:#fbfaf4;--ky-turn-bg:transparent;--ky-turn-ink:#1f2320;--ky-turn-rule:rgba(31,35,32,.22);--ky-turn-chip:rgba(255,255,255,.86);--ky-turn-chip-on:#1f2320;--ky-turn-chip-on-ink:#fff;${JUDGING_LIGHT};--ky-up-blk-a:#e9ece4;--ky-up-blk-b:#c9cdc3;--ky-up-blk-c:#a4aa9f;--ky-up-blk-roof:#f4f5f0;--ky-up-blk-line:rgba(40,46,42,.38);--ky-up-plate:rgba(47,109,176,.5);--ky-up-plate-line:#2f6db0}
|
|
9
|
-
@media (prefers-color-scheme:dark){:where(html:not([data-theme=light]) .ky-turn:not([data-theme=light])){--ky-cr-bed:#242a32;--ky-cr-empty:#4a535f;--ky-cr-gap:#050709;--ky-cr-conc:#2a3038;--ky-cr-dim:.82;--ky-up-roof:rgba(60,66,62,.6);--ky-up-roofline:rgba(200,206,200,.5);--ky-up-fascia:#505650;--ky-up-ivy:#3d6633;--ky-up-brick:#7a4434;--ky-up-canopy:rgba(78,84,80,.9);--ky-up-door:#6a4f33;--ky-up-gal:#2d2621;--ky-up-aisle:#8f7752;--ky-up-alcove:#7d5c36;--ky-up-purple:#43204f;--ky-up-clock:#cfcbc0;--ky-up-room:#6d675a;--ky-up-roomback:#58534a;--ky-up-ceiling:#8c8a82;--ky-up-railw:#d9d6cc;--ky-up-riser:#251f1b;--ky-up-slab:#6b6455;--ky-up-slabedge:#585143;--ky-up-seatc:#2f231c;--ky-up-seatb:#1c1411;--ky-up-dais:#7d5230;--ky-up-dais-side:#52361f;--ky-up-sbframe:#0c0f0d;--ky-up-sbedge:#7a847d;--ky-up-sbline:#8a928c;--ky-up-pole:#d6d4ca;--ky-up-white:#e8e6dc;--ky-up-wood:#a89873;--ky-up-leg:#8a928c;--ky-up-ground:#242823;--ky-up-cagepad:#8f969f;--ky-up-wall:#4d6b55;--ky-up-clay:#7d5231;--ky-up-cap:#c9d2cc;--ky-up-board:#8d928b;--ky-up-glass:rgba(150,200,240,.2);--ky-up-backboard:rgba(255,255,255,.34);--ky-up-outline:#e7e4d8;--ky-up-mesh:rgba(236,236,226,.62);--ky-up-netfill:rgba(255,255,255,.08);--ky-up-tape:#efede2;--ky-turn-ink:#ece8dc;--ky-turn-rule:rgba(236,232,220,.28);--ky-turn-chip:rgba(24,28,25,.82);--ky-turn-chip-on:#ece8dc;--ky-turn-chip-on-ink:#1f2320;${JUDGING_DARK};--ky-up-blk-a:#59626b;--ky-up-blk-b:#444b53;--ky-up-blk-c:#30363c;--ky-up-blk-roof:#69727b;--ky-up-blk-line:rgba(220,226,220,.3);--ky-up-plate:rgba(127,176,232,.45);--ky-up-plate-line:#7fb0e8}}
|
|
10
|
-
:where(html[data-theme=dark] .ky-turn,.ky-turn[data-theme=dark]){--ky-cr-bed:#242a32;--ky-cr-empty:#4a535f;--ky-cr-gap:#050709;--ky-cr-conc:#2a3038;--ky-cr-dim:.82;--ky-up-roof:rgba(60,66,62,.6);--ky-up-roofline:rgba(200,206,200,.5);--ky-up-fascia:#505650;--ky-up-ivy:#3d6633;--ky-up-brick:#7a4434;--ky-up-canopy:rgba(78,84,80,.9);--ky-up-door:#6a4f33;--ky-up-gal:#2d2621;--ky-up-aisle:#8f7752;--ky-up-alcove:#7d5c36;--ky-up-purple:#43204f;--ky-up-clock:#cfcbc0;--ky-up-room:#6d675a;--ky-up-roomback:#58534a;--ky-up-ceiling:#8c8a82;--ky-up-railw:#d9d6cc;--ky-up-riser:#251f1b;--ky-up-slab:#6b6455;--ky-up-slabedge:#585143;--ky-up-seatc:#2f231c;--ky-up-seatb:#1c1411;--ky-up-dais:#7d5230;--ky-up-dais-side:#52361f;--ky-up-sbframe:#0c0f0d;--ky-up-sbedge:#7a847d;--ky-up-sbline:#8a928c;--ky-up-pole:#d6d4ca;--ky-up-white:#e8e6dc;--ky-up-wood:#a89873;--ky-up-leg:#8a928c;--ky-up-ground:#242823;--ky-up-cagepad:#8f969f;--ky-up-wall:#4d6b55;--ky-up-clay:#7d5231;--ky-up-cap:#c9d2cc;--ky-up-board:#8d928b;--ky-up-glass:rgba(150,200,240,.2);--ky-up-backboard:rgba(255,255,255,.34);--ky-up-outline:#e7e4d8;--ky-up-mesh:rgba(236,236,226,.62);--ky-up-netfill:rgba(255,255,255,.08);--ky-up-tape:#efede2;--ky-turn-ink:#ece8dc;--ky-turn-rule:rgba(236,232,220,.28);--ky-turn-chip:rgba(24,28,25,.82);--ky-turn-chip-on:#ece8dc;--ky-turn-chip-on-ink:#1f2320;${JUDGING_DARK};--ky-up-blk-a:#59626b;--ky-up-blk-b:#444b53;--ky-up-blk-c:#30363c;--ky-up-blk-roof:#69727b;--ky-up-blk-line:rgba(220,226,220,.3);--ky-up-plate:rgba(127,176,232,.45);--ky-up-plate-line:#7fb0e8}
|
|
8
|
+
:where(.ky-turn){--ky-up-saddle:#ecebe4;--ky-up-saddle-wall:#c6c9c3;--ky-up-saddle-beam:#d8dad4;--ky-left:#2f6db0;--ky-right:#b5452c;--ky-cr-home:#b5452c;--ky-cr-away:#2f6db0;--ky-cr-bed:#4a525d;--ky-cr-empty:#7d8794;--ky-cr-gap:#14181d;--ky-cr-conc:#8c929b;--ky-cr-dim:1;--ky-up-roof:rgba(214,218,212,.6);--ky-up-roofline:rgba(40,46,42,.55);--ky-up-fascia:#9aa09a;--ky-up-ivy:#5b8a45;--ky-up-brick:#a8604a;--ky-up-canopy:rgba(232,235,230,.9);--ky-up-door:#8a6a46;--ky-up-window:rgba(150,200,240,.55);--ky-up-sash:#f2f0e6;--ky-up-banner:#26211d;--ky-up-bannerline:#c8b88a;--ky-up-room:#efe8d6;--ky-up-roomback:#d6cdb9;--ky-up-ceiling:#dedcd5;--ky-up-railw:#fbfaf6;--ky-up-wainline:#6b4a2a;--ky-up-riser:#3f342c;--ky-up-slab:#d8cfba;--ky-up-slabedge:#c2b69c;--ky-up-seatc:#46342a;--ky-up-seatb:#2d211b;--ky-up-dais:#a0683a;--ky-up-dais-side:#6a4326;--ky-up-shrine:#c9b48f;--ky-up-shrine-side:#8f7a55;--ky-up-gal:#4d4037;--ky-up-aisle:#dcc196;--ky-up-panel:rgba(95,58,22,.3);--ky-up-alcove:#b58a52;--ky-up-purple:#5b2a6e;--ky-up-clock:#ffffff;--ky-up-rail:#3a2c1f;--ky-up-matedge:#2a2a26;--ky-up-sbframe:#1a1f1c;--ky-up-sbedge:#5b645e;--ky-up-sbline:#59615b;--ky-up-pole:#e9e7de;--ky-up-white:#f6f4ec;--ky-up-yellow:#f2c230;--ky-up-red:#c8372d;--ky-up-orange:#f26a1b;--ky-up-wood:#e3d4b4;--ky-up-leg:#474e49;--ky-up-pad:#2f6db0;--ky-up-cagepad:#2a2d32;--ky-up-table:#18243f;--ky-up-foot:rgba(0,0,0,.25);--ky-up-ground:#d9d5c7;--ky-up-wall:#2f4a36;--ky-up-clay:#a8703f;--ky-up-cap:#1d2a22;--ky-up-board:#ece9df;--ky-up-glass:rgba(138,190,232,.26);--ky-up-backboard:rgba(255,255,255,.88);--ky-up-outline:#f2f0e6;--ky-up-rim:#e8591a;--ky-up-mesh:rgba(24,30,27,.7);--ky-up-netfill:rgba(255,255,255,.2);--ky-up-tape:#fbfaf4;--ky-turn-bg:transparent;--ky-turn-ink:#1f2320;--ky-turn-rule:rgba(31,35,32,.22);--ky-turn-chip:rgba(255,255,255,.86);--ky-turn-chip-on:#1f2320;--ky-turn-chip-on-ink:#fff;${JUDGING_LIGHT};--ky-up-blk-a:#e9ece4;--ky-up-blk-b:#c9cdc3;--ky-up-blk-c:#a4aa9f;--ky-up-blk-roof:#f4f5f0;--ky-up-blk-line:rgba(40,46,42,.38);--ky-up-plate:rgba(47,109,176,.5);--ky-up-plate-line:#2f6db0}
|
|
9
|
+
@media (prefers-color-scheme:dark){:where(html:not([data-theme=light]) .ky-turn:not([data-theme=light])){--ky-up-saddle:#aeb1ab;--ky-up-saddle-wall:#7e847f;--ky-up-saddle-beam:#979c97;--ky-cr-bed:#242a32;--ky-cr-empty:#4a535f;--ky-cr-gap:#050709;--ky-cr-conc:#2a3038;--ky-cr-dim:.82;--ky-up-roof:rgba(60,66,62,.6);--ky-up-roofline:rgba(200,206,200,.5);--ky-up-fascia:#505650;--ky-up-ivy:#3d6633;--ky-up-brick:#7a4434;--ky-up-canopy:rgba(78,84,80,.9);--ky-up-door:#6a4f33;--ky-up-gal:#2d2621;--ky-up-aisle:#8f7752;--ky-up-alcove:#7d5c36;--ky-up-purple:#43204f;--ky-up-clock:#cfcbc0;--ky-up-room:#6d675a;--ky-up-roomback:#58534a;--ky-up-ceiling:#8c8a82;--ky-up-railw:#d9d6cc;--ky-up-riser:#251f1b;--ky-up-slab:#6b6455;--ky-up-slabedge:#585143;--ky-up-seatc:#2f231c;--ky-up-seatb:#1c1411;--ky-up-dais:#7d5230;--ky-up-dais-side:#52361f;--ky-up-sbframe:#0c0f0d;--ky-up-sbedge:#7a847d;--ky-up-sbline:#8a928c;--ky-up-pole:#d6d4ca;--ky-up-white:#e8e6dc;--ky-up-wood:#a89873;--ky-up-leg:#8a928c;--ky-up-ground:#242823;--ky-up-cagepad:#8f969f;--ky-up-wall:#4d6b55;--ky-up-clay:#7d5231;--ky-up-cap:#c9d2cc;--ky-up-board:#8d928b;--ky-up-glass:rgba(150,200,240,.2);--ky-up-backboard:rgba(255,255,255,.34);--ky-up-outline:#e7e4d8;--ky-up-mesh:rgba(236,236,226,.62);--ky-up-netfill:rgba(255,255,255,.08);--ky-up-tape:#efede2;--ky-turn-ink:#ece8dc;--ky-turn-rule:rgba(236,232,220,.28);--ky-turn-chip:rgba(24,28,25,.82);--ky-turn-chip-on:#ece8dc;--ky-turn-chip-on-ink:#1f2320;${JUDGING_DARK};--ky-up-blk-a:#59626b;--ky-up-blk-b:#444b53;--ky-up-blk-c:#30363c;--ky-up-blk-roof:#69727b;--ky-up-blk-line:rgba(220,226,220,.3);--ky-up-plate:rgba(127,176,232,.45);--ky-up-plate-line:#7fb0e8}}
|
|
10
|
+
:where(html[data-theme=dark] .ky-turn,.ky-turn[data-theme=dark]){--ky-up-saddle:#aeb1ab;--ky-up-saddle-wall:#7e847f;--ky-up-saddle-beam:#979c97;--ky-cr-bed:#242a32;--ky-cr-empty:#4a535f;--ky-cr-gap:#050709;--ky-cr-conc:#2a3038;--ky-cr-dim:.82;--ky-up-roof:rgba(60,66,62,.6);--ky-up-roofline:rgba(200,206,200,.5);--ky-up-fascia:#505650;--ky-up-ivy:#3d6633;--ky-up-brick:#7a4434;--ky-up-canopy:rgba(78,84,80,.9);--ky-up-door:#6a4f33;--ky-up-gal:#2d2621;--ky-up-aisle:#8f7752;--ky-up-alcove:#7d5c36;--ky-up-purple:#43204f;--ky-up-clock:#cfcbc0;--ky-up-room:#6d675a;--ky-up-roomback:#58534a;--ky-up-ceiling:#8c8a82;--ky-up-railw:#d9d6cc;--ky-up-riser:#251f1b;--ky-up-slab:#6b6455;--ky-up-slabedge:#585143;--ky-up-seatc:#2f231c;--ky-up-seatb:#1c1411;--ky-up-dais:#7d5230;--ky-up-dais-side:#52361f;--ky-up-sbframe:#0c0f0d;--ky-up-sbedge:#7a847d;--ky-up-sbline:#8a928c;--ky-up-pole:#d6d4ca;--ky-up-white:#e8e6dc;--ky-up-wood:#a89873;--ky-up-leg:#8a928c;--ky-up-ground:#242823;--ky-up-cagepad:#8f969f;--ky-up-wall:#4d6b55;--ky-up-clay:#7d5231;--ky-up-cap:#c9d2cc;--ky-up-board:#8d928b;--ky-up-glass:rgba(150,200,240,.2);--ky-up-backboard:rgba(255,255,255,.34);--ky-up-outline:#e7e4d8;--ky-up-mesh:rgba(236,236,226,.62);--ky-up-netfill:rgba(255,255,255,.08);--ky-up-tape:#efede2;--ky-turn-ink:#ece8dc;--ky-turn-rule:rgba(236,232,220,.28);--ky-turn-chip:rgba(24,28,25,.82);--ky-turn-chip-on:#ece8dc;--ky-turn-chip-on-ink:#1f2320;${JUDGING_DARK};--ky-up-blk-a:#59626b;--ky-up-blk-b:#444b53;--ky-up-blk-c:#30363c;--ky-up-blk-roof:#69727b;--ky-up-blk-line:rgba(220,226,220,.3);--ky-up-plate:rgba(127,176,232,.45);--ky-up-plate-line:#7fb0e8}
|
|
11
11
|
.ky-turn{position:relative;display:block;width:100%;color:var(--ky-turn-ink);font-family:var(--ky-font,system-ui,-apple-system,"Segoe UI","Hiragino Sans","Noto Sans JP",sans-serif);background:var(--ky-turn-bg)}
|
|
12
12
|
.ky-turn-view{position:relative;isolation:isolate;width:100%;aspect-ratio:var(--ky-turn-ratio,16/10);min-height:260px;overflow:hidden;touch-action:pan-y;cursor:grab;user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent;border-radius:12px;outline-offset:2px}
|
|
13
13
|
.ky-turn[data-touch=turn] .ky-turn-view{touch-action:none}
|
|
@@ -94,6 +94,16 @@ export const KYOGIJO_TURN_STYLE = `
|
|
|
94
94
|
.ky-turn .u-proxy-c{fill:color-mix(in srgb,var(--ky-up-blk-c) 52%,#324b72)}
|
|
95
95
|
.ky-turn .u-proxy-roof{fill:color-mix(in srgb,var(--ky-up-blk-roof) 60%,#5f7fae);stroke:var(--ky-up-blk-line);stroke-width:.6;stroke-linejoin:round}
|
|
96
96
|
.ky-turn .u-roof{fill:var(--ky-up-roof);stroke:var(--ky-up-roofline);stroke-width:.8;stroke-linejoin:round}
|
|
97
|
+
/* The Saddledome's building (venue.saddle.ts): the roof's net of quads, its beam, the pier between two panels, and the veils of shade and light that give each facet its tone. */
|
|
98
|
+
.ky-turn .u-saddle{fill:var(--ky-up-saddle);stroke:var(--ky-up-roofline);stroke-width:.3;stroke-linejoin:round}
|
|
99
|
+
.ky-turn .u-saddle-beam{fill:var(--ky-up-saddle-beam);stroke:var(--ky-up-roofline);stroke-width:.4;stroke-linejoin:round}
|
|
100
|
+
.ky-turn .u-saddle-wall{fill:var(--ky-up-saddle-wall);stroke:var(--ky-up-roofline);stroke-width:.3;stroke-linejoin:round}
|
|
101
|
+
.ky-turn .u-pier{fill:none;stroke:color-mix(in srgb,var(--ky-up-white) 55%,var(--ky-up-fascia));stroke-width:3}
|
|
102
|
+
.ky-turn .u-clad{stroke:var(--ky-up-roofline);stroke-width:.3;stroke-opacity:.5}
|
|
103
|
+
.ky-turn .u-stair-round{fill:var(--ky-up-yellow);stroke:var(--ky-up-roofline);stroke-width:.4}
|
|
104
|
+
.ky-turn .u-stair-square{fill:var(--ky-up-red);stroke:var(--ky-up-roofline);stroke-width:.4}
|
|
105
|
+
.ky-turn .u-shade{fill:#000}
|
|
106
|
+
.ky-turn .u-lite{fill:#fff}
|
|
97
107
|
.ky-turn .u-signplate{fill:var(--ky-turn-bg);fill-opacity:.9;stroke:var(--ky-turn-rule);stroke-width:.5}
|
|
98
108
|
.ky-turn .u-sign{fill:var(--ky-turn-ink);font-family:var(--ky-font,system-ui,-apple-system,"Segoe UI","Hiragino Sans","Noto Sans JP",sans-serif);font-weight:600}
|
|
99
109
|
.ky-turn .u-mast{fill:var(--ky-up-fascia);stroke:var(--ky-up-roofline);stroke-width:.4}
|
package/dist/venue.real.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { type Pt, type RealShell, type StandRing } from "./crowd.ts";
|
|
2
2
|
import { type Plane, type Upright, type V3 } from "./turn.kit.ts";
|
|
3
|
-
/** How far a lid rises from its edge towards the middle,
|
|
3
|
+
/** How far a lid rises from its edge towards the middle, in feet (ours: the sources give a roof's kind, not its height). */
|
|
4
4
|
export declare const LID_RISE = 22;
|
|
5
|
-
export declare const SADDLE_RISE = 30;
|
|
6
5
|
/** How far a barrel vault's crown stands over its springing at the long sides, in feet (ours: the article says the roof looks like a Quonset hut, not how high it rises). */
|
|
7
6
|
export declare const BARREL_RISE = 34;
|
|
8
|
-
/** The saddle's share of its rise at a point (0 at the middle of a side, 1 at the middle of an end): half a saddle's way from one to the other, as a hyperbolic paraboloid (u squared less v squared) lies over the building's box. */
|
|
9
|
-
export declare function saddleAt(real: Pick<RealShell, "footprint">, [x, y]: Pt): number;
|
|
10
7
|
/** The barrel vault's share of its rise at a point (0 at the springing along each long side, 1 over the middle line): a round arch over the building's short axis, the quarter of a circle's rise at each step in from the side. */
|
|
11
8
|
export declare function barrelAt(real: Pick<RealShell, "footprint">, [, y]: Pt): number;
|
|
12
9
|
/** The height of the roof over a point of the building's edge, above the surface, in feet. */
|
package/dist/venue.real.js
CHANGED
|
@@ -7,21 +7,12 @@ import { rayAt } from "./crowd.js";
|
|
|
7
7
|
import { bar, box, n, pole, shy, wall } from "./turn.kit.js";
|
|
8
8
|
import { pointList, raked } from "./venue.geom.js";
|
|
9
9
|
import { ribbedRoof, ribbedWalls } from "./venue.ribbed.js";
|
|
10
|
+
import { SADDLE_CELLS, saddleHeight, saddleRoof, saddleTowers, saddleWalls } from "./venue.saddle.js";
|
|
10
11
|
import { edgeDistance, inside } from "./venues.geo.js";
|
|
11
|
-
/** How far a lid rises from its edge towards the middle,
|
|
12
|
+
/** How far a lid rises from its edge towards the middle, in feet (ours: the sources give a roof's kind, not its height). */
|
|
12
13
|
export const LID_RISE = 22;
|
|
13
|
-
export const SADDLE_RISE = 30;
|
|
14
14
|
/** How far a barrel vault's crown stands over its springing at the long sides, in feet (ours: the article says the roof looks like a Quonset hut, not how high it rises). */
|
|
15
15
|
export const BARREL_RISE = 34;
|
|
16
|
-
/** The saddle's share of its rise at a point (0 at the middle of a side, 1 at the middle of an end): half a saddle's way from one to the other, as a hyperbolic paraboloid (u squared less v squared) lies over the building's box. */
|
|
17
|
-
export function saddleAt(real, [x, y]) {
|
|
18
|
-
const xs = real.footprint.map((p) => p[0]);
|
|
19
|
-
const ys = real.footprint.map((p) => p[1]);
|
|
20
|
-
const [cx, cy] = [(Math.min(...xs) + Math.max(...xs)) / 2, (Math.min(...ys) + Math.max(...ys)) / 2];
|
|
21
|
-
const [hx, hy] = [(Math.max(...xs) - Math.min(...xs)) / 2, (Math.max(...ys) - Math.min(...ys)) / 2];
|
|
22
|
-
const s = ((x - cx) / hx) ** 2 - ((y - cy) / hy) ** 2;
|
|
23
|
-
return (1 + Math.max(-1, Math.min(1, s))) / 2;
|
|
24
|
-
}
|
|
25
16
|
/** The barrel vault's share of its rise at a point (0 at the springing along each long side, 1 over the middle line): a round arch over the building's short axis, the quarter of a circle's rise at each step in from the side. */
|
|
26
17
|
export function barrelAt(real, [, y]) {
|
|
27
18
|
const ys = real.footprint.map((p) => p[1]);
|
|
@@ -30,7 +21,7 @@ export function barrelAt(real, [, y]) {
|
|
|
30
21
|
return Math.sqrt(1 - v * v);
|
|
31
22
|
}
|
|
32
23
|
/** The height of the roof over a point of the building's edge, above the surface, in feet. */
|
|
33
|
-
export const roofAt = (real, p) =>
|
|
24
|
+
export const roofAt = (real, p) => (real.roof === "saddle" && real.saddle !== undefined ? saddleHeight(real.saddle, p) : real.edge + (real.roof === "barrel" ? BARREL_RISE * barrelAt(real, p) : 0));
|
|
34
25
|
/** How near a wall must stand to a canopy's outline to be the wall under it, in feet. */
|
|
35
26
|
const CANOPY_REACH = 50;
|
|
36
27
|
/** The height of the wall of a building under canopies at a point of its rim: where a canopy is over it, the canopy's back edge, which the wall carries up to (the outside of Lumen Field's roofs is one curved face to the ground); elsewhere the rim's own height. */
|
|
@@ -207,6 +198,21 @@ export function mastPlanes(real, c, z, masts) {
|
|
|
207
198
|
export function realBuilding(real, top, centre, lift, steps, open = false, parts = { walls: true, roof: true }) {
|
|
208
199
|
const items = [];
|
|
209
200
|
const c = [centre[0], centre[1]];
|
|
201
|
+
// The Saddledome's building is its own: a round wall that leans out to a beam, under one saddle roof (`venue.saddle.ts`).
|
|
202
|
+
if (real.roof === "saddle" && real.saddle !== undefined) {
|
|
203
|
+
const cells = steps >= 100 ? SADDLE_CELLS.high : steps >= 48 ? SADDLE_CELLS.auto : SADDLE_CELLS.low;
|
|
204
|
+
if (parts.walls) {
|
|
205
|
+
const walls = [...saddleWalls(real.saddle, lift, cells, c), ...saddleTowers(real.saddle, lift)];
|
|
206
|
+
if (walls.length > 0)
|
|
207
|
+
items.push({ id: "shell", kind: "walls", at: centre, height: heightOf(walls), planes: walls });
|
|
208
|
+
}
|
|
209
|
+
if (parts.roof) {
|
|
210
|
+
const roof = saddleRoof(real.saddle, lift, cells);
|
|
211
|
+
if (roof.length > 0)
|
|
212
|
+
items.push({ id: "roof", kind: "roof", at: centre, height: heightOf(roof), planes: roof });
|
|
213
|
+
}
|
|
214
|
+
return items;
|
|
215
|
+
}
|
|
210
216
|
const rim = Array.from({ length: steps }, (_, k) => rimPoint(real, c, (2 * Math.PI * k) / steps));
|
|
211
217
|
const planes = [];
|
|
212
218
|
// A ribbed shell (the Olympic Stadium's) is its own: ribs and glazed bays in place of a drum of walls.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Pt, RealShell } from "./crowd.ts";
|
|
2
|
+
import { type Plane, type V3 } from "./turn.kit.ts";
|
|
3
|
+
/** The saddle's measure, in the drawing's frame: its middle, the radius of its round plan, the unit direction of the line through its two high points (and the one across it), and the heights of the high points and of the low rim (feet over the surface). */
|
|
4
|
+
export type Saddle = NonNullable<RealShell["saddle"]>;
|
|
5
|
+
/** The cells to a side of the roof's grid (the plan is 4 times that round the rim), and the rings of the wall, at each detail. */
|
|
6
|
+
export declare const SADDLE_CELLS: {
|
|
7
|
+
readonly low: 8;
|
|
8
|
+
readonly auto: 10;
|
|
9
|
+
readonly high: 16;
|
|
10
|
+
};
|
|
11
|
+
/** How thick the beam round the roof's edge is, how far it overhangs the wall's top, how far the wall leans out over its height (a share of the height of the edge there), in feet or as a share (ours: measured on photographs, a hand's accuracy). */
|
|
12
|
+
export declare const EAVE: {
|
|
13
|
+
readonly depth: 5;
|
|
14
|
+
readonly overhang: 7;
|
|
15
|
+
readonly lean: 0.14;
|
|
16
|
+
};
|
|
17
|
+
/** A pier stands on the wall at every this many facets, and the band of small windows lies between these shares of the wall's height (ours). */
|
|
18
|
+
export declare const PIER_EVERY = 2;
|
|
19
|
+
export declare const WINDOWS: {
|
|
20
|
+
readonly from: 0.4;
|
|
21
|
+
readonly to: 0.44;
|
|
22
|
+
};
|
|
23
|
+
/** The height of the roof over a point of the plan, above the surface, in feet: a hyperbolic paraboloid over the round plan, high along `axis` and low across it. */
|
|
24
|
+
export declare function saddleHeight(s: Saddle, [x, y]: Pt): number;
|
|
25
|
+
/**
|
|
26
|
+
* A quad of four corners (in order round it) as one plane: its first corner, its side to the second and its side to the fourth span the plane; the third corner is put where the plane has it (a quad of a doubly curved surface is not quite
|
|
27
|
+
* flat, and the plane is the nearest flat piece: within a foot or two at every cut). `paint` gets the corners in the plane's own feet, and the plane's own (unit) normal as it lies in the drawing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function quadPlane(id: string, kind: Plane["kind"], corners: readonly [V3, V3, V3, V3], paint: (local: [Pt, Pt, Pt, Pt]) => string): Plane | undefined;
|
|
30
|
+
/** The roof: the net of quads over the round plan, `cells` to a side, with the beam round its edge. Every plane is a roof's, cut away from above and, by its side, from the eye's; the beam is the edge of the roof's own item. */
|
|
31
|
+
export declare function saddleRoof(s: Saddle, lift: number, cells: number): Plane[];
|
|
32
|
+
/** The wall: a facet between each two points of the rim, leaning out from its foot to the beam, with a pier between every `PIER_EVERY` panels, the fine lines of its cladding and a few windows. Each gives way by the eye's side as a wall does. */
|
|
33
|
+
export declare function saddleWalls(s: Saddle, lift: number, cells: number, centre: Pt): Plane[];
|
|
34
|
+
/** The two stair towers at each end of the roof's high line, a round one and a square one, on the wall's foot at either side of the end: how tall each stands (a share of the wall there) and how big it is, in feet (ours: photographs show each, not its size). */
|
|
35
|
+
export declare const TOWERS: {
|
|
36
|
+
readonly round: {
|
|
37
|
+
readonly turn: -24;
|
|
38
|
+
readonly radius: 11;
|
|
39
|
+
readonly share: 0.55;
|
|
40
|
+
};
|
|
41
|
+
readonly square: {
|
|
42
|
+
readonly turn: 24;
|
|
43
|
+
readonly half: 17;
|
|
44
|
+
readonly share: 0.45;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/** The stair towers: at each of the roof's two high points, a round tower and a square one against the wall, taller where the wall is. */
|
|
48
|
+
export declare function saddleTowers(s: Saddle, lift: number): Plane[];
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { plane, shy } from "./turn.kit.js";
|
|
2
|
+
/** The cells to a side of the roof's grid (the plan is 4 times that round the rim), and the rings of the wall, at each detail. */
|
|
3
|
+
export const SADDLE_CELLS = { low: 8, auto: 10, high: 16 };
|
|
4
|
+
/** How thick the beam round the roof's edge is, how far it overhangs the wall's top, how far the wall leans out over its height (a share of the height of the edge there), in feet or as a share (ours: measured on photographs, a hand's accuracy). */
|
|
5
|
+
export const EAVE = { depth: 5, overhang: 7, lean: 0.14 };
|
|
6
|
+
/** A pier stands on the wall at every this many facets, and the band of small windows lies between these shares of the wall's height (ours). */
|
|
7
|
+
export const PIER_EVERY = 2;
|
|
8
|
+
/** The lines of the cladding across a panel, as shares of its height (ours). */
|
|
9
|
+
const CLADDING = [0.1, 0.2, 0.3, 0.52, 0.6, 0.68, 0.76, 0.84, 0.92];
|
|
10
|
+
export const WINDOWS = { from: 0.4, to: 0.44 };
|
|
11
|
+
/** The light the shading is cut from, in the drawing's frame (x along the rink, y down the page, z up): from above, to the upper left (ours). */
|
|
12
|
+
const LIGHT = (() => {
|
|
13
|
+
const l = [-0.42, -0.5, 0.76];
|
|
14
|
+
const k = Math.hypot(...l);
|
|
15
|
+
return [l[0] / k, l[1] / k, l[2] / k];
|
|
16
|
+
})();
|
|
17
|
+
/** A length to a tenth of a foot: all a facet's drawing needs. */
|
|
18
|
+
const t = (value) => String(Math.round(value * 10) / 10);
|
|
19
|
+
const sub = (a, b) => [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
|
|
20
|
+
const dot = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
21
|
+
const cross = (a, b) => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
|
|
22
|
+
const unit = (a) => {
|
|
23
|
+
const l = Math.hypot(...a) || 1;
|
|
24
|
+
return [a[0] / l, a[1] / l, a[2] / l];
|
|
25
|
+
};
|
|
26
|
+
/** The height of the roof over a point of the plan, above the surface, in feet: a hyperbolic paraboloid over the round plan, high along `axis` and low across it. */
|
|
27
|
+
export function saddleHeight(s, [x, y]) {
|
|
28
|
+
const [dx, dy] = [(x - s.centre[0]) / s.radius, (y - s.centre[1]) / s.radius];
|
|
29
|
+
const [a, b] = [dx * s.axis[0] + dy * s.axis[1], -dx * s.axis[1] + dy * s.axis[0]];
|
|
30
|
+
return (s.high + s.low) / 2 + ((s.high - s.low) / 2) * (a * a - b * b);
|
|
31
|
+
}
|
|
32
|
+
/** A point of the unit disk for a point of the square (a fair mapping: a square grid becomes a net of quads that is fine everywhere, with no pole in the middle). */
|
|
33
|
+
const diskOf = (s, t) => [s * Math.sqrt(1 - (t * t) / 2), t * Math.sqrt(1 - (s * s) / 2)];
|
|
34
|
+
/** The plan point and height of a point `(a, b)` of the unit disk (`a` along the axis, `b` across it), at `scale` of the radius and `z` over the surface. */
|
|
35
|
+
function pointOf(s, [a, b], scale = 1, z) {
|
|
36
|
+
const x = s.centre[0] + s.radius * scale * (a * s.axis[0] - b * s.axis[1]);
|
|
37
|
+
const y = s.centre[1] + s.radius * scale * (a * s.axis[1] + b * s.axis[0]);
|
|
38
|
+
return [x, y, z ?? saddleHeight(s, [x, y])];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A quad of four corners (in order round it) as one plane: its first corner, its side to the second and its side to the fourth span the plane; the third corner is put where the plane has it (a quad of a doubly curved surface is not quite
|
|
42
|
+
* flat, and the plane is the nearest flat piece: within a foot or two at every cut). `paint` gets the corners in the plane's own feet, and the plane's own (unit) normal as it lies in the drawing.
|
|
43
|
+
*/
|
|
44
|
+
export function quadPlane(id, kind, corners, paint) {
|
|
45
|
+
const [a, b, c, d] = corners;
|
|
46
|
+
const u = sub(b, a);
|
|
47
|
+
const v = sub(d, a);
|
|
48
|
+
const [lu, lv] = [Math.hypot(...u), Math.hypot(...v)];
|
|
49
|
+
if (lu < 1e-6 || lv < 1e-6)
|
|
50
|
+
return undefined;
|
|
51
|
+
// Where the third corner is, in the plane's own feet: the least squares of c - a over u and v.
|
|
52
|
+
const w = sub(c, a);
|
|
53
|
+
const [uu, uv, vv, uw, vw] = [dot(u, u), dot(u, v), dot(v, v), dot(u, w), dot(v, w)];
|
|
54
|
+
const det = uu * vv - uv * uv;
|
|
55
|
+
if (Math.abs(det) < 1e-9)
|
|
56
|
+
return undefined;
|
|
57
|
+
const [ca, cb] = [(uw * vv - vw * uv) / det, (vw * uu - uw * uv) / det];
|
|
58
|
+
const local = [[0, 0], [lu, 0], [ca * lu, cb * lv], [0, lv]];
|
|
59
|
+
return plane(id, kind, a, u, v, paint(local));
|
|
60
|
+
}
|
|
61
|
+
/** The shade of a facet from its normal and the light: nothing where it is lit square, a darker veil where it turns away, a lighter one where it faces the light. `up` is the side of the normal that is the facet's outside. */
|
|
62
|
+
function veil(corners, outside) {
|
|
63
|
+
let normal = unit(cross(sub(corners[1], corners[0]), sub(corners[3], corners[0])));
|
|
64
|
+
if (dot(normal, outside) < 0)
|
|
65
|
+
normal = [-normal[0], -normal[1], -normal[2]];
|
|
66
|
+
const s = dot(normal, LIGHT);
|
|
67
|
+
const [dark, light] = [Math.max(0, Math.min(0.3, (0.5 - s) * 0.45)), Math.max(0, Math.min(0.22, (s - 0.68) * 0.8))];
|
|
68
|
+
return { s, dark: Math.round(dark * 100) / 100, light: Math.round(light * 100) / 100 };
|
|
69
|
+
}
|
|
70
|
+
/** The facet's polygon, then the veil over it (a darker or a lighter wash of the facet's own shape), as one drawing. */
|
|
71
|
+
function facet(cls, local, shade, extra = "") {
|
|
72
|
+
const pts = local.map(([x, y]) => `${t(x)},${t(y)}`).join(" ");
|
|
73
|
+
const wash = shade.dark > 0 ? `<polygon class="u-shade" fill-opacity="${shade.dark}" points="${pts}"/>` : shade.light > 0 ? `<polygon class="u-lite" fill-opacity="${shade.light}" points="${pts}"/>` : "";
|
|
74
|
+
return `<polygon class="${cls}" points="${pts}"/>${wash}${extra}`;
|
|
75
|
+
}
|
|
76
|
+
/** The grid of the roof as points of the unit disk: `cells + 1` to a side. */
|
|
77
|
+
function gridOf(cells) {
|
|
78
|
+
return Array.from({ length: cells + 1 }, (_, i) => Array.from({ length: cells + 1 }, (_, j) => diskOf(-1 + (2 * i) / cells, -1 + (2 * j) / cells)));
|
|
79
|
+
}
|
|
80
|
+
/** The rim as points of the unit disk, going once round: along the four sides of the grid, `cells` to a side. */
|
|
81
|
+
function rimOf(cells) {
|
|
82
|
+
const g = gridOf(cells);
|
|
83
|
+
const out = [];
|
|
84
|
+
for (let i = 0; i < cells; i += 1)
|
|
85
|
+
out.push(g[i][0]);
|
|
86
|
+
for (let j = 0; j < cells; j += 1)
|
|
87
|
+
out.push(g[cells][j]);
|
|
88
|
+
for (let i = cells; i > 0; i -= 1)
|
|
89
|
+
out.push(g[i][cells]);
|
|
90
|
+
for (let j = cells; j > 0; j -= 1)
|
|
91
|
+
out.push(g[0][j]);
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
/** The roof: the net of quads over the round plan, `cells` to a side, with the beam round its edge. Every plane is a roof's, cut away from above and, by its side, from the eye's; the beam is the edge of the roof's own item. */
|
|
95
|
+
export function saddleRoof(s, lift, cells) {
|
|
96
|
+
const planes = [];
|
|
97
|
+
const grid = gridOf(cells);
|
|
98
|
+
const at = ([a, b]) => {
|
|
99
|
+
const p = pointOf(s, [a, b]);
|
|
100
|
+
return [p[0], p[1], lift + p[2]];
|
|
101
|
+
};
|
|
102
|
+
for (let i = 0; i < cells; i += 1) {
|
|
103
|
+
for (let j = 0; j < cells; j += 1) {
|
|
104
|
+
const corners = [at(grid[i][j]), at(grid[i + 1][j]), at(grid[i + 1][j + 1]), at(grid[i][j + 1])];
|
|
105
|
+
const [mx, my] = [(corners[0][0] + corners[1][0] + corners[2][0] + corners[3][0]) / 4 - s.centre[0], (corners[0][1] + corners[1][1] + corners[2][1] + corners[3][1]) / 4 - s.centre[1]];
|
|
106
|
+
const shade = veil(corners, [0, 0, 1]);
|
|
107
|
+
const p = quadPlane(`roof-${i}-${j}`, "roof", corners, (local) => facet("u-saddle", local, shade));
|
|
108
|
+
if (p === undefined)
|
|
109
|
+
continue;
|
|
110
|
+
const away = Math.hypot(mx, my) || 1;
|
|
111
|
+
planes.push({ ...p, shy: [mx / away, my / away], fadeTo: 0.06 });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// The beam round the roof's edge: from the roof's rim down and in to the top of the wall.
|
|
115
|
+
const rim = rimOf(cells);
|
|
116
|
+
rim.forEach((a, k) => {
|
|
117
|
+
const b = rim[(k + 1) % rim.length];
|
|
118
|
+
const [top0, top1] = [at(a), at(b)];
|
|
119
|
+
const foot = (p, ab) => {
|
|
120
|
+
const q = pointOf(s, ab, 1 - EAVE.overhang / s.radius, p[2] - EAVE.depth);
|
|
121
|
+
return [q[0], q[1], q[2]];
|
|
122
|
+
};
|
|
123
|
+
const corners = [top0, top1, foot(top1, b), foot(top0, a)];
|
|
124
|
+
const mid = [(top0[0] + top1[0]) / 2 - s.centre[0], (top0[1] + top1[1]) / 2 - s.centre[1], 0];
|
|
125
|
+
const shade = veil(corners, mid);
|
|
126
|
+
const away = Math.hypot(mid[0], mid[1]) || 1;
|
|
127
|
+
const p = quadPlane(`beam-${k}`, "roof", corners, (local) => facet("u-saddle-beam", local, shade));
|
|
128
|
+
if (p !== undefined)
|
|
129
|
+
planes.push({ ...p, shy: [mid[0] / away, mid[1] / away], fadeTo: 0.02 });
|
|
130
|
+
});
|
|
131
|
+
return planes;
|
|
132
|
+
}
|
|
133
|
+
/** The wall: a facet between each two points of the rim, leaning out from its foot to the beam, with a pier between every `PIER_EVERY` panels, the fine lines of its cladding and a few windows. Each gives way by the eye's side as a wall does. */
|
|
134
|
+
export function saddleWalls(s, lift, cells, centre) {
|
|
135
|
+
const planes = [];
|
|
136
|
+
const rim = rimOf(cells);
|
|
137
|
+
const topOf = (ab) => {
|
|
138
|
+
const e = pointOf(s, ab);
|
|
139
|
+
const q = pointOf(s, ab, 1 - EAVE.overhang / s.radius, e[2] - EAVE.depth);
|
|
140
|
+
return [q[0], q[1], lift + q[2]];
|
|
141
|
+
};
|
|
142
|
+
const footOf = (ab) => {
|
|
143
|
+
const e = pointOf(s, ab);
|
|
144
|
+
const q = pointOf(s, ab, 1 - (EAVE.overhang + EAVE.lean * e[2]) / s.radius, lift);
|
|
145
|
+
return [q[0], q[1], q[2]];
|
|
146
|
+
};
|
|
147
|
+
rim.forEach((a, k) => {
|
|
148
|
+
const b = rim[(k + 1) % rim.length];
|
|
149
|
+
const corners = [footOf(a), footOf(b), topOf(b), topOf(a)];
|
|
150
|
+
const mid = [(corners[0][0] + corners[1][0]) / 2 - centre[0], (corners[0][1] + corners[1][1]) / 2 - centre[1], 0];
|
|
151
|
+
const shade = veil(corners, mid);
|
|
152
|
+
const pier = k % PIER_EVERY === 0;
|
|
153
|
+
const plank = quadPlane(`shell-${k}`, "wall", corners, (local) => {
|
|
154
|
+
// A point of the facet by its share along the foot (x) and up the wall (y).
|
|
155
|
+
const at = (x, y) => {
|
|
156
|
+
const [a0, b0, c0, d0] = local;
|
|
157
|
+
const low = [a0[0] + (b0[0] - a0[0]) * x, a0[1] + (b0[1] - a0[1]) * x];
|
|
158
|
+
const high = [d0[0] + (c0[0] - d0[0]) * x, d0[1] + (c0[1] - d0[1]) * x];
|
|
159
|
+
return [low[0] + (high[0] - low[0]) * y, low[1] + (high[1] - low[1]) * y];
|
|
160
|
+
};
|
|
161
|
+
const line = (y) => `M${t(at(0, y)[0])} ${t(at(0, y)[1])}L${t(at(1, y)[0])} ${t(at(1, y)[1])}`;
|
|
162
|
+
// The finer the cut, the more of the wall's detail: the lowest has neither the cladding nor the windows, the next the windows, the finest both.
|
|
163
|
+
const cladding = cells >= SADDLE_CELLS.high ? `<path class="u-clad" fill="none" d="${CLADDING.map(line).join("")}"/>` : "";
|
|
164
|
+
// Three small windows in a row across the middle of the panel, a pane's width apart.
|
|
165
|
+
const panes = [0.2, 0.42, 0.64].map((x) => [at(x, WINDOWS.from), at(x + 0.16, WINDOWS.from), at(x + 0.16, WINDOWS.to), at(x, WINDOWS.to)]);
|
|
166
|
+
const windows = cells < SADDLE_CELLS.auto ? "" : panes.map((q) => `<polygon class="u-glazing" points="${q.map(([x, y]) => `${t(x)},${t(y)}`).join(" ")}"/>`).join("");
|
|
167
|
+
const post = pier ? `<path class="u-pier" d="M${t(local[0][0])} ${t(local[0][1])}L${t(local[3][0])} ${t(local[3][1])}"/>` : "";
|
|
168
|
+
return facet("u-saddle-wall", local, shade, `${cladding}${windows}${post}`);
|
|
169
|
+
});
|
|
170
|
+
if (plank === undefined)
|
|
171
|
+
return;
|
|
172
|
+
planes.push({ ...shy(plank, centre), fadeTo: 0.02 });
|
|
173
|
+
});
|
|
174
|
+
return planes;
|
|
175
|
+
}
|
|
176
|
+
/** The two stair towers at each end of the roof's high line, a round one and a square one, on the wall's foot at either side of the end: how tall each stands (a share of the wall there) and how big it is, in feet (ours: photographs show each, not its size). */
|
|
177
|
+
export const TOWERS = { round: { turn: -24, radius: 11, share: 0.55 }, square: { turn: 24, half: 17, share: 0.45 } };
|
|
178
|
+
/** A prism over a polygon on the plan (`ring`, `height` feet over `lift`), each side a facet shaded by the light and the top a flat cap, as a stair tower is; every piece gives way with the wall it stands against (`out` is the way out of the building there). */
|
|
179
|
+
function prism(id, cls, ring, lift, height, out) {
|
|
180
|
+
const planes = [];
|
|
181
|
+
const mx = ring.reduce((t, p) => t + p[0], 0) / ring.length;
|
|
182
|
+
const my = ring.reduce((t, p) => t + p[1], 0) / ring.length;
|
|
183
|
+
ring.forEach((a, k) => {
|
|
184
|
+
const b = ring[(k + 1) % ring.length];
|
|
185
|
+
const corners = [[a[0], a[1], lift], [b[0], b[1], lift], [b[0], b[1], lift + height], [a[0], a[1], lift + height]];
|
|
186
|
+
const shade = veil(corners, [(a[0] + b[0]) / 2 - mx, (a[1] + b[1]) / 2 - my, 0]);
|
|
187
|
+
const p = quadPlane(`${id}-${k}`, "wall", corners, (local) => facet(cls, local, shade));
|
|
188
|
+
if (p !== undefined)
|
|
189
|
+
planes.push({ ...p, shy: out, fadeTo: 0.02 });
|
|
190
|
+
});
|
|
191
|
+
const [x0, x1, y0, y1] = [Math.min(...ring.map((p) => p[0])), Math.max(...ring.map((p) => p[0])), Math.min(...ring.map((p) => p[1])), Math.max(...ring.map((p) => p[1]))];
|
|
192
|
+
const pts = ring.map(([x, y]) => `${t(x - x0)},${t(y - y0)}`).join(" ");
|
|
193
|
+
planes.push({ ...plane(`${id}-top`, "wall", [x0, y0, lift + height], [x1 - x0, 0, 0], [0, y1 - y0, 0], `<polygon class="${cls}" points="${pts}"/>`), shy: out, fadeTo: 0.02 });
|
|
194
|
+
return planes;
|
|
195
|
+
}
|
|
196
|
+
/** The stair towers: at each of the roof's two high points, a round tower and a square one against the wall, taller where the wall is. */
|
|
197
|
+
export function saddleTowers(s, lift) {
|
|
198
|
+
const planes = [];
|
|
199
|
+
for (const end of [0, 1]) {
|
|
200
|
+
const [round, square] = [TOWERS.round, TOWERS.square];
|
|
201
|
+
for (const [name, spec] of [["round", round], ["square", square]]) {
|
|
202
|
+
// Where the tower stands: at `turn` degrees from the high point (round the plan), against the wall's foot, which leans out from the beam's.
|
|
203
|
+
const turn = ((spec.turn + end * 180) * Math.PI) / 180;
|
|
204
|
+
const [ax, ay] = [s.axis[0], s.axis[1]];
|
|
205
|
+
const dir = [ax * Math.cos(turn) - ay * Math.sin(turn), ay * Math.cos(turn) + ax * Math.sin(turn)];
|
|
206
|
+
const edgeAt = pointOf(s, [Math.cos(turn), Math.sin(turn)]);
|
|
207
|
+
const foot = s.radius - EAVE.overhang - EAVE.lean * edgeAt[2];
|
|
208
|
+
const size = name === "round" ? TOWERS.round.radius : TOWERS.square.half;
|
|
209
|
+
const middle = [s.centre[0] + dir[0] * (foot + size * 0.55), s.centre[1] + dir[1] * (foot + size * 0.55)];
|
|
210
|
+
const height = (edgeAt[2] - EAVE.depth) * spec.share;
|
|
211
|
+
const ring = name === "round"
|
|
212
|
+
? Array.from({ length: 10 }, (_, k) => [middle[0] + TOWERS.round.radius * Math.cos((2 * Math.PI * k) / 10), middle[1] + TOWERS.round.radius * Math.sin((2 * Math.PI * k) / 10)])
|
|
213
|
+
: [[-1, -0.8], [1, -0.8], [1, 0.8], [-1, 0.8]].map(([a, b]) => [middle[0] + TOWERS.square.half * (a * ax - b * ay), middle[1] + TOWERS.square.half * (a * ay + b * ax)]);
|
|
214
|
+
planes.push(...prism(`tower-${end}-${name}`, name === "round" ? "u-stair-round" : "u-stair-square", ring, lift, height, dir));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return planes;
|
|
218
|
+
}
|
|
@@ -5,5 +5,6 @@ export const VENUE = {
|
|
|
5
5
|
"en": { "title": "Scotiabank Saddledome", "revision": 1377341466 },
|
|
6
6
|
"seats": { "hockey": 19289, "source": "wikipedia", "wikidata": 16605, "read": "the infobox's present figure for hockey (19,289, from 1995), which the article's amenities line gives too; Wikidata's 16,605 is the 1983 figure and the first the infobox lists" },
|
|
7
7
|
"tiers": { "count": 2, "basis": "documented", "read": "the article speaks of the lower bowl, a second level and upper loges above it: two seating levels with suites at the top of the lower bowl" },
|
|
8
|
-
"roof": { "kind": "saddle", "basis": "documented", "read": "the article says the roof is a reverse hyperbolic paraboloid, shaped like a horse saddle; which way the saddle lies
|
|
8
|
+
"roof": { "kind": "saddle", "basis": "documented", "read": "the article says the roof is a reverse hyperbolic paraboloid, shaped like a horse saddle, the longest spanning hyperbolic paraboloid concrete shell; which way the saddle lies and how high it stands are read from photographs, below", "saddle": { "bearing": 60, "low": 78, "high": 138, "read": "the line through the two high points runs 60 degrees (east-northeast and west-southwest: 60 and 240 from north), from three photographs taken from known places (Commons: Scotiabank Saddledome, southeast view 20240819 1, taken from the southeast looking north-northwest, the roof sagging between its high ends left and right; Scotiabank Saddledome from Calgary Tower 2025-07-14, taken from the northwest looking southeast; Scotiabank Saddledome, southwest view 20240819 1, taken from the west looking east along the line, the roof an arch over its near high end), and from the outline's one bulge, the west entrance annex, which lies at 215 to 270 degrees from the building's middle; the low rim stands about 78 feet over the ice (the event level lies below the plaza) and the high points about 138 feet: ours, measured on those photographs, good to about a sixth" } },
|
|
9
|
+
"bowl": { "round": true, "rises": [20, 30], "read": "the arena's bowl is round (the interior photographs on Commons show tiers curving all the way round, and the outline's own shape is a circle of 142 metres across less an annex); the rows' rises are ours, lower than the usual because the roof is low over the sides (the lower tier 20 feet, the upper 30)" },
|
|
9
10
|
};
|
package/dist/venues.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { type Box, type Pt, type RealBowl } from "./crowd.ts";
|
|
|
4
4
|
export declare const VENUE_ATTRIBUTION = "(c) OpenStreetMap contributors, ODbL 1.0, openstreetmap.org/copyright";
|
|
5
5
|
/** How a fact is known: `documented` is what a source cited with it says; `plausible` is ours, for a bowl no source describes. */
|
|
6
6
|
export type VenueBasis = "documented" | "plausible";
|
|
7
|
-
/** The kinds of roof the venues have: `fixed` is a lid over the bowl, `saddle` a roof that rises at
|
|
7
|
+
/** The kinds of roof the venues have: `fixed` is a lid over the bowl, `saddle` a roof that rises at two opposite points of its rim and falls at the two between (the Scotiabank Saddledome's), `barrel` a barrel vault along the rink, a round arch over its short axis (the American Airlines Center's). */
|
|
8
8
|
export type VenueRoof = "fixed" | "saddle" | "barrel";
|
|
9
9
|
/** The NHL's divisions, in the order of the league's own listing: the Western Conference's two, then the Eastern's. A division none of whose arenas has a venue yet has no venues in `venuesIn`. */
|
|
10
10
|
export declare const VENUE_DIVISIONS: readonly ["pacific", "central", "atlantic", "metropolitan"];
|
|
@@ -51,8 +51,25 @@ export interface RealVenueData {
|
|
|
51
51
|
roof: {
|
|
52
52
|
kind: VenueRoof;
|
|
53
53
|
basis: VenueBasis;
|
|
54
|
-
read: string;
|
|
54
|
+
read: string;
|
|
55
|
+
/** A long skylight over the middle of the roof, closed in round it: drawn where the venue says so (ours). */
|
|
55
56
|
skylight?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* A `saddle` roof's measure: the compass bearing of the line through its two high points (degrees clockwise from north, 0 up to 180: a line has two ends), and the height of the high points and of the low rim over the surface, in feet. Measured on
|
|
59
|
+
* photographs of the building taken from known places, with the outline's own bulge at the end of the line; the heights are ours, as accurate as a photograph allows. `read` says what each was taken from.
|
|
60
|
+
*/
|
|
61
|
+
saddle?: {
|
|
62
|
+
bearing: number;
|
|
63
|
+
low: number;
|
|
64
|
+
high: number;
|
|
65
|
+
read: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/** A bowl the sources describe as other than the usual: a round plan (the Saddledome's), and the rise of each tier in feet where it is not the usual (ours, from photographs). */
|
|
69
|
+
bowl?: {
|
|
70
|
+
round?: boolean;
|
|
71
|
+
rises?: [number, number];
|
|
72
|
+
read: string;
|
|
56
73
|
};
|
|
57
74
|
}
|
|
58
75
|
/** What OpenStreetMap gave of a venue: ODbL 1.0 data, "(c) OpenStreetMap contributors". */
|
|
@@ -145,6 +162,8 @@ export declare const WALK_RISE = 16;
|
|
|
145
162
|
export declare const MAX_RAKE = 36;
|
|
146
163
|
/** The height a roof's edge stands over the top row, at the least, in feet. */
|
|
147
164
|
export declare const CLEARANCE = 22;
|
|
165
|
+
/** The least a saddle roof's low rim stands over the top row, in feet: the roof is lower over the bowl's sides than a lid is, and falls to the rim over the top row (ours, from photographs). */
|
|
166
|
+
export declare const SADDLE_CLEARANCE = 8;
|
|
148
167
|
/** The plan of a venue: its building in the drawing's frame, the bowl fitted inside, and how it lies. */
|
|
149
168
|
export interface VenuePlan {
|
|
150
169
|
venue: RealVenue;
|
package/dist/venues.data.js
CHANGED
|
@@ -15,7 +15,8 @@ export const VENUE_DATA = [
|
|
|
15
15
|
"en": { "title": "Scotiabank Saddledome", "revision": 1377341466 },
|
|
16
16
|
"seats": { "hockey": 19289, "source": "wikipedia", "wikidata": 16605, "read": "the infobox's present figure for hockey (19,289, from 1995), which the article's amenities line gives too; Wikidata's 16,605 is the 1983 figure and the first the infobox lists" },
|
|
17
17
|
"tiers": { "count": 2, "basis": "documented", "read": "the article speaks of the lower bowl, a second level and upper loges above it: two seating levels with suites at the top of the lower bowl" },
|
|
18
|
-
"roof": { "kind": "saddle", "basis": "documented", "read": "the article says the roof is a reverse hyperbolic paraboloid, shaped like a horse saddle; which way the saddle lies
|
|
18
|
+
"roof": { "kind": "saddle", "basis": "documented", "read": "the article says the roof is a reverse hyperbolic paraboloid, shaped like a horse saddle, the longest spanning hyperbolic paraboloid concrete shell; which way the saddle lies and how high it stands are read from photographs, below", "saddle": { "bearing": 60, "low": 78, "high": 138, "read": "the line through the two high points runs 60 degrees (east-northeast and west-southwest: 60 and 240 from north), from three photographs taken from known places (Commons: Scotiabank Saddledome, southeast view 20240819 1, taken from the southeast looking north-northwest, the roof sagging between its high ends left and right; Scotiabank Saddledome from Calgary Tower 2025-07-14, taken from the northwest looking southeast; Scotiabank Saddledome, southwest view 20240819 1, taken from the west looking east along the line, the roof an arch over its near high end), and from the outline's one bulge, the west entrance annex, which lies at 215 to 270 degrees from the building's middle; the low rim stands about 78 feet over the ice (the event level lies below the plaza) and the high points about 138 feet: ours, measured on those photographs, good to about a sixth" } },
|
|
19
|
+
"bowl": { "round": true, "rises": [20, 30], "read": "the arena's bowl is round (the interior photographs on Commons show tiers curving all the way round, and the outline's own shape is a circle of 142 metres across less an annex); the rows' rises are ours, lower than the usual because the roof is low over the sides (the lower tier 20 feet, the upper 30)" },
|
|
19
20
|
},
|
|
20
21
|
{
|
|
21
22
|
"id": "rogers-place",
|
package/dist/venues.js
CHANGED
|
@@ -106,6 +106,8 @@ const TIER_IDS = { 1: ["lower"], 2: ["lower", "upper"], 3: ["lower", "middle", "
|
|
|
106
106
|
const FILL = { lower: 1, middle: 0.94, upper: 0.88 };
|
|
107
107
|
/** The height a roof's edge stands over the top row, at the least, in feet. */
|
|
108
108
|
export const CLEARANCE = 22;
|
|
109
|
+
/** The least a saddle roof's low rim stands over the top row, in feet: the roof is lower over the bowl's sides than a lid is, and falls to the rim over the top row (ours, from photographs). */
|
|
110
|
+
export const SADDLE_CLEARANCE = 8;
|
|
109
111
|
const lerp = (a, b, t) => a + (b - a) * t;
|
|
110
112
|
const between = (a, b, t) => ({ kind: "rrect", x0: lerp(a.x0, b.x0, t), y0: lerp(a.y0, b.y0, t), x1: lerp(a.x1, b.x1, t), y1: lerp(a.y1, b.y1, t), r: lerp(a.r, b.r, t) });
|
|
111
113
|
/** The parameter in `[lo, hi]` at which an increasing function reaches `target` (bisection), or `hi` where it does not. */
|
|
@@ -160,7 +162,7 @@ function plan(venue, rink) {
|
|
|
160
162
|
// The first row round the rink, and the largest bowl-shaped outline that fits inside the building round the middle of the hall: as much longer than wide as the hall is, and as round at the corners as a bowl is.
|
|
161
163
|
const first = { kind: "rrect", x0: rink.x - FIRST_ROW.end, y0: rink.y - FIRST_ROW.side, x1: rink.x + rink.w + FIRST_ROW.end, y1: rink.y + rink.h + FIRST_ROW.side + FIRST_ROW.bench, r: FIRST_ROW.corner };
|
|
162
164
|
// The aspect that holds the most: a bowl is between 1.15 and 1.6 times as long as it is wide, as much as the hall allows.
|
|
163
|
-
const shapedAs = (long, s) => ({ kind: "rrect", x0: at[0] - long * s, y0: at[1] - s, x1: at[0] + long * s, y1: at[1] + s, r: CORNER * s });
|
|
165
|
+
const shapedAs = (long, s) => ({ kind: "rrect", x0: at[0] - long * s, y0: at[1] - s, x1: at[0] + long * s, y1: at[1] + s, r: (venue.bowl?.round === true ? 1 : CORNER) * s });
|
|
164
166
|
const largest = (long) => {
|
|
165
167
|
let [lo, hi] = [60, Math.max(fb.x1 - fb.x0, fb.y1 - fb.y0)];
|
|
166
168
|
for (let i = 0; i < 24; i += 1) {
|
|
@@ -172,7 +174,8 @@ function plan(venue, rink) {
|
|
|
172
174
|
}
|
|
173
175
|
return lo;
|
|
174
176
|
};
|
|
175
|
-
const
|
|
177
|
+
const circular = venue.bowl?.round === true;
|
|
178
|
+
const tries = (circular ? [1] : [1.15, 1.25, 1.35, 1.45, 1.6]).map((long) => ({ long, s: largest(long) }));
|
|
176
179
|
const best = tries.reduce((a, b) => (a.long * a.s * a.s >= b.long * b.s * b.s ? a : b));
|
|
177
180
|
const lo = best.s;
|
|
178
181
|
const shaped = (s) => shapedAs(best.long, s);
|
|
@@ -203,7 +206,7 @@ function plan(venue, rink) {
|
|
|
203
206
|
const tier = TIER_IDS[count][k];
|
|
204
207
|
// The band's depth along the two long sides on average, where the bowl is the shallowest and the rake the steepest: the rise is what a rake of at most `MAX_RAKE` degrees gives over it, up to the usual rise of a tier of its place.
|
|
205
208
|
const run = (region.y1 - hole.y1 + (hole.y0 - region.y0)) / 2;
|
|
206
|
-
const rise = Math.min(RISES[count][k], Math.max(6, run * Math.tan((MAX_RAKE * Math.PI) / 180)));
|
|
209
|
+
const rise = Math.min((count === 2 ? venue.bowl?.rises?.[k] : undefined) ?? RISES[count][k], Math.max(6, run * Math.tan((MAX_RAKE * Math.PI) / 180)));
|
|
207
210
|
const [h0, h1] = [k === 0 ? FIRST_HEIGHT : up + WALK_RISE, (k === 0 ? FIRST_HEIGHT : up + WALK_RISE) + rise];
|
|
208
211
|
up = h1;
|
|
209
212
|
rings.push({
|
|
@@ -239,17 +242,47 @@ function plan(venue, rink) {
|
|
|
239
242
|
rings[rings.length - 1].seats += missing;
|
|
240
243
|
const total = rings.reduce((sum, ring) => sum + ring.seats, 0);
|
|
241
244
|
const top = rings[rings.length - 1].height[1];
|
|
242
|
-
const
|
|
245
|
+
const saddled = venue.roof.kind === "saddle" ? venue.roof.saddle : undefined;
|
|
246
|
+
const edge = saddled === undefined ? Math.max(round((venue.osm.height ?? 0) * FEET_PER_METRE), top + CLEARANCE) : Math.max(saddled.low, top + SADDLE_CLEARANCE);
|
|
243
247
|
const north = orientation.basis === "none" ? undefined : orientation.north;
|
|
244
248
|
const room = north === undefined ? 0 : NORTH_ROOM;
|
|
245
249
|
const bowl = {
|
|
246
250
|
rings,
|
|
247
251
|
off: { left: FIRST_ROW.end, right: FIRST_ROW.end, top: FIRST_ROW.side, bottom: FIRST_ROW.side + FIRST_ROW.bench },
|
|
248
252
|
reach: { left: Math.max(0, rink.x - fb.x0), right: Math.max(0, fb.x1 - rink.x - rink.w), top: Math.max(0, rink.y - fb.y0) + room, bottom: Math.max(0, fb.y1 - rink.y - rink.h) },
|
|
249
|
-
shell: { footprint, hall: { ...outer, x0: outer.x0 - HALL, y0: outer.y0 - HALL, x1: outer.x1 + HALL, y1: outer.y1 + HALL, r: outer.r + HALL }, ...(north === undefined ? {} : { north }), roof: venue.roof.kind, edge, ...(venue.facade === undefined ? {} : { podium: venue.facade.podium }), ...(venue.roof.skylight === true ? { skylight: true } : {}) },
|
|
253
|
+
shell: { footprint, hall: { ...outer, x0: outer.x0 - HALL, y0: outer.y0 - HALL, x1: outer.x1 + HALL, y1: outer.y1 + HALL, r: outer.r + HALL }, ...(north === undefined ? {} : { north }), roof: venue.roof.kind, edge, ...(saddled === undefined ? {} : { saddle: saddleOf(saddled, footprint, at, orientation.heading, edge) }), ...(venue.facade === undefined ? {} : { podium: venue.facade.podium }), ...(venue.roof.skylight === true ? { skylight: true } : {}) },
|
|
250
254
|
};
|
|
251
255
|
return { venue, orientation, box: rink, footprint, bowl, seats: rings.map((ring) => ({ tier: ring.tier, seats: ring.seats })), total, seatArea, fit: tight ? "tight" : "fits" };
|
|
252
256
|
}
|
|
257
|
+
/**
|
|
258
|
+
* A saddle roof's measure in the drawing's frame: its middle at the bowl's, the radius of its round plan (the middle distance of the building's outline from the middle, so that an annex's bulge does not swell it), and the line through
|
|
259
|
+
* its two high points turned from the compass bearing the data gives by the way the rink lies (the frame has the rink's long side along x). `edge` is the low rim's height.
|
|
260
|
+
*/
|
|
261
|
+
function saddleOf(data, footprint, at, heading, edge) {
|
|
262
|
+
const radii = Array.from({ length: 72 }, (_, k) => {
|
|
263
|
+
const a = (2 * Math.PI * k) / 72;
|
|
264
|
+
return rayLength(footprint, at, a);
|
|
265
|
+
}).sort((a, b) => a - b);
|
|
266
|
+
const turn = ((data.bearing - heading) * Math.PI) / 180;
|
|
267
|
+
return { centre: at, radius: round(radii[36], 1), axis: [round(Math.cos(turn), 4), round(Math.sin(turn), 4)], low: edge, high: data.high };
|
|
268
|
+
}
|
|
269
|
+
/** How far a ray from `from` at `angle` runs before it leaves a polygon. */
|
|
270
|
+
function rayLength(poly, from, angle) {
|
|
271
|
+
const [dx, dy] = [Math.cos(angle), Math.sin(angle)];
|
|
272
|
+
let best = Infinity;
|
|
273
|
+
poly.forEach(([ax, ay], i) => {
|
|
274
|
+
const [bx, by] = poly[(i + 1) % poly.length];
|
|
275
|
+
const [ex, ey] = [bx - ax, by - ay];
|
|
276
|
+
const den = dx * ey - dy * ex;
|
|
277
|
+
if (Math.abs(den) < 1e-12)
|
|
278
|
+
return;
|
|
279
|
+
const t = ((ax - from[0]) * ey - (ay - from[1]) * ex) / den;
|
|
280
|
+
const u = ((ax - from[0]) * dy - (ay - from[1]) * dx) / den;
|
|
281
|
+
if (t > 1e-6 && u >= 0 && u <= 1 && t < best)
|
|
282
|
+
best = t;
|
|
283
|
+
});
|
|
284
|
+
return Number.isFinite(best) ? best : 0;
|
|
285
|
+
}
|
|
253
286
|
/** The stands of a venue for `layoutOf` and the 3D view, round a rink: `planVenue`'s bowl. */
|
|
254
287
|
export const venueBowl = (venue, rink) => planVenue(venue, rink).bowl;
|
|
255
288
|
/** Whether the bowl lies inside the building: every corner of every tier's outer edge is inside the footprint. */
|
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.
|
|
2
|
+
export declare const VERSION = "0.48.1";
|
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.
|
|
2
|
+
export const VERSION = "0.48.1";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.1",
|
|
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",
|
|
@@ -342,6 +342,7 @@
|
|
|
342
342
|
"arenas:check": "node scripts/check-arenas.mjs",
|
|
343
343
|
"venues": "node scripts/build-venues.mjs",
|
|
344
344
|
"venues:fetch": "node scripts/fetch-venues.mjs",
|
|
345
|
+
"venues:rink": "node scripts/fetch-rink-evidence.mjs",
|
|
345
346
|
"stadiums": "node scripts/build-stadiums.mjs",
|
|
346
347
|
"stadiums:fetch": "node scripts/fetch-stadiums.mjs",
|
|
347
348
|
"walk": "node scripts/build-walk.mjs",
|