
Thatopen Impl Clipping Plans
- 5 installs
- 17 repo stars
- Updated July 8, 2026
- openaec-foundation/thatopen-claude-skill-package
Helps with productivity & planning tasks.
About
thatopen-impl-clipping-plans is a Claude Code skill in the Productivity & Planning category.
- thatopen-impl-clipping-plans
- Productivity & Planning
- AI-coding skill
Thatopen Impl Clipping Plans by the numbers
- 5 all-time installs (skills.sh)
- Ranked #2,303 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Jul 26, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/thatopen-claude-skill-package --skill thatopen-impl-clipping-plansAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 17 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/thatopen-claude-skill-package ↗ |
What it does
Helps with productivity & planning tasks.
Files
ThatOpen Clipping Planes & Floor Plans
Overview
Clipping planes slice through 3D BIM geometry to reveal internal structure. Floor plan views combine clipping planes with styled edge visualization and a top-down camera. In ThatOpen v3, three components work together:
| Component | Package | Role |
|---|---|---|
Clipper | @thatopen/components | Creates and manages clipping planes |
ClipStyler | @thatopen/components-front | Adds styled edge/fill visualization to clips |
Views | @thatopen/components | Manages named section views with camera sync |
v2 to v3 BREAKING CHANGE: The Plans component and standalone ClipEdges component from v2 are removed. ALWAYS use ClipStyler + Views in v3. See the migration section at the bottom of this file.
Prerequisites
- World with
OrthoPerspectiveCameraand renderer (seethatopen-impl-viewer) - Model loaded via
FragmentsManager(seethatopen-syntax-ifc-loading) - For styled edges:
@thatopen/components-frontandLineMaterialfrom
three/examples/jsm/lines/LineMaterial.js
import * as OBC from "@thatopen/components";
import * as OBF from "@thatopen/components-front";
import * as THREE from "three";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";---
1. Clipper: Creating Clipping Planes
The Clipper component creates and manages SimplePlane instances that clip the scene geometry. It lives in @thatopen/components (works in browser and Node.js).
Setup
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;Interactive Creation (Raycast-Based)
Create a clipping plane where the user clicks on geometry:
container.ondblclick = () => {
if (clipper.enabled) {
clipper.create(world);
}
};create(world) casts a ray from the current mouse position, finds the intersection point and surface normal, and places a draggable plane there. Returns Promise<SimplePlane | null> (null if no intersection).
Programmatic Creation
Create a plane at an exact position and orientation:
const normal = new THREE.Vector3(0, -1, 0); // pointing down
const point = new THREE.Vector3(0, 3.5, 0); // at y=3.5m
const planeId = clipper.createFromNormalAndCoplanarPoint(world, normal, point);Returns the string ID of the created plane. Use this ID with ClipStyler.createFromClipping() to add edge visualization.
Deletion
// Delete plane under mouse cursor (interactive)
await clipper.delete(world);
// Delete a specific plane by ID
await clipper.delete(world, planeId);
// Delete ALL planes
clipper.deleteAll();
// Delete only planes of a specific type
clipper.deleteAll(new Set(["floor-plans"]));Keyboard Shortcut Pattern
window.onkeydown = (event) => {
if (event.code === "Delete" || event.code === "Backspace") {
clipper.delete(world);
}
};Properties
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enables/disables the clipper |
visible | boolean | true | Shows/hides all plane helpers |
size | number | 5 | Geometric size of plane helpers |
material | MeshBasicMaterial | — | Material for plane helpers |
orthogonalY | boolean | false | Forces planes orthogonal to Y |
toleranceOrthogonalY | number | 0.7 | Threshold for Y orthogonality |
autoScalePlanes | boolean | true | Scale planes based on camera distance |
Events
Key events (see references/methods.md for full list):
| Event | Payload | When |
|---|---|---|
onAfterCreate | SimplePlane | After plane is created |
onBeforeDrag | SimplePlane | Drag operation starts |
onAfterDrag | SimplePlane | Drag operation ends |
onAfterDelete | SimplePlane | After plane is deleted |
clipper.onAfterCreate.add((plane) => {
console.log("Created plane:", plane.three.normal, plane.three.constant);
});SimplePlane Instance
Each plane in clipper.list is a SimplePlane with properties: three (THREE.Plane), origin, normal, enabled, visible, size, type, controls (TransformControls). Key method: setFromNormalAndCoplanarPoint(normal, point) to reposition. See references/methods.md for full API.
---
2. ClipStyler: Styled Edge Visualization
ClipStyler adds colored edge outlines and fill materials to clipping planes. It lives in @thatopen/components-front (browser-only).
Setup
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;ALWAYS set .world before creating any styled edges.
Defining Styles
Styles are named combinations of line material and fill material:
clipStyler.styles.set("ArchBlue", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
fillsMaterial: new THREE.MeshBasicMaterial({
color: 0xadd8e6,
side: THREE.DoubleSide,
}),
});
clipStyler.styles.set("StructRed", {
linesMaterial: new LineMaterial({ color: 0xff0000, linewidth: 3 }),
fillsMaterial: new THREE.MeshBasicMaterial({
color: 0xffcccc,
side: THREE.DoubleSide,
}),
});ALWAYS define styles BEFORE calling any create* method.
Creating Styled Edges from a Clipping Plane
Link edge visualization to an existing Clipper plane by its ID:
// Listen for new clipping planes and auto-style them
clipper.list.onItemSet.add(({ key }) => {
clipStyler.createFromClipping(key, {
items: {
All: { style: "ArchBlue" },
},
});
});Creating Styled Edges from a View
Link edge visualization to a View (camera-synced section):
const views = components.get(OBC.Views);
const sectionView = views.create(
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 1.5, 0),
);
clipStyler.createFromView(sectionView, {
items: {
Walls: {
style: "ArchBlue",
data: { "BuildingElement.Class": ["IFCWALL", "IFCWALLSTANDARDCASE"] },
},
Structure: {
style: "StructRed",
data: { "BuildingElement.Class": ["IFCSLAB", "IFCCOLUMN"] },
},
},
});Creating Styled Edges from a Raw Plane
const rawPlane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 3.5);
const edges = clipStyler.create(rawPlane, {
items: { All: { style: "ArchBlue" } },
});ClipEdgesCreationConfig
interface ClipEdgesCreationConfig {
link?: boolean; // Auto-sync with source plane
id?: string; // Custom identifier
world?: OBC.World; // Override default world
items?: Record<string, ClipEdgesItemStyle>; // Named item groups
}
interface ClipEdgesItemStyle {
style: string; // Style name from clipStyler.styles
data?: OBC.ClassifierIntersectionInput; // Filter by classification
}Visibility Control
clipStyler.visible = false; // Hide all styled edges
clipStyler.visible = true; // Show all styled edgesSee references/methods.md for full ClipEdges instance API.
---
3. Views: Named Section Views
The Views component manages named orthogonal section views. Each view has a primary clipping plane, a far clipping plane, and a camera configuration.
Setup
const views = components.get(OBC.Views);
views.world = world;Creating Views
// From normal and point
const floorView = views.create(
new THREE.Vector3(0, -1, 0), // normal pointing down
new THREE.Vector3(0, 1.5, 0), // coplanar point at y=1.5m
{ id: "floor-1" },
);
// From a THREE.Plane
const plane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 1.5);
const sectionView = views.createFromPlane(plane, { id: "section-A" });
// From IFC building storeys (auto-creates one view per storey)
const storeyViews = await views.createFromIfcStoreys({
offset: 0.25, // 25cm above slab
});
// Elevation views (front, back, left, right)
const elevationViews = await views.createElevations({
combine: true, // merge all models into one bounding box
});Opening and Closing Views
// Open a view — switches camera to plan mode, enables clipping
views.open("floor-1");
// Close the active view — restores default camera
views.close("floor-1");
// Close any open view
views.close();
// Check if any view is open
if (views.hasOpenViews) { /* ... */ }View Instance
Key properties: id, plane (THREE.Plane), farPlane, camera (OrthoPerspectiveCamera), open (boolean), range (distance between front/back planes, default 15), planesEnabled, helpersVisible. Methods: update(), flip(), dispose(). See references/methods.md for full View API.
---
4. Complete Floor Plan Workflow
This is the canonical pattern for creating a floor plan view with styled edges.
import * as OBC from "@thatopen/components";
import * as OBF from "@thatopen/components-front";
import * as THREE from "three";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
// --- Assume world, components, and model are already set up ---
// Step 1: Configure ClipStyler with styles
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.styles.set("Default", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
fillsMaterial: new THREE.MeshBasicMaterial({
color: 0xf0f0f0,
side: THREE.DoubleSide,
}),
});
// Step 2: Create views from IFC storeys
const views = components.get(OBC.Views);
views.world = world;
const storeyViews = await views.createFromIfcStoreys({
offset: 0.25,
});
// Step 3: Add styled edges to each storey view
for (const [id, view] of views.list) {
clipStyler.createFromView(view, {
items: {
All: { style: "Default" },
},
});
}
// Step 4: Open a floor plan view (activates clipping + plan camera)
views.open("ground-floor");
// Step 5: Set orthographic projection for true 2D plan
await world.camera.projection.set("Orthographic");Returning to 3D
// Close the view (restores camera)
views.close();
// Switch back to perspective
await world.camera.projection.set("Perspective");
// Return to orbit navigation
world.camera.set("Orbit");---
5. Programmatic Section Workflow
For a quick section cut without the View system:
// Step 1: Enable clipper
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
// Step 2: Create plane programmatically
const planeId = clipper.createFromNormalAndCoplanarPoint(
world,
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 3.0, 0),
);
// Step 3: Add styled edges
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.styles.set("Section", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
});
clipStyler.createFromClipping(planeId, {
items: { All: { style: "Section" } },
});
// Step 4: Hide the plane helper (keep the cut visible)
clipper.visible = false;---
6. Per-Category Styling
Use multiple styles and ClipEdgesItemStyle.data to apply different edge colors per IFC element type. The data field uses ClassifierIntersectionInput (same format as Classifier.find()). See references/examples.md example 6 for full code.
---
7. v2 to v3 Migration
| v2 Pattern | v3 Replacement | Notes |
|---|---|---|
Plans component | Views + ClipStyler.createFromView() | Complete redesign |
ClipEdges component (standalone) | ClipStyler.create/createFromClipping() | Now managed by ClipStyler |
plans.create(planConfig) | views.create(normal, point) | Different API shape |
plans.goTo(planId) | views.open(viewId) | Renamed |
plans.exitPlanView() | views.close() | Renamed |
| Manual edge geometry | ClipEdgesCreationConfig | Declarative config |
clipEdges.visible = true | clipStyler.visible = true | Managed through ClipStyler |
NEVER use Plans or standalone ClipEdges imports — they do not exist in v3. ALWAYS use Views + ClipStyler for floor plan and section visualization.
---
Critical Rules
1. ALWAYS set clipStyler.world = world before creating styled edges. 2. ALWAYS define styles in clipStyler.styles before calling create*. 3. NEVER use Plans or standalone ClipEdges from v2 — they are removed. 4. ALWAYS use ClipStyler for edge visualization in v3. 5. ALWAYS call clipper.enabled = true before creating planes. 6. ALWAYS use views.open(id) to activate a view — it handles camera switching and plane activation automatically. 7. NEVER manually position the camera for floor plans when using Views — views.open() handles this. 8. ALWAYS dispose clipping resources when done: clipper.deleteAll() and clipStyler.dispose(). 9. ALWAYS use LineMaterial from three/examples/jsm/lines/LineMaterial.js for edge line styles — regular LineBasicMaterial does not support linewidth. 10. NEVER forget to await projection.set() — it returns a Promise.
Reference Files
- references/methods.md — Full API signatures for
Clipper, ClipStyler, ClipEdges, Views, View, SimplePlane
- references/examples.md — Basic clipping, floor
plan, styled edges, programmatic sections
- references/anti-patterns.md — v2 patterns,
missing ClipStyler setup, common mistakes
Source Verification
All API signatures verified against:
- GitHub:
ThatOpen/engine_componentsmain branch
(packages/core/src/core/Clipper/, packages/front/src/core/ClipStyler/, packages/core/src/core/Views/)
- Examples:
Clipper/example.ts,ClipStyler/example.ts - Research:
docs/research/vooronderzoek-thatopen.mdSections 2.6, 2.8, 6
Anti-Patterns — Clipping Planes & Floor Plans
1. Using v2 Plans Component
WRONG — Plans does not exist in v3:
// BROKEN — Plans is removed in v3
import { Plans } from "@thatopen/components";
const plans = components.get(Plans);
plans.create({ name: "Floor 1", ... });
plans.goTo("Floor 1");RIGHT — Use Views + ClipStyler:
import * as OBC from "@thatopen/components";
import * as OBF from "@thatopen/components-front";
const views = components.get(OBC.Views);
views.world = world;
const view = views.create(normal, point, { id: "floor-1" });
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.createFromView(view, { items: { All: { style: "Default" } } });
views.open("floor-1");---
2. Using Standalone ClipEdges from v2
WRONG — Standalone ClipEdges is removed:
// BROKEN — ClipEdges is not a standalone component in v3
const clipEdges = components.get(ClipEdges);
clipEdges.styles.create("Default", [], material);RIGHT — ClipEdges are managed through ClipStyler:
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.styles.set("Default", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
});
clipStyler.createFromClipping(planeId, {
items: { All: { style: "Default" } },
});---
3. Forgetting to Set ClipStyler World
WRONG — Missing world assignment:
const clipStyler = components.get(OBF.ClipStyler);
// clipStyler.world = world; // MISSING!
clipStyler.createFromClipping(planeId, { ... });
// Edges created but not added to any sceneRIGHT — ALWAYS set world first:
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world; // REQUIRED
clipStyler.createFromClipping(planeId, { ... });---
4. Creating Styled Edges Before Defining Styles
WRONG — Style referenced but not defined:
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
// Style "Section" not yet defined!
clipStyler.createFromClipping(planeId, {
items: { All: { style: "Section" } },
});
// Too late
clipStyler.styles.set("Section", { ... });RIGHT — Define styles first:
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.styles.set("Section", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
});
clipStyler.createFromClipping(planeId, {
items: { All: { style: "Section" } },
});---
5. Forgetting to Enable Clipper
WRONG — Clipper disabled by default:
const clipper = components.get(OBC.Clipper);
// clipper.enabled is false by default!
clipper.create(world); // Does nothingRIGHT — Enable before use:
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
clipper.create(world);---
6. Using LineBasicMaterial for Edge Lines
WRONG — linewidth has no effect with LineBasicMaterial:
clipStyler.styles.set("Default", {
linesMaterial: new THREE.LineBasicMaterial({
color: 0x000000,
linewidth: 3, // IGNORED by WebGL
}),
});RIGHT — Use LineMaterial from Three.js examples:
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
clipStyler.styles.set("Default", {
linesMaterial: new LineMaterial({
color: 0x000000,
linewidth: 3, // Works correctly
}),
});---
7. Manually Positioning Camera for Floor Plans
WRONG — Manual camera setup when using Views:
views.open("floor-1");
// Redundant — views.open() already handles camera
world.camera.set("Plan");
await world.camera.controls.setLookAt(x, y, z, tx, ty, tz);RIGHT — Let views.open() handle camera positioning:
views.open("floor-1");
// Only set projection if needed
await world.camera.projection.set("Orthographic");views.open() automatically switches to Plan mode and positions the camera relative to the view plane. NEVER manually reposition the camera after opening a view.
---
8. Not Disposing Clipping Resources
WRONG — Memory leak:
// Creating planes without cleanup
for (const floor of floors) {
clipper.createFromNormalAndCoplanarPoint(world, normal, point);
}
// No disposal — planes and edge geometry accumulateRIGHT — Clean up when done:
// Remove all clipping planes
clipper.deleteAll();
// Or dispose the entire ClipStyler (clears styles and edges)
clipStyler.dispose();---
9. Forgetting to Close Views Before Switching
WRONG — Opening another view without closing:
views.open("floor-1");
// ... user clicks another floor
views.open("floor-2"); // Previous view may not be properly deactivatedRIGHT — Close first, or rely on Views auto-management:
views.close(); // Close current view
views.open("floor-2"); // Open new oneNote: views.open() ensures only one view per world is active, but explicitly closing first is clearer and avoids edge cases.
---
10. Creating Planes Without a Loaded Model
WRONG — Interactive plane creation on empty scene:
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
clipper.create(world); // Returns null — no geometry to raycast againstRIGHT — Load geometry first, or use programmatic creation:
// Option A: Load model first
await fragments.load(data);
clipper.create(world); // Now raycasts hit geometry
// Option B: Use programmatic creation (no raycast needed)
clipper.createFromNormalAndCoplanarPoint(world, normal, point);Examples — Clipping Planes & Floor Plans
1. Basic Interactive Clipping
Minimal setup to let users create clipping planes by double-clicking on geometry.
import * as OBC from "@thatopen/components";
// Assume components and world are set up (see thatopen-impl-viewer)
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
// Double-click to create a plane at intersection point
container.ondblclick = () => {
if (clipper.enabled) {
clipper.create(world);
}
};
// Delete key removes the plane under cursor
window.onkeydown = (event) => {
if (event.code === "Delete" || event.code === "Backspace") {
clipper.delete(world);
}
};2. Programmatic Section Cut
Create a horizontal section at a specific elevation without user interaction.
import * as OBC from "@thatopen/components";
import * as THREE from "three";
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
// Horizontal cut at y=3.0m, normal pointing down
const planeId = clipper.createFromNormalAndCoplanarPoint(
world,
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 3.0, 0),
);
// Hide the plane helper visual
clipper.visible = false;
// Later: remove the plane
await clipper.delete(world, planeId);3. Styled Section with ClipStyler
Add edge outlines to a programmatic clipping plane.
import * as OBC from "@thatopen/components";
import * as OBF from "@thatopen/components-front";
import * as THREE from "three";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
// Create clipper plane
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
const planeId = clipper.createFromNormalAndCoplanarPoint(
world,
new THREE.Vector3(0, -1, 0),
new THREE.Vector3(0, 3.0, 0),
);
// Set up ClipStyler
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
// Define a style
clipStyler.styles.set("Section", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
fillsMaterial: new THREE.MeshBasicMaterial({
color: 0xe0e0e0,
side: THREE.DoubleSide,
}),
});
// Link styled edges to the clipping plane
clipStyler.createFromClipping(planeId, {
items: { All: { style: "Section" } },
});4. Auto-Style New Planes
Automatically add styled edges whenever a new clipping plane is created.
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.styles.set("Default", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
});
// React to new planes
clipper.list.onItemSet.add(({ key }) => {
clipStyler.createFromClipping(key, {
items: { All: { style: "Default" } },
});
});
// Now any user-created or programmatic plane gets edges
container.ondblclick = () => clipper.create(world);5. Floor Plan from IFC Storeys
Generate floor plan views automatically from the IFC spatial structure.
import * as OBC from "@thatopen/components";
import * as OBF from "@thatopen/components-front";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
import * as THREE from "three";
// Set up Views
const views = components.get(OBC.Views);
views.world = world;
// Create views from IFC storeys (one per floor)
const storeyViews = await views.createFromIfcStoreys({
offset: 0.25, // 25cm above slab level
});
// Set up ClipStyler
const clipStyler = components.get(OBF.ClipStyler);
clipStyler.world = world;
clipStyler.styles.set("Plan", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 2 }),
fillsMaterial: new THREE.MeshBasicMaterial({
color: 0xf5f5f5,
side: THREE.DoubleSide,
}),
});
// Add styled edges to each storey view
for (const [id, view] of views.list) {
clipStyler.createFromView(view, {
items: { All: { style: "Plan" } },
});
}
// Open the ground floor plan
views.open("ground-floor");
await world.camera.projection.set("Orthographic");6. Per-Category Floor Plan Styling
Different styles for walls, windows, and structural elements.
// Define multiple styles
clipStyler.styles.set("Walls", {
linesMaterial: new LineMaterial({ color: 0x000000, linewidth: 3 }),
fillsMaterial: new THREE.MeshBasicMaterial({ color: 0xcccccc, side: 2 }),
});
clipStyler.styles.set("Windows", {
linesMaterial: new LineMaterial({ color: 0x0066ff, linewidth: 1 }),
fillsMaterial: new THREE.MeshBasicMaterial({ color: 0xccddff, side: 2 }),
});
clipStyler.styles.set("Structure", {
linesMaterial: new LineMaterial({ color: 0x333333, linewidth: 2 }),
fillsMaterial: new THREE.MeshBasicMaterial({ color: 0xaaaaaa, side: 2 }),
});
// Apply per-category
clipStyler.createFromView(view, {
items: {
WallGroup: {
style: "Walls",
data: { "BuildingElement.Class": ["IFCWALL", "IFCWALLSTANDARDCASE"] },
},
WindowGroup: {
style: "Windows",
data: { "BuildingElement.Class": ["IFCWINDOW"] },
},
StructureGroup: {
style: "Structure",
data: { "BuildingElement.Class": ["IFCSLAB", "IFCCOLUMN", "IFCBEAM"] },
},
},
});7. Elevation Views
Create front/back/left/right elevation views from the model bounding box.
const views = components.get(OBC.Views);
views.world = world;
const elevations = await views.createElevations({
combine: true, // single bounding box for all models
});
// Open the front elevation
views.open("front");
await world.camera.projection.set("Orthographic");8. Floor Plan Toggle UI
Switch between 3D view and floor plans.
function openFloorPlan(viewId: string) {
views.open(viewId);
world.camera.projection.set("Orthographic");
clipStyler.visible = true;
}
function returnTo3D() {
views.close();
world.camera.projection.set("Perspective");
world.camera.set("Orbit");
clipStyler.visible = false;
}
// Wire to UI buttons
floorPlanButton.onclick = () => openFloorPlan("ground-floor");
threeDButton.onclick = () => returnTo3D();9. Vertical Section Cut
Create a vertical section through a building.
const clipper = components.get(OBC.Clipper);
clipper.enabled = true;
// Vertical plane cutting along X axis
const planeId = clipper.createFromNormalAndCoplanarPoint(
world,
new THREE.Vector3(1, 0, 0), // normal pointing in +X
new THREE.Vector3(5.0, 0, 0), // at x=5.0m
);
// Add styled edges
clipStyler.createFromClipping(planeId, {
items: { All: { style: "Section" } },
});10. Cleanup Pattern
Proper disposal of all clipping resources.
// Remove all clipping planes
clipper.deleteAll();
// Dispose ClipStyler (clears all styles and edges)
clipStyler.dispose();
// Or dispose everything at once via components
components.dispose();API Reference — Clipper, ClipStyler, ClipEdges, Views
Clipper
Package: @thatopen/components UUID: 66290bc5-18c4-4cd1-9379-2e17a0617611 Implements: Component, Createable, Disposable, Configurable
Constructor
constructor(components: Components)Properties
| Property | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enables/disables the component |
visible | boolean | true | Shows/hides all plane helpers |
size | number | 5 | Geometric size of plane helpers |
material | THREE.MeshBasicMaterial | — | Material for plane helpers |
orthogonalY | boolean | false | Forces planes orthogonal to Y axis |
toleranceOrthogonalY | number | 0.7 | Threshold for Y orthogonality |
autoScalePlanes | boolean | true | Auto-scale based on camera distance |
list | DataMap<string, SimplePlane> | — | All created planes |
config | ClipperConfigManager | — | Configuration manager |
isSetup | boolean | false | Whether setup() has been called |
Type | Constructor<SimplePlane> | SimplePlane | Plane type to instantiate |
Methods
// Interactive creation via raycast
create(world: World): Promise<SimplePlane | null>
// Programmatic creation — returns plane ID
createFromNormalAndCoplanarPoint(
world: World,
normal: THREE.Vector3,
point: THREE.Vector3
): string
// Delete plane (interactive if no ID, specific if ID given)
delete(world: World, planeId?: string): Promise<void>
// Delete all planes, optionally filtered by type
deleteAll(types?: Set<string>): void
// Initialize with configuration
setup(config?: Partial<ClipperConfig>): void
// Clean up all resources
dispose(): voidEvents
| Event | Payload | Description |
|---|---|---|
onBeforeCreate | void | Before plane creation |
onAfterCreate | SimplePlane | After plane is created |
onBeforeDrag | SimplePlane | Before drag starts |
onAfterDrag | SimplePlane | After drag ends |
onBeforeDelete | void | Before deletion |
onAfterDelete | SimplePlane | After plane is deleted |
onBeforeCancel | void | Before creation cancelled |
onAfterCancel | void | After creation cancelled |
onSetup | void | After setup completes |
onDisposed | string | Component disposed |
onStateChanged | string[] | State property changed |
---
SimplePlane
Package: @thatopen/components
Constructor
constructor(
components: Components,
world: World,
origin: THREE.Vector3,
normal: THREE.Vector3,
material: THREE.Material,
size?: number, // default: 5
activateControls?: boolean // default: true
)Properties
| Property | Type | Description |
|---|---|---|
three | THREE.Plane | Underlying Three.js plane |
origin | THREE.Vector3 | Plane origin point |
normal | THREE.Vector3 | Plane normal vector |
enabled | boolean | Whether plane clips geometry |
visible | boolean | Whether helper is visible |
autoScale | boolean | Auto-scale with camera distance |
size | number | Helper geometric size |
type | string | Custom identifier (default "default") |
title | string | Display title |
meshes | THREE.Mesh[] | Raycasting meshes (readonly) |
planeMaterial | THREE.Material | Helper material |
helper | THREE.Object3D | Helper object (readonly) |
controls | TransformControls | Drag controls (readonly) |
components | Components | Components instance |
world | World | Associated world |
Methods
setFromNormalAndCoplanarPoint(normal: THREE.Vector3, point: THREE.Vector3): void
update(): void
dispose(): voidEvents
| Event | Description |
|---|---|
onDraggingStarted | Drag begins |
onDraggingEnded | Drag ends |
onDisposed | Plane disposed |
---
ClipStyler
Package: @thatopen/components-front UUID: 24dfc306-a3c4-410f-8071-babc4afa5e4d Implements: Component, Disposable
Constructor
constructor(components: OBC.Components)Properties
| Property | Type | Description |
|---|---|---|
enabled | boolean | Component active state |
world | `OBC.World \ | null` |
styles | DataMap<string, ClipStyle> | Named style definitions |
list | DataMap<string, ClipEdges> | Managed ClipEdges instances (readonly) |
visible | boolean | Show/hide all edges |
Methods
// Create from a raw THREE.Plane
create(plane: THREE.Plane, config?: ClipEdgesCreationConfig): ClipEdges
// Create from a View (camera-synced)
createFromView(view: OBC.View, config?: ClipEdgesCreationConfig): ClipEdges
// Create from a Clipper plane ID
createFromClipping(id: string, config?: ClipEdgesCreationConfig): ClipEdges
// Clean up
dispose(): voidEvents
| Event | Description |
|---|---|
onDisposed | Component disposed |
---
ClipEdges
Package: @thatopen/components-front (managed by ClipStyler) Implements: Disposable
Constructor
constructor(components: OBC.Components, plane: THREE.Plane)Properties
| Property | Type | Description |
|---|---|---|
three | THREE.Group | Group holding edge/fill meshes |
plane | THREE.Plane | Associated clipping plane (readonly) |
items | DataMap<string, ClipEdgesItemStyle> | Named item style groups |
world | OBC.World | Associated world |
visible | boolean | Show/hide in scene |
Methods
// Recalculate edges (all or specific groups)
update(groups?: string[]): Promise<void>
// Clean up
dispose(): voidEvents
| Event | Description |
|---|---|
onDisposed | Instance disposed |
---
Types
ClipStyle
interface ClipStyle {
linesMaterial?: LineMaterial; // Edge line material
fillsMaterial?: THREE.Material; // Fill material for cut surfaces
}ClipEdgesItemStyle
interface ClipEdgesItemStyle {
style: string; // Name of style in clipStyler.styles
data?: OBC.ClassifierIntersectionInput; // Filter by classification
}ClipEdgesCreationConfig
interface ClipEdgesCreationConfig {
link?: boolean; // Auto-sync with source plane
id?: string; // Custom identifier
world?: OBC.World; // Override default world
items?: Record<string, ClipEdgesItemStyle>; // Named item groups with styles
}---
Views
Package: @thatopen/components
Properties
| Property | Type | Description |
|---|---|---|
list | DataMap<string, View> | All views (readonly) |
enabled | boolean | Component active state |
world | `OBC.World \ | undefined` |
hasOpenViews | boolean | Whether any view is active (getter) |
defaultRange | number | Default range (15 units, static) |
Methods
// Create view from normal vector and point
create(
normal: THREE.Vector3,
point: THREE.Vector3,
config?: CreateViewConfig
): View
// Create from THREE.Plane
createFromPlane(
plane: THREE.Plane,
config?: CreateViewConfig
): View
// Create views from IFC building storeys
createFromIfcStoreys(
config?: CreateViewFromIfcStoreysConfig
): Promise<View[]>
// Create elevation views (front, back, left, right)
createElevations(
config?: CreateElevationViewsConfig
): Promise<View[]>
// Activate a view by ID
open(id: string): void
// Deactivate a view (or any open view if no ID)
close(id?: string): voidConfig Types
interface CreateViewConfig {
id?: string;
world?: OBC.World;
}
interface CreateViewFromIfcStoreysConfig {
modelIds?: RegExp[];
storeyNames?: RegExp[];
offset?: number; // default: 0.25
world?: OBC.World;
}
interface CreateElevationViewsConfig {
combine?: boolean; // default: false
modelIds?: RegExp[];
world?: OBC.World;
namingCallback?: (modelId: string) => {
front: string; back: string; left: string; right: string;
};
}---
View
Package: @thatopen/components
Constructor
constructor(
components: Components,
config?: { id?: string; normal?: THREE.Vector3; point?: THREE.Vector3 }
)Properties
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier |
plane | THREE.Plane | Primary clipping plane |
farPlane | THREE.Plane | Back clipping plane |
camera | OrthoPerspectiveCamera | Associated camera |
open | boolean | Whether view is active |
range | number | Distance between front/back planes |
distance | number | Plane constant value |
world | `OBC.World \ | null` |
planesEnabled | boolean | Toggle plane clipping |
helpersVisible | boolean | Toggle debug helpers |
planeHelperColor | THREE.Color | Primary helper color (set only) |
farPlaneHelperColor | THREE.Color | Far helper color (set only) |
Methods
update(): void // Sync camera and far plane
flip(): void // Reverse view direction
dispose(): void // Clean upEvents
| Event | Payload | Description |
|---|---|---|
onStateChanged | string[] | State property changed |
onUpdated | undefined | After update |
onDisposed | undefined | View disposed |