package { import hype.framework.layout.AbstractLayout; import hype.framework.layout.ILayout; import flash.display.DisplayObject; import flash.geom.Point; public class MagneticField implements ILayout { protected var field:Vector.>; protected var cols:uint; protected var rows:uint; protected var resolution:uint; protected var rotation_style:String; protected var _index:uint; protected var mag_index:uint = 0; public var grid_total:uint; private var magnets:Array = []; //r = resolution of grid i.e. pixel size of each cell //w = grid width //h = grid height //firstP = positive pole //firstN = negative pole //rotational can be 'cos', 'sin', 'tan', defaults to '' which is normal magnetic field public function MagneticField(r:int, w:int, h:int, firstP:Point, firstN:Point, rotational = '') { resolution = r;//the spacing of cells w/h cols = w/resolution; rows = h/resolution; field = new Vector.>(); grid_total = cols * rows; magnets['pos'] = []; magnets['neg'] = []; //a field needs at least 1 magnet addMagnet(firstP, firstN); rotation_style = rotational; //build the field makeField(); } public function build() { makeField(); } private function makeField() { for (var i:int = 0; i < rows; i++) { field[i] = new Vector.(); for (var j:int = 0; j < cols; j++) { //mid point at which we are calculating force in the field var forcePoint:Point = new Point((j + 1) * resolution - resolution / 2, (i + 1) * resolution - resolution / 2); //add all positives and add all negs, average them, then do sum var posRad:Number = 0; var negRad:Number = 0; for (var key:String in magnets['pos']){ posRad += setAngle(forcePoint, magnets['pos'][key], 1); } posRad = posRad / magnets['pos'].length; for (var key:String in magnets['neg']){ negRad += setAngle(forcePoint, magnets['neg'][key], -1); } negRad = negRad / magnets['pos'].length; field[i][j] = new Point(Math.cos(posRad - negRad), Math.sin(posRad - negRad)); } } } private function setAngle(mid:Point, pole:Point, polarity:Number) { //distance from mid point to the pole var magn:Point = new Point(pole.x - mid.x, pole.y - mid.y); var radians:Number; //this is the angle in radians if (rotation_style == 'cos') { radians = polarity * (Math.cos(Math.atan2(magn.y, magn.x))); } else if (rotation_style == 'sin') { radians = polarity * (Math.sin(Math.atan2(magn.y, magn.x))); } else if (rotation_style == 'tan') { radians = polarity * (Math.tan(Math.atan2(magn.y, magn.x))); } else { radians = polarity * Math.atan2(magn.y, magn.x); } return radians; }//end getAngle function public function applyLayout(object:DisplayObject):void { if (_index < grid_total) { var rotate:Number = getAngle(); object.rotation = rotate; var pt:Point = ILayout(this).getNextPoint(); object.x = pt.x; object.y = pt.y; } } public function getNextPoint():Point { var pt:Point = new Point(); var row:uint = Math.floor(_index / cols); var col:uint = _index % cols; pt.x = (col + 1) * resolution - (resolution/2); pt.y = (row + 1) * resolution - (resolution/2); ++_index; return pt; } public function getAngle() { var row:uint = Math.floor(_index / cols); var col:uint = _index % cols; return Math.atan2(field[row][col].y, field[row][col].x)*180/Math.PI; } public function addMagnet(p:Point, n:Point) { //push this magnet into our array magnets['pos'].push(p); magnets['neg'].push(n); } } }