- SEE ALSO
- COPYRIGHT AND LICENSE
GIS::Distance - Calculate geographic distances.
use GIS::Distance; # Use the GIS::Distance::Haversine formula by default. my $gis = GIS::Distance->new(); # Or choose a different formula. my $gis = GIS::Distance->new( 'Polar' ); # Returns a Class::Measure object. my $distance = $gis->distance( $lat1, $lon1, $lat2, $lon2 ); print $distance->meters();
This module calculates distances between geographic points on, at the moment, planet Earth. Various "FORMULAS" are available that provide different levels of accuracy versus speed.
GIS::Distance::Fast, a separate distribution, ships with C implmentations of some of the formulas shipped with GIS::Distance. If you're looking for speed then install it and the ::Fast formulas will be automatically used by this module.
my $distance = $gis->distance( $lat1, $lon1, $lat2, $lon2 ); my $point1 = Geo::Point->latlong( $lat1, $lon1 ); my $point2 = Geo::Point->latlong( $lat2, $lon2 ); my $distance = $gis->distance( $point1, $point2 );
Takes either two decimal latitude and longitude pairs, or two Geo::Point objects.
Returns a Class::Measure::Length object for the distance between the two degree lats/lons.
See "distance_metal" for a faster, but less feature rich, method.
This works just like "distance" except for:
Does not accept Geo::Point objects. Only decimal latitude and longitude pairs.
Does not return a Class::Measure object. Instead kilometers are always returned.
Does no argument checking.
Does not support formula arguments which are supported by at least the GIS::Distance::GeoEllipsoid formula.
Calling this gets you pretty close to the fastest bare metal speed you can get. The speed improvements of calling this is noticeable over hundreds of thousands of iterations only and you've got to decide if its worth the safety and features you are dropping. Read more in the "SPEED" section.
my $gis = GIS::Distance->new( $formula );
When you call
new() you may pass a partial or full formula class name as the first argument. The default is
If you pass a partial name, as in:
my $gis = GIS::Distance->new( 'Haversine' );
Then the following modules will be looked for in order:
GIS::Distance::Fast::Haversine GIS::Distance::Haversine Haversine
Install GIS::Distance::Fast to get access to the
Fast:: (XS) implementations of the formula classes.
You may globally disable the automatic use of the
Fast:: formulas by setting the
GIS_DISTANCE_PP environment variable. Although, its likely simpler to just provide a full class name to get the same effect:
my $gis = GIS::Distance->new( 'GIS::Distance::Haversine' );
Not that this module is slow, but if you're doing millions of distance calculations a second you may find that adjusting your code a bit may make it faster. Here are some options.
Install GIS::Distance::Fast to get the XS variants for most of the PP formulas.
Call the undocumented
_distance() function that each formula class has. For example you could bypass this module entirely and just do:
use GIS::Distance::Fast::Haversine; my $km = GIS::Distance::Fast::Haversine::_distance( @coords );
The above would be the ultimate speed demon (as shown in benchmarking) but throws away some flexibility and adds some foot-gun support.
Here's a benchmarks for these options:
2019-03-13T09:34:00Z GIS::Distance 0.15 GIS::Distance::Fast 0.12 GIS::Distance::Fast::Haversine 0.12 GIS::Distance::Haversine 0.15 Rate PP Haversine - GIS::Distance->distance 123213/s XS Haversine - GIS::Distance->distance 196232/s PP Haversine - GIS::Distance->distance_metal 356379/s PP Haversine - GIS::Distance::Haversine::_distance 385208/s XS Haversine - GIS::Distance->distance_metal 3205128/s XS Haversine - GIS::Distance::Fast::Haversine::_distance 8620690/s
You can run your own benchmarks using the included
author/bench script. The above results were produced with:
author/bench -f Haversine
The slowest result was about
125000/s, or about
8ms each call. This could be a substantial burden in some contexts, such as live HTTP responses to human users and running large batch jobs, to name just two.
As always with performance and benchmarking, YMMV.
When passing latitudinal and longitudinal coordinates to "distance" they must always be in decimal degree format. Here is some sample code for converting from other formats to decimal:
# DMS to Decimal my $decimal = $degrees + ($minutes/60) + ($seconds/3600); # Precision Six Integer to Decimal my $decimal = $integer * .000001;
If you want to convert from decimal radians to degrees you can use Math::Trig's rad2deg function.
These formulas come bundled with this distribution:
These formulas are available on CPAN:
Take a look at GIS::Distance::Formula for instructions on authoring new formula classes.
Geo::Distance - Is deprecated in favor of using this module.
Geo::Distance::Google - While in the Geo::Distance namespace, this isn't actually related to Geo::Distance at all. Might be useful though.
GIS::Distance::Lite - An old fork of this module, not recommended.
Please submit bugs and feature requests to the GIS-Distance GitHub issue tracker:
Aran Clary Deltac <email@example.com> Mohammad S Anwar <firstname.lastname@example.org>
Copyright (C) 2003 Aran Clary Deltac
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.