point to line using angles and haversine with 3 lat long points

I wish to get the distance to a line and started using haversine code.

 private static final double _eQuatorialEarthRadius = 6378.1370D;
    private static final double _d2r = (Math.PI / 180D);
    private static double PRECISION = 0.001;

    // Haversine Algorithm
    // source: http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates

    private static double HaversineInM(double lat1, double long1, double lat2, double long2) {
        return  (1000D * HaversineInKM(lat1, long1, lat2, long2));

    }

    private static double HaversineInKM(double lat1, double long1, double lat2, double long2) {
        double dlong = (long2 - long1) * _d2r;
        double dlat = (lat2 - lat1) * _d2r;
        double a = Math.pow(Math.sin(dlat / 2D), 2D) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r)
                * Math.pow(Math.sin(dlong / 2D), 2D);
        double c = 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a));
        double d = _eQuatorialEarthRadius * c;

        return d;
    }

    // Distance between a point and a line

    public static double pointLineDistanceTest(double[] aalatlng,double[] bblatlng,double[] ttlatlng) {


        double [] a = aalatlng;
        double [] b = bblatlng;
        double [] c = ttlatlng;


        double[] nearestNode = nearestPointGreatCircle(a, b, c);
//        System.out.println("nearest node: " + Double.toString(nearestNode[0]) + "," + Double.toString(nearestNode[1]));
        double result =  HaversineInM(c[0], c[1], nearestNode[0], nearestNode[1]);
//        System.out.println("result: " + Double.toString(result));


              return (result);


    }

    // source: http://stackoverflow.com/questions/1299567/how-to-calculate-distance-from-a-point-to-a-line-segment-on-a-sphere
    private static double[] nearestPointGreatCircle(double[] a, double[] b, double c[])
    {
        double[] a_ = toCartsian(a);
        double[] b_ = toCartsian(b);
        double[] c_ = toCartsian(c);

        double[] G = vectorProduct(a_, b_);
        double[] F = vectorProduct(c_, G);
        double[] t = vectorProduct(G, F);

        return fromCartsian(multiplyByScalar(normalize(t), _eQuatorialEarthRadius));
    }

    @SuppressWarnings("unused")
    private static double[] nearestPointSegment (double[] a, double[] b, double[] c)
    {
       double[] t= nearestPointGreatCircle(a,b,c);
       if (onSegment(a,b,t))
         return t;

       return (HaversineInKM(a[0], a[1], c[0], c[1]) < HaversineInKM(b[0], b[1], c[0], c[1])) ? a : b;
    }

     private static boolean onSegment (double[] a, double[] b, double[] t)
       {
         // should be   return distance(a,t)+distance(b,t)==distance(a,b), 
         // but due to rounding errors, we use: 
         return Math.abs(HaversineInKM(a[0], a[1], b[0], b[1])-HaversineInKM(a[0], a[1], t[0], t[1])-HaversineInKM(b[0], b[1], t[0], t[1])) < PRECISION;
       }


    // source: http://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates
    private static double[] toCartsian(double[] coord) {
        double[] result = new double[3];
        result[0] = _eQuatorialEarthRadius * Math.cos(Math.toRadians(coord[0])) * Math.cos(Math.toRadians(coord[1]));
        result[1] = _eQuatorialEarthRadius * Math.cos(Math.toRadians(coord[0])) * Math.sin(Math.toRadians(coord[1]));
        result[2] = _eQuatorialEarthRadius * Math.sin(Math.toRadians(coord[0]));


        return result;
    }

    private static double[] fromCartsian(double[] coord){
        double[] result = new double[2];
        result[0] = Math.toDegrees(Math.asin(coord[2] / _eQuatorialEarthRadius));
        result[1] = Math.toDegrees(Math.atan2(coord[1], coord[0]));

        return result;
    }


    // Basic functions
    private static double[] vectorProduct (double[] a, double[] b){
        double[] result = new double[3];
        result[0] = a[1] * b[2] - a[2] * b[1];
        result[1] = a[2] * b[0] - a[0] * b[2];
        result[2] = a[0] * b[1] - a[1] * b[0];

        return result;
    }

    private static double[] normalize(double[] t) {
        double length = Math.sqrt((t[0] * t[0]) + (t[1] * t[1]) + (t[2] * t[2]));
        double[] result = new double[3];
        result[0] = t[0]/length;
        result[1] = t[1]/length;
        result[2] = t[2]/length;
        return result;
    }

    private static double[] multiplyByScalar(double[] normalize, double k) {
        double[] result = new double[3];
        result[0] = normalize[0]*k;
        result[1] = normalize[1]*k;
        result[2] = normalize[2]*k;
        return result;
    }

and had many errors so wrote this to calculate using bearings to get the angle then using distance (point a, target) to calculate the target to (point a, point b) line. Point A and B are the line and I want the distance from target to line. No great circle. sin angle (difference in bearings) *point a to target distance= Length of the side of a right angle triangle from the right angle on AB line to target.

 public  double pointlinedistancetest(){

     //set latlng location point a
     Location apoint=new Location("");

     apoint.setLatitude(lata);
     apoint.setLongitude(lona);


     //set latlng location point b
     Location bpoint=new Location("");

     bpoint.setLatitude(latb);
     bpoint.setLongitude(lonb);


     //set latlng location target to get dis to line
     Location tpoint=new Location("");

     tpoint.setLatitude(lat);
     tpoint.setLongitude(lon);


     float pbearingf = apoint.bearingTo(bpoint);

     float tbearingf= apoint.bearingTo(tpoint);

     double tb=tbearingf;
     double ab=pbearingf;



             //get angle degree difference 
    float angle= Math.min((pbearingf-tbearingf)<0?pbearingf-tbearingf+360:pbearingf-tbearingf, (tbearingf-pbearingf)<0?tbearingf-pbearingf+360:tbearingf-pbearingf);
//   float angle= Math.min((tbearingf-pbearingf)<0?tbearingf-pbearingf+360:tbearingf-pbearingf, (pbearingf-tbearingf)<0?pbearingf-tbearingf+360:pbearingf-tbearingf); 

    // min((a1-a2)<0?a1-a2+360:a1-a2, (a2-a1)<0?a2-a1+360:a2-a1)


     double aabearing=angle;

              float atot=apoint.distanceTo(tpoint);

     double atotdis=atot;

             //right angle triangle formula
     dis=(Math.sin(aabearing))*atotdis;

     return (dis);

}

Now both are still showing massive errors of up to 30%. Does this code look correct and is there any better way of doing this or are my errors else where. My GPS is showing 4 metre accuracy and my formulas(code) is showing errors of 10 to 20 metres and does not seem to be remotely the same.


You can use Google Geometry library to find length of line and its bearing .

From documentation

computeDistanceBetween(from:LatLng, to:LatLng, radius?:number) Returns the distance between two LatLngs as a number in meters. The radius defaults to the Earth's radius in meters(6378137).

computeHeading(from:LatLng, to:LatLng) Returns the heading from one LatLng to another LatLng. Headings are expressed in degrees clockwise from North within the range [-180,180) as a number.

computeOffset(from:LatLng, distance:number, heading:number, radius?:number) Returns the LatLng resulting from moving a distance from an origin in the specified heading (expressed in degrees clockwise from north) as LatLng.

在这里输入图像描述

First find distance between start and end of line

var spherical = google.maps.geometry.spherical; 
var length = google.maps.geometry.spherical.computeDistanceBetween(A,B);

Then find bearing of line

 var heading = google.maps.geometry.spherical.computeHeading(A,B);

From image 120 degrees

Then find distance and bearing between start of line A and point C

var length2 = google.maps.geometry.spherical.computeDistanceBetween(A,C);
var heading2 = google.maps.geometry.spherical.computeHeading(A,C);

From image 50 degrees

var angleBAC = heading1-heading2

Angle BAC = 120 - 50 degrees = 70 degrees

As you now know angle BAC and distance from A to C you can use triginometry to find length CD

sineBAC = opp/Hypotenuese

var CD = Math.sin(angleBAC) * length2;

From Image

opp = sine 70 degrees X length AC

From image 0.9397 X 5 = 4.6984

链接地址: http://www.djcxy.com/p/85008.html

上一篇: 使用极坐标的最近邻居

下一篇: 指向使用角度和半径为3 lat的三角形