Three-Dimensional Projective Space & Plücker Lines
Part 0 built the projective plane: homogeneous coordinates, the rule that scale doesn't matter, and the point/line duality that makes cross products do all the work. But photographs are of the real world, so the objects we ultimately care about are 3D points, and the maps that turn them into pixels are maps P³ → P². This page does the same job for three dimensions. It generalizes point/plane duality to P³, then gives 3D lines a concrete, computable representation — Plücker coordinates (d, m) — that we can carry through matrices, transform, and project into an image with a single cross product.
Why P³
Motivation
Suppose you have two photographs of the same object and want its shape. Every point you want to recover lives in 3D; every measurement you actually have lives in a 2D image; and the object connecting the two — a camera — is a map from 3D points to 2D points. That is three different dimensions of geometry talking to each other, and the clean language for all of it is projective space one dimension up from Part 0: P³.
Three concrete needs make P³ unavoidable in what follows:
1. Reconstruction needs 3D points. Triangulation (Part 10), PnP (Part 11) and bundle adjustment (Part 15) all take 2D image measurements back to a 3D point X̃ = (X, Y, Z, W). The whole point of the series is to recover these, so their space has to come first.
2. A camera is a map P³ → P². Part 4's camera matrix is 3×4, literally a linear map from 4-vectors to 3-vectors. You cannot write that map down, or reason about its null space (the camera center), without knowing what a 3D projective point is.
3. Lines in space are the awkward object. Lots of real features are lines — building edges, lane markings, poles, the edges of a cube. A 3D line has no single obvious coordinate vector the way a point or a plane does. It needs a dedicated representation, and that representation (Plücker coordinates) is exactly what the trifocal tensor (Part 12) and line-based structure from motion are built on.
d · m = 0. Nothing here depends on a camera yet — it is pure geometry, ready for Part 4 to project.Points, planes, and incidence in P³
The duality, one dimension up
A point in P³ is a homogeneous 4-vector X̃ = (X, Y, Z, W), defined up to scale, exactly as in Part 0. A plane is also a 4-vector π = (π₁, π₂, π₃, π₄), and the plane is the set of points satisfying the incidence equation:
That is exactly Part 0's point-on-line rule l · x̃ = 0, with one more coordinate. In P² a point and a line are both 3-vectors related by a dot product; in P³ a point and a plane are both 4-vectors related by a dot product. This symmetry is the whole game: P³ has a duality between points and planes, and in this dimension a plane plays the role that a line played in P².
Everything Part 0 got from cross products has a P³ analogue, computed with a 4×4 determinant / generalized cross product:
meet: intersection of two planes π₁, π₂ → a line (a 2-dimensional subspace of the 4-vector space)
plane through two points and a line, or three planes meeting in a point — all determinant constructions
(The plane-through-three-points formula is the generalized cross product: πᵢ is the 3×3 minor of the 4×3 matrix whose columns are the three points, taken with an alternating sign, so that π is orthogonal to all three points at once — the same reason x̃₁ × x̃₂ was orthogonal to both points in Part 0.)
The plane at infinity. The special plane π∞ = (0, 0, 0, 1) acts on a point by reading off its last coordinate: π∞ · X̃ = W. So a point lies on the plane at infinity precisely when W = 0. Those are the ideal points — points at infinity — one for each 3D direction: a Euclidean direction d corresponds to the ideal point X̃∞ = (d, 0). Part 4 uses this directly: projecting an ideal point makes the camera's translation drop out and produces a vanishing point, v = K R d. The plane at infinity is also the object that separates a projective reconstruction from an affine one (Part 16).
Lines. A line is the intersection (meet) of two planes, which as a set is { X̃ : π₁ · X̃ = 0 and π₂ · X̃ = 0 } — a 2-dimensional subspace of the 4-dimensional vector space. It is not naturally a 4-vector like a point or plane; the set of all such 2-subspaces is the Grassmannian Gr(2, 4), whose dimension is 2 × (4 − 2) = 4. So a line in P³ has 4 degrees of freedom — and the rest of this page is about giving those 4 DOF usable coordinates.
Plücker coordinates for a line
A concrete representation, and its one constraint
Take a line in P³ and pick two distinct points on it, written in homogeneous form as X̃₁ = (X₁, W₁) and X̃₂ = (X₂, W₂), where each Xᵢ is the Euclidean 3-vector part and Wᵢ is the last coordinate. Define the pair
m = X₁ × X₂ (— the line’s moment)
This is the convention used throughout this page: d is the direction, m is the moment (the 3-vector cross product of the two Euclidean point parts), and for finite points (W₁ = W₂ = 1) this simplifies to d = X₂ − X₁ and m = X₁ × X₂, which is the familiar geometry: the direction along the line, and the position of the line encoded by the cross product of two of its points.
The pair (d, m) is defined only up to a common scale — scaling both points equally, or choosing different points on the same line, rescales (d, m) together. And the two 3-vectors are not independent. They satisfy the Plücker relation:
because a triple product with a repeated vector is always zero. This is the only equation the pair must obey, and it has a clean counting consequence:
Six numbers, one scale redundancy, one constraint — exactly the 4 degrees of freedom a line in P³ has, matching the Grassmannian count from Step 1. The set of all (d, m) in P⁵ satisfying d · m = 0 is a quadric hypersurface called the Klein quadric, and every point of it corresponds to exactly one line in P³.
Dual form (line as the meet of two planes). The same recipe runs on plane coordinates. Two planes π = (π₀, π₄) and σ = (σ₀, σ₄) (each with a Euclidean normal 3-vector and a constant) meet in a line, and its Plücker matrix is L* = πσᵀ − σπᵀ, the formal dual of the point-based matrix below. In the dual, the direction comes from the normals and the moment from the plane constants, and the same constraint d · m = 0 holds.
The Plücker matrix. The most compact bookkeeping device is the skew 4×4 matrix
It is skew-symmetric and rank 2, and it stores the line without any explicit parameterization. Its 2-dimensional column space is precisely the line, i.e. the span of X̃₁ and X̃₂ — so X̃ lies on the line exactly when X̃ is in the column space of L. Its null space is the pencil of planes through the line, so the matrix tests incidence on planes directly:
π contains the line ⇔ L π = 0
(L π = 0 holds precisely when π · X̃₁ = π · X̃₂ = 0, i.e. when plane π passes through both defining points. Note that incidence is tested on the left by planes, not by points — the left action of L annihilates planes through the line.)
How the line transforms. Apply a 3D projective map H (a 4×4 matrix) to the whole space. The image line is spanned by H X̃₁ and H X̃₂, so its Plücker matrix is
For the 6-vector (d, m), the answer is not simply d′ = H d — d is a 3-vector and H is 4×4, so that product does not even type-check. The pair transforms linearly by the exterior square (“compound matrix”) ∧²H, a 6×6 matrix induced by H on the 2-forms. In the common cases it simplifies to something you can read off. For an affine map H = [[A, b], [0, 1]] (rotation, translation, and non-uniform scale, no projective part):
m′ = det(A) A⁻ᵀ m + b × (A d)
and for a pure rigid motion (A = R a rotation, b = t, det R = 1) this becomes d′ = R d and m′ = R m + t × (R d): the direction simply rotates, while the moment picks up a translation term. In all cases the Plücker relation is preserved automatically, because H L Hᵀ is still skew of rank 2, hence still a valid line.
Projecting a line to an image line. Finally, the operation the rest of the series needs: given a camera P (3×4), a 3D line with two points X̃₁, X̃₂ projects to the image line through the two projected points, computed by Part 0's cross product:
One caveat carries real weight later: if the 3D line passes through the camera center, the two projected points coincide and l = 0. That is not a bug — the line is seen exactly edge-on, as a single pixel, and has no well-defined image line. Away from that degenerate case, every point of the 3D line projects onto l, which is the transfer that line-based multi-view methods rely on.
Play: a draggable 3D line and its Plücker coordinates
Interactive
(d, m) from the drawn endpoints every time you move a slider, and d · m comes out zero — not by luck, but because any pair built as (X₂ − X₁, X₁ × X₂) satisfies the Plücker relation identically. Move the line anywhere in the cube: the constraint never breaks.The 3D scene shows the world axes, a translucent reference cube, and an orange segment whose two endpoints you control with the six sliders. Two synthetic cameras watch the line: camera 1 sits at the world origin with identity rotation (its optical axis is the world +z axis, the OpenCV-style “z-forward” convention this series uses), and camera 2 has a modest rotation and a translation, positioned so it looks back at the scene. Each camera's image plane is drawn as a translucent square one unit in front of it, and the line's projected image is drawn on that plane. Both cameras are full 3×4 projection matrices P = K[R | −RC] computed live in JavaScript.
Drag to orbit the 3D scene, scroll to zoom. Faint square = a camera's image plane; the colored segment on it is the projected image line.
Watch two things. First, d · m always reads a numerical zero (something like 1e-16) no matter how you drag the line — that is the Plücker constraint, holding identically. Second, the two image lines' coefficients l₁ and l₂ change completely as the line moves, yet each one stays orthogonal to its own projected endpoints: l · (P X̃) = 0. That is Part 0's incidence equation reappearing inside a camera, and it confirms the projection and the drawing are numerically the same thing. Untick “Project into two views” to hide the image planes and see the 3D line on its own.
Cheat sheet
Recap
| Quantity | Expression | Where it resurfaces |
|---|---|---|
| 3D point | X̃ = (X, Y, Z, W) ∈ P³ | Every P X̃ (Part 4); triangulation (Part 10); bundle adjustment (Part 15) |
| Plane | π = (π₁, π₂, π₃, π₄) | Homography induced by a plane (Part 8); plane fitting in reconstruction |
| Incidence | π · X̃ = 0 | Part 0's l · x̃ = 0 one dimension up; plane & line tests everywhere |
| Plane through 3 points | generalized cross product (4×4 minors) | Horizon / vanishing constructions; fitting planes to reconstructed points |
| Plane at infinity | π∞ = (0, 0, 0, 1); ideal points have W = 0 | Vanishing points (Part 4); projective → affine → metric upgrade and self-calibration (Part 16) |
| Line as meet of 2 planes | { X̃ : π₁·X̃ = π₂·X̃ = 0 } | Line reconstruction; the trifocal tensor (Part 12) |
| Plücker pair | d = W₁X₂ − W₂X₁, m = X₁ × X₂ | Line features in SLAM / SfM; line-based triangulation; trifocal tensor (Part 12) |
| Constraint | d · m = 0 (Klein quadric in P⁵) | Enforcing that a 6-vector is a valid line during estimation |
| DOF | 6 − 1 (scale) − 1 (constraint) = 4 | Minimal line parameterization for nonlinear optimization (Part 15) |
| Plücker matrix | L = X̃₁X̃₂ᵀ − X̃₂X̃₁ᵀ, skew rank 2; Lπ = 0 ⇔ π ∋ line | Incidence tests; line-plane transfer; transform L′ = HLHᵀ |
| Image of a line | l = (P X̃₁) × (P X̃₂) | Line features across views; line-based SfM; degenerate when the line passes through the camera center |
P = K[R|t] whose center is the null space of P, and whose back-projection inverts the lost depth.
Continue: the pinhole camera →