0

my problem consists of rotating a triangle around the T axis so that the point A faces the point P. The only known points are A, B, C and the T (the center of the triangle), look at the left figure below.

My question is how to make this transformation and have the new coordinates (x, y) of the 3 points (A,B,C) that form the triangle as in the right figure below :

enter image description here

EDIT:

VertexArray rotatedTri(Vector2f T,Vector2f P,Vector2f A,Vector2f B,Vector2f C)
{

VertexArray mtri(Triangles);

double s = atan2(P.y-T.y,P.x-T.x) - atan2(A.y-T.y,A.x-T.x);

double aX = P.x + cos(s) * (A.x-P.x) + sin(s) * (A.y - P.y);
double aY = P.y + sin(s) * (A.y-P.y) + cos(s) * (A.x - P.x);

double bX = P.x + cos(s) * (B.x-P.x) + sin(s) * (B.y - P.y);
double bY = P.y + sin(s) * (B.y-P.y) + cos(s) * (B.x - P.x);

double cX = P.x + cos(s) * (C.x-P.x) + sin(s) * (C.y - P.y);
double cY = P.y + sin(s) * (C.y-P.y) + cos(s) * (C.x - P.x);


mtri.append(Vector2f(aX,aY));
mtri.append(Vector2f(bX,bY));
mtri.append(Vector2f(cX,cY));

return mtri;
}
ganzo db
  • 25
  • 5

2 Answers2

0

Write each point like $A$ as $(a_x, a_y)$.

Let $$ s = atan2(p_y- t_y, p_x - t_x) - atan2(a_y - t_y, a_x - t_x); $$ That's the angle ($\bmod 2\pi$) between the rays $TA$ and $TP$. Then $$ a'_x = t_x + \cos(s) (a_x - t_x) - \sin(s) ( a_y - t_y) \\ a'_y = t_y + \sin(s) (a_x - t_x) + \cos(s) ( a_y - t_y) $$ and similar formulas hold for $B'$ and $C'$, where primed points indicate "post-transform". So $$ b'_x = t_x + \cos(s) (b_x - t_x) - \sin(s) ( b_y - t_y) \\ b'_y = t_y + \sin(s) (b_x - t_x) + \cos(s) ( b_y - t_y) $$ etc.

(Note: atan2 is a standard function in most computer math libraries; roughly, $atan2(y, x)$ is a slight generalization of $\arctan(\frac{y}{x})$ to handle angles of magnitude greater than $\pi/2$.)

Matlab code:

function mse2()
% pick three points A, B, C, and let T be their average, to give a point to
% rotate around. Then pick $P$ that's farther from $T$ than any of the
% three points:
clear;
close all;

A = rand(2, 1); B = rand(2, 1); C = rand(2, 1); 
T = (A + B + C)/3; 
m = max([dot(T-A, T-A), dot(T-B, T-B), dot(T-C, T-C)]); 
d = 2 * sqrt(m); % twice the distance to the closest point. 
v = rand(1); 
P = T + [d * cos(v), d* sin(v)]; 

% show this 
hold on; 
tplot(A, 'A');
tplot(B, 'B');
tplot(C, 'C');
tplot(T, 'T');
tplot(P, 'P');
plot([A(1), B(1), C(1), A(1)], [A(2), B(2), C(2), A(2)], '-r');

%
% OK, now compute the primed points:
s = atan2( P(2) - T(2), P(1) - T(1)) - atan2(A(2) - T(2), A(1) - T(1)); 
cc = cos(s);
ss = sin(s); 
M = [cc, -ss; ss, cc];

Ap = T + M*(A-T);
Bp = T + M *(B-T);
Cp = T + M * (C-T)
tplot(Ap, 'Ap');
tplot(Bp, 'Bp');
tplot(Cp, 'Cp');
plot([Ap(1), Bp(1), Cp(1), Ap(1)], [Ap(2), Bp(2), Cp(2), Ap(2)], '-g');
hold off;
figure(gcf)

function tplot(X, name)
plot(X(1), X(2), 'o');
text(X(1) + 0.01, X(2), name);

Here's a typical (graphics) output of the program, showing before (Red) and after (green): enter image description here

John Hughes
  • 93,729
  • Thank you, i'll try it ! – ganzo db Jul 20 '17 at 13:56
  • I've tried the formula but the result is a straight line formed of the three points (A, B, C) instead of a triangle – ganzo db Jul 20 '17 at 14:45
  • Can you show your code, please? I'm pretty sure what I wrote is correct (or very nearly so). – John Hughes Jul 20 '17 at 14:47
  • I've edited my post ! – ganzo db Jul 20 '17 at 14:53
  • Fixed. I mistakenly wrote "p" in the formula where I should have had "t", and got the $+/-$ on the sines in the wrong places so that the rotation went in the wrong direction. – John Hughes Jul 20 '17 at 15:04
  • I don't know why but the shape of the triangle has been changed, they have not kept their original measure, and the rotation has not succeeded (There are random angles), the formula is supposed to rotate them not change shape if I understand correctly ? – ganzo db Jul 20 '17 at 15:31
  • The code I provided (in matlab, but I'm hoping you can make some sense of it) works fine, as the attached image example shows. I can't really do much more than give you formulas and a working implementation of them; debugging your own code is really up to you. – John Hughes Jul 20 '17 at 15:52
  • If you replace your posted code with your updated code, I'll take a quick look, but... – John Hughes Jul 20 '17 at 15:53
  • Wait...I just noticed that in the second line of each formula (the formula for $a_y'$, for instance) I had the $x$s and $y$s swapped. i've fixed those now, and perhaps this will help make your code work. – John Hughes Jul 20 '17 at 15:56
0

[This is a variation of John Hughes’ answer that doesn’t require explicitly computing any angles or trigonometric functions of them.].

Let the coordinates of the points be $A(a_x,a_y)$, $B(b_x,b_y)$, etc. A rotation about the point $T$ is accomplished by first translating $T$ to the origin, rotating about the origin, and then translating back. The first and last steps are done by subtracting/adding, respectively, the coordinates of $T$ to those of the other points, so the only tricky part is working out the rotation in between.

We can break that rotation down into two steps: first, rotating so that the point $A$ is on the positive $x$-axis, and then rotating from there to align it with $P$. Using the fact that the columns of a transformation matrix are the images of the basis, we can write down a matrix for the second rotation without explicitly computing the rotation angle. The $x$-axis gets sent to a unit vector in the direction of $P-T$, so the first column is $P-T$, normalized. The second column is the image of the $y$-axis, which is just $P-T$ rotated 90° counterclockwise and normalized. So, the second rotation is represented by the matrix $$R_2={1\over\sqrt{(p_x-t_x)^2+(p_y-t_y)^2}}\begin{bmatrix}p_x-t_x & -(p_y-t_y) \\ p_y-t_y & p_x-t_x \end{bmatrix}.$$ We can construct the first rotation matrix $R_1$ in a similar way. However, for that we want to rotate $A-T$ to to $x$-axis, so we want the inverse matrix, which for a rotation is its transpose. That is, instead of $A-T$ being the first column, it’s the first row. That gives $$R_1={1\over\sqrt{(a_x-t_x)^2+(a_y-t_y)^2}}\begin{bmatrix} a_x-t_x & a_y-t_y \\ -(a_y-t_y) & a_x-t_x \end{bmatrix}.$$ The matrix for the total rotation is the product of these two matrices: $$R=R_2R_1={1\over\sqrt{({a'_x}^2+{a'_y}^2)({p'_x}^2+{p'_y}^2)}}\begin{bmatrix} a'_xp'_x+a'_yp'_y & -(a'_xp'_y-a'_yp'_x) \\ a'_xp'_y-a'_yp'_x & a'_xp'_x+a'_yp'_y\end{bmatrix}$$ where $A'=(a'_x,a'_y)=A-T=(a_x-t_x,a_y-t_y)$ and so on. Comparing this to John Hughes’ answer, we can see that $$\begin{align} \cos(s) &= {a'_xp'_x+a'_yp'_y \over \sqrt{({a'_x}^2+{a'_y}^2)({p'_x}^2+{p'_y}^2)}} \\ \sin(s) &= {a'_xp'_y-a'_yp'_x \over \sqrt{({a'_x}^2+{a'_y}^2)({p'_x}^2+{p'_y}^2)}} \end{align}$$ so you can use these formulas to get the sine and cosine of the total rotation angle directly without needing to compute any of the angles explicitly. From there, you can proceed as in the other answer. (These two expressions can also be derived from the formulas for the sine and cosine of the difference of two angles.)

It’s also useful to perform a couple of sanity checks to make sure that you haven’t made a sign error or some other mistake along the way. Since you want $A$ to end up aligned with $P$, you can compute the resulting point directly: it’s just $T+{|A-T|\over|P-T|}(P-T)$. Compute that for a couple of sample configurations and compare it to the result you’re getting from the rotation. Another sanity check is to compute the determinant $$\begin{vmatrix}a_x&a_y&1\\b_x&b_y&1\\c_x&c_y&1\end{vmatrix}$$ before and after rotating the points. The values should be equal.

amd
  • 53,693
  • Thank you for the time spent on this answer, I can't vote because of my level but I can say again thank you @adm, and John Hughes too ! – ganzo db Jul 21 '17 at 17:23