@johnmorrisdotca/kyogijo-stadiums 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/NOTICE.md +4 -0
  3. package/README.md +71 -16
  4. package/dist/annotate.js +1 -1
  5. package/dist/athletics/describe.d.ts +8 -0
  6. package/dist/athletics/describe.js +41 -0
  7. package/dist/athletics/events.d.ts +17 -0
  8. package/dist/athletics/events.js +48 -0
  9. package/dist/athletics/facilities.d.ts +80 -0
  10. package/dist/athletics/facilities.js +176 -0
  11. package/dist/athletics/infield.d.ts +79 -0
  12. package/dist/athletics/infield.js +166 -0
  13. package/dist/athletics/layout.d.ts +13 -0
  14. package/dist/athletics/layout.js +98 -0
  15. package/dist/athletics/oval.d.ts +57 -0
  16. package/dist/athletics/oval.js +116 -0
  17. package/dist/athletics/plan.d.ts +97 -0
  18. package/dist/athletics/plan.js +355 -0
  19. package/dist/athletics/races.d.ts +102 -0
  20. package/dist/athletics/races.js +355 -0
  21. package/dist/athletics/steeplechase.d.ts +72 -0
  22. package/dist/athletics/steeplechase.js +196 -0
  23. package/dist/athletics/stencil.d.ts +13 -0
  24. package/dist/athletics/stencil.js +85 -0
  25. package/dist/athletics/track.d.ts +54 -0
  26. package/dist/athletics/track.js +105 -0
  27. package/dist/athletics/types.d.ts +77 -0
  28. package/dist/athletics/types.js +1 -0
  29. package/dist/athletics-entry.d.ts +17 -0
  30. package/dist/athletics-entry.js +11 -0
  31. package/dist/athletics.style.d.ts +16 -0
  32. package/dist/athletics.style.js +51 -0
  33. package/dist/atlas-entry.d.ts +4 -2
  34. package/dist/atlas-entry.js +3 -2
  35. package/dist/atlas.d.ts +83 -7
  36. package/dist/atlas.js +108 -8
  37. package/dist/charts-entry.d.ts +6 -1
  38. package/dist/charts-entry.js +3 -0
  39. package/dist/charts.athletics.d.ts +183 -0
  40. package/dist/charts.athletics.js +455 -0
  41. package/dist/charts.curling.heat.d.ts +24 -0
  42. package/dist/charts.curling.heat.js +116 -0
  43. package/dist/charts.curling.js +14 -3
  44. package/dist/charts.pool.d.ts +67 -0
  45. package/dist/charts.pool.js +76 -0
  46. package/dist/charts.skating.d.ts +204 -0
  47. package/dist/charts.skating.js +426 -0
  48. package/dist/charts.types.d.ts +53 -1
  49. package/dist/court.d.ts +85 -2
  50. package/dist/court.js +102 -7
  51. package/dist/court.more.d.ts +46 -0
  52. package/dist/court.more.js +219 -0
  53. package/dist/courts.style.d.ts +14 -2
  54. package/dist/courts.style.js +51 -4
  55. package/dist/crowd.d.ts +154 -0
  56. package/dist/crowd.draw.d.ts +17 -0
  57. package/dist/crowd.draw.js +198 -0
  58. package/dist/crowd.js +465 -0
  59. package/dist/crowd.park.d.ts +19 -0
  60. package/dist/crowd.park.js +153 -0
  61. package/dist/curling.stats.d.ts +271 -0
  62. package/dist/curling.stats.js +301 -0
  63. package/dist/draw.d.ts +16 -0
  64. package/dist/draw.js +318 -35
  65. package/dist/element-entry.d.ts +1 -1
  66. package/dist/element-entry.js +1 -1
  67. package/dist/element.d.ts +13 -2
  68. package/dist/element.js +77 -3
  69. package/dist/features.js +131 -0
  70. package/dist/fields.kit.d.ts +2 -2
  71. package/dist/fields.types.d.ts +18 -4
  72. package/dist/frames.providers.js +63 -8
  73. package/dist/geojson.js +3 -0
  74. package/dist/geometry-entry.d.ts +2 -1
  75. package/dist/geometry-entry.js +2 -1
  76. package/dist/geometry.d.ts +20 -0
  77. package/dist/geometry.js +78 -1
  78. package/dist/grounds.d.ts +4 -0
  79. package/dist/grounds.data.js +12 -0
  80. package/dist/hardwood.d.ts +31 -0
  81. package/dist/hardwood.js +157 -0
  82. package/dist/heat.js +4 -3
  83. package/dist/heat.types.d.ts +5 -0
  84. package/dist/heat.zones.d.ts +2 -2
  85. package/dist/heat.zones.js +154 -6
  86. package/dist/homeside.js +17 -0
  87. package/dist/index.d.ts +16 -2
  88. package/dist/index.js +10 -1
  89. package/dist/layers.d.ts +1 -1
  90. package/dist/layers.env.d.ts +3 -1
  91. package/dist/layers.env.js +4 -2
  92. package/dist/layers.js +4 -4
  93. package/dist/leagues/athletics.d.ts +63 -0
  94. package/dist/leagues/athletics.js +87 -0
  95. package/dist/leagues/courts.d.ts +269 -4
  96. package/dist/leagues/courts.js +155 -1
  97. package/dist/leagues/skating.d.ts +145 -0
  98. package/dist/leagues/skating.js +73 -0
  99. package/dist/leagues/sources.js +20 -0
  100. package/dist/leagues/types.d.ts +1 -1
  101. package/dist/leagues-entry.d.ts +4 -2
  102. package/dist/leagues-entry.js +2 -1
  103. package/dist/leagues.d.ts +14 -4
  104. package/dist/leagues.js +146 -5
  105. package/dist/look.d.ts +3 -3
  106. package/dist/look.js +39 -6
  107. package/dist/outline.d.ts +1 -1
  108. package/dist/outline.js +30 -2
  109. package/dist/pageant.d.ts +120 -0
  110. package/dist/pageant.draw.d.ts +21 -0
  111. package/dist/pageant.draw.js +171 -0
  112. package/dist/pageant.js +207 -0
  113. package/dist/pageant.style.d.ts +8 -0
  114. package/dist/pageant.style.js +42 -0
  115. package/dist/png.d.ts +8 -1
  116. package/dist/png.js +21 -1
  117. package/dist/pool.d.ts +176 -0
  118. package/dist/pool.figures.d.ts +304 -0
  119. package/dist/pool.figures.js +144 -0
  120. package/dist/pool.js +304 -0
  121. package/dist/pool.kit.d.ts +48 -0
  122. package/dist/pool.kit.js +141 -0
  123. package/dist/pool.labels.d.ts +20 -0
  124. package/dist/pool.labels.js +257 -0
  125. package/dist/pool.race.d.ts +65 -0
  126. package/dist/pool.race.js +140 -0
  127. package/dist/pool.replay.d.ts +46 -0
  128. package/dist/pool.replay.js +127 -0
  129. package/dist/pool.section.d.ts +13 -0
  130. package/dist/pool.section.js +83 -0
  131. package/dist/pool.style.d.ts +20 -0
  132. package/dist/pool.style.js +169 -0
  133. package/dist/pool.types.d.ts +145 -0
  134. package/dist/pool.types.js +3 -0
  135. package/dist/pool.words.d.ts +13 -0
  136. package/dist/pool.words.js +101 -0
  137. package/dist/ranges.names.js +47 -3
  138. package/dist/replay-entry.d.ts +3 -0
  139. package/dist/replay-entry.js +2 -0
  140. package/dist/restyle.js +1 -1
  141. package/dist/score.js +70 -5
  142. package/dist/sheet.d.ts +3 -0
  143. package/dist/sheet.js +7 -3
  144. package/dist/skating/describe.d.ts +7 -0
  145. package/dist/skating/describe.js +44 -0
  146. package/dist/skating/events.d.ts +24 -0
  147. package/dist/skating/events.js +47 -0
  148. package/dist/skating/figure.d.ts +24 -0
  149. package/dist/skating/figure.js +37 -0
  150. package/dist/skating/long.d.ts +54 -0
  151. package/dist/skating/long.js +111 -0
  152. package/dist/skating/parts.d.ts +43 -0
  153. package/dist/skating/parts.js +40 -0
  154. package/dist/skating/plan.d.ts +55 -0
  155. package/dist/skating/plan.js +197 -0
  156. package/dist/skating/short.d.ts +47 -0
  157. package/dist/skating/short.js +89 -0
  158. package/dist/skating/track.d.ts +66 -0
  159. package/dist/skating/track.js +94 -0
  160. package/dist/skating/types.d.ts +57 -0
  161. package/dist/skating/types.js +3 -0
  162. package/dist/skating-entry.d.ts +17 -0
  163. package/dist/skating-entry.js +11 -0
  164. package/dist/skating.style.d.ts +4 -0
  165. package/dist/skating.style.js +24 -0
  166. package/dist/strings.d.ts +296 -0
  167. package/dist/strings.js +328 -11
  168. package/dist/style.d.ts +2 -0
  169. package/dist/style.js +11 -1
  170. package/dist/surfaces/artistic.d.ts +9 -0
  171. package/dist/surfaces/artistic.js +94 -0
  172. package/dist/surfaces/athletics.d.ts +16 -0
  173. package/dist/surfaces/athletics.js +132 -0
  174. package/dist/surfaces/baseball.js +15 -0
  175. package/dist/surfaces/basketball.floor.d.ts +27 -0
  176. package/dist/surfaces/basketball.floor.js +83 -0
  177. package/dist/surfaces/basketball.gear.d.ts +27 -0
  178. package/dist/surfaces/basketball.gear.js +90 -0
  179. package/dist/surfaces/basketball.js +43 -21
  180. package/dist/surfaces/curling.d.ts +16 -0
  181. package/dist/surfaces/curling.fold.d.ts +67 -0
  182. package/dist/surfaces/curling.fold.js +107 -0
  183. package/dist/surfaces/curling.js +37 -3
  184. package/dist/surfaces/dive.d.ts +9 -0
  185. package/dist/surfaces/dive.js +128 -0
  186. package/dist/surfaces/field.d.ts +7 -2
  187. package/dist/surfaces/field.js +15 -9
  188. package/dist/surfaces/hockey.js +1 -0
  189. package/dist/surfaces/net.d.ts +2 -1
  190. package/dist/surfaces/net.js +160 -15
  191. package/dist/surfaces/polo.d.ts +12 -0
  192. package/dist/surfaces/polo.js +159 -0
  193. package/dist/surfaces/pool.d.ts +27 -0
  194. package/dist/surfaces/pool.js +198 -0
  195. package/dist/surfaces/skating.d.ts +6 -0
  196. package/dist/surfaces/skating.js +62 -0
  197. package/dist/surfaces/soccer.js +2 -1
  198. package/dist/surfaces/surface.d.ts +44 -0
  199. package/dist/surfaces/venue.d.ts +15 -0
  200. package/dist/surfaces/venue.js +95 -0
  201. package/dist/tenants.d.ts +77 -0
  202. package/dist/tenants.data.d.ts +8 -0
  203. package/dist/tenants.data.js +945 -0
  204. package/dist/tenants.js +46 -0
  205. package/dist/turn-entry.d.ts +12 -0
  206. package/dist/turn-entry.js +7 -0
  207. package/dist/turn.camera.d.ts +105 -0
  208. package/dist/turn.camera.js +168 -0
  209. package/dist/turn.dom.d.ts +40 -0
  210. package/dist/turn.dom.js +351 -0
  211. package/dist/turn.kit.d.ts +86 -0
  212. package/dist/turn.kit.js +110 -0
  213. package/dist/turn.markup.d.ts +48 -0
  214. package/dist/turn.markup.js +108 -0
  215. package/dist/turn.model.d.ts +78 -0
  216. package/dist/turn.model.js +91 -0
  217. package/dist/turn.style.d.ts +5 -0
  218. package/dist/turn.style.js +55 -0
  219. package/dist/types.d.ts +183 -18
  220. package/dist/units.d.ts +1 -1
  221. package/dist/units.js +15 -1
  222. package/dist/uprights.board.d.ts +17 -0
  223. package/dist/uprights.board.js +59 -0
  224. package/dist/uprights.d.ts +37 -0
  225. package/dist/uprights.fields.d.ts +32 -0
  226. package/dist/uprights.fields.js +172 -0
  227. package/dist/uprights.goal.d.ts +49 -0
  228. package/dist/uprights.goal.js +69 -0
  229. package/dist/uprights.js +160 -0
  230. package/dist/uprights.more.d.ts +7 -0
  231. package/dist/uprights.more.js +183 -0
  232. package/dist/uprights.net.d.ts +12 -0
  233. package/dist/uprights.net.js +109 -0
  234. package/dist/uprights.netkit.d.ts +28 -0
  235. package/dist/uprights.netkit.js +67 -0
  236. package/dist/uprights.pools.d.ts +8 -0
  237. package/dist/uprights.pools.js +190 -0
  238. package/dist/uprights.rinks.d.ts +27 -0
  239. package/dist/uprights.rinks.js +106 -0
  240. package/dist/uprights.track.d.ts +50 -0
  241. package/dist/uprights.track.js +246 -0
  242. package/dist/version.d.ts +1 -1
  243. package/dist/version.js +1 -1
  244. package/package.json +19 -2
@@ -0,0 +1,246 @@
1
+ // What stands in an athletics stadium and at a skating rink, in 3D: the hurdles of the races drawn and the steeplechase's barriers with the water jump's, the uprights and bars of the high jump and the
2
+ // pole vault, the discus and hammer cage; the padding round a long or short track and the boards of a figure skating rink. The plans are in metres in the frame of their own origin, and the drawing's
3
+ // frame is feet from the corner of the plan's box, so every point goes through `at`. The heights are cited in docs/sources.md ("Heights in the 3D view"): the cage's from the Track and Field
4
+ // Facilities Manual 2019 (2.4.1.3), the hurdles' and the barriers' from the Technical Rules (22, 23), the padding's from the ISU's Rule 228.2; the bars' heights are ours, a bar being set at the height of
5
+ // the competition.
6
+ import { athleticsPlan } from "./athletics/plan.js";
7
+ import { outward, ahead } from "./athletics/races.js";
8
+ import { HURDLE, INSIDE, OUTSIDE, scPose } from "./athletics/steeplechase.js";
9
+ import { laneRadius, pose } from "./athletics/track.js";
10
+ import { feet } from "./pool.js";
11
+ import { iceRadius } from "./skating/long.js";
12
+ import { skatingPlan } from "./skating/plan.js";
13
+ import { bar, mesh, n, plane, pole, shy, threads, wall } from "./turn.kit.js";
14
+ import { BOARD_HEIGHT } from "./uprights.rinks.js";
15
+ /** The hurdles' heights: the men's 110 m (and the covered 60 m) 1.067 m, the women's 100 m 0.838 m, the 400 m 0.914 m (Technical Rule 22); a steeplechase barrier 0.914 m (Rule 23.5). */
16
+ export const HURDLE_HEIGHT = { "110m-hurdles": 1.067, "60m-hurdles": 1.067, "100m-hurdles": 0.838, "400m-hurdles": 0.914, steeplechase: 0.914 };
17
+ /** A hurdle is 1.18 to 1.20 m wide (Rule 22): 1.2 m is drawn. */
18
+ const HURDLE_WIDTH = 1.2;
19
+ /** The cage's netting is at least 4 m high, and at least 6 m for the 3 m nearest the front of each side (Facilities Manual 2.4.1.3). */
20
+ export const CAGE = { low: 4, high: 6, highLength: 3 };
21
+ /** The high jump's uprights are 4.02 m apart (Manual 2.3.3.3) and the pole vault's at least 5.20 m (2.3.4.3). The heights of the bars are ours. */
22
+ export const JUMPS = { highUprights: 4.02, highBar: 2, highPost: 2.5, vaultUprights: 5.2, vaultBar: 5, vaultPost: 6, vaultBarLength: 4.5 };
23
+ /** The padding round a track is at least 0.80 m high and 0.30 m thick (ISU Rule 228.2). */
24
+ export const PADDING = { height: 0.8 };
25
+ /** A hurdle: a bar across the lane with stripes on its top, and its two uprights. */
26
+ function hurdlePlane(id, a, b, height, thin) {
27
+ const run = Math.hypot(b[0] - a[0], b[1] - a[1]);
28
+ const top = Math.max(feet(0.07), thin);
29
+ const stripes = 8;
30
+ let bands = "";
31
+ for (let i = 0; i < stripes; i += 1)
32
+ bands += `<rect x="${n((run * i) / stripes)}" width="${n(run / stripes)}" height="${n(top)}" class="${i % 2 === 0 ? "u-white" : "u-leg"}"/>`;
33
+ const side = Math.max(feet(0.04), thin * 0.8);
34
+ const sides = `<rect width="${n(side)}" height="${n(height)}" class="u-leg"/><rect x="${n(run - side)}" width="${n(side)}" height="${n(height)}" class="u-leg"/>`;
35
+ return wall(id, "wall", a[0], a[1], b[0], b[1], 0, height, `${sides}${bands}`);
36
+ }
37
+ /** The hurdles of the races a drawing marks, and the steeplechase's barriers. */
38
+ function hurdles(plan, at, thin) {
39
+ const planes = [];
40
+ const o = plan.oval;
41
+ for (const race of plan.races) {
42
+ if (race.hurdles === undefined)
43
+ continue;
44
+ const height = feet(HURDLE_HEIGHT[race.race.id] ?? HURDLE_HEIGHT["110m-hurdles"]);
45
+ for (const { lane, at: marks } of race.hurdles) {
46
+ marks.forEach((s, k) => {
47
+ const id = `hurdle-${race.race.id}-${lane}-${k + 1}`;
48
+ if (race.race.kind === "straight") {
49
+ // The lane of the straight: from its top line to the next, the 50 mm line on its right left out.
50
+ const top = plan.straight?.y0 ?? o.radius;
51
+ const sl = plan.straight?.lane ?? o.lane;
52
+ const y = top + (lane - 0.5) * sl - 0.025;
53
+ planes.push(hurdlePlane(id, at(s + 0.1, y - HURDLE_WIDTH / 2), at(s + 0.1, y + HURDLE_WIDTH / 2), height, thin));
54
+ }
55
+ else {
56
+ // On the oval: the point of the running line at that distance, and the middle of the lane across from it.
57
+ const run = laneRadius(o, lane);
58
+ const p = pose(o, run, s);
59
+ const [nx, ny] = outward(p.heading);
60
+ const rc = o.radius + (lane - 0.5) * o.lane - 0.025;
61
+ const c = [p.x + (rc - run) * nx, p.y + (rc - run) * ny];
62
+ planes.push(hurdlePlane(id, at(c[0] - (HURDLE_WIDTH / 2) * nx, c[1] - (HURDLE_WIDTH / 2) * ny), at(c[0] + (HURDLE_WIDTH / 2) * nx, c[1] + (HURDLE_WIDTH / 2) * ny), height, thin));
63
+ }
64
+ });
65
+ }
66
+ }
67
+ const items = [];
68
+ if (planes.length > 0)
69
+ items.push({ id: "hurdles", kind: "hurdles", at: [0, 0], height: Math.max(...planes.map((p) => -p.v[2])), planes });
70
+ if (plan.waterJump !== undefined) {
71
+ const barriers = [];
72
+ const variant = plan.waterJump;
73
+ const h = feet(HURDLE_HEIGHT.steeplechase);
74
+ (variant === "outside" ? OUTSIDE.hurdles : INSIDE.hurdles).forEach((s, i) => {
75
+ const p = scPose(o, variant, s);
76
+ const [nx, ny] = outward(p.heading);
77
+ const width = i === 3 ? HURDLE.pit : HURDLE.width;
78
+ const a = -p.innerOffset - HURDLE.inside;
79
+ const [x0, y0] = at(p.x + a * nx, p.y + a * ny);
80
+ const [x1, y1] = at(p.x + (a + width) * nx, p.y + (a + width) * ny);
81
+ const run = Math.hypot(x1 - x0, y1 - y0);
82
+ const cap = Math.max(feet(HURDLE.bar), thin);
83
+ barriers.push(wall(i === 3 ? "water-jump-barrier" : `steeplechase-barrier-${i + 1}`, "wall", x0, y0, x1, y1, 0, h, `<rect width="${n(run)}" height="${n(h)}" class="u-board"/><rect width="${n(run)}" height="${n(cap)}" class="u-leg"/>`));
84
+ if (i === 3) {
85
+ // The pit, 3.66 m along the run from its barrier and 3.66 m across: the water, level with the track.
86
+ const [fx, fy] = ahead(p.heading);
87
+ const lift = 0.04;
88
+ barriers.push(plane("water-pit", "board", [x0, y0, lift], [fx * feet(HURDLE.pit), fy * feet(HURDLE.pit), 0], [x1 - x0, y1 - y0, 0], `<rect width="${n(feet(HURDLE.pit))}" height="${n(run)}" class="u-pad"/>`));
89
+ }
90
+ });
91
+ items.push({ id: "steeplechase", kind: "steeplechase", at: [0, 0], height: h, planes: barriers });
92
+ }
93
+ return items;
94
+ }
95
+ /** The high jump's two sets of uprights with their bars, and the pole vault's. */
96
+ function jumps(plan, at, thin) {
97
+ const items = [];
98
+ const posts = Math.max(feet(0.05), thin * 1.2);
99
+ const bars = Math.max(feet(0.03), thin * 0.7);
100
+ const high = [];
101
+ const vault = [];
102
+ for (const f of plan.facilities) {
103
+ if (f.event !== "high-jump" && f.event !== "pole-vault")
104
+ continue;
105
+ const [ux, uy] = ahead(f.heading);
106
+ const [vx, vy] = outward(f.heading);
107
+ const isHigh = f.event === "high-jump";
108
+ const half = (isHigh ? JUMPS.highUprights : JUMPS.vaultUprights) / 2;
109
+ // The pole vault's uprights stand 0.1 m beyond the middle of the stop board (the drawing's); the high jump's on the take-off line.
110
+ const along = isHigh ? 0 : 0.1;
111
+ const a = at(f.x + along * ux - half * vx, f.y + along * uy - half * vy);
112
+ const b = at(f.x + along * ux + half * vx, f.y + along * uy + half * vy);
113
+ const top = feet(isHigh ? JUMPS.highPost : JUMPS.vaultPost);
114
+ const barZ = feet(isHigh ? JUMPS.highBar : JUMPS.vaultBar);
115
+ const out = isHigh ? high : vault;
116
+ out.push(...pole(`${f.id}-upright-a`, "post", a[0], a[1], 0, top, posts, "u-pole"), ...pole(`${f.id}-upright-b`, "post", b[0], b[1], 0, top, posts, "u-pole"));
117
+ // The high jump's bar runs from upright to upright; the vault's rests on supports between them and is 4.5 m long.
118
+ if (isHigh)
119
+ out.push(...bar(`${f.id}-bar`, "post", [a[0], a[1], barZ], [b[0], b[1], barZ], bars, "u-white"));
120
+ else {
121
+ const m = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
122
+ const d = Math.hypot(b[0] - a[0], b[1] - a[1]);
123
+ const k = (feet(JUMPS.vaultBarLength) / 2) / d;
124
+ out.push(...bar(`${f.id}-bar`, "post", [m[0] - (b[0] - a[0]) * k, m[1] - (b[1] - a[1]) * k, barZ], [m[0] + (b[0] - a[0]) * k, m[1] + (b[1] - a[1]) * k, barZ], bars, "u-white"));
125
+ }
126
+ }
127
+ if (high.length > 0)
128
+ items.push({ id: "high-jump", kind: "high-jump", at: [0, 0], height: feet(JUMPS.highBar), planes: high });
129
+ if (vault.length > 0)
130
+ items.push({ id: "pole-vault", kind: "pole-vault", at: [0, 0], height: feet(JUMPS.vaultBar), planes: vault });
131
+ return items;
132
+ }
133
+ /** The discus and hammer cage: netting 4 m high, 6 m for the 3 m nearest the front of each side, along the plan's U (the mouth 6 m wide 7 m in front of the circle's centre). */
134
+ function cage(plan, at, thin) {
135
+ const seen = new Set();
136
+ const planes = [];
137
+ const cell = Math.max(feet(0.5), thin * 4);
138
+ const netting = (id, a, b, z, h) => {
139
+ const [x0, y0] = at(a[0], a[1]);
140
+ const [x1, y1] = at(b[0], b[1]);
141
+ const run = Math.hypot(x1 - x0, y1 - y0);
142
+ if (run <= 0)
143
+ return;
144
+ planes.push(wall(id, "wall", x0, y0, x1, y1, z, z + h, `<rect width="${n(run)}" height="${n(h)}" class="u-netfill"/>${threads(mesh(run, h, cell), cell)}<rect width="${n(run)}" height="${n(Math.max(thin * 0.5, 0.1))}" class="u-cap"/>`));
145
+ };
146
+ for (const f of plan.facilities) {
147
+ if (f.event !== "discus-throw" && f.event !== "hammer-throw")
148
+ continue;
149
+ const key = `${f.x.toFixed(2)},${f.y.toFixed(2)}`;
150
+ if (seen.has(key))
151
+ continue;
152
+ seen.add(key);
153
+ const [ux, uy] = ahead(f.heading);
154
+ const [vx, vy] = outward(f.heading);
155
+ const pt = (u, v) => [f.x + u * ux + v * vx, f.y + u * uy + v * vy];
156
+ // The sides, from the mouth back to the circle's level: the first 3 m of each at 6 m, the rest at 4 m. The line is the plan's own: (7, ±3) to (0, ±4.4).
157
+ for (const side of [-1, 1]) {
158
+ const mouth = pt(7, side * 3);
159
+ const back = pt(0, side * 4.4);
160
+ const length = Math.hypot(back[0] - mouth[0], back[1] - mouth[1]);
161
+ const t = CAGE.highLength / length;
162
+ const mid = [mouth[0] + (back[0] - mouth[0]) * t, mouth[1] + (back[1] - mouth[1]) * t];
163
+ netting(`cage-side-${side < 0 ? "a" : "b"}-front`, mouth, mid, 0, feet(CAGE.high));
164
+ netting(`cage-side-${side < 0 ? "a" : "b"}-back`, mid, back, 0, feet(CAGE.low));
165
+ }
166
+ // The rear: the half circle of 4.4 m about the centre, behind it, in eight chords.
167
+ const steps = 8;
168
+ for (let i = 0; i < steps; i += 1) {
169
+ const p0 = (Math.PI * i) / steps;
170
+ const p1 = (Math.PI * (i + 1)) / steps;
171
+ const g = (p) => pt(-4.4 * Math.sin(p), -4.4 * Math.cos(p));
172
+ netting(`cage-rear-${i + 1}`, g(p0), g(p1), 0, feet(CAGE.low));
173
+ }
174
+ }
175
+ return planes.length === 0 ? [] : [{ id: "cage", kind: "cage", at: [0, 0], height: feet(CAGE.high), planes }];
176
+ }
177
+ /** An athletics stadium's uprights, as the plan has its box. */
178
+ export function athleticsUprights(o, thin) {
179
+ const plan = athleticsPlan({ ...o, detail: o.detail });
180
+ const at = (x, y) => [feet(x - plan.box.x0), feet(y - plan.box.y0)];
181
+ return {
182
+ items: [...hurdles(plan, at, thin), ...jumps(plan, at, thin), ...cage(plan, at, thin)],
183
+ area: { x0: 0, y0: 0, x1: feet(plan.box.x1 - plan.box.x0), y1: feet(plan.box.y1 - plan.box.y0) },
184
+ };
185
+ }
186
+ /** The walls of a closed outline of points, as planes of `height`: each segment is a wall whose inner face is drawn, giving way to the eye. */
187
+ function walls(id, points, height, side, top, thin, centre) {
188
+ const planes = [];
189
+ for (let i = 0; i < points.length; i += 1) {
190
+ const [x0, y0] = points[i];
191
+ const [x1, y1] = points[(i + 1) % points.length];
192
+ const run = Math.hypot(x1 - x0, y1 - y0);
193
+ if (run < 1e-6)
194
+ continue;
195
+ const cap = Math.max(thin * 0.8, 0.1);
196
+ planes.push(shy(wall(`${id}-${i}`, "wall", x0, y0, x1, y1, 0, height, `<rect width="${n(run)}" height="${n(height)}" class="${side}"/><rect width="${n(run)}" height="${n(cap)}" class="${top}"/>`), centre));
197
+ }
198
+ return planes;
199
+ }
200
+ /** A stadium's outline (two straights of `f` between the centres of two half circles of radius `r`) as points about the origin, in metres. */
201
+ function stadiumPoints(f, r, steps = 14) {
202
+ const out = [[-f / 2, -r]];
203
+ for (let i = 0; i <= steps; i += 1) {
204
+ const a = (Math.PI * i) / steps;
205
+ out.push([f / 2 + r * Math.sin(a), -r * Math.cos(a)]);
206
+ }
207
+ for (let i = 0; i <= steps; i += 1) {
208
+ const a = (Math.PI * i) / steps;
209
+ out.push([-f / 2 - r * Math.sin(a), r * Math.cos(a)]);
210
+ }
211
+ return out;
212
+ }
213
+ /** A rounded rectangle's outline, half sizes `hx`, `hy` and corner radius `k`, as points about the origin, in metres. */
214
+ function roundedPoints(hx, hy, k, steps = 6) {
215
+ const out = [];
216
+ const corners = [[hx - k, -hy + k, -Math.PI / 2], [hx - k, hy - k, 0], [-hx + k, hy - k, Math.PI / 2], [-hx + k, -hy + k, Math.PI]];
217
+ for (const [cx, cy, a0] of corners)
218
+ for (let i = 0; i <= steps; i += 1)
219
+ out.push([cx + k * Math.cos(a0 + ((Math.PI / 2) * i) / steps), cy + k * Math.sin(a0 + ((Math.PI / 2) * i) / steps)]);
220
+ return out;
221
+ }
222
+ /** What stands at a skating rink: the padding round a long or a short track, 0.80 m high (ISU Rule 228.2); the boards of a figure skating rink, as high as a hockey rink's and with no glass over them. */
223
+ export function skatingUprights(o, thin) {
224
+ const plan = skatingPlan({ ...o, detail: o.detail });
225
+ const at = (p) => [feet(p[0] - plan.box.x0), feet(p[1] - plan.box.y0)];
226
+ const area = { x0: 0, y0: 0, x1: feet(plan.box.x1 - plan.box.x0), y1: feet(plan.box.y1 - plan.box.y0) };
227
+ const centre = at([0, 0]);
228
+ const items = [];
229
+ const style = o.skating;
230
+ const padding = style?.padding !== false;
231
+ if (plan.oval !== undefined && padding) {
232
+ const R = iceRadius(plan.oval);
233
+ const points = stadiumPoints(plan.oval.straight, R).map(at);
234
+ items.push({ id: "padding", kind: "padding", at: centre, height: feet(PADDING.height), planes: walls("padding", points, feet(PADDING.height), "u-pad", "u-cap", thin, centre) });
235
+ }
236
+ else if (plan.short !== undefined && padding) {
237
+ const points = roundedPoints(plan.short.length / 2, plan.short.width / 2, 8.5).map(at);
238
+ items.push({ id: "padding", kind: "padding", at: centre, height: feet(PADDING.height), planes: walls("padding", points, feet(PADDING.height), "u-pad", "u-cap", thin, centre) });
239
+ }
240
+ else if (plan.rink !== undefined) {
241
+ const fig = plan.figures;
242
+ const points = roundedPoints(plan.rink.length / 2, plan.rink.width / 2, fig.corner ?? 8.5).map(at);
243
+ items.push({ id: "rink-boards", kind: "rink-boards", at: centre, height: BOARD_HEIGHT, planes: walls("board", points, BOARD_HEIGHT, "u-board", "u-cap", thin, centre) });
244
+ }
245
+ return { items, area };
246
+ }
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.4.0";
2
+ export declare const VERSION = "0.5.0";
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.4.0";
2
+ export const VERSION = "0.5.0";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@johnmorrisdotca/kyogijo-stadiums",
3
- "version": "0.4.0",
4
- "description": "Kyogijo Stadiums 競技場, sports surfaces as SVG, drawn to scale from the rulebooks: NFL, CFL and IFAF football fields, an NHL rink, an NBA court and MLB ballparks, with each team's name and logo on its side and the score in the middle. Light and dark, accessible, a compact badge for lists, a helper for React and a custom element. Zero dependencies.",
3
+ "version": "0.5.0",
4
+ "description": "Kyogijo Stadiums 競技場, 33 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, 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",
7
7
  "scoreboard",
@@ -129,6 +129,16 @@
129
129
  "import": "./dist/atlas-entry.js",
130
130
  "default": "./dist/atlas-entry.js"
131
131
  },
132
+ "./athletics": {
133
+ "types": "./dist/athletics-entry.d.ts",
134
+ "import": "./dist/athletics-entry.js",
135
+ "default": "./dist/athletics-entry.js"
136
+ },
137
+ "./skating": {
138
+ "types": "./dist/skating-entry.d.ts",
139
+ "import": "./dist/skating-entry.js",
140
+ "default": "./dist/skating-entry.js"
141
+ },
132
142
  "./charts": {
133
143
  "types": "./dist/charts-entry.d.ts",
134
144
  "import": "./dist/charts-entry.js",
@@ -174,6 +184,11 @@
174
184
  "import": "./dist/png-entry.js",
175
185
  "default": "./dist/png-entry.js"
176
186
  },
187
+ "./turn": {
188
+ "types": "./dist/turn-entry.d.ts",
189
+ "import": "./dist/turn-entry.js",
190
+ "default": "./dist/turn-entry.js"
191
+ },
177
192
  "./element/define": {
178
193
  "types": "./dist/element-define.d.ts",
179
194
  "import": "./dist/element-define.js",
@@ -217,6 +232,8 @@
217
232
  "grounds:check": "node scripts/check-grounds.mjs",
218
233
  "parks:coordinates": "node scripts/fetch-park-coordinates.mjs",
219
234
  "names:fetch": "node scripts/fetch-names.mjs",
235
+ "tenants": "node scripts/build-tenants.mjs",
236
+ "tenants:fetch": "node scripts/fetch-tenants.mjs",
220
237
  "parks:check": "node scripts/check-parks.mjs"
221
238
  },
222
239
  "devDependencies": {