@johnmorrisdotca/kyogijo-stadiums 0.35.0 → 0.36.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 +7 -0
- package/dist/draw.js +1 -1
- package/dist/mow.d.ts +4 -2
- package/dist/mow.js +46 -2
- package/dist/surfaces/soccer.js +4 -4
- package/dist/types.d.ts +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ All notable changes to this project are written here. The format follows
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.36.0] - 2026-10-20
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **A diamond mowing pattern** (`stripePattern: "diamonds"`, `菱形` in the demo): the crosshatch of a ballpark's outfield, as in a photograph of T-Mobile Park. On a ballpark it is squares of 30 feet with their sides along the foul lines, from home plate out, lighter and darker alternately (two passes of 45-degree stripes crossing); on a football field and a soccer pitch it is squares of a band turned 45 degrees, one of them centred on the turf so that both ends are mown alike, whatever the size. It is cut to the fair ground or to the turf by a clip path. The infield grass stays one tone, and a separate infield pattern is not offered: the pattern is the outfield's. [Theming](./docs/theming.md), the gallery's mowing sections.
|
|
15
|
+
- **The demo's Mowing choice is for every grass sport**: a football field and a ballpark have it too (it was the soccer pitch's alone), with Diamonds among the choices; the soccer section of the home page shows the diamonds as one more card.
|
|
16
|
+
|
|
10
17
|
## [0.35.0] - 2026-10-20
|
|
11
18
|
|
|
12
19
|
### Added
|
package/dist/draw.js
CHANGED
|
@@ -222,7 +222,7 @@ const safeLength = (value) => {
|
|
|
222
222
|
return Number.isFinite(value) && value > 0 ? num(value) : undefined;
|
|
223
223
|
return typeof value === "string" && /^\d+(?:\.\d+)?(?:px|%|em|rem|vw|vh)?$/.test(value.trim()) ? value.trim() : undefined;
|
|
224
224
|
};
|
|
225
|
-
const PATTERNS = ["bands", "wide", "narrow", "lengthwise", "checks", "diagonal", "circles", "rings", "fan", "none"];
|
|
225
|
+
const PATTERNS = ["bands", "wide", "narrow", "lengthwise", "checks", "diagonal", "diamonds", "circles", "rings", "fan", "none"];
|
|
226
226
|
const GOALS = ["box", "line", "strip", "none"];
|
|
227
227
|
/** The pitch the options ask for: a `pitch` of the caller's, else the size a `ground` publishes, else none (the international pitch). */
|
|
228
228
|
export function pitchOf(o) {
|
package/dist/mow.d.ts
CHANGED
|
@@ -18,7 +18,8 @@ export declare const oddCells: (length: number, cell: number) => number;
|
|
|
18
18
|
/**
|
|
19
19
|
* The lighter tone of a pattern on a rectangle of turf. `band` is the width of the usual stripe, along x; `wide` and `narrow` are twice and half of it.
|
|
20
20
|
* `bands` run across the turf (side by side along x), `lengthwise` along it, `checks` are squares of about `band`, `diagonal` are 45-degree stripes
|
|
21
|
-
* `band` wide across,
|
|
21
|
+
* `band` wide across, `diamonds` are the squares of `checks` turned 45 degrees (the crosshatch of a ballpark's outfield: two passes of 45-degree stripes, `band` wide
|
|
22
|
+
* across, crossing), laid so that a diamond is centred on the turf and both ends are mown alike, and `circles` are rings `band` wide about the middle. A pattern that is not one of these (`none`, `rings`, `fan`) has no tone here.
|
|
22
23
|
*/
|
|
23
24
|
export declare function mowTurf(pattern: StripePattern, turf: Turf, band: number): Mown;
|
|
24
25
|
/** A ballpark's fair ground, as the field of its stripes: how far it reaches either side of the line to centre field and how far out. */
|
|
@@ -30,7 +31,8 @@ export interface Park {
|
|
|
30
31
|
/**
|
|
31
32
|
* The lighter tone of a pattern on a ballpark: coordinates are the field's screen frame (x across, y minus the distance out from home plate). `band` is
|
|
32
33
|
* 30 feet, the width of a stripe of the usual rings. `bands` run across the field at fixed distances out from home, `lengthwise` along the line to centre
|
|
33
|
-
* field, `checks` are squares, `diagonal` run at 45 degrees, `
|
|
34
|
+
* field, `checks` are squares, `diagonal` run at 45 degrees, `diamonds` are squares of `band` with their sides along the foul lines (two passes of stripes parallel to the
|
|
35
|
+
* lines, crossing, from home plate out), `fan` is wedges out from home plate, 6 degrees each. `rings` and `circles` are the park's own
|
|
34
36
|
* arcs about home plate (drawn by the field itself) and `none` is plain, so they have no tone here. The path runs past the fence and must be cut to the fair ground.
|
|
35
37
|
*/
|
|
36
38
|
export declare function mowPark(pattern: StripePattern, park: Park, band?: number): Mown;
|
package/dist/mow.js
CHANGED
|
@@ -5,6 +5,10 @@ import { num } from "./format.js";
|
|
|
5
5
|
const NONE = { path: "", clip: false, evenodd: false };
|
|
6
6
|
/** An odd whole number of cells nearest to a length over a cell: odd, so that both ends of the turf are mown alike. */
|
|
7
7
|
export const oddCells = (length, cell) => Math.max(3, 2 * Math.round((length / cell - 1) / 2) + 1);
|
|
8
|
+
/** A convex polygon from its corners, as a closed subpath. */
|
|
9
|
+
const poly = (corners) => `M${corners.map(([px, py]) => `${num(px)} ${num(py)}`).join("L")}z`;
|
|
10
|
+
/** The corners of the square of a lattice turned a quarter of a right angle: the cell between `a0` and `a1` along the first axis `(ex, ey)` and `b0` and `b1` along the second, from the origin `(ox, oy)`. */
|
|
11
|
+
const lattice = (ox, oy, ex, ey, fx, fy, a0, a1, b0, b1) => [[a0, b0], [a1, b0], [a1, b1], [a0, b1]].map(([a, b]) => [ox + a * ex + b * fx, oy + a * ey + b * fy]);
|
|
8
12
|
const box = (x, y, w, h) => `M${num(x)} ${num(y)}h${num(w)}v${num(h)}h${num(-w)}z`;
|
|
9
13
|
/** An annulus between two radii about a centre, as two circles of one path. */
|
|
10
14
|
const ring = (cx, cy, inner, outer) => {
|
|
@@ -14,7 +18,8 @@ const ring = (cx, cy, inner, outer) => {
|
|
|
14
18
|
/**
|
|
15
19
|
* The lighter tone of a pattern on a rectangle of turf. `band` is the width of the usual stripe, along x; `wide` and `narrow` are twice and half of it.
|
|
16
20
|
* `bands` run across the turf (side by side along x), `lengthwise` along it, `checks` are squares of about `band`, `diagonal` are 45-degree stripes
|
|
17
|
-
* `band` wide across,
|
|
21
|
+
* `band` wide across, `diamonds` are the squares of `checks` turned 45 degrees (the crosshatch of a ballpark's outfield: two passes of 45-degree stripes, `band` wide
|
|
22
|
+
* across, crossing), laid so that a diamond is centred on the turf and both ends are mown alike, and `circles` are rings `band` wide about the middle. A pattern that is not one of these (`none`, `rings`, `fan`) has no tone here.
|
|
18
23
|
*/
|
|
19
24
|
export function mowTurf(pattern, turf, band) {
|
|
20
25
|
const { x, y, w, h } = turf;
|
|
@@ -49,6 +54,26 @@ export function mowTurf(pattern, turf, band) {
|
|
|
49
54
|
parts.push(`M${num(a)} ${num(y + h)}L${num(a + h)} ${num(y)}L${num(a + h + across)} ${num(y)}L${num(a + across)} ${num(y + h)}z`);
|
|
50
55
|
return { path: parts.join(""), clip: true, evenodd: false };
|
|
51
56
|
}
|
|
57
|
+
case "diamonds": {
|
|
58
|
+
// A lattice of squares of side `band` turned 45 degrees, one square centred on the turf: both ends of the turf then have the same tone, whatever its size.
|
|
59
|
+
const cx = x + w / 2;
|
|
60
|
+
const cy = y + h / 2;
|
|
61
|
+
const r = Math.SQRT1_2;
|
|
62
|
+
const reach = Math.ceil((Math.hypot(w, h) / 2) / band) + 1;
|
|
63
|
+
for (let i = -reach; i <= reach; i += 1) {
|
|
64
|
+
for (let j = -reach; j <= reach; j += 1) {
|
|
65
|
+
if (Math.abs(i + j) % 2 !== 1)
|
|
66
|
+
continue;
|
|
67
|
+
const corners = lattice(cx, cy, r, r, -r, r, (i - 0.5) * band, (i + 0.5) * band, (j - 0.5) * band, (j + 0.5) * band);
|
|
68
|
+
const xs = corners.map((c) => c[0]);
|
|
69
|
+
const ys = corners.map((c) => c[1]);
|
|
70
|
+
if (Math.max(...xs) <= x || Math.min(...xs) >= x + w || Math.max(...ys) <= y || Math.min(...ys) >= y + h)
|
|
71
|
+
continue;
|
|
72
|
+
parts.push(poly(corners));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { path: parts.join(""), clip: true, evenodd: false };
|
|
76
|
+
}
|
|
52
77
|
case "circles": {
|
|
53
78
|
const cx = x + w / 2;
|
|
54
79
|
const cy = y + h / 2;
|
|
@@ -64,7 +89,8 @@ export function mowTurf(pattern, turf, band) {
|
|
|
64
89
|
/**
|
|
65
90
|
* The lighter tone of a pattern on a ballpark: coordinates are the field's screen frame (x across, y minus the distance out from home plate). `band` is
|
|
66
91
|
* 30 feet, the width of a stripe of the usual rings. `bands` run across the field at fixed distances out from home, `lengthwise` along the line to centre
|
|
67
|
-
* field, `checks` are squares, `diagonal` run at 45 degrees, `
|
|
92
|
+
* field, `checks` are squares, `diagonal` run at 45 degrees, `diamonds` are squares of `band` with their sides along the foul lines (two passes of stripes parallel to the
|
|
93
|
+
* lines, crossing, from home plate out), `fan` is wedges out from home plate, 6 degrees each. `rings` and `circles` are the park's own
|
|
68
94
|
* arcs about home plate (drawn by the field itself) and `none` is plain, so they have no tone here. The path runs past the fence and must be cut to the fair ground.
|
|
69
95
|
*/
|
|
70
96
|
export function mowPark(pattern, park, band = 30) {
|
|
@@ -96,6 +122,24 @@ export function mowPark(pattern, park, band = 30) {
|
|
|
96
122
|
parts.push(`M${num(a)} 0L${num(a + reach)} ${num(-reach)}L${num(a + reach + across)} ${num(-reach)}L${num(a + across)} 0z`);
|
|
97
123
|
return { path: parts.join(""), clip: true, evenodd: false };
|
|
98
124
|
}
|
|
125
|
+
case "diamonds": {
|
|
126
|
+
// The foul lines are the axes: a cell is `band` along each, from home plate, and the cells either side of a corner alternate.
|
|
127
|
+
const r = Math.SQRT1_2;
|
|
128
|
+
const last = Math.ceil((reach * Math.SQRT2) / band) + 1;
|
|
129
|
+
for (let i = 0; i < last; i += 1) {
|
|
130
|
+
for (let j = 0; j < last; j += 1) {
|
|
131
|
+
if ((i + j) % 2 !== 1)
|
|
132
|
+
continue;
|
|
133
|
+
const corners = lattice(0, 0, r, -r, -r, -r, i * band, (i + 1) * band, j * band, (j + 1) * band);
|
|
134
|
+
const xs = corners.map((c) => c[0]);
|
|
135
|
+
const ys = corners.map((c) => c[1]);
|
|
136
|
+
if (Math.max(...xs) < umin - band || Math.min(...xs) > umax + band || Math.min(...ys) > band || Math.max(...ys) < -reach)
|
|
137
|
+
continue;
|
|
138
|
+
parts.push(poly(corners));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { path: parts.join(""), clip: true, evenodd: false };
|
|
142
|
+
}
|
|
99
143
|
case "fan": {
|
|
100
144
|
const step = (6 * Math.PI) / 180;
|
|
101
145
|
const R = reach * 1.5;
|
package/dist/surfaces/soccer.js
CHANGED
|
@@ -13,10 +13,10 @@ const BANDS = { bands: 19, wide: 9, narrow: 39 };
|
|
|
13
13
|
function stripes(pattern, L, W, id) {
|
|
14
14
|
if (pattern === "none")
|
|
15
15
|
return { path: "", defs: "" };
|
|
16
|
-
if (pattern === "circles") {
|
|
17
|
-
// Rings about the middle, as wide as a usual band, cut to the pitch.
|
|
18
|
-
const mown = mowTurf(
|
|
19
|
-
return { path: mown.path, defs: `<clipPath id="${id}-turf"><rect x="0" y="0" width="${n(L)}" height="${n(W)}"/></clipPath>`, evenodd:
|
|
16
|
+
if (pattern === "circles" || pattern === "diamonds") {
|
|
17
|
+
// Rings about the middle, or squares turned 45 degrees about it, as wide as a usual band, cut to the pitch.
|
|
18
|
+
const mown = mowTurf(pattern, { x: 0, y: 0, w: L, h: W }, L / BANDS.bands);
|
|
19
|
+
return { path: mown.path, defs: `<clipPath id="${id}-turf"><rect x="0" y="0" width="${n(L)}" height="${n(W)}"/></clipPath>`, evenodd: mown.evenodd };
|
|
20
20
|
}
|
|
21
21
|
const rect = (x, y, w, h) => `M${n(x)} ${n(y)}h${n(w)}v${n(h)}h${n(-w)}z`;
|
|
22
22
|
const parts = [];
|
package/dist/types.d.ts
CHANGED
|
@@ -73,11 +73,11 @@ export interface Placement {
|
|
|
73
73
|
/** How much of the surface's markings are drawn. `simple` leaves out the small ones, such as hash marks. */
|
|
74
74
|
export type Detail = "full" | "simple";
|
|
75
75
|
/**
|
|
76
|
-
* How grass is mown: bands across the surface (the usual), wide ones or narrow ones, along it, in checks, on the diagonal, in rings round the
|
|
76
|
+
* How grass is mown: bands across the surface (the usual), wide ones or narrow ones, along it, in checks, on the diagonal, in diamonds (the checks turned 45 degrees: a ballpark outfield's crosshatch, its sides along the foul lines), in rings round the
|
|
77
77
|
* middle (`circles`), or `none`. A ballpark is mown in `rings` by default (arcs about home plate) and may also be mown in a `fan` (wedges out from
|
|
78
78
|
* home plate). A football field and a ballpark take the same options as a soccer pitch; a surface that is not grass ignores them.
|
|
79
79
|
*/
|
|
80
|
-
export type StripePattern = "bands" | "wide" | "narrow" | "lengthwise" | "checks" | "diagonal" | "circles" | "rings" | "fan" | "none";
|
|
80
|
+
export type StripePattern = "bands" | "wide" | "narrow" | "lengthwise" | "checks" | "diagonal" | "diamonds" | "circles" | "rings" | "fan" | "none";
|
|
81
81
|
/**
|
|
82
82
|
* How a goal is drawn, seen from above. A soccer goal: the net as a box behind the goal line, a line on it, a solid strip, or not at all.
|
|
83
83
|
* A hockey net: the same four (`box` is the open frame behind the goal line, `strip` a filled net). A basketball basket: `box` is the backboard,
|
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.36.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.
|
|
2
|
+
export const VERSION = "0.36.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
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",
|