Skip to content

Instantly share code, notes, and snippets.

@honzabrecka
Last active December 11, 2015 21:39
Show Gist options
  • Save honzabrecka/4663911 to your computer and use it in GitHub Desktop.
Save honzabrecka/4663911 to your computer and use it in GitHub Desktop.
//-----------------------
// creation
var r:RotationalRectangle = RotationalRectangle(250, 300, 50, 100);
//-----------------------
// rotation
r.rotateAroundTopLeft( 20 );
r.rotateAroundCenter( 30 );
r.rotateAroundPoint(new Point(30, 40), 20);
trace(r.rotation);
//-----------------------
// collisions
// with point
function isPointInRectangle(vertices:Vector.<Point>, point:Point):Boolean
{
var c:Boolean = false;
for (var i:uint = 0, j:uint = vertices.length - 1; i < vertices.length; j = i++)
{
if ( ((vertices[i].y > point.y) != (vertices[j].y > point.y))
&& (point.x < (vertices[j].x - vertices[i].x) * (point.y - vertices[i].y) / (vertices[j].y - vertices[i].y) + vertices[i].x) )
c = !c;
}
return c;
}
trace(isPointInRectangle(r.vertices, new Point(200, 50)));
package
{
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* RotationalRectangle
*
* @author Jan Břečka
*/
public class RotationalRectangle
{
private var _x:Number = 0;
private var _y:Number = 0;
private var _width:Number = 0;
private var _height:Number = 0;
private var _rotation:Number = 0;
private var _matrix:Matrix;
private var _vertices:Vector.<Point> = new Vector.<Point>(4, true);
private var _bounds:Rectangle = new Rectangle();
public function RotationalRectangle(x:Number, y:Number, width:Number, height:Number)
{
_x = x;
_y = y;
_width = width;
_height = height;
_matrix = new Matrix(_width, 0, 0, _height, x, y);
vertices[0] = new Point();
vertices[1] = new Point();
vertices[2] = new Point();
vertices[3] = new Point();
invalidateVertices();
}
public function set x(value:Number):void
{
if (value == _x) return;
_matrix.translate(value - _x, 0);
invalidateVertices();
}
public function get x():Number
{
return _x;
}
public function set y(value:Number):void
{
if (value == _y) return;
_matrix.translate(0, value - _y);
invalidateVertices();
}
public function get y():Number
{
return _y;
}
public function set width(value:Number):void
{
if (value == _width) return;
if (value)
{
var ratio:Number = value / _width;
_matrix.a *= ratio;
_matrix.b *= ratio;
}
else
{
var sky:Number = Math.atan2(_matrix.a, _matrix.b);
_matrix.a = Math.cos( sky ) * value;
_matrix.b = Math.sin( sky ) * value;
}
_width = value;
invalidateVertices();
}
public function get width():Number
{
return _width;
}
public function set height(value:Number):void
{
if (value == _height) return;
if (value)
{
var ratio:Number = value / _height;
_matrix.c *= ratio;
_matrix.d *= ratio;
}
else
{
var skx:Number = Math.atan2(-_matrix.c, _matrix.d);
_matrix.c = -Math.sin( skx ) * value;
_matrix.d = Math.cos( skx ) * value;
}
_height = value;
invalidateVertices();
}
public function get height():Number
{
return _height;
}
public function get rotation():Number
{
return _rotation;
}
/**
* Top Left
* Top Right
* Bottom Right
* Bottom Left
*/
public function get vertices():Vector.<Point>
{
return _vertices;
}
public function get bounds():Rectangle
{
return _bounds;
}
public function rotateAroundPoint(registrationPoint:Point, rotation:Number):void
{
// <0; 360) degrees
rotation = rotation % 360;
if (rotation < 0) rotation = 360 + rotation;
rotation = Math.abs( rotation );
var rotationInRadians:Number = Math.PI * 2 * ((rotation - _rotation) / 360);
_matrix.translate(-registrationPoint.x, -registrationPoint.y);
_matrix.rotate( rotationInRadians );
_matrix.translate(registrationPoint.x, registrationPoint.y);
invalidateVertices();
_rotation = rotation;
}
public function rotateAroundCenter(rotation:Number):void
{
var x:Number = vertices[0].x + (vertices[2].x - vertices[0].x) * .5;
var y:Number = vertices[0].y + (vertices[2].y - vertices[0].y) * .5;
var center:Point = new Point(x, y);
rotateAroundPoint(center, rotation);
}
public function rotateAroundTopLeft(rotation:Number):void
{
rotateAroundPoint(vertices[0], rotation);
}
private function invalidateVertices():void
{
_x = vertices[0].x = _matrix.tx;
_y = vertices[0].y = _matrix.ty;
vertices[1].x = _matrix.tx + _matrix.a;
vertices[1].y = _matrix.ty + _matrix.b;
vertices[2].x = _matrix.tx + _matrix.a + _matrix.c;
vertices[2].y = _matrix.ty + _matrix.b + _matrix.d;
vertices[3].x = _matrix.tx + _matrix.c;
vertices[3].y = _matrix.ty + _matrix.d;
invalidateBounds();
}
private function invalidateBounds():Rectangle
{
var left:Number = Math.min( Math.min(vertices[0].x, vertices[1].x), Math.min(vertices[2].x, vertices[3].x) );
var right:Number = Math.max( Math.max(vertices[0].x, vertices[1].x), Math.max(vertices[2].x, vertices[3].x) );
var top:Number = Math.min( Math.min(vertices[0].y, vertices[1].y), Math.min(vertices[2].y, vertices[3].y) );
var bottom:Number = Math.max( Math.max(vertices[0].y, vertices[1].y), Math.max(vertices[2].y, vertices[3].y) );
_bounds.x = left;
_bounds.width = right - left;
_bounds.y = top;
_bounds.height = bottom - top;
return _bounds;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment