# Bridge Alignment Guide

## Overview

Bridge alignments define the horizontal and vertical geometry of roadways and structures. In OpenBrIM, all 3D geometry and FEA models are positioned relative to alignments using station-based coordinates. This guide explains how to implement alignment-based positioning for bridge objects.

**Key Concepts:**

* **Alignment**: A 3D curve defined by horizontal geometry, vertical profile, and cross-slope (transverse)
* **Station**: Distance along the alignment centerline (longitudinal coordinate)
* **Offset**: Perpendicular distance from alignment centerline (transverse coordinate)
* **Elevation**: Vertical coordinate derived from vertical profile and superelevation
* **Alignment Modes**: How objects follow alignment geometry (Warp, Orient, Ignore)
* **Sub-Alignments**: Secondary alignments for edges, gridlines, and complex geometry

## Alignment Coordinate Systems

### 1. Global vs Alignment-Based Coordinates

**Global Coordinates (X, Y, Z):**

* Standard Cartesian coordinates
* Project-wide coordinate system
* Used for fixed geometry

**Alignment-Based Coordinates (Station, Offset, Elevation):**

* **Station (X)**: Distance along alignment centerline
* **Offset (Y)**: Perpendicular distance from centerline (positive typically = left)
* **Elevation (Z)**: Height relative to alignment vertical profile

### 2. Alignment Components

**Horizontal Alignment:**

* Tangents, curves, spirals
* Defines plan view geometry
* Accessed via `alignH()`, `alignHX()`, `alignHY()`, `alignHA()` functions

**Vertical Alignment:**

* Grades, vertical curves (parabolic)
* Defines profile elevation
* Accessed via `alignV()` function

**Transverse/Superelevation:**

* Cross-slope rotation of roadway
* Banking in curves
* Accessed via `alignT()`, `alignTA()` functions

***

## Alignment Modes

### 1. AlignH - Horizontal Alignment Mode

Controls how objects follow the horizontal alignment curvature.

**Values:**

* `AlignH="Warp"` - Follow alignment curvature (default for most bridge objects)
* `AlignH="Orient"` - Orient tangent to alignment but don't warp
* `AlignH="Ignore"` - Ignore horizontal alignment (straight in global coordinates)
* `AlignH="0"` (Right), `AlignH="1"` (Center), `AlignH="2"` (Left) - Alignment rule for girders

**Example - Deck Following Alignment:**

```xml
<O N="ConcreteDeck" T="Line"
   Alignment="deck_alignment"
   AlignH="Warp"
   AlignV="Warp"
   AlignT="Warp">
  <P N="Section" V="DeckSection" T="Section"/>
  <O T="Point" X="0" Y="0" Z="0"/>      <!-- Start station -->
  <O T="Point" X="1200" Y="0" Z="0"/>   <!-- End station -->
</O>
```

**Warp vs Orient:**

* **Warp**: Cross-section follows alignment curvature (curves with road)
* **Orient**: Cross-section rotates to be tangent but remains planar

### 2. AlignV - Vertical Alignment Mode

Controls how objects follow the vertical profile.

**Values:**

* `AlignV="Warp"` - Follow vertical profile elevation changes
* `AlignV="Ignore"` - Ignore vertical profile

**Example:**

```xml
<O N="Girder" T="Line" Alignment="deck_alignment" AlignV="Warp">
  <!-- Girder follows vertical grades and curves -->
</O>
```

### 3. AlignT - Transverse/Superelevation Mode

Controls how objects follow cross-slope rotation.

**Values:**

* `AlignT="Warp"` - Follow superelevation rotation
* `AlignT="Ignore"` - No superelevation rotation
* `AlignT="mid_grd_algnT"` - Custom transverse mode from parameter

**Example - Deck Section with Selective Transverse:**

```xml
<O N="DeckSection" T="Section">
  <O T="Shape" AlignH="Orient" AlignY="0">
    <!-- Top of deck - no transverse rotation -->
    <O T="Point" X="staDepLeftY3d" Y="0" AlignTB="No"/>

    <!-- Bottom of overhang - follow transverse rotation -->
    <O T="Point" X="staDepLeftY3d" Y="-sd_oh_left" AlignT="Warp" AlignTB="No"/>
  </O>
</O>
```

### 4. AlignTB - Transverse Banking

Controls transverse rotation behavior for individual points.

**Values:**

* `AlignTB="No"` or `AlignTB="0"` - Do not apply transverse banking to this point
* `AlignTB="Yes"` or `AlignTB="2"` - Apply transverse banking (default)

***

## Primary Alignment Reference

### Specifying the Alignment

Use the `Alignment` attribute to reference the alignment object:

```xml
<O N="DeckObject" T="Line" Alignment="deck_alignment">
  <!-- Object positioned relative to deck_alignment -->
</O>
```

**Parameter Definition:**

```xml
<P N="deck_alignment" V="bridge.centerlineAlignment" T="Alignment"/>
```

### Station-Based Geometry

Points are defined using station (X coordinate):

```xml
<O T="Line" Alignment="deck_alignment" AlignH="Warp" AlignV="Warp" AlignT="Warp">
  <O T="Point" X="100*12" Y="0" Z="0"/>   <!-- Station 100 ft (1200 in) -->
  <O T="Point" X="200*12" Y="0" Z="0"/>   <!-- Station 200 ft (2400 in) -->
</O>
```

**Key Points:**

* X = Station along alignment
* Y = Offset from centerline (+ = left, - = right typically)
* Z = Elevation offset from alignment vertical profile

***

## Sub-Alignments

Sub-alignments allow objects to follow secondary alignment paths (deck edges, girder paths, etc.).

### 1. SubAlignment Attribute

**Syntax:**

```xml
<O T="Point" X="0" Y="0"
   Alignment="deck_alignment"
   SubAlignment="left_edge_alignment"/>
```

**Use Cases:**

* Deck edge geometry following independent edge paths
* Girder paths that may vary from deck centerline
* Utility conduits with custom routing

### 2. Deck Edge Sub-Alignments

**Pattern:**

```xml
<P N="left_edge_alignment" V="..." T="Alignment" Role="Input"/>
<P N="right_edge_alignment" V="..." T="Alignment" Role="Input"/>

<O N="DeckSection" T="Section">
  <O T="Shape">
    <!-- Left edge points follow left edge alignment -->
    <O T="Point" X="-barrierWidth" Y="0"
       Alignment="deck_alignment"
       SubAlignment="left_edge_alignment"/>

    <!-- Right edge points follow right edge alignment -->
    <O T="Point" X="barrierWidth" Y="0"
       Alignment="deck_alignment"
       SubAlignment="right_edge_alignment"/>
  </O>
</O>
```

**When Using Sub-Alignments:**

* Primary `Alignment` provides base coordinate system
* `SubAlignment` provides local path to follow
* X coordinate on sub-alignment is relative to sub-alignment's station
* Useful for variable-width structures with independent edge geometries

### 3. Girder Path Sub-Alignments

**Pattern:**

```xml
<P N="gpath" V="grd.girder_path" T="Alignment"/>

<O T="Point" Y="GTz" X="lftH"
   SubAlignment="gpath"
   AlignH="g_a_rule"
   AlignmentLine="ref_no_elev"
   AlignmentLineX="algnXs"
   AlignT="mid_grd_algnT"
   AlignTB="mid_grd_algnTB"/>
```

**Purpose:**

* Deck section points follow girder paths for haunches
* Each girder can have unique horizontal geometry
* Creates variable deck thickness over girders

***

## Alignment Functions

### 1. Horizontal Alignment Functions

#### `alignH(alignment, station, offset)`

Returns all horizontal alignment data at once.

**Returns:** Object - `{X, Y, Angle}`

**Example:**

```xml
<P N="HData" V="alignH(deck_alignment, 600, 0)"/>
<P N="GlobalX" V="HData.X"/>
<P N="GlobalY" V="HData.Y"/>
<P N="Bearing" V="HData.Angle"/>
```

***

#### `alignHX(alignment, station, offset)`

Returns global X coordinate.

**Example:**

```xml
<P N="PierX" V="alignHX(deck_alignment, 100*12, 0)"/>
```

***

#### `alignHY(alignment, station, offset)`

Returns global Y coordinate.

**Example:**

```xml
<P N="PierY" V="alignHY(deck_alignment, 100*12, 0)"/>
```

***

#### `alignHZ(alignment, station, offset)`

Returns global Z coordinate (horizontal plane only, NOT vertical profile).

**Note:** Use `alignV()` for vertical profile elevation.

***

#### `alignHA(alignment, station, offset)`

Returns horizontal angle (bearing) at station.

**Example:**

```xml
<P N="BearingAngle" V="alignHA(deck_alignment, 600, 0)"/>
```

***

### 2. Vertical Alignment Functions

#### `alignV(alignment, station)`

Returns vertical profile elevation at station.

**Example:**

```xml
<P N="ProfileElev" V="alignV(deck_alignment, 100*12)"/>
```

***

### 3. Transverse/Superelevation Functions

#### `alignT(alignment, station, offset, mode?)`

Returns transverse elevation (superelevation) at station and offset.

**Parameters:**

* `alignment` (Alignment): The alignment object
* `station` (Number): Station value
* `offset` (Number): Transverse offset from centerline
* `mode` (Number, optional): Calculation mode

**Returns:** Number - Transverse elevation

**Example:**

```xml
<!-- Elevation difference between two offsets -->
<P N="alignTDifLeft" V="-alignT(deck_alignment, coord_x_left, staDepLeftY3d - leftTopChamfer)
                          + alignT(deck_alignment, coord_x_left, staDepLeftY3d - barrierWidth, 0)"/>
```

**Use Cases:**

* Computing deck cross-slope
* Variable deck thickness due to superelevation
* Barrier/rail positioning

***

#### `alignTA(alignment, station, offset)`

Returns transverse slope angle.

**Returns:** Number - Slope angle in radians

***

### 4. Coordinate Conversion Functions

#### `alignLocal(alignment, x, y, z)`

Converts global coordinates to local alignment coordinates.

**Returns:** Object - `{Station, Offset}`

**Example:**

```xml
<P N="LocalCoords" V="alignLocal(deck_alignment, 1000, 500, 0)"/>
<P N="Station" V="LocalCoords.Station"/>
<P N="Offset" V="LocalCoords.Offset"/>
```

***

## Station-Dependent Parameters

### 1. Station-Dependent Values

Parameters can vary along alignment station using the station-dependent format or `makestadep()` function.

**Array Format:**

```xml
<P N="Depth" V="[[0, 1200], 60, [1200, 2400], 72, [2400, 3600], 60]"/>
<!-- Station 0-1200: 60", Station 1200-2400: 72", Station 2400-3600: 60" -->
```

**makestadep Function:**

```xml
<P N="gstas" V="[0, 1200, 2400, 3600]"/>
<P N="off_list" V="[[10, 12], [12, 15], [15, 12], [12, 10]]"/>
<P N="variation" V="['linear', 'linear', 'linear']"/>
<P N="off_sd" V="makestadep(gstas, off_list, variation)"/>
```

***

### 2. Using atstation() with Alignment Values

Evaluate station-dependent parameters at specific locations:

```xml
<P N="DepthAtMidspan" V="atstation(600, Depth)"/>
```

***

## Alignment Lines for Sections

### 1. AlignmentLine and AlignmentLineX

For sections with multiple points following different paths, use alignment lines to map points to their respective paths.

**Syntax:**

```xml
<O T="Point" X="lftH" Y="GTz"
   AlignmentLine="ref_no_elev"
   AlignmentLineX="algnXs"/>
```

**Where:**

* `AlignmentLine`: Array of path coordinates defining the line to follow
* `AlignmentLineX`: Array of stations where alignment line is defined

**Example - Girder Haunch Points:**

```xml
<P N="ref_no_elev" V="map(grd.sPts, [x[0], x[1], 0])"/>  <!-- Girder path points -->
<P N="algnXs" V="map(grd.supports, x.gs_loc.s_sta)"/>     <!-- Support stations -->

<O T="Point" Y="GTz" X="lftH"
   SubAlignment="gpath"
   AlignH="g_a_rule"
   AlignmentLine="ref_no_elev"
   AlignmentLineX="algnXs"/>
```

**Purpose:**

* Section points follow girder paths instead of deck centerline
* Creates haunches, variable thickness over supports
* Each point can follow independent alignment path

***

### 2. Grid Lines and GridsYAlignH

For FEA meshing with multiple gridlines following different alignments.

**Syntax:**

```xml
<O T="FEMeshSurface"
   Alignment="deck_alignment"
   GridLinesY="gridlines"
   GridsYAlignH="gridalignlist">
```

**Where:**

* `GridLinesY`: Array of gridline paths (typically girder centerlines)
* `GridsYAlignH`: Array of alignment rules for each gridline (0=Right, 1=Center, 2=Left)

**Example:**

```xml
<P N="gridlines" V="concat([leftGridline], grd_lines_all_mod, [rightGridline])"/>
<P N="gridalignlist" V="concat([2], map(grd_lines_all, 1), [0])"/>
<!-- Left edge = 2 (Left), Girders = 1 (Center), Right edge = 0 (Right) -->

<O T="FEMeshSurface"
   Alignment="deck_alignment"
   GridLinesY="gridlines"
   GridsYAlignH="gridalignlist"
   AlignH="Warp"
   AlignV="Warp"
   AlignT="Warp">
</O>
```

***

## Skew and Rotation

### 1. Skew Angles

Apply skew angles at start and end of objects using `StartSkewX` and `EndSkewX`.

**Syntax:**

```xml
<O T="Line"
   Alignment="deck_alignment"
   StartSkewX="s_st_skew"
   EndSkewX="s_end_skew"
   SkewOnFacesOnly="1">
```

**Example - Computing Skew from Support Lines:**

```xml
<P N="s_st_sta" V="100*12"/>
<P N="s_end_sta" V="200*12"/>

<!-- Extract skew angles from support line data -->
<P N="s_st_skew" V="onlinex(sup_line_skews, s_st_sta)[1]"/>
<P N="s_end_skew" V="onlinex(sup_line_skews, s_end_sta)[1]"/>

<O N="ConcreteDeck" T="Line"
   Alignment="deck_alignment"
   StartSkewX="s_st_skew"
   EndSkewX="s_end_skew"
   SkewOnFacesOnly="1">
  <O T="Point" X="s_st_sta" Y="0" Z="0"/>
  <O T="Point" X="s_end_sta" Y="0" Z="0"/>
</O>
```

**SkewOnFacesOnly:**

* `SkewOnFacesOnly="1"`: Apply skew only to end faces (most common for bridges)
* `SkewOnFacesOnly="0"`: Skew entire object geometry

***

### 2. Skew Compensation in Section Points

When skew is applied, section points may need coordinate adjustments:

```xml
<P N="x_left_st" V="(staDepLeftY3d - leftTopChamfer) * tan(s_st_skew)"/>
<P N="x_left_end" V="(staDepLeftY3d - leftTopChamfer) * tan(s_end_skew)"/>

<!-- Station-dependent X coordinate accounting for skew -->
<P N="coord_x_left" V="[[s_st_sta, s_end_sta],
                        variation('linear', s_st_sta + x_left_st, s_end_sta + x_left_end)]"/>
```

***

## Complete Deck Alignment Example

### Deck Object with Full Alignment Implementation

```xml
<O N="OBPBase_GirderDeck" T="Project">
  <!-- Alignment references -->
  <P N="deck_alignment" V="bridge.centerlineAlignment" T="Alignment"/>
  <P N="left_edge_alignment" V="NULL" T="Alignment" Role="Input"/>
  <P N="right_edge_alignment" V="NULL" T="Alignment" Role="Input"/>

  <!-- Deck geometry parameters -->
  <P N="sd_thickness" V="8"/>
  <P N="sd_oh_left" V="36"/>
  <P N="sd_oh_right" V="36"/>

  <!-- Station extents -->
  <P N="s_st_sta" V="0"/>
  <P N="s_end_sta" V="1200"/>

  <!-- Skew angles -->
  <P N="s_st_skew" V="0"/>  <!-- radians -->
  <P N="s_end_skew" V="0.1"/>  <!-- 5.7 degrees -->

  <!-- 3D Deck Volume -->
  <O N="ConcreteDeck" T="Line"
     Alignment="deck_alignment"
     AlignH="Warp"
     AlignV="Warp"
     AlignT="Warp"
     StartSkewX="s_st_skew"
     EndSkewX="s_end_skew"
     SkewOnFacesOnly="1"
     SegmentsAlong="30">

    <P N="Section" V="DeckSection" T="Section"/>

    <O T="Point" X="s_st_sta" Y="0" Z="0"/>
    <O T="Point" X="s_end_sta" Y="0" Z="0"/>
  </O>

  <!-- Deck Section Definition -->
  <O N="DeckSection" T="Section" Is3DOnly="1">
    <O T="Shape" AlignH="Orient" AlignY="0">

      <!-- Left edge - follow left_edge_alignment if provided -->
      <O T="Point" X="-leftTopChamfer" Y="0"
         Guard="left_edge_alignment != NULL"
         Alignment="deck_alignment"
         SubAlignment="left_edge_alignment"/>

      <O T="Point" X="0" Y="-leftTopChamfer"
         AlignTB="No"
         Guard="left_edge_alignment != NULL"
         Alignment="deck_alignment"
         SubAlignment="left_edge_alignment"/>

      <O T="Point" X="0" Y="-sd_oh_left"
         AlignT="Warp"
         AlignTB="No"
         Guard="left_edge_alignment != NULL"
         Alignment="deck_alignment"
         SubAlignment="left_edge_alignment"/>

      <!-- Left edge - default (no sub-alignment) -->
      <O T="Point" X="staDepLeftY3d-leftTopChamfer" Y="0"
         Guard="left_edge_alignment == NULL"/>

      <O T="Point" X="staDepLeftY3d" Y="-leftTopChamfer"
         AlignTB="No"
         Guard="left_edge_alignment == NULL"/>

      <O T="Point" X="staDepLeftY3d" Y="-sd_oh_left"
         AlignT="Warp"
         AlignTB="No"
         Guard="left_edge_alignment == NULL"/>

      <!-- Girder haunch points (repeat for each girder) -->
      <O N="LREP" T="Repeat" S="0" E="length(girders_at_span)-1" I="1" CTRL="index" index="0">
        <P N="grd" V="girders_at_span[index]"/>
        <P N="gpath" V="grd.girder_path"/>
        <P N="ref_no_elev" V="map(grd.sPts, [x[0], x[1], 0])"/>
        <P N="algnXs" V="map(grd.supports, x.gs_loc.s_sta)"/>
        <P N="GTz" V="-sd_thickness + grd.top_off_3d + at_sd"/>
        <P N="lftH" V="off_sd + grd.tf_w * 0.5"/>

        <O T="Point" Y="GTz" X="lftH"
           SubAlignment="gpath"
           AlignH="g_a_rule"
           AlignmentLine="ref_no_elev"
           AlignmentLineX="algnXs"
           AlignT="Ignore"
           AlignTB="0"/>
      </O>

      <!-- Right edge - similar to left edge -->
      <O T="Point" X="0" Y="-sd_oh_right"
         AlignT="Warp"
         AlignTB="No"
         Guard="right_edge_alignment != NULL"
         Alignment="deck_alignment"
         SubAlignment="right_edge_alignment"/>
    </O>
  </O>
</O>
```

***

## FEA Mesh Alignment Implementation

### FEMeshSurface with Multiple Gridlines

```xml
<O N="DECK" T="FEMeshSurface"
   Alignment="deck_alignment"
   AlignH="Warp"
   AlignV="Warp"
   AlignT="Warp"
   GridLinesY="gridlines"
   GridsYAlignH="gridalignlist"
   SubAlignments="all_sub_algn"
   AlignmentLine="mesh_align_lines"
   AlignmentLineX="mesh_align_lines_x"
   MeshDirection="[[0,0,0], [1,0,0], [1,1,0]]"
   CX="longMeshSize"
   CY="120"
   Thickness="sd_thickness"
   Material="@d_mat|Material">

  <!-- Mesh boundary surface -->
  <O T="Surface"
     EndNodeTx="tx_stadep"
     EndNodeTy="ty_stadep"
     EndNodeTz="tz_stadep"
     EndNodeRx="rx_stadep"
     EndNodeRy="ry_stadep"
     EndNodeRz="rz_stadep">

    <O T="Repeat" S="0" E="length(meshboundary_)-1" I="1" CTRL="index" index="0">
      <O T="Point"
         X="meshboundary_[index][0]"
         Y="meshboundary_[index][1]"
         Z="meshboundary_[index][2]"/>
    </O>
  </O>

  <!-- Mesh regions with thickness overrides -->
  <O T="FEMeshRegion"
     Node1OffZ="lOffZ"
     Node2OffZ="lOffZ"
     Node3OffZ="lOffZ"
     Node4OffZ="lOffZ"
     Thickness="sd_oh_left">
    <!-- Left overhang region -->
  </O>

  <O T="FEMeshRegion"
     Node1OffZ="rOffZ"
     Node2OffZ="rOffZ"
     Node3OffZ="rOffZ"
     Node4OffZ="rOffZ"
     Thickness="sd_oh_right">
    <!-- Right overhang region -->
  </O>
</O>
```

**Key FEA Alignment Parameters:**

* `GridLinesY`: Array of gridline paths (girder centerlines, deck edges)
* `GridsYAlignH`: Alignment rule for each gridline (0/1/2)
* `SubAlignments`: Array of sub-alignment objects for gridlines
* `AlignmentLine`/`AlignmentLineX`: Station-dependent alignment path
* `MeshDirection`: Orientation of mesh quad elements

***

## Best Practices

### 1. Alignment Reference Organization

**Organize alignment parameters in a dedicated group:**

```xml
<O N="AlignmentRefs" T="Group">
  <P N="deck_alignment" V="bridge.centerlineAlignment" T="Alignment"/>
  <P N="left_edge_alignment" V="NULL" T="Alignment" Role="Input"/>
  <P N="right_edge_alignment" V="NULL" T="Alignment" Role="Input"/>
</O>
```

***

### 2. Station Extent Calculations

**Always compute station extents from span data:**

```xml
<P N="s_st_sta" V="iif(sp[0] == d_css[0][0],
                       d_css[0][0].s_sta + d_css[0][1],
                       sp[0].s_sta) - iif(si == 0, cantLengStart, 0)"/>

<P N="s_end_sta" V="iif(sp[1] == last(d_css)[0],
                        last(d_css)[0].s_sta + last(d_css)[1],
                        sp[1].s_sta) + iif(si == length(spans)-1, cantLengEnd, 0)"/>
```

***

### 3. Conditional Sub-Alignments

**Use guards to switch between centerline and edge alignments:**

```xml
<!-- With sub-alignment -->
<O T="Point" X="0" Y="-sd_oh_left"
   Guard="left_edge_alignment != NULL"
   Alignment="deck_alignment"
   SubAlignment="left_edge_alignment"
   AlignT="Warp"
   AlignTB="No"/>

<!-- Without sub-alignment -->
<O T="Point" X="staDepLeftY3d" Y="-sd_oh_left"
   Guard="left_edge_alignment == NULL"
   AlignT="Warp"
   AlignTB="No"/>
```

***

### 4. Station-Dependent Paths

**Use makestadep for girder paths with varying offsets:**

```xml
<P N="gstas" V="map(grd.supports, x.gs_loc.s_sta)"/>
<P N="offsets" V="map(ref_corr_forstadep, x[1])"/>
<P N="off_list" V="filter(map(offsets, [offsets[xi-1], x]), xi > 0)"/>
<P N="variation" V="map(off_list, 'linear')"/>
<P N="off_sd" V="makestadep(gstas, off_list, variation)"/>
```

***

### 5. Transverse Elevation Differences

**Compute relative transverse elevations for variable thickness:**

```xml
<P N="alignTDifLeft" V="-alignT(deck_alignment, coord_x_left, staDepLeftY3d-leftTopChamfer)
                        + alignT(deck_alignment, coord_x_left, staDepLeftY3d-barrierWidth, 0)"/>

<O T="Point" X="staDepLeftY3d-barrierWidth" Y="additionalTh+alignTDifLeft"/>
```

***

### 6. Mesh Alignment Lines

**Provide alignment lines for complex mesh geometry:**

```xml
<P N="mesh_align_lines" V="concat([leftGridline], girder_paths, [rightGridline])"/>
<P N="mesh_align_lines_x" V="concat([left_stations], girder_stations, [right_stations])"/>

<O T="FEMeshSurface"
   AlignmentLine="mesh_align_lines"
   AlignmentLineX="mesh_align_lines_x">
</O>
```

***

## Common Pitfalls

### 1. Missing Alignment Mode Specifications

**Problem:** Not specifying AlignH/AlignV/AlignT

```xml
<!-- Wrong - no alignment modes -->
<O T="Line" Alignment="deck_alignment">
```

**Solution:** Always specify alignment modes explicitly

```xml
<!-- Correct -->
<O T="Line" Alignment="deck_alignment" AlignH="Warp" AlignV="Warp" AlignT="Warp">
```

***

### 2. Incorrect AlignTB Usage

**Problem:** Forgetting AlignTB="No" for points that shouldn't rotate

```xml
<!-- Wrong - top of deck will rotate with superelevation -->
<O T="Point" X="0" Y="0"/>
```

**Solution:** Explicitly disable transverse banking where needed

```xml
<!-- Correct - top of deck stays level -->
<O T="Point" X="0" Y="0" AlignTB="No"/>
```

***

### 3. Sub-Alignment Without Primary Alignment

**Problem:** Using SubAlignment without Alignment

```xml
<!-- Wrong - no primary alignment -->
<O T="Point" X="0" Y="0" SubAlignment="left_edge_alignment"/>
```

**Solution:** Always specify both

```xml
<!-- Correct -->
<O T="Point" X="0" Y="0"
   Alignment="deck_alignment"
   SubAlignment="left_edge_alignment"/>
```

***

### 4. Station vs Global Coordinates Confusion

**Problem:** Using global coordinates when alignment is specified

```xml
<!-- Wrong - X should be station, not global coordinate -->
<O T="Line" Alignment="deck_alignment">
  <O T="Point" X="1000000" Y="500000" Z="100"/>
</O>
```

**Solution:** Use station-based coordinates

```xml
<!-- Correct - X is station along alignment -->
<O T="Line" Alignment="deck_alignment">
  <O T="Point" X="1200" Y="0" Z="0"/>  <!-- Station 1200 inches -->
</O>
```

***

### 5. Skew Angle Units

**Problem:** Using degrees instead of radians

```xml
<!-- Wrong - skew angles in degrees -->
<P N="s_st_skew" V="30"/>  <!-- 30 degrees? -->
```

**Solution:** Convert to radians

```xml
<!-- Correct - skew in radians -->
<P N="s_st_skew" V="30 * PI / 180"/>  <!-- 30 degrees = 0.524 radians -->
```

***

## Summary

Bridge alignment implementation in OpenBrIM uses station-based positioning to create complex 3D geometry and FEA models:

**Core Concepts:**

* **Alignment Modes**: AlignH, AlignV, AlignT control how objects follow alignment geometry
* **Station Coordinates**: X = station, Y = offset, Z = elevation offset
* **Sub-Alignments**: Secondary paths for edges, girders, and complex geometry
* **Alignment Functions**: alignH(), alignV(), alignT() for coordinate transformation

**Key Patterns:**

* Primary alignment reference with `Alignment="deck_alignment"`
* Alignment modes: `AlignH="Warp"`, `AlignV="Warp"`, `AlignT="Warp"`
* Sub-alignments for deck edges: `SubAlignment="left_edge_alignment"`
* Girder path following: `AlignmentLine`, `AlignmentLineX`, `SubAlignment`
* Skew angles: `StartSkewX`, `EndSkewX`, `SkewOnFacesOnly`
* Transverse banking control: `AlignTB="No"` for level surfaces

**FEA Mesh Alignment:**

* `GridLinesY` and `GridsYAlignH` for multi-path meshing
* `SubAlignments` array for gridline alignments
* `AlignmentLine`/`AlignmentLineX` for station-dependent paths
* Thickness and offset overrides with `FEMeshRegion`

**Best Practices:**

* Always specify alignment modes explicitly
* Use guards for conditional sub-alignments
* Compute station extents from span data
* Use `makestadep()` for station-dependent geometry
* Specify `AlignTB="No"` for non-rotating surfaces
* Convert skew angles to radians

By following these patterns, AI agents can create accurate bridge geometry that follows roadway alignments through horizontal curves, vertical grades, and superelevation transitions.
