基盤地図情報対応ogr2ogrの出力が多少残念になる問題
2013/5/31 この問題について対応して下さっています。
id:yellow_73:20130411 で出てきた基盤地図情報対応GDAL/OGRの続き。
問題無いという問題な判断
金曜日にtwitterで流れてきた話。基盤地図情報2500の建物とか道路縁とかのベクタデータを ogr2ogr で他の書式に変換しようとした際に、地理院さんが公開しているコンバータFGDVと結構ちがってくる、というのが証拠付きで出しておられる方がいらっしゃいました。ogr2ogrの出力の方が問題がありそうな雰囲気で、ogr2ogrでの出力は「ガクガクしている」「箱型になるべきが箱型になってない」ようなかんじでした。
当初私はogr2ogrの結果と基盤地図コンバータの結果とを、重ね合わせずに見比べて、「こちらではそういう症状は全く出ない」と判断しました。FreeBSDをソースからコンパイルしたのを使っていたので、Windowsバイナリ特有の問題ではないか、と。これで無事解決。
ところが、月曜日になって、金曜日に作成したogr2ogrの出力とFGDVの出力とを自分の手元で実際に合わせてみる。
(JGD2000経度緯度 青がogr2ogr, 赤がFGDV)
なんということか、Windowsバイナリ特有の問題ではなかったのです。完全に間違ってたorz
いや意外と気付きにくかったんです、本当です信じて下さい、かなり拡大しないと分かりにくかったんです、それにウィンドウを並べて見比べるだけでは分かりにくいんです…重ねて表示させろってことですねorz
floatをdoubleにすればOK
で、ソースを見ると、経度緯度文字列をsscanfで数値型に変える際に、floatを使っていました。これをdoubleに変えれば、精度の問題なら解決するはず。
変更に先立ち、他のところでもfloatを使ってないかチェックしないといけない。出力までの間にfloatに落とされるなら、結局はdoubleでやっても意味がないです。
文字列からsscanfで読み取った値を納めている変数 fLon, fLat は、文脈に応じて m_poPoint, m_poLineString, m_poPolygon にポイントを上書きしたり追加したりします。
いずれも src/ogr/ogr_geometry.h にある OGRRawPoint を使っています。これのメンバ変数(x,y)はdouble型変数でした。
よって、floatをdoubleに変えると何かいいことがあるかもしれない、と判断。
src/ogr/ogrsf_frmts/fgd/fgdreader.cpp で
727行の
float fLon, fLat;
を
double fLon, fLat;
にします。
読み込みには sscanf() を使っていて、%f だと float型を読むので、double型だと %lf にしないといけません。
ということで同じく src/ogr/ogrsf_frmts/fgd/fgdreader.cpp で
730行の
sscanf( m_szTempChar, "%f %f", &fLat, &fLon );
を
sscanf( m_szTempChar, "%lf%lf", &fLat, &fLon );
にします。
(5/28 1:55 "%lf %lf"の真ん中の空白文字を消しました。仕様上区切りの文字列が"SPCひとつと0文字以上の空白文字"と定まってないのではないかと思った(確認してない)ため)
結果はこのようになります。
(JGD2000経度緯度 緑が訂正ogr2ogr、赤がFGDV 重なっている)
他への影響は検討していませんが、とりあえずうまくいきます。
出典
上記の画像は基盤地図情報(縮尺レベル2500)を使用しています。