vectores seno sacar rectas puntos por plano espacio entre distancia coordenadas con como cartesiano calcular angulos angulo math google-maps

math - seno - como sacar angulos por coordenadas



Calcular el ángulo entre dos puntos de latitud/longitud (16)

Asegúrese de que no sea un gran rumbo, ya que el rodamiento inicial cambia de acuerdo con la distancia.

double angle= Math.min((pbearingf-tbearingf) < 0 ? pbearingf-tbearingf+360:pbearingf-tbearingf, (tbearingf-pbearingf)<0?tbearingf-pbearingf+360:tbearingf-pbearingf);

¿Hay una manera de calcular el ángulo entre dos puntos de latitud / longitud?

Lo que estoy tratando de lograr es saber hacia dónde se dirige el usuario. Por ejemplo, el usuario se dirige al Norte, al Sur, al Sureste, etc.

Pero solo tengo dos puntos (Lng / Ltd)

Gracias


Basado en la respuesta de Nayanesh Gupte, aquí hay una implementación de Python si alguien la necesita:

def angleFromCoordinate(lat1, long1, lat2, long2): dLon = (long2 - long1) y = math.sin(dLon) * math.cos(lat2) x = math.cos(lat1) * math.sin(lat2) - math.sin(lat1) * math.cos(lat2) * math.cos(dLon) brng = math.atan2(y, x) brng = math.degrees(brng) brng = (brng + 360) % 360 brng = 360 - brng # count degrees clockwise - remove to make counter-clockwise return brng

Donde un ángulo de 0 grados indica un rumbo hacia el norte.


Código javascript de muestra si la distancia entre puntos es menor -

brng = Math.atan2(newLat - oldLat, newLong - oldLong); brng = brng * (180 / Math.PI); brng = (brng + 360) % 360; brng = 360 - brng;



En El Javascript, creo un nombre de función angleFromCoordinate en el que paso dos lat / lng. Esta función devolverá el ángel entre esos dos lat / lng

function angleFromCoordinate(lat1,lon1,lat2,lon2) { var p1 = { x: lat1, y: lon1 }; var p2 = { x: lat2, y: lon2 }; // angle in radians var angleRadians = Math.atan2(p2.y - p1.y, p2.x - p1.x); // angle in degrees var angleDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI; console.log(angleDeg); return angleDeg; }

Fragmento de código de trabajo

function angleFromCoordinate(lat1,lon1,lat2,lon2) { var p1 = { x: lat1, y: lon1 }; var p2 = { x: lat2, y: lon2 }; // angle in radians var angleRadians = Math.atan2(p2.y - p1.y, p2.x - p1.x); // angle in degrees var angleDeg = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI; document.getElementById(''rotation'').innerHTML ="Rotation : "+ angleDeg; return angleDeg; } angleFromCoordinate(37.330604,-122.028947,37.3322109,-122.0329665);

<html> <p id="rotation">Rotation : </p> </html>


En caso de que alguien necesite código PHP para esta funcionalidad:

/** * Calculate angle between 2 given latLng * @param float $lat1 * @param float $lat2 * @param float $lng1 * @param float $lng2 * @return integer */ function angle($lat1, $lat2, $lng1, $lng2) { $dLon = $lng2 - $lng1; $y = sin($dLon) * cos($lat2); $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon); return 360 - ((rad2deg(atan2($y, $x)) + 360) % 360); }


La fórmula general para calcular el ángulo (rumbo) entre dos puntos es la siguiente:

θ = atan2(sin(Δlong)*cos(lat2), cos(lat1)*sin(lat2) − sin(lat1)*cos(lat2)*cos(Δlong))

Tenga en cuenta que el ángulo (θ) se debe convertir a radianes antes de usar esta fórmula y Δlong = long2 - long1.

atan2 es una función común que se encuentra en casi todos los lenguajes de programación (principalmente en el paquete / biblioteca Math). Por lo general, también hay funciones para la conversión entre grados y radianes (también en el paquete / biblioteca de Matemáticas).

Recuerde que atan2 devuelve valores en el rango de -π ... + π, para convertir el resultado en un rumbo de la brújula, debe multiplicar θ por 180 / π y luego usar (θ + 360)% 360, donde% es la división de módulo Operación devolviendo el resto de la división.

El siguiente enlace es un buen recurso para fórmulas que involucran latitudes y longitudes. También proporcionan la implementación de Javascript de sus fórmulas. De hecho, esta respuesta se basa en la información de esta página:

http://www.yourhomenow.com/house/haversine.html


Para aquellos que usan C / C ++, a continuación está el código probado:

static const auto PI = 3.14159265358979323846, diameterOfEarthMeters = 6371.0 * 2 * 1000; double degreeToRadian (double degree) { return (degree * PI / 180); }; double radianToDegree (double radian) { return (radian * 180 / PI); }; double CoordinatesToAngle (const double latitude1, const double longitude1, const double latitude2, const double longitude2) { const auto longitudeDifferenceRadians = degreeToRadian(longitude2 - longitude1); auto latitude1Radian = degreeToRadian(latitude1), latitude2Radian = degreeToRadian(latitude2); const auto x = std::cos(latitude1Radian) * std::sin(latitude2Radian) - std::sin(latitude1Radian) * std::cos(latitude2Radian) * std::cos(longitudeDifferenceRadians); const auto y = std::sin(longitudeDifferenceRadians) * std::cos(latitude2Radian); return radianToDegree(std::atan2(y, x)); } double CoordinatesToMeters (const double latitude1, const double longitude1, const double latitude2, const double longitude2) { auto latitude1Radian = degreeToRadian(latitude1), longitude1Radian = degreeToRadian(longitude1), latitude2Radian = degreeToRadian(latitude2), longitude2Radian = degreeToRadian(longitude2); auto x = std::sin((latitude2Radian - latitude1Radian) / 2), y = std::sin((longitude2Radian - longitude1Radian) / 2); return diameterOfEarthMeters * std::asin(std::sqrt((x * x) + (std::cos(latitude1Radian) * std::cos(latitude2Radian) * y * y))); }


Para proporcionar rumbo hay que calcular el rumbo.

Para entender los rodamientos lea este artículo .

Según este artículo (sección de rodamiento) la fórmula es:

θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ ) where φ1, λ1 is the start point, φ2, λ2 the end point, Δλ is the difference in longitude`

Aquí hay una muestra de cómo calcular el ángulo (en grados) entre dos puntos expresados ​​en Lat / Lon. (hecho en C #)

Digamos que Point es una clase simple con dos atributos double X (para la longitud) y Y (para la latitud).

public double ComputeBearing(Point start,Point end) { var φ1 = start.Y; //latitude 1 var λ1 = start.X; //longitude 1 var φ2 = end.Y; //latitude 2 var λ2 = end.X; //longitude 2 var y = Math.Sin(this.degreeToRadian(λ2 - λ1)) * Math.Cos(this.degreeToRadian(φ2)); var x = Math.Cos(this.degreeToRadian(φ1)) * Math.Sin(this.degreeToRadian(φ2)) - Math.Sin(this.degreeToRadian(φ1)) * Math.Cos(this.degreeToRadian(φ2)) * Math.Cos(this.degreeToRadian(λ2 - λ1)); var θ = Math.Atan2(y, x); θ = this.radianToDegree(θ); return θ; }

Usando los siguientes métodos:

public double degreeToRadian(double angle) { return Math.PI * angle / 180.0; } public double radianToDegree(double angle) { return angle * (180.0 / Math.PI); }

Al utilizar ComputeBearing , obtendrá fácilmente un ángulo expresado en grados fácilmente utilizables como encabezado


Si está utilizando google maps (Android), hay una manera fácil: use SpericalUtil

double angle = SphericalUtil.computeHeading(fromLatLng, toLatLng);

Considera que tenemos 2 puntos y su lat y lng Luego crea su objeto Latlng

LatLng latlng = new LatLng(latValue, lngValue);

Después de obtener la latencia de 2 puntos, use la utilidad esférica para obtener el ángulo.

//import com.google.maps.android.SphericalUtil; double sphericalValue = SphericalUtil.computeHeading(latLng1, latLng2);

SpericalValue es el ángulo. Considere que tiene un ícono de automóvil y gírelo de acuerdo a la dirección en la que va. Aquí es de latLng1 a latLng2 entonces

Bitmap vehiclePin = rotateIconBitmap(sphericalValue); mMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(latLng2)) .setIcon(BitmapDescriptorFactory.fromBitmap(vehiclePin));

Usa el siguiente método para rotar

Bitmap rotateIconBitmap(double angle) { Bitmap source = BitmapFactory.decodeResource(getResources(), R.drawable.ic_vehicle_say_car); Matrix matrix = new Matrix(); matrix.postRotate((float) angle); return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); }

Una manera fácil de lograr uber como iconos rotados

Nota: es posible que tenga que agregar un desplazamiento de, por ejemplo, 90 grados si el icono del marcador no está apuntado a cero grados


Si necesita un método preciso en un elipsoide de revolución (es decir, WGS 84), los algorithms vuelven realmente pesados. Puede beneficiarse de GeographicLib , que se ha implementado en C / C ++, Java, JavaScript, Python, Matlab / Octave y otros.

Para la pregunta, hay una línea geodesic o una línea de rumbo entre el primer y el segundo punto.

Geodésico

Una geodésica es el camino más corto entre dos puntos en una superficie curva. Es la interpretación más común de dónde se dirige un "usuario" (de la pregunta), ya que es la más corta y directa. Un cálculo geodésico inverso se puede resolver utilizando GeodSolve . También puede utilizar la interfaz en línea . Esta herramienta tiene la entrada / salida:

lat1 lon1 lat2 lon2azi1 azi2 s12

Donde lat1 lon1 es el par de coordenadas para el primer punto, y lat2 lon2 es el par de coordenadas para el segundo punto. Todas las unidades están en grados (no radianes). El resultado, azi1 o α 1 , es el azimut (también conocido como rumbo) desde el punto de inicio, dado en grados hacia la derecha desde el norte. El segundo acimut está en el segundo punto, porque el ángulo entre los dos puntos a lo largo de una geodésica no es constante. Y s12 es la distancia entre los dos puntos, en metros, con una precisión de 15 nm.

Línea de rumbo

Una línea de rumbo conecta dos puntos de coordenadas con un azimut constante (o rumbo). Un cálculo de línea de rumbo inverso se puede resolver utilizando RhumbSolve . También puede utilizar la interfaz en línea . Esta herramienta tiene la entrada / salida:

lat1 lon1 lat2 lon2azi12 s12

Estos parámetros son los mismos que GeodSolve, excepto que azi12 es un ángulo constante entre los puntos.


Solo puedes usar el computeHeading de google maps:

var point1 = new google.maps.LatLng(lat1, lng1); var point2 = new google.maps.LatLng(lat2, lng2); var heading = google.maps.geometry.spherical.computeHeading(point1,point2);


Tal vez esto es lo que quieres:

cos(say) = (cosd(90-lat(1))) * (cos(90-lat(2))) + (sin(90-lat(1))) * (sind(90-lat(2)) * (cosd(abs(Landa(2)-landa(1)))));


Teniendo en cuenta la respuesta de Nayanesh Gupte y sus comentarios. He cambiado alguna parte del código y lo escribí en PHP .

  • La latitud y la longitud se han convertido a radianes dentro de la función.

Aquí está la función:

function angleFromCoordinate($lat1, $long1, $lat2, $long2) { $lat1 = deg2rad($lat1); $lat2 = deg2rad($lat2); $long1 = deg2rad($long1); $long2 = deg2rad($long2); $dLon = $long2 - $long1; $y = sin($dLon) * cos($lat2); $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon); $brng = atan2($y, $x); $brng = $brng * 180 / pi(); $brng = fmod($brng + 360, 360); return $brng; }


usando this referencia para calcular el ángulo:

private double angleFromCoordinate(double lat1, double long1, double lat2, double long2) { double dLon = (long2 - long1); 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.atan2(y, x); brng = Math.toDegrees(brng); brng = (brng + 360) % 360; brng = 360 - brng; // count degrees counter-clockwise - remove to make clockwise return brng; }


function calculateAngle(lat, lng) { var checkLengthInterval = 2; // Calculate Angle //If ObjFeed == [] add first object. if (ObjFeed.length == 0) { ObjFeed.push({ ''lat'': lat, ''lng'': lng }); } else { // Get last object from list to calculate angle betwn last and latest. var tempNode = ObjFeed[ObjFeed.length - 1]; // If last lat and lng is same as current it will always return 0 angle.so only push lat lng in obj which is diff than last one. if (!(tempNode.lat == lat && tempNode.lng == lng)) { ObjFeed.push({ ''lat'': lat, ''lng'': lng }); } else { console.log(''exact match for lat lng''); } } // this is for to keep only few objects in the list and remove other if (ObjFeed.length >= checkLengthInterval) { // calculating angle only if previous data point is available ObjFeed = ObjFeed.slice(-1 * checkLengthInterval); // remove all items in array except last two var point1 = ObjFeed[ObjFeed.length - checkLengthInterval]; var point2 = ObjFeed[ObjFeed.length - 1]; console.log(''previous point1'', point1); console.log(''next point2'', point2); var dLng = (point2.lng - point1.lng); var dLat = (point2.lat - point1.lat); dLng = dLng * 10000; dLat = dLat * 10000; var dlat_by_dlan = 0; try { dlat_by_dlan = dLng / dLat; } catch (err) { dlat_by_dlan = NaN; console.log(''Exception: dLat == 0''); } var angleDegreeBearing = 0, angleBearingRad = 0; angleBearingRad = Math.atan(dlat_by_dlan); angleDegreeBearing = angleBearingRad * 180 / Math.PI; if (dLat < 0 && dLng < 0) { angleDegreeBearing = angleDegreeBearing + 180; } else if (dLat < 0 && dLng > 0) { angleDegreeBearing = angleDegreeBearing + 180; } else if (dLat == 0 && dLng == 0) { angleDegreeBearing = prevVechicleAngle; } else if (dlat_by_dlan == NaN) { angleDegreeBearing = prevVechicleAngle; } console.log(''angleDegreeBearing'', angleDegreeBearing); } else { // setting up default angle to 0 if previous data point is not available to calculate actual anglle console.log(''feedArray default angle 0''); angleDegreeBearing = 0; } prevVechicleAngle = angleDegreeBearing; return angleDegreeBearing; }