المسافة من نقطة إلى الخط وظيفة الدائرة الكبرى لا تعمل الحق.

StackOverflow https://stackoverflow.com/questions/1051723

سؤال

وأنا بحاجة للحصول على المسافة من نقطة خطوط الطول / الغاز الطبيعي المسال للخط. يحتاج بالطبع لمتابعة الدائرة العظمى.

ولقد وجدت كبيرة من المادة في هذا على 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;
    } 

وخطوط الطول / lon1 = -94.127592، 41.81762

وخطوط الطول / lon2 = -94.087257، 41.848202

وخطوط الطول / lon3 = -94.046875، 41.791057

وهذه التقارير 0.865 ميل. المسافة الفعلية هي 4.29905 ميل.

وأي أدلة إلى كيفية إصلاح هذا؟ أنا لست عالم الرياضيات، مجرد طويلة في مبرمج الأسنان.

هل كانت مفيدة؟

المحلول

ومعظم وظائف علم حساب المثلثات تحتاج راديان. هي تدابير الزاوية الخاصة بك في درجة؟ ربما أنها تحتاج إلى تحويلها باستخدام الصيغة المعتادة:

<اقتباس فقرة>   

2 * π راديان = 360 درجة

إذا نظرتم تحت صيغة لصيغة Haversine، سترى هذا:

<اقتباس فقرة>   

و(لاحظ أن زوايا يجب أن تكون بالراديان لتمريرها إلى علم حساب المثلثات وظائف).

نصائح أخرى

هل وظيفة الخاص بك إعادة نفس القيمة لهذه الإحداثيات:

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);

وأعتقد أنه ينبغي ولكن الألغام لا. نقطة 3RD دائما 0.1 إلى الشمال من خط الاستواء. فقط التغييرات الطول الذي يجب أن لا يؤثر على النتيجة. كما يبدو أنه يفعل.

وحاولت هذه 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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top