Overview
Shapes are 3D geometric primitives that provide solid modeling capabilities in OpenPlans. They extend the OpenGeometry kernel classes and are used both as standalone objects and as building blocks for more complex elements.
Shapes implement the IShape interface and can be used to create custom architectural elements or standalone 3D objects.
Available Shapes
Cuboid Shape
A three-dimensional rectangular box defined by center point and dimensions.
Source: src/shapes/cuboid.ts:11
const cuboid = openPlans . cuboid ({
center: new Vector3 ( 0 , 1 , 0 ),
width: 2 , // X-axis dimension
height: 1 , // Y-axis dimension
depth: 3 , // Z-axis dimension
color: 0xFF0000
});
// Modify cuboid properties
cuboid . setOPConfig ({
center: new Vector3 ( 2 , 1.5 , 0 ),
width: 2.5 ,
height: 1.5 ,
depth: 3.5 ,
color: 0x00FF00
});
Properties
The center point of the cuboid in 3D space
Width of the cuboid along the X-axis
Height of the cuboid along the Y-axis
Depth of the cuboid along the Z-axis
Color of the cuboid in hexadecimal format
Unique identifier for the cuboid
Cuboid in Elements
Cuboids are the primary building blocks for architectural elements:
Source: src/elements/base-door.ts:242
// Door panel using Cuboid
const doorPanel = new Cuboid ({
center: new Vector3 ( 0 , doorHeight / 2 , 0 ),
width: doorLength - 0.1 ,
height: doorHeight - 0.1 ,
depth: doorThickness ,
color: doorColor
});
// Door frame components using Cuboids
const leftFrame = new Cuboid ({
center: new Vector3 ( startX , doorHeight / 2 , 0 ),
width: 0.1 ,
height: doorHeight ,
depth: frameThickness ,
color: frameColor
});
Source: src/elements/base-slab.ts:182
// Slab body using Cuboid
const slabBody = new Cuboid ({
center: new Vector3 ( 0 , - slabThickness / 2 , 0 ),
width: slabWidth ,
height: slabThickness ,
depth: slabLength ,
color: slabColor
});
Cylinder Shape
A cylindrical 3D shape defined by center point, radius, and height.
Source: src/shapes/cylinder.ts:11
const cylinder = openPlans . cylinder ({
center: new Vector3 ( 0 , 0.5 , 0 ),
radius: 0.5 ,
height: 1.0 ,
color: 0x0000FF
});
// Modify cylinder properties
cylinder . setOPConfig ({
center: new Vector3 ( 2 , 0.75 , 0 ),
radius: 0.75 ,
height: 1.5 ,
color: 0xFF00FF
});
Properties
The center point of the cylinder in 3D space
Height of the cylinder along the Y-axis
Color of the cylinder in hexadecimal format
Unique identifier for the cylinder
Use Cases
Cylinders are useful for:
Columns and pillars
Circular structural elements
Pipes and ducts
Decorative elements
// Create a structural column
const column = openPlans . cylinder ({
center: new Vector3 ( 3 , 1.5 , 3 ),
radius: 0.2 ,
height: 3.0 ,
color: 0x808080
});
// Create a circular planter
const planter = openPlans . cylinder ({
center: new Vector3 ( 0 , 0.3 , 0 ),
radius: 0.6 ,
height: 0.6 ,
color: 0x8B4513
});
Shape Interface
All shapes implement the IShape interface:
interface IShape {
ogType : string ; // Type identifier
ogid : string ; // Unique ID
subNodes : Map < string , THREE . Object3D >; // Child objects
selected : boolean ; // Selection state
edit : boolean ; // Edit mode state
propertySet : object ; // Configuration
setOPConfig ( config : any ) : void ; // Update configuration
getOPConfig () : any ; // Get configuration
setOPGeometry () : void ; // Update geometry
setOPMaterial () : void ; // Update material
}
Kernel Integration
Shapes extend kernel classes from OpenGeometry:
Source: src/shapes/cuboid.ts:11
import { ICuboidOptions , Cuboid } from '../kernel/' ;
export class CuboidShape extends Cuboid implements IShape {
ogType : string = 'CuboidShape' ;
propertySet : ICuboidOptions ;
constructor ( properties ?: ICuboidOptions ) {
super ( properties );
this . propertySet = { ... properties , ... this . options };
}
}
This inheritance provides:
Efficient geometry generation
BREP (Boundary Representation) data
Material management
Automatic mesh creation
Property Management
Getting Configuration
const config = cuboid . getOPConfig ();
console . log ( config );
// {
// ogid: "...",
// center: Vector3 { x: 0, y: 1, z: 0 },
// width: 2,
// height: 1,
// depth: 3,
// color: 0xFF0000
// }
Setting Configuration
Source: src/shapes/cuboid.ts:40
cuboid . setOPConfig ({
center: new Vector3 ( 1 , 1 , 1 ),
width: 3 ,
height: 2 ,
depth: 4 ,
color: 0x00FF00
});
// Internally calls:
// - this.discardGeometry() to clean up
// - this.setConfig(config) to regenerate
Always use setOPConfig() rather than modifying propertySet directly. This ensures geometry is properly cleaned up and regenerated.
Geometry Lifecycle
Creation
Shapes are added to the scene automatically:
Source: src/index.ts:270
cuboid ( config ?: ICuboidOptions ) {
const cuboid = new CuboidShape ( config );
this . openThree . scene . add ( cuboid );
this . ogElements . push ( cuboid );
return cuboid ;
}
Updates
When you call setOPConfig(), the shape:
Calls discardGeometry() to clean up existing meshes
Updates the propertySet
Calls setConfig() to regenerate geometry
Updates materials if needed
Source: src/shapes/cuboid.ts:40
setOPConfig ( config : ICuboidOptions ): void {
this . discardGeometry (); // Clean up old geometry
this . propertySet = config ;
this . setConfig ( config ); // Generate new geometry
}
Disposal
Always dispose shapes when no longer needed:
openPlans . disposeElement ( cuboid . ogid );
Working with Shapes
As Standalone Objects
// Create standalone 3D objects
const box = openPlans . cuboid ({
center: new Vector3 ( 0 , 0.5 , 0 ),
width: 1 ,
height: 1 ,
depth: 1 ,
color: 0xFF0000
});
const pillar = openPlans . cylinder ({
center: new Vector3 ( 3 , 1.5 , 3 ),
radius: 0.3 ,
height: 3.0 ,
color: 0x808080
});
As Element Components
Shapes are commonly used within elements:
// Stairs use multiple cuboids for steps
// Source: src/elements/base-stair.ts:180
for ( let i = 0 ; i < numberOfSteps ; i ++ ) {
const tread = new Cuboid ({
center: new Vector3 ( stepPosition , stepHeight , width / 2 ),
width: treadDepth ,
height: stepThickness ,
depth: stairWidth ,
color: stairColor
});
stepsGroup . add ( tread );
}
Creating Custom Elements
You can compose shapes to create custom elements:
class CustomTable extends THREE . Group implements IShape {
ogType = 'CustomTable' ;
constructor () {
super ();
// Table top using Cuboid
const top = new Cuboid ({
center: new Vector3 ( 0 , 0.75 , 0 ),
width: 1.5 ,
height: 0.05 ,
depth: 0.8 ,
color: 0x8B4513
});
// Table legs using Cylinders
const legPositions = [
[ - 0.7 , 0.375 , - 0.35 ],
[ 0.7 , 0.375 , - 0.35 ],
[ - 0.7 , 0.375 , 0.35 ],
[ 0.7 , 0.375 , 0.35 ]
];
legPositions . forEach ( pos => {
const leg = new Cylinder ({
center: new Vector3 ( ... pos ),
radius: 0.04 ,
height: 0.75 ,
color: 0x654321
});
this . add ( leg );
});
this . add ( top );
}
}
Advanced Features
Sub-Nodes Management
Shapes maintain a map of child objects:
subNodes : Map < string , THREE . Object3D > = new Map ();
// Add custom sub-nodes
cuboid . subNodes . set ( 'decoration' , decorationMesh );
// Access sub-nodes
const decoration = cuboid . subNodes . get ( 'decoration' );
Selection State
// Track selection
cuboid . selected = true ;
// Track edit mode
cuboid . edit = true ;
Material Updates
Implement custom material logic:
setOPMaterial (): void {
// Custom material update logic
const material = new THREE . MeshStandardMaterial ({
color: this . propertySet . color ,
roughness: 0.7 ,
metalness: 0.3
});
// Apply to mesh
}
Best Practices
Choose the right shape for your needs: // Good: Use Cuboid for rectangular objects
const beam = openPlans . cuboid ({ width: 0.2 , height: 0.3 , depth: 5 });
// Good: Use Cylinder for round objects
const column = openPlans . cylinder ({ radius: 0.3 , height: 3 });
Always dispose of shapes when done: // Dispose individual shapes
openPlans . disposeElement ( cuboid . ogid );
// Or get all shapes and dispose
const allCuboids = openPlans . getEntitiesByType ( 'CuboidShape' );
allCuboids . forEach ( c => openPlans . disposeElement ( c . ogid ));
Use Vector3 for positions
Import and use Vector3 from the kernel: import { Vector3 } from 'openplans' ;
const cuboid = openPlans . cuboid ({
center: new Vector3 ( 1 , 2 , 3 ),
// ...
});
Examples
Creating a Simple Building
import { Vector3 } from 'openplans' ;
// Foundation
const foundation = openPlans . cuboid ({
center: new Vector3 ( 0 , - 0.2 , 0 ),
width: 10 ,
height: 0.4 ,
depth: 10 ,
color: 0x808080
});
// Walls (4 walls using cuboids)
const walls = [
{ center: new Vector3 ( 0 , 1.5 , - 5 ), width: 10 , depth: 0.2 }, // Back
{ center: new Vector3 ( 0 , 1.5 , 5 ), width: 10 , depth: 0.2 }, // Front
{ center: new Vector3 ( - 5 , 1.5 , 0 ), width: 0.2 , depth: 10 }, // Left
{ center: new Vector3 ( 5 , 1.5 , 0 ), width: 0.2 , depth: 10 } // Right
];
walls . forEach ( wall => {
openPlans . cuboid ({
center: wall . center ,
width: wall . width ,
height: 3 ,
depth: wall . depth ,
color: 0xDDDDDD
});
});
// Columns at corners
const cornerPositions = [
[ - 5 , 1.5 , - 5 ],
[ 5 , 1.5 , - 5 ],
[ - 5 , 1.5 , 5 ],
[ 5 , 1.5 , 5 ]
];
cornerPositions . forEach ( pos => {
openPlans . cylinder ({
center: new Vector3 ( ... pos ),
radius: 0.3 ,
height: 3 ,
color: 0x888888
});
});
Creating Furniture
// Bookshelf using multiple cuboids
const shelfHeight = 0.03 ;
const shelfCount = 5 ;
const shelfSpacing = 0.4 ;
// Back panel
openPlans . cuboid ({
center: new Vector3 ( 0 , 1 , 0 ),
width: 1.2 ,
height: 2 ,
depth: 0.02 ,
color: 0x8B4513
});
// Shelves
for ( let i = 0 ; i < shelfCount ; i ++ ) {
openPlans . cuboid ({
center: new Vector3 ( 0 , i * shelfSpacing , 0.15 ),
width: 1.2 ,
height: shelfHeight ,
depth: 0.3 ,
color: 0x8B4513
});
}
// Side panels
[ - 0.6 , 0.6 ]. forEach ( x => {
openPlans . cuboid ({
center: new Vector3 ( x , 1 , 0.15 ),
width: 0.02 ,
height: 2 ,
depth: 0.3 ,
color: 0x8B4513
});
});