2007/3/11 日曜日

GPSデータからグラフ作り:4)経度・緯度で指定した各地点の標高データを求める(SRTMから標高取得)

Filed under: 開発メモ — matoyan @ 21:13:52

前回まででGPXファイルの標高データをもとにグラフを描くことができました。ただ、標高データがないGPXファイルの場合はグラフを描くことができないので、別の標高データを取ってくる必要があります。



国土地理院の提供する標高情報で言うと「数値地図50mメッシュ(標高)」という標高データがあります。が、これをサービスとして提供するには結構な手続きが必要になります。

具体的にはCD-ROM3枚を購入した上で、測量法第29条又は第30条の規定に従って 「測量成果の複製・使用承認手続」が必要になります。申請の際には開発目的とか開発計画を届け出て承認が出るまで数週間待つようです。



そこでもっと簡単に使える標高データがないか探してみました。

最終的に使えそうなデータとして

・国土地理院の地球地図日本

というデータと、

・NASAの提供するスペースシャトル地形データ(SRTM)

の2つぐらいに絞れました。



どちらのデータも登山ルートの標高グラフを作ってみたのですが、地球地図の方の標高メッシュデータは精度が低すぎてグラフが本来の形とはかけ離れたものになってしまいました。



SRTMを使った標高取得プログラムを作って、グラフ作成をしました。

標高データの入手からプログラム作成までの流れをまとめると、、、



1)標高データを入手

SRTMの標高データはFTPサーバ(ftp://e0srp01u.ecs.nasa.gov/srtm/)から入手できます。



2)データフォーマットを理解

地形データは緯度経度ごとに分けられていて、例えばN37E138.hgtファイルには北緯37度、東経138度〜北緯38度、東経139度までのデータが入っています。日本のデータはEurasiaの中にあります。

データフォーマットなどの詳細は

ftp://e0srp01u.ecs.nasa.gov/srtm/version2/Documentation/SRTM_Topo.pdf

に書かれています。



仕様書とデータを見て、分かったところだけざっくり説明すると、(間違っているかもしれませんが・・・)



・各ファイルには縦に1201個、横に1201個のデータが入っていて、境界部分のデータは2つのファイルに同じデータが重なって入っている。

 ⇒ 一番北西の標高データから東に向かって1201個の標高データが並んだ後、一段南に下がって次の1201個のデータが西から東に向かってならんでいくイメージです。

srtmの説明1
srtmの説明2


・データにヘッダはなく、標高データだけがバイナリ形式で16バイトのBigEndianで並んでいる。

 ⇒ 例えば0x0115なら、277mという感じ。



サンプルコードも貼り付けておきます。

LatLng2Height:::緯度経度から標高算出APIのような機能を自分のサーバ内で作りたい方はご利用ください。

PHP:
  1. <html><head><title>SRTM標高計算サンプル</title></head><body>
  2. <?php
  3.  
  4. $lat=36.3423;   // 経度:度で指定
  5. $lon=138.1245// 緯度:度で指定
  6.  
  7. $b1=intval($lat);
  8. $l1=intval($lon);
  9. $fn = "./srtm/N".$b1."E".$l1.".hgt";
  10.  
  11. if(is_file($fn)) {
  12.   $b=$lat;
  13.   $l=$lon;
  14.   $ofs = (floor((1-($b-$b1))*1200)*1201 + floor(($l-$l1)*1200)) * 2;
  15.  
  16.   $fhandle = fopen($fn, "rb");
  17.   #左上の標高
  18.   fseek($fhandle, $ofs);
  19.   $h1 = unpack("n", fread($fhandle, 2));
  20.   #右上の標高
  21.   $h2 = unpack("n", fread($fhandle, 2));
  22.   #左下の標高
  23.   fseek($fhandle, ($ofs+2402));
  24.   $h3 = unpack("n", fread($fhandle, 2));
  25.   #右下の標高
  26.   $h4 = unpack("n", fread($fhandle, 2));
  27.  
  28.   $tmp=1-($b-$b1)*1200;
  29.   $d=$tmp-floor($tmp); #下との距離
  30.   $c=1-$d; #上との距離
  31.   $tmp=($l-$l1)*1200;
  32.   $a=$tmp-floor($tmp); #左との距離
  33.   $b=1-$a; #右との距離
  34.  
  35.   $ele1 = $a/($a+$b)*($h2[1]-$h1[1])+$h1[1];
  36.   $ele2 = $a/($a+$b)*($h4[1]-$h3[1])+$h3[1];
  37.   $ele = round($c/($c+$d)*($ele2-$ele1)+$ele1);
  38.  
  39.   print "【座標】<br />\n";
  40.   print "経度:".$lat." - 緯度:".$lon."<br />\n<br />\n";
  41.   print "【四隅の標高】<br />\n左上:".$h1[1]."m - 右上:".$h2[1]."m<br />\n";
  42.   print "左下:".$h3[1]."m - 右下:".$h4[1]."m<br />\n<br />\n";
  43.   print "【距離】<br />\n左".$a."<br />\n";
  44.   print "右".$b."<br />\n";
  45.   print "上".$c."<br />\n";
  46.   print "下".$d."<br />\n<br />\n";
  47.   print "【結果】:".$ele."m";
  48. } else {
  49.   print "file open error:".$fn;
  50. }
  51.  
  52. ?>
  53. </body></html>



サンプルコードを実行してみる。

サンプルコードをダウンロード



あとはSRTMのデータの欠落部分を修正し、メッシュデータと座標位置との変換をしつつグラフを作ることができました。

makegrp4.png
↑完成したグラフ

次のページ »

HTML convert time: 1.073 sec. Powered by WordPress ME