@expofp/wayfinding-compiler 0.0.0-bootstrap.0 → 0.0.0-stage
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/README.md +2 -445
- package/package.json +3 -34
- package/dist/index.d.ts +0 -14
- package/dist/index.js +0 -3
- package/dist/lib/attach.d.ts +0 -43
- package/dist/lib/attach.js +0 -199
- package/dist/lib/axes.d.ts +0 -76
- package/dist/lib/axes.js +0 -103
- package/dist/lib/blockers.d.ts +0 -134
- package/dist/lib/blockers.js +0 -289
- package/dist/lib/cell-array.d.ts +0 -14
- package/dist/lib/cell-array.js +0 -25
- package/dist/lib/centering.d.ts +0 -14
- package/dist/lib/centering.js +0 -88
- package/dist/lib/compile-layer.d.ts +0 -41
- package/dist/lib/compile-layer.js +0 -241
- package/dist/lib/compile-wayfinding.d.ts +0 -90
- package/dist/lib/compile-wayfinding.js +0 -203
- package/dist/lib/connect.d.ts +0 -35
- package/dist/lib/connect.js +0 -206
- package/dist/lib/diagnostics.d.ts +0 -190
- package/dist/lib/diagnostics.js +0 -634
- package/dist/lib/doorways.d.ts +0 -78
- package/dist/lib/doorways.js +0 -331
- package/dist/lib/emit-network.d.ts +0 -47
- package/dist/lib/emit-network.js +0 -105
- package/dist/lib/emit-v1.d.ts +0 -31
- package/dist/lib/emit-v1.js +0 -56
- package/dist/lib/entries.d.ts +0 -123
- package/dist/lib/entries.js +0 -448
- package/dist/lib/floor-grids.d.ts +0 -48
- package/dist/lib/floor-grids.js +0 -185
- package/dist/lib/framing.d.ts +0 -20
- package/dist/lib/framing.js +0 -187
- package/dist/lib/geom/boolean-ops.d.ts +0 -21
- package/dist/lib/geom/boolean-ops.js +0 -1
- package/dist/lib/geom/clipper2-ops.d.ts +0 -7
- package/dist/lib/geom/clipper2-ops.js +0 -50
- package/dist/lib/geom/footprint.d.ts +0 -26
- package/dist/lib/geom/footprint.js +0 -203
- package/dist/lib/geom/frames.d.ts +0 -116
- package/dist/lib/geom/frames.js +0 -233
- package/dist/lib/geom/mesh-outline.d.ts +0 -13
- package/dist/lib/geom/mesh-outline.js +0 -90
- package/dist/lib/geom/normalize.d.ts +0 -28
- package/dist/lib/geom/normalize.js +0 -118
- package/dist/lib/geom/point-key.d.ts +0 -16
- package/dist/lib/geom/point-key.js +0 -15
- package/dist/lib/geom/primitives.d.ts +0 -105
- package/dist/lib/geom/primitives.js +0 -184
- package/dist/lib/geom/split-crossings.d.ts +0 -14
- package/dist/lib/geom/split-crossings.js +0 -171
- package/dist/lib/geom/types.d.ts +0 -9
- package/dist/lib/geom/types.js +0 -1
- package/dist/lib/geom/walls.d.ts +0 -31
- package/dist/lib/geom/walls.js +0 -71
- package/dist/lib/graph-invariants.d.ts +0 -49
- package/dist/lib/graph-invariants.js +0 -129
- package/dist/lib/graph-types.d.ts +0 -143
- package/dist/lib/graph-types.js +0 -7
- package/dist/lib/grid-network.d.ts +0 -20
- package/dist/lib/grid-network.js +0 -349
- package/dist/lib/lattice-map.d.ts +0 -19
- package/dist/lib/lattice-map.js +0 -92
- package/dist/lib/lattice-network.d.ts +0 -32
- package/dist/lib/lattice-network.js +0 -289
- package/dist/lib/mask.d.ts +0 -54
- package/dist/lib/mask.js +0 -210
- package/dist/lib/min-heap.d.ts +0 -24
- package/dist/lib/min-heap.js +0 -73
- package/dist/lib/network-build.d.ts +0 -21
- package/dist/lib/network-build.js +0 -4
- package/dist/lib/network-graph.d.ts +0 -80
- package/dist/lib/network-graph.js +0 -467
- package/dist/lib/network-setup.d.ts +0 -50
- package/dist/lib/network-setup.js +0 -76
- package/dist/lib/network-sizes.d.ts +0 -29
- package/dist/lib/network-sizes.js +0 -22
- package/dist/lib/network-store.d.ts +0 -173
- package/dist/lib/network-store.js +0 -430
- package/dist/lib/openings.d.ts +0 -54
- package/dist/lib/openings.js +0 -387
- package/dist/lib/place-path.d.ts +0 -47
- package/dist/lib/place-path.js +0 -346
- package/dist/lib/post-passes.d.ts +0 -31
- package/dist/lib/post-passes.js +0 -305
- package/dist/lib/reachability.d.ts +0 -58
- package/dist/lib/reachability.js +0 -220
- package/dist/lib/report.d.ts +0 -49
- package/dist/lib/report.js +0 -374
- package/dist/lib/router.d.ts +0 -111
- package/dist/lib/router.js +0 -388
- package/dist/lib/runs.d.ts +0 -92
- package/dist/lib/runs.js +0 -232
- package/dist/lib/scale.d.ts +0 -58
- package/dist/lib/scale.js +0 -185
- package/dist/lib/steiner-network.d.ts +0 -19
- package/dist/lib/steiner-network.js +0 -183
- package/dist/lib/strip.d.ts +0 -43
- package/dist/lib/strip.js +0 -200
- package/dist/lib/stubs.d.ts +0 -84
- package/dist/lib/stubs.js +0 -316
- package/dist/lib/transitions.d.ts +0 -72
- package/dist/lib/transitions.js +0 -191
- package/dist/lib/types.d.ts +0 -126
- package/dist/lib/types.js +0 -1
- package/dist/lib/validate-source.d.ts +0 -41
- package/dist/lib/validate-source.js +0 -133
- package/dist/lib/walkable.d.ts +0 -104
- package/dist/lib/walkable.js +0 -140
package/dist/lib/router.js
DELETED
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
// The axis router: a four-heading walk over the mask with turn and proximity costs — one grid per
|
|
2
|
-
// drawn direction, walked as one.
|
|
3
|
-
import { cellArray } from './cell-array.js';
|
|
4
|
-
import { fromFrame, linesMeet, nearestFrame, toFrame } from './geom/frames.js';
|
|
5
|
-
import { MinHeap } from './min-heap.js';
|
|
6
|
-
import { MIN_PASS } from './network-sizes.js';
|
|
7
|
-
const NEAR_PENALTY = 1.5;
|
|
8
|
-
const TIGHT_PENALTY = 8;
|
|
9
|
-
const DIRS = [
|
|
10
|
-
[1, 0],
|
|
11
|
-
[-1, 0],
|
|
12
|
-
[0, 1],
|
|
13
|
-
[0, -1],
|
|
14
|
-
];
|
|
15
|
-
/**
|
|
16
|
-
* Build the router. Per grid: coarse cells free when any mask cell is, seam flags so a thin wall still
|
|
17
|
-
* blocks a step, and a cost that keeps off walls. A roomy cell may step onto another grid at the cost of a
|
|
18
|
-
* turn; along an aisle its own grid runs straight while the others zigzag, so the walk picks it naturally.
|
|
19
|
-
* @param grids The floor per direction, plan axes first; a direction may have several grids.
|
|
20
|
-
* @param cfg Network sizes.
|
|
21
|
-
* @returns The router.
|
|
22
|
-
*/
|
|
23
|
-
export function makeRouter(grids, cfg) {
|
|
24
|
-
const f = Math.max(1, Math.round(cfg.pitch / grids[0].ctx.cs));
|
|
25
|
-
const pitch = f * grids[0].ctx.cs;
|
|
26
|
-
const layout = grids.map(({ ctx }) => ({
|
|
27
|
-
w2: Math.max(2, Math.floor(ctx.w / f)),
|
|
28
|
-
h2: Math.max(2, Math.floor(ctx.h / f)),
|
|
29
|
-
offset: 0,
|
|
30
|
-
}));
|
|
31
|
-
let cells = 0;
|
|
32
|
-
for (const grid of layout) {
|
|
33
|
-
grid.offset = cells;
|
|
34
|
-
cells += grid.w2 * grid.h2;
|
|
35
|
-
}
|
|
36
|
-
const ok = cellArray(Uint8Array, cells);
|
|
37
|
-
const stepCost = cellArray(Float32Array, cells);
|
|
38
|
-
// A router cell is free when ANY of its mask cells is (keeps narrow doorways), which alone would let a
|
|
39
|
-
// step cross a thin wall. These flag whether the shared edge of two neighbors has a free mask-cell pair
|
|
40
|
-
// across it, so a wall along the seam blocks the step.
|
|
41
|
-
const passX = cellArray(Uint8Array, cells);
|
|
42
|
-
const passY = cellArray(Uint8Array, cells);
|
|
43
|
-
/** 1 where a cell has clearance to turn in (including onto another grid). */
|
|
44
|
-
const roomy = cellArray(Uint8Array, cells);
|
|
45
|
-
/** Which grid a cell belongs to. */
|
|
46
|
-
const gridOf = cellArray(Int32Array, cells);
|
|
47
|
-
grids.forEach(({ ctx }, g) => {
|
|
48
|
-
const { w2, h2, offset } = layout[g];
|
|
49
|
-
const maskFree = (i) => ctx.mask[i] === 1 && ctx.dist[i] >= MIN_PASS;
|
|
50
|
-
gridOf.fill(g, offset, offset + w2 * h2);
|
|
51
|
-
for (let y = 0; y < h2; y++)
|
|
52
|
-
for (let x = 0; x < w2; x++) {
|
|
53
|
-
const c = offset + y * w2 + x;
|
|
54
|
-
let any = 0;
|
|
55
|
-
let dmax = 0;
|
|
56
|
-
for (let dy = 0; dy < f; dy++)
|
|
57
|
-
for (let dx = 0; dx < f; dx++) {
|
|
58
|
-
const i = (y * f + dy) * ctx.w + (x * f + dx);
|
|
59
|
-
if (maskFree(i))
|
|
60
|
-
any = 1;
|
|
61
|
-
dmax = Math.max(dmax, ctx.dist[i]);
|
|
62
|
-
}
|
|
63
|
-
ok[c] = any;
|
|
64
|
-
roomy[c] = dmax < cfg.clear ? 0 : 1;
|
|
65
|
-
stepCost[c] =
|
|
66
|
-
pitch *
|
|
67
|
-
(1 +
|
|
68
|
-
Math.max(0, NEAR_PENALTY - dmax) * NEAR_PENALTY +
|
|
69
|
-
(dmax < cfg.clear ? TIGHT_PENALTY : 0));
|
|
70
|
-
if (x + 1 < w2) {
|
|
71
|
-
const xa = x * f + f - 1;
|
|
72
|
-
const xb = (x + 1) * f;
|
|
73
|
-
let open = 0;
|
|
74
|
-
for (let dy = 0; dy < f && !open; dy++) {
|
|
75
|
-
const row = (y * f + dy) * ctx.w;
|
|
76
|
-
if (maskFree(row + xa) && maskFree(row + xb))
|
|
77
|
-
open = 1;
|
|
78
|
-
}
|
|
79
|
-
passX[c] = open;
|
|
80
|
-
}
|
|
81
|
-
if (y + 1 < h2) {
|
|
82
|
-
const ya = (y * f + f - 1) * ctx.w;
|
|
83
|
-
const yb = (y + 1) * f * ctx.w;
|
|
84
|
-
let open = 0;
|
|
85
|
-
for (let dx = 0; dx < f && !open; dx++) {
|
|
86
|
-
const col = x * f + dx;
|
|
87
|
-
if (maskFree(ya + col) && maskFree(yb + col))
|
|
88
|
-
open = 1;
|
|
89
|
-
}
|
|
90
|
-
passY[c] = open;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
// A grid with no roomy cell would be an island; there the walk may change grids from any cell.
|
|
95
|
-
const turnsAnywhere = grids.map((_, g) => {
|
|
96
|
-
const { w2, h2, offset } = layout[g];
|
|
97
|
-
for (let c = offset; c < offset + w2 * h2; c++)
|
|
98
|
-
if (ok[c] && roomy[c])
|
|
99
|
-
return false;
|
|
100
|
-
return true;
|
|
101
|
-
});
|
|
102
|
-
const canTurn = (c) => roomy[c] === 1 || turnsAnywhere[gridOf[c]];
|
|
103
|
-
const states = cells * 4;
|
|
104
|
-
const dist = cellArray(Float32Array, states);
|
|
105
|
-
const seen = cellArray(Int32Array, states);
|
|
106
|
-
const parent = cellArray(Int32Array, states);
|
|
107
|
-
let epoch = 0;
|
|
108
|
-
/**
|
|
109
|
-
* A point's cell on one grid.
|
|
110
|
-
* @param g The grid.
|
|
111
|
-
* @param x Point x.
|
|
112
|
-
* @param y Point y.
|
|
113
|
-
* @returns The cell, or -1 off that grid.
|
|
114
|
-
*/
|
|
115
|
-
const cellOn = (g, x, y) => {
|
|
116
|
-
const { ctx, frame } = grids[g];
|
|
117
|
-
const { w2, h2, offset } = layout[g];
|
|
118
|
-
const [u, v] = toFrame(frame, x, y);
|
|
119
|
-
const gx = Math.floor((u - ctx.ox) / pitch);
|
|
120
|
-
const gy = Math.floor((v - ctx.oy) / pitch);
|
|
121
|
-
return gx >= 0 && gy >= 0 && gx < w2 && gy < h2 ? offset + gy * w2 + gx : -1;
|
|
122
|
-
};
|
|
123
|
-
const cellsOf = (x, y) => {
|
|
124
|
-
const out = [];
|
|
125
|
-
for (let g = 0; g < grids.length; g++) {
|
|
126
|
-
const c = cellOn(g, x, y);
|
|
127
|
-
if (c >= 0)
|
|
128
|
-
out.push(c);
|
|
129
|
-
}
|
|
130
|
-
return out;
|
|
131
|
-
};
|
|
132
|
-
// A direction may have several grids over different ground.
|
|
133
|
-
const frames = grids.map((grid) => grid.frame);
|
|
134
|
-
const sameFrame = grids.map((grid) => grids.flatMap((other, g) => (other.frame === grid.frame ? [g] : [])));
|
|
135
|
-
const gridsAlong = (dx, dy) => sameFrame[nearestFrame(frames, dx, dy)];
|
|
136
|
-
const cellIn = (x, y, frame) => {
|
|
137
|
-
for (const g of sameFrame[frames.indexOf(frame)] ?? []) {
|
|
138
|
-
const c = cellOn(g, x, y);
|
|
139
|
-
if (c >= 0)
|
|
140
|
-
return c;
|
|
141
|
-
}
|
|
142
|
-
return -1;
|
|
143
|
-
};
|
|
144
|
-
const cellOf = (x, y, dx, dy) => cellIn(x, y, frames[nearestFrame(frames, dx, dy)]);
|
|
145
|
-
/**
|
|
146
|
-
* Exact center of a cell.
|
|
147
|
-
* @param c The cell.
|
|
148
|
-
* @returns The center in plan coordinates.
|
|
149
|
-
*/
|
|
150
|
-
const centerOf = (c) => {
|
|
151
|
-
const g = gridOf[c];
|
|
152
|
-
const { ctx, frame } = grids[g];
|
|
153
|
-
const { w2, offset } = layout[g];
|
|
154
|
-
const i = c - offset;
|
|
155
|
-
return fromFrame(frame, ctx.ox + ((i % w2) + 0.5) * pitch, ctx.oy + (Math.floor(i / w2) + 0.5) * pitch);
|
|
156
|
-
};
|
|
157
|
-
const worldOf = (c) => {
|
|
158
|
-
const [x, y] = centerOf(c);
|
|
159
|
-
return [+x.toFixed(2), +y.toFixed(2)];
|
|
160
|
-
};
|
|
161
|
-
const cellsAlong = (x0, y0, x1, y1, own = false) => {
|
|
162
|
-
const out = [];
|
|
163
|
-
const len = Math.hypot(x1 - x0, y1 - y0);
|
|
164
|
-
const n = Math.max(1, Math.ceil(len / (pitch * 0.5)));
|
|
165
|
-
const only = own ? gridsAlong(x1 - x0, y1 - y0) : null;
|
|
166
|
-
for (let g = 0; g < grids.length; g++)
|
|
167
|
-
for (let k = 0; k <= n && (!only || only.includes(g)); k++) {
|
|
168
|
-
const c = cellOn(g, x0 + ((x1 - x0) * k) / n, y0 + ((y1 - y0) * k) / n);
|
|
169
|
-
if (c >= 0)
|
|
170
|
-
out.push(c);
|
|
171
|
-
}
|
|
172
|
-
// Not reached by its own grids: fall back to every grid.
|
|
173
|
-
return out.length || !own ? out : cellsAlong(x0, y0, x1, y1);
|
|
174
|
-
};
|
|
175
|
-
const stepTo = (c, nd) => {
|
|
176
|
-
const { w2, h2, offset } = layout[gridOf[c]];
|
|
177
|
-
const i = c - offset;
|
|
178
|
-
const x = (i % w2) + DIRS[nd][0];
|
|
179
|
-
const y = Math.floor(i / w2) + DIRS[nd][1];
|
|
180
|
-
if (x < 0 || y < 0 || x >= w2 || y >= h2)
|
|
181
|
-
return -1;
|
|
182
|
-
const nc = offset + y * w2 + x;
|
|
183
|
-
if (!ok[nc])
|
|
184
|
-
return -1;
|
|
185
|
-
const step = DIRS[nd][0] === 1
|
|
186
|
-
? passX[c]
|
|
187
|
-
: DIRS[nd][0] === -1
|
|
188
|
-
? passX[nc]
|
|
189
|
-
: DIRS[nd][1] === 1
|
|
190
|
-
? passY[c]
|
|
191
|
-
: passY[nc];
|
|
192
|
-
return step ? nc : -1;
|
|
193
|
-
};
|
|
194
|
-
/**
|
|
195
|
-
* Cells from a reached state back to its seed, reached first.
|
|
196
|
-
* @param s The reached state.
|
|
197
|
-
* @returns The cells, consecutive repeats removed.
|
|
198
|
-
*/
|
|
199
|
-
const pathTo = (s) => {
|
|
200
|
-
const cells = [];
|
|
201
|
-
let cur = s;
|
|
202
|
-
while (cur >= 0) {
|
|
203
|
-
const cc = Math.floor(cur / 4);
|
|
204
|
-
if (!cells.length || cells[cells.length - 1] !== cc)
|
|
205
|
-
cells.push(cc);
|
|
206
|
-
cur = parent[cur];
|
|
207
|
-
}
|
|
208
|
-
return cells;
|
|
209
|
-
};
|
|
210
|
-
/**
|
|
211
|
-
* Offer one step to the search.
|
|
212
|
-
* @param s State stepped from.
|
|
213
|
-
* @param nc Cell stepped onto.
|
|
214
|
-
* @param nd Heading there.
|
|
215
|
-
* @param ncost Cost there.
|
|
216
|
-
* @param heap The heap.
|
|
217
|
-
*/
|
|
218
|
-
const offer = (s, nc, nd, ncost, heap) => {
|
|
219
|
-
const ns = nc * 4 + nd;
|
|
220
|
-
if (seen[ns] !== epoch || ncost < dist[ns]) {
|
|
221
|
-
seen[ns] = epoch;
|
|
222
|
-
dist[ns] = ncost;
|
|
223
|
-
parent[ns] = s;
|
|
224
|
-
// Push the Float32-rounded cost: the stale check `du > dist[s]` compares against it.
|
|
225
|
-
heap.push(dist[ns], ns);
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
/**
|
|
229
|
-
* Offer every step out of a state: four along its grid, and onto the other grids.
|
|
230
|
-
* @param s State just popped.
|
|
231
|
-
* @param du Its cost.
|
|
232
|
-
* @param heap The heap.
|
|
233
|
-
*/
|
|
234
|
-
const relax = (s, du, heap) => {
|
|
235
|
-
const c = Math.floor(s / 4);
|
|
236
|
-
const d = s % 4;
|
|
237
|
-
for (let nd = 0; nd < 4; nd++) {
|
|
238
|
-
const nc = stepTo(c, nd);
|
|
239
|
-
if (nc >= 0)
|
|
240
|
-
offer(s, nc, nd, du + stepCost[nc] + (nd !== d ? cfg.turn : 0), heap);
|
|
241
|
-
}
|
|
242
|
-
// Change grids only where roomy: in a tight aisle the grids' costs differ over one spot, and the walk
|
|
243
|
-
// would hop between them for the cheaper reading.
|
|
244
|
-
if (grids.length < 2 || !canTurn(c))
|
|
245
|
-
return;
|
|
246
|
-
const [x, y] = centerOf(c);
|
|
247
|
-
for (let g = 0; g < grids.length; g++) {
|
|
248
|
-
if (g === gridOf[c])
|
|
249
|
-
continue;
|
|
250
|
-
const nc = cellOn(g, x, y);
|
|
251
|
-
if (nc >= 0 && ok[nc] && canTurn(nc))
|
|
252
|
-
offer(s, nc, d, du + cfg.turn, heap);
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
// A cell starts the search in all four headings at cost 0.
|
|
256
|
-
const seed = (c, heap) => {
|
|
257
|
-
for (let d = 0; d < 4; d++) {
|
|
258
|
-
const s = c * 4 + d;
|
|
259
|
-
dist[s] = 0;
|
|
260
|
-
seen[s] = epoch;
|
|
261
|
-
parent[s] = -1;
|
|
262
|
-
heap.push(0, s);
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
const route = (seeds, isTarget) => {
|
|
266
|
-
epoch++;
|
|
267
|
-
const heap = new MinHeap();
|
|
268
|
-
for (const c of seeds)
|
|
269
|
-
if (c >= 0 && ok[c])
|
|
270
|
-
seed(c, heap);
|
|
271
|
-
while (heap.size) {
|
|
272
|
-
const s = heap.pop();
|
|
273
|
-
const du = heap.poppedKey;
|
|
274
|
-
if (seen[s] !== epoch || du > dist[s])
|
|
275
|
-
continue;
|
|
276
|
-
if (isTarget[Math.floor(s / 4)])
|
|
277
|
-
return pathTo(s);
|
|
278
|
-
relax(s, du, heap);
|
|
279
|
-
}
|
|
280
|
-
return null;
|
|
281
|
-
};
|
|
282
|
-
const grow = (seeds, group, reseed, onJoin) => {
|
|
283
|
-
// One epoch for the whole growth: settled states stay settled across targets.
|
|
284
|
-
epoch++;
|
|
285
|
-
const heap = new MinHeap();
|
|
286
|
-
const tree = new Set();
|
|
287
|
-
const join = (c) => {
|
|
288
|
-
if (tree.has(c) || !ok[c])
|
|
289
|
-
return;
|
|
290
|
-
tree.add(c);
|
|
291
|
-
seed(c, heap);
|
|
292
|
-
};
|
|
293
|
-
for (const c of seeds)
|
|
294
|
-
join(c);
|
|
295
|
-
for (;;) {
|
|
296
|
-
if (!heap.size) {
|
|
297
|
-
const next = reseed();
|
|
298
|
-
if (!next)
|
|
299
|
-
break;
|
|
300
|
-
for (const c of next)
|
|
301
|
-
join(c);
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
const s = heap.pop();
|
|
305
|
-
const du = heap.poppedKey;
|
|
306
|
-
if (seen[s] !== epoch || du > dist[s])
|
|
307
|
-
continue;
|
|
308
|
-
const c = Math.floor(s / 4);
|
|
309
|
-
if (group[c] >= 0) {
|
|
310
|
-
const cells = pathTo(s);
|
|
311
|
-
const reached = group[c];
|
|
312
|
-
group[c] = -1;
|
|
313
|
-
const rest = onJoin(cells, reached);
|
|
314
|
-
for (const cell of cells)
|
|
315
|
-
join(cell);
|
|
316
|
-
for (const cell of rest)
|
|
317
|
-
join(cell);
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
relax(s, du, heap);
|
|
321
|
-
}
|
|
322
|
-
return tree;
|
|
323
|
-
};
|
|
324
|
-
const segmentsAlong = (cells) => {
|
|
325
|
-
const floor = grids[0].ctx;
|
|
326
|
-
// Straight runs: consecutive same-grid steps with one cell offset. Compared by offset, since rounded
|
|
327
|
-
// centers on a turned grid are not exactly collinear.
|
|
328
|
-
const runs = [];
|
|
329
|
-
for (let i = 0; i + 1 < cells.length; i++) {
|
|
330
|
-
const same = gridOf[cells[i]] === gridOf[cells[i + 1]];
|
|
331
|
-
const grid = same ? gridOf[cells[i]] : -1;
|
|
332
|
-
const step = same ? cells[i + 1] - cells[i] : 0;
|
|
333
|
-
const to = worldOf(cells[i + 1]);
|
|
334
|
-
const last = runs[runs.length - 1];
|
|
335
|
-
if (last && grid >= 0 && last.grid === grid && last.step === step)
|
|
336
|
-
last.to = to;
|
|
337
|
-
else
|
|
338
|
-
runs.push({ grid, step, from: worldOf(cells[i]), to });
|
|
339
|
-
}
|
|
340
|
-
const poly = runs.length ? [runs[0].from] : [];
|
|
341
|
-
for (let r = 0; r < runs.length; r++) {
|
|
342
|
-
const run = runs[r];
|
|
343
|
-
const before = runs[r - 1];
|
|
344
|
-
const after = runs[r + 1];
|
|
345
|
-
// A grid change between two runs: lay it through the corner where the two runs' lines meet.
|
|
346
|
-
if (run.grid < 0 && before && after && before.grid >= 0 && after.grid >= 0) {
|
|
347
|
-
const met = linesMeet(before.from, [before.to[0] - before.from[0], before.to[1] - before.from[1]], after.from, [after.to[0] - after.from[0], after.to[1] - after.from[1]]);
|
|
348
|
-
// Only within a cell of the switch: near-parallel directions meet far off the walked path.
|
|
349
|
-
if (met &&
|
|
350
|
-
met.ta >= 0 &&
|
|
351
|
-
met.tb <= 1 &&
|
|
352
|
-
Math.hypot(met.at[0] - before.to[0], met.at[1] - before.to[1]) <= pitch &&
|
|
353
|
-
floor.lineFree(before.from[0], before.from[1], met.at[0], met.at[1]) &&
|
|
354
|
-
floor.lineFree(met.at[0], met.at[1], after.to[0], after.to[1])) {
|
|
355
|
-
poly[poly.length - 1] = met.at;
|
|
356
|
-
poly.push(after.to);
|
|
357
|
-
after.from = met.at;
|
|
358
|
-
r++;
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
poly.push(run.to);
|
|
363
|
-
}
|
|
364
|
-
const out = [];
|
|
365
|
-
for (let i = 0; i + 1 < poly.length; i++) {
|
|
366
|
-
const [x0, y0] = poly[i];
|
|
367
|
-
const [x1, y1] = poly[i + 1];
|
|
368
|
-
if (Math.hypot(x1 - x0, y1 - y0) >= 0.01)
|
|
369
|
-
out.push([x0, y0, x1, y1]);
|
|
370
|
-
}
|
|
371
|
-
return out;
|
|
372
|
-
};
|
|
373
|
-
return {
|
|
374
|
-
cells,
|
|
375
|
-
ok,
|
|
376
|
-
pitch,
|
|
377
|
-
route,
|
|
378
|
-
grow,
|
|
379
|
-
stepTo,
|
|
380
|
-
cellsOf,
|
|
381
|
-
cellOf,
|
|
382
|
-
cellIn,
|
|
383
|
-
frameOf: (c) => grids[gridOf[c]].frame,
|
|
384
|
-
worldOf,
|
|
385
|
-
cellsAlong,
|
|
386
|
-
segmentsAlong,
|
|
387
|
-
};
|
|
388
|
-
}
|
package/dist/lib/runs.d.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { type AisleAxis } from './axes.js';
|
|
2
|
-
import { type Blockers } from './blockers.js';
|
|
3
|
-
import type { Doorway } from './doorways.js';
|
|
4
|
-
import { type Frame } from './geom/frames.js';
|
|
5
|
-
import type { Segment, Vec2 } from './geom/types.js';
|
|
6
|
-
import type { NetworkSizes } from './network-sizes.js';
|
|
7
|
-
import type { Router } from './router.js';
|
|
8
|
-
/** The floor a path's ends and runs must keep to. */
|
|
9
|
-
export interface Placement {
|
|
10
|
-
/** The directions the layer is drawn in, the plan's first. */
|
|
11
|
-
readonly frames: readonly Frame[];
|
|
12
|
-
/** The aisle axes the stub tips define. */
|
|
13
|
-
readonly axes: readonly AisleAxis[];
|
|
14
|
-
/** The layer's doorways. */
|
|
15
|
-
readonly doors: readonly Doorway[];
|
|
16
|
-
/** Walls and solid outlines: a corridor's sides. */
|
|
17
|
-
readonly blockers: Blockers;
|
|
18
|
-
/** Whether a line may be laid: on the floor, across nothing blocked. */
|
|
19
|
-
readonly mayLay: (seg: Segment) => boolean;
|
|
20
|
-
}
|
|
21
|
-
/** One straight run of a path: consecutive cells of one grid stepping the same way. */
|
|
22
|
-
export interface Run {
|
|
23
|
-
/** The frame of the run's grid. */
|
|
24
|
-
frame: Frame;
|
|
25
|
-
/** The run lies along the frame's first axis. */
|
|
26
|
-
horiz: boolean;
|
|
27
|
-
/** Across coordinate the run was walked at: its cells' centers. */
|
|
28
|
-
walked: number;
|
|
29
|
-
/** Across coordinate the run is laid at. */
|
|
30
|
-
c: number;
|
|
31
|
-
/** Along coordinate of the first cell's center. */
|
|
32
|
-
lo: number;
|
|
33
|
-
/** Along coordinate of the last cell's center. */
|
|
34
|
-
hi: number;
|
|
35
|
-
/** Sign of the walk along. */
|
|
36
|
-
sign: number;
|
|
37
|
-
/** The cells walked. */
|
|
38
|
-
cells: number[];
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* How far across a run may be pulled onto a line: a tip stands within the clearance of its aisle's
|
|
42
|
-
* axis, and a run's cells are centered within half a pitch of what they pass.
|
|
43
|
-
* @param cfg Network sizes.
|
|
44
|
-
* @returns The distance.
|
|
45
|
-
*/
|
|
46
|
-
export declare function pullOf(cfg: NetworkSizes): number;
|
|
47
|
-
/**
|
|
48
|
-
* A point in a run's coordinates.
|
|
49
|
-
* @param run The run.
|
|
50
|
-
* @param x Plan x.
|
|
51
|
-
* @param y Plan y.
|
|
52
|
-
* @returns Along the run, and across it.
|
|
53
|
-
*/
|
|
54
|
-
export declare function runCoords(run: Run, x: number, y: number): [number, number];
|
|
55
|
-
/**
|
|
56
|
-
* The point at a run's coordinates, on the centimeter grid.
|
|
57
|
-
* @param run The run.
|
|
58
|
-
* @param along Coordinate along the run.
|
|
59
|
-
* @param across Coordinate across it.
|
|
60
|
-
* @returns The point.
|
|
61
|
-
*/
|
|
62
|
-
export declare function onRun(run: Run, along: number, across: number): Vec2;
|
|
63
|
-
/**
|
|
64
|
-
* The run's line at an across coordinate, from its first cell's center to its last's.
|
|
65
|
-
* @param run The run.
|
|
66
|
-
* @param c The across coordinate.
|
|
67
|
-
* @returns The segment.
|
|
68
|
-
*/
|
|
69
|
-
export declare function runLine(run: Run, c: number): Segment;
|
|
70
|
-
/**
|
|
71
|
-
* The unit direction the run was walked in.
|
|
72
|
-
* @param run The run.
|
|
73
|
-
* @returns The direction.
|
|
74
|
-
*/
|
|
75
|
-
export declare function runDirection(run: Run): Vec2;
|
|
76
|
-
/**
|
|
77
|
-
* The straight runs of a path: consecutive cells of one grid stepping the same way.
|
|
78
|
-
* @param router The raster router the path was walked on.
|
|
79
|
-
* @param cells The path.
|
|
80
|
-
* @returns The runs.
|
|
81
|
-
*/
|
|
82
|
-
export declare function runsOf(router: Router, cells: readonly number[]): Run[];
|
|
83
|
-
/**
|
|
84
|
-
* Lays a run where its place says: a doorway's middle, its aisle's axis, its corridor's middle,
|
|
85
|
-
* else where it was walked.
|
|
86
|
-
* @param run The run; `c` is set.
|
|
87
|
-
* @param place What the runs are laid on.
|
|
88
|
-
* @param cfg Network sizes.
|
|
89
|
-
* @param mayLay Whether a line may be laid.
|
|
90
|
-
*/
|
|
91
|
-
export declare function placeRun(run: Run, place: Placement, cfg: NetworkSizes, mayLay: (seg: Segment) => boolean): void;
|
|
92
|
-
//# sourceMappingURL=runs.d.ts.map
|