GTFSからベクターデータ(SVG)を作成し、見栄えの良い路線図を手間をかけずに作ります。
その第一弾、まずは小手調べとして、群馬県前橋で事業を展開する永井運輸の前橋大島駅線の路線図を描きました。
データの権利(ライセンス)について
OpenStreetMap
路線図(完成)図の背景地図として、OpenStreetMapを色を薄くする加工を行って使用しました。CC BY-SA 2.0(表示-継承 2.0)のもとに提供されています。
永井バス GTFSデータ
路線図を作成するにあたり、永井運輸が作成・配布しているデータを使用しました。なお、ファイルはGTFS(2018-04-20_1714nagai).zip(2018年4月1日改正)です。CC BY 4.0(表示 4.0)のもとに提供されています。
GTFSとは?
公共交通の時刻データや地理的データをひとまとめにしたフォーマットのことです。国土交通省が2017年3月に「標準的なバス情報フォーマット」(GTFSに日本の経路検索で必要となる項目を追加したもの)を定めたことで、利用が広がっています。詳しいことは、以下のページをご覧いただくか、検索してみてください。
- General Transit Feed Specification – Wikipedia
- 公共交通政策:経路検索の充実に向けた取組 – 国土交通省
- 「標準的なバス情報フォーマット広め隊」結成、各地で始まる「GTFS」公共交通データ整備【地図と位置情報】 – INTERNET Watch
- オープンデータ標準を作る: GTFS物語
永井運輸とは?
群馬県前橋市にある、トラック輸送を軸に、乗合バス、貸切バス、タクシー、倉庫に観光代理店と幅広く事業を展開する事業者です。乗合バスの台数は26台で、前橋駅を中心に、元々は大手事業者が運行していた系統や、コミュニティバスを運行します。
記事執筆時点では、関東地方で唯一のGTFSのデータを公開している、先駆的な事業者でもあります。
材料・道具と手順について
- GTFSファイル
- 路線図の元になるものです。永井運輸のGTFSデータ置き場を見てみると、3種類のファイルがあります。2つ目のファイルは路線が複数含まれていますが、1つ目のファイルは1路線だけですので、小手調べにはぴったりですね。2つ目のファイルが行政からの補助金を受けている路線で、今回描く前橋大島駅線は補助金を受けていない路線ということらしいです。
- Processing
- GTFSファイルをSVGデータに変換します。GTFSデータはバラしてしまえばCSVデータです。私が知っていて使えるCSVからSVGを書き出す道具がprocessingしかない消去法的に使うのですが、何か他に便利なものがあれば教えてほしいです。
- Affinity Designer
- SVGデータを加工し、見栄えの良い路線図にします。Adobe Illustratorが使えない環境なので、というだけです。
- OpenStreetMap
- SVGを加工して見栄えを良くした路線図の下に敷きます。複製の許可を取れば、地理院地図でもよいでしょう。
ProcessingにGTFSを読み込ませる
PDEファイルがある階層に、dataフォルダーを作りました。
dataフォルダーの中に、永井運輸のGTFSファイルの中にあるファイルのうち、路線図に関わりそうなものを配置しました。拡張子が.txtだと上手く読み込めなかったので、.csvに変更しました。
なお、routes.csvは系統を、shapes.csvは系統が走る緯度経度の情報を、stops.csvはバス停の緯度経度の情報をそれぞれ持っています。
ファイルを配置したら、試行錯誤しながらプログラミングを書いていきました。今回描くのはとりあえず1系統だけなので、それほど複雑なところはありません。
(作業風景)
sketch_nagai_oshima.pde
//使う関数・ライブラリーの読込み import processing.svg.*; Table shapes,routes,stops; PFont font; //shapes.csv int shape_id; float shape_pt_lat,shape_pt_lon; int shape_pt_sequence; //routes.csv(一応読み込ませているが、今回は未使用) int route_id; String route_long_name; //stops.csv String stop_id,stop_name; float stop_lat,stop_lon; void setup() { size(1024,1024); background(#ffffff); //CSVファイルを読み込ませる shapes = loadTable("shapes.csv", "header"); routes = loadTable("routes.csv", "header"); stops = loadTable("stops.csv", "header"); //文字サイズとフォントを設定(SVGにフォントは反映されないが…) font = createFont("Meiryo", 18); textFont(font); } void draw() { //endRecordと対になる beginRecord(SVG, "nagai_oshima.svg"); //今回は、shape_idが150のみのデータを使う int id= 150; noFill(); //vertexの線で描く beginShape(); for (TableRow row : shapes.rows()) { //ズームレベル15の地図タイルの区切りに合うように、緯度経度をx軸y軸の値に変換 float y = map(row.getFloat("shape_pt_lat"),36.377068,36.368222,512,768); float x = map(row.getFloat("shape_pt_lon"),139.097900,139.108887,256,512); if (row.getInt("shape_id")==id) { vertex(x,y); }else{ //shape_id150を書き終わったら、線の描画を閉じてfor文から抜ける endShape(); break; } } for (TableRow row : stops.rows()) { float y = map(row.getFloat("stop_lat"),36.377068,36.368222,512,768); float x = map(row.getFloat("stop_lon"),139.097900,139.108887,256,512); //バス停の丸 noFill(); stroke(#000000); ellipse(x,y,7,7); //バス停名 fill(#000000); noStroke(); text(row.getString("stop_name"),x+9,y+6); } //SVGを保存 endRecord(); //確認のためPNGも保存 save("nagai_oshima.png"); //画面を閉じる exit(); }
このプログラムを実行すると、以下のようなPNGとSVGが作成されます。
(クリックすると、大きな画像が表示されます。以下同様)
バス停名を打ったり、線を引いたりせずに、路線図らしいものが得られました!
SVGを加工する
GTFSのデータは、上り下りの経路情報とバス停情報を別々に持ちます。そのため、上記の図では線やバス停が二重になっている箇所があります。路線図にするには片方だけあれば十分なので、思い切って片方を消します。道路の中心からズレて見えてしまわないか心配になってしまいますが、案外大丈夫です。
文字が小さいですね。Processingが書き出すSVGは、文字の大きさとフォントが上手く埋め込まれていないようです。とりあえず、Affinity Designer上で変更することで対処しましょう。
プログラミングの段階で、片方だけのバス停だけ描くのもアリだとは思います。
完成
さらに、文字の大きさ、線の太さなどを整えます。
そして、下地にOpenStreetMapを敷いたら完成です。
良い感じに仕上がりました! 次回は、複数系統のバス路線を描いてみたいと思います。
つづく
- 2018-10-07 初版