Archive for August 21st, 2012

MySQLで緯度経度からの半径で円内検索する

Rails3 では、model に

  scope :origin, ->(lat,lng){
    factor=Math.cos(lat/180*Math::PI)
    select([table_name+".*", sanitize_sql_array(["111.11*GLength(LineString( point(?,?), point(x(geom)*?,y(geom)) )) AS distance", lng*factor, lat, factor])])
  }

としておいて、

  Location.origin(lat,lng).order("distance")

とか、

  Location.origin(lat,lng).where("'distance' < ?", dist)

とか。

計算式は何をしてるかというと、まず、中心地点の緯度から、その地点における緯度と経度の長さの比を算出。(緯度1度あたりの距離は地球上どこでも同じだが、経度1度あたりの距離は赤道から離れるほど小さくなる。東京では0.8倍くらい)これをfactorに保存。
GLength(LineString(point,point)) で三平方の定理を計算してくれるので、経度を補正してこれに入れ、出てきたものに111.11km(赤道における1度の長さ)を掛ける。