ライセンス | MIT |
URL | http://www.remotesensing.org/proj/ |
緯度経度⇔投影座標値との相互変換を行うライブラリです。
ほぼ世界中の座標系と、マニアックな投影法までをカバーしてあります。
GRASSやMapServer等のオープンソースのGISソフトでは必ずといっていいほど使用されています。
コンパイル
ver. 4.5.0
./fonfigure
→ make
で普通にできますが、DLLが作れません。
nmakeで作ることはできるようです。この場合はsrcフォルダに移動してnmake -f makefile.vc
を実行してください。
準備
必要なヘッダファイルはprojects.hとproj_api.hで、projects.hをインクルードします。
同時にwindows.hをインクルードしていると、PVALUE型が衝突するので、適当な名前に変更しておきます。
pj_init()関数
まず、pj_init()
関数によって投影法、楕円体、その投影座標での原点の緯度経度を指定します。
指定方法の例は、以下のとおり。
static char *params[]={ "proj=utm", "ellps=GRS80", "lon_0=135", "no_defs" }; PJ *ref; if ( !( ref = pj_init( sizeof(params)/sizeof((char *), params) ) ) { fprintf( stderr, "%sn", pj_strerrno( pj_errno ) ); }
またはpj_init_plus()
関数を使って以下のように設定することもできます。
sprintf( szInit, "+proj=tmerc +lat_0=%s +lon_0=%s +k=0.999900 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs", szLat[iSystem], szLon[iSystem] ); if ( !( ref = pj_init_plus( szInit ) ) ) { ::MessageBox( NULL, "座標系の初期化に失敗しました", "Error", MB_OK ); return; }
1行目は投影方法、2行目は楕円体、3,4行目は投影座標の中心を指定するらしい。
特に指定しなくてもいい場合があるらしく、その場合はno_defs
を指定します。
たとえば、UTM座標値を求めたい場合などは、北半球では緯度の設定は不要です。
各項目で、設定することができる値は以下を参照。
proj4のソースコードの中にはnadフォルダの中にepsgというファイルがあります。
この中身は各座標系のepsgコードとそのパラメータが記述されています。
なので、MapServerのmapファイルの記述のようにpj_init_plus( "epsg=4724" );
などと指定できそうなものですが、どうもできないようです。
EPSGコードで指定したい場合はpj_init_plus("+init=epsg:4612");
とします。
座標値の求め方
pj_init()
関数が成功したら、ライブラリはその投影法と楕円体、原点を元に変換するようになります。
緯度経度から座標値を求めるには、以下のようにする。
projUV data; data.v *= DEG_TO_RAD; data.u *= DEG_TO_RAD; data = pj_fwd( data, ref ); if ( data.u != HUGE_VAL ) { printf( "%.3ft%.3fn", data.u, data.v ); } else { fprintf( stderr, "!2n" ); }
gdalを使うなら
gdalを使うと、EPSG番号で変換することができます。
内部的にはgdalからproj4を呼んでいます。
この場合のコードは大体以下のようにします。
gdalがエクスポートしているクラスを使ってもいいはずですが、
筆者の環境ではなぜかOGRSpatialReference
オブジェクトをdelete
するときに謎の赤バツが出てしまいます。
(何かしでかしているんだとは思いますが、、、)
#include "ogr_srs_api.h" int main( int argc, char *argv[] ) { OGRSpatialReferenceH hIn, hOut; OGRCoordinateTransformationH hCT; double aX[] = { 0.0, 1000.0, -1000.0, 2000.0 }; double aY[] = { 0.0, 1000.0, -1000.0, 2000.0 }; hIn = OSRNewSpatialReference( NULL ); hOut = OSRNewSpatialReference( NULL ); OSRImportFromEPSG( hIn, 2451 ); OSRImportFromEPSG( hOut, 4319 ); hCT = OCTNewCoordinateTransformation( hIn, hOut ); OCTTransform( hCT, 4, aX, aY, NULL ); for ( int i = 0; i < 4; i++ ) { printf( "%8.3f, %8.3fn", aX[i], aY[i] ); } OCTDestroyCoordinateTransformation( hCT ); OSRDestroySpatialReference( hIn ); OSRDestroySpatialReference( hOut ); return 0; }