public override void Compute(CircleNodeScene scene) { this.mAlg = new BCCAlgorithm <CircleNode, ArrowEdge>( scene.Graph, this.Reversed); this.mAlg.Compute(); Digraph <CircleNode, ArrowEdge> .GEdge[] comp; Digraph <CircleNode, ArrowEdge> .GEdge[][] comps = this.mAlg.Components; int i, j, sC = sLineColors.Length; for (i = 0; i < comps.Length; i++) { comp = comps[i]; for (j = 0; j < comp.Length; j++) { comp[j].Data.LineColor = sLineColors[i % sC]; } } Digraph <CircleNode, ArrowEdge> .GNode[] nodes = this.mAlg.ArticulationNodes; for (i = 0; i < nodes.Length; i++) { nodes[i].Data.MarkerColor = sLineColors[0]; } this.mAlg.ArticulateToLargerCompactGroups(); Digraph <CircleNode, ArrowEdge> .GNode[][] cGrps = this.mAlg.CompactGroups; for (i = 0; i < cGrps.Length; i++) { nodes = cGrps[i]; for (j = 0; j < nodes.Length; j++) { nodes[j].Data.BorderColor = sLineColors[i % sC]; } } }
// Possible force-directed generalized three stage process: // 1. Calculate layout of Digraph<BCCNode, BCCEdge> // 2. In each BCCNode, for each edge connecting a node // in that BCCNode to another BCCNode or outside Node, // create a "port", which is a temporary node pinned on the // outside rim of the BCCNode at the angle of the BCCEdge // containing the edge connecting it to an outside BCCNode/Node // 3. Calculate the layout of graphs in each BCCNode // and then remove the temporary "port" nodes and edges. // Perhaps "port" nodes might not even need to be temporary, // since the sub-graphs are created on-the-fly for the layout only. // Perhaps generalize to a three stage process: // 1. Calculate layout of graphs in each BCCNode // 2. Calculate layout of quasi-graphs in each BCCEdge; // Perhaps special rules for edges connecting Nodes to BCCNodes? // 3. Calculate layout of Digraph<BCCNode, BCCEdge> // Perhaps effects as follows // 1. Position of each Node | Size of each BCCNode // 2. Position of each Node | Position? of each BCCNode // 3. Position of each BCCNode private static Digraph <BCCNode, BCCEdge> BCCCompactGraph( Digraph <Node, Edge> graph) { int i, j; Digraph <Node, Edge> .GNode[] nodes = graph.InternalNodes; Digraph <Node, Edge> .GEdge[] edges = graph.InternalEdges; BCCAlgorithm <Node, Edge> bccAlg = new BCCAlgorithm <Node, Edge>(graph, false); bccAlg.Compute(); bccAlg.ArticulateToLargerCompactGroups(); Digraph <Node, Edge> .GNode[][] bccGroups = bccAlg.CompactGroups; int bccGroupCount = bccAlg.CompactGroupCount; int[] bccGroupIds = bccAlg.CompactGroupIds; Digraph <BCCNode, BCCEdge> bccGraph = new Digraph <BCCNode, BCCEdge>( bccGroupCount, bccGroupCount / 2); PortNode[][] portNodes = new PortNode[bccGroupCount][]; BCCEdge[][] bccEdges = new BCCEdge[bccGroupCount][]; BCCNode[] bccNodes = new BCCNode[bccGroupCount]; BCCNode bccNode; Digraph <Node, Edge> .GNode[] bccGroup; for (i = 0; i < bccGroupCount; i++) { bccGroup = bccGroups[i]; bccNode = new BCCNode(i, bccGroup.Length, nodes.Length); for (j = 0; j < bccGroup.Length; j++) { bccNode.Subgraph.AddNode(bccGroup[j].Data); } bccGraph.AddNode(bccNode); bccNodes[i] = bccNode; bccEdges[i] = new BCCEdge[bccGroupCount]; portNodes[i] = new PortNode[nodes.Length]; } int si, di; Digraph <Node, Edge> .GEdge edge; BCCEdge bccEdge; PortNode spn, dpn; for (i = 0; i < edges.Length; i++) { edge = edges[i]; si = bccGroupIds[edge.SrcNode.Index]; di = bccGroupIds[edge.DstNode.Index]; if (si == di) { bccNodes[si].Subgraph.AddEdge(new SubEdge( edge.SrcNode.Data, edge.DstNode.Data, edge.Data)); } else { bccEdge = bccEdges[si][di]; if (bccEdge == null) { bccEdge = new BCCEdge(bccNodes[si], bccNodes[di]); bccGraph.AddEdge(bccEdge); bccEdges[si][di] = bccEdge; } //spn = bccNodes[di].PortNodes[dEdge.mSrcNode.Index]; spn = portNodes[di][edge.SrcNode.Index]; if (spn == null) { spn = new PortNode(edge.SrcNode.Data, si); bccNodes[di].Subgraph.AddNode(spn); //bccNodes[di].PortNodes[dEdge.mSrcNode.Index] = spn; portNodes[di][edge.SrcNode.Index] = spn; bccEdge.AddDstPort(spn); } bccNodes[di].Subgraph.AddEdge(new SubEdge( spn, edge.DstNode.Data, edge.Data)); //dpn = bccNodes[si].PortNodes[edge.mDstNode.Index]; dpn = portNodes[si][edge.DstNode.Index]; if (dpn == null) { dpn = new PortNode(edge.DstNode.Data, di); bccNodes[si].Subgraph.AddNode(dpn); //bccNodes[si].PortNodes[dEdge.mDstNode.Index] = dpn; portNodes[si][edge.DstNode.Index] = dpn; bccEdge.AddSrcPort(dpn); } bccNodes[si].Subgraph.AddEdge(new SubEdge( edge.SrcNode.Data, dpn, edge.Data)); } } return(bccGraph); }