Acme-Geo-Whitwell-Name

 view release on metacpan or  search on metacpan

lib/Acme/Geo/Whitwell/Name.pm  view on Meta::CPAN

    } 
    my $lat = $value;

    ($value, $negative) = _coord_for(lc($lon_name));
    if ($negative) {
        if ($opts{signed}) {
            $value = -$value;
        }
        else {
            $value .= "W";
        }
    }
    else {
        unless ($opts{signed}) {
            $value .= "E";
        }
    } 
    my $lon = $value;

    return ($lat, $lon);
    
}

sub _coord_for {
    my($original) = my($string) = @_;

    # Determine if the string starts in the vowel table or the consonant table.
    my @tables  = (\@consonants, \@vowels);
    my $vowel_found;
    my $current = ($string =~ /^[aeiouy]/) || 0;

    # Decompose and look up the character(s).
    my $coord_string;
    my $try_sign = 0;
    my $is_negative = 0;
    my $sign_checked = 0;

  PARSE:
    while ($string) {
        # If we need to look for the sign character, 
        # do so. Since we've allowed names to start in either table
        # as seems to have been the historical precedent (yes, someone
        # actually did use this at least once for a real placename),
        # we check for both sign characters and record whether or not
        # we found one.
        if ($try_sign) {
            # Don't try more than once.
            $try_sign = 0;
            if ($string =~ s/^[vs]//) {
                $is_negative = 1;
                # Return to the vowel table again.
                $current = 1;
                next PARSE;
            }
            # Note we've looked for the sign once, so we shouldn't look
            # again. This wil trap badly-placed sign characters.
            $sign_checked = 1; 
        }
        # Longer entries occur at the end of the vowel table, so
        # to avoid parsing 'ee' as 'e' and 'e', we try the longer
        # strings first. However: complicating this process is the '0'
        # entry, which is also a longer one, so it has to be checked first.
        for my $i (0, reverse 1..9) {
            my $char = $tables[$current]->[$i];
            if ($string =~ s/^$char//) {
                # Found it. Tack the number onto the coordinate string,
                # swap tables, and see if we need to check the sign.
                $coord_string .= $i;
                $try_sign = ($current == 1 and !$sign_checked);
                $current = !$current;
                next PARSE;
            }
        }
        # The current table should have matched, so the input string is bad.
        croak "Bad character or sequencing found in '$original' at '$string'";
    }
    # Insert the decimal point such that the resulting number is < 180.
    # This allows "high-precision" Whitwell names (constructed in some
    # manner other than via to_whitwell) to be converted back correctly.
    if (length($coord_string) >= 3) { 
        # Need to insert a decimal point. The final value must be < 180,
        # and we asssume at least two decimal places.

        # Let's try the easy case first, and insert a decimal point 
        # right before the last two digits. All names generated via 
        # to_whitwell() will work with this case. Since we know the 
        # coordinate string only has numbers in it, we can just divide
        # by 100.
        my $trial_value = $coord_string/100;

        # Manufactured by some other means. Move the decimal left one
        # character at a time until the number is < 180. We never do this
        # at all if our initial guess worked.
        $trial_value /= 10 while $trial_value > 180;
        $coord_string = $trial_value;
    }
    else {
        # < 3, so can't be > 180. Just add decimals.
        $coord_string .= ".00";
    }
    return ($coord_string, $is_negative);
}

=head1 AUTHOR

Joe McMahon, C<< <mcmahon at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-acme-geo-whitwell-name at
rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Acme-Geo-Whitwell-Name>.  I
will be notified, and then you'll automatically be notified of progress on your
bug as I make changes.

=head2 KNOWN BUGS

=over

=item * (0,0) isn't handled correctly; however, since there's nothing there
but water, this is not a practical limitation.



( run in 2.626 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )