【问题标题】:Distance from Point To Line great circle function not working right.从点到线的距离大圆功能无法正常工作。
【发布时间】:2009-06-26 23:42:00
【问题描述】:

我需要获取从 lat/lng 点到直线的距离。当然需要跟随大循环。

我在http://www.movable-type.co.uk/scripts/latlong.html找到了一篇很棒的文章

但代码运行不正常。要么我做错了什么,要么缺少了一些东西。这是有问题的功能。如果需要,请参阅其他功能的链接。

    var R = 3961.3
    LatLon.crossTrack = function(lat1, lon1, lat2, lon2, lat3, lon3) {
     var d13 = LatLon.distHaversine(lat1, lon1, lat3, lon3);
     var brng12 = LatLon.bearing(lat1, lon1, lat2, lon2);
     var brng13 = LatLon.bearing(lat1, lon1, lat3, lon3);
     var dXt = Math.asin(Math.sin(d13/R)*Math.sin(brng13-brng12)) * R;
     return dXt;
    } 

纬度/经度1 = -94.127592, 41.81762

纬度/经度2 = -94.087257, 41.848202

纬度/经度3 = -94.046875, 41.791057

这报告了 0.865 英里。实际距离为 4.29905 英里。

关于如何解决这个问题的任何线索?我不是数学家,只是一个初出茅庐的程序员。

【问题讨论】:

  • 我在计算跨轨距离时也遇到了一些麻烦。我希望您使用您的代码作为示例来检查我的结果,但我无法理解您的坐标。当纬度值仅在 -90 和 +90 之间定义时,您的纬度值如何

标签: line distance point great-circle


【解决方案1】:

大多数三角函数都需要弧度。你的角度测量是度数吗?也许它们需要使用通常的公式进行转换:

2*π 弧度 = 360 度

如果您查看Haversine 公式的公式,您会看到:

(请注意,角度需要以弧度为单位才能传递给三角函数)。

【讨论】:

  • 确实如此!我只是空白轴承方法的返回值是度数。一个拍头。谢谢!
【解决方案2】:

您的函数是否为这些坐标返回相同的值:

crossTrack(0,0,0,1,0.1,0.5);
crossTrack(0,0,0,1,0.1,0.6);
crossTrack(0,0,0,1,0.1,0.4);

我认为应该,但我没有。第三个点始终是赤道以北 0.1。只有经度变化不应该影响结果。看起来确实如此。

【讨论】:

    【解决方案3】:

    我试过这个 pointlinedistancetest 发送它 aalatlon 等

    private static final double _eQuatorialEarthRadius = 6378.1370D;
    private static final double _d2r = (Math.PI / 180D);
    private static double PRECISION = 1;
    
    
    
    
    
    // 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[]cclatlng){
    
    
    
        double [] a = aalatlng;
        double [] b = bblatlng;
        double [] c = cclatlng;
    
    
    
    
        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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      • 2017-09-23
      • 2013-11-06
      • 2013-10-29
      相关资源
      最近更新 更多