More readable graph in GraphStream - JAVA

2019-07-23 17:47发布

问题:

I am working on application by using GraphStream Library. So far I have implemented Dijkstra's Shortest Path Algorithm. My graph is working fine but the readability of graph is not what I was expecting. Here is the screen shot of graph :

As you can see that graph is not readable due to alot of edge crossing. Is there any way to make my graph more readable. I am studying Graph Stream Generators BUT I dont think that they will be best in my case. So I am looking for accurate solution to my problem. In the above figure the graph is 70% readble BUT there can be more nodes and more edges, In that case graph is totally unreadable. Here is my code till now for you guys to have an idea, What I am doing.

public class GraphTest {

    Connection conn = null;
    SingleGraph graph;
    Statement stmt = null;
    JLabel label;
    JButton show_graph;
    JTextField enter_numbers;
    int i = 0;
    double zoomLevel = 1.0;
    String result, result2;
    ImageIcon loading;

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        GraphTest graphTest = new GraphTest();
        graphTest.createConnection();
    }

    public GraphTest() throws SQLException {
        JFrame frame = new JFrame("GRAPH");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        @SuppressWarnings("serial")
        JPanel panel = new JPanel(new GridLayout()) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(1300, 600);
            }
        };
        panel.setBorder(BorderFactory.createLineBorder(Color.blue, 5));

        graph = new SingleGraph("Tutorial", false, true);
        Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);

        final ViewPanel viewPanel = viewer.addDefaultView(false);
        viewer.enableAutoLayout();

        graph.setAutoCreate(true);
        graph.setStrict(false);
        graph.addAttribute("ui.quality");
        graph.addAttribute("ui.antialias");

        label = new JLabel("Enter Numbers : ");
        enter_numbers = new JTextField(15);
        Font bigFont = enter_numbers.getFont().deriveFont(Font.PLAIN, 17f);
        enter_numbers.setFont(bigFont);
        show_graph = new JButton("SHOW GRAPH");

        viewPanel.add(label);
        viewPanel.add(enter_numbers);
        viewPanel.add(show_graph);
        show_graph.addActionListener(showGraphListener);

        panel.add(viewPanel);
        frame.add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        viewPanel.addMouseWheelListener(new MouseWheelListener() {
            public void mouseWheelMoved(MouseWheelEvent e) {
                if (e.getWheelRotation() == -1) {
                    zoomLevel = zoomLevel - 0.1;
                    if (zoomLevel < 0.1) {
                        zoomLevel = 0.1;
                    }
                    viewPanel.getCamera().setViewPercent(zoomLevel);
                }
                if (e.getWheelRotation() == 1) {
                    zoomLevel = zoomLevel + 0.1;
                    viewPanel.getCamera().setViewPercent(zoomLevel);
                }
            }
        });
    }

    private Connection createConnection() throws ClassNotFoundException, SQLException {
        Class.forName("org.h2.Driver");
        conn = DriverManager.getConnection("jdbc:h2:file:G:/hs_data/h2_db/test", "sa", "sa");
        return conn;
    }

    ActionListener showGraphListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            String user_input = enter_numbers.getText();
            if (user_input == null || user_input.isEmpty()) {
                JOptionPane.showMessageDialog(null, "Please enter atleast two numbers with comma seperated");
            } else {
                ArrayList<String> items = new ArrayList<String>(Arrays.asList(user_input.split("\\s*,\\s*")));
                try {
                    showGraph(items);
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
        }
    };

    private void showGraph(ArrayList<String> items) throws SQLException {

        stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT ANUMBER,BNUMBER FROM CDR LIMIT 4500");
        while (rs.next()) {
            result = rs.getString("ANUMBER");
            result2 = rs.getString("BNUMBER");
            graph.addNode(result);
            graph.addNode(result2);
            i++;
            graph.addEdge("String" + i, result, result2);
            for (Node node : graph) {
                node.addAttribute("ui.hide");
            }
            for (Edge edge : graph.getEachEdge()) {
                edge.addAttribute("ui.hide");
            }
        }
        conn.close();

        Dijkstra dijkstra = new Dijkstra(Dijkstra.Element.EDGE, null, null);
        dijkstra.init(graph);

        ArrayList<String> rl = new ArrayList<String>();
        ArrayList<String> lr = new ArrayList<String>();
        rl = items;

        lr.addAll(rl);
        Collections.reverse(lr);
        for (String anumber : rl) {
            lr.remove(lr.size() - 1);
            for (String bnumber : lr) {

                dijkstra.setSource(graph.getNode(anumber));
                dijkstra.compute();

                for (Node node : dijkstra.getPathNodes(graph.getNode(bnumber))) {
                    node.addAttribute("ui.style", "fill-color: blue;");
                    node.addAttribute("ui.label", node.getId());
                    node.removeAttribute("ui.hide");
                }

                for (Edge edge : dijkstra.getPathEdges(graph.getNode(bnumber))) {
                    edge.addAttribute("ui.style", "fill-color: red;");
                    edge.removeAttribute("ui.hide");
                }

                graph.getNode(anumber).addAttribute("ui.style", "fill-color: green;");
                graph.getNode(anumber).addAttribute("ui.style", "size: 16px;");
                graph.getNode(bnumber).addAttribute("ui.style", "fill-color: green;");
                graph.getNode(bnumber).addAttribute("ui.style", "size: 16px;");


            }
        }
        dijkstra.clear();
    }
}

回答1:

You'll want to experiment with the layout algorithm used by your Viewer. You can specify the layout by passing a concrete Layout to enableAutoLayout(): SpringBox is the default, but LinLog may be worth trying. See also this list of attributes with a predefined meaning for the layout algorithms, as well as examples shown here and here.