How can I check if my lat/long is in the city limits or example, Greater London is enclosed by:
[bbox=-0.489,51.28,0.236,51.686]
Source :
http://wiki.openstreetmap.org/wiki/Bounding_Box
How can I check if a location (lat/lon):
51.55238,0.047032
Is there a gem already for this? Or what would be the best way to do this?
Bounty update:
I have a working solution but I feel its not the right one, I'm using geocoder gem, and my user has geocoded_by, and lat/long attributes. So here is how I do it :
def self.user_from_dublin(user_id)
near([53.349937,-6.261917], 15).pluck(:id).include?(user_id)
end
So this loads all users from Dublin and compares the id of the user to those users in Dublin. If the id is found the user is considered to be from Dublin.
I don't think this will work well when there is more users.
Update
I'm using postgres database
Can you use raw sql? The
<@
geometric operator will check if thepoint
is contained in thebox
Maybe this is an overkill, but if you are using postgres you can install postgis extension to manage spatial data. Then in a irb you can do something like this:
The query is checking if the point is inside the given bbox using the ST_contains function
This will return:
Then you can do:
This will return:
With this point -0.7265, 44.483 (a point outside the bbox) the result will be:
If you don't want to use raw sql you can use gems to manage spatial data. A very good one is: rgeo. I recommend to read the creator's blog
Using rgeo you can define attributes for your models with "geotypes" like points, polygons, etc. and then use functions like contains?
I leave you with a gist with very basic instructions to install postgis with ubuntu.
BoundBox is rectangle and not an exact city boundary. And it's not efficient to calculate city boundary in each query. I think you can save city relation in callback before save record using geocoder. Please share your solution if you have better one.
I've made a few assumptions, let me know if they are true:
Assumption #1: This lat/long represents where a user lives and will be updated infrequently when a user physically moves his home.
Assumption #2: This lat/long does not represent a users current position and will be updated constantly
Assumption #3: You have bounding boxes for all of the cities you wish to include in the system
Given these assumptions, I think the best way to handle this is to place each person into "City" buckets. Create a city model with a many to many relationship with user:
Now you can query users in a city with:
A KISS solution might be helpful since you have
lat
andlon
attributes to the user model.If you have London's box you could form an
activerecord
scope which would implementthus enabling you to use
User.inside_london
Keep in mind that this type of double range query will not perform that good, it cannot use a proper index in MySQL. For that @david has provided a useful comment, the use of
mongodb
and its geospatial abilities will help. (But a DB change is a serious decision)You can use this Gem https://github.com/square/border_patrol
First you need a small KLM with the limits of the city you want