I have a series of GPS coordinates in decimal dotted format, multiplied by 1.000.000. For example a latitude of 51.1 and a longitude of 4.1 would be saved as Y 51100000 and X 4100000. These coordinates are saved in an SQlite 3 database.
Using Ruby 1.9.2 and Rails 3.0.8, I need to be able to get all records that are within a certain radius of a certain center point. For instance, given a center point of latitude 51 and longitude 4, I need to find all records within a 10 kilometer radius.
This article explains pretty well how to perform a query to get those records, but SQlite does not seem to support the mathematical functions that are used: http://www.movable-type.co.uk/scripts/latlong-db.html
Is there any other way I would be able to retrieve the proper records from the database that does not involve iterating through the entire table?
Thanks!
Unless you MUST use SQLite, try it with Sphinx:
I would convert GPS coordinates to lat/lng coordinates, and then use Sphinx (there is gem thinking-sphinx for rails: http://freelancing-god.github.com/ts/en/). With Sphinx you can search points within a given circle with Sphinx's function: #geodist
A brilliant example of how to do it you will see here: http://joeyschoblaska.com/blog_posts/220-thinking-sphinx-searching-by-location-and-keyword
Related
I am currently using Firestore for my iOS app and I need to implement a scalable solution for my posts feed. I need to get posts within say 20 miles, order them by date, and limit the amount of posts fetched for pagination. Any and all database solutions would very much appreciated! Thank you!
As a low budget/time alternative to libraries, we have implemented storing the first few digits of lat/long coordinates as a document or collection name and then accessed data that way. The first decimal place gives resolution to around 10 miles or so (exact values for longitude change depending on what latitude you are at). So in your database you could have a collection or document named something like +33.6-112.0. This would mark a reference in Firestore to put all data within (33.8 N, 112.0 W). Be careful with how you round the exact location data before placing it in the respective document or collection.
Then you can retrieve all data at any location you want. This may not give you exactly 20 miles, but some client side sorting can handle that. Note you could make the reference go to any decimal place necessary to achieve the level of precision you are looking for to minimize data base calls (to save you money) and minimize impact on the user's cell data plan.
This is a rather simple solution with limitations, maybe for an MVP, and if not careful could pull way more data than anticipated.
Below is a chart showing the approximate physical distance between each decimal place at the equator. So for example, the distance between (33.3 N, 0 W) and (33.5 N, 0 W) would be about 14 miles.
Neither of those databases have native geospatial querying capabilities. You would have to use some sort of add-on library to help with that. Geofire and Geofirestore are popular for this.
I am thinking about how to structure the data within my app and one of the most important lookups will be closest location from a collection of location (10,000+ locations) and I'm looking for the fastest and most efficient way to do this.
Ideas I have:
Use Core Data and store cllocations or doubles, query with a predicate to order by closest to reference location
Store them in an sqlite database and use the distance formula in sql query
Load all locations into memory into some sort of a data structure (array, linked list, hashmap, etc.) and compute the distance a different way
Of these solustions, which would be the fastest/most efficient? Or is there another solution you would recommend?
As others have mentioned, you can't sort by a calculated value with Core Data, so a query for the closest location is unfortunately out. I've used the following "boxing" approach to approximate that, which might or might not meet your needs:
Calculate a box around the target location. The offset in degrees is something you'll need to work out, but the Wikipedia article on decimal degrees can be a good starting point. Offset your target by +/- some number of degrees to get a rough rectangle.
Fetch every location within that rectangle.
Sort the results in memory to find the closest result.
If you want to make one request for the closest location, you'll probably have to work with SQLite directly. I wouldn't load all of the points into memory without a careful examination of the total memory impact of doing so, and an understanding of how much memory your app is using for other reasons at the same time.
I am considering the use of Thinking Sphinx, as I already have used ElasticSearch and would like to try something new.
In using ThinkingSphinx, how would one go about setting up a geo distance filter. There would be a User model containing the basic information of a user that includes their zip code. There a Locations model that would have the geographical information of the United States (zip code, latitude, longitude, state).
EXAMPLE: Current user “Michael” zip code is 30601. Michael types in the search form “programmer, video games”. The return results will
show Users who have the words “programmer” or “video games” from a
attribute in the User model that are located within 100 miles of
Michael’s zip code 30601.
I have installed ThinkingSphinx, and on my app if I performed the search as detailed in the above example it will return the “programmer” or “video games” matches but only with users who have a 100% exact match to the zip code (it cancels out using geo dist). Now with the code I have I can perform a geo distance search using the zip code, which would returning surrounding Users. The geo distance doesn't seem to work when I factor in attributes from the User model with the zip code.
This was done with ease using Elastic in the past, but I wanted to see how Thinking Sphinx works. If someone has a clue with how this would look in the Searches controller, please
From the perspective of Sphinx, zip codes are not useful - it all comes down to latitude and longitude.
So, if in your example Michael is current_user, you might have a search call looking something like this:
User.search 'programmer video games',
:geo => [current_user.latitude, current_user.longitude],
:with => {:geodist => 0.0..161_000.0},
:order => 'geodist ASC'
Keep in mind this presumes you have latitude and longitude values stored in radians, not degrees. If they are in degrees, then you'll want to convert them in your index definition (as noted in the docs) and when you're searching as well (e.g. current_user.latitude * Math::PI / 180.0).
When filtering by distance, Sphinx uses metres - one mile is almost 1610 metres, hence the conversion in my example above.
At the moment I have a Fusion Table with 3 columns:
Column A (text): name of a store
Column B (location): city of that store
Column C (number): radius in which the store advertises (so for instance 5km around store location).
Here is a link to the table:
https://www.google.com/fusiontables/DataSource?docid=15YqM0NN0hCc9IfSUfdOiVqS1sFIKehtaYAjg8nU
Now what I would like to do is visualize these advertising radius-es of all these stores on a map. As the radius-es vary for each store (5km for store 1, 10km for store 2, etc.), I have no idea how to start working on this with the API.
I would really appreciate any help here.
With your current setup this is not possible at all, because your Location-colum is geocoded, it's not possible to access the geocoded LatLng in any manner.
Even when you had the LatLng's it wouldn't be possible to visualize a circle via a FusionTablesLayer, because circles are not supported by KML.
So the only thing you can do is:
Request the complete data(may be done via AJAX, JSONP is supported), geocode the City-column an draw a google.maps.Circle based on the returned LatLng and the radius stored in the Number-column(of course it would be better when you had stored LatLng's instead of city-names, because you wouldn't have to geocode the cities each time).
I've been using the geokit and geokit-rails gem for rails for awhile but one question I haven't found answered is how to find the calculated aggregate center for a collection of points. I know how to calculate the distance between two points, but not more than 2.
My reason is, I have a series of points all in the same city... all things being perfect the city would have a center which I could just use, but some cities, say berlin do not have a perfect center. They have multiple centers, and I just want to use the whole list of places I have in my database to calculate a center for a particular distribution. Has anyone else had this problem?
Any tips? Thanks
Having never used Geokit before, the math behind this operation is relatively simple to implement yourself. Assuming these points consist of a latitude and a longitude, you just need the average latitude and average longitude for all the points. Once you have those two values, you've got your center point.
points = [[14, 19], [-5, 57], [23, -12]]
points.transpose.map{|c| c.inject{|a, b| a + b}.to_f / c.size}
Likewise, if these points are Geokit::LatLng objects instead of a 2-dimensional array, you can just map their lat and lng values simply by calling #to_a on them beforehand.
points.map(&:to_a).transpose.map{|c| c.inject{|a, b| a + b}.to_f / c.size}