Previous part: Geometric algebra in 2D and 3D
Disclaimer: there will be NO proofs or rigorous explanations here, just some results and notes on how to use the library
We start with lines. As you can remember, the equation for a line in 2D looks like this:
In order to do operations on lines, as elements of the algebra, let's convert it to the form where it will be linear combination of basis vectors:
Here we introduce new kind of basis vector
For example,

Let's see what elements this algebra consists of:
1
e1 e2 e0
e20 e01 e12
e120
As elements of the algebra, we can add lines together:
Sum of two lines will be some other line, which goes through their intersection point.
For example,

One thing to note here:
In code I define struct that represents line:
struct line2 {
float32 a, b, c;
};
Let's see what basis lines
This is line Oy.

This is line Ox.

Wait a minute, this is nonsense! But if we pause for a minute, this is very useful representation for our purposes, because it works out exactly as the line at infinity!
You have to imagine line that goes around whole plane at infinite distance, being perpendicular to every other "real" line.

Beside lines we also want to represent points. Turns out, outer product of two lines results in intersection point!
This operation is often called meet because it returns a point, where two lines meet.
This is exactly the representation of homogeneous coordinates in 2D:

In code points are represented just like you expect:
struct point2 {
float32 x, y, w;
};
and you can get an intersection of two lines by using outer product:
point2 outer(line2, line2);
But what if we want to intersect two parallel lines? Let's calculate intersection point of
auto line_1 = make_line2(1, -1, -1); // x - y - 1 = 0
auto line_2 = make_line2(1, -1, 1); // x - y + 1 = 0
auto intersection = outer(line_1, line_2);
Remember how we learned that in homogeneous coordinates (x, y, 1) represent point, while (x, y, 0) represent vectors? Turns out we rediscovered those vectors! In projective geometric algebra vectors are points at infinity:

Duality is somewhat new concept for us, in geometric algebra each line have a dual point, and each point have a dual line. Usually dual of a multivector is defined by multiplying by something, but I just replace basis vectors with corresponding dual basis:
We see that dual of a line is just point, where normal vector points to, or just normal vector, if line goes through the origin.
Let's see a couple of examples:


The most amazing feat of duality, is that everything can be turn around, but math will work out just the same. For example, in the Projective geometric algebra Wiki basis elements are swapped onto duals comparing to our implementation, but every result still holds.
Now when we know and understand duality, we can connect two points with a line.
For example, let's draw two points:

The trick goes like this: we see that dual lines cross at some point, let's find this point:
auto point_1 = make_point2(-3, 2);
auto point_2 = make_point2( 3, 1);
auto dual_line_1 = dual(point_1);
auto dual_line_2 = dual(point_2);
auto intersection = outer(dual_line_1, dual_line_2);

Now let's find dual of that intersection point:
auto dual_of_intersection = dual(intersection);

By finding intersection (point that connects two lines) in dual space, we also found line that connects two points in real space. If you ask me, this is kinda magic.
In projective geometric algebra this whole operation is very useful, so they gave it a name regressive product, and write like this:
This operation is often called join because it joins two points by a line.
In code you can use it by calling this function:
line2 join(point2, point2);
In projective geometric algebra we can define inner and outer product not only between vectors, but between any two objects!
The
For example,
Now let's see what the inner product of a line and a point will result to:
This is a line, that goes through a point, but perpendicular to the original line!

Now we can use it to make two projections. First, let's observe that if we find intersection of those two lines, we find projection of a point to a line:
auto line = make_line2(-1, 2, 3);
auto point = make_point2(-1, 2);
auto projected_point = outer(inner(line, point), line);

But if we decided to find the perpendicular line again, we could find so called projection of a line onto a point:
auto projected_line = inner(inner(point, line), point);

In projective geometric algebra all kinds of projections can be found by applying this formula:
but in code, in order to match types, I changed it to inner(inner(B, A), B)
and outer(inner(B, A), B)
. You also can use functions:
point2 project(point2, line2);
line2 project(line2, point2);
In geometric algebra reflections through the line are computed by the formula:
Let's reflect a line
Note that coefficient besides
In code we can't just elliminate one of the coefficient, so element that we got is like a line, but with pseudoscalar. This object is often called flector because it reflects things.
struct flector {
float32 _e1, _e2, _e0, _e120;
};
But because we know for sure that coefficient besides
line2 get_line2(flector f) {
line2 result;
result._e1 = f._e1;
result._e2 = f._e2;
result._e0 = f._e0;
return result;
}
auto L1 = make_line2(-1, 1, -2);
auto L2 = make_line2(-1, 3, -2);
auto L_prime = get_line2(L2 * L1 * L2);

Just like a line with pseudoscalar is a flector, likewise a point with a scalar is a special kind of object, called rotor or motor.
Let's multiply two lines, not with outer product, but with geometric product:
This object will rotate objects around the point, just like quaternion does, twice the angle between original two lines. Also just like quaternions, you can apply rotation using this formula:
Where
For example, I made two lines 45 degrees apart each other, multiplied to make a motor, and then rotated a line by it:
auto line_1 = make_line2(1, -1, -1);
auto line_2 = make_line2(0, 1, -1);
auto motor = line_1 * line_2;
auto line_3 = make_line2(1, 0, 2);
auto line_4 = to_line2(conjugated(motor) * line_3 * motor);

You can rotate points just like lines:
auto line_1 = make_line2(1, -1, -1);
auto line_2 = make_line2(0, 1, -1);
auto motor = line_1 * line_2;
auto point_1 = make_point2(-2, 1);
auto point_2 = to_point2(conjugated(motor) * point_1 * motor);

Why some people call motor a motor, and not a rotor, is because in projective geometric algebra you can use it to make translations and rotations at the same time. You can achieve translation by making motor out of two parallel lines. Then it will translate any object by twice the distance between those two lines.
For example:
auto line_1 = make_line2(1, 1, -1);
auto line_2 = make_line2(1, 1, 1);
auto motor = line_1 * line_2;
auto point_1 = make_point2(-1, 2);
auto point_2 = to_point2(conjugated(motor) * point_1 * motor);

And that's it for 2D case. You can find my library which can do everything I have shown here and the examples all working here.
References: