]> git.mxchange.org Git - simgear.git/blob - simgear/bucket/newbucket.hxx
8e27579f7c7a50feee374f5c8308367ddd62f8b9
[simgear.git] / simgear / bucket / newbucket.hxx
1 /**************************************************************************
2  * newbucket.hxx -- new bucket routines for better world modeling
3  *
4  * Written by Curtis L. Olson, started February 1999.
5  *
6  * Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA  02111-1307, USA.
22  *
23  * $Id$
24  **************************************************************************/
25
26
27 #ifndef _NEWBUCKET_HXX
28 #define _NEWBUCKET_HXX
29
30 #include <simgear/compiler.h>
31 #include <simgear/constants.h>
32
33 #ifdef FG_HAVE_STD_INCLUDES
34 #  include <cmath>
35 #  include <cstdio> // sprintf()
36 #  include <iostream>
37 #else
38 #  include <math.h>
39 #  include <stdio.h> // sprintf()
40 #  include <iostream.h>
41 #endif
42
43 // I don't understand ... <math.h> or <cmath> should be included
44 // already depending on how you defined FG_HAVE_STD_INCLUDES, but I
45 // can go ahead and add this -- CLO
46 #ifdef __MWERKS__
47 #  include <math.h> // needed fabs()
48 #endif
49
50 #include STL_STRING
51
52 FG_USING_STD(string);
53
54 #if ! defined( FG_HAVE_NATIVE_SGI_COMPILERS )
55 FG_USING_STD(ostream);
56 #endif
57
58
59
60 #define SG_BUCKET_SPAN      0.125   // 1/8 of a degree
61 #define SG_HALF_BUCKET_SPAN 0.0625  // 1/2 of 1/8 of a degree = 1/16 = 0.0625
62
63 class SGBucket;
64 ostream& operator<< ( ostream&, const SGBucket& );
65 bool operator== ( const SGBucket&, const SGBucket& );
66
67
68 // return the horizontal tile span factor based on latitude
69 inline double sg_bucket_span( double l ) {
70     if ( l >= 89.0 ) {
71         return 360.0;
72     } else if ( l >= 88.0 ) {
73         return 8.0;
74     } else if ( l >= 86.0 ) {
75         return 4.0;
76     } else if ( l >= 83.0 ) {
77         return 2.0;
78     } else if ( l >= 76.0 ) {
79         return 1.0;
80     } else if ( l >= 62.0 ) {
81         return 0.5;
82     } else if ( l >= 22.0 ) {
83         return 0.25;
84     } else if ( l >= -22.0 ) {
85         return 0.125;
86     } else if ( l >= -62.0 ) {
87         return 0.25;
88     } else if ( l >= -76.0 ) {
89         return 0.5;
90     } else if ( l >= -83.0 ) {
91         return 1.0;
92     } else if ( l >= -86.0 ) {
93         return 2.0;
94     } else if ( l >= -88.0 ) {
95         return 4.0;
96     } else if ( l >= -89.0 ) {
97         return 8.0;
98     } else {
99         return 360.0;
100     }
101 }
102
103
104 class SGBucket {
105
106 private:
107     double cx, cy;  // centerpoint (lon, lat) in degrees of bucket
108     int lon;        // longitude index (-180 to 179)
109     int lat;        // latitude index (-90 to 89)
110     int x;          // x subdivision (0 to 7)
111     int y;          // y subdivision (0 to 7)
112
113 public:
114
115     // default constructor
116     inline SGBucket();
117
118     // constructor for specified location
119     inline SGBucket(const double dlon, const double dlat);
120
121     // create an impossible bucket if false
122     inline SGBucket(const bool is_good);
123
124     // Parse a unique scenery tile index and find the lon, lat, x, and y
125     inline SGBucket(const long int bindex);
126
127     // default destructor
128     inline ~SGBucket();
129
130     // Set the bucket params for the specified lat and lon
131     void set_bucket( double dlon, double dlat );
132     void set_bucket( double *lonlat );
133
134     // create an impossible bucket
135     inline void SGBucket::make_bad( void ) {
136         set_bucket(0.0, 0.0);
137         lon = -1000;
138     }
139
140     // Generate the unique scenery tile index for this bucket
141     // 
142     // The index is constructed as follows:
143     // 
144     // 9 bits - to represent 360 degrees of longitude (-180 to 179)
145     // 8 bits - to represent 180 degrees of latitude (-90 to 89)
146     //
147     // Each 1 degree by 1 degree tile is further broken down into an 8x8
148     // grid.  So we also need:
149     //
150     // 3 bits - to represent x (0 to 7)
151     // 3 bits - to represent y (0 to 7)
152
153     inline long int gen_index() const {
154         return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x;
155     }
156
157     inline string gen_index_str() const {
158         char tmp[20];
159         sprintf(tmp, "%ld", 
160                 (((long)lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x);
161         return (string)tmp;
162     }
163
164     // Build the path name for this bucket
165     string gen_base_path() const;
166
167     // return the center lon of a tile
168     inline double get_center_lon() const {
169         double span = sg_bucket_span( lat + y / 8.0 + SG_HALF_BUCKET_SPAN );
170
171         if ( span >= 1.0 ) {
172             return lon + span / 2.0;
173         } else {
174             return lon + x * span + span / 2.0;
175         }
176     }
177
178     // return the center lat of a tile
179     inline double get_center_lat() const {
180         return lat + y / 8.0 + SG_HALF_BUCKET_SPAN;
181     }
182
183     // return width of the tile in degrees
184     double get_width() const;
185     // return height of the tile in degrees
186     double get_height() const;
187
188     // return width of the tile in meters
189     double get_width_m() const; 
190     // return height of the tile in meters
191     double get_height_m() const;
192  
193     // Informational methods
194     inline int get_lon() const { return lon; }
195     inline int get_lat() const { return lat; }
196     inline int get_x() const { return x; }
197     inline int get_y() const { return y; }
198
199     // friends
200     friend ostream& operator<< ( ostream&, const SGBucket& );
201     friend bool operator== ( const SGBucket&, const SGBucket& );
202 };
203
204
205 // offset a bucket specified by dlon, dlat by the specified tile units
206 // in the X & Y direction
207 SGBucket sgBucketOffset( double dlon, double dlat, int x, int y );
208
209
210 // calculate the offset between two buckets
211 void sgBucketDiff( const SGBucket& b1, const SGBucket& b2, int *dx, int *dy );
212
213
214 inline ostream&
215 operator<< ( ostream& out, const SGBucket& b )
216 {
217     return out << b.lon << ":" << b.x << ", " << b.lat << ":" << b.y;
218 }
219
220
221 inline bool
222 operator== ( const SGBucket& b1, const SGBucket& b2 )
223 {
224     return ( b1.lon == b2.lon &&
225              b1.lat == b2.lat &&
226              b1.x == b2.x &&
227              b1.y == b2.y );
228 }
229
230
231 #endif // _NEWBUCKET_HXX
232
233