FCS Classes, Blocks & Distributions

This document covers parametric geometry classes, instantiation, and distribution patterns.

GClass (Geometry Class)

A gclass defines a reusable parametric component loaded from an external file.

Basic Syntax

gclass {name} filename "<file.fcs>" parameters { param1 := value1, param2 := value2 }

Components

Part Description
{name} Identifier for the class
filename Path to .fcs file (relative or absolute)
parameters Optional parameter overrides

Examples

# Simple class from file
gclass 1 filename ("Hoop.fcs") parameters {D = D, aC = aC, bC = bC, rC = rC}

# Named class
gclass {gCss} filename "css\I_profile_rotated.fcs"

# Class with dynamic filename
gclass {gCss} filename ("css\"+Css_ID+".fcs")

# Hierarchical loading (relative paths)
gclass {gBeamPartDistribution} filename "BeamPartDistribution.fcs"

Resources Pattern

Common pattern for loading shared resources:

gclass {res} filename "_FcsComponentResources.fcs"

# Then access resources via:
myStyle := res.defaults.LabelStyle

GBlock (Geometry Block)

A gblock instantiates a gclass with a specific local coordinate system and parameters.

Basic Syntax

gblock {name} gclass {gclass_name} lcs <coordinate_system> parameters { ... }

With Conditional

gblock {name} gclass {class} lcs (Lcs) if (condition) parameters { ... }

LCS (Local Coordinate System) Options

# Global coordinate system
lcs GCS

# Explicit origin and axes
lcs {Origin={0,0,0}, Axes=GCS.Axes}

# Transformed GCS
lcs (GCS.Tz(height).Rx(angle))

# Complex transformation
lcs {Origin={x,y,z}, Axes=GCS.Axes.Ry(-PI/2)}

Parameter Binding

# Direct values
parameters {h := 0.3}

# Expression values  
parameters {length := BeamLength.Sum, angle := RoofAngle}

# Array element binding
parameters {Length := BeamLength[i], Height := Heights[i+1]}

Complete Examples

# Positioned cross-section
gclass {gCss} filename "css\I_profile_rotated.fcs"
gblock {gbCss1} gclass {gCss} lcs {Origin={gbCss1.h/2,0,0},Axes={GCS.Axes}} parameters {h:=0.3}

# Multiple instances with different positions
gblock {gbColumn} gclass {gBeamPart} lcs {Origin={0,0,0}, Axes=GCS.Axes.Ry(-PI/2)} parameters {BeamLength:=ColumnLength}
gblock {gbRafter} gclass {gBeamPart} lcs {Origin={0,0,ColumnLength.Sum}, Axes=GCS.Axes.Ry(RoofAngle)} parameters {BeamLength:=RafterLength}

# Mirrored instance
gblock {gbFramePartLeft} gclass {gFramePart} lcs GCS
gblock {gbFramePartRight} gclass {gFramePart} lcs {Origin={Span,0,0},Axes={GCS.Axes.Rz(PI)}}

# Conditional instantiation
gblock {gbArrow} gclass {ArrowForce} lcs (Lcs.Ry(-PI/2)) if (Fx != 0) parameters { Length := Fx/maxFM*Length }

Self-Reference Pattern

GBlocks can reference their own exported properties:

gblock {gbCss1} gclass {gCss} lcs {Origin={gbCss1.h/2,0,0},Axes={GCS.Axes}} parameters {h:=0.3}
#                                          ^^^^^^^^^ self-reference to h property

Distribution

Distributions create repeated instances of geometry with specified transformations.

Basic Syntax

distribution {name} geometries {geom1} {geom2} repetitions count <n>

Full Syntax

distribution {name} gclass {class} lcs {lcs} 
    transformation translation direction {x,y,z} 
    repetitions count (expression) spacings <array>
    specialization ithparameters { ... }

Components

Part Description
geometries List of geometries to distribute
gclass Class to instantiate repeatedly
transformation Type: translation, rotation
direction Direction vector for translation
repetitions count Number of repetitions
spacings Array of spacing distances
ithparameters Parameters varying per instance

Simple Distribution

# Distribute geometries between two endpoints
distribution 1 geometries {hoopTop} {hoopBottom} repetitions count nHoops

Linear Array Distribution

distribution {dBeam} gclass {gBeam} 
    lcs {Origin={0,0,0}, Axes=GCS.Axes} 
    transformation translation direction {1,0,0} 
    repetitions count (BeamLength.Count) 
    spacings BeamLength 
    specialization ithparameters {
        Length := BeamLength[ith.i], 
        HeadCut := ((ith.i==0) ? (HeadCut) : 0), 
        Headh := Heights[ith.i], 
        Endh := Heights[ith.i+1]
    }

The ith Object

Inside ithparameters, the special ith object provides iteration context:

ithparameters {
    index := ith.i,
    isFirst := (ith.i == 0),
    isLast := (ith.i == ith.n - 1)
}

Distribution Examples

# Cage structure with distributed vertical bars
distribution 5 geometries {b2} {v10} repetitions count 4
distribution 6 geometries {b3} {v11} repetitions count 4

# Variable-spaced beam segments
BeamLength := [2.25, 2, 2, 2]
distribution {dBeam} gclass {gBeam} 
    transformation translation direction {1,0,0} 
    repetitions count (BeamLength.Count) 
    spacings BeamLength

Traction (Lofted Geometry)

Tractions create swept/lofted geometry between cross-sections.

Syntax

traction {name} sections {section1, section2, ...} layer {layer}

Example

# Variable I-beam with changing cross-sections
gblock {gbCss1} gclass {gCss} parameters {h := 0.3}
gblock {gbCss2} gclass {gCss} parameters {h := 0.8}
gblock {gbCss3} gclass {gCss} parameters {h := 0.3}

traction {tBeam1} sections {gbCss1, gbCss2} layer {Primary}
traction {tBeam2} sections {gbCss2, gbCss3} layer {Primary}

This creates a beam with web height varying from 0.3 to 0.8 to 0.3.


Label

Labels create 3D text annotations.

Syntax

label {name} lcs { Origin, Axes } text "<format>" arguments {arg1, arg2} layer (layer) styles [style1, style2]

Format Strings

Uses .NET composite formatting:

Example

LabelString := "GA 15"

label {lLabel} lcs {
    Origin = { 0, 0, 0 },
    Axes = GCS.Axes
} text "{1}{0:0}" arguments {LabelString, ""} layer (LabelStyle.Layer) styles [ LabelStyle.TextStyle, LabelStyle.ViewStyle ]

Style

Styles define visual properties for geometry.

Text Style Properties

TextStyle := {
    Size := 12,
    Font := "Arial",
    Color := Red
}

View Style Properties

ViewStyle := {
    LineWidth := 2,
    LineType := Solid
}

Usage with Labels

styles [ TextStyle, ViewStyle ]

Layer

Layers organize geometry and control visibility/appearance.

Syntax

layer {name} color <color>

Colors

Built-in color names: Red, Green, Blue, Orange, Yellow, White, Black, Lime, etc.

Examples

layer {Primary} color Orange
layer {lLoadLayer} color Lime
layer {structural} color Blue

# Assign geometry to layer
vertex {v1} xyz 0 0 0 layer {Primary}

Filleted Polyline Curves

Creates polyline curves with optional filleted corners.

Syntax

curve {name} filletedpoly radiusmultiplier <mult> vertexes {v1} {v2} ... fillets <r1> <r2> ...

Components

Part Description
radiusmultiplier Scales all fillet radii
vertexes Ordered list of vertices
fillets Fillet radius at each vertex (0 = sharp corner)

Examples

# I-beam cross-section with rounded corners
curve 1 filletedpoly radiusmultiplier 1 
    vertexes 1 2 3 4 5 6 7 8 9 10 11 12 1 
    fillets 0 0 r2 r1 r1 r2 0 0 r2 r1 r1 r2 0

# Rectangle with rounded corners  
curve {c1} filletedpoly radiusmultiplier 0 
    vertexes {v1} {v2} {v3} {v4} {v1} 
    fillets 1 1 1 1 1

# Polyline with selective filleting
curve 1 filletedpoly radiusmultiplier 0.15 
    vertexes 1 2 3 
    fillets 0 1 0   # Only middle vertex is filleted

Complete Parametric Example

# Welded portal frame with variable cross-sections

# Parameters
L := 8                    # Span
hL := 4                   # Left column height
hP := 5                   # Peak height
hR := 6                   # Right column height

alfaL := Atan((hP-hL)/(L/2))
alfaR := Atan((hP-hR)/(L/2))

# Layer
layer {Primary} color Orange

# Frame geometry
vertex 1 xyz 0 0 0
vertex 2 xyz 0 0 hL
vertex 3 xyz (L/2) 0 hP
vertex 4 xyz L 0 hR
vertex 5 xyz L 0 0

curve 1 vertex 1 2
curve 2 vertex 2 3
curve 3 vertex 3 4
curve 4 vertex 4 5

# Cross-section class
gclass {gCss} filename "css\I_profile_rotated.fcs"

# Variable cross-sections at key locations
gblock {gbCss1} gclass {gCss} lcs {Origin={0.15,0,0}, Axes=GCS.Axes} parameters {h:=0.3}
gblock {gbCss2} gclass {gCss} lcs {Origin={0,0,hL}, Axes=GCS.Axes.Ry(-alfaL/2)} parameters {h:=0.8}
gblock {gbCss3} gclass {gCss} lcs {Origin={L/2,0,hP}, Axes=GCS.Axes.Ry(PI/2)} parameters {h:=0.3}
gblock {gbCss4} gclass {gCss} lcs {Origin={L,0,hR}, Axes=GCS.Axes.Ry(PI+alfaR/2)} parameters {h:=0.8}
gblock {gbCss5} gclass {gCss} lcs {Origin={L-0.15,0,0}, Axes=GCS.Axes.Ry(PI)} parameters {h:=0.3}

# Lofted beam segments between cross-sections
traction {tBeam1} sections {gbCss1, gbCss2} layer {Primary}
traction {tBeam2} sections {gbCss2, gbCss3} layer {Primary}
traction {tBeam3} sections {gbCss3, gbCss4} layer {Primary}
traction {tBeam4} sections {gbCss4, gbCss5} layer {Primary}

Best Practices

1. Parameter Organization

Group related parameters and use descriptive names:

# Geometry parameters
BeamLength := [2.25, 2, 2, 2]
BeamCssHeights := [0.54, 0.28, 0.24, 0.28, 0.36]

# Analysis parameters
meshSize := 0.1
loadCase := "Dead"

2. Class Hierarchy

Structure components in folders:

project/
├── main.fcs
├── css/                   # Cross-sections
│   ├── I_profile.fcs
│   └── 2C_profile.fcs
├── components/            # Reusable components
│   ├── BeamPart.fcs
│   └── Connection.fcs
└── _Resources.fcs         # Shared resources

3. Conditional Instantiation

Use if to conditionally create geometry:

gblock {beam} gclass {gBeam} lcs (Lcs) if (isBeamEnabled) parameters { ... }

4. Array-Driven Distributions

Use arrays for variable repetitions:

lengths := [2.0, 2.5, 3.0, 2.5, 2.0]
distribution {d} gclass {gc} 
    transformation translation direction {1,0,0}
    repetitions count (lengths.Count)
    spacings lengths

Summary Table

Keyword Purpose
gclass Define parametric component from file
gblock Instantiate gclass with position/params
distribution Create repeated instances
traction Loft geometry between sections
layer Organize geometry, control appearance
label Create 3D text annotation
style Define visual properties
filletedpoly Polyline curve with rounded corners

Zero-Spacing Distribution (Absolute Coordinate Trick)

When each distribution segment computes its own absolute world coordinates from its index (e.g. helix, spiral staircase), you do not want the distribution to add any translation. Use an array of zeros as the spacings:

# nSeg segments; array length = nSeg - 1 (one fewer than count)
spacingIndices := Fcs.Converters.EnumerableRange(nSeg - 1)
zeroSpacings   := spacingIndices.Select(i => 0.0)

distribution {dSpring} gclass {gcSeg} lcs (GCS)
    transformation translation direction {0, 0, 1}
    repetitions count (nSeg)
    spacings (zeroSpacings)
    specialization ithparameters {idx := ith.i, R := R, dTheta := dTheta, dZ := dZ}

Inside gcSeg each segment uses idx to compute its own helix coordinates:

# HelixSegment.fcs (the gcSeg gclass)
theta0 := idx * dTheta
x0     := R * Cos(theta0)
y0     := R * Sin(theta0)
z0     := idx * dZ
vertex {vStart} xyz x0 y0 z0

Key points:


Per-Index Parameter Arrays

Use Fcs.Converters.EnumerableRange + .Select() to compute per-instance arrays for tapered or otherwise varying distributions:

# TrussTower.fcs — tapered lattice tower with nPanels panels
panelIndices := Fcs.Converters.EnumerableRange(nPanels)

# Width at bottom and top of each panel (linear taper)
panelWBots := panelIndices.Select(i => baseWidth - (baseWidth - topWidth) * i / nPanels)
panelWTops := panelIndices.Select(i => baseWidth - (baseWidth - topWidth) * (i + 1) / nPanels)

# Spacing array for distribution (uniform panel height)
panelHeights := panelIndices.Select(i => panelHeight)

distribution {dTower} gclass {gPanel} lcs (GCS)
    transformation translation direction {0, 0, 1}
    repetitions count (nPanels)
    spacings (panelHeights)
    specialization ithparameters {
        wBot   := panelWBots[ith.i],
        wTop   := panelWTops[ith.i],
        hPanel := panelHeight,
    }

The [ith.i] subscript inside ithparameters is the standard way to look up the i-th element of a pre-computed array.


Profile Orientation Reference

Cross-section profiles are defined in the local XZ plane (Y = 0, normal = local Y) by convention. The Axes= parameter on a gblock rotates that local frame into world space so the profile face is perpendicular to the intended member axis.

Member along Y (default beam axis)

No rotation needed — local Y is the beam axis, profile lies in XZ plane:

gblock {gbRoot} gclass {gXCss} lcs {Origin={0,0,0}, Axes=GCS.Axes} parameters {…}

Member along Z (vertical leg)

Rx(PI/2) rotates the local frame so local Y → global Z. The profile (still in the local XZ plane) ends up in the global XY plane — perpendicular to the Z axis:

gblock {csBot} gclass {gXCss} lcs {Origin={x, y, 0}, Axes=GCS.Axes.Rx(PI/2)} parameters {…}

Member along a slope (rafter at angle α to horizontal)

Ry(α) tilts the local Y axis from horizontal to the slope direction. The profile stays perpendicular to the rafter axis:

gblock {gbCss} gclass {gHEA} lcs {Origin={…}, Axes=GCS.Axes.Ry(roofAngle)} parameters {…}

Cladding panels (wall / roof sheets)

Wall panels in the YZ plane (X = const face, running along Y):

distribution {dWall} … lcs {Origin={0,0,0}, Axes=GCS.Axes.Rz(PI/2)} …

Roof left slope (tilt from vertical by roofAngle, then swing to Y direction):

distribution {dRoofL} … lcs {Origin={0,0,wallH}, Axes=GCS.Axes.Ry(PI/2 - roofAngle).Rz(PI/2)} …

Roof right slope (opposite tilt):

distribution {dRoofR} … lcs {Origin={span,0,wallH}, Axes=GCS.Axes.Ry(roofAngle - PI/2).Rz(PI/2)} …

Matrix form LCS (arbitrary rotation)

For profiles that require a fully arbitrary orientation, use the lcs … matrix form:

vertex {v0} xyz 0 0 0
lcs {lcsFrame} origin {v0} matrix 0 0 1 (-1) 0 0 0 (-1) 0

gblock {gb1} gclass {gHEA} lcs {lcsFrame} parameters {h=h}

The nine numbers are the rows of the 3×3 rotation matrix: [row0] [row1] [row2].


Directional Placement with Rz

Objects typically face local −Y by default (backrest / opening at +Y). Rz rotations re-orient placed instances:

# Faces +Y (object rotated 180°)
gblock {gbSW}  gclass {gcChair} lcs (GCS.Ty(swY).Rz(PI))

# Faces −X (rotate 90° clockwise when viewed from above)
gblock {gbD1}  gclass {gcChair} lcs (GCS.Tx(x).Ty(y).Rz(-PI/2))

# Faces +X (rotate 90° anticlockwise)
gblock {gbD4}  gclass {gcChair} lcs (GCS.Tx(x).Ty(y).Rz(PI/2))

# Faces −Y (default, no rotation needed)
gblock {gbD7}  gclass {gcChair} lcs (GCS.Ty(d7Y))

Imperial Unit Constants (for Benchmarking)

When validating against RISA/AISC results in US units:

ft  := 0.3048         # feet → metres
ksi := 6894757.0      # ksi  → Pa
kft := 14593.903      # kips/ft → N/m
kip := 4448.222       # kips → N
in2 := 6.4516E-4      # in²  → m²
in4 := 4.162314E-7    # in⁴  → m⁴

Power Operator

FCS supports the ** operator for exponentiation (in addition to Pow()):

rafterLength := Sqrt(halfSpan**2 + ridgeRise**2)