OPMVP

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?:

  1. 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
  2. Assuming that goes well, place doors based on all the load factors of those rooms (auto firewall?)
  3. Assuming that goes well, windows with their own placement logic
  4. Then the first priority objects and their adjacencies per sub space, moving down the list to second and third and so on
  5. What do you do when you have a large leftover middle area (subdivide tools)
  6. room object auto-orientation based on egress and clearance

Required co-creation tools?

  1. room bounds grips
  2. room layer level
  3. room position magnets (edge 1/3 : L C R T M B )corner: TL TR BL BR)
  4. object re-ordering
  5. 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"]
        }
      }
    ]
  }
}