in reply to Locator to Lat/Long code: works, but is inelegant
(Repetition is nasty when you get into 100's or 1000's of lines of code, with some things being repeated multiple times -- no programmer good enough to deserve a living wage would ever do that.)
The only difference between the "alpha" and "numeric" blocks is the value that gets multiplied with your "div" value, so work that out just once, then handle the lat vs. long decision:
The "for" loop there is about half as many lines as the one in the OP, and seems to produce the same output.sub maidenhead2latlong { # convert a Maidenhead Grid location (eg FN03ir) # to decimal degrees # this code could be cleaner/shorter/clearer my @locator = split( //, uc(shift) ); # convert arg to upper case array my $lat = my $long = 0; my ( $latdiv, $longdiv ); my @divisors = ( 72000, 36000, 7200, 3600, 300, 150 ); # long,lat field size in seconds my $max = ( @locator > @divisors ) ? $#divisors : $#locator; for my $i ( 0 .. $max ) { my $val = ( int( $i/2 ) % 2 ) ? $locator[$i] : ord($locator[$i +]) - ord('A'); if ( $i % 2 ) { # lat $latdiv = $divisors[$i]; # save latdiv for later $lat += $val * $latdiv; } else { # long $longdiv = $divisors[$i]; # save longdiv for later $long += $val * $longdiv; } } $lat += ( $latdiv / 2 ); # location of centre of square $long += ( $longdiv / 2 ); return ( ( $lat / 3600 ) - 90, ( $long / 3600 ) - 180 ); }
|
|---|