如何从Java的字符串列表中绘制平面图来绘制游戏的世界地图

时间:2018-07-10 18:52:20

标签: java graph jung planar-graph

基本上,我有一款游戏,其中有一张涵盖116个地区的大地图。每个地区都有一个名称,其他一些属性以及带有其邻居名称的关联String []。并非每个区域都相互连接(我认为一个区域至少有1个连接,最多9个连接)。

因此,将区域像图形一样绘制将产生平面图。我尝试使用JUNG库(根据本网站和其他网站的建议)来执行此操作,但是它们所使用的每个布局算法都只会导致图形中包含许多交叉边缘,而这正是我要避免的。在我的代码下面(再次,Territory类具有name属性,其邻居的名称具有String []。传递给该方法的地图将领土的名称作为关键字)。

所以我的问题是:是否可以使用布局算法从区域地图上绘制平面图?我应该使用另一个库?我可以遵循的教程吗?预先感谢大家!

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);
}'

(使用JUNG库,我的进口货清单:

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;

game.getID()方法是我在另一个类中编写的一种方法,用于将颜色(与区域相关联的颜色,灰色,橙色,品红色或蓝色)转换为整数。顶点也应该是我的代码实际上完成的那种颜色!

我尝试使用以下布局:KKLayout,FRLayout,SpringLayout,ISOMLayout,CircleLayout。

1 个答案:

答案 0 :(得分:0)

这里有两种情况:

  1. 您拥有115个领土的实际(地理)地图,或者
  2. 您只是拥有它们之间的边界关系(也就是说,您所知道的是哪个领土与其他领土接壤)。

在第一种情况下,您可以根据区域的位置来布局:为每个区域选择一个点,并创建一个具有该位置的节点。您可以使用StaticLayout指定已知的节点位置。 WorldMapGraphDemo中有一个示例。

在第2种情况下,取决于图形的生成方式,您可能实际上并不确定它是平面的。您尚未说明如何知道。如果不确定,可以使用以下算法之一进行测试:https://en.wikipedia.org/wiki/Planarity_testing

如果您发现图形确实是平面的,并且JUNG布局算法没有帮助您,那么我没有任何直接建议。通常,在图形布局中避免边缘交叉是NP-hard problem,并且这些算法都没有尝试直接解决它。