@johnmorrisdotca/kyogijo-stadiums 0.40.2 → 0.44.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 +72 -0
- package/NOTICE.md +22 -0
- package/README.md +1 -3
- package/dist/cityctx-entry.d.ts +3 -0
- package/dist/cityctx-entry.js +3 -0
- package/dist/cityctx.d.ts +19 -0
- package/dist/cityctx.data.d.ts +11 -0
- package/dist/cityctx.data.js +7139 -0
- package/dist/cityctx.js +34 -0
- package/dist/context.d.ts +175 -0
- package/dist/context.js +369 -0
- package/dist/crowd.d.ts +9 -0
- package/dist/district-entry.d.ts +16 -1
- package/dist/district-entry.js +9 -0
- package/dist/district.d.ts +99 -4
- package/dist/district.dom.d.ts +31 -0
- package/dist/district.dom.js +52 -0
- package/dist/district.js +103 -25
- package/dist/district.turn.js +89 -19
- package/dist/gates.d.ts +56 -0
- package/dist/gates.js +95 -0
- package/dist/halls.d.ts +2 -0
- package/dist/halls.js +1 -1
- package/dist/kodokan.d.ts +116 -0
- package/dist/kodokan.data.d.ts +61 -0
- package/dist/kodokan.data.js +20 -0
- package/dist/kodokan.js +92 -0
- package/dist/osm-entry.d.ts +2 -0
- package/dist/osm-entry.js +2 -0
- package/dist/osm.context.data.d.ts +10 -0
- package/dist/osm.context.data.js +1107 -0
- package/dist/outside.d.ts +43 -0
- package/dist/outside.dom.d.ts +44 -0
- package/dist/outside.dom.js +203 -0
- package/dist/outside.js +227 -0
- package/dist/outside.paint.d.ts +57 -0
- package/dist/outside.paint.js +88 -0
- package/dist/plateau-entry.d.ts +3 -0
- package/dist/plateau-entry.js +3 -0
- package/dist/plateau.credit.d.ts +5 -0
- package/dist/plateau.credit.js +7 -0
- package/dist/plateau.data.d.ts +7 -0
- package/dist/plateau.data.js +757 -0
- package/dist/stadiums.d.ts +14 -0
- package/dist/stadiums.data.js +2 -1
- package/dist/stadiums.js +2 -0
- package/dist/strings.d.ts +3 -1
- package/dist/strings.js +4 -4
- package/dist/turn.dom.d.ts +10 -0
- package/dist/turn.dom.js +21 -0
- package/dist/turn.kit.d.ts +12 -3
- package/dist/turn.kit.js +7 -0
- package/dist/turn.markup.js +15 -3
- package/dist/turn.model.d.ts +3 -0
- package/dist/turn.style.js +20 -3
- package/dist/venue.real.d.ts +22 -1
- package/dist/venue.real.js +76 -7
- package/dist/venues.d.ts +9 -1
- package/dist/venues.data.js +2 -1
- package/dist/venues.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/walk.d.ts +56 -0
- package/dist/walk.data.d.ts +4 -0
- package/dist/walk.data.js +1295 -0
- package/dist/walk.js +120 -0
- package/package.json +25 -1
package/dist/walk.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// The walkable mask of a district: the cells of a fine grid on the ground where a person may stand, worked out from the features OpenStreetMap maps round the venues (`walk.data.ts`, ODbL 1.0): the paths, sidewalks,
|
|
2
|
+
// plazas, squares, parks and platforms people stand on, the apron of each venue's own ground, minus what stops a crowd (carriageways at the width their lanes give them, cycle tracks, railways, water and every building).
|
|
3
|
+
// Pure arithmetic on typed arrays, in Node or in a page: data in, a grid out. Nothing is drawn here; the roads are never drawn, and the shape of a crowd on this mask is what shows where they are.
|
|
4
|
+
import { WALK_DATA, WALK_UNIT } from "./walk.data.js";
|
|
5
|
+
/** The side of a cell of the mask, in metres: half a metre, finer than the narrowest path and a person's width. */
|
|
6
|
+
export const WALK_CELL = 0.5;
|
|
7
|
+
/** The districts there are masks for. */
|
|
8
|
+
export const WALK_IDS = Object.freeze(Object.keys(WALK_DATA));
|
|
9
|
+
/** A path from its packed form: the first point, then the step to each next one, in metres. */
|
|
10
|
+
export function unpack(packed, from = 0) {
|
|
11
|
+
const out = [];
|
|
12
|
+
let [x, y] = [0, 0];
|
|
13
|
+
for (let i = from; i + 1 < packed.length; i += 2) {
|
|
14
|
+
x += packed[i];
|
|
15
|
+
y += packed[i + 1];
|
|
16
|
+
out.push([x * WALK_UNIT, y * WALK_UNIT]);
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
/** Fill the cells inside a polygon (its rings, the even-odd rule: a ring inside another is a hole) with `value`. */
|
|
21
|
+
function fillPolygon(mask, rings, value) {
|
|
22
|
+
const { cell, x0, y0, width, height, cells } = mask;
|
|
23
|
+
let [lo, hi] = [Infinity, -Infinity];
|
|
24
|
+
for (const ring of rings)
|
|
25
|
+
for (const p of ring)
|
|
26
|
+
[lo, hi] = [Math.min(lo, p[1]), Math.max(hi, p[1])];
|
|
27
|
+
const first = Math.max(0, Math.floor((lo - y0) / cell));
|
|
28
|
+
const last = Math.min(height - 1, Math.ceil((hi - y0) / cell));
|
|
29
|
+
const crossings = [];
|
|
30
|
+
for (let row = first; row <= last; row += 1) {
|
|
31
|
+
const y = y0 + (row + 0.5) * cell;
|
|
32
|
+
crossings.length = 0;
|
|
33
|
+
for (const ring of rings) {
|
|
34
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {
|
|
35
|
+
const [xi, yi] = ring[i];
|
|
36
|
+
const [xj, yj] = ring[j];
|
|
37
|
+
if (yi > y !== yj > y)
|
|
38
|
+
crossings.push(xi + ((y - yi) / (yj - yi)) * (xj - xi));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
crossings.sort((a, b) => a - b);
|
|
42
|
+
for (let k = 0; k + 1 < crossings.length; k += 2) {
|
|
43
|
+
const from = Math.max(0, Math.ceil((crossings[k] - x0) / cell - 0.5));
|
|
44
|
+
const to = Math.min(width - 1, Math.floor((crossings[k + 1] - x0) / cell - 0.5));
|
|
45
|
+
if (to >= from)
|
|
46
|
+
cells.fill(value, row * width + from, row * width + to + 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Set the cells within `half` metres of a line (round at the ends) to `value`. */
|
|
51
|
+
function strokeLine(mask, line, half, value) {
|
|
52
|
+
const { cell, x0, y0, width, height, cells } = mask;
|
|
53
|
+
const r2 = half * half;
|
|
54
|
+
for (let s = 0; s + 1 < line.length || (s === 0 && line.length === 1); s += 1) {
|
|
55
|
+
const [ax, ay] = line[s];
|
|
56
|
+
const [bx, by] = line[Math.min(s + 1, line.length - 1)];
|
|
57
|
+
const [dx, dy] = [bx - ax, by - ay];
|
|
58
|
+
const len2 = dx * dx + dy * dy;
|
|
59
|
+
const c0 = Math.max(0, Math.floor((Math.min(ax, bx) - half - x0) / cell));
|
|
60
|
+
const c1 = Math.min(width - 1, Math.ceil((Math.max(ax, bx) + half - x0) / cell));
|
|
61
|
+
const r0 = Math.max(0, Math.floor((Math.min(ay, by) - half - y0) / cell));
|
|
62
|
+
const r1 = Math.min(height - 1, Math.ceil((Math.max(ay, by) + half - y0) / cell));
|
|
63
|
+
for (let row = r0; row <= r1; row += 1) {
|
|
64
|
+
const y = y0 + (row + 0.5) * cell;
|
|
65
|
+
for (let col = c0; col <= c1; col += 1) {
|
|
66
|
+
const x = x0 + (col + 0.5) * cell;
|
|
67
|
+
const t = len2 < 1e-12 ? 0 : Math.max(0, Math.min(1, ((x - ax) * dx + (y - ay) * dy) / len2));
|
|
68
|
+
const [ex, ey] = [x - (ax + t * dx), y - (ay + t * dy)];
|
|
69
|
+
if (ex * ex + ey * ey <= r2)
|
|
70
|
+
cells[row * width + col] = value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const masks = new Map();
|
|
76
|
+
/**
|
|
77
|
+
* The mask of a district, rasterised from `WALK_DATA` (and kept for the next call): the walkable areas and the paths at their width, the apron round each venue, then the carriageways, cycle tracks, railways, water and buildings cut out
|
|
78
|
+
* of them, and the venues' own buildings last. A person stands in a cell with value 1, and nowhere else.
|
|
79
|
+
*/
|
|
80
|
+
export function walkMask(id, extras) {
|
|
81
|
+
const key = `${id}:${extras.apron}:${extras.buildings.map((b) => b.length).join(",")}`;
|
|
82
|
+
const kept = masks.get(key);
|
|
83
|
+
if (kept !== undefined)
|
|
84
|
+
return kept;
|
|
85
|
+
const data = WALK_DATA[id];
|
|
86
|
+
if (data === undefined)
|
|
87
|
+
throw new Error(`no walkable mask ${id}: the masks are ${WALK_IDS.join(", ")}`);
|
|
88
|
+
const [west, south, east, north] = data.box;
|
|
89
|
+
const width = Math.ceil((east - west) / WALK_CELL);
|
|
90
|
+
const height = Math.ceil((north - south) / WALK_CELL);
|
|
91
|
+
const mask = { id, origin: data.origin, cell: WALK_CELL, x0: west, y0: south, width, height, cells: new Uint8Array(width * height), walkable: 0 };
|
|
92
|
+
const polygon = (rings) => rings.map((ring) => unpack(ring));
|
|
93
|
+
for (const area of data.walkAreas)
|
|
94
|
+
fillPolygon(mask, polygon(area), 1);
|
|
95
|
+
for (const line of data.walkLines)
|
|
96
|
+
strokeLine(mask, unpack(line, 1), line[0] / 20, 1);
|
|
97
|
+
// The venue's own ground: a band round its building.
|
|
98
|
+
for (const ring of extras.buildings)
|
|
99
|
+
strokeLine(mask, [...ring, ring[0]], extras.apron, 1);
|
|
100
|
+
for (const line of data.blockLines)
|
|
101
|
+
strokeLine(mask, unpack(line, 1), line[0] / 20, 0);
|
|
102
|
+
for (const area of data.blockAreas)
|
|
103
|
+
fillPolygon(mask, polygon(area), 0);
|
|
104
|
+
for (const ring of extras.buildings)
|
|
105
|
+
fillPolygon(mask, [ring], 0);
|
|
106
|
+
let walkable = 0;
|
|
107
|
+
for (let i = 0; i < mask.cells.length; i += 1)
|
|
108
|
+
walkable += mask.cells[i];
|
|
109
|
+
mask.walkable = walkable;
|
|
110
|
+
masks.set(key, mask);
|
|
111
|
+
return mask;
|
|
112
|
+
}
|
|
113
|
+
/** Whether a point (metres east and north of the mask's origin) is in a walkable cell. */
|
|
114
|
+
export function walkable(mask, x, y) {
|
|
115
|
+
const col = Math.floor((x - mask.x0) / mask.cell);
|
|
116
|
+
const row = Math.floor((y - mask.y0) / mask.cell);
|
|
117
|
+
return col >= 0 && row >= 0 && col < mask.width && row < mask.height && mask.cells[row * mask.width + col] === 1;
|
|
118
|
+
}
|
|
119
|
+
/** The mask a set of venues stand on, if there is one: the first mask that names one of them (by id, whatever configuration). */
|
|
120
|
+
export const walkIdFor = (venueIds) => WALK_IDS.find((id) => WALK_DATA[id].venues.some((key) => venueIds.includes(key.split(":")[0])));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.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",
|
|
@@ -143,6 +143,21 @@
|
|
|
143
143
|
"import": "./dist/district-entry.js",
|
|
144
144
|
"default": "./dist/district-entry.js"
|
|
145
145
|
},
|
|
146
|
+
"./plateau": {
|
|
147
|
+
"types": "./dist/plateau-entry.d.ts",
|
|
148
|
+
"import": "./dist/plateau-entry.js",
|
|
149
|
+
"default": "./dist/plateau-entry.js"
|
|
150
|
+
},
|
|
151
|
+
"./cityctx": {
|
|
152
|
+
"types": "./dist/cityctx-entry.d.ts",
|
|
153
|
+
"import": "./dist/cityctx-entry.js",
|
|
154
|
+
"default": "./dist/cityctx-entry.js"
|
|
155
|
+
},
|
|
156
|
+
"./osm": {
|
|
157
|
+
"types": "./dist/osm-entry.d.ts",
|
|
158
|
+
"import": "./dist/osm-entry.js",
|
|
159
|
+
"default": "./dist/osm-entry.js"
|
|
160
|
+
},
|
|
146
161
|
"./grounds": {
|
|
147
162
|
"types": "./dist/grounds-entry.d.ts",
|
|
148
163
|
"import": "./dist/grounds-entry.js",
|
|
@@ -305,6 +320,15 @@
|
|
|
305
320
|
"venues:fetch": "node scripts/fetch-venues.mjs",
|
|
306
321
|
"stadiums": "node scripts/build-stadiums.mjs",
|
|
307
322
|
"stadiums:fetch": "node scripts/fetch-stadiums.mjs",
|
|
323
|
+
"walk": "node scripts/build-walk.mjs",
|
|
324
|
+
"osm-context": "node scripts/build-osm-context.mjs",
|
|
325
|
+
"cityctx": "node scripts/build-cityctx.mjs",
|
|
326
|
+
"cityctx:fetch": "node scripts/fetch-cityctx.mjs",
|
|
327
|
+
"cityctx:vox": "python3.13 -I scripts/cityctx_vox.py",
|
|
328
|
+
"walk:fetch": "node scripts/fetch-walk.mjs",
|
|
329
|
+
"outside:cost": "node scripts/outside-cost.mjs",
|
|
330
|
+
"plateau": "node scripts/build-plateau.mjs",
|
|
331
|
+
"plateau:fetch": "node scripts/fetch-plateau.mjs",
|
|
308
332
|
"boards": "node scripts/make-boards.mjs",
|
|
309
333
|
"grounds": "node scripts/build-grounds.mjs",
|
|
310
334
|
"grounds:check": "node scripts/check-grounds.mjs",
|