Search code examples
javaswingaffinetransform

Determine if mouseclicked inside a rotated rectangle in Java (AWT, swing)


I am having some trouble figuring out how to determine if a mouseclick event was clicked inside of a rectangle, if the rectangle has been rotated.

Lets say I have a MouseAdapter as simple as this. It just prints out a statement saying that we hit inside the rectangle if the mousePressed was in fact within the rectangle.

MouseAdapter mAdapter = new MouseAdapter() {
    public void mousePressed(MouseEvent e) {
        int xPos = e.getX();
        int yPos = e.getY();
        if(xPos >= rect.x && xPos <= rect.x + rect.width && yPos >= rect.y && yPos <= rect.y + rect.height) {
            System.out.println("HIT INSIDE RECTANGLE");
        }
    }
};

My issue comes from when I rotate the rectangle. The if statement above obviously doesn't consider the rotation, so after I rotate the rectangle, my hit test fails. For rotate, I'm doing something as simple as this in a paint() function:

class drawRect {

    Rectangle rect = new Rectangle();

    ...

    public void paint(Graphics g) {
        Graphcis2D g2 = (Graphics2D) g;
        AffineTransform old = g2.getTransform();
        g.rotate(Math.toRadians(90), rect.x, rect.y); 
        g2.draw(rect);
        g2.setTransform(old);
    }
}

This is just some quick pseudocode, so that you guys can understand what I am trying to do. So please don't worry about syntax and all of that. Any help would be appreciated!


Solution

  • You could apply the rotation to your mouse coordinates as well. Dry-coded:

    MouseAdapter mAdapter = new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            // Create the same transform as used for drawing the rectangle
            AffineTransform t = new AffineTransform();
            t.rotate(Math.toRadians(90), rect.x, rect.y);
            Point2D tp = t.inverseTransform(e.getPoint());
    
            if(rect.contains(tp)) {
                System.out.println("HIT INSIDE RECTANGLE");
            }
        }
    };