Error for an unknown mode or an invalid reach (SectionPlane.setAnnotationReach)
Whether the end caps draw each object's cap style (Viewer3d.setCapStyles: a pattern per kind of
material at a spacing fixed on screen) with cut outlines around the caps and between their objects: the
realtime setting experimentalCapStyles, switched while the viewer runs. Starts from that setting, false
without it. With objectEndcaps the patterns lie over the objects' colours. Viewer3D draws only its uniform hatch
Whether the cut surfaces are closed with end caps
Enabled/disable hatching of section plane end-caps
Whether the end caps take the colours of the objects they cut (with their hover and selection tints), and a
pick on a cap finds that object at the point on the cut: the realtime setting experimentalObjectEndcaps,
switched while the viewer runs. Starts from that setting, false without it
Show or hide the drag icons of the section planes. A plane that is hidden (SectionPlane.setVisible) shows no icon either way
Whether another plane fits: false while all six slots cut, as they do with a section box. The face widget and Ctrl + left drag then start nothing; startPlaneAt and startStandardPlane still replace the plane that cuts with their normal, and a standard plane that cuts already can still be put back.
Optionalnormal: vec3Whether a plane with this normal fits: also while all six cut, when one of them cuts with this normal (within 1°), as the new plane then takes its slot. Need not be unit length
Disable all the active section planes, this removed the actual section plane cutting, and the visualisations of the planes
The plane in a slot (0..5) of the six section-plane slots, whether it cuts or not. Which slot a plane takes depends on what cut before; getPlanes lists the planes that cut
The icon markup as last passed to setIcon, or DEFAULT_SECTION_PLANE_ICON
The planes that cut the model now, oldest first: single planes and the faces of a box alike. A new array; the planes in it are live, and stop cutting when disabled (SectionPlane.disable). For a list a user interface shows, kept current with onPlanesChange.
The widget that previews a section plane on the face under the cursor, armed by startFaceTouchOff or while Ctrl is held. With Ctrl held over an object it shows where a new plane goes, over a section plane where no object is that plane is grabbed instead; a plane's icon grabs it anywhere.
How the planes and the box cut the model now, as a value to give back to setState later: a tool
that cuts the model for a while (the clash view's section box) saves the user's own planes this way and
restores them when it is done. Render frame, mm. A box from startSectionBox is box, with
planes empty; anything else (single planes, or the six planes of a box from startSectionBoxFromObb)
is the enabled planes.
A new value: changing it changes nothing, and later changes to the planes do not show in it
Whether the default icon is showing
fn(enabled) is called whenever the model goes from no section to at least one section plane or box, or back
A function that unsubscribes
fn is called whenever the list of getPlanes changes: a plane started or put back, removed, renamed, hidden or shown (SectionPlane.setVisible), a box started. Not while a plane is dragged.
A function that unsubscribes
Replace the drag icon every section plane shows, including planes already on screen. Pass SVG markup of a single-colour filled glyph; any viewBox works (it is scaled to fit and centred), and its own colours are replaced by the icon colour (white on the section plane blue), so a stroke-only drawing with fill="none" will be filled in. Scripts and event-handler attributes are removed. Pass null to restore the default icon (DEFAULT_SECTION_PLANE_ICON).
Cuts the model exactly as state says: every plane and box is disabled first, then the box or the planes of
the state are started again, each plane in its slot with its widget sized to the loaded models, with the
annotation mode new planes start with, its name and standard plane, drawn or hidden, in the order of the state.
A plane without a name gets a new plane's name, one without visible is drawn. A state without planes and box
only disables. Of planes with the same normal (within 1°) only the one that cuts furthest is started, in its
slot: it cuts away all the others did. setState(getState()) changes nothing visible.
Error when a plane's index is not 0..5, or a coordinate, normal or box corner is not three finite
numbers, or a normal is zero, or a name is not a string with more than white space, or a standard plane is not
a StandardSectionPlane, or visible is not a boolean, or a box's hidden is not an array of
StandardSectionPlane; nothing is changed then
The standard plane the slot of an index (0..5) used to hold: top, bottom, left, right, front, back
startStandardPlane, which also returns the plane; the plane no longer goes into that slot
startStandardPlane("back")
The SectionPlane, or null when no model is loaded or no plane fits
startStandardPlane("bottom")
The SectionPlane, or null when no model is loaded or no plane fits
Arm the face widget: the next click on a surface places a new section plane there and drags it (Sections › Face in BIM.works). getSectionPlaneWidget().deactivate() disarms it without placing one. Does nothing while no plane fits (canStartPlane).
startStandardPlane("front")
The SectionPlane, or null when no model is loaded or no plane fits
startStandardPlane("left")
The SectionPlane, or null when no model is loaded or no plane fits
Start a new SectionPlane through a point, cutting away everything on the side the normal points to. Given a PickResult it starts a plane on the picked face, which is what the "Section plane" entry of the BIM.works context menu does: a picked normal faces the camera, so the plane cuts away what lies on the camera's side of the face. The user then drags the plane by its icon.
Every call starts a new plane, as Ctrl + left drag and the face widget do, named "Plane 1", "Plane 2" and so on (the lowest number no other plane has; SectionPlane.setName renames it). It replaces the plane that cuts with the same normal (within 1°), a standard plane too, taking its slot; else it takes the next free slot. The other planes stay. The drawn plane is sized to the main bounds of the loaded models.
A point on the plane in render space (millimetres, globalBaseTranslation included), as PickResult.coordinate
Points to the side that is cut away; need not be unit length. As PickResult.normal
The SectionPlane, or null when no model is loaded or no plane fits (canStartPlane with this normal)
A context menu with a "Section plane" entry for the face that was right-clicked, the same
behaviour as the BIM.works app. showMenu(x, y, items) stands for your own menu component.
const viewer = new Viewer3d(objectStateManager, undefined, {
// Called on the canvas' contextmenu event, after the viewer picked what is under the pointer
rightMouseClick: (event, qid, pick) => {
if (qid == null) {
return; // the BIM.works app only opens its menu over an object
}
showMenu(event.clientX, event.clientY, [{
label: "Section plane",
// A pick without a surface (no normal) cannot place a plane, and none fits while all six cut with other normals
enabled: pick.normal != null && viewer.getSectionPlanes().canStartPlane(pick.normal),
action: () => {
viewer.getSectionPlanes().startPlaneAt(pick.coordinate, pick.normal);
// Optional: the BIM.works app also clears the selection
objectStateManager.setToSelectionSet([]);
}
}]);
}
});
await viewer.initializeViewer();
Starts a plane in the slot of an index (0..5) through a point with a normal, in place of what cuts in that slot;
obb (from Viewer3d.getObjectsObb) limits its widget to that box, the models' box without one. The plane
is named as startPlaneAt names one. Another plane that cuts with the same normal (within 1°) is removed.
Prefer startPlaneAt, which takes a free slot or that of the plane with the same normal, and leaves the
user's other planes alone; an active box loses the coupling of its faces
startStandardPlane("right")
The SectionPlane, or null when no model is loaded or no plane fits
Start a SectionBox based on the axis aligned bounding box of all loaded models combined. Starting a SectionBox will clear all other section planes: its six faces take the six slots, and getPlanes lists them by the names of the standard planes they are ("Top", "Bottom", "Left", "Right", "Front", "Back"). Dragging a face resizes the box. Once a face is removed (SectionPlane.disable) or put back (startStandardPlane), the other faces stay where they are as planes of their own, and the box is no longer active.
OptionalboundingBox: AxisAlignedBoundingBox3D | { max: vec3; min: vec3 }An optional box (render space) around which the section box should initially be drawn, a box or a value such as Viewer3d.getObjectsAabb returns. When this is not provided, the main bounds of the loaded models will be used.
Optionaloptions: { padding?: number }padding: grow the box by this many mm on every side (0 when absent), so a box around an object or a clash keeps some context around it
The SectionBox
Starts a section box around a box from Viewer3d.getObjectsObb, or around the models' box without one; its faces as those of startSectionBox
Optionalobb: Obb | nullStart a standard plane on a face of the oriented box around the loaded models, named after it ("Top", ...). When that standard plane cuts already, it goes back to its place on the face instead, keeping its name, its place in getPlanes and whether it is drawn (SectionPlane.setVisible); otherwise it is a new plane, which replaces the plane that cuts with the face's normal (within 1°), taking its slot, or else takes the next free slot. When a SectionBox is active this puts that face of the box back (the box's faces are the six standard planes), and its other faces stay, as planes of their own.
Optionaloptions: { coordinate?: vec3; obb?: Obb | null }coordinate: a point the plane goes through instead of the face's centre, the normal staying that of the face (a top plane at a storey's elevation); obb: the box the drawn plane is sized to, from Viewer3d.getObjectsObb, the models' box without one
The SectionPlane, or null when no model is loaded or no plane fits (canStartPlane)
Error for a side that is not a StandardSectionPlane
startStandardPlane("top"): a plane on the top of the oriented box around all loaded models combined
The SectionPlane, or null when no model is loaded or no plane fits
The annotation mode and reach every newly started plane or box begins with: the starters, startPlaneAt(), Ctrl + drag and the face widget, startSectionBox(). For the planes a user draws, which no code gets to set afterwards. Setting it leaves the planes already started alone; a field left out keeps its current value. Starts from the realtime settings sectionPlaneAnnotationMode and sectionPlaneAnnotationReach, {mode: "hide", reach: Infinity} without them.