# NAME
GIS::Distance - Calculate geographic distances.
# SYNOPSIS
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' );
my $distance = $gis->distance( $lat1,$lon1 => $lat2,$lon2 );
print $distance->meters();
# DESCRIPTION
This module calculates distances between geographic points on, at the moment,
planet Earth. Various ["FORMULAS"](#formulas) are available that provide different levels
of accuracy versus speed.
[GIS::Distance::Fast](https://metacpan.org/pod/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.
# METHODS
## distance
my $distance = $gis->distance( $lat1,$lon1 => $lat2,$lon2 );
Returns a [Class::Measure::Length](https://metacpan.org/pod/Class::Measure::Length) object for the distance between the
two degree lats/lons.
See ["distance\_km"](#distance_km) and ["distance\_metal"](#distance_metal) to return raw kilometers instead.
## distance\_km
This works just like ["distance"](#distance), but returns a raw kilometer measurement,
and is faster when benchmarked over millions of iterations.
## distance\_metal
This works just like ["distance\_km"](#distance_km), but does no argument checking and ignores
any formula ["args"](#args). Calling this gets you pretty close to the fastest bare
metal speed you can get. Again, like with ["distance\_km"](#distance_km), the speed
improvements of calling this is noticeable over millions of iterations only
and you've got to decide if its worth the safety and features you are dropping.
# ATTRIBUTES
## formula
Returns the formula name which was passed as the first argument to `new()`.
The formula can be specified as a partial or full module name for that
formula. For example, if the formula is set to `Haversine` 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
Note that a `Fast::` version of the class will be looked for first. By default
the `Fast::` versions of the formulas, written in C, are not available and the
pure perl ones will be used instead. If you would like the `Fast::` formulas
then install [GIS::Distance::Fast](https://metacpan.org/pod/GIS::Distance::Fast) and they will be automatically used.
You may disable the automatic use of the `Fast::` formulas by setting the
`GIS_DISTANCE_PP` environment variable.
## args
Returns the formula arguments, an array ref, containing the rest of the
arguments passed to `new()` (anything passed after the ["formula"](#formula)).
Most formulas do not take arguments. If they do it will be described in
their respective documentation.
## module
Returns the fully qualified module name that ["formula"](#formula) resolved to.
# SPEED
Not that this module is slow, but if you're doing millions of distance
calculations you may find that adjusting your code a bit may make it
faster. Here are some options.
Install [GIS::Distance::Fast](https://metacpan.org/pod/GIS::Distance::Fast).
Use ["distance\_km"](#distance_km) or ["distance\_metal"](#distance_metal) instead of ["distance"](#distance).
Call the undocumented `distance()` function that each formula module
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.
# COORDINATES
When passing latitudinal and longitudinal coordinates to ["distance"](#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](https://metacpan.org/pod/Math::Trig)'s
rad2deg function.
# FORMULAS
These formulas come with this distribution:
[GIS::Distance::Cosine](https://metacpan.org/pod/GIS::Distance::Cosine)
[GIS::Distance::GreatCircle](https://metacpan.org/pod/GIS::Distance::GreatCircle)
[GIS::Distance::Haversine](https://metacpan.org/pod/GIS::Distance::Haversine)
[GIS::Distance::MathTrig](https://metacpan.org/pod/GIS::Distance::MathTrig)
[GIS::Distance::Null](https://metacpan.org/pod/GIS::Distance::Null)
[GIS::Distance::Polar](https://metacpan.org/pod/GIS::Distance::Polar)
[GIS::Distance::Vincenty](https://metacpan.org/pod/GIS::Distance::Vincenty)
These formulas are available on CPAN:
[GIS::Distance::Fast::Cosine](https://metacpan.org/pod/GIS::Distance::Fast::Cosine)
[GIS::Distance::Fast::GreatCircle](https://metacpan.org/pod/GIS::Distance::Fast::GreatCircle)
[GIS::Distance::Fast::Haversine](https://metacpan.org/pod/GIS::Distance::Fast::Haversine)
[GIS::Distance::Fast::Polar](https://metacpan.org/pod/GIS::Distance::Fast::Polar)
[GIS::Distance::Fast::Vincenty](https://metacpan.org/pod/GIS::Distance::Fast::Vincenty)
[GIS::Distance::GeoEllipsoid](https://metacpan.org/pod/GIS::Distance::GeoEllipsoid)
# SEE ALSO
[GIS::Distance::Lite](https://metacpan.org/pod/GIS::Distance::Lite) was long ago forked from GIS::Distance and modified
to have less dependencies. Since then GIS::Distance itself has become
tremendously lighter dep-wise, and is still maintained, I suggest you not
use GIS::Distance::Lite.
[Geo::Distance](https://metacpan.org/pod/Geo::Distance) has long been deprecated in favor of using this module.
[Geo::Distance::XS](https://metacpan.org/pod/Geo::Distance::XS) used to be used by [Geo::Distance](https://metacpan.org/pod/Geo::Distance) but no longer does.
[Geo::Inverse](https://metacpan.org/pod/Geo::Inverse) seems to do some distance calculation using [Geo::Ellipsoid](https://metacpan.org/pod/Geo::Ellipsoid)
but if you look at the source code it clearly states that the entire meat of
it is copied from Geo::Ellipsoid... so I'm not sure why it exists... just use
Geo::Ellipsoid or [GIS::Distance::GeoEllipsoid](https://metacpan.org/pod/GIS::Distance::GeoEllipsoid) which wraps Geo::Ellipsoid
into the GIS::Distance interface.
[Geo::Distance::Google](https://metacpan.org/pod/Geo::Distance::Google) looks pretty neat.
# TODO
- Create a GIS::Coord class that represents a geographic coordinate. Then modify
this module to accept input as either lat/lon pairs, or as GIS::Coord objects.
This would make coordinate conversion as described in ["COORDINATES"](#coordinates) automatic.
Maybe use [Geo::Point](https://metacpan.org/pod/Geo::Point).
- Create some sort of equivalent to [Geo::Distance](https://metacpan.org/pod/Geo::Distance)'s closest() method.
- Write a formula module called GIS::Distance::Geoid. Some very useful info is
at [http://en.wikipedia.org/wiki/Geoid](http://en.wikipedia.org/wiki/Geoid).
- Make [GIS::Distance::Google](https://metacpan.org/pod/GIS::Distance::Google) (or some such name) and wrap it around
[Geo::Distance::Google](https://metacpan.org/pod/Geo::Distance::Google) (most likely).
- Figure out why [GIS::Distance::Polar](https://metacpan.org/pod/GIS::Distance::Polar) has issues.
# SUPPORT
Please submit bugs and feature requests to the GIS-Distance GitHub issue tracker:
[https://github.com/bluefeet/GIS-Distance/issues](https://github.com/bluefeet/GIS-Distance/issues)
# AUTHORS
Aran Clary Deltac
# LICENSE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.