Skip to content

Instantly share code, notes, and snippets.

@chsh
Created July 8, 2012 14:33
Show Gist options
  • Select an option

  • Save chsh/3071193 to your computer and use it in GitHub Desktop.

Select an option

Save chsh/3071193 to your computer and use it in GitHub Desktop.
Add geometry calculation support for ActiveRecord using PostGIS.
# Add geometry calculation support.
# extend this module for ActiveRecord model.
module GeometrySupport
def by_distance_from_center(center, opts = {})
opts.reverse_merge! :meters => 500
cp = LatLng.from(center).to_point
sw_ne = boundary_from_meters(center,
opts[:meters]).map {|ll| ll.to_point}
cc = ComplexCondition.new
cc.push "SetSRID(MakeBox3D(GeomFromText(?, #{LatLng::WGS84}), GeomFromText(?, #{LatLng::WGS84})), #{LatLng::WGS84}) && location", sw_ne[0].as_text, sw_ne[1].as_text
cc.push "distance_sphere(location, GeomFromText(?, #{LatLng::WGS84})) < #{opts[:meters]}", cp.as_text
self.where(cc.conditions).
select("*, distance_sphere(location, GeomFromText('#{cp.as_text}', #{LatLng::WGS84})) as distance").
order('distance')
end
def count_from_center(center, opts = {})
opts.reverse_merge! :meters => 500
cp = LatLng.from(center).to_point
sw_ne = boundary_from_meters(center,
opts[:meters]).map {|ll| ll.to_point}
cc = ComplexCondition.new
cc.push "SetSRID(MakeBox3D(GeomFromText(?, #{LatLng::WGS84}), GeomFromText(?, #{LatLng::WGS84})), #{LatLng::WGS84}) && location", sw_ne[0].as_text, sw_ne[1].as_text
cc.push "distance_sphere(location, GeomFromText(?, #{LatLng::WGS84})) < #{opts[:meters]}", cp.as_text
self.where(cc.conditions).count
end
private
EN = 20 * 60 * 60
def meter_to_unit(meters)
meters.to_f / EN.to_f
end
def boundary_from_meters(center, meters)
m = meters.to_f
c = LatLng.from(center)
unit = meter_to_unit(m)
cu = LatLng.new(c.lat + unit, c.lng).to_point
cr = LatLng.new(c.lat, c.lng + unit).to_point
cp = c.to_point
distance_lat = cu.distance(cp)
distance_lng = cr.distance(cp)
ll_ofs = LatLng.new(unit / distance_lat * m,
unit / distance_lng * m)
cll = c - ll_ofs
cur = c + ll_ofs
[cll, cur]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment