Projective geometric algebra
Reflections in PGA 2D
In PGA, a normalized line can act as a mirror. Point reflection is the base operation; polygon reflection applies the same action to each vertex.
The meet/join article used lines as constraints. A normalized line can also act as an operator. We stay in ganja's plane-based 2D PGA convention, Algebra(2,0,1): lines are grade-1 vectors, finite points are grade-2 bivectors, and a finite point still has the form 1e12 - x * 1e02 + y * 1e01.
Axis-aligned mirrors such as x = 0 or y = 0 reduce reflection to a coordinate sign change. An arbitrary normalized line handles the same operation directly.
Normalize The Mirror
A line is represented as
line = a e1 + b e2 + c e0For reflection, the line should be normalized so the Euclidean normal has unit length:
length = sqrt(line.e1 * line.e1 + line.e2 * line.e2)
mirror = line / lengthRepresentative scale leaves the geometry fixed. Normalization happens at the action boundary, so a different nonzero representative of the same line gives the same reflection.
Sandwich Action
Ganja writes the sandwich action with >>>:
P' = mirror >>> PFor a normalized mirror line, that action is the geometric reflection of the point. The explicit version is the same idea as mirror P reverse(mirror); ganja's operator matches the notation used in its PGA examples.
A polygon uses the same reflection formula on each vertex. Its vertices are finite PGA points, so each reflected vertex is another normalized point bivector.
One Reflection Reverses Orientation
The reflected polygon has the same edge lengths and the same distances to the mirror line, but its orientation flips. In ordinary graphics terms, one reflection changes handedness. The signed area before and after reflection records the reversal as a sign change.
Two reflections restore orientation and produce ordinary rigid motions: rotations when the mirror lines meet, translations when they are parallel.
From Points To Shapes
The same point action applies to every vertex of a shape:
P = e12 - x e02 + y e01
P' = mirror >>> P
-> normalized finite point bivector
triangle.map((V) => mirror >>> V)
-> normalized reflected point bivectorsThe reflected shape is the collection of reflected vertex points. Keeping those points in bivector form keeps the operation in the algebra before converting back to coordinate tuples.