From 3b3102d7c8b3454b53b3b43e8141caab9db0cded Mon Sep 17 00:00:00 2001 From: david Date: Sun, 22 Sep 2002 15:52:46 +0000 Subject: [PATCH] Simple perl script for calculating a tile path based on lon/lat. Does not depend on SimGear, but doesn't handle objects right on the poles either. --- scripts/perl/scenery/calc-tile.pl | 159 ++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 scripts/perl/scenery/calc-tile.pl diff --git a/scripts/perl/scenery/calc-tile.pl b/scripts/perl/scenery/calc-tile.pl new file mode 100644 index 000000000..7b032b107 --- /dev/null +++ b/scripts/perl/scenery/calc-tile.pl @@ -0,0 +1,159 @@ +#!/usr/bin/perl -w +######################################################################## +# calc-tile.pl +# +# Synopsis: Calculate a FlightGear tile base on longitude and latitude. +# Usage: perl calc-tile.pl +######################################################################## + +use strict; +use POSIX; + + + +######################################################################## +# Constants. +######################################################################## + +my $EPSILON = 0.0000001; +my $DIRSEP = '/'; + + + +######################################################################## +# Functions. +######################################################################## + +# +# Calculate the number of columns of tiles in a degree of longitude. +# +sub bucket_span { + my ($lat) = (@_); + if ($lat>= 89.0 ) { + return 360.0; + } elsif ($lat>= 88.0 ) { + return 8.0; + } elsif ($lat>= 86.0 ) { + return 4.0; + } elsif ($lat>= 83.0 ) { + return 2.0; + } elsif ($lat>= 76.0 ) { + return 1.0; + } elsif ($lat>= 62.0 ) { + return 0.5; + } elsif ($lat>= 22.0 ) { + return 0.25; + } elsif ($lat>= -22.0 ) { + return 0.125; + } elsif ($lat>= -62.0 ) { + return 0.25; + } elsif ($lat>= -76.0 ) { + return 0.5; + } elsif ($lat>= -83.0 ) { + return 1.0; + } elsif ($lat>= -86.0 ) { + return 2.0; + } elsif ($lat>= -88.0 ) { + return 4.0; + } elsif ($lat>= -89.0 ) { + return 8.0; + } else { + return 360.0; + } +} + +# +# Format longitude as e/w. +# +sub format_lon { + my ($lon) = (@_); + if ($lon < 0) { + return sprintf("w%03d", int(0-$lon)); + } else { + return sprintf("e%03d", int($lon)); + } +} + +# +# Format latitude as n/s. +# +sub format_lat { + my ($lat) = (@_); + if ($lat < 0) { + return sprintf("s%02d", int(0-$lat)); + } else { + return sprintf("n%02d", int($lat)); + } +} + +# +# Generate the directory name for a location. +# +sub directory_name { + my ($lon, $lat) = (@_); + my $lon_floor = POSIX::floor($lon); + my $lat_floor = POSIX::floor($lat); + my $lon_chunk = POSIX::floor($lon/10.0) * 10; + my $lat_chunk = POSIX::floor($lat/10.0) * 10; + return format_lon($lon_chunk) . format_lat($lat_chunk) . $DIRSEP + . format_lon($lon_floor) . format_lat($lat_floor); +} + +# +# Generate the tile index for a location. +# +sub tile_index { + my ($lon, $lat) = (@_); + my $lon_floor = POSIX::floor($lon); + my $lat_floor = POSIX::floor($lat); + my $span = bucket_span($lat); + + my $x; + if ($span < $EPSILON) { + $lon = 0; + $x = 0; + } elsif ($span <= 1.0) { + $x = int(($lon - $lon_floor) / $span); + } else { + if ($lon >= 0) { + $lon = int(int($lon/$span) * $span); + } else { + $lon = int(int(($lon+1)/$span) * $span - $span); + if ($lon < -180) { + $lon = -180; + } + } + $x = 0; + } + + my $y; + $y = int(($lat - $lat_floor) * 8); + + + my $index = 0; + $index += ($lon_floor + 180) << 14; + $index += ($lat_floor + 90) << 6; + $index += $y << 3; + $index += $x; + + return $index; +} + + + +######################################################################## +# Main program. +######################################################################## + +my ($lon, $lat) = (@ARGV); + +my $dir = directory_name($lon, $lat); +my $index = tile_index($lon, $lat); +my $path = "$dir$DIRSEP$index.stg"; + +print "Longitude: $lon\n"; +print "Latitude: $lat\n"; +print "Tile: $index\n"; +print "Path: \"$path\"\n"; + +1; -- 2.39.5