Getting transformed, rotated coordinates relative to the center of a rotated image.

983 Views Asked by At

I've got an image on a canvas and I need to figure out the position of the mouse relative to that image, including it's rotation.

Here the image is shown with no rotation. The mouse is at the absolute position 850, 400 which is 250, 0 relative to the center of the image.

enter image description here

If I rotate the image 270° the mouse is now at the absolute position 600, 150, but the position relative to the image is exactly the same.

enter image description here

Given the absolute position of the center of the image, the rotation of the image, and the absolute position of the mouse, how can I determine the position of the mouse relative to center of the rotated image?

Final solution

In case anyone else prefers code to fancy math symbols, here's Mr. Janisch's answer translated to Javascript:

/**
 * Translate a point's absolute coordinates to it's coordinates 
 * relative to a possibly rotated center point
 * -------------------------------------------------------------
 * @param {number} absPointX - The absolute x ordinate of the point to translate
 * @param {number} absPointY - The absolute y ordinate of the point to translate
 * @param {number} centerX - The absolute x ordinate of the center point of rotation
 * @param {number} centerY - The absolute y ordinate of the center point of rotation
 * @param {number} rotationDegrees - The angle of rotation in degrees
 * @returns {x, y} - The translated point's coordinates
 */
function translatePoint(absPointX, absPointY, centerX, centerY, rotationDegrees=0) {
    // Get coordinates relative to center point
    absPointX -= centerX;
    absPointY -= centerY;
    
    // Convert degrees to radians
    var radians = rotationDegrees * (Math.PI / 180);
    
    // Translate rotation
    var cos = Math.cos(radians);
    var sin = Math.sin(radians);
    var x = (absPointX * cos) + (absPointY * sin);
    var y = (-absPointX * sin) + (absPointY * cos);
    
    // Round to nearest hundredths place
    x = Math.floor(x * 100) / 100;
    y = Math.floor(y * 100) / 100;
    
    return {x, y};
}

Also, the bottom half of Mr. Janisch's answer wasn't what I was originally seeking, but incase anyone else was, here's that answer translated to Javascript as well:

function transformPoint(pointX, pointY, centerX, centerY, rotationDegrees){
  var radians = rotationDegrees * (Math.PI/180);
  var cos = Math.cos(radians);
  var sin = Math.sin(radians);
  var x = centerX + (pointX * cos) - (pointY * sin);
  var y = centerY + (pointX * sin) + (pointY * cos);
  return {x, y};
}
1

There are 1 best solutions below

6
On BEST ANSWER

Edit: I just noticed what your actual question was: Namely, you want to determine the relative position of the cursor to the image if you get the state of current rotation of the image. What I explained below is how to get to this state.

Given: The degree $\theta\in[0,2\pi[$ of rotation of the image, the absolute position $(a,b)^\top$ of the center of the image, absolute position of the mouse $(p_1,p_2)^\top=(a+x,b+y)^\top$.

Question: What is the relative position of the cursor to the center of the image if I were to "unrotate" the image and cursor?

Answer: We can simply rotate the cursor by $-\theta$ degrees around the center of the image. The "unrotated" position of the cursor is thus (explanation below) \begin{split} \text{unrotated position of the cursor}&=\begin{pmatrix}a+x\cos(-\theta)-y\sin(-\theta)\\b+x\sin(-\theta)+y\cos(-\theta)\end{pmatrix}\\ &=\begin{pmatrix}a+x\cos\theta+y\sin\theta\\b-x\sin\theta+y\cos\theta\end{pmatrix}. \end{split}

Thus, the relative position of the "unrotated" cursor with respect to the center of the image is $$\begin{pmatrix}x\cos\theta+y\sin\theta\\-x\sin\theta+y\cos\theta\end{pmatrix}.$$

Example. Your rotated coordinates are $a=600$, $b=400$, $x=p_1-a=600-600=0$, $y=p_2-b=150-400=-250$. Your image is rotated by $\theta=270^\circ = \frac32\pi$. Thus $\sin\theta=-1$, $\cos \theta = 0$. By using the above formula, we get that the relative position of the unrotated cursor with respect to the center of the image is $(0+250,-0+0)^\top$. This is correct.


Short answer:

Given the absolute position of the center of the image $(a,b)^\top$ and the absolute position of the cursor $(p_1, p_2)^\top$, define the relative coordinates of the cursor to the image center by $(x,y)^\top:=(p_1-a,p_2-b)^\top$. Then the new coordinates of the cursor after a rotation by $\theta$ degrees are given by (in absolute terms) \begin{equation} \begin{pmatrix}a+x\cos\theta-y\sin\theta\\b+x\sin\theta+y\cos\theta\end{pmatrix}.\end{equation}

Remark: You will sometimes have to round the above two numbers.

Example: In your case, we have $a=600$, $b=400$, $x=250$, $y=0$. You rotate by $\theta=270 \text{ degrees} = \frac32\pi$. Thus $\sin\theta=-1$, $\cos \theta = 0$. Thus, the new coordinates are $(600+0-0,400-250+0)=(600,150)$.

Explanation:

Let $(0,0)^\top$ be the top left corner of the screen. Let $(a,b)^\top$ be the center of the image. Then the (original) cursor position can be written as $(a+x,b+y)^\top$ (where $(x,y)^\top$ corresponds to the relative position of the cursor to the center of the image.)

Suppose you want to rotate by a degree $\theta$. The corresponding rotation matrix is \begin{equation}A(\theta):=\begin{pmatrix}\cos\theta & -\sin \theta \\ \sin\theta & \cos \theta\end{pmatrix}\end{equation}

We can "move" the circle with center $(a,b)^\top$ and edge point $(a+x,b+y)^\top$ to a circle around $(0,0)^\top$ by substracting $(a,b)^\top$. Then we can use the linear rotation map induced by $A(\theta)$ to rotate and we can finally add back $(a,b)^\top$. Thus, we have the result: \begin{equation}\text{new coordinates}=A(\theta)\begin{pmatrix}x\\y\end{pmatrix}+\begin{pmatrix}a\\b\end{pmatrix}=\begin{pmatrix}a+x\cos\theta-y\sin\theta\\b+x\sin\theta+y\cos\theta\end{pmatrix}.\end{equation}