line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Acme::Geo::Whitwell::Name; |
2
|
|
|
|
|
|
|
|
3
|
6
|
|
|
6
|
|
157831
|
use strict; |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
221
|
|
4
|
6
|
|
|
6
|
|
33
|
use warnings; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
173
|
|
5
|
6
|
|
|
6
|
|
32
|
use Carp qw(croak); |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
444
|
|
6
|
|
|
|
|
|
|
|
7
|
6
|
|
|
6
|
|
33
|
use Exporter; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
431
|
|
8
|
|
|
|
|
|
|
@Acme::Geo::Whitwell::Name::ISA = qw(Exporter); |
9
|
|
|
|
|
|
|
@Acme::Geo::Whitwell::Name::EXPORT_OK = qw(to_whitwell from_whitwell); |
10
|
|
|
|
|
|
|
|
11
|
6
|
|
|
6
|
|
90
|
use Scalar::Util qw(looks_like_number); |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
8834
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Acme::Geo::Whitwell::Name - Steadman Whitwell's "rational geographic nomenclature" |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 VERSION |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Version 0.04 |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=cut |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our $VERSION = '0.04'; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 SYNOPSIS |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
use Acme::Geo::Whitwell::Name qw(to_whitwell from_whitwell); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# Convert Sunnyvale, CA's lat and lon to a Whitwell name pair. |
30
|
|
|
|
|
|
|
my @names = to_whitwell("37.37N", "122.03"); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# Same conversion, using signed latitude and longitude instead. |
33
|
|
|
|
|
|
|
my @names = to_whitwell(37.37, -122.03); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Convert a Whitwell name to a latitude and longitude. |
36
|
|
|
|
|
|
|
# (Washington DC's "rational" name to N/S lat and E/W long.) |
37
|
|
|
|
|
|
|
my($lat_string, $lon_string) = from_whitwell("Feiro Nyvout"); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# If you want signed values, add signed => some true value. |
40
|
|
|
|
|
|
|
my($lat, $long) = from_whitwell("Feiro Nyvout", signed=>1); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 DESCRIPTION |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
This module implements Steadman Whitwell's "rational system of geographic |
45
|
|
|
|
|
|
|
nomenclature", in which place names are generated by converting the latitude |
46
|
|
|
|
|
|
|
and longitude of the location into a two-part name by means of a |
47
|
|
|
|
|
|
|
transliteration scheme. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
Whitwell devised this scheme in an attempt to provide an alternative to |
50
|
|
|
|
|
|
|
the proliferation of similarly-named towns in the early US. However, people |
51
|
|
|
|
|
|
|
seemed to prefer creating many Springfields and Washingtons in preference to |
52
|
|
|
|
|
|
|
using Whitwell's uniquely quirky names. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head2 THE SCHEME |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Two tables of number-to-letter(s) are used to translate latitudes and |
57
|
|
|
|
|
|
|
longitudes of two-decimal precision, digit-by-digit, into |
58
|
|
|
|
|
|
|
vaguely-pronounceable two-part names. |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
1 2 3 4 5 6 7 8 9 0 |
61
|
|
|
|
|
|
|
latitude a e i o u y ee ei ie ou vowels |
62
|
|
|
|
|
|
|
longitude b d f k l m n p r t consonants |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Transliteration is done by looking up the apropriate digit in the tables above, |
65
|
|
|
|
|
|
|
switching rows until all the digits are consumed. If the coordinate is negative, |
66
|
|
|
|
|
|
|
a special 'sign consonant' is inserted into the (partial) name after the first |
67
|
|
|
|
|
|
|
vowel is added, and the transliteration continues by choosing again from the |
68
|
|
|
|
|
|
|
vowel table, then continuing to alternate again. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
This is very orderly, but confusing to generate by hand (putting aside the |
71
|
|
|
|
|
|
|
fact that no one in their right mind really wants to live in "Isilu Buban" |
72
|
|
|
|
|
|
|
instead of Sydney, AU, or "Feiro Nyvout" instead of Washington, DC). |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
The generated names are guaranteed to have alternating consonants and vowels, |
75
|
|
|
|
|
|
|
and should be pronounceable (though most likely bizarre). I have not been able |
76
|
|
|
|
|
|
|
to locate the original documentation of the scheme, so I am unable to determine |
77
|
|
|
|
|
|
|
why some example names are built in "reverse": with the first letter for the |
78
|
|
|
|
|
|
|
latitude selected from the longitude table, and vice versa for the longitude. I |
79
|
|
|
|
|
|
|
can only guess that the alternate construction was deemed more pronounceable or |
80
|
|
|
|
|
|
|
"interesting". Since this is the case, I generate both alternatives so you can |
81
|
|
|
|
|
|
|
choose the one that seems "better". In the cases of places like McMurdo Base |
82
|
|
|
|
|
|
|
("Eeseepu Bymeem" or "Neeveil Amyny"), I'm not sure there I a "better". |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
However, solely for the purposes of amusement, it can be interesting to find |
85
|
|
|
|
|
|
|
out what a given location would have been called in the alternate universe |
86
|
|
|
|
|
|
|
where Whitwell's scheme caught on. |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
It would be lovely to use this module to change all the place names on |
89
|
|
|
|
|
|
|
online maps, wouldn't it? |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 SOURCES |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=over |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=item * I, William E. |
96
|
|
|
|
|
|
|
Wilson, Indiana University Press, 1984, p. 154 |
97
|
|
|
|
|
|
|
=item * Search books.google.com for '"new harmony gazette" whitwell' |
98
|
|
|
|
|
|
|
=item * http://www.kirchersociety.org/blog/2007/05/15/whitwells-system-for-a-rational-geographical-nomenclature/ |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=back |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=cut |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# These tables define the letters that the numbers will be transliterated into. |
105
|
|
|
|
|
|
|
# 0 1 2 3 4 5 6 7 8 9 |
106
|
|
|
|
|
|
|
my @vowels = qw(ou a e i o u y ee ei ie); |
107
|
|
|
|
|
|
|
my @consonants = qw(t b d f k l m n p r); |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# Allows us to detect when to insert the "sign consonant" for negative |
110
|
|
|
|
|
|
|
# lats and lons. |
111
|
|
|
|
|
|
|
my %vowel; |
112
|
|
|
|
|
|
|
@vowel{@vowels} = (); |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head1 EXPORT |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 FUNCTIONS |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=head2 to_whitwell($lat, $lon) |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Generates a properly-capitalized Whitwell name from a latitude-longitude pair. |
121
|
|
|
|
|
|
|
Latitude and longitude are truncated to the two digits after the decimal point, |
122
|
|
|
|
|
|
|
in keeping with Whitwell's original scheme. Zeroes are added after the decimal |
123
|
|
|
|
|
|
|
point as necessary. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
North latitudes are positve, and south latitudes are negative. East longitudes |
126
|
|
|
|
|
|
|
are positive, west longitudes are negative. Trailing E/W and N/S are converted |
127
|
|
|
|
|
|
|
into the appropriate sign. If you supply both for some reason, trailing |
128
|
|
|
|
|
|
|
sign indicators override signs. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Returns both alternatives for the name (see L). |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=cut |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub to_whitwell { |
135
|
6
|
|
|
6
|
1
|
13287
|
my($lat, $lon) = @_; |
136
|
6
|
|
|
|
|
12
|
return ( _vowel_build($lat) . ' ' . _consonant_build($lon), |
137
|
|
|
|
|
|
|
_consonant_build($lat) . ' ' . _vowel_build($lon) |
138
|
|
|
|
|
|
|
); |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
23
|
|
|
23
|
|
11607
|
sub _vowel_build { _gen(shift, [\@vowels, \@consonants], 's') } |
142
|
18
|
|
|
18
|
|
65
|
sub _consonant_build { _gen(shift, [\@consonants, \@vowels], 'v') } |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub _gen { |
145
|
|
|
|
|
|
|
# The coordinate, the letter lists, and the appropriate sign consonant. |
146
|
41
|
|
|
41
|
|
73
|
my($coord, $lists, $neg) = @_; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Turn the floating-point number into a list of digits. |
149
|
|
|
|
|
|
|
# Note that _two_decimal does NOT CARE about sign or sign indicators. |
150
|
41
|
|
|
|
|
79
|
$coord = uc(my $orig_coord = $coord); |
151
|
41
|
|
|
|
|
87
|
my @coord = grep {/(\d)/} (split //, _two_decimal($coord)); |
|
206
|
|
|
|
|
507
|
|
152
|
|
|
|
|
|
|
|
153
|
41
|
|
|
|
|
75
|
my $word = ''; |
154
|
41
|
|
|
|
|
79
|
my $list = 0; |
155
|
41
|
|
|
|
|
47
|
my $signed = 0; |
156
|
|
|
|
|
|
|
|
157
|
41
|
|
|
|
|
133
|
my ($is_negative) = ($coord =~ s/[SW]//g); |
158
|
41
|
|
|
|
|
102
|
my ($is_positive) = ($coord =~ s/[NE]//g); |
159
|
|
|
|
|
|
|
|
160
|
41
|
100
|
|
|
|
166
|
croak |
161
|
|
|
|
|
|
|
"Coordinate '$orig_coord' does not look like a proper coordinate" |
162
|
|
|
|
|
|
|
if !looks_like_number($coord); |
163
|
|
|
|
|
|
|
|
164
|
40
|
100
|
|
|
|
94
|
$is_negative = ($coord < 0) unless $is_negative; |
165
|
|
|
|
|
|
|
|
166
|
40
|
100
|
100
|
|
|
150
|
my $conflicting = ($is_negative and $is_positive) ? 'conflicting ' : ''; |
167
|
40
|
100
|
100
|
|
|
271
|
croak "Multiple ${conflicting}sign indicators detected in '$orig_coord'" |
|
|
|
100
|
|
|
|
|
168
|
|
|
|
|
|
|
if $conflicting or $is_negative > 1 or $is_positive > 1; |
169
|
|
|
|
|
|
|
|
170
|
36
|
|
|
|
|
61
|
foreach my $digit (@coord) { |
171
|
|
|
|
|
|
|
# Convert the next digit into a letter from the proper table. |
172
|
146
|
|
|
|
|
252
|
my $letter = $lists->[$list]->[$digit]; |
173
|
|
|
|
|
|
|
### "$letter -> $digit" |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# Decide whether to insert a sign consonant. |
176
|
146
|
100
|
100
|
|
|
556
|
if (exists $vowel{$letter} and $is_negative and not $signed) { |
|
|
|
100
|
|
|
|
|
177
|
|
|
|
|
|
|
# If negative, we have a vowel, and we haven't inserted the sign |
178
|
|
|
|
|
|
|
# consonant yet, insert it. |
179
|
16
|
|
|
|
|
18
|
$letter .= $neg; |
180
|
|
|
|
|
|
|
# Now signed. |
181
|
16
|
|
|
|
|
27
|
$signed = 1; |
182
|
16
|
|
|
|
|
19
|
$list = !$list; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
# Add new letter(s) to word and continue; |
185
|
146
|
|
|
|
|
153
|
$word .= $letter; |
186
|
146
|
|
|
|
|
231
|
$list = !$list; |
187
|
|
|
|
|
|
|
} |
188
|
36
|
|
|
|
|
226
|
return ucfirst $word; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub _two_decimal { |
192
|
78
|
|
|
78
|
|
29546
|
my ($coord) = @_; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Discard non-digits except for a decimal point. |
195
|
78
|
|
|
|
|
296
|
$coord =~ s/[^\d\.]//g; |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# Drop leading zeros. |
198
|
78
|
|
|
|
|
272
|
$coord =~ s/^0*//g; |
199
|
78
|
100
|
|
|
|
202
|
$coord = 0 unless $coord; |
200
|
|
|
|
|
|
|
|
201
|
78
|
100
|
|
|
|
247
|
if (abs($coord) > 180) { |
202
|
2
|
|
|
|
|
41
|
croak "$coord must be between -180 and +180\n"; |
203
|
|
|
|
|
|
|
} |
204
|
76
|
100
|
|
|
|
225
|
unless ($coord =~ /\./) { |
205
|
|
|
|
|
|
|
# add decimals |
206
|
24
|
|
|
|
|
282
|
$coord .= "."; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
# Add two more zeroes; we'll discard them if we don't need them. |
209
|
76
|
|
|
|
|
109
|
$coord .= "00"; |
210
|
76
|
|
|
|
|
301
|
($coord) = ($coord =~ /^(\d{0,3}\.\d\d)/); |
211
|
76
|
|
|
|
|
241
|
return $coord; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=head2 from_whitwell($whitwell_name, signed => $yes_or_no) |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Converts a Whitwell name back into a lat/lon pair, in trailing indicator |
217
|
|
|
|
|
|
|
format. Results will be undefined if the string does not match the Whitwell |
218
|
|
|
|
|
|
|
scheme; if the strings I Whitwell-compatible, but includes extra letters, |
219
|
|
|
|
|
|
|
these will be assumed to be further digits after the decimal point. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
If you supply the 'signed' option with a true value, the returned values are |
222
|
|
|
|
|
|
|
signed numbers rather than numbers with trailing sign indicators. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub from_whitwell { |
227
|
10
|
|
|
10
|
1
|
5873
|
my($name, %opts) = @_; |
228
|
10
|
|
|
|
|
28
|
my ($lat_name, $lon_name) = split(/\s+/, $name); |
229
|
|
|
|
|
|
|
|
230
|
10
|
|
|
|
|
13
|
my ($value, $negative); |
231
|
10
|
|
|
|
|
24
|
($value, $negative) = _coord_for(lc($lat_name)); |
232
|
10
|
100
|
|
|
|
22
|
if ($negative) { |
233
|
5
|
100
|
|
|
|
12
|
if ($opts{signed}) { |
234
|
2
|
|
|
|
|
4
|
$value = -$value; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
else { |
237
|
3
|
|
|
|
|
13
|
$value .= "S"; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
else { |
241
|
5
|
100
|
|
|
|
11
|
unless ($opts{signed}) { |
242
|
3
|
|
|
|
|
22
|
$value .= "N"; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
} |
245
|
10
|
|
|
|
|
14
|
my $lat = $value; |
246
|
|
|
|
|
|
|
|
247
|
10
|
|
|
|
|
22
|
($value, $negative) = _coord_for(lc($lon_name)); |
248
|
10
|
100
|
|
|
|
22
|
if ($negative) { |
249
|
4
|
100
|
|
|
|
9
|
if ($opts{signed}) { |
250
|
2
|
|
|
|
|
4
|
$value = -$value; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
else { |
253
|
2
|
|
|
|
|
7
|
$value .= "W"; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
else { |
257
|
6
|
100
|
|
|
|
11
|
unless ($opts{signed}) { |
258
|
4
|
|
|
|
|
17
|
$value .= "E"; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
} |
261
|
10
|
|
|
|
|
14
|
my $lon = $value; |
262
|
|
|
|
|
|
|
|
263
|
10
|
|
|
|
|
32
|
return ($lat, $lon); |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub _coord_for { |
268
|
27
|
|
|
27
|
|
6285
|
my($original) = my($string) = @_; |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# Determine if the string starts in the vowel table or the consonant table. |
271
|
27
|
|
|
|
|
47
|
my @tables = (\@consonants, \@vowels); |
272
|
27
|
|
|
|
|
32
|
my $vowel_found; |
273
|
27
|
|
100
|
|
|
105
|
my $current = ($string =~ /^[aeiouy]/) || 0; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# Decompose and look up the character(s). |
276
|
27
|
|
|
|
|
26
|
my $coord_string; |
277
|
27
|
|
|
|
|
29
|
my $try_sign = 0; |
278
|
27
|
|
|
|
|
32
|
my $is_negative = 0; |
279
|
27
|
|
|
|
|
31
|
my $sign_checked = 0; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
PARSE: |
282
|
27
|
|
|
|
|
49
|
while ($string) { |
283
|
|
|
|
|
|
|
# If we need to look for the sign character, |
284
|
|
|
|
|
|
|
# do so. Since we've allowed names to start in either table |
285
|
|
|
|
|
|
|
# as seems to have been the historical precedent (yes, someone |
286
|
|
|
|
|
|
|
# actually did use this at least once for a real placename), |
287
|
|
|
|
|
|
|
# we check for both sign characters and record whether or not |
288
|
|
|
|
|
|
|
# we found one. |
289
|
115
|
100
|
|
|
|
199
|
if ($try_sign) { |
290
|
|
|
|
|
|
|
# Don't try more than once. |
291
|
35
|
|
|
|
|
37
|
$try_sign = 0; |
292
|
35
|
100
|
|
|
|
83
|
if ($string =~ s/^[vs]//) { |
293
|
11
|
|
|
|
|
12
|
$is_negative = 1; |
294
|
|
|
|
|
|
|
# Return to the vowel table again. |
295
|
11
|
|
|
|
|
10
|
$current = 1; |
296
|
11
|
|
|
|
|
24
|
next PARSE; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
# Note we've looked for the sign once, so we shouldn't look |
299
|
|
|
|
|
|
|
# again. This wil trap badly-placed sign characters. |
300
|
24
|
|
|
|
|
26
|
$sign_checked = 1; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
# Longer entries occur at the end of the vowel table, so |
303
|
|
|
|
|
|
|
# to avoid parsing 'ee' as 'e' and 'e', we try the longer |
304
|
|
|
|
|
|
|
# strings first. However: complicating this process is the '0' |
305
|
|
|
|
|
|
|
# entry, which is also a longer one, so it has to be checked first. |
306
|
104
|
|
|
|
|
149
|
for my $i (0, reverse 1..9) { |
307
|
658
|
|
|
|
|
815
|
my $char = $tables[$current]->[$i]; |
308
|
658
|
100
|
|
|
|
4834
|
if ($string =~ s/^$char//) { |
309
|
|
|
|
|
|
|
# Found it. Tack the number onto the coordinate string, |
310
|
|
|
|
|
|
|
# swap tables, and see if we need to check the sign. |
311
|
102
|
|
|
|
|
172
|
$coord_string .= $i; |
312
|
102
|
|
100
|
|
|
814
|
$try_sign = ($current == 1 and !$sign_checked); |
313
|
102
|
|
|
|
|
108
|
$current = !$current; |
314
|
102
|
|
|
|
|
290
|
next PARSE; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
# The current table should have matched, so the input string is bad. |
318
|
2
|
|
|
|
|
32
|
croak "Bad character or sequencing found in '$original' at '$string'"; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
# Insert the decimal point such that the resulting number is < 180. |
321
|
|
|
|
|
|
|
# This allows "high-precision" Whitwell names (constructed in some |
322
|
|
|
|
|
|
|
# manner other than via to_whitwell) to be converted back correctly. |
323
|
25
|
100
|
|
|
|
49
|
if (length($coord_string) >= 3) { |
324
|
|
|
|
|
|
|
# Need to insert a decimal point. The final value must be < 180, |
325
|
|
|
|
|
|
|
# and we asssume at least two decimal places. |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Let's try the easy case first, and insert a decimal point |
328
|
|
|
|
|
|
|
# right before the last two digits. All names generated via |
329
|
|
|
|
|
|
|
# to_whitwell() will work with this case. Since we know the |
330
|
|
|
|
|
|
|
# coordinate string only has numbers in it, we can just divide |
331
|
|
|
|
|
|
|
# by 100. |
332
|
24
|
|
|
|
|
70
|
my $trial_value = $coord_string/100; |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# Manufactured by some other means. Move the decimal left one |
335
|
|
|
|
|
|
|
# character at a time until the number is < 180. We never do this |
336
|
|
|
|
|
|
|
# at all if our initial guess worked. |
337
|
24
|
|
|
|
|
54
|
$trial_value /= 10 while $trial_value > 180; |
338
|
24
|
|
|
|
|
32
|
$coord_string = $trial_value; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
else { |
341
|
|
|
|
|
|
|
# < 3, so can't be > 180. Just add decimals. |
342
|
1
|
|
|
|
|
3
|
$coord_string .= ".00"; |
343
|
|
|
|
|
|
|
} |
344
|
25
|
|
|
|
|
71
|
return ($coord_string, $is_negative); |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=head1 AUTHOR |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Joe McMahon, C<< >> |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head1 BUGS |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
Please report any bugs or feature requests to C
|
354
|
|
|
|
|
|
|
rt.cpan.org>, or through the web interface at |
355
|
|
|
|
|
|
|
L. I |
356
|
|
|
|
|
|
|
will be notified, and then you'll automatically be notified of progress on your |
357
|
|
|
|
|
|
|
bug as I make changes. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=head2 KNOWN BUGS |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
=over |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=item * (0,0) isn't handled correctly; however, since there's nothing there |
364
|
|
|
|
|
|
|
but water, this is not a practical limitation. |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=back |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=head1 SUPPORT |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
perldoc Acme::Geo::Whitwell::Name |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
You can also look for information at: |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=over 4 |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
L |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
L |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=item * CPAN Ratings |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
L |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=item * Search CPAN |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
L |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=back |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
Copyright 2008 Joe McMahon, all rights reserved. |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
406
|
|
|
|
|
|
|
under the same terms as Perl itself. |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=cut |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
1; # End of Acme::Geo::Whitwell::Name |