User:Konat/ksj2osm-river.pl
Jump to navigation
Jump to search
主たる用途
国土数値情報(河川データ)XMLをOpenStreetMapのXMLに変換するために用います。
説明
変換元データファイルの入手先
- 国土数値情報(河川データ)XMLファイル http://nlftp.mlit.go.jp/ksj/jpgis/datalist/KsjTmplt-W05.html
このスクリプトでできること
- 変換元の都道府県別河川データ丸ごと大きなOSM向けXMLデータを生成できます。
- 特定の河川指定でOSM向けXMLデータを生成できます。
生成するOSMデータについて
- 情報ソースを示すタグはWayにのみ付与しノードには付与しません。
- 水域ラベルは現時点[1]では殆ど提供されていないため生成しません(水域コードのみ生成)。
- Wayは基本的に waterway:riverで生成します。ただし、下記条件に一致する場合は、waterway:stream で生成します。
- 名称不明 は 一律 stream。
- COPが4(指定区間外),8(指定区間外かつ湖沼区間を兼ねる),0(不明)の何れかで、かつ、河川名称の末尾が 沢、谷、ヤツ、クボ、窪、入、俣、タルの何れかの場合。
- Wayにレイヤタグを一律設定します(デフォルト -1)
- 名称不明のwaterwayにname関連タグは付与しません。
- 一括変換の場合にはnameタグのみ付与します。他のname関連タグ(name:enなど)は付与しません。
実行環境について
- ksj2osm-river.pl と ksj2osm-river-rebuild.pl の2本セットで機能します。
- WindowsXP Pro環境でのみ動作確認を行っています。尚、Windows環境でのPerlおよび必要となるプラグインについては他のインポータスクリプトの要件と同等です。
スクリプトの使い方について
- ksj2osm-river.pl のヘッダを参照してください。
インポート作業について
- とある「わたし」のやりかた
- 分割されたウェイの重複ノードの排除。
- 隣接都道府県中のウェイに接続すべきウェイの重複ノードの排除。
- JOSMでValidationプラグインを利用可能にしておきます。
- JOSMに読み込みます。(都道府県別データを一括で読み込む場合は環境により時間が掛かります。)
- 「妥当性検証エラー」レイヤーをOFFにします。(おすすめ)
- "データの妥当性を検証"を実行します。
- レポートされるノードの複製を"エラー">"ノードの複製"から"修正"ボタンを押下して一括修正します。
- (ここで念のためデータを保存)
- OSMにアップロードします。(チャンクサイズ500とか1000とか・・・進捗を把握しやすいです)
- アップロードしたデータが隣接する他都道府県の境界周辺データをOSMよりダウンロードします。
- 境界周辺オブジェクトをマメに矩形選択して、都度、前掲と同様にノードの複製を修正し是正していきます。
- この変更をアップロード。
- アップロード中は作業マシンが自動的にrebootしたり電源が落ちないように配慮しましょう・・・changesetのrevertスクリプトを学ぶことになってしまいます。
コード
ksj2osm-river.pl
#! /usr/bin/perl
use strict;
use warnings;
# use encoding "utf8";
use encoding "utf8", STDIN => "shiftjis", STDOUT => "shiftjis", STDERR => "shiftjis"; # for Windows
use Encode;
use open IO => "utf8";
use XML::LibXML;
#####
#
# KSJ2 River Data
#
# National-Land Numerical Information (River) 2006, MLIT Japan
# 国土数値情報(河川データ)平成18年 国土交通省
#
# ・河川Wayは上流→下流でデータを生成します。
# ・情報ソースを示すタグはWayにのみ付与しノードには付与しません。
# ・水域ラベルは現状殆ど提供されていないため生成しません(水域コードのみ生成)
# ・Wayは基本的に waterway:riverで生成します。
# ただし、下記条件に一致する場合は、waterway:stream で生成します。
# - 名称不明 は 一律 stream。
# - $unknown_is_stream = "no" とすることで riverで出力可能。
# - COPが4(指定区間外),8(指定区間外かつ湖沼),0(不明)の何れかで、
# かつ、河川名称の末尾が 沢、谷、ヤツ、クボ、窪、入、俣、タルの何れかの場合。
# - $stream_on = "no" とすることで riverで出力可能。
# ・Wayにレイヤタグを一律設定します(デフォルト -1)
#
# 使い方
# ・UTF-8で保存した変換対象の国土数値情報(河川データ)のXMLファイルを
# 本スクリプトと同じフォルダに配置します。
# ・ksj2osm-revier-rebuild.pl を同じディレクトリに配置してください。
# ・スクリプトはすべて必ずUTF-8で保存してください。
# ・用途に応じて下記のパラメータを書き換えて本スクリプトを保存し実行します。
# - file_in : 変換対象河川情報XMLデータ(必須)
# - selected_river_name : 特定河川のみ変換する場合設定 例. 多摩川
# - selected_river_name_en : 特定河川のみ変換する場合設定 例. Tama-River
# - selected_river_name_jprm : 特定河川のみ変換する場合設定 例. Tamagawa
# - force_write_node : 特定河川のみ変換の際に全ノードを出力するか
# - need_to_write_node_detail_tag : ノードに詳細タグを付与して生成するか
# - layer : レイヤ・タグの数値(デフォルト:-1)
#
# 実行方法
#
# <用例.1> 河川データXML中のwaterwayを全変換する場合(つまり都道府県ごと一括)
#
# ksj2osm-river.pl 引数なし
#
# 但し、スクリプト内の下記のパラメータを予めすべて""(空文字)に設定しておくこと。
#
# ・$selected_river_name = "";
# ・$selected_river_name_en = "";
# ・$selected_river_name_jprm = "";
#
# <用例.2> 特定河川のみ変換する
# - 変換対象河川をスクリプト呼び出しパラメータで指定したい場合
#
# ※但し、Windows実行環境でのみ有効。Windows実行環境ではない場合は、用例3を参照のこと。
#
# ksj2osm-river.pl [変換対象河川名(日本語)] [ローマ字表記河川名] [英語表示河川名]
#
# ・変換対象河川名(日本語) : $selected_river_name相当
# ・ローマ字表記河川名 : $selected_river_name_jprm相当
# ・英語表示河川名 : $selected_river_name_en相当
#
# 例. ksj2osm-river.pl 多摩川 Tamagawa Tama-River
#
# <用例.3> 特定河川のみ変換する
# - 変換したい河川をスクリプト内埋め込み定義パラメータで指定したい場合
#
# ksj2osm-river.pl 引数なし
#
# ・selected_river_name : 特定河川のみ変換する場合設定 例. 多摩川
# ・selected_river_name_en : 特定河川のみ変換する場合設定 例. Tama-River
# ・selected_river_name_jprm : 特定河川のみ変換する場合設定 例. Tamagawa
#
# Files
# Input
# XML file : W05-08_*.xml
# Output
# Osm file : ksj2osm-river-nn[name:en]00n.osm
# または
# ksj2osm-river-nn-[name:en]-all.osm
#
# 本スクリプトについて
# miyabi氏公開の ksj2osm-coastline.pl をベースとし改造して作成したものです。
# 公開を前提にコードを修正してこなかったため、私しか読めないこんなものに仕上がりましたw
#
#
#####
#our $file_in = "W05-07_47"; # target file 沖縄
our $file_in = "W05-08_11"; # target file 埼玉
#our $file_in = "W05-08_13"; # target file 東京
#our $file_in = "W05-08_14"; # target file 神奈川
#our $file_in = "W05-07_17"; # target file 石川
#our $file_in = "W05-07_02"; # target file 青森
#our $file_in = "W05-07_42"; # target file 長崎
#our $file_in = "W05-07_41"; # target file 佐賀
#our $file_in = "W05-07_18"; # target file 福井
#our $file_in = "W05-07_16"; # target file 富山
# 特定の河川のみ変換したい場合、河川名をUTF-8で定義する。
# 全てのデータを変換したい場合、""を定義する。
# ※特定河川変換の場合、基本動作として生成するOSMファイルを分割しません。
# 但し、$force_write_node = "yes" とした場合は分割します。
#our $selected_river_name = "琴沢";
#our $selected_river_name = "野川";
#our $selected_river_name = "石神井川";
#our $selected_river_name = "北川";
our $selected_river_name = "";
# 特定の河川のみ変換したい場合、河川名ローマ字読みを定義する。
# 全てのデータを変換したい場合、""を定義する。
# ※このローマ字を定義した場合のみ、変換ファイル名(jprmを引用)と各タグ(name:en,name:jp_rm)に反映される。
# スペース入れないでね
#our $selected_river_name_jprm = "Tamagawa";
#our $selected_river_name_en = "Tama River";
our $selected_river_name_jprm = "";
our $selected_river_name_en = "";
#our $selected_river_name_jprm = "Shakujiigawa";
#our $selected_river_name_en = "Shakujii River";
#our $selected_river_name_jprm = "Nogawa";
#our $selected_river_name_en = "Ochisawa";
#our $selected_river_name_jprm = "Kita-Gawa";
#our $selected_river_name_en = "Kitagawa-River";
# ノード情報に詳細タグを付与しないで出力したい場合"no"
# ※但しWayには詳細タグを強制付与します。
our $need_to_write_node_detail_tag = "no" ;
# ※いろいろ書いてますがもはや yes のままで良いです。
# 特定河川変換の際にはノード情報も河川名を参照してマッチする
# ノード情報のみ出力しますが、Wayで参照するノード情報に河川名が
# 設定されておらず、ノード参照エラーとなる場合に"yes”と
# 定義することで、無関係なノードも出力しますがエラーには
# ならないようにします。
# この場合は出力OSMファイルを強制的に分割することで余計なノード数を減らします。
our $force_write_node = "yes" ;
# 特定の河川のみ変換した際に、分割されたOSMファイルを1つにまとめるか
# yes = まとめる ファイル名は ksj2osm-river-nn[name:en]-all.osm として出力。
# yes以外 = まとめない
# ※yesでまとめる指定をしても分割ファイルも出力されます。不要ですので手動で削除してください。
our $combine_all = "yes";
# 沢 などを waterway=stream で出力する場合は yes
# 条件は、COPが4(指定区間外),8指定区間外でか湖沼(),0(不明)の何れかで、
# かつ、河川名称の末尾が 沢、谷、ヤツ、クボ、窪、入、俣、タルの何れかの場合に適用する。
our $stream_on = "yes";
# さらに、COPは上記と同一条件で、「名称不明」をstreamで出力する場合
our $unknown_is_stream = "yes";
# レイヤ・タグ埋め込み数値
our $layer = -1 ;
# デバッグ用情報出力レベル
our $dbg_level = 98;
###################################################### you dont need to change
our $max_ways = 30; # for splitting output files.
#our $max_ways = 9999999; # for splitting output files.
our $max_nodes_per_file = 1500; # max nodes per a file
#our $max_nodes_per_file = 9999999; # max nodes per a file
our $file_name = "ksj2osm-river";
our $max_nodes_per_way = 1500; # max nodes per a way
our $current_osmfn;
our $any_valid_data_in_osmfile;
our @osm_ndref;
our $all_osmfn;
###################################################### you dont need to change
sub open_log() {
my $time = localtime(time);
open(LOG, ">$file_name.log");
print LOG "***** KSJ2 River Data 2006 : Start $time\n";
print "***** KSJ2 River Data 2006 : Start $time\n";
} # end sub open_log()
sub close_log() {
my $time = localtime(time);
print LOG "***** Done!: End $time\n";
close LOG;
print "***** Done!: End $time\n";
} # end sub close_log()
################# rebuild_osm_file が うまく動かない。。。 #################
sub is_print_node() {
my $id = $_[0];
foreach my $ndref ( @osm_ndref ) {
if ( $id eq $ndref->getAttribute('ref') ) { return (1 ); }
}
return ( 0 ) ;
}
sub rebuild_osm_file() {
my ($count_files) = @_;
my $osmfn = sprintf("%s-%s%s-%03d.osm", $file_name, substr($file_in,7,2),$selected_river_name_jprm,$count_files);
my $osmtempfn = ">__tempfile__$count_files.xml";
open(OSMTMP, $osmtempfn);
my $xml = XML::LibXML->new();
# my $osm_doc1 = $xml->parse_string($osmfn);
# print Dumper($osm_doc1)."\n";
my $osm_doc1 = $xml->parse_file("$osmfn") or die "can't parse $osmfn: $@";
my @osm_node = $osm_doc1->getElementsByTagName('node')->get_nodelist();
my @osm_way = $osm_doc1->getElementsByTagName('way')->get_nodelist();
@osm_ndref = $osm_doc1->getElementsByTagName('nd')->get_nodelist();
print OSMTMP "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print OSMTMP "<osm version=\"0.5\" generator=\"KSJ2OSM\">\n";
foreach my $way ( @osm_way ) {
printf OSMTMP ("%s\n",$way->toString(1));
}
foreach my $node ( @osm_node ) {
my $id = $node->getAttribute('id');
if ( &is_print_node( $id ) ne 0 ) { printf OSMTMP ("%s\n",$node->toString(1)); }
}
print OSMTMP "</osm>";
close OSMTMP;
} # end of rebuild_osm_file()
################# rebuild_osm_file が うまく動かない。。。 #################
sub open_osm_file() {
my ($count_files) = @_;
my $osmfn = ">";
$current_osmfn = sprintf("%s-%s%s-%03d.osm", $file_name, substr($file_in,7,2),$selected_river_name_jprm,$count_files);
$any_valid_data_in_osmfile = "no";
$osmfn .= $current_osmfn;
open(OSM, $osmfn);
print OSM "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print OSM "<osm version=\"0.5\" generator=\"KSJ2OSM\">\n";
} # end sub open_osm_file()
sub close_osm_file(){
my ($count_files) = @_;
print OSM "</osm>";
close OSM;
if ( $any_valid_data_in_osmfile eq "no" ) {
my $status_unlink = unlink( $current_osmfn );
} else {
## if ( $selected_river_name ne "" ) { &rebuild_osm_file($count_files); }
if ( $selected_river_name ne "" ) {
if ( $combine_all eq "yes" || $combine_all eq "yesopened" ) {
if ( $combine_all ne "yesopened" ) {
$combine_all = "yesopened";
$all_osmfn = sprintf("%s-%s-%s-all.osm", $file_name, substr($file_in,7,2),$selected_river_name_jprm);
print "FILENAME is ".$all_osmfn."\n";
open ALLOSM, ">"."$all_osmfn";
print ALLOSM "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print ALLOSM "<osm version=\"0.5\" generator=\"KSJ2OSM\">\n";
close ALLOSM;
}
system("ksj2osm-river-rebuild.pl $current_osmfn $all_osmfn");
} else {
system("ksj2osm-river-rebuild.pl $current_osmfn");
}
}
}
} # end sub close_osm_file()
# get AAC label in AdminAreaCd.xml from ASL code
sub get_aac_label(){
my $aac_code = $_[0];
my $aac_label = "no use";
### my $xml_aac = XML::LibXML->new();
### my $aac_doc = $xml_aac->parse_file("AdminAreaCd_090101.xml");
### my @aac_list = $aac_doc->getElementsByTagName('codelabel');
### foreach my $aac_list (@aac_list){
### my $aac_list_code = $aac_list->getAttribute('code');
### if($aac_code eq $aac_list_code){
### $aac_label = $aac_list->getAttribute('label');
### last;
### }
### }
return $aac_label;
} # end sub get_aac_label()
sub get_cop_label() {
my %hash = (
"1" => "1級直轄区間",
"2" => "1級指定区間",
"3" => "2級河川区間",
"4" => "指定区間外",
"5" => "1級直轄区間でかつ湖沼区間を兼ねる",
"6" => "1級指定区間でかつ湖沼区間を兼ねる",
"7" => "2級河川区間でかつ湖沼区間を兼ねる",
"8" => "指定区間外でかつ湖沼区間を兼ねる",
"0" => "不明"
);
return $hash{$_[0]};
} # end sub get_cop_label()
# set tag data for writing OSM file
sub write_osm_constant_tag(){
my $tags;
my %hash = (
"created_by" => "National-Land-Numerical-Information_MLIT_Japan",
"note" => "National-Land Numerical Information (River) 2006, MLIT Japan",
"note:ja" => "国土数値情報(河川データ)平成18年国土交通省",
"source" => "KSJ2",
"source_ref" => "http://nlftp.mlit.go.jp/ksj/jpgis/datalist/KsjTmplt-W05.html",
"KSJ2:filename" => $file_in . ".xml",
);
foreach my $key ( keys( %hash ) ){
$tags .= "<tag k=\"$key\" v=\"$hash{$key}\"/>";
}
return $tags;
} # end sub write_osm_constant_tag()
# create nd-tab data for write way to OSM file
sub create_nd_tag() {
my ($nd_tag_ref) = @_;
my $node_ref = "";
# for write way data to OSM file
foreach my $nd_tag ( @{$nd_tag_ref} ){
$node_ref .= $nd_tag;
} # end foreach my $nd_tag ( @node_ref )
return $node_ref;
}
# write way data to OSM file
sub write_osm_way_tag() {
my ($tag_id, $tag_data, $nd_data) = @_;
my $tags = sprintf("<way id=\"%d\" action=\"modify\" visible=\"true\">", $tag_id);
my $need_to_write = "no" ;
$tags .= &create_nd_tag($nd_data);
$tags .= &write_osm_constant_tag();
# $tags .= "<tag k=\"waterway\" v=\"river\"/>";
$tags .= "<tag k=\"layer\" v=\"$layer\"/>";
foreach my $key ( keys( %{$tag_data} ) ){
unless( $key eq "KSJ2:coordinate"
|| $key eq "KSJ2:lat"
|| $key eq "KSJ2:long"
|| $key eq "KSJ2:SOR"
|| $key eq "KSJ2:EOR"
|| $key eq "KSJ2:SOS"
|| $key eq "KSJ2:EOS"
|| $key eq "KSJ2:COP"
|| $key eq "KSJ2:ODC"
|| $key eq "KSJ2:ODC_label"
|| $key eq "KSJ2:WSC_label"
|| $key eq "KSJ2:RIC_label"
){
$tags .= "<tag k=\"$key\" v=\"$tag_data->{$key}\"/>";
if( $key eq "KSJ2:RIN" && !($tag_data->{$key} eq "名称不明") ){
if( $selected_river_name_jprm ne "" ) {
$tags .= "<tag k=\"name\" v=\"$tag_data->{$key} ($selected_river_name_jprm)\"/>";
} else {
$tags .= "<tag k=\"name\" v=\"$tag_data->{$key}\"/>";
}
if( $selected_river_name_en ne "" ) {
$tags .= "<tag k=\"name:en\" v=\"$selected_river_name_en\"/>";
}
$tags .= "<tag k=\"name:ja\" v=\"$tag_data->{$key}\"/>";
if( $selected_river_name_jprm ne "" ) {
$tags .= "<tag k=\"name:ja_rm\" v=\"$selected_river_name_jprm\"/>";
}
}
if( $key eq "KSJ2:RIN" && ( $tag_data->{$key} eq $selected_river_name || $selected_river_name eq "") ){
$need_to_write = "yes";
$any_valid_data_in_osmfile = "yes"
}
}
}
$tags .= "</way>";
if( $need_to_write eq "yes" ) {
print OSM $tags;
}
} # end sub write_osm_way_tag()
# write node data to OSM file
sub write_osm_node_tag() {
my $need_to_write = "no" ;
my ($tag_id, $hash, $coodinate) = @_;
# if $cordinate have data
if( defined( $coodinate ) ){
$hash->{"KSJ2:coordinate"} = $coodinate;
($hash->{"KSJ2:lat"}, $hash->{"KSJ2:long"}) = split(/\s/, $hash->{"KSJ2:coordinate"});
if ( $dbg_level >= 99 ) {
printf "pos = lat: %s / long: %s\n", $hash->{"KSJ2:lat"}, $hash->{"KSJ2:long"};
}
}
my $tags = sprintf("<node id=\"%d\" visible=\"true\" lat=\"%0.6f\" lon=\"%0.6f\">", $tag_id, $hash->{"KSJ2:lat"}, $hash->{"KSJ2:long"});
if ( $need_to_write_node_detail_tag eq "yes" ) { $tags .= &write_osm_constant_tag(); }
foreach my $key ( keys( %{$hash} ) ){
if ($key eq "KSJ2:river_id"
|| $key eq "KSJ2:curve_id"
|| $key eq "KSJ2:RIN"
|| $key eq "KSJ2:lat"
|| $key eq "KSJ2:long"
|| $key eq "KSJ2:coordinate" ){
if ( $need_to_write_node_detail_tag eq "yes" ) { $tags .= "<tag k=\"$key\" v=\"$hash->{$key}\"/>"; }
if( $key eq "KSJ2:RIN" && ( $hash->{$key} eq $selected_river_name || $selected_river_name eq "") ){
$need_to_write = "yes";
}
}
}
$tags .= "</node>";
if( $need_to_write eq "yes" || $force_write_node eq "yes" ) { print OSM $tags; }
return %{$hash};
} # end sub write_osm_node_tag()
# get the data of Attribute
sub get_attr_data() {
my $ksj_attr = $_[0];
my $tmp;
my %hash;
=pod
my %hash = (
"KSJ2:river_id" => $GB02_id
"KSJ2:WSC" => $wsc_code,
"KSJ2:WSC_label" => $wsc_label,
"KSJ2:LOC" => $LOC_idref,
"KSJ2:RIC" => $ric_code,
"KSJ2:RIC_label" => $ric_label,
"KSJ2:COP" => $cop_id,
"KSJ2:COP_label" => $cop_label,
"KSJ2:RIN" => $rin,
"KSJ2:SOS" => $sos_ref,
"KSJ2:EOS" => $eos_ref,
"KSJ2:ODC" => $odc_code,
"KSJ2:ODC_label" => $odc_label,
"KSJ2:DFD" => $dfd
"KSJ2:SOR" => $sor_ref,
"KSJ2:EOR" => $eor_ref,
"waterway" => $river_type
);
=cut
# get the Data of CP-id
$hash{"KSJ2:river_id"} = $ksj_attr->getAttribute('id');
# get code & label of WaterSystemCodeCd
$hash{"KSJ2:WSC"} = $ksj_attr->getChildrenByTagName('ksj:WSC')->get_node(0)->textContent;
$hash{"KSJ2:WSC_label"} = &get_aac_label( $hash{"KSJ2:WSC"} ); #+++ NO ACTION
# get the Data of LOC-idref
$hash{"KSJ2:LOC"} = $ksj_attr->getChildrenByTagName('ksj:LOC')->get_node(0)->getAttribute('idref');
# get code & label of RiverCodeCd
$hash{"KSJ2:RIC"} = $ksj_attr->getChildrenByTagName('ksj:RIC')->get_node(0)->textContent;
$hash{"KSJ2:RIC_label"} = &get_aac_label( $hash{"KSJ2:RIC"} ); #+++ NO ACTION
$hash{"KSJ2:COP"} = $ksj_attr->getChildrenByTagName('ksj:COP')->get_node(0)->textContent;
$hash{"KSJ2:COP_label"} = &get_cop_label( $hash{"KSJ2:COP"} ); #--- added
# get Name of river
if($ksj_attr->find('ksj:RIN')){
$hash{"KSJ2:RIN"} = $ksj_attr->getChildrenByTagName('ksj:RIN')->get_node(0)->textContent;
if( $hash{"KSJ2:RIN"} eq "不明" ){
$hash{"KSJ2:RIN"} = "名称不明";
}
}
$hash{"KSJ2:SOS"} = $ksj_attr->getChildrenByTagName('ksj:SOS')->get_node(0)->getAttribute('idref');
$hash{"KSJ2:EOS"} = $ksj_attr->getChildrenByTagName('ksj:EOS')->get_node(0)->getAttribute('idref');
# get code & label of OriginalDataCodeCd
$hash{"KSJ2:ODC"} = $ksj_attr->getChildrenByTagName('ksj:ODC')->get_node(0)->textContent;
$hash{"KSJ2:ODC_label"} = &get_aac_label( $hash{"KSJ2:ODC"} ); #+++ NO ACTION
# get Direction of the River
my $dfd_bool = $ksj_attr->getChildrenByTagName('ksj:DFD')->get_node(0)->textContent;
if ($dfd_bool eq 1){
$hash{"KSJ2:DFD"} = "流下方向判明";
}else{
$hash{"KSJ2:DFD"} = "流下方向不明";
}
$hash{"KSJ2:SOR"} = $ksj_attr->getChildrenByTagName('ksj:SOR')->get_node(0)->getAttribute('idref');
$hash{"KSJ2:EOR"} = $ksj_attr->getChildrenByTagName('ksj:EOR')->get_node(0)->getAttribute('idref');
$hash{"waterway"} = "river";
if ( $stream_on eq "yes" ) {
if ( $hash{"KSJ2:COP"} eq "4" ||
$hash{"KSJ2:COP"} eq "8" ||
$hash{"KSJ2:COP"} eq "0" ) {
if ( $hash{"KSJ2:RIN"} =~ /谷$/ ||
$hash{"KSJ2:RIN"} =~ /沢$/ ||
$hash{"KSJ2:RIN"} =~ /俣$/ ||
$hash{"KSJ2:RIN"} =~ /ヤツ$/ ||
$hash{"KSJ2:RIN"} =~ /タル$/ ||
$hash{"KSJ2:RIN"} =~ /窪$/ ||
$hash{"KSJ2:RIN"} =~ /クボ$/ ||
$hash{"KSJ2:RIN"} =~ /入$/ ||
( $unknown_is_stream eq "yes" && $hash{"KSJ2:RIN"} eq "名称不明" ) ) {
$hash{"waterway"} = "stream";
}
}
}
if ( $dbg_level >= 99 ) {
printf "---------------------------\n";
printf "GB02_id: %s\n", $hash{"KSJ2:river_id"};
printf "WSC: %d %s\n",$hash{"KSJ2:WSC"},$hash{"KSJ2:WSC_label"};
printf "LOC: %s\n", $hash{"KSJ2:LOC"};
printf "RIC: %d %s\n", $hash{"KSJ2:RIC"},$hash{"KSJ2:RIC_label"};
printf "COP: %d %s\n", $hash{"KSJ2:COP"},$hash{"KSJ2:COP_label"};
printf "RIN: %s\n", $hash{"KSJ2:RIN"};
printf "SOS-EOS: %s %s\n",$hash{"KSJ2:SOS"},$hash{"KSJ2:EOS"};
printf "DFD: %s\n", $hash{"KSJ2:DFD"};
printf "SOR-EOR: %s %s\n",$hash{"KSJ2:SOR"},$hash{"KSJ2:EOR"};
}
return %hash;
} # sub get_attr_data()
# get point data from KSJ file
sub get_ksj_point_data() {
my ($ksj_node) = @_ ;
my %hash;
my $coordinate = $ksj_node->getElementsByTagName('DirectPosition.coordinate')->get_node(0)->textContent;
return $coordinate;
} #end sub get_ksj_point_data()
sub main (){
if ( $#ARGV eq 2 ) {
$selected_river_name = decode 'Shiftjis', $ARGV[0];
$selected_river_name_jprm = $ARGV[1];
$selected_river_name_en = $ARGV[2];
}
printf ( "[NAME]:%s [Roman]:%s [Eng]:%s\n", $selected_river_name, $selected_river_name_jprm, $selected_river_name_en );
# for creating Element ID
my $negative_id = 0;
my $node_id;
my %node_ref_id = ();
my $node_per_file = 0; # nodes per a file
my $xml = XML::LibXML->new();
my $ksj_doc = $xml->parse_file("$file_in.xml");
# for sepalate files
my $count_files = 0;
my $count_way = 0;
my $file_start_id = 0;
&open_log();
&open_osm_file($count_files);
# この4行もはやどうでもいい
if ( $selected_river_name ne "" && !$force_write_node eq "yes" ) {
$max_ways = 9999999; # for splitting output files.
$max_nodes_per_file = 9999999; # max nodes per a file
}
if ( $selected_river_name eq "" ) {
$max_ways = 9999999; # for splitting output files.
$max_nodes_per_file = 9999999; # max nodes per a file
}
my @ksj_attr = $ksj_doc->getElementsByTagName('ksj:GB02')->get_nodelist();
my @ksj_way = $ksj_doc->getElementsByTagName('jps:GM_Curve')->get_nodelist();
my @ksj_node = $ksj_doc->getElementsByTagName('jps:GM_Point')->get_nodelist();
# get the data of Attribute
foreach my $ksj_attr (@ksj_attr){
# get the data of Attribute
my %ksj_tag = &get_attr_data($ksj_attr);
# write the ways only the selected river when the order river,
# or the all ways when no the selected river
if( $ksj_tag{"KSJ2:RIN"} eq $selected_river_name || $selected_river_name eq "" ){
=pod
my %hash = (
"KSJ2:river_id" => $GB02_id
"KSJ2:WSC" => $wsc_code,
"KSJ2:WSC_label" => $wsc_label,
"KSJ2:LOC" => $LOC_idref,
"KSJ2:RIC" => $ric_code,
"KSJ2:RIC_label" => $ric_label,
"KSJ2:COP" => $cop_id,
"KSJ2:COP_label" => $cop_label,
"KSJ2:RIN" => $rin,
"KSJ2:SOS" => $sos_ref,
"KSJ2:EOS" => $eos_ref,
"KSJ2:ODC" => $odc_code,
"KSJ2:ODC_label" => $odc_label,
"KSJ2:DFD" => $dfd,
"KSJ2:SOR" => $sor_ref,
"KSJ2:EOR" => $eor_ref,
"waterway" => $river_type
);
=cut
if ( $dbg_level >= 99 ) {
printf " -------------(%d)--------------\n",$count_files;
printf " GB02_id: %s\n", $ksj_tag{"KSJ2:river_id"};
printf " WSC: %d %s\n",$ksj_tag{"KSJ2:WSC"},$ksj_tag{"KSJ2:WSC_label"};
printf " LOC: %s\n", $ksj_tag{"KSJ2:LOC"};
printf " RIC: %d %s\n", $ksj_tag{"KSJ2:RIC"},$ksj_tag{"KSJ2:RIC_label"};
printf " COP: %d %s\n", $ksj_tag{"KSJ2:COP"},$ksj_tag{"KSJ2:COP_label"};
printf " RIN: %s\n", $ksj_tag{"KSJ2:RIN"};
printf " SOS-EOS: %s %s\n",$ksj_tag{"KSJ2:SOS"},$ksj_tag{"KSJ2:EOS"};
printf " DFD: %s\n", $ksj_tag{"KSJ2:DFD"};
printf " SOR-EOR: %s %s\n",$ksj_tag{"KSJ2:SOR"},$ksj_tag{"KSJ2:EOR"};
}
# get the data of Line
foreach my $ksj_way (@ksj_way){
# for create "<nd>" tag
my $node_ref = "";
my @nd_tag = ();
my $node_count = 0;
my %temp_node_data = ();
my $gm_curve_id = $ksj_way->getAttribute('id');
# Routine when agreeing to information that data of acquired line targets.
if($gm_curve_id eq $ksj_tag{"KSJ2:LOC"}){
$ksj_tag{"KSJ2:curve_id"} = $gm_curve_id;
# write way data to OSM file
#### &write_osm_way_tag($negative_id, \%ksj_tag);
# get the data of Point
my @ksj_way_node = $ksj_way->getElementsByTagName('GM_PointArray.column')->get_nodelist();
foreach my $ksj_way_node (@ksj_way_node){
$node_count++;
# sequence for sepalate file
if( ($count_way >= $max_ways) || ( $node_per_file >=$max_nodes_per_file)){
&close_osm_file($count_files);
$count_way = 0;
$node_per_file = 0;
$count_files++;
&open_osm_file($count_files);
$file_start_id = $negative_id;
$negative_id--;
# setting nt-tag for conect ways between separate files
if( keys(%temp_node_data) ){
&write_osm_node_tag($negative_id, \%temp_node_data);
@nd_tag = sprintf("<nd ref=\"%d\" />", $negative_id );
}
}
$negative_id--;
$node_id = $negative_id;
# Routine when acquired point is reference data.
if($ksj_way_node->find('jps:GM_Position.indirect')){
my $ksj_point_ref = $ksj_way_node->getElementsByTagName('GM_PointRef.point')->get_node(0)->getAttribute('idref');
foreach my $ksj_node (@ksj_node){
my $ksj_point_id = $ksj_node->getAttribute('id');
# Routine when it is point in line that data of acquired point targets.
if ( ($ksj_point_id eq $ksj_point_ref) ){
if( !exists($node_ref_id{"$ksj_point_id"}) || ($node_ref_id{"$ksj_point_id"} > $file_start_id) ){
# get Point data & write node to OSM file
my $pos_coodinate = &get_ksj_point_data($ksj_node);
%temp_node_data = &write_osm_node_tag($node_id, \%ksj_tag, $pos_coodinate);
$node_ref_id{"$ksj_point_id"} = $node_id;
}else{
$node_id = $node_ref_id{"$ksj_point_id"};
}
last;
} # end if ($ksj_point_id eq $ksj_point_ref)
} # end foreach my $ksj_node (@ksj_node)
} # end if($ksj_way_node->find('jps:GM_Position.indirect'))
# Routine when acquired point is direct data.
elsif($ksj_way_node->find('jps:GM_Position.direct')){
# get Point data & write node to OSM file
my $direct_pos_coodinate = &get_ksj_point_data($ksj_way_node);
%temp_node_data = &write_osm_node_tag($node_id, \%ksj_tag, $direct_pos_coodinate);
} # end elsif($ksj_way_node->find('jps:GM_Position.direct'))
# for write way data to OSM file
push( @nd_tag, sprintf("<nd ref=\"%d\" />", $node_id ) );
if( $node_count >= $max_nodes_per_way ){
$negative_id--;
# write way data to OSM file
&write_osm_way_tag($negative_id, \%ksj_tag, \@nd_tag);
$node_ref = "";
# setting nt-tag for conect ways
@nd_tag = sprintf("<nd ref=\"%d\" />", $node_id );
$count_way++; # count ways for separating OSM file
$node_per_file += $node_count;
$node_count = 0;
}
} # end foreach my $ksj_way_node (@ksj_way_node)
$negative_id--;
# write way data to OSM file
&write_osm_way_tag($negative_id, \%ksj_tag, \@nd_tag);
$node_ref = "";
$count_way++; # count ways for separating OSM file
$node_per_file += $node_count;
} # end if($gm_curve_id eq $ksj_tag{"KSJ2:LOC"})
} # end foreach my $ksj_way (@ksj_way)
} # end if( $ksj_tag{"KSJ2:RIN"} eq $selected_river_name || $selected_river_name eq "" )
} # end foreach my $ksj_attr (@ksj_attr)
&close_osm_file($count_files);
&close_log();
if ( $combine_all eq "yesopened" ) {
open ALLOSM, ">>".$all_osmfn;
print ALLOSM "</osm>";
close ALLOSM;
}
} # end main()
main();
ksj2osm-river-rebuild.pl
#! /usr/bin/perl
use strict;
use warnings;
# use encoding "utf8";
use encoding "utf8", STDOUT => "shiftjis", STDERR => "shiftjis"; # for Windows
use Encode;
use open IO => "utf8";
use XML::LibXML;
our @osm_ndref;
sub is_print_node() {
my $id = $_[0];
foreach my $ndref ( @osm_ndref ) {
if ( $id eq $ndref->getAttribute('ref') ) { return (1 ); }
}
return ( 0 ) ;
}
sub main() {
my $osmfilein = $ARGV[0];
my $osmtempfn = "__tempfile__.xml";
open(OSM, ">".$osmtempfn);
my $xml = XML::LibXML->new();
# my $osm_doc = $xml->parse_file("ksj2osm-river-13Kuromegawa-025.osm");
# my $osm_doc = $xml->parse_file("ksj2osm-river-13Shakujiigawa-016.osm");
my $osm_doc = $xml->parse_file("$osmfilein");
my @osm_node = $osm_doc->getElementsByTagName('node')->get_nodelist();
my @osm_way = $osm_doc->getElementsByTagName('way')->get_nodelist();
@osm_ndref = $osm_doc->getElementsByTagName('nd')->get_nodelist();
printf OSM ("<osm version=\"0.5\" generator=\"KSJ2OSM\">\n");
if ( $#ARGV gt 0 ) { my $allsomfn = $ARGV[1]; open(ALLOSM, ">>".$allsomfn ); }
foreach my $way ( @osm_way ) {
printf OSM ("%s\n",$way->toString(1));
if ( $#ARGV gt 0 ) { printf ALLOSM ("%s\n",$way->toString(1)); }
}
foreach my $node ( @osm_node ) {
my $id = $node->getAttribute('id');
if ( &is_print_node( $id ) ne 0 ) {
printf OSM ("%s\n",$node->toString(1));
if ( $#ARGV gt 0 ) { printf ALLOSM ("%s\n",$node->toString(1)); }
}
}
printf OSM ("</osm>\n");
close OSM;
if ( $#ARGV gt 0 ) { close ALLOSM; }
my $rm_stat = unlink ( $osmfilein );
##printf( "unlink:%d - %s\n",$rm_stat, $osmfilein );
my $mv_stat = rename ( "$osmtempfn" , "$osmfilein" );
##printf( "rename:%d - %s -> %s\n",$mv_stat, $osmtempfn, $osmfilein );
}
main();
ksj2osm-river-getriver.pl
- おまけスクリプト
- 同一フォルダ中に配置されたすべての国土数値情報(河川データ)XMLファイルから、河川名一覧(水域コード6桁+河川名でsort | uniq)を標準出力にリストします。
- 例えば、W05-08_11.xml(埼玉)、W05-08_13.xml(東京)、W05-08_14.xml(神奈川)があれば、それらを総ナメしてリストします。
- 河川名一覧をテキストファイルに保存するようにコードを追加しました。 (2010.09.23)
- 同一フォルダ中に配置されたすべての国土数値情報(河川データ)XMLファイルから、河川名一覧(水域コード6桁+河川名でsort | uniq)を標準出力にリストします。
#! /usr/bin/perl
use strict;
use warnings;
# use encoding "utf8";
use encoding "utf8", STDOUT => "shiftjis", STDERR => "shiftjis"; # for Windows
use Encode;
use open IO => "utf8";
use XML::LibXML;
our @osm_ndref;
sub is_print_node() {
my $id = $_[0];
foreach my $ndref ( @osm_ndref ) {
if ( $id eq $ndref->getAttribute('ref') ) { return (1 ); }
}
return ( 0 ) ;
}
sub main() {
my %river_hash;
my $total_GB02 = 0;
my $count_GB02;
my @river_array;
my @river_array_sorted;
my $dir = ".";
opendir(DIR, "$dir");
my @files = readdir(DIR);
closedir(DIR);
open(RIVER_LST, '>', "River-List.txt");
foreach my $osmfile ( @files ) {
next if ( ! ( $osmfile =~ /W[0-9][0-9]-[0-9][0-9]_[0-9][0-9]\.xml$/ ) ) ;
print "$osmfile\n";
print RIVER_LST "$osmfile\n";
my $xml = XML::LibXML->new();
my $osm_doc = $xml->parse_file("$osmfile");
my @osm_GB02 = $osm_doc->getElementsByTagName('ksj:GB02')->get_nodelist();
$count_GB02 = 0;
foreach my $GB02 ( @osm_GB02 ) {
push ( @river_array,
$GB02->getChildrenByTagName('ksj:WSC')->get_node(0)->textContent . " "
. $GB02->getChildrenByTagName('ksj:RIN')->get_node(0)->textContent) ;
$count_GB02 ++;
}
$total_GB02 += $count_GB02;
print " $count_GB02 GB02 - total $total_GB02\n";
print RIVER_LST " $count_GB02 GB02 - total $total_GB02\n";
}
### foreach my $key ( sort @river_array ) {
### print "$key\n";
### }
@river_array_sorted = sort @river_array;
print $river_array_sorted[0]."\n";
for ( my $i = 1; $i < $total_GB02; $i++ ) {
if ( $river_array_sorted[$i] ne $river_array_sorted[$i-1] ) {
print $river_array_sorted[$i]."\n";
print RIVER_LST $river_array_sorted[$i]."\n";
}
}
close RIVER_LST;
}
main();
最後に
本スクリプトは、miyabi氏公開の ksj2osm-coastline.pl [1] をベースとし改造して作成したものです。 公開を前提にコードを修正してこなかったため、私しか読めないこんなものに仕上がりました。ご了承ください。無論、改良大歓迎です。
「このコードを読み解く時間があるのなら、野に出てロギングしてきたほうがマシだ」 -- マッパー・ダッカー
脚注
- ↑ 2010/5時点