dcsimg
A Flash Developer Resource Site

Results 1 to 10 of 10

Thread: Find four points of rotated rectangle

  1. #1
    Senior Member
    Join Date
    Jan 2003
    Location
    Nebraska
    Posts
    448

    Cow Icon Find four points of rotated rectangle

    Hello. Been searching for this, but the amount of rectangle related questions make it hard to find the answer I'm looking for.
    Anyway, I would like to draw 4 lines making a rectangle based on a given width, height, center point, and rotation.
    So if I give the program say a 0,0 center point, a width and height of 5, and a rotation of 0, then it would draw four lines like so:
    -2,-2 > 2,-2
    -2,-2 > -2,2
    -2,2 > 2,2
    2,-2 > 2,2
    (think that's right!)
    But yea, hope you get the basic idea. For me it gets real complicated once you add in rotation and such. For my program I will need all 4 points of the rectangle as I have a collision detection that is based colliding with lines...so four lines for each rectangle.
    Thanks!

  2. #2
    Senior Member
    Join Date
    May 2006
    Location
    Manhattan
    Posts
    246
    to define the points generally given rotation, you transform the local coordinates you've defined (would be 2.5 in your example though!):
    Code:
    transformedX = x * cos( theta ) - y * sin( theta )
    transformedY = x * sin( theta ) + y * cos( theta )
    where theta is your rotation in radians (radians = degrees * pi / 180). you can do a search for "2d rotation matrix" to get a background on the math.
    so, if you had a method for getting the top left point of the rectangle only, it would look like this:
    Code:
    function getTopLeft( width:Number, height:Number, theta:Number ) : Point
    {
    	//half width and height directed appropriately (for top left)
    	var hw:Number = -width / 2;
    	var hh:Number = -height / 2;
    	var cos:Number = Math.cos( theta );
    	var sin:Number = Math.sin( theta );
    	return new Point( hw * cos - hh * sin, hw * sin + hh * cos );
    }
    This is obviously very specific and you probably want to handle the problem generally instead, but i thought this would illustrate the solution to the purely mathematical end of it- the algorithm's design should be application specific.

  3. #3
    Senior Member
    Join Date
    Jan 2003
    Location
    Nebraska
    Posts
    448
    Hey, thanks for the response! Math is not my strong point (although I code actionscript daily!) so I'm not completely following your solution...
    I started trying to punch this into my program, then realized I still couldn't plot the points for my rectangle.
    I see how you use a transformedX and Y, but don't understand how to work that into the code. The function you have (getTopLeft) does not ask for an x or y coordinate so I'm not exactly sure how the point it returns relates to where my rectangle x and y is. I'm sure transformedX/Y works in here somewhere but I don't know how to put the two together......I mean I could do a transformX on my coordinates and I could run a similar function that returns a point, but I don't know how to put the two together .
    I think I might be able to calculate theta on my own though .

  4. #4
    Senior Member
    Join Date
    May 2006
    Location
    Manhattan
    Posts
    246
    the 2 don't go together- the transformedX etc. is just pseudocode for transforming a point rotationally. getTopLeft just defines the point in the rectangle's local space first then transforms it. hw in that algorithm is synonymous with x in the pseudocode.

    to add your rectangle's position and get your points (in global coordinates), you literally add the position of the rectangle to the transformed point. because you're defining the points by a width and a height, they exist in the "rectangle's space". when you rotate the rectangle, its vertices don't rotate relative to itself... only to a different coordinate space.

    define the rectangle's 4 points locally:
    top left = -w/2, -h/2
    top right = w/2, -h/2
    bottom right = w/2, h/2
    bottom left = -w/2, h/2

    if there is no rotation, it's easy to see where these points lie globally. let's say your rectangle's width is 10 and it's located at an x position of 100- the left edge will be at 95 and the right edge will be at 105. all you're doing is adding the point to the rectangle's translation.

    now when rotating, you first have to transform the point according to the rotation of the rectangle. after that it's the same step- adding the global translation of the rectangle.
    Last edited by newblack; 08-21-2008 at 12:24 AM.

  5. #5
    Senior Member
    Join Date
    Jan 2003
    Location
    Nebraska
    Posts
    448

    Cool

    Thanks alot man! I think I've got it. Here is some code I have so far based on what I have learned...it needs some fine tuning and compression for performance, but as is:
    code:

    private function createBlock(xPos:int,yPos:int,widthSent:int,height Sent:int,angle:int):void {
    var theta:Number =angle*(Math.PI/180);
    var transformedX:Number = xPos * Math.cos( theta ) - yPos * Math.sin( theta );
    var transformedY:Number = xPos * Math.sin( theta ) + yPos * Math.cos( theta );
    var transformedPoint=new Point(transformedX,transformedY);
    var topLeftPoint:Point=getTopLeft( widthSent, heightSent, angle ).add(transformedPoint);
    var topRightPoint:Point=getTopRight( widthSent, heightSent, angle ).add(transformedPoint);
    var bottomLeftPoint:Point=getBottomLeft( widthSent, heightSent, angle ).add(transformedPoint);
    var bottomRightPoint:Point=getBottomRight( widthSent, heightSent, angle ).add(transformedPoint);
    newWalls.push({from: topRightPoint,to:topLeftPoint});
    newWalls.push({from: topLeftPoint,to:bottomLeftPoint});
    newWalls.push({from: bottomLeftPoint,to:bottomRightPoint});
    newWalls.push({from: bottomRightPoint,to:topRightPoint});
    }
    private function getTopLeft( widthSent:int, heightSent:int, theta:Number ):Point {
    var hw:Number = -widthSent / 2;
    var hh:Number = -heightSent / 2;
    var cos:Number = Math.cos( theta );
    var sin:Number = Math.sin( theta );
    return new Point(hw * cos - hh * sin,hw * sin + hh * cos);
    }
    private function getTopRight( widthSent:int, heightSent:int, theta ):Point {
    var hw:Number = widthSent / 2;
    var hh:Number = -heightSent / 2;
    var cos:Number = Math.cos( theta );
    var sin:Number = Math.sin( theta );
    return new Point(hw * cos - hh * sin,hw * sin + hh * cos);
    }
    private function getBottomLeft( widthSent:int, heightSent:int, theta ):Point {
    var hw:Number = -widthSent / 2;
    var hh:Number = heightSent / 2;
    var cos:Number = Math.cos( theta );
    var sin:Number = Math.sin( theta );
    return new Point(hw * cos - hh * sin,hw * sin + hh * cos);
    }
    private function getBottomRight( widthSent:int, heightSent:int, theta ):Point {
    var hw:Number = widthSent / 2;
    var hh:Number = heightSent / 2;
    var cos:Number = Math.cos( theta );
    var sin:Number = Math.sin( theta );
    return new Point(hw * cos - hh * sin,hw * sin + hh * cos);
    }


    newWalls is just an array I hold all collision walls of my game in before creation. I can use this new code to create blocks like so:
    code:

    createBlock(400,300,300,300,0);


    totalWalls=newWalls.length-1;
    for (count=0; count<=totalWalls; count++) {
    var currentN=new Point(newWalls[count].from.y-newWalls[count].to.y,newWalls[count].to.x-newWalls[count].from.x);
    currentN.normalize(1);
    var currentV= new Point(newWalls[count].to.x-newWalls[count].from.x,newWalls[count].to.y-newWalls[count].from.y);
    var currentX=newWalls[count].from.x;
    var currentY=newWalls[count].from.y;
    walls.push({x: currentX, y: currentY,v: currentV,n: currentN});
    }
    this.graphics.lineStyle(1,000000);
    for (count=0; count<=totalWalls; count++) {
    this.graphics.moveTo(walls[count].x,walls[count].y);
    this.graphics.lineTo(walls[count].x+walls[count].v.x, walls[count].y+walls[count].v.y);
    }


    putting all that extra stuff in the walls array is for my collision detection code. Which, honestly I barely understand some of the math behind that either, just been putting this frankenstien game together from stuff I learn here and there . Thanks again for the help...

  6. #6
    Senior Member
    Join Date
    Jan 2003
    Location
    Nebraska
    Posts
    448
    Ehhh..spoke to soon. Getting close, but when I try it with an angle the block ends up rotating to another location and not around it's center....Well at this point hopefully I can tweak away until I figure it out. Definetally very close .

  7. #7
    Viral tick lordofduct's Avatar
    Join Date
    May 2008
    Location
    South Florida
    Posts
    159
    Code:
    function getRotatedRectPoint( angle:Number, point:Point, rotationPoint:Point = null):Point
    {
    	var ix:Number = (rotationPoint) ? rotationPoint.x : 0;
    	var iy:Number = (rotationPoint) ? rotationPoint.y : 0;
    	
    	var m:Matrix = new Matrix( 1,0,0,1, point.x - ix, point.y - iy);
    	m.rotate(angle);
    	return new Point( m.tx + ix, m.ty + iy);
    }
    Use matrices, it makes it a lot faster and easier.

    angle is in radians
    point the corner's position you are finding.
    rotationPoint - position in the rectangle when not rotated to be rotating around... if you don't include a rotationPoint and leave it null, it rotates around (0,0), or the upperleft corner.

    so for instance a rectangle rotated around (0,0) with width = 100, and height = 50, and rotated 90 degrees:

    Code:
    var upperRight:Point = getRotatedRectPoint( Math.PI / 2, new Point(100,0));
    var lowerRight:Point = getRoatedRectPoint(Math.PI / 2, new Point(100,50));
    var lowerLeft:Point = getRotatedRectPoint(Math.PI / 2, new Point(0,50));
    Last edited by lordofduct; 08-21-2008 at 07:10 PM.

  8. #8
    Senior Member
    Join Date
    Jan 2003
    Location
    Nebraska
    Posts
    448
    Thanks for the matrix tip man. I had to move on to programming something else for a bit, but will try this out when I get a chance and let you know.

  9. #9
    Prasanna
    Join Date
    Mar 2009
    Location
    Mumbai, India
    Posts
    3
    Quote Originally Posted by lordofduct View Post
    Code:
    function getRotatedRectPoint( angle:Number, point:Point, rotationPoint:Point = null):Point
    {
    	var ix:Number = (rotationPoint) ? rotationPoint.x : 0;
    	var iy:Number = (rotationPoint) ? rotationPoint.y : 0;
    	
    	var m:Matrix = new Matrix( 1,0,0,1, point.x - ix, point.y - iy);
    	m.rotate(angle);
    	return new Point( m.tx + ix, m.ty + iy);
    }
    Use matrices, it makes it a lot faster and easier.

    angle is in radians
    point the corner's position you are finding.
    rotationPoint - position in the rectangle when not rotated to be rotating around... if you don't include a rotationPoint and leave it null, it rotates around (0,0), or the upperleft corner.

    so for instance a rectangle rotated around (0,0) with width = 100, and height = 50, and rotated 90 degrees:

    Code:
    var upperRight:Point = getRotatedRectPoint( Math.PI / 2, new Point(100,0));
    var lowerRight:Point = getRoatedRectPoint(Math.PI / 2, new Point(100,50));
    var lowerLeft:Point = getRotatedRectPoint(Math.PI / 2, new Point(0,50));
    I just got a typo:
    getRoatedRectPoint will be getRotatedRectPoint.

    Thanks
    nice one.

  10. #10
    Prasanna
    Join Date
    Mar 2009
    Location
    Mumbai, India
    Posts
    3
    Can you please post a sample application.
    Please.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center