目次


Perl、GD、および plot-latlong を使用して、データをプロットした地図を作成する

世界地図や米国地図の上にカスタム・データ・プロットを作成する (地域に濃淡を付けたデータも表示する)

Comments

人や組織は、データを地図上に表示させて視覚化することをしばしば必要とします。Google マップなどの既存の地図作成ツールには、制限はあるものの優れたオプションが用意されています。この記事では、Yahoo が提供する無料の「ローカルサーチ Web サービス」を利用した、位置検索用の簡単な Perl のコードを使用します。次に、取得した緯度と経度を使用して、オプションにほとんど制限のない実用的な地図を作成する方法を示します。それには、CAIDA の plot-latlong アプリケーションと、GD による注釈を使用します。

plot-latlong と Perl-GD の両方を使って地図を作成したら、背景となる地図の輪郭を変更します。地図上のポイントを示したり、州に関連のある数量データを表示したりするために、GD の塗りつぶしなどのツールを使用して「濃淡付け可能」版の米国地図を作成します。

ここで説明するツールと技法を使用すれば、オープン・ソース・ソフトウェアと、無料で提供されている「ローカルサーチ Web サービス」を利用して、独自にカスタマイズした地図データのプロットを作成できます。既存の地図作成ツールの API を使用した場合、世界のいたるところにポイントをプロットできますが、特定のデータに基づいて州、国、または地域に濃淡を付ける簡単な方法がありません。また、何千ものポイントを示すカスタマイズ可能な標識を地図に素早くプロットすることもできません。非常に印象的な地図を素早く作成するには、GD、Perl、plot-latlong といったツールが必要となります。

要件

ハードウェア

西暦 2000 年より後に製造された PC であれば、この記事で紹介するコードのコンパイルと実行に十分な処理能力が備わっています。ほとんどの処理は、CAIDA の plot-latlong と GD が行います。これらのプログラムは、非常に優れた設計になっていて、高速処理を実現します。

ソフトウェア

使用する操作環境に最新版の Perl が入っていれば、あとは位置情報取得モジュール、GD Perl モジュール、および CAIDA の plot-latlong をインストールするだけです。GD モジュールは、任意の CPAN ミラー・サイトからダウンロードしてインストールしてください。また、Geo::Coder:Yahoo Perl モジュールとその関連モジュール Yahoo::Search もインストールしてください。

plot-latlong のアーカイブを解凍したら、.mapimages ディレクトリーと .mapinfo ファイルを ${HOME}ディレクトリーにコピーしてください。これらは、後から何回かの地図生成ステップで使用します。

実際の住所の位置情報取得

今回の目的では、位置情報取得を、指定された住所の緯度と経度を検索することと定義します。plot-latlong で作成できる実用的なデータ地図の多くには、都市や郊外が細部にいたるまで詳細に表示されます。以下の住所リストのような一連の住所を指定されれば、緯度と経度を調べて、plot-latlong でその住所を世界地図の上に表示します。

リスト 1. locationNames サンプル・データ・ファイル
cary, nc
oswego, ny
potsdam, germany
beijing, china
london, england
bangalore, india
brasilia, brazil

ここで使用する位置情報取得モジュールと検索サービスは高性能で、Cary, N.C. が米国の都市であって、New Caledonia に住む Cary という人物ではないことが自動的に認識されます。locationNames データ・ファイルを処理して位置情報データ・セットを作成する、次のスクリプトを検討してください。

リスト 2. yahooGeoCode.pl
#!/usr/bin/perl -w
# yahooGeoCode.pl - lookup long/lat of an address using yahoo
use strict;

use Geo::Coder::Yahoo;
my $geocoder = Geo::Coder::Yahoo->new(appid => 'my_app' );

while( my $line = <STDIN> )
{
chomp($line);
my $location = "";
$location = $geocoder->geocode( location => "$line" );

for ( @{$location} )
{
my %hash = %{$_};
print "$hash{latitude} $hash{longitude} # $line \n";
} 
}#while stdin

コマンド cat locationNames | perl yahooGeoCode.pl >cityCoords を使用して、位置情報取得モジュールを実行します。その結果、緯度、経度、および都市名を含むファイルが作成されます。いずれの位置情報取得モジュールを使用しても、cityCoords に適したフォーマットのファイルを生成することができます。この記事では、その正確性と容易性から Ask Bjoern Hansen による Yahoo/Perl を使った位置情報取得モジュールを選びました。

リスト 3. cityCoords サンプル・データ・ファイル
35.791458 -78.781174 # cary, nc 
43.455471 -76.510048 # oswego, ny 
52.400002 13.07 # potsdam, germany 
40.25 116.5 # beijing, china 
51.52 -0.1 # london, england 
12.97 77.559998 # bangalore, india 
-15.78 -47.91 # brasilia, brazil

plot-latlong による注釈付き地図作成

plot-latlong の標準的な使用方法

この時点で、plot-latlong プログラムを使用して、cityCoords ファイルに含まれている位置情報レコードを世界地図の上に描画することができます。plot-latlong.pl プログラムがカレント・ディレクトリーに入っていること確認して、そのプログラムをコマンド cat cityCoords | perl plot-latlong.pl -s 5 >cityMap1.png で実行します。その結果、plot-latlong 形式の標準的な地図が作成され、都市の上には大きな長方形の標識が表示されています。

地図の注釈

GD を使用すれば、タイトル・テキスト、作成者テキスト、凡例の説明、および装飾的な枠線で地図画像ファイルに注釈を付けることができます。しかし plot-latlong の本当に優れた機能は、位置情報が与えられた場所の正確なピクセル位置を返すことです。ピクセル座標を使用すれば、ポイントから線を描画したり、線の色を変更したり、線同士を繋げたり、周りに色を塗ったりすることもできます。ほかにも、GD で実現可能なことはすべて実現できます。例えば、画像 ID とテキストを使用して、地図画像の上部にキーを作成するとします。画像 ID とテキストを含んだそれぞれのボックスから、地図上の関連座標に線を引きます。リスト 4 に示すカスタム Perl スクリプトを使用すれば、この処理を自動化することができます。必要となるピクセル座標を作成するには、-c オプションを plot-latlong に渡すだけです。ピクセル座標が stderr に出力されるので、プロット・コマンド cat cityCoords | perl plot-latlong.pl -s 5 -c >cityMap1.png 2>cityPixels を再実行してください。

リスト 4. worldCompositeMap.pl セクション 1
#!/usr/bin/perl -w
# worldCompositeMap.pl - overlay text, images and shapes on map image
use strict;
use GD;

die "specify: pixelFile dataFile sourceImage destImage" unless @ARGV == 4;

my $newMap = newFromPng GD::Image( $ARGV[2] );

my $imageWidth = $newMap->width();
my $imageHeight = $newMap->height();
my $topMargin = 110;
my $blankMap = new GD::Image($imageWidth, $imageHeight+$topMargin);

my $white = $blankMap->colorAllocate(255,255,255);
my $black = $blankMap->colorAllocate(0,0,0);

$blankMap->copy( $newMap, 0,$topMargin, 0,0, $imageWidth,$imageHeight );

my @pixels = ();
my @data = ();
open( PIXELFILE, "$ARGV[0]" ) or die "can't open pixels file";
while( my $line = <PIXELFILE> ){ push @pixels, $line }
close(PIXELFILE);

open( DATAFILE, "$ARGV[1]" ) or die "can't open data file";
while( my $line = <DATAFILE> ){ push @data, $line }
close(DATAFILE);

my $posCount = 0;
my $textX = 25;
my $textY = 20;
my $annotateRowIncrement = 150;

worldCompositeMap.pl プログラムのセクション 1 では、コマンド・ラインを検査し、背景画像を設定します。$blankMap 変数が新規 GD 画像として作成され、画像の幅は入力画像と同じ幅に、上部には注釈情報を保持するためのスペースが設定されます。その際、期待どおりに画像に色が付けられるようにモノクロの色が指定されます。オリジナルの plot-latlong の出力地図は、110 ピクセルに下げられて blankMap にコピーされます。

次のセクションでは、ピクセル座標を @pixels 配列にロードします。ピクセル値は worldCompositeMap.pl コードのセクション 2 で処理されます。@data 配列に情報 (今回の場合は、場所名と注釈画像名) を付けてロードする場合も、同じように処理されます。ここで使用するファイルには、対応する一連の項目があります。ピクセル・データ・ファイルの 1 行目には、都市データ・ファイルの 1 行目で指定された場所の座標が指定されます。worldCompositeMap.pl プログラムのセクション 2 では、データ・ファイル全体で処理が繰り返された後、画像に注釈が付けられます。

リスト 5. worldCompositeMap.pl セクション 2
for my $dataLine ( @data )
{
my( undef, undef, $pointX, $pointY) =  split " ", $pixels[$posCount];
my( $text, $faceImgName ) = split '##', $dataLine;

$blankMap->stringFT( $black, '/usr/share/fonts/bitstream-vera/Vera.ttf',
8,0,$textX,$textY, "$text", 
{   linespacing=>0.6,
charmap  => 'Unicode',
});

$blankMap->rectangle( $textX-10, 5, $textX+120, 100, $black);
$blankMap->line($textX+50, 100, $pointX, $pointY+$topMargin, $black );

my $faceImg = newFromPng GD::Image( $faceImgName );
$blankMap->copyResized( $faceImg, $textX,$textY+10, 0,0, 60,60, 115,115 );

$textX += $annotateRowIncrement;
$posCount++;

}#for each data line

open( TILEOUT,"> $ARGV[3]") or die "can't write $ARGV[3]";
print TILEOUT $blankMap->png;
close(TILEOUT);

データ配列の各行で、画像内の正確なピクセル座標を抽出します。指定のテキストと注釈の画像ファイル名をデータ配列から取得し、指定のテキストを画像に書き込みます。テキストが画像上に描画されたら、そのテキストの周りに細い黒色のボックスを作成して、そのボックスの底辺から関連データ・ポイントまで線を引きます。

次に、サイズ変更した注釈画像をロードして、それを指定のテキストの下にあるボックスにコピーします。その際、「現在」の位置が画像の右方向に指定の長さだけ移動される処理が繰り返し行われて、画像が描画されます。画像の描画が完了すると、プログラムが終了し、次のような出力が生成されます。

図 1. worldCompositeMap.pl サンプル出力
図 1. worldCompositeMap.pl サンプル出力
図 1. worldCompositeMap.pl サンプル出力

図 1 に示す画像ファイルを作成するには、コマンド perl worldComposite.pl cityPixels locationNames cityMap1.png worldCityMap_done.png を実行します。

線で囲われた部分の濃淡付けと、plot-latlong によるプロット

一般的な方法

米国地図上のさまざまな州に濃淡を付けることは、単にポイントをプロットすることで得られる情報以外に、別の情報チャネルを提供する効果的な手段です。下記コードと処理の説明により、比較的簡単な方法で、地図画像と plot-latlong プログラムを変更して実用的な濃淡付き米国地図を作成できます。

地図画像の変更

州 (または、線で囲われた他の部分) に濃淡を付けるときに、単純な GD->Fill コマンドを使用するのであれば、その囲われた内側の領域は連続していなければなりません。これまでに Redmond Paint や The Gimp の「Paint Bucket」ツールを使用したことがあれば、このコマンドの動作もすぐに理解できます。

特に、州地図の場合、Fill コマンドがうまく機能するように、地図上の州の境界線を変更する必要があります。変更には、州の境界線に対して Edge Enhance (エッジ強調) 効果とピクセル・レベルの編集を組み合わせて使用します。ミシガン州の半島になっている上の部分とそれ以外の部分や、2 つに分かれているメリーランド州が 1 つになるようにしてください。この変更を自分で行うか、または州の塗りつぶし用に提供されている画像と座標ファイルを使用してください。座標ファイル「state.coords」は、単なる経度/緯度のペア (通常、州都) で構成されており、GD->Fill コマンドではこのデータが使用されます。特定の地域や全世界の濃淡付け可能な地図を作成するには、濃淡付け可能な地域ごとに画像を編集したり、座標ファイルを作成したりして連続した領域となるようにする必要があります。

構成ファイルの変更

ダウンロード」セクションで入手した変更済みの米国各州の画像ファイル (statemap.png) を ~/.mapimages ディレクトリーにコピーします。次に、~/.mapinfo ファイルを変更して、新しい地図を plot-latlong に認識させます。以下の行を ~/.mapinfo ファイルにコピーしてください。

リスト 6. ~/.mapinfo の構成
MAP statemap statemap.png 50 -125 24 -66
MAP temporary temporary.png 50 -125 24 -66
PROJECTION statemap ALBER 2812.7  30.8 45.5 21.7 -99.9 929 1561
PROJECTION temporary ALBER 2812.7  30.8 45.5 21.7 -99.9 929 1561

plot-latlong のプロットの変更

州を 1 つにする処理が進行する過程で、temporary.png ファイルが作成されます。statemap.png ファイルは USA200.png 地図に基づいて作成されています。例えば Web ページなどで、オンデマンドで表示を行う場合、処理時間を短くするためにサイズの小さな地図を使用することは実用的と考えられかもしれません。ほかには、赤色のボックスの代わりに青色の円を描画するように、plot-latlong プログラムを変更する必要があります。これにより、別のレベルの情報が提供されます。また、この作業は GD を使用すれば簡単に実現することができます。plot-latlong で、リスト 7 に示す行をコメントアウトして、リスト 8 に示す行を挿入してください。

リスト 7. plot-latlong のボックス
$map->filledRectangle($left_x, $top_y,
$left_x + $point_size - 1, $top_y + $point_size - 1,
$red);
リスト 8. plot-latlong の円
my $blue = $map->colorAllocate(64,64,255);
$map->filledEllipse( $left_x + ($point_size/2), $top_y + ($point_size/2),
$point_size, $point_size,
$blue)

plot-latlong の濃淡付けの変更

plot-latlong ファイルをfillState_plot-latlong という名前のファイルにコピーします。このファイルを開いて、リスト 8 に示す行を削除します。削除した場所に、下記の行を挿入して、円や長方形を描画する代わりに連続している領域を塗りつぶします。

my $color = $map->colorAllocate(255, 255 - $value, 8);
$map->fill( $left_x, $top_y, $color);

my ($lat, $long) = split /\s+/; という行も my ($lat, $long, $value) = split /\s+/; に変更する必要があります。この 1 行を変更することで、上述の濃淡の程度を決定するパーセント値を読み込むことができます。

サンプル・パーセント・データ・ファイル

fillState_plot-latlong のコードを効果的に使用するには、適切なデータ・ファイルを構成する必要があります。これを実現する簡単な方法の 1 つとして、データの範囲を絞り込んで、すべてのデータが 0 から 100 までの値に収まるようにする方法があります。この場合、値が 0 のときは、濃いオレンジ色が使用され、値が 100 のときは、オレンジ色と黄色の中間色が使用されます。この方法では、州ごとの数量に関する情報内容を比較的直感的に理解することができ、また情報による濃淡が適切な範囲に収まるようになります。リスト 9 に、0 パーセントから 100 パーセントで各州に関連付けられたデータを示します。

リスト 9. サンプル usStatePercs ファイル
32.22434 -86.20379 75 #../../data/coords/AL.MONTGOMERY_
44.33064 -69.72971 98 #../../data/coords/ME.AUGUSTA_
33.51623 -112.02711 7 #../../data/coords/AZ.PHOENIX_
34.72240 -92.35407 11 #../../data/coords/AR.LITTLE_ROCK_
...

参考文献」で入手できる state.coords ファイルを使用するか、または各州の境界内に位置する座標で構成されたリストを独自に作成します。以下のコマンドを使用すれば、リスト 9 に示すようなサンプル・パーセント・ファイルを作成することができます。

cat state.coords | \
perl -lane '$r=int(rand(99));print "$F[0] $F[1] $r $F[2]"' >usStatesPercs

現在、usStatesPercs ファイルには、塗りつぶしを開始する場所の座標と、それに関連する州に該当する濃淡率が入っています。次の作業は、リスト 10 のコマンドで米国各州の濃淡および注釈付きの地図を都市のプロット付きで作成することです。最初のコマンドで、米国各州の濃淡付きの地図が作成されます。2 番目のコマンドで、この地図が、次のステップのベースの地図となるように、~/.mapimages ディレクトリーにコピーされます。さきほど世界地図を描画した場合と同様に、3 番目のコマンドで、濃淡付きの州地図に大きな青色の円が描画され、それぞれのピクセル座標が画像に記録されます。濃淡付きの地図にピクセル座標を使用することで、通常のボックス、画像、および線で画像に注釈が付けられます。

リスト 10 濃淡と注釈が合成された州地図を作成するコマンド
cat usStatesPercs | perl fillState_plot-latlong -m statemap -s 7 >usStates1.png

cp usStates1.png ~/.mapimages/temporary.png

cat usStatesCoords | \
perl plot-latlong -m temporary -s 20 -c >usStates2.png 2>usStatesPixels

perl stateCompositeMap.pl usStatesPixels stateData \
usStates2.png usStatesFinal.png

リスト 10 のコマンドにより作成された出力画像を以下に示します。

図 2. stateCompositeMap.pl サンプル出力
図 2. stateCompositeMap.pl サンプル出力
図 2. stateCompositeMap.pl サンプル出力

stateCompositeMap.pl プログラムは、「ダウンロード」セクションからダウンロードすることができます。stateCompositeMap.pl は worldCompositeMap.pl プログラムによく似ています。つまり、その変更作業は、さまざまな注釈コンポーネントを異なるサイズの基本画像に合わせることに向けられています。

今後の変更について

ここで述べた技法、位置情報取得モジュール、および地図作成ツールを使用すれば、地域に濃淡が付き、都市がプロットされた地図を作成する方法としては、無数の方法が考えられます。plot-latlong データ・ファイルを変更して、データの値や位置だけでなくさまざまな要素も読み込むようにした場合を検討してみてください。そうすれば、さらに多種多様の地図を作成できるようになります。また、長方形や円の代わりに、GD を使って地図上の特定のポイントに円グラフを描画してみてください。GD でピクセル座標間を接続して、出張販売員の活動地域を塗りつぶすこともできます。あるいは、指定した都市を囲むように、その都市に存在している組織の従業員数に応じた半径の円をアルファブレンディングによって表示することも検討してみてください。提供されるピクセル・データを使用すると、さまざまな地域のクリッカブル画像マップを自動的に作成することができます。ほかにも、時間とともにデータをプロットし、mencoder などを使用して画像から動画を作成することもできます。plot-latlong と GD を使用すれば、データを視覚化するためのほとんど無限の可能性が提供されるのです。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=249249
ArticleTitle=Perl、GD、および plot-latlong を使用して、データをプロットした地図を作成する
publish-date=04102007