OpenStreetMapのplanetファイル(.osm.bz2)から地域データをメッチャ沢山切り出すbash


概要

OpenStreetMapのplanetファイルはかなり大きなサイズですので、Planetから各地域のデータを切り出すのはかなり時間がかかります。
さらに、複数の多くの地域を切り出すとなると、メッチャ時間が掛かります。
さらにさらに、時系列の複数のPlanetファイルから切り出すとなると、もう気が遠くなります。

それを効率よく切り出すためのアイデアです。

準備

planet files

planetフィルは、 http://planet.openstreetmap.org/ からダウンロードします。
以下では、約9年分、96ファイルの処理を行います。

# planet date list
planet_date_list=(    090421 090506 090603 090708 090805 090902 091007 091104 091202 \
 100106 100203 100303 100401 100505 100602 100707 100804 100901 101006 101103 101201 \
 110105 110202 110302 110406 110504 110602 110706 110803 110907 111005 111102 111207 \
 120104 120201 120307 120401 120508 120613 120704 120801 120912 121017 121107 121205 \
 130102 130206 130304 130417 130502 130606 130703 130814 130904 131002 131103 131203 \
 140101 140205 140305 140401 140507 140604 140703 140806 140903 141008 141105 141203 \
 150105 150202        150406 150504 150601 150713 150803 150907 151005 151102 151207 \
 160104 160201 160307 160404 160502 160606 160704 160801 160912 161003 161107 161205 \
 170102 170206 170306 170403)

切り出す地域 poly

地域を切り出すpolyファイルが必要です。
polyファイルは、このあたりからダウンロードできます。 http://download.geofabrik.de/
以下では、50地域くらいの処理をしています。
切り出すデータのサイズが大きい順に並べると、より効率的に処理できると思います。

# region list : 49 + 2 regions
region_list=( russia-european-part russia-asian-part \
    us-pacific us-northeast us-west us-south us-midwest \
    france  japan germany united_kingdom spain netherlands slovakia haiti monaco \
    czech belgium luxembourg new-zealand philippines south-korea taiwan india \
    mexico cuba argentina italy switzerland denmark china canada australia \
    finland brazil morocco colombia ecuador iran thailand  south-africa-and-lesotho\
    indonesia croatia lithuania greece romania ireland-and-northern-ireland \
    turkey  portugal belarus slovenia norway hungary sweden ukraine poland austria chile )

osmosis

OSMのデータを扱うライブラリです。インストールしてください。

xargs

xargsで、並列の処理をしています。
以下では、8coreで書いてありますが、環境に合わせて書き換えてください。

dir

コード内の、各ファイルのディレクトルの指定は、環境に合わせて適時書き換えてください。

切り出し処理

bash コード

以下が、bashのコードです。
全ての処理が完了すると、5000くらいのファイルが出力される筈です。
普通にシリアルに処理すると、1〜2年くらいかかるかと・・・。たぶん。環境にもよるけど。
以下で処理すると、たぶん半年くらいで出力できるんじゃないかな・・・・。たぶん。保証はできませんが。

planet_to_region.sh
#!/bin/bash

# planet_dir
planet_dir=/osm/planet

# region_dir
region_dir=/osm/region

# poly_dir
poly_dir=/osm/poly

# temp_dir
#temp_dir=/osm/temp

#prefix
prefix=pla2reg

# planet date list
planet_date_list=(    090421 090506 090603 090708 090805 090902 091007 091104 091202 \
 100106 100203 100303 100401 100505 100602 100707 100804 100901 101006 101103 101201 \
 110105 110202 110302 110406 110504 110602 110706 110803 110907 111005 111102 111207 \
 120104 120201 120307 120401 120508 120613 120704 120801 120912 121017 121107 121205 \
 130102 130206 130304 130417 130502 130606 130703 130814 130904 131002 131103 131203 \
 140101 140205 140305 140401 140507 140604 140703 140806 140903 141008 141105 141203 \
 150105 150202        150406 150504 150601 150713 150803 150907 151005 151102 151207 \
 160104 160201 160307 160404 160502 160606 160704 160801 160912 161003 161107 161205 \
 170102 170206 170306 170403)

# region list : 49 + 2 regions
region_list=( russia-european-part russia-asian-part \
    us-pacific us-northeast us-west us-south us-midwest \
    france  japan germany united_kingdom spain netherlands slovakia haiti monaco \
    czech belgium luxembourg new-zealand philippines south-korea taiwan india \
    mexico cuba argentina italy switzerland denmark china canada australia \
    finland brazil morocco colombia ecuador iran thailand  south-africa-and-lesotho\
    indonesia croatia lithuania greece romania ireland-and-northern-ireland \
    turkey  portugal belarus slovenia norway hungary sweden ukraine poland austria chile )

######### function option {region} {date}
func_extract_region ()
{
    # planet_dir
    planet_dir=/osm/planet
    # region_dir
    region_dir=/osm/region
    # poly_dir
    poly_dir=/osm/poly

    temp_osm_data=$planet_dir/planet-$2.osm
    region_file=$region_dir/$1/$1-$2.osm.bz2

    if [ ! -e $region_file ];then
        echo -- making  $1 : $region_file
        osmosis --read-xml file=$temp_osm_data --bounding-polygon file=$poly_dir/$1.poly --write-xml file=- | bzip2 > $region_file
    fi
}

cd $planet_dir

#### array
for date in ${planet_date_list[@]};do

    temp_osm_data=$planet_dir/planet-$date.osm
    data_flag=0

    region_make_list=()
    for region in ${region_list[@]};do
        if [ ! -e $region_dir/$region/$region-$date.osm.bz2 ]; then
            data_flag=1
            region_make_list=(${region_make_list[@]} $region)
        fi
    done
    echo ---- $date : ${region_make_list[*]}

    if [ 1 -eq $data_flag ]; then
        echo = = = = = = = = = = =
        echo `date +"%Y/%m/%d %H:%M:%S"` ===== extracting planet-$date.osm.bz2
        echo - - - - - - - - - - - - - - - - to $temp_osm_data
        bzip2 -dk $planet_dir/planet-$date.osm.bz2

        echo  `date +"%Y/%m/%d %H:%M:%S"` ---- making region files -- $date
        export -f func_extract_region
        (for region in ${region_make_list[@]};do echo $region ; done) | xargs -n8 -P8 -I % bash -c "func_extract_region % $date"
    fi

    if [ -e $temp_osm_data ]; then
        echo `date +"%Y/%m/%d %H:%M:%S"` ===== Delete Temp file
        echo - - - - - - - - - - - - - - - - - Deleting $temp_osm_data
        rm $temp_osm_data
    fi

done

まとめ

良い子は真似しない方がいいかもしれません。
数ヶ月くらい時間の余裕のある紳士淑女にはオススメです。