I am looking for good solution to calculate distance between two points.
I want to sort by distance my Geo points.
I have:
Cursor c = database.rawQuery("SELECT name,latitude,longitude,((longitude-21.15)*(longitude-21.15) +(latitude-54.05)*(latitude-54.05)) AS len FROM Object ORDER BY len;", null);
But this is wrong solution...
Distance is wrong...
Please help me.
The problem you have here is that you're combining:
GPS coordinates (WGS84) that are used to represent a point on a sphere.
Pythagoras theorem, requires a 2D rectangular coordinate system, to determine distance.
This will simply not work if you're after accuracy!
Here are some options that I've used.
Option 1 - Use great circle distance
This formula is used to calculate the distance in meters between two GPS co-ordinates
Android provides a function distanceBetween as part of the android.location.Location class to assist with this.
The downside is you have to pull out all your points from SQLite in order to calculate the distance.
I have also seen some hybrids such as:
treating WGS84 (GPS) as rectangular
specifying a zones in your db to limit the size of data you pull out when calculating distance.
and then using the distanceBetween function to further filter the results.
Option 2 - Use a rectangular coordinate system
If your distances are small then you can solve this problem is by storing the database points in UTM which is rectangular.
Using a formula almost identical, but using easting and northings, the SQLite db can be used to provide the x closest points to a UTM point. Once these points are identified the square-root function can be performed on the x results to get the distance in meters.
Huh?
There are some caveats about using UTM also. It might help you looking at Calculating Distance Between Two Sets of Coordinates
So your solution ultimately depends on your application and is a compromise between speed and accuracy.
You are calculating the square of the distance. Since SQLite doesn't have a square-root function, you will need to calculate this in your Java code.
If all you need is to sort by distance, then your current code is fine.
You can use static method distanceBetween of android.location.Location class. Then based on calculated distance you can produce some sorted collection of object like SortedMap.
Related
I'm working on an android application which can track movements. My problem is that I need to convert gps coordinates to 2-d coordinate on a plane.
The coordinates which I obtain now are in WSG84 format. I need those coordinates because a I need to compute the distance between a point and a line in order to understand if I'm getting too far from a pre-defined path. The area in which I'm working on is not big in respect to the whole earth, so I think it's okay to not care about z axis.
I have no map, so I just need to compute these coordinates in background. Thanks!
This:
I need to compute the distance between a point and a line in order to understand if I'm getting too far from a pre-defined path
seems to be the key question you are posing. So that is what I will answer.
In a strict sense, converting from spherical to euclidean coordinates is not possible, which is why people invented to the UTM system among many others. The problem with using UTM for your purpose is that a given lat/lon may be in different regions, so the (x,y) pairs will not correlate usefully.
Assuming you have three points A, B and P, where A & B define the start and end of your line, and P is the point you want to know about, then my best suggestion is to:
calculate the great circle distance (d) from P to B
calculate the bearing from the P to B (theta)
calculate the bearing from A to B (alpha)
If the points are actually very close to each other then the space you are working in is locally euclidean, so the distance from the line from A to B is:
d sin(alpha - theta)
There are numerous online references on calculating great circle distance and bearing in Java for WGS84. eg.
http://openmap.bbn.com/svn/openmap/trunk/src/openmap/com/bbn/openmap/proj/GreatCircle.java
...is just one of many.
I'm trying to implement a small part of AR, The purpose is to filter locations based on My Location and A direction (North by example) :
I know that to know Direction i need to use Sensor type Orientation
Memory Conception
So can someone help ?
Well, you can get the distance and angle to a point by using Location.distanceTo(). So you'd want to loop through all the points, get the distance and bearing. If the object is close enough and the bearing is within the angle you want, then you treat it as a good point and display it. If it isn't, you skip it.
In my application I need to calculate the distance between two gps devices.
When using a GPS coordinates (longitude, latitude, altitude) there is a problem:
The height is determined with greater absolute error. You can verify this by calculating the error
phi and tetta (latitude and longitude) on the basis of formulas
x = r*sin(tetta)*cos(phi)
y = r*sin(tetta)*cos(phi)
z = r*cos(tetta)
However, it is obvious that the GPS receiver is at the beginning accepts data in a Cartesian coordinate system (x, y, z), and then translates them
the system of coordinates r, tetta, phi (altitude, latitude, longitude).
How can I get the original coordinates x,y,z? Are there existing methods in the API? Once again, I don't need conversion formulas
from a spherical coordinate system in a rectangular, I need the accuracy of the original data obtained from a GPS receiver. Is it possible?
You are right the GPS receiver internally uses the ECEF Coordinate system, which is cartesian.
But you cannot get that coordinates on a smartphone. See the above link for conversion from WGS84 coordinates you get in the smartphone to ECEF.
But be warned ECEF this is a 3d cartesian, so the direct line between two points will cut through the earth, that is usefull only for flight applications.
For vehicles (cars, ships) normally you should forget the height of an GPS, just calculate the ground distance (2d- cartesian).
Another solution: first do a (lat,lon) to 2-d cartesian conversion with units meter, then add the height as 3d dimension, this then modells a small part of the earth as flat.
It always depends for whoich purpose you need the calculation.
Why is it obvious that the GPS starts with Cartesian coordinates?
In any case, I'm not seeing a way to get the accuracy of a particular element of the location from the API. It is true that altitude tends to be most error prone (and depends on chipset and is above the reference geoid rather than anything physical). You could get some indication of accuracy by recording data for altitude and modelling the variation.
I have this table in sqlite
Locations
ID
Lat ( latitude)
Lon ( longitude)
Type
Name
City
I have for example 100 records
what I need is to get (using my own coordinates) the nearest point in my table.
What I did is to get the shortest distance between my current point and each one in the table, and return the shortest one, but I am searching for a better solution
Thanks
A possible solution is to use a grid for the whole map your are interested in and pre-assign points to a particular row/column. Then:
Calculate the grid location of your new point - add a column to the database for this.
Calculate the distance of all coordinates in the current grid - if one exists
You still need to calculate all the distances in the next grid out (you are unlikely to be perfectly centered in your current square, you always need to check one grid distance out from the one your best match was in.)
Should cut down a lot on the number of calculations you need to do.
If you expect to always find a location within X distance you could query for x/y coords that would fall within that range your coords +/- x KM (a square), calculate if they then fall within the xKM circle from your point, and then choose the shortest.
UPDATE - Grid option
I am assuming you already are doing the distance between two points calculation and will not describe that.
If you have an atlas handy you can see an example by looking a place up in the index. It will give you a page and a grid location like M5. If you go to that page it will have rows and columns labeled with numbers and letters and if you look in the square where row M and column 5 intersect you will find the city there. To do it for your system you need to:
determine how big your grid should be (how dense are your points - would be no good to have a big grid and all your points land in one square).
For each point calculate which grid it is in. If your polygons are complex there is tons of point in polygon code out there to copy. If (as my example is) you just use squares, you just need to determine which row/column each point is between.
See map for user location and closest points example:
So if the user is the green marker, he would be in C4. You would search all other points in C4 and determine that the closest is #2. Then you would also have to check one grid out all the way around to make sure there wasn't a closer item than the one you found, so this includes squares: B3,B4,B5,C3,C5,D3,D4,D5. When you do you will pick #3 from C3 and you are finished.
If the user had been in square D2 where there are no other points your would have found your first match in say C2. When checking C1,C2,C3,D1,D3,E1,E2,E3. Once found you would then again need to check another radius out, which would have be: B0-4, C0,C4,D0,D4,E0,E4,F0-4. etc. You can see that grid selection will be important to make this as efficient as possible.
Also Note this assumes your grids are equal unlike my hand drawn example.
Option 2:
If you expect a result within X km, and you want something your DB will calculate quickly you can do this:
LatMin = currentLatCoord-radiusValInDegrees
LatMax = currentLatCoord+radiusValInDegrees
LonMin = currentLonCoord-radiusValInDegrees
LonMax = currentLonCoord+radiusValInDegrees
SELECT *
From Locations
WHERE Lat BETWEEN LatMin AND LatMax
AND Lon BETWEEN LonMin AND LonMax
Now this gives you all results in a square. It is important that you then check they are actually in the circle - you need to drop any in the corners as there may actually be closer coordinates than those on the edge of the circle. So for each point check if it is inside the circle first (Equation for testing if a point is inside a circle) then calculate the distance and keep the closest one. If you do not get a result, widen the circle.
Again, selecting a good radius will depend on your data.
Have you check this Site of how to count for the distance between two points on Earth?
But just keep in mind that it give the Distance based on Earth Surface not based on the actual path to reach at that position. So if you want to count distance based on the Actual Path to reach that position then you can get it by using Google MAP API.
Google Maps API gives the distance between two point based on the actual path.
Hope this information surly help you.
Enjoy Coding... :)
Distance between two points: ((x1 - x2) ^ 2 + (y1 - y2) ^ 2) ^ 0.5. However, distance between these points are straight lines. Most likely, there are variables like local vs highway, not to mention one-way streets and waterways, where you need to find the nearest bridge. Therefore, I suggest using Google and Bing maps api. The are free for a limited number of searches.
There's a rather clever solution over at Query to get records based on Radius in SQLite?
based on precalculating some trigonometric values for each position when inserting the rows which then lets you calculate the distance in your query only using arithmetic functions.
I've used it very successfully in my own code
Let me make sure this is right: You have point a, and a table of points a[]. Currently, you do something like:
loop over b[]
get distance from b[i] to a
if distance is less than minimumDistance
set minimumDistance = distance
set closestPoint = i
return closestPoint
If so, you're finding it in O(n) time, which can't really be improved upon much. You have to check all the points to see which are the closest.
However, as Matthew points out, you can prune n by assigning points to a grid. This can drastically reduce the amount of points needed to compare. The expense is a bit of time preprocessing, and slightly more complicated logic. If you have a long list of points(or the distance() function takes a long time), you'll definitely want to do something like this.
Depends how much you care about being correct when near the poles
if closest by pythagorean distance is good enough you can use this in the orderby of the sql
eg. SELECT * FROM locations ORDERBY (Lat-myLat)*(Lat-myLat) + (Lon-myLon)*(Lon-myLon) LIMIT 1
Not technically the most correct, but saves getting all locations from the database and looping over them, let sqlite do that for you
You can use my php class hilbert curve # phpclasses.org. It uses a monster curve and a quadkey to find the shortest distance. To search the quadkey you can use any depth.
Though this is not a best option.
Let you are trying to figure out shortest distance within N mile/km radious for fixed no of locations/your location table data are not changing regularly.
Add another column Distance_Index (DI) a self multi reference key ArrayType. Once run a procedure and update the DI with ID in ascending order accoording to distance from this DI.
Now from next time onwords distance is with you. just make a query to the database and use it.
Now, in your problem no of location are less within N, then DI will not be too much long.Just as an opinion.
I have the coordinates of a player and another object. Both are with geographical coordinates (Latitude and longitude). I have also the direction in what the player is facing (compass). How can I calculate the angle to the other object from the player direction? e.g. I want to know if the object is to the right/left of the player and how many degrees.
Thanks a lot!
With a few it depends, the answer is in essence, you want to know about how to do geographic navigation. One of the reasons it depends is that the distances involve as well as the accuracy needed may influence the answer.
For short distances (<10km) you may be able to ignore the curvature of the Earth, and treat it like a two dimensional Cartesian map (latitude / longitude as X-Y). Then you question becomes basic trigonometry.
For larger distances, or improved accuracy, you can either approximate using an spheroid model of the Earth (assume the Earth is a perfect sphere, which it is not) and calculate the Great Circle bearing and distance.
Or you can model the Earth as an ellipsoid, and calculate its geographic navigation.
Two web pages that may help: Details for computing distance using lat/long coordinates and Calculate distance, bearing and more between Latitude/Longitude points.
Note: atan2 and Haversine formula are often useful implementation details.
Small added note: bearing is a synonym for heading or direction in this context.
You need this spherical trig formula: http://williams.best.vwh.net/avform.htm#Crs Once you have the course (angle relative to true north), you can subtract off the compass heading of the direction the player is facing to get the relative heading.
(I don't know if Android automatically compensates for magnetic variation or not, but if not you'll have to account for it too to get the angle right in all areas)
There are tools in the API to do this for you: Location.bearingTo(Location) and GeomagneticSensor will give you the direction from your position to the target - which you can then adjust based off the devices current heading.
If you've already got a MapView running & are lazy, set up a MyLocationOverlay, enableCompass and skip the GeomagneticSensor and let the MapView do it for you.