Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

PEAR::Image_Graphvizを使って山手線の路線図を書いてみた


GraphvizAT&Tが作ったグラフ構造を描画するツールで、こんな図こんな図SVG形式、pngやgifで出力できます。
で、PEARにもPEAR::Image_Graphvizが登録されています。このパッケージの仕組みはかなりベタベタで、dotコマンド(Graphvizで用意されているコマンドの1つ)にパラメータを渡して実行・実ファイルを作成してそれを返す、といったものになりますので、当然コマンド群をインストールしておく必要があります。
PHPスクリプトの例は、pear/Image/GraphViz.phpのコメントにもありますが、次の様な感じです。

<?php
require_once 'Image/GraphViz.php';

$graph = new Image_GraphViz();

$graph->addNode(
  'Node1',
  array(
    'URL'   => 'http://link1',
    'label' => 'This is a label',
    'shape' => 'box'
  )
);

$graph->addNode(
  'Node2',
  array(
    'URL'      => 'http://link2',
    'fontsize' => '14'
  )
);

$graph->addNode(
  'Node3',
  array(
    'URL'      => 'http://link3',
    'fontsize' => '20'
  )
);

$graph->addEdge(
  array(
    'Node1' => 'Node2'
  ),
  array(
    'label' => 'Edge Label'
  )
);

$graph->addEdge(
  array(
    'Node1' => 'Node2'
  ),
  array(
    'color' => 'red'
  )
);

$graph->image();
?>

このコードで、

のようなsvgファイルが出力されます。ただし、日本語を使う場合、

する必要があるんですが、毎回mb_convert_encodingとかしてると面倒なので、

<?php
require_once 'Image/GraphViz.php';
class Image_GraphViz2 extends Image_GraphViz {
    function _convertEncoding($str) {
        return mb_convert_encoding($str, 'utf-8', 'auto');
    }

    function Image_GraphViz2($directed, $attributes, $name) {
        parent::Image_GraphViz($directed, $attributes, $name);
    }

    function parse() {
        return $this->_convertEncoding(parent::parse());
    }
}

みたいなクラスを作ってしまった方が早いと思います。
ここまでを踏まえて、タイトル通り、山手線の路線図を書いてみました。次の様なコードになります。

<?php
error_reporting(E_ALL);
require_once 'Image/GraphViz.php';

class Image_GraphViz2 extends Image_GraphViz {
    function _convertEncoding($str) {
        return mb_convert_encoding($str, 'utf-8', 'auto');
    }

    function Image_GraphViz2($directed, $attributes, $name) {
        parent::Image_GraphViz($directed, $attributes, $name);
    }

    function parse() {
        return $this->_convertEncoding(parent::parse());
    }
}
?>
<?php
    $stations = array('品川',
                      '田町',
                      '浜松町',
                      '新橋',
                      '有楽町',
                      '東京',
                      '神田',
                      '秋葉原',
                      '御徒町',
                      '上野',
                      '鶯谷',
                      '日暮里',
                      '西日暮里',
                      '田端',
                      '駒込',
                      '巣鴨',
                      '大塚',
                      '池袋',
                      '目白',
                      '高田馬場',
                      '新大久保',
                      '新宿',
                      '代々木',
                      '原宿',
                      '渋谷',
                      '恵比寿',
                      '目黒',
                      '五反田',
                      '大崎');

    $default_options = array('fontsize' => '12',
                             'fontname' => '/usr/share/fonts/ja/TrueType/kochigothic.ttf');
    $graph_attributes = array();
    $graph = new Image_GraphViz2(false, $graph_attributes, '山手線');

    $prev_station = null;
    foreach ($stations as $station) {
        $graph->addNode($station, $default_options);
        if (is_null($prev_station)) {
            $graph->addEdge(array($stations[count($stations) - 1] => $station));
        } else {
            $graph->addEdge(array($prev_station => $station));
        }
        $prev_station = $station;
    }


    $graph->image('png');
//    var_dump($graph->parse());

まあ、路線図書いたからってどうってことないんですが(^^;、何らかのフローを機械的に描きたいときとかは便利かな、と。PHPソースからフローチャートを生成する - Shin x blogで紹介されていたツールも、頑張ればできるかも。。。