This project showcases a “House Generator”, a parametric design tool developed in Python for Rhino. Leveraging the rhinoscriptsyntax library for geometric operations and the Eto.Forms framework for the user interface, the script enables rapid generation of residential building typologies. Users can define key parameters such as building dimensions, floor plan types and fenestration sizes through a custom configurator, allowing for efficient design exploration and iteration.
The dialog exposes only the decisions that matter — length, width, plan type, two window sizes, main and internal door widths — and derives everything else. A Check button previews the resulting 2D plan with room names and dimensions before committing; Generate builds the full 3D model.
The dialog floats beside the model instead of locking Rhino, so a preview can be orbited and inspected between runs. Before it builds, the script sets the document to metres with a millimetre tolerance, so the model comes out the same whatever file it runs in, and it draws in wireframe until the last solid is placed.
- PythonScripted logic and parameters
- rhinoscriptsyntaxGeometry · Eto.Forms interface
- RhinocerosModel output
- Type
- Individual project
- Collaboration
- TH OWL, Detmold
- Location
- Detmold, Germany
- Course
- TH OWL — MID Computational Design
From a dialog to a dictionary
The dialog is an Eto form, and it never talks to the geometry directly. Every button reads the seven controls through one method, which hands back a plain dictionary of numbers and names. Check and Generate both start from that dictionary, so the preview and the model can never disagree about what was typed — and adding an eighth input means adding one line here rather than finding every place a value is read.
def get_parameters(self):
return {
"length": self.length_numeric.Value,
"width": self.width_numeric.Value,
"plan_type": str(self.plan_combo.SelectedValue),
"w1_wid": float(self.window1_combo.SelectedValue),
"w2_wid": float(self.window2_combo.SelectedValue),
"main_door": float(self.main_door_combo.SelectedValue),
"dr_wid": float(self.internal_door_combo.SelectedValue)
}
How the plan resolves
Building dimensions and plan type drive column positions, internal walls, and the standardised internal dimensions that in turn place entrance openings, facade openings, internal door openings, windows and the staircase. Because each stage reads from the one before it, a change to overall width propagates through the whole plan rather than breaking it.
The plan is written as proportions, not measurements. Room depths are fixed fractions of the width — the living and dining area takes 4.5/15 of it, the kitchen 3.5/15, the room 4/15 — the rooms run half the length, and the corridor is a fifth of it. Those proportions set a small family of named points: the C points place the columns, the letters A to L the walls, doors and staircase. Every later step is built from those points, never from absolute coordinates.
Two plan types share the same points. Plan-1 keeps a kitchen beside the living area; Plan-2 carries one wall across the full length, turning that space into a study and adds a kitchen and store room at the back.
Exposed parameters
- Length
- Width
- Plan type
- Window type 1
- Window type 2
- Main door
- Internal door
int_len_1 = length/2 # Length of the first internal wall
corridor_wid = 1/5*length # Corridor width
room1_wid = 4/15*width # Width of room 1
kitchen_wid = 3.5/15*width # Width of kitchen
living_room_wid = 4.5/15*width # Width of living/dinning area
staircase_wid = 4.5
A facade that counts its panels
The glazing never stretches. Every facade panel is 2 m wide, so the script starts from the front length and sets about 4 m aside for the entrance bay. What is left is the stretch the glazing has to fill.
It fills it with whole panels only. When the remainder divides into 2 m panels exactly, they all fit; when it does not, % 2 rounds it down to the last whole panel and the leftover goes back to the entrance. The elevation closes cleanly at any size, and a longer house simply gains another panel of light over the living space.
The side facade over the living room follows the same rule with one addition. If less than half a metre would be left beside the glazing, it gives up one more panel, so the corner is never a sliver of wall too thin to build.
if length > 0:
ent_main = 4
fac_1 = length - ent_main
if fac_1 % 2 == 0:
facade_1 = fac_1
ent_main = length - facade_1
else:
facade_1 = fac_1 - (fac_1 % 2)
ent_main = length - facade_1
if width > 0:
if living_room_wid % 2 >= 0.5:
facade_2 = living_room_wid - (living_room_wid % 2)
else:
facade_2 = living_room_wid - (living_room_wid % 2) - 2
% 2 is the panel width, and whatever it leaves over goes to the entranceAround that, the model is built as real construction rather than massing: 300 mm outer walls and 150 mm inner walls, a plinth slab, a first floor with the stair opening cut out of it, and an overhanging flat roof. Windows are made once as Rhino blocks and inserted at each position. The main door is a glass double door that becomes a single leaf when a narrower opening is chosen, and internal door openings are cut through both floors at the chosen width.
In the model
- Columns
- Outer walls
- Inner walls
- Slabs & roof
- Facade frames
- Window blocks
- Glass main door
- Dog-leg staircase
- Glass balustrade