ff[2]: rectangle match

by makc3d forked from forked from: rectangle match (diff: 18)
♥0 | Line 132 | Modified 2012-10-02 06:42:22 | MIT License
play

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);
	}
}