Finding a gps locations near another one based on a dynamic radius - ruby-on-rails

I have aGpsLocation model, this model has a latitude, a longitude and a radius property.
I want to find a GpsLocation based on its latitude and longitude and radius.
So lets say i am on location [52, 4], i want to find a GpsLocation instance that has these exact coordinates or is radius meters away.
I am using the geocoder gem but the near function does not do the job. Also tried monkey patching the near function so i can use a database column instead of a variable inside the query but still no luck, there are some mechanics that transform the lat/long to a range when providing a radius parameter.
Any help is appreciated

Calculating the distance between two points on a sphere can be done using the Haversine formula. There is a gem called haversine that can help. Or, if you're using PostgreSQL, there is also the earthdistance module.
However, you may find it easier to relax your definition of "near" somewhat, as dealing with circles can be annoying. Instead, consider using squares or rectangles.
Say you define "near" as within 10 miles. If you treat that as a plus or minus factor around the latitude and longitude of a given point, then you can do a simple query to find all nearby points at once, rather than a series of Haversine calculations. You query might look something like this:
# Only accurate in the U.S.
MILES_PER_LATITUDE = 69.0
MILES_PER_LONGITUDE = 55.0
min_latitude = thisLocation.latitude - (10.0 / MILES_PER_LATITUDE)
max_latitude = thisLocation.latitude + (10.0 / MILES_PER_LATITUDE)
min_longitude = thisLocation.longitude - (10.0 / MILES_PER_LONGITUDE)
max_longitude = thisLocation.longitude + (10.0 / MILES_PER_LONGITUDE)
nearby_points = GpsLocation.where(latitude: min_latitude..max_latitude).where(longitude: min_longitude..max_longitude)

Related

idea: getting locations nearby

currently, i have a table with locations (latitude, longitude). I calculate nearby calculations using sin, cos as described here
This seems rather slow. I am having the idea of pre-calculating the distance to a fixed point f and store it along the locations. When I now want to find locations nearby i just calculate distance to the same fix point and can then find them by doing some less or equal comparing.
Does my idea make sense? Is there a standard way to do that? I am in the thinking phase, so i do not have any code to show yet.
Your idea won't work unless all your locations are collinear, which most probably is not the case.
Are you using SQL to do the calculations? Are you properly using indexes? Maybe you could share a bit of your code with us.

Wrong distance using distanceFromLocation:

I'm trying to find out what's wrong but it seems like the mentioned method is just returning wrong values. I'm setting coordinates in simulator, then just print them and calculate distance:
(lldb) p location.coordinate
(CLLocationCoordinate2D) $1 = (latitude = 51, longitude = 0.10000000000000001)
(lldb) p _oldLocation.coordinate
(CLLocationCoordinate2D) $2 = (latitude = 51, longitude = 0)
Now I'm calculating distance:
distance = (CGFloat)[location distanceFromLocation:_trackEndLocation];
And when I print it i get:
(lldb) po self.trackDistance
7019.76758
Now, the problem is that users tell me that app returns too big distance. As I wanted to debug it, I've checked the distance at page to calculate distance between two points.
The results are as following:
As you can notice, the distance according to the webpage is 6.997km while Apple method tells me 7.019km. I wonder who is incorrect, Apple or the webpage and what to do with this matter. The difference isn't big, but when you accumulate it between few points it can be disturbing.
The Apple doc page for distanceFromLocation says this:
This method measures the distance between the two locations by tracing a line between them that follows the curvature of the Earth. The resulting arc is a smooth curve and does not take into account specific altitude changes between the two locations.
I suspect Google Maps does consider the terrain between the two points, and that's why you saw a 0.3% difference in your test. However, I doubt your customers are complaining about that level of error. It's more likely the error is from a different cause.
Without knowing more about your algorithm it's hard to say, but if you're tracking distance traveled, the error might be caused by jitter in the phone's GPS coordinates. (That would cause a straight line path to look like a zigzag, which would yield a longer distance.) You could record some real data from your app to see for sure.
The problem was that I was checking the accuracy and filtered some results out if the accuracy was bad. That's why sometimes the distance was wrong. I've fixed the accuracy filtration and everything is working fine.

RoR: Check for a location within a radius of the other location, using google maps api

I am using google maps fo rails gem https://github.com/apneadiving/Google-Maps-for-Rails/ . I am trying to find out a way through which I can see if a location is inside the map circle. For instance
#circles_json = '[
{"lng": -122.214897, "lat": 37.772323, "radius": 1000000},
]
'
This helps me create the circle. But how do I see if, lets say, 'Location B' is inside #circles_json ?
I was thinking of using the gem ruby geocoderhttp://www.rubygeocoder.com/. If so, how do I go ahead with that? I watched the railscasts. But it mostly depends on the local db. What I am looking for is to see if the two location entered in my database fall close to each other or not. In this case, in a 50M radius.
Any guidance is appreciated.
Thanks
To check if a point is within a circle, calculate the distance between the point and the circle's center. If the distance is greater than the radius, it is outside the circle. If the radius is greater than the distance, it is inside the circle.
Ruby Geocoder has a convenient method to calculate the distance between two points.
Geocoder::Calculations.distance_between(point1, point2)
To make this return true/false, use a simple comparator:
in_circle? = Geocoder::Calculations.distance_between(point1, point2) < radius
Read the documentation for help using #distance_between.

Ruby Geocoder how to set a minimum .near distance

Using Alex Reisner's Ruby Geocoder and finding the .near method very useful. One question we have is how can we set it so that we can search for objects between distance x and distance y from the origin (at the moment the .near method only sets the max distance it seems):
documentation here
We're looking for something like:
places = Place.near("Washington", min_distance, max_distance).reorder("score")
or some way of modifying the query so that we get the same effect without using .reorder (which we're using to sort on another "score" field)
The end result we want is the ability to have places ordered by score which are between x and y miles from the origin.
AFAIK it is not natively implemented.
If using ActiveRecord, you can try to use Geocoder's private class methods (see from line 105 to 147) to roll your own "reverse" method, with an algorithm that should be more or less :
calculate bounding box for mininum distance query with Geocoder::Calculations#bounding_box
build SQL to find all records in bounding box AND with #distance_sql(lat,lon,options) >= min_distance
stuff this logic inside a where scope, chain it to near, and voilĂ ! If you feel lazy you can even just copy/paste the whole method and just change the <= predicate.
On a side note, it would be great to file a feature request at geocoder's github, as i think it would be quick to implement for them.
The query generated by Geocoder includes a distance column so all you need to do is add a condition for the minimum distance, for example:
Venue.near("Washington", max_distance).having("distance >= ?", min_distance)
Note that you need to use HAVING, not WHERE.

How do I calculate the nearest country on a given heading?

I'd like to calculate the closest country (as viewed on a world map) in a given direction (provided in degrees) from a user's current location.
I realize one way of doing this is to use the formula provided here to step in, for example, 5-mile increments from point to point until I finally reach a country that is not the user's starting country. However, that seems horribly inefficient with regard to use of geocoding resources.
Do any of you know of a better algorithm I could use for this?
Thanks in advance.
One way to reduce the amount of reverse geocoding operations is to treat this problem as a search for the border. If you use a binary search algorithm, and reverse geocode each point, you find where the country changes from your current country to the adjacent country with a minimum number of reverse geocode operations.
In the binary search, your heading is constant, and you have a minimum range (5 miles) and a maximum range (12,000 miles), you are searching for the range at which the border lies. Then you reverse geocode a position just beyond the border to find out what country is there. One problem is that just beyond the border might be ocean.
I would use MKReverseGeocoding. Check this SO question for code examples.

Resources