arcanum_jp’s blog

おっさんの日記

nメートル以内にオブジェクトが存在するか(PostGIS)


PostGSIで半径nメートルの範囲内に存在するオブジェクトを取得するSQLを書きたいってことがあってメートルから度へ変換するにはどうするか調べていたことを書きます。

へー、簡単だよ!

おお!簡単簡単・・・こんな感じにすりゃいいんじゃ・・・

select * from hogehoge_tbl where ST_DWithin(position, GeomFromText('POINT(30.1234 140.5678)', 4326), ????)

※ hogehoge_tblのpositionフィールドが座標のフィールドだとします。

あれれ??4326って単位が度、度ってどういうこと??メートルに直すのってどうすんの??えぇ〜!!


 例えば半径500mの範囲内にあるって表現したいとき、傍目には下記図の左側なんだけど、実はSQL上では下記図の右側を考えなくてはならない。

 ううーー算数が苦手な自分に訳の分からん計算させるとは・・・うぬーー・・・orz...

地球の円周から1度の距離数を算出

地球の円周・・・グーグル様にお願いしたら検索結果ではなくこんな画面が!これは間違いなく信じていい!そう思っていいよね!おれ!

この距離を360°で割ると、1度あたりの距離数が求められます。

 40,075(km) ÷ 360 ≒ 111.319(km)

 おお!地球の円周1度あたり111.319Kmあるってことですか!結構な距離ありますね。なるほど!図にするとこんな感じです。


まだまだ大きくて扱いづらいので秒の距離を求めます

1度は3600秒ですので、111.319Kmを3600で割れば1秒あたりの距離が求められます。その際、Kmだとわかりづらいので1000をかけてメートル単位にします。

 (111.319(km) × 1000) ÷ 3600 ≒ 30.9219444...

 1秒あたり約30.92194mまでわかりました。図にするとこんな感じです。

 30m単位だと使いづらいので、1メートルあたりの秒数にしてあげます。

 1 ÷ 30.92194 ≒ 0.0323394

 これで1メートルあたりの秒数が求められました。

例題の500メートル範囲にするには

 1メートルあたりの秒数が求められましたので、あとは500をかけて、秒数→度数変換ですので3600で割れば半径nメートル範囲内の度数が分かります。

 (0.0323394 × 500)÷ 3600 = 0.0044915833333333 

 あとはSQLに使うだけです。

select * from hogehoge_tbl where ST_DWithin(position, GeomFromText('POINT(30.1234 140.5678)', 4326), 0.004491583)


おお!やっとわかった。めでたしめでたし・・・