it-swarm-eu.dev

Jak mohu změřit vzdálenost a vytvořit ohraničovací rámeček založený na dvou zeměpisných šířkách + zeměpisných délkách v Javě?

Chci najít vzdálenost mezi dvěma různými body. To vím, může být dosaženo s velkou vzdálenost kruhu. http://www.meridianworlddata.com/Distance-calculation.asp

Poté, co jsem udělal, s bodem a vzdáleností bych chtěl najít bod, který se nachází na sever a vzdálenost na východ, aby se kolem bodu vytvořila krabice.

75
will

Měli jsme nějaký úspěch pomocí OpenMap pro vykreslení mnoha pozičních dat. Tam je LatLonPoint třída, která má některé základní funkce, včetně vzdálenosti.

21
Brendan Cashman

Zde je Java implementace Haversine formula. Používám to v projektu pro výpočet vzdálenosti v míle mezi lat/longs.

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

Nebo můžete použít SimpleLatLng . Apache 2.0 je licencován a používán v jednom výrobním systému, který znám: moje.

Krátký příběh:

Hledal jsem jednoduchou geo knihovnu a nemohl jsem ji najít, aby vyhovoval mým potřebám. A kdo chce psát a testovat a ladit tyto malé geo nástroje znovu a znovu v každé aplikaci? Musí být lepší způsob!

SimpleLatLng se tak narodil jako způsob ukládání dat zeměpisné šířky, výpočtu vzdáleností a vytváření tvarovaných hranic.

Vím, že jsem dva roky pozdě na to, abych pomohl originálnímu plakátu, ale mým cílem je pomoci lidem jako já, kteří tuto otázku najdou ve vyhledávání. Rád bych, aby někteří lidé používat a přispět k testování a vize tohoto malého lehký nástroj.

44
JavadocMD

Pro přesnější vzdálenost (0,5 mm) můžete také použít aproximaci 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;
}

Tento kód byl volně upraven z http://www.movable-type.co.uk/scripts/latlong-vincenty.html

11
Victor P.

Opravený vzorec vzdálenosti 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;
}   
6
Matthew Hager

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

Vím, že existuje mnoho odpovědí, ale při provádění některých výzkumů na toto téma jsem zjistil, že většina odpovědí zde používá vzorec Haversine, ale Vincentův vzorec je ve skutečnosti přesnější. Tam byl jeden příspěvek, který přizpůsobil výpočet z verze Javascript, ale je to velmi nepraktické. Našla jsem verzi, která je lepší, protože:

  1. Má také otevřenou licenci.
  2. Používá principy OOP.
  3. Má větší flexibilitu při výběru elipsoidu, který chcete použít.
  4. Má více metod umožňujících různé výpočty v budoucnu.
  5. Je to dobře zdokumentováno.

VincentyPodporaKalkulačka

1
mikeho

Tato metoda vám pomůže najít vzdálenost mezi geografickou polohou v 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;
}
1
Ad Infinitum

Můžete použít Java Geodesy Library pro GPS , používá Vincentyho vzorce které berou v úvahu zakřivení povrchu zeminy.

Implementace probíhá takto:

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

Výsledná vzdálenost je v metrech.

1
Oscar Salguero

Pro Android existuje jednoduchý přístup.

 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, výstup [])

0
makata

Obvykle používám MATLAB s Mapping Toolbox , a pak používám kód v Javě pomocí MATLAB Builder JA. Je to můj život mnohem jednodušší. Vzhledem k tomu, že většina škol má přístup ke studentům zdarma, můžete si to vyzkoušet (nebo si vyzkoušet zkušební verzi, abyste se dostali přes svou práci).

0
Chetan Rawal