0

I can't seem to get the standard answer to work. I'm trying to find the new x,y coordinates of a point inside a larger rectangle, after rotating the larger rectangle around its center. (The end goal is to calculate the 4 corners of a collision box inside the larger rectangle.)

The rectangle is 50W x 128H, and the point inside the rectangle is at 15,111. If I rotate this same rectangle 90 degrees clockwise in Photoshop around its center, the point becomes 17,15 inside the rectangle that is now 128W and 50H.

However, if I use the formula I've found 100 times around here for the same question, I get a completely different answer.

import java.awt.*;


public class MyClass {
    public static void main(String args[]) {
        int width=50;
        int height=128;
        int cx = width/2;
        int cy = height/2;

        // should get 17,15
        rotateXY(15,111,cx,cy,-90D); // returns 61,85, which is not even inside the image anymore
        rotateXY(15,111,cx,cy,90D); // returns -11,66. 
    }


    
    public static void rotateXY(int x, int y, int cx, int cy, double degrees) {
        // x, y - coordinates of a corner point of the square
        // cx, cy - center of square coordinates

        double angle = Math.toRadians(degrees);

        double x1 = x - cx;
        double y1 = y - cy;
        
        double x2 = x1 * Math.cos(angle) - y1 * Math.sin(angle);
        double y2 = y1 * Math.cos(angle) + x1 * Math.sin(angle);
        
        int rx = (int) x2 + cx;
        int ry = (int) y2 + cy;
        System.out.println(rx + "," + ry);
    }

}

Before rotating

After rotating

The method I used to rotate the image in java:

    public static BufferedImage rotate(BufferedImage bimg, Double angle) {
        double sin = Math.abs(Math.sin(Math.toRadians(angle))),
                cos = Math.abs(Math.cos(Math.toRadians(angle)));
        int w = bimg.getWidth();
        int h = bimg.getHeight();
        int neww = (int) Math.floor(w*cos + h*sin),
                newh = (int) Math.floor(h*cos + w*sin);
        BufferedImage rotated = new BufferedImage(neww, newh, bimg.getType());
        Graphics2D graphic = rotated.createGraphics();
        graphic.translate((neww-w)/2, (newh-h)/2);
        graphic.rotate(Math.toRadians(angle), w/2, h/2);
        graphic.drawRenderedImage(bimg, null);
        graphic.dispose();
        return rotated;
    }
Zizzyzizzy
  • 309
  • 1
  • 7
  • Something I noticed when playing with the standard answer for this problem is that the numbers calculate correctly only if the full image is exactly square. All bets are off when it is a rectangle, however. I tried spoofing it as a rectangle and then doing some adjustments before and after the calculation, but could never get it working correctly for arbitrary rotation angles. – Zizzyzizzy Jun 27 '22 at 22:10

1 Answers1

1

I assume you created an AffineTransform. With that you need three transformations:

  1. translate the rectangle so it's center point is the origin
  2. rotate the rectangle by some angle
  3. translate the rectangle back to the position where it came from

Now with this you were able to transform the rectangle's coordinates (corners) into new screen coordinates. What you need is a transformation to get from new screen coordinates back to coordinates inside your rectangle. I think it looks like this:

  1. translate the point the same as in step 1
  2. rotate by the negative angle
  3. undo step 1

These AffineTransforms can be applied quite efficiently, compared to your algorightm using trigonometry which even may have a limited range of validity.

See also Rotating Image with AffineTransform

Queeg
  • 7,748
  • 1
  • 16
  • 42
  • Nope, I used a wonderful method someone here used as an answer for rotating a BufferedImage without unwanted cropping. https://stackoverflow.com/questions/44086310/how-to-rotate-a-buffered-image-without-cropping-it-is-there-any-way-to-rotate-a – Zizzyzizzy Jun 27 '22 at 01:59