#!/usr/bin/perl -w ########################################################################### # long-lat v1.0.1 ########################################################################### # # Parses coordinates selected from a cylindrical projection # and returns longitude and latitude. # # Output # ###### # # Returns longitude latitude with appropriate number of decimals # for the size of the xmax and ymax you input, # ie roughly calculates precision. # This is up to a maximum of 5 decimal places but can be easily extended if # anyone needs it (by editting the script of course!). # # Gives only positive/negative values, not E/W/N/W. # # N,E = + W,S = - # # Output values seperated by space. # # Input # ##### # # long-lat Xmax,Ymax Xgmt X,Y Expects integer input values. # # Xmax and Ymax are the largest values of X and Y respectively # for the coordinate grid you are using. # eg max X and Y size of image. # # Xgmt is the X value of the zero meridian known as GMT. # # X and Y are the coordinates you want to know the longitude and latitude for. # # Your values should start at 0, so if they instead start at 1, then # a simple solution would be to subtract 1 from all values before # running them through this script. # # I could do a whole lot of fancy maths in this script, but half the # time I think the input would be given this way anyway, so why bother? # # ie Make sure that the maximum X you could supply is Xmax, not Xmax - 1 # and make sure the minimum X you could supply is 0, not 1. # Do the same for Y. # # eg if you are using a map which is 300 pixels high, then in fact Ymax = 299, # because you count the fist pixel as 0, not 1. Get it? # # Known bugs: yes, already! # # 1 # # If you give it X = 0 you get -180 if you give it X = Xmax # you get 180. For pixels on an image this is incorrect, # there should be a small discrepency, eg x = 0 should give # -179.5. Who cares? # # Let me know if this matters to you and I will fix it! # # 2 # # An extra space is preserved in the output when there is no '-' sign. # # This should be seen as a feature, since a) who cares, b) it could be # nifty if you generated a list of coordinates, they would all line up. # ########################################################################## # 21 Nov 2002 Simeon Scott simeonscott@iname.com # GPL License applies - see http://opensource.org/licenses/gpl-license.php ########################################################################## use strict; use Math::Trig; # Get input and do sanity checking: unless ($ARGV[0] =~ /^([0-9]+),([0-9]+)$/) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} my $xmax = $1; my $ymax = $2; unless ($ARGV[1] =~ /^[0-9]+$/) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} my $xgmt = $ARGV[1]; unless (0 <= $xgmt) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} unless ($xgmt <= $xmax) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} unless ($ARGV[2] =~ /^([0-9]+),([0-9]+)$/) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} my $x = $1; my $y = $2; unless (0 <= $x) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} unless ($x <= $xmax) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} unless (0 <= $y) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} unless ($y <= $ymax) {die "$0 coords format incorrect.\nPlease use format $0 Xmax,Ymax Xgmt X,Y\n";} # Calculate the longitude from the X coordinate value: my $long = ($x - $xgmt)*360/$xmax; # Calculate $long precision, # ie How many longitude degrees in one X pixel? my $longprec = 360/$xmax; my $lat; # Calculate the latitude from Y coordinate value: if ($y == $ymax/2) {$lat = 0;} elsif ($y < $ymax/2) {$lat = 90*($ymax - 2*$y)/$ymax;} else {$lat = -90*(2*$y - $ymax)/$ymax;} # Calculate $lat precision, # ie How many latitude degrees in one Y pixel? my $latprec = 180/$ymax; # Decimal precision formatting for $long: my $longfmt = '@#'; my $multiplyer = 10; if (abs($long) >= $multiplyer) { $longfmt .= '#'; $multiplyer = 100; if (abs($long) >= $multiplyer) {$longfmt .= '#';} } $multiplyer = 0.4; if ($longprec <= $multiplyer) { $longfmt .= '.#'; $multiplyer = 0.04; while ($longprec <= $multiplyer) { $longfmt .= '#'; $multiplyer *= 0.1; } } # Decimal precision formatting for $lat: my $latfmt = '@#'; $multiplyer = 10; if (abs($lat) >= $multiplyer) { $latfmt .= '#'; $multiplyer = 100; if (abs($lat) >= $multiplyer) {$latfmt .= '#';} } $multiplyer = 0.4; if ($latprec <= $multiplyer) { $latfmt .= '.#'; $multiplyer = 0.04; while ($latprec <= $multiplyer) { $latfmt .= '#'; $multiplyer *= 0.1; } } # Restate $long and $lat as E,W and N,S instead of +,-. #my ($longdir, $latdir); #if ($long < 0) #{ # $long = -1*$long; # $longdir = "W"; #} #else # {$longdir = "E";} # #if ($lat < 0) #{ # $lat = -1*$lat; # $latdir = "S"; #} #else # {$latdir = "N";} # Generate formatting for output: my $format = "format STDOUT =\n" . $longfmt . " " . $latfmt . "\n" #. '$long,$longdir,$lat,$latdir' . "\n" . '$long,$lat' . "\n" . ".\n"; eval $format; die $@ if $@; # Output the results to STDOUT: write;