Come posso misurare la distanza e creare un riquadro di delimitazione basato su due punti di latitudine + longitudine in Java?

Sto cercando la distanza tra due punti diversi. Questo lo so può essere realizzato con la grande distanza del cerchio. http://www.meridianworlddata.com/Distance-calculation.asp

Una volta fatto, con un punto e una distanza mi piacerebbe trovare il punto che la distanza a nord, e quella distanza ad est, al fine di creare una scatola attorno al punto.

Abbiamo avuto un certo successo usando OpenMap per tracciare un sacco di dati posizionali. C’è una class LatLonPoint che ha alcune funzionalità di base, inclusa la distanza.

Ecco un’implementazione Java della formula di Haversine . Lo uso in un progetto per calcolare la distanza in miglia tra 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; } 

O potresti usare SimpleLatLng . Apache 2.0 è concesso in licenza e utilizzato in un sistema di produzione che conosco: il mio.

Storia breve:

Stavo cercando una semplice biblioteca geografica e non riuscivo a trovarne una adatta alle mie esigenze. E chi vuole scrivere, testare e eseguire il debug di questi piccoli strumenti geografici più e più volte in ogni applicazione? Deve esserci un modo migliore!

Quindi SimpleLatLng è nato come un modo per archiviare dati di latitudine-longitudine, fare calcoli a distanza e creare contorni sagomati.

So che sono in ritardo di due anni per aiutare il poster originale, ma il mio objective è aiutare le persone come me che trovano questa domanda in una ricerca. Mi piacerebbe che alcune persone lo usassero e contribuissero al test e alla visione di questa piccola utility leggera.

Per una distanza più accurata (0,5 mm) puoi anche utilizzare l’approssimazione di 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-4 precision * @see Originally posted here */ 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; } 

Questo codice è stato liberamente adattato da http://www.movable-type.co.uk/scripts/latlong-vincenty.html

Corretta la formula di Haversine Distance ….

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

È ansible utilizzare Java Geodesy Library per GPS , utilizza le formule di Vincenty che tengono conto della curvatura della superficie terrestre.

L’implementazione è così:

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

La distanza risultante è in metri.

So che ci sono molte risposte, ma nel fare alcune ricerche su questo argomento, ho trovato che la maggior parte delle risposte qui usa la formula di Haversine, ma la formula di Vincenty è in realtà più accurata. C’era un post che ha adattato il calcolo da una versione Javascript, ma è molto ingombrante. Ho trovato una versione che è superiore perché:

  1. Ha anche una licenza aperta.
  2. Usa i principi OOP.
  3. Ha una maggiore flessibilità per scegliere l’ellissoide che si desidera utilizzare.
  4. Ha più metodi per consentire calcoli diversi in futuro.
  5. È ben documentato

VincentyDistanceCalculator

Questo metodo ti aiuterà a trovare la distanza tra la posizione geografica in 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; } 

Io di solito uso MATLAB con il Mapping Toolbox e quindi uso il codice nel mio Java usando MATLAB Builder JA. Mi rende la vita molto più semplice. Dato che la maggior parte delle scuole ha accesso gratuito agli studenti, puoi provarlo (o ottenere la versione di prova per superare il tuo lavoro).