Wie kann ich Abstand messen und einen Begrenzungsrahmen auf zwei Breite + Länge Punkte in Java-basierte erstellen?

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

Frage

Ich wünsche den Abstand zwischen zwei verschiedenen Punkten zu finden. Das weiß ich kann mit der Großkreisentfernung erreicht werden. http://www.meridianworlddata.com/Distance-calculation.asp

Ist das erledigt, mit einem Punkt und Entfernung würde Ich mag den Punkt finden, dass der Abstand nach Norden, und dass der Abstand Osten, um einen Rahmen um den Punkt zu erstellen.

War es hilfreich?

Lösung

Wir haben einen gewissen Erfolg hatte mit OpenMap viele Positionsdaten plotten. Es gibt einen LatLonPoint Klasse, die einige grundlegende hat Funktionalität, einschließlich der Entfernung.

Andere Tipps

Hier ist eine Java-Implementierung von Haversine Formel. Ich benutze dies in einem Projekt Entfernung in Meilen zwischen lat / Long-Positionen zu berechnen.

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

Oder Sie könnten benutzen SimpleLatLng . Apache 2.0 lizenziert und in einem Produktionssystem verwendet, die ich kenne. Mine

Kurzgeschichte:

Ich war für eine einfache geo Bibliothek suchen und nicht finden kann, um meine Bedürfnisse anzupassen. Und wer will schreiben und zu testen und debuggen diese kleinen Geo-Tools immer und immer wieder in jeder Anwendung? Es muss ein besserer Weg sein!

So SimpleLatLng wurde als ein Weg geboren Berechnungen zu speichern Breite-Länge-Daten, tut Abstand und förmige Grenzen zu schaffen.

Ich weiß, ich bin 2 Jahre zu spät das ursprüngliche Plakate zu helfen, aber mein Ziel ist es, die Menschen wie mir zu helfen, die diese Frage in der Suche. Ich würde gerne einige Leute es verwenden haben und auf das Testen und die Vision dieses kleinen leichten Programms beitragen.

Für einen genaueren Abstand (0,5 mm), die Sie auch die Vincenty Annäherung verwenden können:

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

Dieser Code wurde frei nach http: //www.movable- type.co.uk/scripts/latlong-vincenty.html

Korrigierte Haversine Entfernung Formel ....

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

Sie können die Java Geodäsie Bibliothek für GPS , verwendet es die Vincenty Formeln , die aufgrund der Erdoberfläche nimmt Krümmung.

Die Umsetzung geht wie folgt aus:

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

Der resultierende Abstand in Metern.

Ich weiß, dass es viele Antworten, aber einige der Forschung zu diesem Thema, fand ich, dass die meisten Antworten hier die Haversine Formel verwenden, aber die Vincenty Formel ist eigentlich genauer. Es gab einen Beitrag, der die Berechnung von einer Javascript-Version angepasst, aber es ist sehr unhandlich. Ich fand eine Version, die überlegen ist, weil:

  1. Es hat auch eine offene Lizenz.
  2. Es nutzt OOP-Prinzipien.
  3. Es hat eine größere Flexibilität des Ellipsoid Sie verwenden möchten, wählen.
  4. Es ist mehr Methoden hat für verschiedene Berechnungen in Zukunft zu ermöglichen.
  5. Es ist gut dokumentiert.

VincentyDistanceCalculator

Diese Methode würden Sie helfen, den Abstand zwischen der geographischen Lage in km zu finden.

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

ich verwende in der Regel MATLAB mit dem Mapping Toolbox , und dann den Code in meinem Java verwenden MATLAB Builder JA. Es macht mein Leben viel einfacher. Gegeben die meisten Schulen haben es kostenlos Student Zugang, können Sie es ausprobieren (oder die Testversion erhalten über Ihre Arbeit zu bekommen).

Für Android gibt es eine einfache Lösung.

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

}

;

scroll top