2014-09-07 3 views
0

Я хочу получить расстояние до линии и начать использовать код haversine.Точка к линии с использованием углов и haversine с 3-мя длинными точками

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

и имел много ошибок, так это написал, чтобы вычислить с помощью подшипников, чтобы получить угол затем, используя расстояние (точка а, цель), чтобы вычислить цель на линии (точка а, точка б). Точки A и B - это линия, и я хочу, чтобы расстояние от цели до линии. Нет большого круга. угол гребня (разница в подшипниках) * точка a до целевого расстояния = длина стороны прямоугольного треугольника от правого угла на линии AB до цели.

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

} 

Теперь обе все еще показывают массовые ошибки до 30%. Является ли этот код правильным и есть лучший способ сделать это или мои ошибки где-то еще. Мой GPS показывает точность 4 метра, а мои формулы (код) показывают ошибки от 10 до 20 метров и, похоже, не являются удаленно одинаковыми.

+0

вы пробовали 'distanceTo()' или 'distanceBetween()' методы Класс местоположения .... –

+0

@MichaelShrestha Я использовал distanceTo(), чтобы получить расстояние от точки a до (цель .... * sin angle = противоположная сторона точки a) .. прямоугольного треугольника. Точка B просто обеспечивает опору линии, а треугольник сделан от цели до прямого угла на линии a, b как http://www.mathsisfun.com/algebra/trig-finding-side-right-triangle. HTML. Я не знаю, где он пересекает линию, я просто хочу, чтобы расстояние до нее. – Tomsmith

ответ

0

Вы можете использовать библиотеку Google Geometry, чтобы найти длину линии и ее опору.

Из документации

computeDistanceBetween (от: LatLng, чтобы: LatLng, радиус: число) Возвращает расстояние между двумя LatLngs как число в метрах. Радиус по умолчанию соответствует радиусу Земли в метрах (6378137).

compheHeading (from: LatLng, to: LatLng) Возвращает заголовок от одного LatLng к другому LatLng. Заголовки выражаются в градусах по часовой стрелке с севера в диапазоне [-180,180) в виде числа.

computeOffset (от: LatLng, расстояние: номер, заголовок: число, радиуса: число) Возвращает LatLng в результате перемещения расстояния от начала координат в указанной статье (выраженный в градусах по часовой стрелке с севера), как LatLng.

enter image description here

первое расстояние находка между началом и концом линии

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

затем найти подшипник линии

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

От изображения 120 градусов

Затем найти Количес NCE и подшипниковые между началом линии А и точкой С

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

От изображения 50 градусов

var angleBAC = heading1-heading2 

Угол BAC = 120 - 50 градусов = 70 градусов

Как вы теперь знаете, угол BAC и расстояние от A до C вы можете использовать тригинометрию, чтобы найти длину CD

sineBAC = opp/Hypotenuese

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

От изображения

ОПП = синус 70 градусов длина X AC

От изображения 0,9397 X 5 = 4,6984

+0

У меня все еще возникали бы проблемы, скажем, от 10 до -10 градусов, и я сделал больше тестов, и это то, что дает горе, я думаю, что иногда мой код работает, а это не так. Вы объяснили это намного лучше. – Tomsmith

+0

10 - (-10) = 20 –

+0

Правда, но я ошибался, это 10 -350 в моем коде. Добавил это, но я думаю, что требуется дальнейшее тестирование \t if (bearingr> 360) { \t \t bearingr = bearingr-360; \t} \t if (bearingr <0) { \t \t bearingr = bearingr + 360; \t} \t \t если (bearingl> 360) { \t \t bearingl = bearingl-360; \t} \t if (bearingl <0) { \t \t bearingl = bearingl + 360; \t} – Tomsmith

 Смежные вопросы

  • Нет связанных вопросов^_^