Calculer l'angle entre deux points de Latitude / Longitude

Existe-t-il un moyen de calculer l'angle entre deux points de Latitude/Longitude?

ce que j'essaie de faire, c'est de savoir où va l'utilisateur. Par exemple, l'utilisateur se dirige vers le Nord, le Sud,.... Sud-Est, etc.

Mais j'ai seulement deux points (Gnl/Ltd)

Thx

18
demandé sur bwegs 2010-10-14 15:09:15

15 réponses

en utilisant reference to calculate Angle:

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;
}
38
répondu Nayanesh Gupte 2018-03-20 08:46:49

Vous ne pouvez utiliser les cartes google maps computeHeading:

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);
17
répondu Дария Печайко 2013-02-21 22:40:36

la formule générale pour calculer l'angle (relèvement) entre deux points est la suivante:

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

Notez que l'angle(θ) doivent être convertis en radians avant d'utiliser cette formule et Δlong = long2-long1.

atan2 est une fonction commune dans presque tous les langages de programmation (principalement dans le paquet de Maths/bibliothèque). Habituellement, il ya aussi des fonctions pour la conversion entre les degrés et les radians(également dans le paquet de mathématiques/bibliothèque).

Rappelez-vous que atan2 Renvoie des valeurs dans l'intervalle de-π ... +π, pour convertir le résultat en relèvement de compas, vous devez multiplier θ par 180/π puis utiliser (θ+360) % 360, où % est opération de division de module retournant le reste de la division.

le lien suivant est une bonne ressource pour les formules impliquant des latitudes et des longitudinales. Ils fournissent également L'implémentation Javascript de leurs formules. En fait, cette réponse est basée sur les informations de ce page:

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

10
répondu DotPi 2017-11-10 14:35:07

exemple de code javascript si la distance entre les points est moindre -

brng = Math.atan2(newLat - oldLat, newLong - oldLong);
brng = brng * (180 / Math.PI);
brng = (brng + 360) % 360;
brng = 360 - brng;
3
répondu poorva 2014-10-28 13:32:39

basé sur la réponse de Nayanesh Gupte, voici une implémentation Python Si quelqu'un en a besoin:

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

où un angle de 0 degrés indique un cap Nord.

3
répondu nbeuchat 2017-07-31 20:57:47

je pense que vous voulez pour le calcul des grand cercle portant.

2
répondu High Performance Mark 2010-10-14 11:12:39
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;

}
2
répondu mayur kasar 2018-03-26 14:02:33

c'est Peut-être ce que vous voulez:

cos(say) = (cosd(90-lat(1))) * (cos(90-lat(2)))
         + (sin(90-lat(1))) * (sind(90-lat(2)) * (cosd(abs(Landa(2)-landa(1)))));
1
répondu soroush 2012-05-20 06:56:25

pour ceux qui utilisent C / C++, voici le code testé:

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)));
}
1
répondu iammilind 2015-08-14 07:08:27

En cas de besoin de quelqu'un PHP code pour cette fonctionnalité:

/**
 * 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);
}
1
répondu AmirMasoud 2017-04-08 17:41:29

pour fournir le cap, vous devez calculer le roulement.

Pour comprendre roulement à lire cet article.

selon ceci l'article (section portant) la formule est la suivante :

θ = 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`

Voici un exemple sur la façon de calculer l'angle (en degrés) entre deux points exprimés en Lat/Lon. (fait en C#)

disons Point est une classe simple avec deux double attributs X (pour la longitude) et Y (pour latitude.)

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

en Utilisant les méthodes suivantes :

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

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

En utilisant ComputeBearing vous obtiendrez facilement un angle exprimé en degrés facilement utilisable comme Cap

1
répondu Marc_Alx 2017-09-14 08:04:02

si vous utilisez google maps, il y a un moyen facile - Utilisez SpericalUtil

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

Considérons que nous avons 2 points et ses lat et de gnl Puis créer son objet Latlng

LatLng latlng = new LatLng(latValue, lngValue);

après avoir obtenu Latlng de 2 points, utilisez Sperical util pour obtenir l'angle

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

SpericalValue est l'angle. Considérez que vous avez une icône de voiture et tourner à la direction de sa va. Voici son de latLng1 à latLng2 puis

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

utiliser la méthode ci-dessous pour faire pivoter

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

enter image description here

façon facile d'obtenir uber comme les icônes rotated

Remarque:- Vous pouvez avoir à ajouter un décalage de 90 degrés si l'icône de marque n'est pas fait au degré zéro

1
répondu shijin 2018-07-19 06:17:23

Assurez-vous que c'est une ligne de rhumb portant pas un grand cercle portant comme le changement de rapport initial en fonction de la distance

 double angle= Math.min((pbearingf-tbearingf) < 0 ? pbearingf-tbearingf+360:pbearingf-tbearingf, (tbearingf-pbearingf)<0?tbearingf-pbearingf+360:tbearingf-pbearingf);
0
répondu Tomsmith 2015-06-18 08:54:18

Considérant Nayanesh Gupte's réponse et de ses commentaires. J'ai changé une partie du code et l'a écrit dans PHP.

  • parallèle et longitude ont été convertis radians à l'intérieur de la fonction.

Voici la fonction:

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;
}
0
répondu Siamak A.Motlagh 2017-09-24 08:31:36

si vous avez besoin d'une méthode précise sur un ellipsoïde de révolution (i.e. WGS 84), le algorithmes obtenir vraiment lourd. Vous pouvez bénéficier d' GeographicLib, qui a été implémenté en C / C++, Java, JavaScript, Python, Matlab/Octave, et autres.

pour la question, il y a soit un géodésique et ligne de rhumb entre la première et la deuxième point.

Géodésique

un géodésique est le chemin le plus court entre deux points sur une surface courbée. C'est l'interprétation la plus courante de l'endroit où un "utilisateur se dirige" (à partir de la question), puisqu'elle est la plus courte et la plus directe. Un calcul géodésique inverse peut être résolu en utilisant GeodSolve. Vous pouvez également utiliser le interface en ligne. Cet outil a l'entrée/sortie:

lat1 lon1 lat2 lon2 azi1 azi2 S12

lat1 lon1 est la paire de coordonnées pour le premier point, et lat2 lon2 est la paire de coordonnées pour le second point. Toutes les unités sont en degrés (pas en radians). Le résultat, azi1 ou α1, est l'Azimut(A. K. A. relèvement) à partir du point de départ, en degrés dans le sens des aiguilles d'une montre à partir du Nord. Le deuxième azimut est au deuxième point, parce que l'angle entre les deux points le long d'un géodésique n'est pas constante. Et s12 est la distance entre les deux points, en mètres, avec une précision de 15 nm.

ligne de Rhumb

une ligne de rhumb relie deux points de coordonnées avec un azimut constant (ou relèvement). Un calcul inverse de la ligne de rhumb peut être résolu en utilisant Rumbsolve. Vous pouvez également utiliser le interface en ligne. Cet outil a l'entrée/sortie:

lat1 lon1 lat2 lon2azi12 s12

Ces paramètres sont les mêmes que GeodSolve, sauf que azi12 est un angle constant entre les points.

0
répondu Mike T 2018-07-23 02:28:17