Skip to content

Commit 2a93677

Browse files
committed
Manage edge multiplicity indices to keep parallel edges as "tight" as possible.
1 parent c87744e commit 2a93677

3 files changed

Lines changed: 84 additions & 11 deletions

File tree

src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphEdgeBase.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public interface SmartGraphEdgeBase<E, V> extends SmartGraphEdge<E, V>, SmartLab
6363
*/
6464
int getMultiplicityIndex();
6565

66+
void setMultiplicityIndex(int multiplicityIndex);
67+
6668
/**
6769
* Returns the inbound vertex of the edge.
6870
* @return the inbound vertex of the edge.

src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphEdgeNode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ public int getMultiplicityIndex() {
145145
return multiplicityIndex;
146146
}
147147

148+
@Override
149+
public void setMultiplicityIndex(int multiplicityIndex) {
150+
Args.requireNonNegative(multiplicityIndex, "multiplicityIndex");
151+
152+
this.multiplicityIndex = multiplicityIndex;
153+
154+
update();
155+
}
156+
148157
@Override
149158
public SmartGraphVertexNode<V> getInbound() {
150159
return inbound;

src/main/java/com/brunomnsilva/smartgraph/graphview/SmartGraphPanel.java

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ public class SmartGraphPanel<V, E> extends Pane {
9292
private final Map<Vertex<V>, SmartGraphVertexNode<V>> vertexNodes;
9393
private final Map<Edge<E, V>, SmartGraphEdgeBase<E, V>> edgeNodes;
9494
private final Map<Edge<E,V>, Tuple<Vertex<V>>> connections;
95-
private final Map<Tuple<SmartGraphVertexNode<V>>, Integer> placedEdges = new HashMap<>();
9695
private boolean initialized = false;
9796
private final boolean edgesWithArrows;
9897

@@ -166,7 +165,10 @@ public SmartGraphPanel(@NamedArg("graph") Graph<V, E> theGraph,
166165

167166
this.vertexNodes = new HashMap<>();
168167
this.edgeNodes = new HashMap<>();
169-
this.connections = new HashMap<>();
168+
169+
// We will explore the insertion order of edges for decreasing the multiplicity of edges between the same
170+
// pair of vertices, when others are removed
171+
this.connections = new LinkedHashMap<>();
170172

171173
// consumers initially are not set. This initialization is not necessary, but we make it explicit
172174
// for the sake of readability
@@ -662,12 +664,16 @@ private SmartGraphEdgeBase<E,V> createEdge(Edge<E, V> edge, SmartGraphVertexNode
662664
/*
663665
Edges will be placed with 'multiplicityIndex' starting at 0 for a single edge between a pair of vertices. This represents a straight edge.
664666
When more than an edge exists, the 'multiplicityIndex' will start at 1, forcing the edges to be curved.
667+
668+
Newer edges have higher multiplicity indices.
669+
670+
Note that, indirectly, multiplicity indices will be "recycled", since they are updated (decremented) when edges are removed.
671+
This is performed in 'updateParallelEdgesOf(edge)'.
665672
*/
666673

667674
int maxIndex = getMaxMultiplicityIndexBetween(graphVertexInbound, graphVertexOutbound);
668675

669676
return new SmartGraphEdgeNode<>(edge, graphVertexInbound, graphVertexOutbound, ++maxIndex);
670-
671677
}
672678

673679
private void addVertex(SmartGraphVertexNode<V> v) {
@@ -836,6 +842,9 @@ private void removeNodes() {
836842
}
837843

838844
connections.remove(e);
845+
846+
// Update the multiplicity of the edges between the removed edge connecting vertices
847+
updateParallelEdgesOf(edgeToRemove);
839848
}
840849

841850
//remove vertices (graphical elements) that were removed from the underlying graph
@@ -861,6 +870,45 @@ private void removeEdge(SmartGraphEdgeBase<E,V> e) {
861870
}
862871
}
863872

873+
/*
874+
* Update the multiplicity of the parallel edges of 'e'.
875+
* This is called from removeNodes(), after an edge is removed. Hence, 'e'
876+
* will be a removed edge. We want to update the multiplicities of the remaining
877+
* edges that still subsist after this one is removed.
878+
*
879+
* This work
880+
*/
881+
private void updateParallelEdgesOf(SmartGraphEdgeBase<E,V> e) {
882+
883+
SmartGraphVertexNode<V> v = e.getInbound();
884+
SmartGraphVertexNode<V> w = e.getOutbound();
885+
886+
// 'getEdgesBetween' returns a collection of ages, ordered by their "age".
887+
List<SmartGraphEdgeBase<E, V>> parallelEdges = getEdgesBetween(v, w);
888+
889+
int numEdges = parallelEdges.size();
890+
if(numEdges > 0) {
891+
892+
// Oldest edge will always have multiplicity 0 (straight line)
893+
parallelEdges.get(0).setMultiplicityIndex(0);
894+
895+
// The remaining edges will have their multiplicities as close to 0 has possible,
896+
// while maintaining their parity (same side of the line axis)
897+
int current = 1;
898+
for (int i = 1; i < numEdges; i++) {
899+
int parity = parallelEdges.get(i).getMultiplicityIndex() % 2;
900+
901+
while (current % 2 != parity) {
902+
current++;
903+
}
904+
905+
parallelEdges.get(i).setMultiplicityIndex(current);
906+
current++; // Move to the next possible value
907+
}
908+
}
909+
910+
}
911+
864912
private void removeVertex(SmartGraphVertexNode<V> v) {
865913
getChildren().remove(v);
866914

@@ -1078,25 +1126,39 @@ private int getTotalEdgesBetweenInModel(Vertex<V> v, Vertex<V> u) {
10781126
return count;
10791127
}
10801128

1081-
/*private int getTotalEdgesBetweenInPanel(SmartGraphVertexNode<V> v, SmartGraphVertexNode<V> u) {
1129+
/**
1130+
* Returns the edges between 'v' and 'u', by "age", starting with the "oldest".
1131+
* This is achieved because we use a LinkedHashMap for the 'connections' collection.
1132+
* The order of 'u' and 'v' is irrelevant.
1133+
*
1134+
* @param v first vertex
1135+
* @param u second vertex
1136+
* @return an ordered (by age) list of edges that exist between 'u' and 'v'
1137+
*/
1138+
private List<SmartGraphEdgeBase<E, V>> getEdgesBetween(SmartGraphVertexNode<V> v, SmartGraphVertexNode<V> u) {
10821139
Vertex<V> V = v.getUnderlyingVertex();
10831140
Vertex<V> U = u.getUnderlyingVertex();
10841141

1085-
int count = 0;
1142+
List<SmartGraphEdgeBase<E, V>> parallelEdges = new ArrayList<>();
1143+
10861144
for (Map.Entry<Edge<E, V>, Tuple<Vertex<V>>> edgeTupleEntry : this.connections.entrySet()) {
1087-
//Edge<E, V> edge = edgeTupleEntry.getKey();
1145+
Edge<E, V> edge = edgeTupleEntry.getKey();
10881146
Tuple<Vertex<V>> tuple = edgeTupleEntry.getValue();
10891147

10901148
if ((tuple.first == V && tuple.second == U) || (tuple.first == U && tuple.second == V)) {
1091-
count++;
1149+
parallelEdges.add( edgeNodes.get(edge) );
10921150
}
10931151
}
10941152

1095-
return count;
1096-
}*/
1153+
return parallelEdges;
1154+
}
10971155

1098-
/*
1099-
* Finds the maximum multiplicity index for current edges between two vertices.
1156+
/**
1157+
* Finds the maximum multiplicity index for current edges between two vertices 'v' and 'u'.
1158+
* The order of 'v' and 'u' is irrelevant.
1159+
* @param v first vertex
1160+
* @param u second vertex
1161+
* @return the maximum multiplicity index for current edges between two vertices 'v' and 'u'
11001162
*/
11011163
private int getMaxMultiplicityIndexBetween(SmartGraphVertexNode<V> v, SmartGraphVertexNode<V> u) {
11021164
int max = -1;

0 commit comments

Comments
 (0)