Tri coordonnées gps

nicdu40 Messages postés 25 Date d'inscription   Statut Membre Dernière intervention   -  
-
Bonjour,

j'ai un tableau comme suit:

azert;brazil;-14.235004;-51.92528
azerty;bordeaux;44.837789;-0.57918
toto;liboune;44.912998;-0.243985
nom;paris;48.856614;2.3522219
tata;marseille;43.296482;5.36978
kiki;nice;43.7101728;7.2619532

j'ai donc le nom;adresse;latitude;longitude ,

j'arrive a trier sans problème individuellement, par contre comment m'y prendre pour pour faire un trie en fonction des distances entre chaque adresse?

je débute en perl , une piste serait la bien venue, Merci

A voir également:

5 réponses

Utilisateur anonyme
 
Bonsoir, à cette adresse une source récente pour le calcul de distance suivant la méthode sphérique.

https://codes-sources.commentcamarche.net/source/100762-classe-gps-calcul-distance

Cette méthode donne des résultats approximatifs.
Si tu veux plus précis recherche "loxodromie" sur les sites de l'IGN.


--
0
mpmp93 Messages postés 6648 Date d'inscription   Statut Membre Dernière intervention   1 340
 
Merci pour le "approximatif". Les distances sont précises à quelques mètres et sont valables pour l'altitude 0. Ce sont des distances à vol d'oiseau, c'est à dire en ligne droite.

A+
0
nicdu40 Messages postés 25 Date d'inscription   Statut Membre Dernière intervention   1
 
oui merci pour les distances pas de soucis:

my $pi = 3.14159265358979;

sub deg_to_rad { ($_[0]/180) * $pi }
sub rad_to_deg { ($_[0]/$pi) * 180 }
sub asin { atan2($_[0], sqrt(1 - $_[0] * $_[0])) }
sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }
sub tan { sin($_[0]) / cos($_[0]) }
sub atan { atan2($_[0],1) };

my $lat_a = $lat;
my $lon_a = $lng;
my $aa = $pi / 180;
my $lat1 = $lat_a * $aa;
my $lat2 = $lat_b * $aa;
my $lon1 = $lon_a * $aa;
my $lon2 = $lon_b * $aa;

my $t1 = sin($lat1) * sin($lat2);
my $t2 = cos($lat1) * cos($lat2);
my $t3 = cos($lon1 - $lon2);
my $t4 = $t2 * $t3;
my $t5 = $t1 + $t4;
my $rad_dist = atan(-t5/sqrt(-$t5 * $t5 +1)) + 2 * atan(1);

my $dist = ($rad_dist * 3437.74677 * 1.1508) * 1.6093470878864446;



ce que je cherche c'est comment calculer la distance entre chaque ville pour me retrouver avec un tri a partir d'une ville de départ: exemple:
A la base j'ai:
azert;brazil;-14.235004;-51.92528
azerty;bordeaux;44.837789;-0.57918
toto;liboune;44.912998;-0.243985
nom;paris;48.856614;2.3522219
tata;marseille;43.296482;5.36978
kiki;nice;43.7101728;7.2619532

Si je part de nice,
ça me donnerait:
kiki;nice;43.7101728;7.2619532
tata;marseille;43.296482;5.36978
toto;liboune;44.912998;-0.243985
azerty;bordeaux;44.837789;-0.57918
nom;paris;48.856614;2.3522219
azert;brazil;-14.235004;-51.92528

en fait je pense qu'il faudrait calculer tous les km entre chaque ville a partir de nice, en calculant toutes les combinaisons, et en ne gardant que celle ou il y a le moins de distance.
0
Utilisateur anonyme
 
Je ne connais pas Perl, mais oui, si tu pars de Nice, tu calcules les distances vers tous les autres, tu stockes ça dans une collection (tableau, liste, etc..) et tu le trie.

--
0
mpmp93 Messages postés 6648 Date d'inscription   Statut Membre Dernière intervention   1 340
 
JE vous conseille de faire ce calcul dynamiquement, c'est à dire au moment où vous éditez une fiche ville, vous avez les distances vers toutes les autres villes.
0
nicdu40 Messages postés 25 Date d'inscription   Statut Membre Dernière intervention   1
 
#!/usr/local/bin/perl                                                                                                                                                                          
                                                                                                                                                                                               
use POSIX qw(strftime);                                                                                                                                                                        
use Math::Complex;                                                                                                                                                                             
#use strict;                                                                                                                                                                                   
#use warnings;                                                                                                                                                                                                                                                                 
use DBI;                                                                                                                                                                                                                                                                       
use LWP::Simple; # from CPAN                                                                                                                                                                                                                                                   
use JSON qw( decode_json ); # from CPAN                                                                                                                                                                                                                                        
#récupère  l'entrée standard dans la variable $in                                                                                                                                                                                                                              
read(STDIN, $in, $ENV{CONTENT_LENGTH});                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                               
# la chaine $in est coupée suivant le caractère & et crée la liste @champs                                                                                                                                                                                                     
@champs = split(/&/,$in);                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                               
# traitement de chaque élément $e de la liste @champs                                                                                                                                                                                                                          
foreach $e (@champs) {                                                                                                                                                                                                                                                         
  # dissocie chaque élément, de la forme nom=valeur en une paire de variable (nom,valeur)                                                                                                                                                                                      
  ($nom, $valeur) = split(/=/,$e);                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                               
  # transforme tous les caractères saisis en minuscules                                                                                                                                                                                                                        
  $valeur =~  tr/A-Z/a-z/;                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                               
  # crée à partir du tableau @champs une liste associative %champs                                                                                                                                                                                                             
  $champs{$nom}=$valeur;
}

  my $format = "json"; #can also to 'xml'
  my $geocodeapi = "[https://maps.googleapis.com/maps/api/geocode/]";

# génére l'en-tête du document HTML renvoyé
print("Content-Type: text/html\n\n");
# puis le document HTML
print <<"SORTIE";
<HEAD><TITLE> Réponse </TITLE></HEAD>
<BODY>
<H2 ALIGN=CENTER>RESULTAT</H2>
<CENTER><TABLE BORDER><TR> <TH>Nom du champ <TH>Valeur</TR>
SORTIE

my $adresse;
my $NOM;
my $lat;
my $lng;

# le traitement est ici réduit à afficher les valeurs transmises
while (($nom, $valeur) = each(%champs)) {
        if  ($nom =~ /adresse/){
        $valeur =~ s/\%2c\+/-/g;
        $valeur =~ s/\+/\ /g;
        $adresse = $valeur;
        my $url = $geocodeapi . $format . "?address=" . $adresse . "&sensor=false" ;
        my $json = get($url);
        my $d_json = decode_json( $json );
        $lat = $d_json->{results}->[0]->{geometry}->{location}->{lat};
        $lng = $d_json->{results}->[0]->{geometry}->{location}->{lng};
        }
        if  ($nom =~ /nom/){
        $NOM = $valeur;
        }
print "<TR><Td>$nom = </td><Td>$valeur</td></TR>";
}

###############
open (FH, ">>test-perl");
print  FH "$NOM;$adresse;$lat;$lng\n";
close(FH);
##############
open(FH, "test-perl")  or die "!";
# Copie du contenu du fichier dans un tableau
my @table=<FH>;
# Afficher la taille du tableau
print scalar(@table)."\n";
print "<BR\>";
close(FH);

my $pi = 3.14159265358979;
sub atan { atan2($_[0],1) };
my $aa = $pi / 180;
my $local_lat = 43.637844;
my $local_long = -1.420939;
my $lat_a = $local_lat;
my $lon_a =  $local_long;
my $lat1 = $lat_a * $aa;
my $lon1 = $lon_a * $aa;

foreach $line (@table) {
($nom, $adresse, $lat, $lng, $dist) = split(";", $line);
my $lat_b = $lat; 
my $lon_b =  $lng; 
my $lat2 = $lat_b * $aa;
my $lon2 = $lon_b * $aa;
my $t1 = sin($lat1) * sin($lat2);
my $t2 = cos($lat1) * cos($lat2);
my $t3 = cos($lon1 - $lon2);
my $t4 = $t2 * $t3;
my $t5 = $t1 + $t4;
my $rad_dist = atan(-$t5/sqrt(-$t5 * $t5 +1)) + 2 * atan(1);
my $dist = ($rad_dist * 3437.74677 * 1.1508) * 1.6093470878864446;
$line = $line . ";" . $dist;

}

  @out = sort {
       (split ';', $a )[4] <=> #cmp
     (split ';', $b )[4]
  } @table;
foreach $line (@out) {
($nom, $adresse, $lat, $lng, $dist) = split(";", $line);
print "<TR><Td>$nom</td><Td>$adresse</td><Td>$lat</td><Td>$lng</td><Td>$dist</td></TR>";
}


ce qui me donne:
nom ville lat long km
bobo orx 43.602883 -1.372563 5.49883038421565
nico seignosse 43.692694 -1.384908 6.74821123208138
rhune ascain 43.345172 -1.621327 36.3135240698413
bobo pau 43.2951 -0.370797 92.8625864850123
azert marseille 43.296482 5.36978 548.822503921505
bbb brazil -14.235004 -51.92528 8217.52868892235
nom mexico 23.634501 -102.552784 9051.01695660936
nom mexico 23.634501 -102.552784 9051.01695660936
nom mexico 23.634501 -102.552784 9051.01695660936
nom mexico 23.634501 -102.552784 9051.01695660936
bobo tokio 35.6894875 139.6917064 10350.9145027704

le départ se fait à partir d'une seulle ville : my $local_lat = 43.637844; my $local_long = -1.420939;

ça calcul les distances à partir de ce point, mais ce n'est pas ce que je voudrai
j'avance un peu , mais je n'est pas encore la bonne methode.....

EDIT: Ajout de la coloration syntaxique.
0
nicdu40 Messages postés 25 Date d'inscription   Statut Membre Dernière intervention   1
 
bon voila , pour ceux qui sont intéressé: ça calcul la ville la plus proche du point de départ, puis ensuite depuis l'autre ville , ainsi de suite,
c'est pour optimiser les tournées de RDV , .... ,
Bon j'ai du faire des erreurs, je n'ai jamais suivi de cours , soyez indulgent ;-)


##############
#adresse de départ
my $local_lat = 43.637844;
my $local_long = -1.420939;

my $lat_a = $local_lat;
my $lon_a =  $local_long;

my $pi = 3.14159265358979;
sub atan { atan2($_[0],1) };
my $aa = $pi / 180;

open(FH, "test-perl")  or die "!";
# Copie du contenu du fichier dans un tableau
my @tabl=<FH>;
my $nb_lignes = scalar(@tabl);
# Afficher la taille du tableau
print "NB lignes = $nb_lignes \n";
#print "<BR\>";
close(FH);
#my $lat1 = $lat_a * $aa;
#my $lon1 = $lon_a * $aa;
my $line;

#boucle 
while ($nb_lignes > 0) {

foreach $line (@tabl) {
        my ($nom, $adresse, $lat, $lng) = split("\ ", $line);
        $line = join(' ',$nom,$adresse,$lat,$lng);
        my $lat_b = $lat; 
 my $lat1 = $lat_a * $aa;
my $lon1 = $lon_a * $aa;

        my $lon_b =  $lng; 
        my $lat2 = $lat_b * $aa;
        my $lon2 = $lon_b * $aa;
        my $t1 = sin($lat1) * sin($lat2);
        my $t2 = cos($lat1) * cos($lat2);
        my $t3 = cos($lon1 - $lon2);
        my $t4 = $t2 * $t3;
        my $t5 = $t1 + $t4;
my $dista;
                if (($lat_a == $lat_b)&&($lon_a == $lon_b)) {
                $dista = 0 ;
         
                }else{

                my $rad_dist = atan(-$t5/sqrt(-$t5 * $t5 +1)) + 2 * atan(1);
                $dista = ($rad_dist * 3437.74677 * 1.1508) * 1.6093470878864446;
                }
        $line =~ s/\n//g;
        $line = $line . " " . $dista ;
        }

        @out = sort {
        (split ' ' , $a )[4] <=> 
        (split ' ' , $b )[4]
        } @tabl;

my $proche = shift(@out);
#print "plus proche= $proche\n";
my @col = split( ' ' , $proche);
$lat_a = $col[2];
$lon_a = $col[3];
$nb_lignes -=1;
@tabl =  @out ; 

#print "\n";
my ($nom, $adresse, $lat, $lng, $dista) = split("\ ", $proche);
print "<TR><Td>$nom</td><Td>$adresse</td><Td>$lat</td><Td>$lng</td><Td>$dista</td></TR>";
}
0

 
Salut nicdu40,

Plutôt que de calculer la distance à vol d'oiseau, tu pourrais utiliser une API pour calculer la distance par la route et le temps de trajet. Google a cela :

https://developers.google.com/maps/documentation/javascript/distancematrix
https://developers.google.com/maps/documentation/distance-matrix/start

qui te permet d'obtenir une matrice de distances et temps de parcours entre un ou plusieurs points de départ et un ou plusieurs points d'arrivée.

Par exemple :

#!/usr/bin/perl

use strict;
use warnings;

use LWP::Simple;
use JSON qw( decode_json );
use Data::Dumper;

my $origins         = "&origins=Paris+France|Bordeaux+France|Lyon+France|Marseille+France";
my $destinations    = "&destinations=Paris+France|Bordeaux+France|Lyon+France|Marseille+France";

my $content = get("https://maps.googleapis.com/maps/api/distancematrix/json?" . $origins . $destinations);
die "Couldn't get it!" unless defined $content;

my $data = decode_json($content);
my @rows = @{ $data->{'rows'} };

foreach my $r (@rows) {
    my @elements = @{ $r->{'elements'} };
    foreach my $d (@elements) {
        print $d->{'duration'}{'value'} . "\t\t";                                                                                                                                                                  
    }
    print "\n";
}


donne :

0		20925		15491		26226		
21151 0 18954 21478
15956 19102 0 11233
26751 21713 11269 0


Tu peux ensuite faire tes tris, en fonction de ta ville de départ.


Dal
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
nicdu40 Messages postés 25 Date d'inscription   Statut Membre Dernière intervention   1
 
salut, merci Dal,
faut que j'aille voir ça.
merci à tous les autres dailleur .
de mon coté j'ai réussi a faire ce que je voulais au départ, mais c'est vrais que c'est a vol d'oiseau, c'est bon pour les avions quoi....

en fait j'ai fais tout grace a la permutation "Fischer-Krause ordered permutation generator"
ça m'a ouvert les yeux...
maintenant je vais faire la même avec les conseils de dal.
bon du coup voila, calcul du meilleur itinéraire pour les objets volants:

le fichier test-perl doit être écrit ainsi:
nico hossegor 43.6646192 -1.3976871
lolo orx 43.602883 -1.372563
pipo seignosse 43.69269 -1.384
coco tarnos 43.5408 -1.461038
gaga dax 43.708608 -1.051945



##############
#adresse de départ
my $local_lat = 43.6305177;
my $local_long = -1.3927591;
my $addr = "magazin";
my $lat_a = $local_lat;
my $lon_a =  $local_long;

my $total = 0;
my $pi = 3.14159265358979;
my $pii = $pi / 180;

open(FH, "test-perl")  or die "!";
# Copie du contenu du fichier dans un tableau
my @tabl=<FH>;
my $nb_lignes = scalar(@tabl);
# Afficher la taille du tableau
print "NB lignes = $nb_lignes \n";
#print "<BR\>";
close(FH);

#calcul des distances
sub distanceA_B {
 my ($lat_A,$lat_B,$lon_A,$lon_B) = @_;
	my $lat_a = $lat_A;
	my $lat_b = $lat_B;
	my $lon_a =  $lon_A;
	my $lon_b =  $lon_B;
	my $lat1 = $lat_a * $pii;
	my $lon1 = $lon_a * $pii;  
        my $lat2 = $lat_b * $pii;
        my $lon2 = $lon_b * $pii;
        my $t1 = sin($lat1) * sin($lat2);
        my $t2 = cos($lat1) * cos($lat2);
        my $t3 = cos($lon1 - $lon2);
        my $t4 = $t2 * $t3;
        my $t5 = $t1 + $t4; 
	my $dista;
                if (($lat_a == $lat_b)&&($lon_a == $lon_b)) {
                $dista = 0 ;
                }else{
                my $rad_dist = atan(-$t5/sqrt(-$t5 * $t5 +1)) + 2 * atan(1);
                $dista = ($rad_dist * 3437.74677 * 1.1508) * 1.6093470878864446;
                }
return ($dista);
                
}
######################################################################################################"
foreach my $ligne (@tabl) {
  my ($nom, $adresse, $lat, $lng) = split("\ ", $ligne);
  $ligne = join('_',$nom,$adresse,$lat,$lng);
 }

###permutation :-) 
sub permute (&@) {
  my $code = shift;
  my @idx = 0..$#_;
  while ( $code->(@_[@idx]) ) {
    my $p = $#idx;
    --$p while $idx[$p-1] > $idx[$p];
    my $q = $p or return;
    push @idx, reverse splice @idx, $p;
    ++$q while $idx[$p-1] > $idx[$q];
    @idx[$p-1,$q]=@idx[$q,$p-1];
  }
}
my @a;
permute { push @a, "@_" } @tabl;


foreach my $aa (@a) {
### on remet les coordonnées de départ avant chaque tour de @a
  $lat_a = $local_lat;
  $lon_a =  $local_long;
  my @array = split(' ',$aa);
  
  foreach my $array (@array) {
    $array =~ s/\n//g;
    my ($nom, $adresse, $lat, $lng) = split("_", $array);
    if ($addr eq $adresse) {
      $dista = 0;
    }	else{
	($dista) = distanceA_B ($lat_a,$lat,$lon_a,$lng);  
	}
 #  $array = $array . " " . $dista ;
 #print $array . "\n";

 $total += $dista  ;
### a chaque tour de @array le point gps precedant devient le départ.
  $lat_a = $lat;
  $lon_a = $lng;  
   }
#print   "total distance= $total \n";
$aa = $aa . " " . $total ;
#print $aa . "\n";
  $total=0;
}

###numero de colone oû se trouve le total de chaque possibilité = nb de villes a calculer (+1)
my $col_tot = $nb_lignes ;

###calcul du meilleur total
  @out = sort {
        (split ' ' , $a )[$col_tot] <=> 
        (split ' ' , $b )[$col_tot]
        } @a;

#recupere la 1er ligne
my $proche = shift(@out);
print $proche . "\n";


@tableau_web = split(' ',$proche);

#recupere le nombre de km:
my $total_dist = pop(@tableau_web);

##inscription dans un tableau le meilleur parcour !
foreach my $ligne_web (@tableau_web) {
	my ($nom, $adresse, $lat, $lng) = split("_", $ligne_web);
	print "<TR><Td>$nom</td><Td>$adresse</td><Td>$lat</td><Td>$lng</td></TR>";
print "\n";
}
print "<TR><Td>distance-totale=</td><Td>$total_dist</td></TR>";
0