Calculating points of rectangle after rotation (Trig) help!

Started by
9 comments, last by mtlk 8 years, 8 months ago

I'm missing an essential step and it's been a while since I've taken trig.

Here is the code I'm using. It seems like maybe it's rotating around (0,0) instead of the players pos, which would explain the negative numbers and why the first point isn't always the same (or my math is simply off rolleyes.gif ). I've taken too much time on something that should be simple. Rescue me/point me in the right direction? I was using this article as a guide, but even in the figure I can see this formula is not rotating the rectangle how I was excpecting. -> https://msdn.microsoft.com/en-us/library/dd162943%28v=vs.85%29.aspx.


public Polygon toRectangle(Image image)
	{
		


		//determine verticies of rectangle after rotation

		//original points
		
		
		float x1 = image.getX();
		float y1 = image.getY();
		System.out.println("First set is: " + x1 + ", " + y1);

		float x2 = image.getX() + image.getWidth();
		float y2 = image.getY();
		System.out.println("Second set is: " + x2 + ", " + y2);
		


		float x3 = image.getX() + image.getWidth();
		float y3 = image.getY() + image.getHeight();
		System.out.println("Third set is: " + x3 + ", " + y3);


		float x4 = image.getX();
		float y4 = image.getY() + image.getHeight();
		System.out.println("Fourth set is: " + x4 + ", " + y4);


		//x' = (x * cos A) - (y * sin A) 
		//y' = (x * sin A) + (y * cos A) 

		//Points after rotation
		float newX1 =  (float)(x1 * Math.cos(image.getRotation())) - (float)(y1 * Math.sin(image.getRotation())));
		float newY1 =  (float)(x1 * Math.sin(image.getRotation())) + (float)(y1 * Math.cos(image.getRotation())));

		float newX2 =  (float)(x2 * Math.cos(image.getRotation())) - (float)(y2 * Math.sin(image.getRotation())));
		float newY2 =  (float)(x2 * Math.sin(image.getRotation())) + (float)(y2 * Math.cos(image.getRotation())));

		float newX3 =  (float)(x3 * Math.cos(image.getRotation())) - (float)(y3 * Math.sin(image.getRotation())));
		float newY3 =  (float)(x3 * Math.sin(image.getRotation())) + (float)(y3 * Math.cos(image.getRotation())));

		float newX4 =  (float)(x4 * Math.cos(image.getRotation())) - (float)(y4 * Math.sin(image.getRotation())));
		float newY4 =  (float)(x4 * Math.sin(image.getRotation())) + (float)(y4 * Math.cos(image.getRotation())));


		System.out.println("First Point after rotation of " + image.getRotation() + ": " + newX1 +", " + newY1 );
		System.out.println("Second Point: " + newX2 +", " + newY2 );
		System.out.println("Third Point: " + newX3 +", " + newY3 );
		System.out.println("Fourth Point: " + newX4 +", " + newY4 );

		return new Polygon(new float[]{(float)newX1,(float)newY1,(float)newX2,(float)newY2,(float)newX3,(float)newY3,(float)newX4,(float)newY4});

And the output...


Attacking
Animation duration: 0.4
Animation ends at: 1437844348816
Curren time is: 1437844348416
First set is: 314.0, 208.0
Second set is: 349.0, 208.0
Third set is: 349.0, 283.0
Fourth set is: 314.0, 283.0
First Point after rotation of 90.0: -326.64642, 187.51566
Second Point: -342.32898, 218.80551
Third Point: -409.37872, 185.19998
Fourth Point: -393.69617, 153.91013
Attacking
Animation duration: 0.4
Animation ends at: 1437844353899
Curren time is: 1437844353499
First set is: 314.0, 207.0
Second set is: 349.0, 207.0
Third set is: 349.0, 282.0
Fourth set is: 314.0, 282.0
First Point after rotation of -180.0: -353.75507, 127.68069
Second Point: -374.70117, 155.72104
Third Point: -434.7876, 110.83652
Fourth Point: -413.8415, 82.79617
Attacking
Animation duration: 0.4
Animation ends at: 1437844357899
Curren time is: 1437844357499
First set is: 314.0, 207.0
Second set is: 349.0, 207.0
Third set is: 349.0, 282.0
Fourth set is: 314.0, 282.0
First Point after rotation of -90.0: 44.362198, -373.4662
Second Point: 28.679626, -404.75604
Third Point: 95.72937, -438.36157
Fourth Point: 111.41194, -407.07172
Attacking
Animation duration: 0.4
Animation ends at: 1437844361816
Curren time is: 1437844361416
First set is: 314.0, 210.0
Second set is: 349.0, 210.0
Third set is: 349.0, 285.0
Fourth set is: 314.0, 285.0
First Point after rotation of 0.0: 314.0, 210.0
Second Point: 349.0, 210.0
Third Point: 349.0, 285.0
Fourth Point: 314.0, 285.0
Mob Hit!

Should I be converting degrees to radians? I seriously didn't excpect this function to cause me any trouble dry.png

Any help is appreciated!

Advertisement


It seems like maybe it's rotating around (0,0) instead of the players pos

I don't have time to read through in more depth right now, but if that's the case...

When rotating around a point, you want to subtract the rotation point, do the sin/cos stuff, and then add the rotation point back in.

You might, as you say, also need to verify if your functions expect radians or degrees.

Hello to all my stalkers.

So simple! Thanks a bunch.

The unit circle, which defines the sine (=y value of the unit vector) and cosine (=x value of the unit vector) functions, has its center located at (x=0, y=0)
You have to subtract the coordinates of the center of rotation from every point to be transformed and add them again after transformation. If you dont do that you will always rotate around (0, 0)

The unit circle, which defines the sine (=y value of the unit vector) and cosine (=x value of the unit vector) functions, has its center located at (x=0, y=0)
You have to subtract the coordinates of the center of rotation from every point to be transformed and add them again after transformation. If you dont do that you will always rotate around (0, 0)

This is what I did, and it worked like a charm. Makes perfect sense, I guess I just should have had more coffee this morning. Thanks guys!

Edit:

For anyone having the same issue, here is what it looks like in code now.


//Points after rotation
		float newX1 =  (float)((x1 - x1)  * Math.cos(image.getRotation())) - (float)(y1 - y1) * (float)Math.sin(image.getRotation()) + x1;
		float newY1 =  (float)((x1 - x1) * Math.sin(image.getRotation())) + (float)(y1-y1) * (float)Math.cos(image.getRotation()) + y1;

		float newX2 =  (float)((x2 - x1) * Math.cos(image.getRotation())) - (float)(y2-y1) * (float)Math.sin(image.getRotation()) + x1;
		float newY2 =  (float)((x2 - x1) * Math.sin(image.getRotation())) + (float)(y2-y1) * (float)Math.cos(image.getRotation()) + y1;

		float newX3 =  (float)((x3 - x1) * Math.cos(image.getRotation())) - (float)(y3-y1) * (float)Math.sin(image.getRotation()) + x1;
		float newY3 =  (float)((x3 - x1) * Math.sin(image.getRotation())) + (float)(y3-y1) * (float)Math.cos(image.getRotation()) + y1;

		float newX4 =  (float)((x4 - x1) * Math.cos(image.getRotation())) - (float)(y4-y1) * (float)Math.sin(image.getRotation()) + x1;
		float newY4 =  (float)((x4 - x1) * Math.sin(image.getRotation())) + (float)(y4-y1) * (float)Math.cos(image.getRotation()) + y1;

As a sidenote: for performance reasons you could calculate the sine and cosine just once and store them in variables

As a sidenote: for performance reasons you could calculate the sine and cosine just once and store them in variables

It doesn't seem to be to slow for what I'm using it for. I don't calculate every update, just when a player attacks. I'll keep that in mind though, that is usually how I would handle something like this. Thanks again!

Edit:

Somehow I misunderstood the post. Just changed the code again as I couldn't find a reason not to, besides laziness.

As a sidenote: for performance reasons you could calculate the sine and cosine just once and store them in variables

I wonder whether the compiler doesn't do this already.

Another reason to do this is to reduce the clutter, and improve readability of the source code. A short variable name is easier to read than Math.sin(image.getRotation()) everywhere. It takes mental effort to see all instances are really the same for expressions.

I wonder whether the compiler doesn't do this already.

If the compiler is clever enough to identify it as an invariant expression it might. But i doubt it given that it actually consists of 2 nested expressions and the inner is reading from a non const variable which might make it hard for the compiler to actually do so.

I wonder whether the compiler doesn't do this already.

If the compiler is clever enough to identify it as an invariant expression it might. But i doubt it given that it actually consists of 2 nested expressions and the inner is reading from a non const variable which might make it hard for the compiler to actually do so.

Just tried that (in C++), with Image defined as a simple class with one member variable and a getter function, and it indeed only calls cos and sin once. However, it certainly needs to know the definition of getRotation to make sure it is invariant and has no side effects.

This topic is closed to new replies.

Advertisement