Here is a module that I wrote for that purpose. It will have to be modified for your needs, but should give you a good starting point for further development. Someday I will get around to making it an independent module.
HTH
package Zips;
use strict;
use Time::HiRes qw(gettimeofday);
sub get_coords {
my ($s) = shift;
my $dbh = $s->dbh;
my ($zip) = @_;
my $sth = $dbh->prepare(qq! SELECT lat,lng FROM zipcodes WHERE zip
+='$zip' !);
$sth->execute();
my ($lat,$lng) = $sth->fetchrow();
$sth->finish();
return ($lat,$lng);
}
sub radius_select {
my ($s) = shift;
my $dbh = $s->dbh;
my ($zip,$m) = @_;
my ($lat, $lng) = $s->get_coords($zip);
if (($lat)&&($lng)) {
print "<div align=center>Lat: $lat Long: $lng</div>\n";
my $d = $m / 3958.75;
my $div = 57.2958;
my $sth = $dbh->prepare(qq!
SELECT zip,cname,state, ( 3958.75 *
+ ACOS( COS($lat/$div
) * COS(lat/$div)
+ SIN($lat/$div) * SIN(lat/$div)
* COS($lng/$div - lng/$div) ) ) as
+dist FROM zipcodes
WHERE (ACOS( COS($lat/$div) * COS(l
+at/$div)
+ SIN($lat/$div) * SIN(lat/$div)
* COS($lng/$div - lng/$div) )) < $d
ORDER BY dist
!) || die "Can't select from zipcodes:
+ ", $dbh->errstr;
#$s->write_log($sth->{Statement});
my $b = gettimeofday;
$sth->execute() || die "Can't execute select on zipcodes: ", $
+sth->errstr;
$s->e->{'qtime'} = gettimeofday-$b;
my $r_all = $sth->fetchall_arrayref();
$sth->finish();
return $r_all;
} else {
print "Invalid Zip Code.\n";
}
}
sub get_limit_byzip {
my ($s) = shift;
my $dbh = $s->dbh;
my ($zip,$m) = @_;
my $d = 200 / 3958.75;
my ($lat, $lng) = $s->get_coords($zip);
if (($lat)&&($lng)) {
print "<div align=center>Lat: $lat Long: $lng</div>\n";
my $d = $m / 3958.75;
my $div = 57.2958;
my $sth = $dbh->prepare(qq!
SELECT zip,cname,state, ( 3958.75 *
+ ACOS( COS($lat/$div
) * COS(lat/$div)
+ SIN($lat/$div) * SIN(lat/$div)
* COS($lng/$div - lng/$div) ) ) as
+dist FROM zipcodes
WHERE (ACOS( COS($lat/$div) * COS(l
+at/$div)
+ SIN($lat/$div) * SIN(lat/$div)
* COS($lng/$div - lng/$div) )) < $d
Group by dist limit $m
!) || die "Can't select from zipcodes:
+ ", $dbh->errstr;
#$s->write_log($sth->{Statement});
my $b = gettimeofday;
$sth->execute() || die "Can't execute select on zipcodes: ", $
+sth->errstr;
$s->e->{'qtime'} = gettimeofday-$b;
my $r_all = $sth->fetchall_arrayref();
$sth->finish();
return $r_all;
} else {
print "Invalid Zip Code.\n";
}
}
sub get_dist_byzip {
my ($s) = shift;
my ($zip, $zip2) = @_;
my ($lat, $lng) = $s->get_coords($zip);
my ($lat2,$lng2) = $s->get_coords($zip2);
my $div = 57.2958;
my $dist = (3958.75 * acos( cos($lat/$div) * cos($lat2/$div)
+ sin($lat/$div) * sin($lat2/$div)
* cos($lng/$div - $lng2/$div) ) );
return $dist;
}
sub get_zips_bycity {
my ($s) = shift;
my ($city,$state,$dist) = @_;
my $sth = $s->dbh->prepare(qq! SELECT zip FROM zipcodes WHERE cnam
+e='$city' and state=
'$state' !);
$sth->execute();
my $zip = $sth->fetchrow();
$sth->finish();
return $s->radius_select($zip,$dist);
}
sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ); }
1;
__END__
=pod
=head1 NAME
Zips.pm
=head1 METHODS AVAILABLE
$s->get_zips($zip, $dist)
$s->get_coords($zip) => ($lat,$lng);
$s->radius_select($zip,$m) => $r_all;
$s->dist_select_byzip($zip, $zip2) => $dist;
$s->acos()
=head1 AUTHOR
Stephen T. Walker <swalker@ssdw.com>
August 2000
=cut
|