Designing Geometric Algebras - Rotors

In the first part of this series we learnt how to create geometric algebras that can represent arbitrary objects. In this second part we will learn about how to create the rotors we want to perform translation, rotation and so on.

Rotor Recap

With each pair of basis vectors we can form a bivector. The bivector can be exponentiated which results in a rotor that, when an object is sandwiched with it, will perform one of three operations depending on what the bivectorBsquares to:
B2etBSandwich action on vector
-1cos(t)+Bsin(t)Rotates between B's two vectors
01+tBTranslates orthogonal to B's two vectors
+1cosh(t)+Bsinh(t)Boosts between B's two vectors
Let's take a look at ordinary 3-space GA. We have three basis vectorsex,ey,ezthat each square to +1. We have three bivectorsexy,eyz,exzthat each square to -1. Thus the bivectors perform a rotation in their planes, meaning, between the components of the two basis vectors they are composed of when applied with the sandwich product to a vector.

Rotors for different up functions

With a more complicated up function this is no different. The bivectors will still eg. rotate between two components of two basis vectors. The result looks more interesting though. If we have a basis vector for thex2term and another basis vector for a constant term, we can rotate between a parabola and a straight line! This is demonstrated below with an algebra that has 3 basis vectors and corresponding terms in the up functionx2,y,1.Here's another example where we rotate an elliptic curve into vertical lines (the algebra can represent vertical line tuples).

Basis vectors as mirrors

If you've seen Steven De Keninck's presentation on dual quaternions you have seen how the rotors arise naturally from viewing the action of the basis vectors as mirrors in the dual view. For example using ordinary 3-space again, each basis vector when applied with the sandwich product will reflect the components along its axis.
As you might have hoped or expected, nothing changes. If we reflect in a basis vector that has anx2coefficient in the up function, sandwiching with that basis vector will reflect in a parabola instead of a line. This is hard to visualize, especially for understanding how the rotors arise from these mirrors but it does all work out the same.

Rotor exploration

Here are some things I tried. I might remove this section later or move it to a new page once I figure out a good pattern for constructing our desired rotors. Beware of mistakes.
PGA-like rotors for rotation and translation
Depending on what our basis vectors square to we will get different squares for the bivectors. This makes it tricky to get all the transformations we want. For example we can't easily get both rotation betweene1,e2and translation orthogonal to it.
However we can introduce a new basis vectore3that squares to zero and add it to our up function with a constant coefficient. Assuming our two basis vectorse1,e2we started with both square to one, we get rotors for rotation betweene1,e2as well as translations in either direction if we sandwich with the exponential of the dual of a vector. For exampleed2e1=1+d2e1is a translator (a rotor doing translation) in the 1-direction bydwhen applied with the sandwich product.
Shear rotors
So far this was all relatively specific to the up function used by PGA where the extra basis vector has a constant coefficient. How does the action of such a rotor look like if the coefficient is not a constant?
Let's look at the simple case with two basis vectors and up functionup(x,y)=xe1+ye2ande12=1bute22=0. We have the bivectore12which squares to zero. When we exponentiate it and apply it with the sandwich product to a vector we get(1+d2e12)(xe1+ye2)(1d2e12)=(1+d2e12)(xe1+ye2d2xe2)=xe1+ye2dxe2=xe1+(ydx)e2It does some sort of translation in thee2direction proportional to thee1value. Forx=0thee2direction is unaffected. The bigger thee1component gets the more thee2direction gets translated. This is a shear in thee2direction, the vector which squares to zero.
"Opposite-PGA" exploration
Let's try the previous PGA rotor example but instead makee12=e22=0ande32=1.

Applyinge13to a vector (line)(1+d2e13)(xe1+ye2+1e3)(1d2e13)=(1+d2e12)(xe1+ye2+1e3+d2e1+d2ye123)=xe1+ye2+1e3+de1+dye123=(x+d)e1+ye2+1e3+dye123This does translation in thee1direction and also some kind of shear ine123proportional to thee2component.e23does the same thing but withe1ande2swapped.

Applyinge12to a vector (line):(1+d2e12)(xe1+ye2+1e3)(1d2e12)=(1+d2e12)(xe1+ye2+1e3d2e123)=xe1+ye2+1e3de123This does translation ine123.

Applyinge12to a bivector (point):(1+d2e12)(xe31+ye23+1e12)(1d2e12)=(1+d2e12)(xe31+ye23+1e12)=xe31+ye23+1e12This is the identity map.

Applyinge13to a bivector (point):(1+d2e13)(xe31+ye23+1e12)(1d2e13)=(1+d2e12)(xe31+ye23+1e12+d2ye12)=xe31+ye23+1e12+dye12=xe31+ye23+(1+dy)e12This is a shear in thee12direction proportional to thee23component. The last bivectore23will do the same thing in the but proportional to thee13component. Since this is a projective point (which follows from inverting the up function, not conjecture!) it's a division of both x and y by1+xor1+y. Also composing the two rotors will give us the following:R=(1+dx2e23)(1+dy2e13)=1+dx2e23+dy2e13+dxdy4e12RpR~=x1+dxx+dyye31+y1+dxx+dyye23+1e12Interestingly the composed rotor picks up thee12part for which we already showed that it is the identity map. In different notation, the composed map is(x,y)(x1+dxx+dyy,y1+dxx+dyy)Perhaps it is possible to construct scaling rotors for each direction this way if we could change thexandyin the denominator by adjusting our up function and basis vectors.
Non-isotropic scaling rotor
We want rotors that only scale in one direction, instead of scaling all directions equally. Start with PGA, but for up instead use the logarithm on the coordinatesup(x,y)=log(x)e1+log(y)e2+1e0If we try to find the inverse mapping (ie. get the(x,y)coordinates a bivector represents) we havex=exp(p1p0),y=exp(p2p0)If we now apply a translatorTx(log(sx))that translates bylog(sx)in theexdirection (just like in the usual PGA), we getTx(log(sx))up(x,y)Tx~(log(sx))=(log(x)+log(sx))ex+log(y)ey+1e0=log(xsx)ex+log(y)ey+1e0Recovering the(x,y)coordinates this result represents using the inverse up mapping we getx=exp(log(xsx)1)=xsxy=exp(log(y)1)=yAnd we have non-isotropic scaling, yay! Of course the same will work for scalingytoo. There is still a big issue though:xandyhave to be greater than zero since the logarithm is not defined otherwise (or we could just use the complex logarithm? although maybe there's a nicer GA way of avoiding arbitrary complex numbers here).
Translators in any variable for polynomial up functions
This part is flawed / wrong, but I left it up since it still contains some useful ideas.
Assume we have an up functionup(x,...)=xe1+x2e2+1e0+...which can represent parabolas, lines, points and so on. If we want to have translation as rotors (translators), it's not that easy. In PGA we only have one basis vector with anxcoefficient so we can do the translation using a single rotored2ex0, but if we did with the above up function we would change thexcoefficient while leaving thex2coefficient untouched. If we look at the OPNS / VPNS of a point that was only translated ine1(xe1+x2e2+1e0)((a+d)e1+be2+ce0)=xbe12+xce10+x2(a+d)e21+x2ce20+(a+d)e01+be02=(xcad)e10+(xbad)e12+(x2cb)e20=0we get three equations that have to vanishxcad=0xbad=0x2cb=0Notice the first and second equation together givexb=xc. But the third equation givesb=x2c. Both of these together givex3c=xcwhich can only be true forx=0. and our wrongly translated point does indeed not represent anything useful.
To get something useful again we need to translate all coefficients wherexappears in the up function. For instancex2should get translated as(1)x2(x+d)2=x2+d2+2dxFirst we need to translate thee2coefficient byd2which is easy using the rotored22e20. Next we need to translate thee2part by2dxwhich is a shear. This is not possible with the current set of basis vectors we have available as we can only translate by constants and not in proportion toxas required here.
We introduce a new basis vectore32=0with coefficientxin the up function. Then we get the rotors we need asede13(note, no division by 2 as we need twice the amount). This solves the issue of translating thex2part. However this introduces a new problem. The new basis vector we introduced has coefficientxso in order to keep it consistent (non-empty OPNS / VPNS) we need to translate it too.
Again this is not that easy because usually we use the bivectors containinge0to do translations. We can't do that here to translatee3because it squares to zero and thus the bivectore30will result in zero when multiplied withe0=e123which is the part that usually enables us to do translation for non-zero squaring basis vectors.
The idea in this step is wrong which makes the entire thing not work out. The bivector will give a shearor not a translator, and will also affect the wrong dual basis vector.We introduce a new basis vectore42=1with coefficient1in the up function. This will allow us to do translations ine3with the bivectore34because it squares to zero (ie. does translation) ande34e4=e34e0123=e0124instead of zero.
Now we can compose all the rotors we just came up with to get a single rotor that does translation inxbyd. In conclusion, we introduced two new basis vectors, one for allowing us to do translation in proportional toxand another to allow us to translate the new basis vector by a constant. The composed rotor is a lot more complicated too. However this will work for any polynomial if we apply this idea recursively. For example forx3we want(x+d)3=x3+d3+3d2x+3dx2. Here we could do the same thing:
  1. Translatex3part byd3
  2. Introduce new basis vector with coeff.xfor translation bydx
  3. Introduce new basis vector for translating the new basis vector byd
  4. Introduce new basis vector for translation relative tox2
  5. New basis vector needs to be translated as(x+d)2so we can apply the same idea
  6. ...
  7. Tears, lots of new basis vectors, complicated rotors, but it works out
Finally here's an example of this in action, however the renderer doesn't seem to like this very much as the points don't get rendered correctly (or I made a mistake somewhere?) but you get the idea hopefully.Perhaps there's a better way. I don't know whether this works for functions other than polynomials either, it might for some, but it certainly doesn't for many because the correction terms can not be done with translators, although if we had more rotors in our toolbox than just translators this might be fixable.

Next: Design of Geometric Algebras - Interpolating Points