Overview
OpenPlans supports headless generation of floor plans from JSON data structures. This enables:- Programmatic floor plan creation from databases
- Serialization and deserialization of designs
- Integration with external data sources
- Batch processing of building data
JSON Floor Plan Structure
A complete floor plan is defined using a hierarchical JSON structure:Copy
Ask AI
{
"building_id": "Building_123",
"building_name": "Building Name",
"floors": [],
"rooms": [],
"walls": [],
"windows": [],
"doors": []
}
Creating Elements from JSON
All OpenPlans elements support creation from configuration objects.Primitives from JSON
Copy
Ask AI
// Line from JSON
const lineConfig = {
ogid: "line-001",
startPoint: [0, 0, 0],
endPoint: [10, 0, 0],
color: 0x000000
};
const line = openPlans.line(lineConfig);
// Rectangle from JSON
const rectConfig = {
ogid: "rect-001",
center: [5, 0, 5],
width: 10,
breadth: 8,
color: 0x0000FF
};
const rectangle = openPlans.rectangle(rectConfig);
// Polyline from JSON
const polylineConfig = {
ogid: "poly-001",
points: [
[0, 0, 0],
[5, 0, 0],
[5, 0, 3],
[0, 0, 3],
[0, 0, 0]
],
color: 0x000000
};
const polyline = openPlans.polyline(polylineConfig);
Architectural Elements from JSON
Copy
Ask AI
// Door from JSON
const doorConfig = {
type: "door",
labelName: "Main Entrance",
dimensions: {
start: { x: 0, y: 0, z: 0 },
end: { x: 0, y: 0, z: 0 },
length: 2
},
doorPosition: [3, 0, 3],
doorType: "WOOD",
doorHeight: 2.1,
doorThickness: 0.2,
frameThickness: 0.2,
doorColor: 9127187,
frameColor: 0,
doorRotation: 1.5,
doorQuadrant: 2,
coordinates: [],
id: "door-001"
};
const door = openPlans.baseDoor(doorConfig);
// Window from JSON
const windowConfig = {
labelName: "Bedroom Window",
windowPosition: [2, 0, 5],
windowLength: 1.5,
windowHeight: 1.2,
windowThickness: 0.1,
windowColor: 11393254,
frameColor: 0
};
const window = openPlans.baseSingleWindow(windowConfig);
3D Shapes from JSON
Copy
Ask AI
import { Vector3 } from 'openplans';
// Cuboid from JSON
const cuboidConfig = {
ogid: '86302abc-d71e-47be-affc-dc05de1db8fe',
width: 20,
height: 10,
depth: 1,
color: 0x000000,
center: new Vector3(20, 0, 0)
};
const cuboid = openPlans.cuboid(cuboidConfig);
// Cylinder from JSON
const cylinderConfig = {
ogid: 'cylinder-001',
center: new Vector3(5, 1, 5),
radius: 0.3,
height: 2,
segments: 32,
color: 0xCCCCCC
};
const cylinder = openPlans.cylinder(cylinderConfig);
Complete Floor Plan JSON Example
Here’s a complete JSON structure for a multi-room floor plan:Copy
Ask AI
{
"building_id": "Building_123",
"building_name": "Residential Building",
"floors": [
{
"OG_ID": "Floor_1",
"OG_TYPE": "OG_FLOOR",
"OG_DATA": ["Room_1", "Room_2"]
}
],
"rooms": [
{
"OG_ID": "Room_1",
"OG_TYPE": "OG_ROOM",
"type": "Bedroom",
"OG_DATA": [
{"OG_ID": "Wall_1", "OG_TYPE": "OG_WALL"},
{"OG_ID": "Window_1", "OG_TYPE": "OG_WINDOW"},
{"OG_ID": "Door_1", "OG_TYPE": "OG_DOOR"}
],
"coordinates": [[0, 0, 0], [4, 0, 0], [4, 0, 3.5], [0, 0, 3.5]],
"connections": ["Room_2"]
},
{
"OG_ID": "Room_2",
"OG_TYPE": "OG_ROOM",
"type": "Living Room",
"OG_DATA": [
{"OG_ID": "Wall_2", "OG_TYPE": "OG_WALL"},
{"OG_ID": "Window_2", "OG_TYPE": "OG_WINDOW"}
],
"coordinates": [[4, 0, 0], [10, 0, 0], [10, 0, 4], [4, 0, 4]],
"connections": ["Room_1"]
}
],
"walls": [
{
"OG_ID": "Wall_1",
"OG_TYPE": "OG_WALL",
"type": "internal",
"thickness": 0.2,
"start": [4, 0, 0],
"end": [4, 0, 3.5]
},
{
"OG_ID": "Wall_2",
"OG_TYPE": "OG_WALL",
"type": "external",
"thickness": 0.3,
"start": [0, 0, 0],
"end": [0, 0, 3.5]
}
],
"windows": [
{
"OG_ID": "Window_1",
"OG_TYPE": "OG_WINDOW",
"type": "internal",
"thickness": 0.2,
"start": [2, 0, 3.5],
"end": [2, 0, 4.5]
}
],
"doors": [
{
"OG_ID": "Door_1",
"OG_TYPE": "OG_DOOR",
"type": "internal",
"thickness": 0.25,
"hingeThickness": 0.125,
"start": [0, 0, 1.0],
"end": [0, 0, 1.8],
"position": [0, 0, 1.0]
}
]
}
Loading JSON Floor Plans
From External File
Copy
Ask AI
import { OpenPlans } from 'openplans';
async function loadFloorPlanFromJSON() {
const openPlans = new OpenPlans(container);
await openPlans.setupOpenGeometry();
// Fetch JSON data
const response = await fetch('./floor-plan.json');
const floorPlanData = await response.json();
// Process the JSON and create elements
generateFloorPlan(openPlans, floorPlanData);
}
function generateFloorPlan(openPlans, data) {
// Create walls
data.walls?.forEach(wall => {
openPlans.line({
ogid: wall.OG_ID,
startPoint: wall.start,
endPoint: wall.end,
color: 0x000000
});
});
// Create doors
data.doors?.forEach(door => {
openPlans.baseDoor({
labelName: door.OG_ID,
doorPosition: door.position,
doorLength: calculateLength(door.start, door.end),
doorHeight: 2.1,
doorThickness: door.thickness
});
});
// Create windows
data.windows?.forEach(window => {
openPlans.baseSingleWindow({
labelName: window.OG_ID,
windowPosition: window.start,
windowLength: calculateLength(window.start, window.end),
windowHeight: 1.2
});
});
}
function calculateLength(start, end) {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
const dz = end[2] - start[2];
return Math.sqrt(dx*dx + dy*dy + dz*dz);
}
From URL
Copy
Ask AI
// Load from remote URL
const jsonURL = "https://example.com/floor-plans/building-123.json";
const response = await fetch(jsonURL);
const floorPlanData = await response.json();
generateFloorPlan(openPlans, floorPlanData);
Exporting to JSON
Exporting Element Configurations
Copy
Ask AI
// Get configuration from any element
const doorConfig = door.getOPConfig();
const lineConfig = line.getOPConfig();
const rectConfig = rectangle.getOPConfig();
// Serialize to JSON
const doorJSON = JSON.stringify(doorConfig, null, 2);
console.log(doorJSON);
Exporting Complete Floor Plans
Copy
Ask AI
function exportFloorPlan(openPlans) {
const floorPlan = {
building_id: "exported-building",
building_name: "Exported Floor Plan",
timestamp: new Date().toISOString(),
elements: []
};
// Export all lines
const lines = openPlans.getEntitiesByType('LinePrimitive');
lines.forEach(line => {
floorPlan.elements.push({
type: 'line',
config: line.getOPConfig()
});
});
// Export all rectangles
const rectangles = openPlans.getEntitiesByType('RectanglePrimitive');
rectangles.forEach(rect => {
floorPlan.elements.push({
type: 'rectangle',
config: rect.getOPConfig()
});
});
// Export all doors
const doors = openPlans.getEntitiesByType('baseDoor');
doors.forEach(door => {
floorPlan.elements.push({
type: 'door',
config: door.getOPConfig()
});
});
// Export all windows
const windows = [
...openPlans.getEntitiesByType('baseSingleWindow'),
...openPlans.getEntitiesByType('baseDoubleWindow')
];
windows.forEach(window => {
floorPlan.elements.push({
type: 'window',
config: window.getOPConfig()
});
});
return JSON.stringify(floorPlan, null, 2);
}
// Export and download
const jsonData = exportFloorPlan(openPlans);
const blob = new Blob([jsonData], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'floor-plan.json';
link.click();
Format Conversion
OpenPlans includes a converter for the Implenia format:Copy
Ask AI
import { convertToOGFormat } from 'openplans';
// Load external format
const impleniaData = await fetch('./implenia-format.json');
const impleniaJSON = await impleniaData.json();
// Convert to OpenGeometry format
const ogFormat = convertToOGFormat(impleniaJSON);
// Use with OpenPlans
openPlans.convertImpleniaToOGFormat(impleniaJSON);
Batch Processing
Process multiple floor plans from JSON:Copy
Ask AI
async function processBatch(floorPlanURLs) {
const container = document.getElementById('app');
const openPlans = new OpenPlans(container);
await openPlans.setupOpenGeometry();
for (const url of floorPlanURLs) {
// Load floor plan
const response = await fetch(url);
const data = await response.json();
// Generate floor plan
generateFloorPlan(openPlans, data);
// Export as image or perform analysis
// ...
// Clear for next floor plan
clearAllElements(openPlans);
}
}
function clearAllElements(openPlans) {
const allElements = [
...openPlans.getEntitiesByType('LinePrimitive'),
...openPlans.getEntitiesByType('RectanglePrimitive'),
...openPlans.getEntitiesByType('baseDoor'),
...openPlans.getEntitiesByType('baseSingleWindow')
];
allElements.forEach(element => {
openPlans.disposeElement(element.ogid);
});
}
Validation and Error Handling
Copy
Ask AI
function validateFloorPlanJSON(data) {
const errors = [];
// Check required fields
if (!data.building_id) {
errors.push('Missing building_id');
}
// Validate rooms
if (data.rooms) {
data.rooms.forEach((room, index) => {
if (!room.OG_ID) {
errors.push(`Room ${index} missing OG_ID`);
}
if (!room.coordinates || room.coordinates.length < 3) {
errors.push(`Room ${room.OG_ID} has invalid coordinates`);
}
});
}
// Validate walls
if (data.walls) {
data.walls.forEach((wall, index) => {
if (!wall.start || !wall.end) {
errors.push(`Wall ${wall.OG_ID || index} missing start or end`);
}
});
}
return {
isValid: errors.length === 0,
errors
};
}
// Use validation
const validation = validateFloorPlanJSON(floorPlanData);
if (!validation.isValid) {
console.error('Invalid floor plan data:', validation.errors);
} else {
generateFloorPlan(openPlans, floorPlanData);
}
Complete Example
Copy
Ask AI
import { OpenPlans } from 'openplans';
async function createFromJSON() {
const container = document.getElementById('app');
const openPlans = new OpenPlans(container);
await openPlans.setupOpenGeometry();
// Sample JSON data
const floorPlanJSON = {
building_id: "sample-001",
building_name: "Sample Apartment",
rooms: [
{
id: "bedroom",
type: "bedroom",
outline: [[0, 0, 0], [4, 0, 0], [4, 0, 3.5], [0, 0, 3.5], [0, 0, 0]]
},
{
id: "living",
type: "living_room",
outline: [[4, 0, 0], [10, 0, 0], [10, 0, 5], [4, 0, 5], [4, 0, 0]]
}
],
doors: [
{
id: "door-1",
position: [0, 0, 1],
length: 2,
quadrant: 1
}
],
windows: [
{
id: "window-1",
position: [2, 0, 3.5],
length: 1.5
}
]
};
// Generate rooms
floorPlanJSON.rooms.forEach(room => {
openPlans.polyline({
ogid: room.id,
points: room.outline,
color: 0x000000
});
// Add label
const center = calculateCenter(room.outline);
const label = openPlans.glyph(
room.type.replace('_', ' '),
6,
0x000000
);
label.position.set(center[0], center[1], center[2]);
});
// Generate doors
floorPlanJSON.doors.forEach(door => {
openPlans.baseDoor({
labelName: door.id,
doorPosition: door.position,
doorLength: door.length,
doorHeight: 2.1,
doorQuadrant: door.quadrant
});
});
// Generate windows
floorPlanJSON.windows.forEach(window => {
openPlans.baseSingleWindow({
labelName: window.id,
windowPosition: window.position,
windowLength: window.length,
windowHeight: 1.2
});
});
}
function calculateCenter(points) {
const sum = points.reduce((acc, p) => [
acc[0] + p[0],
acc[1] + p[1],
acc[2] + p[2]
], [0, 0, 0]);
return [
sum[0] / points.length,
sum[1] / points.length,
sum[2] / points.length
];
}
createFromJSON();
Next Steps
- Review Creating Floor Plans for manual creation
- Learn about Working with Primitives for element details
- Explore Architectural Elements for component options