NAME
Geo::Distance - Calc Distances and Closest Locations (v0.03)
SYNOPSIS
use Geo::Distance;
my $geo = new Get::Distance;
my $dist1 = $geo->distance( unit=>'mile', lon1=>$lon1, lat1=>$lat1, lon2=>$lon2, lat2=>$lat2 );
my $dist2 = $geo->distance_dirty('light_second',$lon1,$lat1,$lon2,$lat2);
my $dist3 = $geo->distance_dirty('centimeter',$ary_ref1,$ary_ref2);
my $locations = $geo->find_closest(lon => $lon,lat => $lat,distance => $dist,unit => $unt,dbh => $dbh,table => $tbl,field => $fld);
or
use Geo::Distance qw{ :all };
my $dist1 = geo_distance( unit=>'meter', lon1=>$lon1, lat1=>$lat1, lon2=>$lon2, lat2=>$lat2 );
my $dist2 = geo_distance_dirty('inch',$lon1,$lat1,$lon2,$lat2);
my $dist3 = geo_distance_dirty('foot',$ary_ref1,$ary_ref2);
my $locations = geo_find_closest(lon => $lon,lat => $lat,distance => $dist,unit => $unt,dbh => $dbh,table => $tbl,field => $fld);
DESCRIPTION
This perl library provides the ability to calculate the distance between two geographic points and to find the closest locations to a single point using a database connection. There is both a function oriented interface, and an object oriented interface. Both have the same capabilities. Your choice of interface depends on your programming style and needs. Geo::Distance only recognizes standard decimal based longitude and latitude measurements. If you have other coordinate systems that you would like to use, then take a peak at the Geo::Coordinates::* modules.
The latest version of the Geo::Distance modules can be found here:
http://www.bluefeet.net/perl/modules/geo-distance/
Soon to be available will be some free to download and use data sets for use with find_closest().
OO VERSUS POLLUTION
This module provides two styles of programming, the first of which being an elegant object oriented interface and the second being a namespace polluting function interface. Personally, I like to pollute my namespace, but an object oriented interface does come in handy at times.
Both the object oriented interface and the function interface have the same functions, just with slightly different names.
At the moment there are several ways to import functions. The most common being the :all export tag. This will export the geo_distance(), geo_distance_dirty(), and geo_find_closest() functions. You may also export the functions individually, as follows:
# Export just geo_distance().
use Geo::Distance qw( geo_distance );
# Export just geo_distance_dirty().
use Geo::Distance qw( geo_distance_dirty );
# Export all functions.
use Geo::Distance qw( geo_distance geo_distance_dirty geo_find_closest );
# or
use Geo::Distance qw( :all );
METHODS
Currently there are three methods supplied by this module, each with function oriented and object oriented interface. Whatever the interface, these methods take the same arguments and return the same results.
DISTANCE
Takes a name value pairs in a hash style. All arguments will be validated. Returns the distance between the two locations in the unit type passed to it.
# unit => mile|light_second|kilometer|meter|centimeter|yard|foot|inches
# lon1,lat1 => Latitude and longitude in decimal format for the first location.
# lon2,lat2 => Ditto, but for the second location.
my $dist1 = geo_distance( unit=>'meter', lon1=>$lon1, lat1=>$lat1, lon2=>$lon2, lat2=>$lat2 );
my $dist2 = $geo->distance( unit=>'mile', lon1=>$lon1, lat1=>$lat1, lon2=>$lon2, lat2=>$lat2 );
DISTANCE_DIRTY
This method is used internally by distance() to do the actual distance calculation. The benefit of using distance_dirty() is that it is faster than its counterpart because it does not check the input and does not accept a hash style argument list.
This method takes arguments in two forms, as five arguments or as three. The five arguments are unit, lon1, lat1, lon2, and lat2. See the distance method for a description of these arguments. The three arguments are unit, array_ref1, and array_ref2. The array_refs are array references each with two entries, the first being lon, and the second being lat.
my $dist1 = $geo->distance_dirty('light_second',$lon1,$lat1,$lon2,$lat2);
my $dist2 = geo_distance_dirty('inch',$lon1,$lat1,$lon2,$lat2);
my $dist3 = $geo->distance_dirty('centimeter',$ary_ref1,$ary_ref2);
my $dist4 = geo_distance_dirty('foot',$ary_ref1,$ary_ref2);
FIND_CLOSEST
When passed a DBI database connection this method will search it for the closest locations in the selected table and will return an array ref filled with the values of the field that you passed in.
This method uses some very simplistic calculations to SQL select out of the $dbh. This means that the SQL should work fine on almost any database (only tested on MySQL!) and this also means that it is very fast. Once this sub set of locations has been retrieved then more precise calculations are made to narrow down the result set. Remember, though, that the farther out your distance is, and the more locations in the table, the slower your searches will be.
The table that you want to search in must have lon and lat fields, both being of the type float.
# Find all counties within 50 miles of Wilbarger, TX, USA.
my $dbh = DBI->connect('DBI:mysql:database=geography;host=localhost', '', '', {AutoCommit=>1,RaiseError=>1});
my($lon,$lat) = $dbh->selectrow_array('SELECT lon,lat FROM counties WHERE fips=48487');
my $counties = geo_find_closest(
lon => $lon,
lat => $lat,
distance => 200,
unit => 'mile',
dbh => $dbh,
table => 'counties',
field => 'fips'
);
For reference, this internally creates an SQL statement similar to:
SELECT fips,lon,lat FROM counties WHERE ...
BUGS
None known right now, but by the time you read this, who knows? Check http://www.bluefeet.net/perl/modules/geo-distance/ for the latest bugs and enhancements.
NOTES
Geo::Distance is currently in its alpha stage. The interface may, and probably will change, features will be added and removed without notice, and good things will hopefully happen before the bad. So, until this module reaches beta stage, don't be too peeved if something doesn't work when you upgrade.
This module relies on Math::Trig (great_circle_distance) for most of its computations. Math::Trig is a core Perl module.
AUTHOR
Copyright (C) 2003 Aran Clary Deltac (CPAN: BLUEFEET)
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Address bug reports and comments to: <geo_distance@bluefeet.net>. When sending bug reports, please provide the version of Geo::Distance, the version of Perl, and the name and version of the operating system you are using. Patches are welcome if you are brave!
SEE ALSO
Math::Trig - Inverse and hyperbolic trigonemetric Functions.