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

Lesson 18 of 44 13 minIntermediate

Planes: point and normal, ax + by + cz + d

A plane is a flat surface that goes on for ever: a floor level, a wall face, a roof slope, a section cut. Store it as a point and a normal, or as four numbers a, b, c and d, and build one from three points.

Levels, wall faces, roof slopes, work planes and section cuts are all planes: flat surfaces that go on for ever in every direction. A BIM model is full of them, and most 3D questions (“how high is the roof here?”, “where does this pipe cross the slab?”) start with one.

A plane needs just two things: a point P0 on it and a normal n, a vector at right angles to it. Change the normal’s tilt and direction and the value d below, and watch how the equation changes.

Interactive

A plane: normal and d

XYZP0n
n = (a, b, c)(0, 0, 1)
|n|1.000
equationz − 3 = 0
P0 = −d × n(0, 0, 3)
n·P0 + d0.000
distance from origin|d| = 3.00
This plane is horizontal: a floor, ceiling or level. Every point X on it satisfies n·X + d = 0. Because n is a unit vector, |d| = 3.00 is the plane’s distance from the origin, and P0 = −d × n is its closest point to the origin.

Point and normal

A point X is on the plane when the step from P0 to X lies flat in the plane, which means it is at right angles to the normal: (X − P0)·n = 0. This is the dot-product test for “perpendicular” from the Vectors module.

The equation ax + by + cz + d = 0

Multiply out (X − P0)·n = 0 and you get n·X − n·P0 = 0. Write n = (a, b, c) and d = −n·P0, and it becomes ax + by + cz + d = 0. Four numbers describe the whole plane. If n is a unit vector, they mean something useful:

  • (a, b, c) is the direction the plane faces.
  • |d| is the plane’s distance from the origin, and −d·n is its closest point to the origin (P0 in the widget).
  • Putting any point into ax + by + cz + d gives its signed distance from the plane. That is the subject of the next lesson.
PlaneUnit normal (a, b, c)dEquation
Level 2 floor at 3.6 m(0, 0, 1)−3.6z − 3.6 = 0
Wall face along X at y = 5(0, 1, 0)−5y − 5 = 0
Roof rising north at 36.87° from eaves at z = 3(0, −0.6, 0.8)−2.4−0.6y + 0.8z − 2.4 = 0
Section cut at x = 12(1, 0, 0)−12x − 12 = 0

A plane from three points

Survey data and modelling tools often give a plane as three points on it, such as three corners of a roof. Two edges from the first point lie in the plane, so their cross product is a normal. Normalise it, then d = −n·A.

PlaneFromPoints.cs
var a = new V3(0, 0, 3);                  // eaves, one endvar b = new V3(10, 0, 3);                 // eaves, other endvar c = new V3(0, 4, 6);                  // a point on the ridge V3 n = V3.Cross(b - a, c - a).Normalized();double d = -V3.Dot(n, a);Console.WriteLine($"n = {n}, d = {d:0.###}");Console.WriteLine($"Pitch {Math.Acos(n.Z) * 180 / Math.PI:F2} deg"); foreach (var q in new V3[] { new(5, 2, 4.5), new(5, 2, 5) }){    double s = V3.Dot(n, q) + d;    Console.WriteLine($"{q}: {(Math.Abs(s) < 1e-9 ? "on the roof plane" : "off the plane")}");} 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 static V3 Cross(V3 a, V3 b) =>        new(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);    public double Length => Math.Sqrt(Dot(this, this));    public V3 Normalized() => this * (1 / Length);    public override string ToString() => $"({X:0.###}, {Y:0.###}, {Z:0.###})";}
Output
n = (0, -0.6, 0.8), d = -2.4
Pitch 36.87 deg
(5, 2, 4.5): on the roof plane
(5, 2, 5): off the plane

The pitch comes free: the angle between the roof’s normal and straight up equals the angle between the roof and the horizontal, and n·(0, 0, 1) is just n.z.

Which way does the normal point?

n and −n describe the same plane, with d changing sign. The choice still matters, because it says which side is “in front”. BIM and mesh formats use one convention: face normals point out of the solid, so a floor’s top face points up and a wall’s exterior face points outdoors. The order of the three points sets the direction: seen from the side the normal points to, A → B → C runs counterclockwise. The polygon-winding lesson in this module builds on that.

Quick check

What is the plane z − 3.6 = 0?

Quick check

n = (0, 0, 1) with d = −3, and n = (0, 0, −1) with d = 3. What are they?

Practice

A wall face runs at 45° in plan through the point (2, 0, 0), with normal (1, 1, 0). Normalise the normal, compute d, and test whether the points (0, 2, 5) and (2, 2, 0) lie on the face, with a tolerance of 1e-6. For a point that is off it, print how far off it is.

Show a hint

n = (1, 1, 0) ÷ √2 and d = −n·(2, 0, 0). Because n is a unit vector, n·q + d is the distance itself.

Show the solution
Solution.cs
var p0 = new V3(2, 0, 0);V3 n = new V3(1, 1, 0).Normalized();double d = -V3.Dot(n, p0);Console.WriteLine($"n = {n}, d = {d:0.###}"); foreach (var q in new V3[] { new(0, 2, 5), new(2, 2, 0) }){    double s = V3.Dot(n, q) + d;    Console.WriteLine(Math.Abs(s) < 1e-6 ? $"{q}: on the plane" : $"{q}: {s:0.###} m off");} 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 static V3 Cross(V3 a, V3 b) =>        new(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);    public double Length => Math.Sqrt(Dot(this, this));    public V3 Normalized() => this * (1 / Length);    public override string ToString() => $"({X:0.###}, {Y:0.###}, {Z:0.###})";}
Output
n = (0.707, 0.707, 0), d = -1.414
(0, 2, 5): on the plane
(2, 2, 0): 1.414 m off

Remember

  • A plane is a point P0 and a normal n; X is on it when (X − P0)·n = 0.
  • Expanded, that is ax + by + cz + d = 0 with (a, b, c) = n and d = −n·P0.
  • With a unit normal, |d| is the distance from the origin and ax + by + cz + d is a signed distance.
  • Three points give a plane: n = (B − A) × (C − A), normalised; check for collinear points first.
  • n and −n give the same plane; by convention, face normals point out of the solid.
0 of 44 lessons completed