Distance of wgs point from a wgs defined line segment

我怕爱的太早我们不能终老 提交于 2019-12-03 20:40:45
Jason Huntley

You can use the spherical law of cosines:

You will have to use the earth's radius for calculations:

EARTH_RADIUS_KM = 6371;

Here, from my contributions to OsmMercator.java, from openstreetmap.org:

/**
 * Gets the distance using Spherical law of cosines.
 *
 * @param la1 the Latitude in degrees
 * @param lo1 the Longitude in degrees
 * @param la2 the Latitude from 2nd coordinate in degrees
 * @param lo2 the Longitude from 2nd coordinate in degrees
 * @return the distance
 */
public static double getDistance(double la1, double lo1, double la2, double lo2) {
    double aStartLat = Math.toRadians(la1);
    double aStartLong = Math.toRadians(lo1);
    double aEndLat =Math.toRadians(la2);
    double aEndLong = Math.toRadians(lo2);

    double distance = Math.acos(Math.sin(aStartLat) * Math.sin(aEndLat)
            + Math.cos(aStartLat) * Math.cos(aEndLat)
            * Math.cos(aEndLong - aStartLong));

    return (EARTH_RADIUS_KM * distance);
}

All you need to do is find the closest point with dot product and use that with the distance equation.

Here's the closest point example:

double[] nearestPointSegment (double[] a, double[] b, double[] c)
{
   double[] t= nearestPointGreatCircle(a,b,c);
   if (onSegment(a,b,t))
     return t;
   return (distance(a,c) < distance(b,c)) ? a : c;
}

Keep in mind the units haven't been explicitly declared. When dealing with points in space there're are a variety of ways to determine position. The main thing is you have to nail down your units to a consistent type.

When working with position on the earth, I mainly use lat/long coordinates and vectors for magnitude/direction. There're are several known types to use for vectors and earth's position. Among them are the following:

  • Earth-centered earth-fixed (ECEF) coordinate system
  • North-East-Down (NED)
  • Geodetic coordinate system

For your example, I might consider sticking to Geodetic.

Now, bringing this together, you might have some pseudo code which looks like this:

Where a Vector is made up of Geodetic coordinates:
class Vector {
 double x=0.0; //latitude
 double y=0.0; //longitude
 double h=0.0; //height
...
}

public Vector closestPoint(Vector lineStartA, Vector lineEndB, final Vector thePoint ) {
    Vector w = thePoint.subtract(lineStartA);
    double proj = w.dot(lineEndB);
    // endpoint 0 is closest point
    if ( proj <= 0.0f )
        return lineStartA;
    else
    {
        //Vector square 
        double vsq = lineEndB.dot(lineEndB);
        // endpoint 1 is closest point
        if ( proj >= vsq )
            return lineStartA.add(lineEndB);
        else
            return lineStartA.add(lineEndB.multiply(proj/vsq));
    }
}      

double DistanceInKilometres(Vector lineStartA, Vector lineEndB, Vector thePoint) {
  Vector cp=closestPoint(lineStartA, lineEndB, thePoint);
  return getDistance(cp.x, cp.y, thePoint.x, thePoint.y);
}
Sam Axe

If your point lies within a corridor that is defined by the end points of your line segment, and perpendicular to the line, then this answer should do.

If your point lies outside that corridor then compute the distance from your point to each end of the line segment and take the smaller.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!