I ain’t calling whatever this stack of work is BIM. This mystery project is simply titled OnlyPlans after our April fools joke from a year ago, and perhaps for my propensity to want to automate plan so I can think in elevations/ sections more easily.
System rules for the OPMVP so Far:
The Facade Container
All buildings have a closed boundary, this is the facade, or ‘canvas container’
Rooms are Closed
Within that closed boundary are rooms, also a closed boundary of minimum area, the closed boundary is a cell
Edges are Walls
Edges that separate cells from each other will be considered walls
{
"wall_rules": {
"rooms": [
{
"name": "Living Room",
"id": "room_001"
},
{
"name": "Kitchen",
"id": "room_002"
}
],
"wall_properties": {
"material": "Drywall",
"thickness_inch": 6,
"insulation": {
"type": "Fiberglass",
"r_value": 13
},
"soundproofing": {
"rating": "STC 50",
"requirements": [
"No major appliances adjacent",
"Sealed gaps"
]
},
"fire_rating": {
"duration_hours": 1,
"requirements": [
"Fire-rated drywall",
"No penetrations without firestop"
]
},
"doorways": {
"allowed": true,
"max_width_ft": 4,
"min_distance_from_corner_ft": 2
},
"windows": {
"allowed": false
},
"load_bearing": {
"status": "Non-load-bearing",
"supporting_structure": null
},
"electrical_requirements": {
"outlets_per_wall": 2,
"conduit_type": "Metallic",
"requirements": [
"No exposed wiring",
"Grounded outlets"
]
}
},
"shared_wall_rules": {
"shared_wall_insulation": "Double-layer fiberglass",
"shared_wall_thickness_inch": 8,
"noise_reduction_coefficient": 0.85,
"ventilation": {
"status": "Required",
"vent_type": "Shared HVAC duct",
"requirements": [
"Backdraft damper",
"Sound insulation within duct"
]
}
}
}
}
Rooms have requirements
- min / max size
- door / window elements hosted on walls
- specific egress load (driving door and window elements)
- power / water / wastewater / air / stc rating / R rating
- wall hosted objects
- floor hosted objects
{
"room": {
"name": "Conference Room",
"dimensions": {
"width_ft": 20,
"length_ft": 30,
"height_ft": 10
},
"occupancy": {
"max_people": 25,
"type": "Business"
},
"features": {
"windows": 2,
"doors": 1,
"electrical_outlets": 4,
"lighting_type": "LED",
"hvac": true,
"natural_light": true,
"soundproofing": "High"
},
"furniture": {
"tables": {
"type": "Conference Table",
"quantity": 1,
"dimensions_ft": {
"length": 15,
"width": 5
}
},
"chairs": {
"type": "Ergonomic Office Chair",
"quantity": 25
},
"whiteboard": {
"type": "Magnetic",
"quantity": 1,
"dimensions_ft": {
"width": 6,
"height": 4
}
}
},
"technology": {
"projector": true,
"screen_size_inch": 120,
"speakers": true,
"microphone": true,
"wifi": true
},
"requirements": {
"fire_safety": {
"smoke_detectors": 2,
"sprinklers": true,
"fire_extinguishers": 1
},
"accessibility": {
"wheelchair_accessible": true,
"hearing_aid_compatible": false
},
"energy_efficiency": {
"insulation_rating": "R30",
"solar_panels": false
}
}
}
}
Objects Have Requirements
Every room has its object requirements, but objects have their own requirements.
{
"object_requirements": [
{
"id": "obj_001",
"type": "Sofa",
"clearances": {
"from_walls": {
"min_ft": 1,
"preferred_ft": 2,
"regulation": "IBC Section 1208" // Reference to IBC code on spatial clearance
},
"from_adjacent_objects": {
"Coffee Table": {
"min_ft": 2,
"max_ft": 5,
"regulation": "IBC Section 1208" // General clearance requirements
}
}
},
"ada_requirements": {
"accessible_path_width_ft": 3, // ADA path clearance width
"turning_space_diameter_ft": 5, // ADA turning radius for wheelchair access
"regulation": "ADA 2010 Standards, Section 307"
},
"placement_rules": {
"must_be_adjacent_to": ["Wall"],
"must_not_be_adjacent_to": ["Window", "Door"],
"must_face": "Television",
"justification": "center"
}
},
{
"id": "obj_002",
"type": "Coffee Table",
"clearances": {
"from_adjacent_objects": {
"Sofa": {
"min_ft": 2,
"max_ft": 5,
"regulation": "IBC Section 1208"
}
}
},
"nfpa_requirements": {
"distance_from_fire_extinguisher_ft": 10, // NFPA rule for fire extinguisher access
"flammable_material_clearance_ft": 3, // Clearance from any flammable objects
"regulation": "NFPA 10, Chapter 6"
},
"placement_rules": {
"must_be_adjacent_to": ["Sofa"],
"justification": "left"
}
},
{
"id": "obj_003",
"type": "Television",
"clearances": {
"from_walls": {
"min_ft": 0,
"regulation": "IBC Section 1208"
},
"from_adjacent_objects": {
"Sofa": {
"min_ft": 8,
"max_ft": 12,
"regulation": "IBC Section 1208"
}
}
},
"placement_rules": {
"must_be_adjacent_to": ["Wall"],
"must_face": "Sofa",
"justification": "center"
},
"nfpa_requirements": {
"distance_from_heat_sources_ft": 4, // Safe distance from any heat-generating objects (NFPA)
"regulation": "NFPA 70 (National Electric Code)"
}
}
]
}
Doors and Windows are Owned by 2 Rooms
Since we don’t ever want to place a door and then change its type, we want to, in fact, never place any object manually first. Doors and windows need to be jointly owned in concept.
{
"doors": [
{
"from_room": "Living Room",
"to_room": "Kitchen",
"door_details": {
"type": "Sliding Door",
"material": "Glass",
"dimensions": {
"width_ft": 6,
"height_ft": 7
},
"notes": "A glass sliding door connecting the living room and kitchen"
}
},
{
"from_room": "Living Room",
"to_room": "Master Bedroom",
"door_details": {
"type": "Swing Door",
"material": "Wood",
"dimensions": {
"width_ft": 3,
"height_ft": 7
},
"notes": "A wooden swing door leading to the master bedroom"
}
},
{
"from_room": "Kitchen",
"to_room": "Bathroom",
"door_details": {
"type": "Swing Door",
"material": "Wood",
"dimensions": {
"width_ft": 3,
"height_ft": 7
},
"notes": "A swing door connecting the kitchen to the bathroom"
}
},
{
"from_room": "Master Bedroom",
"to_room": "Dining Room",
"door_details": {
"type": "Pocket Door",
"material": "Wood",
"dimensions": {
"width_ft": 4,
"height_ft": 7
},
"notes": "A wooden pocket door leading to the dining room"
}
}
]
}
Alright so here is the information hierarchy in my head:
Deal Pipeline > Deal > Scheme > Site > Building > Room > Object
This MVP will take a building shape as an input, place rooms from a program lookup (the shape will be named). Still a bit more thinking to go before I fully understand the full problem…
Required placement Algorithms?:
- Populate generic mass with rooms (could use ben) but the hierarchies and adjacencies will be compute heavy (could precompute min size based on object requirements
- Assuming that goes well, place doors based on all the load factors of those rooms (auto firewall?)
- Assuming that goes well, windows with their own placement logic
- Then the first priority objects and their adjacencies per sub space, moving down the list to second and third and so on
- What do you do when you have a large leftover middle area (subdivide tools)
- room object auto-orientation based on egress and clearance
Required co-creation tools?
- room bounds grips
- room layer level
- room position magnets (edge 1/3 : L C R T M B )corner: TL TR BL BR)
- object re-ordering
- relabel room (drive literally the entire model)
I think we could create something with a polygon and a label as base human input and get meaningful room level geometry from it, as long as this system is simple. Need to simplify even further if possible.
Error Handling Ideas
-If no room is placed and there is leftover space, default it to circulation space (often this literally is the leftover space).
-If in an object lookup table, all required items have been placed, then we can place filler items. Filler items need a max count/ inch or % (Kitchen Configurator)
-Fully clipping geometry by hierarchy is a winning strat not only for rooms but for series of objects:
{
"room": {
"id": "room_001",
"name": "Living Room",
"dimensions": {
"width_ft": 20,
"length_ft": 15,
"height_ft": 10
},
"objects": [
{
"id": "obj_001",
"type": "Sofa",
"dimensions": {
"width_ft": 6,
"length_ft": 3,
"height_ft": 3
},
"position": {
"edge_number": 1, // Edge 1 could represent a specific wall
"min_distance_ft": 2, // Minimum distance from edge 1
"preferred_position_percent": 50, // Centered along the edge
"justification": "center" // Sofa should be center-aligned
},
"placement_priority": 1,
"adjacency_rules": {
"must_be_adjacent_to": ["Wall"],
"distance_from": {
"Coffee Table": {
"min_ft": 2,
"max_ft": 5
}
}
}
},
{
"id": "obj_002",
"type": "Coffee Table",
"dimensions": {
"width_ft": 4,
"length_ft": 2,
"height_ft": 1.5
},
"position": {
"edge_number": 2, // Placed along a different edge
"min_distance_ft": 1, // Minimum distance from edge 2
"preferred_position_percent": 30, // 30% along the edge
"justification": "left" // Coffee table is left-aligned along the edge
},
"placement_priority": 2,
"adjacency_rules": {
"must_be_adjacent_to": ["Sofa"],
"distance_from": {
"Sofa": {
"min_ft": 2,
"max_ft": 5
}
}
}
},
{
"id": "obj_003",
"type": "Television",
"dimensions": {
"width_ft": 5,
"length_ft": 0.5,
"height_ft": 3
},
"position": {
"edge_number": 3,
"min_distance_ft": 0, // Directly on edge 3 (likely a wall)
"preferred_position_percent": 50, // Centered along edge 3
"justification": "center"
},
"placement_priority": 3,
"adjacency_rules": {
"must_face": "Sofa",
"must_be_adjacent_to": ["Wall"],
"distance_from": {
"Sofa": {
"min_ft": 8,
"max_ft": 12
}
}
}
},
{
"id": "obj_004",
"type": "Bookshelf",
"dimensions": {
"width_ft": 4,
"length_ft": 1,
"height_ft": 6
},
"position": {
"edge_number": 4,
"min_distance_ft": 1,
"preferred_position_percent": 75, // Positioned at 75% along edge 4
"justification": "right"
},
"placement_priority": 4,
"adjacency_rules": {
"must_be_adjacent_to": ["Wall"]
}
}
]
}
}