簡體   English   中英

如何通過JUNG2繪制相同的邊緣名稱

[英]How to draw same edge name by JUNG2

我正在做JUNG2的繪制網絡拓撲項目,現在發現JUNG2無法在不同的頂點繪制相同的邊緣(名稱)。 並報告如下:

Exception in thread "main" java.lang.IllegalArgumentException: edge GigabitEthernet0/3<--->GigabitEthernet0/0/0/0 already exists in this graph with endpoints <HKBR1, HKBR3> and cannot be added with endpoints <HKBR2, HKBR4>
at edu.uci.ics.jung.graph.AbstractGraph.getValidatedEndpoints(AbstractGraph.java:93)
at edu.uci.ics.jung.graph.SparseMultigraph.addEdge(SparseMultigraph.java:123)
at edu.uci.ics.jung.graph.AbstractGraph.addEdge(AbstractGraph.java:60)
at pkg.DrawnTopology.DrawnTopology(DrawnTopology.java:45)
at pkg.ReadLine.main(ReadLine.java:85)

我已將所有邊和頂點存儲到二維數組中。 二維數組數據從不同的文件中學習,因此數據是動態的。 由於網絡拓撲可能具有相同的邊緣名稱,那么如何解決呢?

問題顯然缺乏細節,但從描述和錯誤信息中,人們可能會猜到這里有什么問題:

您的圖形可以定義為Graph<V, String>

它可能是Graph的子類,頂點類型無關緊要。 關鍵點是邊緣類型是String

並且您正嘗試向圖表添加邊緣,如下所示:

g.addEdge("edge0", v0, v1);
g.addEdge("edge0", v2, v3);

這將導致錯誤,因為邊緣"edge0"存在兩次。 (這是有道理的。否則:當你向圖表詢問"edge0"的端點時會發生什么?它應該返回v0,v1還是v2,v3 ?它只是模糊不清)。

(注意,這不僅是邊緣類型為String時的情況。對於任何邊緣類型都會發生,只要兩條邊彼此equal )。

這里一個簡單的解決方案是引入一個包裝String的專用Edge類:

class Edge
{
    private final String name;

    Edge(String name)
    {
        this.name = name;
    }

    @Override
    public String toString()
    {
        return name;
    }
}

這個類沒有equals方法重寫。 因此,即使字符串相等,這種類型的兩個對象也不會相等:

Edge e0 = new Edge("edge0");
Edge e1 = new Edge("edge0");
System.out.println(e0.equals(e1)); // prints "false"

然后,邊標簽可以簡單地是這些邊的toString表示,它返回原始字符串。

一個例子:

import javax.swing.JFrame;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;

class Edge
{
    private final String name;

    Edge(String name)
    {
        this.name = name;
    }

    @Override
    public String toString()
    {
        return name;
    }
}

public class JungDuplicateEdgesTest
{
    public static void main(String[] args)
    {
        JFrame jf = new JFrame();
        final Graph<String, Edge> g = getGraph();
        VisualizationViewer<String, Edge> vv = 
            new VisualizationViewer<String, Edge>(
                new FRLayout<String, Edge>(g));

        class EdgeLabelTransformer implements Transformer<Edge, String>
        {
            @Override
            public String transform(Edge edge)
            {
                return edge.toString();
            }
        }
        vv.getRenderContext().setEdgeLabelTransformer(
            new EdgeLabelTransformer());

        jf.getContentPane().add(vv);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);
    }

    public static Graph<String, Edge> getGraph()
    {
        Graph<String, Edge> g = new DirectedSparseGraph<String, Edge>();
        g.addVertex("v0");
        g.addVertex("v1");
        g.addEdge(new Edge("e0"), "v0", "v1");
        g.addEdge(new Edge("e0"), "v1", "v0");
        return g;
    }
}

旁注:對於某些應用程序,也可以將邊緣的頂點存儲在Edge類中。 然后你可以實現equalshashCode方法,它允許你在兩個邊具有相同的頂點時將它們視為相等。

從技術上講,邊緣名稱必須是唯一的,但您可以操縱圖表中顯示的內容。 為了獲得邊的唯一名稱,我使用以下模式來表示邊的名稱:fromVertex_edgeName_toVertex。

然后,您需要一個EdgeLabelTransformer

private class EdgeLabelTransformer<V> implements Transformer<V, String> {

    @Override
    public String transform(V v) {
        return v.toString().substring(v.toString().indexOf("_") + 1, v.toString().lastIndexOf("_"));
    }
}

這個變換器實際上告訴VisualViewer要顯示什么。 因此,在我的情況下,它只顯示中間部分,這導致您可以在圖形中具有多個具有相同顯示名稱的邊。

像這樣添加變換器:

visualViewer.getRenderContext().setEdgeLabelTransformer(new EdgeLabelTransformer<String>());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM