android - studio - Calcule la marcación entre dos ubicaciones(lat, long)
location provider android (7)
Estoy tratando de desarrollar mi propio motor de realidad aumentada.
Buscando en internet, he encontrado este tutorial útil. Al leerlo, veo que lo importante es el rumbo entre la ubicación del usuario, la ubicación del punto y el norte.
La siguiente imagen es de ese tutorial.
Siguiendo, escribí un método Objective-C para obtener la versión beta:
+ (float) calculateBetaFrom:(CLLocationCoordinate2D)user to:(CLLocationCoordinate2D)destination
{
double beta = 0;
double a, b = 0;
a = destination.latitude - user.latitude;
b = destination.longitude - user.longitude;
beta = atan2(a, b) * 180.0 / M_PI;
if (beta < 0.0)
beta += 360.0;
else if (beta > 360.0)
beta -= 360;
return beta;
}
Pero, cuando lo intento, no funciona muy bien.
Entonces, revisé el kit de herramientas AR del iPhone para ver cómo funciona (he estado trabajando con este kit de herramientas, pero es muy grande para mí).
Y, en ARGeoCoordinate.m hay otra implementación de cómo obtener beta:
- (float)angleFromCoordinate:(CLLocationCoordinate2D)first toCoordinate:(CLLocationCoordinate2D)second {
float longitudinalDifference = second.longitude - first.longitude;
float latitudinalDifference = second.latitude - first.latitude;
float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference / longitudinalDifference);
if (longitudinalDifference > 0)
return possibleAzimuth;
else if (longitudinalDifference < 0)
return possibleAzimuth + M_PI;
else if (latitudinalDifference < 0)
return M_PI;
return 0.0f;
}
Utiliza esta fórmula:
float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference / longitudinalDifference);
¿Por qué está (M_PI * .5f) en esta fórmula? No lo entiendo
Y continuar con la búsqueda, he encontrado otra page habla sobre cómo calcular la distancia y el rumbo de 2 ubicaciones. En esta página hay otra implementación:
/**
* Returns the (initial) bearing from this point to the supplied point, in degrees
* see http://williams.best.vwh.net/avform.htm#Crs
*
* @param {LatLon} point: Latitude/longitude of destination point
* @returns {Number} Initial bearing in degrees from North
*/
LatLon.prototype.bearingTo = function(point) {
var lat1 = this._lat.toRad(), lat2 = point._lat.toRad();
var dLon = (point._lon-this._lon).toRad();
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) -
Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x);
return (brng.toDeg()+360) % 360;
}
¿Cuál es la correcta?
En la formula
float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference / longitudinalDifference);
el término (M_PI * .5f)
significa π / 2 que es 90 °. Eso significa que es la misma fórmula que mencionó al principio, porque con respecto a la figura anterior se sostiene
β = arctan (a / b) = 90 ° - arctan (b / a).
Entonces, ambas fórmulas son similares si a
refiere a la diferencia de longitud y b
a la diferencia de latitud. La última fórmula calcula nuevamente lo mismo usando la primera parte de mi ecuación.
Intente esto para obtener un resultado preciso:
private static double degreeToRadians(double latLong) {
return (Math.PI * latLong / 180.0);
}
private static double radiansToDegree(double latLong) {
return (latLong * 180.0 / Math.PI);
}
public static double getBearing() {
//Source
JSONObject source = step.getJSONObject("start_location");
double lat1 = Double.parseDouble(source.getString("lat"));
double lng1 = Double.parseDouble(source.getString("lng"));
// destination
JSONObject destination = step.getJSONObject("end_location");
double lat2 = Double.parseDouble(destination.getString("lat"));
double lng2 = Double.parseDouble(destination.getString("lng"));
double fLat = degreeToRadians(lat1);
double fLong = degreeToRadians(lng1);
double tLat = degreeToRadians(lat2);
double tLong = degreeToRadians(lng2);
double dLon = (tLong - fLong);
double degree = radiansToDegree(Math.atan2(sin(dLon) * cos(tLat),
cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(dLon)));
if (degree >= 0) {
return degree;
} else {
return 360 + degree;
}
}
Puede probar el resultado del rodamiento en sunearthtools.com/tools/distance.php .
Sé que esta pregunta es antigua, pero aquí hay una solución más fácil:
rodamiento flotante = loc1.bearingTo (loc2);
Si lo desea, puede echar un vistazo al código utilizado en el motor de realidad aumentada mixare, está en github y también hay una versión para iPhone: github.com/mixare
a
en el diagrama es la diferencia de longitud, b
es la diferencia de latitud, por lo tanto, en el método que has escrito, los obtuviste al revés.
a = destination.latitude - user.latitude; // should be b
b = destination.longitude - user.longitude; // should be a
Intenta cambiarlos y ver qué pasa.
Consulte la respuesta de Palund para obtener respuestas al resto de sus preguntas.
Calcular rodamiento
//Source
JSONObject source = step.getJSONObject("start_location");
double lat1 = Double.parseDouble(source.getString("lat"));
double lng1 = Double.parseDouble(source.getString("lng"));
// destination
JSONObject destination = step.getJSONObject("end_location");
double lat2 = Double.parseDouble(destination.getString("lat"));
double lng2 = Double.parseDouble(destination.getString("lng"));
double dLon = (lng2-lng1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
double brng = Math.toDegrees((Math.atan2(y, x)));
brng = (360 - ((brng + 360) % 360));
Convertir grados en radianes
Radians = Degrees * PI / 180
Convertir radianes en grados
Degrees = Radians * 180 / PI
here is the code for calculating bearing angle between two points(startPoint, endPoint):
public float CalculateBearingAngle(double startLatitude,double startLongitude, double endLatitude, double endLongitude){
double Phi1 = Math.toRadians(startLatitude);
double Phi2 = Math.toRadians(endLatitude);
double DeltaLambda = Math.toRadians(endLongitude - startLongitude);
double Theta = atan2((sin(DeltaLambda)*cos(Phi2)) , (cos(Phi1)*sin(Phi2) - sin(Phi1)*cos(Phi2)*cos(DeltaLambda)));
return (float)Math.toDegrees(Theta);
}
call for function:
float angle = CalculateBearingAngle(startLatitude, startLongitude, endLatitude, endLongitude);
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.sin;