# Parametric Engine Guide

## Overview

OpenBrIM is a cloud-based parametric bridge information modeling platform with an extensible ecosystem where bridge components and concepts are defined in a parametric way and assembled like LEGO pieces to represent bridge projects (3D views, finite element analysis models, CAD drawings, design documents, reports, and more).

This guide explains the core parametric engine for AI agents who will create XML-based components and models using this system.

## Core Concepts

### 1. Objects (`Obj`)

Objects are the fundamental building blocks in the system. Every component, structure, or entity is represented as an object.

**Key characteristics:**

* Every object has a unique `ID` (GUID)
* Every object has a `Name` (`N` attribute)
* Every object has a `Type` (`T` attribute) that defines its class or base object
* Objects can contain **parameters** and **child objects**
* Objects form a hierarchical tree structure through parent-child relationships
* Objects can inherit from other objects by using that object's name as their `Type`

#### 1.1 Library Objects

Library objects are reusable template objects that other objects can inherit from. They follow a specific pattern:

**Library Object Structure:**

```xml
<O N="OBP_GirderStressSummaryTable" T="Project"
   Tags="@secondlayer,usastandard,steelIGirder,release"
   ObjLabel="Girder Stress Summary Table"
   Category="Code Check Objects:Code Check Sub Objects">

  <!-- Define parameters and child objects -->
  <P N="MaxStress" V="0" Role="Input" UT="Stress"/>
  <P N="AllowableStress" V="36" Role="Input" UT="Stress"/>

  <!-- Child objects, calculations, etc. -->
</O>
```

**Key Attributes:**

* `N`: The library object name (used by other objects to inherit from this)
* `T="Project"`: Marks this as a library/template object
* `Tags`: Classification tags for organizing and filtering library objects
  * `@secondlayer`: Visibility layer in UI
  * `usastandard`, `steelIGirder`, `release`: Descriptive tags
* `ObjLabel`: Human-readable display name
* `Category`: Organizational category (uses `:` for subcategories)

**Using Library Objects (Inheritance):**

Other objects reference library objects by setting their `T` attribute to the library object's `N` value:

```xml
<!-- Create an instance that inherits from the library object -->
<O N="Girder1_StressCheck" T="OBP_GirderStressSummaryTable">
  <!-- Override or add parameters specific to this instance -->
  <P N="MaxStress" V="42.5"/>
  <P N="GirderName" V="Girder 1"/>
</O>

<!-- Create another instance with different values -->
<O N="Girder2_StressCheck" T="OBP_GirderStressSummaryTable">
  <P N="MaxStress" V="38.2"/>
  <P N="GirderName" V="Girder 2"/>
</O>
```

**How Inheritance Works:**

1. The child object (`T="OBP_GirderStressSummaryTable"`) inherits all parameters and structure from the library object
2. Child objects can override inherited parameter values
3. Child objects can add new parameters not in the library object
4. Changes to the library object automatically affect all instances (unless overridden)

**Common Library Object Categories:**

* `Code Check Objects`: Design code compliance checks
* `Report Objects`: Report templates and layouts
* `Component Objects`: Reusable structural components (beams, columns, connections)
* `Material Objects`: Material property definitions
* `Section Objects`: Cross-section definitions

**Example: Creating a Custom Library Object**

```xml
<!-- Define a reusable column template -->
<O N="StandardColumn" T="Project"
   Tags="@library,structural,column"
   ObjLabel="Standard Concrete Column"
   Category="Structural Components:Columns">

  <!-- Default parameters -->
  <P N="Width" V="24" Role="Input" UT="Length" D="Column width"/>
  <P N="Depth" V="24" Role="Input" UT="Length" D="Column depth"/>
  <P N="Height" V="120" Role="Input" UT="Length" D="Column height"/>
  <P N="Concrete_fc" V="4000" Role="Input" UT="Stress" D="Concrete strength"/>

  <!-- Geometry definition -->
  <O T="Volume" N="ColumnVolume">
    <!-- Volume definition here -->
  </O>
</O>

<!-- Use the library object in your project -->
<O T="Repeat" N="Columns" S="0" E="5" I="1" CTRL="i" i="0">
  <O N="Column" T="StandardColumn">
    <!-- This column inherits Width, Depth, Height, etc. -->
    <P N="Height" V="120 + i*10"/>  <!-- Override height for this column -->
  </O>
</O>
```

#### 1.2 Export Objects

Export objects are containers within library objects that expose computed parameters and generated child objects to instances. Parameters placed inside `<O T="Export">` containers become accessible to other objects.

**Purpose:**

* Export computed/calculated parameters from library objects to instances
* Make generated child objects (geometry, components, etc.) accessible
* Share internal calculations with other objects in the project
* Parameters with `Role="Input"` are automatically exported - no need to add them to Export objects

**Important Dependency Rule:** If an exported parameter depends on other parameters, those dependencies must also be exported OR have `Role="Input"`. Parameters without a role (private by default) cannot be accessed by exported parameters.

**Export Object Structure:**

```xml
<!-- ❌ WRONG - Exported params depend on non-exported params -->
<O N="WrongExample" T="Project">
  <O T="Group">
    <P N="param1" V="12"/>
    <P N="param2" V="13"/>
  </O>
  <O T="Export">
    <P N="param3" V="param1+param2"/>  <!-- ERROR: param1, param2 not accessible -->
  </O>
</O>

<!-- ✅ CORRECT - Option 1: Put dependencies in Export -->
<O N="CorrectExample1" T="Project">
  <O T="Export">
    <P N="param1" V="12"/>
    <P N="param2" V="13"/>
    <P N="param3" V="param1+param2"/>
  </O>
</O>

<!-- ✅ CORRECT - Option 2: Use Role="Input" for dependencies -->
<O N="CorrectExample2" T="Project">
  <O T="Group">
    <P N="param1" V="12" Role="Input"/>
    <P N="param2" V="13" Role="Input"/>
  </O>
  <O T="Export">
    <P N="param3" V="param1+param2"/>  <!-- OK: param1, param2 are Input -->
  </O>
</O>
```

**Complete Example:**

```xml
<O N="MyLibraryObject" T="Project"
   ObjLabel="Custom Component"
   Category="Components">

  <!-- Input parameters (automatically exported) -->
  <P N="Length" V="100" Role="Input" UT="Length"/>
  <P N="Width" V="50" Role="Input" UT="Length"/>

  <!-- Export object - computed results accessible to other objects -->
  <O T="Export">
    <!-- Can access Role="Input" parameters directly -->
    <P N="ComputedArea" V="Length*Width" UT="Area" D="Total area"/>
    <P N="ComputedPerimeter" V="2*(Length+Width)" UT="Length" D="Total perimeter"/>
    <P N="AspectRatio" V="Length/Width" D="Length to width ratio"/>

    <!-- Generated geometry is also exported -->
    <O T="Surface" N="BoundaryBox">
      <O T="Point" X="0" Y="0" Z="0"/>
      <O T="Point" X="Length" Y="0" Z="0"/>
      <O T="Point" X="Length" Y="Width" Z="0"/>
      <O T="Point" X="0" Y="Width" Z="0"/>
    </O>
  </O>
</O>
```

**How Export Works:**

1. **Input Parameters** (`Role="Input"`):
   * Automatically exported to instances
   * Users can modify these values
   * No need to include in Export objects
   * Can be referenced by parameters inside Export objects
2. **Export Container** (`<O T="Export">`):
   * Parameters inside are accessible to other objects
   * Computed from Input parameters or other exported params
   * Read-only in instances (calculated from library)
   * Child objects (geometry, etc.) inside are also exported
3. **Private Parameters** (no role):
   * NOT accessible to Export parameters
   * Cannot be used as dependencies for exported calculations
   * For internal use only within the same scope

**Using Exported Values:**

When you create an instance of a library object, exported parameters become accessible:

```xml
<!-- Create an instance -->
<O N="MyComponent" T="MyLibraryObject">
  <P N="Length" V="150"/>  <!-- Override input parameter -->
  <P N="Width" V="75"/>    <!-- Override input parameter -->
  <!-- ComputedArea, ComputedPerimeter, AspectRatio are automatically available -->
</O>

<!-- Other objects can reference the exported values -->
<P N="TotalArea" V="MyComponent.ComputedArea"/>
<P N="Ratio" V="MyComponent.AspectRatio"/>
```

**Best Practices:**

1. **Ensure Proper Dependencies**:
   * Exported parameters can ONLY depend on: `Role="Input"` params OR other exported params
   * If you need intermediate calculations, put them inside the Export object
2. **Don't Export Inputs**:
   * Input parameters are already exported automatically
   * Only use Export objects for computed/calculated results
3. **Name Export Objects for Override**:

   * Give Export objects a name (e.g., `<O N="Results" T="Export">`) when you want child objects to override them
   * Named Export groups can be overridden using `Override="1"` in extended objects:

   ```xml
   <!-- Base object -->
   <O N="BaseGirder" T="Project">
     <O N="Calculations" T="Export">
       <P N="Weight" V="Length*UnitWeight"/>
     </O>
   </O>

   <!-- Extended object - override Export group -->
   <O N="HeavyGirder" T="Project" Extends="BaseGirder">
     <O N="Calculations" T="Export" Override="1">
       <P N="Weight" V="Length*UnitWeight*1.5"/>  <!-- Modified formula -->
     </O>
   </O>
   ```
4. **⚠️ CRITICAL: Never Add Guard Directly to T="Export" Objects**:

   **Problem:** When `Guard` is added directly to `T="Export"` objects in library objects, the Guard appears on the library object instance in the source code, which can cause the entire object to not execute.

   ```xml
   <!-- ❌ WRONG: Guard on Export object -->
   <O N="LibraryObject" T="Project" ObjLabel="Library Object">
       <O T="Export" Guard="Param1 .EQ. 0">
           <P N="Param2" V="[1,2,3,4]" />
           <P N="Param3" V="[3,4]" />
       </O>
   </O>

   <!-- Result in app source code: -->
   <O N="Library Object Objects" T="Group">
       <O N="LB1" T="LibraryObject" Guard="Param1 .EQ. 0">  <!-- ❌ Guard on object! -->
           <P N="Param2" V="[1,2,3,4]" />
           <P N="Param3" V="[3,4]" />
       </O>
   </O>
   <!-- The Guard on T="LibraryObject" means the entire object may not execute -->
   ```

   **Solution:** Add Guard to a nested Group within the Export object:

   ```xml
   <!-- ✅ CORRECT: Guard on nested Group -->
   <O N="LibraryObject" T="Project" ObjLabel="Library Object">
       <O T="Export">
           <O N="Group1" T="Group" Guard="Param1 .EQ. 0">
               <P N="Param2" V="[1,2,3,4]" />
               <P N="Param3" V="[3,4]" />
           </O>
       </O>
   </O>

   <!-- Result in app source code: -->
   <O N="Library Object Objects" T="Group">
       <O N="LB1" T="LibraryObject">  <!-- ✅ No Guard on object -->
           <O N="Group1" T="Group" Guard="Param1 .EQ. 0" Exported="1">
               <P N="Param2" V="[1,2,3,4]" />
               <P N="Param3" V="[3,4]" />
           </O>
       </O>
   </O>
   <!-- Guard is on Group1, not on the object itself -->
   ```

   **Rule:** Always wrap guarded parameters in a nested `T="Group"` within the Export object.

**For more details:** See `AI-Export.md`

***

#### 1.3 DesignRun Objects

DesignRun objects are **bridge objects** that override parameters of a target library object specified by `LibObjTypeName`. They work similarly to `Extends` + `Override="1"`, but with a critical restriction: **only parameters that exist within the `LibObjTypeName` object can be overridden** (scoped override, not hierarchical).

**Purpose:**

* Override parameters of a specific library object (scoped to that object only)
* Act as a bridge between user-defined parameters and library object parameters
* Execute design calculations with custom parameter values

**Key Parameters:**

* **`LibObjTypeName`** (CRITICAL): Specifies which library object's parameters to override
* **`LibObjVersion`**: Version number of the target library object

**Key Restrictions:**

1. **Parameters only** - Cannot override child objects (cannot use `Override="1"` on objects)
2. **Must pre-exist** - Can only override parameters that already exist within `LibObjTypeName` scope
3. **Scoped to `LibObjTypeName`** - Overrides parameters within that library object and its extended objects
4. **Includes extended objects** - If `LibObjTypeName` has child objects using `Extends`, their parameters can also be overridden

**Common Practice:**

* **Typically override `Role="Input"` parameters** - These are data inputs from users
* **Rarely override calculated parameters** - If logic needs changing, modify the base library object instead
* **Rationale:** DesignRun is for **data override**, not **logic override**

**DesignRun Object Structure:**

```xml
<!-- Base object that will be extended -->
<O N="BaseCalc" T="Project">
  <P N="factor" V="5" Role="Input"/>
  <P N="multiplier" V="10" Role="Input"/>
</O>

<!-- Library Object extends BaseCalc -->
<O N="MyCodeCheck" T="Project">
  <P N="width_input" V="10" Role="Input"/>    <!-- Direct parameter -->
  <P N="height_input" V="20" Role="Input"/>   <!-- Direct parameter -->

  <!-- Extended object brings in factor and multiplier -->
  <O N="Calc" T="BaseCalc" Extends="BaseCalc"/>

  <!-- Calculations using both direct and extended parameters -->
  <P N="area" V="width_input * height_input"/>
  <P N="result" V="area * Calc.factor"/>

  <!-- Child objects: CANNOT override via DesignRun -->
  <O N="SubCalc" T="Group">
    <P N="final" V="result * 2"/>
  </O>
</O>

<!-- Instance Object uses DesignRun -->
<O N="MyDesignRun" T="Group">
  <P N="UserWidth" V="15" Role="Input"/>
  <P N="UserHeight" V="25" Role="Input"/>
  <P N="UserFactor" V="99" Role="Input"/>

  <!-- DesignRun overrides library parameters -->
  <O N="CodeCheckRun" T="DesignRun">
    <P N="LibObjTypeName" V="MyCodeCheck" T="Text"/>
    <P N="LibObjVersion" V="1"/>

    <!-- ✅ Override direct parameters -->
    <P N="width_input" V="UserWidth"/>     <!-- OK: direct param in MyCodeCheck -->
    <P N="height_input" V="UserHeight"/>   <!-- OK: direct param in MyCodeCheck -->

    <!-- ✅ Override extended object parameters -->
    <P N="factor" V="UserFactor"/>         <!-- OK: exists in Calc (extended from BaseCalc) -->

    <!-- ❌ INVALID: These won't work -->
    <!-- <P N="new_param" V="100"/>  - new_param doesn't exist in MyCodeCheck scope -->
    <!-- <O N="SubCalc" Override="1">  - Cannot override objects -->
    <!-- <O N="Calc" Override="1">  - Cannot override objects -->
  </O>
</O>
```

**How DesignRun Works:**

```
┌─────────────────┐
│ User Parameters │  (e.g., UserWidth = 15)
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│   DesignRun     │  OVERRIDES library parameters
│  T="DesignRun"  │  width_input = UserWidth
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Library Object  │  (MyCodeCheck)
│ (LibObjTypeName)│  Uses overridden: width_input
└─────────────────┘
```

1. **DesignRun** specifies target library object via `LibObjTypeName`
2. **Parameters in DesignRun** override corresponding parameters **within that library object's scope**
3. **Extended objects included** - Parameters from objects extended within `LibObjTypeName` can also be overridden
4. **If the same parameter name appears multiple times** in the library scope, **all instances are overridden**
5. **Library object** uses the overridden parameter values in its calculations
6. **Only parameters that exist in `LibObjTypeName` scope** can be overridden (no new parameters)

**CRITICAL: Bidirectional Parameter Synchronization**

DesignRun overrides are **scoped to the `LibObjTypeName` object only** (unlike `Extends` + `Override="1"` which is hierarchical). This means **parameter names must match** between the library object and DesignRun. When you rename a parameter:

**Direction 1: Library → DesignRun** If you rename a parameter in the library object that is overridden by DesignRun:

1. Find all DesignRun objects with `LibObjTypeName` pointing to that library
2. Update the parameter name in those DesignRun objects

**Direction 2: DesignRun → Library** If you rename a parameter in DesignRun that overrides a library parameter:

1. Check the library object specified in `LibObjTypeName`
2. Update the parameter name in that library object
3. Update all internal references to that parameter in the library

**Example 1: Scoped Override (Only LibObjTypeName)**

```xml
<!-- Library has param_a -->
<O N="MyLibrary" T="Project">
  <P N="param_a" V="10"/>          <!-- This will be overridden -->
  <P N="area_calc" V="100"/>       <!-- This can be overridden -->
  <P N="result" V="param_a * 2"/>
</O>

<O N="Instance" T="Group">
  <O N="Run" T="DesignRun">
    <P N="LibObjTypeName" V="MyLibrary" T="Text"/>
    <P N="param_a" V="20"/>      <!-- ✅ Overrides param_a in MyLibrary -->
    <P N="area_calc" V="50"/>    <!-- ✅ Overrides area_calc in MyLibrary -->
    <!-- Note: Can ONLY override parameters that exist in MyLibrary -->
  </O>
</O>
```

**Example 2: Overriding Extended Object Parameters**

```xml
<!-- Base object with parameters -->
<O N="BaseCalc" T="Project">
  <P N="factor" V="5"/>
  <P N="offset" V="10"/>
</O>

<!-- Library extends BaseCalc -->
<O N="MyLibrary" T="Project">
  <P N="width" V="100"/>

  <!-- Extends brings in factor and offset -->
  <O N="Calc" T="BaseCalc" Extends="BaseCalc"/>

  <P N="result" V="width * Calc.factor + Calc.offset"/>
</O>

<O N="Instance" T="Group">
  <O N="Run" T="DesignRun">
    <P N="LibObjTypeName" V="MyLibrary" T="Text"/>
    <P N="width" V="200"/>    <!-- ✅ Overrides direct parameter -->
    <P N="factor" V="99"/>    <!-- ✅ Overrides extended parameter (Calc.factor) -->
    <P N="offset" V="50"/>    <!-- ✅ Overrides extended parameter (Calc.offset) -->
  </O>
</O>

<!-- Result: MyLibrary scope uses width=200, factor=99, offset=50 -->
```

**Example 3: Renaming Parameters**

```xml
<!-- BEFORE: Library has param_a -->
<O N="MyLibrary" T="Project">
  <P N="param_a" V="10"/>
  <P N="result" V="param_a * 2"/>
</O>

<O N="Instance" T="Group">
  <O N="Run" T="DesignRun">
    <P N="LibObjTypeName" V="MyLibrary" T="Text"/>
    <P N="param_a" V="20"/>      <!-- Overrides library's param_a -->
  </O>
</O>

<!-- AFTER: Renaming param_a → param_b in library -->
<O N="MyLibrary" T="Project">
  <P N="param_b" V="10"/>          <!-- ✅ Renamed -->
  <P N="result" V="param_b * 2"/>  <!-- ✅ Updated reference -->
</O>

<O N="Instance" T="Group">
  <O N="Run" T="DesignRun">
    <P N="LibObjTypeName" V="MyLibrary" T="Text"/>
    <P N="param_b" V="20"/>      <!-- ✅ MUST update to param_b -->
  </O>
</O>
```

**Step-by-Step: Renaming Parameters**

When you need to rename a parameter that's involved in DesignRun override:

**Starting from Library Object:**

1. **Identify the library object** (e.g., `OBPBase_MyCodeCheck`)
2. **Change the parameter name** in the library object (e.g., `oldName` → `newName`)
3. **Update all internal references** to that parameter within the library
4. **Search for all DesignRun objects** with `LibObjTypeName = "OBPBase_MyCodeCheck"`
5. **Update parameter names** in those DesignRun objects to match the new name

**Starting from DesignRun Object:**

1. **Find `LibObjTypeName`** value to identify the target library object
2. **Change the parameter name** in DesignRun (e.g., `oldName` → `newName`)
3. **Open the library object** specified in `LibObjTypeName`
4. **Update the parameter name** in the library object
5. **Update all internal references** to that parameter within the library

**⚠️ WARNING: Non-Input Parameter Override Behavior**

DesignRun has a **dangerous capability** that must be carefully controlled:

**The Problem:** DesignRun can override **ANY parameter** in the `LibObjTypeName` scope, not just `Role="Input"` parameters. When you override a non-Input parameter:

* **ALL occurrences** of that parameter name in the library object scope are overridden
* This includes uses in calculations, expressions, and child objects
* The override affects the entire `LibObjTypeName` object and its extended objects

**Example - Unintended Override:**

```xml
<!-- Library Object -->
<O N="MyCodeCheck" T="Project">
  <P N="width_input" V="10" Role="Input"/>    <!-- Input parameter -->
  <P N="safety_factor" V="1.5"/>              <!-- NOT an Input parameter -->

  <P N="area" V="width_input * 20"/>
  <P N="capacity" V="area * safety_factor"/>
  <P N="check1" V="capacity * safety_factor"/>
  <P N="check2" V="width_input * safety_factor"/>
</O>

<!-- DR Object - PROBLEMATIC -->
<O N="MyDesignRun" T="Group">
  <P N="UserWidth" V="15" Role="Input"/>
  <P N="UserSafetyFactor" V="2.0" Role="Input"/>

  <O N="Run" T="DesignRun">
    <P N="LibObjTypeName" V="MyCodeCheck" T="Text"/>

    <!-- OK: Override Input parameter -->
    <P N="width_input" V="UserWidth"/>

    <!-- ⚠️ PROBLEM: Overriding non-Input parameter -->
    <P N="safety_factor" V="UserSafetyFactor"/>
    <!-- This overrides safety_factor EVERYWHERE in MyCodeCheck:
         - capacity calculation (area * 2.0 instead of area * 1.5)
         - check1 calculation (capacity * 2.0)
         - check2 calculation (width * 2.0)
         ALL will now use 2.0 instead of 1.5 -->
  </O>
</O>
```

**Result:**

* `width_input` = 15 (from UserWidth) ✅ Expected
* `safety_factor` = 2.0 (from UserSafetyFactor) ⚠️ Overridden everywhere
* `capacity` = (15 \* 20) \* 2.0 = 600 (uses overridden safety\_factor)
* `check1` = 600 \* 2.0 = 1200 (uses overridden safety\_factor)
* `check2` = 15 \* 2.0 = 30 (uses overridden safety\_factor)

**When This Happens:**

* ❌ **Breaks library object's internal logic** - calculated parameters no longer use intended values
* ❌ **Creates maintenance nightmare** - changes to library don't behave as expected
* ❌ **Violates separation of concerns** - DR should only provide input data, not override calculations
* ❌ **Hard to debug** - override affects multiple locations silently
* ❌ **Unexpected behavior** - other developers don't expect internal parameters to be overridden

**What To Do Instead:**

**If user needs to control a parameter that's not `Role="Input"`:**

1. **Add `Role="Input"` to that parameter in the library object** (RECOMMENDED)

   ```xml
   <!-- Fix in library object -->
   <P N="safety_factor" V="1.5" Role="Input"/>
   ```

   * Makes it officially part of the library object's API
   * Clear to all developers that this parameter is meant to be configurable
   * Proper design pattern - data inputs belong in `Role="Input"`
2. **If parameter should remain internal:**
   * Do NOT override it from DesignRun
   * Modify library object logic if behavior needs to change
   * Keep data override (DR) separate from logic (library)

**Comparison:**

| Aspect                  | `Role="Input"` Parameter     | Non-Input Parameter           |
| ----------------------- | ---------------------------- | ----------------------------- |
| **Purpose**             | User-configurable data input | Internal constant/calculation |
| **Recommended for DR?** | ✅ **YES** - primary use case | ❌ **NO** - problematic        |
| **Override behavior**   | Standard, expected           | Overrides ALL occurrences     |
| **Best practice**       | Always map these in DR       | NEVER override from DR        |
| **User expectation**    | Should be controllable       | Should be internal/fixed      |
| **When found in DR**    | Normal, correct usage        | Flag as error in code review  |

**Best Practices:**

1. **Parameters only, not objects** - DesignRun can only override parameters, not child objects
2. **Must pre-exist in library scope** - Cannot add new parameters; can only override existing ones (including extended objects)
3. **Scoped to `LibObjTypeName`** - Overrides parameters within library object and its extended objects
4. **Extended objects included** - Parameters from `Extends` objects within library can be overridden
5. **ONLY override `Role="Input"` parameters** - These are data inputs designed to be overridden
6. **NEVER override non-Input parameters** - This breaks library logic and creates bugs
   * ⚠️ If you find a non-Input override in DR: **Add `Role="Input"` to library or remove from DR**
7. **Multiple same-name parameters** - If the library has the same parameter name multiple times, **all are overridden**
8. **Data override, not logic override** - Use DesignRun for data inputs, use library edits for logic changes
9. **Bidirectional sync is critical** - Changes in either location require updates in the other
10. **Always check `LibObjTypeName`** to find which library object is being overridden
11. **Check extended objects too** - If library uses `Extends`, those parameters can also be overridden
12. **Search across multiple files** - DesignRun objects may be in different files than the library
13. **Test after renaming** to ensure overrides still work correctly
14. **Code review must flag non-Input overrides** - These are bugs that need fixing

### 2. Parameters (`Param`)

Parameters store data and expressions within objects. They are the "DNA" of parametric behavior.

**Parameter Types:**

* **Number** (`ParamType.Number`): Numeric values or mathematical expressions
* **Text** (`ParamType.Text`): String values or object references

**Value Types:**

* **Expression** (`ValueType.Expression`): Contains formulas that are evaluated (e.g., `"L/2 + 10"`)
* **Value** (`ValueType.Value`): Contains literal values (e.g., `100`)

**Parameter Properties:**

* `Name` (`N`): Parameter identifier
* `Value` (`V`): The expression or value
* `Type` (`T`): Expr, Num, Text, or ObjectType (for references)
* `Description` (`D`): Human-readable description
* `UnitType` (`UT`): Length, Force, Stress, etc.
* `UnitCategory` (`UC`): Default, Metric, Imperial, etc.
* `Role`: None, Input, Private, Export, Import
* `Category`: For grouping parameters in UI
* `DisplayWidth`: UI display width
* `Attr`: If "1", parameter is serialized as XML attribute (for brevity)
* `Optional`: If "1", parameter is optional

### 3. Expression Evaluation (`Eval`)

The evaluation engine computes parameter values by:

1. **Parsing** expressions using JavaScript-compatible syntax
2. **Resolving** identifiers to their values from the parametric model
3. **Executing** mathematical operations and functions
4. **Caching** results for performance

**Supported Operations:**

* Arithmetic: `+`, `-`, `*`, `/`, `%`, `^`
* Comparison: `<`, `>`, `<=`, `>=`, `==`, `!=`
* Logical: `&&`, `||`, `!`
* Ternary: `condition ? value1 : value2`
* Mathematical functions: `sqrt`, `abs`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `min`, `max`, `pow`, `exp`, `log`, `floor`, `ceil`, `round`, etc.

**Identifier Resolution:**

* Parameters are referenced by name (e.g., `Length`, `Width`)
* The system uses a distance-based algorithm to resolve identifiers (detailed below)
* Objects are referenced by name and accessed with dot notation (e.g., `Girder1.Length`)
* Use brackets for indexed access (e.g., `Girders[0].Width`)

#### 3.1 Lazy Evaluation

The parametric engine uses **lazy evaluation**, meaning expressions are not computed when they are defined—they are evaluated only when their values are actually needed.

**How It Works:**

1. **Definition Time**: Expressions are stored as text strings and compiled into an Abstract Syntax Tree (AST)
2. **Evaluation Time**: When a parameter value is requested (e.g., for display, geometry generation, or use in another expression), the `GetValue()` method is called
3. **Backward Evaluation**: The engine works backward through dependencies—if ParamA needs ParamB, it evaluates ParamB first, which might need ParamC, and so on
4. **Caching**: Computed values are cached to avoid redundant calculations. The cache is invalidated when dependencies change
5. **Circular Dependency Detection**: The execution stack tracks the evaluation chain to detect and prevent circular dependencies

**Benefits:**

* **Performance**: Only computes what's actually needed
* **Flexibility**: Parameters can reference objects/parameters that are defined later in the XML
* **Dynamic Updates**: When an input parameter changes, only affected downstream parameters are re-evaluated on next access

**Example:**

```xml
<O N="Bridge" T="Structure">
  <P N="SpanLength" V="120" Role="Input"/>
  <P N="MidSpan" V="SpanLength / 2"/>      <!-- Not evaluated yet -->
  <P N="QuarterSpan" V="MidSpan / 2"/>     <!-- Not evaluated yet -->

  <O T="Point" N="MidPoint" X="MidSpan" Y="0" Z="0"/>
  <!-- When MidPoint.X is requested for geometry rendering:
       1. Needs MidPoint.X → evaluates expression "MidSpan"
       2. Searches for MidSpan parameter → finds it
       3. MidSpan needs evaluation → evaluates "SpanLength / 2"
       4. Searches for SpanLength → finds literal value 120
       5. Computes 120 / 2 = 60 (cached)
       6. Returns 60 for MidPoint.X

       Note: QuarterSpan is NEVER evaluated unless something requests its value! -->
</O>
```

**Evaluation Chain Example:**

```xml
<O N="Calculation" T="Group">
  <P N="Result" V="A + B"/>
  <P N="A" V="C * 2"/>
  <P N="B" V="D + 5"/>
  <P N="C" V="10"/>
  <P N="D" V="3"/>
</O>

<!-- When Result is requested:
     1. Evaluate Result → needs A and B
     2. Evaluate A → needs C → evaluates C (10) → computes 10*2 = 20
     3. Evaluate B → needs D → evaluates D (3) → computes 3+5 = 8
     4. Compute Result: 20 + 8 = 28

     The engine worked BACKWARD from Result through all dependencies. -->
```

#### 3.2 Distance-Based Parameter Resolution

When multiple parameters or objects have the same name, the engine uses a **distance-based algorithm** to determine which one to use. This allows parameters to be overridden at different levels of the hierarchy.

**Resolution Algorithm:**

When an expression references an identifier (e.g., `Width` or `Beam1`):

1. **Search Parent Chain First**: Walk up from current object to root, looking for the parameter
   * Current object's parameters
   * Parent's parameters
   * Grandparent's parameters, etc.
   * Stop if found or root is reached
2. **Search Entire Project** (if not found in parent chain): Get ALL parameters/objects with that name from the entire project
3. **Calculate Distance** for each candidate:

   ```
   Distance = Steps through hierarchy + Scope Penalties

   Where:
   - Steps = number of parent→child hops from current object to candidate through their common ancestor
   - Scope Penalty = +100 for EACH scope boundary crossed:
     • Crossing into or out of an object with Scoped="1": +100
     • Crossing into or out of a Private object: +100
   ```
4. **Pick Closest**: Select the parameter/object with the minimum distance

**Example: Basic Distance Resolution**

```xml
<P N="ParamB" V="ParamC+3"/>  <!-- Parent level: distance 1 from "New Group" -->

<O N="New Group" T="Group">
  <P N="ValueToEval" V="ParamA"/>   <!-- When evaluated, triggers lazy evaluation chain -->
  <P N="ParamA" V="ParamB+3"/>       <!-- Distance 0 from "New Group" -->
  <P N="ParamB" V="ParamC+3"/>       <!-- Distance 0 from "New Group" - THIS ONE IS USED -->
</O>

<!-- Evaluation flow when ValueToEval is requested:
     1. ValueToEval → evaluates "ParamA"
     2. Searches for ParamA:
        - Finds ParamA at distance 0 (same object "New Group")
     3. Evaluates ParamA → expression is "ParamB+3"
     4. Searches for ParamB:
        - "New Group".ParamB: distance 0 ✓ CLOSEST
        - Parent.ParamB: distance 1
     5. Uses "New Group".ParamB (distance 0 wins)
     6. Evaluates "ParamC+3" (triggers another resolution for ParamC...)

     Key Point: Distance 0 beats distance 1, even though parent ParamB
                appears first in XML. Distance is hierarchy-based, not order-based! -->
```

**Example: Parameter Shadowing (Override Pattern)**

```xml
<O N="Building" T="Structure">
  <P N="Width" V="100" D="Default building width"/>

  <O N="WestWing" T="Section">
    <P N="Width" V="80" D="Overrides parent Width"/>
    <P N="Length" V="Width * 2"/>
    <!-- Resolution for Width:
         - WestWing.Width: distance 0 ✓ USED
         - Building.Width: distance 1
         Result: Length = 80 * 2 = 160 -->
  </O>

  <O N="EastWing" T="Section">
    <P N="Length" V="Width * 2"/>
    <!-- Resolution for Width:
         - EastWing has no Width parameter
         - Building.Width: distance 1 ✓ USED
         Result: Length = 100 * 2 = 200 -->
  </O>
</O>
```

**Example: Scope Penalty (+100 Distance)**

```xml
<O N="Project" T="Root">
  <P N="GlobalValue" V="1000"/>

  <O N="Module1" T="Module" Scoped="1">  <!-- Creates scope boundary -->
    <P N="GlobalValue" V="500"/>  <!-- Shadows parent, but with penalty -->
    <P N="LocalParam" V="GlobalValue"/>
    <!-- Resolution for GlobalValue:
         - Module1.GlobalValue: distance 0 ✓ USED
         - Project.GlobalValue: distance 1 + 100 (scope) = 101
         Result: LocalParam = 500 -->
  </O>

  <O N="Module2" T="Module">
    <P N="CrossModuleRef" V="GlobalValue"/>
    <!-- Resolution for GlobalValue:
         - Project.GlobalValue: 1 step up = distance 1 ✓ USED
         - Module1.GlobalValue: 1 up + 1 down + 100 (scope) = 102
         Result: CrossModuleRef = 1000

         The scope penalty makes Module1.GlobalValue "far away" from Module2! -->
  </O>
</O>
```

**Distance Calculation Reference:**

| Scenario                 | Steps  | Penalties | Total Distance | Notes                         |
| ------------------------ | ------ | --------- | -------------- | ----------------------------- |
| Same object              | 0      | 0         | **0**          | Always wins                   |
| Parent object            | 1      | 0         | **1**          |                               |
| Grandparent              | 2      | 0         | **2**          |                               |
| Sibling (same parent)    | 2      | 0         | **2**          | Up 1, down 1                  |
| Through scoped parent    | 1      | +100      | **101**        | Scope creates strong boundary |
| Sibling in scoped object | 2      | +100      | **102**        |                               |
| Cross 2 scope boundaries | varies | +200      | **high**       | Rarely wins                   |
| Uncle (parent's sibling) | 3      | 0         | **3**          | Up 2, down 1                  |

**Example: Nested Scopes**

```xml
<O N="System" T="Root">
  <P N="Config" V="'default'"/>

  <O N="SubsystemA" T="Subsystem" Scoped="1">
    <P N="Config" V="'subsystemA'"/>

    <O N="ComponentA1" T="Component" Scoped="1">
      <P N="Config" V="'componentA1'"/>
      <P N="Value" V="Config"/>
      <!-- Resolution: ComponentA1.Config, distance 0 ✓ -->
    </O>

    <O N="ComponentA2" T="Component">
      <P N="Value" V="Config"/>
      <!-- Resolution for Config:
           - SubsystemA.Config: distance 1 ✓ USED
           - ComponentA1.Config: distance 2 + 100 (scope) = 102
           - System.Config: distance 2 + 100 (SubsystemA scope) = 102
           Result: Value = 'subsystemA' -->
    </O>
  </O>
</O>
```

### 4. Repeat/Iteration (`Repeat`)

The `Repeat` object enables parametric arrays and iterations.

**Key Parameters:**

* `CTRL`: Name of the control parameter (loop variable)
  * ⚠️ **WARNING**: Do NOT use reserved keywords as CTRL names (e.g., `pi`, `e`, `sin`, `cos`, etc.)
  * `pi` is reserved for π (3.14159...) and cannot be used as a loop variable
  * Use descriptive names like `i`, `j`, `k`, `idx`, `pileIndex`, etc.
* `S`: Start value
* `E`: End value
* `I`: Increment (default: 1)

During compilation, the Repeat generates copies of its child content for each iteration.

**Example:** Create 5 points along a line

```xml
<O T="Repeat" N="Points" S="0" E="4" I="1" CTRL="i" i="0">
  <O T="Point" N="Pt" X="i*10" Y="0" Z="0" />
</O>
```

**For details** See `AI-Core-Objects.md`

## Guards - Conditional Object Activation

**Guard** is a special parameter that activates or deactivates objects based on conditions.

### Purpose

Guards allow conditional geometry, calculations, or object creation based on user selections or parameter values.

### Syntax

```xml
<P N="Guard" V="condition_expression" />
```

The Guard parameter must evaluate to a boolean (true/false):

* **True** → Object is active and evaluated
* **False** → Object is deactivated (skipped)

### Common Guard Operators

* `.EQ.` - Equal to
* `.NE.` - Not equal to
* `.GT.` - Greater than
* `.LT.` - Less than
* `.GE.` - Greater than or equal
* `.LE.` - Less than or equal
* `.AND.` - Logical AND
* `.OR.` - Logical OR

### Example: Conditional Column Geometry

```xml
<O N="ColumnDesign" T="Project">
    <!-- Define column type options -->
    <O N="ColumnType" T="Group">
        <P N="Rectangular" V="1" />
        <P N="Circular" V="2" />
    </O>
    
    <!-- Input parameters -->
    <O N="Input" T="Group">
        <P N="W" V="10" D="column width" Role="Input" Category="Input" />
        <P N="L" V="10" D="column length" Role="Input" Category="Input" />
        <P N="D" V="10" D="column diameter" Role="Input" Category="Input" />
        <P N="H" V="100" D="column height" Role="Input" Category="Input" />
        <P N="ColumnType" V="Circular" Role="Input" Category="Input" />
    </O>
    
    <!-- Geometry with Guards -->
    <O N="Geometry" T="Group">
        
        <!-- Rectangular column - only active when ColumnType = Rectangular -->
        <O T="Surface" Z="0">
            <P N="Guard" V="ColumnType .EQ. Rectangular" />
            <P N="Thickness" V="H" />
            <O T="Point" X="0" Y="0" />
            <O T="Point" X="W" Y="0" />
            <O T="Point" X="W" Y="L" />
            <O T="Point" X="0" Y="L" />
        </O>
        
        <!-- Circular column - only active when ColumnType = Circular -->
        <O T="Circle" Z="0">
            <P N="Guard" V="ColumnType .EQ. Circular" />
            <P N="Thickness" V="H" />
            <P N="Radius" V="D/2" />
        </O>
        
    </O>
</O>
```

**How it works:**

1. User selects `ColumnType` (Rectangular or Circular)
2. Each geometry object has a Guard checking the selection
3. Only the matching object is activated and creates geometry
4. The other object is skipped

### Multiple Conditions

Guards can use complex conditions:

```xml
<!-- Active only for steel AND short columns -->
<O T="Group">
    <P N="Guard" V="material .EQ. 'Steel' .AND. height .LT. 120" />
    <!-- Steel short column logic -->
</O>

<!-- Active for concrete OR masonry -->
<O T="Group">
    <P N="Guard" V="material .EQ. 'Concrete' .OR. material .EQ. 'Masonry'" />
    <!-- Concrete/masonry logic -->
</O>

<!-- Active for range of values -->
<O T="Group">
    <P N="Guard" V="span .GE. 100 .AND. span .LE. 200" />
    <!-- Medium span logic -->
</O>
```

### Common Patterns

**Option Selection:**

```xml
<O N="Options" T="Group">
    <P N="Type_A" V="1" />
    <P N="Type_B" V="2" />
    <P N="Type_C" V="3" />
</O>

<P N="selected_type" V="Type_A" Role="Input" />

<O T="Group">
    <P N="Guard" V="selected_type .EQ. Type_A" />
    <!-- Type A specific logic -->
</O>
```

**Threshold-Based:**

```xml
<O T="Group">
    <P N="Guard" V="load .GT. 1000" />
    <!-- Heavy load case -->
</O>

<O T="Group">
    <P N="Guard" V="load .LE. 1000" />
    <!-- Light load case -->
</O>
```

**Multiple Criteria:**

```xml
<O T="Group">
    <P N="Guard" V="material .EQ. 'Steel' .AND. height .GT. 100 .AND. width .GT. 50" />
    <!-- Complex condition -->
</O>
```

***

## XML Format

### Basic Structure

```xml
<O N="ObjectName" T="ObjectType" ID="unique-guid">
  <!-- Parameters -->
  <P N="ParamName" V="Value" T="Type" D="Description" UT="UnitType" UC="UnitCategory"/>
  
  <!-- Child Objects -->
  <O N="ChildName" T="ChildType">
    ...
  </O>
</O>
```

### Concise vs. Verbose Format

**Concise (Preferred):** When possible, define parameters as attributes on the object node:

```xml
<O N="MyRect" T="Surface">
  <O T="Point" X="0" Y="0"/>
  <O T="Point" X="10" Y="0"/>
  <O T="Point" X="10" Y="10"/>
  <O T="Point" X="0" Y="10"/>
</O>
```

**Verbose:** When you need to specify parameter metadata (units, description, role, etc.):

```xml
<O N="MyBeam" T="Beam">
  <P N="L" V="100" T="Expr" D="Beam length" UT="Length" UC="Default"/>
  <P N="Material" V="Steel" T="Text"/>
</O>
```

### Common Patterns

#### 1. Simple Numeric Parameter

```xml
<P N="Length" V="100"/>
```

#### 2. Expression Parameter

```xml
<P N="MidSpan" V="TotalLength / 2"/>
```

#### 3. Parameter with Units

```xml
<P N="Force" V="1000" UT="Force" UC="Default" D="Applied force"/>
```

#### 4. Text Parameter

```xml
<P N="Name" V="Beam1" T="Text"/>
```

#### 5. Object Reference

```xml
<P N="Material" V="ASTM_A992" T="Material"/>
```

#### 6. Object Reference (Attribute Style)

When defining as an attribute, prefix with `@` and optionally specify type with `|`:

```xml
<O N="MyBeam" T="Beam" Material="@ASTM_A992|Material"/>
```

#### 7. User Input Parameter

```xml
<P N="Width" V="12" Role="Input" D="Beam width"/>
```

#### 8. List/Array Parameter

```xml
<P N="Stations" V="[0, 10, 20, 30, 40]"/>
```

#### 9. Referencing Objects Pattern (Bidirectional References)

This pattern establishes automatic two-way references between parent and child objects. When a child object references a parent, it automatically appears in the parent's "Referencing Objects" list. This is essential for navigating object relationships in complex models.

**Use Cases:**

* Girder → Cross Frames (bracings)
* Pier Column → Foundation
* Deck → Barrier

**Parent Object (Girder):**

```xml
<O N="OBPBase_Girder" T="Project">
    <!-- Referencing Objects - populated automatically by child objects -->
    <O N="Referencing Objects" T="Group">
        <P N="bracings" V="[]" D="Cross Frames" Role="Input" Category="Referencing Objects" />
        <O T="ParamInfo" Param="bracings" Required="0" ReadOnly="1" />
    </O>
</O>
```

**Child Object (CrossFrame):**

```xml
<O N="OBPBase_CrossFrame" T="Project">
    <O N="General" T="Group">
        <!-- Reference to parent with RefParam for back-reference -->
        <P N="Girders" V="[]" T="OBPBase_Girder" D="Girders" Role="Input" Category="General" />
        <O T="ParamInfo" Param="Girders" Min="2" Max="2" Required="1" RefParam="@bracings"/>
    </O>
</O>
```

**Key Components:**

| Component              | Location                             | Purpose                                                   |
| ---------------------- | ------------------------------------ | --------------------------------------------------------- |
| `bracings` parameter   | Parent's "Referencing Objects" group | Stores list of child objects                              |
| `ReadOnly="1"`         | Parent's ParamInfo                   | Prevents manual editing, system-managed                   |
| `RefParam="@bracings"` | Child's ParamInfo                    | Tells system to add this object to parent's bracings list |

**How It Works:**

1. User creates child object (CrossFrame) and selects parent (Girder)
2. System automatically adds CrossFrame to Girder's `bracings` list via RefParam
3. Parent's "Referencing Objects" tab shows all children
4. When child is deleted, it's automatically removed from parent's list

**Navigation Through References:**

Other objects can navigate through referencing objects to access nested data. For example, a Deck object takes a girder list as input, then can access each girder's cross frames via `girder.bracings`:

```xml
<!-- Deck accessing girder's cross frames -->
<P N="girders" V="[G1,G2,G3]" T="OBPBase_Girder" />
<P N="firstGirderBracings" V="girders[0].bracings" />
<P N="bracePoint" V="firstGirderBracings[0].BracePoint" />
```

#### 9. Referencing Objects Pattern (Bidirectional References)

This pattern establishes automatic two-way references between parent and child objects. When a child object references a parent, it automatically appears in the parent's "Referencing Objects" list. This is essential for navigating object relationships in complex models.

**Use Cases:**

* Girder → Cross Frames (bracings)
* Pier Column → Foundation
* Deck → Barrier

**Parent Object (Girder):**

```xml
<O N="OBPBase_Girder" T="Project">
    <!-- Referencing Objects - populated automatically by child objects -->
    <O N="Referencing Objects" T="Group">
        <P N="bracings" V="[]" D="Cross Frames" Role="Input" Category="Referencing Objects" />
        <O T="ParamInfo" Param="bracings" Required="0" ReadOnly="1" />
    </O>
</O>
```

**Child Object (CrossFrame):**

```xml
<O N="OBPBase_CrossFrame" T="Project">
    <O N="General" T="Group">
        <!-- Reference to parent with RefParam for back-reference -->
        <P N="Girders" V="[]" T="OBPBase_Girder" D="Girders" Role="Input" Category="General" />
        <O T="ParamInfo" Param="Girders" Min="2" Max="2" Required="1" RefParam="@bracings"/>
    </O>
</O>
```

**Key Components:**

| Component              | Location                             | Purpose                                                   |
| ---------------------- | ------------------------------------ | --------------------------------------------------------- |
| `bracings` parameter   | Parent's "Referencing Objects" group | Stores list of child objects                              |
| `ReadOnly="1"`         | Parent's ParamInfo                   | Prevents manual editing, system-managed                   |
| `RefParam="@bracings"` | Child's ParamInfo                    | Tells system to add this object to parent's bracings list |

**How It Works:**

1. User creates child object (CrossFrame) and selects parent (Girder)
2. System automatically adds CrossFrame to Girder's `bracings` list via RefParam
3. Parent's "Referencing Objects" tab shows all children
4. When child is deleted, it's automatically removed from parent's list

**Navigation Through References:**

Other objects can navigate through referencing objects to access nested data. For example, a Deck object takes a girder list as input, then can access each girder's cross frames via `girder.bracings`:

```xml
<!-- Deck accessing girder's cross frames -->
<P N="girders" V="[G1,G2,G3]" T="OBPBase_Girder" />
<P N="firstGirderBracings" V="girders[0].bracings" />
<P N="bracePoint" V="firstGirderBracings[0].BracePoint" />
```

## Practical Examples

### Example 1: Simple Rectangle

```xml
<O N="MyRect" T="Surface">
  <O T="Point" X="0" Y="0" Z="0"/>
  <O T="Point" X="10" Y="0" Z="0"/>
  <O T="Point" X="10" Y="10" Z="0"/>
  <O T="Point" X="0" Y="10" Z="0"/>
</O>
```

### Example 2: Parametric Rectangle

```xml
<O N="ParamRect" T="Surface">
  <P N="Width" V="10" Role="Input" D="Rectangle width"/>
  <P N="Height" V="5" Role="Input" D="Rectangle height"/>

  <O T="Point" X="0" Y="0" Z="0"/>
  <O T="Point" X="Width" Y="0" Z="0"/>
  <O T="Point" X="Width" Y="Height" Z="0"/>
  <O T="Point" X="0" Y="Height" Z="0"/>
</O>
```

### Example 3: Array of Points Using Repeat

```xml
<O N="PointArray" T="Group">
  <P N="Spacing" V="5"/>
  <P N="Count" V="10"/>
  
  <O T="Repeat" N="Points" S="0" E="Count - 1" I="1" CTRL="i" i="0">
    <O T="Point" N="Pt" X="i*Spacing" Y="0" Z="0" />
  </O>
</O>
```

### Example 4: Girder with Cross-Section

```xml
<O N="SteelGirder" T="Girder">
  <P N="Length" V="120" Role="Input" UT="Length" D="Girder length"/>
  <P N="Depth" V="72" Role="Input" UT="Length" D="Girder depth"/>
  
  <!-- Cross-section definition -->
  <O N="Section" T="IShape">
    <P N="d" V="Depth"/>
    <P N="tw" V="0.5" UT="Length" D="Web thickness"/>
    <P N="bf" V="12" UT="Length" D="Flange width"/>
    <P N="tf" V="1" UT="Length" D="Flange thickness"/>
  </O>
  
  <!-- Start point -->
  <O N="StartPoint" T="Point" X="0" Y="0" Z="0"/>

  <!-- End point -->
  <O N="EndPoint" T="Point" X="Length" Y="0" Z="0"/>
</O>
```

### Example 5: Multi-Girder Bridge

```xml
<O N="BridgeGirders" T="Group">
  <P N="NumGirders" V="5" Role="Input" D="Number of girders"/>
  <P N="GirderSpacing" V="10" Role="Input" UT="Length" D="Spacing between girders"/>
  <P N="SpanLength" V="120" Role="Input" UT="Length" D="Span length"/>
  
  <O T="Repeat" N="Girders" S="0" E="NumGirders - 1" I="1" CTRL="i" i="0">
    <O N="Girder" T="Girder">
      <P N="Y" V="i * GirderSpacing"/>
      <O N="StartPt" T="Point" X="0" Y="Y" Z="0"/>
      <O N="EndPt" T="Point" X="SpanLength" Y="Y" Z="0"/>
    </O>
  </O>
</O>
```

### Example 6: Conditional Objects (Guards)

```xml
<O N="OptionalStiffener" T="Plate">
  <P N="Guard" V="RequireStiffener == 1"/>
  <P N="Width" V="6"/>
  <P N="Thickness" V="0.5"/>
</O>
```

### Example 7: Object Inheritance (Creating Variations)

```xml
<!-- Define a base column object with default dimensions -->
<O N="StandardCol" T="Volume">
  <P N="Width" V="12" Role="Input" UT="Length" D="Column width"/>
  <P N="Height" V="12" Role="Input" UT="Length" D="Column height"/>
  <P N="Length" V="20" Role="Input" UT="Length" D="Column length"/>
  <!-- Additional properties like material, geometry, etc. -->
</O>

<!-- Create narrower column by inheriting from StandardCol -->
<O N="NarrowCol" T="StandardCol" Width="8" Height="8"/>

<!-- Create taller column -->
<O N="TallCol" T="StandardCol" Length="30"/>

<!-- Create wide, short column -->
<O N="WideShortCol" T="StandardCol" Width="18" Height="18" Length="10"/>

<!-- Use the columns in a structure -->
<O T="Repeat" N="Columns" S="0" E="3" I="1" CTRL="i" i="0">
  <!-- Mix different column types -->
  <O N="Col1" T="i < 2 ? NarrowCol : WideShortCol">
    <O T="Point" X="i*20" Y="0" Z="0"/>
  </O>
</O>
```

## Advanced Features

### Object Inheritance

Objects can inherit from other objects in the project by using the base object's name as their `Type`. When you do this, the new object inherits all parameters and child objects from the base object, and you can override specific parameters as needed.

**Pattern:**

1. Define a base object with parameters
2. Create derived objects using the base object's name as the `T` attribute
3. Override parameters by specifying them as attributes or child parameters

**Example:**

```xml
<!-- Define base column object -->
<O N="Col" T="Volume">
  <P N="Width" V="10" Role="Input" UT="Length"/>
  <P N="Height" V="10" Role="Input" UT="Length"/>
  <P N="Depth" V="12" Role="Input" UT="Length"/>
  <!-- Geometry and other properties -->
</O>

<!-- Create derived column by using Col as Type and overriding parameters -->
<O N="SkinnyCol" T="Col" Width="6" Height="6"/>

<!-- Another derived column with different dimensions -->
<O N="WideCol" T="Col" Width="24" Height="18" Depth="24"/>
```

In the above example, `SkinnyCol` and `WideCol` inherit all the parameters, child objects, and behavior from `Col`, but override the dimensional parameters. This is particularly useful for creating variations of standard components.

### Extends - Importing Library Objects

#### Overview

The `Extends` attribute copies all parameters and child objects from one or more library objects into your current object. This is the primary mechanism for:

* Importing AASHTO chapter implementations
* Reusing calculation modules
* Building complex objects from simpler components
* Creating object namespaces

**Key Concept:** Think of Extends as **copying the entire object tree** from the library object(s) into your object.

***

`Extends` creates a **new instance** (copy) of the library object. Think of the library as a **class/template**, and each `Extends` creates a **new object instance** from that template.

**Key Concept:** Each time you use `Extends`, you create a separate instance with its own copy of the library's code.

**Example - Creating Multiple Instances:**

```xml
<!-- Creating INSTANCE 1 with Extends + Override -->
<O N="Chapter3_4_Instance1" T="Group"
   Extends="AASHTO_Section3_4::v3"
   Scoped="1"
   Override="1">
  <!-- These override parameters in THIS instance's copy -->
  <P N="ADTTSL" V="5000"/>
  <P N="NumYears" V="75"/>
</O>

<!-- Creating INSTANCE 2 with different values -->
<O N="Chapter3_4_Instance2" T="Group"
   Extends="AASHTO_Section3_4::v3"
   Scoped="1"
   Override="1">
  <!-- These override parameters in THIS instance's copy -->
  <P N="ADTTSL" V="8000"/>
  <P N="NumYears" V="100"/>
</O>

<!-- Access each instance's calculated results -->
<P N="LoadFactor1" V="Chapter3_4_Instance1.FatiqueI_LLandIMandCEonly.LL"/>  <!-- Uses ADTTSL=5000 -->
<P N="LoadFactor2" V="Chapter3_4_Instance2.FatiqueI_LLandIMandCEonly.LL"/>  <!-- Uses ADTTSL=8000 -->
```

**What Happens:**

1. **Extends creates a new instance**: `Extends="AASHTO_Section3_4::v3"` makes a complete copy of the library's structure into the new object
2. **Each Extends = Separate Instance**: Instance1 and Instance2 are independent copies with their own parameter values
3. **Override="1" enables parameter replacement**: Allows you to define parameters that **replace** same-named parameters in **this instance's copy**
4. **Original library unchanged**: The AASHTO\_Section3\_4 library itself remains unchanged
5. **Independent calculations**: Instance1 calculates with ADTTSL=5000, Instance2 with ADTTSL=8000

**Object-Oriented Programming Analogy:**

```javascript
// Library is like a class
class AASHTO_Section3_4 {
  constructor(ADTTSL = 0, NumYears = 100) {
    this.ADTTSL = ADTTSL;
    this.NumYears = NumYears;
    this.FatiqueI = { LL: 1.5 * (this.ADTTSL / this.NumYears) };
  }
}

// Extends + Override = new instance with constructor parameters
let instance1 = new AASHTO_Section3_4(5000, 75);   // Chapter3_4_Instance1
let instance2 = new AASHTO_Section3_4(8000, 100);  // Chapter3_4_Instance2

// Access instance results
let loadFactor1 = instance1.FatiqueI.LL;
let loadFactor2 = instance2.FatiqueI.LL;
```

**Without Override (Reading Default Values):**

```xml
<!-- Create instance with library's default parameter values -->
<O N="Chapter3_4_Default" T="Group"
   Extends="AASHTO_Section3_4::v3"
   Scoped="1"/>

<!-- Access results calculated with defaults (ADTTSL=0, NumYears=100) -->
<P N="DefaultLoadFactor" V="Chapter3_4_Default.FatiqueI_LLandIMandCEonly.LL"/>
```

**With Override (Setting Instance Parameters):**

```xml
<!-- Create instance and override input parameters -->
<O N="Chapter3_4_Custom" T="Group"
   Extends="AASHTO_Section3_4::v3"
   Scoped="1"
   Override="1">
  <!-- Replace ADTTSL and NumYears in this instance -->
  <P N="ADTTSL" V="5000"/>
  <P N="NumYears" V="75"/>
</O>

<!-- Access results calculated with custom values (ADTTSL=5000, NumYears=75) -->
<P N="CustomLoadFactor" V="Chapter3_4_Custom.FatiqueI_LLandIMandCEonly.LL"/>
```

**Key Takeaways:**

* `Extends` = Create new instance (copy) from library template
* `Override="1"` = Enable replacing parameters and objects in this instance
* Each `Extends` creates a **separate, independent instance**
* Parameters/objects you define replace same-named parameters/objects in **that instance only**
* Original library remains unchanged

## **For more detailed explanation:** See `AI-Extends.md`

#### Overriding Objects (Not Just Parameters)

With `Override="1"`, you can override **child objects** by defining objects with the same name, not just parameters.

**Example - Overriding Child Objects:**

```xml
<!-- Create instance and override both parameters AND objects -->
<O N="Chapter3_4_Custom" T="Group"
   Extends="AASHTO_Section3_4::v3"
   Scoped="1"
   Override="1">

  <!-- Override parameters -->
  <P N="ADTTSL" V="5000"/>
  <P N="NumYears" V="75"/>

  <!-- Override a child object by using the same name -->
  <O N="FatiqueI_LLandIMandCEonly" T="Group">
    <!-- Completely replace the library's FatiqueI_LLandIMandCEonly object -->
    <P N="LL" V="2.0"/>  <!-- Custom load factor instead of calculated -->
    <P N="CustomParam" V="100"/>  <!-- Add additional parameters -->
  </O>
</O>

<!-- Access the overridden object -->
<P N="CustomLoadFactor" V="Chapter3_4_Custom.FatiqueI_LLandIMandCEonly.LL"/>  <!-- Returns 2.0 -->
<P N="CustomValue" V="Chapter3_4_Custom.FatiqueI_LLandIMandCEonly.CustomParam"/>  <!-- Returns 100 -->
```

**How Override Works:**

1. The engine copies the library into the instance
2. For each parameter/object you define in the instance
3. It searches for a matching name in the copied library
4. If found, it **replaces** that parameter/object entirely
5. This works for both parameters (`<P>`) and objects (`<O>`)

**Use Cases:**

* Override specific calculation modules while keeping the rest of the library
* Replace default implementations with custom logic
* Inject test values for specific sub-objects

***

#### Multiple Extends

You can extend from multiple objects by using array syntax:

```xml
<O N="Chapter6_5" T="Group" Extends="AASHTO_9th_Section6Sub5::v3" Scoped="1" Override="1" />
<O N="Chapter3_6" T="Group" Extends="AASHTO_9th_Section3Sub6::v3" Scoped="1" Override="1" />

<!-- Extend from multiple container objects -->
<O N="MyCodeCheck" T="Group" Extends="[Chapter6_5, Chapter3_6]">
  <!-- Now has access to content from both chapters -->
  <P N="PhiFactor" V="Chapter6_5.SC6_5_4_2.phi_f"/>
  <P N="TrafficData" V="Chapter3_6.ADTTSL"/>
</O>
```

**Key Points:**

* Use array syntax: `Extends="[Obj1, Obj2, Obj3]"`
* All listed objects are copied into your object
* If objects have parameters with the same name, the last one in the list wins
* Transitive: If you extend A, and A extends B, you also get B's content

***

#### Override Attribute - Setting Library Inputs

Library objects often define input parameters (with `Role="Input"`). The `Override="1"` attribute allows you to provide values for these inputs when extending the library.

**Think of it Like a Function Call:**

```xml
<!-- Library object is like a function with inputs -->
<O N="AASHTO_Section4_6" T="DesignCode">
  <P N="Mmajbend" V="0" Role="Input" D="Major-axis bending moment"/>
  <P N="Ddepth" V="0" Role="Input" D="Web depth"/>
  <P N="lunbr" V="0" Role="Input" D="Unbraced length"/>
  <P N="Rrad" V="0" Role="Input" D="Girder radius"/>

  <!-- Internal calculations using the inputs -->
  <O N="SC4_6_1_2" T="Group">
    <P N="M_lat" V="someComplexCalculation(Mmajbend, Ddepth, lunbr, Rrad)"/>
  </O>
</O>

<!-- Your code "calls" it by extending with Override -->
<O N="ForCurvatureEffects_AbsMax" T="Group"
   Extends="AASHTO_Section4_6::v3"
   Scoped="1"
   Override="1">
  <!-- Override the input parameters with your values -->
  <P N="Mmajbend" V="max(abs(MuStrPos), abs(MuStrNeg))" D="[NAME_ALIAS: M]" UT="Moment" UC="DR_ForceU"/>
  <P N="Ddepth" V="dw_Input" D="[NAME_ALIAS: D]" UT="Length" UC="DR_StructU"/>
  <P N="lunbr" V="Lb_Input" D="[NAME_ALIAS: l]" UT="Length" UC="DR_StructU"/>
  <P N="Rrad" V="RadOfGird" D="[NAME_ALIAS: R]" UT="Length" UC="DR_StructU"/>
</O>

<!-- Access the calculated results -->
<P N="LateralMoment" V="ForCurvatureEffects_AbsMax.SC4_6_1_2.M_lat"/>
```

**Conceptual Equivalent in Programming:**

```javascript
// Library is like a function
function AASHTO_Section4_6(Mmajbend, Ddepth, lunbr, Rrad) {
  // Internal calculations
  let M_lat = someComplexCalculation(Mmajbend, Ddepth, lunbr, Rrad);
  return { SC4_6_1_2: { M_lat: M_lat } };
}

// Extending with Override is like calling the function
let ForCurvatureEffects_AbsMax = AASHTO_Section4_6(
  Mmajbend: max(abs(MuStrPos), abs(MuStrNeg)),
  Ddepth: dw_Input,
  lunbr: Lb_Input,
  Rrad: RadOfGird
);

// Access the result
let LateralMoment = ForCurvatureEffects_AbsMax.SC4_6_1_2.M_lat;
```

***

#### Scoped Attribute with Extends

The `Scoped="1"` attribute is commonly used with library imports to prevent parameter name conflicts.

**Without Scoped:**

```xml
<O N="Chapter3_4" T="Group" Extends="AASHTO_9th_Section3Sub4::v3">
  <!-- All parameters from AASHTO library are exposed at this level -->
  <!-- If library has common names like "Width", "Length", they might conflict -->
</O>

<P N="Length" V="100"/>  <!-- Might conflict with library's internal "Length" -->
```

**With Scoped:**

```xml
<O N="Chapter3_4" T="Group" Extends="AASHTO_9th_Section3Sub4::v3" Scoped="1">
  <!-- Library internals are isolated -->
  <!-- Must use dot notation to access: Chapter3_4.SomeParameter -->
</O>

<P N="Length" V="100"/>  <!-- No conflict, this is separate from library internals -->
```

**Best Practice:** Always use `Scoped="1"` when importing library objects to avoid unintended parameter shadowing.

***

#### Versioning with ::v3

Library objects often include version tags (e.g., `::v3`) to support multiple versions of the same code.

```xml
<!-- Import specific version of AASHTO chapter -->
<O N="Chapter6_10" T="Group" Extends="AASHTO_9th_Section6Sub10::v3" Scoped="1" Override="1" />

<!-- Later, if a v4 is released, you can upgrade -->
<O N="Chapter6_10_New" T="Group" Extends="AASHTO_9th_Section6Sub10::v4" Scoped="1" Override="1" />
```

**Benefits:**

* Backward compatibility - old projects keep using ::v3
* Gradual migration - test ::v4 in parallel
* Clear dependency tracking

***

#### Complete Real-World Example

```xml
<!-- Import multiple AASHTO chapters as namespaces -->
<O N="Chapter6_5" T="Group" Extends="AASHTO_9th_Section6Sub5::v3" Scoped="1" Override="1" />
<O N="Chapter3_4" T="Group" Extends="AASHTO_9th_Section3Sub4::v3" Scoped="1" Override="1" />
<O N="Chapter3_6" T="Group" Extends="AASHTO_9th_Section3Sub6::v3" Scoped="1" Override="1" />

<!-- Create a code check object that uses these chapters -->
<O N="SteelGirderCodeCheck" T="CodeCheck"
   Extends="[OBPEnum_LoadType::v3, OBPEnum_States::v3]">

  <!-- Get resistance factor from Chapter 6.5 -->
  <P N="phi_f" V="Chapter6_5.SC6_5_4_2.phi_f" D="Resistance factor for flexure"/>

  <!-- Get traffic data from Chapter 3.6 -->
  <P N="ADTT_SL" V="Chapter3_6.ADTTSL" D="Single lane ADTT"/>

  <!-- Get fatigue load factors from Chapter 3.4 -->
  <P N="Ftg1LLF" V="Chapter3_4.FatiqueI_LLandIMandCEonly.LL" D="Fatigue I load factor"/>
  <P N="Ftg2LLF" V="Chapter3_4.FatiqueII_LLandIMandCEonly.LL" D="Fatigue II load factor"/>

  <!-- Import curvature calculation and override inputs -->
  <O N="ForCurvatureEffects" T="Group"
     Extends="AASHTO_7thW2015And2016_Section4Sub6::v3"
     Scoped="1"
     Override="1">
    <P N="Mmajbend" V="max(abs(MuStrPos), abs(MuStrNeg))" D="Major-axis moment"/>
    <P N="Ddepth" V="dw_Input" D="Web depth"/>
    <P N="lunbr" V="Lb_Input" D="Unbraced length"/>
    <P N="Rrad" V="RadOfGird" D="Girder radius"/>
  </O>

  <!-- Use the curvature calculation result -->
  <P N="fl_curvature" V="ForCurvatureEffects.SC4_6_1_2.M_lat / S_top_flange"
     D="Lateral bending stress due to curvature"/>
</O>
```

***

#### Key Takeaways

1. **Extends = Copy**: Copies the entire object tree from library into your object
2. **Container Pattern**: Create `<O N="ChapterName" T="Group" Extends="Library::v3" Scoped="1"/>` for namespacing
3. **Override="1"**: Allows setting input parameters of the extended library object
4. **Scoped="1"**: Isolates library internals from your project namespace
5. **Dot Notation**: Access library content via `ContainerName.InternalPath.Parameter`
6. **Multiple Extends**: Use array syntax `Extends="[Obj1, Obj2, Obj3]"`
7. **Versioning**: Use `::v3` for version control

***

#### Common Patterns Summary

**Pattern 1: Import Library as Namespace**

```xml
<O N="Chapter3_4" T="Group" Extends="AASHTO_9th_Section3Sub4::v3" Scoped="1" Override="1" />
<P N="Value" V="Chapter3_4.SomeParameter"/>
```

**Pattern 2: Import Library with Input Override**

```xml
<O N="MyCalc" T="Group" Extends="CalculationLibrary::v3" Scoped="1" Override="1">
  <P N="Input1" V="myValue1"/>
  <P N="Input2" V="myValue2"/>
</O>
<P N="Result" V="MyCalc.OutputParameter"/>
```

**Pattern 3: Extend Multiple Libraries**

```xml
<O N="MyObject" T="Group" Extends="[Lib1::v3, Lib2::v3, Lib3::v3]">
  <!-- Has access to all three libraries -->
</O>
```

**Pattern 4: Transitive Access**

```xml
<O N="BaseLib" T="Group" Extends="CoreLib::v3"/>
<O N="MyObject" T="Group" Extends="BaseLib">
  <!-- Has access to both BaseLib and CoreLib (transitive) -->
</O>
```

***

### Station-Dependent Parameters

Some parameters can vary along a station (alignment coordinate):

```xml
<P N="Depth" V="[[0,100],60, [100,200],72, [200,300],60]"/>
```

Format: `[[station_start, station_end], value, ...]`

### Built-in Functions

Common parametric functions available in expressions:

* **Geometric:** `online(p1, p2, t)`, `intersect(line1, line2)`, `point(obj, station)`
* **Array:** `sum(array)`, `min(...)`, `max(...)`, `length(array)`, `first(array)`, `last(array)`
* **Units:** `convert(value, fromUnit, toUnit)`, `withunits(value, unitType, unitCat)`
* **Object queries:** `refs(objType)`, `objs(objType)`, `value(objName, paramName)`
* **Geometry:** `surfarea(surface)`, `volume(solid)`, `perimeter(boundary)`

### Special Identifiers

* `self`: Reference to current object
* `myself`: Reference to current parameter's parent object
* `pi`: π constant
* `NULL`: Null object reference

## Best Practices

### 1. Use Descriptive Names

```xml
<!-- Good -->
<P N="GirderSpacing" V="10" D="Transverse spacing between girders"/>

<!-- Avoid -->
<P N="S" V="10"/>
```

### 2. Provide Default Values for Inputs

```xml
<P N="NumSpans" V="3" Role="Input" D="Number of spans"/>
```

### 3. Use Appropriate Unit Types

```xml
<P N="Force" V="1000" UT="Force" UC="Default"/>
<P N="Length" V="120" UT="Length" UC="Default"/>
<P N="Stress" V="50000" UT="Stress" UC="Default"/>
```

### 4. Prefer Concise Format When Possible

```xml
<!-- Concise (preferred when metadata not needed) -->
<O T="Point" X="0" Y="0" Z="0"/>

<!-- Verbose (when you need descriptions, units, roles) -->
<O T="Point">
  <P N="X" V="0" UT="Length" D="X coordinate"/>
  <P N="Y" V="0" UT="Length" D="Y coordinate"/>
  <P N="Z" V="0" UT="Length" D="Z coordinate"/>
</O>
```

### 5. Group Related Objects

```xml
<O N="Geometry" T="Group">
  <!-- Geometric objects here -->
</O>

<O N="Materials" T="Group">
  <!-- Material definitions here -->
</O>
```

### 6. Use Guards for Conditional Content

Choose the appropriate guard type for your use case:

* **Guard**: For typical optional components (most common)
* **GuardX**: For library development when you need to preserve the guard condition
* **DesignGuard**: For design checks that may not apply in all cases

```xml
<P N="IncludeDiaphragms" V="1" Role="Input"/>
<P N="UseDetailedAnalysis" V="0" Role="Input"/>

<!-- Guard: Typical conditional inclusion -->
<O T="Repeat" N="Diaphragms" Guard="IncludeDiaphragms == 1">
  <!-- Diaphragm objects only exist if condition is true -->
</O>

<!-- GuardX: Preserve guard for documentation -->
<O T="Analysis" N="DetailedAnalysis" GuardX="UseDetailedAnalysis == 1">
  <!-- GuardX parameter persists after compilation -->
</O>

<!-- DesignGuard: Design check that may not apply -->
<O T="Check" N="DeflectionCheck" DesignGuard="LiveLoad > 0">
  <!-- Shows "does not apply" in reports if LiveLoad <= 0 -->
</O>
```

### 7. Use map() for Parameter Loops, Repeat Only for Objects

**CRITICAL PERFORMANCE RULE:** Never use Repeat for calculating parameter values—always use functional programming instead.

```xml
<!-- ❌ BAD: Creates hundreds of unnecessary objects -->
<O T="Repeat" N="Forces" S="0" E="length(Stations)-1" I="1" CTRL="i" i="0">
  <P N="Station" V="Stations[i]"/>
  <P N="Moment" V="force(Element, LoadCase, 'My', Station)"/>
</O>

<!-- ✅ GOOD: Single parameter with map() - 100x faster -->
<P N="Moments" V="map(Stations, force(Element, LoadCase, 'My', x))"/>
```

**When to use each:**

* **Use Repeat**: Creating actual objects (Points, Lines, Volumes, Girders, etc.)
* **Use map()**: Transforming data, extracting properties, calculating values
* **Use filter()**: Selecting subset of data based on conditions
* **Use reduce()**: Aggregating data to single value

```xml
<!-- Examples of correct usage -->
<O T="Repeat" N="Points" S="0" E="10" I="1" CTRL="i" i="0">
  <O T="Point" N="Pt" X="i*12" Y="0" Z="0"/>  <!-- ✅ Creates objects -->
</O>

<P N="GirderNames" V="map(Girders, x => x.N)"/>  <!-- ✅ Data transformation -->
<P N="LongGirders" V="filter(Girders, x => x.Length > 100)"/>  <!-- ✅ Filtering -->
<P N="TotalArea" V="reduce(Areas, x + y)"/>  <!-- ✅ Aggregation -->
```

See section 4.1 for detailed explanation and performance impact.

### 8. Document Complex Expressions

```xml
<P N="MomentCapacity" V="Fy * Zx" D="Plastic moment capacity: Fy * Zx"/>
```

### 8. Use Scoped Objects Deliberately

Use `Scoped="1"` to create isolated parameter namespaces and prevent accidental parameter resolution from outside:

```xml
<O N="StandardColumnLibrary" T="Group" Scoped="1">
  <!-- Internal parameters with common names like "Width", "Height" won't
       interfere with parameters in the main project -->
  <P N="Width" V="12"/>
  <P N="Height" V="12"/>
  <P N="StandardColumn" V="..."/>
</O>

<O N="Bridge" T="Structure">
  <P N="Width" V="100"/>  <!-- Different "Width", isolated from library -->
  <O T="Column" T="StandardColumnLibrary.StandardColumn"/>
  <!-- Bridge.Width and StandardColumnLibrary.Width don't conflict
       due to +100 scope penalty -->
</O>
```

### 9. Avoid Unintentional Parameter Shadowing

Be deliberate when using the same parameter name at multiple hierarchy levels. If shadowing is unintentional, use unique names:

```xml
<!-- Deliberate shadowing (override pattern) - GOOD -->
<O N="Project">
  <P N="DefaultWidth" V="100"/>
  <O N="SpecialSection">
    <P N="DefaultWidth" V="80"/>  <!-- Intentional override -->
  </O>
</O>

<!-- Unintentional shadowing - PROBLEMATIC -->
<O N="Project">
  <P N="Width" V="100"/>
  <O N="Section">
    <P N="Width" V="50"/>  <!-- May cause confusion if forgotten -->
    <O N="Detail">
      <P N="Calc" V="Width * 2"/>  <!-- Which Width? Not obvious! -->
    </O>
  </O>
</O>

<!-- Better: Use unique names - CLEARER -->
<O N="Project">
  <P N="ProjectWidth" V="100"/>
  <O N="Section">
    <P N="SectionWidth" V="50"/>
    <O N="Detail">
      <P N="Calc" V="SectionWidth * 2"/>  <!-- Crystal clear! -->
    </O>
  </O>
</O>
```

### 10. Understand Distance-Based Resolution

When multiple parameters share the same name, document the expected resolution in comments:

```xml
<O N="Bridge">
  <P N="Spacing" V="10"/>
  <O T="Repeat" N="Bents">
    <P N="Spacing" V="30"/>  <!-- Overrides Bridge.Spacing for this level -->
    <O N="Bent">
      <O N="Girder">
        <P N="X" V="Spacing"/>
        <!-- Uses Bents.Spacing (30) at distance 2, not Bridge.Spacing (10) at distance 3 -->
      </O>
    </O>
  </O>
</O>
```

### 11. Optimize for Lazy Evaluation

Structure your model to take advantage of lazy evaluation:

```xml
<!-- Good: Expensive calculations only if needed -->
<P N="UseDetailedAnalysis" V="0" Role="Input"/>
<P N="DetailedResult" V="expensiveCalculation(...)"/>
<O N="Display">
  <P N="Guard" V="UseDetailedAnalysis == 1"/>
  <P N="Value" V="DetailedResult"/>
  <!-- DetailedResult only evaluated if Guard is true! -->
</O>

<!-- Also good: Cached results -->
<P N="ComplexGeometry" V="generateMesh(...)"/>
<P N="Area" V="ComplexGeometry.Area"/>
<P N="Perimeter" V="ComplexGeometry.Perimeter"/>
<!-- ComplexGeometry evaluated once, then both Area and Perimeter use cached result -->
```

### 12. Consider Hierarchy Performance

Avoid excessively deep hierarchies for frequently-accessed parameters:

```xml
<!-- Less optimal: Deep nesting -->
<O N="A"><O N="B"><O N="C"><O N="D"><O N="E"><O N="F">
  <P N="DeepValue" V="100"/>
</O></O></O></O></O></O>
<O N="SomewhereElse">
  <P N="X" V="DeepValue"/>  <!-- Must search deep hierarchy every time -->
</O>

<!-- Better: Flatten or use strategic scoping -->
<O N="Config" T="Group">
  <P N="DeepValue" V="100"/>  <!-- Easier to find -->
</O>
<O N="SomewhereElse">
  <P N="X" V="DeepValue"/>  <!-- Faster resolution -->
</O>
```

## Common Pitfalls to Avoid

1. **Using Repeat for Parameter Loops (CRITICAL PERFORMANCE ISSUE):** This is the #1 performance mistake in ParamML models.

   **❌ WRONG:**

   ```xml
   <O T="Repeat" N="CalcLoop" S="0" E="99" I="1" CTRL="i" i="0">
     <P N="Result" V="InputList[i] * 2"/>
   </O>
   ```

   **Problem:** Creates 100 objects in project tree, slow compilation, high memory usage

   **✅ CORRECT:**

   ```xml
   <P N="Results" V="map(InputList, x => x * 2)"/>
   ```

   **Why:** Single parameter, instant evaluation, minimal memory

   **Rule:** Use Repeat ONLY to create objects that must exist in the 3D model, FEA mesh, or project tree. For all data transformations, use `map()`, `filter()`, or `reduce()`.

   See section 4.1 for detailed explanation.
2. **Circular Dependencies:** Ensure Parameter A doesn't depend on Parameter B if B depends on A. The lazy evaluation system will detect this and throw an error.
3. **Undefined References:** Always ensure referenced objects/parameters exist in the hierarchy or project.
4. **Type Mismatches:** Don't use numeric expressions for Text parameters.
5. **Missing Units:** Specify unit types for physical quantities (Length, Force, Stress, etc.).
6. **Invalid Guards:** Guard expressions must evaluate to 0 (false) or 1 (true).
7. **Repeat Issues:** Ensure S, E, and I parameters create finite iterations.
8. **Unintended Parameter Shadowing:** When multiple parameters have the same name at different hierarchy levels, the closest one (by distance) is used. This can cause unexpected behavior if you're not aware of which parameter is being resolved.

   ```xml
   <!-- Example of unintended shadowing: -->
   <O N="Project">
     <P N="Width" V="100"/>  <!-- Intended global width -->
     <O N="Section">
       <P N="Width" V="50"/>  <!-- Local override, but may be forgotten -->
       <O N="SubComponent">
         <P N="Area" V="Width * Height"/>
         <!-- Uses Section.Width (50), NOT Project.Width (100)! -->
       </O>
     </O>
   </O>
   ```
9. **Scope Boundary Surprises:** Objects with `Scoped="1"` add +100 to distance calculations, creating strong isolation boundaries. Parameters inside scoped objects are "far away" from outside objects.

   ```xml
   <O N="Root">
     <P N="SharedValue" V="1000"/>
     <O N="ScopedModule" Scoped="1">
       <P N="SharedValue" V="500"/>  <!-- +100 penalty when accessed from outside -->
     </O>
     <O N="OtherModule">
       <P N="X" V="SharedValue"/>  <!-- Gets Root.SharedValue (1000), distance 1
                                        NOT ScopedModule.SharedValue (102) -->
     </O>
   </O>
   ```
10. **Distance vs. XML Order Confusion:** Parameter resolution is based on **hierarchy distance**, not the order parameters appear in XML. The engine always picks the closest parameter by distance, even if another parameter with the same name was defined first.
11. **Lazy Evaluation Timing:** Remember that expressions are NOT evaluated when defined. They're evaluated on-demand. Changing an input parameter doesn't automatically update dependent parameters until they're accessed.

    ```xml
    <P N="Input" V="10" Role="Input"/>
    <P N="Output" V="Input * 2"/>
    <!-- If you change Input from 10 to 20:
         - Output is NOT immediately recalculated
         - Output is recalculated the NEXT TIME it's accessed
         - The cached value (20) is invalidated when Input changes -->
    ```
12. **Guard Expression Restrictions:** Guard/GuardX expressions cannot reference parameters inside the object they guard (this would create a circular dependency during compilation). Always reference external parameters for guard conditions.

    ```xml
    <!-- WRONG: Circular dependency -->
    <O T="Beam" N="LongBeam" Guard="Length > 100">
      <P N="Length" V="120"/>  <!-- Can't reference this in Guard! -->
    </O>

    <!-- CORRECT: Reference external parameter -->
    <P N="BeamLength" V="120"/>
    <O T="Beam" N="LongBeam" Guard="BeamLength > 100">
      <P N="Length" V="BeamLength"/>  <!-- OK -->
    </O>
    ```

    Additionally, remember that Guard and GuardX are compile-time (object removed if false), while DesignGuard is runtime (object marked "not applicable" in reports).
13. **Deep Hierarchy Performance:** Extremely deep hierarchies (10+ levels) can slow down parameter resolution. Consider flattening the structure or using scoped objects strategically to limit search scope.

## Debugging Tips

1. **Check Parameter Names:** Names are case-sensitive.
2. **Verify Object Types:** Ensure `T` attribute matches actual class names.
3. **Test Expressions:** Start with simple literals before adding complexity.
4. **Use Descriptive Names:** Makes debugging much easier and reduces shadowing issues.
5. **Check Parent-Child Structure:** Ensure objects are properly nested.
6. **Validate XML:** Ensure proper closing tags and attribute quoting.
7. **Trace Parameter Resolution:** When a parameter has an unexpected value, manually calculate the distance from the evaluation point to all candidates with that name. The one with minimum distance wins.

   ```
   Example: If "Width" evaluates to unexpected value:
   1. Find all parameters/objects named "Width" in the project
   2. For each, count steps from current object through common ancestor
   3. Add +100 for each Scoped="1" boundary crossed
   4. The one with lowest total distance is being used
   ```
8. **Check Scope Boundaries:** Look for `Scoped="1"` attributes in parent objects. They create isolation that may prevent expected parameter resolution.
9. **Verify Lazy Evaluation:** If a parameter doesn't seem updated after changing an input, check if anything has actually requested its value. Try explicitly accessing it to trigger re-evaluation.
10. **Use Unique Names Strategically:** If shadowing is causing confusion, use unique parameter names across the hierarchy, or use very deliberate shadowing for override patterns.
11. **Debug with Comments:** Add XML comments showing expected distance calculations to document your resolution assumptions:

    ```xml
    <P N="Value" V="GlobalParam"/>
    <!-- Expected: GlobalParam at distance 2 (up to parent, up to grandparent) -->
    ```

## Advanced Library Development Features

The following features are essential for creating reusable library components with rich UI integration and metadata.

### 1. ParamInfo Object

`ParamInfo` is a special object type that provides metadata and configuration for parameters, controlling their UI behavior, validation, and visibility.

**Common ParamInfo Attributes:**

* `Param`: Name of the parameter being configured (use `@` prefix for object references)
* `Required`: If "1", parameter must be provided (UI enforces)
* `Pick`: If "1", enables object picker UI for selection
* `List`: If "1", parameter is a list/array
* `Min`: Minimum number of list items
* `Max`: Maximum number of list items
* `ListColumnHeaders`: Array of column header names for list UI
* `ListColumnTypes`: Array of types for each column
* `ParamGuard`: Conditional visibility expression (see ParamGuard section below)
* `ParamInterface`: Custom parameter input interface (see ParamInterface section below)

**⚠️ CRITICAL: Min and Max for List Parameters**

When using `Pick="1"` with list parameters, **BOTH Min and Max must be specified** if you want to allow multiple selections. If only `Min` is provided without `Max`, the system defaults `Max` to 1, allowing only a single selection even if `Min > 1`.

```xml
<!-- ❌ WRONG: Only Min specified -->
<P N="ParamName" V="[]" T="OBPBase_Object" Role="Input" />
<O T="ParamInfo" Param="ParamName" Required="1" Min="2" List="1" Pick="1" />
<!-- Result: Only 1 object can be picked (Max defaults to 1) -->

<!-- ✅ CORRECT: Both Min and Max specified -->
<P N="ParamName" V="[]" T="OBPBase_Object" Role="Input" />
<O T="ParamInfo" Param="ParamName" Required="1" Min="2" Max="10" List="1" Pick="1" />
<!-- Result: 2-10 objects can be picked -->
```

**Rule:** For list inputs with unknown maximum count, always specify a reasonable `Max` value (e.g., `Max="100"`).

**Example: Required Object with Picker**

```xml
<O T="ParamInfo" Param="@Girder" Required="1" Pick="1"/>
```

This makes the `Girder` parameter required and adds a UI picker button for selecting girder objects.

**Example: List Parameter with UI Configuration**

```xml
<O T="ParamInfo" Param="@NonCompCase" List="1" Min="1" Max="50"
   ParamInterface="@OBPParamInterfaceCombinationAndFactors" />
```

This configures `NonCompCase` as a list with 1-50 items and uses a custom interface for input.

**Example: List with Column Headers**

```xml
<O T="ParamInfo" Param="@addStation" List="1" Min="1" Max="100"
   ListColumnHeaders="['Additional Stations']"
   ListColumnTypes="['Number']"/>
```

This creates a list parameter with a single column labeled "Additional Stations".

**Complete Example:**

```xml
<O N="MyLibraryObject" T="Project">
  <!-- Parameter definitions -->
  <P N="Girder" V="G1" T="OBPBase_GirderAnalysisResultsRef"/>
  <P N="LoadCases" V="[]" T="Text"/>
  <P N="StationList" V="[0, 50, 100]"/>

  <!-- ParamInfo metadata -->
  <O T="ParamInfo" Param="@Girder" Required="1" Pick="1"/>
  <O T="ParamInfo" Param="@LoadCases" List="1" Min="1" Max="20"
     ListColumnHeaders="['Load Case Name']"/>
  <O T="ParamInfo" Param="@StationList" List="1" Min="1" Max="100"
     ListColumnHeaders="['Station (ft)']"/>
</O>
```

### 2. Object Metadata Attributes

Library objects can include metadata attributes that control organization, categorization, and UI display.

**Metadata Attributes:**

* `Tags`: Comma-separated tags for filtering and categorization (prefix with `@` for tag names)
* `ObjLabel`: User-friendly display name for the object
* `Category`: Hierarchical category path (use `:` separator for subcategories)

**Example:**

```xml
<O N="OBP_GirderStressSummaryTable" T="Project"
   Tags="@secondlayer,usastandard,steelIGirder,release"
   ObjLabel="Girder Stress Summary Table"
   Category="Code Check Objects:Code Check Sub Objects">
  <!-- Object content -->
</O>
```

**Tag Usage:**

* `@secondlayer`: Indicates this is a secondary-level component
* `@usastandard`: US design standards
* `@steelIGirder`: Applies to steel I-girder bridges
* `@release`: Ready for production release

**Category Hierarchy:** The category path creates a tree structure in the UI:

```
Code Check Objects
  └─ Code Check Sub Objects
       └─ Girder Stress Summary Table
```

**Best Practices:**

* Use descriptive `ObjLabel` values that users will recognize
* Create consistent tag vocabularies across your library
* Organize categories hierarchically from general to specific
* Use tags for filtering (e.g., bridge type, code standard, region)

### 3. Extends Attribute

The `Extends` attribute provides a different inheritance mechanism than the `T` (Type) attribute. While `T` specifies the object's class or base type, `Extends` allows you to inherit parameters and structure from another object while maintaining a different base type.

**Syntax:**

```xml
<O N="ObjectName" T="BaseType" Extends="SourceObject::Version">
```

**Key Differences:**

* **Type (`T`)**: Defines the object's fundamental class (e.g., `Project`, `Group`, `Volume`)
* **Extends**: Imports parameters and child objects from another object without changing the base type

**Example:**

```xml
<!-- Base unit definitions -->
<O N="Base_DesignSubUnits" T="Group">
  <P N="Length" V="'ft'" T="Text"/>
  <P N="Force" V="'kip'" T="Text"/>
  <P N="Stress" V="'ksi'" T="Text"/>
</O>

<!-- Version 3 of base units -->
<O N="Base_DesignSubUnits::v3" T="Group">
  <P N="Length" V="'ft'" T="Text"/>
  <P N="Force" V="'kip'" T="Text"/>
  <P N="Stress" V="'ksi'" T="Text"/>
  <P N="Temperature" V="'F'" T="Text"/>
</O>

<!-- Object that extends the versioned base -->
<O N="Units" T="Group" Extends="Base_DesignSubUnits::v3">
  <!-- Inherits all parameters from Base_DesignSubUnits::v3 -->
  <!-- Can override specific parameters -->
  <P N="Stress" V="'MPa'"/>
</O>
```

**Versioning Pattern:** Use `::vN` suffix for versioned objects to maintain backward compatibility:

```xml
<O N="StandardColumn::v1" T="Volume">...</O>
<O N="StandardColumn::v2" T="Volume">...</O>
<O N="MyColumn" Extends="StandardColumn::v2">...</O>
```

**When to Use Extends vs Type:**

* Use **Type (`T`)**: To define what kind of object it is (Volume, Group, Project, etc.)
* Use **Extends**: To import a set of default parameters and structure from a template

### 4. ParamGuard

`ParamGuard` is different from `Guard` - while `Guard` removes entire objects, `ParamGuard` controls **parameter visibility** in the UI based on conditions.

**Key Differences:**

| Feature        | Guard                   | ParamGuard                       |
| -------------- | ----------------------- | -------------------------------- |
| **Applied To** | Objects                 | Parameters (via ParamInfo)       |
| **Effect**     | Removes object if false | Hides parameter UI if false      |
| **Evaluation** | Compile-time            | Runtime (UI update)              |
| **Use Case**   | Conditional components  | Conditional parameter visibility |

**Syntax:**

```xml
<O T="ParamInfo" ParamGuard="Condition" Param="ParameterName"/>
```

**Example: Conditional Parameter Visibility**

```xml
<O N="ReinforcementConfig" T="Group">
  <!-- Input parameter controlling mode -->
  <P N="ReinfDataPref" V="0" Role="Input" D="0=Lumped, 1=Detailed"/>

  <!-- Parameters shown/hidden based on mode -->
  <P N="LumpedTopReinfArea" V="5.0" Role="Input"/>
  <P N="DetailedBarSize" V="8" Role="Input"/>
  <P N="DetailedBarSpacing" V="6" Role="Input"/>

  <!-- ParamInfo controls visibility -->
  <O T="ParamInfo" ParamGuard="ReinfDataPref == 0" Param="LumpedTopReinfArea"/>
  <O T="ParamInfo" ParamGuard="ReinfDataPref == 1" Param="DetailedBarSize"/>
  <O T="ParamInfo" ParamGuard="ReinfDataPref == 1" Param="DetailedBarSpacing"/>
</O>
```

In this example:

* When `ReinfDataPref == 0`: Only `LumpedTopReinfArea` is visible in UI
* When `ReinfDataPref == 1`: `DetailedBarSize` and `DetailedBarSpacing` are visible

**Complex Conditions:**

```xml
<O T="ParamInfo" ParamGuard="BridgeType == 'Steel' && SpanLength > 100"
   Param="StiffenerSpacing"/>
```

**Best Practices:**

* Use ParamGuard to simplify UI by hiding irrelevant parameters
* Guard expressions should reference other parameters in the same object or parent objects
* Combine with `Required` flag: `Required="1"` only enforces when ParamGuard is true
* Keep guard expressions simple and fast (evaluated on every UI update)

### 5. ParamInterface

`ParamInterface` specifies a custom UI component for parameter input, enabling specialized editing experiences beyond standard text/number inputs.

**Syntax:**

```xml
<O T="ParamInfo" Param="@ParameterName" ParamInterface="@InterfaceObjectName"/>
```

**Common Custom Interfaces:**

* `@OBPParamInterfaceCombinationAndFactors`: Load combination editor
* `@OBPParamInterfaceStationPicker`: Station selection with alignment visualization
* `@OBPParamInterfaceColorPicker`: Color selection UI
* `@OBPParamInterfaceMaterialPicker`: Material database browser

**Example: Load Combination Interface**

```xml
<P N="LoadCombinations" V="[]" T="Text"/>
<O T="ParamInfo" Param="@LoadCombinations" List="1" Min="1" Max="50"
   ParamInterface="@OBPParamInterfaceCombinationAndFactors"/>
```

**Example: Custom Table Interface**

```xml
<P N="ReinforcementSchedule" V="[]"/>
<O T="ParamInfo" Param="@ReinforcementSchedule" List="1"
   ListColumnHeaders="['Bar Size', 'Spacing', 'Location']"
   ListColumnTypes="['Number', 'Number', 'Text']"
   ParamInterface="@OBPParamInterfaceRebarTable"/>
```

**Creating Custom Interfaces:** Custom interfaces are defined as objects with specific UI behavior:

```xml
<O N="OBPParamInterfaceCustomEditor" T="ParamInterface">
  <P N="EditorType" V="'CustomGrid'" T="Text"/>
  <P N="Columns" V="['Name', 'Value', 'Unit']"/>
  <!-- Interface configuration -->
</O>
```

### 6. List Parameters with UI Configuration

List (array) parameters can be configured with rich UI metadata using ParamInfo.

**List Configuration Attributes:**

* `List="1"`: Declares parameter as a list
* `Min`: Minimum number of items (enforced by UI)
* `Max`: Maximum number of items
* `ListColumnHeaders`: Array of column names (as JSON array string)
* `ListColumnTypes`: Array of types for each column ('Number', 'Text', 'Object', etc.)

**Example: Simple List**

```xml
<P N="Stations" V="[0, 50, 100, 150]"/>
<O T="ParamInfo" Param="@Stations" List="1" Min="2" Max="100"
   ListColumnHeaders="['Station (ft)']"
   ListColumnTypes="['Number']"/>
```

**Example: Multi-Column List**

```xml
<P N="LoadDefinitions" V="[[100, 'Dead', 1.2], [50, 'Live', 1.6]]"/>
<O T="ParamInfo" Param="@LoadDefinitions" List="1" Min="1" Max="20"
   ListColumnHeaders="['Magnitude', 'Type', 'Factor']"
   ListColumnTypes="['Number', 'Text', 'Number']"/>
```

**Example: List of Object References**

```xml
<P N="Girders" V="[G1, G2, G3]" T="Text"/>
<O T="ParamInfo" Param="@Girders" List="1" Min="1" Max="10" Pick="1"
   ListColumnHeaders="['Girder']"
   ListColumnTypes="['OBPGirder']"/>
```

**Accessing List Items in Expressions:**

```xml
<P N="FirstStation" V="Stations[0]"/>
<P N="StationCount" V="length(Stations)"/>
<P N="TotalLoad" V="sum(map(LoadDefinitions, x => x[0]))"/>
```

**Best Practices:**

* Always set reasonable `Min` and `Max` limits
* Provide descriptive column headers
* Match `ListColumnTypes` to actual data types for proper validation
* Use `Pick="1"` for lists of object references to enable picker UI

### 7. NAME\_ALIAS and EXPR\_ALIAS

These special documentation markers in parameter descriptions provide human-readable aliases for parameters and expressions, improving code readability and auto-generated documentation.

**Syntax in Description Field:**

```xml
<P N="InternalName" V="Expression" D="[NAME_ALIAS: UserFriendlyName] Description"/>
<P N="InternalName" V="Expression" D="[EXPR_ALIAS: ReadableExpression] Description"/>
```

**NAME\_ALIAS - Readable Parameter Names:**

```xml
<P N="My_Pos_MaxF_Total" V="max(MyPos, MzPos)"
   D="[NAME_ALIAS: My_Total] Total positive moment including all sources"/>

<P N="Mx_Neg_DL_Max" V="forceNeg('Mx', Girder, 'DeadLoad')"
   D="[NAME_ALIAS: Mx_DL] Maximum negative moment due to dead load"/>
```

When referenced in reports or UI:

* Shows "My\_Total" instead of "My\_Pos\_MaxF\_Total"
* Shows "Mx\_DL" instead of "Mx\_Neg\_DL\_Max"

**EXPR\_ALIAS - Readable Expressions:**

```xml
<P N="StressRatio" V="ActualStress / AllowableStress"
   D="[EXPR_ALIAS: σ/σ_allowable] Stress ratio for code check"/>

<P N="SlendernessRatio" V="EffectiveLength / RadiusOfGyration"
   D="[EXPR_ALIAS: KL/r] Column slenderness ratio"/>
```

In documentation and error messages:

* Shows "σ/σ\_allowable" instead of the internal expression
* Shows "KL/r" instead of "EffectiveLength / RadiusOfGyration"

**Complete Example:**

```xml
<O N="MomentCheck" T="DesignCheck">
  <!-- Internal calculation with aliases -->
  <P N="M_FactoredDeadLoad" V="forceM('Girder', 'DeadLoad') * 1.25"
     D="[NAME_ALIAS: M_DL] [EXPR_ALIAS: 1.25×M_DL] Factored dead load moment"/>

  <P N="M_FactoredLiveLoad" V="forceM('Girder', 'LiveLoad') * 1.75"
     D="[NAME_ALIAS: M_LL] [EXPR_ALIAS: 1.75×M_LL] Factored live load moment"/>

  <P N="M_TotalFactored" V="M_FactoredDeadLoad + M_FactoredLiveLoad"
     D="[NAME_ALIAS: M_u] [EXPR_ALIAS: 1.25M_DL + 1.75M_LL] Ultimate moment demand"/>

  <P N="CapacityRatio" V="M_TotalFactored / M_n"
     D="[NAME_ALIAS: DCR] [EXPR_ALIAS: M_u/M_n] Demand-capacity ratio"/>
</O>
```

**Benefits:**

* Auto-generated reports show clean, professional notation
* Error messages reference familiar names
* Code remains self-documenting
* Maintains backward compatibility (internal names unchanged)

**Best Practices:**

* Use NAME\_ALIAS for commonly referenced parameters
* Use EXPR\_ALIAS for mathematical expressions with standard notation (Greek letters, engineering symbols)
* Place aliases at the beginning of the description
* Keep aliases concise and meaningful

### 8. StaticParams on Repeat

`StaticParams` is a performance optimization attribute for `Repeat` objects that identifies parameters whose values don't change across iterations.

**Problem:** In a `Repeat` object, child objects are instantiated for each iteration. Normally, all parameters are re-evaluated for every iteration, even if they reference values that are constant across all iterations.

**Solution:** `StaticParams` tells the engine which parameters can be evaluated once and reused across all iterations.

**Syntax:**

```xml
<O T="Repeat" N="RepeatName" StaticParams="[Param1, Param2, Param3, ...]">
  <!-- Repeat content -->
</O>
```

**IMPORTANT:** The StaticParams value MUST be enclosed in square brackets `[]`. Without brackets, it will not work correctly.

```xml
<!-- ❌ WRONG: Missing square brackets -->
<O T="Repeat" StaticParams="Param1,Param2">...</O>

<!-- ✅ CORRECT: With square brackets -->
<O T="Repeat" StaticParams="[Param1,Param2]">...</O>
```

**Example Without StaticParams (Inefficient):**

```xml
<O N="SecPropUniq" T="Repeat" S="0" E="length(SecDimUniq)-1" I="1" CTRL="i" i="0">
  <!-- These are evaluated 100 times even though they don't change: -->
  <P N="GirderRef" V="Girder"/>
  <P N="ReinfPref" V="ReinfDataPref"/>
  <P N="MaterialProps" V="Girder.Material"/>

  <!-- This changes per iteration: -->
  <P N="Dimensions" V="SecDimUniq[i]"/>
  <O T="SectionAnalysis">...</O>
</O>
```

**Example With StaticParams (Optimized):**

```xml
<O N="SecPropUniq" T="Repeat" S="0" E="length(SecDimUniq)-1" I="1" CTRL="i" i="0"
   StaticParams="[Girder, ReinfDataPref, MaterialProps]">
  <!-- These are evaluated ONCE and cached: -->
  <P N="GirderRef" V="Girder"/>
  <P N="ReinfPref" V="ReinfDataPref"/>
  <P N="MaterialProps" V="Girder.Material"/>

  <!-- This still evaluates per iteration: -->
  <P N="Dimensions" V="SecDimUniq[i]"/>
  <O T="SectionAnalysis">...</O>
</O>
```

**Real-World Example:**

```xml
<O T="Repeat" N="StressCheckStations" S="0" E="length(CheckStations)-1" I="1" CTRL="i" i="0"
   StaticParams="[Girder, NonCompCase, CompCase, fy, E, AllowableTension, AllowableCompression]">
  <P N="Station" V="CheckStations[i]"/>

  <!-- Static parameters (constant across all stations): -->
  <P N="Girder" V="@GirderAnalysisResults"/>
  <P N="fy" V="50" D="Steel yield strength"/>
  <P N="E" V="29000" D="Modulus of elasticity"/>

  <!-- Dynamic parameters (vary with station): -->
  <P N="Moment" V="atstation(Station, forceM(Girder, NonCompCase))"/>
  <P N="Stress" V="Moment / SectionModulus"/>
  <P N="Ratio" V="Stress / AllowableCompression"/>
</O>
```

**Performance Impact:**

* Without `StaticParams`: If repeating 100 times with 10 static parameters = 1,000 evaluations
* With `StaticParams`: 10 evaluations (static) + 100 evaluations (dynamic) = 110 evaluations
* **\~90% reduction in redundant calculations**

**Best Practices:**

* Include all parameters that reference parent objects or global constants
* Include material properties, design codes, and analysis settings
* Exclude parameters that use the iteration variable (`i`, `CTRL`)
* Exclude parameters that reference the current iteration's data
* Test with and without to verify performance improvement (significant for large repeats)

### 9. Section Geometry Objects

Section objects define cross-sectional geometry for structural elements. These are used for visualization, analysis, and design calculations.

**Core Section Objects:**

* `Section`: Container for cross-section definition
* `Shape`: Defines a 2D closed polygon within a section
* `Circle`: Defines a circular shape within a section
* `Point`: Vertices of shapes (2D local coordinates)

**Section Object Structure:**

```xml
<O N="SectionName" T="Section" ComputeProp="0">
  <O N="ShapeName" T="Shape" Y="VerticalOffset">
    <O T="Point" Y="y1" X="x1"/>
    <O T="Point" Y="y2" X="x2"/>
    <!-- More points defining the shape boundary -->
  </O>
  <!-- More shapes -->
</O>
```

**Example: I-Girder Section**

```xml
<O N="IGirder" T="Section" ComputeProp="0">
  <!-- Top Flange -->
  <O N="Top Flange" T="Shape" Y="-tft_Input">
    <O T="Point" Y="tft_Input" X="-bft_Input/2"/>
    <O T="Point" Y="tft_Input" X="bft_Input/2"/>
    <O T="Point" Y="0" X="bft_Input/2"/>
    <O T="Point" Y="0" X="-bft_Input/2"/>
  </O>

  <!-- Web -->
  <O N="Web" T="Shape" Y="0">
    <O T="Point" Y="d_Input-tft_Input-tfb_Input" X="-tw_Input/2"/>
    <O T="Point" Y="d_Input-tft_Input-tfb_Input" X="tw_Input/2"/>
    <O T="Point" Y="0" X="tw_Input/2"/>
    <O T="Point" Y="0" X="-tw_Input/2"/>
  </O>

  <!-- Bottom Flange -->
  <O N="Bottom Flange" T="Shape" Y="d_Input-tft_Input-tfb_Input">
    <O T="Point" Y="tfb_Input" X="-bfb_Input/2"/>
    <O T="Point" Y="tfb_Input" X="bfb_Input/2"/>
    <O T="Point" Y="0" X="bfb_Input/2"/>
    <O T="Point" Y="0" X="-bfb_Input/2"/>
  </O>
</O>
```

**Example: Rectangular Section with Circular Void**

```xml
<O N="HollowRectangle" T="Section">
  <!-- Outer rectangle -->
  <O N="Outer" T="Shape">
    <O T="Point" X="-Width/2" Y="-Depth/2"/>
    <O T="Point" X="Width/2" Y="-Depth/2"/>
    <O T="Point" X="Width/2" Y="Depth/2"/>
    <O T="Point" X="-Width/2" Y="Depth/2"/>
  </O>

  <!-- Circular void (subtract from section properties) -->
  <O N="Void" T="Circle" CX="0" CY="0" R="VoidRadius" IsVoid="1"/>
</O>
```

**Circle Object Attributes:**

* `CX`: X-coordinate of center
* `CY`: Y-coordinate of center
* `R`: Radius
* `IsVoid`: If "1", circle is subtracted from section (void/opening)

**ComputeProp Attribute:**

* `ComputeProp="0"`: Section properties are NOT automatically computed (you provide them manually)
* `ComputeProp="1"`: Section properties (area, inertia, etc.) are automatically computed from geometry

**Section with Properties:**

```xml
<O N="StandardBeam" T="Section" ComputeProp="0">
  <!-- Geometry definition -->
  <O N="IShape" T="Shape">...</O>

  <!-- Manually specified properties (when ComputeProp="0") -->
  <P N="Area" V="50.5" UT="Length2"/>
  <P N="Ix" V="4500" UT="Length4"/>
  <P N="Iy" V="250" UT="Length4"/>
  <P N="Sx" V="500" UT="Length3"/>
</O>
```

**Using Sections in Structural Elements:**

```xml
<O N="Girder1" T="Girder">
  <P N="Section" V="@IGirder" T="Section"/>
  <P N="Length" V="120"/>
  <!-- The girder uses the IGirder section definition -->
</O>
```

**Station-Dependent Sections:**

```xml
<P N="Section" V="atstation(x, Station < 50 ? IGirder_Uniform : IGirder_Tapered)"/>
```

### 10. Custom Object Types

Custom object types enable type-safe parameter references and ensure parameters reference objects of the correct type.

**Standard Type Attribute:**

```xml
<P N="Length" V="100" T="Expr"/>
<P N="Name" V="Beam1" T="Text"/>
```

**Custom Object Type:**

```xml
<P N="Girder" V="G1" T="OBPBase_GirderAnalysisResultsRef"/>
<P N="Material" V="A992" T="MaterialSteel"/>
<P N="InsertionPoint" V="IP1" T="OBPInsertionPoint"/>
```

**Type Hierarchy Example:**

```xml
<!-- Base type definition -->
<O N="OBPBase_GirderAnalysisResultsRef" T="Object">
  <P N="TypeName" V="'GirderAnalysisResults'" T="Text"/>
  <!-- Expected properties -->
  <P N="N" V="''" T="Text" D="Name of girder"/>
  <P N="Forces" V="[]" D="Force results array"/>
</O>

<!-- Usage in library object -->
<O N="MyCodeCheck" T="DesignCheck">
  <P N="Girder" V="G1" T="OBPBase_GirderAnalysisResultsRef"/>
  <O T="ParamInfo" Param="@Girder" Required="1" Pick="1"/>

  <!-- Now Girder parameter is type-checked and UI knows to show only
       objects of type OBPBase_GirderAnalysisResultsRef in the picker -->
</O>
```

**Common Custom Types in OpenBrIM:**

* `OBPBase_GirderAnalysisResultsRef`: Reference to girder analysis results
* `OBPInsertionPoint`: Reference to an insertion point object
* `OBPSection`: Reference to a section definition
* `OBPLoadCase`: Reference to a load case
* `OBPCombination`: Reference to a load combination
* `MaterialSteel`: Reference to a steel material object
* `MaterialConcrete`: Reference to a concrete material object

**Benefits of Custom Types:**

* **Type Safety**: Prevents assigning wrong object types to parameters
* **UI Integration**: Picker dialogs filter to show only compatible objects
* **Auto-completion**: IDEs and editors can suggest valid objects
* **Documentation**: Makes code intent clear (what kind of object is expected)
* **Validation**: Runtime checks ensure correct object types

**Example: Type-Safe Design Check**

```xml
<O N="BeamDesignCheck" T="DesignCheck">
  <!-- Type-safe parameter declarations -->
  <P N="Beam" V="B1" T="OBPStructuralBeam"/>
  <P N="LoadCombination" V="Combo1" T="OBPCombination"/>
  <P N="Material" V="A992" T="MaterialSteel"/>
  <P N="Section" V="W36x150" T="OBPSection"/>

  <!-- ParamInfo with type-aware pickers -->
  <O T="ParamInfo" Param="@Beam" Required="1" Pick="1"/>
  <O T="ParamInfo" Param="@LoadCombination" Required="1" Pick="1"/>
  <O T="ParamInfo" Param="@Material" Required="1" Pick="1"/>

  <!-- Calculations using type-safe references -->
  <P N="Fy" V="Material.Fy"/>
  <P N="Sx" V="Section.Sx"/>
  <P N="Mu" V="forceM(Beam.N, LoadCombination.N)"/>
</O>
```

**Creating Custom Types:**

```xml
<!-- Define a new custom type -->
<O N="MyProject_CustomBeamType" T="Object">
  <P N="TypeID" V="'CustomBeam'" T="Text"/>
  <P N="ExpectedProperties" V="['Length', 'Section', 'Material']"/>
</O>

<!-- Use the custom type -->
<P N="SpecialBeam" V="SB1" T="MyProject_CustomBeamType"/>
```

### 11. Required and Pick Flags

The `Required` and `Pick` flags on ParamInfo objects control parameter validation and UI behavior.

**Required Flag:**

```xml
<O T="ParamInfo" Param="@ParameterName" Required="1"/>
```

* `Required="1"`: Parameter MUST have a valid value before object can be used
* UI prevents saving/executing until required parameters are filled
* Combines with ParamGuard: only required when guard condition is true

**Example:**

```xml
<P N="Girder" V="" T="OBPGirder"/>
<O T="ParamInfo" Param="@Girder" Required="1"/>
<!-- User MUST select a girder before this object is valid -->
```

**Pick Flag:**

```xml
<O T="ParamInfo" Param="@ParameterName" Pick="1"/>
```

* `Pick="1"`: Adds a picker button in the UI next to the parameter
* Clicking picker opens object selection dialog
* Dialog is filtered by parameter's Type (if custom type specified)

**Example:**

```xml
<P N="Material" V="A992" T="MaterialSteel"/>
<O T="ParamInfo" Param="@Material" Pick="1"/>
<!-- UI shows a "..." button that opens material picker dialog showing only MaterialSteel objects -->
```

**Combined Usage:**

```xml
<P N="LoadCase" V="" T="OBPLoadCase"/>
<O T="ParamInfo" Param="@LoadCase" Required="1" Pick="1"/>
<!-- User MUST pick a load case (can't leave empty) using the picker dialog -->
```

**Conditional Required:**

```xml
<P N="UseDetailedAnalysis" V="0" Role="Input"/>
<P N="AdvancedSettings" V="" T="OBPSettings"/>
<O T="ParamInfo" Param="@AdvancedSettings"
   Required="1"
   ParamGuard="UseDetailedAnalysis == 1"/>
<!-- AdvancedSettings is only required when UseDetailedAnalysis is enabled -->
```

**List with Required:**

```xml
<P N="Supports" V="[]" T="Text"/>
<O T="ParamInfo" Param="@Supports" List="1" Min="2" Required="1" Pick="1"/>
<!-- User must select at least 2 support objects using picker -->
```

**Best Practices:**

* Always use `Required="1"` for critical parameters (girders, load cases, materials)
* Combine `Required="1"` with `Pick="1"` for object references to guide users
* Use `Required` with `Min` on lists to enforce minimum item count
* Combine with ParamGuard to make parameters conditionally required
* Provide sensible default values when possible (reduces required fields)

**Example: Complete Parameter Configuration**

```xml
<O N="CodeCheckObject" T="DesignCheck">
  <!-- Required object reference with picker -->
  <P N="Girder" V="" T="OBPGirder"/>
  <O T="ParamInfo" Param="@Girder" Required="1" Pick="1"/>

  <!-- Required list with minimum items -->
  <P N="LoadCases" V="[]" T="Text"/>
  <O T="ParamInfo" Param="@LoadCases" List="1" Min="1" Max="20" Required="1" Pick="1"
     ListColumnHeaders="['Load Case']"/>

  <!-- Conditionally required parameter -->
  <P N="DetailedMode" V="0" Role="Input"/>
  <P N="AdditionalFactors" V="1.0"/>
  <O T="ParamInfo" Param="@AdditionalFactors"
     Required="1"
     ParamGuard="DetailedMode == 1"/>

  <!-- Optional parameter with picker (not required) -->
  <P N="AlternateSection" V="" T="OBPSection"/>
  <O T="ParamInfo" Param="@AlternateSection" Pick="1"/>
</O>
```

### 12. Advanced ParamInfo Attributes

Beyond the basic ParamInfo features, OpenBrIM provides advanced attributes for UI optimization, custom interactions, and reference management.

#### 12.1 ExpensiveComputation

Marks parameters as computationally expensive to enable UI performance optimizations.

**Purpose:** When set, the spreadsheet view caches computed values to avoid repeated evaluation of expensive expressions during rendering.

**Syntax:**

```xml
<O T="ParamInfo" Param="@ParameterName" ExpensiveComputation="1"/>
```

**Example:**

```xml
<P N="Volume" V="volume(View3D)" D="Concrete volume" UT="Volume" UC="Geometry"/>
<O T="ParamInfo" Param="@Volume" ReadOnly="1" ExpensiveComputation="1"/>

<P N="BottomSurfaceArea" V="volumesurfareas(View3D)[0]" UT="Area"/>
<O T="ParamInfo" Param="@BottomSurfaceArea" ReadOnly="1" ExpensiveComputation="1"/>

<P N="AllMoments" V="map(StationList, force(Element, LoadCase, 'My', x))"/>
<O T="ParamInfo" Param="@AllMoments" ReadOnly="1" ExpensiveComputation="1"/>
```

**When to use:**

* FEA result extractions (`force()`, `stress()`, `disp()`)
* Geometric calculations (`volume()`, `surfarea()`, `volumesurfareas()`)
* Nested `map()` operations over large datasets
* Complex iterative algorithms
* Any parameter that takes >100ms to compute

**Best Practices:**

* Combine with `ReadOnly="1"` for computed results
* Use for parameters accessed frequently in UI but rarely changed
* Don't overuse—only for genuinely expensive computations

#### 12.2 CustomCellActions

Provides custom context menu actions for spreadsheet cells, enabling specialized editing interfaces.

**Purpose:** Adds custom actions to the right-click context menu in the spreadsheet view for interactive parameter editing.

**Syntax:**

```xml
<O T="ParamInfo" Param="@ParameterName" CustomCellActions="['ActionName1', 'ActionName2']"/>
```

**Available Actions:**

**Stiffness/Matrix Editing:**

* `"6x6Stiffness"` - Edit 6x6 stiffness matrix (for nodes with StiffnessMatrix parameter)
* `"EditStiffness"` - Edit spring stiffness values
* `"EditStiffnessTx"`, `"EditStiffnessTy"`, `"EditStiffnessTz"` - Directional translational stiffness
* `"EditStiffnessRx"`, `"EditStiffnessRy"`, `"EditStiffnessRz"` - Directional rotational stiffness

**Analysis Curves:**

* `"EditMomentCurvature"` - Edit moment-curvature relationship
* `"ResponseSpectrumCurve"` - Edit response spectrum curves
* `"PrestressingDetails"` - Display tendon prestressing details

**CADD Drawing:**

* `"CADPolyDraw"` - Draw polygon in CADD view
* `"CADPolyLineDraw"` - Draw polyline in CADD view
* `"CADRectDraw"` - Draw rectangle in CADD view
* `"CADPointDraw"` - Draw point in CADD view
* `"CADCircleDraw"` - Draw circle in CADD view
* `"CADLineDraw"` - Draw line in CADD view

**Other:**

* `"DuplicateSection"` - Duplicate section from ExtObj
* `"EditPath"` - Edit path points interactively
* `"EditSpanLoc"` - Edit span locations
* `"CentFactor"`, `"WheelFactor"`, `"ImpactFactor"` - Edit load factors

**Example:**

```xml
<!-- 6x6 stiffness matrix editor -->
<P N="stiffness_matrix" V="[]" D="6x6 Stiffness Matrix"/>
<O T="ParamInfo" Param="@stiffness_matrix"
   CustomCellActions="['6x6Stiffness']"
   ParamGuard="bottom_fixity .EQ. 1"/>

<!-- CADD polygon drawing -->
<P N="polygon_coords" V="[]"/>
<O T="ParamInfo" Param="@polygon_coords"
   CustomCellActions="['CADPolyDraw']"
   List="1"/>

<!-- Multiple actions -->
<P N="section_data" V="[[600, Rectangle, Rectangle]]"/>
<O T="ParamInfo" Param="@section_data"
   CustomCellActions="['DuplicateSection', 'EditPath']"/>
```

**Best Practices:**

* Only add actions relevant to the parameter's purpose
* Combine with ParamGuard to show actions contextually
* Use CADD actions for geometric input parameters
* Use stiffness actions for FEA boundary condition parameters

#### 12.3 RefParam

Establishes bidirectional references between objects for automatic dependency tracking.

**Purpose:** When an object is added/removed, automatically updates reference lists in related objects.

**Syntax:**

```xml
<O T="ParamInfo" Param="@ParameterName" RefParam="@TargetListParameter"/>
```

**How it works:**

* When object is created, its name is added to the target list
* When object is deleted, its name is removed from the target list
* Maintains synchronized references across the project

**Example:**

```xml
<!-- In a load case object -->
<O N="MyLoadCase" T="LoadCase">
  <P N="Name" V="LiveLoad" T="Text"/>
  <O T="ParamInfo" Param="@Name" RefParam="@LoadCaseList"/>
  <!-- When this load case is created, "LiveLoad" is added to LoadCaseList
       in related objects that reference load cases -->
</O>

<!-- In a design object that uses load cases -->
<O N="DesignCheck" T="Group">
  <P N="LoadCaseList" V="[]" D="Available load cases"/>
  <!-- Automatically populated as load cases are created/deleted -->
</O>
```

**Use Cases:**

* Maintaining lists of available load cases
* Tracking which supports reference a pier
* Maintaining object inventories
* Automatic dropdown population

**Note:** RefParam creates two-way dependencies. Use carefully in modular library objects.

#### 12.4 ReadOnly (Enhanced)

Makes parameters read-only in the UI while allowing programmatic updates.

**Purpose:** Prevents manual editing of computed values while displaying them to users.

**Syntax:**

```xml
<O T="ParamInfo" Param="@ParameterName" ReadOnly="1"/>
```

**Visual Effect:**

* Text color: Gray (#626262)
* Cell editing: Disabled
* Custom actions: Hidden

**Example:**

```xml
<!-- Computed quantity that shouldn't be edited -->
<P N="TotalWeight" V="Volume * MaterialDensity" UT="Force"/>
<O T="ParamInfo" Param="@TotalWeight" ReadOnly="1" ExpensiveComputation="1"/>

<!-- Result from expensive calculation -->
<P N="MaxStress" V="maxl(map(Stations, stress(Element, LoadCase, x)))" UT="Stress"/>
<O T="ParamInfo" Param="@MaxStress" ReadOnly="1" ExpensiveComputation="1"/>

<!-- Version tracking (readonly) -->
<P N="LibraryVersion" V="3" D="Object version"/>
<O T="ParamInfo" Param="@LibraryVersion" ReadOnly="1"/>
```

**Common Pattern - Readonly Computed Quantities:**

```xml
<P N="Volume" V="volume(View3D)" UT="Volume"/>
<O T="ParamInfo" Param="@Volume" ReadOnly="1" ExpensiveComputation="1"/>

<P N="Weight" V="Volume * MaterialDensity" UT="Force"/>
<O T="ParamInfo" Param="@Weight" ReadOnly="1"/>

<P N="MaterialName" V="Material.N" D="Material (readonly)"/>
<O T="ParamInfo" Param="@MaterialName" ReadOnly="1"/>
```

**Best Practices:**

* Always use for derived/computed values
* Combine with ExpensiveComputation for performance
* Use for displaying object properties (e.g., `Material.N`, `Section.Depth`)
* Don't use for input parameters

### 13. Coordinate Systems (CoorSys)

User-defined coordinate systems for local transformations and FEA boundary conditions.

**Purpose:** Define custom local coordinate systems using origin point and rotation (quaternion or Euler angles).

**Type:** `CoorSys`

**Key Parameters:**

* **X, Y, Z**: Origin coordinates
* **Qx, Qy, Qz, Qw**: Quaternion rotation components
* **Alpha, Beta, Gamma**: Alternative Euler angles (ZYX order)

**Quaternion Representation:**

* Qx, Qy, Qz: Vector part
* Qw: Scalar part
* Identity (no rotation): \[0, 0, 0, 1]

**Syntax:**

```xml
<O N="CoordinateSystemName" T="CoorSys"
   X="x_origin"
   Y="y_origin"
   Z="z_origin"
   Qx="qx_value"
   Qy="qy_value"
   Qz="qz_value"
   Qw="qw_value"/>
```

**Example - Using Quaternions:**

```xml
<!-- Pier coordinate system with rotation about Z-axis -->
<P N="pier_rot" V="45 * PI / 180"/>  <!-- 45 degrees -->
<O N="UCSPIER" T="CoorSys"
   Qx="0"
   Qy="0"
   Qz="sin(pier_rot/2)"
   Qw="cos(pier_rot/2)"
   X="100"
   Y="200"
   Z="0"/>

<!-- 90-degree rotation about X-axis -->
<O N="RotatedCS" T="CoorSys"
   Qx="0.707"  <!-- sin(45°) for 90° rotation -->
   Qy="0"
   Qz="0"
   Qw="0.707"  <!-- cos(45°) -->
   X="0" Y="0" Z="0"/>
```

**Example - Using with Objects:**

```xml
<!-- Define coordinate system -->
<O N="PierCS" T="CoorSys"
   X="alignHX(Alignment, Station, 0)"
   Y="alignHY(Alignment, Station, 0)"
   Z="0"
   Qx="0" Qy="0"
   Qz="sin(SkewAngle/2)"
   Qw="cos(SkewAngle/2)"/>

<!-- Use coordinate system for object positioning -->
<O T="Point" N="ColumnBase"
   X="0" Y="0" Z="bottom_elev"
   CoorSys="@PierCS|CoorSys"/>
<!-- Point position is transformed by PierCS -->
```

**Quaternion Conversion Formulas:**

```
For rotation by angle θ about axis (nx, ny, nz):
Qx = nx * sin(θ/2)
Qy = ny * sin(θ/2)
Qz = nz * sin(θ/2)
Qw = cos(θ/2)

Common rotations:
Z-axis by θ: Qx=0, Qy=0, Qz=sin(θ/2), Qw=cos(θ/2)
Y-axis by θ: Qx=0, Qy=sin(θ/2), Qz=0, Qw=cos(θ/2)
X-axis by θ: Qx=sin(θ/2), Qy=0, Qz=0, Qw=cos(θ/2)
```

**Use Cases:**

* Skewed bridge piers
* Rotated foundations
* Local coordinate systems for boundary conditions
* Transformed geometry placement
* Consistent node positioning

**Best Practices:**

* Use quaternions for single-axis rotations (more intuitive)
* Quaternions avoid gimbal lock issues
* Set origin at logical reference point
* Document rotation axis and angle in description
* Verify coordinate system orientation in 3D view

### 16. Object Attributes for Library Development

#### 16.1 Override Attribute

Marks a group as overrideable by derived objects.

**Purpose:** Allows child objects to override entire groups of parameters when inheriting.

**Syntax:**

```xml
<O N="GroupName" T="Group" Override="1">
  <!-- Parameters that can be overridden -->
</O>
```

**Example:**

```xml
<!-- Base library object with overrideable IFC export settings -->
<O N="BaseColumn" T="Volume">
  <P N="Width" V="12"/>
  <P N="Height" V="12"/>

  <O N="IFCOverrideable" T="Group" Override="1">
    <P N="ifc_type" V="IfcColumn" T="Text"/>
    <P N="ifc_predefined" V="COLUMN" T="Text"/>
    <P N="ifc_parent" V="SUBSTRUCTURE" T="Text"/>
  </O>
</O>

<!-- Derived object overrides IFC settings -->
<O N="PierStem" T="BaseColumn">
  <O N="IFCOverrideable" T="Group" Override="1">
    <P N="ifc_predefined" V="PIERSTEM" T="Text"/>
    <!-- Other IFC parameters inherited -->
  </O>
</O>
```

**Use Cases:**

* IFC export configurations
* Material overrides
* Display settings
* Analysis options

#### 16.2 Opacity Attribute

Controls 3D object transparency.

**Purpose:** Sets opacity for visualization (0.0 = transparent, 1.0 = opaque).

**Syntax:**

```xml
<O T="Volume" N="ObjectName" Opacity="value"/>
```

**Range:** 0.0 to 1.0

**Example:**

```xml
<!-- Semi-transparent hinge visualization -->
<P N="v3d_op" V="iif(gen_top_hinge .EQ. 1 .OR. gen_bot_hinge .EQ. 1, 0.5, 1)"/>
<O N="View3D" T="Volume" Opacity="v3d_op">
  <!-- Geometry -->
</O>

<!-- Fully opaque column -->
<O N="Column" T="Volume" Opacity="1.0">
  <!-- Geometry -->
</O>

<!-- Transparent reference geometry -->
<O N="RefGeometry" T="Volume" Opacity="0.3">
  <!-- Geometry -->
</O>
```

**Opacity Inheritance:**

* Child objects inherit parent opacity unless explicitly set
* `SpecifiedOpacity` and opacity overrides can modify behavior
* Final opacity = min(own opacity, parent opacity, overrides)

**Use Cases:**

* Highlighting active elements
* Showing/hiding secondary geometry
* Construction sequence visualization
* Context geometry display

**Best Practices:**

* Use 1.0 for primary structural elements
* Use 0.3-0.7 for reference geometry
* Use 0.0 to hide (better than Guard for temporary hiding)
* Consider performance impact of many transparent objects

### 13. Library Organization and Template System

OpenBrIM provides a comprehensive system for organizing library objects, workflows, and templates using metadata attributes. These attributes control how objects appear in the library tree view, template screens, and project workflows.

#### 13.1 Core Organization Attributes

**Metadata Attributes:**

* `Tags`: Comma-separated tags for filtering and categorization
* `ObjLabel`: User-friendly display name (appears in UI)
* `Category`: Hierarchical organization path (use `:` separator)
* `Role`: Object role ("WorkFlow", "Template", "Input", etc.)
* `DocumentURL`: Link to online documentation
* `ObjectVersion`: Version number for tracking updates
* `Deprecated`: If "1", marks object as deprecated

#### 13.2 Tags Attribute

Tags enable filtering, categorization, and special behaviors for library objects.

**Syntax:**

```xml
Tags="@tag1,tag2,tag3,..."
```

**Common Tag Categories:**

**Geographic/Standard Tags:**

* `@usastandard`: US design standards (AASHTO, ACI, AISC)
* `@eustandard`: European standards (Eurocode)
* `@aashto`, `@aci`, `@aisc`: Specific code standards

**Bridge Type Tags:**

* `@steelIGirder`: Steel I-girder bridges
* `@precastIGirder`: Precast concrete I-girders
* `@splicedIGirder`: Spliced girder systems
* `@concreteBox`: Concrete box girders

**Functional Tags:**

* `@workflow`: Workflow definition object
* `@workflowtemplate`: Template with workflow structure
* `@release`: Ready for production use
* `@secondlayer`: Secondary-level component

**Special Tags:**

* `@doc:URL`: Embeds documentation link
* `@img:ImageName`: Specifies template image

**Example:**

```xml
<O N="OBPWorkflowGirderPrecastI" T="Project"
   Tags="@usastandard,workflow,release"
   ObjLabel="Precast I Girder Bridge"
   Category="Project Templates:Concrete Bridge Workflows">
  <!-- Workflow content -->
</O>
```

#### 13.3 Role Attribute

The `Role` attribute defines how OpenBrIM treats and displays the object.

**Role Values:**

| Role       | Purpose                  | Behavior                                             |
| ---------- | ------------------------ | ---------------------------------------------------- |
| `WorkFlow` | Workflow definition      | Appears in workflow tree with hierarchical structure |
| `Template` | Project template         | Appears on "Open Project" screen with thumbnail      |
| `Input`    | User input parameter     | Highlighted in parameter list, shows in input forms  |
| `Export`   | Output/result parameter  | Shown in results, available for export               |
| `Private`  | Internal parameter       | Hidden from standard UI views                        |
| `Import`   | Imported/referenced data | Marks data from external sources                     |

**Example: Workflow Object**

```xml
<O N="OBPWorkflowGirderPrecastI" T="Project"
   Role="WorkFlow"
   Tags="@usastandard,workflow,release"
   ObjLabel="Precast I Girder Bridge">

  <O N="WF" T="WorkFlow" Label="Precast I Girder Bridge">
    <O T="Group" Label="Bridge Geometry">
      <O N="W1" T="WorkFlowItem" ObjectType="@Alignment" Label="Roadway Alignment"/>
      <O N="W2" T="WorkFlowItem" ObjectType="@OBPBridge" Label="Bridge Alignment"/>
    </O>
  </O>
</O>
```

**Example: Template Object**

```xml
<O N="OBPTemplateAllTypeSuperstructure" T="Project"
   Role="Template"
   ObjLabel="All-in-One Bridge Workflow"
   Tags="@usastandard,workflowtemplate,release,doc:https://...,img:AllInOneBridgeImg"
   Category="Project Templates::All-in-One Bridge Workflows">
  <!-- Template extends multiple workflows -->
  <O T="Group" Extends="OBPWorkflowGirderSteel::v60"/>
  <O T="Group" Extends="OBPWorkflowGirderPrecastI::v48"/>
</O>
```

#### 13.4 Category Attribute

The `Category` attribute controls how objects and parameters are organized in the UI. **Important:** The behavior differs significantly between object-level and parameter-level usage.

**13.4.1 Object-Level Categories (T="Project" Objects)**

Objects with `T="Project"` support **hierarchical categories** using the `::` separator:

**Syntax:**

```xml
<O T="Project" N="MyObject" Category="Parent::Child::Grandchild">
```

**Example:**

```xml
<O T="Project" N="OBPCADDFoundationPlan"
   Category="Bridge Workflow::CADD">
```

This creates a tree structure in the library browser:

```
Bridge Workflow/
  └── CADD/
       └── OBPCADDFoundationPlan
```

**Multiple Levels:**

```xml
Category="Level1::Level2::Level3"
```

**Common Category Hierarchies:**

**Project Templates:**

```
Project Templates::Concrete Bridge Workflows
Project Templates::Steel Bridge Workflows
Project Templates::All-in-One Bridge Workflows
```

**Generative:**

```
Generative::Modeling
Generative::FEA
Generative::Deliverables
```

**Databases:**

```
Databases::Time Dependent
Databases::Materials
Databases::Sections
```

**Use Cases:**

* Library organization
* Template categorization
* Code check object grouping
* Project structure hierarchy

***

**13.4.2 Parameter-Level Categories (P Elements)**

Parameters support **single-level categories only** - the `::` syntax is **NOT supported**.

**Syntax:**

```xml
<P N="MyParam" Category="CategoryName" />
```

**✅ CORRECT Examples:**

```xml
<P N="DispColumn" Category="Column" />
<P N="Width" Category="Dimensions" />
<P N="Material" Category="Properties" />
<P N="DispStaMarker" Category="Detailing" />
```

**❌ INCORRECT - Will Not Work:**

```xml
<!-- Do NOT use :: in parameter categories -->
<P N="DispColumn" Category="Display Settings::Column" />  ❌
<P N="Width" Category="Geometry::Dimensions" />          ❌
```

**How It Appears in UI:** Parameters are grouped by their Category value in the parameter panel:

```
┌─ Detailing ────────────┐
│ DispStaMarker    [1]   │
│ MarknthDist      1200  │
└────────────────────────┘
┌─ Column ───────────────┐
│ DispColumn       [1]   │
│ DispColumnFtgPile [0]  │
└────────────────────────┘
```

**Use Cases:**

* Grouping input parameters in UI
* Organizing display settings
* Categorizing geometry parameters
* Database field organization

***

**13.4.3 Key Differences**

| Feature            | Object Category            | Parameter Category       |
| ------------------ | -------------------------- | ------------------------ |
| **Syntax**         | `Category="Parent::Child"` | `Category="SingleLevel"` |
| **Hierarchy**      | ✅ Multi-level supported    | ❌ Single level only      |
| **`::` Separator** | ✅ Supported                | ❌ **Not supported**      |
| **UI Location**    | Library browser tree       | Parameter panel groups   |
| **Applies To**     | `<O T="Project">` objects  | `<P>` parameters         |
| **Example**        | `"Bridge Workflow::CADD"`  | `"Detailing"`            |

***

**13.4.4 Common Mistakes**

**Mistake #1: Using `::` in Parameter Categories**

```xml
<!-- WRONG -->
<O N="Display Settings" T="Group">
    <P N="DispColumn" Category="Display Settings::Column" />  ❌
    <P N="DispAbutment" Category="Display Settings::Abutment" /> ❌
</O>

<!-- CORRECT -->
<O N="Display Settings" T="Group">
    <P N="DispColumn" Category="Column" />  ✅
    <P N="DispAbutment" Category="Abutment" /> ✅
</O>
```

**Why:** OpenBrIM/ParamML does not parse `::` in parameter Category attributes. The entire string is treated as a single category name.

**Mistake #2: Confusing Nested Groups with Category Hierarchy**

Nested groups (`<O T="Group">`) provide organizational structure in XML but **do NOT create category hierarchy** for parameters:

```xml
<O N="Display Settings" T="Group">
    <O N="Column Display" T="Group">
        <!-- This does NOT create "Display Settings::Column Display" category -->
        <P N="DispColumn" Category="Column" />
    </O>
</O>
```

Parameters inherit nothing from parent group names - they must specify their own Category.

***

**13.4.5 Best Practices**

**For Objects:**

* Use descriptive hierarchies: `"Domain::Subdomain::Type"`
* Keep depth reasonable (2-4 levels maximum)
* Match existing library structure conventions
* Use `::` (double colon) as the separator

**For Parameters:**

* Use concise, clear category names
* Group related parameters together
* Common categories: "General", "Geometry", "Properties", "Display", "Advanced", "Detailing"
* Coordinate with existing parameter categories in your library
* Do NOT use `::` separator

**Mixed Usage Example:**

```xml
<!-- Object with hierarchical category -->
<O T="Project" N="OBPCADDFoundationPlan"
   Category="Bridge Workflow::CADD">

    <!-- Parameters with single-level categories -->
    <O N="Display Settings" T="Group">
        <P N="DispColumn" Category="Column" />
        <P N="DispAbutment" Category="Abutment" />
        <P N="DispStaMarker" Category="Detailing" />
    </O>
</O>
```

***

**13.4.6 Why the Difference?**

**Technical Reason:**

* Object categories organize the **library structure** (file/folder metaphor)
* Parameter categories organize **UI panels** (flat grouping)
* Different UI contexts require different organizational models

**Design Reason:**

* Parameter panels work best with **flat, scannable groups**
* Deep hierarchies in parameter panels would be cumbersome
* Library browsers benefit from **tree navigation**

***

#### 13.5 WorkFlow and WorkFlowItem Objects

Workflows provide structured, step-by-step guidance for bridge modeling.

**WorkFlow Structure:**

```xml
<O N="WF" T="WorkFlow" Label="Bridge Workflow Name">
  <O T="Group" Label="Section Name">
    <O N="W1" T="WorkFlowItem"
       ObjectType="@ObjectTypeReference"
       Label="User-Friendly Step Name"
       ObjectVersion="12"
       DocumentURL="https://docs.link"/>

    <O N="W2" T="WorkFlowItem" .../>

    <O T="Group" Label="Subsection">
      <O N="W3" T="WorkFlowItem" .../>
    </O>
  </O>
</O>
```

**WorkFlowItem Attributes:**

* `ObjectType`: Reference to the library object type (use `@` prefix)
* `Label`: Display name in workflow tree
* `ObjectVersion`: Minimum required version
* `DocumentURL`: Link to documentation
* `IconStageCons`: If "1", shows construction stage icon

**Complete Workflow Example:**

```xml
<O N="OBPWorkflowGirderPrecastI" T="Project"
   Role="WorkFlow"
   Tags="@usastandard,workflow,release"
   ObjLabel="Precast I Girder Bridge"
   Category="Project Templates:Concrete Bridge Workflows">

  <O N="WF" T="WorkFlow" Label="Precast I Girder Bridge">
    <O T="Group" Label="Bridge Geometry">
      <O N="W1" T="WorkFlowItem"
         ObjectType="@Alignment"
         Label="Roadway Alignment"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/bridge-geometry-pig/roadway-alignment-pig"/>

      <O N="W2" T="WorkFlowItem"
         ObjectType="@OBPBridge"
         Label="Bridge Alignment"
         ObjectVersion="12"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/bridge-geometry-pig/bridge-alignment-pig"/>

      <O N="W3" T="WorkFlowItem"
         ObjectType="@OBPSupportLine"
         Label="Support Lines"
         ObjectVersion="9"/>
    </O>

    <O T="Group" Label="Properties">
      <O N="W6" T="WorkFlowItem"
         ObjectType="@Material"
         Label="Materials"/>

      <O N="W7" T="WorkFlowItem"
         ObjectType="@Section"
         Label="Sections"/>
    </O>

    <O T="Group" Label="Superstructure">
      <O T="Group" Label="Girders">
        <O N="W10" T="WorkFlowItem"
           ObjectType="@OBPGirderPrecastI"
           Label="Precast I Girder"
           ObjectVersion="18"/>
      </O>

      <O T="Group" Label="Deck">
        <O N="W11" T="WorkFlowItem"
           ObjectType="@OBPDeckConcretePrecastIGirder"
           Label="Concrete Deck"
           ObjectVersion="20"/>
      </O>
    </O>

    <O T="Group" Label="Construction">
      <O T="WorkFlowItem"
         ObjectType="@OBPConstructionStage"
         Label="Construction Stage"
         ObjectVersion="6"
         IconStageCons="1"/>
    </O>
  </O>
</O>
```

#### 13.6 Template Objects

Templates appear on the "Open Project" screen and provide pre-configured starting points.

**Template Structure:**

```xml
<O N="TemplateName" T="Project"
   Role="Template"
   ObjLabel="Display Name"
   Tags="@usastandard,workflowtemplate,release,doc:URL,img:ImageName"
   Category="Project Templates::Category Name">

  <!-- Templates typically extend workflows -->
  <O T="Group" Extends="Workflow1::vN">
    <!-- Can override specific parts -->
    <O N="SomeGroup" T="Group" Override="1"/>
  </O>

  <O T="Group" Extends="Workflow2::vM"/>
</O>
```

**Special Tags for Templates:**

* `doc:URL`: Documentation link (e.g., `doc:https://docs.openbrim.com/...`)
* `img:ImageName`: Image identifier for thumbnail (e.g., `img:AllInOneBridgeImg`)

**Example: All-in-One Template**

```xml
<O N="OBPTemplateAllTypeSuperstructure" T="Project"
   Role="Template"
   ObjLabel="All-in-One Bridge Workflow"
   TransAlignRule="Right"
   Tags="@usastandard,workflowtemplate,release,doc:https://docs.openbrim.org/quick-guides/all-in-one-bridge-combination-of-workflows,img:AllInOneBridgeImg"
   Category="Project Templates::All-in-One Bridge Workflows">

  <!-- Includes Steel I Girder workflow -->
  <O T="Group" Extends="OBPWorkflowGirderSteel::v60">
    <!-- Override to remove summary object -->
    <O N="Steel I Girder Workflow Summary Report Objects" T="Group" Override="1"/>
  </O>

  <!-- Includes Precast I Girder workflow -->
  <O T="Group" Extends="OBPWorkflowGirderPrecastI::v48">
    <O N="Precast I Girder Workflow Summary Report Objects" T="Group" Override="1"/>
  </O>

  <!-- Includes Spliced Girder workflow -->
  <O T="Group" Extends="OBPWorkflowGirderSplicedI::v35">
    <O N="Precast I Girder Workflow Summary Report Objects" T="Group" Override="1"/>
  </O>
</O>
```

#### 13.7 Version Management

Track object versions for compatibility and updates.

**ObjectVersion Attribute:**

```xml
<O N="W10" T="WorkFlowItem"
   ObjectType="@OBPGirderPrecastI"
   Label="Precast I Girder"
   ObjectVersion="18"/>
```

**Versioned Object References:**

```xml
<!-- Extends with specific version -->
<O T="Group" Extends="OBPWorkflowGirderSteel::v60"/>

<!-- Latest version reference -->
<O T="Group" Extends="OBPWorkflowGirderSteel"/>
```

**Deprecation:**

```xml
<O N="W75c" T="WorkFlowItem"
   ObjectType="@OBPTemplate_PrestressedIGirderCodeCheck"
   Label="(*deprecated*) Prestressed I Girder Code Check"
   ObjectVersion="4"
   Deprecated="1"/>
```

#### 13.8 Documentation Integration

Link objects to external documentation for user guidance.

**DocumentURL Attribute:**

```xml
<O N="W1" T="WorkFlowItem"
   ObjectType="@Alignment"
   Label="Roadway Alignment"
   DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/bridge-geometry-pig/roadway-alignment-pig"/>
```

**Documentation in Tags:**

```xml
Tags="@usastandard,release,doc:https://docs.openbrim.org/quick-guides/all-in-one-bridge-combination-of-workflows"
```

#### 13.9 Organization Best Practices

**1. Use Consistent Naming:**

```xml
<!-- Good: Clear, descriptive names -->
<O N="OBPGirderPrecastI" ObjLabel="Precast I Girder"/>
<O N="OBPDeckConcretePrecastIGirder" ObjLabel="Concrete Deck"/>

<!-- Avoid: Ambiguous names -->
<O N="Obj1" ObjLabel="Thing"/>
```

**2. Hierarchical Categories:**

```xml
<!-- Good: Logical hierarchy -->
Category="Loading:Static Loads:Surface Loads"

<!-- Good: Progressive detail -->
Category="Code Check Objects:Superstructure Checks:Girder Checks"
```

**3. Appropriate Tags:**

```xml
<!-- Good: Specific, relevant tags -->
Tags="@usastandard,steelIGirder,codecheck,release"

<!-- Avoid: Generic or excessive tags -->
Tags="@generic,stuff,things,misc,other"
```

**4. Documentation Links:**

```xml
<!-- Always provide documentation for user-facing objects -->
<O T="WorkFlowItem"
   ObjectType="@OBPGirderPrecastI"
   Label="Precast I Girder"
   DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/superstructure-pig/girders-pig/precast-i-girder-pig"/>
```

**5. Version Tracking:**

```xml
<!-- Track versions for compatibility -->
<O T="Group" Extends="OBPWorkflowGirderSteel::v60">
  <!-- Explicit version ensures compatibility -->
</O>
```

**6. Template Organization:**

```xml
<!-- Use descriptive labels and categories -->
<O N="Template" T="Project"
   Role="Template"
   ObjLabel="Steel Box Girder Bridge"
   Category="Project Templates::Steel Bridge Workflows"
   Tags="@usastandard,workflowtemplate,release,img:SteelBoxGirderImg">
  <!-- Template content -->
</O>
```

#### 13.10 Complete Organization Example

```xml
<O N="OBPWorkflowGirderPrecastI" T="Project"
   TransAlignRule="Right"
   Tags="@usastandard,workflow,release"
   Role="WorkFlow"
   ObjLabel="Precast I Girder Bridge"
   Category="Project Templates:Concrete Bridge Workflows">

  <!-- Units and enumerations -->
  <O N="Units" T="Group" Extends="Base_DesignSubUnits::v3"/>
  <O N="WFLoadTypeEnums" T="Group" Extends="OBPEnum_LoadType::v3"/>

  <!-- Workflow structure -->
  <O N="WF" T="WorkFlow" Label="Precast I Girder Bridge">
    <O T="Group" Label="Bridge Geometry">
      <O N="W1" T="WorkFlowItem"
         ObjectType="@Alignment"
         Label="Roadway Alignment"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/bridge-geometry-pig/roadway-alignment-pig"/>

      <O N="W2" T="WorkFlowItem"
         ObjectType="@OBPBridge"
         Label="Bridge Alignment"
         ObjectVersion="12"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/bridge-geometry-pig/bridge-alignment-pig"/>
    </O>

    <O T="Group" Label="Properties">
      <O N="W6" T="WorkFlowItem"
         ObjectType="@Material"
         Label="Materials"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/properties-pig/materials-pig"/>

      <O N="W7" T="WorkFlowItem"
         ObjectType="@Section"
         Label="Sections"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/properties-pig/sections-pig"/>
    </O>

    <O T="Group" Label="Superstructure">
      <O T="Group" Label="Girders">
        <O N="W10" T="WorkFlowItem"
           ObjectType="@OBPGirderPrecastI"
           Label="Precast I Girder"
           ObjectVersion="18"
           DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/superstructure-pig/girders-pig/precast-i-girder-pig"/>
      </O>

      <O T="Group" Label="Deck">
        <O N="W11" T="WorkFlowItem"
           ObjectType="@OBPDeckConcretePrecastIGirder"
           Label="Concrete Deck"
           ObjectVersion="20"
           DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/superstructure-pig/deck-pig/concrete-deck-pig"/>
      </O>
    </O>

    <O T="Group" Label="Loading">
      <O T="Group" Label="Static Loads">
        <O N="W57" T="WorkFlowItem"
           ObjectType="@OBPSurfaceLoad2"
           Label="Surface Load"
           ObjectVersion="5"
           DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/loading-pig/loads-pig/static-loads-pig/surface-load-pig"/>
      </O>
    </O>

    <O T="Group" Label="Templates for Code Check and Load Rating">
      <O N="W75f" T="WorkFlowItem"
         ObjectType="@OBPTemplate_ConcreteGirderCodeCheck"
         Label="Concrete Girder Code Check"
         DocumentURL="https://docs.openbrim.org/templates/precast-i-girder-bridge-workflow/templates-for-code-check-and-load-rating-pig/concrete-girder-code-check-t-pig"
         ObjectVersion="8"/>
    </O>
  </O>

  <!-- Object grouping parameters -->
  <P N="ConcreteGirderGroup" V="Concrete Girder Code Check" T="Group"/>

  <!-- IFC schema -->
  <O N="DEFAULT" T="IFCSchema"/>

  <!-- Backwards compatibility -->
  <O N="BackComp" T="Group" Extends="OBPBaseBackwardsCompatibility::v8" Override="1" Scoped="1"/>
</O>
```

#### 13.11 Template Display System

Templates with `Role="Template"` appear on the "Open Project" screen.

**Display Elements:**

* **Thumbnail**: Specified by `img:ImageName` tag
* **Title**: From `ObjLabel` attribute
* **Description**: Generated from category and tags
* **Documentation**: From `doc:URL` tag

**Example Template Card Display:**

```
┌─────────────────────────────┐
│   [Thumbnail Image]         │
│                             │
│ All-in-One Bridge Workflow  │  ← ObjLabel
│                             │
│ Supports steel, precast,    │  ← Generated from
│ and spliced girder bridges  │    tags/content
│                             │
│ [Documentation Link]        │  ← doc: tag
└─────────────────────────────┘
```

**Key Features:**

* Searchable by tags and labels
* Filterable by category
* Clickable documentation links
* Visual preview via thumbnail

#### 13.12 Database Objects

Database objects are special library containers that organize collections of reusable components like sections, materials, or reinforcement patterns. They appear in the library tree under the "Databases" category and provide pre-configured objects that users can select and use in their projects.

**Database Object Characteristics:**

* `Category="Databases:..."`: Places object in Databases category
* `Tags` includes `@database`: Marks as database object
* Contains grouped collections of related objects
* Each item has `Role="Input"` parameters for configuration

**Database Structure:**

```xml
<O N="DatabaseName" T="Project"
   Category="Databases:Database Type"
   ObjLabel="Display Name"
   Tags="@database,usastandard,bridgeTypes,release"
   TransAlignRule="Right">

  <!-- Units definition -->
  <O N="Units" T="Group">
    <O N="Internal" T="Unit" Length="Inch" Force="Kip" Angle="Radian" Temperature="Fahrenheit"/>
  </O>

  <!-- Optional unit system selector -->
  <P N="unitSystem" V="2" D="Unit System[SI=1/Imperial=2]"/>

  <!-- Organized groups of objects -->
  <O N="GroupName" T="Group">
    <O N="Object1" T="Section">
      <!-- Parametric definition -->
    </O>
    <O N="Object2" T="Section">
      <!-- Parametric definition -->
    </O>
  </O>

  <O N="AnotherGroup" T="Group">
    <!-- More objects -->
  </O>
</O>
```

**Common Database Categories:**

| Category                      | Purpose                | Typical Contents                  |
| ----------------------------- | ---------------------- | --------------------------------- |
| `Databases:Section Database`  | Cross-section shapes   | Girders, barriers, columns, piles |
| `Databases:Material Database` | Material properties    | Concrete grades, steel types      |
| `Databases:Rebar Database`    | Reinforcement patterns | Bar sizes, spacing patterns       |
| `Databases:Vehicle Database`  | Load vehicles          | AASHTO trucks, railroad loads     |
| `Databases:Load Database`     | Load definitions       | Wind, seismic, temperature        |

**Example: Barrier Section Database**

```xml
<O N="DBBarrierSections" T="Project"
   TransAlignRule="Right"
   Category="Databases:Section Database"
   ObjLabel="Barrier Sections"
   Tags="@database,usastandard,steelIGirder,precastIGirder,concreteBoxGirder,release">

  <!-- Units -->
  <O N="Units" T="Group">
    <O N="Internal" T="Unit" Length="Inch" Force="Kip" Angle="Radian" Temperature="Fahrenheit"/>
  </O>

  <P N="unitSystem" V="2" D="Unit System[SI=1/Imperial=2]"/>

  <!-- General/Generic sections -->
  <O N="General" T="Group">
    <O N="SingleSlopeRight" T="Section">
      <P N="tw" V="18" D="Top Width" Role="Input" Category="General Shape" UT="Length" UC="Property"/>
      <P N="bw" V="24" D="Bottom Width" Role="Input" Category="General Shape" UT="Length" UC="Property"/>
      <P N="d" V="42" D="Depth" Role="Input" Category="General Shape" UT="Length" UC="Property"/>

      <O N="SingleSlopeRightShape" T="Shape">
        <O T="Point" X="0" Y="-d"/>
        <O T="Point" X="-bw" Y="-d"/>
        <O T="Point" X="-tw" Y="0"/>
        <O T="Point" X="0" Y="0"/>
      </O>
    </O>

    <O N="SingleSlopeLeft" T="Section">
      <P N="tw" V="18" D="Top Width" Role="Input" Category="General Shape" UT="Length" UC="Property"/>
      <P N="bw" V="24" D="Bottom Width" Role="Input" Category="General Shape" UT="Length" UC="Property"/>
      <P N="d" V="42" D="Depth" Role="Input" Category="General Shape" UT="Length" UC="Property"/>

      <O N="SingleSlopeLeftShape" T="Shape">
        <O T="Point" X="0" Y="-d"/>
        <O T="Point" X="bw" Y="-d"/>
        <O T="Point" X="tw" Y="0"/>
        <O T="Point" X="0" Y="0"/>
      </O>
    </O>
  </O>

  <!-- Agency-specific sections -->
  <O N="NYSDOT" T="Group">
    <O N="BD_RC20" T="Section">
      <O T="Shape" Y="0">
        <O T="Point" X="-3" Y="0"/>
        <O T="Point" X="3" Y="0"/>
        <O T="Point" X="8" Y="-19"/>
        <O T="Point" Y="-29" X="15"/>
        <O T="Point" Y="-32" X="15"/>
        <O T="Point" X="3" Y="-32"/>
        <O T="Point" Y="-30"/>
        <O T="Point" Y="-32" X="-3"/>
        <O T="Point" Y="-32" X="-15"/>
        <O T="Point" Y="-29" X="-15"/>
        <O T="Point" Y="-19" X="-8"/>
      </O>
    </O>
  </O>
</O>
```

**Database Organization Patterns:**

**1. By Agency/Standard:**

```xml
<O N="DatabaseName" T="Project">
  <O N="AASHTO" T="Group">
    <!-- AASHTO standard objects -->
  </O>
  <O N="NYSDOT" T="Group">
    <!-- New York DOT objects -->
  </O>
  <O N="CALTRANS" T="Group">
    <!-- California DOT objects -->
  </O>
</O>
```

**2. By Type/Category:**

```xml
<O N="SectionDatabase" T="Project">
  <O N="IBeams" T="Group">
    <!-- I-beam sections -->
  </O>
  <O N="BoxGirders" T="Group">
    <!-- Box girder sections -->
  </O>
  <O N="TBeams" T="Group">
    <!-- T-beam sections -->
  </O>
</O>
```

**3. By Size Range:**

```xml
<O N="RebarDatabase" T="Project">
  <O N="SmallBars" T="Group">
    <!-- #3 through #6 -->
  </O>
  <O N="MediumBars" T="Group">
    <!-- #7 through #9 -->
  </O>
  <O N="LargeBars" T="Group">
    <!-- #10 through #18 -->
  </O>
</O>
```

**Parametric Database Objects:**

Database objects can be parametric, allowing users to configure dimensions:

```xml
<O N="ParametricIBeam" T="Section">
  <!-- Input parameters with Role="Input" -->
  <P N="depth" V="36" D="Beam Depth" Role="Input" Category="Dimensions" UT="Length" UC="Property"/>
  <P N="topFlangeWidth" V="12" D="Top Flange Width" Role="Input" Category="Dimensions" UT="Length" UC="Property"/>
  <P N="botFlangeWidth" V="12" D="Bottom Flange Width" Role="Input" Category="Dimensions" UT="Length" UC="Property"/>
  <P N="webThickness" V="0.5" D="Web Thickness" Role="Input" Category="Dimensions" UT="Length" UC="Property"/>
  <P N="flangeThickness" V="1.0" D="Flange Thickness" Role="Input" Category="Dimensions" UT="Length" UC="Property"/>

  <!-- ParamInfo for UI behavior -->
  <O T="ParamInfo" Param="@depth" Required="1"/>
  <O T="ParamInfo" Param="@topFlangeWidth" Required="1"/>
  <O T="ParamInfo" Param="@botFlangeWidth" Required="1"/>

  <!-- Computed parameters -->
  <P N="area" V="topFlangeWidth*flangeThickness + webThickness*(depth-2*flangeThickness) + botFlangeWidth*flangeThickness"
     D="Cross-sectional area" UT="Area" UC="Property"/>

  <!-- Geometry definition -->
  <O N="IBeamShape" T="Shape">
    <!-- Points using parametric dimensions -->
    <O T="Point" X="-topFlangeWidth/2" Y="0"/>
    <O T="Point" X="topFlangeWidth/2" Y="0"/>
    <O T="Point" X="topFlangeWidth/2" Y="-flangeThickness"/>
    <O T="Point" X="webThickness/2" Y="-flangeThickness"/>
    <O T="Point" X="webThickness/2" Y="-(depth-flangeThickness)"/>
    <O T="Point" X="botFlangeWidth/2" Y="-(depth-flangeThickness)"/>
    <O T="Point" X="botFlangeWidth/2" Y="-depth"/>
    <O T="Point" X="-botFlangeWidth/2" Y="-depth"/>
    <O T="Point" X="-botFlangeWidth/2" Y="-(depth-flangeThickness)"/>
    <O T="Point" X="-webThickness/2" Y="-(depth-flangeThickness)"/>
    <O T="Point" X="-webThickness/2" Y="-flangeThickness"/>
    <O T="Point" X="-topFlangeWidth/2" Y="-flangeThickness"/>
  </O>
</O>
```

**Fixed Database Objects:**

For standard, non-parametric objects (like agency-specific standards):

```xml
<O N="AASHTO_TypeIV" T="Section">
  <!-- No Role="Input" parameters - fixed dimensions -->
  <P N="StandardDesignation" V="AASHTO Type IV"/>
  <P N="depth" V="54"/>
  <P N="topFlangeWidth" V="26"/>
  <P N="botFlangeWidth" V="26"/>

  <O N="TypeIV_Shape" T="Shape">
    <!-- Fixed coordinates -->
    <O T="Point" X="-13" Y="0"/>
    <O T="Point" X="13" Y="0"/>
    <!-- ... more points ... -->
  </O>
</O>
```

**Database Object Usage:**

Users access database objects in two ways:

**1. Direct Reference:**

```xml
<!-- Reference a specific database object -->
<P N="BarrierSection" V="@DBBarrierSections.NYSDOT.BD_RC20|Section"/>
```

**2. Object Picker UI:**

```xml
<!-- User selects from database via UI picker -->
<P N="BarrierSection" V="" T="Section"/>
<O T="ParamInfo" Param="@BarrierSection" Required="1" Pick="1"/>
<!-- UI shows database tree for selection -->
```

**Best Practices for Database Objects:**

**1. Organization:**

```xml
<!-- Good: Logical hierarchy -->
<O N="General" T="Group">          <!-- Generic/customizable -->
<O N="AASHTO" T="Group">           <!-- By standard -->
<O N="AgencySpecific" T="Group">   <!-- By agency -->
```

**2. Naming Conventions:**

```xml
<!-- Good: Clear, standard names -->
<O N="AASHTO_TypeIV" T="Section"/>
<O N="W36x150" T="Section"/>
<O N="SingleSlopeBarrier" T="Section"/>

<!-- Avoid: Ambiguous names -->
<O N="Section1" T="Section"/>
<O N="Thing" T="Section"/>
```

**3. Documentation:**

```xml
<!-- Include descriptions for parameters -->
<P N="depth" V="54" D="Girder depth from top to bottom" Role="Input"/>

<!-- Reference standards -->
<P N="StandardRef" V="AASHTO LRFD Bridge Design Specifications, 9th Edition"/>
```

**4. Units:**

```xml
<!-- Always define internal units -->
<O N="Units" T="Group">
  <O N="Internal" T="Unit" Length="Inch" Force="Kip" Angle="Radian" Temperature="Fahrenheit"/>
</O>

<!-- Use unit-aware parameters -->
<P N="depth" V="36" UT="Length" UC="Property"/>
```

**5. Tags:**

```xml
<!-- Include relevant bridge type tags -->
Tags="@database,usastandard,steelIGirder,precastIGirder,concreteBoxGirder,release"
```

**Database Object Categories:**

**Section Databases:**

```xml
Category="Databases:Section Database"
<!-- Contains: Girders, columns, piles, barriers, abutments -->
```

**Material Databases:**

```xml
Category="Databases:Material Database"
<!-- Contains: Concrete grades, steel types, soil properties -->
```

**Reinforcement Databases:**

```xml
Category="Databases:Rebar Database"
<!-- Contains: Bar sizes, strand types, reinforcement patterns -->
```

**Load Databases:**

```xml
Category="Databases:Vehicle Database"
<!-- Contains: AASHTO trucks, permit vehicles, railroad loads -->

Category="Databases:Load Database"
<!-- Contains: Wind profiles, seismic spectra, temperature curves -->
```

**Example: Material Database**

```xml
<O N="DBConcreteMaterials" T="Project"
   Category="Databases:Material Database"
   ObjLabel="Concrete Materials"
   Tags="@database,usastandard,release">

  <O N="Units" T="Group">
    <O N="Internal" T="Unit" Length="Inch" Force="Kip" Angle="Radian" Temperature="Fahrenheit"/>
  </O>

  <O N="AASHTO" T="Group">
    <O N="Concrete_3ksi" T="Material">
      <P N="fc" V="3" D="Compressive Strength" Role="Input" UT="Stress" UC="Property"/>
      <P N="E" V="3320" D="Elastic Modulus" UT="Stress" UC="Property"/>
      <P N="nu" V="0.2" D="Poisson's Ratio"/>
      <P N="density" V="0.15" D="Unit Weight" UT="Density" UC="Property"/>
    </O>

    <O N="Concrete_4ksi" T="Material">
      <P N="fc" V="4" D="Compressive Strength" Role="Input" UT="Stress" UC="Property"/>
      <P N="E" V="3834" D="Elastic Modulus" UT="Stress" UC="Property"/>
      <P N="nu" V="0.2" D="Poisson's Ratio"/>
      <P N="density" V="0.15" D="Unit Weight" UT="Density" UC="Property"/>
    </O>

    <O N="Concrete_5ksi" T="Material">
      <P N="fc" V="5" D="Compressive Strength" Role="Input" UT="Stress" UC="Property"/>
      <P N="E" V="4287" D="Elastic Modulus" UT="Stress" UC="Property"/>
      <P N="nu" V="0.2" D="Poisson's Ratio"/>
      <P N="density" V="0.15" D="Unit Weight" UT="Density" UC="Property"/>
    </O>
  </O>
</O>
```

**Database Integration with Projects:**

Projects reference database objects for consistent, standardized components:

```xml
<O N="BridgeProject" T="Project">
  <!-- Reference barrier section from database -->
  <P N="LeftBarrierSection" V="@DBBarrierSections.NYSDOT.BD_RC20|Section"/>
  <P N="RightBarrierSection" V="@DBBarrierSections.General.SingleSlopeRight|Section"/>

  <!-- Reference materials from database -->
  <P N="DeckConcrete" V="@DBConcreteMaterials.AASHTO.Concrete_4ksi|Material"/>
  <P N="GirderConcrete" V="@DBConcreteMaterials.AASHTO.Concrete_5ksi|Material"/>

  <!-- Use in bridge components -->
  <O N="Barrier1" T="OBPBarrierCustom">
    <P N="Section" V="LeftBarrierSection"/>
  </O>

  <O N="Deck1" T="OBPDeckConcrete">
    <P N="Material" V="DeckConcrete"/>
  </O>
</O>
```

**Summary:**

Database objects provide:

* **Centralized libraries** of standard components
* **Reusable templates** for common elements
* **Agency standards** compliance
* **Parametric flexibility** for customization
* **Consistent organization** across projects
* **Easy selection** via UI pickers

Key attributes:

* `Category="Databases:Type"`
* `Tags` includes `@database`
* Organized in hierarchical groups
* Parameters marked with `Role="Input"` for user configuration
* Complete units and metadata definitions

## Summary

The OpenBrIM parametric engine provides a powerful XML-based system for creating reusable, parametric bridge components. Key principles:

* **Objects** form hierarchical structures with names and types
* **Parameters** store values and expressions that define object behavior
* **Expressions** create parametric relationships between objects and parameters
* **Repeat** objects enable arrays and iterations for creating multiple instances (use ONLY for objects, NOT for parameter loops)
* **map(), filter(), reduce()** for all parameter transformations (10-100x faster than Repeat)
* **ParamInfo** provides rich metadata for parameter UI, validation, and behavior
  * Advanced features: ExpensiveComputation, CustomCellActions, RefParam, ReadOnly
* **Guards** control conditional object inclusion (Guard) and parameter visibility (ParamGuard)
* **Metadata attributes** (Tags, ObjLabel, Category) organize library components
* **Extends** enables template-based inheritance with versioning
* **Custom types** provide type-safe object references
* **Section objects** define cross-sectional geometry for structural analysis
* **FEA nodes** support MergeNearest, MergeSameLoc, StiffnessMatrix for advanced mesh control
* **FEA elements** support IsRigid, BetaAngle, CastingDay, and node releases for connection modeling
* **CoorSys** defines user coordinate systems with quaternions for local transformations
* **Override** and **Opacity** attributes for library flexibility and visualization
* **Performance features** like StaticParams and ExpensiveComputation optimize large-scale parametric models
* **Concise XML** should be preferred when metadata isn't required
* **Inheritance** is achieved by using an object's name as the Type of a new object, allowing you to create variations by overriding specific parameters

By following this guide, AI agents can create sophisticated parametric bridge models that are flexible, reusable, and maintainable.
