@expofp/wayfinding-compiler 0.0.0-experimental.3b0db16 → 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.
Files changed (100) hide show
  1. package/README.md +2 -445
  2. package/package.json +3 -34
  3. package/dist/index.d.ts +0 -14
  4. package/dist/index.js +0 -3
  5. package/dist/lib/attach.d.ts +0 -43
  6. package/dist/lib/attach.js +0 -199
  7. package/dist/lib/axes.d.ts +0 -76
  8. package/dist/lib/axes.js +0 -103
  9. package/dist/lib/blockers.d.ts +0 -134
  10. package/dist/lib/blockers.js +0 -289
  11. package/dist/lib/cell-array.d.ts +0 -14
  12. package/dist/lib/cell-array.js +0 -25
  13. package/dist/lib/compile-layer.d.ts +0 -41
  14. package/dist/lib/compile-layer.js +0 -241
  15. package/dist/lib/compile-wayfinding.d.ts +0 -90
  16. package/dist/lib/compile-wayfinding.js +0 -203
  17. package/dist/lib/connect.d.ts +0 -35
  18. package/dist/lib/connect.js +0 -206
  19. package/dist/lib/diagnostics.d.ts +0 -190
  20. package/dist/lib/diagnostics.js +0 -634
  21. package/dist/lib/doorways.d.ts +0 -78
  22. package/dist/lib/doorways.js +0 -331
  23. package/dist/lib/emit-network.d.ts +0 -47
  24. package/dist/lib/emit-network.js +0 -105
  25. package/dist/lib/emit-v1.d.ts +0 -31
  26. package/dist/lib/emit-v1.js +0 -56
  27. package/dist/lib/entries.d.ts +0 -123
  28. package/dist/lib/entries.js +0 -448
  29. package/dist/lib/floor-grids.d.ts +0 -48
  30. package/dist/lib/floor-grids.js +0 -185
  31. package/dist/lib/framing.d.ts +0 -20
  32. package/dist/lib/framing.js +0 -187
  33. package/dist/lib/geom/boolean-ops.d.ts +0 -21
  34. package/dist/lib/geom/boolean-ops.js +0 -1
  35. package/dist/lib/geom/clipper2-ops.d.ts +0 -7
  36. package/dist/lib/geom/clipper2-ops.js +0 -50
  37. package/dist/lib/geom/footprint.d.ts +0 -26
  38. package/dist/lib/geom/footprint.js +0 -203
  39. package/dist/lib/geom/frames.d.ts +0 -116
  40. package/dist/lib/geom/frames.js +0 -233
  41. package/dist/lib/geom/mesh-outline.d.ts +0 -13
  42. package/dist/lib/geom/mesh-outline.js +0 -90
  43. package/dist/lib/geom/normalize.d.ts +0 -28
  44. package/dist/lib/geom/normalize.js +0 -118
  45. package/dist/lib/geom/point-key.d.ts +0 -16
  46. package/dist/lib/geom/point-key.js +0 -15
  47. package/dist/lib/geom/primitives.d.ts +0 -105
  48. package/dist/lib/geom/primitives.js +0 -184
  49. package/dist/lib/geom/split-crossings.d.ts +0 -14
  50. package/dist/lib/geom/split-crossings.js +0 -171
  51. package/dist/lib/geom/types.d.ts +0 -9
  52. package/dist/lib/geom/types.js +0 -1
  53. package/dist/lib/geom/walls.d.ts +0 -31
  54. package/dist/lib/geom/walls.js +0 -71
  55. package/dist/lib/graph-invariants.d.ts +0 -49
  56. package/dist/lib/graph-invariants.js +0 -129
  57. package/dist/lib/graph-types.d.ts +0 -143
  58. package/dist/lib/graph-types.js +0 -7
  59. package/dist/lib/mask.d.ts +0 -54
  60. package/dist/lib/mask.js +0 -210
  61. package/dist/lib/min-heap.d.ts +0 -24
  62. package/dist/lib/min-heap.js +0 -73
  63. package/dist/lib/network-build.d.ts +0 -21
  64. package/dist/lib/network-build.js +0 -4
  65. package/dist/lib/network-graph.d.ts +0 -80
  66. package/dist/lib/network-graph.js +0 -467
  67. package/dist/lib/network-sizes.d.ts +0 -29
  68. package/dist/lib/network-sizes.js +0 -22
  69. package/dist/lib/network-store.d.ts +0 -173
  70. package/dist/lib/network-store.js +0 -430
  71. package/dist/lib/openings.d.ts +0 -54
  72. package/dist/lib/openings.js +0 -387
  73. package/dist/lib/place-path.d.ts +0 -47
  74. package/dist/lib/place-path.js +0 -346
  75. package/dist/lib/post-passes.d.ts +0 -31
  76. package/dist/lib/post-passes.js +0 -305
  77. package/dist/lib/reachability.d.ts +0 -58
  78. package/dist/lib/reachability.js +0 -220
  79. package/dist/lib/report.d.ts +0 -49
  80. package/dist/lib/report.js +0 -374
  81. package/dist/lib/router.d.ts +0 -111
  82. package/dist/lib/router.js +0 -388
  83. package/dist/lib/runs.d.ts +0 -92
  84. package/dist/lib/runs.js +0 -232
  85. package/dist/lib/scale.d.ts +0 -58
  86. package/dist/lib/scale.js +0 -185
  87. package/dist/lib/steiner-network.d.ts +0 -19
  88. package/dist/lib/steiner-network.js +0 -183
  89. package/dist/lib/strip.d.ts +0 -43
  90. package/dist/lib/strip.js +0 -200
  91. package/dist/lib/stubs.d.ts +0 -84
  92. package/dist/lib/stubs.js +0 -316
  93. package/dist/lib/transitions.d.ts +0 -72
  94. package/dist/lib/transitions.js +0 -191
  95. package/dist/lib/types.d.ts +0 -126
  96. package/dist/lib/types.js +0 -1
  97. package/dist/lib/validate-source.d.ts +0 -41
  98. package/dist/lib/validate-source.js +0 -133
  99. package/dist/lib/walkable.d.ts +0 -104
  100. package/dist/lib/walkable.js +0 -140
@@ -1,374 +0,0 @@
1
- import { poiKey } from './diagnostics.js';
2
- import { boundsOf } from './geom/primitives.js';
3
- import { ENTRANCE_REACH } from './openings.js';
4
- /** How many names a message spells out before it counts the rest. */
5
- const NAMES_SHOWN = 8;
6
- /** Why a floor has no floor, in words. */
7
- const FLOOR_CAUSES = {
8
- 'layer-no-walls': {
9
- cause: 'no-walls',
10
- text: 'the floor has no walls, so there is nothing to build routes inside',
11
- },
12
- 'layer-no-outer-contour': {
13
- cause: 'outline-open',
14
- text: 'the outer walls do not close into a contour. Check the outer walls of this floor',
15
- },
16
- 'floor-carved-away': {
17
- cause: 'carved-away',
18
- text: 'the walls and POI drawn on it cover it whole',
19
- },
20
- 'floor-too-large': {
21
- cause: 'too-large',
22
- text: "it spans more than routes are built over. Check the plan's units, and any wall or POI drawn far from the hall",
23
- },
24
- };
25
- /** Why a POI is not connected, in words — for one POI or for many. */
26
- const POI_CAUSES = {
27
- 'coordinate-not-finite': (one) => `${they(one)} ${one ? 'has' : 'have'} a coordinate that is not a number`,
28
- 'footprint-empty': (one) => `${they(one)} ${one ? 'has' : 'have'} no outline the plan can read`,
29
- 'dock-empty': () => 'the rectangle routes arrive at has no area',
30
- 'outside-building': (one) => `${they(one)} ${one ? 'stands' : 'stand'} outside the building outline; routes are built inside it only`,
31
- 'entrance-far-from-walls': (one) => `${they(one)} ${one ? 'stands' : 'stand'} more than ${ENTRANCE_REACH} m from the nearest wall; an entrance outside the building is connected only within ${ENTRANCE_REACH} m of a wall`,
32
- 'no-floor-behind-wall': (one) => `no wall near ${one ? 'it' : 'them'} opens onto floor; check that the building outline closes and that nothing stands right behind the wall`,
33
- 'no-floor-in-front': (one) => `there is no floor to stand on in front of ${one ? 'it' : 'them'}`,
34
- 'no-way-in': (one) => `${they(one)} ${one ? 'has' : 'have'} no open side and no doorway`,
35
- 'approach-blocked': () => 'a wall or another POI stands right in front of every way in',
36
- 'cut-off': (one) => `the floor in front of ${one ? 'it' : 'them'} is a pocket no route reaches`,
37
- 'lost-while-tidying': (one) => `${they(one)} ${one ? 'was' : 'were'} attached, then lost while the routes were tidied — reason unknown`,
38
- unknown: () => 'reason unknown',
39
- };
40
- /**
41
- * The pronoun for the POI a message is about.
42
- * @param one True for a single POI.
43
- * @returns `it` or `they`.
44
- */
45
- function they(one) {
46
- return one ? 'it' : 'they';
47
- }
48
- /** The network stage's reason, as the report's cause. */
49
- const REASON_CAUSE = {
50
- 'no-floor': 'no-floor-in-front',
51
- 'no-way-in': 'no-way-in',
52
- 'way-in-blocked': 'approach-blocked',
53
- 'cut-off': 'cut-off',
54
- detached: 'lost-while-tidying',
55
- };
56
- /** The order problems are listed in: whole-plan first, then by what a designer fixes first. */
57
- const KIND_ORDER = [
58
- 'plan-invalid',
59
- 'nothing-to-build',
60
- 'floor-not-built',
61
- 'poi-not-connected',
62
- 'network-split',
63
- 'floors-not-connected',
64
- ];
65
- /**
66
- * A floor by the name the plan gave it.
67
- * @param layer The layer id.
68
- * @param start True at the start of a sentence.
69
- * @returns `Floor "BG"`, or `the floor` for the one unnamed floor.
70
- */
71
- function floorName(layer, start = true) {
72
- const word = start ? 'Floor' : 'floor';
73
- if (layer === '')
74
- return start ? 'The floor' : 'the floor';
75
- return `${word} "${layer}"`;
76
- }
77
- /**
78
- * Names as a sentence tail: the first few in full, the rest counted.
79
- * @param refs The POI.
80
- * @returns `A, B and 3 more`.
81
- */
82
- function names(refs) {
83
- const shown = refs.slice(0, NAMES_SHOWN).map((ref) => (ref.id === '' ? 'unnamed POI' : ref.id));
84
- const rest = refs.length - shown.length;
85
- if (rest > 0)
86
- return `${shown.join(', ')} and ${rest} more`;
87
- return shown.join(', ');
88
- }
89
- /**
90
- * Fold the compile's facts into what a designer reads: every problem is a diagnostic or a binding, grouped.
91
- * @param diagnostics Every fact of the compile.
92
- * @param reachability What the emitted graph connects.
93
- * @param source The plan in plan units, for the outlines a problem points at.
94
- * @returns The report.
95
- */
96
- export function buildReport(diagnostics, reachability, source) {
97
- const problems = [];
98
- const has = (code) => diagnostics.filter((d) => d.code === code);
99
- const outline = (ref) => {
100
- const destination = source.layers.find((l) => l.layer === ref.layer)?.destinations[ref.index];
101
- const ring = destination?.dock ?? destination?.polygon ?? [];
102
- // A ring with a NaN vertex would put NaN bounds into serializable data.
103
- if (!ring.length || !ring.every(([x, y]) => Number.isFinite(x) && Number.isFinite(y)))
104
- return [];
105
- const [x0, y0, x1, y1] = boundsOf(ring);
106
- return [{ type: 'bounds', layer: ref.layer, box: [x0, y0, x1, y1] }];
107
- };
108
- // The plan cannot be read at all: an input error that names no layer poisons the whole of it.
109
- for (const d of diagnostics.filter((f) => f.stage === 'input' && f.severity === 'error' && f.layer === undefined)) {
110
- const messages = {
111
- 'units-per-meter-invalid': `The plan's units per meter is ${String(source.unitsPerMeter)}; it must be a positive number. Check the plan's units and map anchors.`,
112
- };
113
- problems.push({
114
- kind: 'plan-invalid',
115
- cause: d.code,
116
- message: messages[d.code] ?? 'A floor has no id; the plan cannot be built.',
117
- poi: [],
118
- highlight: [],
119
- });
120
- }
121
- const empty = source.layers.length === 0 ||
122
- source.layers.every((l) => l.walls.length === 0 && l.destinations.length === 0);
123
- if (!problems.length && empty)
124
- problems.push({
125
- kind: 'nothing-to-build',
126
- cause: source.layers.length === 0 ? 'no-floors' : 'nothing-drawn',
127
- message: source.layers.length === 0
128
- ? 'Nothing to build: the plan has no floors.'
129
- : 'Nothing to build: the plan has no walls and no POI.',
130
- poi: [],
131
- highlight: [],
132
- });
133
- // An unreadable or empty plan reports only that; everything after would repeat it.
134
- if (problems.length)
135
- return notBuilt(problems, source.layers.reduce((n, layer) => n + layer.destinations.length, 0));
136
- // A floor that got no floor: one problem for the floor, none for each POI standing on it.
137
- const unbuilt = new Set();
138
- // A floor whose walls cannot be read as numbers is skipped whole; the rest of the plan compiles.
139
- for (const d of diagnostics.filter((f) => f.stage === 'input' && f.severity === 'error' && f.layer !== undefined)) {
140
- const layer = d.layer ?? '';
141
- const messages = {
142
- 'wall-coordinate-not-finite': `${floorName(layer)}: a wall has a coordinate that is not a number; the floor is not built.`,
143
- };
144
- unbuilt.add(layer);
145
- problems.push({
146
- kind: 'plan-invalid',
147
- layer,
148
- cause: d.code,
149
- message: messages[d.code] ?? `${floorName(layer)}: its data cannot be read; the floor is not built.`,
150
- poi: [],
151
- highlight: [],
152
- });
153
- }
154
- for (const d of diagnostics.filter((f) => f.stage === 'walkable' && FLOOR_CAUSES[f.code])) {
155
- const layer = d.layer ?? '';
156
- const { cause, text } = FLOOR_CAUSES[d.code];
157
- const count = Number(d.facts?.destinations ?? 0);
158
- unbuilt.add(layer);
159
- problems.push({
160
- kind: 'floor-not-built',
161
- layer,
162
- cause,
163
- message: `${floorName(layer)}: no floor could be built — ${text}.${count && cause === 'no-walls'
164
- ? ` ${count} POI ${count === 1 ? 'stands' : 'stand'} on it.`
165
- : ''}`,
166
- poi: [],
167
- highlight: [],
168
- });
169
- }
170
- // POI bound to nothing, grouped by floor and their proven cause.
171
- const flagged = (code) => new Set(has(code).map(({ ref }) => poiKey(ref?.layer ?? '', ref?.index ?? -1)));
172
- const notFinite = flagged('destination-coordinate-not-finite');
173
- const dockEmpty = flagged('destination-dock-empty');
174
- const footprintEmpty = flagged('destination-footprint-empty');
175
- // One pass over the network stage's facts: the proven cause, and the tip to point at.
176
- const unreachedOf = new Map(has('destination-unreached').map(({ ref, facts, geometry }) => [
177
- poiKey(ref?.layer ?? '', ref?.index ?? -1),
178
- {
179
- cause: facts?.reason === 'no-floor' && facts.outside === true
180
- ? facts.floorBehind === false
181
- ? 'no-floor-behind-wall'
182
- : typeof facts.nearestWall === 'number'
183
- ? 'entrance-far-from-walls'
184
- : 'outside-building'
185
- : (REASON_CAUSE[String(facts?.reason)] ?? 'unknown'),
186
- geometry: geometry ?? [],
187
- },
188
- ]));
189
- const unconnected = new Map();
190
- for (const { ref, part } of reachability.poi) {
191
- if (part >= 0 || unbuilt.has(ref.layer))
192
- continue;
193
- const at = poiKey(ref.layer, ref.index);
194
- const cause = notFinite.has(at)
195
- ? 'coordinate-not-finite'
196
- : dockEmpty.has(at)
197
- ? 'dock-empty'
198
- : footprintEmpty.has(at)
199
- ? 'footprint-empty'
200
- : (unreachedOf.get(at)?.cause ?? 'unknown');
201
- const group = `${ref.layer}\u0000${cause}`;
202
- const entry = unconnected.get(group) ?? { layer: ref.layer, cause, poi: [] };
203
- entry.poi.push(ref);
204
- unconnected.set(group, entry);
205
- }
206
- for (const { layer, cause, poi } of unconnected.values()) {
207
- const one = poi.length === 1;
208
- problems.push({
209
- kind: 'poi-not-connected',
210
- layer,
211
- cause,
212
- message: `${floorName(layer)}: ${poi.length} POI ${one ? 'is' : 'are'} not connected to the routes — ${POI_CAUSES[cause](one)}: ${names(poi)}.`,
213
- poi,
214
- // The POI's own rectangle, and the stub tip where the failing way in ends, when one is known.
215
- highlight: poi.flatMap((ref) => [
216
- ...outline(ref),
217
- ...(unreachedOf.get(poiKey(ref.layer, ref.index))?.geometry ?? []),
218
- ]),
219
- });
220
- }
221
- // POI on a part the main one does not reach, one problem per floor.
222
- const detached = new Map();
223
- const splits = [];
224
- // Floors whose network stage proved the refusal: the ties tried every link and gave up.
225
- const untied = new Set(has('network-pieces-untied').map(({ layer }) => layer));
226
- for (const { ref, part } of reachability.poi)
227
- if (part > 0) {
228
- const list = detached.get(ref.layer);
229
- if (list)
230
- list.push(ref);
231
- else
232
- detached.set(ref.layer, [ref]);
233
- }
234
- for (const [layer, poi] of detached) {
235
- const onFloor = reachability.parts.filter((part) => part.layers.includes(layer));
236
- const others = reachability.parts.slice(1).filter((part) => part.layers.includes(layer));
237
- const lines = [
238
- { type: 'lines', layer, lines: others.flatMap((part) => part.lines) },
239
- ];
240
- // The main part never reaches this floor: its routes are whole, but no shaft joins them to the plan.
241
- if (onFloor[0] !== reachability.parts[0]) {
242
- problems.push({
243
- kind: 'floors-not-connected',
244
- layer,
245
- cause: 'floor-detached',
246
- message: `${floorName(layer)}: its routes are not connected to the rest of the plan; no transition joins them. ${poi.length} POI ${poi.length === 1 ? 'is' : 'are'} cut off: ${names(poi)}.`,
247
- poi,
248
- highlight: lines,
249
- });
250
- continue;
251
- }
252
- splits.push({ layer, parts: onFloor.length });
253
- // The proven cause needs both facts: the stage recorded the refusal, and the emitted graph
254
- // still falls apart here — later passes may have joined what the ties could not.
255
- const proven = untied.has(layer);
256
- problems.push({
257
- kind: 'network-split',
258
- layer,
259
- cause: proven ? 'no-link-found' : 'unknown',
260
- message: `${floorName(layer)}: the routes fall into ${onFloor.length} separate parts${proven ? ': the growth found no lawful link and no floor path between the parts' : ''}. ${poi.length} POI ${poi.length === 1 ? 'is' : 'are'} on parts not connected to the rest: ${names(poi)}.`,
261
- poi,
262
- highlight: lines,
263
- });
264
- }
265
- // Shafts that do not join the floors they serve.
266
- for (const d of [
267
- ...has('transition-kind-missing'),
268
- ...has('transition-coordinate-not-finite'),
269
- ...has('transition-too-few-stops'),
270
- ...has('transition-stop-unknown-layer'),
271
- ...has('transition-stop-no-dock'),
272
- ...has('transition-single-floor'),
273
- ]) {
274
- const id = d.ref?.id ?? '';
275
- const name = id ? `Transition "${id}"` : 'A transition';
276
- const layer = d.layer ?? '';
277
- const whole = d.code === 'transition-kind-missing' ||
278
- d.code === 'transition-coordinate-not-finite' ||
279
- d.code === 'transition-too-few-stops';
280
- const message = d.code === 'transition-kind-missing'
281
- ? `${name} names no kind (stairs, escalator, elevator…) and is left out.`
282
- : d.code === 'transition-coordinate-not-finite'
283
- ? `${name} has a stop whose coordinate is not a number and is left out.`
284
- : d.code === 'transition-too-few-stops'
285
- ? `${name} serves fewer than two floors.`
286
- : d.code === 'transition-stop-unknown-layer'
287
- ? `${name} names a floor the plan does not have: "${layer}".`
288
- : d.code === 'transition-single-floor'
289
- ? `${name} is connected to the routes of ${floorName(layer, false)} only, so it joins no floors.`
290
- : `${name} does not reach the routes of ${floorName(layer, false)}${d.facts?.pointId ? ` (stop "${String(d.facts.pointId)}")` : ''}.`;
291
- problems.push({
292
- kind: 'floors-not-connected',
293
- ...(whole ? {} : { layer }),
294
- cause: d.code,
295
- message,
296
- poi: [],
297
- highlight: d.geometry ?? [],
298
- });
299
- }
300
- const layerOrder = new Map(source.layers.map((l, index) => [l.layer, index]));
301
- problems.sort((a, b) => KIND_ORDER.indexOf(a.kind) - KIND_ORDER.indexOf(b.kind) ||
302
- (layerOrder.get(a.layer ?? '') ?? -1) - (layerOrder.get(b.layer ?? '') ?? -1));
303
- const total = reachability.poi.length;
304
- const connected = reachability.poi.filter(({ part }) => part >= 0).length;
305
- const counts = {
306
- poi: total,
307
- poiConnected: connected,
308
- poiNotConnected: total - connected,
309
- poiOnDetachedParts: reachability.poi.filter(({ part }) => part > 0).length,
310
- networkParts: reachability.parts.length,
311
- floorsWithoutFloor: unbuilt.size,
312
- };
313
- const built = reachability.parts.some((part) => part.lines.length > 0);
314
- const outcome = !built ? 'not-built' : problems.length ? 'built-with-gaps' : 'built';
315
- return { outcome, summary: summarize(outcome, problems, counts, splits), problems, counts };
316
- }
317
- /**
318
- * The report of a plan that cannot be read or has nothing on it.
319
- * @param problems The one reason, already worded.
320
- * @param poi How many POI the source lists.
321
- * @returns The report.
322
- */
323
- function notBuilt(problems, poi) {
324
- const counts = {
325
- poi,
326
- poiConnected: 0,
327
- poiNotConnected: poi,
328
- poiOnDetachedParts: 0,
329
- networkParts: 0,
330
- floorsWithoutFloor: 0,
331
- };
332
- return {
333
- outcome: 'not-built',
334
- summary: summarize('not-built', problems, counts, []),
335
- problems,
336
- counts,
337
- };
338
- }
339
- /**
340
- * One line for the whole plan.
341
- * @param outcome What came of it.
342
- * @param problems The grouped problems.
343
- * @param counts The counts.
344
- * @param splits The floors whose routes fall apart, with the number of parts on each.
345
- * @returns The line.
346
- */
347
- function summarize(outcome, problems, counts, splits) {
348
- if (outcome === 'not-built') {
349
- const first = problems[0];
350
- if (!first)
351
- return 'Routes are not built.';
352
- if (first.kind === 'nothing-to-build')
353
- return first.message;
354
- if (first.kind === 'plan-invalid')
355
- return `Routes are not built: ${first.message}`;
356
- if (first.kind === 'floor-not-built')
357
- return 'Routes are not built: no floor could be built.';
358
- return `Routes are not built: none of the ${counts.poi} POI could be connected.`;
359
- }
360
- if (outcome === 'built')
361
- return counts.poi
362
- ? `Routes are built: all ${counts.poi} POI are connected.`
363
- : 'Routes are built.';
364
- const gaps = [];
365
- if (counts.poiNotConnected)
366
- gaps.push(`${counts.poiNotConnected} of ${counts.poi} POI are not connected`);
367
- for (const { layer, parts } of splits)
368
- gaps.push(`the routes on ${floorName(layer, false)} fall into ${parts} parts`);
369
- if (counts.floorsWithoutFloor)
370
- gaps.push(`${counts.floorsWithoutFloor} floor(s) could not be built`);
371
- if (problems.some(({ kind }) => kind === 'floors-not-connected'))
372
- gaps.push('some floors are not connected');
373
- return `Routes are built, with gaps: ${gaps.join(', and ')}.`;
374
- }
@@ -1,111 +0,0 @@
1
- import { type Frame } from './geom/frames.js';
2
- import type { Segment, Vec2 } from './geom/types.js';
3
- import type { MaskCtx } from './mask.js';
4
- import { type NetworkSizes } from './network-sizes.js';
5
- /** The floor read along one direction: its frame and the mask in frame coordinates. */
6
- export interface Grid {
7
- /** The direction. */
8
- readonly frame: Frame;
9
- /** Mask in the frame's coordinates. */
10
- readonly ctx: MaskCtx;
11
- }
12
- /**
13
- * Four-heading walk over the grids, cells numbered through all of them; stepping onto the same spot of
14
- * another grid costs a turn.
15
- */
16
- export interface Router {
17
- /** Cell count over all grids. */
18
- readonly cells: number;
19
- /** 1 for a walkable cell. */
20
- readonly ok: Uint8Array;
21
- /** Cell size, meters. */
22
- readonly pitch: number;
23
- /**
24
- * Cheapest path from any seed to any target.
25
- * @param seeds Start cells.
26
- * @param isTarget 1 for each target cell.
27
- * @returns Cells from the target back to its seed, or null.
28
- */
29
- route(seeds: Iterable<number>, isTarget: Uint8Array): number[] | null;
30
- /**
31
- * One growing search: each reached target group joins the tree and the search continues from it.
32
- * @param seeds Initial tree cells; may be empty.
33
- * @param group Target group per cell, -1 for none; the reached cell is cleared here.
34
- * @param reseed Cells to start a new tree from once nothing is reachable; null to stop.
35
- * @param onJoin Gets the path (target first) and the group; returns other cells joining with it, their
36
- * `group` cleared. Must not search the router (shared state).
37
- * @returns Every cell of every tree.
38
- */
39
- grow(seeds: Iterable<number>, group: Int32Array, reseed: () => Iterable<number> | null, onJoin: (cells: number[], group: number) => Iterable<number>): Set<number>;
40
- /**
41
- * Neighbor of `c` in direction `nd` on its grid.
42
- * @param c The cell.
43
- * @param nd Direction, 0…3.
44
- * @returns The neighbor, or -1 when blocked or off the grid.
45
- */
46
- stepTo(c: number, nd: number): number;
47
- /**
48
- * A point's cell on each grid that covers it.
49
- * @param x Point x.
50
- * @param y Point y.
51
- * @returns The cells.
52
- */
53
- cellsOf(x: number, y: number): number[];
54
- /**
55
- * A point's cell on the grid nearest a direction.
56
- * @param x Point x.
57
- * @param y Point y.
58
- * @param dx Direction x.
59
- * @param dy Direction y.
60
- * @returns The cell, or -1 off that grid.
61
- */
62
- cellOf(x: number, y: number, dx: number, dy: number): number;
63
- /**
64
- * A point's cell on a grid of a frame.
65
- * @param x Point x.
66
- * @param y Point y.
67
- * @param frame One of the grids' frames.
68
- * @returns The cell, or -1 off every grid of that frame.
69
- */
70
- cellIn(x: number, y: number, frame: Frame): number;
71
- /**
72
- * Frame of a cell's grid.
73
- * @param c The cell.
74
- * @returns Its frame.
75
- */
76
- frameOf(c: number): Frame;
77
- /**
78
- * Center of a cell.
79
- * @param c The cell.
80
- * @returns The center, rounded to centimeters.
81
- */
82
- worldOf(c: number): Vec2;
83
- /**
84
- * Cells a segment passes through, on every grid or only on its own direction's (every grid when its
85
- * own does not reach it).
86
- * @param x0 Start x.
87
- * @param y0 Start y.
88
- * @param x1 End x.
89
- * @param y1 End y.
90
- * @param own Only the segment's own direction.
91
- * @returns The cells, grid by grid, in order along the segment.
92
- */
93
- cellsAlong(x0: number, y0: number, x1: number, y1: number, own?: boolean): number[];
94
- /**
95
- * A cell path as segments between centers. A step between grids is laid through the corner where the
96
- * arriving and leaving lines meet, when the floor there is free.
97
- * @param cells The path.
98
- * @returns Segments in path order, each at least a centimeter.
99
- */
100
- segmentsAlong(cells: readonly number[]): Segment[];
101
- }
102
- /**
103
- * Build the router. Per grid: coarse cells free when any mask cell is, seam flags so a thin wall still
104
- * blocks a step, and a cost that keeps off walls. A roomy cell may step onto another grid at the cost of a
105
- * turn; along an aisle its own grid runs straight while the others zigzag, so the walk picks it naturally.
106
- * @param grids The floor per direction, plan axes first; a direction may have several grids.
107
- * @param cfg Network sizes.
108
- * @returns The router.
109
- */
110
- export declare function makeRouter(grids: readonly Grid[], cfg: NetworkSizes): Router;
111
- //# sourceMappingURL=router.d.ts.map