Basically, I have a game that has a big map existing out of 116 territories. Each territory has a name, some other properties and also an associated String[] with the names of its neighbour. Not every territory is connected to eachother ( I think a territory has atleast 1 connection and at most 9 connections).
So, drawing the territories like a graph should result in a planar graph. I tried using the JUNG library (as adviced on this site and on others) to do so, but every layout-algorithm they have just results in a graph that has a lot of crossing edges, which is exactly what I want to avoid. Below my code (once again the Territory class has a name property and a String[] of its neighbours' names. The map passed into the method has as key the name of the territory).
So my question is: is there a layout algoritm I can use to draw a planar graph from the territory map? Another library I should use? A tutorial I could follow? Thanks in advance guys!
public static void drawMap(Map<String, Territory> allTerritories) {
// TODO Auto-generated constructor stub
DirectedSparseGraph<String, String> g = new DirectedSparseGraph<>();
Game game = new Game();
int counter = 0;
for (Territory t : allTerritories.values()) {
g.addVertex(t.getName() + "(" + game.getID(t.getColor()) + ")");
for (String s : t.getNeighbours()) {
Territory neighbour = allTerritories.get(s);
g.addEdge("Edge" + counter, t.getName() + "(" + game.getID(t.getColor()) + ")",
s + "(" + game.getID(neighbour.getColor()) + ")");
counter++;
}
}
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = screenSize.width;
int height = screenSize.height;
// KKLayout does a sort of good job
CircleLayout<String, String> layout = new CircleLayout<String, String>(g);
VisualizationImageServer<String, String> vv = new VisualizationImageServer<String, String>(layout,
new Dimension(width, height));
Function<String, String> transformer = new Function<String, String>() {
@Override
public String apply(String arg0) {
if (arg0.contains("-1")) {
String noNumber = arg0.replace(arg0.substring(arg0.length() - 4), "");
return noNumber;
} else {
String noNumber = arg0.replace(arg0.substring(arg0.length() - 3), "");
return noNumber;
}
}
};
vv.getRenderContext().setVertexLabelTransformer((Function<? super String, String>) transformer);
vv.getRenderer().setVertexRenderer(new MyRenderer());
// The following code adds capability for mouse picking of
// vertices/edges. Vertices can even be moved!
JFrame frame = new JFrame();
frame.getContentPane().add(vv);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}'
(Using the JUNG library, list of my imports:
import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationImageServer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.geom.Point2D;
import java.util.Map;
import javax.swing.JFrame;
The game.getID() method is a method I wrote in another class to convert a color (associated with a territory, its either gray, orange, magenta or blue) into an integer. The vertexes should also be in that color, which my code actually accomplishes!
I tried using the following layouts: KKLayout, FRLayout, SpringLayout, ISOMLayout, CircleLayout.