Japanese Only

Step 3: 自動レイアウト機能の利用

  1. 自動レイアウトの実装方法
  2. 既存のレイアウト機能の使い方
  3. 用意されているレイアウト機能
目次ページへ

自動レイアウトの実装方法

自動レイアウト機能の実装

簡単な自動レイアウト機能を実装してみましょう。最も簡単なグラフのレイアウトはノードをランダムな位置に配置するものです。そのプログラムは下のようになります。

RandomLayout.java

  1: import java.awt.Dimension;

  2: import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
  3: import edu.uci.ics.jung.graph.Graph;

  4: public class RandomLayout<V,E> extends AbstractLayout<V,E> {

  5:     public RandomLayout(Graph<V,E> g) {
  6:         super(g);
  7:     }

  8:     public RandomLayout(Graph<V,E> g, Dimension d) {
  9:         super(g);
 10:         setSize(d);
 11:     }

 12:     @Override
 13:     public void initialize() {
 14:         layoutNodes();
 15:     }

 16:     @Override
 17:     public void reset() {
 18:     }

 19:     private void layoutNodes() {
 20:         int clearance = 20;

 21:         Dimension d = getSize();
 22:         int width = d.width - clearance * 2;
 23:         int height = d.height - clearance * 2;

 24:         for (V v : getGraph().getVertices()) {
 25:             if (isLocked(v)) continue;
 26:             double x = Math.random() * width + clearance;
 27:             double y = Math.random() * height + clearance;
 28:             transform(v).setLocation(x, y);
 29:         }
 30:     }

 31: }

自動レイアウト機能を実装するには、Layout<V,E>インタフェースを実装する必要があります。Layout<V,E>インタフェースを部分的に実装したAbstractLayout<V,E>クラスがあるので、それを継承すると便利です。AbstractLayout<V,E>クラスを継承する場合には、initialize()メソッドとreset()メソッドを実装します。initialize()メソッドの本体はlayoutNodes()メソッドで、描画領域のサイズを獲得し、その範囲内に納まるようにノードの位置をランダムに決めているだけです。reset()メソッドも実装していますが、本体は空です(*1)。

(*1) reset()メソッドはその名の通り何かをリセットするために使われるのだと思いますが、APIの記述がありません。

自動レイアウト機能の利用

実装した自動レイアウト機能を利用するには下のようにします。このプログラムはSample3.javaと基本的な構造は同じです。ただし、グラフを作成する部分をcreateGraph()メソッドに切り出し、変数layoutにStaticLayout<MyNode,MyEdge>クラスのインスタンスを代入していたところを、上で定義したRandomLayout<MyNode,MyEdge>クラスのインスタンスを代入しています。

Sample3b.java

  1: import java.awt.Dimension;
  2: import javax.swing.JFrame;

  3: import edu.uci.ics.jung.algorithms.layout.Layout;
  4: import edu.uci.ics.jung.graph.Graph;
  5: import edu.uci.ics.jung.graph.UndirectedSparseGraph;
  6: import edu.uci.ics.jung.visualization.BasicVisualizationServer;

  7: public class Sample3b {

  8:     public static void main(String[] args) {
  9:         Dimension viewArea = new Dimension(300, 300);
 10:         Graph<MyNode,MyEdge> graph = createGraph();
 11:         Layout<MyNode,MyEdge> layout = new RandomLayout<MyNode,MyEdge>(graph, viewArea);
 12:         BasicVisualizationServer<MyNode,MyEdge> panel = 
                 new BasicVisualizationServer<MyNode,MyEdge>(layout, viewArea);

 13:         JFrame frame = new JFrame("Graph View: Random Layout");
 14:         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 15:         frame.getContentPane().add(panel);
 16:         frame.pack();
 17:         frame.setVisible(true);
 18:     }

 19:     private static Graph<MyNode,MyEdge> createGraph() {
 20:         Graph<MyNode,MyEdge> g = new UndirectedSparseGraph<MyNode,MyEdge>();
 21:         MyNode n1 = new MyNode("n1");
 22:         MyNode n2 = new MyNode("n2");
 23:         MyNode n3 = new MyNode("n3");
 24:         MyNode n4 = new MyNode("n4");
 25:         MyNode n5 = new MyNode("n5");
 26:         MyNode n6 = new MyNode("n6");
 27:         MyNode n7 = new MyNode("n7");
 28:         MyNode n8 = new MyNode("n8");
 29:         g.addEdge(new MyEdge("e1"), n1, n2);
 30:         g.addEdge(new MyEdge("e2"), n2, n3);
 31:         g.addEdge(new MyEdge("e3"), n3, n4);
 32:         g.addEdge(new MyEdge("e4"), n4, n1);
 33:         g.addEdge(new MyEdge("e5"), n5, n6);
 34:         g.addEdge(new MyEdge("e6"), n6, n7);
 35:         g.addEdge(new MyEdge("e7"), n7, n8);
 36:         g.addEdge(new MyEdge("e8"), n8, n5);
 37:         g.addEdge(new MyEdge("e9"), n1, n5);
 38:         g.addEdge(new MyEdge("e10"), n2, n6);
 39:         g.addEdge(new MyEdge("e11"), n3, n7);
 40:         g.addEdge(new MyEdge("e12"), n4, n8);
 41:         return g;
 42:     }

 43: }

このプログラムを実行するとすると下のようなウィンドウが現われます。ただし、ノードの配置はランダムなので、実行の度に変ります。

Execution result of Sample3b.java

継続的にレイアウトを変更する

RandomLayout<V,E>クラスを下のように改造すると、レイアウトを変更し続けます。ここでは別のファイルにするためにクラス名をRandomLayout2.javaに変更していますが、Sample3bクラスで使う場合には、ファイル名(クラス名)を修正する必要はありません。

修正箇所はInteractiveContextインタフェースの実装です。InteractiveContextインタフェースは、done()メソッドとstep()メソッドを必要とするので、それら二つのメソッドを実装する必要があります。

RandomLayout2.java

  1: import java.awt.Dimension;

  2: import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
  3: import edu.uci.ics.jung.algorithms.util.IterativeContext;
  4: import edu.uci.ics.jung.graph.Graph;

  5: public class RandomLayout2<V,E> extends AbstractLayout<V,E> implements IterativeContext {

  6:     public RandomLayout2(Graph<V,E> g) {
  7:         super(g);
  8:     }
(中略)
 20:     @Override
 21:     public void step() {
 22:         layoutNodes();
 23:     }

 24:     @Override
 25:     public boolean done() {
 26:         return false;
 27:     }

 28:     protected void layoutNodes() {
(中略)
 39:     }

 40: }

done()メソッドは自動レイアウトが終了したかどうかを示すメソッドです。上の例ではいつもfalseを返すので、いつまでもレイアウトは終了しないということになります。InteractiveContextインタフェースを実装したLayoutオブジェクトの場合、一定時間毎にstep()メソッドが呼び出されます。上の例では、一定時間毎にlayoutNodes()メソッドが呼び出されることで、レイアウトをランダムに変更し続けます。

既存のレイアウト機能の使い方

JUNG2.0にはすでにいくつかの自動レイアウト機能が用意されています。自分で自動レイアウト機能を実装しなくても、これらを利用することで簡単に自動レイアウトを行うことができます。たとえばFRLayout<V,E>クラス(edu.uci.ics.jung.algorithms.layout.FRLayout<V,E>クラス)を利用すれば、古典的なグラフ描画アルゴリズムであるFruchterman and Reingoldの力指向アルゴリズムを利用できます。FRLayout<V,E>クラスを使用するにはSample3b.javaを下のように改造します。

Sample3d.java

  3: import edu.uci.ics.jung.algorithms.layout.FRLayout;
(中略)
  9:     public static void main(String[] args) {
 10:         Dimension viewArea = new Dimension(300, 300);
 11:         Graph<MyNode,MyEdge> graph = createGraph();
 12:         Layout<MyNode,MyEdge> layout = new FRLayout<MyNode,MyEdge>(graph, viewArea);
(中略)
 19:     }

 20:     private static Graph<MyNode,MyEdge> createGraph() {
(中略)
 43:     }
 44: }

このプログラムを実行すると下のようなウィンドウが現われます。ただし、FRLayoutにもランダムな要素があるため、必ずしもこれと同じ配置にならないかも知れません。それでも、RandomLayoutほどのばらつきはないので、グラフが立方体の構造を持っていることは分るでしょう。

Execution result of Sample3c.java

用意されているレイアウト機能

その他の自動レイアウト機能

FRLayout以外にも、以下のようなアルゴリズムが用意されています。

目次ページへ