3
votes

I hava a class representing a point (x and y coordinates are double type) and a function to rotate the point around another point:

public Point2D rotate(double angle, Point2D origin) {
    double sin = Math.sin(angle);
    double cos = Math.cos(angle);

    x -= origin.getX();
    y -= origin.getY();

    x = x*cos - y*sin;
    y = x*sin + y*cos;

    x += origin.getX();
    y += origin.getY();

    return this;
}

However when I repeat the rotation many times (i.e. by 1 Degree) I loose much of precision. Example:

    Point2D point = new Point2D(10, 10);
    System.out.println(point);
    for(int i = 0; i < 360; i++)
        point.rotate(Math.toRadians(1), new Point2D(300, 150));
    System.out.println(point);

And the results:

[10.0, 10.0]
[25.5048671135757, 17.40466547204096]

Do you have any idea how to solve this issue? Thanks in advance.

1
Either accept the error, use a discreet formula or rewrite the equations to reduce intermediate errors.user2864740
Ok, I solved the problem. Error was in rotate function.hakubaa
Oh, exactly what was it - How did you fix the problem? Were you able to simply reduce the error or ..?user2864740
Insted of this: x = xcos - ysin; y = xsin + ycos; It should be this: double xnew = xcos - ysin; double ynew = xsin + ycos; x = xnew + origin.getX(); y = ynew + origin.getY();hakubaa
it probably is using floating points... ie. float or double. These are inherently non-precise.SnakeDoc

1 Answers

0
votes

firstly, there's an error in your formula...

the line

x = x*cos - y*sin;

modifies the value of x and the modified value is used in the next line

y = x*sin + y*cos;

You have to use a temp variable to store the new value of x and y, this is what user2602548 meant with his sugestion. I guess you're already using double since you would otherwise need a cast to float for those two lines.

If you fix the algorithmic error you get something like [9.99999999999659, 9.999999999998778] .

If that's not good enough for you, you could either round after the rotations and if that's also not good enough use a lib that provides trigonometric functions with more precision like apfloat.

Using BigDecimal with that problem won't give you any more precision because the problem here is that the results of sin() and cos() are still only double precision.