@johnmorrisdotca/kyogijo-stadiums 0.4.0 → 0.6.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.
- package/CHANGELOG.md +133 -0
- package/NOTICE.md +182 -2
- package/README.md +106 -19
- package/dist/annotate.js +1 -1
- package/dist/arenas-entry.d.ts +4 -0
- package/dist/arenas-entry.js +3 -0
- package/dist/arenas.d.ts +125 -0
- package/dist/arenas.data.d.ts +2 -0
- package/dist/arenas.data.js +3763 -0
- package/dist/arenas.js +72 -0
- package/dist/athletics/describe.d.ts +8 -0
- package/dist/athletics/describe.js +41 -0
- package/dist/athletics/events.d.ts +17 -0
- package/dist/athletics/events.js +48 -0
- package/dist/athletics/facilities.d.ts +80 -0
- package/dist/athletics/facilities.js +176 -0
- package/dist/athletics/infield.d.ts +79 -0
- package/dist/athletics/infield.js +166 -0
- package/dist/athletics/layout.d.ts +13 -0
- package/dist/athletics/layout.js +98 -0
- package/dist/athletics/oval.d.ts +57 -0
- package/dist/athletics/oval.js +116 -0
- package/dist/athletics/plan.d.ts +97 -0
- package/dist/athletics/plan.js +355 -0
- package/dist/athletics/races.d.ts +102 -0
- package/dist/athletics/races.js +355 -0
- package/dist/athletics/steeplechase.d.ts +72 -0
- package/dist/athletics/steeplechase.js +196 -0
- package/dist/athletics/stencil.d.ts +13 -0
- package/dist/athletics/stencil.js +85 -0
- package/dist/athletics/track.d.ts +54 -0
- package/dist/athletics/track.js +105 -0
- package/dist/athletics/types.d.ts +77 -0
- package/dist/athletics/types.js +1 -0
- package/dist/athletics-entry.d.ts +17 -0
- package/dist/athletics-entry.js +11 -0
- package/dist/athletics.style.d.ts +16 -0
- package/dist/athletics.style.js +51 -0
- package/dist/atlas-entry.d.ts +6 -2
- package/dist/atlas-entry.js +4 -2
- package/dist/atlas.d.ts +117 -23
- package/dist/atlas.js +197 -12
- package/dist/background.js +2 -1
- package/dist/budo/describe.d.ts +13 -0
- package/dist/budo/describe.js +120 -0
- package/dist/budo/dojo.api.d.ts +64 -0
- package/dist/budo/dojo.api.js +46 -0
- package/dist/budo/dojo.d.ts +72 -0
- package/dist/budo/dojo.js +300 -0
- package/dist/budo/judo.d.ts +61 -0
- package/dist/budo/judo.js +109 -0
- package/dist/budo/karate.d.ts +29 -0
- package/dist/budo/karate.js +80 -0
- package/dist/budo/kendo.d.ts +18 -0
- package/dist/budo/kendo.js +44 -0
- package/dist/budo/kimarite.d.ts +19 -0
- package/dist/budo/kimarite.js +33 -0
- package/dist/budo/kit.d.ts +16 -0
- package/dist/budo/kit.js +24 -0
- package/dist/budo/kyudo.d.ts +28 -0
- package/dist/budo/kyudo.js +66 -0
- package/dist/budo/looks.d.ts +28 -0
- package/dist/budo/looks.js +58 -0
- package/dist/budo/parts.d.ts +32 -0
- package/dist/budo/parts.js +10 -0
- package/dist/budo/plan.d.ts +64 -0
- package/dist/budo/plan.js +139 -0
- package/dist/budo/room.d.ts +133 -0
- package/dist/budo/room.js +111 -0
- package/dist/budo/sumo.d.ts +31 -0
- package/dist/budo/sumo.js +71 -0
- package/dist/budo/tatami.d.ts +55 -0
- package/dist/budo/tatami.js +156 -0
- package/dist/budo/types.d.ts +192 -0
- package/dist/budo/types.js +2 -0
- package/dist/budo-entry.d.ts +22 -0
- package/dist/budo-entry.js +13 -0
- package/dist/budo.board.d.ts +28 -0
- package/dist/budo.board.js +81 -0
- package/dist/budo.score.d.ts +18 -0
- package/dist/budo.score.js +52 -0
- package/dist/budo.style.d.ts +6 -0
- package/dist/budo.style.js +67 -0
- package/dist/charts-entry.d.ts +6 -1
- package/dist/charts-entry.js +3 -0
- package/dist/charts.athletics.d.ts +183 -0
- package/dist/charts.athletics.js +455 -0
- package/dist/charts.baseball.js +1 -1
- package/dist/charts.curling.heat.d.ts +24 -0
- package/dist/charts.curling.heat.js +116 -0
- package/dist/charts.curling.js +14 -3
- package/dist/charts.js +4 -4
- package/dist/charts.pool.d.ts +67 -0
- package/dist/charts.pool.js +76 -0
- package/dist/charts.skating.d.ts +204 -0
- package/dist/charts.skating.js +426 -0
- package/dist/charts.soccer.js +3 -3
- package/dist/charts.types.d.ts +63 -1
- package/dist/colour.d.ts +4 -4
- package/dist/colour.js +4 -4
- package/dist/court.d.ts +85 -2
- package/dist/court.js +102 -7
- package/dist/court.more.d.ts +46 -0
- package/dist/court.more.js +219 -0
- package/dist/courts.style.d.ts +14 -2
- package/dist/courts.style.js +51 -4
- package/dist/crowd.d.ts +164 -0
- package/dist/crowd.draw.d.ts +17 -0
- package/dist/crowd.draw.js +204 -0
- package/dist/crowd.js +480 -0
- package/dist/crowd.park.d.ts +19 -0
- package/dist/crowd.park.js +153 -0
- package/dist/curling.stats.d.ts +271 -0
- package/dist/curling.stats.js +301 -0
- package/dist/draw.d.ts +16 -0
- package/dist/draw.js +462 -54
- package/dist/element-entry.d.ts +3 -1
- package/dist/element-entry.js +2 -1
- package/dist/element.d.ts +13 -2
- package/dist/element.js +79 -4
- package/dist/emblems-source.d.ts +50 -0
- package/dist/emblems-source.js +56 -0
- package/dist/eras.d.ts +3 -1
- package/dist/eras.js +8 -3
- package/dist/features.js +204 -0
- package/dist/field.data.d.ts +16 -0
- package/dist/field.data.js +50 -0
- package/dist/fields.kit.d.ts +2 -2
- package/dist/fields.types.d.ts +24 -4
- package/dist/formations.js +18 -7
- package/dist/formations.sports.d.ts +8 -0
- package/dist/formations.sports.js +251 -0
- package/dist/frames.providers.js +71 -8
- package/dist/geojson.js +3 -0
- package/dist/geometry-entry.d.ts +2 -1
- package/dist/geometry-entry.js +2 -1
- package/dist/geometry.d.ts +20 -0
- package/dist/geometry.js +78 -1
- package/dist/grounds.d.ts +4 -0
- package/dist/grounds.data.js +12 -0
- package/dist/halls.d.ts +65 -0
- package/dist/halls.js +122 -0
- package/dist/hardwood.d.ts +31 -0
- package/dist/hardwood.js +157 -0
- package/dist/heat.js +21 -13
- package/dist/heat.types.d.ts +5 -0
- package/dist/heat.zones.d.ts +4 -2
- package/dist/heat.zones.js +207 -7
- package/dist/homeside.js +24 -0
- package/dist/index.d.ts +30 -4
- package/dist/index.js +18 -2
- package/dist/layers-entry.d.ts +2 -1
- package/dist/layers-entry.js +1 -0
- package/dist/layers.d.ts +2 -1
- package/dist/layers.env.d.ts +12 -1
- package/dist/layers.env.js +36 -4
- package/dist/layers.js +32 -13
- package/dist/layers.types.d.ts +9 -2
- package/dist/leagues/athletics.d.ts +63 -0
- package/dist/leagues/athletics.js +87 -0
- package/dist/leagues/budo.d.ts +196 -0
- package/dist/leagues/budo.js +105 -0
- package/dist/leagues/courts.d.ts +269 -4
- package/dist/leagues/courts.js +155 -1
- package/dist/leagues/hockey.js +41 -19
- package/dist/leagues/skating.d.ts +145 -0
- package/dist/leagues/skating.js +73 -0
- package/dist/leagues/sources.js +41 -0
- package/dist/leagues/types.d.ts +1 -1
- package/dist/leagues-entry.d.ts +4 -2
- package/dist/leagues-entry.js +2 -1
- package/dist/leagues.d.ts +17 -4
- package/dist/leagues.js +246 -5
- package/dist/lineup.codes.d.ts +23 -0
- package/dist/lineup.codes.js +122 -0
- package/dist/logo.d.ts +25 -0
- package/dist/logo.js +47 -0
- package/dist/look.d.ts +3 -3
- package/dist/look.js +39 -6
- package/dist/outline.d.ts +1 -1
- package/dist/outline.js +46 -4
- package/dist/pageant.d.ts +120 -0
- package/dist/pageant.draw.d.ts +21 -0
- package/dist/pageant.draw.js +171 -0
- package/dist/pageant.js +211 -0
- package/dist/pageant.style.d.ts +8 -0
- package/dist/pageant.style.js +42 -0
- package/dist/png.d.ts +8 -1
- package/dist/png.js +21 -1
- package/dist/pointer-entry.d.ts +2 -0
- package/dist/pointer-entry.js +2 -0
- package/dist/pointer.d.ts +113 -0
- package/dist/pointer.js +151 -0
- package/dist/pool.d.ts +176 -0
- package/dist/pool.figures.d.ts +306 -0
- package/dist/pool.figures.js +148 -0
- package/dist/pool.js +304 -0
- package/dist/pool.kit.d.ts +48 -0
- package/dist/pool.kit.js +141 -0
- package/dist/pool.labels.d.ts +20 -0
- package/dist/pool.labels.js +258 -0
- package/dist/pool.race.d.ts +65 -0
- package/dist/pool.race.js +140 -0
- package/dist/pool.replay.d.ts +46 -0
- package/dist/pool.replay.js +127 -0
- package/dist/pool.section.d.ts +13 -0
- package/dist/pool.section.js +83 -0
- package/dist/pool.style.d.ts +20 -0
- package/dist/pool.style.js +169 -0
- package/dist/pool.types.d.ts +145 -0
- package/dist/pool.types.js +3 -0
- package/dist/pool.words.d.ts +13 -0
- package/dist/pool.words.js +101 -0
- package/dist/ranges.names.js +53 -3
- package/dist/replay-entry.d.ts +3 -0
- package/dist/replay-entry.js +2 -0
- package/dist/restyle.js +1 -1
- package/dist/road.draw.js +3 -2
- package/dist/road.js +2 -1
- package/dist/road.types.d.ts +3 -0
- package/dist/rules.d.ts +138 -0
- package/dist/rules.js +511 -0
- package/dist/rules.types.d.ts +4 -0
- package/dist/rules.types.js +64 -0
- package/dist/score.d.ts +3 -0
- package/dist/score.js +93 -6
- package/dist/sheet.d.ts +3 -0
- package/dist/sheet.js +7 -3
- package/dist/situation.d.ts +135 -0
- package/dist/situation.draw.d.ts +34 -0
- package/dist/situation.draw.js +202 -0
- package/dist/situation.js +337 -0
- package/dist/situation.style.d.ts +2 -0
- package/dist/situation.style.js +45 -0
- package/dist/situation.types.d.ts +77 -0
- package/dist/situation.types.js +3 -0
- package/dist/situation.widgets.d.ts +39 -0
- package/dist/situation.widgets.js +129 -0
- package/dist/skating/describe.d.ts +7 -0
- package/dist/skating/describe.js +44 -0
- package/dist/skating/events.d.ts +24 -0
- package/dist/skating/events.js +47 -0
- package/dist/skating/figure.d.ts +24 -0
- package/dist/skating/figure.js +37 -0
- package/dist/skating/long.d.ts +54 -0
- package/dist/skating/long.js +111 -0
- package/dist/skating/parts.d.ts +43 -0
- package/dist/skating/parts.js +40 -0
- package/dist/skating/plan.d.ts +55 -0
- package/dist/skating/plan.js +197 -0
- package/dist/skating/short.d.ts +47 -0
- package/dist/skating/short.js +89 -0
- package/dist/skating/track.d.ts +66 -0
- package/dist/skating/track.js +94 -0
- package/dist/skating/types.d.ts +57 -0
- package/dist/skating/types.js +3 -0
- package/dist/skating-entry.d.ts +17 -0
- package/dist/skating-entry.js +11 -0
- package/dist/skating.style.d.ts +4 -0
- package/dist/skating.style.js +24 -0
- package/dist/strings.d.ts +470 -0
- package/dist/strings.js +674 -13
- package/dist/style.d.ts +2 -0
- package/dist/style.js +19 -2
- package/dist/surfaces/artistic.d.ts +9 -0
- package/dist/surfaces/artistic.js +94 -0
- package/dist/surfaces/athletics.d.ts +16 -0
- package/dist/surfaces/athletics.js +132 -0
- package/dist/surfaces/baseball.js +17 -0
- package/dist/surfaces/basketball.floor.d.ts +27 -0
- package/dist/surfaces/basketball.floor.js +83 -0
- package/dist/surfaces/basketball.gear.d.ts +27 -0
- package/dist/surfaces/basketball.gear.js +90 -0
- package/dist/surfaces/basketball.js +44 -22
- package/dist/surfaces/budo.d.ts +6 -0
- package/dist/surfaces/budo.js +104 -0
- package/dist/surfaces/curling.d.ts +16 -0
- package/dist/surfaces/curling.fold.d.ts +67 -0
- package/dist/surfaces/curling.fold.js +107 -0
- package/dist/surfaces/curling.js +37 -3
- package/dist/surfaces/dive.d.ts +9 -0
- package/dist/surfaces/dive.js +128 -0
- package/dist/surfaces/field.d.ts +7 -2
- package/dist/surfaces/field.js +15 -9
- package/dist/surfaces/football.js +7 -0
- package/dist/surfaces/hockey.js +4 -2
- package/dist/surfaces/net.d.ts +2 -1
- package/dist/surfaces/net.js +160 -15
- package/dist/surfaces/polo.d.ts +12 -0
- package/dist/surfaces/polo.js +159 -0
- package/dist/surfaces/pool.d.ts +27 -0
- package/dist/surfaces/pool.js +198 -0
- package/dist/surfaces/skating.d.ts +6 -0
- package/dist/surfaces/skating.js +62 -0
- package/dist/surfaces/soccer.js +2 -1
- package/dist/surfaces/surface.d.ts +76 -0
- package/dist/surfaces/venue.d.ts +15 -0
- package/dist/surfaces/venue.js +95 -0
- package/dist/target-entry.d.ts +2 -0
- package/dist/target-entry.js +2 -0
- package/dist/target.d.ts +200 -0
- package/dist/target.js +525 -0
- package/dist/team.common.d.ts +1 -1
- package/dist/team.common.js +3 -3
- package/dist/team.formation.d.ts +3 -1
- package/dist/team.formation.js +3 -3
- package/dist/team.layers.d.ts +2 -2
- package/dist/team.layers.js +4 -1
- package/dist/team.lineup.d.ts +27 -0
- package/dist/team.lineup.js +207 -0
- package/dist/team.network.js +6 -5
- package/dist/team.shape.js +5 -5
- package/dist/team.types.d.ts +40 -1
- package/dist/tenants.d.ts +77 -0
- package/dist/tenants.data.d.ts +8 -0
- package/dist/tenants.data.js +1793 -0
- package/dist/tenants.js +46 -0
- package/dist/turn-entry.d.ts +12 -0
- package/dist/turn-entry.js +7 -0
- package/dist/turn.camera.d.ts +116 -0
- package/dist/turn.camera.js +184 -0
- package/dist/turn.dom.d.ts +40 -0
- package/dist/turn.dom.js +353 -0
- package/dist/turn.kit.d.ts +86 -0
- package/dist/turn.kit.js +110 -0
- package/dist/turn.markup.d.ts +48 -0
- package/dist/turn.markup.js +108 -0
- package/dist/turn.model.d.ts +78 -0
- package/dist/turn.model.js +91 -0
- package/dist/turn.style.d.ts +5 -0
- package/dist/turn.style.js +56 -0
- package/dist/types.d.ts +221 -20
- package/dist/units.d.ts +1 -1
- package/dist/units.js +22 -1
- package/dist/uprights.board.d.ts +17 -0
- package/dist/uprights.board.js +59 -0
- package/dist/uprights.budo.d.ts +17 -0
- package/dist/uprights.budo.js +87 -0
- package/dist/uprights.d.ts +37 -0
- package/dist/uprights.fields.d.ts +32 -0
- package/dist/uprights.fields.js +172 -0
- package/dist/uprights.goal.d.ts +49 -0
- package/dist/uprights.goal.js +69 -0
- package/dist/uprights.js +169 -0
- package/dist/uprights.more.d.ts +7 -0
- package/dist/uprights.more.js +183 -0
- package/dist/uprights.net.d.ts +12 -0
- package/dist/uprights.net.js +109 -0
- package/dist/uprights.netkit.d.ts +28 -0
- package/dist/uprights.netkit.js +67 -0
- package/dist/uprights.pools.d.ts +8 -0
- package/dist/uprights.pools.js +190 -0
- package/dist/uprights.rinks.d.ts +27 -0
- package/dist/uprights.rinks.js +106 -0
- package/dist/uprights.track.d.ts +50 -0
- package/dist/uprights.track.js +246 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/zones-entry.d.ts +2 -0
- package/dist/zones-entry.js +2 -0
- package/package.json +56 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { el, num } from "../format.js";
|
|
2
|
+
import { feet } from "../pool.js";
|
|
3
|
+
import { box, deckMarkup, leastWidth, paintDefs, poolIds, waterMarkup } from "../pool.kit.js";
|
|
4
|
+
import { DIVING, DIVING_LINES } from "../pool.figures.js";
|
|
5
|
+
import { textWidth } from "../text.js";
|
|
6
|
+
import { GUTTER } from "./pool.js";
|
|
7
|
+
import { edges, ft, quarterTurn, textOn } from "./surface.js";
|
|
8
|
+
/** The name a board goes by in the words of the landmarks. */
|
|
9
|
+
const markId = (b) => (b.kind === "springboard" ? `springboard-${b.height}m` : `platform-${String(b.height).replace(".", "-")}m`);
|
|
10
|
+
/**
|
|
11
|
+
* A diving well seen from above, from World Aquatics' rules (Part Four, Article 15 and Appendix 2): the pool wall the boards stand at on the left, the diving direction towards the right. Every springboard is 4.88 m
|
|
12
|
+
* long and 0.50 m wide with its front edge, the plummet, 2.22 m beyond the wall; each platform has the length and width of the table, its front edge 0.75 to 1.50 m beyond the wall (15.4.9); the boards stand the preferred
|
|
13
|
+
* distance (Appendix 2, B and C) from the side wall and from each other. The three lines across the well (15.6.3.1) are 21 m long, 2.5 m apart, the first under the plummet of the 3 m springboard.
|
|
14
|
+
*/
|
|
15
|
+
export function diving(o, plan, ctx = {}) {
|
|
16
|
+
const L = plan.length;
|
|
17
|
+
const W = plan.width;
|
|
18
|
+
const ids = ctx.ids ?? poolIds(o.id);
|
|
19
|
+
const full = o.detail === "full";
|
|
20
|
+
const m = ctx.bare === true ? 0 : (o.margin ?? feet(2.5));
|
|
21
|
+
// The stands, and the names of the springboards on the deck behind them, stand in the room behind the wall.
|
|
22
|
+
const behind = plan.behind + 4;
|
|
23
|
+
let base = box(o, "gutter", "ky-boards", -GUTTER, -GUTTER, L + GUTTER, W + GUTTER);
|
|
24
|
+
base += waterMarkup(o, ids, plan.look, 0, 0, L, W);
|
|
25
|
+
// The three lines across the well, under the plummet of the 3 m springboard and 2.5 m apart.
|
|
26
|
+
const three = plan.boards.find((b) => b.kind === "springboard" && b.height === 3);
|
|
27
|
+
const first = three?.x ?? DIVING.A.springboard3[1];
|
|
28
|
+
const lw = leastWidth(o, DIVING.lines.width, 0.32);
|
|
29
|
+
let lines = "";
|
|
30
|
+
let floor = "";
|
|
31
|
+
const y0 = (W - DIVING.lines.length) / 2;
|
|
32
|
+
for (let k = 0; k < DIVING_LINES; k += 1)
|
|
33
|
+
floor += `M${num(feet(first + k * DIVING.lines.apart))} ${num(feet(y0))}V${num(feet(y0 + DIVING.lines.length))}`;
|
|
34
|
+
lines += el("path", { class: ft(o, "lane-lines", "ky-line"), d: floor, "stroke-width": lw, fill: "none" });
|
|
35
|
+
// The stands behind the wall: one block under the platforms, a pedestal under each springboard.
|
|
36
|
+
const platforms = plan.boards.filter((b) => b.kind === "platform");
|
|
37
|
+
let stands = "";
|
|
38
|
+
if (platforms.length > 0) {
|
|
39
|
+
const ya = Math.min(...platforms.map((b) => b.y - b.width / 2)) - 0.5;
|
|
40
|
+
const yb = Math.max(...platforms.map((b) => b.y + b.width / 2)) + 0.5;
|
|
41
|
+
const xa = -Math.max(...platforms.map((b) => b.length - b.x)) - 0.4;
|
|
42
|
+
stands += el("rect", { class: ft(o, "stands", "ky-pl-sd"), x: feet(xa), y: feet(ya), width: feet(-xa), height: feet(yb - ya), rx: feet(0.2) });
|
|
43
|
+
}
|
|
44
|
+
const springboards = plan.boards.filter((one) => one.kind === "springboard");
|
|
45
|
+
const springStand = springboards.length === 0 ? 0 : Math.min(...springboards.map((b) => b.x - b.length)) - 0.4;
|
|
46
|
+
if (springboards.length > 0) {
|
|
47
|
+
const ya = Math.min(...springboards.map((b) => b.y)) - 1.1;
|
|
48
|
+
const yb = Math.max(...springboards.map((b) => b.y)) + 1.1;
|
|
49
|
+
stands += el("rect", { class: ft(o, "stands", "ky-pl-sd"), x: feet(springStand), y: feet(ya), width: feet(-springStand), height: feet(yb - ya), rx: feet(0.2) });
|
|
50
|
+
}
|
|
51
|
+
base += stands;
|
|
52
|
+
// The boards: a platform is a rectangle with its front edge over the water; a springboard is a bar reaching out from its stand. Tall ones over the low.
|
|
53
|
+
let boards = "";
|
|
54
|
+
let labels = "";
|
|
55
|
+
const size = feet(0.95);
|
|
56
|
+
const ordered = [...plan.boards].sort((a, b) => (a.kind === b.kind ? a.height - b.height : a.kind === "platform" ? -1 : 1));
|
|
57
|
+
for (const b of ordered) {
|
|
58
|
+
const x0 = b.x - b.length;
|
|
59
|
+
if (b.kind === "platform") {
|
|
60
|
+
boards += el("rect", { class: ft(o, "platforms", "ky-pl-pf"), x: feet(x0), y: feet(b.y - b.width / 2), width: feet(b.length), height: feet(b.width), rx: feet(0.1) });
|
|
61
|
+
if (full)
|
|
62
|
+
boards += el("path", { class: "ky-line ky-pl-fe", d: `M${num(feet(b.x))} ${num(feet(b.y - b.width / 2))}V${num(feet(b.y + b.width / 2))}`, "stroke-width": feet(0.12), fill: "none" });
|
|
63
|
+
// Turned back upright on a tall drawing, the word lies across the platform's width: it is made to fit.
|
|
64
|
+
const text = `${String(b.height)} m`;
|
|
65
|
+
const fit = o.portrait ? Math.min(size, (feet(b.width) * 0.9) / textWidth(text)) : size;
|
|
66
|
+
labels += textOn(o.portrait, feet(b.x - Math.min(2.2, b.length * 0.4)), feet(b.y) + fit * 0.36, text, { size: fit, anchor: "middle", cls: "ky-pl-bt", weight: 800 });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
boards += el("rect", { class: ft(o, "springboards", "ky-pl-spb"), x: feet(x0), y: feet(b.y - b.width / 2), width: feet(b.length), height: feet(b.width), rx: feet(0.12) });
|
|
70
|
+
// The name stands on the deck behind the springboards' stand, level with the board; turned upright on a tall drawing it is made to fit between two boards.
|
|
71
|
+
const word = `${b.height} m`;
|
|
72
|
+
const fit = o.portrait ? Math.min(size * 0.9, (feet(DIVING.C.springboard1[0]) * 0.92) / textWidth(word)) : size * 0.9;
|
|
73
|
+
labels += textOn(o.portrait, feet(springStand - 0.4), feet(b.y) + fit * 0.36, word, { size: fit, anchor: o.portrait ? "middle" : "end", cls: "ky-pl-bu", weight: 800 });
|
|
74
|
+
}
|
|
75
|
+
// The plummet: the vertical line through the middle of the front edge.
|
|
76
|
+
if (full)
|
|
77
|
+
boards += el("circle", { class: "ky-pl-pm", cx: feet(b.x), cy: feet(b.y), r: feet(0.14) });
|
|
78
|
+
}
|
|
79
|
+
lines += boards + labels;
|
|
80
|
+
const marks = [];
|
|
81
|
+
if (o.landmarks === true) {
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
for (const b of plan.boards) {
|
|
84
|
+
const id = markId(b);
|
|
85
|
+
if (seen.has(id))
|
|
86
|
+
continue;
|
|
87
|
+
seen.add(id);
|
|
88
|
+
marks.push({ id, x: feet(b.x), y: feet(b.y - (b.kind === "platform" ? b.width / 2 : b.width)), side: "top" });
|
|
89
|
+
}
|
|
90
|
+
marks.push({ id: "diving-line", x: feet(first + DIVING.lines.apart), y: feet(y0 + DIVING.lines.length), side: "bottom" });
|
|
91
|
+
}
|
|
92
|
+
const view0 = { x: -feet(behind) - m, y: -m - feet(GUTTER), w: feet(L + behind) + 2 * m, h: feet(W) + 2 * m + 2 * feet(GUTTER) };
|
|
93
|
+
if (ctx.bare !== true)
|
|
94
|
+
base = deckMarkup(o, ids, plan.deck, view0.x, view0.y, view0.w, view0.h) + base;
|
|
95
|
+
const Lf = feet(L);
|
|
96
|
+
const Wf = feet(W);
|
|
97
|
+
const cy = Wf / 2;
|
|
98
|
+
const turned = o.portrait;
|
|
99
|
+
const surface = {
|
|
100
|
+
sport: "diving",
|
|
101
|
+
view: view0,
|
|
102
|
+
base,
|
|
103
|
+
lines,
|
|
104
|
+
defs: ctx.bare === true ? "" : paintDefs(ids, plan.look, plan.deck, plan.seed),
|
|
105
|
+
left: { cx: -feet(behind) - m / 2, cy, w: Wf, h: m, rot: -90 },
|
|
106
|
+
right: { cx: Lf + m / 2, cy, w: Wf, h: m, rot: 90 },
|
|
107
|
+
plate: turned ? { cx: Lf * 0.62, cy, w: Wf * 0.9, h: Lf * 0.3 } : { cx: Lf * 0.62, cy, w: Lf * 0.34, h: Wf * 0.5 },
|
|
108
|
+
turned,
|
|
109
|
+
};
|
|
110
|
+
surface.box = { x: 0, y: 0, w: Lf, h: Wf };
|
|
111
|
+
surface.lineRef = { width: lw, feet: 1 };
|
|
112
|
+
// Where the springboards stand and where the platforms: split between the last springboard and the first platform.
|
|
113
|
+
const sb = plan.boards.filter((b) => b.kind === "springboard");
|
|
114
|
+
const pf = plan.boards.filter((b) => b.kind === "platform");
|
|
115
|
+
const split = sb.length > 0 && pf.length > 0 ? (Math.max(...sb.map((b) => b.y)) + Math.min(...pf.map((b) => b.y - b.width / 2))) / 2 : W / 2;
|
|
116
|
+
surface.ranges = {
|
|
117
|
+
springboards: edges(0, 0, Lf * 0.55, feet(split)),
|
|
118
|
+
platforms: edges(0, feet(split), Lf * 0.55, Wf),
|
|
119
|
+
};
|
|
120
|
+
if (o.landmarks === true)
|
|
121
|
+
surface.marks = marks;
|
|
122
|
+
if (turned) {
|
|
123
|
+
const t = quarterTurn(view0);
|
|
124
|
+
surface.view = t.view;
|
|
125
|
+
surface.turn = t.turn;
|
|
126
|
+
}
|
|
127
|
+
return surface;
|
|
128
|
+
}
|
package/dist/surfaces/field.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import type { FieldPlan } from "../fields.types.ts";
|
|
1
|
+
import type { Area, FieldPlan, Shape } from "../fields.types.ts";
|
|
2
2
|
import type { GoalStyle } from "../types.ts";
|
|
3
3
|
import { type BuildOptions, type Surface } from "./surface.ts";
|
|
4
|
+
/** The path of one shape that is drawn as a line, or of one filled bar. */
|
|
5
|
+
export declare function pathOf(shape: Shape): string;
|
|
6
|
+
export declare const areaD: (a: Area) => string;
|
|
4
7
|
/** The painted lines of a plan: the shapes drawn with the line's paint, those alike in feature, width and dash put in one path. */
|
|
5
|
-
export declare function strokes(plan: FieldPlan, o: Pick<BuildOptions, "exact" | "features">): string;
|
|
8
|
+
export declare function strokes(plan: Pick<FieldPlan, "shapes" | "lineWidth" | "drawnLine">, o: Pick<BuildOptions, "exact" | "features">): string;
|
|
9
|
+
/** The filled marks of a plan: the bars in one path to a feature, the dots one each. */
|
|
10
|
+
export declare function marks(plan: Pick<FieldPlan, "shapes">, o: Pick<BuildOptions, "exact" | "features">): string;
|
|
6
11
|
/**
|
|
7
12
|
* A field sport's surface lying wide, from the sport's plan: the ground, the mown turf, the painted areas, the lines, the goals, and, on a score, the
|
|
8
13
|
* ends painted in the teams' colours and the place for the board. The markings are the plan's, which are the rulebook's (leagues/*.ts).
|
package/dist/surfaces/field.js
CHANGED
|
@@ -4,7 +4,7 @@ import { mowTurf, oddCells } from "../mow.js";
|
|
|
4
4
|
import { ft, quarterTurn } from "./surface.js";
|
|
5
5
|
const RAD = Math.PI / 180;
|
|
6
6
|
/** The path of one shape that is drawn as a line, or of one filled bar. */
|
|
7
|
-
function pathOf(shape) {
|
|
7
|
+
export function pathOf(shape) {
|
|
8
8
|
switch (shape.kind) {
|
|
9
9
|
case "line":
|
|
10
10
|
return shape.y0 === shape.y1 ? `M${num(shape.x0)} ${num(shape.y0)}H${num(shape.x1)}` : shape.x0 === shape.x1 ? `M${num(shape.x0)} ${num(shape.y0)}V${num(shape.y1)}` : `M${num(shape.x0)} ${num(shape.y0)}L${num(shape.x1)} ${num(shape.y1)}`;
|
|
@@ -27,7 +27,7 @@ function pathOf(shape) {
|
|
|
27
27
|
return "";
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
const areaD = (a) => {
|
|
30
|
+
export const areaD = (a) => {
|
|
31
31
|
if (a.d !== undefined)
|
|
32
32
|
return a.d;
|
|
33
33
|
if (a.frame !== undefined) {
|
|
@@ -61,19 +61,21 @@ export function strokes(plan, o) {
|
|
|
61
61
|
return out;
|
|
62
62
|
}
|
|
63
63
|
/** The filled marks of a plan: the bars in one path to a feature, the dots one each. */
|
|
64
|
-
function marks(plan, o) {
|
|
64
|
+
export function marks(plan, o) {
|
|
65
65
|
const bars = new Map();
|
|
66
66
|
let dots = "";
|
|
67
67
|
const lift = o.exact ? 1 : 1.6;
|
|
68
68
|
for (const shape of plan.shapes) {
|
|
69
69
|
if (shape.kind === "bar")
|
|
70
|
-
bars.set(shape.feature
|
|
70
|
+
bars.set(`${shape.feature}|${shape.cls ?? ""}`, [...(bars.get(`${shape.feature}|${shape.cls ?? ""}`) ?? []), pathOf(shape)]);
|
|
71
71
|
else if (shape.kind === "dot")
|
|
72
|
-
dots += el("circle", { class: ft(o, shape.feature, shape.paint === "post" ? "ky-post-end" : "ky-fill-line"), cx: shape.cx, cy: shape.cy, r: shape.r * lift });
|
|
72
|
+
dots += el("circle", { class: ft(o, shape.feature, shape.paint === "post" ? "ky-post-end" : shape.paint === "block" ? "ky-ska-block" : shape.paint === "cone" ? "ky-ska-cone" : "ky-fill-line"), cx: shape.cx, cy: shape.cy, r: shape.r * lift });
|
|
73
73
|
}
|
|
74
74
|
let out = "";
|
|
75
|
-
for (const [
|
|
76
|
-
|
|
75
|
+
for (const [key, d] of bars) {
|
|
76
|
+
const [feature, cls] = key.split("|");
|
|
77
|
+
out += el("path", { class: ft(o, feature, cls === "" ? "ky-fill-line" : cls), d: d.join("") });
|
|
78
|
+
}
|
|
77
79
|
return out + dots;
|
|
78
80
|
}
|
|
79
81
|
/** One goal as the options ask for it: the net behind the goal line as a box, a line across the mouth, a solid strip, or nothing. */
|
|
@@ -118,8 +120,8 @@ export function fieldSurface(o, plan, style = {}) {
|
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
for (const area of plan.areas)
|
|
121
|
-
base += el("path", { class: ft(o, area.feature, area.cls), d: areaD(area), "fill-rule": area.frame === undefined ? undefined : "evenodd" });
|
|
122
|
-
const ends = o.score && plan.ends !== undefined ? plan.ends : undefined;
|
|
123
|
+
base += el("path", { class: ft(o, area.feature, area.cls), d: areaD(area), "fill-rule": area.frame === undefined && area.evenodd !== true ? undefined : "evenodd" });
|
|
124
|
+
const ends = o.score && o.pageant !== true && plan.ends !== undefined ? plan.ends : undefined;
|
|
123
125
|
if (ends !== undefined) {
|
|
124
126
|
for (const side of ["left", "right"]) {
|
|
125
127
|
const b = ends[side];
|
|
@@ -152,6 +154,10 @@ export function fieldSurface(o, plan, style = {}) {
|
|
|
152
154
|
surface.box = { x: 0, y: 0, w: L, h: W };
|
|
153
155
|
surface.lineRef = { width: thick, feet: 1 };
|
|
154
156
|
surface.ranges = plan.ranges;
|
|
157
|
+
// A pageant's pictures keep clear of a cricket pitch, which runs through the middle.
|
|
158
|
+
const pitch = plan.sport === "cricket" ? plan.ranges?.pitch : undefined;
|
|
159
|
+
if (pitch !== undefined && !("left" in pitch))
|
|
160
|
+
surface.pageant = { clear: pitch.w / 2 };
|
|
155
161
|
if (o.landmarks === true)
|
|
156
162
|
surface.marks = full ? [...plan.marks] : plan.marks.filter((mark) => !mark.id.startsWith("~"));
|
|
157
163
|
if (o.portrait) {
|
|
@@ -93,6 +93,8 @@ export function football(spec, o, marks = { hashMarks: true, postShape: "slingsh
|
|
|
93
93
|
if (numbered && spec.id === "cfl" && (yardsLong / 2) % 10 !== 0)
|
|
94
94
|
positions.push({ x: e + (yardsLong / 2) * 3, label: spec.centre, pos: yardsLong / 2 });
|
|
95
95
|
let numbers = "";
|
|
96
|
+
const arrows = [];
|
|
97
|
+
const numerals = [];
|
|
96
98
|
for (const side of ["near", "far"]) {
|
|
97
99
|
const y = side === "near" ? W - centreY : centreY;
|
|
98
100
|
for (const p of positions) {
|
|
@@ -100,6 +102,9 @@ export function football(spec, o, marks = { hashMarks: true, postShape: "slingsh
|
|
|
100
102
|
const centre = p.label === spec.centre || p.pos === yardsLong / 2;
|
|
101
103
|
const digits = [...p.label];
|
|
102
104
|
const flip = side === "far";
|
|
105
|
+
// The numeral's box in the wide frame: the digits stand along the field, or across it when the field is turned.
|
|
106
|
+
const spread = digits.length === 1 ? 3 : 5.9;
|
|
107
|
+
numerals.push([p.x, y, turned ? DIGIT_HEIGHT / 2 : spread, turned ? spread : DIGIT_HEIGHT / 2]);
|
|
103
108
|
if (digits.length === 1)
|
|
104
109
|
numbers += textOn(turned, p.x, y + DIGIT_HEIGHT / 2, p.label, { size, anchor: "middle", cls: numCls, flip, weight: 700 });
|
|
105
110
|
else {
|
|
@@ -118,6 +123,7 @@ export function football(spec, o, marks = { hashMarks: true, postShape: "slingsh
|
|
|
118
123
|
if (full && !centre && Number(p.label) < 50) {
|
|
119
124
|
const ax = nearGoalLeft ? p.x - 8.4 : p.x + 8.4;
|
|
120
125
|
const dir = nearGoalLeft ? -1 : 1;
|
|
126
|
+
arrows.push([ax, y, 1.5, 1.6]);
|
|
121
127
|
numbers += el("path", { class: ft(o, "numbers", "ky-fill-line"), d: `M${num(ax + dir * 1.5)} ${num(y)}L${num(ax - dir * 1.5)} ${num(y - 1.6)}V${num(y + 1.6)}Z` });
|
|
122
128
|
}
|
|
123
129
|
}
|
|
@@ -169,6 +175,7 @@ export function football(spec, o, marks = { hashMarks: true, postShape: "slingsh
|
|
|
169
175
|
};
|
|
170
176
|
surface.lineRef = { width: lw, feet: 1 };
|
|
171
177
|
surface.box = { x: 0, y: 0, w: L, h: W };
|
|
178
|
+
surface.anchors = { kind: "football", length: spec.length, endZone: e, width: W, arrows, numerals };
|
|
172
179
|
// The red zone is the 20 yards before a goal line and the end zone behind it; the half is from an end line to midfield.
|
|
173
180
|
const twenty = 60;
|
|
174
181
|
const half = atEnds((end) => (end === "left" ? edges(0, 0, L / 2, W) : edges(L / 2, 0, L, W)));
|
package/dist/surfaces/hockey.js
CHANGED
|
@@ -15,8 +15,8 @@ export function boardsY(x, radius = NHL.cornerRadius) {
|
|
|
15
15
|
* season (today's by default) marked it; with a `rink` (leagues.ts), that league's, in feet.
|
|
16
16
|
*/
|
|
17
17
|
export function hockey(o, era, rink = NHL_RINK) {
|
|
18
|
-
// The NHL's rink has a history of its own (eras.ts); a league's, if it has one, is already in its `rink`.
|
|
19
|
-
const nhl = rink === NHL_RINK ? (era ?? rulesFor("nhl").rules) : undefined;
|
|
18
|
+
// The NHL's rink has a history of its own (eras.ts), and so has an arena's rink of another size (an `era` given with it); a league's, if it has one, is already in its `rink`.
|
|
19
|
+
const nhl = rink === NHL_RINK || era !== undefined ? (era ?? rulesFor("nhl").rules) : undefined;
|
|
20
20
|
const { length: L, width: W, cornerRadius: r } = rink;
|
|
21
21
|
const g = nhl?.goalLine ?? rink.goalLine;
|
|
22
22
|
const blueLine = nhl?.blueLine ?? rink.blueLine;
|
|
@@ -128,6 +128,8 @@ export function hockey(o, era, rink = NHL_RINK) {
|
|
|
128
128
|
};
|
|
129
129
|
surface.lineRef = { width: thin, feet: 1 };
|
|
130
130
|
surface.box = { x: 0, y: 0, w: L, h: W };
|
|
131
|
+
surface.centreRadius = rink.circleRadius;
|
|
132
|
+
surface.anchors = { kind: "hockey", length: L, width: W, blueLine, goalLine: g, cornerRadius: r, net: net_ };
|
|
131
133
|
// The zones of the ice: from the end boards to a blue line, and between the blue lines.
|
|
132
134
|
const zone = atEnds((end) => (end === "left" ? edges(0, 0, blueLine, W) : edges(L - blueLine, 0, L, W)));
|
|
133
135
|
surface.ranges = {
|
package/dist/surfaces/net.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type CourtPlan } from "../court.ts";
|
|
|
2
2
|
import { type BuildOptions, type Surface } from "./surface.ts";
|
|
3
3
|
/**
|
|
4
4
|
* A net sport's court lying wide: the ground, the free zone, the court, its painted areas, its lines, the net with its posts (and, in volleyball, its antennae)
|
|
5
|
-
* and, on a score, the place for the board. Every length that is a rulebook's figure comes from the league (leagues/courts.ts) through `courtGeometry`.
|
|
5
|
+
* and, on a score, the place for the board. Every length that is a rulebook's figure comes from the league (leagues/courts.ts) through `courtGeometry`. The courts of
|
|
6
|
+
* the sports added after the first five may also have walls, rings (circles and arcs), a table or a set, and no net.
|
|
6
7
|
*/
|
|
7
8
|
export declare function netCourt(o: BuildOptions, plan: CourtPlan): Surface;
|
package/dist/surfaces/net.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { courtGeometry, courtSize, sideReach } from "../court.js";
|
|
1
|
+
import { bandReach, courtGeometry, courtSize, sideReach } from "../court.js";
|
|
2
2
|
import { el, num } from "../format.js";
|
|
3
3
|
import { atEnds, edges, ft, quarterTurn } from "./surface.js";
|
|
4
4
|
/** A rectangle as a closed sub-path. */
|
|
@@ -8,9 +8,35 @@ function mark(f, cls) {
|
|
|
8
8
|
const half = f.size / 2;
|
|
9
9
|
return f.shape === "round" ? el("circle", { class: cls, cx: f.x, cy: f.y, r: half }) : el("rect", { class: cls, x: f.x - half, y: f.y - half, width: f.size, height: f.size });
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* A ring or an arc as a stroked line: a circle element for a whole circle, else a path from `a0` to `a1` in pieces of at most a quarter turn (an arc of exactly half a circle,
|
|
13
|
+
* drawn in one piece with rounded numbers, can lose its centre). The line's outer edge is at the radius, so its middle is half a width inside it.
|
|
14
|
+
*/
|
|
15
|
+
function ringMarkup(o, ring) {
|
|
16
|
+
const { cx, cy, w } = ring;
|
|
17
|
+
const r = Math.max(0.001, ring.r - w / 2);
|
|
18
|
+
const cls = ft(o, "lines", "ky-line");
|
|
19
|
+
if (ring.a0 === undefined || ring.a1 === undefined)
|
|
20
|
+
return el("circle", { class: cls, cx, cy, r, "stroke-width": w });
|
|
21
|
+
const turns = Math.max(1, Math.ceil((ring.a1 - ring.a0) / (Math.PI / 2) - 1e-9));
|
|
22
|
+
const at = (a) => `${num(cx + r * Math.cos(a))} ${num(cy + r * Math.sin(a))}`;
|
|
23
|
+
let d = `M${at(ring.a0)}`;
|
|
24
|
+
for (let i = 1; i <= turns; i += 1)
|
|
25
|
+
d += `A${num(r)} ${num(r)} 0 0 1 ${at(ring.a0 + ((ring.a1 - ring.a0) * i) / turns)}`;
|
|
26
|
+
return el("path", { class: cls, d, "stroke-width": w });
|
|
27
|
+
}
|
|
28
|
+
/** What each kind of band is drawn with: the class and the feature it belongs to. */
|
|
29
|
+
const BAND = { wall: ["walls", "ky-wall"], mesh: ["fence", "ky-mesh"], face: ["wall-face", "ky-face"], tin: ["tin", "ky-tin"] };
|
|
30
|
+
/** A solid on the court: a table is a rectangle, a roundnet set a rim round a net. */
|
|
31
|
+
function solid(o, s) {
|
|
32
|
+
if (s.kind === "table")
|
|
33
|
+
return el("path", { class: ft(o, "table", "ky-table"), d: box(s.rect) });
|
|
34
|
+
return el("circle", { class: ft(o, "net", "ky-nt-post"), cx: s.cx, cy: s.cy, r: s.r }) + el("circle", { class: ft(o, "net", "ky-set-net"), cx: s.cx, cy: s.cy, r: s.r * 0.84 });
|
|
35
|
+
}
|
|
11
36
|
/**
|
|
12
37
|
* A net sport's court lying wide: the ground, the free zone, the court, its painted areas, its lines, the net with its posts (and, in volleyball, its antennae)
|
|
13
|
-
* and, on a score, the place for the board. Every length that is a rulebook's figure comes from the league (leagues/courts.ts) through `courtGeometry`.
|
|
38
|
+
* and, on a score, the place for the board. Every length that is a rulebook's figure comes from the league (leagues/courts.ts) through `courtGeometry`. The courts of
|
|
39
|
+
* the sports added after the first five may also have walls, rings (circles and arcs), a table or a set, and no net.
|
|
14
40
|
*/
|
|
15
41
|
export function netCourt(o, plan) {
|
|
16
42
|
const geometry = courtGeometry(plan);
|
|
@@ -23,7 +49,10 @@ export function netCourt(o, plan) {
|
|
|
23
49
|
const side = Math.max(zone?.side ?? 0, sideReach(geometry));
|
|
24
50
|
const end = zone?.end ?? 0;
|
|
25
51
|
const m = o.margin ?? L * 0.035;
|
|
26
|
-
|
|
52
|
+
// Walls and the like stand beyond the court's edges, and may make the ground wider on one side than on the other.
|
|
53
|
+
const beyond = bandReach(geometry);
|
|
54
|
+
const [left, right, top, bottom] = [Math.max(end, beyond.left), Math.max(end, beyond.right), Math.max(side, beyond.top), Math.max(side, beyond.bottom)];
|
|
55
|
+
const view0 = { x: -left - m, y: -top - m, w: L + left + right + 2 * m, h: W + top + bottom + 2 * m };
|
|
27
56
|
// Lines are drawn a little thicker than painted, as the other surfaces' are, unless asked for the true widths: the thin dimension of a line is raised to a least.
|
|
28
57
|
const least = o.exact ? 0 : L * 0.0026;
|
|
29
58
|
const thick = (r) => {
|
|
@@ -39,12 +68,31 @@ export function netCourt(o, plan) {
|
|
|
39
68
|
base += el("rect", { class: ft(o, "court", "ky-surface"), x: 0, y: 0, width: L, height: W });
|
|
40
69
|
if (geometry.areas.length > 0)
|
|
41
70
|
base += el("path", { class: ft(o, "areas", "ky-area"), d: geometry.areas.map(box).join("") });
|
|
71
|
+
for (const band of geometry.bands) {
|
|
72
|
+
const [feature, cls] = BAND[band.kind];
|
|
73
|
+
base += el("path", { class: ft(o, feature, cls), d: box(band.rect) });
|
|
74
|
+
}
|
|
42
75
|
const lineRects = [...geometry.lines, ...(full ? geometry.small : [])].map(thick);
|
|
43
76
|
let lines = el("path", { class: ft(o, "lines", "ky-fill-line"), d: lineRects.map(box).join("") });
|
|
44
|
-
//
|
|
45
|
-
|
|
77
|
+
// Circles and arcs are lines too, drawn at least as thick as the others.
|
|
78
|
+
for (const ring of geometry.rings)
|
|
79
|
+
lines += ringMarkup(o, { ...ring, w: Math.max(ring.w, least) });
|
|
80
|
+
if (geometry.wallLines.length > 0)
|
|
81
|
+
lines += el("path", { class: ft(o, "wall-lines", "ky-wall-line"), d: geometry.wallLines.map(thick).map(box).join("") });
|
|
82
|
+
for (const s of geometry.solids)
|
|
83
|
+
lines += solid(o, s);
|
|
84
|
+
// The net: a line across the court at its middle, from post to post; its posts and, in volleyball, the antennae at the side lines. A court without a net has none.
|
|
46
85
|
const net = geometry.net;
|
|
47
|
-
|
|
86
|
+
// Over a centre line (volleyball's, sepak takraw's) the net is drawn a little wider than the line, so that the line shows between its edges.
|
|
87
|
+
const under = geometry.underNet;
|
|
88
|
+
const nw = under === null ? Math.max(L * 0.004, 0.02) : Math.max(under, least) * 2.4;
|
|
89
|
+
if (net !== null)
|
|
90
|
+
lines += el("rect", { class: ft(o, "net", "ky-nt-line"), x: net.x - nw / 2, y: net.y0, width: nw, height: net.y1 - net.y0 });
|
|
91
|
+
// The centre line runs under the net (volleyball Rule 1.3.3): the net is drawn over it, so the line is drawn again over the net, in a narrower stroke, to show through.
|
|
92
|
+
if (net !== null && under !== null) {
|
|
93
|
+
const core = Math.max(under, least);
|
|
94
|
+
lines += el("rect", { class: ft(o, "lines", "ky-fill-line"), x: net.x - core / 2, y: 0, width: core, height: W });
|
|
95
|
+
}
|
|
48
96
|
for (const post of geometry.posts)
|
|
49
97
|
lines += mark(post, ft(o, "posts", "ky-nt-post"));
|
|
50
98
|
if (full) {
|
|
@@ -54,22 +102,30 @@ export function netCourt(o, plan) {
|
|
|
54
102
|
lines += mark(antenna, ft(o, "antennae", "ky-red-fill"));
|
|
55
103
|
}
|
|
56
104
|
// The teams' names are not painted on these courts: the board names the teams. The board lies over the net, between the lines it needs.
|
|
57
|
-
|
|
58
|
-
const
|
|
105
|
+
// A roundnet court is square, with no sides: it lies the same wherever it is turned.
|
|
106
|
+
const turned = o.portrait && plan.sport !== "roundnet";
|
|
107
|
+
// The board lies over the net, between the lines it needs; on a roundnet court that is the set, so it lies on the ground below the circles.
|
|
108
|
+
const room = plan.sport === "roundnet" ? W / 2 - plan.figures.servingRadius : 0;
|
|
109
|
+
const clear = plan.sport === "roundnet" ? { cx, cy: cy + plan.figures.servingRadius + room / 2, w: L * 0.9, h: room * 0.9 } : undefined;
|
|
110
|
+
// Netball's board has no net to lie over: it lies in the centre third, and the teams' names are painted in the goal thirds.
|
|
111
|
+
const centred = plan.sport === "netball" ? (turned ? { cx, cy, w: W * 0.88, h: L * 0.36 } : { cx, cy, w: L * 0.4, h: W * 0.66 }) : undefined;
|
|
112
|
+
const spot = clear ?? centred ?? (turned ? { cx, cy, w: W * 0.88, h: L * 0.5 } : { cx, cy, w: L * 0.58, h: W * 0.66 });
|
|
113
|
+
const places = plan.sport === "netball" ? { left: { cx: L * 0.15, cy, w: L * 0.2, h: W * 0.4, rot: 0 }, right: { cx: L * 0.85, cy, w: L * 0.2, h: W * 0.4, rot: 0 } } : { left: { cx: L * 0.2, cy, w: L * 0.2, h: W * 0.4, rot: 0 }, right: { cx: L * 0.8, cy, w: L * 0.2, h: W * 0.4, rot: 0 } };
|
|
59
114
|
const surface = {
|
|
60
115
|
sport: plan.sport,
|
|
61
116
|
view: view0,
|
|
62
117
|
base,
|
|
63
118
|
lines,
|
|
64
119
|
defs: "",
|
|
65
|
-
left:
|
|
66
|
-
right:
|
|
120
|
+
left: places.left,
|
|
121
|
+
right: places.right,
|
|
67
122
|
plate: spot,
|
|
68
123
|
turned,
|
|
69
124
|
};
|
|
70
125
|
surface.box = { x: 0, y: 0, w: L, h: W };
|
|
71
126
|
// One side of the net.
|
|
72
|
-
|
|
127
|
+
const middle = net === null ? cx : net.x;
|
|
128
|
+
surface.ranges = { "half-court": atEnds((end) => (end === "left" ? edges(0, 0, middle, W) : edges(middle, 0, L, W))) };
|
|
73
129
|
surface.lineRef = { width: plan.sport === "tabletennis" ? plan.figures.edgeLine : plan.figures.lineWidth, feet: 1 };
|
|
74
130
|
if (o.landmarks === true)
|
|
75
131
|
surface.marks = netMarks(plan, L, W);
|
|
@@ -116,11 +172,12 @@ function netMarks(plan, L, W) {
|
|
|
116
172
|
case "badminton": {
|
|
117
173
|
const f = plan.figures;
|
|
118
174
|
return [
|
|
119
|
-
|
|
175
|
+
// The back boundary line is the singles long service line too (Diagram A); the line inside it is the doubles long service line.
|
|
176
|
+
{ id: "back-boundary-line", x: f.lineWidth / 2, y: W * 0.8, side: "bottom" },
|
|
120
177
|
{ id: "sideline", x: L * 0.12, y: 0, side: "top" },
|
|
121
178
|
{ id: "singles-sideline", x: L * 0.12, y: W - f.singlesInset, side: "bottom" },
|
|
122
|
-
{ id: "long-service-line", x: f.doublesLongServiceInset + f.lineWidth / 2, y: W * 0.2, side: "top" },
|
|
123
|
-
{ id: "short-service-line", x: cx - f.shortServiceLine - f.lineWidth / 2, y: W * 0.3, side: "
|
|
179
|
+
{ id: "doubles-long-service-line", x: f.doublesLongServiceInset + f.lineWidth / 2, y: W * 0.2, side: "top" },
|
|
180
|
+
{ id: "short-service-line", x: cx - f.shortServiceLine - f.lineWidth / 2, y: W * 0.3, side: "bottom" },
|
|
124
181
|
{ id: "centre-line", x: L * 0.2, y: cy, side: "bottom" },
|
|
125
182
|
net,
|
|
126
183
|
];
|
|
@@ -136,7 +193,7 @@ function netMarks(plan, L, W) {
|
|
|
136
193
|
net,
|
|
137
194
|
];
|
|
138
195
|
}
|
|
139
|
-
|
|
196
|
+
case "tabletennis": {
|
|
140
197
|
const f = plan.figures;
|
|
141
198
|
return [
|
|
142
199
|
{ id: "end-line", x: f.edgeLine / 2, y: W * 0.8, side: "bottom" },
|
|
@@ -147,5 +204,93 @@ function netMarks(plan, L, W) {
|
|
|
147
204
|
net,
|
|
148
205
|
];
|
|
149
206
|
}
|
|
207
|
+
case "padel": {
|
|
208
|
+
const f = plan.figures;
|
|
209
|
+
return [
|
|
210
|
+
{ id: "back-wall", x: 0, y: W * 0.8, side: "bottom" },
|
|
211
|
+
{ id: "side-wall", x: f.enclosure.sideWall / 2, y: 0, side: "top" },
|
|
212
|
+
{ id: "metal-fence", x: L * 0.3, y: W, side: "bottom" },
|
|
213
|
+
{ id: "service-line", x: cx - f.serviceLine + f.lineWidth / 2, y: W * 0.25, side: "top" },
|
|
214
|
+
{ id: "centre-service-line", x: cx - f.serviceLine / 2, y: cy, side: "bottom" },
|
|
215
|
+
net,
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
case "squash": {
|
|
219
|
+
const f = plan.figures;
|
|
220
|
+
const near = L - f.shortLine;
|
|
221
|
+
return [
|
|
222
|
+
{ id: "tin", x: -f.wall.tin / 2, y: W * 0.15, side: "top" },
|
|
223
|
+
{ id: "wall-service-line", x: -f.wall.serviceLine - f.lineWidth / 2, y: W * 0.45, side: "bottom" },
|
|
224
|
+
{ id: "front-wall-line", x: -f.wall.frontWallLine - f.lineWidth / 2, y: W * 0.15, side: "top" },
|
|
225
|
+
{ id: "short-line", x: near - f.lineWidth / 2, y: W * 0.3, side: "top" },
|
|
226
|
+
{ id: "squash-half-court-line", x: L - f.shortLine / 2, y: cy, side: "bottom" },
|
|
227
|
+
{ id: "service-box", x: near + f.serviceBox / 2, y: f.serviceBox / 2, side: "top" },
|
|
228
|
+
{ id: "back-wall", x: L, y: W * 0.7, side: "bottom" },
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
case "racquetball": {
|
|
232
|
+
const f = plan.figures;
|
|
233
|
+
const back = L - f.shortLine;
|
|
234
|
+
const front = back - f.serviceLine;
|
|
235
|
+
return [
|
|
236
|
+
{ id: "front-wall", x: 0, y: W * 0.3, side: "top" },
|
|
237
|
+
{ id: "service-line", x: front + f.lineWidth / 2, y: W * 0.7, side: "bottom" },
|
|
238
|
+
{ id: "service-zone", x: (front + back) / 2, y: cy, side: "top" },
|
|
239
|
+
{ id: "service-box", x: (front + back) / 2, y: W - f.serviceBox / 2, side: "bottom" },
|
|
240
|
+
{ id: "drive-serve-line", x: (front + back) / 2, y: f.driveServe - f.lineWidth / 2, side: "top" },
|
|
241
|
+
{ id: "short-line", x: back - f.lineWidth / 2, y: W * 0.15, side: "top" },
|
|
242
|
+
{ id: "safety-zone", x: back + f.receiving.behind / 2, y: cy, side: "bottom" },
|
|
243
|
+
{ id: "receiving-line", x: back + f.receiving.behind - f.lineWidth / 2, y: W * 0.8, side: "bottom" },
|
|
244
|
+
{ id: "back-wall", x: L, y: cy, side: "bottom" },
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
case "sepaktakraw": {
|
|
248
|
+
const f = plan.figures;
|
|
249
|
+
const k = Math.SQRT1_2 * f.quarterCircle;
|
|
250
|
+
return [
|
|
251
|
+
{ id: "back-line", x: f.lineWidth / 2, y: W * 0.8, side: "bottom" },
|
|
252
|
+
{ id: "sideline", x: L * 0.12, y: 0, side: "top" },
|
|
253
|
+
{ id: "centre-line", x: cx + f.centreLine, y: W * 0.8, side: "bottom" },
|
|
254
|
+
{ id: "quarter-circle", x: cx - k, y: k, side: "top" },
|
|
255
|
+
{ id: "service-circle", x: f.serviceCircle.fromBack, y: cy - f.serviceCircle.radius, side: "top" },
|
|
256
|
+
net,
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
case "teqball": {
|
|
260
|
+
const f = plan.figures;
|
|
261
|
+
return [
|
|
262
|
+
{ id: "court-surround", x: 0, y: W * 0.8, side: "bottom" },
|
|
263
|
+
{ id: "halfway-line", x: cx, y: W * 0.15, side: "top" },
|
|
264
|
+
{ id: "service-line", x: cx - f.serviceLine, y: W * 0.7, side: "bottom" },
|
|
265
|
+
{ id: "service-line", x: cx + f.serviceLine, y: W * 0.3, side: "top" },
|
|
266
|
+
{ id: "table", x: cx + f.table.length * 0.3, y: cy + f.table.width * 0.3, side: "bottom" },
|
|
267
|
+
{ id: "court-net", x: cx, y: cy - f.net.width / 2, side: "top" },
|
|
268
|
+
];
|
|
269
|
+
}
|
|
270
|
+
case "roundnet": {
|
|
271
|
+
const f = plan.figures;
|
|
272
|
+
const k = Math.SQRT1_2;
|
|
273
|
+
return [
|
|
274
|
+
{ id: "roundnet-set", x: cx - f.set.diameter * 0.25, y: cy + f.set.diameter * 0.1, side: "bottom" },
|
|
275
|
+
{ id: "no-hit-zone", x: cx + f.noHitRadius * k, y: cy - f.noHitRadius * k, side: "top" },
|
|
276
|
+
{ id: "service-circle", x: cx - f.servingRadius * k, y: cy - f.servingRadius * k, side: "top" },
|
|
277
|
+
{ id: "service-position", x: cx + f.servingRadius, y: cy, side: "bottom" },
|
|
278
|
+
{ id: "service-position", x: cx - f.servingRadius, y: cy, side: "bottom" },
|
|
279
|
+
{ id: "service-position", x: cx, y: cy - f.servingRadius, side: "top" },
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
default: {
|
|
283
|
+
const f = plan.figures;
|
|
284
|
+
const k = Math.SQRT1_2 * f.goalCircle;
|
|
285
|
+
return [
|
|
286
|
+
{ id: "goal-line", x: f.lineWidth / 2, y: W * 0.8, side: "bottom" },
|
|
287
|
+
{ id: "sideline", x: L * 0.12, y: 0, side: "top" },
|
|
288
|
+
{ id: "transverse-line", x: L / 3, y: 0, side: "top" },
|
|
289
|
+
{ id: "centre-circle", x: cx + f.centreCircle / 2, y: cy, side: "bottom" },
|
|
290
|
+
{ id: "goal-circle", x: k, y: cy - k, side: "top" },
|
|
291
|
+
{ id: "goalpost", x: f.post.poleDiameter / 2, y: cy, side: "bottom" },
|
|
292
|
+
{ id: "goal-ring", x: L - f.post.poleDiameter - f.post.ring.bar - f.post.ring.inside / 2, y: cy, side: "top" },
|
|
293
|
+
];
|
|
294
|
+
}
|
|
150
295
|
}
|
|
151
296
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PoloPlan } from "../pool.ts";
|
|
2
|
+
import { type PoolCtx } from "../pool.kit.ts";
|
|
3
|
+
import { type BuildOptions, type Surface } from "./surface.ts";
|
|
4
|
+
/** The space behind each goal line where the goal's net hangs, in metres (Part Six 21.6.5 and 21.7.2.1: the goal at least 0.3 m deep, the lane rope 0.3 m behind the goal line): the pool is the field of play, 25 m between the goal lines (Part Six 20.2.2.1), and this behind each of them. */
|
|
5
|
+
export declare const POLO_BEHIND: 0.3;
|
|
6
|
+
/**
|
|
7
|
+
* A water polo field of play lying wide, from World Aquatics' rules: 25 by 20 m between the goal lines; lane ropes along both sides whose floats are white at the goal line and the half distance line, red to
|
|
8
|
+
* the 2 m mark, yellow from 2 to 6 m and green from 6 m to the half distance line, with a red mark at 5 m (Part Six 21.7.1 and 21.7.2); the 2 m lines from the goal posts that make the goal areas
|
|
9
|
+
* (Part Six 20.4 and 21.7.2.1.2); the goals, 3 m between the posts (21.6.3.2); the re-entry area 2.0 by 1.08 m in each corner on the side away from the official table (20.7); the referees' platforms 1 m wide along both sides, coloured
|
|
10
|
+
* as the ropes are (21.9.3); the official table (21.10) and the area for flying substitutions on the side of the benches (20.6).
|
|
11
|
+
*/
|
|
12
|
+
export declare function waterPolo(o: BuildOptions, plan: PoloPlan, ctx?: PoolCtx): Surface;
|