<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. BIM Math
  3. Lines and curves
All lessons in this course

Lesson 12 of 44 13 minIntermediate

Lines, rays and segments in parametric form

One formula, P(t) = A + t·d, describes a line, a ray and a segment: only the allowed range of t changes. Learn to read t, to walk along a wall by distance, and why BIM tools never use y = mx + c.

At school a line is y = mx + c. Geometry software almost never uses that form. It cannot describe a vertical line (m would be infinite), and in a plan, north–south walls are everywhere. It also has no simple 3D version. Instead, software uses the parametric form: a start point plus a multiple of a direction.

P(t) = A + t·d. With d = B − A, the number t says how far along you are: t = 0 is A, t = 1 is B, t = 0.5 is the midpoint, t = 2 is as far past B as B is from A, and a negative t is behind A. Switch between line, ray and segment and watch which values of t are allowed.

Interactive

P(t) = A + t·(B − A)

Move the t slider, and drag A and B (or focus one and use the arrow keys).

t=0t=1PAB
d = B − A⟨4, 3⟩
t × d⟨2, 1.5⟩
P = A + t × d(−1, −0.5)
distance from A2.50
allowed t0 ≤ t ≤ 1
on the segment?yes
t = 0.5 is the midpoint: half of d added to A.

One formula, three shapes

ShapeAllowed tIn a BIM model
Lineany tgrid lines, reference planes seen in plan, axes of symmetry
Rayt ≥ 0a pick ray from the mouse, a line of sight, the ray in a point-in-polygon test
Segment0 ≤ t ≤ 1a wall’s location line, a pipe or duct run, a beam, a dimension

This is why the Revit API has a single Line class with Line.CreateBound(p1, p2) and Line.CreateUnbound(origin, direction), and a Curve.IsBound property. A bound line is a segment and an unbound one is infinite: the same formula with a different range of t.

Two choices of direction

Direction dt meansB is atUse it when you think in
B − Aa fraction of the way from A to Bt = 1proportions: the midpoint, thirds, 40% along
the unit vector ua distance from A, in model unitst = |B − A|distances: a door 1.2 m from the corner, a hanger every 1.5 m

The samples in this module use a small V2 struct, the 2D cousin of the Vec3 from the last module. It is repeated at the bottom of each sample, so every sample runs on its own.

Stations.cs
var a = new V2(2, 1);var b = new V2(10, 7);V2 d = b - a;                             // (8, 6): a 10 m wall foreach (double t in new[] { 0, 0.25, 0.5, 1, 1.5 })    Console.WriteLine($"t = {t,-4}  P = {a + d * t}"); V2 u = d * (1 / d.Length);                // unit direction (0.8, 0.6)Console.WriteLine($"1.2 m along: {a + u * 1.2}");Console.WriteLine($"3 m along:   {a + u * 3}"); readonly record struct V2(double X, double Y){    public static V2 operator +(V2 a, V2 b) => new(a.X + b.X, a.Y + b.Y);    public static V2 operator -(V2 a, V2 b) => new(a.X - b.X, a.Y - b.Y);    public static V2 operator *(V2 v, double k) => new(v.X * k, v.Y * k);    public static double Dot(V2 a, V2 b) => a.X * b.X + a.Y * b.Y;    public static double Cross(V2 a, V2 b) => a.X * b.Y - a.Y * b.X;    public double Length => Math.Sqrt(X * X + Y * Y);    public override string ToString() => $"({X:0.###}, {Y:0.###})";}
Output
t = 0     P = (2, 1)
t = 0.25  P = (4, 2.5)
t = 0.5   P = (6, 4)
t = 1     P = (10, 7)
t = 1.5   P = (14, 10)
1.2 m along: (2.96, 1.72)
3 m along:   (4.4, 2.8)

Finding t for a point

The reverse question comes up just as often: here is a point on the wall, how far along is it? Take the step from A to the point and project it onto d with the dot product: t = (Q − A)·d ÷ (d·d). With d = B − A, comparing t with 0 and 1 then tells you whether the point is behind A, on the wall, or past B.

WhereOnTheWall.cs
var a = new V2(2, 1);var b = new V2(10, 7);V2 d = b - a; foreach (var q in new V2[] { new(6, 4), new(14, 10), new(-2, -2) }){    double t = V2.Dot(q - a, d) / V2.Dot(d, d);    string where = t < 0 ? "behind A" : t > 1 ? "past B" : "on the wall";    Console.WriteLine($"{q}: t = {t}, {where}");} readonly record struct V2(double X, double Y){    public static V2 operator +(V2 a, V2 b) => new(a.X + b.X, a.Y + b.Y);    public static V2 operator -(V2 a, V2 b) => new(a.X - b.X, a.Y - b.Y);    public static V2 operator *(V2 v, double k) => new(v.X * k, v.Y * k);    public static double Dot(V2 a, V2 b) => a.X * b.X + a.Y * b.Y;    public static double Cross(V2 a, V2 b) => a.X * b.Y - a.Y * b.X;    public double Length => Math.Sqrt(X * X + Y * Y);    public override string ToString() => $"({X:0.###}, {Y:0.###})";}
Output
(6, 4): t = 0.5, on the wall
(14, 10): t = 1.5, past B
(-2, -2): t = -0.5, behind A

These three points lie exactly on the line. A point that is slightly off it still gets a t: the t of the nearest point on the line. That is the subject of the next lesson.

Lines in 3D: nothing changes

The formula is the same with three coordinates. A sloping drain, a ramp and a ray from the camera into the model are all A + t·d. Here is the invert level of a drain at 5 m intervals, between a manhole and an outfall 0.5 m lower and 20 m away (a 1 in 40 fall):

DrainFall.cs
var start = new V3(0, 0, 3.0);            // invert level at the manholevar end = new V3(20, 0, 2.5);             // 0.5 m lower, 20 m away: a 1:40 fallV3 d = end - start; for (double x = 0; x <= 20; x += 5){    V3 p = start + d * (x / d.X);         // t from the horizontal distance    Console.WriteLine($"Station {x,2} m: invert {p.Z:F3} m");} readonly record struct V3(double X, double Y, double Z){    public static V3 operator +(V3 a, V3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z);    public static V3 operator -(V3 a, V3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z);    public static V3 operator *(V3 v, double k) => new(v.X * k, v.Y * k, v.Z * k);    public static double Dot(V3 a, V3 b) => a.X * b.X + a.Y * b.Y + a.Z * b.Z;    public double Length => Math.Sqrt(Dot(this, this));    public override string ToString() => $"({X:0.###}, {Y:0.###}, {Z:0.###})";}
Output
Station  0 m: invert 3.000 m
Station  5 m: invert 2.875 m
Station 10 m: invert 2.750 m
Station 15 m: invert 2.625 m
Station 20 m: invert 2.500 m
Quick check

P(t) = A + t(B − A). Which t gives the point one third of the way back from B towards A?

Quick check

Why do BIM tools avoid y = mx + c for walls?

Practice

A sloping beam runs from (1, 2, 3) to (9, 2, 9). Write PointAt(a, b, s) that returns the point s metres along the beam, measured along its own length. Print the beam’s length and a bolt position every 2.5 m from one end to the other.

Show a hint

Divide d = b − a by its length to get the unit direction, then multiply by s. The beam is 10 m long (8 across and 6 up), so the bolts are at s = 0, 2.5, 5, 7.5 and 10.

Show the solution
Solution.cs
var a = new V3(1, 2, 3);var b = new V3(9, 2, 9);double length = (b - a).Length;Console.WriteLine($"Length: {length} m"); for (double s = 0; s <= length + 1e-9; s += 2.5)    Console.WriteLine($"{s,4} m: {PointAt(a, b, s)}"); static V3 PointAt(V3 a, V3 b, double s){    V3 d = b - a;    return a + d * (s / d.Length);        // unit direction times distance} readonly record struct V3(double X, double Y, double Z){    public static V3 operator +(V3 a, V3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z);    public static V3 operator -(V3 a, V3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z);    public static V3 operator *(V3 v, double k) => new(v.X * k, v.Y * k, v.Z * k);    public static double Dot(V3 a, V3 b) => a.X * b.X + a.Y * b.Y + a.Z * b.Z;    public double Length => Math.Sqrt(Dot(this, this));    public override string ToString() => $"({X:0.###}, {Y:0.###}, {Z:0.###})";}
Output
Length: 10 m
   0 m: (1, 2, 3)
 2.5 m: (3, 2, 4.5)
   5 m: (5, 2, 6)
 7.5 m: (7, 2, 7.5)
  10 m: (9, 2, 9)

Remember

  • A line in parametric form is P(t) = A + t·d: a start point plus a multiple of a direction.
  • Line, ray and segment are the same formula; t is unrestricted, t ≥ 0, or 0 ≤ t ≤ 1.
  • With d = B − A, t is a fraction of the way; with a unit d, t is a distance in model units.
  • Find the t of a point with a projection: t = (Q − A)·d ÷ (d·d).
  • It works unchanged in 3D, and it handles vertical lines that y = mx + c cannot.
0 of 44 lessons completed