Flood Alignment Pipeline — Reference

Rhino Formatting Guide

Layer names and 3D geometry encode every value FloodAdapt needs. Author the design; the pipeline reads the metadata.

v1.0 · March 2026

Here's how you name the layers and how that naming breaks down to pieces of information that inform FloodAdapt. The pipeline reads the layer name and (where present) the geometry's Z coordinates, then writes a ready-to-ingest GeoJSON. Per-feature attribute entry via Rhino's SetUserText is still supported as an override but is no longer required.

01Layer Names

The pattern is:

Layer name pattern
<canonical_type>[_<value><unit>][_<value><unit>]

The canonical type tells the pipeline what kind of intervention this is. Each trailing _<value><unit> token sets one parameter on every feature on that layer. Tokens stack and are order-independent; a plain canonical name (no suffix) uses the layer's defaults.

Canonical types

Layer nameBecomesGeometryWhat it represents
leveelevee measureLineStringEarthen embankment / generic wall
seawalllevee measure (seawall variant)LineStringShoreline barrier
gategate measureLineStringDeployable barrier / floodgate
platformlevee measure (platform variant)PolygonFlat elevated pad — single crest height
mesh_surfacemany platform measures3D Mesh / Brep / SurfaceElevated form with grading — auto-contoured into iso-band platforms
pumppump measure2-vertex LineStringActive stormwater pump (line direction = source → sink)
culvertculvert measure2-vertex LineStringPassive drainage culvert (inlet → outlet)
retentionretention basinPolygonDetention / retention basin
green_infragreen infrastructurePolygonDistributed green infra coverage area
buildingscustom building exposurePolygon / Brep / MeshProposed or hypothetical building footprint

Suffix units

Append _<value><unit> to encode a parameter. The unit determines the attribute and which conversion (if any) is applied. Units that aren't valid for the canonical type are rejected with a warning and the layer still resolves without that attribute.

SuffixSetsConversionValid on
mcrest_elevation_m× 1levee, seawall, gate, platform
cmscapacity_cms× 1pump, culvert
m3scapacity_cms (alias)× 1pump, culvert
m3capacity_m3× 1retention
mmhrinfiltration_rate_mm_hr× 1retention
pctretention_pct÷ 100green_infra

Examples

Layer nameResolves to
seawall_5.33m seawall measure with crest_elevation_m = 5.33
platform_4.064m platform with crest_elevation_m = 4.064
pump_20cms  or  pump_20m3s pump with capacity_cms = 20
retention_10000m3 retention basin with capacity_m3 = 10000
retention_10000m3_5mmhr retention basin with capacity_m3 = 10000, infiltration_rate_mm_hr = 5
green_infra_30pct green infrastructure with retention_pct = 0.30

Multiple input layers can resolve to the same canonical type with different parameter values. pump_5cms and pump_20cms both write into one <stem>_pump.geojson with mixed-capacity features; the pipeline reads capacity per-feature.

Variants _v<N> and options _opt<X>

Two tag suffixes let you author multiple design alternatives in one Rhino file. They serve different purposes and follow different rules — pick the right one.

SuffixMeaningTypical useCo-linking
_v1, _v2, … Design variant — paired across multiple measure types that move together. Seawall + pump pairs: seawall_v1 goes with pump_20cms_v1; seawall_v2 goes with pump_5cms_v2. Coupled. The scenario builder snaps all variant-bearing measures to the same v# at once. Mixed pairs (e.g. seawall v1 + pump v2) are not run.
_optA, _optB, … Independent option — exclusive alternatives for a single measure type that are not tied to any other measure. Platform proposals: platform_optA, platform_optB, platform_optC — three distinct platform designs to evaluate side-by-side. Decoupled. Selecting platform option A does not change which seawall or pump is active. Currently only used on the platform layer.

Each variant + option combination writes to its own geojson: platform_optA_4.064m<stem>_platform_optA.geojson. The properties dict on every feature carries variant and/or option fields so downstream code can filter.

Tags are order-independent and stack with parameter tokens. platform_optA_4.064m, platform_4.064m_optA, and platform_optA (with crest set via UserText) all resolve correctly.

02Auto-Derive From Geometry Z

Drawing geometry at non-zero Z lets the pipeline read elevation directly. Z values are converted from the source CRS units to metres automatically — Rhino models in EPSG:2263 (US survey feet) get a 0.3048 multiplier; EPSG:32618 (metres) doesn't. The factor is logged on every ingest.

Barriers and platforms

For LineStrings on levee / seawall / gate layers and Polygons on the platform layer:

Z valuesWhat happens
All vertices at z=0 (the default Rhino plane) No Z signal — falls through to layer-name suffix or layer default.
All vertices at uniform Z (range ≤ 0.05 m) Mean Z becomes crest_elevation_m.
Z varies (range > 0.05 m) Refused — feature is skipped with a warning. Either flatten, move to mesh_surface, or set crest_elevation_m via UserText.

Buildings

For 3D Brep / Mesh / Extrusion footprints on the buildings layer:

2D building footprints (closed polylines drawn flat) keep working — the pipeline samples ground elevation from the DEM and uses the layer-default height.

mesh_surface (the special case)

For elevated forms with grading — a rail station with sloping ramps, a podium that steps down between streets, a complex landform — author the design as a single 3D mesh on a layer named mesh_surface. The pipeline rasterizes the mesh to a height field, slices it into elevation bands at --contour-interval (default 0.5 m), and emits one platform polygon per band. Each polygon is tagged with the band's mid-elevation as crest_elevation_m.

Per-mesh UserText keys contour_interval_m and raster_res_m override the CLI defaults for that mesh.

Below-grade portions are masked, not excavated

Iso-band features carry raise_only=true automatically. If part of the massing dips below existing grade — a ramp that overshoots, a modeling artifact — those cells leave the SFINCS DEM at its existing terrain value rather than digging a trench. You'll see an raise_only platforms: N cells left at existing grade line in the SFINCS run log when this happens.

03Geometry per Layer

LayerWhat to draw
levee, seawall, gate Open polyline — do not close. Snap endpoints precisely to avoid gaps.
platform, retention, green_infra Closed polyline or closed curve.
mesh_surface 3D Mesh / Brep / Surface — the design's elevation IS the source of truth.
pump, culvert 2-vertex polyline. First vertex = source / inlet; second vertex = sink / outlet. Direction encodes flow.
buildings Closed polyline, Extrusion, Brep, or Mesh. 3D solids let the pipeline read ground + height from Z.

04Coordinate System

Declare the CRS at ingest time. Common options:

CRSEPSGUnits
NY State Plane Long Island2263US survey feet (auto-converted)
NY State Plane LI (NAD83 2011)6539US survey feet (auto-converted)
UTM Zone 18N32618metres
Terminal
python scripts/ingest_cad.py my_design.3dm --source-crs EPSG:2263
Match Rhino model units to the declared CRS

The pipeline auto-detects whether the CRS is foot-based or metre-based and applies the conversion to Z values. But if your Rhino model is drawn in metres and you declare a foot-based CRS (or vice versa), Z will be off by 3.28×. Verify the per-ingest log line:

      source CRS 'EPSG:2263' uses 'us survey foot' → z×0.3048

05Precedence

When multiple sources supply the same attribute, the higher source wins:

#SourceGranularityUse when…
1Layer-map defaultAll features on layer Lowest fallback. Implicit; nothing to author.
2Layer-name suffixAll features on layer One value applies to every feature on the layer (e.g. all pumps on this layer have capacity 20 m³/s).
3Geometry ZPer-feature You drew the design at the right elevation — no extra typing needed.
4Per-object UserTextPer-feature Highest. Explicit override for one feature.

06UserText (Override Path)

For per-feature exceptions — one pump that's bigger than the rest, one barrier with a custom name — use Rhino's SetUserText command. UserText overrides everything from the layer name and from geometry Z.

Rhino Command Line
SetUserText crest_elevation_m 5.33
SetUserText capacity_cms 12.5
SetUserText measure_name "East Harlem Seawall — Section A"

// On a mesh_surface mesh, override the contour interval / resolution
SetUserText contour_interval_m 0.25
SetUserText raster_res_m 0.5

07Pitfalls

MistakeWhat goes wrongFix
Closed polyline for a barrier Read as a Polygon — barrier becomes a filled area, not a line Open the curve (delete the closing segment)
Pump line drawn river → inland Pump pumps water into the protected area instead of draining it Reverse the line direction (first vertex = source, second = sink)
Barrier polyline with varying Z (snapped to terrain) Feature refused with a warning — no output Flatten the polyline, use mesh_surface, or set crest_elevation_m via UserText
pump_20m3 (volume unit on a flow-rate-rated pump) Token rejected with a warning; capacity falls back to default 5 m³/s Use pump_20cms or pump_20m3s
Stacked contour-platforms for a graded surface Tedious, error-prone, out of sync with the 3D source Author one 3D mesh on the mesh_surface layer; the pipeline contours it
3D massing that dips below existing grade Nothing — those bands are silently masked at burn time (no excavation) No fix needed. The pipeline tags mesh_surface bands with raise_only=true so they only ever raise the DEM. Check the run log for raise_only platforms: N cells left at existing grade.
Rhino model in metres but ingested with a foot-based CRS Z values 3.28× too low (or the inverse) Match model units to the CRS. Verify the ingest log: z×0.3048 vs z×1.0000
Stray geometry on an unrecognized layer Skipped with a warning — no output for those features Move to a canonical layer or delete
Quick validation

Run python scripts/ingest_cad.py your_file.3dm --source-crs EPSG:2263 --dry-run to see exactly what the ingest will produce — every layer, every feature, every parsed suffix, every Z signal — without writing any files.