]> git.mxchange.org Git - flightgear.git/blob - scripts/perl/scenery/calc-tile.pl
gcc 3.2 fixes
[flightgear.git] / scripts / perl / scenery / calc-tile.pl
1 #!/usr/bin/perl -w
2 ########################################################################
3 # calc-tile.pl
4 #
5 # Synopsis: Calculate a FlightGear tile base on longitude and latitude.
6 # Usage: perl calc-tile.pl <lon> <lat>
7 ########################################################################
8
9 use strict;
10 use POSIX;
11
12
13 \f
14 ########################################################################
15 # Constants.
16 ########################################################################
17
18 my $EPSILON = 0.0000001;
19 my $DIRSEP = '/';
20
21
22 \f
23 ########################################################################
24 # Functions.
25 ########################################################################
26
27 #
28 # Calculate the number of columns of tiles in a degree of longitude.
29 #
30 sub bucket_span {
31   my ($lat) = (@_);
32   if ($lat>= 89.0 ) {
33     return 360.0;
34   } elsif ($lat>= 88.0 ) {
35     return 8.0;
36   } elsif ($lat>= 86.0 ) {
37     return 4.0;
38   } elsif ($lat>= 83.0 ) {
39     return 2.0;
40   } elsif ($lat>= 76.0 ) {
41     return 1.0;
42   } elsif ($lat>= 62.0 ) {
43     return 0.5;
44   } elsif ($lat>= 22.0 ) {
45     return 0.25;
46   } elsif ($lat>= -22.0 ) {
47     return 0.125;
48   } elsif ($lat>= -62.0 ) {
49     return 0.25;
50   } elsif ($lat>= -76.0 ) {
51     return 0.5;
52   } elsif ($lat>= -83.0 ) {
53     return 1.0;
54   } elsif ($lat>= -86.0 ) {
55     return 2.0;
56   } elsif ($lat>= -88.0 ) {
57     return 4.0;
58   } elsif ($lat>= -89.0 ) {
59     return 8.0;
60   } else {
61     return 360.0;
62   }
63 }
64
65 #
66 # Format longitude as e/w.
67 #
68 sub format_lon {
69   my ($lon) = (@_);
70   if ($lon < 0) {
71     return sprintf("w%03d", int(0-$lon));
72   } else {
73     return sprintf("e%03d", int($lon));
74   }
75 }
76
77 #
78 # Format latitude as n/s.
79 #
80 sub format_lat {
81   my ($lat) = (@_);
82   if ($lat < 0) {
83     return sprintf("s%02d", int(0-$lat));
84   } else {
85     return sprintf("n%02d", int($lat));
86   }
87 }
88
89 #
90 # Generate the directory name for a location.
91 #
92 sub directory_name {
93   my ($lon, $lat) = (@_);
94   my $lon_floor = POSIX::floor($lon);
95   my $lat_floor = POSIX::floor($lat);
96   my $lon_chunk = POSIX::floor($lon/10.0) * 10;
97   my $lat_chunk = POSIX::floor($lat/10.0) * 10;
98   return format_lon($lon_chunk) . format_lat($lat_chunk) . $DIRSEP
99     . format_lon($lon_floor) . format_lat($lat_floor);
100 }
101
102 #
103 # Generate the tile index for a location.
104 #
105 sub tile_index {
106   my ($lon, $lat) = (@_);
107   my $lon_floor = POSIX::floor($lon);
108   my $lat_floor = POSIX::floor($lat);
109   my $span = bucket_span($lat);
110
111   my $x;
112   if ($span < $EPSILON) {
113     $lon = 0;
114     $x = 0;
115   } elsif ($span <= 1.0) {
116     $x = int(($lon - $lon_floor) / $span);
117   } else {
118     if ($lon >= 0) {
119       $lon = int(int($lon/$span) * $span);
120     } else {
121       $lon = int(int(($lon+1)/$span) * $span - $span);
122       if ($lon < -180) {
123         $lon = -180;
124       }
125     }
126     $x = 0;
127   }
128
129   my $y;
130   $y = int(($lat - $lat_floor) * 8);
131
132
133   my $index = 0;
134   $index += ($lon_floor + 180) << 14;
135   $index += ($lat_floor + 90) << 6;
136   $index += $y << 3;
137   $index += $x;
138
139   return $index;
140 }
141
142
143 \f
144 ########################################################################
145 # Main program.
146 ########################################################################
147
148 my ($lon, $lat) = (@ARGV);
149
150 my $dir = directory_name($lon, $lat);
151 my $index = tile_index($lon, $lat);
152 my $path = "$dir$DIRSEP$index.stg";
153
154 print "Longitude: $lon\n";
155 print "Latitude:  $lat\n";
156 print "Tile:      $index\n";
157 print "Path:      \"$path\"\n";
158
159 1;