Amateur radio operators sometimes use the Maidenhead Grid Locator Square system to identify location. Here’s my attempt at a translator, written in slightly squirrelly Perl:
#!/usr/bin/perl -w # maidenhead - 6 character locator # created by scruss/VA3PID on 02011/04/01 # RCS/CVS: $Id: maidenhead,v 1.3 2011/04/03 11:04:38 scruss Exp $ use strict; sub latlong2maidenhead; sub maidenhead2latlong; if ( $#ARGV >= 1 ) { # two or more args # convert lat/long to grid print latlong2maidenhead( $ARGV[0], $ARGV[1] ), "\n"; } elsif ( $#ARGV == 0 ) { # one arg # convert grid to lat/long print join( ", ", maidenhead2latlong( $ARGV[0] ) ), "\n"; } else { # no args # print usage print 'Usage: ', $0, ' dd.dddddd ddd.dddddd', "\n", ' or', "\n", $0, ' grid_location', "\n"; } exit; 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 = 0; my $long = 0; my $latdiv = 0; my $longdiv = 0; my @divisors = ( 72000, 36000, 7200, 3600, 300, 150 ) ; # long,lat field size in seconds my $max = ( $#locator > $#divisors ) ? $#divisors : $#locator; for ( my $i = 0 ; $i <= $max ; $i++ ) { if ( int( $i / 2 ) % 2 ) { # numeric if ( $i % 2 ) { # lat $latdiv = $divisors[$i]; # save for later $lat += $locator[$i] * $latdiv; } else { # long $longdiv = $divisors[$i]; $long += $locator[$i] * $longdiv; } } else { # alpha my $val = ord( $locator[$i] ) - ord('A'); if ( $i % 2 ) { # lat $latdiv = $divisors[$i]; # save for later $lat += $val * $latdiv; } else { # long $longdiv = $divisors[$i]; $long += $val * $longdiv; } } } $lat += ( $latdiv / 2 ); # location of centre of square $long += ( $longdiv / 2 ); return ( ( $lat / 3600 ) - 90, ( $long / 3600 ) - 180 ); } sub latlong2maidenhead { # convert a WGS84 coordinate in decimal degrees # to a Maidenhead grid location my ( $lat, $long ) = @_; my @divisors = ( 72000, 36000, 7200, 3600, 300, 150 ); # field size in seconds my @locator = (); # add false easting and northing, convert to seconds $lat = ( $lat + 90 ) * 3600; $long = ( $long + 180 ) * 3600; for ( my $i = 0 ; $i < 3 ; $i++ ) { foreach ( $long, $lat ) { my $div = shift(@divisors); my $part = int( $_ / $div ); if ( $i == 1 ) { # do the numeric thing for 2nd pair push @locator, $part; } else { # character thing for 1st and 3rd pair push @locator, chr( ( ( $i < 1 ) ? ord('A') : ord('a') ) + $part ); } $_ -= ( $part * $div ); # leaves remainder in $long or $lat } } return join( '', @locator ); }
Grid square to lat/long and grid square shapefiles to follow.
4 replies on “Maidenhead Grid Locator, in Perl”
Thanks for this piece of code. Just what I was looking for. If you want to see how I used it, then go to my site. 73 de Hans
Argh; someone on PerlMonks reminded me of two modules that will do this already: Ham::Locator and Astro::Coord::ECI.
[…] locations are given as grid squares, which are a few kilometres […]
[…] IRazoo – View Site. […]