Closed kristofsmits closed 2 years ago
Thanks for your interest! Are you mainly interested in the layout algorithms and not necessarily rendering them in the visualization? Is there another reason you want headless mode? Let me know.
Some of the layout algorithms spawn a new thread (by default) to do the work. If you access locations before the thread has completed its work, you will get an empty set. You can run the layout algorithm with threaded=false so that it will not spawn a thread. It will block until the layout is done. Here is an example of just getting locations. I also included the call to get the edge articulations (where they bend) from the layout algorithm. You asked about Sugiyama layout, but you may also want to consider the EiglspergerLayoutAlgorithm. It will give you fewer edge articulations. To use it instead, just do this below:
EiglspergerLayoutAlgorithm<Integer, Integer> layoutAlgorithm =
EiglspergerLayoutAlgorithm.<Integer, Integer>edgeAwareBuilder()
.threaded(false)
.layering(Layering.TOP_DOWN)
.build();`
package org.jungrapht.samples.sugiyama;
import org.jgrapht.Graph; import org.jgrapht.graph.builder.GraphTypeBuilder; import org.jgrapht.util.SupplierUtil; import org.jungrapht.visualization.layout.algorithms.SugiyamaLayoutAlgorithm; import org.jungrapht.visualization.layout.algorithms.sugiyama.Layering; import org.jungrapht.visualization.layout.model.LayoutModel;
import java.util.stream.IntStream; public class SugiyamaLayoutPoints {
public SugiyamaLayoutPoints() {
Graph<Integer, Integer> graph = createInitialGraph();
SugiyamaLayoutAlgorithm<Integer, Integer> layoutAlgorithm =
SugiyamaLayoutAlgorithm.<Integer, Integer>edgeAwareBuilder()
.threaded(false). // don't spawn a thread
.layering(Layering.TOP_DOWN)
.build();
LayoutModel<Integer> layoutModel = LayoutModel.<Integer>builder().size(100, 100).graph(graph).build();
layoutAlgorithm.visit(layoutModel);
System.err.println("locations of vertices: "+layoutModel.getLocations());
graph.edgeSet().stream().map(e -> "e:" + e + ", articulations: " + layoutAlgorithm.getEdgeArticulationFunction().apply(e)).forEach(System.err::println);
}
Graph<Integer, Integer> createInitialGraph() {
Graph<Integer, Integer> graph =
GraphTypeBuilder.<Integer, Integer>directed()
.edgeSupplier(SupplierUtil.createIntegerSupplier())
.vertexSupplier(SupplierUtil.createIntegerSupplier())
.buildGraph();
IntStream.rangeClosed(1, 23).forEach(graph::addVertex);
graph.addEdge(1, 3);
graph.addEdge(1, 4);
graph.addEdge(1, 13);
graph.addEdge(1, 21);
graph.addEdge(2, 3);
graph.addEdge(2, 20);
graph.addEdge(3, 4);
graph.addEdge(3, 5);
graph.addEdge(3, 23);
graph.addEdge(4, 6);
graph.addEdge(5, 7);
graph.addEdge(6, 8);
graph.addEdge(6, 16);
graph.addEdge(6, 23);
graph.addEdge(7, 9);
graph.addEdge(8, 10);
graph.addEdge(8, 11);
graph.addEdge(9, 12);
graph.addEdge(10, 13);
graph.addEdge(10, 14);
graph.addEdge(10, 15);
graph.addEdge(11, 15);
graph.addEdge(11, 16);
graph.addEdge(12, 20);
graph.addEdge(13, 17);
graph.addEdge(14, 17);
graph.addEdge(14, 18);
// no 15 targets
graph.addEdge(16, 18);
graph.addEdge(16, 19);
graph.addEdge(16, 20);
graph.addEdge(18, 21);
graph.addEdge(19, 22);
graph.addEdge(21, 23);
graph.addEdge(22, 23);
return graph;
}
public static void main(String[] args) { new SugiyamaLayoutPoints(); } }
Thanks for the quick reply! I'm indeed only interested in the layout, and not in the rendering. I completely overlooked the thread option. When I set it to false, it now works without the use of the VisualisationViewer, and in headless mode, great. So not a bug, but just a feature I didn't notice.
Thanks for the EiglspergerLayoutAlgorithm tip, keep up the good work!
Hi,
First off all : great library, love it!
If I apply the TidierTree algorithm (layoutAlgorithm = TidierTreeLayoutAlgorithm), following piece of code works fine, and all locations are calculated
But if I use the same code for Sugiyama ((layoutAlgorithm = SugiyamaLayoutAlgorithm) or some other layout algorithms, then the locations list is empty, no locations are calculated
Based on the sample code, I managed to fix this by changing the code into
So in theory this works fine now, but the annoying thing is that VisualizationViewer requires to run with headless mode = false (even if there is no interaction with UI, keyboard, etc)
The reason why the VisualizationViewer cannot run in headless mode, is that
Maybe I overlook something, but it would be great if the Sugiyama algorithm would just work without using VisualizationViewer, or if VisualizationViewer or DefaultGraphMouse would work in a non-headless mode.
Thanks for your reaction and keep up the good work!