derive_transitions
Derive transitions between two finish types by comparing every room of each, committing where finishes touch in the same space and flagging wall-separated thresholds for manual confirmation.
Instructions
Mint the transition where two finishes MEET (#202) — the derivation that follows derive_base, and the line an estimator draws by hand on every job. Pass the two finish tags and the tag the transition commits under (e.g. condition_a 'CPT-1', condition_b 'PT-1', condition 'T-1'), and every committed room of each is compared against every committed room of the other.
WHAT THE GEOMETRY ACTUALLY IS, because it decides what you get back: flood-traced rooms DO NOT SHARE EDGES. A trace fills to the wall linework, so two rooms across a partition are separated by four to eight inches of nothing — testing for a shared edge finds zero transitions on a real planset. What is there is proximity, in two flavours that mean completely different things:
• BUTT JOINT — the two rings run together inside ONE open space (a lobby that changes from carpet to tile with no wall between). The transition IS that run, and it commits as a linear shape under your tag, origin.derived naming both parent shapes and the measured gap.
• WALL-SEPARATED — the rings run parallel across a partition. The rooms are adjacent, but the transition is NOT the shared wall: it is a threshold, in the doorway, and NOTHING in the trace record says where the doorway is (the flood engine seals openings and reports how MUCH boundary it synthesised, never where). Committing 34 LF of threshold because two rooms share 34 LF of wall would be a wrong bid with a machine's confidence behind it. These come back in withheld — measured, with their length, their gap in inches, and an at point — as questions you answer by LOOKING (view_sheet at at, then measure_line or place_count the threshold yourself). The symbol_sweep doctrine: a near-match is never a silent commit and never a silent drop.
Tuning: max_gap_in (default 12) is how far apart two rings can be and still count as adjacent at all — raise it for thick walls, and every extra inch turns more of the plan into wall_separated questions, never into committed LF. min_run_in (default 12) drops corner artifacts. The butt-joint threshold is fixed at one inch and is not a knob: "these two finishes touch" is not a judgement call.
All-or-nothing, like derive_base: an unknown tag, a transition landing on either source tag, the same tag twice, or a sheet without a scale refuses the whole call before anything commits. The whole sweep is ONE undo step. After it, LOOK — view_sheet {overlay: true} over each run — before trusting total_lf. Coordinates are image px at render scale 2.0: PDF pt × 2, origin top-left, y down (the browser canvas's native space). Sheet payloads carry dims in both px and pt.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| condition | Yes | Finish tag the transitions commit under (minted on first use), e.g. 'T-1'. Must differ from both sources | |
| max_gap_in | No | How far apart two rings can be and still count as adjacent, in inches (default 12 — a thick partition). Wider only produces more wall_separated QUESTIONS, never more committed LF | |
| min_run_in | No | Shortest run worth reporting, in inches (default 12) — below this is a corner where two rooms clip, not a transition | |
| condition_a | Yes | First finish tag, e.g. 'CPT-1' — its committed rooms are walked, and runs are traced along their boundaries | |
| condition_b | Yes | Second finish tag, e.g. 'PT-1' |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| note | Yes | ||
| runs | Yes | ||
| between | Yes | The two finish tags | |
| total_lf | Yes | Sum of committed run lengths — butt joints only | |
| withheld | Yes | Adjacency across a wall: real, measured, and NOT committed — the transition there is a threshold at a doorway this cannot locate | |
| committed | Yes | ||
| condition | Yes | The tag the transitions committed under | |
| withheld_lf | Yes | Shared-wall length held back — never part of total_lf |