4

I am trying to rotate a 2D Point in java around another with a specified degree value, in this case simply around Point (0, 0) at 90 degrees.

Method:

public void rotateAround(Point center, double angle) {
    x = center.x + (Math.cos(Math.toRadians(angle)) * (x - center.x) - Math.sin(Math.toRadians(angle)) * (y - center.y));
    y = center.y + (Math.sin(Math.toRadians(angle)) * (x - center.x) + Math.cos(Math.toRadians(angle)) * (y - center.y));
}

Expected for (3, 0): X = 0, Y = -3

Returned for (3, 0): X = 1.8369701987210297E-16, Y = 1.8369701987210297E-16

Expected for (0, -10): X = -10, Y = 0

Returned for (0, -10): X = 10.0, Y = 10.0

Is something wrong with the method itself? I ported the function from (Rotating A Point In 2D In Lua - GPWiki) to Java.

EDIT:

Did some performance tests. I wouldn't have thought so, but the vector solution won, so I'll use this one.

Community
  • 1
  • 1
Aich
  • 962
  • 2
  • 9
  • 19

2 Answers2

11

If you have access to java.awt, this is just

double[] pt = {x, y};
AffineTransform.getRotateInstance(Math.toRadians(angle), center.x, center.y)
  .transform(pt, 0, pt, 0, 1); // specifying to use this double[] to hold coords
double newX = pt[0];
double newY = pt[1];
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Is it fast enough? I need the method to be ultra fast for using in a game. Native routines doesn't seem to be that performance-optimized. – Aich Apr 03 '12 at 01:35
  • AWT is built for graphics, which frequently means games -- so, I wouldn't worry. – Louis Wasserman Apr 03 '12 at 04:13
2

You're mutating the X value of center before performing the calculation on the Y value. Use a temporary point instead.

Additionally, that function takes three parameters. Why does yours only take two?

Peter
  • 4,021
  • 5
  • 37
  • 58
  • In the Lua Code the first parameter is the point that shall move. Functions there seem to be not bind to classes, like in PHP. In my java code the first parameter comes before the method call, point.rotateAround(center, angle). – Aich Apr 03 '12 at 00:22
  • Added the temp coordinates, the method does still return unexpected values. =/ – Aich Apr 03 '12 at 00:35
  • 1
    Can you post your new code then? Because @Peter has correctly explained why your code doesn't do the right thing. It sounds like you haven't correctly understood what he asked you to do. – Dawood ibn Kareem Apr 03 '12 at 04:15
  • 1
    @Peter @David `public class Point { double x, y; public Point(double x, double y) { this.x = x; this.y = y; } public void rotateAround(Point center, double angle) { double tempx = center.x + (Math.cos(Math.toRadians(angle)) * (x - center.x) - Math.sin(Math.toRadians(angle)) * (y - center.y)); double tempy = center.y + (Math.sin(Math.toRadians(angle)) * (x - center.x) + Math.cos(Math.toRadians(angle)) * (y - center.y)); x = tempx; y = tempy; } public String toString() { return "Point { X = " + String.valueOf(x) + ", Y = " + String.valueOf(y) + " }"; } }` – Aich Apr 03 '12 at 04:31
  • The code format broke, sorry, you should reformat it on an IDE. – Aich Apr 03 '12 at 04:32
  • @Aichi, I just ran this code, and got much what I expected. There's a tiny rounding error, but this was no surprise. What do you think it's doing wrong? – Dawood ibn Kareem Apr 03 '12 at 07:31
  • For example, <10, 0> around <0, 0> rotated by 90* returns <6.123, 10> while I'd expect <0, -10>. Do you get the right coords with these values? – Aich Apr 03 '12 at 07:39
  • 1
    OK, that's not 6.123..., that's 6.123 x 10^-16. Which is a tiny number, and is just the usual inaccuracy you'd expect when dealing with floating point numbers. That is, it's effectively indistinguishable from zero. And the reason why y comes out as 10, not -10, is that your formula rotates ANTICLOCKWISE; so going 90 degrees from ( 10, 0 ) gives you ( 0, 10 ). – Dawood ibn Kareem Apr 03 '12 at 10:57