Edit C:\galaxie\Back\galaxie\js\treegraph\TreeGraphModel.js
// // This work is licensed under the Creative Commons Attribution 2.5 License. To // view a copy of this license, visit // http://creativecommons.org/licenses/by/2.5/ // or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San // Francisco, California, 94105, USA. // // All copies and derivatives of this source must contain the license statement // above and the following attribution: // // Author: Kyle Scholz http://kylescholz.com/ // Copyright: 2006 // /** * TreeNodeModel: * * Represents a node in a Tree Graph. */ var TreeNode = function( id, radius, fanAngle, startX, startY ) { // Represents the angle of entry of this node's parent edge ... // Defaults to random so edges are randomly distributed from a root node. this['rootAngle'] = parseInt(Math.random()*360); // Each node knows it's parent so we can simplify calcuation of "branch weight". this['parent']; // indicates that this nodes is selected this['selected'] = false; // indicates whether this node can move this['isStatic'] = false; // Branch weight represents the weight of all of this node's children. this['branchWeight']=0; // A unique identifier this['id'] = id; // Indicates the radius (or length of edges rooted in this node) this['radius'] = radius; // Indicates the angle that can be filled with this nodes children. this['fanAngle'] = fanAngle; // Target Angle and Radius this['target']=new Object(); this['target']['t'] = 0; this['target']['r'] = 0; // Current Position this['position']=new Object(); this['position']['x'] = startX; this['position']['y'] = startY; this['position']['t'] = 0; this['position']['r'] = 0; // This node's children this['children'] = new Array(); // TODO: Replace "children"; This is exactly the same thing. this['edges'] = new Array(); // Indicates if this node has reached it's target this['done'] = true; // JSA this['offset']=0; this['parts']=new Array(); this['part']=null; /* */ this.initParts=function() { //alert("initParts"); fa=this['fanAngle']; if (fa==null) fa=160; this.initPart("north",0,fa); this.initPart("south",180,fa); }; this.initPart=function(id,ra,fa) { part=new Object(); part['rootAngle']=ra; part['fanAngle']=fa; part['children']=new Array(); part['id']=id; this.parts[id]=part; }; /* * Increments this branch's weight. */ this.incrementBranchWeight = function() { this['branchWeight']++; if ( this['parent'] ) { this['parent'].incrementBranchWeight(); } }; /* * Adds a child to this node. jsa-add offsetAngle */ this.addEdge = function( node, partId ) { this['children'].push(node); node['parent'] = this; node['isStatic'] = false; node['edges'].push(this); if (partId!=null) { part=this.parts[partId]; part['children'].push(node); node['part']=part; node['position']['t'] = part['rootAngle']; } else { node['position']['t'] = this['rootAngle']; } this.incrementBranchWeight(); this.updateChildren(); return node; }; /* * Updates target positions for a set of child nodes any time the set * of child nodes changes. */ this.updateChildren___ = function() { // for each child node, calculate a new target for ( var i=0; i<this['children'].length; i++ ) { var angle; var node = this['children'][i]; part=node['part']; if (part==null) { // If there's only one child, it's target angle is the angle of entry of // it's parent's "parent edge". nb=this['children'].length; fa=this['fanAngle']; ra=this['rootAngle']; pos=i; id="none"; } else { nb=part['children']; fa=part['fanAngle']; ra=part['rootAngle']; pos=i; id=part['id']; } // alert("nb:"+nb+" pos:"+pos+" fa:"+fa+" ra:"+ra+" id:"+id); if ( nb == 1 ) { angle=ra; // Otherwise, it's a function of the number of child nodes and the // fanAngle that has been specified that they must fit in. } else { angle=(pos*fa)/nb + ra - (fa*(nb-1))/(2*nb); //angle=pos*fa/nb+ra; } //angle=pos*(fa/nb)+ra //angle =fa*pos/nb + ra - (fa*(nb-1)/nb/2); node['rootAngle'] = parseInt(angle); node['target']['t'] = angle; node['target']['r'] = this['radius']; node['done'] = false; node.updateChildren(); } }; this.updateChildren=function() { for (key in this['parts']) { part=this['parts'][key]; this.updateChildrenPart(part); } } this.updateChildrenPart = function(part) { // for each child node, calculate a new target for ( var i=0; i<part['children'].length; i++ ) { var angle; var node = part['children'][i]; nb=part['children'].length; fa=part['fanAngle']; ra=part['rootAngle']; pos=i; id=part['id']; // alert("nb:"+nb+" pos:"+pos+" fa:"+fa+" ra:"+ra+" id:"+id); if ( nb == 1 ) { angle=ra; // Otherwise, it's a function of the number of child nodes and the // fanAngle that has been specified that they must fit in. } else { angle=(pos*fa)/nb + ra - (fa*(nb-1))/(2*nb); //angle=pos*fa/nb+ra; } //angle=pos*(fa/nb)+ra //angle =fa*pos/nb + ra - (fa*(nb-1)/nb/2); node['rootAngle'] = parseInt(angle); node['target']['t'] = angle; node['target']['r'] = this['radius']; node['done'] = false; node.updateChildren(); } }; } /** * Distance: * * Calculates distance in for vectors and 2D space. */ var Distance = function( pointA, pointB ) { // X Distance this['dx'] = pointA['x'] - pointB['x']; // Y Distance this['dy'] = pointA['y'] - pointB['y']; this['d2'] = (this['dx']*this['dx']+this['dy']*this['dy']); // Distance this['d'] = Math.sqrt(this['d2']); return this; }; /** * TreeGraphModel: * * Performs positioning on nodes. * * @extends GraphModel */ var TreeGraphModel = function( frameWidth, frameHeight ) { this.initialize( frameWidth, frameHeight ); }; TreeGraphModel.prototype = { // A collection of GraphModelListeners that want to receive updates from this graph subscribers: new Array(), // A collection of root nodes updateQueue: new Array(), // nextUID: 0, // 'fluidity' is a constant that dictates the smoothness of animation. We'll // always make a tradeoff between smoothness and speed. For different graph // applications, different fluidity values will be appropriate. // // In Tree Graphs, 'fluidity' indicates the denominator in a function that dictates // the amount of distance between the current and target angles (ie: (TA-CA)/fluidity) fluidity: 3, // A boolean that indicates whether this graph should stagger node positions for // readability. doStagger: false, staggerPixels: 30, /* * Initialize this instance. * * @overrides GraphModel.initialize */ initialize: function( frameWidth, frameHeight ) { this['frameWidth'] = frameWidth; this['frameHeight'] = frameHeight; // A factor that skews the positions on the graph relative to the dimenions // of the enclosing frame. this['skew'] = frameWidth/frameHeight; }, /* * */ update: function() { var entropy = 0; for ( var i=0; i<this['updateQueue'].length; i++ ) { entropy += this.setChildrenForces( this['updateQueue'][i] ); } return entropy; }, /* * Moves child nodes closer to target. * * TODO: rename ... there are no forces */ setChildrenForces: function( node ) { var count=0; for( var i=0; i<node['children'].length; i++ ) { // Get new angle and radius values for this node var dt = (node['children'][i]['position']['t'] - node['children'][i]['target']['t']); var dr = (node['children'][i]['position']['r'] - node['children'][i]['target']['r']); if ( dt<1 && dr<1 ) { node['children'][i]['done'] = true; } var newAngle = node['children'][i]['position']['t'] - (dt / this['fluidity']); var newRadius = node['children'][i]['position']['r'] - (dr / this['fluidity']); node['children'][i]['position']['t'] = newAngle; node['children'][i]['position']['r'] = newRadius; // Determine if we should stagger var stagger = 0; if ( this['doStagger'] && i % 2 ) { stagger = this['staggerPixels']; } // Set coordinates based on angle and radius node['children'][i]['position']['y'] = node['position']['y'] - (Math.cos(newAngle*(Math.PI/180)) * (node['children'][i]['position']['r']+stagger)); node['children'][i]['position']['x'] = node['position']['x'] - ((Math.sin(newAngle*(Math.PI/180)) * (node['children'][i]['position']['r']+stagger)))*this['skew']; // Tell subscribers to draw nodes. for( var j=0; j<this['subscribers'].length; j++ ) { // TODO: fix this['subscribers'][j].drawNode( node ); this['subscribers'][j].drawNode( node['children'][i] ); } if ( !node['children'][i]['done'] ) { count++; } // this.setChildrenForces( node['children'][i] ); } return( count ); }, /* * Add a new TreeNode. */ addNode: function( radius, fanAngle, startX, startY ) { var node = new TreeNode( this['nextUID']++, radius, fanAngle, startX, startY ); node.initParts(fanAngle); return node; }, /* * Add a new edge. */ addEdge: function( nodeI, nodeJ ) { } } TreeGraphModel.extend(GraphModel);
Ms-Dos/Windows
Unix
Write backup
jsp File Browser version 1.2 by
www.vonloesch.de