# GeoCoordinate.pm
#
# Copyright (c) 2002 Cunningham & Cunningham, Inc.
# Released under the terms of the GNU General Public License version 2 or later.
#
# Perl translation by Dave W. Smith <dws@postcognitive.com>

package GeoCoordinate;

use strict;

sub new {
    my $pkg = shift;
    my($lat, $lon) = @_;

    bless {
	lat => $lat,
	lon => $lon,
	@_
    }, $pkg;
}

sub parse {
    my($string) = @_;

    my @n = (0, 0, 0, 0, 0, 0);
    my $north = 1;
    my $east = 1;

    my $i = 0;
    foreach my $token ( $string =~ m/(-?\d+|'|"|[nsew])/ig ) {
	$north = 0 if lc($token) eq "s";
        $east = 0  if lc($token) eq "w";
	if ( $token =~ /^-?\d/ ) {
	    $n[$i++] = $token;
	}
	$i = 3 if $i > 0 && $token =~ m/nsew/i;
    }
    
    my $lat = $n[0] + $n[1]/60 + $n[2]/3600;
    my $lon = $n[3] + $n[4]/60 + $n[5]/3600;
    return new GeoCoordinate($north ? $lat : -$lat, $east ? $lon : -$lon);
}

sub equals {
    my $self = shift;
    my($arg) = @_;
    my $precision = 0.00001;

    return 0 if ! $arg->isa('GeoCoordinate');
    return int($self->{'lat'}/$precision) == int($arg->{'lat'}/$precision) &&
           int($self->{'lon'}/$precision) == int($arg->{'lon'}/$precision);
}

sub hash {
    my $self = shift;

    die "GeoCoordinate::hash() shouldn't be needed";
}

sub toString {
    my $self = shift;

    sprintf "%.4f%s %.4f%s",
	abs($self->{'lat'}), $self->{'lat'} >= 0 ? "N" : "S",
        abs($self->{'lon'}), $self->{'lon'} >= 0 ? "E" : "W";
}


1;

__END__
package eg.net;

// Copyright (c) 2002 Cunningham & Cunningham, Inc.
// Released under the terms of the GNU General Public License version 2 or later.

// import java.util.regex.*;

import java.util.StringTokenizer;
import java.text.DecimalFormat;

public class GeoCoordinate {

    float lat;
    float lon;

    public GeoCoordinate (float lat, float lon) {
        this.lat = lat;
        this.lon = lon;
    }

    public static GeoCoordinate parse (String string) {
        StringTokenizer t = new StringTokenizer (string, "nNsSeEwW \'\",", true);
        float n[] = {0,0,0,0,0,0};
        boolean north=true, east=true;
        for (int i=0; i<6 && t.hasMoreTokens(); ) {
            String token = t.nextToken().toLowerCase();
            char ch = token.charAt(0);
            if (Character.isDigit(ch) || ch == '-')     {n[i++] = Float.parseFloat(token);}
            if (ch == 's')                              {north = false;}
            if (ch == 'w')                              {east = false;}
            if (i>0 && "nsew".indexOf(ch)>=0)           {i = 3;}
        }
        float lat = n[0] + n[1]/60 + n[2]/3600;
        float lon = n[3] + n[4]/60 + n[5]/3600;
        return new GeoCoordinate(north?lat:-lat, east?lon:-lon);
    }

    static double precision = 0.00001;

    public boolean equals(Object arg) {
        if (!getClass().isInstance(arg)) return false;
        GeoCoordinate coord = (GeoCoordinate)arg;
        return
            ((long)(lat/precision)) == ((long)(coord.lat/precision)) &&
            ((long)(lon/precision)) == ((long)(coord.lon/precision));
    }

    public long hash() {
        return ((long)(lat/precision)) + ((long)(lon/precision));
    }

    public String toString () {
        DecimalFormat coord = new DecimalFormat();
        coord.setMaximumFractionDigits(4);
        return
            coord.format(Math.abs(lat)) + (lat>=0 ? "N " : "S ") +
            coord.format(Math.abs(lon)) + (lon>=0 ? "E " : "W ");
    }
}
