ff[2]: rectangle match
forked from forked from: rectangle match (diff: 18)
ActionScript3 source code
/**
* Copyright makc3d ( http://wonderfl.net/user/makc3d )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/mLhk
*/
// forked from makc3d's forked from: rectangle match
// forked from nicoptere's rectangle match
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
/**
* @author Nicolas Barradeau
* http://en.nicoptere.net
*/
public class RectangleMatch extends Sprite
{
private var maxRadius:Number;
public function RectangleMatch()
{
stage.addEventListener( MouseEvent.MOUSE_DOWN, reset );
reset();
}
private function reset( e:MouseEvent = null ):void
{
graphics.clear();
graphics.beginFill( 0x333333 );
graphics.drawRect( 0, 0, stage.stageWidth, stage.stageHeight );
var rect:Rectangle = getRandomRect();
var frame:Rectangle = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight );
var candidates:Vector.<Candidate> = new Vector.<Candidate>();
for (var i:int = 0; i < 500; i++)
{
var r:Rectangle = getRandomRect();
drawRect( r, 0XFFCC00, .05 );
var c:Candidate = new Candidate( r, i );
c.compute( frame );
candidates.push( c );
}
c = candidates[ getClosest( frame, rect, candidates ) ];
drawRect( c.r, 0xFF0000, .5 );
drawRect( rect, 0x00FF00, .25 );
}
private function getClosest( frame:Rectangle, rect:Rectangle, list:Vector.<Candidate> ):uint
{
var candidate:Candidate = new Candidate( rect, -1 );
candidate.compute( frame );
var mini:Number = Number.POSITIVE_INFINITY;
var id:int = -1;
var score:Number;
for (var i:int = 0; i < list.length; i++)
{
score = list[ i ].compare( candidate );
if ( score < mini )
{
mini = score;
if( id != -1 )drawRect( list[ id ].r, 0xFFFFFF );
id = list[ i ].id;
}
}
return id;
}
private function drawRect(rect:Rectangle, color:uint, alpha:Number = .15 ):void
{
graphics.lineStyle( 0, color );
graphics.beginFill( color, alpha );
graphics.drawRect( rect.x, rect.y, rect.width, rect.height );
graphics.endFill();
}
private function getRandomRect():Rectangle
{
var w:int = stage.stageWidth;
var h:int = stage.stageHeight;
var rw:int = Math.random() * w * .25;
var rh:int = Math.random() * h * .25;
return new Rectangle( Math.random() * ( w - rw ), Math.random() * ( h - rh ), rw, rh );
}
}
}
import flash.geom.Point;
import flash.geom.Rectangle;
class Candidate
{
public var char:String;
public var id:int;
public var r:Rectangle;
public var indices:Vector.<int>;
public function Candidate( r:Rectangle, id:int, char:String = '' )
{
this.r = r;
this.id = id;
this.char = char;
}
public function compute( frame:Rectangle ):void
{
var frameCenter:Point = new Point( frame.x + frame.width * .5, frame.y + frame.height * .5 );
var frameRadius:Number = Math.sqrt( Math.pow( frame.width * .5, 2 ) + Math.pow( frame.height * .5 , 2 ) );
var tl:Point = r.topLeft;
var tr:Point = new Point( r.right, r.top );
var br:Point = r.bottomRight;
var bl:Point = new Point( r.left, r.bottom );
var corners:Array = [ tl, tr, br, bl ];
indices = new Vector.<int>();
for each( var p:Point in corners )
{
indices.push( int( map( getAngle( frameCenter, p ), -Math.PI, Math.PI, 0, 360 ) ) );
}
}
private function getAngle( p0:Point, p1:Point ):Number
{
return Math.atan2( p1.y - p0.y, p1.x - p0.x );
}
public function compare( other:Candidate ):Number
{
var score:Number = 0;
if (
(
(r.width <= other.r.width) && (r.height <= other.r.height)
) ||
(
(r.width >= other.r.width) && (r.height >= other.r.height)
)
)
{
// one of rectangles fits in another - return difference area
return Math.abs (r.width * r.height - other.r.width * other.r.height);
}
//return Number.MAX_VALUE;
// ok MAX_VALUE is not good, but what can we do?
// let's try union - intersection
return Math.abs (r.width - other.r.width) * Math.min (r.height, other.r.height) +
Math.abs (r.height - other.r.height) * Math.min (r.width, other.r.width);
}
private function normalize(value:Number, minimum:Number, maximum:Number):Number
{
return (value - minimum) / (maximum - minimum);
}
private function lerp(normValue:Number, minimum:Number, maximum:Number):Number
{
return minimum + (maximum - minimum) * normValue;
}
private function map(value:Number, min1:Number, max1:Number, min2:Number, max2:Number):Number
{
return lerp( normalize(value, min1, max1), min2, max2);
}
}