Reputation: 2864
In my Rails app I have search areas, which are geographic polygons (created using the Google Maps API). Once drawn on the map, the search area's coordinates are saved to a record as an array of hashes. It looks something like this:
SearchArea.last.geo
=> [{"lat"=>"48.425555463221066", "lng"=>"-123.3793830871582"}, {"lat"=>"48.41336528699442", "lng"=>"-123.37800979614258"}, {"lat"=>"48.41006090395106", "lng"=>"-123.31672668457031"}, {"lat"=>"48.44696663691928", "lng"=>"-123.32067489624023"}]
I also have a handful of location records whose coordinates are saved as a hash, like so:
Location.last.geo
=> {"lat"=>"28.8138124", "lng"=>"-96.9977682"}
I need to be able to search for/filter records that have geo coordinates that fall within a given search area. I have no experience with geospatial programming, so I'm hoping someone can lend a hand here. It would be really appreciated!
Things I've looked in to:
Upvotes: 1
Views: 1292
Reputation: 2864
Nate suggested PostGis in the comments above, so I went with that.
I ended up using this tutorial to install PostGis on my Rails app, with some minor changes for 2016:
require 'active_record/connection_adapters/postgis_adapter/railtie'
should actually be require 'active_record/connection_adapters/postgis_adapter'
t.point :latlon, :geographic => true
to t.geography "latlon", limit: {:srid=>4326, :type=>"point", :geographic=>true}
Based on this issue I also added the following initializer:
RGeo::ActiveRecord::SpatialFactoryStore.instance.tap do |config|
config.default = RGeo::Geographic.spherical_factory(srid: 4326)
end
The rest of the tutorial was a pretty good reference, from installing the gems to updating the database configuration.
From there I was then able to create a Location with a Point
:
Location.last.geo = "POINT(-123.366 48.428)"
As well as my polygonal area to search within using a Polygon
:
SearchArea.last.geo = "POLYGON((-123.382 48.426, -123.353 48.402, -123.314 48.423, -123.332 48.443, -123.382 48.426))"
Finally, the query; it was so simple!
sa = SearchArea.last
Location.where("ST_Intersects(geo, '#{sa.geo}')")
Thanks for the suggestion, Nate!
Upvotes: 3