Reputation: 171
I am working with some SVG files, and I would like to know how to differentiate a simple rotation, from a flip PLUS a rotation.
What I know :
example matrix :
transform="matrix(a,b,c,d,e,f)" Theorical
transform="matrix(1.866 0 -0 1.866 91.480 278.480)" Practical
We can determinate the flip of an element in this matrix by looking at the elements "a" and "d". A negative "a" means an horizontal flip and a negative "d" means a vertical flip.
My troubles arrive when I do a flip PLUS a rotation. The fact is that when I do a simple rotation, "a" and "d" can be negative too ! So how can we determinate if we have only a flip, or only a rotation, or a rotation PLUS a flip ?
Here is a matrix of an element on which I did a simple horizontal flip :
transform="matrix(-2.150 -0.012 -0.012 2.150 252.235 43.335)"
"a" element(-2.150) is negative.
Here is a matrix of an element on which I did a rotation of 135 degrees anti clockwise :
transform="matrix(-1.560 -1.479 1.479 -1.560 245.655 46.646)"
"a" element(-1.560) is negative too, but it is a simple rotation with no flip.
Here is a matrix of an element on which I did a horizontal flip PLUS a rotation of 135 degrees anti clockwise :
transform="matrix(1.674 -1.349 -1.349 -1.674 238.428 45.969)"
"a" element(1.674) is positive dispite of the flip.
Do you know a method with which I could always know if there is a simple rotation, or a simple flip, or a rotation PLUS a flip ?
If I am not clear enough, do not hesitate to ask me for more details.
Upvotes: 2
Views: 599
Reputation: 171
Thanks for the answer, but it did not completely answered my question. I found a solution, so I post it here. I know my solution is not the best and could be improved easily, but I did not have the time to optimize it.
Here is what I did :
With the a and b element of the matrix, I calculated the radiant angle with the atan2 ( in Java Math.atan2(b, a) ). I transformed it in degrees.
Once we have got the degree angle, I did four cases, one for each quarter of the trigonometric circle :
First, I noticed that when you do a flip (horizontal or vertical), "b" and "c" elements have always the same sign.
So, here is the first condition : (sign of b) == (sign of c).
Depending on the sign of "b" element (or "c", because "b" == "c") AND of "d" element, we can determinate if we do a horizontal or a vertical flip.
So to determine precisely if we do a flip (H or V), we need to know the sign of "b" and "c", PLUS the sign of "d".
The last condition is on the sign of the degree angle calculated at the start. It will help us to determine the angle of rotation.
What I understood is that the axes move while we do a flip.
Let me show you the complete solution. I found four conditions, one for each quarter of the trigonometric circle :
double radianAngle = Math.atan2(b, a);
double degreeAngle = Math.toDegrees(radianAngle);
// if "b" and "c" have the same sign means there is a flip (H or V)
if (((b < 0) == ( c < 0))) {
if (b < 0 && d > 0 && degreeAngle < 0) {
// It is a horizontal flip
// The new angle is (- 180 - degreeAngle)
} else if (b > 0 && d < 0 && degreeAngle > 0) {
// It is a vertical flip
// The new angle is (-degreeAngle)
} else if (b > 0 && d > 0 && degreeAngle > 0) {
// It is a horizontal flip
// The new angle is (180 - degreeAngle)
} else if (b < 0 && d < 0 && degreeAngle < 0) {
// It is a horizontal flip
// The new angle is (-degreeAngle)
}
} else {
// No flip (H or V)
}
There are two more conditions which match the cases to the limits :
if (degreeAngle == 180 && a < 0) {
// It is a pure horizontal flip, with no rotation
} else if (degreeAngle == 0 && d < 0) {
// It is a pure vertical flip with no rotation
}
Here is what I finally used, and it works for all the cases. I think it would have been easier to understand with more draws, but I do not have the time to do a more detailed answer.
Hope it helps,
Upvotes: 1
Reputation: 61
Short answer: if ad - bc < 0, it's a reflection.
Long answer: if I understand the Mozilla docs correctly, (x, y) -> (ax + cy, bx + dy) plus a translation we don't need to worry about.
So, what we do is imagine the vectors in 3 dimensions: (x,y,0) -> (ax+cy,bx+dy,0). Take a unit i vector (1,0,0), and a unit j vector (0,1,0) and apply the transformation to each, to get i' and j'.
Now, the cunning bit: calculate the cross product of i' and j' and see whether it still points in the same direction as i x j (= k, (0,0,1) ). If so, the pair i' and j' are the same 'handedness' as i and j and no reflection has taken place. If it is opposite (i.e. pointing along -k) it has been reflected.
Cranking through the numbers, i' = (a,b,0) and j' is (c,d,0), and i' x j' is (0,0,ad-bc). If ad-bc < 0, then it's pointing along -k and a reflection has taken place.
Upvotes: 2