Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Finding the Distance between longitude and latitude pairs

by cacharbe (Curate)
on Mar 07, 2002 at 16:37 UTC ( [id://150054]=sourcecode: print w/replies, xml ) Need Help??
Category: Miscellaneous
Author/Contact Info Chuck Charbeneau (cacharbe)
ccharbeneau@lear.com
Description: A while back my younger sister asked me to help her with homework from her college trig course. She had to solve a Great Circle Distance problem. After showing her the steps, it got me to thinking, and then reading, and then finally coding. What I found was quite interesting, and from that research spawned an application to find the distances between to corporate locations from their zip codes that I implemented on our intranet.

There are actually a couple of different methods for determining the distance between 2 long/lat pairs and you need to be aware of the accuracy of each. The Great Circle method is the least accurate IIRC, but is the most accessible, as it is a part of Math::Trig. I wrote some code to do this using the various methods. As I mentioned, it finds the distances between two zip codes for which the long/lat pairs are known, but I've removed the database interface for brevity and just given the pertinent code. You should also read: this, this and (my favorite) this article.

I was pretty explicit in my code so that my non-programming sister could understand it when I showed it too her to explain the different algorithms, but I think it gets the point across.

C-.

use strict;
use Math::Trig qw(deg2rad pi great_circle_distance asin acos);

############################
## Distances are in Miles ##
############################
 
                      
my ($lat1, $long1);
my ($lat2, $long2);

print "Haversine   : ". &Haversine($lat1, $long1, $lat2, $long2) ."\n"
+;
print "Law Cosines : ". &LawCosines($lat1, $long1, $lat2, $long2)."\n"
+;
print "Flat-Earth  : ". &FlatEarth($lat1, $long1, $lat2, $long2) ."\n"
+;
print "Great Circle: ". &GreatCircle($lat1, $long1, $lat2, $long2)."\n
+";
                   

sub LawCosines {
my ($lat1, $long1, $lat2, $long2) = @_;
my $r=3956;

  my $dist = acos(sin(deg2rad($lat1))*
                sin(deg2rad($lat2))+
                cos(deg2rad($lat1))*
                cos(deg2rad($lat2))*
                cos(deg2rad($long2)- deg2rad($long1))) 
                * $r;
  return $dist;

}

sub FlatEarth {
    my ($lat1, $long1, $lat2, $long2) = @_;
    my $r=3956;

    my $a = (pi/2)- deg2rad($lat1);               
    my $b = (pi/2)- deg2rad($lat2);
    my $c = sqrt($a**2 + $b**2 - 2 * $a *$b
            *cos(deg2rad($long2)-deg2rad($long1)));
    my $dist = $c * $r;

return $dist;

}

sub Haversine {
  my ($lat1, $long1, $lat2, $long2) = @_;
  my $r=3956;

               
  $dlong = deg2rad($long1) - deg2rad($long2);
  $dlat  = deg2rad($lat1) - deg2rad($lat2);

  $a = sin($dlat/2)**2 +cos(deg2rad($lat1)) 
                    * cos(deg2rad($lat2))
                    * sin($dlong/2)**2;
  $c = 2 * (asin(sqrt($a)));
  $dist = $r * $c;               


return $dist;

}

sub GreatCircle {
my ($lat1, $long1, $lat2, $long2) = @_;
my $r=3956;
    my @zip1 = (deg2rad($long1), deg2rad(90-$lat1));
    my @zip2 = (deg2rad($long2), deg2rad(90-$lat2));
    my $dist = great_circle_distance(@zip1, @zip2,$r);
                     

return $dist;

}
Replies are listed 'Best First'.
•Re: Finding the Distance between longitude and latitude pairs
by merlyn (Sage) on Mar 07, 2002 at 19:24 UTC
      Also - WWW::MapBlast by Lee Goddard. He's going to be using some of my code shown above in his next release.

      C-.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://150054]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-20 01:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found