Appearance
Sections
Section lines and what they cut — the scriptable counterpart of the Section tool, the Sections list in the Views panel and a section's properties panel. Accessed via snaptrude.presentation.sections.
A section is a line drawn on the plan. Its cutting plane runs through the line, vertical, and the section looks one way along it; its view keeps depth behind the line, between base and top. Create, read, edit and delete sections, open a section's view, and ask what a section cuts with getCut. getCut is computed from the model: it needs no open view and changes nothing.
Positions are world coordinates in Snaptrude units (1 unit = 0.254 m, Y up; see snaptrude.core.units). A section's heads are plan points { x, z }.
At a glance
| Method | What it does | Mutates? |
|---|---|---|
list() | Every section, in Views panel order | — |
get(sectionId) | One section, or null | — |
getActive() | The section whose view is open, or null | — |
setActive(sectionId | null) | Open a section's view, or close the open one | — |
create(start, end, options?) | Draw a section line between two plan points | ✓ |
update(sectionId, patch) | Heads, flip, depth, vertical slice, name, mark, hidden | ✓ |
delete(sectionId) | Delete a section, closing its view if open | ✓ |
getCut(sectionId, options?) | Every element the section cuts, with area, outline and extent | — |
Undo and locking
Every write is one step of the model's undo history. Geometry edits (start, end, isFlipped, depth, base, top) are refused with PRECONDITION_FAILED on a locked section; names, marks and hiding are not, and a patch that repeats a locked section's geometry unchanged is not a geometry edit. View-only collaborators cannot write.
Direction
Unflipped, a section looks along its line's direction turned a quarter turn: a line drawn from { x: 0, z: 0 } toward { x: 10, z: 0 } looks toward +z. update(id, { isFlipped: true }) makes it look the other way. Flipping without a depth carries the depth to the far side of the model in the new direction, as create does; pass depth with the flip to set it yourself.
setActive(null) closes the open section view and returns to 3D; with no section view open it does nothing.
Reading a cut
getCut returns the cut in the plane's own frame. u runs along the line from the first head (0) to the second (the line's length); v is world Y. origin, uAxis and normal turn a (u, v) back into a world point: origin + u · uAxis + v · (0, 1, 0).
Each element carries:
area— the cut area inside the section's extents, exact for closed solids;perimeter— the length of the cut outline inside the extents;extent— where the cut lies on the plane. For a wall crossed square-on,extent.uMax − extent.uMinis its thickness; for a slab,extent.vMax − extent.vMinis;isHatched—falsefor masses and voids, which the section drawing leaves unfilled;isOpening— doors and windows, which the drawing fills white;segments— the outline itself as[u0, v0, u1, v1]segments, only whenmaxSegmentsPerElementasks for them.
Furniture is left out, as in the drawing, and so is anything hidden in the model (a hidden storey, a hidden element). Repeated calls reuse the cuts of elements that have not changed since the last call.
Types
PluginSection
| Property | Type | Description |
|---|---|---|
sectionId | string | The section's id |
name | string | Its name in the Views panel ("Section 1") |
tagLabel | string | What its heads are marked with on the plan ("A") |
buildingId | string | The building it belongs to |
start | PluginSectionPoint | First head on the plan |
end | PluginSectionPoint | Second head on the plan |
isFlipped | boolean | Looks the other way along the line |
depth | number | How far behind the line the view keeps |
base | number | Bottom of the slice, world Y |
top | number | Top of the slice, world Y |
isHidden | boolean | The line is hidden on the plan |
isLocked | boolean | Geometry edits are refused |
isActive | boolean | It is the section view open now |
PluginSectionCreateOptions
| Property | Type | Description |
|---|---|---|
name | string | undefined | Name in the Views panel (default: the next "Section N") |
tagLabel | string | undefined | Head mark on the plan (default: the next free mark) |
depth | number | undefined | View depth behind the line (default: to the far side of the model) |
base | number | undefined | Bottom of the slice, world Y (default: the building's base) |
top | number | undefined | Top of the slice, world Y (default: the building's top) |
buildingId | string | undefined | Building it belongs to (default: the active one) |
isActive | boolean | undefined | Open the section view once created (default false) |
PluginSectionPatch
Every field of PluginSectionCreateOptions except buildingId and isActive, plus start, end, isFlipped and isHidden; all optional.
PluginSectionCut
| Property | Type | Description |
|---|---|---|
sectionId | string | The section |
origin | { x, y, z } | World point at u = 0, v = 0: the first head, at Y 0 |
uAxis | { x, y, z } | Unit direction of u, from the first head to the second |
normal | { x, y, z } | Unit direction the section looks |
extent | PluginSectionExtent | The cut rect: u 0 to the line's length, v base to top |
elements | PluginSectionCutElement[] | What it cuts, largest area first |
candidateCount | number | Meshes near the plane that were tested |
durationInMs | number | Time the query took |
PluginSectionCutElement
| Property | Type | Description |
|---|---|---|
entityId | string | The element's component id |
type | string | Its component type ("wall", "slab", "mass", …) |
area | number | Cut area inside the extents, square Snaptrude units |
perimeter | number | Cut outline length inside the extents |
extent | PluginSectionExtent | { uMin, uMax, vMin, vMax } of the cut |
isHatched | boolean | false for masses and voids |
isOpening | boolean | Doors and windows |
segments | [u0, v0, u1, v1][] | Outline segments, when asked for |
droppedSegmentCount | number | Segments not returned because of maxSegmentsPerElement |
Worked example: what does a section cut?
ts
const section = await snaptrude.presentation.sections.create(
{ x: -40, z: 10 },
{ x: 40, z: 10 },
{ name: "Through the core" }
);
const cut = await snaptrude.presentation.sections.getCut(section.sectionId);
for (const element of cut.elements.filter((e) => e.type === "wall")) {
const thickness = element.extent.uMax - element.extent.uMin;
console.log(element.entityId, thickness.toFixed(2));
}
await snaptrude.presentation.sections.setActive(section.sectionId);