4

In my Android app, I need to calculate the distance from a point (the device's location, which is a lat/lon coordinate) to a line (defined by two lat/lon coordinates), and get the result in meters.

I've taken a look at this page and the Java-code there, but I realize that I can't use that code (at least not with the lat/lon coordinates) because it will give me the distance/difference in degrees between the point and the line, and not in meters, and if I'm guessing right, it isn't possible to convert the difference in degrees to meters, right?

Therefore, I wonder how I can do this in another way, to get the distance in meters between a line and a point, both defined with lat/lon values.

EDIT: I took another aproach to the problem. Now I instead have a method which finds the point on the line which is closest to the device location.
This formula doesn't work exactly as intended when feeding it with lat/lon coorinates however. When the device location is on the line, it points right, but as the device movest away from the line, the error just gets bigger and bigger, until it stops at the end of the line.

Here is the function (based on the code in the first alternative of this answer):

/**
 * Get the closest point on a line.
 *
 * @param a The first point of the line.
 * @param b The second point of the line.
 * @param p The point to start at.
 *
 * @return The point at the line a->b which is closest to the point p.
 */
public static Location closestPointOnLine(Location a, Location b, Location p)
{
    // Store the vector a->p
    Vector a_to_p = new Vector(a, p);
    // Store the vector a->b
    Vector a_to_b = new Vector(a, b);

    // Find the square magnitude of a->b
    double squareMagnitude = square(a_to_b.x) + square(a_to_b.y);
    // Calculate the dot product of a->p and a->b
    double atp_dot_atb = a_to_p.x * a_to_b.x + a_to_p.y * a_to_b.y;

    // Calculate the normalized distance from a to the closest point
    double t = clamp(atp_dot_atb / squareMagnitude, 0d, 1d);

    // Create a new Location to store the result values in
    Location location = new Location(LocationManager.PASSIVE_PROVIDER);
    // Set the result coordinate values
    location.setLatitude(a.getLatitude() + a_to_b.x * t);
    location.setLongitude(a.getLongitude() + a_to_b.y * t);

    // Return the location
    return location;
}

The Vector class is just a class which holds two double values and represent a vector.
The clamp(double v, double min, double max) method clamps a value (v) between a minimum (min) and a maximum (max) value, in this case 0 and 1.
The square(double v) method calculates the square of a value (simply v * v).

I would be happy if someone could help me with either modifying this code a bit to return a correct point for WGS84/lat-lon coordinates, or suggest another way of doing it.
The result point should be as accurate as possible, lets say, less than 5 meters error.

  • You can transform degrees to meters. There are many free programs out there. If you know a point's coordinates on the line you can calculate the distance with the following formula: d=sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2) – Nikos Aug 3 '15 at 9:40
  • @Nikos Yes, if I can determine the point at the line which is closest to the device location, I can calculate the distance between them, but then I need another method. If you know how to write such a method, I would be more than happy! – Daniel Kvist Aug 3 '15 at 11:35
  • Don't you know the start and end coordinates of the line or a point on the line and the line's direction? If so, you can use a CAD software like AutoCAD, import the line and device coordinates and then draw a line starting from the device perpendicularly to the line. From trigonometry we know that's the closest distance. Can you upload all the data you have? Maybe I can help you. – Nikos Aug 3 '15 at 14:24
  • @Nikos Yes, I do know the start and end coordinates of the line. However, I can't use CAD, because this "calculation" is going to be performed once a second, and on an Android device, in my app. What I need is a formula/some code. – Daniel Kvist Aug 3 '15 at 17:26
  • You can calculate the vector lengths for the 3 pairs of points, draw it on a piece of paper and use trigonometry to find what you need. No need for coding! Our brain is the best machine there is! – Nikos Aug 9 '15 at 13:13
5

you can't really convert convert distances in degrees into meters as the size of a degree varies as you approach the poles. convert your locations into a projected coordinate system, then calculate your distances.

  • 1
    Can you give an example of a projected coordinate system? (It needs to cover Sweden, so SWEREF99TM might work?) – Daniel Kvist Aug 3 '15 at 9:18
  • The EUROPEAN COMMISSION lists as map projections for Sweden: SE_RT90/SE_TM. Here are more information about the projection: en.wikipedia.org/wiki/Swedish_grid – Iris Aug 3 '15 at 11:49
  • @Iris So, if I read that page correctly, one unit is equal to one meter when the coordinate values has a length of seven digits each? – Daniel Kvist Aug 3 '15 at 13:02
  • Yes, that should be correct. – Iris Aug 3 '15 at 13:11
  • 1
    Maybe there is an official WMS Server for Sweden which you can use to calculate what you need. – Nikos Aug 3 '15 at 14:26
0

I managed to solve the problem by converting all of the coordinates to contain in the formula to SWEREF99TM before I calculated the closest point. Then, I converted the closest point found with the formula, back to WGS84.

I used SWEREF99TM because it is a grid system, so the formula will work correctly.
Note that this will probably not work outside of Sweden, as the SWEREF99TM coordinate system, which I believe only works in Sweden, is used.
If the calculation only needs to work in a specific country, the key to solve this problem is to find a grid system for that country and convert the coordinates to that system before using the formula.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.