Get vertices of a rotated rectangle

Monkey Forums/Monkey Programming/Get vertices of a rotated rectangle

Shinkiro1(Posted 2012) [#1]
Hey, spent the last few hours trying to come up with a solution for this:



I want to get the X & Y coordinates for A, B, C & D.
The rectangle is rotated in degrees.
The rectangle is center aligned.

I already did a lot of research, the solutions either involves Matrix operations (didn't try, no module) or this formula:
[monkeycode]
x = rectX - rectHandleX
y = rectY - rectHandleY
newX = x * Cos (angle) - y * Sin (angle)
newY = y * Sin (angle) + y * Cos (angle)[/monkeycode]
The above will do it anticlockwise I think, but even if I put a minus sign before the angle it still doesn't work.


AdamRedwoods(Posted 2012) [#2]
NewY = x*Sin(angle) + y*Cos(angle)
(....note the "x")


maltic(Posted 2012) [#3]
I think that formula is using radians, not degrees. Also it looks wrong, newY should have an x instead of a y.

If you rotate point (px, py) around point (ox, oy) by the angle theta you'll get:

newX = Cos(theta) * (px-ox) - Sin(theta) * (py-oy) + ox
newY = Sin(theta) * (px-ox) + Cos(theta) * (py-oy) + oy

So just calculate the center of your rectangle (x1, y1, width, height) as follows:

ox = x1 + (width/2)
oy = y1 + (height/2)

Then apply the aforementioned formula to A, B, C and D.

I haven't tested any of this in code though, so beware.


Jesse(Posted 2012) [#4]
this is similar to what maltic posted but more flexible.
This will find the position of point a, b, c, d relative to the handle if the handle is anywhere in or outside of the rectangle.
[monkeycode]
a.x = -handle.x
a.y = rect.height - handle.y

b.x = rect.width - handle.x
b.y = rect.height - handle.y

c.x = rect.width - handle.x
c.y = -handle.y

d.x = -handle.x
d.y = -handle.y
[/monkeycode]

if you are rotating it by the handle then do the rotation based on that

[monkeycode]
tx = a.x * Cos(angle) - a.y * Sin(angle)
ty = a.y * Sin(angle) + a.x * Cos(angle)
a.x = tx
a.y = ty
[/monkeycode]

the new position will be

newx = x + handle.x + a.x
newy = y + handle.y + a.y


this is just for one point. you need to do it for each of the points.

although for your case all you need to do is find one point and just change the signs for tx and ty to get the others.


Shinkiro1(Posted 2012) [#5]
Thanks for the answers, unfortunatley they didn't work for me.
I think the part with the handles confuses me.
I want to rotate the points around the rectangle's center (which are just the x & y position because it's midhandled)

How would I get the rotated top left corner?

This is what I have now (angle in degrees)
[monkeycode]
tx = position.x - handle_x 'Get top left x
ty = position.y - handle_y 'Get top left y
newX = tx * Cos(-rotation) - tx * Sin(-rotation)
newY = tx * Sin(-rotation) + ty * Cos(-rotation)
[/monkeycode]


NoOdle(Posted 2012) [#6]
You could try the matrix route, it is a little tricky at first but this should help: http://www.monkeycoder.co.nz/Community/posts.php?topic=1992


Gerry Quinn(Posted 2012) [#7]
Here's code from a card-based puzzle game.
hCard and wCard are the height and width, xC and yC are the centre and angle is the angle from the vertical.

	' Calculate corners: scale allows corners of a 'smaller' card to be calculated
	Method CalculateCorners:Void( cors:Float[], scale:Float = 1.0 )
		Local rad:Float = 0.5 * Sqrt( hCard * hCard + wCard * wCard ) * scale * globalCardScale
		Local theta0:Float = ATan2( hCard, wCard )
		Local theta1:Float = 180.0 - theta0
		Local x0:Float = rad * Cos( theta0 + angle )
		Local y0:Float = rad * Sin( theta0 + angle )
		Local x1:Float = rad * Cos( theta1 + angle )
		Local y1:Float = rad * Sin( theta1 + angle )
		cors[ 0 ] = xC + x0
		cors[ 1 ] = yC + y0
		cors[ 2 ] = xC + x1
		cors[ 3 ] = yC + y1
		cors[ 4 ] = xC - x0
		cors[ 5 ] = yC - y0
		cors[ 6 ] = xC - x1
		cors[ 7 ] = yC - y1
	End	



Floyd(Posted 2012) [#8]
The main idea is that the easy case is when the rectangle is centered at the origin. You work out the rotated vertex positions for that, then add the x and y values for wherever the center really is.

Presumably you already know the rectangle's width and height. If the rectangle were centered at (0,0) then one of the corners ( the one called A? ) is at (width/2,height/2). Let's call this (w2,h2) for convenience. For more terseness lets use cr to mean Cos( rotation ) and sr for Sin( rotation ). Then the rotated position is

newX = w2 * cr - h2 * sr
newY = w2 * sr + h2 * cr

Finally, add the x,y values for wherever the center really is.


Note that you don't have to do all that multiplying and "Cosining" for the other three corners. The symmetry makes the case where the rectangle is centered at the origin very simple. Once you have worked (x,y) for one of the corners then the other three corners ( called B,C,D? ) are (-y,x) and (-x,-y) and (y,-x).

And of course you must still add the actual center values to get the actual corner values.


Gerry Quinn(Posted 2012) [#9]
Floyd is right - my code above is maybe a little easier to understand but it calculates an extra Sin and Cos. (Also rad and theta, but these could be made constants so long as wCard and hCard are.)


Shinkiro1(Posted 2012) [#10]
Wow, it works!
I've used Gerry Quinn's code and it worked immediately. Thanks a lot.

@Noodle: We will be doing matrices in school soon so your matrix class will surely come in handy :)

(As for the redunant sin/cos calls: it isn't for real-time purposes anyway so ...)

Also thanks to all others that helped. For now I am just happy that it works.