# ParamML Functions Reference

## Overview

ParamML provides a comprehensive set of built-in functions that can be used within expressions to perform calculations, manipulate geometry, convert units, and query parametric models. This guide documents all available functions for AI agents creating ParamML expressions.

**Key Concepts:**

* Functions are called within ParamML expressions using standard syntax: `functionName(arg1, arg2, ... )`
* Functions are implemented in the `ExprProvFunctionCall` method ([Param.ts:655](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/PML/Param.ts#L655))
* Some functions are context-dependent (require specific modules like FEA, SEC, or OpenBrIM to be loaded)
* All functions are case-sensitive

**ParamML Operators:** ParamML uses standard JavaScript-like operators for expressions:

* **Comparison Operators:** `<`, `>`, `<=`, `>=`, `==`, `!=`
* **Logical Operators:** `&&` (AND), `||` (OR), `!` (NOT)
* **Arithmetic Operators:** `+`, `-`, `*`, `/`, `%`, `^` (power)
* **Ternary Operator:** `condition ? value1 : value2`
* **Unary Operators:** `-` (negation), `!` (logical NOT), `+` (positive)

**Example:**

```xml
<P N="IsValid" V="Width > 0 && Height > 0 ? 1 : 0"/>
<P N="NeedsReinforcement" V="Stress >= AllowableStress || Depth < MinDepth"/>
<P N="Power" V="Base ^ Exponent"/>
```

**Function Categories:**

1. [Array/List Operations](#arraylist-operations)
2. [Geometric Transformations](#geometric-transformations)
3. [Line/Curve Operations](#linecurve-operations)
4. [Surface/Volume Operations](#surfacevolume-operations)
5. [Unit Conversion](#unit-conversion)
6. [Advanced Geometry](#advanced-geometry)
7. [Mesh Generation](#mesh-generation)
8. [Object/Point Functions](#objectpoint-functions)
9. [Value/Expression Functions](#valueexpression-functions)
10. [String Manipulation](#string-manipulation)
11. [Functional Programming & Advanced Operations](#functional-programming--advanced-operations)
12. [External Module Functions](#external-module-functions)

***

## Array/List Operations

### `length(list)`

Returns the number of elements in an array or list.

**Parameters:**

* `list` (Array): The array to measure

**Returns:** Number - The count of elements

**Example:**

```xml
<P N="Count" V="length(Points)"/>
<!-- If Points has 5 elements, Count = 5 -->
```

**Related:** `first()`, `last()`

***

### `parent(obj)`

Returns the parent object of the given object in the hierarchical tree.

**Parameters:**

* `obj` (Object): The object whose parent to retrieve

**Returns:** Object - The parent object

**Example:**

```xml
<P N="ParentName" V="parent(self).Name"/>
```

***

### `project()`

Returns the root project object (top of the object hierarchy).

**Parameters:** None

**Returns:** Object - The root project object

**Example:**

```xml
<P N="ProjectName" V="project().Name"/>
```

***

### `getlistitem(list, index)` / `listitem(list, index)`

Accesses an element at a specific index in a list. Supports multi-dimensional indexing.

**Parameters:**

* `list` (Array): The array to access
* `index` (Number or multiple Numbers): The index/indices to retrieve

**Returns:** Any - The element at the specified index

**Example:**

```xml
<P N="FirstPoint" V="getlistitem(Points, 0)"/>
<P N="SecondPoint" V="listitem(Points, 1)"/>
<!-- Multi-dimensional: -->
<P N="Element" V="listitem(Matrix, 0, 2)"/>
```

**Related:** `first()`, `last()`

***

### `last(list)`

Returns the last element of an array.

**Parameters:**

* `list` (Array): The array to query

**Returns:** Any - The last element

**Example:**

```xml
<P N="LastStation" V="last(Stations)"/>
```

**Related:** `first()`, `length()`

***

### `first(list)`

Returns the first element of an array.

**Parameters:**

* `list` (Array): The array to query

**Returns:** Any - The first element

**Example:**

```xml
<P N="StartPoint" V="first(Points)"/>
```

**Related:** `last()`, `length()`

***

### `list(args...)`

Creates a new list from the provided arguments.

**Parameters:**

* `args...` (Any): Variable number of arguments to combine into a list

**Returns:** Array - A new list containing all arguments

**Example:**

```xml
<P N="MyList" V="list(1, 2, 3, 4, 5)"/>
<P N="Points" V="list(Pt1, Pt2, Pt3)"/>
```

***

### `sum(list, startIndex?, endIndex?)`

Calculates the sum of numeric elements in an array.

**Parameters:**

* `list` (Array): The array of numbers to sum
* `startIndex` (Number, optional): Starting index (default: 0)
* `endIndex` (Number, optional): Ending index (default: array length)

**Returns:** Number - The sum of elements

**Example:**

```xml
<P N="TotalLength" V="sum(SpanLengths)"/>
<P N="PartialSum" V="sum(Values, 2, 5)"/>
```

**Related:** `length()`

***

### `mergel(listOfLists)`

Merges nested lists into a single flat list.

**Parameters:**

* `listOfLists` (Array of Arrays): Nested array structure

**Returns:** Array - Flattened array

**Example:**

```xml
<P N="AllPoints" V="mergel(PointGroups)"/>
<!-- If PointGroups = [[P1,P2], [P3,P4]], result = [P1,P2,P3,P4] -->
```

**Related:** `concat()`

***

### `concat(list1, list2, ...)`

Concatenates multiple arrays into a single array. Can accept any number of arrays (not limited to two).

**Parameters:**

* `list1, list2, ...` (Arrays): Arrays to concatenate

**Returns:** Array - Combined array containing all elements in order

**Example:**

```xml
<P N="AllStations" V="concat(StartStations, MidStations, EndStations)"/>

<!-- Multiple arrays example -->
<O N="ConcatFunction" T="Group">
    <P N="list1" V="[1,2,3,4]" />
    <P N="list2" V="[3,4]" />
    <P N="list3" V="[5,6]" />
    <P N="concatParams1" V="concat(list1,list2,list3)" />
    <!-- concatParams1 = [1,2,3,4,3,4,5,6] -->
    <!-- The concat function can utilize multiple lists (or arrays); it is not strictly limited to just two -->
    <P N="concatParams2" V="concat(concat(list1,list2),list3)" />
    <!-- concatParams2 = [1,2,3,4,3,4,5,6] (same result) -->
</O>
```

**Notes:**

* Accepts unlimited number of array arguments
* Elements appear in order of arrays provided
* Duplicate values are preserved (not removed)

**Related:** `mergel()`

***

### `refine(list, refinement)`

Refines a list by interpolating additional points between existing elements. **Works only on simple number lists, not on point/coordinate lists.**

**Parameters:**

* `list` (Array of Numbers): The list to refine (must be simple number array, not point array)
* `refinement` (Number): Maximum spacing between refined values

**Returns:** Array - Refined list with interpolated values

**Example:**

```xml
<P N="RefinedPoints" V="refine(Points, 2)"/>
<!-- Detailed example -->
<O T="Group">
    <!-- ✅ CORRECT: Works with simple number list -->
    <P N="list1" V="[10,20,90,100]" />
    <P N="refine1" V="refine(list1,30)" />
    <!-- refine1 = [10,20,43.33,66.66,90,100] -->

    <!-- ❌ WRONG: Cannot refine point lists directly -->
    <P N="list2" V="[[0,0,0],[10,10,10],[90,90,90],[100,100,100]]" />
    <P N="refine2" V="refine(list2,30)" />
    <!-- refine2 = [[0,0,0],[10,10,10],[90,90,90],[100,100,100]] (unchanged) -->

    <!-- ✅ WORKAROUND: To refine point lists -->
    <P N="line1" V="[[10,0,0],[20,0,0],[90,0,0],[100,0,0]]" />
    <!-- Step 1: Extract X locations from points -->
    <P N="line1_xloc" V="map(line1,x[0])" />
    <!-- line1_xloc = [10,20,90,100] -->

    <!-- Step 2: Refine the X location list -->
    <P N="line1_xloc_refined" V="refine(line1_xloc,30)" />
    <!-- line1_xloc_refined = [10,20,43.33,66.66,90,100] -->

    <!-- Step 3: Use onlinex() to get refined points on line -->
    <P N="line1_locs_refined" V="map(line1_xloc_refined,onlinex(line1,x))" />
    <!-- line1_locs_refined = [[10,0,0],[20,0,0],[43.33,0,0],[66.66,0,0],[90,0,0],[100,0,0]] -->
</O>
```

**Notes:**

* **Important:** `refine()` only works on simple number arrays, not point/coordinate arrays
* For point lists, extract coordinates, refine them, then reconstruct points using `onlinex()` or similar
* Refinement value represents maximum spacing between output values

**Related:** `onlinex()`, `map()`

***

### `slice(list, start, end)`

Extracts a portion of an array from start to end index.

**Parameters:**

* `list` (Array): The source array
* `start` (Number): Starting index (inclusive)
* `end` (Number): Ending index (exclusive)

**Returns:** Array - Sliced portion of the array

**Example:**

```xml
<P N="MiddlePoints" V="slice(AllPoints, 2, 5)"/>
<!-- Extracts elements at indices 2, 3, 4 -->
```

***

## Geometric Transformations

### `translate(point, tx, ty, tz)`

Translates a point by the specified offset values.

**Parameters:**

* `point` (Point or Array): The point to translate
* `tx` (Number): Translation in X direction
* `ty` (Number): Translation in Y direction
* `tz` (Number): Translation in Z direction

**Returns:** Point - The translated point

**Example:**

```xml
<P N="ShiftedPoint" V="translate(OriginalPoint, 10, 0, 5)"/>
```

**Related:** `rotate()`

***

### `rotate(point, rx, ry, rz, origin?)`

Rotates a point (or array of points \[x,y,z]) around specified axes.

**Parameters:**

* `point` (Point or Array): The point(s) to rotate
* `rx` (Number): Rotation around X axis (degrees)
* `ry` (Number): Rotation around Y axis (degrees)
* `rz` (Number): Rotation around Z axis (degrees)
* `origin` (Point, optional): Origin point for rotation (default: \[0,0,0])

**Returns:** Point or Array - The rotated point(s)

**Example:**

```xml
<P N="RotatedPoint" V="rotate(Point, 0, 0, 45)"/>
<!-- Rotate 45 degrees around Z axis -->
<P N="RotatedAboutOrigin" V="rotate(Point, 30, 0, 0, CenterPoint)"/>
```

**Related:** `translate()`

***

## Line/Curve Operations

### `online(line, x, y)`

Returns a point on a line at specified local coordinates.

**Parameters:**

* `line` (Line3D): The line object
* `x` (Number): Local X coordinate along the line
* `y` (Number): Local Y coordinate (offset perpendicular to line)

**Returns:** Point - Point on the line

**Example:**

```xml
<O T="Point" N="MidPoint" X="online(CenterLine, 50, 0).X" Y="online(CenterLine, 50, 0).Y"/>
```

**Related:** `onlineg()`, `onliner()`, `onlinea()`

***

### `onlineg(line, x, y)`

Returns a point on a line in global coordinates.

**Parameters:**

* `line` (Line3D): The line object
* `x` (Number): Global X coordinate
* `y` (Number): Global Y coordinate

**Returns:** Point - Point on the line

**Example:**

```xml
<P N="GlobalPoint" V="onlineg(Baseline, 100, 50)"/>
```

**Related:** `online()`, `toglobal()`

***

### `onliner(line, n)`

Returns a point on a line at a relative position (0 to 1).

**Parameters:**

* `line` (Line3D): The line object
* `n` (Number): Relative position (0 = start, 1 = end, 0.5 = midpoint)

**Returns:** Point - Point on the line

**Example:**

```xml
<P N="QuarterPoint" V="onliner(Beam, 0.25)"/>
<P N="MidPoint" V="onliner(Beam, 0.5)"/>
```

**Related:** `onlinea()`, `online()`

***

### `onlinea(line, n)`

Returns a point on a line at an absolute distance from the start.

**Parameters:**

* `line` (Line3D): The line object
* `n` (Number): Absolute distance from start

**Returns:** Point - Point on the line

**Example:**

```xml
<P N="PointAt10ft" V="onlinea(Girder, 10)"/>
```

**Related:** `onliner()`, `linel()`

***

### `onlinerel(line, n)`

Returns a point on a line at a relative distance in the line's local direction.

**Parameters:**

* `line` (Line3D): The line object
* `n` (Number): Relative distance

**Returns:** Point - Point on the line

**Example:**

```xml
<P N="RelPoint" V="onlinerel(Edge, 0.3)"/>
```

**Related:** `onliner()`, `onlinea()`

***

### `onlinex(line, n)`

Returns a point on a line at a specific X coordinate.

**Parameters:**

* `line` (Line3D): The line object
* `n` (Number): X coordinate value

**Returns:** Point - Point on the line at the specified X

**Example:**

```xml
<P N="AtX100" V="onlinex(Baseline, 100)"/>
```

**Related:** `onliney()`, `onlinez()`

***

### `onliney(line, n)`

Returns a point on a line at a specific Y coordinate.

**Parameters:**

* `line` (Line3D): The line object
* `n` (Number): Y coordinate value

**Returns:** Point - Point on the line at the specified Y

**Example:**

```xml
<P N="AtY50" V="onliney(Baseline, 50)"/>
```

**Related:** `onlinex()`, `onlinez()`

***

### `onlinez(line, n)`

Returns a point on a line at a specific Z coordinate (elevation).

**Parameters:**

* `line` (Line3D): The line object
* `n` (Number): Z coordinate value

**Returns:** Point - Point on the line at the specified Z

**Example:**

```xml
<P N="AtElevation" V="onlinez(Profile, 120)"/>
```

**Related:** `onlinex()`, `onliney()`

***

### `oncircle(radius, x, y?, direction?)`

Returns a point on a circle at specified parameters.

**Parameters:**

* `radius` (Number): Circle radius
* `x` (Number): Angle in degrees or arc length
* `y` (Number, optional): Offset from circle (default: 0)
* `direction` (Number, optional): Direction modifier (default: 1)

**Returns:** Point - Point on the circle

**Example:**

```xml
<P N="CirclePoint" V="oncircle(10, 45)"/>
<!-- Point at 45 degrees on a circle of radius 10 -->
```

***

### `linel(line)`

Returns the length of a line.

**Parameters:**

* `line` (Line3D): The line object

**Returns:** Number - Length of the line

**Example:**

```xml
<P N="BeamLength" V="linel(Centerline)"/>
```

**Related:** `perimeter()`, `surfarea()`

***

### `closestPointOnLine(line, point)`

Finds the closest point on a line to a given point (projection).

**Parameters:**

* `line` (Line3D): The line object
* `point` (Point): The reference point

**Returns:** Point - Closest point on the line

**Example:**

```xml
<P N="Projection" V="closestPointOnLine(Edge, TargetPoint)"/>
```

**Related:** `intersect()`

***

### `closestLineIndex(lines, line)`

Finds the index of the closest line in a collection to a given line.

**Parameters:**

* `lines` (Array of Line3D): Collection of lines
* `line` (Line3D): Reference line

**Returns:** Number - Index of the closest line

**Example:**

```xml
<P N="NearestIndex" V="closestLineIndex(AllEdges, TargetEdge)"/>
```

***

### `toglobal(line)`

Converts a line from local to global coordinates.

**Parameters:**

* `line` (Line3D): The line in local coordinates

**Returns:** Line3D - Line in global coordinates

**Example:**

```xml
<P N="GlobalLine" V="toglobal(LocalLine)"/>
```

**Related:** `onlineg()`

***

### `nonlinearpoints(points)`

Removes collinear points from a point list, keeping only points that create non-linear segments.

**Parameters:**

* `points` (Array of Point): List of points

**Returns:** Array of Point - Filtered list with collinear points removed

**Example:**

```xml
<P N="SimplifiedPoints" V="nonlinearpoints(AllPoints)"/>
```

***

### `linesplit(line, breakIndex)`

Splits a line at a specified index into two lines.

**Parameters:**

* `line` (Line3D): The line to split
* `breakIndex` (Number): Index at which to split

**Returns:** Array - Two lines \[line1, line2]

**Example:**

```xml
<P N="SplitLines" V="linesplit(OriginalLine, 3)"/>
```

***

### `intersect(line1, line2, plane?, rayMode?)`

Finds the intersection point between two lines.

**Parameters:**

* `line1` (Line3D): First line
* `line2` (Line3D): Second line
* `plane` (String, optional): Plane for 2D intersection ("XY", "XZ", "YZ")
* `rayMode` (Boolean, optional): If true, extends lines as rays

**Returns:** Point - Intersection point, or null if no intersection

**Example:**

```xml
<P N="CrossPoint" V="intersect(LineA, LineB, 'XY')"/>
```

**Related:** `intersectalong()`, `polygonLineIntersect()`

***

### `intersectalong(line1, line2, extLen?, plane?)`

Finds intersection between two lines with optional extension length.

**Parameters:**

* `line1` (Line3D): First line
* `line2` (Line3D): Second line
* `extLen` (Number, optional): Extension length for lines
* `plane` (String, optional): Intersection plane

**Returns:** Point - Intersection point

**Example:**

```xml
<P N="ExtendedIntersection" V="intersectalong(Edge1, Edge2, 5, 'XY')"/>
```

**Related:** `intersect()`

***

### `polygonLineIntersect(polygon, line, mode?)`

Finds intersection points between a polygon and a line.

**Parameters:**

* `polygon` (Surface3D): The polygon
* `line` (Line3D): The line
* `mode` (Number, optional): Intersection mode

**Returns:** Array of Point - Intersection points

**Example:**

```xml
<P N="CutPoints" V="polygonLineIntersect(Slab, CutLine)"/>
```

**Related:** `intersect()`

***

## Surface/Volume Operations

### `surfarea(surface)`

Calculates the area of a surface.

**Parameters:**

* `surface` (Surface3D): The surface object

**Returns:** Number - Surface area

**Example:**

```xml
<P N="DeckArea" V="surfarea(DeckSurface)"/>
```

**Related:** `volume()`, `perimeter()`

***

### `volumesurfareas(volume)`

Returns an array of areas for all surfaces of a volume.

**Parameters:**

* `volume` (Volume): The volume object

**Returns:** Array of Numbers - Areas of each surface

**Example:**

```xml
<P N="FaceAreas" V="volumesurfareas(BeamVolume)"/>
<P N="TopArea" V="volumesurfareas(BeamVolume)[0]"/>
```

**Related:** `volumesurfperimeters()`, `volume()`

***

### `volumesurfperimeters(volume)`

Returns an array of perimeters for all surfaces of a volume.

**Parameters:**

* `volume` (Volume): The volume object

**Returns:** Array of Numbers - Perimeters of each surface

**Example:**

```xml
<P N="EdgeLengths" V="volumesurfperimeters(Column)"/>
```

**Related:** `volumesurfareas()`, `perimeter()`

***

### `volumesideareas(volume, side)`

Returns the area of a specific side of a volume.

**Parameters:**

* `volume` (Volume): The volume object
* `side` (Number or String): Side identifier

**Returns:** Number - Area of the specified side

**Example:**

```xml
<P N="TopSurfaceArea" V="volumesideareas(Pier, 'top')"/>
```

**Related:** `volumesurfareas()`

***

### `volumesurfdims(volume, algorithm?, side?)`

Returns dimensions of volume surfaces (width, height, etc.).

**Parameters:**

* `volume` (Volume): The volume object
* `algorithm` (Number, optional): Algorithm type for dimension calculation
* `side` (Number, optional): Specific side index

**Returns:** Object or Array - Surface dimensions

**Example:**

```xml
<P N="Dimensions" V="volumesurfdims(Beam)"/>
<P N="Width" V="volumesurfdims(Beam).Width"/>
```

**Related:** `volumesurfareas()`

***

### `volume(volume)`

Calculates the volume of a 3D solid.

**Parameters:**

* `volume` (Volume): The volume object

**Returns:** Number - Volume value

**Example:**

```xml
<P N="ConcreteVolume" V="volume(PierVolume)"/>
```

**Related:** `surfarea()`

***

### `volumeextvectorlength(volume, mode?)`

Returns the length of the extrusion vector for an extruded volume.

**Parameters:**

* `volume` (Volume): The extruded volume object
* `mode` (Number, optional): Calculation mode

**Returns:** Number - Extrusion vector length

**Example:**

```xml
<P N="ExtrusionLength" V="volumeextvectorlength(ExtrudedBeam)"/>
```

***

### `perimeter(surface, isOpen?)`

Calculates the perimeter of a surface or boundary.

**Parameters:**

* `surface` (Surface3D): The surface object
* `isOpen` (Boolean, optional): Whether the surface is open

**Returns:** Number - Perimeter length

**Example:**

```xml
<P N="SlabPerimeter" V="perimeter(DeckSurface, false)"/>
```

**Related:** `surfarea()`, `linel()`

***

### `punchingperimeter(surface, distance, boundary)`

Calculates the punching shear perimeter at a distance from a boundary.

**Parameters:**

* `surface` (Surface3D): The surface (usually a slab)
* `distance` (Number): Distance from the boundary
* `boundary` (Boundary): The loaded area boundary

**Returns:** Number - Punching perimeter length

**Example:**

```xml
<P N="ShearPerimeter" V="punchingperimeter(Slab, EffectiveDepth, ColumnFace)"/>
```

**Related:** `punchingperimeterlines()`

***

### `punchingperimeterlines(surface, distance, boundary)`

Returns the line segments forming the punching shear perimeter.

**Parameters:**

* `surface` (Surface3D): The surface
* `distance` (Number): Distance from the boundary
* `boundary` (Boundary): The loaded area boundary

**Returns:** Array of Line3D - Perimeter lines

**Example:**

```xml
<P N="PerimeterLines" V="punchingperimeterlines(Slab, d, Column)"/>
```

**Related:** `punchingperimeter()`

***

## Unit Conversion

### `withunits(num, primaryUnit, secondaryUnit?, unitType?, decimals?)`

Formats a number with unit labels.

**Parameters:**

* `num` (Number): The numeric value
* `primaryUnit` (String): Primary unit system ("ft", "m", etc.)
* `secondaryUnit` (String, optional): Secondary unit for dual display
* `unitType` (String, optional): Unit category ("Length", "Force", etc.)
* `decimals` (Number, optional): Decimal places

**Returns:** String - Formatted string with units

**Example:**

```xml
<P N="LengthLabel" V="withunits(120.5, 'ft', 'in', 'Length', 2)"/>
<!-- Result: "120.50 ft" or "120'-6\"" depending on format -->
```

**Related:** `convert()`, `unitlabel()`

***

### `unitlabel(unitCategory, unitType)`

Returns the unit label for a given category and type.

**Parameters:**

* `unitCategory` (String): Unit category ("Default", "Metric", "Imperial")
* `unitType` (String): Unit type ("Length", "Force", "Stress", etc.)

**Returns:** String - Unit label (e.g., "ft", "kN", "MPa")

**Example:**

```xml
<P N="LengthUnit" V="unitlabel('Default', 'Length')"/>
```

**Related:** `withunits()`, `convert()`

***

### `convert(num, unitType, fromUnit, toUnit)`

Converts a value from one unit to another.

**Parameters:**

* `num` (Number): The value to convert
* `unitType` (String): Type of unit ("Length", "Force", "Stress", etc.)
* `fromUnit` (String): Source unit ("ft", "m", "kip", "kN", etc.)
* `toUnit` (String): Target unit

**Returns:** Number - Converted value

**Example:**

```xml
<P N="LengthInMeters" V="convert(100, 'Length', 'ft', 'm')"/>
<!-- Converts 100 feet to meters -->
<P N="ForceInKN" V="convert(50, 'Force', 'kip', 'kN')"/>
```

**Related:** `withunits()`, `unitlabel()`

***

### `stationlabel(station, format?, decimals?)`

Formats a station value according to standard station notation.

**Parameters:**

* `station` (Number): Station value
* `format` (String, optional): Format string
* `decimals` (Number, optional): Decimal places

**Returns:** String - Formatted station label

**Example:**

```xml
<P N="StationText" V="stationlabel(1234.56)"/>
<!-- Result: "12+34.56" -->
```

**Related:** `withunits()`

***

## Advanced Geometry

### `crange(value, min, max)`

Maps a value to a color range (for visualization).

**Parameters:**

* `value` (Number): The value to map
* `min` (Number): Minimum value of range
* `max` (Number): Maximum value of range

**Returns:** Color - Color value based on range

**Example:**

```xml
<P N="StressColor" V="crange(Stress, 0, MaxStress)"/>
```

***

### `voronoi(surface, sitePoints, cutoutPoints?)`

Generates a Voronoi diagram on a surface.

**Parameters:**

* `surface` (Surface3D): The base surface
* `sitePoints` (Array of Point): Site points for Voronoi cells
* `cutoutPoints` (Array of Point, optional): Points to exclude

**Returns:** Array of Surface3D - Voronoi cells

**Example:**

```xml
<P N="VoronoiCells" V="voronoi(DeckSurface, ColumnLocations)"/>
```

**Related:** `voronoipts()`

***

### `voronoipts(surface, sitePoints, cutoutPoints?)`

Returns the vertices of Voronoi cells.

**Parameters:**

* `surface` (Surface3D): The base surface
* `sitePoints` (Array of Point): Site points
* `cutoutPoints` (Array of Point, optional): Points to exclude

**Returns:** Array of Point - Voronoi vertices

**Example:**

```xml
<P N="VoronoiVertices" V="voronoipts(Slab, Supports)"/>
```

**Related:** `voronoi()`

***

### `hittest(surface, point, local?)`

Tests if a point hits (is inside) a surface.

**Parameters:**

* `surface` (Surface3D): The surface to test
* `point` (Point): The point to test
* `local` (Boolean, optional): Use local coordinates

**Returns:** Boolean - True if point is inside surface

**Example:**

```xml
<P N="IsInside" V="hittest(DeckBoundary, TestPoint, false)"/>
```

***

## Mesh Generation

### `stripmesh(line1, x1, line2, x2)`

Generates a strip mesh between two lines.

**Parameters:**

* `line1` (Line3D): First boundary line
* `x1` (Number): Parameter on first line
* `line2` (Line3D): Second boundary line
* `x2` (Number): Parameter on second line

**Returns:** Mesh - Strip mesh object

**Example:**

```xml
<P N="DeckMesh" V="stripmesh(LeftEdge, 0, RightEdge, 0)"/>
```

**Related:** `gridmesh()`

***

### `gridmesh(arg0, arg1, arg2?, arg3?)`

Generates a grid mesh from parameters.

**Parameters:**

* `arg0`, `arg1`, `arg2`, `arg3`: Grid definition parameters (varies by use case)

**Returns:** Mesh - Grid mesh object

**Example:**

```xml
<P N="SlabMesh" V="gridmesh(Boundary, 12, 12)"/>
<!-- Creates 12x12 mesh within boundary -->
```

**Related:** `stripmesh()`

***

## Object/Point Functions

### `point(obj, index?)`

Retrieves a point from an object.

**Parameters:**

* `obj` (Object): The object containing points
* `index` (Number, optional): Point index

**Returns:** Point - The requested point

**Example:**

```xml
<P N="StartPoint" V="point(Line, 0)"/>
<P N="EndPoint" V="point(Line, 1)"/>
```

***

### `cog(obj)`

Calculates the center of gravity (centroid) of an object.

**Parameters:**

* `obj` (Object): The object (surface, volume, or line)

**Returns:** Point - Center of gravity

**Example:**

```xml
<O T="Point" N="Centroid" X="cog(Slab).X" Y="cog(Slab).Y" Z="cog(Slab).Z"/>
```

**Related:** `surfarea()`, `volume()`

***

## Value/Expression Functions

### `value(targetParam, sourceParam?, sourceValue?)`

Evaluates the value of a parameter in a different context.

**Parameters:**

* `targetParam` (String): Name of parameter to evaluate
* `sourceParam` (String, optional): Source parameter for context
* `sourceValue` (Any, optional): Value for source parameter

**Returns:** Any - Evaluated parameter value

**Example:**

```xml
<P N="BeamDepth" V="value('Depth', 'Station', 100)"/>
<!-- Gets the value of Depth parameter at Station=100 -->
```

**Note:** This is useful for evaluating station-dependent parameters at specific locations.

***

## String Manipulation

### `startswith(str, prefix)`

Tests if a string starts with a specified prefix.

**Parameters:**

* `str` (String): The string to test
* `prefix` (String): The prefix to check

**Returns:** Boolean - True if string starts with prefix

**Example:**

```xml
<P N="IsGirder" V="startswith(Name, 'Girder')"/>
```

**Related:** `endswith()`

***

### `endswith(str, suffix)`

Tests if a string ends with a specified suffix.

**Parameters:**

* `str` (String): The string to test
* `suffix` (String): The suffix to check

**Returns:** Boolean - True if string ends with suffix

**Example:**

```xml
<P N="IsSteel" V="endswith(MaterialName, 'Steel')"/>
```

**Related:** `startswith()`

***

### `substringcount(str, substring)`

Counts occurrences of a substring within a string.

**Parameters:**

* `str` (String): The string to search
* `substring` (String): The substring to count

**Returns:** Number - Count of occurrences

**Example:**

```xml
<P N="HyphenCount" V="substringcount(Label, '-')"/>
```

***

### `replaceall(str, find, replace)`

Replaces all occurrences of a substring with another string.

**Parameters:**

* `str` (String): The source string
* `find` (String): The substring to find
* `replace` (String): The replacement string

**Returns:** String - Modified string

**Example:**

```xml
<P N="CleanName" V="replaceall(RawName, '_', ' ')"/>
<!-- Replaces all underscores with spaces -->
```

**Related:** `removewhitespaces()`

***

### `removewhitespaces(str)`

Removes all whitespace characters from a string.

**Parameters:**

* `str` (String): The string to process

**Returns:** String - String without whitespace

**Example:**

```xml
<P N="CompactName" V="removewhitespaces(Name)"/>
```

**Related:** `replaceall()`

***

### `mergeLinePoints(targetLines, constraints?, tolerance?)`

Merges nearby points in a collection of lines based on tolerance.

**Parameters:**

* `targetLines` (Array of Line3D): Lines to process
* `constraints` (Object, optional): Merge constraints
* `tolerance` (Number, optional): Distance tolerance for merging

**Returns:** Array of Line3D - Lines with merged points

**Example:**

```xml
<P N="CleanedLines" V="mergeLinePoints(RawLines, null, 0.001)"/>
```

***

## Functional Programming & Advanced Operations

These advanced functions provide functional programming capabilities, station-dependent expressions, and conditional logic.

### `map(list, lambda)`

Applies a lambda function to each element of a list and returns a new list with the results.

**Parameters:**

* `list` (Array): The array to map over
* `lambda` (Lambda Expression): Function to apply to each element (uses `x` for element, `i` for index)

**Returns:** Array - New array with transformed elements

**Example:**

```xml
<P N="DoubledValues" V="map(Numbers, x => x * 2)"/>
<P N="Squares" V="map([1,2,3,4,5], x => x ^ 2)"/>
```

**⚠️ CRITICAL PERFORMANCE NOTE:**

**ALWAYS use `map()` for parameter loops—NEVER use `Repeat` for data transformations!**

Using `Repeat` to calculate parameter values creates unnecessary objects in the project tree, causing severe performance degradation (10-100x slower). Use `map()` for all data transformations.

**❌ WRONG - Using Repeat for calculations:**

```xml
<!-- Creates 100 objects - VERY SLOW! -->
<O T="Repeat" N="Loop" S="0" E="99" I="1" CTRL="i" i="0">
  <P N="Value" V="InputList[i] * 2"/>
</O>
<P N="Results" V="Loop.*.Value"/>
```

**✅ CORRECT - Using map():**

```xml
<!-- Single parameter - FAST! -->
<P N="Results" V="map(InputList, x => x * 2)"/>
```

**Common Use Cases for map():**

```xml
<!-- Extract property from objects -->
<P N="GirderLengths" V="map(Girders, x => x.Length)"/>

<!-- Multi-station FEA results -->
<P N="Moments" V="map(Stations, force(Element, 'LC1', 'My', x))"/>

<!-- Transform coordinates -->
<P N="ZeroElevPoints" V="map(Points, [x[0], x[1], 0])"/>

<!-- Extract nested properties -->
<P N="SupportStations" V="map(Supports, x.location.station)"/>
```

**When to Use Repeat vs map():**

* **Use Repeat:** Creating objects (Points, FENodes, Volumes, Beams, etc.)
* **Use map():** Transforming data, extracting properties, calculating values

See the Parametric Engine Guide section 4.1 for detailed explanation.

**Related:** `filter()`, `reduce()`

***

### `filter(list, lambda)`

Filters a list based on a condition, returning only elements that match.

**Parameters:**

* `list` (Array): The array to filter
* `lambda` (Lambda Expression): Condition to test each element (uses `x` for element, `i` for index)

**Returns:** Array - Filtered array containing only matching elements

**Example:**

```xml
<P N="PositiveValues" V="filter(Numbers, x => x > 0)"/>
<P N="EvenNumbers" V="filter([1,2,3,4,5,6], x => x % 2 == 0)"/>
```

**Related:** `map()`, `index()`

***

### `reduce(list, lambda)`

Reduces a list to a single value by applying a function cumulatively.

**Parameters:**

* `list` (Array): The array to reduce
* `lambda` (Lambda Expression): Reduction function (uses `x` for accumulator, `y` for current element)

**Returns:** Any - Single accumulated value

**Example:**

```xml
<P N="Sum" V="reduce([1,2,3,4,5], x + y)"/>
<P N="Product" V="reduce(Values, x * y)"/>
```

**Related:** `suml()`, `avg()`

***

### `maxl(list, lambda?)`

Finds the maximum value in a list based on an optional lambda function.

**Parameters:**

* `list` (Array): The array to search
* `lambda` (Lambda Expression, optional): Function to extract comparison value from each element. If omitted, compares the values directly.

**Returns:** Any - Maximum value

**Example:**

```xml
<!-- With lambda for object properties -->
<P N="MaxLength" V="maxl(Beams, x => x.Length)"/>
<P N="MaxAbsolute" V="maxl(Values, x => abs(x))"/>

<!-- Without lambda for simple numeric lists -->
<P N="MaxValue" V="maxl(NumberList)"/>
```

**Related:** `minl()`, `max()`

***

### `minl(list, lambda?)`

Finds the minimum value in a list based on an optional lambda function.

**Parameters:**

* `list` (Array): The array to search
* `lambda` (Lambda Expression, optional): Function to extract comparison value from each element. If omitted, compares the values directly.

**Returns:** Any - Minimum value

**Example:**

```xml
<!-- With lambda for object properties -->
<P N="MinWidth" V="minl(Columns, x => x.Width)"/>
<P N="MinAbsolute" V="minl(Values, x => abs(x))"/>

<!-- Without lambda for simple numeric lists -->
<P N="MinValue" V="minl(NumberList)"/>
```

**Related:** `maxl()`, `min()`

***

### `suml(list, lambda?)`

Calculates the sum of values extracted from a list using an optional lambda function.

**Parameters:**

* `list` (Array): The array to sum
* `lambda` (Lambda Expression, optional): Function to extract value from each element. If omitted, sums the values directly.

**Returns:** Number - Sum of extracted values

**Example:**

```xml
<!-- With lambda for object properties -->
<P N="TotalArea" V="suml(Surfaces, x => x.Area)"/>
<P N="WeightedSum" V="suml(Items, x => x.Value * x.Quantity)"/>

<!-- Without lambda for simple numeric lists -->
<P N="Total" V="suml(NumberList)"/>
```

**Related:** `avg()`, `reduce()`, `sum()`

***

### `avg(list, lambda?)`

Calculates the average of values extracted from a list using an optional lambda function.

**Parameters:**

* `list` (Array): The array to average
* `lambda` (Lambda Expression, optional): Function to extract value from each element. If omitted, averages the values directly.

**Returns:** Number - Average of extracted values

**Example:**

```xml
<!-- With lambda for object properties -->
<P N="AvgHeight" V="avg(Buildings, x => x.Height)"/>
<P N="MeanStress" V="avg(Elements, x => x.Stress)"/>

<!-- Without lambda for simple numeric lists -->
<P N="Average" V="avg(NumberList)"/>
```

**Related:** `suml()`

***

### `sort(list, lambda?, ascending?)`

Sorts a list based on a comparison function.

**Parameters:**

* `list` (Array): The array to sort
* `lambda` (Lambda Expression, optional): Function to extract sort key from each element
* `ascending` (Number, optional): 1 for ascending (default), 0 for descending

**Returns:** Array - Sorted array

**Example:**

```xml
<P N="SortedNumbers" V="sort([5,2,8,1,9])"/>
<P N="SortedByLength" V="sort(Beams, x => x.Length)"/>
<P N="DescendingOrder" V="sort(Values, x => x, 0)"/>
```

**Related:** `reverse()`

***

### `reverse(list)`

Reverses the order of elements in a list.

**Parameters:**

* `list` (Array): The array to reverse

**Returns:** Array - Reversed array

**Example:**

```xml
<P N="ReversedList" V="reverse([1,2,3,4,5])"/>
<!-- Result: [5,4,3,2,1] -->
```

**Related:** `sort()`

***

### `unique(list, lambda)` / `removedup(list, lambda)`

Removes duplicate elements from a list based on a lambda function.

**Parameters:**

* `list` (Array): The array to filter
* `lambda` (Lambda Expression): Function to extract comparison value from each element

**Returns:** Array - Array with duplicates removed

**Example:**

```xml
<P N="UniqueIDs" V="unique(Objects, x => x.ID)"/>
<P N="UniqueMaterials" V="removedup(Elements, x => x.Material)"/>
```

**Related:** `filter()`

***

### `index(list, lambda)`

Finds the index of the first element that matches a condition.

**Parameters:**

* `list` (Array): The array to search
* `lambda` (Lambda Expression): Condition to test each element

**Returns:** Number - Index of first matching element, or -1 if not found

**Example:**

```xml
<P N="FirstNegative" V="index(Values, x => x < 0)"/>
<P N="FoundIndex" V="index(Beams, x => x.Name == 'MainGirder')"/>
```

**Related:** `filter()`

***

### `iif(condition1, value1, condition2, value2, ..., elseValue?)`

Inline if-elseif-else function for conditional expressions.

**Parameters:**

* `condition1, condition2, ...` (Boolean): Conditions to test
* `value1, value2, ...` (Any): Values to return when conditions are true
* `elseValue` (Any, optional): Default value if no conditions match

**Returns:** Any - First matching value, or elseValue, or 0

**Example:**

```xml
<P N="Grade" V="iif(Score >= 90, 'A', Score >= 80, 'B', Score >= 70, 'C', 'F')"/>
<P N="Status" V="iif(Stress > Yield, 'Failed', Stress > AllowableStress, 'Warning', 'OK')"/>
```

**Note:** More flexible than ternary operator for multiple conditions

***

### `atstation(station, expression)`

Evaluates an expression at a specific station value, temporarily overriding the current station context.

**Parameters:**

* `station` (Number): Station value to evaluate at
* `expression` (Expression): Expression to evaluate

**Returns:** Any - Result of expression evaluated at the given station

**Example:**

```xml
<P N="DepthAtMidspan" V="atstation(60, Depth)"/>
<P N="ForceAt100" V="atstation(100, forceM('Girder', 'DeadLoad'))"/>
```

**Note:** Useful for evaluating station-dependent parameters at specific locations

***

### `makestadep(stations, values, variations?)`

Creates a station-dependent expression from discrete station/value pairs. The function returns a station-dependent parameter that can be evaluated at any station using `atstation()`.

**Parameters:**

* `stations` (Array of Numbers): Station values
* `values` (Array of Numbers or Arrays): Values at each station. **Note:** The `values` array should have one less element than `stations` (i.e., values.length = stations.length - 1), as shown in examples. Each element can be a single number or an array of numbers (for multiple values per station).
* `variations` (Array of Strings, optional): Variation types between stations ('linear', 'parabola', 'circle', 'polynomial'). Should match the number of gaps (stations.length - 1).

**Returns:** Number - Interpolated value at current station

**Example:**

```xml
<P N="VariableDepth" V="makestadep([0,50,100,150], [60,72,72,60], ['linear','linear','linear'])"/>
<!-- Depth varies from 60 at station 0 to 72 at stations 50-100, back to 60 at 150 -->
```

**Additional Example for Array Values (Multiple Values per Station):**

```xml
<P N="MultiValueParam" V="makestadep([0,100], [[10,20]], ['linear'])"/>
<!-- At station 0: 10, at station 100: 20, interpolated linearly (1 gap) -->
```

**Another Example (3 Stations, 2 Gaps):**

```xml
<P N="MultiValueParam2" V="makestadep([0,100,200], [[10,20], [15,25]], ['linear','linear'])"/>
<!-- At station 0: 10, at station 99: 19.9, at station 100: 20, at station 101: 15.1, at station 200: 25,interpolated linearly -->
```

**Related:** `variation()`, `makestadepexpr()` **Example:**

```xml
<O N="MakestadepFunction" T="Group">
    <P N="stationlist" V="[0,100,200]" />
    <P N="Valueslist" V="[10,20,30]" />
    <P N="varTextlist" V="['linear','linear']" />
    <P N="staDepParam" V="makestadep(stationlist,Valueslist,varTextlist)" />
    <P N="test1" V="atstation(50,staDepParam)" />
    <!-- test1 value = 15 (interpolated at station 50) -->
</O>
```

**Related:** `atstation()`, `variation()`, `makestadepexpr()`

***

### `makestadepexpr(stations, values, variations?)`

Creates a station-dependent expression string (not evaluated).

**Parameters:**

* `stations` (Array of Numbers): Station values
* `values` (Array of Numbers): Values at each station
* `variations` (Array of Strings, optional): Variation types

**Returns:** String - Station-dependent expression as text

**Example:**

```xml
<P N="DepthExpression" V="makestadepexpr([0,100,200], [60,72,60])"/>
```

**Related:** `makestadep()`

***

### `variation(type, fromValue, toValue, ...)`

Creates a variation between two values based on relative position (0 to 1).

**Parameters:**

* `type` (String): Variation type - 'linear', 'parabola', 'circle', 'polynomial', 'custom'
* `fromValue` (Number): Starting value
* `toValue` (Number): Ending value
* Additional parameters depend on type:
  * **parabola**: `parabolaType` ('concavedown' or 'concaveup')
  * **circle**: `radius`, `circleType`
  * **polynomial**: `startGrade`, `endGrade`
  * **custom**: `lambda` function

**Returns:** Number - Interpolated value

**Example:**

```xml
<P N="LinearVariation" V="variation('linear', 0, 100)"/>
<P N="ParabolicVariation" V="variation('parabola', 60, 72, 'concavedown')"/>
<P N="CustomVariation" V="variation('custom', x => sin(x * pi))"/>
```

**Note:** Requires context with station or relative position (x) set

***

### `variations(params...)`

Returns the list of variation types used in the given parameters.

**Parameters:**

* `params...` (Parameters): Parameters to check for variations

**Returns:** Array of Strings - List of variation types found

**Example:**

```xml
<P N="UsedVariations" V="variations(Depth, Width, Height)"/>
<!-- Might return ['parabola', 'linear'] -->
```

***

### `makelist(params...)` / `rangelist(params...)`

Creates a list from station-dependent range values.

**Parameters:**

* `params...` (Parameters): Parameters with range values

**Returns:** Array - Unique values from all ranges

**Example:**

```xml
<P N="AllStations" V="makelist(BeamStations, ColumnStations)"/>
<P N="CombinedRanges" V="rangelist(Range1, Range2, Range3)"/>
```

**Note:** Automatically extracts values from station-dependent ranges

***

### `exportval(paramName, object?, defaultReturn?)`

Exports a parameter value from an object, with optional default.

**Parameters:**

* `paramName` (String): Name of parameter to export
* `object` (Object, optional): Object to export from
* `defaultReturn` (Any, optional): Default value if parameter not found (default: 0)

**Returns:** Any - Parameter value or default

**Example:**

```xml
<P N="MaterialStrength" V="exportval('Fy', MaterialObject, 50)"/>
<P N="BeamLength" V="exportval('Length', Girder)"/>
```

***

### `paramlabel(param)`

Returns the display label of a parameter or object name.

**Parameters:**

* `param` (Parameter or Object): Parameter or object to get label from

**Returns:** String - Parameter label or object name

**Example:**

```xml
<P N="DepthLabel" V="paramlabel(Depth)"/>
```

**Note:** Returns the user-facing label, not the internal parameter name

***

## External Module Functions

These functions are available when specific modules are loaded in the context.

### Section Analysis Functions (SEC.Functions)

Available when section analysis module is loaded. Defined in [Functions.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/SEC/Functions.ts).

#### `momentCapacity(section, orientation, strain, axial, ...)`

Calculates moment capacity of a cross-section.

**Parameters:**

* `section` (Section): The section object
* `orientation` (Number): Load orientation angle
* `strain` (Number): Maximum strain
* `axial` (Number): Axial force
* Additional parameters for analysis settings

**Returns:** Number - Moment capacity value

**Example:**

```xml
<P N="Capacity" V="momentCapacity(BeamSection, 0, 0.003, 0)"/>
```

**Related:** `momentCapacityNA()`, `interactionDiagram()`

***

#### `momentCapacityNA(section, orientation, strain, axial, ...)`

Returns neutral axis distance from section centroid for moment capacity calculation.

**Parameters:** Same as `momentCapacity()`

* `section`: Section object to analyze
* `orientation`: Rotation angle in radians (**clockwise positive**)
* `strain`: Concrete strain limit (typically 0.003)
* `axial`: Corresponding axial force (compression positive)

**Returns:** Number - Neutral axis distance from centroid (positive upward from origin)

**How It Works:**

1. **Rotates the section** (including all rebars and tendons) clockwise by the specified `orientation` angle about the $(0, 0)$ coordinate point.
2. **Applies compression** from top (positive Y direction) relative to origin (0,0)
3. **Returns NA distance** from centroid, positive upward:
   * **Positive value**: NA is above centroid (compression zone above)
   * **Negative value**: NA is below centroid (rare, large tension forces)

**Key Points:**

* Coordinate system origin at (0,0)
* Compression side is upward (positive Y)
* Result measured in the rotated coordinate system
* Section rotates **with all reinforcement** (rebars and tendons)

**Example Usage:**

```xml
<!-- Compression from top (0° rotation) -->
<P N="NA_distance" V="momentCapacityNA(mySection, 0, 0.003, 1000)" />
<!-- Returns positive distance (NA above centroid) -->

<!-- Compression from different angle (90° clockwise rotation) -->
<P N="NA_distance_rotated" V="momentCapacityNA(mySection, pi/2, 0.003, 1000)" />
<!-- Returns positive distance in rotated system -->
```

**Important:** When filtering rebars or calculating distances in the **original** coordinate system, you may need to adjust the sign of the returned NA value depending on the rotation angle and which side of the section you're working with.

**Related:** `momentCapacity()`, `interactionDiagram()`

***

#### `momentCapacityTension(section, orientation, strain, axial, ...)`

Returns tension force at moment capacity.

**Returns:** Number - Tension force

***

#### `momentCapacityCompression(section, orientation, strain, axial, ...)`

Returns compression force at moment capacity.

**Returns:** Number - Compression force

***

#### `momentCapacityCurvature(section, orientation, strain, axial, ...)`

Returns curvature at moment capacity.

**Returns:** Number - Curvature value

***

#### `sectionDepth(section, station?)`

Returns the depth of a section at a given station.

**Parameters:**

* `section` (Section): The section object
* `station` (Number, optional): Station location

**Returns:** Number - Section depth

**Example:**

```xml
<P N="Depth" V="sectionDepth(GirderSection, 50)"/>
```

**Related:** `sectionWidth()`, `sectionExt()`

***

#### `sectionWidth(section, station?)`

Returns the width of a section.

**Parameters:**

* `section` (Section): The section object
* `station` (Number, optional): Station location

**Returns:** Number - Section width

***

#### `sectionExt(section, station?)`

Returns the extents (bounding box) of a section.

**Returns:** Object - {minX, maxX, minY, maxY}

***

#### `sectionShapeCoords(section)`

Returns coordinates defining the section shape.

**Returns:** Array of Point2D - Shape coordinates

***

#### `sectionHasTendon(section)`

Checks if section has post-tensioning tendons.

**Returns:** Boolean

***

#### `sectionHasRebar(section)`

Checks if section has reinforcing bars.

**Returns:** Boolean

***

#### `sectionIsComposite(section)`

Checks if section is composite.

**Returns:** Boolean

***

#### `interactionDiagram(section, ...)`

Generates interaction diagram data (P-M diagram).

**Returns:** Array - Interaction curve points

**Example:**

```xml
<P N="PMDiagram" V="interactionDiagram(ColumnSection, 0, 100, 0.003)"/>
```

***

#### `crackedInertia(section, ...)`

Calculates cracked moment of inertia.

**Returns:** Number - Cracked inertia value

***

#### `maxRebarTensileStress(section, ...)`

Calculates maximum tensile stress in reinforcement.

**Returns:** Number - Maximum stress

***

### Alignment/Bridge Functions (OpenBrIM.Functions)

Available for bridge alignment operations. Defined in [Functions.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/OBrIM/Functions.ts).

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

Returns the global X coordinate on an alignment.

**Parameters:**

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

**Returns:** Number - X coordinate

**Example:**

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

**Related:** `alignHY()`, `alignHZ()`, `alignH()`

***

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

Returns the global Y coordinate on an alignment.

**Parameters:** Same as `alignHX()`

**Returns:** Number - Y coordinate

***

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

Returns the global Z coordinate (elevation) on an alignment.

**Parameters:** Same as `alignHX()`

**Returns:** Number - Z coordinate

**Note:** This returns horizontal plane Z, use `alignV()` for vertical profile elevation.

***

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

Returns the horizontal angle (bearing) of alignment at a station.

**Parameters:**

* `alignment` (Alignment): The alignment object
* `station` (Number): Station value
* `offset` (Number): Transverse offset

**Returns:** Number - Angle in degrees

**Example:**

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

***

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

Returns all horizontal alignment data (X, Y, angle) at once.

**Parameters:** Same as `alignHX()`

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

**Example:**

```xml
<P N="HData" V="alignH(Centerline, 100, 5)"/>
<O T="Point" X="HData.X" Y="HData.Y"/>
```

***

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

Converts global coordinates to local alignment coordinates (station, offset).

**Parameters:**

* `alignment` (Alignment): The alignment object
* `x`, `y`, `z` (Numbers): Global coordinates

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

**Example:**

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

**Related:** `alignH()`, `alignProjection()`

***

#### `alignProjection(sourceAlign, targetAlign, station, offset, ...)`

Projects a point from one alignment to another.

**Parameters:**

* `sourceAlign` (Alignment): Source alignment
* `targetAlign` (Alignment): Target alignment
* `station` (Number): Station on source
* `offset` (Number): Offset on source
* Additional parameters for projection method

**Returns:** Object - {Station, Offset} on target alignment

***

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

Returns transverse elevation at a station and offset.

**Parameters:**

* `alignment` (Alignment): The alignment object
* `station` (Number): Station value
* `offset` (Number): Transverse offset

**Returns:** Number - Elevation

***

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

Returns transverse slope angle at a station and offset.

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

***

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

Returns vertical profile elevation at a station.

**Parameters:**

* `alignment` (Alignment): The alignment object
* `station` (Number): Station value

**Returns:** Number - Elevation from vertical profile

**Example:**

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

***

#### `alignA(alignment, station)`

Returns alignment angle (bearing) at a station.

**Parameters:**

* `alignment` (Alignment): The alignment object
* `station` (Number): Station value

**Returns:** Number - Bearing angle

***

#### `alignLength(alignment, ...)`

Returns the total length of an alignment.

**Returns:** Number - Alignment length

***

#### `alignRad(alignment, station, ...)`

Returns the horizontal radius at a station.

**Returns:** Number - Radius (positive for curves, very large for tangents)

***

#### `stationDifference(alignment, station1, station2, ...)`

Calculates the difference between two stations accounting for equations.

**Returns:** Number - Station difference

***

#### `verticalClearance(alignment, ...)`

Calculates vertical clearance at a location.

**Returns:** Number - Clearance value

***

#### `CutFillPolygon(surface1, surface2, ...)`

Generates cut/fill polygons between two surfaces.

**Returns:** Array - Cut and fill regions

***

#### `SplitPolygonByLine(polygon, line, ...)`

Splits a polygon by a line.

**Returns:** Array - Split polygon pieces

***

#### `mto(objects, ...)`

Performs material take-off calculations.

**Returns:** Object - Material quantities

***

#### `alignLine(alignment, startStation, endStation, ...)`

Extracts a line segment from an alignment between stations.

**Returns:** Line3D

***

#### `stressStrainCurvePoints(material, ...)`

Returns points on a material stress-strain curve.

**Returns:** Array - Curve points

***

#### `lineProjection(line, targetAlignment, ...)`

Projects a line onto an alignment.

**Returns:** Object - Projection data

***

#### `pointProjection(point, targetAlignment, ...)`

Projects a point onto an alignment.

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

***

#### `controlLocations(alignment, ...)`

Returns control point locations on an alignment.

**Returns:** Array - Control points

***

#### `alignHCenter(alignment, station, ...)`

Returns horizontal center point at a station.

**Returns:** Point

***

#### `convertToLocal(alignment, point, ...)`

Converts a point to local alignment coordinates.

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

***

### Finite Element Analysis Functions (FEA.Functions)

Available when FEA analysis is performed. Defined in [Functions.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/FEA/Functions.ts).

#### `feobj(objectName, paramName?, repeat?, index?)`

Retrieves a finite element object or its parameter value.

**Parameters:**

* `objectName` (String): Name of FEA object
* `paramName` (String, optional): Parameter name to retrieve
* `repeat` (Number, optional): Repeat index
* `index` (Number, optional): Sub-index

**Returns:** Object or Value - FEA object or parameter value

**Example:**

```xml
<P N="NodeDisp" V="feobj('Node1', 'UZ')"/>
```

***

#### Dynamic Output Functions

FEA provides dynamic functions based on analysis results. Common patterns:

**Force Functions:**

* `force(element, loadCase, component)` - Element forces
* `forceN(element, loadCase)` - Axial force
* `forceV(element, loadCase)` - Shear force
* `forceM(element, loadCase)` - Moment

**Displacement Functions:**

* `disp(node, loadCase, component)` - Node displacements
* `dispX(node, loadCase)` - X displacement
* `dispY(node, loadCase)` - Y displacement
* `dispZ(node, loadCase)` - Z displacement

**Stress Functions:**

* `stress(element, loadCase, component)` - Element stresses
* `stressXX(element, loadCase)` - Normal stress XX
* `stressVM(element, loadCase)` - Von Mises stress

**Example:**

```xml
<P N="MaxDisp" V="dispZ('MidspanNode', 'LiveLoad')"/>
<P N="Moment" V="forceM('GirderElement', 'DeadLoad')"/>
```

***

#### `forceNeg(component, elementPath, loadCase, station?)`

Retrieves the negative (minimum) force/moment value from analysis results.

**Parameters:**

* `component` (String): Force component ('N', 'V', 'M', 'Mx', 'My', 'Mz', etc.)
* `elementPath` (String): Full path to the element (use `fullname()` for dynamic paths)
* `loadCase` (String): Load case or combination name
* `station` (Number, optional): Station location along element

**Returns:** Number - Negative (minimum) force value

**Example:**

```xml
<P N="MaxNegativeMoment" V="forceNeg('My', Girder.N + '.MainSpan', 'DeadLoad')"/>
<P N="MinShear" V="forceNeg('V', fullname(Beam) + '.Section', LoadCase, Station)"/>
```

**Use Cases:**

* Finding maximum negative moments for bottom flange design
* Determining compression forces for member design
* Envelope analysis across multiple load cases

**Related:** `forcePos()`, `forceM()`, `fullname()`

***

#### `forcePos(component, elementPath, loadCase, station?)`

Retrieves the positive (maximum) force/moment value from analysis results.

**Parameters:**

* `component` (String): Force component ('N', 'V', 'M', 'Mx', 'My', 'Mz', etc.)
* `elementPath` (String): Full path to the element
* `loadCase` (String): Load case or combination name
* `station` (Number, optional): Station location along element

**Returns:** Number - Positive (maximum) force value

**Example:**

```xml
<P N="MaxPositiveMoment" V="forcePos('My', Girder.N + '.MainSpan', 'LiveLoad')"/>
<P N="MaxTension" V="forcePos('N', fullname(Cable), Combination)"/>
```

**Use Cases:**

* Finding maximum positive moments for top flange design
* Determining tension forces for member design
* Strength envelope calculations

**Related:** `forceNeg()`, `forceM()`, `fullname()`

***

#### `fullname(object)`

Returns the full hierarchical path name of an object, including all parent object names.

**Parameters:**

* `object` (Object or Parameter): The object to get the full path for

**Returns:** String - Full dot-notation path (e.g., "Project.Bridge.Girder1")

**Example:**

```xml
<P N="ElementPath" V="fullname(Girder)"/>
<!-- Result: "BridgeModel.Superstructure.Girder1" -->

<P N="Forces" V="forceNeg('My', fullname(Beam) + '.Comb', LoadCase, Station)"/>
<!-- Dynamically constructs path like "Bridge.Beams.Beam1.Comb" -->
```

**Use Cases:**

* Dynamically constructing element paths for analysis queries
* Building unique identifiers for objects in repeats
* Debugging parameter resolution issues
* Creating reports with full object references

**Common Pattern - Force Queries in Repeats:**

```xml
<O T="Repeat" N="GirderChecks" S="0" E="length(Girders)-1" I="1" CTRL="i" i="0">
  <P N="CurrentGirder" V="Girders[i]"/>

  <!-- Use fullname to construct dynamic path -->
  <P N="MomentDL" V="forceM(fullname(CurrentGirder), 'DeadLoad')"/>
  <P N="MomentLL" V="forceM(fullname(CurrentGirder), 'LiveLoad')"/>
</O>
```

**Related:** `forceNeg()`, `forcePos()`, `feobj()`

***

#### `tshortTermLoss(tendon, point)`

Calculates short-term prestress losses in a tendon.

**Parameters:**

* `tendon` (Tendon): The tendon object
* `point` (Number or Point): Evaluation point

**Returns:** Number - Stress loss

***

#### `getPushoverSubStageNames(analysisCase, ...)`

Returns substage names from a pushover analysis.

**Returns:** Array of Strings - Substage names

***

#### `getPushoverControlNode(analysisCase, ...)`

Returns the control node for pushover analysis.

**Returns:** String - Node name

***

## Best Practices

### 1. Use Functions Directly

All ParamML functions can be called directly in expressions. The execution context is handled automatically by the evaluation engine, so you never need to provide it manually.

### 2. Check Array Lengths

Before accessing array elements, verify the array has sufficient length:

```xml
<P N="Value" V="length(Points) > 0 ? first(Points).X : 0"/>
```

### 3. Use Appropriate Units

Always specify unit types for physical quantities:

```xml
<P N="BeamLength" V="linel(Centerline)" UT="Length" UC="Default"/>
```

### 4. Handle Null Returns

Some functions may return null (e.g., `intersect()` if lines don't intersect). Use guards:

```xml
<P N="Guard" V="intersect(Line1, Line2) != NULL"/>
<P N="IntX" V="intersect(Line1, Line2).X"/>
```

### 5. Leverage Object Hierarchy

Use the parametric tree structure with `parent()` and `project()`:

```xml
<P N="ProjectWidth" V="project().Width"/>
<P N="ParentLength" V="parent(self).Length"/>
```

### 6. Optimize Performance

* Cache expensive calculations in parameters
* Use `value()` for station-dependent parameters instead of recalculating
* Prefer built-in functions over custom implementations

### 7. Document Complex Expressions

Use parameter descriptions to explain complex function usage:

```xml
<P N="Capacity" V="momentCapacity(Section, 0, 0.003, Axial)"
   D="Moment capacity at 0.003 strain with axial load"/>
```

***

## Common Usage Patterns

### Creating Points Along a Line

```xml
<O T="Repeat" N="StationPoints" S="0" E="NumStations - 1" I="1" CTRL="i" i="0">
  <O T="Point" N="Pt" X="onliner(Baseline, i/(NumStations-1)).X" Y="onliner(Baseline, i/(NumStations-1)).Y" Z="onliner(Baseline, i/(NumStations-1)).Z" />
</O>
```

### Alignment-Based Geometry

```xml
<O T="Point" N="BridgePoint" X="alignHX(Centerline, Station, Offset)" Y="alignHY(Centerline, Station, Offset)" Z="alignV(Centerline, Station)+alignT(Centerline, Station, Offset)">
  <P N="Station" V="100" Role="Input"/>
  <P N="Offset" V="10" Role="Input"/>
</O>
```

### Conditional Geometry Based on Analysis

```xml
<P N="RequireStiffener" V="forceM('Girder', 'Ultimate') > AllowableMoment ? 1 : 0"/>
<O T="Plate" N="Stiffener">
  <P N="Guard" V="RequireStiffener == 1"/>
  <!-- Stiffener geometry -->
</O>
```

### Section Property Queries

```xml
<P N="UseComposite" V="sectionIsComposite(BeamSection) ? 1 : 0"/>
<P N="Depth" V="sectionDepth(BeamSection, Station)"/>
<P N="Width" V="sectionWidth(BeamSection, Station)"/>
```

***

## Function Implementation Reference

For AI agents developing or debugging ParamML:

**Primary Dispatcher:**

* [Param.ts:655-973](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/PML/Param.ts#L655-L973) - `ExprProvFunctionCall()` method

**Implementation Files:**

* [ParamFunc.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/PML/ParamFunc.ts) - Core function implementations
* [SEC/Functions.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/SEC/Functions.ts) - Section analysis functions
* [OBrIM/Functions.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/OBrIM/Functions.ts) - Alignment/bridge functions
* [FEA/Functions.ts](https://github.com/openbrim/platform/blob/master/docs/developers/llm-guides/Code/FEA/Functions.ts) - Finite element analysis functions

**Error Handling:** All functions use `ParamML.Param.ThrowError(message)` for error reporting. Always validate:

* Parameter types (arrays, numbers, objects)
* Parameter count
* Null/undefined values
* Context requirements

***

## Summary

ParamML provides 90+ functions organized into categories:

* **Array/List**: Manipulation and queries of collections
* **Geometric**: Transformations and geometric calculations
* **Line/Curve**: Operations on linear geometry
* **Surface/Volume**: Area, volume, and perimeter calculations
* **Unit Conversion**: Formatting and converting physical units
* **Advanced Geometry**: Voronoi, intersection, mesh operations
* **String**: Text manipulation utilities
* **External Modules**: Context-specific functions for FEA, sections, and alignments

**Key Principles:**

1. Functions are case-sensitive
2. Most geometric functions require execution context
3. External module functions are only available in appropriate contexts
4. Functions can be nested and combined in expressions
5. Always handle potential null returns from geometric operations
6. Use appropriate unit types for engineering calculations

This comprehensive function library enables AI agents to create sophisticated parametric bridge models with complex geometric relationships, engineering calculations, and analysis integrations.
