Mouse cursor inside rotated rectangle

Started by
6 comments, last by andy82 17 years, 6 months ago
Hi, I'm looking for a way to determine if the mouse cursor is inside my rotated rectangle. For example I have an rectangle defined by x1,y1,x2,y2 and the rotation angle alpha. Now I want to find out when the mouse cursor is inside that rectangle and when it is outside. The standard 2D collision detection between two rectangles does not work here because the rectangle is rotated. Furthermore, I do not have the rotated rectangle as a gfx bitmap in memory, so I cannot check if the pixels are transparent or opaque either. Anyone got a idea for this case? Thanks in advance! Andy
Advertisement
For the purposes of this test, is the mouse cursor represented as a point or a rectangle? (I couldn't quite tell from your post...)
You can either rotate the cursor around the same origin that the rectangle is rotated and then run the intersection, or unrotate the rectangle and 'unrotate' the cursor with the rectangle. The important thing here is to bring both the entities into the same space. When the rectangle is rotated and the cursor is not, the rectangle is in world space and the cursor in screen space, even though though they are both views in screen space:

    *   *   *  *       *             C *           *    *       *       *   *          *

TO:
                       C*   *   *   **           **           **   *   *   *

The bottom one is the rectangle unrotated and the cursor rotated back to keep it in the right place. You can then do your simple bounds checking.

There are other algorithms for doing this ofcourse.

Dave
@jyk: The cursor is just represented as a point.
@Dave: Ok, sounds good, thanks. I'll try to do it that way.

Andy
Hmm. I've some problems implementing the version suggested by Dave. Specifically, I don't know how to check the collision after rotating the pointer coordinates.

Here's what I do (pseudo-code):

drawrect(0, 0, 100, 100, 45) ; 100x100 rect at 0:0 - by rotated 45 degreesfunction onmousemove(mousex, mousey)   angle = (360 - 45) * PI / 180   ; move to same origin as rectangle   mousex = mousex - 100 / 2   mousey = mousey - 100 / 2      ; rotate   rx = mousex * cos(angle) - mousey * sin(angle)   ry = mousey * sin(angle) + mousey * cos(angle)     ; move back   rx = rx + 100 / 2   ry = ry + 100 / 2endfunction


Now the question is: How do I check the collision between rx,ry and the rotated rectangle? I've problems imagining the solution... I mean, now I have the rotated mouse cursor coordinates rx,ry but I still do not see how I could use them to check if they're inside the rotated rectangle which looks like this in 45 degrees.

      *    *   *  *       **           *  *       *    *   *      *
You shouldn't be thinking of this rotation as a straightforward rotation in 2-space, but as a coordinate transformation. Imagine the image of a horizontal line (moving your mouse from side to side) under this transformation: it is a (generally) diagonal line parallel to two of the sides of the rectangle. Similarly, vertical mouse movenment will transform to be parallel to the other two sides.

So the transformation has aligned the two coordinate systems, and hence the intersection test is simple. Allow me to generalise your pseudocode somewhat:

drawrect(RECT_L, RECT_T, RECT_R, RECT_B, RECT_ORIENTATION) ; (RECT_R - RECT_L)x(RECT_B - RECT_T) rect at (RECT_L, RECT_T) rotated by RECT_ORIENTATION degrees clockwisebool IsMouseInRect(mousex, mousey)   angle = (360 - RECT_ORIENTATION) * PI / 180   ; move to same origin as rectangle   mousex = mousex - (RECT_R + RECT_L) / 2   mousey = mousey - (RECT_B + RECT_T) / 2      ; rotate   rx = mousex * cos(RECT_ORIENTATION) - mousey * sin(RECT_ORIENTATION)   ry = mousey * sin(RECT_ORIENTATION) + mousey * cos(RECT_ORIENTATION)     ; move back   rx = rx + (RECT_R + RECT_L) / 2   ry = ry + (RECT_B + RECT_T) / 2   if (rx > RECT_R) return false   if (rx < RECT_L) return false   if (ry > RECT_B) return false   if (ry < RECT_T) return false   return trueendfunction


Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Regarding my suggestion, the idea is to rotate the rectangle so that it is squared up, but with it you rotate the cursor position, around the same origin as the rectangle. This is keeping the cursor in the same position relative to the rectangle. You can then do regular bounds testing.

Dave
Thanks guys. It's working now. I'm doing it the way Dave suggested, i.e. unrotate the rectangle and the cursor coordinates, then check if the two things collide.

This topic is closed to new replies.

Advertisement