@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/blockers.js
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
// What a straight run may not cross — walls, outlines of destinations nobody walks through, doorway
|
|
2
|
-
// gaps — indexed by the cells they cover, and the rays and boxes read through the index.
|
|
3
|
-
import { rayVsSegment, ringEdges, segmentsCross } from './geom/primitives.js';
|
|
4
|
-
import { NODE_SNAP } from './graph-types.js';
|
|
5
|
-
/** {@link SegmentGrid} cell side, meters: a booth or two, so a query reads a few cells. */
|
|
6
|
-
const GRID_CELL = 4;
|
|
7
|
-
/** Padding a segment is filed with, so a hit a hair past its end or on a cell border still finds it. */
|
|
8
|
-
const GRID_PAD = 1e-3;
|
|
9
|
-
/** What a blocker segment is. */
|
|
10
|
-
export var BlockerKind;
|
|
11
|
-
(function (BlockerKind) {
|
|
12
|
-
BlockerKind[BlockerKind["Wall"] = 0] = "Wall";
|
|
13
|
-
BlockerKind[BlockerKind["Solid"] = 1] = "Solid";
|
|
14
|
-
BlockerKind[BlockerKind["Gap"] = 2] = "Gap";
|
|
15
|
-
})(BlockerKind || (BlockerKind = {}));
|
|
16
|
-
/**
|
|
17
|
-
* Blocker segments bucketed by the cells their bounds cover. It only narrows the candidates: a segment it
|
|
18
|
-
* leaves out has bounds apart from the query's, so no test could hold for it.
|
|
19
|
-
*/
|
|
20
|
-
export class SegmentGrid {
|
|
21
|
-
/** Every blocker segment, in {@link Blockers} order: walls, then outlines, then gaps. */
|
|
22
|
-
segs = [];
|
|
23
|
-
/** What each segment is. */
|
|
24
|
-
from = [];
|
|
25
|
-
/** Owning destination of a solid edge; empty for walls and gaps. */
|
|
26
|
-
owner = [];
|
|
27
|
-
cells = new Map();
|
|
28
|
-
seen;
|
|
29
|
-
stamp = 0;
|
|
30
|
-
/** Bounds of the filed cells, so a ray knows when it has left them all. */
|
|
31
|
-
c0 = Infinity;
|
|
32
|
-
c1 = -Infinity;
|
|
33
|
-
r0 = Infinity;
|
|
34
|
-
r1 = -Infinity;
|
|
35
|
-
constructor(blockers) {
|
|
36
|
-
const add = (seg, from, owner) => {
|
|
37
|
-
this.segs.push(seg);
|
|
38
|
-
this.from.push(from);
|
|
39
|
-
this.owner.push(owner);
|
|
40
|
-
};
|
|
41
|
-
for (const wall of blockers.walls)
|
|
42
|
-
add(wall, BlockerKind.Wall, '');
|
|
43
|
-
for (const poi of blockers.solid)
|
|
44
|
-
for (const edge of poi.edges)
|
|
45
|
-
add(edge, BlockerKind.Solid, poi.id);
|
|
46
|
-
for (const gap of blockers.gaps)
|
|
47
|
-
add(gap, BlockerKind.Gap, '');
|
|
48
|
-
this.seen = new Int32Array(this.segs.length);
|
|
49
|
-
// The cells the segments reach: a query looks no farther.
|
|
50
|
-
for (const seg of this.segs) {
|
|
51
|
-
this.c0 = Math.min(this.c0, Math.floor((Math.min(seg[0], seg[2]) - GRID_PAD) / GRID_CELL));
|
|
52
|
-
this.c1 = Math.max(this.c1, Math.floor((Math.max(seg[0], seg[2]) + GRID_PAD) / GRID_CELL));
|
|
53
|
-
this.r0 = Math.min(this.r0, Math.floor((Math.min(seg[1], seg[3]) - GRID_PAD) / GRID_CELL));
|
|
54
|
-
this.r1 = Math.max(this.r1, Math.floor((Math.max(seg[1], seg[3]) + GRID_PAD) / GRID_CELL));
|
|
55
|
-
}
|
|
56
|
-
this.segs.forEach((seg, i) => this.cover(Math.min(seg[0], seg[2]) - GRID_PAD, Math.min(seg[1], seg[3]) - GRID_PAD, Math.max(seg[0], seg[2]) + GRID_PAD, Math.max(seg[1], seg[3]) + GRID_PAD, (key) => {
|
|
57
|
-
const list = this.cells.get(key);
|
|
58
|
-
if (list)
|
|
59
|
-
list.push(i);
|
|
60
|
-
else
|
|
61
|
-
this.cells.set(key, [i]);
|
|
62
|
-
}));
|
|
63
|
-
}
|
|
64
|
-
cover(x0, y0, x1, y1, visit) {
|
|
65
|
-
const c0 = Math.max(this.c0, Math.floor(x0 / GRID_CELL));
|
|
66
|
-
const c1 = Math.min(this.c1, Math.floor(x1 / GRID_CELL));
|
|
67
|
-
const r0 = Math.max(this.r0, Math.floor(y0 / GRID_CELL));
|
|
68
|
-
const r1 = Math.min(this.r1, Math.floor(y1 / GRID_CELL));
|
|
69
|
-
for (let c = c0; c <= c1; c++)
|
|
70
|
-
for (let r = r0; r <= r1; r++)
|
|
71
|
-
visit(c * 1_000_003 + r);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Walk the cells a ray passes through, nearest first, handing each segment once.
|
|
75
|
-
* @param ox Ray origin x.
|
|
76
|
-
* @param oy Ray origin y.
|
|
77
|
-
* @param nx Ray direction x.
|
|
78
|
-
* @param ny Ray direction y.
|
|
79
|
-
* @param from Ray parameter to start at.
|
|
80
|
-
* @param visit Gets a cell's new segments and the parameter where the ray leaves it; true stops.
|
|
81
|
-
*/
|
|
82
|
-
alongRay(ox, oy, nx, ny, from, visit) {
|
|
83
|
-
const sx = ox + nx * from;
|
|
84
|
-
const sy = oy + ny * from;
|
|
85
|
-
let c = Math.floor(sx / GRID_CELL);
|
|
86
|
-
let r = Math.floor(sy / GRID_CELL);
|
|
87
|
-
const stepC = nx > 0 ? 1 : nx < 0 ? -1 : 0;
|
|
88
|
-
const stepR = ny > 0 ? 1 : ny < 0 ? -1 : 0;
|
|
89
|
-
// Ray parameter at the next column/row border, and its growth per cell.
|
|
90
|
-
const border = (p, d, cell) => d > 0 ? ((cell + 1) * GRID_CELL - p) / d : d < 0 ? (cell * GRID_CELL - p) / d : Infinity;
|
|
91
|
-
let nextC = from + border(sx, nx, c);
|
|
92
|
-
let nextR = from + border(sy, ny, r);
|
|
93
|
-
const perC = nx ? GRID_CELL / Math.abs(nx) : Infinity;
|
|
94
|
-
const perR = ny ? GRID_CELL / Math.abs(ny) : Infinity;
|
|
95
|
-
this.stamp++;
|
|
96
|
-
// A ray going nowhere meets only what its start cell holds.
|
|
97
|
-
const still = !stepC && !stepR;
|
|
98
|
-
for (;;) {
|
|
99
|
-
const fresh = [];
|
|
100
|
-
for (const i of this.cells.get(c * 1_000_003 + r) ?? []) {
|
|
101
|
-
if (this.seen[i] === this.stamp)
|
|
102
|
-
continue;
|
|
103
|
-
this.seen[i] = this.stamp;
|
|
104
|
-
fresh.push(i);
|
|
105
|
-
}
|
|
106
|
-
if (visit(fresh, Math.min(nextC, nextR)) || still)
|
|
107
|
-
return;
|
|
108
|
-
if (nextC < nextR) {
|
|
109
|
-
c += stepC;
|
|
110
|
-
nextC += perC;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
r += stepR;
|
|
114
|
-
nextR += perR;
|
|
115
|
-
}
|
|
116
|
-
// Past the last filed cell the ray meets nothing more.
|
|
117
|
-
if ((stepC > 0 && c > this.c1) || (stepC < 0 && c < this.c0))
|
|
118
|
-
return;
|
|
119
|
-
if ((stepR > 0 && r > this.r1) || (stepR < 0 && r < this.r0))
|
|
120
|
-
return;
|
|
121
|
-
if (!stepC && (c < this.c0 || c > this.c1))
|
|
122
|
-
return;
|
|
123
|
-
if (!stepR && (r < this.r0 || r > this.r1))
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Segments whose bounds meet a box, each once, in {@link Blockers} order.
|
|
129
|
-
* @param x0 Box min x.
|
|
130
|
-
* @param y0 Box min y.
|
|
131
|
-
* @param x1 Box max x.
|
|
132
|
-
* @param y1 Box max y.
|
|
133
|
-
* @returns Their positions in {@link segs}.
|
|
134
|
-
*/
|
|
135
|
-
near(x0, y0, x1, y1) {
|
|
136
|
-
const found = [];
|
|
137
|
-
this.stamp++;
|
|
138
|
-
this.cover(x0, y0, x1, y1, (key) => {
|
|
139
|
-
for (const i of this.cells.get(key) ?? []) {
|
|
140
|
-
if (this.seen[i] === this.stamp)
|
|
141
|
-
continue;
|
|
142
|
-
this.seen[i] = this.stamp;
|
|
143
|
-
const seg = this.segs[i];
|
|
144
|
-
if (Math.max(seg[0], seg[2]) >= x0 &&
|
|
145
|
-
Math.min(seg[0], seg[2]) <= x1 &&
|
|
146
|
-
Math.max(seg[1], seg[3]) >= y0 &&
|
|
147
|
-
Math.min(seg[1], seg[3]) <= y1)
|
|
148
|
-
found.push(i);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
return found.sort((a, b) => a - b);
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Whether a segment crosses any blocker of one kind (exact `segmentsCross` on the candidates).
|
|
155
|
-
* @param seg The segment.
|
|
156
|
-
* @param from Blocker kind.
|
|
157
|
-
* @param except Destination whose own edges do not count.
|
|
158
|
-
* @returns True when one crosses it.
|
|
159
|
-
*/
|
|
160
|
-
crosses(seg, from, except) {
|
|
161
|
-
return this.crossing(seg, from, except).length > 0;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* The blockers of one kind a segment crosses (exact `segmentsCross` on the candidates).
|
|
165
|
-
* @param seg The segment.
|
|
166
|
-
* @param from Blocker kind.
|
|
167
|
-
* @param except Destination whose own edges do not count.
|
|
168
|
-
* @returns The blockers crossed.
|
|
169
|
-
*/
|
|
170
|
-
crossing(seg, from, except) {
|
|
171
|
-
return this.near(Math.min(seg[0], seg[2]), Math.min(seg[1], seg[3]), Math.max(seg[0], seg[2]), Math.max(seg[1], seg[3]))
|
|
172
|
-
.filter((i) => this.from[i] === from &&
|
|
173
|
-
(except === undefined || this.owner[i] !== except) &&
|
|
174
|
-
segmentsCross(seg, this.segs[i]))
|
|
175
|
-
.map((i) => this.segs[i]);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Walls and outlines whose bounds meet a box.
|
|
180
|
-
* @param blockers The blockers.
|
|
181
|
-
* @param box The box.
|
|
182
|
-
* @returns Each segment with its owning destination; no owner for a wall.
|
|
183
|
-
*/
|
|
184
|
-
export function blockersNear(blockers, box) {
|
|
185
|
-
const grid = blockerGrid(blockers);
|
|
186
|
-
const [x0, y0, x1, y1] = box;
|
|
187
|
-
return grid
|
|
188
|
-
.near(x0, y0, x1, y1)
|
|
189
|
-
.filter((i) => grid.from[i] !== BlockerKind.Gap)
|
|
190
|
-
.map((i) => grid.from[i] === BlockerKind.Solid
|
|
191
|
-
? { seg: grid.segs[i], owner: grid.owner[i] }
|
|
192
|
-
: { seg: grid.segs[i] });
|
|
193
|
-
}
|
|
194
|
-
/** One grid per blockers object, built lazily. */
|
|
195
|
-
const grids = new WeakMap();
|
|
196
|
-
/**
|
|
197
|
-
* The index of a blockers object, built once and kept with it.
|
|
198
|
-
* @param blockers The blockers.
|
|
199
|
-
* @returns Their index.
|
|
200
|
-
*/
|
|
201
|
-
export function blockerGrid(blockers) {
|
|
202
|
-
let grid = grids.get(blockers);
|
|
203
|
-
if (!grid) {
|
|
204
|
-
grid = new SegmentGrid(blockers);
|
|
205
|
-
grids.set(blockers, grid);
|
|
206
|
-
}
|
|
207
|
-
return grid;
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Whether a segment crosses a wall, a closed doorway side or the outline of a destination nobody
|
|
211
|
-
* walks through: the rule every network line keeps.
|
|
212
|
-
* @param blockers The blockers.
|
|
213
|
-
* @param seg The segment.
|
|
214
|
-
* @returns True when it crosses one.
|
|
215
|
-
*/
|
|
216
|
-
export function crossesBlocker(blockers, seg) {
|
|
217
|
-
const grid = blockerGrid(blockers);
|
|
218
|
-
return grid.crosses(seg, BlockerKind.Wall) || grid.crosses(seg, BlockerKind.Solid);
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* What a run out of a destination may not cross, read once for the layer.
|
|
222
|
-
* @param destinations Every destination on the layer.
|
|
223
|
-
* @param walls The layer's wall segments.
|
|
224
|
-
* @param doors The layer's doorways.
|
|
225
|
-
* @param drawn The rest of each destination's drawing, by the destination's id.
|
|
226
|
-
* @param walled Destinations entered through doorways: the walls they line stand in for them.
|
|
227
|
-
* @param passes Wall spans an entrance's dock may cross, by the entrance's id.
|
|
228
|
-
* @returns The blockers.
|
|
229
|
-
*/
|
|
230
|
-
export function blockersOf(destinations, walls, doors, drawn = [], walled = new Set(), passes) {
|
|
231
|
-
return {
|
|
232
|
-
walls,
|
|
233
|
-
solid: [
|
|
234
|
-
...destinations
|
|
235
|
-
.filter((d) => !d.crossable && d.polygon.length >= 3)
|
|
236
|
-
.map((d) => ({ id: d.id, edges: ringEdges(d.polygon) })),
|
|
237
|
-
...drawn.map((block) => ({ id: block.id, edges: ringEdges(block.ring) })),
|
|
238
|
-
],
|
|
239
|
-
gaps: doors.map((door) => door.gap),
|
|
240
|
-
walled,
|
|
241
|
-
...(passes && { passes }),
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* How far a ray runs before it meets a blocker, by exact intersection, and what it met.
|
|
246
|
-
* @param ox Ray origin x.
|
|
247
|
-
* @param oy Ray origin y.
|
|
248
|
-
* @param nx Ray direction x.
|
|
249
|
-
* @param ny Ray direction y.
|
|
250
|
-
* @param ownId Destination the ray leaves.
|
|
251
|
-
* @param own `'skip'` ignores its outline; `'ahead'` counts only the outline ahead of the start.
|
|
252
|
-
* @param withGaps Whether a doorway gap stops the ray.
|
|
253
|
-
* @param blockers What the ray may meet.
|
|
254
|
-
* @returns The distance, or `Infinity` when the ray meets nothing.
|
|
255
|
-
*/
|
|
256
|
-
export function freeRun(ox, oy, nx, ny, ownId, own, withGaps, blockers) {
|
|
257
|
-
let best = Infinity;
|
|
258
|
-
const hit = [0, 0];
|
|
259
|
-
// `from`: where hits start to count. A wall along the start face closes the ray; the own outline there
|
|
260
|
-
// is the face itself and does not.
|
|
261
|
-
const test = (seg, from) => {
|
|
262
|
-
if (!rayVsSegment(hit, ox, oy, nx, ny, seg[0], seg[1], seg[2], seg[3]))
|
|
263
|
-
return;
|
|
264
|
-
const [t, u] = hit;
|
|
265
|
-
if (u < -1e-9 || u > 1 + 1e-9 || t <= from)
|
|
266
|
-
return;
|
|
267
|
-
if (t < best)
|
|
268
|
-
best = Math.max(0, t);
|
|
269
|
-
};
|
|
270
|
-
const grid = blockerGrid(blockers);
|
|
271
|
-
// Cell by cell outward: a hit's segment is filed in the hit's cell, so once the best hit is nearer than
|
|
272
|
-
// the cell being left, no later cell holds a nearer one.
|
|
273
|
-
grid.alongRay(ox, oy, nx, ny, -2 * NODE_SNAP, (ids, leaves) => {
|
|
274
|
-
for (const i of ids) {
|
|
275
|
-
const seg = grid.segs[i];
|
|
276
|
-
const owner = grid.owner[i];
|
|
277
|
-
if (grid.from[i] === BlockerKind.Wall)
|
|
278
|
-
test(seg, -NODE_SNAP);
|
|
279
|
-
else if (grid.from[i] === BlockerKind.Gap) {
|
|
280
|
-
if (withGaps)
|
|
281
|
-
test(seg, NODE_SNAP);
|
|
282
|
-
}
|
|
283
|
-
else if (owner !== ownId || own !== 'skip')
|
|
284
|
-
test(seg, owner === ownId ? NODE_SNAP : -NODE_SNAP);
|
|
285
|
-
}
|
|
286
|
-
return best < leaves - GRID_PAD;
|
|
287
|
-
});
|
|
288
|
-
return best;
|
|
289
|
-
}
|
package/dist/lib/cell-array.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/** The engine refused the memory a floor's raster needs: the floor is too large for this device. */
|
|
2
|
-
export declare class CellsRefusedError extends Error {
|
|
3
|
-
constructor(length: number);
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* A raster-sized typed array. An engine refuses a valid length only for want of memory, whatever its
|
|
7
|
-
* message says, so any refusal of one throws {@link CellsRefusedError}; an invalid length is a bug and
|
|
8
|
-
* its error passes through.
|
|
9
|
-
* @param Ctor The typed array class.
|
|
10
|
-
* @param length Its length, in cells.
|
|
11
|
-
* @returns The zeroed array.
|
|
12
|
-
*/
|
|
13
|
-
export declare function cellArray<T>(Ctor: new (length: number) => T, length: number): T;
|
|
14
|
-
//# sourceMappingURL=cell-array.d.ts.map
|
package/dist/lib/cell-array.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/** The engine refused the memory a floor's raster needs: the floor is too large for this device. */
|
|
2
|
-
export class CellsRefusedError extends Error {
|
|
3
|
-
constructor(length) {
|
|
4
|
-
super(`the engine refused a raster of ${length} cells`);
|
|
5
|
-
this.name = 'CellsRefusedError';
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* A raster-sized typed array. An engine refuses a valid length only for want of memory, whatever its
|
|
10
|
-
* message says, so any refusal of one throws {@link CellsRefusedError}; an invalid length is a bug and
|
|
11
|
-
* its error passes through.
|
|
12
|
-
* @param Ctor The typed array class.
|
|
13
|
-
* @param length Its length, in cells.
|
|
14
|
-
* @returns The zeroed array.
|
|
15
|
-
*/
|
|
16
|
-
export function cellArray(Ctor, length) {
|
|
17
|
-
try {
|
|
18
|
-
return new Ctor(length);
|
|
19
|
-
}
|
|
20
|
-
catch (error) {
|
|
21
|
-
if (Number.isSafeInteger(length) && length >= 0)
|
|
22
|
-
throw new CellsRefusedError(length);
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
25
|
-
}
|
package/dist/lib/centering.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How far off the middle of its corridor each cell stands: 0 on the middle row, rising to 1 at the
|
|
3
|
-
* walls — `1 - d / dmax`, where `d` is the cell's clearance and `dmax` the clearance of the ridge the
|
|
4
|
-
* cell climbs to, which is half the corridor's width there. A corridor an even number of cells wide
|
|
5
|
-
* has two middle rows; the one with the greater index is charged half the step to the next row, so
|
|
6
|
-
* the minimum is one row.
|
|
7
|
-
* @param width Grid width in cells.
|
|
8
|
-
* @param height Grid height in cells.
|
|
9
|
-
* @param clearance Meters from each cell to the nearest blocker, row-major.
|
|
10
|
-
* @param ok 1 for a walkable cell.
|
|
11
|
-
* @returns The offset per cell; 0 for a cell that is not walkable.
|
|
12
|
-
*/
|
|
13
|
-
export declare function offCenter(width: number, height: number, clearance: Float32Array, ok: Uint8Array): Float32Array;
|
|
14
|
-
//# sourceMappingURL=centering.d.ts.map
|
package/dist/lib/centering.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
// Centering: how far off the middle of its corridor each router cell stands, read off the clearance
|
|
2
|
-
// field alone. The middle is one row of cells, so two paths along one corridor lie on one line.
|
|
3
|
-
/** Clearances are compared by the millimeter: chamfer sums differ by float noise only below it. */
|
|
4
|
-
const QUANTUM = 1000;
|
|
5
|
-
/**
|
|
6
|
-
* How far off the middle of its corridor each cell stands: 0 on the middle row, rising to 1 at the
|
|
7
|
-
* walls — `1 - d / dmax`, where `d` is the cell's clearance and `dmax` the clearance of the ridge the
|
|
8
|
-
* cell climbs to, which is half the corridor's width there. A corridor an even number of cells wide
|
|
9
|
-
* has two middle rows; the one with the greater index is charged half the step to the next row, so
|
|
10
|
-
* the minimum is one row.
|
|
11
|
-
* @param width Grid width in cells.
|
|
12
|
-
* @param height Grid height in cells.
|
|
13
|
-
* @param clearance Meters from each cell to the nearest blocker, row-major.
|
|
14
|
-
* @param ok 1 for a walkable cell.
|
|
15
|
-
* @returns The offset per cell; 0 for a cell that is not walkable.
|
|
16
|
-
*/
|
|
17
|
-
export function offCenter(width, height, clearance, ok) {
|
|
18
|
-
const cells = width * height;
|
|
19
|
-
const level = new Int32Array(cells);
|
|
20
|
-
let top = 0;
|
|
21
|
-
for (let cell = 0; cell < cells; cell++) {
|
|
22
|
-
if (!ok[cell])
|
|
23
|
-
continue;
|
|
24
|
-
level[cell] = Math.round(clearance[cell] * QUANTUM);
|
|
25
|
-
top = Math.max(top, level[cell]);
|
|
26
|
-
}
|
|
27
|
-
// Cells from the highest clearance down, index order among equals: a counting sort.
|
|
28
|
-
const start = new Int32Array(top + 2);
|
|
29
|
-
for (let cell = 0; cell < cells; cell++)
|
|
30
|
-
if (ok[cell])
|
|
31
|
-
start[top - level[cell] + 1]++;
|
|
32
|
-
for (let i = 1; i < start.length; i++)
|
|
33
|
-
start[i] += start[i - 1];
|
|
34
|
-
const order = new Int32Array(start[top + 1]);
|
|
35
|
-
for (let cell = 0; cell < cells; cell++)
|
|
36
|
-
if (ok[cell])
|
|
37
|
-
order[start[top - level[cell]]++] = cell;
|
|
38
|
-
// Each cell climbs to its highest neighbor, and takes the ridge that one reached.
|
|
39
|
-
const ridge = new Int32Array(cells);
|
|
40
|
-
for (const cell of order) {
|
|
41
|
-
const x = cell % width;
|
|
42
|
-
const y = (cell - x) / width;
|
|
43
|
-
let up = -1;
|
|
44
|
-
for (let dy = -1; dy <= 1; dy++)
|
|
45
|
-
for (let dx = -1; dx <= 1; dx++) {
|
|
46
|
-
const nx = x + dx;
|
|
47
|
-
const ny = y + dy;
|
|
48
|
-
if ((!dx && !dy) || nx < 0 || ny < 0 || nx >= width || ny >= height)
|
|
49
|
-
continue;
|
|
50
|
-
const near = ny * width + nx;
|
|
51
|
-
if (ok[near] && level[near] > level[cell] && (up < 0 || level[near] > level[up]))
|
|
52
|
-
up = near;
|
|
53
|
-
}
|
|
54
|
-
ridge[cell] = up < 0 ? level[cell] : ridge[up];
|
|
55
|
-
}
|
|
56
|
-
const off = new Float32Array(cells);
|
|
57
|
-
// Whether the cell `step` away from `cell`, at `at` along its row or column, stands lower or is no floor.
|
|
58
|
-
const lower = (cell, at, limit, step) => at < 0 || at >= limit || !ok[cell + step] || level[cell + step] < level[cell];
|
|
59
|
-
/**
|
|
60
|
-
* What the second of two equal rows across a corridor is charged: half the step to the next row.
|
|
61
|
-
* @param cell The cell.
|
|
62
|
-
* @param at Its place along the axis across the corridor.
|
|
63
|
-
* @param limit The grid's size along that axis.
|
|
64
|
-
* @param step The index step along that axis.
|
|
65
|
-
* @returns The charge, 0 when the cell is not such a row's.
|
|
66
|
-
*/
|
|
67
|
-
const secondRow = (cell, at, limit, step) => {
|
|
68
|
-
const twin = cell - step;
|
|
69
|
-
if (at < 1 || !ok[twin] || level[twin] !== level[cell])
|
|
70
|
-
return 0;
|
|
71
|
-
if (!lower(cell, at + 1, limit, step) || !lower(twin, at - 2, limit, -step))
|
|
72
|
-
return 0;
|
|
73
|
-
const next = at + 1 < limit && ok[cell + step] ? level[cell + step] : 0;
|
|
74
|
-
return (0.5 * (level[cell] - next)) / ridge[cell];
|
|
75
|
-
};
|
|
76
|
-
for (const cell of order) {
|
|
77
|
-
if (!ridge[cell])
|
|
78
|
-
continue;
|
|
79
|
-
const x = cell % width;
|
|
80
|
-
const y = (cell - x) / width;
|
|
81
|
-
off[cell] =
|
|
82
|
-
1 -
|
|
83
|
-
level[cell] / ridge[cell] +
|
|
84
|
-
secondRow(cell, x, width, 1) +
|
|
85
|
-
secondRow(cell, y, height, width);
|
|
86
|
-
}
|
|
87
|
-
return off;
|
|
88
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { NormalizeFacts } from './diagnostics.js';
|
|
2
|
-
import type { BooleanOps } from './geom/boolean-ops.js';
|
|
3
|
-
import type { RouteNetwork } from './graph-types.js';
|
|
4
|
-
import type { SourceDestination, WayfindingLayerSource } from './types.js';
|
|
5
|
-
import { type WalkableArea } from './walkable.js';
|
|
6
|
-
/** One layer's stage artifacts. */
|
|
7
|
-
interface CompiledLayer {
|
|
8
|
-
/** Globally unique layer id. */
|
|
9
|
-
readonly layer: string;
|
|
10
|
-
/** The destinations as the stages saw them, rings normalized and carved. */
|
|
11
|
-
readonly destinations: SourceDestination[];
|
|
12
|
-
/** Walkable area. */
|
|
13
|
-
readonly walkable: WalkableArea;
|
|
14
|
-
/** Route network. */
|
|
15
|
-
readonly network: RouteNetwork;
|
|
16
|
-
/** What normalization did to the drawing, for the diagnostics. */
|
|
17
|
-
readonly facts: NormalizeFacts;
|
|
18
|
-
}
|
|
19
|
-
/** Options of one layer's compile. */
|
|
20
|
-
interface CompileLayerOptions {
|
|
21
|
-
/** A walkable area already built for this layer; the stage is skipped. */
|
|
22
|
-
readonly walkable?: WalkableArea;
|
|
23
|
-
/** Called as each stage finishes; `cached` when it was handed its artifact. */
|
|
24
|
-
readonly onStage?: (stage: 'walkable' | 'network', cached: boolean) => void;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* One layer's pipeline: walkable area, then route network.
|
|
28
|
-
* @param source One layer's walls and destinations.
|
|
29
|
-
* @param ops Polygon boolean backend.
|
|
30
|
-
* @param options A ready walkable area and the stage callback.
|
|
31
|
-
* @returns The layer's walkable area and route network.
|
|
32
|
-
*/
|
|
33
|
-
export declare function compileLayer(source: WayfindingLayerSource, ops: BooleanOps, options?: CompileLayerOptions): CompiledLayer;
|
|
34
|
-
/**
|
|
35
|
-
* Destinations sorted by id, then outline, so input order does not change the network.
|
|
36
|
-
* @param destinations The destinations as given.
|
|
37
|
-
* @returns A sorted copy.
|
|
38
|
-
*/
|
|
39
|
-
export declare function inCanonicalOrder(destinations: readonly SourceDestination[]): SourceDestination[];
|
|
40
|
-
export {};
|
|
41
|
-
//# sourceMappingURL=compile-layer.d.ts.map
|