File Coverage

blib/lib/Geo/Geotude.pm
Criterion Covered Total %
statement 35 35 100.0
branch 2 2 100.0
condition n/a
subroutine 7 7 100.0
pod 3 4 75.0
total 47 48 97.9


line stmt bran cond sub pod time code
1             # $Id: Geotude.pm,v 1.5 2007/08/09 02:10:54 asc Exp $
2              
3 3     3   4757 use strict;
  3         7  
  3         219  
4             package Geo::Geotude;
5              
6             $Geo::Geotude::VERSION = '1.0';
7              
8             =head1 NAME
9              
10             Geo::Geotude - OOP for performing geotude location conversions.
11              
12             =head1 SYNOPSIS
13              
14             my $lat = '3.106254';
15             my $lon = '101.630517';
16              
17             my $geo = Geo::Geotude->new('latitude' => $lat, 'longitude' => $lon);
18             print $geo->geotude();
19              
20             # prints '53281.86.93.30.75.41.67'
21              
22             =head1 DESCRIPTION
23              
24             Geowhat? A Geotude is : "permanent and hierarchical. [As] a trade-off: A Geotude
25             is less intuitive than address, but more intuitive than latitude/longitude. A
26             Geotude is more precise than address, but less precise than latitude/longitude."
27              
28             This package provides OOP methods for converting a decimal latitude and longitude
29             in to Geotude and vice versa.
30              
31             =cut
32              
33 3     3   2791 use POSIX qw (floor);
  3         25284  
  3         22  
34 3     3   7435 use Memoize;
  3         8716  
  3         1749  
35              
36             memoize("geotude2point", "point2geotude");
37              
38             =head1 PACKAGE METHODS
39              
40             =cut
41              
42             =head2 __PACKAGE__->new(%args)
43              
44             Valid arguments are :
45              
46             =over 4
47              
48             =item * B
49              
50             A Geotude string.
51              
52             Must be present if neither I or I are
53             defined.
54              
55             =item * B
56              
57             A latitude, in decimal format.
58              
59             Must be present if I is defined.
60              
61             =item * B
62              
63             A longitude, in decimal format.
64              
65             Must be present if I is defined.
66              
67             =back
68              
69             Returns a I object.
70              
71             =cut
72            
73             sub new {
74 2     2 1 2215 my $pkg = shift;
75 2         9 my %self = @_;
76 2         10 return bless \%self, $pkg;
77             }
78              
79             =head1 OBJECT METHODS
80              
81             =cut
82              
83             =head2 $obj->point()
84              
85             Returns a comma-separated string when called in a scalar context.
86              
87             When called in an array context, returns a list containing decimal
88             latitude and longitude.
89              
90             =cut
91              
92             sub point {
93 1     1 1 625 my $self = shift;
94 1         37 return &geotude2point($self->{'geotude'});
95             }
96              
97             =head2 $obj->geotude()
98              
99             Returns a geotude string when called in scalar context.
100              
101             When called in an array context, returns a list containing the
102             major and minor (or sub) geotudes.
103              
104             =cut
105              
106             sub geotude {
107 2     2 1 933 my $self = shift;
108 2         11 return &point2geotude($self->{'latitude'}, $self->{'longitude'});
109             }
110              
111             sub geotude2point {
112             my $gt = shift;
113              
114             my @parts = split(/\./, $gt);
115              
116             $gt = shift @parts;
117             $gt -= 10000;
118              
119             my $dlat = '';
120             my $dlon = '';
121              
122             foreach my $str (@parts) {
123             $dlat .= substr($str, 0, 1);
124             $dlon .= substr($str, 1, 1);
125             }
126              
127             my $lat = ($gt - $gt % 500) / 500;
128             $lat .= ".$dlat";
129              
130             my $lon = $gt % 500;
131             $lon .= ".$dlon";
132              
133             $lat = 90 - $lat;
134             $lon = $lon - 180;
135              
136             my $fmt = "%." . length($dlat) . "f";
137              
138             $lat = sprintf($fmt, $lat);
139             $lon = sprintf($fmt, $lon);
140              
141             return (wantarray) ? ($lat, $lon) : "$lat,$lon";
142             }
143              
144             sub point2geotude {
145 2     2 0 4 my $lat = shift;
146 2         3 my $lon = shift;
147            
148 2         7 $lat = 90 - $lat;
149 2         4 $lon = $lon + 180;
150              
151 2         21 my $flat = floor($lat);
152 2         5 my $flon = floor($lon);
153              
154             # kind of dirty, but easier
155             # than dealing with math-isms
156              
157 2         43 $lat =~ s/$flat\.//;
158 2         24 $lon =~ s/$flon\.//;
159            
160 2         6 my $gt = 500 * $flat + $flon + 10000;
161              
162 2         3 my $pts = length($lat);
163 2         4 my @sub = ();
164              
165 2         9 for (my $i=0; $i < $pts; $i++) {
166 12         16 my $slat = substr($lat, $i, 1);
167 12         14 my $slon = substr($lon, $i, 1);
168 12         27 push @sub, $slat.$slon;
169             }
170              
171 2         2 my $major = $gt;
172 2         6 my $minor = join(".", @sub);
173 2         3 my @res = ($major, $minor);
174              
175 2 100       14 return (wantarray) ? @res : join(".", @res);
176             }
177              
178             =head1 VERSION
179              
180             1.0
181              
182             =head1 DATE
183              
184             $Date: 2007/08/09 02:10:54 $
185              
186             =head1 AUTHOR
187              
188             Aaron Straup Cope Eascope@cpan.orgE
189              
190             =head1 SEE ALSO
191              
192             L
193              
194             =head1 BUGS
195              
196             Please report all bugs via http://rt.cpan.org/
197              
198             =head1 LICENSE
199              
200             Copyright (c) 2007 Aaron Straup Cope. All Rights Reserved.
201              
202             This is free software. You may redistribute it and/or
203             modify it under the same terms as Perl itself.
204              
205             =cut
206              
207             return 1;