Skip to content
The Lumenary
Advanced undergraduateUndergraduate 115 min

Projective geometry

The geometry of perspective, where parallel lines meet at the horizon. Points at infinity, homogeneous coordinates, a perfect duality between points and lines, the theorems of Desargues and Pappus, the cross-ratio — and why every conic is a circle in disguise.

Formally verified · 14 LeanComputationally tested · 2 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review
MotivationH

What a camera keeps

Stand between the rails of a straight railway line in the Karoo and look along it. The rails, which never meet, appear to converge to a point on the horizon. The sleepers, laid exactly one metre apart, appear closer and closer together. A broadcast camera above a football pitch in Buenos Aires does the same thing to the touchlines and the penalty box: lengths, angles and parallelism are all distorted.

Yet some things survive every photograph. Straight lines stay straight. Points on a line stay on a line, and lines through a point still pass through a point. And a less obvious quantity survives too: from four points on a line one can compute a number, the cross-ratio, that is the same on the ground and in the picture. Sports-analytics software uses exactly these invariants to recover the true positions of players from television images, and photogrammetry uses them to measure buildings from photographs.

Projective geometry is the geometry of what perspective preserves. To make it work, we must give parallel lines a place to meet: a point at infinity for each direction, all lying on a line at infinity — the horizon. The reward is a geometry of remarkable symmetry, in which every theorem comes with a free twin, and in which ellipses, parabolas and hyperbolas turn out to be the same curve seen from different places.

vanishing pointhorizon
Perspective: parallel rails meet at a vanishing point on the horizon, and equally spaced sleepers appear ever closer together. Distances are not preserved, but the cross-ratio of any four sleepers is.
IntuitionH

Lines through the eye

Put your eye at the origin of R3\R^3 and hold a transparent picture plane at height z=1z = 1. Each point (x,y)(x, y) of the picture is seen along a line through the eye, the line through (x,y,1)(x, y, 1). So points of the picture are lines through the origin. A line in the picture, together with the eye, spans a plane through the origin, so lines of the picture are planes through the origin.

Now the lines through the eye that are horizontal — parallel to the picture plane — never meet it. They are perfectly good lines through the origin, so we add them as new points: the points at infinity, one for each horizontal direction, and together they form a new line, the horizontal plane through the eye, which is the line at infinity. Two parallel lines in the picture span two planes through the eye whose intersection is a horizontal line: they now meet, at a point at infinity, exactly as the rails meet on the horizon.

This is the real projective plane RP2\R P^2: the set of lines through the origin in R3\R^3. Linear algebra on R3\R^3 becomes geometry on RP2\R P^2. Two distinct lines through the origin span a plane: two points determine a line. Two distinct planes through the origin meet in a line: two lines determine a point, with no exception for parallels. The two statements are twins, and that symmetry runs through the whole subject.

DefinitionsH

Definitions

Throughout, KK is a field, usually R\R.

Definition— projective space, homogeneous coordinates

The projective space KPnKP^n is the set of one-dimensional subspaces of Kn+1K^{n+1}. The line through a non-zero vector (x0,…,xn)(x_0, \dots, x_n) is written [x0:⋯:xn][x_0 : \dots : x_n]; these are its homogeneous coordinates, determined up to a non-zero scalar: [x0:⋯:xn]=[λx0:⋯:λxn][x_0 : \dots : x_n] = [\lambda x_0 : \dots : \lambda x_n] for λ≠0\lambda \ne 0.

Definition— affine chart and line at infinity

In RP2\R P^2 the points [x:y:z][x : y : z] with z≠0z \ne 0 form the affine chart {[x:y:1]}≅R2\{[x : y : 1]\} \cong \R^2. The remaining points [x:y:0][x : y : 0] form the line at infinity; [x:y:0][x : y : 0] is the point at infinity in the direction of (x,y)(x, y).

Definition— lines and incidence

A line of RP2\R P^2 is the set of points of a two-dimensional subspace of R3\R^3, that is, {[x:y:z]:ax+by+cz=0}\{[x : y : z] : ax + by + cz = 0\} for some (a,b,c)≠0(a, b, c) \ne 0, itself defined up to scale. We write the line as [a:b:c][a : b : c] too. The point pp lies on the line ℓ\ell (they are incident) exactly when ℓ⋅p=0\ell \cdot p = 0. Points are collinear if they lie on a common line; lines are concurrent if they pass through a common point. Four points are in general position if no three are collinear.

Definition— projective transformation

An invertible matrix A∈GL3(R)A \in GL_3(\R) induces a bijection [v]↦[Av][v] \mapsto [Av] of RP2\R P^2, a projective transformation. Since AA and λA\lambda A induce the same map, the group of projective transformations is PGL3(R)=GL3(R)/R×PGL_3(\R) = GL_3(\R)/\R^\times. On the projective line RP1=R∪{∞}\R P^1 = \R \cup \{\infty\}, the matrix (abcd)\begin{pmatrix} a & b \\ c & d \end{pmatrix} acts in the affine coordinate by the Möbius transformation x↦(ax+b)/(cx+d)x \mapsto (ax + b)/(cx + d), with −d/c↦∞-d/c \mapsto \infty and ∞↦a/c\infty \mapsto a/c.

Definition— cross-ratio

The cross-ratio of four distinct collinear points with affine coordinates a,b,c,da, b, c, d on a line is

(a,b;c,d)=(a−c)(b−d)(a−d)(b−c).(a, b; c, d) = \frac{(a - c)(b - d)}{(a - d)(b - c)}.

In homogeneous coordinates a=[a1:a2]a = [a_1 : a_2] etc. on RP1\R P^1, with the bracket [p q]=p1q2−p2q1[p\,q] = p_1 q_2 - p_2 q_1, it is (a,b;c,d)=[a c][b d][a d][b c](a, b; c, d) = \dfrac{[a\,c][b\,d]}{[a\,d][b\,c]}, which also makes sense when one point is ∞=[1:0]\infty = [1 : 0]. (Several conventions are in use; they differ by reordering the points.)

Definition— conic

A conic in RP2\R P^2 is the zero set of a quadratic form Q(x)=xTMxQ(\mathbf x) = \mathbf x^{\mathsf T} M \mathbf x, with MM a symmetric 3×33 \times 3 matrix; it is non-degenerate if det⁡M≠0\det M \ne 0. In the chart z=1z = 1, Q=0Q = 0 is a second-degree equation Ax2+Bxy+Cy2+Dx+Ey+F=0Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0.

Worked examplesH

Examples and non-examples

Example— Parallel lines meet at infinity

In the chart, y=2x+1y = 2x + 1 is 2x−y+z=02x - y + z = 0, the line [2:−1:1][2 : -1 : 1], and y=2x−3y = 2x - 3 is [2:−1:−3][2 : -1 : -3]. Their common point is the cross product (Theorem 1 below):

(2,−1,1)×(2,−1,−3)=((−1)(−3)−1⋅(−1),  1⋅2−2⋅(−3),  2⋅(−1)−(−1)⋅2)=(4,8,0),(2, -1, 1) \times (2, -1, -3) = \big((-1)(-3) - 1 \cdot (-1),\; 1 \cdot 2 - 2 \cdot (-3),\; 2 \cdot (-1) - (-1) \cdot 2\big) = (4, 8, 0),

so they meet at [4:8:0]=[1:2:0][4 : 8 : 0] = [1 : 2 : 0], the point at infinity in the direction (1,2)(1, 2) of slope 22. The opposite direction (−1,−2)(-1, -2) gives the same point [−1:−2:0]=[1:2:0][-1 : -2 : 0] = [1 : 2 : 0]: a line has one point at infinity, not two.

Example— The line through a point and a direction

The line through (1,0)=[1:0:1](1, 0) = [1 : 0 : 1] and the vertical point at infinity [0:1:0][0 : 1 : 0] is (1,0,1)×(0,1,0)=(−1,0,1)(1, 0, 1) \times (0, 1, 0) = (-1, 0, 1), the line −x+z=0-x + z = 0, i.e. x=1x = 1 in the chart — the vertical line through (1,0)(1, 0), as it should be.

Example— What the projective line and plane look like

RP1\R P^1 is a circle: a line through the origin of R2\R^2 is determined by where it crosses the upper half of the unit circle, and the two ends of the half-circle (the horizontal line) are the same point. Equivalently, RP1=R∪{∞}\R P^1 = \R \cup \{\infty\} with the two "ends" of R\R joined at ∞\infty. RP2\R P^2 is the upper hemisphere with antipodal points of the equator identified, or a disc with opposite boundary points glued. It is a closed surface that cannot be embedded in R3\R^3 and is non-orientable: a neighbourhood of the line at infinity is a Möbius band.

Example— A finite projective plane

Over the field F2={0,1}\mathbb F_2 = \{0, 1\}, the plane F2P2\mathbb F_2 P^2 has 23−1=72^3 - 1 = 7 points and 77 lines, each line containing 33 points and each point on 33 lines: the Fano plane. Over Fp\mathbb F_p there are p2+p+1p^2 + p + 1 points, with p+1p + 1 on each line; the second experiment checks the incidence axioms exhaustively for p≤7p \le 7.

The Fano plane $\mathbb F_2 P^2$: seven points and seven lines (six straight segments and the circle), any two points on exactly one line, any two lines meeting in exactly one point.

Example— Non-example: midpoints and distances are not projective

The perspective map x↦x/(x+2)x \mapsto x/(x + 2) of the line (a photograph of a fence, used in the first experiment) sends 0,1,20, 1, 2 to 0,13,120, \tfrac13, \tfrac12. The point 11 is the midpoint of 00 and 22, but 13\tfrac13 is not the midpoint of 00 and 12\tfrac12. Midpoints, ratios of lengths, distances and angles are not projective notions; collinearity, incidence and cross-ratio are. Check: (0,2;1,∞)=(0−1)(2−1)=−1(0, 2; 1, \infty) = \frac{(0 - 1)}{(2 - 1)} = -1, and the images 0,12,130, \tfrac12, \tfrac13 and 11 (the image of ∞\infty) have (0,12;13,1)=(0−13)(12−1)(0−1)(12−13)=1/6−1/6=−1\big(0, \tfrac12; \tfrac13, 1\big) = \frac{(0 - \frac13)(\frac12 - 1)}{(0 - 1)(\frac12 - \frac13)} = \frac{1/6}{-1/6} = -1.

ProofH

Incidence, duality and the fundamental theorem

Theorem— Theorem 1 (incidence)

In KP2KP^2, two distinct points lie on exactly one line, and two distinct lines meet in exactly one point. In coordinates, the line through pp and qq is p×qp \times q, and the point on the lines ℓ\ell and mm is ℓ×m\ell \times m.

Proof

Distinct points [p]≠[q][p] \ne [q] are independent vectors, so they span a unique two-dimensional subspace: a unique line. Distinct lines are distinct two-dimensional subspaces of K3K^3; their sum is K3K^3, so by the dimension formula dim⁡(U∩W)=2+2−3=1\dim(U \cap W) = 2 + 2 - 3 = 1: a unique point. For the coordinates: p⋅(p×q)=q⋅(p×q)=0p \cdot (p \times q) = q \cdot (p \times q) = 0, so p×qp \times q is a line through both points, and p×q≠0p \times q \ne 0 when p,qp, q are independent. If ℓ\ell is any line through pp and qq, the expansion ℓ×(p×q)=(ℓ⋅q)p−(ℓ⋅p)q=0\ell \times (p \times q) = (\ell \cdot q)p - (\ell \cdot p)q = 0 shows ℓ\ell is parallel to p×qp \times q, i.e. the same line. The statement about lines is the same computation with the roles exchanged.

∎

The last sentence of the proof is the principle of duality. Incidence, ℓ⋅p=0\ell \cdot p = 0, is symmetric in ℓ\ell and pp. So exchanging the words "point" and "line" (and "collinear" and "concurrent", "join" and "meet") turns every true statement about incidence in KP2KP^2 into another true statement. Theorem 1 is self-dual; Desargues' theorem below is dual to its own converse, and Pascal's theorem on conics is dual to Brianchon's. We get every projective theorem twice for the price of one proof.

Theorem— Theorem 2 (fundamental theorem: four points)

If p1,p2,p3,p4p_1, p_2, p_3, p_4 and q1,q2,q3,q4q_1, q_2, q_3, q_4 are two quadruples of points of KP2KP^2 in general position, there is exactly one projective transformation TT with T(pi)=qiT(p_i) = q_i for i=1,…,4i = 1, \dots, 4.

Proof

It suffices to treat q1,…,q4=[e1],[e2],[e3],[e1+e2+e3]q_1, \dots, q_4 = [e_1], [e_2], [e_3], [e_1 + e_2 + e_3] (the standard frame), because we can then compose one transformation with the inverse of another. Choose vectors viv_i representing pip_i. Since p1,p2,p3p_1, p_2, p_3 are not collinear, v1,v2,v3v_1, v_2, v_3 form a basis, and v4=λ1v1+λ2v2+λ3v3v_4 = \lambda_1 v_1 + \lambda_2 v_2 + \lambda_3 v_3. Every λi≠0\lambda_i \neq 0: if, say, λ3=0\lambda_3 = 0, then p1,p2,p4p_1, p_2, p_4 would be collinear. Let BB be the matrix with columns λ1v1,λ2v2,λ3v3\lambda_1 v_1, \lambda_2 v_2, \lambda_3 v_3. Then BB is invertible, Bei=λiviBe_i = \lambda_i v_i represents pip_i, and B(e1+e2+e3)=v4B(e_1 + e_2 + e_3) = v_4; so T=[B−1]T = [B^{-1}] sends the pip_i to the standard frame. Uniqueness: if [A][A] fixes the standard frame then Aei=μieiAe_i = \mu_i e_i and A(e1+e2+e3)=μ(e1+e2+e3)A(e_1 + e_2 + e_3) = \mu(e_1 + e_2 + e_3), so μ1=μ2=μ3=μ\mu_1 = \mu_2 = \mu_3 = \mu and A=μIA = \mu I induces the identity.

∎

On the projective line the same argument shows that a projective transformation is determined by the images of three distinct points. On RP2\R P^2 the four-point theorem says that any convex quadrilateral can be mapped onto a square by a perspective map — the homography used to rectify photographs.

ProofH

The cross-ratio

Theorem— Theorem 3 (invariance of the cross-ratio)

Projective transformations of a line preserve the cross-ratio of four distinct points. Consequently, if four collinear points of RP2\R P^2 are projected from a point OO onto another line, their cross-ratio is unchanged.

Proof

In homogeneous coordinates, [Ap Aq]=det⁡A⋅[p q][Ap\,Aq] = \det A \cdot [p\,q] for a 2×22 \times 2 matrix AA (the bracket is a determinant). So replacing a,b,c,da, b, c, d by Aa,Ab,Ac,AdAa, Ab, Ac, Ad multiplies the numerator [a c][b d][a\,c][b\,d] and the denominator [a d][b c][a\,d][b\,c] both by (det⁡A)2(\det A)^2; and rescaling any one point multiplies numerator and denominator by the same factor. So the cross-ratio is well defined on RP1\R P^1 and invariant. In the affine coordinate the same proof reads: for f(x)=ax+bcx+df(x) = \frac{ax + b}{cx + d},

f(x)−f(y)=(ad−bc)(x−y)(cx+d)(cy+d),f(x) - f(y) = \frac{(ad - bc)(x - y)}{(cx + d)(cy + d)},

and in (f(a)−f(c))(f(b)−f(d))(f(a)−f(d))(f(b)−f(c))\frac{(f(a) - f(c))(f(b) - f(d))}{(f(a) - f(d))(f(b) - f(c))} the factors (ad−bc)2(ad - bc)^2 and all four denominators cancel. For the second statement, choose coordinates on the two lines; the projection from OO is the restriction of a linear map of the plane through OO, hence a projective map between the two lines.

∎

Three points and a cross-ratio determine the fourth point, which is how one locates the fourth fence post in a photograph from the first three (first experiment). Permuting the four points changes the cross-ratio in a controlled way: the 2424 orderings give at most six values,

λ,1λ,1−λ,11−λ,λ−1λ,λλ−1,\lambda, \quad \frac1\lambda, \quad 1 - \lambda, \quad \frac{1}{1 - \lambda}, \quad \frac{\lambda - 1}{\lambda}, \quad \frac{\lambda}{\lambda - 1},

which collapse to three when λ=−1\lambda = -1. Four points with cross-ratio −1-1 form a harmonic range: for example 00 and ∞\infty separate 11 and −1-1 harmonically, and the midpoint mm of aa and bb satisfies (a,b;m,∞)=−1(a, b; m, \infty) = -1. This is how projective geometry recovers midpoints once the line at infinity is known — exactly what a perspective artist does with the horizon.

ProofH

The theorems of Desargues and Pappus

Theorem— Theorem 4 (Desargues)

Let ABCABC and A′B′C′A'B'C' be triangles in KP2KP^2 such that the lines AA′AA', BB′BB', CC′CC' meet in a point OO (the triangles are in perspective from a point). Then the three points P=AB∩A′B′P = AB \cap A'B', Q=BC∩B′C′Q = BC \cap B'C', R=CA∩C′A′R = CA \cap C'A' are collinear (the triangles are in perspective from a line).

Proof

Use vectors O,A,B,CO, A, B, C representing the points (we use the same letters). The point A′A' lies on the line OAOA and differs from AA, so we can scale its representative to A′=O+aAA' = O + aA; similarly B′=O+bBB' = O + bB and C′=O+cCC' = O + cC. Put

P=aA−bB,Q=bB−cC,R=cC−aA.P = aA - bB, \qquad Q = bB - cC, \qquad R = cC - aA.

The vector PP is a combination of AA and BB, so it lies on the line ABAB; and P=A′−B′P = A' - B', so it lies on A′B′A'B' too. Hence PP represents AB∩A′B′AB \cap A'B' (if P=0P = 0, the lines ABAB and A′B′A'B' coincide and there is nothing to prove). Likewise QQ and RR. Finally P+Q+R=0P + Q + R = 0, so the three vectors are linearly dependent: the points are collinear.

∎

There is a classical synthetic proof too. If the two triangles lie in different planes of a three-dimensional projective space, the lines ABAB and A′B′A'B' lie in the plane OABOAB and therefore meet, and all three meeting points lie on the line where the planes ABCABC and A′B′C′A'B'C' intersect. The planar case follows by projecting a three-dimensional configuration. So Desargues' theorem in the plane is a shadow of the third dimension.

OABCA′B′C′PQR
Desargues' theorem: the triangles $ABC$ and $A'B'C'$ are in perspective from $O$ (dashed rays), so the meets $P$, $Q$, $R$ of corresponding sides lie on one line (gold).

Theorem— Theorem 5 (Pappus)

Let A,B,CA, B, C be distinct points on a line ℓ\ell and A′,B′,C′A', B', C' distinct points on another line mm, none of them equal to ℓ∩m\ell \cap m. Then the three points AB′∩A′BAB' \cap A'B, AC′∩A′CAC' \cap A'C and BC′∩B′CBC' \cap B'C are collinear.

Proof

By Theorem 2 we may choose coordinates in which ℓ\ell and mm are the xx- and yy-axes, and (over an infinite field) the line at infinity misses all six points. Then A=(a,0)A = (a, 0), B=(b,0)B = (b, 0), C=(c,0)C = (c, 0) and A′=(0,a′)A' = (0, a'), B′=(0,b′)B' = (0, b'), C′=(0,c′)C' = (0, c') with all six numbers non-zero; write α=1/a\alpha = 1/a, α′=1/a′\alpha' = 1/a' and so on. The line AB′AB' is αx+β′y=1\alpha x + \beta' y = 1, i.e. [α:β′:−1][\alpha : \beta' : -1], and A′BA'B is [β:α′:−1][\beta : \alpha' : -1]. Their meet is the cross product

P=(α′−β′,  α−β,  αα′−ββ′).P = (\alpha' - \beta',\; \alpha - \beta,\; \alpha\alpha' - \beta\beta').

In the same way Q=AC′∩A′C=(α′−γ′,α−γ,αα′−γγ′)Q = AC' \cap A'C = (\alpha' - \gamma', \alpha - \gamma, \alpha\alpha' - \gamma\gamma') and R=BC′∩B′C=(β′−γ′,β−γ,ββ′−γγ′)R = BC' \cap B'C = (\beta' - \gamma', \beta - \gamma, \beta\beta' - \gamma\gamma'). Now P−Q+R=0P - Q + R = 0, so P,Q,RP, Q, R are linearly dependent: the three points are collinear.

∎

The proof used that multiplication commutes (in forming αα′\alpha\alpha' and writing the cross product). That is no accident. Projective planes can be built over any division ring DD, where multiplication need not commute, such as Hamilton's quaternions. Hilbert (1899) showed that Desargues' theorem holds in a projective plane exactly when it can be coordinatised by a division ring, and Pappus' theorem holds exactly when that division ring is commutative, a field. So Desargues holds and Pappus fails in the quaternionic plane. There are even planes satisfying the incidence axioms in which Desargues fails, such as Moulton's plane (1902) and finite planes of order 99. Hessenberg (1905) proved synthetically that Pappus implies Desargues, and by Wedderburn's theorem (1905) every finite division ring is a field, so in a finite plane Desargues implies Pappus.

ProofH

Conics: one curve, three shadows

Theorem— Theorem 6 (projective classification of conics)

(a) Every non-degenerate real conic is either empty or projectively equivalent to the circle x2+y2=z2x^2 + y^2 = z^2. (b) In the affine chart z=1z = 1, a non-degenerate conic Ax2+Bxy+Cy2+Dx+Ey+F=0Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0 meets the line at infinity in 00, 11 or 22 points according as B2−4AC<0B^2 - 4AC < 0, =0= 0 or >0> 0; correspondingly it is an ellipse, a parabola (tangent to the line at infinity) or a hyperbola (whose asymptote directions are the two points at infinity).

Proof

(a) By the spectral theorem the symmetric matrix MM is QΛQTQ\Lambda Q^{\mathsf T} with QQ orthogonal; rescaling the eigenvector coordinates by 1/∣λi∣1/\sqrt{|\lambda_i|} (all λi≠0\lambda_i \ne 0 since det⁡M≠0\det M \ne 0) turns the form into ±u2±v2±w2\pm u^2 \pm v^2 \pm w^2. Multiplying the whole equation by −1-1 changes nothing, so up to sign there are two cases: u2+v2+w2u^2 + v^2 + w^2, with no real zeros, and u2+v2−w2u^2 + v^2 - w^2, the circle. (This is Sylvester's law of inertia in three variables.)

(b) The points at infinity of the conic are the solutions of Q(x,y,0)=Ax2+Bxy+Cy2=0Q(x, y, 0) = Ax^2 + Bxy + Cy^2 = 0 with (x,y)≠0(x, y) \neq 0. This binary quadratic has no real root directions, one double root direction, or two root directions according as its discriminant B2−4ACB^2 - 4AC is negative, zero or positive. A double root means the line at infinity is tangent to the conic.

∎

For example x2+y2−z2x^2 + y^2 - z^2 becomes y2−uwy^2 - uw under x=u−w2x = \frac{u - w}2, z=u+w2z = \frac{u + w}2: in the chart w=1w = 1 that is the parabola y2=uy^2 = u. So the circle and the parabola are the same projective curve, seen with different lines chosen as "at infinity". The visualisation below moves the line at infinity continuously. Two further classical facts, stated without proof: five points in general position determine exactly one conic (a symmetric 3×33 \times 3 matrix up to scale has five degrees of freedom, and each point imposes one linear condition); and Pascal's theorem (1640) says that for a hexagon inscribed in a conic, the three meets of opposite sides are collinear. Pappus' theorem is the case of the degenerate conic ℓ∪m\ell \cup m.

Formal mathematicsF

Projective geometry in Lean and Mathlib

Mathlib's Projectivization K V (notation ℙ K V) is the type of lines through 00 in VV, with Projectivization.mk K v hv the point with homogeneous coordinates v≠0v \ne 0. Homogeneous coordinates are defined up to scale, and opposite vectors give the same point — one point at infinity per direction:

mk_eq_mk_iffLean 4Applies a library theoremFormally verified
/-- **Homogeneous coordinates are defined up to scale**: `[v] = [w]` in `ℙ K V` exactly when
`v = a • w` for some scalar `a` (Mathlib's `Projectivization.mk_eq_mk_iff'`). -/
theorem mk_eq_mk_iff {K V : Type*} [Field K] [AddCommGroup V] [Module K V] (v w : V)
    (hv : v ≠ 0) (hw : w ≠ 0) :
    Projectivization.mk K v hv = Projectivization.mk K w hw ↔ ∃ a : K, a • w = v :=
  Projectivization.mk_eq_mk_iff' K v w hv hw
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
mk_negLean 4Proved here from basic factsFormally verified
/-- **Opposite directions give the same point.** `[v] = [−v]`: in particular a direction in the
plane and its reverse determine the *same* point at infinity `[x : y : 0] = [−x : −y : 0]`. -/
theorem mk_neg {K : Type*} [Field K] (v : Fin 3 → K) (hv : v ≠ 0) :
    Projectivization.mk K v hv = Projectivization.mk K (-v) (neg_ne_zero.mpr hv) := by
  rw [Projectivization.mk_eq_mk_iff]
  exact ⟨-1, by simp⟩
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor

Theorem 1 with the cross product u⨯3vu ⨯_3 v from Mathlib.LinearAlgebra.CrossProduct. The theorem line_unique is proved once, and read in two ways: for points p,qp, q it says the line is unique; for lines it says the meet is unique. That is the principle of duality inside a proof assistant.

cross_on_bothLean 4Applies a library theoremFormally verified
/-- **The line through `p` and `q` is `p × q`**: the cross product is orthogonal to both factors,
so both points lie on it (Mathlib's `dot_self_cross` and `dot_cross_self`). Read dually, with
`p`, `q` lines: the point `p × q` lies on both lines. -/
theorem cross_on_both {K : Type*} [CommRing K] (p q : Fin 3 → K) :
    p ⬝ᵥ (p ⨯₃ q) = 0 ∧ q ⬝ᵥ (p ⨯₃ q) = 0 :=
  ⟨dot_self_cross p q, dot_cross_self p q⟩
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
cross_ne_zero_iffLean 4Applies a library theoremFormally verified
/-- `p × q ≠ 0` exactly when `p` and `q` are linearly independent, i.e. represent **distinct**
points (Mathlib's `crossProduct_ne_zero_iff_linearIndependent`). -/
theorem cross_ne_zero_iff {K : Type*} [Field K] (p q : Fin 3 → K) :
    p ⨯₃ q ≠ 0 ↔ LinearIndependent K ![p, q] :=
  crossProduct_ne_zero_iff_linearIndependent
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
incident_cross_zeroLean 4Proved here from basic factsFormally verified
/-- If the line `ℓ` passes through `p` and `q`, then `ℓ × (p × q) = 0`, i.e. `ℓ` and `p × q` are
parallel vectors. Proof: the expansion `ℓ × (p × q) = (ℓ · q) p − (p · ℓ) q` (Mathlib's
`cross_cross_eq_smul_sub_smul'`) has both coefficients zero. -/
theorem incident_cross_zero {K : Type*} [CommRing K] (ℓ p q : Fin 3 → K) (hp : ℓ ⬝ᵥ p = 0)
    (hq : ℓ ⬝ᵥ q = 0) : ℓ ⨯₃ (p ⨯₃ q) = 0 := by
  rw [cross_cross_eq_smul_sub_smul', hq, dotProduct_comm, hp, zero_smul, zero_smul, sub_zero]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
line_uniqueLean 4Proved here from basic factsFormally verified
/-- **Two distinct points lie on exactly one line.** If `p × q ≠ 0` (distinct points) and `ℓ`
passes through both, then `ℓ` is a scalar multiple of `p × q` — the same projective line. By
duality (swap the roles of points and lines) the *same theorem* says that two distinct lines
meet in exactly one point, their cross product. -/
theorem line_unique {K : Type*} [Field K] (ℓ p q : Fin 3 → K) (hpq : p ⨯₃ q ≠ 0)
    (hp : ℓ ⬝ᵥ p = 0) (hq : ℓ ⬝ᵥ q = 0) : ∃ c : K, c • (p ⨯₃ q) = ℓ := by
  have h1 : (p ⨯₃ q) ⨯₃ ℓ = 0 := by
    rw [← cross_anticomm, incident_cross_zero ℓ p q hp hq, neg_zero]
  have h2 : ¬ LinearIndependent K ![p ⨯₃ q, ℓ] := by
    rw [← crossProduct_ne_zero_iff_linearIndependent, not_not]
    exact h1
  rw [LinearIndependent.pair_iff' hpq] at h2
  push Not at h2
  exact h2
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
triple_product_detLean 4Applies a library theoremFormally verified
/-- **Collinearity test**: three points `u, v, w` of `ℙ²` are collinear (lie on a common line)
exactly when `det [u, v, w] = 0`; the triple product `u · (v × w)` is that determinant
(Mathlib's `triple_product_eq_det`). -/
theorem triple_product_det {K : Type*} [CommRing K] (u v w : Fin 3 → K) :
    u ⬝ᵥ (v ⨯₃ w) = Matrix.det ![u, v, w] :=
  triple_product_eq_det u v w
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor

The cross-ratio and Theorem 3, in the affine form of the proof (a Möbius map and the cancellation of (ad−bc)2(ad - bc)^2):

crossRatioLean 4Formally verified
/-- The **cross-ratio** of four numbers (affine coordinates of four points on a line):
`(a, b; c, d) = ((a − c)(b − d)) / ((a − d)(b − c))`. (Lean's division by `0` gives `0`.) -/
def crossRatio {K : Type*} [Field K] (a b c d : K) : K :=
  ((a - c) * (b - d)) / ((a - d) * (b - c))
Axioms used: propext, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
mobius_subLean 4Proved here from basic factsFormally verified
/-- The key identity behind cross-ratio invariance: for `f(x) = (a x + b)/(c x + d)`,
`f(x) − f(y) = (ad − bc)(x − y) / ((c x + d)(c y + d))`. -/
theorem mobius_sub {K : Type*} [Field K] (a b c d x y : K) (hx : c * x + d ≠ 0)
    (hy : c * y + d ≠ 0) :
    (a * x + b) / (c * x + d) - (a * y + b) / (c * y + d)
      = (a * d - b * c) * (x - y) / ((c * x + d) * (c * y + d)) := by
  rw [div_sub_div _ _ hx hy]
  congr 1
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
cross_ratio_mobiusLean 4Proved here from basic factsFormally verified
/-- **The cross-ratio is a projective invariant.** A projective transformation of the line,
`f(x) = (a x + b)/(c x + d)` with `ad − bc ≠ 0`, preserves the cross-ratio of any four points
where it is defined. In each of the four differences the factor `ad − bc` and the denominators
`c x + d` cancel between numerator and denominator — exactly the lesson's proof. -/
theorem cross_ratio_mobius {K : Type*} [Field K] (a b c d p q r s : K) (hdet : a * d - b * c ≠ 0)
    (hp : c * p + d ≠ 0) (hq : c * q + d ≠ 0) (hr : c * r + d ≠ 0) (hs : c * s + d ≠ 0) :
    let f := fun x => (a * x + b) / (c * x + d)
    crossRatio (f p) (f q) (f r) (f s) = crossRatio p q r s := by
  intro f
  simp only [crossRatio, f]
  rw [mobius_sub a b c d p r hp hr, mobius_sub a b c d q s hq hs, mobius_sub a b c d p s hp hs,
    mobius_sub a b c d q r hq hr]
  set D := a * d - b * c
  have hP : (c * p + d) * (c * r + d) * ((c * q + d) * (c * s + d)) ≠ 0 := by
    apply mul_ne_zero <;> apply mul_ne_zero <;> assumption
  rw [div_mul_div_comm, div_mul_div_comm]
  rw [show (c * p + d) * (c * s + d) * ((c * q + d) * (c * r + d))
      = (c * p + d) * (c * r + d) * ((c * q + d) * (c * s + d)) by ring]
  rw [div_div_div_cancel_right₀ hP]
  rw [show D * (p - r) * (D * (q - s)) = (D * D) * ((p - r) * (q - s)) by ring,
    show D * (p - s) * (D * (q - r)) = (D * D) * ((p - s) * (q - r)) by ring]
  exact mul_div_mul_left _ _ (mul_ne_zero hdet hdet)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor

Desargues' theorem exactly as proved above, and Pappus' theorem in homogeneous coordinates adapted to the two lines. The Pappus statement covers points at infinity too (it allows any [a1:0:a2][a_1 : 0 : a_2] on the first line), and its proof is a single polynomial identity checked by ring. Both hold in any commutative ring, and changing one point off its line makes the ring check fail.

desarguesLean 4Proved here from basic factsFormally verified
/-- **Desargues' theorem** in homogeneous coordinates. Triangles `ABC` and `A'B'C'` are in
perspective from `O`: `A' = O + a A`, `B' = O + b B`, `C' = O + c C` (every point of the line `OA`
other than `A` has a representative of this form). Then `P = aA − bB` lies on the lines `AB` and
`A'B'` (because `P = A' − B'`), similarly `Q` on `BC` and `B'C'` and `R` on `CA` and `C'A'`, and
`P + Q + R = 0` makes `P, Q, R` collinear: the triple product `P · (Q × R)` vanishes. -/
theorem desargues {K : Type*} [CommRing K] (O A B C : Fin 3 → K) (a b c : K) :
    let A' := O + a • A
    let B' := O + b • B
    let C' := O + c • C
    let P := a • A - b • B
    let Q := b • B - c • C
    let R := c • C - a • A
    (A ⬝ᵥ (B ⨯₃ P) = 0 ∧ A' ⬝ᵥ (B' ⨯₃ P) = 0) ∧
    (B ⬝ᵥ (C ⨯₃ Q) = 0 ∧ B' ⬝ᵥ (C' ⨯₃ Q) = 0) ∧
    (C ⬝ᵥ (A ⨯₃ R) = 0 ∧ C' ⬝ᵥ (A' ⨯₃ R) = 0) ∧
    P ⬝ᵥ (Q ⨯₃ R) = 0 := by
  intro A' B' C' P Q R
  simp only [A', B', C', P, Q, R, cross_apply, dotProduct, Fin.sum_univ_three]
  refine ⟨⟨?_, ?_⟩, ⟨?_, ?_⟩, ⟨?_, ?_⟩, ?_⟩ <;> simp <;> ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
pappusLean 4Proved here from basic factsFormally verified
/-- **Pappus' theorem** in homogeneous coordinates. After a projective change of coordinates the
two lines are `y = 0` and `x = 0`, so `A, B, C = [a₁ : 0 : a₂], …` and `A', B', C' = [0 : d₁ : d₂], …`.
The three cross-joins `AB' ∩ A'B`, `AC' ∩ A'C`, `BC' ∩ B'C` — each a cross product of two
cross products — are collinear: their triple product is identically zero. The proof is a
polynomial identity checked by `ring`, valid in every *commutative* ring: commutativity of
multiplication is exactly what Pappus needs. -/
theorem pappus {K : Type*} [CommRing K] (a₁ a₂ b₁ b₂ c₁ c₂ d₁ d₂ e₁ e₂ f₁ f₂ : K) :
    let A : Fin 3 → K := ![a₁, 0, a₂]
    let B : Fin 3 → K := ![b₁, 0, b₂]
    let C : Fin 3 → K := ![c₁, 0, c₂]
    let A' : Fin 3 → K := ![0, d₁, d₂]
    let B' : Fin 3 → K := ![0, e₁, e₂]
    let C' : Fin 3 → K := ![0, f₁, f₂]
    let P := (A ⨯₃ B') ⨯₃ (A' ⨯₃ B)
    let Q := (A ⨯₃ C') ⨯₃ (A' ⨯₃ C)
    let R := (B ⨯₃ C') ⨯₃ (B' ⨯₃ C)
    P ⬝ᵥ (Q ⨯₃ R) = 0 := by
  intro A B C A' B' C' P Q R
  simp only [A, B, C, A', B', C', P, Q, R, cross_apply, dotProduct, Fin.sum_univ_three]
  simp
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor

Conics: the explicit change of coordinates taking the circle to a parabola, and Mathlib's version of Sylvester's law used in Theorem 6(a):

circle_to_parabolaLean 4Proved here from basic factsFormally verified
/-- **The circle and the parabola are projectively the same conic.** With
`P = [[1/2, 0, −1/2], [0, 1, 0], [1/2, 0, 1/2]]` (invertible: `det P = 1/2`), the form
`x² + y² − z²` (the circle `x² + y² = 1` when `z = 1`) becomes `y² − u w`, i.e. `Pᵀ C P = D` —
the parabola `y² = u` in the chart `w = 1`. Concretely, `x = (u − w)/2`, `z = (u + w)/2`. -/
theorem circle_to_parabola :
    let P : Matrix (Fin 3) (Fin 3) ℚ := !![1/2, 0, -1/2; 0, 1, 0; 1/2, 0, 1/2]
    let C : Matrix (Fin 3) (Fin 3) ℚ := !![1, 0, 0; 0, 1, 0; 0, 0, -1]
    let D : Matrix (Fin 3) (Fin 3) ℚ := !![0, 0, -1/2; 0, 1, 0; -1/2, 0, 0]
    Pᵀ * C * P = D ∧ P.det ≠ 0 := by
  intro P C D
  refine ⟨?_, ?_⟩
  · ext i j
    fin_cases i <;> fin_cases j <;> norm_num [P, C, D, Matrix.mul_apply, Fin.sum_univ_three]
  · norm_num [P, Matrix.det_fin_three]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor
real_quadratic_formsLean 4Applies a library theoremFormally verified
/-- **Sylvester's classification of real quadratic forms**: a non-degenerate quadratic form on a
real `n`-dimensional space is equivalent to `Σ wᵢ xᵢ²` with every `wᵢ = ±1` (Mathlib's
`QuadraticForm.equivalent_one_neg_one_weighted_sum_squared`). For `n = 3`, up to an overall sign
only `x² + y² + z²` (an empty conic) and `x² + y² − z²` (the circle) remain: so all non-empty
non-degenerate real conics are projectively equivalent. -/
theorem real_quadratic_forms {M : Type*} [AddCommGroup M] [Module ℝ M] [FiniteDimensional ℝ M]
    (Q : QuadraticForm ℝ M) (hQ : (QuadraticMap.associated (R := ℝ) Q).SeparatingLeft) :
    ∃ w : Fin (Module.finrank ℝ M) → ℝ,
      (∀ i, w i = -1 ∨ w i = 1) ∧ QuadraticMap.Equivalent Q (QuadraticMap.weightedSumSquares ℝ w) :=
  Q.equivalent_one_neg_one_weighted_sum_squared hQ
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ProjectiveGeometry.leanTry it in the Lean web editor

What is and is not formalised. Independent: [v]=[−v][v] = [-v], the uniqueness half of Theorem 1 (and its dual), the cross-ratio identity and Theorem 3 for Möbius maps, Desargues' theorem (Theorem 4) and Pappus' theorem (Theorem 5) as coordinate identities, and the circle-to-parabola transformation. From Mathlib: equality in ℙ K V, the cross-product incidence facts, the triple product as a determinant, and the classification of real quadratic forms. Not formalised: Theorem 2 (four points), the reduction "choose coordinates so that the lines are the axes" (we state Pappus directly in those coordinates), Theorem 6(b), Hilbert's coordinatisation theorems and Pascal's theorem. Mathlib does not yet have synthetic projective planes. The Lean exercises ask for [v]=[−v][v] = [-v] and the incidence lemma.

ComputationC

Cross-ratios exactly, and planes with finitely many points

The first program stores points of the projective line as homogeneous pairs of fractions, so that ∞=[1:0]\infty = [1 : 0] needs no special case. It applies 300300 random Möbius transformations and checks that every cross-ratio is preserved, while ordinary ratios of lengths almost never are. It lists the six values of the cross-ratio under reordering (three in the harmonic case), and locates the fourth fence post of a photograph from the first three.

The cross-ratio under projective maps, exactlyPythonExact computationExperimental evidenceComputationally tested
"""The cross-ratio: invariant under every projective map of the line.

Points of the projective line are stored as homogeneous pairs [x : y] of exact
fractions, so the point at infinity [1 : 0] needs no special treatment. With
the bracket [p q] = p_x q_y - p_y q_x, the cross-ratio is

    (a, b; c, d) = [a c][b d] / ([a d][b c]),

which agrees with ((a - c)(b - d)) / ((a - d)(b - c)) for finite points. The
program applies seeded random Moebius transformations x -> (ax + b)/(cx + d)
(2 x 2 matrices with non-zero determinant) to random quadruples and checks
the cross-ratio exactly, while the simple ratio (a - c)/(b - c) changes. It
lists the six values taken by the cross-ratio under the 24 orderings, and uses
invariance to locate a fence post in a perspective photograph.

All arithmetic is exact: a finite exhaustive check of the cases listed.
"""

import random
from fractions import Fraction
from itertools import permutations

INFINITY = (Fraction(1), Fraction(0))

def point(x):
    """The homogeneous pair [x : 1] of a finite point."""
    return (Fraction(x), Fraction(1))

def bracket(p, q):
    """The 2 x 2 determinant [p q] = p_x q_y - p_y q_x."""
    return p[0] * q[1] - p[1] * q[0]

def cross_ratio(a, b, c, d):
    """(a, b; c, d) = [a c][b d] / ([a d][b c]) for homogeneous pairs."""
    return (bracket(a, c) * bracket(b, d)) / (bracket(a, d) * bracket(b, c))

def apply(m, p):
    """Apply the 2 x 2 matrix m = ((a, b), (c, d)) to the homogeneous pair p."""
    (a, b), (c, d) = m
    return (a * p[0] + b * p[1], c * p[0] + d * p[1])

def affine(p):
    """The affine coordinate x/y of [x : y], or None for the point at infinity."""
    return None if p[1] == 0 else p[0] / p[1]

def random_mobius(rng):
    """A random integer 2 x 2 matrix with non-zero determinant."""
    while True:
        m = tuple(tuple(Fraction(rng.randint(-9, 9)) for _ in range(2))
                  for _ in range(2))
        if m[0][0] * m[1][1] - m[0][1] * m[1][0] != 0:
            return m

def six_values(lam):
    """The values of the cross-ratio over all 24 orderings of four points.

    The points lam, 1, 0, infinity have cross-ratio (lam, 1; 0, inf) = lam.
    """
    base = [point(lam), point(1), point(0), INFINITY]
    values = {cross_ratio(*[base[i] for i in perm])
              for perm in permutations(range(4))}
    return sorted(values)

def fourth_point(a, b, c, lam):
    """The affine x with ((a - c)(b - x)) / ((a - x)(b - c)) = lam.

    Clearing denominators gives b - x = k (a - x) with k = lam (b - c)/(a - c).
    """
    k = lam * (b - c) / (a - c)
    return (k * a - b) / (k - 1)

def photo(x):
    """Position in a perspective photo of a point x metres along the fence."""
    return Fraction(x) / (x + 2)

def main():
    rng = random.Random(2024)
    trials, invariant, ratio_changed = 300, 0, 0
    for _ in range(trials):
        xs = rng.sample(range(-20, 21), 4)
        quad = [point(x) for x in xs]
        if rng.random() < 0.25:
            quad[rng.randrange(4)] = INFINITY
        m = random_mobius(rng)
        images = [apply(m, p) for p in quad]
        if any(bracket(images[i], images[j]) == 0
               for i in range(4) for j in range(i)):
            continue
        invariant += cross_ratio(*images) == cross_ratio(*quad)
        a, b, c = (affine(p) for p in quad[:3])
        a2, b2, c2 = (affine(p) for p in images[:3])
        if None not in (a, b, c, a2, b2, c2):
            ratio_changed += (a - c) / (b - c) != (a2 - c2) / (b2 - c2)
    print(f"{trials} random Moebius maps on random quadruples (exact):")
    print(f"   cross-ratio unchanged in {invariant} of {trials} cases")
    print(f"   simple ratio (a - c)/(b - c) changed in {ratio_changed} cases")
    print()
    for lam in (Fraction(3), Fraction(-1)):
        vals = six_values(lam)
        print(f"orderings of four points with cross-ratio {lam}: "
              f"{len(vals)} values")
        print("   " + ", ".join(str(v) for v in vals))
    print()
    posts = [0, 1, 2, 3]
    cr_ground = cross_ratio(*[point(x) for x in posts])
    seen = [photo(x) for x in posts[:3]]
    print("Fence posts 1 m apart at 0, 1, 2, 3 have cross-ratio", cr_ground)
    print("In the photo (x -> x/(x + 2)) the first three appear at",
          ", ".join(str(s) for s in seen))
    x = fourth_point(*seen, cr_ground)
    print(f"Invariance predicts the fourth at {x}; the photo has"
          f" {photo(posts[3])}")
    print()
    print("Epistemic status: exact rational arithmetic over finitely many\n"
          "random cases (and two worked examples). This is evidence, not a\n"
          "proof, of invariance; the proof is the algebra in the lesson,\n"
          "checked in Lean as cross_ratio_mobius.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The second program builds the finite planes FpP2\mathbb F_p P^2 for p=2,3,5,7p = 2, 3, 5, 7. It checks by exhaustion that each has p2+p+1p^2 + p + 1 points and lines, that two points determine one line and two lines one point, and that the conic x2+y2=z2x^2 + y^2 = z^2 has exactly p+1p + 1 points for odd pp, just as a real conic is a circle, the projective line in disguise. It then tests Desargues and Pappus on random configurations in F7P2\mathbb F_7P^2.

Finite projective planes: incidence, conics, Desargues, PappusPythonExhaustive finite checkExperimental evidenceComputationally tested
"""Finite projective planes PG(2, p): counting, incidence, Desargues, Pappus.

Over the field F_p of integers mod a prime p, the projective plane PG(2, p)
has as points the non-zero vectors of F_p^3 up to non-zero scalars, and lines
likewise (a line l contains the point x when l . x = 0 mod p). The program

* counts points and lines (p^2 + p + 1 each) and points per line (p + 1);
* checks exhaustively that two distinct points lie on exactly one line and
  two distinct lines meet in exactly one point;
* counts the points of the conic x^2 + y^2 = z^2 (p + 1 for odd p);
* tests the theorems of Desargues and Pappus on seeded random configurations
  in PG(2, 7), computing joins and meets with cross products mod p.

Incidence checks are exhaustive for the listed p; the theorem checks are
random samples, i.e. evidence for that plane only.
"""

import random
from itertools import combinations, product

def normalise(v, p):
    """Scale a non-zero vector mod p so that its first non-zero entry is 1."""
    v = [x % p for x in v]
    for x in v:
        if x:
            inv = pow(x, p - 2, p)
            return tuple(y * inv % p for y in v)
    raise ValueError("zero vector")

def points(p):
    """All points of PG(2, p), as normalised triples."""
    return sorted({normalise(v, p) for v in product(range(p), repeat=3)
                   if any(v)})

def dot(u, v, p):
    return sum(a * b for a, b in zip(u, v)) % p

def cross(u, v, p):
    """The cross product mod p: the line through two points (or the meet)."""
    return ((u[1] * v[2] - u[2] * v[1]) % p, (u[2] * v[0] - u[0] * v[2]) % p,
            (u[0] * v[1] - u[1] * v[0]) % p)

def collinear(u, v, w, p):
    """True when the three points lie on one line (determinant zero mod p)."""
    return dot(u, cross(v, w, p), p) == 0

def incidence_report(p):
    """(#points, set of points-per-line counts, axioms hold) for PG(2, p)."""
    pts = points(p)
    lines = pts  # by duality the lines are the same triples
    on = {l: [x for x in pts if dot(l, x, p) == 0] for l in lines}
    per_line = {len(v) for v in on.values()}
    two_points = all(sum(1 for l in lines if dot(l, x, p) == 0 and
                         dot(l, y, p) == 0) == 1
                     for x, y in combinations(pts, 2))
    two_lines = all(sum(1 for x in pts if dot(l, x, p) == 0 and
                        dot(m, x, p) == 0) == 1
                    for l, m in combinations(lines, 2))
    return len(pts), per_line, two_points and two_lines

def conic_points(p):
    """Number of points of x^2 + y^2 = z^2 in PG(2, p)."""
    return sum(1 for (x, y, z) in points(p) if (x * x + y * y - z * z) % p == 0)

def desargues_trial(rng, p):
    """Random triangles perspective from a point; are the meets collinear?"""
    while True:
        o, a, b, c = (rng.choices(range(p), k=3) for _ in range(4))
        s, t, u = (rng.randrange(1, p) for _ in range(3))
        a2 = [(o[i] + s * a[i]) % p for i in range(3)]
        b2 = [(o[i] + t * b[i]) % p for i in range(3)]
        c2 = [(o[i] + u * c[i]) % p for i in range(3)]
        tri = [a, b, c, a2, b2, c2, o]
        if any(not any(v) for v in tri):
            continue
        if collinear(a, b, c, p) or collinear(a2, b2, c2, p):
            continue
        meets = [cross(cross(a, b, p), cross(a2, b2, p), p),
                 cross(cross(b, c, p), cross(b2, c2, p), p),
                 cross(cross(c, a, p), cross(c2, a2, p), p)]
        if any(not any(m) for m in meets):
            continue
        return collinear(*meets, p)

def pappus_trial(rng, p):
    """Three points on each of two lines; are the cross-joins collinear?"""
    while True:
        l, m = (rng.choices(range(p), k=3) for _ in range(2))
        if not any(cross(l, m, p)):
            continue
        pts = points(p)
        on_l = [x for x in pts if dot(l, x, p) == 0 and dot(m, x, p) != 0]
        on_m = [x for x in pts if dot(m, x, p) == 0 and dot(l, x, p) != 0]
        a, b, c = rng.sample(on_l, 3)
        a2, b2, c2 = rng.sample(on_m, 3)
        meets = [cross(cross(a, b2, p), cross(a2, b, p), p),
                 cross(cross(a, c2, p), cross(a2, c, p), p),
                 cross(cross(b, c2, p), cross(b2, c, p), p)]
        return collinear(*meets, p)

def main():
    print(" p   points  points/line  2 pts -> 1 line, 2 lines -> 1 pt"
          "  conic pts")
    for p in (2, 3, 5, 7):
        n, per_line, axioms = incidence_report(p)
        conic = conic_points(p) if p > 2 else "-"
        print(f"{p:2d}   {n:6d}  {sorted(per_line)!s:>11}  {axioms!s:>31}"
              f"  {conic!s:>9}")
    print("(p^2 + p + 1 points, p + 1 per line; a conic has p + 1 points)")
    print()
    rng = random.Random(2024)
    trials = 300
    des = sum(desargues_trial(rng, 7) for _ in range(trials))
    pap = sum(pappus_trial(rng, 7) for _ in range(trials))
    print(f"PG(2, 7): Desargues held in {des} of {trials} random "
          "configurations")
    print(f"PG(2, 7): Pappus held in {pap} of {trials} random configurations")
    print()
    print("Epistemic status: the counts and incidence axioms are exhaustive\n"
          "checks for p = 2, 3, 5, 7. The Desargues and Pappus results are\n"
          "random samples in one finite plane: evidence, not proof. The\n"
          "proofs (valid over every field) are in the lesson and in Lean.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The incidence counts are exhaustive, hence proofs for those particular planes. The random Desargues and Pappus tests are evidence in one plane; the coordinate proofs (and the Lean theorems) cover every field at once.

Explore

Explore: one conic, three shadows

The curve below is the image of the unit circle under the projective transformation [x:y:z]↦[x:y:z+ay][x : y : z] \mapsto [x : y : z + ay], drawn in the chart z=1z = 1. That is, the circle is fixed and the line sent to infinity moves: it is the line y=−1/ay = -1/a. For 0≤a<10 \le a < 1 that line misses the circle and the image is an ellipse. At a=1a = 1 the line is tangent at (0,−1)(0, -1), and the image is a parabola. For a>1a > 1 it cuts the circle twice, and the image is a hyperbola whose two branches are joined through the two points at infinity. Slide aa slowly through 11.

The circle under a projective map: ellipse, parabola, hyperbola

A point moves along the curve as t changes: x and y are both functions of t.

  • image of the circle
  • (0.522, 0.522)

Möbius transformations z↦az+bcz+dz \mapsto \frac{az + b}{cz + d} are the projective transformations of the complex projective line CP1=C∪{∞}\C P^1 = \C \cup \{\infty\}, the Riemann sphere. They preserve the complex cross-ratio, and they send circles and lines to circles and lines (a line is a circle through ∞\infty). Watch the grid lines bend into circles.

A Möbius transformation of the Riemann sphere

See a grid in the z-plane carried to the w-plane. Wherever f′(z) ≠ 0, small right angles stay right angles.

Function
Grid
z-plane
×z₀
w-plane · w = (z − 1)/(z + 1)
f(z₀)
  • horizontal lines and their images
  • vertical lines and their images
  • small cross at z₀ and its image

Drag the points, or focus one with Tab and use the arrow keys (hold Shift for small steps).

z₀ =+i
z₀
0.5 + 0.5i
w₀ = f(z₀)
−0.2 + 0.4i
f′(z₀)
0.64 − 0.48i
Local scale factor |f′(z₀)|
0.8
Local rotation arg f′(z₀)
−36.9°
Angle between the image curves
90°

Conformal at z₀: the little right angle is turned by −36.9° and scaled by 0.8, and it stays a right angle.

A Möbius map: lines and circles go to lines and circles; the imaginary axis becomes the unit circle and the right half-plane becomes the unit disc.

Exercises

Exercises

1. Projective geometry

Warm-upHuman

In RP2\mathbb{R}P^2, where do the lines y=3x+1y = 3x + 1 and y=3x−2y = 3x - 2 (in the chart z=1z = 1) meet? (Choose all correct descriptions of the meeting point.)

Choose all that apply

2. Projective geometry

Warm-upHuman

How many points does the projective plane F3P2\mathbb{F}_3P^2 over the field with three elements have?

3. Projective geometry

CoreHuman

Four distinct collinear points have cross-ratio (a,b;c,d)=3(a, b; c, d) = 3. Over all 2424 orderings of the four points, how many different values does the cross-ratio take?

4. Projective geometry

CoreHuman

Which properties are preserved by every projective transformation of RP2\mathbb{R}P^2? (Choose all that apply.)

Choose all that apply

5. Projective geometry

CoreHuman

In the proof of Theorem 2 (four points), we write v4=λ1v1+λ2v2+λ3v3v_4 = \lambda_1 v_1 + \lambda_2 v_2 + \lambda_3 v_3 and claim every λi≠0\lambda_i \neq 0. Why?

Choose one

6. Projective geometry

CoreHuman

The non-degenerate conic x2−4xy+4y2+x=0x^2 - 4xy + 4y^2 + x = 0 meets the line at infinity in how many points, and what kind of affine conic is it?

Choose one

7. Projective geometry

CoreFormal

The Lean theorem line_unique has hypotheses (hpq : p ⨯₃ q ≠ 0) (hp : ℓ ⬝ᵥ p = 0) (hq : ℓ ⬝ᵥ q = 0) and concludes ∃ c : K, c • (p ⨯₃ q) = ℓ. What goes wrong if hpq is dropped?

Choose one

8. Projective geometry

StretchHuman

Which statements about the theorems of Desargues and Pappus are true? (Choose all that apply.)

Choose all that apply

9. Projective geometry

StretchComputational

Write join(p, q) returning the cross product of two triples (the line through two points, or the point on two lines) and collinear(p, q, r) returning True when the three points of RP2\mathbb{R}P^2 lie on a line (use the triple product p⋅(q×r)p \cdot (q \times r), with exact integer or fraction arithmetic). Then confirm Pappus' theorem on an example.

Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.
Common misconceptionsH

Common misconceptions

Misconception

"Each direction has two points at infinity, one at each end." A line in the projective plane has exactly one point at infinity: [x:y:0]=[−x:−y:0][x : y : 0] = [-x : -y : 0] (the Lean theorem mk_neg). Walking off to infinity along a line in one direction, you come back from the other side. That is why RP1\R P^1 is a circle and why RP2\R P^2 is non-orientable.

Misconception

"Distances and angles are projective notions." Projective transformations preserve incidence, collinearity and cross-ratio, but not distances, ratios of lengths, midpoints, angles or parallelism. A perspective photograph of a square is usually not a square, and a circle can become a parabola. Distances come back only when extra structure is fixed: in Klein's view, Euclidean geometry is projective geometry with a distinguished line at infinity and a pair of "circular points" on it.

Misconception

"The cross-ratio doesn't depend on the order of the points." It does. The 2424 orderings give up to six values λ,1/λ,1−λ,…\lambda, 1/\lambda, 1 - \lambda, \dots (three for a harmonic range). What is invariant is the cross-ratio of four points in a given order under projective maps.

Misconception

"Ellipses, parabolas and hyperbolas are fundamentally different curves." Affinely they are, but projectively they are one curve: the difference is only how the conic meets the line at infinity (0, 1 or 2 points), as Theorem 6 and the visualisation show. Even the empty "conic" x2+y2+z2=0x^2 + y^2 + z^2 = 0 becomes a circle over C\C.

Misconception

"Desargues' theorem is a consequence of the incidence axioms." It is not. There are projective planes satisfying "two points determine a line, two lines meet in a point" (plus a non-degeneracy axiom) in which Desargues fails. Desargues' theorem is exactly the condition for coordinates from a division ring, and the proof above needed coordinates, or a third dimension.

ViewpointsH

Many ways of seeing

Geometry— Klein's hierarchy: projective, affine, Euclidean, hyperbolic

In Klein's Erlangen programme (1872) a geometry is a space together with a group of transformations, and projective geometry, with PGLn+1PGL_{n+1}, sits at the top of a hierarchy. Fixing a line at infinity cuts the group down to the affine group, which also preserves parallelism and ratios along lines. Fixing also the two circular points [1:±i:0][1 : \pm i : 0] cuts it down to the similarities, the transformations of Euclidean geometry up to scale; every circle passes through the circular points, which is why two circles meet in at most two finite points. Fixing a non-degenerate conic instead gives the projective model of the hyperbolic plane (the Beltrami–Klein model), where the distance between two points is 12∣log⁡∣\tfrac12|\log| of a cross-ratio — Cayley's projective metric (1859). See transformation geometry and non-Euclidean geometry.

Topology— RP² is a non-orientable surface; RPⁿ and its loops

RP2\R P^2 is a disc with antipodal boundary points identified: a compact surface with Euler characteristic 11 (one vertex, one edge, one face in the obvious cell structure). A neighbourhood of a line is a Möbius band, so it is non-orientable, and it cannot be embedded in R3\R^3, although it can be immersed (Boy's surface, 1901). Its fundamental group is Z/2\Z/2: a projective line, traversed once, is a loop that cannot be shrunk, and traversed twice it can. The same holds for RP3\R P^3, which is the rotation group SO(3)SO(3) (see matrix groups), while CP1\C P^1 is the 2-sphere and CPn\C P^n is simply connected. See surfaces and Euler characteristic and the fundamental group.

Algebra— Coordinates from axioms, and the home of algebraic geometry

The theorems of Desargues and Pappus are algebra in disguise. Starting from the incidence axioms alone, Hilbert built coordinates for a plane satisfying Desargues by constructing addition and multiplication of points on a line geometrically; the associative law of multiplication is Desargues, and commutativity is Pappus. Projective space is also the natural home of algebraic geometry: a homogeneous polynomial equation defines a subset of KPnKP^n, and counting works perfectly there. Bézout's theorem says that two plane curves of degrees dd and ee without common component meet in exactly dede points of CP2\C P^2, counted with multiplicity. Two "parallel" lines meet at infinity, a line meets a conic in two points (possibly complex or coincident), and two circles meet in their two finite points plus the two circular points at infinity. See algebraic geometry.

Combinatorics— Finite planes, designs and codes

A finite projective plane of order nn has n2+n+1n^2 + n + 1 points and as many lines, n+1n + 1 points on each line. Planes of every prime-power order exist, from finite fields. Whether any plane exists whose order is not a prime power is a famous open problem. The Bruck–Ryser theorem (1949) rules out orders n≡1,2(mod4)n \equiv 1, 2 \pmod 4 that are not sums of two squares (so no plane of order 66, 1414, 2121, …). Order 1010 was ruled out in 1989 by Lam, Thiel and Swiercz after an enormous computer search, and order 1212 is still undecided. Finite planes are symmetric block designs. The Fano plane gives the [7,4][7, 4] Hamming code, whose codewords of weight 33 are its seven lines, and finite projective geometries underlie much of coding theory and the design of experiments. See combinatorics.

Computation— Homographies in computer vision

A camera is, to first order, a projective map RP3→RP2\R P^3 \to \R P^2 given by a 3×43 \times 4 matrix, and two photographs of a plane differ by a 3×33 \times 3 homography. By Theorem 2, four point correspondences determine it. In practice one solves a least-squares problem with many noisy correspondences (the direct linear transformation algorithm), discarding outliers with random sampling (RANSAC, Fischler and Bolles, 1981). This is how panoramas are stitched, documents rectified, and players located on a pitch from a broadcast. Homogeneous coordinates are also the standard in computer graphics, where translations, rotations and perspective all become 4×44 \times 4 matrix products.

Category theory— Projectivisation as a functor; duality as an equivalence

Sending a vector space VV to its projective space P(V)\mathbb P(V) and an injective linear map to the induced map is a functor, from vector spaces and injections to sets (or to spaces). The principle of duality is the identification P(V∗)≅{hyperplanes of P(V)}\mathbb P(V^*) \cong \{\text{hyperplanes of } \mathbb P(V)\}: the lines of RP2\R P^2 are the points of the dual plane P((R3)∗)\mathbb P((\R^3)^*). Because V↦V∗V \mapsto V^* is contravariant, duality reverses inclusions, turning "point on line" into "line through point" (see advanced linear algebra). In algebraic geometry, Pn\mathbb P^n is a scheme representing a functor: maps to Pn\mathbb P^n correspond to line bundles with n+1n + 1 generating sections, a first glimpse of the functor of points (see representable functors).

History & global context

History and global context

  • Optics and perspective. Ibn al-Haytham's Book of Optics (Cairo, c. 1011–1021) established that vision works by light travelling in straight lines from objects to the eye, the geometric basis of perspective; it was widely read in Latin translation. In Florence, Filippo Brunelleschi demonstrated linear perspective around 1415–1420, and Leon Battista Alberti codified it in De pictura (1435). Piero della Francesca and Albrecht Dürer wrote treatises on perspective construction.
  • Ancient roots. Pappus of Alexandria (c. 320 CE) proved the theorem now named after him in his Collection, together with results equivalent to the invariance of the cross-ratio.
  • Desargues and Pascal. Girard Desargues, an architect and engineer in Lyon, introduced points at infinity and treated conics as perspective images of circles in his Brouillon project (1639); his theorem on triangles was published by Abraham Bosse in 1648. Blaise Pascal, aged sixteen, proved his hexagon theorem (1640).
  • The nineteenth-century revival. Jean-Victor Poncelet, a prisoner of war in Saratov in 1813–1814, developed projective methods in his Traité des propriétés projectives des figures (1822). August Möbius (1827) and Julius Plücker introduced homogeneous coordinates, Joseph Gergonne and Poncelet formulated duality, and Karl von Staudt (1847) made projective geometry independent of distance. Arthur Cayley (1859) and Felix Klein (1871–1872) showed that Euclidean and non-Euclidean metrics arise from projective geometry.
  • Foundations. David Hilbert's Grundlagen der Geometrie (1899) linked Desargues and Pappus to the algebra of coordinates, F. R. Moulton gave a non-Desarguesian plane (1902), Oswald Veblen and Joseph Wedderburn found non-Desarguesian finite planes (1907), and R. C. Bose's work in India in the 1930s and 1940s connected finite geometries to the design of statistical experiments and to coding theory.
Further reading

Further reading

  • H. S. M. Coxeter, Projective Geometry (1964; 2nd ed. 1974) — the classic synthetic introduction, axioms to conics.
  • Jürgen Richter-Gebert, Perspectives on Projective Geometry (2011) — homogeneous coordinates, cross-ratios, conics and computation, beautifully illustrated.
  • Pierre Samuel, Projective Geometry (1986; English 1988) — a short, linear-algebra-first course including cross-ratios and conics.
  • Robin Hartshorne, Foundations of Projective Geometry (1967) — axioms, Desargues, Pappus and coordinatisation.
  • Marcel Berger, Geometry I and II (1977; English 1987) — projective geometry within the whole of classical geometry.
  • Richard Hartley and Andrew Zisserman, Multiple View Geometry in Computer Vision (2000; 2nd ed. 2004) — projective geometry at work in cameras and images.