Skip to content

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 ​

MethodWhat it doesMutates?
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.uMin is its thickness; for a slab, extent.vMax − extent.vMin is;
  • isHatched — false for 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 when maxSegmentsPerElement asks 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 ​

PropertyTypeDescription
sectionIdstringThe section's id
namestringIts name in the Views panel ("Section 1")
tagLabelstringWhat its heads are marked with on the plan ("A")
buildingIdstringThe building it belongs to
startPluginSectionPointFirst head on the plan
endPluginSectionPointSecond head on the plan
isFlippedbooleanLooks the other way along the line
depthnumberHow far behind the line the view keeps
basenumberBottom of the slice, world Y
topnumberTop of the slice, world Y
isHiddenbooleanThe line is hidden on the plan
isLockedbooleanGeometry edits are refused
isActivebooleanIt is the section view open now

PluginSectionCreateOptions ​

PropertyTypeDescription
namestring | undefinedName in the Views panel (default: the next "Section N")
tagLabelstring | undefinedHead mark on the plan (default: the next free mark)
depthnumber | undefinedView depth behind the line (default: to the far side of the model)
basenumber | undefinedBottom of the slice, world Y (default: the building's base)
topnumber | undefinedTop of the slice, world Y (default: the building's top)
buildingIdstring | undefinedBuilding it belongs to (default: the active one)
isActiveboolean | undefinedOpen 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 ​

PropertyTypeDescription
sectionIdstringThe 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
extentPluginSectionExtentThe cut rect: u 0 to the line's length, v base to top
elementsPluginSectionCutElement[]What it cuts, largest area first
candidateCountnumberMeshes near the plane that were tested
durationInMsnumberTime the query took

PluginSectionCutElement ​

PropertyTypeDescription
entityIdstringThe element's component id
typestringIts component type ("wall", "slab", "mass", …)
areanumberCut area inside the extents, square Snaptrude units
perimeternumberCut outline length inside the extents
extentPluginSectionExtent{ uMin, uMax, vMin, vMax } of the cut
isHatchedbooleanfalse for masses and voids
isOpeningbooleanDoors and windows
segments[u0, v0, u1, v1][]Outline segments, when asked for
droppedSegmentCountnumberSegments 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);