In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

2.2 lines: non-intersecting lines

using an intersection test on top of the distance function to join the dots
Get Adobe Flash player
by nicoptere 27 Dec 2010
/**
 * Copyright nicoptere ( http://wonderfl.net/user/nicoptere )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/gkXV
 */

package 
{
	import com.bit101.components.HUISlider;
	import com.bit101.components.PushButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	
	/**
	 * @author Nicolas Barradeau
	 * http://en.nicoptere.net
	 */
	public class ProximityIntersectDistribution extends Sprite 
	{
		
		private var points:Vector.<Point> = Vector.<Point>([ new Point(297.48,180.02),new Point(302.56,145.32),new Point(283.75,88.31),new Point(237.16,66.59),new Point(198.93,78.66),new Point(184.90,103.70),new Point(193.26,129.34),new Point(201.62,152.56),new Point(195.35,169.76),new Point(179.52,176.70),new Point(158.32,165.23),new Point(148.46,132.35),new Point(175.64,75.64),new Point(249.40,50.90),new Point(334.51,84.99),new Point(354.52,140.20),new Point(345.56,182.73),new Point(310.92,233.71),new Point(261.05,299.77),new Point(250.00,352.87),new Point(238.35,352.87),new Point(247.31,294.04),new Point(275.68,228.88),new Point(246.12,450.90),new Point(224.02,441.86),new Point(214.76,419.53),new Point(224.02,397.21),new Point(246.12,387.86),new Point(268.52,397.21),new Point(277.47,419.53),new Point(268.22,441.86)]);
		private var pairs:Vector.<Point> = new Vector.<Point>();
		
		private var distanceSlider:HUISlider;
		private var minDist:Number;
		
		public function ProximityIntersectDistribution() 
		{
			var randomizeBtn:PushButton = new PushButton( this, 200, 10, 'randomize', onRandomizeButtonClick );
			
			distanceSlider = new HUISlider( this, 10, 10, 'distance', onDistanceChange );
			distanceSlider.maximum = 500;
			distanceSlider.value = 25;
			onDistanceChange( null );
			
		}
		
		private function onDistanceChange( e:Event ):void 
		{
			minDist = distanceSlider.value * distanceSlider.value;
			redraw();
		}
		
		private function redraw():void 
		{
			graphics.clear();
			graphics.lineStyle( 0 );
			
			pairs.length = 0;	//resets pairs associations
			var addPair:Boolean;
			
			var i:int;
			var p:Point, pp:Point;
			for each( p in points )
			{
				for each( pp in points )
				{
					if ( p === pp ) continue;
					
					if ( ( ( p.x - pp.x ) * ( p.x - pp.x ) + ( p.y - pp.y ) * ( p.y - pp.y ) ) < minDist )
					{
						//if we're under the minimum distance
						
						addPair = true;
						
						//for each existing pair
						
						intersection : for ( i = 0; i < pairs.length; i += 2 )
						{
							
							//checks if the segment p-pp intersects any existing segment 
						
							if ( lineIntersectLine( pairs[ i ], pairs[ i + 1 ], p, pp ) != null )
							{
								addPair = false;
								break intersection; // this breaks the "intersection" for() loop
							}
							
						}
						
						//nothing intersected the segment p-pp
						if ( addPair ) pairs.push( p, pp );
						
					}
				}
			}
			
			//drawing the valid pairs
			for ( i = 0; i < pairs.length; i += 2 )
			{
				graphics.moveTo( pairs[ i ].x, pairs[ i ].y );
				graphics.lineTo( pairs[ i + 1 ].x, pairs[ i + 1 ].y );
			}
		}
		
		
		/**
		 * original function by Keith Hair:
		 * http://keith-hair.net/blog/2008/08/04/find-intersection-point-of-two-lines-in-as3/
		 * 
		 * extended by Hristo Dachev
		 * http://blog.controul.com/2009/05/line-segment-intersection/
		 * 
		 * @param	A line 1 point 1
		 * @param	B line 1 point 2
		 * @param	E line 2 point 1
		 * @param	F line 2 point 2
		 * @param	ABasSeg should the test consider line 1 as a segment  
		 * @param	EFasSeg should the test consider line 2 as a segment
		 * @return
		 */
		
		public function lineIntersectLine (	A : Point, B : Point,
											E : Point, F : Point,
											ABasSeg : Boolean = true, EFasSeg : Boolean = true ) : Point
		{
			
			var a1:Number = B.y - A.y;
			var a2:Number = F.y - E.y;
			var b1:Number = A.x - B.x;
			var b2:Number = E.x - F.x;
		 
			var denom:Number = a1 * b2 - a2 * b1;
			if (denom == 0) 
			{
				return null;
			}
			
			var c1:Number = B.x * A.y - A.x * B.y;
			var c2:Number = F.x * E.y - E.x * F.y;
			
			var ip:Point = new Point(	(b1 * c2 - b2 * c1) / denom,
										(a2 * c1 - a1 * c2) / denom		);
			
			//---------------------------------------------------
			//Do checks to see if intersection to endpoints
			//distance is longer than actual pairs.
			//Return null if it is with any.
			//---------------------------------------------------
			if ( A.x == B.x )
				ip.x = A.x;
			else if ( E.x == F.x )
				ip.x = E.x;
			if ( A.y == B.y )
				ip.y = A.y;
			else if ( E.y == F.y )
				ip.y = E.y;

			//	Constrain to segment.

			if ( ABasSeg )
			{
				if ( ( A.x < B.x ) ? ip.x < A.x || ip.x > B.x : ip.x > A.x || ip.x < B.x )
					return null;
				if ( ( A.y < B.y ) ? ip.y < A.y || ip.y > B.y : ip.y > A.y || ip.y < B.y )
					return null;
			}
			if ( EFasSeg )
			{
				if ( ( E.x < F.x ) ? ip.x < E.x || ip.x > F.x : ip.x > E.x || ip.x < F.x )
					return null;
				if ( ( E.y < F.y ) ? ip.y < E.y || ip.y > F.y : ip.y > E.y || ip.y < F.y )
					return null;
			}
			return ip;
		}
		
		private function onRandomizeButtonClick( e:Event ):void 
		{
			points.sort( randomize );
			redraw();
		}
		
        private function randomize( a:Point, b:Point ):Number
        {
            return ( Math.random() > .5 ) ? -1 : 1;
        }
	}
}