I convince myself here of the form of a projective transformation of the plane expressed in Cartesian coordinates.
Generators of projective transformations:
Lets see what happens it we introduce one projective transformation which is not affine.
Consider two planes in 3 space:
Consider the projection thru the origin (0, 0, 0).
Consider a different point P in 3 space with integer coordinates (X, Y, Z).
The line thru the origin and P pierces plane 1 at (1, Y/X, Z/X) and plane 2 at (X/Y, 1, Z/Y).
(1, Y/X, Z/X) → (X/Y, 1, Z/Y).
In local coordinates (Y/X, Z/X) → (X/Y, Z/Y).
Stirring with (x, y) → (x+a, y) gives
I think this converges at
(x', y') = A(x, y)
where A is a real 2 by 2 matrix.
x' = x + a
The two above generate all of the affine transformations.
Perhaps those two can best be combined as
(x, y) → (ax + by + c, dx + ey + f)
This correctly counts the 6 degrees of affine freedom.
The triples above are conventional 3D coordinates for 3 space.
Equivalently (x, y) → (1/x, y/x) is the same transformation.
(x, y) → (1/(x+a), y/(x+a))
In the other order we get
(x, y) → (1/x + a, y/x)
adding (x, y) → (y, x) yields
(x, y) → (1/y + a, x/y) and
(x, y) → (y/x, 1/x + a).
(x, y) → ((dx + ey + f)/(ax + by + c), (gx + hy + i)/(ax + by + c)).
The line ax + by + c = 0 is the inverse image of the line at infinity.
If k is a non zero real then multiplying a, b, c,... i each by k produces the same transformation.
This indicates 8 degrees of freedom in agreement with the projective square.
These transformations map rational points onto rational points when the coefficients are rational.
This indicates that an n-dimensional projection has (n+1)2−1 degrees of freedom.
The following code says that the composition of two of these projections leaves collinear points, collinear.
(define (P a b c d e f g h i) (lambda (p) (apply (lambda (x y)
(let* ((D (/ (+ (* a x) (* b y) c))))
(list (* D (+ (* d x) (* e y) f)) (* D (+ (* g x) (* h y) i))))) p)))
(define p1 (P 3 2 4 5 3 6 5 4 7))
(define p2 (P 2 -5 4 3 2/3 5 4 4 5))
(define (p3 x) (p1 (p2 x)))
(ylppa ((fileVal "Matrix") '() 0 zero? 1 + - * /)
(lambda (rm matm matinv ip tr det i? v= m=)
(det (map (lambda (p) (cons 1 p))
(list (p3 '(2 3)) (p3 '(3 5)) (p3 '(9/2 8))))))) ; => 0