Author: tomithy
Date: 2010-07-10 10:17:52 -0700 (Sat, 10 Jul 2010)
New Revision: 20896

Modified:
   cytoscapeweb/branches/gsoc2010/demos/src/GBEB/Mesh.as
Log:
/* Version control file 11/7/10

Version 0.3
- Mesh is able to merge shape; 
- DataDisplay shows different Shapes in Mesh;
- Able to calculate Mesh for different Layouts.

Version 0.4 
- cleanup function is written to free up resources
Mesh: - shapes no longer contain repeated edges
                         - Patch is used to reflect the gradient around the 
point, as there is some unknown bug causing the gradient to be reflected about 
the y-axis
                         - Functions implemented: 
                                                4a) generateMeshEdges; 
getNodesForMeshEdge; isSourceNodeAssigned, generateNonRedundantShapeIndexArray, 
findCentroid,
                                                                
generateLineFromPointAndGradient, intersectionWithVertical, 
intersectionWithHorizontal
                                                4b) mergeNodes_All(), 
mergeNodes_Pairwise, calculateDistanceBetweenNodes - disabled as there are some 
bugs
Class GeometryUtil is added to store lineIntersectline Math function
DataDisplay:  - displays the centroid of Shapes, 
                                        - displays the mesh itself, which is 
accurate except for occurance of vertical straight lines due to known issue (1)

Version 0.5
Shape/ DataDisplay: - control points are set up. Initially they are added via 
GBEB properties and mirrored in edge.points
                                                                                
- control points are successfully added to all dataEdges that intersects with 
meshEdges - the control point is the avg of the intersection points of 
the meshEdge with the dataEdges passing through it. 

Version 0.6
Bundler added - it extends from edge render. Used Shapes.BEZIER for rendering, 
the effect is only satisfactory in general, but sometimes confusing for lines 
with > 1 control points,
due to BEZIER's mathemathical property
Comments: It doesnt work very well on simple graphs and the curves thens to 
complicate.
                                        Messy graphs like circle or radial can 
be improved if the resolution is set higher at the expense of runtime. 

Next:
Version 0.7 - allow dynamic adjusting of resolution by merging Shapes by the 
factor of 2
                                                - include edge quality 
calculation
                                                - implement another renderer 
for meshEdges to obtain better graphical control that default Bezier does not 
offer. 

Comments: Indent layout is rather slow to compute. Perhaps because of the huge 
centre shape. 

Known issues: 1) If the mesh edge is vertical or horizontal and it lies 
directly above the grid, its source/traget nodes cannot be retrieve. 
                                                                Eg. Edge 9 of 
"social network.xml" -
                                                                Function 
responsible: intersectsVertical and getNodesForMeshEdge
                                                        2) MergeNodes_All() - 
Is acting weirdly, so it is disabled for now. 
                                                        3) Edges cannot be 
added when nodes are not added
                                                        4) Indent Layout does 
not work. 
                                                        5) Sample 2 does not 
work as some nodes are not assigned any location, and are hence out of bounce. 

*/

Modified: cytoscapeweb/branches/gsoc2010/demos/src/GBEB/Mesh.as
===================================================================
--- cytoscapeweb/branches/gsoc2010/demos/src/GBEB/Mesh.as       2010-07-10 
17:17:21 UTC (rev 20895)
+++ cytoscapeweb/branches/gsoc2010/demos/src/GBEB/Mesh.as       2010-07-10 
17:17:52 UTC (rev 20896)
@@ -3,9 +3,9 @@
        import flare.vis.data.Data;
        import flare.vis.data.DataSprite;
        import flare.vis.data.EdgeSprite;
+       import flare.vis.data.NodeSprite;
        
        import flash.display.Sprite;
-       import flash.events.MouseEvent;
        import flash.geom.Point;
        import flash.geom.Rectangle;
 
@@ -15,15 +15,21 @@
        ////////////////////////////////////////////////////////////////
        public class Mesh extends Sprite
        {               
-               public var _grid:Array;                           //stores the 
array of Shapes
+               public var grid:Array;                    //stores the array of 
Shapes
                public var gridSize:int = 20; // size of initial bounding grid, 
in pixel
+               public var _mesh:Data = new Data(); //stores the actual edges 
and nodes of the points for the mesh
+               public var nonRedundantShapeIndexArray:Array = new Array(); // 
Stores Shape that actually contain meshEdges and have a general direction
+               private var _data:Data; 
+               private var _meshEdgeArray:Array; //Stores the array of 
meshEdges for processing
                private var _bounds:Rectangle = new Rectangle(); // stores the 
bound of the visualisation
-               private var _data:Data;
+               private var _originalGrid:Array; //stores the array of Shapes 
at maximum resolution
                
                
                private var angleResolution:int = 15; //stores the angle 
resolution needed to resolve grid joining. 
                private var edgeCounter:int = 1;
                
+               private const _meshNodesMinDistance:Number = 2.0; //Defines the 
minimum distnance between any 2 nodes in the mesh
+               
                public var numGridsX:int = -1;
                public var numGridsY:int = -1;
                
@@ -36,11 +42,36 @@
                public function Mesh (data:Data):void
                {
                        _data = data;
-                       _grid = new Array();
+                       grid = new Array();
                }
                
+               public function cleanup():void
+               {
+                       grid = null;
+                       nonRedundantShapeIndexArray = null;
+                       
+                       cleanupMeshEdges();
+                       
+                       _data = null;
+                       _mesh = null;
+                       _meshEdgeArray = null;
+                       _bounds = null;
+                       _originalGrid = null;
+                       
+               }
                
+                               private function cleanupMeshEdges():void
+                               {
+                                       for each (var edge:EdgeSprite in 
_data.edges)
+                                       {
+                                               var props:* = 
edge.props.GBEBProperties;
+                                               if(props != null)       props = 
null;
+                                       }
+                               }
+               
+               
                // Follows the step below to generate a Mesh
+               // 0. Assign GBEBProperty to all edges
                // 1. Generate a uniform grid of 20pix per grid for the entire 
bound
                // 2. For each grid, detect what edges are inside and store 
them in shape | There is no need to
                // store nodes at all. 
@@ -65,7 +96,15 @@
                        
                        assignDataToGrid();
                        
+                       //changeresolution();
+                       
+                       _data.edges.visit(assignProps);
+                       
                        mergeShapeUsingPrimaryDirections();
+                       
+                       generateMeshEdges();
+                       
+                       addControlPointsToAll();
                        //_grid = mergeShape(angleResolution); 
                        
                        
@@ -75,8 +114,16 @@
                        //trace("Mesh: Testing testIntersection: " + 
testIntersection(new Rectangle(-1,-1,5,5), new Point(2,2), new Point(10,5))); 
//testing the intersection of glancing contact
                }
                
+               
//////////////////////////////////////////////////////////////////////////////////////////////
+               //Step 0: function to assign GBEB Properties to each mesh Edge 
that is used for controling them
+               
/////////////////////////////////////////////////////////////////////////////////////////////
+               public function assignProps(e:EdgeSprite):void
+               {
+                       var prop:GBEBProperty = e.props.GBEBProperty;           
+                       prop = new GBEBProperty();
+                       e.props.GBEBProperty = prop;
+               }
                
-               
                //////////////////////////////////////////////
                //Step 1: function to generate the grid from scratch    
                //////////////////////////////////////////////
@@ -98,7 +145,7 @@
                
                        while( _counterY <= numGridsY ) //-22
                        {
-                               while( _counterX <= numGridsX - 10)// -20
+                               while( _counterX <= numGridsX )// -20
                                {
                                        
                                        var _shape:Shape = new Shape();
@@ -126,7 +173,7 @@
                        } 
                        
                        
-                       _grid = _newGrid;
+                       grid = _newGrid;
 
                        return void;
                }
@@ -142,7 +189,7 @@
                {
                        if(d != null) _data = d;
                                                        
-                       if(_grid.length == 0) return;
+                       if(grid.length == 0) return;
                                                                
                        //data.edges.sortBy({"x", "y"});
                                                
@@ -159,7 +206,7 @@
                                trace((edge.source.data["name"]), " (" + 
edge.x1 + "," +  edge.y1 + ") ", " | " 
                                        + edge.target.data["name"] + " ( " + 
edge.x2 + "," + edge.y2 + ")"); 
 
-                               for each(var _shape:Shape in _grid) 
+                               for each(var _shape:Shape in grid) 
                                {
                                        
                                        for each (var __grid:Rectangle in 
_shape.storedGrids)
@@ -185,7 +232,7 @@
                                
                        }// end of huge for loop
                                                
-                       for each( var _shape:Shape in _grid)
+                       for each( var _shape:Shape in grid)
                        {
                                _shape.computeDirection();
                        }
@@ -274,7 +321,7 @@
                        var iterationIndexArray:Array = new Array(); //this 
array stores the index of the shapes that 
                        //needs to be iterated through by the merged Shapes 
function
                        
-                       for each (var s1:Shape in _grid)
+                       for each (var s1:Shape in grid)
                        {
                                if(s1.direction != -1)
                                {
@@ -345,7 +392,7 @@
                        }
                
                
-                       return null; // to be edited. 
+                       return null;
                } 
                
                
@@ -388,6 +435,8 @@
                                {
                                //      trace("Mesh: MergeShape: is called!");
                                        
+                                       var e2:EdgeSprite;
+                                       
                                        if(s1 == null && s2 == null) return 
null;
                                        if(s2 == null) return s1;
                                        if(s1 == null) return s2;
@@ -396,7 +445,9 @@
                                        while(s2.storedDataEdges.length != 0)
                                        {
                                                //transfers the edges from s2 
to s1
-                                               
s1.storedDataEdges.push(s2.storedDataEdges.pop());
+                                               e2 = s2.storedDataEdges.pop();
+                                               
+                                               
if(s1.storedDataEdges.indexOf(e2) == -1) s1.storedDataEdges.push(e2);
                                        }
                                        
                                        //transfer storedGrid Index
@@ -406,7 +457,7 @@
                                        
                                        for each (var p:Point in s2.gridIndex)
                                        {
-                                               _grid[indexFromPoint(p)] = s1;
+                                               grid[indexFromPoint(p)] = s1;
                                                s1.gridIndex.push(p);
                                                //trace("Mesh: MergeShape: 
Point "+ p.toString() + " is added to " + s1.gridIndex[0]);
                                        }
@@ -422,9 +473,476 @@
                                        
                                        return s1;
                                }
+                               
+                               
+       //////////////////////////////////////////////
+       // Step 4a. Obtain _meshEdges (1 for each Shape), and their respective 
nodes. 
+       // The direction variable in each shape with a majority direction gives 
the gradient of the mesh edge passing through the particular shape.
+       // The Mesh edge needs an intersection point within the shape and this 
intersection point is precisely the 
+       // centroid of the shape. 
+       //////////////////////////////////////////////
+                               
+       public function generateMeshEdges():void
+       {
+               if(grid == null) return;
+               
+               var gradient:Number = 1;
+               var meshEdge:EdgeSprite = new EdgeSprite();
+               var currentGrid:Point = new Point(-1,-1); //stores the index of 
the grid that is currently being tested for intersection 
+               
+               _meshEdgeArray = new Array();
+               
+               trace("Mesh: Generate meshEdges: running!");
+               
+               generateNonRedundantShapeIndexArray();
+               
+               for each (var p1:Point in nonRedundantShapeIndexArray)
+               {
+                       var s1:Shape = returnShapeFromIndex(p1);
+                       var angleOfLine:Number = 0;
+                       
+                       if(s1.direction == -1) continue;
+                       //only shapes with a main direction will continue until 
here. 
+                       
+                       //trace("Mesh: GenerateMeshEdges: Gradient Calculation: 
for " + s1.direction + " gradient = " + Math.tan((s1.direction / 180) * 
Math.PI));
+                       gradient = -1 / Math.tan((s1.direction / 180) * 
Math.PI);       
+                       
+                       //angleOfLine = Math.atan(gradient) * 180 / Math.PI;
+                       //trace("Mesh: Testing Gradient: Edge " + cycles + " | 
direction " + s1.direction + " | Gradient:" + gradient + " |Angle: " + 
angleOfLine);
+                       
+                       s1.centroid = findCentroid(s1);
+                       
+                       //trace("Mesh: Generate meshEdges: " + 
returnIndexFromXY(s1.centroid.x, s1.centroid.y).toString() + " | " + 
s1.centroid.toString());
+                       meshEdge = 
generateLineFromPointAndGradient(s1.centroid, gradient);
+                       
+                       currentGrid = returnIndexFromXY(s1.centroid.x, 
s1.centroid.y);
+                       
+                       if( currentGrid.x < 0 || currentGrid.y < 0 || 
currentGrid.x > numGridsX || currentGrid.y > numGridsY ) continue; 
+                       
+                       meshEdge.source = new NodeSprite(); meshEdge.source.x = 
meshEdge.x1; meshEdge.source.y = meshEdge.y1;
+                       
+                       meshEdge.target = new NodeSprite(); meshEdge.target.x = 
meshEdge.x2; meshEdge.target.y = meshEdge.y2;
+                       
+                       meshEdge.target.name = meshEdge.source.name = 
(cycles).toString();
+                       meshEdge.name = (cycles++).toString();
+                       
+                       getNodesForMeshEdge(returnIndexFromXY(s1.centroid.x, 
s1.centroid.y), meshEdge, meshEdge.source, "None");
+                       
+                       
+                       //trace("Mesh: GenerateMeshEdges: Assigning names: " + 
meshEdge.x1);
+                       
+                       s1.meshEdge = meshEdge;
+                       
+                       if(meshEdge != null)
+                       {
+                               _meshEdgeArray.push(meshEdge);
+                               _mesh.addNode(meshEdge.source);
+                               _mesh.addNode(meshEdge.target);
+                               _mesh.addEdge(meshEdge);
+                               
+                               //_mesh.edges.add(meshEdge); //adding the mesh 
edge to datalist; technically, I can use the _mesh.edge.visit function to runs
+                               //mergeNodes_All(), but it might be quite messy 
as I have to visit the list of edges in the fashion of bubble sort. 
+                       }
+               }
+               //trace("Mesh: GenerateMeshEdges: " + _mesh.edges);
+               trace("Mesh: GenerateMeshEdes: No. of meshEdges generated = " + 
_meshEdgeArray.length + " | Nodes " + _mesh.nodes.length + " | Edges" + 
_mesh.edges.length);
+                
+               
+               
+               //mergeNodes_All(); //huge sub-routine to merge all neigbouring 
nodes. 
+               
+               
+               return;
+       }
+       
+                               //This will cause the edge to shift. 
+                               //Step 4a.1 :: Recurrsive function. Takes in 
the grid index and an edge sprite to return an edge that is assigned with nodes
+                               //the nodes are the found at the boundary of 
each Shape. It uses the last prevDir variable to pass on the information on 
which direction the 
+                               //edge came from, in order not to get a double 
hit. (For example, if the edge passes through the top of the prev grid, it 
would definitely pass
+                               //through the bottom of the top adjoining grid, 
but that is not the next intersection that we are interested to find). This 
function also handles
+                               //the special case where the gradient is 0 or 
infinity. 
+                               private function 
getNodesForMeshEdge(currentGridIndex:Point, edge:EdgeSprite, node:NodeSprite, 
prevDir:String):NodeSprite
+                               {
+                                       //trace("Mesh: getNodesForMeshEdge is 
running! EdgeNo :" + edge.name + " | CurrentGridIndex: " + currentGridIndex, "| 
source", edge.x1,
+                                       //      edge.y1, "| target", edge.x2, 
edge.y2);
                                        
+                                       var currentGridXY:Point = 
returnXYFromIndex(currentGridIndex);
+                                       var currentShape:Shape = 
returnShapeFromIndex(currentGridIndex);
+                                       var newGrid:Point = new Point(0,0); 
+                                       var grid:Rectangle = new 
Rectangle(currentGridXY.x, currentGridXY.y, gridSize, gridSize);
+               
+                                       var intersectionPoint:Point; 
+               
+                                       var p1:Point = new Point(edge.x1, 
edge.y1); //stores the x,y coordinates of the source of edgeNode temporarily.
+                                       var p2:Point = new Point(edge.x2, 
edge.y2); //stores the x,y coordinates of the target of edgeNode temporarily.
+               
+                                       intersectionPoint = 
intersectsHorizontal(grid.topLeft, topRight(grid), p1, p2); //check if the edge 
intersects with the top
                                        
+                                       if(intersectionPoint != null && prevDir 
!= "Bottom" )
+                                       {                                       
+                                               newGrid.x = currentGridIndex.x; 
newGrid.y = currentGridIndex.y - 1;
+                                               node.x = intersectionPoint.x, 
node.y = intersectionPoint.y;
+                                               
if(searchShapeForIndex(currentShape, newGrid))
+                                               {
+                                                       node = 
getNodesForMeshEdge(newGrid, edge, node, "Top");
+                                               } else if (prevDir != "None") {
+                                                       return node;
+                                               } 
+                                       } 
+               
+                               
                                        
+                                       //I am overloading this huge recurrsive 
to handle both the source and target nodes together. This function basically 
ask if
+                                       //this is the first time the function 
is called for an edge. If it is, and that if edge.source has been moved to an 
intersection point
+                                       //it will continue to work with the 
edge.target as node. 
+                                       //Notes: It doesnt matter that the 
variable node is coninuously assigned to edge.target.
+                                       if(prevDir == "None" && 
isSourceNodeAssigned(edge))  
+                                       {
+                                               node = edge.target;
+                                       }
+               
+                                       //check if the edge intersects with the 
bottomEdge
+                                       intersectionPoint = 
intersectsHorizontal(bottomLeft(grid), grid.bottomRight, p1, p2); 
+                                       
+                                       //trace("Mesh: getNodesForMeshEdge: 
IntersectionPoint: " + intersectionPoint.toString());
+               
+                                       if(intersectionPoint != null && prevDir 
!= "Top" )
+                                       {
+                                               newGrid.x = currentGridIndex.x; 
newGrid.y = currentGridIndex.y + 1;
+                                               node.x = intersectionPoint.x, 
node.y = intersectionPoint.y;
+                                               
if(searchShapeForIndex(currentShape, newGrid))
+                                               {
+                                                       node = 
getNodesForMeshEdge(newGrid, edge, node,"Bottom");
+                                               } else if (prevDir != "None") {
+                                                       return node;
+                                               } 
+                                       } 
+               
+               
+                       
+                                       if(prevDir == "None" && 
isSourceNodeAssigned(edge))  
+                                       {
+                                               node = edge.target;
+                                       }
+               
+                                       //check if the edge intersects with the 
leftEdge
+                                       intersectionPoint = 
intersectsVertical(grid.topLeft, bottomLeft(grid), p1, p2);
+
+                                       
+                                       if(intersectionPoint != null && prevDir 
!= "Right" )
+                                       {
+                                               newGrid.x = currentGridIndex.x 
- 1; newGrid.y = currentGridIndex.y;
+                                               node.x = intersectionPoint.x, 
node.y = intersectionPoint.y;
+                                               
if(searchShapeForIndex(currentShape, newGrid))
+                                               {       
+                                                       node = 
getNodesForMeshEdge(newGrid, edge, node, "Left");                        
+                                               } else if (prevDir != "None") {
+                                                       return node;
+                                               } 
+                                       } 
+               
+                                       //I have included the whole statement 
for consistency. Technically, if can do without the right portion after "&&")
+                                       //as each grid is guranteed to have 2 
intersections points, so by the 4th assignment must belong to the edge. 
+                                       if(prevDir == "None" && 
isSourceNodeAssigned(edge))  
+                                       {
+                                               node = edge.target;
+                                       }
+               
+                                       //check if the edge intersects with the 
rightEdge
+                                       intersectionPoint = 
intersectsVertical(topRight(grid), grid.bottomRight, p1, p2);
+
+                                       if(intersectionPoint != null && prevDir 
!= "Left" )
+                                       {
+                                               newGrid.x = currentGridIndex.x 
+ 1; newGrid.y = currentGridIndex.y;
+                                               node.x = intersectionPoint.x, 
node.y = intersectionPoint.y;
+                                               
if(searchShapeForIndex(currentShape, newGrid))
+                                               {       
+                                                       node = 
getNodesForMeshEdge(newGrid, edge, node, "Right");
+                                               } else if (prevDir != "None") {
+                                                       return node;
+                                               } 
+                                       } 
+               
+                                               //trace("Mesh: 
getNodesForMeshEdge: " +  centroid.toString() + "(It is only suppose to fall 
through once per edge!)"); //since each centroid is unique
+                                               return node;
+                                       }
+       
+                               
+                                       //Step 4a.1     :: Support. This 
function is basically asking if the previous
+                                       // the intersections for the "source 
Node" has been found. 
+                                       //Worry about flash arithmetic? (what 
if the change is very small? what if "==" does not
+                                       private function 
isSourceNodeAssigned(edge:EdgeSprite):Boolean
+                                       {                                       
+                                               if( Math.abs(edge.source.x - 
edge.x1) < 0.5 && Math.abs(edge.source.y - edge.y1) < 0.5)
+                                               {
+                                                       return false;
+                                               }
+                                       
+                                               return true;
+                                       }
+       
+       
+                                       //Step 4a.2 ::This function is a clean 
up function which generates an array of nonRedundant index of Unique shapes 
that have
+                                       //a major direction which helps in 
further processesing of these edges
+                                       private function 
generateNonRedundantShapeIndexArray():Array
+                                       {
+                                               nonRedundantShapeIndexArray = 
new Array();
+                                               
+                                               for each (var s1:Shape in grid)
+                                               {
+                                                       if(s1.direction != -1 
&& nonRedundantShapeIndexArray.indexOf(s1.gridIndex[0]) == -1)
+                                                       {
+                                                                       
nonRedundantShapeIndexArray.push(s1.gridIndex[0]);
+                                                       }
+                                               }
+
+                                               return 
nonRedundantShapeIndexArray;
+                                       }
+       
+                                       //Step 4a.3 ::this function is usually 
very complication if the Shapes are irregular. However, since I have 
+                                       //define the primitive shape as a 
square a very special case of shapes, this function becomes 
+                                       //quite simple. (=
+                                       private function 
findCentroid(s:Shape):Point
+                                       {
+                                               if(s == null) return null;
+                                               
+                                               var numPoints:int = 0; 
+                                               var xCoor:Number = 0;
+                                               var yCoor:Number = 0;
+                                               var xyCoor:Point = new 
Point(0,0);
+                                               
+                                               for each (var p:Point in 
s.gridIndex)
+                                               {
+                                                       xyCoor = 
returnXYFromIndex(p);
+                                                       
+                                                       xCoor += (xyCoor.x + 
0.5 * gridSize);
+                                                       yCoor += (xyCoor.y + 
0.5 * gridSize);
+                                                       
+                                                       numPoints++;
+                                               }
+                                               
+                                               if(numPoints == 0) return null; 
+                                               
+                                               return new Point( (xCoor / 
numPoints), ( yCoor / numPoints) );
+                                               
+                                               //check if centroid lies within 
the Area of the shape?
+                                               //yes, I have have to. Should I 
assign the closet grid?
+                                               
+                                               //return returnXYFromIndex( new 
Point( (xIndex / numPoints), (yIndex / numPoints) ));
+                                       }
+                                       
+                                       //Step 4a.4 This function takes in the 
point in which the line passes through, and the gradient of the lines
+                                       //and return a straight EdgeSprite that 
is defined by the the bottom left (source coordinates) to the top-right (target 
corrdinates),
+                                       //where the source and target are the 
intersection of the line with the boundies of the graph
+                                       private function 
generateLineFromPointAndGradient(p:Point, gradient:Number): EdgeSprite
+                                       {
+                                               var pointsArray:Array = new 
Array(); //temp storage for the target and source
+                                               var edgeSprite:EdgeSprite = new 
EdgeSprite();
+                                               var isSourceAssigned:Boolean = 
false;
+                                               
+                                               //trace("Mesh: 
generateLineFromPoint: Checking for gradient :" + gradient + " at " + 
p.toString());
+                                               
+                                               //boundary conditions
+                                               //if (gradient == 
Number.POSITIVE_INFINITY || gradient == Number.NEGATIVE_INFINITY)
+                                               if( gradient > 500 || gradient 
< -500)
+                                               {
+                                                       if(Math.abs(p.x - 
_bounds.x) <= 0.01)
+                                                       {
+                                                               
pointsArray.push(new Point(_bounds.x, _bounds.y));
+                                                               
pointsArray.push(new Point((_bounds.width), (_bounds.height)));
+                                                       } else {
+                                                               
pointsArray.push(new Point(p.x, _bounds.y));
+                                                               
pointsArray.push(new Point(p.x, _bounds.height));
+                                                       }
+                                                       
+                                                       //trace("Mesh: 
generateLineFromPoint: Checking for gradient = infinity");
+                                               } else if ( gradient > -0.01 && 
gradient < 0.01)
+                                               {
+                                                       //if gradient is 
nearing 0 
+                                                       if(Math.abs(p.y - 
_bounds.y) <= 0.01)
+                                                       {
+                                                               
pointsArray.push(new Point(_bounds.x, _bounds.y));
+                                                               
pointsArray.push(new Point((_bounds.width), _bounds.y));
+                                                       } else {
+                                                               
pointsArray.push(new Point(_bounds.x, p.y));
+                                                               
pointsArray.push(new Point(_bounds.width, p.y));
+                                                       }
+                                                       
+                                                       //trace("Mesh: 
generateLineFromPoint: Checking for gradient = 0");
+                                               } else {
+                                                       
+                                                       //gradient = -1 
/gradient;
+                                                       
+                                                       
pointsArray.push(intersectionWithVertical(_bounds.x, p.x, p.y, gradient)); 
//with left boundary
+                                                       
pointsArray.push(intersectionWithVertical(_bounds.width + _bounds.x, p.x, p.y,  
gradient)); //with right boundary
+                                                       
pointsArray.push(intersectionWithHorizontal(_bounds.y, p.y, p.x, gradient)); 
//with top boundary
+                                                       
pointsArray.push(intersectionWithHorizontal(_bounds.height + _bounds.y, p.y, 
p.x, gradient)); //with bottom boundary
+                                                       
+                                                       //trace("Mesh: 
generateLineFromPoint: Checking for normal gradients...");
+                                               }
+                                               
+                                               for each ( var p:Point in 
pointsArray)
+                                               {
+                                                       if( p != null)
+                                                       {       
+                                                               
if(!isSourceAssigned)
+                                                               {       
+                                                                       
edgeSprite.x1 = p.x;
+                                                                       
edgeSprite.y1 = p.y;
+                                                                       
isSourceAssigned = true;
+                                                               } else {
+                                                                       
edgeSprite.x2 = p.x;
+                                                                       
edgeSprite.y2 = p.y;
+                                                               }
+                                                               
+                                                               //trace("Mesh: 
generateLineFromPoint: pointsArray can be assigned " + edgeSprite.x1, 
edgeSprite.y1, " | ", edgeSprite.x2, edgeSprite.y2 );
+                                                               
+                                                               //for tracing
+                                                               //var 
angle:Number = (edgeSprite.y2 - edgeSprite.y1) / (edgeSprite.x2 - 
edgeSprite.x1);
+                                                               //angle = 
Math.atan(angle) / Math.PI * 180;
+                                                               //trace("Mesh: 
generateLineFromPoint:" + cycles + " | angle " + angle);
+                                                       }else {
+                                                               //trace("Mesh: 
MeshEdge Generator: PointsArray.length: " + pointsArray.length + " | 
NULL!!!!!");
+                                                       }
+                                               }
+                                               //trace("Mesh: 
generateLineFromPoint: " + edgeSprite.x1 + "!!!!!");
+                                               
+                                               return edgeSprite;
+                                       }
+                                                       
+                                                               //Step 4a.4.1 
This function checks if the edge generated intersects with the vertical 
boundary of the _mesh/_bounds boundary. If it does,
+                                                               // it returns 
the intersection point. Vice versa for 4a.4.2, except that it checks against 
the horizontal boundary. 
+                                                               //Does it 
handle the case where gradient = 0 or infinity?
+                                                               private 
function intersectionWithVertical(xBoundary:Number, x1:Number, y1:Number, 
gradient:Number):Point
+                                                               {
+                                                                       var 
yCoor:Number = (gradient * ( xBoundary - x1)) + y1; //stores the y coordinate 
of the intersection point with the vertical boundary
+                                                                       
+                                                                       var 
diff:Number = yCoor - y1;//Patch to reflect the gradient about the y -axis; 
necessary due to unknown bug
+                                                                       yCoor 
-= 2 * diff;//Patch to reflect the gradient about the y -axis; necessary due to 
unknown bug
+                                                                       
+                                                                       if( 
yCoor <= _bounds.y + _bounds.height && yCoor >= _bounds.y)  //if intersects 
directly at the corner, the vertial function will return the points
+                                                                       {
+                                                                               
return new Point(xBoundary, yCoor);
+                                                                       }       
        
+                                                                       return 
null;
+                                                               }
+                                                               
+                                                               //Step 4a.4.2
+                                                               private 
function intersectionWithHorizontal(yBoundary:Number, y1:Number, x1:Number, 
gradient:Number):Point
+                                                               {               
                
+                                                                       
gradient = 1/gradient;
+                                                                       
+                                                                       var 
xCoor:Number = (gradient  * (yBoundary - y1)) + x1;
+                                                                       
+                                                                       var 
diff:Number = xCoor - x1;//Patch to reflect the gradient about the y -axis; 
necessary due to unknown bug
+                                                                       xCoor 
-= 2 * diff;//Patch to reflect the gradient about the y -axis; necessary due to 
unknown bug
+                                                                       
+                                                                       if( 
xCoor < _bounds.x + _bounds.width && xCoor > _bounds.x)  //if intersects 
directly at the corner, the vertial function will return the points
+                                                                       {
+                                                                               
return new Point(xCoor, yBoundary);
+                                                                       }       
                                        
+                                                                       return 
null;
+                                                               }
+                                                               
+                                                               
+                               //Step 4b. Merge nodes that are too close 
together. ( < x pix )
+                               //Since the nodes itself doesnt not contain any 
reference to the edges, edges are input instead,
+                               //so he edge's parameteres can be altered. It 
does a pairwise comparison with all nodes on the mesh
+                               public function mergeNodes_All():void
+                               {
+                                       var currEdge:EdgeSprite;
+                                       var currNode:NodeSprite;
+                                                                       
+                                       trace("Mesh: MergeNodes is running.");  
+                               
+                                       while(_meshEdgeArray.length != 0)
+                                       {
+                                               currEdge = _meshEdgeArray.pop();
+                                               currNode = currEdge.source;
+                                                                               
+                                               for each (var edge2:EdgeSprite 
in _meshEdgeArray)
+                                               {
+                                                       
if(calculateDistanceBetweenNodes(currNode, edge2.source) < 
_meshNodesMinDistance)
+                                                       {
+                                                               
mergeNodes_Pairwise(currEdge, "source", edge2, "source");
+                                                               continue;
+                                                       } else if  
(calculateDistanceBetweenNodes(currNode, edge2.target) < _meshNodesMinDistance)
+                                                       {
+                                                               
mergeNodes_Pairwise(currEdge, "source", edge2, "target");
+                                                               continue;
+                                                       }
+                                                                               
        
+                                                       currNode = 
currEdge.target;
+                                                                               
        
+                                                       
if(calculateDistanceBetweenNodes(currNode, edge2.source) < 
_meshNodesMinDistance)
+                                                       {       
+                                                               
mergeNodes_Pairwise(currEdge, "target", edge2, "source");
+                                                               continue;
+                                                       } else if  
(calculateDistanceBetweenNodes(currNode, edge2.target) < _meshNodesMinDistance)
+                                                       {
+                                                               
mergeNodes_Pairwise(currEdge, "target", edge2, "target");
+                                                               continue;
+                                                       }
+                                               }
+                                       }
+                                                                       
+                                               }
+                                               
+                                                               //Step 4b.1 
This function checks if 2 nodeSprites are too close together. The minimum 
distance is
+                                                               //defined by 
the const _meshNodesMinDistance
+                                                               private 
function calculateDistanceBetweenNodes(node1:NodeSprite, 
node2:NodeSprite):Number
+                                                               {
+                                                                       var 
distance:Number = 0;
+                                                       
+                                                                       //this 
is Pythogoras' Theorem
+                                                                       
distance = Math.sqrt( Math.pow((node1.x - node2.x), 2) + Math.pow((node1.y - 
node2.y), 2));
+                                                                       if 
(distance < _meshNodesMinDistance) trace("Mesh: CalculateDistanceBetweenNodes: 
" + distance,  "|", 
+                                                                               
node1.x, node1.y, "||", node2.x, node2.y);
+                                                               
+                                                                               
return distance;
+                                                               }
+                                                       
+                                                               //Step 4b.2 
this function creates a new node in the intersection between the extension of 
the 2 edges
+                                                               private 
function mergeNodes_Pairwise(edge1:EdgeSprite, s1:String, edge2:EdgeSprite, 
s2:String):void
+                                                               {
+                                                                       
if(edge1 == null || s1 == null || edge2 == null || s2 == null) return;
+                                                       
+                                                                       var 
a:Point = new Point(edge1.x1, edge1.y1);
+                                                                       var 
b:Point = new Point(edge1.x2, edge1.y2);
+                                                                       var 
e:Point = new Point(edge2.x1, edge2.y1);
+                                                                       var 
f:Point = new Point(edge2.x2, edge2.y2);
+                                                       
+                                                                       var 
ip:Point =  GBEB.GeometryUtil.lineIntersectLine( a, b, e, f); //stores the 
intersectionPoint
+                                                       
+                                                                       if( ip 
== null ) return;
+                                                                       
+                                                                       
trace("Mesh: Clustering Neigbouring Nodes: A new intersectionPoint has been 
created at " + ip.toString() 
+                                                                               
+ "\nfrom points (" + edge1[s1].x + "," + edge1[s1].y + ") " + s1 + " of Edge: 
" + edge1.name + " and (" 
+                                                                               
+ edge2[s2].x + "," + edge2[s2].y + ") " + s2 + " of Edge: " + edge2.name );
+                                                       
+                                                                       //below 
checks for the particular source/target node of edge2, which will be moved to 
the intersection Point
+                                                                       //then 
it assigns the particular source/target node of edge1 to the previously moved 
node. This results in the removal of
+                                                                       //nodes 
in the graph and reduces its node density, by "clustering" nodes
+                                                       
+                                                                       
(edge2[s2] as NodeSprite).x = ip.x; (edge2[s2] as NodeSprite).y = ip.y
+                                                       
+                                                                       
edge1[s1] = edge2[s2];
+                                                       
+                                                                       return;
+                                                               }
+                                       
+                                                               
+               // Step 5. For each edge in _data, check for their intersection 
with _mesh.edge and record these 
+               // intersection points as CPand their CP - this is actually 
quite a challenge
+               public function addControlPointsToAll():void
+               {                       
+                       for each (var p:Point in nonRedundantShapeIndexArray)
+                       {
+                               var s:Shape = returnShapeFromIndex(p);
+                               s.addControlPoint();
+                       }                                               
+               }                       
+                                       
                                        ////////////////////////////////
                                        // Helper functions
                                        ////////////////////////////////
@@ -437,19 +955,27 @@
                                                var gridX:int = Math.floor(( x 
- _bounds.x) / gridSize );
                                                var gridY:int = Math.floor(( y 
- _bounds.y) / gridSize );
                                                
-                                               return (_grid[gridY * 
(numGridsX - ( 10 - 1) )+ gridX] as Shape); //remove the -20 after trials
+                                               return (grid[gridY * (numGridsX 
- (- 1) )+ gridX] as Shape); //remove the (10-1) after trials 
                                        }
                                        
                                        public function 
returnShapeFromIndex(p:Point):Shape
                                        {
-                                               return (_grid[p.y * (numGridsX 
- 9 )+ p.x] as Shape); //remove the -20 after trials
+                                               return (grid[p.y * (numGridsX + 
1 )+ p.x] as Shape); //remove the (10-1) after trials
                                        }
                                        
                                        public function 
indexFromPoint(p:Point):int
                                        {
-                                               return p.x + p.y * (numGridsX - 
9 );
+                                               return p.x + p.y * (numGridsX + 
1 ); //remove the (10-1) after trials
                                        }
                                        
+                                       public function 
returnIndexFromXY(x:Number, y:Number):Point
+                                       {
+                                               x = Math.floor( (x - _bounds.x) 
/ gridSize);
+                                               y = Math.floor( (y - _bounds.y) 
/ gridSize);
+                                               
+                                               return new Point(x, y);
+                                       }
+
                                        //returns the actual (x,y) coordinate 
from index, returns the top-left point of the grid. 
                                        //May return any intermediate value if 
the Point p given is not any integer. 
                                        public function 
returnXYFromIndex(p:Point):Point 
@@ -457,6 +983,19 @@
                                                return new Point( (p.x * 
gridSize) + _bounds.x , (p.y * gridSize) + _bounds.y );
                                        }
        
+                                       //searches the GridIndex array of a 
given Shape for an index. Returns true, if the index exist in the Grid Array
+                                       public function 
searchShapeForIndex(s:Shape, index:Point):Boolean
+                                       {
+                                               if(s == null) return false;
+                                               
+                                               for each(var p:Point in 
s.gridIndex)
+                                               {
+                                                       if(p.x == index.x && 
p.y == index.y) return true; 
+                                               }
+                                               
+                                               return false;
+                                       }
+                                       
                                        ////////////////////////////////
                                        // functions that I am testing out
                                        ////////////////////////////////        
                

-- 
You received this message because you are subscribed to the Google Groups 
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/cytoscape-cvs?hl=en.

Reply via email to