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

Fowler angles

Get Adobe Flash player
by makc3d 03 Mar 2011
    Embed
package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	/**
	 * Fowler vs Ebert & Co, Ebert wins
	 */
	public class FowlerAngleTest extends Sprite{
		private var bd:BitmapData = new BitmapData (400, 400);
		public function FowlerAngleTest () {
			var E:Number = 1410;
			bd.lock ();
			for (var i:int = 0; i < 200; i++)
			for (var j:int = 0; j < 200; j++) {
				var dx:Number = i - 99.5;
				var dy:Number = j - 99.5;
				var a1:Number = 4 + 4 * Math.atan2 (dy, dx) / Math.PI;
				var a2:Number = FowlerAngle (-dy, -dx);
				bd.setPixel (i, j, 0x10101 * int ( 32 * a2 ));
				bd.setPixel (i + 200, j, 0x10101 * int ( 128 + E * (a2 - a1) ));
			}
			for (i = 0; i < 200; i++)
			for (j = 0; j < 200; j++) {
				dx = i - 99.5;
				dy = j - 99.5;
				a1 = 4 + 4 * Math.atan2 (dy, dx) / Math.PI;
				a2 = 4 + 4 * atan2 (dy, dx) / Math.PI;
				bd.setPixel (i, j + 200, 0x10101 * int ( 32 * a2 ));
				bd.setPixel (i + 200, j + 200, 0x10101 * int ( 128 + E * (a2 - a1) ));
			}
			bd.unlock ();
			addChild (new Bitmap (bd));
		}
		/**
		 * @see http://paulbourke.net/geometry/fowler/
		   This function is due to Rob Fowler.  Given dy and dx between 2 points
		   A and B, we calculate a number in [0.0, 8.0) which is a monotonic
		   function of the direction from A to B. 

		   (0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0) correspond to
		   (  0,  45,  90, 135, 180, 225, 270, 315, 360) degrees, measured
		   counter-clockwise from the positive x axis.
		*/
		private function FowlerAngle (dy:Number, dx:Number):Number {
			var adx:Number, ady:Number;    /* Absolute Values of Dx and Dy */
			var code:int;        /* Angular Region Classification Code */

			adx = (dx < 0) ? -dx : dx;  /* Compute the absolute values. */
			ady = (dy < 0) ? -dy : dy;

			code = (adx < ady) ? 1 : 0;
			if (dx < 0)  code += 2;
			if (dy < 0)  code += 4;

			switch (code)
			{
				case 0: return (dx==0) ? 0 : ady/adx;  /* [  0, 45] */
				case 1: return (2.0 - (adx/ady));      /* ( 45, 90] */
				case 3: return (2.0 + (adx/ady));      /* ( 90,135) */
				case 2: return (4.0 - (ady/adx));      /* [135,180] */
				case 6: return (4.0 + (ady/adx));      /* (180,225] */
				case 7: return (6.0 - (adx/ady));      /* (225,270) */
				case 5: return (6.0 + (adx/ady));      /* [270,315) */
				case 4: return (8.0 - (ady/adx));      /* [315,360) */
			}

			// never happens, but "Error: Function does not return a value."
			return 8;
		}
		/**
		 * Computes and returns the angle of the point <code>y/x</code> in radians, when measured counterclockwise
		 * from a circle's <em>x</em> axis (where 0,0 represents the center of the circle).
		 * The return value is between positive pi and negative pi.
		 *
		 * @author Eugene Zatepyakin
		 * @author Joa Ebert
		 * @author Patrick Le Clec'h
		 *
		 * @param y A number specifying the <em>y</em> coordinate of the point.
		 * @param x A number specifying the <em>x</em> coordinate of the point.
		 *
		 * @return A number.
		 */
		public static function atan2(y:Number, x:Number):Number {
			var sign:Number = 1.0 - (int(y < 0.0) << 1)
			var absYandR:Number = y * sign + 2.220446049250313e-16
			var partSignX:Number = (int(x < 0.0) << 1) // [0.0/2.0]
			var signX:Number = 1.0 - partSignX // [1.0/-1.0]
			absYandR = (x - signX * absYandR) / (signX * x + absYandR)
			return ((partSignX + 1.0) * 0.7853981634 + (0.1821 * absYandR * absYandR - 0.9675) * absYandR) * sign
		}
	}
}