2.5.7.4. Station math

2.5.7.4.1. Internal raw distance vs displayed station

The horizontal-geometry engine carries two related but distinct parameters along the centreline:

  • Raw distance s ∈ [0, TotalLength] — the actual arc length from the start of the geometry. This is what the chain of elements is parameterised by; PointAtDistance(s) is exact.

  • Station (displayed chainage) — the value users / drawings reference. It begins at StartStation and equals StartStation + s if no station equations are present; when equations are present, the mapping is piecewise.

The forward mapping raw ➜ station is RawToStation:

\[\begin{split}\text{Station}(s) = \text{StartStation} + s + \sum_{\substack{e \in \text{equations} \\ s \ge e.\text{RawStation}}} (e.\text{StationAhead} - e.\text{StationBack})\end{split}\]

— that is, the start-station offset plus the raw distance plus the cumulative jump of every equation whose raw position has been reached.

The reverse mapping station ➜ raw is StationToRaw: a true piecewise inverse of the forward mapping. Walk equations sorted by RawStation, accumulate offset, stop in the segment whose displayed-station range contains the query value:

cum := 0
for each eq in (equations sorted by RawStation):
   boundaryStation := StartStation + eq.RawStation + cum
   if Station ≤ boundaryStation: break
   cum += (eq.StationAhead - eq.StationBack)
raw := Station - StartStation - cum
clamp raw to [0, TotalLength]

The ≤ (not strict <) at the boundary is deliberate — it means both the back station value and the ahead station value of an equation map to the same raw distance (eq.RawStation), i.e. the same physical point on the alignment. Without it, Setout(back) and Setout(ahead) would give different X/Y for what is one physical equation point.

2.5.7.4.2. Why this matters everywhere

Every alignment query that takes a “station” must convert through StationToRaw first. The engine does:

  • PointAtStation / DirectionAtStation / CurvatureAtStation — Setout / MeasureOffset / drawing trace use StationToRaw to find the right element and the local distance within it.

  • Vertical profile lookup — the PVI/VC table is keyed by chainage but the physical point is defined by raw distance. To get a single unique elevation at an equation point the engine queries the profile at the continuous chainage StartStation + StationToRaw(Station) — i.e. it removes equation jumps before looking up. Back and ahead therefore collapse to the same vertical entry.

  • Cross-section collections — superelevation, widening, horizontal/vertical offset, cant: queried the same way through ContinuousChainage(Station) = StartStation + StationToRaw(Station).

So adding a station equation does not require redesigning the vertical profile or the cross-section tables; the engine automatically resolves the displayed station to its physical location.

2.5.7.4.3. End station

The end-station displayed in the status bar (and the default Batch Setout To field) is Engine.HGeometry.EndStation which is defined as

\[\text{EndStation} = \text{RawToStation}(\text{TotalLength}).\]

It naturally includes every equation offset, so after adding an equation that adds +10 000 to all downstream chainages, the end station immediately rises by +10 000 — no separate “rebuild” is needed.

2.5.7.4.4. Where the math is implemented

In source:

  • UAECAlignmentGeometry.pas — RawToStation, StationToRaw, FormatStation (1000-based k+mmm.ddd formatting), and the station-equation storage / API (StationEquationCount, GetStationEquation, AddStationEquation, ClearStationEquations).

  • AlignmentEngine.pas — ContinuousChainage(Station) is the one private helper used at every vertical / cross-section lookup site (Measure, MeasureOffset, Setout, SetoutOffset, SetoutRail, Setout3D, etc.) so back ≡ ahead at the equation point.

For the user-facing introduction to station equations (back / ahead semantics, when to use them, the editor UX), see StationEquations.