Java의 두 개의 위도+경도 지점을 기반으로 거리를 측정하고 경계 상자를 만드는 방법은 무엇입니까?

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

문제

나는 두 개의 다른 지점 사이의 거리를 찾고 싶다. 이것은 내가 아는 것이 큰 원 거리로 달성 될 수 있습니다.http://www.meridianworlddata.com/distance-calculation.asp

일단 완료되면 포인트와 거리로 북쪽으로 떨어지는 지점과 그 지점 주위에 상자를 만들기 위해 동쪽으로 거리를 찾고 싶습니다.

도움이 되었습니까?

해결책

우리는 약간의 성공을 거두었습니다 OpenMap 많은 위치 데이터를 플로팅합니다. 거기에 Latlonpoint 거리를 포함한 몇 가지 기본 기능이있는 클래스.

다른 팁

다음은 Java 구현입니다 Haversine 공식. 나는 이것을 프로젝트에서 사용하여 LAT/Long 사이의 마일로 거리를 계산합니다.

public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
    double earthRadius = 3958.75; // miles (or 6371.0 kilometers)
    double dLat = Math.toRadians(lat2-lat1);
    double dLng = Math.toRadians(lng2-lng1);
    double sindLat = Math.sin(dLat / 2);
    double sindLng = Math.sin(dLng / 2);
    double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
            * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    double dist = earthRadius * c;

    return dist;
    }

또는 사용할 수 있습니다 Simplelatlng. Apache 2.0은 내가 알고있는 하나의 생산 시스템에서 라이센스 및 사용 : Mine.

단편:

간단한 GEO 라이브러리를 찾고 있었고 내 필요에 맞는 도서관을 찾을 수 없었습니다. 그리고 모든 애플리케이션 에서이 작은 GEO 도구를 반복해서 쓰고 테스트하고 디버깅하고 싶은 사람은 누구입니까? 더 나은 방법이 있어야합니다!

따라서 Simplelatlng는 위도-단위 데이터를 저장하고 거리 계산을 수행하며 모양의 경계를 만드는 방법으로 태어났습니다.

나는 원래 포스터를 돕기에는 2 년이 너무 늦었다는 것을 알고 있지만, 내 목표는 검색 에서이 질문을 찾는 나와 같은 사람들을 돕는 것입니다. 나는 일부 사람들이 그것을 사용 하고이 작은 가벼운 유틸리티의 테스트와 비전에 기여하고 싶습니다.

보다 정확한 거리 (0.5mm)의 경우 Vincenty 근사치를 사용할 수도 있습니다.

/**
 * Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula
 * for ellipsoids
 * 
 * @param lat1
 *            first point latitude in decimal degrees
 * @param lon1
 *            first point longitude in decimal degrees
 * @param lat2
 *            second point latitude in decimal degrees
 * @param lon2
 *            second point longitude in decimal degrees
 * @returns distance in meters between points with 5.10<sup>-4</sup> precision
 * @see <a href="http://www.movable-type.co.uk/scripts/latlong-vincenty.html">Originally posted here</a>
 */
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) {
    double a = 6378137, b = 6356752.314245, f = 1 / 298.257223563; // WGS-84 ellipsoid params
    double L = Math.toRadians(lon2 - lon1);
    double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
    double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
    double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
    double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);

    double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
    double lambda = L, lambdaP, iterLimit = 100;
    do {
        sinLambda = Math.sin(lambda);
        cosLambda = Math.cos(lambda);
        sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)
                + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
        if (sinSigma == 0)
            return 0; // co-incident points
        cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
        sigma = Math.atan2(sinSigma, cosSigma);
        sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
        cosSqAlpha = 1 - sinAlpha * sinAlpha;
        cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
        if (Double.isNaN(cos2SigmaM))
            cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)
        double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
        lambdaP = lambda;
        lambda = L + (1 - C) * f * sinAlpha
                * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
    } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);

    if (iterLimit == 0)
        return Double.NaN; // formula failed to converge

    double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
    double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
    double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
    double deltaSigma = B
            * sinSigma
            * (cos2SigmaM + B
                    / 4
                    * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM
                            * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
    double dist = b * A * (sigma - deltaSigma);

    return dist;
}

이 코드는 자유롭게 조정되었습니다 http://www.movable-type.co.uk/scripts/latlong-vincenty.html

수정 된 Haversine 거리 공식 ....

public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2) 
{
    // mHager 08-12-2012
    // http://en.wikipedia.org/wiki/Haversine_formula
    // Implementation

    // convert to radians
    lat1 = Math.toRadians(lat1);
    lng1 = Math.toRadians(lng1);
    lat2 = Math.toRadians(lat2);
    lng2 = Math.toRadians(lng2);

    double dlon = lng2 - lng1;
    double dlat = lat2 - lat1;

    double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);

    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return EARTH_RADIUS * c;
}   

http://www.movable-type.co.uk/scripts/latlong.html

public static Double distanceBetweenTwoLocationsInKm(Double latitudeOne, Double longitudeOne, Double latitudeTwo, Double longitudeTwo) {
        if (latitudeOne == null || latitudeTwo == null || longitudeOne == null || longitudeTwo == null) {
            return null;
        }

        Double earthRadius = 6371.0;
        Double diffBetweenLatitudeRadians = Math.toRadians(latitudeTwo - latitudeOne);
        Double diffBetweenLongitudeRadians = Math.toRadians(longitudeTwo - longitudeOne);
        Double latitudeOneInRadians = Math.toRadians(latitudeOne);
        Double latitudeTwoInRadians = Math.toRadians(latitudeTwo);
        Double a = Math.sin(diffBetweenLatitudeRadians / 2) * Math.sin(diffBetweenLatitudeRadians / 2) + Math.cos(latitudeOneInRadians) * Math.cos(latitudeTwoInRadians) * Math.sin(diffBetweenLongitudeRadians / 2)
                * Math.sin(diffBetweenLongitudeRadians / 2);
        Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return (earthRadius * c);
    }

당신은 사용할 수 있습니다 GPS 용 Java Geodesy 라이브러리, 그것은 사용합니다 Vincenty의 공식 지구 표면 곡률을 고려합니다.

구현은 다음과 같습니다.

import org.gavaghan.geodesy.*;
...
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0);
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0);
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();

결과 거리는 미터입니다.

나는 많은 대답이 있다는 것을 알고 있지만,이 주제에 대한 연구를 할 때, 여기서 대부분의 답변은 Haversine 공식을 사용하지만 Vincenty 공식은 실제로 더 정확합니다. JavaScript 버전에서 계산을 조정 한 게시물이 하나 있었지만 매우 다루기 쉬웠습니다. 우수한 버전을 찾았습니다.

  1. 또한 공개 라이센스도 있습니다.
  2. OOP 원칙을 사용합니다.
  3. 사용하려는 타원체를 선택할 수있는 유연성이 더 높습니다.
  4. 향후 다른 계산을 허용하는 더 많은 방법이 있습니다.
  5. 잘 문서화되어 있습니다.

Vincentydistancecalculator

이 방법은 km의 지리적 위치 사이의 거리를 찾는 데 도움이됩니다.

private double getDist(double lat1, double lon1, double lat2, double lon2)
{
    int R = 6373; // radius of the earth in kilometres
    double lat1rad = Math.toRadians(lat1);
    double lat2rad = Math.toRadians(lat2);
    double deltaLat = Math.toRadians(lat2-lat1);
    double deltaLon = Math.toRadians(lon2-lon1);

    double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
            Math.cos(lat1rad) * Math.cos(lat2rad) *
            Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    double d = R * c;
    return d;
}

나는 일반적으로 matlab을 사용합니다 도구 상자 매핑, 그런 다음 내 Java에서 코드를 사용하여 사용하십시오. MATLAB BUILDER JA. 그것은 내 인생을 훨씬 간단하게 만듭니다. 대부분의 학교가 무료 학생 액세스를 위해이를 가지고 있으면 시도해 볼 수 있습니다 (또는 시험판이 작업을 극복 할 수 있습니다).

안드로이드의 경우 간단한 접근 방식이 있습니다.

 public static float getDistanceInMeter(LatLng start, LatLng end) { 
    float[] results = new float[1];
    Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
    return results[0];

}

;

https://developer.android.com/reference/android/location/location#distancebetween (lat1, lng1, lat2, lng2, output [])

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top