I have been working on the following problem for a while, but I am not making any headway:
Given two points in a view A (ax,ay) and B (bx,by), transform them so that they are positioned at C (cx,cy) and D (dx,dy) respectively. Additionally, since this is for presentation/image processing, the resulting complete transformation must be proportional and not reflected.
Specifically what I want is to directly calculate the single transformation matrix M that can make this change in one step and without using any trigonometric functions, if possible. In other words:
M: A: C:
| xx yx wx | |ax| |cx|
| xy yy wy | * |ay| = |cy|
| 0 0 1 | | 1| | 1|
And
M: B: D:
| xx yx wx | |bx| |dx|
| xy yy wy | * |by| = |dy|
| 0 0 1 | | 1| | 1|
And I want to directly calculate the values of the matrix M.
Now I know that it could be accomplished with the following standard transforms:
- Translate B to the origin: T(-bx,-by)
- Counter-rotate the slope B-A to zero.
- Rotate to the slope D-C.
- Scale distance ||A-B|| to distance ||C-D||: (i.e. ||C-D||/||A-B||)
- Translate from origin to D.
Or, in transform shorthand:
- T(-bx,-by)
- R(-s(B:A))
- R(s(D:C))
- S(|C-D|/|A-B|)
- T(dx,dy)
However, I am using this in a real-time program to present two different dynamic POVs and the overhead of 5 transforms is pretty significant. I also know that I can combine steps 2 and 3, but that would require additional trig functions and trig functions also have a lot of overhead for a real-time display.
Finally, the source points A and B are moving dynamically in the original POV so I cannot just combine all of the steps into one static transform matrix and reuse that (I am actually dynamically remapping the entire view to the second viewport, the GUI will do it for me, if I can supply it with the transform matrix).
I have been trying to derive the calculations by symbolically combining the transformation arrays, or alternatively trying to solve the simultaneous equations using equivalences and proportionality principles but the terms and radicals start to explode and exceed my manual limits pretty quickly. I have been able to avoid the trig functions using slopes and Pythagorean equivalences instead, but that has meant that I end up with a lot of nested expressions with radicals and also the loss of signs that comes with both radicals and slopes. So at this point I think I need some help.
I can supply what I have so far on either approach, but they’re pretty far into the weeds and I’m hoping that this is some standard operation that has a known solution (it’s certainly seems like it would come up a lot). I looked at this question Remapping plane parameters for a different Cartesian system which seemed related, but I didn't understand the question or the answer well enough to reapply it.
Bonus question: Does this operation have a standard name? I have been calling it "Remapping", but that seems pretty generic and search for that doesn't results in anything specific to this.
Also: I don’t know Tex, etc. so anyone who wants the Editor points can edit my post to make it look better symbolically.
I have updated the text above with:
Additionally, since this is for presentation/image processing, the resulting complete transformation must be proportional and not reflected.
Note that $$\left[ \begin{matrix} x_x & y_x & t_x \\ x_y & y_y & t_y \\ 0 & 0 & 1 \end{matrix} \right ] \left [ \begin{matrix} a_x \\ a_y \\ 1 \end{matrix} \right ] = \left [ \begin{matrix} c_x \\ c_y \\ 1 \end{matrix} \right ]$$ is exactly equivalent to $$\left[ \begin{matrix} x_x & y_x \\ x_y & y_y \end{matrix} \right ] \left [ \begin{matrix} a_x \\ a_y \end{matrix} \right ] + \left[ \begin{matrix} t_x \\ t_y \end{matrix} \right ] = \left [ \begin{matrix} c_x \\ c_y \end{matrix} \right ]$$
A pure 2D rotation matrix by counterclockwise angle $\theta$ is $$\mathbf{R}_\theta = \left [ \begin{matrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{matrix} \right ]$$ So, if we write $\mathbf{R}$ as say $$\mathbf{R} = \left [ \begin{matrix} c & -s \\ s & c \end{matrix} \right ]$$ we have four equations in four unknowns ($c$, $s$, $t_x$, and $t_y$): $$\left\lbrace ~ \begin{aligned} c a_x - s a_y + t_x &= c_x \\ s a_x + c a_y + t_y &= c_y \\ c b_x - s b_y + t_x &= d_x \\ s b_x + c b_y + t_y &= d_y \\ \end{aligned} \right.$$ This has exactly one solution, if and only if $$\Delta = (b_x - a_x)^2 + (b_y - a_y)^2 \ne 0$$ or in other words, iff points $A$ and $B$ differ.
To minimize numerical error, I would suggest calculating $$\begin{aligned} \Delta &= (b_x - a_x)^2 + (b_y - a_y)^2 \\ C &= (b_y - a_y)(d_y - c_y) + (b_x - a_x)(d_x - c_x) \\ S &= (b_x - a_x)(d_y - c_y) - (b_y - a_y)(d_x - c_x) \\ \end{aligned}$$ Note that $S^2 + C^2 = 0$ if and only if points $C$ and $D$ are the same, and/or points $A$ and $B$ are the same.
Then, the solution (rotation and scaling, but not skewing or mirroring) for $c$ and $s$ is $$\left\lbrace ~ \begin{aligned} c &= \displaystyle \frac{C}{\Delta} \\ s &= \displaystyle \frac{S}{\Delta} \\ \end{aligned} \right .$$
If you require a pure rotation solution, without scaling, use $$\left\lbrace ~ \begin{aligned} s &= \displaystyle \frac{S}{S^2 + C^2} \\ c &= \displaystyle \frac{C}{S^2 + C^2} \\ \end{aligned} \right .$$
If you are interested in the angle of rotation $\theta$, you can use $$\left\lbrace ~\begin{aligned} \theta &= \operatorname{atan2}(S, C) \\ s &= \cos\theta \\ c &= \sin\theta \\ \end{aligned} \right.$$
After calculating $s$ and $c$, again in an effort to keep numerical errors to a minimum, $$\left\lbrace ~ \begin{aligned} t_x &= \displaystyle \frac{ c_x + d_x + s (a_y + b_y) - c (a_x + b_x) }{2} \\ t_y &= \displaystyle \frac{ c_y + d_y - c (a_y + b_y) - s (a_x + b_x) }{2} \\ \end{aligned}\right.$$
Because the form I used is equivalent to OP's, the single 2×3 transformation matrix sought for is $$\mathbf{M} = \left [ \begin{matrix} c & -s & t_x \\ s & c & t_y \\ 0 & 0 & 1 \end{matrix} \right ]$$