User:Argrath/ksj-osm-road.pl

From OpenStreetMap Wiki
Jump to: navigation, search

国土数値情報統一フォーマットの道路データのインポート方法

  • http://nlftp.mlit.go.jp/ksj/old/cgi-bin/_kategori_view.cgi から「道路(線)」にチェックを入れて[選択]ボタンを押す。
  • インポートする都道府県にチェックを入れて[選択]ボタンを押す。
  • 「世界測地系」の方にチェックを入れて[選択]ボタンを押す。
  • 国土数値情報利用規約をよく確認して、納得したら[同意」ボタンを押す。
  • [ダウンロード]ボタンを押す。
  • *.zipファイルがダウンロードされるので、展開する。
  • 展開したファイルがあるディレクトリに、以下のプログラムを、ファイル名ksj-osm-road.pl、文字コードUTF-8で保存する。
  • 展開したディレクトリで、"perl ksj-osm-road.pl (道路データファイル名) N01_07L_台.txt"を実行する。
  • out.osmファイルが出来るので、オフラインエディタなどで調整後、アップロードする。


#! /usr/bin/perl -w

=pod

=head1 NAME

ksj-osm-road.pl - 固定長国土数値情報(道路データ)をosm形式に変換

=head1 SYNOPSIS

     perl ksj-osm-road.pl N01-07L-2K-27.txt N01_07L_台.txt

=head1 DESCRIPTION

第一引数に都道府県別の道路データファイル名を、第二引数にリンク台帳
データファイル名を指定すると、F<out.osm>に変換したosm形式データを
出力します。

=cut

use strict;
use warnings;
use utf8;

use Encode;

my @highway = qw(road motorway trunk primary secondary tertiary road road);

my %dl;

my %node;
my $newid = -1;

open my $fd, '<', $ARGV[1];
while(<$fd>){
    my (@l) = unpack('A3A10A3A2A24A22A16', $_);
    my %x = (
	type => $l[3],
	name => decode('Shift_JIS', $l[4]),
	subname => decode('Shift_JIS', $l[5]),
	abbr => $l[6],
	);
    $dl{$l[1]} = \%x;
}
close $fd;

open my $fl, '<', $ARGV[0];

open my $fw, '>:encoding(utf-8)', 'out.osm';

print $fw <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="ksj-osm-road.pl">
EOF
;

my %cite;


{
    $_ = <$fl>;
    my (@l) = unpack('A3A10A10A2A4A4', $_);
    my $ye = $l[4];
    my $yj = $ye - 1988;
    %cite = (
	# 引用情報
	created_by => 'National-Land-Numerical-Information_MLIT_Japan',
	note => "National-Land Numerical Information (Road) $ye, MLIT Japan $ARGV[0]",
	'note:ja' => "国土数値情報(道路データ)平成${yj}年 国土交通省 $ARGV[0]",
	source => 'KSJ2',
	source_ref => 'http://nlftp.mlit.go.jp/ksj/',
	'KSJ2:reviewed' => 'no',
	);
}

while(<$fl>){
    my $code = substr($_, 0, 3);
    if($code eq 'L  '){
	# 1行目
	my (@l) = unpack('A3A6A6A6A6A6A2A10A6', $_);
	my $c = $l[8];
	my $startid = $newid;
	my @nodelist = ();
	# 2行目以降
	for (my $i = 0; $i < $c; $i += 5){
	    my $s = <$fl>;
	    my (@ll) = unpack('A8A8A8A8A8A8A8A8A8A8', $s);
	    for(my $j = 0; $j < 5; $j++){
		if($ll[$j * 2] eq ''){last;}
		my $lon = $ll[$j * 2] / 36000;
		my $lat = $ll[$j * 2 + 1] / 36000;
		my $key = sprintf '%3.8f %3.8f', $lat, $lon;
		my $id = $node{$key};
		if(!defined $id){
		    $id = $newid--;
		    $node{$key} = $id;
		}
		push @nodelist, $id;
		printf $fw '<node id="%d" visible="true" lat="%3.8f" lon="%3.8f">' . "\n",
		$id, $lat, $lon;
		my %tag = %cite;
		foreach (sort keys %tag){
		    printf $fw '<tag k="%s" v="%s" />', $_, $tag{$_};
		}
		print $fw "</node>\n";
	    }
	}
	# ウェイ出力
	printf $fw '<way id="%d" action="modify" visible="true">', $newid--;
	foreach (@nodelist){
	    printf $fw '<nd ref="%d" />', $_;
	}
	my $dlx = $dl{$l[7]};
	my %tag = %cite;
	if(defined $dlx){ # 台帳に名前あり
	    my $name = $dlx->{name} . $dlx->{subname};
	    if($name =~ /([0-9]+)号/){ # (数値)号があったら追加処理
		my $ref = $1;
		$ref =~ tr/0-9/0-9/;
		$name =~ tr/0-9/0-9/;
		$tag{ref} = $ref;
		if($dlx->{type} == 2){ # 国道
		    $name .= " (Route $ref)";
		}
	    }
	    $tag{name} = $name;
	    $tag{highway} = $highway[$dlx->{type}];
	}
	foreach (sort keys %tag){
	    printf $fw '<tag k="%s" v="%s" />', $_, $tag{$_};
	}
	print $fw "</way>\n";
    }
}

print $fw "</osm>\n";
close $fw;
close $fl;