はじめに †とある授業で使うかもしれないのと、自分で前から作ってみたかったのでぱぱっと実装。 基本はビジュアライジング・データのサンプルコードを拡張して作りました。 ある映画監督のキャストをネットワークグラフで表示するものです。 サンプルプログラムの実行 †まずはnetwork_visualization_sample.zipをダウンロードして解凍。 †次に https://processing.org/ にアクセスします。 †右のメニューの「Download」をクリックします。 †No Donationを選択して(もちろんDonationしてもOKです)Downloadをクリック †Downloadをクリック †自分のPCの環境に合わせて選択。この例ではWindows 64 bit †ダウンロードファイルの保存場所の指定。この例ではデスクトップ。 †ダウンロードしたファイルをデスクトップで解凍して中のprocessing.exeをダブルクリック。 †Processingメニューの「File」をクリック。 一番最初にダウンロードしたサンプルプログラムの中のnetwork_visualization.pdeをクリック。 †再生ボタンをクリック。 †ネットワークグラフが表示される。 †ソースコード解説 †processingのコアとなるのは
setup関数 †int nodeCount; Node[] nodes = new Node[100]; HashMap nodeTable = new HashMap(); int edgeCount; Edge[] edges = new Edge[500]; static final color selectColor = #FF3030; static final color fixedColor = #FF8080; static final color edgeColor = #000000; static final int minimum_size = 2; PFont font; void setup() { size(1000, 700); loadData(); font = createFont("Meiryo UI", 10); textFont(font); smooth(); } 起動時に一度だけ実行される関数です。 主に初期化処理を実行しています。 sizeはウィンドウのサイズ、loadDataはデータの読み込み、createFont、textFont、smoothはフォントを設定して表示を滑らかにしています。 loadData関数 †void loadData() { String[] lines = loadStrings("sample.txt"); String[] data; for(int i = 0; i < lines.length; i++){ data = split(lines[i], ','); addEdge(data[0], data[1]); } } 起動時にsetup関数経由で実行される関数です。 CSVファイルを配列に変換してグラフを生成しています。 sample.txtから一行ずつ取ってきてsplitで分割しています。 addEdgeはデータ列の一番目と二番目をつなぐグラフを生成ます。 例えば、sample.txtにCSV形式で 天空の蜂,江口洋介 天空の蜂,本木雅弘 天空の蜂,仲間由紀恵 と書かれていた場合には
をそれぞれ接続したグラフが生成されます。 addEdge関数 †void addEdge(String fromLabel, String toLabel) { Node from = findNode(fromLabel); Node to = findNode(toLabel); from.increment(); from.nodeColor = #FFFFFF; to.nodeColor = #FF0000; to.increment(); for (int i = 0; i < edgeCount; i++) { if (edges[i].from == from && edges[i].to == to) { edges[i].increment(); return; } } Edge e = new Edge(from, to); e.increment(); if(edgeCount == edges.length){ edges = (Edge[]) expand(edges); } edges[edgeCount++] = e; } 起動時にsetup関数→loadData関数経由で実行される関数です。 以下の処理を実行します。
findNode関数 †Node findNode(String label) { label = label.toLowerCase(); Node n = (Node) nodeTable.get(label); if (n == null) { return addNode(label); } return n; } addEdge関数から実行される関数です。 既にそのラベルのノードが作られているかどうかを調べます。 もしそのラベルのノードが存在する場合には該当ノードを返します。 もしそのラベルのノードが存在しない場合にはaddNode関数で新たなノードを作成して、作成したノードを返します。 addNode関数 †Node addNode(String label){ Node n = new Node(label); if(nodeCount == nodes.length){ nodes = (Node[]) expand(nodes); } nodeTable.put(label, n); nodes[nodeCount++] = n; return n; } findNode関数から実行される関数です。 新しいノードを作成して、配列nodesのサイズが足りなくなったら配列をexpand関数で2倍に増やします。 draw関数 †void draw() { if (record) { beginRecord(PDF, "output.pdf"); } background(#FFFFFF); for(int i = 0; i < edgeCount; i++){ edges[i].relax(); } for(int i = 0; i < nodeCount; i++){ nodes[i].relax(); } for(int i = 0; i < nodeCount; i++){ nodes[i].update(); } for (int i = 0; i < edgeCount ; i++){ if(edges[i].from.count >= 1 && edges[i].to.count >= 1){ edges[i].draw(); } } for(int i = 0; i < nodeCount; i++){ if(nodes[i].count >= 1){ nodes[i].draw(); } } if(record){ endRecord(); record = false; } } 描画の度に実行される関数です。 まず一番外側のrecordに関係する部分はpdfにグラフを出力する際に使用します。 rキーを押すとrecordがtrueになって中が実行されます。 おわりに †データの取得に関しては別で解説します。 |