基盤地図情報対応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)を使用しています。