This video focuses on conditional design flows that rely on rules to define an outcome, while a Light Rail station is used in this example, the techniques can be applied more broadly across your workflow whether it be structure, facades or master planning.
Light Rail Station Configurator — Step-by-Step
1 — Goal & inputs
Goal: generate a station with a platform, roof (panelized), columns, and conditional ticket machines.
Primary inputs (parameters):
platform_width(example: 7.9 m)platform_length(example: 33 m)roof_length(example: 22 m; controlled byroof_offset)twist/height/num_columnscan be added later
2 — Attach an identity flow to the alignment
Start with the centerline (line geometry) for the stop.
Attach an identity flow (reads the line, writes the line) so you can build transforms relative to that line.
3 — Create roof offset / roof length parameter
Add a
Line Shorten(orline_shorten_transform) block to shorten the input line to create the roof centerline.Expose a single input parameter
roof_offset(number, default3) and write it toparameters.start_offsetandparameters.end_offsetso one parameter drives both ends.Test: change
roof_offsetand verify the roof shrinks symmetrically.
4 — Create the platform (arrayed precast panels)
Model one platform panel block (e.g., 4.0 × 1.2 m, height 0.2 m, base height 0.2 m).
Set the block’s
block_base_pointso it aligns correctly when inserted. Group and name it e.g.,station_platform_panel.Use
array_transform(points along / array along line) with spacing (e.g., 1.2 m) and a start offset (e.g., 0.6 m) to populate panels along the full platform line.Use
instance_group_transformto place thestation_platform_panelinstances along those array points.
5 — Handle start/end special panels (strip + instance groups)
Duplicate your panel block into:
panel_start,panel_middle,panel_end(start/end unique details).Use the array “strip” pattern: separate the first and last items from the middle list.
Extract
mids(middle panels) and placepanel_middle.Place
panel_startat the first position via aninstance_group_transform.Place
panel_endat the last position via aninstance_group_transform.
Embed these arrays so start/end special cases are stable.
6 — Add roof panels (stroke dash) — loose architectural approach
Use
stroke_dash_transformapplied to the shortened roof line to create roof panel segments (dash pattern array).Tune the dash array (e.g.,
[2, 0.2, 1]) to control panel lengths, gaps, and rhythm.If needed, offset the roof line to the platform using
offset_polygon_transform(example offset 2–3 m to place roof over platform).Create a
usagefor roof: clone ausage(e.g.,roofs) to carry color,base_height,height(set thin thickness like0.1 m), thenget_usage+apply_usageto the roof geometry. Remove conflicting defaults (e.g., default roof height) sousagerespects the small thickness.
7 — Add columns derived from stroke dashes
Clone the roof stroke into a new element called
columns.Convert dash positions into column insert points (columns sit at dash positions).
Create a column block (e.g., 0.2–0.3 m square, height
3.3 m,base_height= platform height).Place columns with
instance_group_transformat the column points. Make sure base heights align so columns sit on the platform (don’t penetrate).
8 — Clean geometry sequencing & offsets
Sequence operations carefully: often offset the line first, then create polygons, then offset polygons. This avoids awkward intersections.
If parts look misaligned at ends, tweak start/end offset parameters and the array start/end offsets.
If dash-based roof produces tiny off-cuts, consider block panels for the platform (block approach) or additional trimming techniques later.
9 — Add ticket machines with conditional logic
Create a ticket machine block (rectangle with
base_heightso it sits on platform). Name itticket_machine.Get candidate placement points using
along_point_transformon the platform/roof dashes (e.g., second-last and second positions).Add conditional logic (ternary
if) to insert a third ticket machine for long platforms:Condition:
geometry_length > N(e.g.,> 27 m).If true: compute midpoint (e.g., take the list of along points, find
floor(length/2), pick that item) and include it.If false: return
null(or use a nullish-fixer) so instance group doesn’t fail on null items.
Use an
instance_group_transformto place ticket machine instances at the selected points.
10 — Embed data & package flow
When logic is stable,
embedthe flow data so parameters are stored with the geometry.Rename the flow sensibly (e.g.,
rail_stop_configurator_v1).Keep only the required high-level parameters exposed (e.g.,
platform_length,platform_width,roof_offset,panel_spacing,roof_dash_pattern) — bundle other internal parameters to avoid overwhelming users.
11 — Visual polish & UI values
Set fills, opacities, and materials (e.g., roof color, platform stone color, column dark gray). Set fill opacity to 100% for clarity, and adjust shininess where helpful.
Group usage-driven visual attributes by creating
usages(e.g.,platform,roof,columns) — they carry color, base height, and thickness which flow through when applied.
12 — Testing & edge cases
Test the configurator across short and long platform lengths:
Check start/end panels and columns sizing at very short lengths.
Verify the conditional ticket machine logic toggles exactly at boundary lengths (adjust
Nas needed).
Test corner cases: intersections, nearby obstacles (span panels), and large spans where special panel types are required.
Fix null/empty list errors by wrapping instance inputs in null-safe checks.
13 — Scale & extend
Once functional, clone the flow to create variations (e.g.,
rail_stop_with_canopy,rail_stop_simple,rail_stop_with_more_columns).Add more parameters later:
num_columns,column_spacing,roof_height,canopy_fall, drainage, accessibility features (ramps/elevators), or lighting & MEP placeholders.Export parts lists for fabrication (panel counts, dimensions, weights, crane points) from block instances.
14 — Best practices & tips
Bundle low-level parameters so users see a small, meaningful set of controls.
Prefer blocks for repeatable, fabricable elements (precast panels) when you need accurate counts/weights.
Use stroke/dash for fast architectural iterations; use block arrays for engineering/fabrication detail.
Name your blocks and flows clearly —
panel_middle,panel_start,ticket_machine,roof_usage— it speeds development.Sequence transforms to avoid geometry conflicts (offset → polygon → dash → instance).
Handle exceptions explicitly: starts, ends, inside/outside corners, intersections.
