Skip to content
This repository has been archived by the owner on Nov 13, 2020. It is now read-only.

Fix issue #71 (endless loop in mxHierarchicalLayout) #72

Merged
merged 1 commit into from May 28, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
56 changes: 49 additions & 7 deletions src/com/mxgraph/layout/hierarchical/mxHierarchicalLayout.java
Expand Up @@ -20,6 +20,7 @@
import com.mxgraph.layout.hierarchical.stage.mxHierarchicalLayoutStage;
import com.mxgraph.layout.hierarchical.stage.mxMedianHybridCrossingReduction;
import com.mxgraph.layout.hierarchical.stage.mxMinimumCycleRemover;
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.view.mxCellState;
Expand Down Expand Up @@ -409,13 +410,22 @@ public Set<Object> filterDescendants(Object cell)
for (int i = 0; i < childCount; i++)
{
Object child = model.getChildAt(cell, i);
result.addAll(filterDescendants(child));

// Ignore ports in the layout vertex list, they are dealt with
// in the traversal mechanisms
Comment on lines +414 to +415
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space indents should be tabs

if (!isPort((mxCell) child)) {
result.addAll(filterDescendants(child));
}
}
}

return result;
}

private boolean isPort(mxCell cell) {
return cell.getGeometry().isRelative();
}

/**
* Traverses the (directed) graph invoking the given function for each
* visited vertex and edge. The function is invoked with the current vertex
Expand Down Expand Up @@ -456,19 +466,51 @@ protected void traverse(Object vertex, boolean directed, Object edge,

int edgeCount = model.getEdgeCount(vertex);

boolean[] edgeIsSource = new boolean[edgeCount];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a comment like: "// caching for performance reasons"

if (edgeCount > 0) {
for (int i = 0; i < edgeCount; i++) {
Object e = model.getEdgeAt(vertex, i);
edgeIsSource[i] = view.getVisibleTerminal(e, true) == vertex;
}
}

if (edgeCount > 0)
{
for (int i = 0; i < edgeCount; i++)
{
Object e = model.getEdgeAt(vertex, i);
boolean isSource = view.getVisibleTerminal(e, true) == vertex;

if (!directed || isSource)
if (!directed || edgeIsSource[i])
{
Object next = view.getVisibleTerminal(e, !isSource);
traverse(next, directed, e, allVertices,
currentComp, hierarchyVertices,
filledVertexSet);
Object next = view.getVisibleTerminal(e, !edgeIsSource[i]);

// Check whether there are more edges incoming from the target vertex than outgoing
// The hierarchical model treats bi-directional parallel edges as being sourced
// from the more "sourced" terminal. If the directions are equal in number, the direction
// is that of the natural direction from the roots of the layout.
// The checks below are slightly more verbose than need be for performance reasons
Comment on lines +487 to +491
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space indents should be tabs

int netCount = 1;

for (int j = 0; j < edgeCount; j++) {
if (j != i) {
boolean isSorce2 = edgeIsSource[j];
Object e2 = model.getEdgeAt(vertex, j);
Object otherTerm = view.getVisibleTerminal(e2, !isSorce2);
if (otherTerm == next) {
if (isSorce2) {
netCount++;
} else {
netCount--;
}
}
}
}

if (netCount >= 0){
traverse(next, directed, e, allVertices,
currentComp, hierarchyVertices,
filledVertexSet);
}
}
}
}
Expand Down