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時点