第7章 3D地形図エンジン
著者:梅谷 武
語句:3D地形図エンジン, ITRF, WGS84, ジオイド, GRS80, 地域メッシュ, 1次メッシュ, 2次メッシュ
ToposNoteの3D地形図エンジンについて述べる。
作成:2010-03-11
更新:2011-03-08
 測地系とは地球上の位置を表すための空間座標系です。原点を地球の中心にとり、X-Y平面は赤道面、Z軸は地球の自転軸に一致するように定められます。現在の日本では測量法において、ITRF国際地球基準座標系に準拠した世界測地系を使うことが定められていますが、これは米国のGPSGlobal Positioning Systemで採用されているWGS84との差がcmのオーダーであり、実質的には同じものと考えることが出来ます。ToposNoteはこの世界測地系を採用しています。
 地球の形は回転楕円体として近似できます。地表面の形をより正確に近似するためにガウスJohann Carl Friedrich Gauss, 1777-1855は平均海水面と一致する重力の等ポテンシャル面で近似する方法を提案し、これをジオイドgeoidと名付けました。地球内部の密度分布が一様で無いことから、ジオイドは回転楕円体にはなりません。そこでジオイドを回転楕円体で近似することが必要になってきます。このジオイドを近似する回転楕円体として、さまざまなものが提案されています。現在では1979年の国際測地学地球物理学連合(IUGG)総会で採用されたGRS80が最もよい近似であるとされています。WGS84で採用している回転楕円体とGRS80との差は1mm以下であり、これも実質的には同じものと考えることが出来ます。
 日本では2002年3月31日まで、東京湾平均海面を基準としたベッセル楕円体を使って、独自の天文観測により測定された日本測地系が使われていましたが、これは世界測地系と比較すると東京付近で400m程度の差があります。現状、日本国内においては、旧日本測地系による地図と世界測地系による地図が混在しており、完全に世界測地系に移行するまでにはまだ時間がかかるものと予想されます。
 国土地理院発行の地図においても、世界測地系と旧日本測地系の違いは、新図郭と旧図郭の違いとなって現れます。ToposNoteではこれらが混在する問題に対しては、旧図郭の地図を新図郭に変換する機能で対応しています。
 ToposNoteは便宜上、幾何座標系(Cx,Cy,Cz)と測地座標系(Lat,Lng,Alt)を次の変換式により対応させています。
Lng
=
Cx
360.0
+ K0
Lat
=
Cy
360.0 × Rik
+ I0
Alt
=
250.0 × Cz
                    K0
=
139.75
I0
=
35.666666666666667
Rik
=
1.2254309136009816
この変換により世界座標系の原点に対応する場所は、測量法における日本経緯度原点とは異なり、日本経緯度原点に最も近い2次メッシュの基準点となります。
 曲面を平面に写していますから、角度や距離が正確に保たれませんが、数十kmの範囲の局所的な領域を考えている分には、一般的な利用には十分な近似になっています。但し、測量目的で利用することはできません。より広範囲の領域を考えるときには、Google Earthのような電子地球儀が必要になってきます。
地域メッシュとは、日本国内各地域を統計的に取り扱うために、緯線・経線によりほぼ同じ面積になるように網目状に区分したもので、 それを符号付けしたものが地域メッシュコードです。昭和48年の行政管理庁(現総務省)告示「統計に用いる標準地域メッシュおよび標準地域メッシュ・コード」が1976年にJIS化されて現在に至っています。
 面積が大きい順に1次メッシュ、2次メッシュ、3次メッシュと細分されますが、ToposNoteにおいては1次メッシュと2次メッシュのみを利用しています。1次メッシュは国土地理院発行の1/200000地勢図一枚に対応する4桁の数字で、2次メッシュは同じく1/25000地形図一枚に対応する6桁の数字です。
 日本の領土範囲は、東西が東経122度から154度まで、南北が北緯20度から46度までとなっています。1次メッシュはこの範囲を東西は1度単位で32に、南北は40分単位で39に分割します。これにより、日本の領土は1248区画に分割されますが、各区画の南西端の緯度を1.5倍すると2桁の整数になり、経度から100を引いた数も2桁の整数となります。これらの数を緯度経度の順に並べて作った4桁の数を、この区画の1次メッシュコードと定義します。
 Pythonを使った計算例を示します。
算譜7.1.3.6 1次メッシュコードの計算
# coding: utf-8
 
def LatLng2FirstMeshCode( lat, lng ):
if ( ( lat < 20.0 ) or ( lat >= 46.0 ) ):
print "エラー:緯度が範囲を超えています。"; return;
if ( ( lng < 122.0 ) or ( lng >= 154.0 ) ):
print "エラー:経度が範囲を超えています。"; return;
latd = int( lat * 1.5 );
lngd = int( lng - 100.0 );
print "%d%d" % ( latd, lngd )
 
def FirstMeshCode2LatLng( code ):
latd = int( code[0:2] );
lngd = int( code[2:4] );
if ( ( latd < 30 ) or ( latd >= 69 ) ):
print "エラー:緯度が範囲を超えています。"; return;
if ( ( lngd < 22 ) or ( lngd >= 54 ) ):
print "エラー:経度が範囲を超えています。"; return;
lat = latd / 1.5;
lng = lngd + 100.0;
print "(%f,%f)" % ( lat, lng )
 
LatLng2FirstMeshCode( 34.1, 136.1 );
FirstMeshCode2LatLng( "5136" )
 
LatLng2FirstMeshCode( 19.1, 136.1 );
FirstMeshCode2LatLng( "5160" )
5136
(34.000000,136.000000)
エラー:緯度が範囲を超えています。
エラー:経度が範囲を超えています。
2次メッシュは、1次メッシュの一区画を、東西に7分30秒単位、南北に5分単位で、それぞれ8等分し、64区画に分割します。これはいわゆる八佾はちいつの並び方です。南北の行に南から北に向かって0から7までの数を割り当て、東西に西から東に向かって0から7までの数を割り当てることにより、各区画をこれらをこの順に並べた2桁の数で表し、1次メッシュコードにこの2桁の数を加えた6桁の数を、この区画の2次メッシュコードと定義します。
 Pythonを使った計算例を示します。
算譜7.1.3.11 2次メッシュコードの計算
# coding: utf-8
 
def LatLng2SecondMeshCode( lat, lng ):
# 範囲検査
if ( ( lat < 20.0 ) or ( lat >= 46.0 ) ):
print "エラー:緯度が範囲を超えています。"; return;
if ( ( lng < 122.0 ) or ( lng >= 154.0 ) ):
print "エラー:経度が範囲を超えています。"; return;
# 緯度・経度を秒単位の整数で表す。
latd = int( lat );
tmp  = ( lat - latd ) * 60.0;
latm = int( tmp );
lats = int( int( ( tmp - latm ) * 60.0 * 1000.0 ) / 1000.0 );
lngd = int( lng );
tmp  = ( lng - lngd ) * 60.0;
lngm = int( tmp );
lngs = int( int( ( tmp - lngm ) * 60.0 * 1000.0 ) / 1000.0 );
I = latd * 3600 + latm * 60 + lats;
K = lngd * 3600 + lngm * 60 + lngs;
# 2次メッシュコード表示
print "%d%d%d%d" % ( (I/2400)%100, (K/3600)%100, \
(I%2400)/300, (K%3600)/450 )
 
def SecondMeshCode2LatLng( code ):
# 2次メッシュコード文字列分解
lat1 = int( code[0:2] );
lng1 = int( code[2:4] );
lat2 = int( code[4:5] );
lng2 = int( code[5:6] );
# 範囲検査
if ( ( lat1 < 30 ) or ( lat1 >= 69 ) ):
print "エラー:緯度が範囲を超えています。"; return;
if ( ( lng1 < 22 ) or ( lng1 >= 54 ) ):
print "エラー:経度が範囲を超えています。"; return;
# 緯度・経度を秒単位の整数で表す。
I = lat1 * 2400 + lat2 * 300;
K = ( lng1 + 100 ) * 3600 + lng2 * 450;
# 度単位に変換し、表示する。
lat = I / 3600.0;
lng = K / 3600.0;
print "(%f,%f)" % ( lat, lng )
 
LatLng2SecondMeshCode( 34.345, 136.234 )
SecondMeshCode2LatLng( "513641" )
513641
(34.333333,136.125000)
 ToposNoteの3D地形図エンジンは、国土地理院発行の1/25000地形図を10mメッシュ標高データにより作成した地形ポリゴンに貼り付けて、立体的に見ることを目的として設計されています。特に山登りを含むようなフィールドワークの計画・実施・データ整理の各段階で統一的に利用することを想定しています。
 そのため、ゲームマシンのようなハイスペックのマシンから、現場で持ち歩く携帯用PCまで使えるようなスケーラビリティを持たせるために、エンジンの動作パラメータをマシンに合わせて設定できるようになっています。
 リアルタイムレンダリングのために、10mメッシュ標高データのもつ精緻な地形表現を犠牲にして、10mメッシュを平均化により50mメッシュに変換してポリゴン数を減らしています。このために実際に地形と比べるとややなまったような曲面になっています。また、大まかなナビゲーションのため、ズームを引いたときに1/200000地勢図に切り替えるようになっています。このときはポリゴンを使わず、平面表示します。
 プログラムをインストールした直後の初期状態では、地図データが存在しませんので、必要に応じて国土地理院発行の次の3種類のデータをインストールしなければなりません。
  1. 10mメッシュ標高データ(基盤地図情報):オンライン/無料
  2. 数値地図25000(地図画像):オンライン・CD-ROM/有料
  3. 数値地図200000(地図画像):CD-ROM/有料
 ToposNoteはこれらのデータを内部形式に変換して保存します。この内部形式に準じたファイルを用意すれば、ユーザーが独自に作成した地図を表示することもできます。
 カーソル位置が、例えば(東経136.357度, 北緯34.258度)であるとしましょう。この地点は1次メッシュ5136、2次メッシュ513632に属します。このとき、3D地形図エンジンは次のような図形を描画します。
 九つの1次メッシュ区画に一致する長方形を描き、その上にMAP200000下の対応する地図画像それぞれテクスチャマッピングします。
1/200000モード時
 九つの2次メッシュ区画について、DEM50下の対応する標高データから地形ポリゴンを生成し、MAP25000下の対応する地図画像それぞれテクスチャマッピングします。
1/25000モード時
 カーソル位置の3D地図が一度描画されると、カーソルが中央の区画内にある限り、描画データは同じですが、カーソルが区画の境界を横切り、九つのメッシュコードの組が変化すると、3D地図は最初から描画し直されます。このとき、すべてのデータがファイルから読み込まれるとすると、かなり時間がかかり、応答性が悪くなります。この待ち時間を短縮するために、一度ファイルから読み込んだデータをそのまま物理メモリ上に置いておくためのキャッシュ機構が組み込まれています。
 キャッシュには次の4種類があり、最も使われていないデータが最初に捨てられるLRUアルゴリズムで実装されています。
  1. 50mメッシュ標高データ
  2. 1/25000地図画像
  3. 1/200000地図画像
  4. 地形ポリゴン
 これらのキャッシュの大きさ(=データ個数)はマシンの物理メモリに容量に応じて、プログラム実行ファイルと同じディレクトリ内のconfig.iniで次のように設定することができます。
[Cache]
DEM50 = 25       50mメッシュ標高データ
Map25000 = 12    1/25000地図画像
Map200000 = 12   1/200000地図画像
Topograph50 = 4  地形ポリゴン
 現在、PCに実装されているOpenGLエンジンは大きく分類すると1.x系、2.x系、3.x系の3種類あります。ToposNoteは古いXP機でも動作するように設計されていますので1.x系でも動作します。しかし、なるべく最新機種の性能を動作に反映させるために、OpenGLの版数により処理法を変えることができるようになっています。
 OpenGLの版数の違いがもっともよく表れるのが、地図画像のテクスチャマッピングにおいてです。1.x系においては、テクスチャマッピングする画像サイズは縦横とも2の冪乗でなくてはならないという強い制約があります。典型的な1/25000地図画像に含まれる2次メッシュ領域は4638×3696画素程度であり、これを4096×2048あるいは2048×2048に縮小しなければなりません。地図画像は元々はベクトル表現の線画をビットマップ画像化したもので、これをビットマップ画像として縮小するとどうしても見た目ですぐわかるぐらいに劣化してしまいます。
 2.x系では、任意サイズの画像をテクスチャマッピングすることができます。この機能を使うと地図画像を原画と同じ画質で、地形ポリゴンに貼り付けることができます。
 OpenGLで使用する版数とテクスチャサイズを、プログラム実行ファイルと同じディレクトリ内のconfig.iniで次のように設定することができます。
[OpenGL]
Version = 1      OpenGLの版数:1 or 2
TexWidth = 4096  テクスチャ画像幅
TexHeight = 2048 テクスチャ画像高さ
 TexWidthとTexHeightはVersion=1のときのみ有効で、Version=2のときは対応する画像ファイルの中身がそのままテクスチャマッピングされます。
 config.iniでOpenGL関連項目が設定されない場合は、Version=1, TexWidth=2048, TexHeight=2048 と最も負荷が軽くなるように設定されます。
 config.iniでVersion=2という設定がなされても、実装されているOpenGLの版数が1.x系の場合は、Version=1とみなされます。
 3D地形図エンジンは、[メニュー]→[表示]→[測地座標系]によりONされ、 [メニュー]→[表示]→[幾何座標系]によりOFFされます。
 標高データは国土地理院が基盤地図情報として、無料で提供されているGML形式の10mメッシュデータを利用します。*1 これは次のURLからダウンロードすることができます。
 例えば三重県の場合、次の11個のファイルがダウンロードできます。
  • FG-GML-5035b-DEM10B.zip
  • FG-GML-5035d-DEM10B.zip
  • FG-GML-5036c-DEM10B.zip
  • FG-GML-5136a-DEM10B.zip
  • FG-GML-5136b-DEM10B.zip
  • FG-GML-5136c-DEM10B.zip
  • FG-GML-5136d-DEM10B.zip
  • FG-GML-5236a-DEM10B.zip
  • FG-GML-5236b-DEM10B.zip
  • FG-GML-5236c-DEM10B.zip
  • FG-GML-5236d-DEM10B.zip
これらを解凍することで得られるXML形式ファイルを、ToposNoteへドラッグ&ドロップすると、ToposNoteはその中身を解析し、それがGML形式に準拠する10mメッシュ標高データであれば、プログラム実行ディレクトリのDEM50下に作られる1次メッシュコードを名前とするディレクトリ下に(2次メッシュコード).bemという名前の50mメッシュデータファイル(225×150×4byte=135KB)を作成します。
 これは2次メッシュ内を一辺が50mの正方形に分割し、その平均標高値を32bit浮動小数点数で表現した225×150の配列データであり、上の名前付け規則に従ってこの形式のデータを与えればToposNoteは50mメッシュ標高データとして認識します。*2
 本節の機能は試験的に一枚の地図画像を変換するとき、あるいはライセンス無しで動作確認するときに使用します。ライセンス認証後は7.6節の合併処理をお使いください。
 1/25000地図画像は国土地理院発行の数値地図25000(地図画像)を利用します。これはCD-ROMあるいはオンラインダウンロード形式で購入することができます。
 例えばCD-ROM版の『伊勢』の場合、DATAディレクトリ下に次のようなファイルが存在します。
  • 5136(フォルダ)
  • INDEX.CSV
  • KANRI2KN.CSV
  • KANRI2KT.CSV
  • KANRI2KW.CSV
  • MAGDEF.CSV
  • NEW_HANREI.TIF
  • OLD_HANREI.TIF
 1/25000地図画像を内部形式に変換するには、地図画像に同梱されている管理ファイルの情報が必要です。まず次の二つの管理ファイルをToposNoteへドラッグ&ドロップしてください。
  1. KANRI2KN.CSV(旧図郭地形図管理ファイル)
  2. KANRI2KW.CSV(新図郭地形図管理ファイル)
 管理ファイルの名前は国土地理院発行のすべての1/25000地図画像の配布物に共通しますが、その内容は配布物毎に異なります。そのため、一つの配布物をインストール後、別の配布物をインストールする場合は、管理ファイルのインストールからやり直さなければなりません。また、ToposNoteは管理ファイルの情報を保存しませんので、プログラムを終了するとその情報は失われます。
 管理ファイルがインストールされた状態で、5136下の(2次メッシュコード).TIFという名前が付いた地図画像ファイルをToposNoteへドラッグ&ドロップすると、ToposNoteは現在設定されているOpenGLの状態に応じて、画像を変換し、プログラム実行ディレクトリのMAP25000下に作られる1次メッシュコードを名前とするディレクトリ下に(2次メッシュコード).gifという名前の地図画像ファイルを作成します。地図画像はテクスチャマッピングに都合がいいように上下反転されています。
 上の名前付け規則に従って設定に応じたサイズのGIF画像を与えればToposNoteはそれを地図画像として認識します。
 本節の機能は試験的に一枚の地図画像を変換するとき、あるいはライセンス無しで動作確認するときに使用します。ライセンス認証後は7.7節の合併処理をお使いください。
 1/200000地図画像は国土地理院発行の数値地図200000(地図画像)を利用します。これはCD-ROM形式で購入することができます。
 例えば『日本-II』の場合、DATAディレクトリ下に次のようなファイルが存在します。
  • (1次メッシュコード).TIF (51枚)
  • blkarea.dat
  • HANREI.TIF
  • KANDAT2K.CSV
  • KANRI2K.CSV
  • KANRI2KZ.CSV
  • map12.dat
  • map21.dat
  • map22.dat
  • map23.dat
 1/200000地図画像を内部形式に変換するには、地図画像に同梱されている管理ファイルの情報が必要です。まず次の二つの管理ファイルをToposNoteへドラッグ&ドロップしてください。
  1. KANRI2K.CSV(旧図郭地形図管理ファイル)
  2. KANRI2KZ.CSV(新図郭地形図管理ファイル)
 管理ファイルの名前は国土地理院発行のすべての1/200000地図画像の配布物に共通しますが、その内容は配布物毎に異なります。そのため、一つの配布物をインストール後、別の配布物をインストールする場合は、管理ファイルのインストールからやり直さなければなりません。また、ToposNoteは管理ファイルの情報を保存しませんので、プログラムを終了するとその情報は失われます。
 管理ファイルがインストールされた状態で、(1次メッシュコード).TIFという名前が付いた地図画像ファイルをToposNoteへドラッグ&ドロップすると、ToposNoteは現在設定されているOpenGLの状態に応じて、画像を変換し、プログラム実行ディレクトリのMAP200000下に作られる1次メッシュコードを名前とするディレクトリ下に(1次メッシュコード).gifという名前の地図画像ファイルを作成します。地図画像はテクスチャマッピングに都合がいいように上下反転されています。
 上の名前付け規則に従って設定に応じたサイズのGIF画像を与えればToposNoteはそれを地図画像として認識します。
 本節の機能はライセンス認証後に有効になります。
 合併処理とは、旧図郭の地図画像が対応するメッシュ区画からずれているために、隣接する4枚の地図画像から一つのメッシュ区画を合成するものです。
合併処理
 したがって、合併処理を行なうためには当該地図画像の東・南東・南に隣接する地図画像が存在しなければなりません。ToposNoteの地図画像変換処理は、一つのフォルダ下に管理ファイルと地図画像を統合することにより、必要な管理情報と地図画像を自動的に検知して処理を行ないます。
 例えばORG25000というフォルダを作成し、その中にすべての地図画像をコピーします。このとき、管理ファイルはすべての配布物において同じ名称になっていますが、これについてはメモ帳のようなエディタを使って、合併させる必要があります。
  • 5036(フォルダ)
  • 5136(フォルダ)
  • KANRI2KN.CSV
  • KANRI2KW.CSV
 管理ファイルの合併は、単純にテキストファイルとして追記していけばいいのですが、注意することとしてCSV形式ファイルにおける改行は、1レコードの終わりという意味をもっているということがあります。合併する際に、原ファイルの最後の改行を削除しないようにしてください。結合部分を空行で分離しておくのがいいでしょう。
 地図画像変換は管理ファイルの情報を元にして処理を進めていきますので、地図画像があっても、その管理情報がなければ処理されません。
 日本全国の1/25000地図画像を統合するには30GB程度のディスク容量が必要になります。インストールする前にディスク残量に十分な余裕があることを確認してください。
 [メニュー]→[ヘルプ]→[地図画像変換]により、地図画像変換ダイアログボックスが表示されます。
地図画像変換(1)
 縮尺と変換元フォルダを選択して、[変換実行]を押すと変換が始まります。
地図画像変換(2)
 複数のCD-ROMデータを統合した場合は、かなり長い時間がかかります。途中でやめたいときは[変換中止]を押してください。
 本節の機能はライセンス認証後に有効になります。
 例えばORG200000というフォルダを作成し、その中にすべての地図画像をコピーします。このとき、管理ファイルはすべての配布物において同じ名称になっていますが、これについてはメモ帳のようなエディタを使って、統合する必要があります。
  • (1次メッシュコード).TIF
  • KANRI2K.CSV
  • KANRI2KZ.CSV
 地図画像変換は管理ファイルの情報を元にして処理を進めていきますので、地図画像があっても、その管理情報がなければ処理されません。
 前節の1/25000地図画像の場合と同様です。
注  記
*1GML形式以外のデータには対応していません。
*2国土地理院が50mメッシュとして販売している標高データは、2次メッシュ内を200×200の長方形領域に分割するもので、配列サイズが異なるためにそのままでは使えません。
人  物
ガウス Johann Carl Friedrich Gauss, 1777-1855
 
場  所
地域メッシュ
地域メッシュコード
1次メッシュ
1次メッシュコード
2次メッシュ
2次メッシュコード
 
自  然
ITRF 国際地球基準座標系
GPS Global Positioning System
WGS84
ジオイド geoid
GRS80
 
社  会
八佾 はちいつ
古代中国の周代の天子のための舞楽。八行八列に整列した64人が舞う。論語の第三編の題となっている。
 
Published by SANENSYA Co.,Ltd.