|
|
|
@ -78,31 +78,48 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout |
|
|
|
|
|
|
|
|
|
|
|
void CalculateLayout(PositionedGraph positionedGraph) |
|
|
|
void CalculateLayout(PositionedGraph positionedGraph) |
|
|
|
{ |
|
|
|
{ |
|
|
|
HashSet<PositionedNode> seenNodes = new HashSet<PositionedNode>(); |
|
|
|
// impose a tree structure on the graph
|
|
|
|
HashSet<PositionedEdge> treeEdges = new HashSet<PositionedEdge>(); |
|
|
|
HashSet<PositionedEdge> treeEdges = DetermineTreeEdges(positionedGraph.Root); |
|
|
|
// first layout pass
|
|
|
|
// first layout pass
|
|
|
|
CalculateSubtreeSizes(positionedGraph.Root, seenNodes, treeEdges); |
|
|
|
CalculateSubtreeSizesRecursive(positionedGraph.Root, treeEdges); |
|
|
|
// second layout pass
|
|
|
|
// second layout pass
|
|
|
|
CalculateNodePosRecursive(positionedGraph.Root, treeEdges, MarginTop, MarginBottom); |
|
|
|
CalculateNodePosRecursive(positionedGraph.Root, treeEdges, MarginTop, MarginBottom); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// determines which edges are tree edges, and calculates subtree size for each node
|
|
|
|
|
|
|
|
private void CalculateSubtreeSizes(PositionedNode root, HashSet<PositionedNode> seenNodes, HashSet<PositionedEdge> treeEdges) |
|
|
|
HashSet<PositionedEdge> DetermineTreeEdges(PositionedNode root) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
var treeEdges = new HashSet<PositionedEdge>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var seenNodes = new HashSet<PositionedNode>(); |
|
|
|
|
|
|
|
var q = new Queue<PositionedNode>(); |
|
|
|
|
|
|
|
q.Enqueue(root); |
|
|
|
seenNodes.Add(root); |
|
|
|
seenNodes.Add(root); |
|
|
|
double subtreeSize = 0; |
|
|
|
|
|
|
|
foreach (var property in root.Properties) { |
|
|
|
while (q.Count > 0) { |
|
|
|
var edge = property.Edge; |
|
|
|
var node = q.Dequeue(); |
|
|
|
if (edge != null) { |
|
|
|
foreach (var property in node.Properties) { |
|
|
|
var targetNode = edge.Target; |
|
|
|
var edge = property.Edge; |
|
|
|
if (!seenNodes.Contains(targetNode)) { |
|
|
|
if (edge != null && edge.Target != null) { |
|
|
|
// when we come to a node for the first time, we declare the incoming edge a tree edge
|
|
|
|
if (!seenNodes.Contains(edge.Target)) { |
|
|
|
treeEdges.Add(edge); |
|
|
|
treeEdges.Add(edge); |
|
|
|
CalculateSubtreeSizes(targetNode, seenNodes, treeEdges); |
|
|
|
seenNodes.Add(edge.Target); |
|
|
|
subtreeSize += targetNode.SubtreeSize; |
|
|
|
q.Enqueue(edge.Target); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return treeEdges; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CalculateSubtreeSizesRecursive(PositionedNode root, HashSet<PositionedEdge> treeEdges) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double subtreeSize = 0; |
|
|
|
|
|
|
|
foreach (var child in TreeChildNodes(root, treeEdges)) { |
|
|
|
|
|
|
|
CalculateSubtreeSizesRecursive(child, treeEdges); |
|
|
|
|
|
|
|
// just sum up the sizes of children
|
|
|
|
|
|
|
|
subtreeSize += child.SubtreeSize; |
|
|
|
|
|
|
|
} |
|
|
|
root.SubtreeSize = Math.Max(GetLateralSizeWithMargin(root), subtreeSize); |
|
|
|
root.SubtreeSize = Math.Max(GetLateralSizeWithMargin(root), subtreeSize); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|