@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.
- 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/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/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-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/README.md
CHANGED
|
@@ -1,446 +1,3 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Temporary Holding Version
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
graph: `lines` and `lineEnds`, in the shape of the v1 graph format, its lines not cut where they meet
|
|
5
|
-
(see "The emitted graph"). Pure functions only — no React, no MobX, no live stores,
|
|
6
|
-
no I/O. The same input always yields the same output (covered by a determinism test).
|
|
7
|
-
|
|
8
|
-
This package is the production home of the #1365 auto-routing spike. The plan and per-task status live
|
|
9
|
-
in the tracker: #1221 (phase 1), #1441 (phase 2), #1442 (phase 3). The route-network model it ships —
|
|
10
|
-
`steiner` — is described under "Route network" below.
|
|
11
|
-
|
|
12
|
-
## Entry points
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
import { compileWayfinding, type WayfindingSource } from '@expofp/wayfinding-compiler';
|
|
16
|
-
|
|
17
|
-
const source: WayfindingSource = {
|
|
18
|
-
layers: [{ layer: '1', walls, destinations }], // walls: flat [x,y,…] polylines; destinations: footprints
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const { graph, report } = compileWayfinding(source); // graph: { lines, lineEnds } (v1 shape)
|
|
22
|
-
const debug = compileWayfinding(source, { debug: true }); // + layers, reachability, diagnostics
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
- **`compileWayfinding(source)`** — the main entry. Returns `{ graph, report }`: the graph in the v1
|
|
26
|
-
shape (`lines` + `lineEnds`, not cut where they meet), and the report a designer reads — `outcome` (`built` / `built-with-gaps` / `not-built`), a one-line
|
|
27
|
-
`summary`, POI `counts`, and `problems` grouped by floor and reason, each with the POI names and where
|
|
28
|
-
to look on the plan.
|
|
29
|
-
- **`compileWayfinding(source, { debug: true })`** — the same single pass, adding every stage's artifacts
|
|
30
|
-
per layer (raw inputs, walkable area, route network), the `reachability` of the emitted graph (its
|
|
31
|
-
connected parts and the part every POI is bound to) and `diagnostics` — every technical fact, stage
|
|
32
|
-
by stage — as plain serializable data: what a debug overlay draws. The full catalog of facts is the
|
|
33
|
-
debug-report table under "Diagnostics and the report" below. `debug: { invariants: true }` also
|
|
34
|
-
checks the emitted graph against the geometric invariants (`graph-invariants.ts`: no line through a
|
|
35
|
-
wall or an unserved POI, every dock ending inside its ring; lines may cross or end on one another,
|
|
36
|
-
the converter cuts them there) and appends
|
|
37
|
-
the findings as the `graph` stage. The sweep is pairwise and costs a sizable share of the compile on
|
|
38
|
-
a large plan — about a third more on the largest fixture — so it is opted into, never implied by
|
|
39
|
-
`debug: true`.
|
|
40
|
-
- **`validateWayfindingSource(source)`** — what is wrong with a plan, as a list of `SourceIssue`
|
|
41
|
-
(`severity`, `code`, `message`, and the layer, id and position it belongs to). The same findings are
|
|
42
|
-
part of every compile's report and diagnostics.
|
|
43
|
-
|
|
44
|
-
### The emitted graph
|
|
45
|
-
|
|
46
|
-
The graph has the shape of the v1 format, `lines` + `lineEnds`, with one difference from what
|
|
47
|
-
`wf.data.js` holds: its lines are not cut where they meet. An aisle is one line, a stub ends on its span,
|
|
48
|
-
and two aisles cross whole — as a designer draws them. The graph is not written to `wf.data.js` as it
|
|
49
|
-
stands. Designer saves its lines like hand-drawn ones, and the converter that builds `wf.data.js` from
|
|
50
|
-
the saved lines (`fpsync2`) cuts every line where another crosses it or ends within 0.1 plan units of it
|
|
51
|
-
— 3 cm in feet, 10 cm in meters. The report counts an end joined within the same 0.1 plan units, so it
|
|
52
|
-
says what the converter will join on any scale. An end the compiler emits lies within 2 cm of the line it
|
|
53
|
-
stops at, since a line off the plan's axes holds no point of the centimeter grid exactly: on a drawing in
|
|
54
|
-
tenths (before `fp-ver 5`, 1 cm or 3 mm per 0.1 unit) such an end may stay unjoined, and the report shows
|
|
55
|
-
it so. What a viewer reads is joined end to end, which is all the current runtime (`@expofp/wayfinding`
|
|
56
|
-
on `main`) and every released viewer join lines by. A reader that takes the compiler's graph directly has
|
|
57
|
-
to cut the lines itself.
|
|
58
|
-
|
|
59
|
-
A transition edge joins two stops of one shaft on different floors and carries:
|
|
60
|
-
|
|
61
|
-
- `virtual: true` — how the current runtime (`@expofp/wayfinding` on `main`, and every released viewer)
|
|
62
|
-
tells a floor change from a walk, prices it and places the floor-change markers.
|
|
63
|
-
- `kind` (`stairs`, `escalator` or `elevator`) and `transitionId` — v1 extensions the current runtime
|
|
64
|
-
ignores. The v2 runtime (`feat/wayfinding-v2-graph-format`) reads them first: `kind` makes the edge a
|
|
65
|
-
transition priced by its policy, `transitionId` keeps a lift serving three floors one shaft.
|
|
66
|
-
|
|
67
|
-
`@expofp/schema` describes the fields the current runtime reads; the extensions join it with the runtime
|
|
68
|
-
that reads them.
|
|
69
|
-
|
|
70
|
-
### What the report says
|
|
71
|
-
|
|
72
|
-
`compileWayfinding` never throws over the plan: a plan it cannot read at all — an unnamed layer, a scale
|
|
73
|
-
that is not a scale — comes back `not-built`, with an empty graph and a `plan-invalid` problem. A
|
|
74
|
-
coordinate that is not a number stops only what it touches: a wall skips its floor (a `plan-invalid`
|
|
75
|
-
problem for that floor), a POI or a transition is left out and reported, and the rest of the plan
|
|
76
|
-
compiles. Everything else a compile can carry on around is compiled around and reported: a floor
|
|
77
|
-
that got no floor, or spans more than routes are built over (a plan in the wrong units, a stray drawing
|
|
78
|
-
far off), POI that got no dock (with the reason the stage proved — a POI standing outside the building
|
|
79
|
-
outline is told apart from one with no floor in front, and the problem points at the stub tip where the
|
|
80
|
-
failing way in ends, when one is known), POI on a part of the network the main
|
|
81
|
-
part does not reach, and shafts that name no kind, do not join their floors, or are left docked on one
|
|
82
|
-
floor only. POI that share an id, or
|
|
83
|
-
have none, each dock by their own geometry. One fact makes one problem — a floor that is not built is one
|
|
84
|
-
problem, not one per POI standing on it — and the main part of the network is the one most POI are bound
|
|
85
|
-
to. The reachability behind it is read off the emitted graph by the graph's own rules: nodes joined by
|
|
86
|
-
exact coordinates, lines joined where one ends within 0.1 plan units of another's span or crosses it
|
|
87
|
-
(the converter cuts the lines there), a POI bound to the `lineEnds` inside its `dock ?? polygon`.
|
|
88
|
-
|
|
89
|
-
### Diagnostics and the report
|
|
90
|
-
|
|
91
|
-
One compile speaks to two readers. The **user report** (`CompileResult.report`, built by `report.ts`)
|
|
92
|
-
is for the designer: problems grouped by floor and reason, one fact — one message, in ready English.
|
|
93
|
-
The **debug report** (`WayfindingDebugResult.diagnostics`, produced stage by stage in
|
|
94
|
-
`diagnostics.ts`) is every technical fact the compile established, as plain data for a debug overlay.
|
|
95
|
-
Both are documented here in full; the tables are the contract.
|
|
96
|
-
|
|
97
|
-
#### User report
|
|
98
|
-
|
|
99
|
-
`report.outcome` is `built` when the graph has lines and no problem is left, `built-with-gaps` when it
|
|
100
|
-
has lines and problems, `not-built` when nothing was emitted. `report.counts` counts source POI only
|
|
101
|
-
(`poi`, `poiConnected`, `poiNotConnected`, `poiOnDetachedParts`, `networkParts`,
|
|
102
|
-
`floorsWithoutFloor`); transition pads are not counted. Each problem carries the `poi` it touches
|
|
103
|
-
(with the names the plan gave) and a `highlight` saying where to look, in plan units.
|
|
104
|
-
|
|
105
|
-
Substitutions, used throughout: `{floor}` is the floor's name — `Floor "BG"`, or `The floor` for the
|
|
106
|
-
one unnamed floor (`floor "BG"` / `the floor` inside a sentence); `{n}` is a count; `{names}` lists up
|
|
107
|
-
to 8 POI names and counts the rest (`A, B and 3 more`), a POI with no id as `unnamed POI`; singular and
|
|
108
|
-
plural (`is`/`are`, `it`/`they`) follow the count.
|
|
109
|
-
|
|
110
|
-
| Kind | Cause | When | Message |
|
|
111
|
-
| ---------------------- | ---------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
112
|
-
| `plan-invalid` | `layer-id-missing` | a layer has no id; the plan is not built | `A floor has no id; the plan cannot be built.` |
|
|
113
|
-
| `plan-invalid` | `units-per-meter-invalid` | the scale is not a positive finite number | `The plan's units per meter is {value}; it must be a positive number. Check the plan's units and map anchors.` |
|
|
114
|
-
| `plan-invalid` | `wall-coordinate-not-finite` | a wall coordinate is `NaN`/infinite; that floor alone is skipped | `{floor}: a wall has a coordinate that is not a number; the floor is not built.` |
|
|
115
|
-
| `nothing-to-build` | `no-floors` | the plan has no layers | `Nothing to build: the plan has no floors.` |
|
|
116
|
-
| `nothing-to-build` | `nothing-drawn` | every layer has neither walls nor POI | `Nothing to build: the plan has no walls and no POI.` |
|
|
117
|
-
| `floor-not-built` | `no-walls` | the layer has POI but no walls | `{floor}: no floor could be built — the floor has no walls, so there is nothing to build routes inside. {n} POI stand on it.` |
|
|
118
|
-
| `floor-not-built` | `outline-open` | no wall run closes into an outer contour | `{floor}: no floor could be built — the outer walls do not close into a contour. Check the outer walls of this floor.` |
|
|
119
|
-
| `floor-not-built` | `carved-away` | walls and footprints cover the whole contour | `{floor}: no floor could be built — the walls and POI drawn on it cover it whole.` |
|
|
120
|
-
| `floor-not-built` | `too-large` | the floor spans more than routes are built over | `{floor}: no floor could be built — it spans more than routes are built over. Check the plan's units, and any wall or POI drawn far from the hall.` |
|
|
121
|
-
| `poi-not-connected` | `coordinate-not-finite` | a footprint coordinate is `NaN`/infinite | `{floor}: {n} POI is/are not connected to the routes — it has/they have a coordinate that is not a number: {names}.` |
|
|
122
|
-
| `poi-not-connected` | `footprint-empty` | the footprint encloses no area | `… — they have no outline the plan can read: {names}.` |
|
|
123
|
-
| `poi-not-connected` | `dock-empty` | the `dock` ring encloses no area | `… — the rectangle routes arrive at has no area: {names}.` |
|
|
124
|
-
| `poi-not-connected` | `outside-building` | `no-floor` with the POI outside the outline | `… — it stands/they stand outside the building outline; routes are built inside it only: {names}.` |
|
|
125
|
-
| `poi-not-connected` | `entrance-far-from-walls` | an entrance outside the building with no wall within 10 m | `… — it stands/they stand more than 10 m from the nearest wall; an entrance outside the building is connected only within 10 m of a wall: {names}.` |
|
|
126
|
-
| `poi-not-connected` | `no-floor-behind-wall` | an entrance outside the building whose walls in reach have no floor behind them | `… — no wall near it/them opens onto floor; check that the building outline closes and that nothing stands right behind the wall: {names}.` |
|
|
127
|
-
| `poi-not-connected` | `no-floor-in-front` | `no-floor` inside the building | `… — there is no floor to stand on in front of it/them: {names}.` |
|
|
128
|
-
| `poi-not-connected` | `no-way-in` | walled in on every side | `… — they have no open side and no doorway: {names}.` |
|
|
129
|
-
| `poi-not-connected` | `approach-blocked` | every way in breaks a dock rule (`way-in-blocked`) | `… — a wall or another POI stands right in front of every way in: {names}.` |
|
|
130
|
-
| `poi-not-connected` | `cut-off` | its floor is a pocket no route reaches | `… — the floor in front of them is a pocket no route reaches: {names}.` |
|
|
131
|
-
| `poi-not-connected` | `lost-while-tidying` | attached, then lost to a later pass (`detached`) | `… — they were attached, then lost while the routes were tidied — reason unknown: {names}.` |
|
|
132
|
-
| `poi-not-connected` | `unknown` | no stage proved a cause | `… — reason unknown: {names}.` |
|
|
133
|
-
| `network-split` | `no-link-found` | a POI is bound off the main part AND the network stage recorded the refusal to tie | `{floor}: the routes fall into {n} separate parts: the growth found no lawful link and no floor path between the parts. {n} POI is/are on parts not connected to the rest: {names}.` |
|
|
134
|
-
| `network-split` | `unknown` | a POI is bound off the main part, with no recorded refusal | `{floor}: the routes fall into {n} separate parts. {n} POI is/are on parts not connected to the rest: {names}.` |
|
|
135
|
-
| `floors-not-connected` | `floor-detached` | the main part never reaches this floor, and a POI stands on it | `{floor}: its routes are not connected to the rest of the plan; no transition joins them. {n} POI is/are cut off: {names}.` |
|
|
136
|
-
| `floors-not-connected` | `transition-kind-missing` | a transition names no kind | `{transition} names no kind (stairs, escalator, elevator…) and is left out.` |
|
|
137
|
-
| `floors-not-connected` | `transition-coordinate-not-finite` | a stop coordinate is `NaN`/infinite | `{transition} has a stop whose coordinate is not a number and is left out.` |
|
|
138
|
-
| `floors-not-connected` | `transition-too-few-stops` | fewer than two known floors served | `{transition} serves fewer than two floors.` |
|
|
139
|
-
| `floors-not-connected` | `transition-stop-unknown-layer` | a stop names a layer the plan lacks | `{transition} names a floor the plan does not have: "{layer}".` |
|
|
140
|
-
| `floors-not-connected` | `transition-single-floor` | the shaft docked on one floor only | `{transition} is connected to the routes of {floor} only, so it joins no floors.` |
|
|
141
|
-
| `floors-not-connected` | `transition-stop-no-dock` | a stop got no dock on its layer; the stop is named when it has an id | `{transition} does not reach the routes of {floor} (stop "{id}").` |
|
|
142
|
-
|
|
143
|
-
`{transition}` is `Transition "{id}"`, or `A transition` when the plan gave none. Problems are sorted
|
|
144
|
-
by kind (the order of the table) and then by the plan's layer order. The one-line `summary` restates
|
|
145
|
-
the outcome with the counts.
|
|
146
|
-
|
|
147
|
-
#### Debug report
|
|
148
|
-
|
|
149
|
-
Every fact is a `Diagnostic`: `code`, `severity` (`error` — the plan or part of it cannot be read;
|
|
150
|
-
`warning` — part of the result is lost or doubtful; `info` — what a stage did), `stage`, one technical
|
|
151
|
-
English `message`, and where it applies: `layer`, a `ref` into the source (`kind` +
|
|
152
|
-
`layer`/`index`/`id`), `geometry` to draw (`bounds`/`point`/`lines`, plan units; `lines` are indices
|
|
153
|
-
into `graph.lines`), and `facts` — the stage's own numbers. Stages come in run order: `input`,
|
|
154
|
-
`scale`, then per layer `normalize` → `walkable` → `network` → `emit`, then `transitions`,
|
|
155
|
-
`reachability`, and — only under `debug: { invariants: true }` — `graph` last.
|
|
156
|
-
|
|
157
|
-
| Code | Severity | Stage | When | Message | Context |
|
|
158
|
-
| ----------------------------------- | ----------------------------------- | ------------ | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
159
|
-
| `no-layers` | warning | input | the plan has no layers | `the plan has no layers` | — |
|
|
160
|
-
| `layer-id-missing` | error | input | a layer has no id | `a layer has no id` | — |
|
|
161
|
-
| `layer-id-duplicate` | warning | input | two layers share an id | `two layers share an id` | ref layer |
|
|
162
|
-
| `destination-id-missing` | warning | input | a destination has no id | `a destination has no id` | ref destination (layer, index) |
|
|
163
|
-
| `destination-id-duplicate` | warning | input | two destinations on one layer share an id | `two destinations share an id` | ref destination |
|
|
164
|
-
| `destination-coordinate-not-finite` | warning | input | a footprint coordinate is `NaN`/infinite; the POI is left out | `a coordinate of the footprint is not a finite number` | ref destination |
|
|
165
|
-
| `destination-footprint-empty` | warning | input | no ring of the footprint encloses area | `the footprint encloses no area` | ref destination |
|
|
166
|
-
| `destination-dock-empty` | warning | input | the `dock` ring encloses no area | `the dock ring encloses no area` | ref destination |
|
|
167
|
-
| `wall-coordinate-not-finite` | error | input | a wall coordinate is `NaN`/infinite; the floor is skipped | `a wall coordinate is not a finite number` | ref layer |
|
|
168
|
-
| `transition-kind-missing` | warning | input | a transition names no kind; it is left out | `a transition names no kind` | ref transition (id) |
|
|
169
|
-
| `transition-coordinate-not-finite` | warning | input | a stop coordinate is `NaN`/infinite; the transition is left out | `a transition stop coordinate is not a finite number` | ref transition (id, index) |
|
|
170
|
-
| `transition-too-few-stops` | warning | input | fewer than two known floors served | `a transition serves fewer than two floors` | ref transition (id) |
|
|
171
|
-
| `units-per-meter-invalid` | error | input | the scale is not a positive finite number | `unitsPerMeter must be a finite number above zero` | — |
|
|
172
|
-
| `units-assumed-meters` | info | scale | the plan states no `unitsPerMeter` | `the plan states no units per meter; it is read as meters` | — |
|
|
173
|
-
| `wall-entry-empty` | warning | normalize | a wall entry cleans to nothing | `the wall entry cleans to no wall piece and is dropped` | ref wall (entry index) |
|
|
174
|
-
| `wall-entry-split` | info | normalize | one entry holds several runs | `the wall entry describes {n} separate runs, not one polyline` | ref wall; facts `runs` |
|
|
175
|
-
| `wall-entry-odd-length` | warning | normalize | an entry holds an odd count of numbers | `the wall entry holds an odd count of numbers; the last one names no point and is dropped` | ref wall |
|
|
176
|
-
| `footprint-shape` | info / warning (`bounds-oversized`) | normalize | a footprint drawn as pieces got its outline | one sentence per shape: `traced`, `hull`, `rectilinear`, `bounds`, `bounds-oversized`, `dock` (see `SHAPE_MESSAGES`) | ref destination; facts `how`, `parts` |
|
|
177
|
-
| `footprint-clipped` | info | normalize | the walls cut the footprint back | `the footprint ran over its walls and is cut back to the largest piece they leave` | ref destination |
|
|
178
|
-
| `crossable-inferred` | warning | normalize | a destination is read as walk-through | `the footprint holds other destinations, so it is walked in, not around` / `the footprint stands before the only way into another destination, so routes may cross it` | ref destination; facts `by`, `victims?` |
|
|
179
|
-
| `entrance-openings` | info | normalize | an entrance is reached through a wall or a doorway the walls leave | `routes reach the entrance through the wall inside its bounds, at {n} place(s)` / `the entrance stands {d} m outside the building; routes reach it through the doorway the walls leave` / `… through the nearest wall with floor behind it` | ref destination; geometry points (where the docks cross the wall); facts `by`, `openings`, `distance?` |
|
|
180
|
-
| `entrance-no-wall` | info | normalize | an entrance inside the building stands across no wall | `the entrance stands across no wall and is reached like any POI` | ref destination |
|
|
181
|
-
| `layer-no-walls` | warning | walkable | POI but no walls | `the layer has POI but no walls, so no floor is built` | ref layer; facts counts, `destinations` |
|
|
182
|
-
| `layer-no-outer-contour` | warning | walkable | no closed outer contour | `no wall run closes into an outer contour, so no floor is built` | ref layer; facts counts, `destinations` |
|
|
183
|
-
| `floor-carved-away` | warning | walkable | the contour closes but nothing is left | `the outer contour closes, but walls and footprints cover all of it` | ref layer; facts counts, `destinations` |
|
|
184
|
-
| `floor-built` | info | walkable | the floor is built | `the floor is built` | ref layer; facts counts, `areaM2` |
|
|
185
|
-
| `floor-too-large` | warning | walkable | the floor exceeds the raster budget | `the floor spans more than routes are built over, so no floor is built` | ref layer; facts `widthM`, `heightM`, `destinations` |
|
|
186
|
-
| `destination-unreached` | warning | network | the POI got no dock; shows in the report as `poi-not-connected` with the mapped cause | `the POI got no dock a route can end at ({reason})` | ref destination; geometry point (the failing tip); facts `reason`, `outside?`, `nearestWall?`, `floorBehind?`, `by?` |
|
|
187
|
-
| `doorways-found` | info | network | the stage ran; the count may be 0 | `the walls leave {n} doorway(s) on the layer` | ref layer; facts `count` |
|
|
188
|
-
| `network-shortcuts` | info | network | shortcut links were cut in | `{n} shortcut link(s) are cut in where the network sent a route the long way round` | ref layer; facts `count` |
|
|
189
|
-
| `network-pieces-untied` | warning | network | the ties gave up with pieces left; proves `network-split.cause = 'no-link-found'` on its floor | `the layer's network is left in {n} pieces: the growth found no lawful link and no floor path between them` | ref layer; facts `pieces` (total, not extra) |
|
|
190
|
-
| `floor-pieces-unserved` | info | network | walkable pieces serve nothing and are left out | `{n} walkable floor piece(s) hold no destination and no doorway, so no network is built over them` | ref layer; facts `count` |
|
|
191
|
-
| `network-parts-before-emit` | info | network | the part count before the emit | `the layer's network has {n} part(s) before the emit, shafts not counted` | ref layer; facts `count` |
|
|
192
|
-
| `path-segment-collapsed` | info | emit | segments shorter than the centimeter grid were skipped | `{n} path segment(s) collapse to a point on the centimeter grid and emit no line` | ref layer; facts `count` |
|
|
193
|
-
| `dock-collapsed` | warning | emit | a dock's ends snap to one node: its `lineEnd` stands with no line | `the dock collapses to a point on the centimeter grid: its line end is emitted with no line of its own` | ref destination (source index when known) |
|
|
194
|
-
| `transition-stop-bound` | info | transitions | where a stop rides in | `the transition stop stands in the open and gets a pad of its own` / `the transition stop rides in on the dock of "{name}"` | ref transition-stop; geometry point; facts `pointId?`, `pad`, `destination?` |
|
|
195
|
-
| `transition-stop-ambiguous` | warning | transitions | a stop stands in several destinations | `the transition stop stands in {n} destinations and rides in on the smallest` | ref transition-stop; geometry point; facts `pointId?`, `destinations` |
|
|
196
|
-
| `transition-stop-no-dock` | warning | transitions | the stop's floor gave it no dock | `a transition stop got no dock on its layer, so the shaft does not reach that floor` | ref transition-stop; geometry point; facts `reason`, `pointId?` |
|
|
197
|
-
| `transition-stop-unknown-layer` | warning | transitions | the stop names a layer the plan lacks | `a transition stop names a layer the plan does not have` | ref transition-stop; facts `reason`, `pointId?` |
|
|
198
|
-
| `transition-single-floor` | warning | transitions | the shaft docked on one floor only | `the shaft docked on one floor only, so it connects nothing` | ref transition; geometry points; facts `kind` |
|
|
199
|
-
| `network-split` | warning | reachability | the emitted graph falls into parts | `the emitted graph falls into {n} parts` | facts `nodes[]`, `poi[]` per part |
|
|
200
|
-
| `destination-on-detached-part` | warning | reachability | the POI is bound off the main part | `the POI is bound to a part of the graph the main part does not reach` | ref destination; facts `part` |
|
|
201
|
-
| `destination-unbound` | warning | reachability | no `lineEnd` lies inside the POI | `no line end lies inside the POI` | ref destination |
|
|
202
|
-
| `destination-split-across-parts` | warning | reachability | the POI has ends on several parts | `the POI has line ends on more than one part` | ref destination |
|
|
203
|
-
| `binding-mismatch` | warning | reachability | the network stage and the binding disagree, on a floor the stage ran on, for a POI it was given | `the network stage reports the POI unreached, yet a line end lies inside it` / `…reached, yet no line end lies inside it` | ref destination |
|
|
204
|
-
| `line-end-unowned` | warning | reachability | ends inside no POI that start no shaft | `{n} line end(s) lie inside no POI and start no shaft` | facts `ends` |
|
|
205
|
-
| `line-end-shared` | warning | reachability | ends inside more than one POI | `{n} line end(s) lie inside more than one POI` | facts `ends` |
|
|
206
|
-
| `line-crosses-wall` | warning | graph | a segment or a dock crosses a wall | `the line crosses a wall of its layer` | ref layer; geometry lines (+ point for a dock) |
|
|
207
|
-
| `line-crosses-poi` | warning | graph | a segment or a dock passes through a POI it is not serving | `the line passes through a destination it is not serving` | ref layer; geometry lines (+ point for a dock) |
|
|
208
|
-
| `dock-outside-ring` | warning | graph | a dock's tip lies inside no `dock ?? polygon` ring | `the dock ends inside no ring a destination is bound by` | ref layer; geometry lines + point |
|
|
209
|
-
|
|
210
|
-
Where a fact is also visible in the user report, the two differ on purpose: the diagnostic is the
|
|
211
|
-
technical fact with the stage's own words and numbers (`destination-unreached` with
|
|
212
|
-
`facts.reason: 'way-in-blocked'`), the report problem is the proven cause in ready text
|
|
213
|
-
(`poi-not-connected`, cause `approach-blocked`). The mapping: `destination-unreached` reasons
|
|
214
|
-
`no-floor`/`no-way-in`/`way-in-blocked`/`cut-off`/`detached` become `poi-not-connected` causes
|
|
215
|
-
`no-floor-in-front` (or `outside-building` by `facts.outside` — for an entrance, `no-floor-behind-wall` by
|
|
216
|
-
`facts.floorBehind` or `entrance-far-from-walls` by `facts.nearestWall`)/`no-way-in`/`approach-blocked`/
|
|
217
|
-
`cut-off`/`lost-while-tidying`; input facts `destination-coordinate-not-finite`,
|
|
218
|
-
`destination-dock-empty`, `destination-footprint-empty` take priority in that order;
|
|
219
|
-
`network-pieces-untied` turns `network-split`'s cause to `no-link-found`; the `graph` stage never
|
|
220
|
-
reaches the report.
|
|
221
|
-
|
|
222
|
-
### Reusing the walkable area
|
|
223
|
-
|
|
224
|
-
The walkable stage depends only on the walls and the carved footprints — never on the route network.
|
|
225
|
-
`compileWayfinding(source, { walkable })` takes ready areas by layer id and skips the stage for each of
|
|
226
|
-
them, so a caller iterating on the route-network generator, or holding the artifacts of an earlier
|
|
227
|
-
compile of the same geometry, pays for the network alone. `CompileProgress.cached` says which stages
|
|
228
|
-
were handed their artifact rather than running. The saving is small — the walkable stage is some 6–17%
|
|
229
|
-
of a compile on real plans, the network is the rest.
|
|
230
|
-
|
|
231
|
-
The compile is synchronous and takes seconds on a large plan: call it from a worker. On the main
|
|
232
|
-
thread `onProgress` fires, but nothing is repainted until the compile returns.
|
|
233
|
-
|
|
234
|
-
```ts
|
|
235
|
-
const first = compileWayfinding(source, { debug: true });
|
|
236
|
-
const walkable = Object.fromEntries(first.layers.map((l) => [l.layer, l.walkable]));
|
|
237
|
-
|
|
238
|
-
const again = compileWayfinding(source, { debug: true, walkable }); // route network only
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
The package is **booth-agnostic**: a `destination` is any footprint a route must reach (obstacle + POI +
|
|
242
|
-
connection point). The efp glue maps a booth to one; the compiler never sees the word "booth". A
|
|
243
|
-
destination with `crossable: true` (a bag check, a
|
|
244
|
-
security gate) stays walkable and the route may pass through it. The caller states that flag, and the
|
|
245
|
-
compiler adds two readings of its own: a destination holding smaller destinations inside it is a zone
|
|
246
|
-
people walk about in rather than an obstacle, and a footprint that leaves another destination no lawful
|
|
247
|
-
way in at all — while being reachable itself — is the ground a route has to cross to arrive.
|
|
248
|
-
A destination with `entrance: true` is a way into the building: routes reach it through the wall it
|
|
249
|
-
stands across, inside its bounds, and one outside the building through the nearest wall with floor
|
|
250
|
-
behind it (see [Entrances go through the walls](#entrances-go-through-the-walls)).
|
|
251
|
-
|
|
252
|
-
### Footprints given as pieces, and where a route lands
|
|
253
|
-
|
|
254
|
-
A destination whose real shape is not a polygon the plan can state — a round bar, an L-shaped lounge, a
|
|
255
|
-
cloverleaf hall, a pictogram in two parts — supplies **`parts`** instead: the raw pieces (triangles,
|
|
256
|
-
sub-shapes) it is drawn from. They replace `polygon`. The compiler reads the outline off the mesh's own
|
|
257
|
-
edges — an edge no two pieces share is on the boundary (`geom/mesh-outline.ts`) — and carves the largest
|
|
258
|
-
outer ring as it is, however many corners it turns. A mesh whose edges do not close falls back to the
|
|
259
|
-
older reading (`geom/footprint.ts`): its convex hull when the pieces fill ≥ 95 % of it and the hull has at
|
|
260
|
-
most six vertices, a traced outline when it is one loop of at most twelve axis-aligned edges, and its
|
|
261
|
-
bounding box otherwise; a mesh of more than 64 pieces is boxed without tracing.
|
|
262
|
-
|
|
263
|
-
The drawing and the `dock` rectangle are two statements about one place, so the footprint is the two
|
|
264
|
-
joined. A piece identical to the rectangle is the rectangle delivered twice and is left out of the
|
|
265
|
-
reading: laid over the drawing it runs along the drawing's own edges, those edges are then seen twice,
|
|
266
|
-
and the ring that closed through them disappears with them — a room read as a frame around itself. Where
|
|
267
|
-
the drawing falls into separate blocks, the footprint is the block the rectangle stands in, read from the
|
|
268
|
-
drawing's own rings rather than from the traced answer, which gives one ring and gives the biggest. The
|
|
269
|
-
other blocks are drawn all the same, so they are carved out of the floor as obstacles no route arrives
|
|
270
|
-
at.
|
|
271
|
-
|
|
272
|
-
A destination may also name a **`dock`** — a CONVEX ring inside the footprint that a route endpoint must
|
|
273
|
-
land in. Supply it when the host identifies a destination by a rectangle of its own, especially when its
|
|
274
|
-
containment test only accepts convex polygons. The ways in are then laid from the ring: the middle of each
|
|
275
|
-
of its sides is where the dock ends, and the side's outward normal carries it to the footprint, where the
|
|
276
|
-
whisker leaves — dock end, foot and tip on one line.
|
|
277
|
-
|
|
278
|
-
## Stages
|
|
279
|
-
|
|
280
|
-
`compile-wayfinding.ts` runs the plan: validation and scale, the transition stops, each layer through
|
|
281
|
-
`compile-layer.ts` (the destinations read as the stages see them, then the stages below), the emit and the
|
|
282
|
-
report.
|
|
283
|
-
|
|
284
|
-
| Stage | Module | What it does |
|
|
285
|
-
| ------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
286
|
-
| Normalize | `geom/normalize.ts` | Reads raw wall entries into their real runs (`cleanPolylineRuns`; `geom/walls.ts` runs it over every entry) and cleans destination rings (`cleanRing`). |
|
|
287
|
-
| Walkable area | `walkable.ts` | interior(building outlines) − obstacles − wall strips; the outlines come from `@expofp/wayfinding-geometry`. |
|
|
288
|
-
| Route network | `steiner-network.ts` | The network along the directions the plan is drawn in, one module per pass (named below): a stub per open face, the aisle axes the stub tips define, rows and perimeters on them, one growth over an eroded raster joining the pieces and lone tips with every path laid on those axes, then the passes listed below. |
|
|
289
|
-
| Emit v1 | `emit-v1.ts` | Restates the network as `lines` + `lineEnds` (the v1 graph), moving no point; what collapses on the centimeter grid is counted and reported (`path-segment-collapsed`, `dock-collapsed`). |
|
|
290
|
-
|
|
291
|
-
### The floor a plan draws
|
|
292
|
-
|
|
293
|
-
The floor starts inside the building outlines the walls draw (`buildingOutlines` of
|
|
294
|
-
`@expofp/wayfinding-geometry`, the rule the runtime reads the same walls with; the rule is in that
|
|
295
|
-
package's README). The compiler sets no `maxBridge`, so every opening closes and some floor is built. A
|
|
296
|
-
bridge closing an outline borders the floor and is no wall: strips, blockers and doorways read the walls
|
|
297
|
-
as drawn. Walls that draw no outline leave the layer with walls but no floor (`floor-not-built`, cause
|
|
298
|
-
`outline-open`).
|
|
299
|
-
|
|
300
|
-
### Entrances go through the walls
|
|
301
|
-
|
|
302
|
-
An `entrance` destination (`openings.ts`) is a way into the building. The walls stay whole — the
|
|
303
|
-
walkable area, the blockers and the invariants read them as drawn — and the entrance gets an opening:
|
|
304
|
-
a doorway it owns, standing on the floor half a person past the wall's thickness, from which its dock
|
|
305
|
-
runs back through the wall. That dock is the one line that may cross a wall, and only inside the
|
|
306
|
-
opening's span (`Blockers.passes`); the entrance is reached through its openings alone, never from a
|
|
307
|
-
face. An opening on a doorway the walls already leave is that doorway.
|
|
308
|
-
|
|
309
|
-
- **Across a wall**: every wall piece inside the entrance's bounds (`dock`, else `polygon`) is an
|
|
310
|
-
opening, through its middle, onto each side with floor behind the wall. Pieces on one line (within a
|
|
311
|
-
wall's thickness) are one opening, however many vertices or polylines draw the wall. A piece shorter
|
|
312
|
-
than a person makes no opening, nor does a wall with no floor on either side.
|
|
313
|
-
- **Outside the building**, across no wall: a doorway the walls already leave comes first — the
|
|
314
|
-
stretch of the building outline no wall runs along, at least a person wide, nearest the entrance's
|
|
315
|
-
middle within 10 m (`ENTRANCE_REACH`), with floor behind it and no wall between; the dock runs through
|
|
316
|
-
it and crosses no wall. Only with no such doorway in reach: of the walls within 10 m of its bounds,
|
|
317
|
-
the one nearest to its middle that has floor and a person's clearance on the side away from the
|
|
318
|
-
entrance, with no other wall between, is the opening, where the bounds project onto it, at least a
|
|
319
|
-
person wide around the entrance's middle; the dock runs from it through the wall to the entrance. The
|
|
320
|
-
choice is deterministic, so an entrance between two buildings joins the nearer one. No wall in reach,
|
|
321
|
-
or none that qualifies (an outline that does not close, a second line right behind the wall), opens
|
|
322
|
-
nothing: the entrance is reported with the distance and whether such a wall was found
|
|
323
|
-
(`destination-unreached`, facts `nearestWall`, `floorBehind`), never joined by guesswork.
|
|
324
|
-
- Inside the building and across no wall, an entrance is reached like any POI (`entrance-no-wall`).
|
|
325
|
-
|
|
326
|
-
The graph invariants let an entrance's dock cross a wall (`line-crosses-wall` is not raised for a dock
|
|
327
|
-
that ends in an entrance); every other line keeps the rule.
|
|
328
|
-
|
|
329
|
-
### Route network: the steiner network
|
|
330
|
-
|
|
331
|
-
The raster router works on a soft-eroded clearance field (≥ 0.8 m free; 0.3–0.8 m passable at ~9× cost,
|
|
332
|
-
so a doorway is taken only when no wider path exists) with turn and wall-proximity penalties, which keeps
|
|
333
|
-
axes straight and centered. Doorways come from the gaps the walls leave: a gap counts when nothing is drawn
|
|
334
|
-
across its span — no wall, and no outline of a destination nobody walks through, unless that destination is
|
|
335
|
-
the one the doorway opens into. Gaps between two wall pieces on one line are read first; the line closing a polyline's own
|
|
336
|
-
ends counts where the polyline turns more than half a turn and neither end is already a jamb of such a gap.
|
|
337
|
-
A doorway opens into the destination whose outline it lies on or in; the one destination standing in the room the polyline encloses, POI walked through such as an exit or a stair left out — a room holding more is a hall, its door a way into the space the network reaches; or the outline straight ahead within a person's clearance. The passes, in order:
|
|
338
|
-
|
|
339
|
-
1. **Directions, mask and router** (`floor-grids.ts`, `mask.ts`, `router.ts`) — the directions the destinations are drawn in (`geom/frames.ts`: each by
|
|
340
|
-
its longest side, two sides being one direction while the raster cannot tell them apart along their
|
|
341
|
-
length; a destination whose reach — a stub's length around it — meets no other's of the same direction
|
|
342
|
-
is a stand set at an angle and opens none, and so do stands turned in a hall drawn square: the hall is
|
|
343
|
-
read from the first wall along each of the direction's four ways from each stand's middle, by the length
|
|
344
|
-
that runs along the direction against the length along the plan's axes). For each, the walkable rings without the pieces of floor
|
|
345
|
-
nobody stands in (no destination, no transition stop), a clearance field, and a coarser router grid whose
|
|
346
|
-
seams block steps across thin walls — the plan's own grid over the whole floor, a turned direction's over
|
|
347
|
-
its destinations and their reach. The router walks all the grids as one: a cell with room to turn steps
|
|
348
|
-
onto the same spot of another grid at the cost of a turn (anywhere, on a grid with no room to turn), so
|
|
349
|
-
along an aisle the grid of its own direction wins, running straight where the others climb stairs. A
|
|
350
|
-
doorway is open only at its middle — one person's clearance and a cell either side; the rest of the gap is
|
|
351
|
-
closed in the mask and blocked like the wall beside it. Every doorway's throat counts a person's
|
|
352
|
-
clearance at its middle, however narrow the gap, so a route can pass a door the wall's own thickness
|
|
353
|
-
would otherwise strangle.
|
|
354
|
-
2. **Stubs** (`stubs.ts`) — every way into a destination (`entries.ts`, over `blockers.ts` and `strip.ts`: each edge with room in front of it and every
|
|
355
|
-
doorway that opens into it, measured by exact rays rather than raster probes; a destination with a
|
|
356
|
-
docking ring is entered from the ring's sides, a doorway dock runs along the doorway's normal, or else to
|
|
357
|
-
the ring side facing it) gets a stub, one per side (one in all for a `terminal` destination, doorways
|
|
358
|
-
first): square out of the face to the middle of the aisle ahead, so the stubs from both sides of an
|
|
359
|
-
aisle meet on one line. The aisle is as wide as what stands across the face — other destinations'
|
|
360
|
-
outlines, or wall lines (their doorways included) that a destination entered through doorways lines
|
|
361
|
-
within a person's width behind them — over half the face's width or more (a doorway reads its own
|
|
362
|
-
width), so a room corner or a gap in the row across does not set it, and a hall wall has no row
|
|
363
|
-
across. The stub runs to the middle when the rows on both sides may run that far: a row is two or
|
|
364
|
-
more ways whose aisle middles lie on one line, however their fronts step, and its stubs may run past
|
|
365
|
-
their own length while the run is still a stub (at most `MAX_STRETCH` more of its own length) and
|
|
366
|
-
the detour that adds for two neighbors along the row, out and back, stays within `MAX_STRETCH` of
|
|
367
|
-
the walk along their fronts — the row's pitch. A lone face has no row to share a line with (the side
|
|
368
|
-
across answers by its face alone when it has no row), and an aisle narrower than a person is none.
|
|
369
|
-
Otherwise — open floor, a hall wall, a row across that may not — the stub is half the free run and
|
|
370
|
-
its own length at most. Each with a lawful dock from there; the dock is one straight run from the
|
|
371
|
-
tip to its end. A way in whose dock would cross a wall,
|
|
372
|
-
another destination's outline or a doorway is not laid at all, and the destination is reported with a
|
|
373
|
-
reason.
|
|
374
|
-
3. **Aisle axes** (`axes.ts`; `stubs.ts` defines them from the stubs and runs the stubs to them) — per
|
|
375
|
-
direction, tips the raster cannot tell apart across (one cell) lie on
|
|
376
|
-
one row; a row's line reaches along as far as a person walks beyond its end tips (a strip half a
|
|
377
|
-
person wide either side, clear of walls, outlines and doorways, and never past the floor's own
|
|
378
|
-
size). Rows within one aisle's width (twice the clearance) of each other whose lines' reaches
|
|
379
|
-
overlap along share an axis when one line may serve them all — no nearer than a comfortable
|
|
380
|
-
clearance to any tip's face or to what stands across it; a row whose tips' bands share no line is
|
|
381
|
-
bounded by the tips themselves — at the lower median of their tips across, within that. The stubs that end mid-aisle
|
|
382
|
-
define the aisles' lines first; a stub with open floor ahead runs to such a line ahead of it when no
|
|
383
|
-
corridor fits between the two or its row may run that far, and the rest line up among themselves.
|
|
384
|
-
Each stub then runs to its aisle's axis when its dock stays lawful, over floor only. Destinations
|
|
385
|
-
people walk through frame nothing.
|
|
386
|
-
4. **Rows, rungs and perimeters** (`framing.ts`) — the row along each axis between neighboring tips (a tip
|
|
387
|
-
that could not reach the axis gets a leg to it); a rung between two stubs that face each other on one
|
|
388
|
-
line across an aisle — the shortest way between the two stands, and the line both stubs run along —
|
|
389
|
-
laid onto an aisle's axis running their way within a corridor's width when there is one (legs bring
|
|
390
|
-
the tips over, and only the parts its row has not laid yet), so an aisle keeps one line; and each
|
|
391
|
-
destination's tips chained into a perimeter with square corners, along the direction's axes. A link
|
|
392
|
-
is laid wherever the floor is free, at any length.
|
|
393
|
-
5. **Growth** (`connect.ts`; each path laid by `place-path.ts`, its runs placed by `runs.ts`) — one search
|
|
394
|
-
over the raster from the largest piece of the network to every
|
|
395
|
-
other piece and every tip standing off it, reseeded from what it cannot reach, so islands the main
|
|
396
|
-
network cannot reach still meet. Every straight run of a path is laid on the line its place defines —
|
|
397
|
-
the doorway's middle where it passes one, its aisle's axis, else the middle of its corridor (nearest
|
|
398
|
-
blocker each side along its whole length; an open hall wider than the run is long has none). A run is
|
|
399
|
-
pulled no farther than a tip stands from its axis plus half a cell (the clearance plus half a pitch),
|
|
400
|
-
and "along" or "across" is read as the raster tells directions apart over the length in question. Each
|
|
401
|
-
end meets what it joins at a node: square across the line its own line meets, along a line running the
|
|
402
|
-
same way, else by an elbow. A piece the router cannot reach — its cells too tight, or claimed by
|
|
403
|
-
another piece — is tied by an elbow from one of its nodes, else by a raster path from its own cells.
|
|
404
|
-
The pieces the growth and the ties could not join are returned as a count and land in
|
|
405
|
-
`stats.untiedPieces`.
|
|
406
|
-
6. **Attach** (`attach.ts`) — each stub ends where it first meets the network: a line, or another stub, which then
|
|
407
|
-
ends there too, so the meeting is a node. A stub that has attached is a whisker (`Whisker`, and `anatomy.whiskers` in the
|
|
408
|
-
debug artifacts): its foot on the face, its tip a node of the network. A stub that meets nothing is taken to the network by an
|
|
409
|
-
elbow to the nearest line a free way reaches, else by a raster path laid like a growth path; a stub
|
|
410
|
-
whose tip no line can reach is reported with a reason. Then every line that ends nowhere goes: growth
|
|
411
|
-
reached tips whose stubs met a nearer line, and a dangling end that is no tip serves nothing.
|
|
412
|
-
7. **`completeLines`** (`post-passes.ts`) — a dangling end along an axis of any direction is extended to the first line it
|
|
413
|
-
meets, until no end is left to extend.
|
|
414
|
-
8. **`shortcutDetours`** (`post-passes.ts`) — a link is cut in where the walk along the network is over twice the walk
|
|
415
|
-
across the floor, one link per network point; laid like a growth path. No link laid after the attach
|
|
416
|
-
crosses a stub short of its tip: a route would walk past that destination and back. The links cut
|
|
417
|
-
in are returned as a count and land in `stats.shortcuts`.
|
|
418
|
-
9. **Emit** (`emit-network.ts`) — a doorway dock that turns for a side of its ring gets a line of the network from its tip to
|
|
419
|
-
the doorway's middle and leaves from there; `splitCrossings` (`geom/split-crossings.ts`) makes every
|
|
420
|
-
meeting a vertex; the docks are drawn from the tips into the destinations. A straight run is emitted as
|
|
421
|
-
one line through every meeting on it (`joinStraightRuns`, `network-graph.ts`): an aisle is one line, movable as one in the editor, the stubs
|
|
422
|
-
meeting it end on its span, and two aisles cross whole. The converter cuts a line where another
|
|
423
|
-
ends on it or crosses it when it builds `wf.data.js`. Of the network's pieces, the one with most docks is
|
|
424
|
-
emitted, and each further piece only when it docks a destination no emitted piece does — a piece the
|
|
425
|
-
floor cuts off serves what nothing else can, and nothing else. Every destination without a dock is
|
|
426
|
-
listed in `stats.unreached` with why, and with the facts the stage proved: whether it stands outside
|
|
427
|
-
the building, where the failing way in ends, and which emit check took a `detached` one's whisker.
|
|
428
|
-
Besides `unreached` and `components`, `stats` carries the layer's counts: the doorways found
|
|
429
|
-
(`doorways`), the shortcut links (`shortcuts`), the pieces left untied (`untiedPieces`, only when
|
|
430
|
-
some are), and the walkable floor pieces no destination or doorway serves (`unservedFloorPieces`,
|
|
431
|
-
likewise).
|
|
432
|
-
|
|
433
|
-
Network sizes: fixed in `network-sizes.ts` (`NETWORK_SIZES`), validated on the fixture plans. Every
|
|
434
|
-
other distance the stage reads is derived from them or from the plan: the raster cell for what lies on
|
|
435
|
-
one line, the clearance for what shares an aisle, exact rays for how far a line reaches; the shortcut
|
|
436
|
-
limits (`MAX_STRETCH` and the pass budgets) are the one open item.
|
|
437
|
-
|
|
438
|
-
## Boundaries
|
|
439
|
-
|
|
440
|
-
- **Pure & deterministic.** No I/O, no globals, no framework coupling — safe in Node and the browser.
|
|
441
|
-
- **Geometry cleanup is owned here.** Mechanical normalization of the raw geometry (vertex dedup,
|
|
442
|
-
run splitting, collinear collapse) happens in this compiler, not in the data pipeline.
|
|
443
|
-
- **Boolean ops isolated.** All `clipper2-ts` calls sit behind the internal `BooleanOps` adapter
|
|
444
|
-
(`geom/clipper2-ops.ts` is the only module importing clipper) — swapping the backend is one file.
|
|
445
|
-
- **Self-contained geometry.** Coordinate primitives (`Ring`, `Vec2`) live in `geom/types.ts`;
|
|
446
|
-
`clipper2-ts` is the package's only runtime dependency besides `tslib`.
|
|
3
|
+
This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
|
package/package.json
CHANGED
|
@@ -1,37 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expofp/wayfinding-compiler",
|
|
3
|
-
"version": "0.0.0-
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
"homepage": "https://developer.expofp.com/",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"publishConfig": {
|
|
9
|
-
"access": "public"
|
|
10
|
-
},
|
|
11
|
-
"sideEffects": false,
|
|
12
|
-
"main": "./dist/index.js",
|
|
13
|
-
"module": "./dist/index.js",
|
|
14
|
-
"types": "./dist/index.d.ts",
|
|
15
|
-
"exports": {
|
|
16
|
-
"./package.json": "./package.json",
|
|
17
|
-
".": {
|
|
18
|
-
"@expofp/source": "./src/index.ts",
|
|
19
|
-
"types": "./dist/index.d.ts",
|
|
20
|
-
"import": "./dist/index.js",
|
|
21
|
-
"default": "./dist/index.js"
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"clipper2-ts": "2.0.1-18",
|
|
26
|
-
"tslib": "^2.3.0",
|
|
27
|
-
"@expofp/wayfinding-geometry": "0.0.0-experimental.3b0db16"
|
|
28
|
-
},
|
|
29
|
-
"files": [
|
|
30
|
-
"dist",
|
|
31
|
-
"!**/*.tsbuildinfo",
|
|
32
|
-
"!**/*.map"
|
|
33
|
-
],
|
|
34
|
-
"nx": {
|
|
35
|
-
"targets": {}
|
|
36
|
-
}
|
|
3
|
+
"version": "0.0.0-stage",
|
|
4
|
+
"stub": true,
|
|
5
|
+
"description": "Temporary package placeholder for staged publishing"
|
|
37
6
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export { compileWayfinding } from './lib/compile-wayfinding.js';
|
|
2
|
-
export type { SourceDestination, SourceTransition, SourceTransitionPoint, WayfindingLayerSource, WayfindingSource, } from './lib/types.js';
|
|
3
|
-
export type { WfV1Graph, WfV1Line, WfV1Point } from './lib/types.js';
|
|
4
|
-
export type { SourceIssue } from './lib/validate-source.js';
|
|
5
|
-
export { validateWayfindingSource } from './lib/validate-source.js';
|
|
6
|
-
export type { CompileOptions, CompileProgress, CompileResult, LayerDebug, WayfindingDebugResult, } from './lib/compile-wayfinding.js';
|
|
7
|
-
export type { Diagnostic, Highlight, Severity, SourceRef, Stage } from './lib/diagnostics.js';
|
|
8
|
-
export type { WallLine } from './lib/geom/normalize.js';
|
|
9
|
-
export type { RouteNetwork, RouteNetworkDock, UnreachedReason } from './lib/graph-types.js';
|
|
10
|
-
export type { NetworkPart, PoiBinding, PoiRef, Reachability } from './lib/reachability.js';
|
|
11
|
-
export type { CompileReport, Outcome, Problem, ProblemKind } from './lib/report.js';
|
|
12
|
-
export type { WalkableArea } from './lib/walkable.js';
|
|
13
|
-
export type { Ring, Vec2 } from './lib/geom/types.js';
|
|
14
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
DELETED
package/dist/lib/attach.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { Connector } from './connect.js';
|
|
2
|
-
import { type Whisker } from './entries.js';
|
|
3
|
-
import type { Segment } from './geom/types.js';
|
|
4
|
-
import type { NetworkBuild } from './network-build.js';
|
|
5
|
-
import type { NetworkStore } from './network-store.js';
|
|
6
|
-
import type { Router } from './router.js';
|
|
7
|
-
import { type StubPlan } from './stubs.js';
|
|
8
|
-
/**
|
|
9
|
-
* The first network line a ray meets. A line lying along the ray is met at its nearer end when that is
|
|
10
|
-
* ahead, else at its far end.
|
|
11
|
-
* @param store The network.
|
|
12
|
-
* @param ox Ray origin x.
|
|
13
|
-
* @param oy Ray origin y.
|
|
14
|
-
* @param nx Ray direction x.
|
|
15
|
-
* @param ny Ray direction y.
|
|
16
|
-
* @param maxT How far to look.
|
|
17
|
-
* @returns The segment id and distance, or null within `maxT`.
|
|
18
|
-
*/
|
|
19
|
-
export declare function firstNetworkAlong(store: NetworkStore, ox: number, oy: number, nx: number, ny: number, maxT: number): {
|
|
20
|
-
id: number;
|
|
21
|
-
t: number;
|
|
22
|
-
} | null;
|
|
23
|
-
/** What attaching the stubs reads and extends. */
|
|
24
|
-
interface Attaching extends NetworkBuild {
|
|
25
|
-
/** The stubs planned, and how to retry one that fails. */
|
|
26
|
-
readonly plan: StubPlan;
|
|
27
|
-
/** The network; extended in place. */
|
|
28
|
-
readonly store: NetworkStore;
|
|
29
|
-
/** Lays the links and the raster paths. */
|
|
30
|
-
readonly connector: Connector;
|
|
31
|
-
/** The raster router. */
|
|
32
|
-
readonly router: Router;
|
|
33
|
-
/** Whether a line may be laid. */
|
|
34
|
-
readonly mayLay: (seg: Segment) => boolean;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Attaches every stub to the network, retrying a destination's next way in when one fails.
|
|
38
|
-
* @param attaching What the attach reads and extends.
|
|
39
|
-
* @returns The whiskers: the stubs attached, in the order they attached.
|
|
40
|
-
*/
|
|
41
|
-
export declare function attachStubs(attaching: Attaching): Whisker[];
|
|
42
|
-
export {};
|
|
43
|
-
//# sourceMappingURL=attach.d.ts.map
|