Okay this is a very sloppy thing…it all started when this tweet came across my timeline:

Did you know all rigid transformations in 2D can be parameterized as a rotation about a pivot? Solving for the pivot point of a transformation is a fun brain-teaser you can inflict on your friends!https://t.co/XkppNf2cuV pic.twitter.com/nsFDj3YweZ

— Johnathon Selstad October 15, 2019

which I found pretty neat so I took a quick peek at the source code. Now, me being me, I tossed out an observation which will not be generally obvious. (Note it doesn’t matter in this case…it’s not a computation that’s going to be statistically significant nor is tighten the error bound going to be of any interest…the point of the exercise it so demo a property.) Specifically one operation performed is a *SLERP* with a fixed interpolation value of $\frac{1}{2}$. Basically I made the “clever” observation that algebraically we have:

and since $t=\frac{1}{2}$ this reduces to:

The code also fixes $A=1$ so this further reduces to $\sqrt{B}$. Using trig half-angle identities we get:

As noted in the code comments this version does not handle input with negative $w$. This can be patched up by taking the abs of $w$ when computing $d$ and scaling the bivector by the sign of $d$ (see below).

I quicky remembered that most people won’t be familiar with quaternion square roots, so doubled-down with a follow-up “clever” comment along the lines of: *“Oh and if we think of our two quaternions as points on the 3-sphere then they along with the origin form a plane…so just bisect the coord!”*. Now of course by “clever” I mean the formal meaning of completely useless to anyone expect those that already know what’s being said.

## Being not clever and unfix A

What I really should have said is that *nlerp* is exact at $t=\frac{1}{2}$ so one could just use that instead of slerp. That works out to be about the same complexity as the above (assuming *nlerp* is inlined) with the added patch of handling input with negative $w$. But since I’m typing let’s sketch out the second comment…with a busy figure:

.

Super quick:

- We have two rotations represented by unit quaternions $A$ (blue points) and $B$ (red points).
- There are two of each since all points on a line through the origin (excluded) represent the same rotation. Since we’re restricting ourselves to unit magnitude we’re down to two choices for a given rotation.
- $A$, $B$ and zero (origin) form a plane. This plane intersected with the set of unit quaternion forms a unit circle. We’re a 2D problem from here.
- LERPing from $A$ to $B$ linearly parameterizes the purple coord that connects them. The small purple point is at 1/2.
- SLERPing from $A$ to $B$ linearly parameterizes the angle of the arc between them. The large purple point is at 1/2.
- The line through the origin and $A+B$ (other small purple point) bisects both the coord and the arc.

We have two remaining gotchas:

- We need to choose the shortest path between the pair. If $ A\cdot B $ is negative we need to negate one of the inputs. Gray coord show the long path.
- When the angle between them is $\pi/2$, when \left(A \cdot B = 0 \right)$, we’re at a branch point, the two possible paths are the same length and we have to choose one. This isn’t a quaternion specific issue.

So we need to compute $\left(A+B\right)~$ if $A \cdot B \ge 0$ and otherwise $\left(A-B\right)$, then normalize that result:

We can rework the previous by noting the normalization scale is: $1/\sqrt{d}$ with

These two variants have approximately the same number and mix of operations but with the shuffling around dependencies. Just for fun we could pull out the scaling by the normalization factor and return it to be folded in a later operation: