# Thread: How to rotate a shape in a coordinatesystem?

1. ## How to rotate a shape in a coordinatesystem?

Hello!
I'm struggling with a coordinate-trigonometry-problem.

I'm trying to create a 2D-shape program in Java. The idea is that the user should be able to mark a couple of coordinates in a 2D-coordinate-system, which will be joined together with lines to form a shape of a figure.

One feature will be that the user can rotate the figure by an angle. All the coordinates of the shape should be recalculated and the figure should be rotated and re-drawn by the new coordinates.

My problem is that when I recalculate the coordinates the figure gets a bit deformed and does not exactly look like the original figure. My goal is of course that the figure will be able to rotate without getting derfomed.

When I look at other programs like 3D-studio max they are able to create a figure upon coordinates (the "spine" tool), as can I. But when they rotate their figures the figure stay in the orginal shape without any deformation.

Below I got a link to an image where this is described. The gray image is created by 3D-studio and the yellow is created by my program.

http://www.dsv.su.se/~fr-ander/rot.gif (You may have to click to enlarge the image in the browser.)

The image shows 6 gray images from 3D-studio max showing a figure rotated. The first image is the upper left one. It also shows 2 yellow images from my program. With 3D-studio max you can rotate the figure in any angle without any deformation. The images from my program shows the figure from the begining and after 72 rotations with 5 deg. As you can see the shape gets deformed.

The coordinate-system in my program is a regular x-axis, negative to the left and positive to the right. The y-axis is negative above the origo and positive below the origo.

The coordinates for the shapes are not exactly the same in the two programs, but I do not think that it matters to describe this problem. If you look at the last image you will see the deformation that I talk about.

For each rotation I use this formula, described below, in my program. All the coordinates are saved inside a list/array/vector, below I just refer to it like variables.

(Step 1-3 are only calculated once)
1) When the shape is created for the first time I get the center like this:
a) find the xMin and xMax by searching all the xValues of the coordinates
b) find the yMin and yMax by searching all the yValues of the coordinates
c) Get the xCenter like (xMax+xMin)/2
d) Get the yCenter like (yMax+yMin)/2

2) When the shape is created for the first time I calculate all the differenses between xCenter and xValues and between yCenter and yValues. I do this for all of the coordinates of the shape with this formula:
xDiff = xValues - xCenter
yDiff = yValues - yCenter

3) Now I'm able to find all the radius between the center coordinate (xCenter, yCenter) and all the coordinates of the shape with this formula:
radius = Math.sqrt( (xDiff^2*xDiff^2) + (yDiff^2*yDiff^2))

(Below (step 4-6) get repeated every time I rotate. I guess that I could do step 4 once, as above.)
4) Now I'm able to find the present angles like:
if(yDiff > 0)
{
angle = Math.acos( xDiff / radius );
}
else
{
angle = (2*Math.PI) - Math.acos( xDiff / radius )
}

5) Now I recalculate all the coordinates like:
xNew = xCenter + 1 * ( (xValue-xCenter) * Math.cos( ((2*Math.PI)/72)*dir ) - (yValue-yCenter) * Math.sin( ((2*Math.PI)/72) ) )
yNew = yCenter + 1 * ( (xValue-xCenter) * Math.sin( ((2*Math.PI)/72)*dir ) + (yValue-yCenter) * Math.cos( ((2*Math.PI)/72)) )

6) Since computer screens work with pixles I round each xNew and yNew to an integer. All other values is stored like "double" (numbers with decimals). If you are familiar with Java I use Math.round to get a proper integer.

For my figure I get these coordinates when the figure is created:
-40,-40
40,-40
40,40
8,68
-12,80
-28,72
-40,60
-60,40
-80,0
-40,-40

With the above formula I get these coordinates after 72 (may have been 73) rotations with 5 degr ((2*Math.PI)/72))
-35,-40
40,-40
41,36
-2,73
-12,81
-33,71
-47,55
-63,31
-81,4
-35,-40

So if you see what I'm doing wrong to cause the deformation of the shape/figure, please let me know. How do you think they do it in the 3D-studio max application? If they can do it, anyone can do it, I guess.

Best regards
Fredrik

2. I think it very likely you're seeing the effects of repeatedly rounding to integer values.

Incidentally, there's a way of carrying out the rotation that doesn't involve taking those inverse trig functions (another possible source of rounding errors). A rotation of T round the origin can be expressed as a matrix (cos T, - sin T; sin T, cos T) expressing coordinates in row form, so that (x,y)(a,b;c,d) = (ax+cy, bx+dy). A rotation about the point (x0,y0) can be expressed as (x,y) -> (x-x0,y-y0)(a,b;c,d) + (x0,y0). You might find this faster and more accurate.

3. ## Very interesting...but..?

Hello!

Perhaps you can tell me if I get it right so far.
(x,y) -> (x-x0,y-y0)(a,b;c,d) + (x0,y0).
To me this look like:
(xNew,yNew) = (xPresent-xCenter,yPresent-yCenter) * (Math.cos(angle), - Math.sin(angle); Math.sin(angle), Math.cos(angle)) + (xCenter,yCenter).

Then I guess this is the formula for the x-value of a new coordinate, please correct me if I am wrong:
xNew = (xPresent-xCenter) * (Math.cos(angle) - Math.sin(angle)) + xCenter

I guess this is the formula for the y-value:
yNew = (yPresent-yCenter) * Math.sin(angle) Math.cos(angle)) + yCenter.

Please correct me if I am wrong.

Best regards
Fredrik

4. No, in that notation it would be

xNew = (xPresent-xCenter) * Math.cos(angle) + (yPresent-yCenter) * Math.sin(angle)) + xCenter
yNew = - (xPresent-xCenter) * Math.sin(angle) + (yPresent-yCenter) * Math.cos(angle)) + yCenter

5. ## A bit better, but...

Hello!

It do look a bit better but I still get some deformation.

This is the coordinates after a full rotation turn
-36,-41
40,-40
40,35
18,61
-11,80
-23,72
-31,63
-55,47
-80,5
-36,-41

And compare to the coordinates from the begining:

-40,-40
40,-40
40,40
8,68
-12,80
-28,72
-40,60
-60,40
-80,0
-40,-40

...there is some deformation.

Do you think we can do it in some other way with som other formula? Or is it because of the rounding?

In some way the 3D-studio guys manage it and I do belive that we, or anybody, should be able to manage it as well.

Best regards
Fredrik

6. My guess is that it comes from rounding a dozen times. I don't know exactly how commercial packages do this but I would imagine they use floating-point internally.