1#!/usr/bin/env perl
2use strictures 2;
3
4use GIS::Distance;
5use Module::Find qw( findallmod );
6use Getopt::Long;
7
8Getopt::Long::Configure(qw(
9    gnu_getopt no_ignore_case
10));
11
12GetOptions(
13    'pp!'           => \my $do_pp,
14    'xs!'           => \my $do_xs,
15    'geo'           => \my $do_geo,
16
17    'precision|p=i' => \my $precision,
18
19    'h|help'        => \my $help,
20) or die "Unable to process options!\n";
21
22if ($help) {
23    require Pod::Usage;
24    Pod::Usage::pod2usage( -verbose => 2 );
25    exit 0;
26}
27
28$do_pp = 1 if !defined $do_pp;
29$do_xs = 1 if !defined $do_xs;
30
31$precision ||= 12;
32
33my @coords;
34
35# Beirut to Dimashq.
36@coords = ( 33.863146, 35.52824, 33.516496, 36.287842 );
37
38# https://github.com/bluefeet/Geo-Distance/issues/15
39#@coords = ( 52.484977, 13.385900, 52.485033, 13.370897 );
40
41my %distances;
42
43{
44    my @formulas = (
45        grep { $_ !~ m{::Formula} }
46        grep { $_ ne 'GIS::Distance::Constants' }
47        grep { $_ ne 'GIS::Distance::Fast' }
48        findallmod('GIS::Distance')
49    );
50
51    @formulas = (
52        grep { $_ !~ m{::Fast::} }
53        @formulas
54    ) if !$do_xs;
55
56    @formulas = (
57        grep { $_ =~ m{::Fast::} }
58        @formulas
59    ) if !$do_pp;
60
61    foreach my $formula (@formulas) {
62        my $gis = GIS::Distance->new( $formula );
63        my $km = $gis->distance( @coords )->km();
64        $distances{ $formula } = $km;
65    }
66}
67
68if ($do_geo and $do_pp) {
69    require Geo::Distance;
70    Geo::Distance->import();
71    my @formulas = @Geo::Distance::FORMULAS;
72
73    foreach my $formula (@formulas) {
74        my $geo = Geo::Distance->new();
75        $geo->formula( $formula );
76        my $km = $geo->old_distance( 'kilometer', reverse @coords );
77        $distances{ "Geo::Distance-$formula" } = $km;
78    }
79}
80
81if ($do_geo and $do_xs) {
82    require Geo::Distance::XS;
83    Geo::Distance::XS->import();
84    my @formulas = @Geo::Distance::XS::FORMULAS;
85
86    foreach my $formula (@formulas) {
87        my $geo = Geo::Distance->new();
88        $geo->formula( $formula );
89        my $km = $geo->distance( 'kilometer', reverse @coords );
90        $distances{ "Geo::Distance::XS-$formula" } = $km;
91    }
92}
93
94my %formulas_by_distance;
95foreach my $formula (keys %distances) {
96    my $distance = sprintf("%.0${precision}f", $distances{$formula});
97    my $formulas = $formulas_by_distance{ $distance } ||= [];
98    push @$formulas, $formula;
99}
100
101foreach my $distance (sort keys %formulas_by_distance) {
102  print "$distance:\n";
103  print map { " - $_\n" } sort @{ $formulas_by_distance{$distance} };
104}
105
106__END__
107
108=head1 NAME
109
110author/distances - Display the distance generated by all the formulas.
111
112=head1 SYNOPSIS
113
114    # List distances for every GIS::Distance and GIS::Distance::Fast
115    # formula.
116    author/distances
117
118    # List distances for every GIS::Distance::Fast and
119    # Geo::Distance::XS formula.
120    author/distances --geo --no-pp
121
122    # Displays this handy documentation!
123    author/distances --help
124
125=head1 OPTIONS
126
127=head2 pp
128
129    --no-pp
130
131Disable the C<pp> option, meaning no pure-perl formulas will
132be included.
133
134=head2 xs
135
136    --no-xs
137
138Disable the C<xs> option, meaning no XS formulas will
139be included.
140
141=head2 geo
142
143    --geo
144
145L<Geo::Distance> and/or L<Geo::Distance::XS> formulas will be
146included.
147
148=head2 precision
149
150    --precision=14
151    -p 8
152
153When grouping formulas format the timing to this number of
154decimal places.
155
156The default is C<12>, which does a good job of grouping the
157formulas which really are producing the exact same result.
158
159=head2 help
160
161    --help
162    -h
163
164Displays this handy documentation!
165
166=head1 AUTHORS AND LICENSE
167
168See L<GIS::Distance/AUTHORS> and L<GIS::Distance/LICENSE>.
169
170=cut
171
172