Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 124 additions & 42 deletions docs/ModellerGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,40 +163,33 @@ transparent material at its true opacity, everything else is unaffected.

## What a wall is made of

A plain-looking wall box in the Modeller is real geometry, not a shortcut β€” the file itself only ever
described the wall as one outer shape plus a list of layer thicknesses, never as separate layer shapes.

Take a real one: the party wall between two Duplex units (`2O2Fr$t4X7Zf8NOew3FNbT`) is built from 7
layers β€” plasterboard (16mm), metal stud (41mm), block (193mm), an air gap (50mm), block again (193mm),
metal stud (41mm), plasterboard (16mm). That's real, measured construction. But the source file never
draws those 7 slabs as 7 shapes β€” it draws **one outer box** the size of the whole stack, and records the
7 thicknesses as a side list ("this box is made of, in order..."). The Modeller renders exactly what's
there: one box β€” 14 triangles for this wall (a perfectly plain box tessellates to 12, two per face on
six faces, and 35 of the Duplex's walls are exactly that; this one's outline carries two more). That's
not a placeholder standing in for the real wall. It *is* the real wall, drawn at the detail the file
actually authored.

You can tell a real box from a broken one by whether it can be cut. A door or window cut through a wall
only works if the wall has a real shape to cut β€” a stand-in box has nothing behind it to carve. In the
Duplex, 18 walls carry a door or window hole and each ends up with 28–120 triangles once the cut is
applied; that's proof the geometry underneath is real, not a fallback.
A real wall is not one solid lump β€” it is a stack of layers. Take the party wall between two Duplex
units (`2O2Fr$t4X7Zf8NOew3FKRH`): it is built from 7 layers β€” plasterboard (16mm), metal stud (41mm),
block (193mm), an air gap (50mm), block again (193mm), metal stud (41mm), plasterboard (16mm), 550mm in
all. The source file draws that wall as **one outer shape** and keeps the 7 thicknesses in a side list
("this shape is made of, in order..."). The Modeller reads that list and draws the wall as **7 real
slabs**, one per layer, each at its own measured thickness.

Two of the Duplex party walls (`2O2Fr$t4X7Zf8NOew3FNbT` and its twin `2O2Fr$t4X7Zf8NOew3FKRi`) show
**5 slabs, not 7** β€” and that is correct. The source file itself trims off the neighbour-side stud and
plasterboard, because those belong to the wall on the other side. The Modeller draws the 5 layers that
are really there (493mm) and makes up nothing for the 2 that aren't.

On Duplex, 50 of its 57 walls draw as layer stacks this way. The other 7 are not authored with more than one
layer, so they stay one plain box β€” which is exactly what their source says. Floor slabs and coverings carry layers
too.

**No layers, no stand-in.** If an element is authored with several layers but its layer slabs can't be
found, the Modeller does not draw a plain box in its place β€” it leaves that element out and reports it by
name in the browser console.

**Only Duplex, for now.** Duplex is the only resident that ships its layer data today. The other
residents still draw each wall as the one outer shape its file gives β€” real geometry at the detail the
file authored, not a placeholder.

**Why the Viewer looks richer on the same building.** Open Duplex in the Viewer and you'll see far more
going on β€” because the Viewer loads everything the Modeller deliberately doesn't: pipes, ducts, and other
services (904 extra parts). The walls themselves are identical in both β€” same boxes, same 12 triangles
each. The Modeller is scoped to architecture + structure by design; it isn't missing wall detail the
Viewer somehow has.

**Why a July fix looked dramatic on one building and invisible on another.** An earlier pass removed
*fake* placeholder boxes β€” geometry the pipeline invented when it couldn't resolve a real shape. On one
test building (heavily irregular massing) that fix visibly cleaned up the model. On the Duplex it changed
nothing you could see, because a plain wall's honestly-tessellated box and a fake placeholder box are both
12 triangles β€” removing the fake ones simply left the real ones exactly as they were.

**What changes next.** The file-side link from a wall to its own layer list is now extracted
(`rel_material_layer_set`), so the data needed to draw those 7 slabs individually β€” instead of one box β€”
already exists. Once that slicing ships (Β§LOD400-LAYERS-REAL), this same party wall will render as 7
stacked slabs whose thicknesses sum to the wall's true 550mm, not a single block.
services (904 extra parts). The Modeller is scoped to architecture + structure by design.

---

Expand Down Expand Up @@ -284,7 +277,8 @@ The profile is swept along the spine (an occt pipe) as one signed op β€” the way
![Select the wall to open](img/modeller/cut-select.png)

The opening shows immediately; undo closes it to the exact original frame. (Cutting a seeded ARC wall
promotes its measured box to a B-rep just-in-time, so the subtraction is exact β€” never approximated.)
promotes it to a B-rep just-in-time β€” from its measured box, or, on a layered wall, from its real layer
slabs β€” so it is never approximated. See [What a wall is made of](#what-a-wall-is-made-of).)

![Cut β€” a signed opening void subtracted from the wall](img/modeller/cut-open.png)

Expand All @@ -311,7 +305,13 @@ the building's own recovered relationships before it settles: a hosted door ride
than divorcing from it, and a delta-based conformity gate flags only what the edit actually broke (RED)
or softly disturbed (ORANGE) β€” never a pre-existing condition the building already shipped with. That
combination β€” open a *complete, real, production* IFC and safely edit *part* of it β€” is what a
Bonsai/FreeCAD-style direct editor doesn't do. Full dated disclosure:
Bonsai/FreeCAD-style direct editor doesn't do.

Which elements touch which is worked out from each element's **real shape, where it actually sits** β€” not
from a rough box around its insertion point, which could land up to about 0.4 m off. (Before this was
fixed on 18 September 2026, a gridline drag on a real building could leave its walls where they were.)

Full dated disclosure:
**[Event-Sourced Geometry & the Graph-Cascade Conformity Layer](ModellerKernelFold.md)**.

Select an element and tap **Move** to raise the **transform gizmo** β€” the shared handle for moving,
Expand Down Expand Up @@ -398,6 +398,19 @@ modeller says so rather than inventing one. In practice that means the relations
*SampleHouse* (all 7 hosted openings) and *Duplex* (36 of its 38), and partial on *SampleCastle*, whose
window-frame walls are consumed by their own openings and so aren't separate things to hold or ride.

Since 18 September 2026 four more residents carry it too, so a door or window there holds or rides
its wall the same way:

| Resident | Doors & windows that hold or ride their wall |
|---|---:|
| HHS Office | 99 |
| Clinic | 302 |
| Hospital | 506 |
| HospitalGarage | 36 |

**Terminal is the one exception.** Its source file never says which door or window sits in which wall, so
there is nothing real to hold or ride β€” the Modeller leaves it that way rather than guessing.

**A carved hole comes along too.** If the held or ridden opening has a real cut-through void (a door or
window opening actually subtracted from the wall, not a catalog frame sitting in front of it), the hole
itself is kept in sync with it β€” its centre never drifts off the door under a stretch, its width is held
Expand Down Expand Up @@ -673,18 +686,22 @@ score: of the joins the walker drew, how many land on a real pipe touch.
| HHS_Office | office | out-of-domain | 1 380 | 0.620 | 0 |

The model **degrades gracefully** and never collapses. On **every** building **0 joins were fabricated** and
**0 exceeded the gap bound**. An ARC-only building with no pipes routes **0**, never a guess.
**0 exceeded the gap bound**. That table scores the walker against a building's *own* pipes. On an ARC-only
building there are none to join, so the walk **generates** plumbing instead β€” see *What a walk gives you now*
below.

### Walk them all at once

You don't have to pick the trades one at a time. Under **Not extracted β€” walk from …** in the Outliner,
the first row is **β–Άβ–Ά Walk ALL Disciplines**; its sub-label tells you how many trades the building is
missing (e.g. *4 not extracted Β· x-ray reveal*).
the first row is **β–Άβ–Ά Walk ALL Services**; its sub-label tells you how many service trades the building is
missing (e.g. *4 services not extracted Β· x-ray reveal*).

1. Open a bare ARC building.
2. Click **β–Άβ–Ά Walk ALL Disciplines**.
2. Click **β–Άβ–Ά Walk ALL Services**.

It walks every absent discipline in turn, through exactly the same production path a single click uses β€”
It walks every absent **service** (ACMV, ELEC, PLB, FP) in turn. Structure and roof plates are *not* part of
it: on a large building they are tens of thousands of elements (Terminal's roof alone is 10,584 plates), so
they keep their own rows and you walk them only when you want them. It works through exactly the same production path a single click uses β€”
same rules, same gating, same honest refusal when a trade has nothing to hang on. The difference is the
presentation: X-ray brackets the whole run so you can watch it land, and each discipline's placements
flash amber and settle into their own trade colour just before they're committed, so you can see *which*
Expand All @@ -694,6 +711,34 @@ X-ray is restored afterwards even if a discipline refuses part-way. On a very la
per-element flash is dropped in favour of one batched hold-and-settle β€” the geometry committed is
identical either way, only the reveal animation is coarser.

### What a walk gives you now β€” pipes, one-step undo, and pipes that follow

**Plumbing is routed, not just placed.** Walking **PLB** on a bare building now also draws the pipe runs
between the fixtures: cold water and waste. It works through the same path as any walk, measured on the real
Open β†’ Walk (`W-MEP-OPENPATH`):

| Building | PLB fixtures | Pipe runs drawn | Runs signed into the log |
|---|---:|---:|---:|
| Duplex | 18 | 18 | 18 |
| SampleCastle | 84 | 18 | 18 |
| Terminal | 969 | 2,915 | 60 (a size cap; every run is drawn) |

Typical run length is 2–3 m. The pipe sizes are real, measured from the Duplex plumbing model:
- cold water 25.4 mm (1β€³, the mains size; the Duplex also has Β½β€³ branches)
- waste 48.3 mm (1Β½β€³)

A pipe is never drawn at an invented size. Ducts (ACMV), cable (ELEC) and sprinklers (FP) are placed but not
yet routed.

**One Ctrl+Z takes the whole walk back.** A walk appears in the history as one step, e.g. *Walk PLB (45)*:
the fixtures, the pipe runs and their bend fittings together. `Ctrl+Z` removes all of it from the model and
the screen, and `Ctrl+Y` brings it all back (`W-WALK-GESTURE`).

**Move a fixture and its pipes follow.** Moving a walked fixture, by dragging it or a gridline, re-routes
that trade's pipes from the new positions (`W-MEP-REROUTE`: a 1 m move re-routes the Duplex network so a
run ends at the fixture's new spot). Undo the move and the pipes route back. Two limits for now: the re-routed
runs are shown but not signed, and the bend fittings from the original walk are not recalculated.

### Seed-Trunk β€” route a service trunk

After walking a discipline, route its **service trunk** from a real entry.
Expand Down Expand Up @@ -753,9 +798,45 @@ touching it further.

---

## Share an issue β€” BCF export
## Export β€” .db, IFC, or a BCF issue

Tap the **Export** pill. A small menu offers three things:

- **Native .db** β€” the full-fidelity signed op-log, every edit you made. Re-open it later with
**πŸ“‚ Open β–Έ local .db**.
- **IFC (IFC4)** β€” the building as a standard IFC4 file other BIM tools can read.
- **BCF issue (.bcfzip)** β€” your current view and selection, as an issue (see below).

### IFC β€” the whole building you opened

Export β–Έ IFC downloads `bonsai_model.ifc`. It carries **every element of the building you opened**, plus
the walls you drew with Sketch β†’ Extrude and the openings you Cut:

- Each element keeps its **real class** β€” a door stays an `IfcDoor`, a slab an `IfcSlab`, a stair an
`IfcStair`. A class the exporter doesn't know becomes a generic `IfcBuildingElementProxy`, never
dropped.
- Each element's **shape is the same triangles you see on screen**, written as an IFC4 triangle mesh β€” not
re-computed, not simplified.
- An element whose shape can't be found is **left out and counted**, never swapped for a plain box.
- The invisible ride anchors some buildings carry (SampleCastle has 65) are left out β€” they aren't real
building parts.

Checked by re-reading the exported file: Duplex's 196 elements come back as 196 products (about 4 MB);
SampleCastle's 3,225 come back as 3,225 (about 26 MB).

**Not in the file yet:** materials and colours, property sets, the storey/space structure, and openings as
separate cut objects. It carries the building's real shapes, not yet a fully furnished IFC.

Until 18 September 2026 this export wrote an **empty** file for any opened building β€” only drawn
geometry went in. If you have an old export of a resident, export it again.

The status line after an IFC export counts `walls=` only for walls you drew with Sketch β†’ Extrude, so on
an opened building it can read `walls=0` even though the file is full β€” check the byte count it prints
instead.

### BCF β€” share an issue

Tap the **BCF** pill to export your current view as a **BCF 2.1** file (`.bcfzip`) β€” the open
Pick **Export β–Έ BCF issue** to export your current view as a **BCF 2.1** file (`.bcfzip`) β€” the open
buildingSMART format for exchanging issues between BIM tools. The export carries your live camera
viewpoint and the real `IfcGuid`s of whatever's selected, so the file opens correctly in Navisworks,
Solibri, BIMcollab, Revit (via plugin), or Trimble Connect β€” never a synthetic ID that only means
Expand Down Expand Up @@ -790,9 +871,10 @@ The toolbar is a **β‹― pill rail** at the right edge: tap **β‹―** to fan the pil
| **Apply** | Commit the pending fillet / chamfer |
| **Insert** | Insert a library component β€” assemble, don't draw (`GEOM_INSERT`) |
| **LOD 200** | Refine the last-placed component's level of detail (same signed row) β€” appears once you enter **Insert**, not on the resting rail |
| **IFC** | Export the authored model as IFC4 |
| **Export** | Export menu β€” Native `.db` (the signed op-log), IFC4 (the whole opened building), or a BCF 2.1 issue (see [Export](#export-db-ifc-or-a-bcf-issue)) |
| **Save** | Clash-check + auto-heal, then write a physical-DB snapshot β€” blocks on residual RED (see [Save](#save)) |
| **History** | World History β€” the cross-page timeline shared with the Viewer, iDempiere, and Gravity |
| **Guide** | A short in-app user guide β€” how to Open, walk, edit & export |
| **? Help** | Toolbar & shortcuts β€” the live pill registry |
| **Delete** | Delete the selection (`Del`) |
| **Clear** | Empty the scene |
Expand All @@ -813,7 +895,7 @@ always a safe retreat.
| Symptom | Why | What to do |
|---|---|---|
| **A pill looks stuck in the top-left corner** and won't click | A mode-revealed pill (Extrude, Sweep-Run, Apply) is shown only after you start its mode; the rail lays them out on reveal. | Start the mode first (e.g. finish the Sketch before reaching for **Extrude**). The rail re-positions the pill as it appears β€” if one still looks stranded, toggle the **β‹―** rail closed and open. |
| **Cut / Scale seems to do nothing on a wall from an opened building** | A seeded ARC wall is a *baked* box, not a B-rep. Cut promotes it to a B-rep just-in-time so the subtraction is exact; a rotated/non-box insert is refused up-front (logged) rather than approximated. | Nothing to do for a normal axis-aligned wall β€” the op commits and renders. If a specific insert is *refused*, it isn't box-like enough to cut exactly; sketch the void instead. |
| **Cut / Scale seems to do nothing on a wall from an opened building** | A seeded ARC wall is a *baked* mesh, not a B-rep. Cut promotes it to a B-rep just-in-time β€” from its box, or on a layered wall from its real layer slabs; an insert that is neither a plain box nor layered is refused up-front (logged) rather than approximated. | Nothing to do for a normal axis-aligned wall β€” the op commits and renders. If a specific insert is *refused*, it can't be cut exactly; sketch the void instead. |
| **A Walk seems to hang on a big building** | A discipline walk places hundreds of fixtures; they commit as **one batched signed group**, so a large walk takes a couple of seconds, not a frozen minute. | Wait for the batch β€” the status line reports the result when it lands (e.g. `ELEC β€” 267 placed across 5 storeys Β· 0 routed`). Scrub the slider back to clear them. |
| **I want to "make an opening" but there's no Opening tool** | Opening is not a separate authoring tool β€” the real "cut a window/door" is the **Cut** tool (`GEOM_CUT`). | Select the wall, tap **Cut**. `GEOM_OPENING` is only a legacy sample primitive, never a user action. |
| **Fillet won't pick an edge** | Fillet needs a **B-rep solid**; a seeded ARC insert has no worker edges to round. | Author a solid first (Sketch β†’ Extrude), select it, then **Fillet** β€” its edges become pickable markers. |
Expand Down
Loading