// click to launch particle, // shift-click to change parameters // for more info on Gumoski-Mira maps, see // http://www.artegens.net/on/cic/GA2009Papers/p29.pdf package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.ColorTransform; import flash.geom.Point; [SWF(width=465,height=465)] public class GumoskiMiraOrbits extends Sprite { public var A:Number; public var B:Number; public function F (x:Number):Number { return A * x + 2 * (1 - A) * x * x / (1 + x * x); } public var b:Bitmap; public var bd:BitmapData; public var ct:ColorTransform; public var xy:Vector.<Point>; public var splines:Vector.<Spline2D>; public function GumoskiMiraOrbits () { A = 2 * Math.random () - 1; B = 2 * Math.random () - 1; bd = new BitmapData (465, 465, false, 0); addChild (b = new Bitmap (bd)); ct = new ColorTransform (1, 1, 1, 1, -30, -20, -10); xy = new Vector.<Point> (3); splines = new Vector.<Spline2D> (xy.length); for (var i:int = 0; i < xy.length; i++) { xy [i] = new Point ( 10 * Math.random () - 5.0, 10 * Math.random () - 5.0 ); splines [i] = new Spline2D (xy [i]); } stage.addEventListener (Event.ENTER_FRAME, draw); stage.addEventListener (MouseEvent.CLICK, click); } public function draw (e:Event):void { graphics.clear (); graphics.lineStyle (0, 0xffffff); for (var i:int = 0; i < xy.length; i++) { var z:Point = xy [i]; var aa:Number = z.x * z.x; var bb:Number = z.y * z.y; if (aa + bb < 25) { var xi:Number = B * z.y + F (z.x); var yi:Number = -z.x + F (z.y); if ((z.x - xi)*(z.x - xi) + (z.y - yi)*(z.y - yi) > 1e-3) { z.x = xi; z.y = yi; splines [i].addNextPoint (z, graphics); } else { xy.splice (i, 1); splines.splice (i, 1); i--; } } else { xy.splice (i, 1); splines.splice (i, 1); i--; } } b.visible = false; bd.draw (this); b.visible = true; bd.colorTransform (bd.rect, ct); } public function click (e:MouseEvent):void { if (e.shiftKey) { A = 2 * mouseX / 465 - 1.0; B = 2 * mouseY / 465 - 1.0; } else { xy.push (new Point ( 10 * mouseX / 465 - 5.0, 10 * mouseY / 465 - 5.0 )); splines.push (new Spline2D (xy [xy.length - 1])); } } } } import flash.display.Graphics; import flash.geom.Point; class Spline2D { public var points:Vector.<Point> public function Spline2D (p:Point) { points = new Vector.<Point>; for (var i:int = 0; i < 4; i++) points.push (p.clone ()); } public function addNextPoint (p:Point, g:Graphics):void { points.shift (); points.push (p.clone ()); // draw previous segment g.moveTo (465 * (5 + points [1].x) / 10, 465 * (5 + points [1].y) / 10); for (var i:int = 1; i < 11; i++) { p = spline (points [0], points [1], points [2], points [3], 0.1 * i); g.lineTo (465 * (5 + p.x) / 10, 465 * (5 + p.y) / 10); } } /* * Calculates 2D cubic Catmull-Rom spline. * @see http://www.mvps.org/directx/articles/catmull/ */ private function spline (p0:Point, p1:Point, p2:Point, p3:Point, t:Number):Point { return new Point ( 0.5 * (( 2*p1.x) + t * (( -p0.x +p2.x) + t * ((2*p0.x -5*p1.x +4*p2.x -p3.x) + t * ( -p0.x +3*p1.x -3*p2.x +p3.x)))), 0.5 * (( 2*p1.y) + t * (( -p0.y +p2.y) + t * ((2*p0.y -5*p1.y +4*p2.y -p3.y) + t * ( -p0.y +3*p1.y -3*p2.y +p3.y)))) ); } } Gumoski-Mira orbits