I have in my android application a database table with geo pointes (lat and lon are decimal degree values), about 1000 points. And I need to select 20 nearest point to some given geo point.
I've found at Stackoverflow the answer how to compute distance between two geo points and was very happy, till I tried to write my query. I've found out, that it's not possible to use trignometrical functions in built-in sqlite of android.
But then I've got an Idea. I don't really need to compute a distance. The near a point is to another one the smaller difference in their geo coordinates should be.
How could I use this fact? Would it be enough to order saved points by (lat_0 - lat_n)^2 + (lon0-lon_n)^2, where lat_0 and lon_0 are geo coordinates of a given point?
Thank you,
Mur
UPD
So, the best way to get an answer for my question was to test approach I describe above.
It works pretty well but not really exactly compared to exact distance.
So if you just need to compute a distance, this solution is ok, but in my case I also needed to order stations by distance and couldn't use this solution.
My thanks go on John at CashCommons and Philip. Thank you guys
If your points are separated within a city (more or less), that approximation will work fine. The approximation falls apart if you go worldwide, though.
EDIT: Based on Philip's comment below, you should scale one of the components. Germany is about 50 degrees north latitude, so multiplying the longitude by (cos 50 deg) will do better.
Yes. :-) The actual distance is sqrt( (lat_0 - lat_n)^2 + (lon0-lon_n)^2 ) but ordering by (lat_0 - lat_n)^2 + (lon0-lon_n)^2 is sufficient.
Hmm... I'm not sure how that ordering would work? Wouldn't you need a different order for each point to indicate it's neighbors.
The simplest solution is to just iterate through all the points and compute the geometrical distance between the points. For 1000 points this should happen fairly fast.
The most optimized solution (in terms of retrieval speed) is to compute the neighbors of each point when you insert them in the database. For example you can keep the list of ids as a comma separate string and insert in the database?. Then when you need someones neighbors you do directly to them. However this is going to become a pain if you need to insert new points. Basically you'll need to re-compute the neighbors.
Related
1) For some reason, the longitude and latitude are slightly different after storing them. For example, when i first find them, they are:
25.171057657111998 and 35.013447496224636 but after I store them , they are
25.1710586547852 and 35.0134468078613. Why is this happening? I store them as floats in an sqlite database, retrieve them with Cursor.getFloat, and print them with String.format of 13 digit accuracy.Can this difference affect the end results in a significant way? I am working with distances <100m (328 feet)
2)I am trying to find the center of a location cluster. Here
http://www.geomidpoint.com/calculation.html
method C says I can just take a simple average if I work with <400km. Has anyone tried it? Is it working? Or should I go for the first, more accurate method?
3) After finding the center, do I need anything else to create a new location object for distance purposes?
To solve this problem you may store longitude and latitude in your sqlite database by this way:
longitude*10^10 , latitude*10^10
when you get them you will divide them by 10^10.
because with 5 decimal is accurate
I have a local database with over 2000 locations that I am trying to search through based on the users location. I only want to display a few markers in the Map Fragment nearby the user, but have so far been unable to find a way to do it.
Currently the database is in the form of a csv file, so I can change it to a different type easily. But I was waiting to do so until I could find a utility that can search the coordinates based on a radius around the user. Anybody have any suggestions?
You can define a LatLngBounds object for some box around the user, and then use bounds.contains(LatLng) to determine which of your locations are in that radius. I've used this method for collections of about the same size as yours and it was fast enough for our purposes. You will be searching a rectangle, not a radius, but since the map is a rectangle, maybe that makes more sense anyway?
This is a tricky topic and solution is not straight forward. I am briefly listing down the steps I have used and this works for well over 100k assets in my case.
Assuming you already have logic to get your current location and lets call if as myLocation.
Add your location data in sqlite file and treat location coordinates as nothing more than float.
Use offset as 0.001 which is roughly around 100 m and use the following in the query.
(myTable.lat > (myLocation.lat - offset) AND myTable.lat < (myLocation.lat + offset)) AND
(myTable.lon > (myLocation.lon - offset) AND myTable.lon < (myLocation.lon + offset))
This should give you the list of assets within a small radius
The trick here is to treat location as float and not really location.
For Offset: http://en.wikipedia.org/wiki/Decimal_degrees
I have a database full of map Locations (Latitude, Longitude), is there a way I could do a SQL query to return me all points around a certain location?
Right now I basically grab everything in the database and loop through each one and check the distance using
Location.distanceBetween(startPoint.latitude, startPoint.longitude,endPoint.latitude,endPoint.longitude, results);
and keeping items that are within the set distance but there could be a lot of points to loop through.
So is there anyway to do this in an SQL statement?
You can use a WHERE clause expression to filter on angular distance r from an origin (x0, y0). Since SQLite doesn't have a square root function, you'll have to use the squared distance:
SELECT ... FROM ...
WHERE (Latitude-x0)*(Latitude-x0) + (Longitude-y0)*(Longitude-y0) < r*r;
The only place this won't work well is near the poles or the prime meridian. It's also a planar approximation to the sphere, so it will only work for values of r that are quite small. Finally, it scales latitude and longitude equally, so the selected region looks more and more elliptical the farther away the origin is from the equator.
You will have to convert linear distance (e.g., "within 30 meters") to latitude/longitude differences. This is a rather complex subject because the Earth is not a perfect sphere. However, for rough calculations you can use the approximation that 1 nautical mile = 1852 meters = 1 arc minute of longitude at the equator. Since lines of longitude get closer together as the latitude moves away from the equator, you will need to use some trig to figure out what value of r to use at a given latitude. For more info on this problem see this thread or this one, or search the web for "convert meters to latitude longitude".
I have a database full of map Locations (Latitude, Longitude), is there a way I could do a SQL query to return me all points around a certain location?
You can easily check a square region.
Using very simplified latitude / longitude coordinates say you're at [25.86, 57.03] and you wanted everything in the "neighborhood" (+/- .05) you can use a query like this:
SELECT * FROM Coords WHERE (latitude BETWEEN 25.81 AND 25.91) AND (longitude BETWEEN 56.98 AND 57.08);
You can also use the SQLite R*Tree extension.
An R-Tree is a special index that is designed for doing range queries. R-Trees are most commonly used in geospatial systems where each entry is a rectangle with minimum and maximum X and Y coordinates.
The source code to the SQLite R*Tree module is included as part of the SQLite3 amalgamation but is disabled by default. To enable the R*Tree module, simply compile with the SQLITE_ENABLE_RTREE C-preprocessor macro defined.
I have a SQLite database in Android with a table that contains longitude, latitude and other columns.. now I want to get all records that have the distance smaller or equal to a given distance.
For example, I know my current coordinates(lat,long) and I want to get from my table all records that are at the maximum distance of 10km from me.
I found some links on stack but nothing too solid. Is there someone that knows an optimized solution for this problem?
I have thought that I could get all records that have latitude smaller than my lat + distance and greater than my lat - distance and longitude smaller than my long + distance and greater than long - distance. After this query I should check for some unwanted records since the query is not returning only the wanted records..
Is this a good idea?
You probably want to do this in two parts,
1) Run a query where you find all records that are within a certain value + or - of the current lat/lng of your location, the where clause might look like:
where (#latitude > (lat - .001) and #latitude > (lat - .001)) and
(#longitude> (lng- .001) and #longitude> (longitude- .001))
2) with the rough results from above, use the great circle/haversine method to determine what the actual distance between each location is (great circle/haversinse is already part of the android maps api).
Just for the record, it can be useful.
I don't know what you are trying to do, or if you have a backend or a server. But, if you DO have a server which stores these locations, you can (and should) use MongoDB to store it. It has a great support for geospatial information.
Here is an example of how you do what you want using MongoDB: http://www.mongodb.org/display/DOCS/Geospatial+Indexing#GeospatialIndexing-Querying
Hi
I am having a little trouble figuring out how to convert between types of coordinates. I have a list of coordinate sets with the following description
"Coordinates are always in the WGS84 system. All coordinates a represented as integer
values x and y where the coordinate value is multiplied with 1,000,000."
An example:
559262 6319512
Well, I need to convert these to long/lat (and back) so i can use these in google maps (android). But this is not as easy as it seams. I have been searching around and did find some code to do this, but it does not seam to work properly. Anyone who can provide some code for doing this? If possible, I would like to avoid a big geo framework (it has to be used in an android application).
thanks.
best regards, kenneth
EDIT:
I did find a solution on my own. I downloaded the class described here:
http://www.ibm.com/developerworks/java/library/j-coordconvert/
And it works fine. Hope someone can find it useful.
I am sorry for posting before having done my homework decently. Thanks to everyone who posted
If you're getting the location from the GPS on android, you will get a Location object that holds Lat/Long as doubles. In order to display a point on Google Maps, you need to turn these double values into a GeoPoint object using:
GeoPoint location = new GeoPoint(
(int) (mLocation.getLatitude()) * 1E6),
(int) (mLocation.getLongitude()) * 1E6)
);
Hope thats helpful.
All GPS systems give their latitude and longitude with respect to the WGS84 model of the Earth. Unless you intend to give the lat/lon with respect to a nation's local model, such as the British OSGB36 model, you should be fine treating the coordinates you have as representing microdegrees. Even here in the Britain, the Admiralty now print their nautical charts with lat/lon relative to WGS84, I expect the Ordnance Survey land maps will follow suit soon, if they haven't already done so.