Visualizing Cairngorm with Flare
August 31st, 2008Visualizing Pixlib with Flare
August 31st, 2008Visualizing Papervision 3d with Flare
August 31st, 2008So I've become quite interested in the Flare actionscript library for graphing and started playing around with it this weekend. Using the example given here ::: Flare Dependency Graph , I wrote some perl that parses an actionscript source tree and creates a JSON file suitable for import into the Flare libraries. So here is what Papervision looks like when graphed using Flare :::
Recursive String Reverse Algorithm in Actionscript
July 18th, 2008I've been playing around with recursive functions in actionscript for a bit now and yesterday came across this pretty cool one for reversing a string. The code follows :
function Reverse(s : String ) : String { var tmp : String = null; if ( s.length == 1 ) return s; else { var sLast : String = s.substr( s.length -1, s.length ); var sRemainder : String = s.substr( 0, s.length -1 ); tmp = sLast + Reverse( sRemainder ); return tmp; } } var str : String = "abcdef"; trace( Reverse( str ) );
This little diagram I drew out helped me understand what the execution stack looked like :
Automated Flex Project Generation
June 17th, 2008After reading the book Code Generation in Action I found I was in need of an simple and easy way to roll out Flex project foundations. I create a script that works with a set of template files to build the standard project directory structure, a set of specified views, and a set of basic commands that add the views to a canvas and init the application. The following shows the command line invocation of the perl that creates a Flex project with 5 separate views :
# ./generate.pl usage : generate.pl domain applicationName view1 view2 .. view98 view99
# ./generate.pl extralongfingers mynewapplication helpbutton startbutton stopbutton extralongfingersbutton holymountbutton
After that runs we have a set of directories that looks like this :
Each view specified on the command line created a mxml file in the root directory of the namespace and a corresponding controller in the com.extralongfingers.mynewapplication.client.controllers directory. If you run the script you will see that each mxml view registers itself with the controller that shares its name. The script also creates an application mxml file call Mynewapplication.mxml in the root of the directory structure. This mxml application serves as the entry point for the app and proceeds to run the BuildViews Command upon initialization wherein all the mxml views are instantiated and proceed to link up with their controllers. I'm planning to clean up this perl a bit in order to modularize things a bit more and hope to submit to cpan soon. Let me know what you think and if you found this useful. I've been doing a lot with code generation lately so come back soon for my AMF PHP remoting gateway generator. Flex Generation Framework Source
ViewHelper in Actionscript 3.0
April 28th, 2008I always found the MovieClipHelper.as of the Pixlib framework useful for rolling out applications in a quick and straightforward manner. Although the newest iteration of the framework LowRA is a useful and powerful xml driven environment to roll out RIAs, I still find the need for a manager to hold references to all my views. The power of a centralized repository of all views and standard methods for x, y manipulation is great to have around for any project. I've also been looking through the Vegas framework and was unable to find a View Management tool along the same lines. So I decided to roll my own using Pixlib as a basis and Vegas as my environment. This little class does most of the things you'll find in the Pixlib version like holding all view references in a hash map. This design principle makes managing views incredibly easy. By just defining a single enum file of static strings, you can uniquely name all the views of your application and then subsequently access those views from anywhere in the application. I find this useful when managing sizing and positioning of multiple views that are dependent upon one another. So herein follows a quick and dirty ViewManager designed for Sprites in AS3.
package com.extralongfingers.definitionalliterature.client.util { import flash.display.DisplayObject; import vegas.data.map.HashMap; import flash.geom.Point; import flash.events.EventDispatcher; import flash.display.Sprite; /** * @author Gregory Sogorka */ public class ViewHelper { public var view : Sprite; public var _dispatcher : EventDispatcher = new EventDispatcher(); private static var _a : HashMap = new HashMap(); private var _sName : String; function ViewHelper( s : String, spr : Sprite ) { if( spr == null ) trace( " You must pass a Sprite to the constructor."); else { view = spr; _setName( s ); } } public function setVisible( b : Boolean ) : void { if ( b ) { show(); } else { hide(); } } public function hide() : void { view.visible = false; } public function show() : void { view.visible = true; } public function move( x : Number, y : Number ) : void { view.x = x; view.y = y; } public function getPosition() : Point { return new Point( view.x, view.y ); } public function setSize( w : Number, h : Number ) : void { view.width = w; view.height = h; } public function getSize() : Point { return new Point( view.width, view.height ); } public function getName() : String { return _sName; } public function release() : void { ViewHelper._unregister( _sName ); _sName = null; } public function isVisible() : Boolean { return view.visible; } public static function getMovieClipHelper( sName:String ) : ViewHelper { if (!ViewHelper._a.containsKey( sName ) ) { trace( "Can't find ViewHelper instance with '" + sName + "' name." ); } return _a.get( sName ); } public static function isRegistered( sName:String ) : Boolean { return ViewHelper._a.containsKey( sName ); } //Private methods. private function _setName( name:String ) : void { if ( ViewHelper._register( name, this ) ) _sName = name; } private static function _register( sName:String, oHelper:ViewHelper ) : Boolean { if ( ViewHelper._a.containsKey( sName ) ) { trace( "ViewHelper instance is already registered with '" + sName + "' name." ); return false; } else { ViewHelper._a.put( sName, oHelper ); return true; } } private static function _unregister( sName:String ) : void { ViewHelper._a.remove( sName ); } } }
If you have any suggestions or improvements that might make this type of thing work even better drop me a line.
Insertion Sort in Actionscript 3
April 8th, 2008Started reading the book Introduction to Algorithms by Cormen, Leiserson, Rivet, & Stein. And figured I would start posting my algorithmic implementations in actionscript for those in the community who are interested. First up is a quick and dirty implementation of insertion sort in two forms: 1. Sort in ascending order 2. Sort in descending order. This is pretty simple stuff once you wrap your head around the while loop. I'm interested to see more about how O,
notation, and
notation can help us to determine upper bound running times of recursive operations. I'll keep you all posted as I discover more on this. And now for the increasing insertion sort code:
//Insertion Sort var arr : Array = new Array(4, 3,2324, 28, 999, 821, 423,22, 21, 2, 1); var j : Number = 0; for( j; j < arr.length; j++) { var key : Number = arr[j]; var i : Number = j-1; while( i > -1 && arr[i] > key ) { arr[i+1] = arr[i]; i= i-1; } arr[i+1] = key; } trace( arr );
And the decreasing insertion sort code :
var arr : Array = new Array ( 1, 2, 3,99, 22, 33, 4, 55, 44545, 23, 4 ); for( var j : Number = 0; j< arr.length; j++ ) { var key : Number = arr[j]; var i : Number = j-1; while( i > -1 && arr[i] < key ) { arr[i+1] = arr[i]; i= i-1; } arr[ i+1] = key; } trace( arr );
If anyone in the New York City area is interested in jointly studying this topic with me drop me a line.
Web 2.0 Blue Gradient in Flash
March 23rd, 2008After reading this tutorial here I implemented the gradient used in photoshop within flash. I wrote a quick little static class to create this as a six color gradient on the fly. Source Files
//Gradient package com.extralongfingers.utilities.visual { import flash.display.Sprite; import flash.geom.Matrix; /** * @author Gregory Sogorka */ public class BlueGradientBox { public function BlueGradientBox() { trace( "Ouch! I'm static. " ); } public static function make( _target : Sprite, w : Number, h : Number, x : Number, y : Number, corner : Number ) : void { _target.graphics.lineStyle(1, 0x8c8c8c); //Colors and Ratios copied from Adobe Photoshop gradient presets. var colors : Array = [ 0x02a8e4, 0x47bef0 , 0x147bb6, 0x005081, 0x023761, 0x7295b5 ]; var alphas : Array = [ 50, 70, 100 , 100, 100, 100 ]; var ratios : Array = [ 15, 19, 77, 136, 248, 254 ]; var matrix : Matrix = new Matrix( ); matrix.createGradientBox(w, h); _target.graphics.beginGradientFill("linear", colors, alphas, ratios, matrix); _target.graphics.drawRoundRect(x, y, w, h, corner, corner); } } }
Natural Object Rotation Using Papervision3D
December 27th, 2007
I then proceed to rotate that cube about its y axis using the built-in yaw() method of the Cube class. My naivete initially led me to believe that subsequent rotation about the X axis would require the pitch() method of the Cube class. However since axes are local to a display object, the preceding yaw() method yielded a inversion of the Z and X axes. The follow diagram illustrates the transformation that has occurred:

So..... my project of presenting the user with a simple interface consisting of arrows allowing the rotation of a cube became a bit more difficult. I had to develop a method for tracking the perceived axes and the actual axes to which these perceived axes corresponded. After some thought and sketching I started to tinker with some methods to track cube axes via strings within an object. My object of course was named _objAxes, and its properties were x, y, and z.If we look at this object in its initial state we have the following :

and after the rotation about the y axis we have
Now for the sake of simulation, let us say that I now wish to rotate this cube along its X axis, as perceived by the camera. Initially I thought, "Ok, all I have to do is call the pitch() method of the Cube class and everything would be fine and dandy...." However, since the previous transformation of the Cube resulted inverted Z-X axes the pitch() method would result in the Cube rotating along its perceived Z axis instead of the X axis I intended. Herein lies the necessity of an axis tracking system.What I developed was a two-fold system for determining proper rotation of the object. The first is a decision making process for each type of rotation : Right, Left, Up, or Down. An event enters my Spin.as class and based on the event string sends it to the proper rotation class.The code is as follows:
public class SpinCube implements ISpin { private var _objAxes : Object = { x : "x", y : "y", z : "z" }; private var _cube : Cube ; private var _spr : SpinRight; private var _spl : SpinLeft; private var _spd : SpinDown; private var _spu : SpinUp; private var _cv : CheckVisibility; public function SpinCube( cube : Cube ) { _cube = cube; _spr = new SpinRight( this ); _spl = new SpinLeft ( this ); _spd = new SpinDown( this ); _spu = new SpinUp( this ); _cv = new CheckVisibility( this ); } public function spin( str : String ) : void { if( str == SpinGlobals.SPIN_RIGHT() ) { _spr.spin(); } else if ( str == SpinGlobals.SPIN_LEFT() ) { _spl.spin(); } else if ( str == SpinGlobals.SPIN_DOWN() ) { _spd.spin(); } else if ( str == SpinGlobals.SPIN_UP() ) { _spu.spin(); } } public class SpinRight { private var _ref : SpinCube; private var _cube : Cube; private var _objAxes : Object; private var _str : String; public function SpinRight ( ref : SpinCube ) { _ref = ref; _cube = _ref.getCube(); } public function spin() : void { //GET the CURRENT rotation axes. _objAxes = _ref.getObjAxes(); trace( " SpinCube ::: spin ( e ) :::: spinRight() running."); var rt:Timer = new Timer(1, 90 ); rt.addEventListener( TimerEvent.TIMER, rightSpin ); rt.addEventListener( TimerEvent.TIMER_COMPLETE , rightSpinComplete ); rt.start(); } private function rightSpin( e : Event ) : void { if ( _objAxes[ "y" ] == "y") { _cube.yaw( 1 ); _str = "yaw"; } else if ( _objAxes[ "y" ] == "x" ) { _cube.pitch( 1 ); _str = "pitch"; } else if ( _objAxes[ "y" ] == "z" ) { _cube.roll( 1 ); _str = "roll"; } } private function rightSpinComplete( e : Event ) : void { _ref.processAxes(_str); trace("SPIN RIGHT:::: "+_str+" :::: AFTER ::::: "); _ref.dumpAxes(); }
All that is going on here is the events emanating from the UI Arrow elements are being routed to their proper classes based on their .type property.So for the sake of simulation let us say the Spin class receives a SpinGlobals.SPIN_RIGHT() event the Spin class will call the spin() method on the _spr instance of the SpinRight class. The logic now gets interesting as we have to determine the local object axis of the perceived, from the camera point of view, Y axis.The SpinRight class reads as follows:
//PART 2 public class SpinRight { private var _ref : SpinCube; private var _cube : Cube; private var _objAxes : Object; private var _str : String; public function SpinRight ( ref : SpinCube ) { _ref = ref; _cube = _ref.getCube(); } public function spin() : void { //GET the CURRENT rotation axes. _objAxes = _ref.getObjAxes(); trace( " SpinCube ::: spin ( e ) :::: spinRight() running."); var rt:Timer = new Timer(1, 90 ); rt.addEventListener( TimerEvent.TIMER, rightSpin ); rt.addEventListener( TimerEvent.TIMER_COMPLETE , rightSpinComplete ); rt.start(); } private function rightSpin( e : Event ) : void { if ( _objAxes[ "y" ] == "y") { _cube.yaw( 1 ); _str = "yaw"; } else if ( _objAxes[ "y" ] == "x" ) { _cube.pitch( 1 ); _str = "pitch"; } else if ( _objAxes[ "y" ] == "z" ) { _cube.roll( 1 ); _str = "roll"; } } private function rightSpinComplete( e : Event ) : void { _ref.processAxes(_str); trace("SPIN RIGHT:::: "+_str+" :::: AFTER ::::: "); _ref.dumpAxes(); }
Since a RightSpin Event has been passed along, the SpinRight class now has to determine the local Y axis of the object in order that it can call the proper method on the object. If the SpinRight class finds that the object's local Y axis value is "y" it calls the yaw() method on the object. However if it were to find the local Y axis to be "z", it would call the roll() method on the object and the object would rotate properly. Now, as this rotation occurs a temporary string is written indicating the method being used to perform the rotation on the object. This I realize could be optimized to only store the string once, but this is just a mockup of how to get natural rotation working. This string will be used when the TimerEvent.TIMER_COMPLETE fires the rightSpinComplete() function. What happens here is the string is sent back to the SpinCube class for processing to properly update the _objAxes values.The function that processes that string reads as follows:
//part 3 public function processAxes( _str : String ) : void { if ( _str == "yaw" ) { trace("SPIN :::: yaw() :::: "); trace("SPIN :::: yaw() :::: BEFORE ::::: "); dumpAxes(); if( _objAxes["y"] =="y" ) { _objAxes = { y : _objAxes[ "y"], x : _objAxes[ "z" ] , z : _objAxes[ "x" ] }; } else if ( _objAxes["x"] =="y" ) { _objAxes = { y : _objAxes["z"], x : _objAxes["x"], z: _objAxes["y"] }; } else if ( _objAxes["z"] == "y" ) { _objAxes = { y : _objAxes["x"], x: _objAxes["y"], z : _objAxes["z"] }; } } if ( _str == "pitch" ) { trace("SPIN :::: pitch() :::: "); trace("SPIN :::: pitch() :::: BEFORE ::::: "); dumpAxes(); if( _objAxes[ "x" ] == "x" ) { _objAxes = { y : _objAxes[ "z" ] , x : _objAxes[ "x" ], z : _objAxes[ "y" ] }; } else if ( _objAxes["y"] == "x" ) { _objAxes = { y : _objAxes["y"], x : _objAxes["z"], z: _objAxes["x"] }; } else if ( _objAxes["z"]== "x") { _objAxes = { y: _objAxes["x"], x: _objAxes["y"], z: _objAxes["z"] }; } } if( _str == "roll" ) { trace("SPIN :::: roll() :::: "); trace("SPIN :::: roll() :::: BEFORE ::::: "); dumpAxes(); if( _objAxes[ "z" ] == "z" ) { _objAxes = { y : _objAxes[ "x" ], x: _objAxes[ "y" ], z : _objAxes[ "z" ] }; } else if(_objAxes[ "x" ] == "z" ) { _objAxes = { y : _objAxes[ "z" ], x : _objAxes[ "x" ], z: _objAxes[ "y" ] }; } else if ( _objAxes[ "y" ] == "z" ) { _objAxes = { y : _objAxes[ "y" ], x : _objAxes[ "z" ], z: _objAxes["x"] }; } } trace("Cube After Transformation : " ); dumpAxes(); }
Since yaw() was called on the object and the Y axis was the local y axis before this transformation, the function substitutes _objAxes.x and _objAxes.z values. As far as I can tell through my testing, this processing should not fail to rewrite the object properly and perform all future transformations on the object as intended. Of course there are some caveats to this method of axis tracking; This will only work for rotations of 90 degress in any direction; for a cube this seems natural, but for other objects this may not be the case. Additionally the rotation tracking fails, at this point in time, to recognize the existence of a cube face whose image is upside-down. I am working on an algorithm to determine this state and parse accordingly, but at the current juncture it's not complete. Also I realize that the eventing in the swf example is a bit crude. It does not kill all events when the cube is in motion so therefore it is possible to click storm the cube and get strange rotations. But if you just use one click at a time to rotate my point should be illustrated. Thats about all for now. You can find full source for my spin classes attached to this post. If you have any comments or ideas for optimization of this technique drop me a line.
Sources :1. Natural Object Rotation2. The mailing list posts got me thinking about this problem : Papervision Mailing ListSource Code :Natural Object Rotation Classes.


