📄 data.as
字号:
// sort to group by, then ordering
a.sort(Sort.$(g));
// get property instances for value operations
var p:Array = new Array();
for (i=0; i<len; ++i) {
if (g[i] is String)
p.push(Property.$(g[i]));
}
var f:Property = p[p.length-1];
// connect all items who match on the last group by field
for (i=1; i<a.length; ++i) {
if (!f || f.getValue(a[i-1]) == f.getValue(a[i])) {
if (!ignoreExistingEdges && a[i].isConnected(a[i-1]))
continue;
var e:EdgeSprite = addEdgeFor(a[i-1], a[i], directedEdges);
// add data values from nodes
for (var j:uint=0; j<p.length; ++j) {
p[j].setValue(e, p[j].getValue(a[i]));
}
}
}
}
/**
* Creates a new edge between the given nodes and adds it to the
* data collection.
* @param source the source node (must already be in this data set)
* @param target the target node (must already be in this data set)
* @param directed indicates the directedness of the edge (null to
* use this Data's default, true for directed, false for undirected)
* @param data a data tuple containing data values for the edge
* instance. If non-null, this will become the EdgeSprite's
* <code>data</code> property.
* @return the newly added EdgeSprite
*/
public function addEdgeFor(source:NodeSprite, target:NodeSprite,
directed:Object=null, data:Object=null):EdgeSprite
{
if (!_nodes.contains(source) || !_nodes.contains(target)) {
return null;
}
var d:Boolean = directed==null ? directedEdges : Boolean(directed);
var e:EdgeSprite = newEdge(source, target, d, data);
if (data != null) e.data = data;
source.addOutEdge(e);
target.addInEdge(e);
return addEdge(e);
}
/**
* Internal function for creating a new node. Creates a NodeSprite,
* sets its data property, and applies default values.
* @param data the new node's data property
* @return the newly created node
*/
protected function newNode(data:Object):NodeSprite
{
var ns:NodeSprite = new NodeSprite();
_nodes.applyDefaults(ns);
if (data != null) { ns.data = data; }
return ns;
}
/**
* Internal function for creating a new edge. Creates an EdgeSprite,
* sets its data property, and applies default values.
* @param s the source node
* @param t the target node
* @param d the edge's directedness
* @param data the new edge's data property
* @return the newly created node
*/
protected function newEdge(s:NodeSprite, t:NodeSprite,
d:Boolean, data:Object):EdgeSprite
{
var es:EdgeSprite = new EdgeSprite(s,t,d);
_edges.applyDefaults(es);
if (data != null) { es.data = data; }
return es;
}
// -- Remove -------------------------------------------
/**
* Clears this data set, removing all nodes and edges.
*/
public function clear():void
{
_edges.clear();
_nodes.clear();
for (var name:String in _groups) {
_groups[name].clear();
}
}
/**
* Removes a DataSprite (node or edge) from this data collection.
* @param d the DataSprite to remove
* @return true if removed successfully, false if not found
*/
public function remove(d:DataSprite):Boolean
{
if (d is NodeSprite) return removeNode(d as NodeSprite);
if (d is EdgeSprite) return removeEdge(d as EdgeSprite);
return false;
}
/**
* Removes a node from this data set. All edges incident on this
* node will also be removed. If the node is not found in this
* data set, the method returns null.
* @param n the node to remove
* @returns true if sucessfully removed, false if not found in the data
*/
public function removeNode(n:NodeSprite):Boolean
{
return _nodes.remove(n);
}
/**
* Removes an edge from this data set. The nodes connected to
* this edge will have the edge removed from their edge lists.
* @param e the edge to remove
* @returns true if sucessfully removed, false if not found in the data
*/
public function removeEdge(e:EdgeSprite):Boolean
{
return _edges.remove(e);
}
// -- Events -------------------------------------------
/** @private */
protected function onAddNode(evt:DataEvent):void
{
for each (var d:DataSprite in evt.items) {
var n:NodeSprite = d as NodeSprite;
if (!n) {
evt.preventDefault();
return;
}
}
fireEvent(evt);
}
/** @private */
protected function onRemoveNode(evt:DataEvent):void
{
for each (var n:NodeSprite in evt.items) {
for (var i:uint=n.outDegree; --i>=0;)
removeEdge(n.getOutEdge(i));
for (i=n.inDegree; --i>=0;)
removeEdge(n.getInEdge(i));
}
fireEvent(evt);
}
/** @private */
protected function onAddEdge(evt:DataEvent):void
{
for each (var d:DataSprite in evt.items) {
var e:EdgeSprite = d as EdgeSprite;
if (!(e && _nodes.contains(e.source)
&& _nodes.contains(e.target)))
{
evt.preventDefault();
return;
}
}
fireEvent(evt);
}
/** @private */
protected function onRemoveEdge(evt:DataEvent):void
{
for each (var e:EdgeSprite in evt.items) {
e.source.removeOutEdge(e);
e.target.removeInEdge(e);
}
fireEvent(evt);
}
/** @private */
protected function fireEvent(evt:DataEvent):void
{
// reset the spanning tree on adds and removals
if (evt.type != DataEvent.UPDATE)
_tree = null;
// fire event, if anyone is listening
if (hasEventListener(evt.type)) {
dispatchEvent(evt);
}
}
// -- Visitors -----------------------------------------
/**
* Visit items, invoking a function on all visited elements.
* @param v the function to invoke on each element. If the function
* return true, the visitation is ended with an early exit
* @param group the data group to visit (e.g., NODES or EDGES). If this
* value is null, both nodes and edges will be visited.
* @param filter an optional predicate function indicating which
* elements should be visited. Only items for which this function
* returns true will be visited.
* @param reverse an optional parameter indicating if the visitation
* traversal should be done in reverse (the default is false).
* @return true if the visitation was interrupted with an early exit
*/
public function visit(v:Function, group:String=null,
filter:*=null, reverse:Boolean=false):Boolean
{
if (group == null) {
if (_edges.length > 0 && _edges.visit(v, filter, reverse))
return true;
if (_nodes.length > 0 && _nodes.visit(v, filter, reverse))
return true;
} else {
var list:DataList = _groups[group];
if (list.length > 0 && list.visit(v, filter, reverse))
return true;
}
return false;
}
// -- Spanning Tree ---------------------------------------------------
/** The spanning tree constructor class. */
protected var _span:TreeBuilder = new TreeBuilder();
/** The root node of the spanning tree. */
protected var _root:NodeSprite = null;
/** The the spanning tree. */
protected var _tree:Tree = null;
/** The spanning tree creation policy.
* @see flare.analytics.graph.SpanningTree */
public function get treePolicy():String { return _span.policy; }
public function set treePolicy(p:String):void {
if (_span.policy != p) {
_span.policy = p;
_tree = null;
}
}
/** The edge weight function for computing a minimum spanning tree.
* This function will only have an effect if the
* <code>treePolicy</code> is
* <code>SpanningTree.MINIMUM_SPAN</code> */
public function get treeEdgeWeight():Function {
return (_span ? _span.edgeWeight : null);
}
public function set treeEdgeWeight(w:*):void {
_span.edgeWeight = w;
}
/** The root node of the spanning tree. */
public function get root():NodeSprite { return _root; }
public function set root(n:NodeSprite):void {
if (n != null && !_nodes.contains(n))
throw new ArgumentError("Spanning tree root must be within the graph.");
if (_root != n) {
_tree = null;
_span.root = (_root = n);
}
}
/**
* A spanning tree for this graph. The spanning tree generated is
* determined by the <code>root</code>, <code>treePolicy</code>,
* and <code>treeEdgeWeight</code> properties. By default, the tree
* is built using a breadth-first spanning tree using the first node
* in the graph as the root.
*/
public function get tree():Tree
{
if (_tree == null) { // build tree if necessary
if (_root == null) _span.root = _nodes[0];
_span.calculate(this, _span.root);
_tree = _span.tree;
}
return _tree;
}
public function set tree(t:Tree):void
{
if (t==null) { _tree = null; return; }
var ok:Boolean;
ok = t.root.visitTreeDepthFirst(function(n:NodeSprite):Boolean {
return _nodes.contains(n);
});
if (ok) _tree = t;
}
} // end of class Data
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -