X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fbucket%2Fnewbucket.hxx;h=fe0bbbc4abd305b113723e269a76df7e6796e81f;hb=9447d56332028ea18ccde4712cffd75154064769;hp=3d19d229b204d7acff74283554088217773efe39;hpb=82459a2802a939434f9fc5b88d2b2aea58f0043d;p=simgear.git diff --git a/simgear/bucket/newbucket.hxx b/simgear/bucket/newbucket.hxx index 3d19d229..fe0bbbc4 100644 --- a/simgear/bucket/newbucket.hxx +++ b/simgear/bucket/newbucket.hxx @@ -3,7 +3,7 @@ * * Written by Curtis L. Olson, started February 1999. * - * Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org + * Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -15,125 +15,51 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ **************************************************************************/ +/** \file newbucket.hxx + * A class and associated utiltity functions to manage world scenery tiling. + * + * Tile borders are aligned along circles of latitude and longitude. + * All tiles are 1/8 degree of latitude high and their width in degrees + * longitude depends on their latitude, adjusted in such a way that + * all tiles cover about the same amount of area of the earth surface. + */ #ifndef _NEWBUCKET_HXX #define _NEWBUCKET_HXX #include #include +#include -#ifdef FG_HAVE_STD_INCLUDES -# include -# include // sprintf() -# include -#else -# include -# include // sprintf() -# include -#endif - -// I don't understand ... or should be included -// already depending on how you defined FG_HAVE_STD_INCLUDES, but I -// can go ahead and add this -- CLO -#ifdef __MWERKS__ -# include // needed fabs() -#endif - -#include STL_STRING - -FG_USING_STD(string); - -#if ! defined( FG_HAVE_NATIVE_SGI_COMPILERS ) -FG_USING_STD(ostream); -#endif - - - -#define FG_BUCKET_SPAN 0.125 // 1/8 of a degree -#define FG_HALF_BUCKET_SPAN 0.0625 // 1/2 of 1/8 of a degree = 1/16 = 0.0625 - -class FGBucket; -ostream& operator<< ( ostream&, const FGBucket& ); -bool operator== ( const FGBucket&, const FGBucket& ); - -class FGBucket { - -private: - double cx, cy; // centerpoint (lon, lat) in degrees of bucket - int lon; // longitude index (-180 to 179) - int lat; // latitude index (-90 to 89) - int x; // x subdivision (0 to 7) - int y; // y subdivision (0 to 7) - -public: - - // default constructor - FGBucket(); - - // create a bucket which would contain the specified lon/lat - FGBucket(const double lon, const double lat); - - // create a bucket based on "long int" index - FGBucket(const long int bindex); - - // create an impossible bucket if false - FGBucket(const bool is_good); - - ~FGBucket(); - - // Set the bucket params for the specified lat and lon - void set_bucket( double dlon, double dlat ); - void set_bucket( double *lonlat ) { - set_bucket( lonlat[0], lonlat[1] ); - } +#include +#include +#include +#include - void make_bad ( void ); +// #define NO_DEPRECATED_API - // Generate the unique scenery tile index for this bucket - long int gen_index(); - string gen_index_str() const; +/** + * standard size of a bucket in degrees (1/8 of a degree) + */ +#define SG_BUCKET_SPAN 0.125 - // Build the path name for this bucket - string gen_base_path() const; - - // return the center lon of a tile - double get_center_lon() const; - - // return width of the tile - double get_width() const; - - // return the center lat of a tile - double get_center_lat() const; - - // return height of the tile - double get_height() const; - - // Informational methods - inline int get_lon() const { return lon; } - inline int get_lat() const { return lat; } - inline int get_x() const { return x; } - inline int get_y() const { return y; } - - // friends - friend ostream& operator<< ( ostream&, const FGBucket& ); - friend bool operator== ( const FGBucket&, const FGBucket& ); -}; +/** + * half of a standard SG_BUCKET_SPAN + */ +#define SG_HALF_BUCKET_SPAN ( 0.5 * SG_BUCKET_SPAN ) // return the horizontal tile span factor based on latitude -inline double bucket_span( double l ) { +static double sg_bucket_span( double l ) { if ( l >= 89.0 ) { - return 360.0; - } else if ( l >= 88.0 ) { - return 8.0; + return 12.0; } else if ( l >= 86.0 ) { return 4.0; } else if ( l >= 83.0 ) { @@ -154,189 +80,275 @@ inline double bucket_span( double l ) { return 1.0; } else if ( l >= -86.0 ) { return 2.0; - } else if ( l >= -88.0 ) { - return 4.0; } else if ( l >= -89.0 ) { - return 8.0; + return 4.0; } else { - return 360.0; + return 12.0; } } -// Set the bucket params for the specified lat and lon -inline void FGBucket::set_bucket( double dlon, double dlat ) { - // - // latitude first - // - double span = bucket_span( dlat ); - double diff = dlon - (double)(int)dlon; +/** + * A class to manage world scenery tiling. + * This class encapsulates the world tiling scheme. It provides ways + * to calculate a unique tile index from a lat/lon, and it can provide + * information such as the dimensions of a given tile. + */ - // cout << "diff = " << diff << " span = " << span << endl; +class SGBucket { - if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) { - lon = (int)dlon; - } else { - lon = (int)dlon - 1; +private: + short lon; // longitude index (-180 to 179) + short lat; // latitude index (-90 to 89) + unsigned char x; // x subdivision (0 to 7) + unsigned char y; // y subdivision (0 to 7) + + void innerSet( double dlon, double dlat ); +public: + + /** + * Default constructor, creates an invalid SGBucket + */ + SGBucket(); + + /** + * Check if this bucket refers to a valid tile, or not. + */ + bool isValid() const; + +#ifndef NO_DEPRECATED_API + /** + * Construct a bucket given a specific location. + * @param dlon longitude specified in degrees + * @param dlat latitude specified in degrees + */ + SGBucket(const double dlon, const double dlat); +#endif + + /** + * Construct a bucket given a specific location. + * + * @param geod Geodetic location + */ + SGBucket(const SGGeod& geod); + + /** Construct a bucket given a unique bucket index number. + * + * @param bindex unique bucket index + */ + SGBucket(const long int bindex); + +#ifndef NO_DEPRECATED_API + /** + * Reset a bucket to represent a new location. + * + * @param geod New geodetic location + */ + void set_bucket(const SGGeod& geod); + + + /** + * Reset a bucket to represent a new lat and lon + * @param dlon longitude specified in degrees + * @param dlat latitude specified in degrees + */ + void set_bucket( double dlon, double dlat ); +#endif + + /** + * Create an impossible bucket. + * This is useful if you are comparing cur_bucket to last_bucket + * and you want to make sure last_bucket starts out as something + * impossible. + */ + void make_bad(); + + /** + * Generate the unique scenery tile index for this bucket + * + * The index is constructed as follows: + * + * 9 bits - to represent 360 degrees of longitude (-180 to 179) + * 8 bits - to represent 180 degrees of latitude (-90 to 89) + * + * Each 1 degree by 1 degree tile is further broken down into an 8x8 + * grid. So we also need: + * + * 3 bits - to represent x (0 to 7) + * 3 bits - to represent y (0 to 7) + * @return tile index + */ + inline long int gen_index() const { + return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x; } - // find subdivision or super lon if needed - if ( span < FG_EPSILON ) { - // polar cap - lon = 0; - x = 0; - } else if ( span <= 1.0 ) { - x = (int)((dlon - lon) / span); - } else { - if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) { - lon = (int)( (int)(lon / span) * span); + /** + * Generate the unique scenery tile index for this bucket in ascii + * string form. + * @return tile index in string form + */ + std::string gen_index_str() const; + + /** + * Build the base path name for this bucket. + * @return base path in string form + */ + std::string gen_base_path() const; + + /** + * @return the center lon of a tile. + */ + inline double get_center_lon() const { + double span = sg_bucket_span( lat + y / 8.0 + SG_HALF_BUCKET_SPAN ); + + if ( span >= 1.0 ) { + return lon + get_width() / 2.0; } else { - // cout << " lon = " << lon - // << " tmp = " << (int)((lon-1) / span) << endl; - lon = (int)( (int)((lon + 1) / span) * span - span); - if ( lon < -180 ) { - lon = -180; - } + return lon + x * span + get_width() / 2.0; } - x = 0; } - // - // then latitude - // - diff = dlat - (double)(int)dlat; - - if ( (dlat >= 0) || (fabs(diff) < FG_EPSILON) ) { - lat = (int)dlat; - } else { - lat = (int)dlat - 1; + /** + * @return the center lat of a tile. + */ + inline double get_center_lat() const { + return lat + y / 8.0 + SG_HALF_BUCKET_SPAN; } - y = (int)((dlat - lat) * 8); -} - - -// default constructor -inline FGBucket::FGBucket() {} - -// constructor for specified location -inline FGBucket::FGBucket(const double dlon, const double dlat) { - set_bucket(dlon, dlat); -} + /** + * @return the highest (furthest from the equator) latitude of this + * tile. This is the top edge for tiles north of the equator, and + * the bottom edge for tiles south + */ + double get_highest_lat() const; + + /** + * @return the width of the tile in degrees. + */ + double get_width() const; + /** + * @return the height of the tile in degrees. + */ + double get_height() const; -// create an impossible bucket if false -inline FGBucket::FGBucket(const bool is_good) { - set_bucket(0.0, 0.0); - if ( !is_good ) { - lon = -1000; + /** + * @return the width of the tile in meters. + */ + double get_width_m() const; + + /** + * @return the height of the tile in meters. + */ + double get_height_m() const; + + /** + * @return the center of the bucket in geodetic coordinates. + */ + SGGeod get_center() const + { return SGGeod::fromDeg(get_center_lon(), get_center_lat()); } + + /** + * @return the center of the bucket in geodetic coordinates. + */ + SGGeod get_corner(unsigned num) const + { + double lonFac = ((num + 1) & 2) ? 0.5 : -0.5; + double latFac = ((num ) & 2) ? 0.5 : -0.5; + return SGGeod::fromDeg(get_center_lon() + lonFac*get_width(), + get_center_lat() + latFac*get_height()); } -} - - -// Parse a unique scenery tile index and find the lon, lat, x, and y -inline FGBucket::FGBucket(const long int bindex) { - long int index = bindex; - lon = index >> 14; - index -= lon << 14; - lon -= 180; + // Informational methods. - lat = index >> 6; - index -= lat << 6; - lat -= 90; + /** + * @return the lon of the lower left corner of + * the 1x1 chunk containing this tile. + */ + inline int get_chunk_lon() const { return lon; } - y = index >> 3; - index -= y << 3; + /** + * @return the lat of the lower left corner of + * the 1x1 chunk containing this tile. + */ + inline int get_chunk_lat() const { return lat; } - x = index; -} - - -// default destructor -inline FGBucket::~FGBucket() {} - - -// Generate the unique scenery tile index for this bucket -// -// The index is constructed as follows: -// -// 9 bits - to represent 360 degrees of longitude (-180 to 179) -// 8 bits - to represent 180 degrees of latitude (-90 to 89) -// -// Each 1 degree by 1 degree tile is further broken down into an 8x8 -// grid. So we also need: -// -// 3 bits - to represent x (0 to 7) -// 3 bits - to represent y (0 to 7) - -inline long int FGBucket::gen_index() { - return ((lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x; -} + /** + * @return the x coord within the 1x1 degree chunk this tile. + */ + inline int get_x() const { return x; } -inline string FGBucket::gen_index_str() const { - char tmp[20]; - sprintf(tmp, "%ld", - (((long)lon + 180) << 14) + ((lat + 90) << 6) + (y << 3) + x); - return (string)tmp; -} + /** + * @return the y coord within the 1x1 degree chunk this tile. + */ + inline int get_y() const { return y; } + /** + * @return bucket offset from this by dx,dy + */ + SGBucket sibling(int dx, int dy) const; + + // friends -// return the center lon of a tile -inline double FGBucket::get_center_lon() const { - double span = bucket_span( lat + y / 8.0 + FG_HALF_BUCKET_SPAN ); + friend std::ostream& operator<< ( std::ostream&, const SGBucket& ); + friend bool operator== ( const SGBucket&, const SGBucket& ); +}; - if ( span >= 1.0 ) { - return lon + span / 2.0; - } else { - return lon + x * span + span / 2.0; +inline bool operator!= (const SGBucket& lhs, const SGBucket& rhs) + { + return !(lhs == rhs); } -} - - -// return the center lat of a tile -inline double FGBucket::get_center_lat() const { - return lat + y / 8.0 + FG_HALF_BUCKET_SPAN; -} - - -// return width of the tile -inline double FGBucket::get_width() const { - return bucket_span( get_center_lat() ); -} - - -// return height of the tile -inline double FGBucket::get_height() const { - return FG_BUCKET_SPAN; -} - -// create an impossible bucket -inline void FGBucket::make_bad( void ) { - set_bucket(0.0, 0.0); - lon = -1000; -} - - -// offset a bucket struct by the specified tile units in the X & Y -// direction -FGBucket fgBucketOffset( double dlon, double dlat, int x, int y ); - - -// calculate the offset between two buckets -void fgBucketDiff( const FGBucket& b1, const FGBucket& b2, int *dx, int *dy ); - - -inline ostream& -operator<< ( ostream& out, const FGBucket& b ) -{ - return out << b.lon << ":" << b.x << ", " << b.lat << ":" << b.y; -} +#ifndef NO_DEPRECATED_API +/** + * \relates SGBucket + * Return the bucket which is offset from the specified dlon, dlat by + * the specified tile units in the X & Y direction. + * @param dlon starting lon in degrees + * @param dlat starting lat in degrees + * @param x number of bucket units to offset in x (lon) direction + * @param y number of bucket units to offset in y (lat) direction + * @return offset bucket + */ +SGBucket sgBucketOffset( double dlon, double dlat, int x, int y ); +#endif +/** + * \relates SGBucket + * Calculate the offset between two buckets (in quantity of buckets). + * @param b1 bucket 1 + * @param b2 bucket 2 + * @param dx offset distance (lon) in tile units + * @param dy offset distance (lat) in tile units + */ +void sgBucketDiff( const SGBucket& b1, const SGBucket& b2, int *dx, int *dy ); + + +/** + * \relates SGBucket + * retrieve a list of buckets in the given bounding box + * @param min min lon,lat of bounding box in degrees + * @param max max lon,lat of bounding box in degrees + * @param list standard vector of buckets within the bounding box + */ +void sgGetBuckets( const SGGeod& min, const SGGeod& max, std::vector& list ); + +/** + * Write the bucket lon, lat, x, and y to the output stream. + * @param out output stream + * @param b bucket + */ +std::ostream& operator<< ( std::ostream& out, const SGBucket& b ); + +/** + * Compare two bucket structures for equality. + * @param b1 bucket 1 + * @param b2 bucket 2 + * @return comparison result + */ inline bool -operator== ( const FGBucket& b1, const FGBucket& b2 ) +operator== ( const SGBucket& b1, const SGBucket& b2 ) { return ( b1.lon == b2.lon && b1.lat == b2.lat &&