IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Python Discussion :

Distance entre 2 lieux connus par leurs coordonnées GPS


Sujet :

Contribuez Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut Distance entre 2 lieux connus par leurs coordonnées GPS
    Bonjour,

    Ayant eu besoin de connaître la distance à vol d'oiseau entre 2 lieux connus par leurs coordonnées GPS prises sur Google Maps, je me suis fait un petit code qui marche bien, et je vous en fait profiter ici. Bien sûr, le calcul de cette distance existe déjà dans Google Maps, mais j'avais besoin d'un calcul indépendant.

    Pour avoir les coordonnées sur Google Maps (Windows), il faut pointer à la souris sur le lieu recherché, faire clic-droit => un petit menu popup s'affiche => sélectionner l'item "Plus d'infos sur cet endroit" => lire les coordonnées sur la petite fenêtre qui s'affiche. On peut faire quelque chose d'équivalent avec un smartphone ou une tablette.

    Pour l'exemple:
    Lieu A => la mairie de Tours (47.390668 Nord et 0.689319 Est)
    Lieu B => la mairie de Limoges (45.826516 Nord et 1.260290 Est)

    J'ai ajouté quelques fonctions utilitaires de conversion des angles puisque:
    - les coordonnées GPS qu'on a, peuvent être exprimées en "degrés décimaux" ou en "degrés minutes secondes"
    - la formule de calcul demande que les angles soit donnés en radians.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    """
    Source pour le calcul:
    https://geodesie.ign.fr/contenu/fichiers/Distance_longitude_latitude.pdf
    """
     
    from math import sin, cos, acos, pi
     
    #############################################################################
    def dms2dd(d, m, s):
        """Convertit un angle "degrés minutes secondes" en "degrés décimaux"
        """
        return d + m/60 + s/3600
     
    #############################################################################
    def dd2dms(dd):
        """Convertit un angle "degrés décimaux" en "degrés minutes secondes"
        """
        d = int(dd)
        x = (dd-d)*60
        m = int(x)
        s = (x-m)*60
        return d, m, s
     
    #############################################################################
    def deg2rad(dd):
        """Convertit un angle "degrés décimaux" en "radians"
        """
        return dd/180*pi
     
    #############################################################################
    def rad2deg(rd):
        """Convertit un angle "radians" en "degrés décimaux"
        """
        return rd/pi*180
     
    #############################################################################
    def distanceGPS(latA, longA, latB, longB):
        """Retourne la distance en mètres entre les 2 points A et B connus grâce à
           leurs coordonnées GPS (en radians).
        """
        # Rayon de la terre en mètres (sphère IAG-GRS80)
        RT = 6378137
        # angle en radians entre les 2 points
        S = acos(sin(latA)*sin(latB) + cos(latA)*cos(latB)*cos(abs(longB-longA)))
        # distance entre les 2 points, comptée sur un arc de grand cercle
        return S*RT
     
    #############################################################################
    if __name__ == "__main__":
     
        # cooordonnées GPS en radians du 1er point (ici, mairie de Tours)
        latA = deg2rad(47.390668) # Nord
        longA = deg2rad(0.689319) # Est
     
        # cooordonnées GPS en radians du 2ème point (ici, mairie de Limoges)
        latB = deg2rad(45.826516) # Nord
        longB = deg2rad(1.260290) # Est
     
        dist = distanceGPS(latA, longA, latB, longB)
        print(int(dist))
    Ce qui affiche: 179510 mètres => 179,51 km

    Sur le pdf de référence dont je donne le lien, on voit qu'il y a des possibilités d'avoir plus de précisions puisque la terre n'est pas une sphère parfaite.

    Amusez-vous bien!

  2. #2
    Membre averti
    Homme Profil pro
    Specialiste DataCenter
    Inscrit en
    Juin 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Specialiste DataCenter

    Informations forums :
    Inscription : Juin 2015
    Messages : 14
    Par défaut
    Merci !

    Grace a ton code je peu maintenant faire facilement la détection d'ISS quand il arrive proche de chez moi

  3. #3
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut
    Merci, c'est sympa, reste à mettre cela dans une interface, à choisir le format des coordonnées puis l'unité de sortie

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Citation Envoyé par marco056 Voir le message
    reste à mettre cela dans une interface, à choisir le format des coordonnées puis l'unité de sortie
    Pourquoi pas? Je regarde de mon côté.

  5. #5
    Membre averti
    Homme Profil pro
    Specialiste DataCenter
    Inscrit en
    Juin 2015
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Specialiste DataCenter

    Informations forums :
    Inscription : Juin 2015
    Messages : 14
    Par défaut
    Citation Envoyé par marco056 Voir le message
    Merci, c'est sympa, reste à mettre cela dans une interface, à choisir le format des coordonnées puis l'unité de sortie

    Voici mon remake : https://github.com/Gruniek/IssTracke...iss-tracker.py

    Du coup la actuellement j'ai un email quand la station est proche, l’étape suivante sera de mettre une commande pour enregistrer deux flux audio venant de la radio connecter sur les fréquences de la station, comme ca j'aurais plus a être au taquet

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Et voilà un petit programme graphique "fait sur les genoux" pour faire le calcul. Copie d'écran (j'ai repris mon 1er exemple):

    Nom : distanceGPS.jpg
Affichages : 9749
Taille : 64,9 Ko

    Crée sous Python v3.7, PyQt5 v5.15 et testé sous Windows 10.

    Code du programme (distanceGPS.py):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
     
    """
    Calcul de la distance en vol d'oiseau entre 2 lieux connus par leurs 
    coordonnées GPS.
    (Tyrtamos 12/2020)
     
    Pour calcul distance:
    https://geodesie.ign.fr/contenu/fichiers/Distance_longitude_latitude.pdf
     
    Pour correction GPS (non intégrée dans ce code):
    https://geodesie.ign.fr/contenu/fichiers/Modeles_ellipsoides_France.pdf
    """
     
    import sys
    import os
    from math import sin, cos, acos, pi
     
    from PyQt5 import (QtWidgets, QtGui, QtCore,uic)
    fenetre_ui = "distanceGPS.ui" # fenêtre issue de QtDesigner
     
    #############################################################################
    def dms2dd(d, m, s):
        """Convertit un angle "degrés minutes secondes" en "degrés décimaux"
        """
        return d + m/60 + s/3600
     
    #############################################################################
    def dd2dms(dd):
        """Convertit un angle "degrés décimaux" en "degrés minutes secondes"
        """
        d = int(dd)
        x = (dd-d)*60
        m = int(x)
        s = (x-m)*60
        return d, m, s
     
    #############################################################################
    def deg2rad(dd):
        """Convertit un angle "degrés décimaux" en "radians"
        """
        return dd/180*pi
     
    #############################################################################
    def rad2deg(rd):
        """Convertit un angle "radians" en "degrés décimaux"
        """
        return rd/pi*180
     
    #############################################################################
    def distanceGPS(latA, longA, latB, longB):
        """Retourne la distance en mètres entre les 2 points A et B connus grâce à
           leurs coordonnées GPS (en radians).
        """
        # Rayon de la terre en mètres (sphère IAG-GRS80)
        RT = 6378137
        # angle en radians entre les 2 points
        S = acos(sin(latA)*sin(latB) + cos(latA)*cos(latB)*cos(abs(longB-longA)))
        # distance entre les 2 points, comptée sur un arc de grand cercle
        return S*RT
     
    #############################################################################
    class Fenetre(QtWidgets.QWidget):
     
        #========================================================================
        def __init__(self, parent=None):
            super().__init__(parent)
     
            # charge les paramètres de dessin de la fenêtre
            self.ui = uic.loadUi(os.path.join(REPEXE, fenetre_ui), self)
     
            # lien entre le clic du bouton calculer et la méthode à lancer
            self.ui.calculer.clicked.connect(self.calculdistance)
     
        #========================================================================
        def calculdistance(self):
     
            try:
     
                #-----------------------------------------------------------------
                # latitude 1
                if self.ui.chxlat1dec.isChecked():
                    vallat1dec = float(self.ui.lat1dec.text().replace(',', '.'))
                else:
                    vallat1dec = dms2dd(float(self.ui.lat1deg.text().replace(',', '.')), float(self.ui.lat1min.text().replace(',', '.')), float(self.ui.lat1sec.text().replace(',', '.'))) 
                latitude1 = deg2rad(vallat1dec)
     
                #-----------------------------------------------------------------
                # longitude 1
                if self.ui.chxlong1dec.isChecked():
                    vallong1dec = float(self.ui.long1dec.text().replace(',', '.'))
                else:
                    vallong1dec = dms2dd(float(self.ui.long1deg.text().replace(',', '.')), float(self.ui.long1min.text().replace(',', '.')), float(self.ui.long1sec.text().replace(',', '.'))) 
                longitude1 = deg2rad(vallong1dec)
     
                #-----------------------------------------------------------------
                # latitude 2
                if self.ui.chxlat2dec.isChecked():
                    vallat2dec = float(self.ui.lat2dec.text().replace(',', '.'))
                else:
                    vallat2dec = dms2dd(float(self.ui.lat2deg.text().replace(',', '.')), float(self.ui.lat2min.text().replace(',', '.')), float(self.ui.lat2sec.text().replace(',', '.'))) 
                latitude2 = deg2rad(vallat2dec)
     
                #-----------------------------------------------------------------
                # longitude 2
                if self.ui.chxlong2dec.isChecked():
                    vallong2dec = float(self.ui.long2dec.text().replace(',', '.'))
                else:
                    vallong2dec = dms2dd(float(self.ui.long2deg.text().replace(',', '.')), float(self.ui.long2min.text().replace(',', '.')), float(self.ui.long2sec.text().replace(',', '.'))) 
                longitude2 = deg2rad(vallong2dec)
     
            except Exception:
                QtWidgets.QMessageBox.warning(self, 
                    "Erreur", 
                    "L'une des valeurs saisies n'est pas un nombre")
                return
     
            #---------------------------------------------------------------------
            # calcul et affichage de la distance en km
            distGPS = distanceGPS(latitude1, longitude1, latitude2, longitude2)
            self.ui.distancekm.setText("{:.3f}".format(distGPS/1000))
     
    #############################################################################
    if __name__ == "__main__":
     
        #========================================================================
        # Répertoire d'exécution avec ou sans pyinstaller (onedir ou onefile)
        if getattr(sys, 'frozen', False):
            REPEXE = sys._MEIPASS # programme traité par pyinstaller
        else:
            REPEXE = os.path.dirname(os.path.abspath(__file__)) # prog. normal
     
        #========================================================================
        # initialisation de la bibliothèque graphique
        app = QtWidgets.QApplication(sys.argv)
     
        #========================================================================
        #mettre la même icône pour toutes les fenêtres du programme
        app.setWindowIcon(QtGui.QIcon(os.path.join(REPEXE, "distanceGPS.png")))
     
        #========================================================================
        # style pour toute l'application
        if "Fusion" in [st for st in QtWidgets.QStyleFactory.keys()]:
            app.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
        elif sys.platform=="win32":
            app.setStyle(QtWidgets.QStyleFactory.create("WindowsVista"))
        elif sys.platform=="linux":
            app.setStyle(QtWidgets.QStyleFactory.create("gtk"))
        elif sys.platform=="darwin":    
            app.setStyle(QtWidgets.QStyleFactory.create("macintosh"))
        app.setPalette(QtWidgets.QApplication.style().standardPalette())
     
        #========================================================================
        # pour assurer la traduction automatique du conversationnel à la locale
        locale = QtCore.QLocale.system().name()
        translator = QtCore.QTranslator()
        reptrad = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath)
        translator.load("qtbase_" + locale, reptrad) # <==qtbase_fr.qm
        app.installTranslator(translator)
     
        #========================================================================
        # lancement de la fenêtre
        fen = Fenetre()
        fen.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        fen.show()
     
        #========================================================================
        # boucle de traitement des évènements et sortie
        sys.exit(app.exec_())
    A ce code s'ajoute la configuration de la fenêtre crée avec QtDesigner (distanceGPS.ui), ainsi que les icônes distanceGPS.png (pour la fenêtre QWidget) et distanceGPS.ico (pour l'exécutable Windows).

    Voilà en pièce jointe les éléments de ce programme:

    A télécharger: distanceGPS.zip

    Pour convertir ce code Python en exécutable Windows, j'utilise un fichier bat (distanceGPS.bat) et le programme pyinstaller (adapter l'adresse à votre config!):

    Code bat : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    SET programme=distanceGPS
     
    IF EXIST build_onefile RMDIR /S /Q build_onefile
    IF EXIST dist_onefile RMDIR /S /Q dist_onefile
     
    pyinstaller ^
    --clean ^
    --noconfirm ^
    --noconsole ^
    --onefile ^
    --noupx ^
    --distpath ".\dist_onefile" ^
    --workpath ".\build_onefile" ^
    --add-data ".\%programme%.ui;." ^
    --add-data ".\%programme%.png;." ^
    --add-data "E:\Programmes\Python37\Lib\site-packages\PyQt5\Qt\translations;PyQt5\Qt\translations" ^
    --icon ".\%programme%.ico" ^
    %programme%.py
    PAUSE

    Avec ce code, on obtient sous Windows un exécutable "distanceGPS.exe" facile à utiliser et à transmettre (mais trop gros pour figurer ici en pièce jointe).

    Concernant la précision du résultat: il existe plusieurs formules de calcul et plusieurs rayons de la terre (qui est une sorte de sphère avec les pôles aplatis). Mais les écarts de résultats sont très faibles et compatibles avec l'usage courant. Pour les usages spéciaux, il faut creuser la question avec les spécialistes (dont je ne suis pas).

    Amusez-vous bien!

  7. #7
    Membre Expert
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2013
    Messages
    1 617
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 617
    Par défaut
    Sous linux, j'ai un affichage un peu tronqué :
    Nom : capture-distance.png
Affichages : 9210
Taille : 23,9 Ko
    Sinon, c'est sympa, merci.

  8. #8
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Billets dans le blog
    125
    Par défaut
    Bonsoir @tyrtamos

    Pour information, en Julia, avec le paquet Geodesy.jl, j'obtiens : 179,286 km.

    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    using Geodesy # https://github.com/JuliaGeo/Geodesy.jl
     
    tours =  LLA(47.390668, 0.689319, 0.0 ) # Mairie de Tours
    limoges =  LLA(45.826516, 1.260290, 0.0 ) # Mairie de Limoges
     
    @show euclidean_distance(tours, limoges, wgs84)
    # euclidean_distance(tours, limoges, wgs84) = 179286.40723495942
     
    @show euclidean_distance(tours, limoges, nad27)
    # euclidean_distance(tours, limoges, nad27) = 179285.9144631404 
     
    @show euclidean_distance(tours, limoges, grs80)
    # euclidean_distance(tours, limoges, grs80) = 179286.40723388203

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  9. #9
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonsoir danielhagnoul,

    Citation Envoyé par danielhagnoul Voir le message
    Pour information, en Julia, avec le paquet Geodesy.jl, j'obtiens : 179,286 km.
    Merci pour l'info: on n'est pas loin. Le petit écart (0.1%) vient probablement des facteurs de correction que j'ai évoqué afin de tenir compte du fait que la terre n'est pas tout à fait une sphère (mais plutôt une ellipsoïde). Il y a certainement des utilisations qui nécessitent que cette correction soit apportée.
    Voir le pdf => https://geodesie.ign.fr/contenu/fich...e_latitude.pdf

Discussions similaires

  1. [Mappy] Comment calculer la distance entre deux coordonnées ?
    Par Malek Belkahla dans le forum Bibliothèques & Frameworks
    Réponses: 5
    Dernier message: 17/01/2013, 12h06
  2. [XL-2010] Faire des regroupements selon la distance entre des lieux
    Par flicky dans le forum Macros et VBA Excel
    Réponses: 17
    Dernier message: 03/10/2012, 06h00
  3. Distance entre deux mots par DTW ?
    Par AYDIWALID dans le forum OpenCV
    Réponses: 3
    Dernier message: 09/02/2012, 17h47
  4. Réponses: 2
    Dernier message: 05/09/2011, 10h53
  5. [Mappy] [API Challenge] Comment calculer la distance entre deux coordonnées ?
    Par Malek Belkahla dans le forum Bibliothèques & Frameworks
    Réponses: 0
    Dernier message: 06/07/2010, 11h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo