]> git.mxchange.org Git - flightgear.git/commitdiff
Simple perl script for calculating a tile path based on lon/lat. Does
authordavid <david>
Sun, 22 Sep 2002 15:52:46 +0000 (15:52 +0000)
committerdavid <david>
Sun, 22 Sep 2002 15:52:46 +0000 (15:52 +0000)
not depend on SimGear, but doesn't handle objects right on the poles
either.

scripts/perl/scenery/calc-tile.pl [new file with mode: 0644]

diff --git a/scripts/perl/scenery/calc-tile.pl b/scripts/perl/scenery/calc-tile.pl
new file mode 100644 (file)
index 0000000..7b032b1
--- /dev/null
@@ -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 <lon> <lat>
+########################################################################
+
+use strict;
+use POSIX;
+
+
+\f
+########################################################################
+# Constants.
+########################################################################
+
+my $EPSILON = 0.0000001;
+my $DIRSEP = '/';
+
+
+\f
+########################################################################
+# 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;
+}
+
+
+\f
+########################################################################
+# 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;