From 91efc5ad8772884e073796e44ec3fcc3025c47ab Mon Sep 17 00:00:00 2001 From: curt Date: Mon, 8 Feb 1999 23:52:13 +0000 Subject: [PATCH] Added a new "newbucket.[ch]xx" FGBucket class to replace the old fgBUCKET struct and C routines. This FGBucket class adjusts the tile width towards the poles to ensure the tiles are at least 8 miles wide. --- Bucket/Makefile.am | 9 +- Bucket/bucketutils.h | 7 +- Bucket/newbucket.cxx | 107 +++++++++++++++ Bucket/newbucket.hxx | 297 ++++++++++++++++++++++++++++++++++++++++++ Bucket/testbucket.cxx | 32 +++++ 5 files changed, 450 insertions(+), 2 deletions(-) create mode 100644 Bucket/newbucket.cxx create mode 100644 Bucket/newbucket.hxx create mode 100644 Bucket/testbucket.cxx diff --git a/Bucket/Makefile.am b/Bucket/Makefile.am index 6f7e25dd..34904d0a 100644 --- a/Bucket/Makefile.am +++ b/Bucket/Makefile.am @@ -1,5 +1,12 @@ noinst_LIBRARIES = libBucket.a -libBucket_a_SOURCES = bucketutils.c bucketutils.h bucketutils.hxx +libBucket_a_SOURCES = bucketutils.c bucketutils.h bucketutils.hxx \ + newbucket.cxx newbucket.hxx + +bin_PROGRAMS = testbucket + +testbucket_SOURCES = testbucket.cxx + +testbucket_LDADD = $(top_builddir)/Lib/Bucket/libBucket.a INCLUDES += -I$(top_builddir) diff --git a/Bucket/bucketutils.h b/Bucket/bucketutils.h index 96570cd8..6024a1ef 100644 --- a/Bucket/bucketutils.h +++ b/Bucket/bucketutils.h @@ -63,7 +63,7 @@ void fgBucketParseIndex(long int index, fgBUCKET *p); void fgBucketGenBasePath( const fgBUCKET *p, char *path); -// offset an bucket struct by the specified amounts in the X & Y direction +// offset a bucket struct by the specified amounts in the X & Y direction void fgBucketOffset(fgBUCKET *in, fgBUCKET *out, int x, int y); @@ -85,6 +85,11 @@ void fgBucketGenIdxArray(fgBUCKET *p1, fgBUCKET *tiles, int width, int height); // $Log$ +// Revision 1.5 1999/02/08 23:52:15 curt +// Added a new "newbucket.[ch]xx" FGBucket class to replace the old +// fgBUCKET struct and C routines. This FGBucket class adjusts the tile +// width towards the poles to ensure the tiles are at least 8 miles wide. +// // Revision 1.4 1998/12/09 18:48:09 curt // Use C++ style comments. // diff --git a/Bucket/newbucket.cxx b/Bucket/newbucket.cxx new file mode 100644 index 00000000..66eca096 --- /dev/null +++ b/Bucket/newbucket.cxx @@ -0,0 +1,107 @@ +/************************************************************************** + * newbucket.hxx -- new bucket routines for better world modeling + * + * Written by Curtis L. Olson, started February 1999. + * + * Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + * (Log is kept at end of this file) + **************************************************************************/ + + +#include "newbucket.hxx" + + +// Build the path name for this bucket +string FGBucket::gen_base_path() { + long int index; + int top_lon, top_lat, main_lon, main_lat; + char hem, pole; + char path[256]; + + index = gen_index(); + + path[0] = '\0'; + + top_lon = lon / 10; + main_lon = lon; + if ( (lon < 0) && (top_lon * 10 != lon) ) { + top_lon -= 1; + } + top_lon *= 10; + if ( top_lon >= 0 ) { + hem = 'e'; + } else { + hem = 'w'; + top_lon *= -1; + } + if ( main_lon < 0 ) { + main_lon *= -1; + } + + top_lat = lat / 10; + main_lat = lat; + if ( (lat < 0) && (top_lat * 10 != lat) ) { + top_lat -= 1; + } + top_lat *= 10; + if ( top_lat >= 0 ) { + pole = 'n'; + } else { + pole = 's'; + top_lat *= -1; + } + if ( main_lat < 0 ) { + main_lat *= -1; + } + + sprintf(path, "%c%03d%c%02d/%c%03d%c%02d", + hem, top_lon, pole, top_lat, + hem, main_lon, pole, main_lat); + + return path; +} + + +// find the bucket which is offset by the specified tile units in the +// X & Y direction. We need the current lon and lat to resolve +// ambiguities when going from a wider tile to a narrower one above or +// below. This assumes that we are feeding in +FGBucket fgBucketOffset( double dlon, double dlat, int dx, int dy ) { + FGBucket result( dlon, dlat ); + double clat = result.get_center_lat() + dy * FG_BUCKET_SPAN; + + // walk dy units in the lat direction + result.set_bucket( dlon, clat ); + + // find the lon span for the new latitude + double span = bucket_span( clat ); + + // walk dx units in the lon direction + result.set_bucket( dlon + dx * span, clat ); + + return result; +} + + +// $Log$ +// Revision 1.1 1999/02/08 23:52:16 curt +// Added a new "newbucket.[ch]xx" FGBucket class to replace the old +// fgBUCKET struct and C routines. This FGBucket class adjusts the tile +// width towards the poles to ensure the tiles are at least 8 miles wide. +// diff --git a/Bucket/newbucket.hxx b/Bucket/newbucket.hxx new file mode 100644 index 00000000..e2958edc --- /dev/null +++ b/Bucket/newbucket.hxx @@ -0,0 +1,297 @@ +/************************************************************************** + * newbucket.hxx -- new bucket routines for better world modeling + * + * Written by Curtis L. Olson, started February 1999. + * + * Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + * (Log is kept at end of this file) + **************************************************************************/ + + +#ifndef _NEWBUCKET_HXX +#define _NEWBUCKET_HXX + +#include + +#include + +FG_USING_STD(string); +FG_USING_NAMESPACE(std); + +#include // sprintf() + +#include + + +#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 { + +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); + + ~FGBucket(); + + // Set the bucket params for the specified lat and lon + void set_bucket( double dlon, double dlat ); + + // Generate the unique scenery tile index for this bucket + long int gen_index(); + + // Build the path name for this bucket + string gen_base_path(); + + // return the center lon of a tile + double get_center_lon(); + + // return the center lat of a tile + double get_center_lat(); + + // friends + friend ostream& operator<< ( ostream&, const FGBucket& ); +}; + + +// return the horizontal tile span factor based on latitude +inline double bucket_span( double l ) { + if ( l >= 89.0 ) { + return 0.0; + } else if ( l >= 88.0 ) { + return 8.0; + } else if ( l >= 86.0 ) { + return 4.0; + } else if ( l >= 83.0 ) { + return 2.0; + } else if ( l >= 76.0 ) { + return 1.0; + } else if ( l >= 62.0 ) { + return 0.5; + } else if ( l >= 22.0 ) { + return 0.25; + } else if ( l >= -22.0 ) { + return 0.125; + } else if ( l >= -62.0 ) { + return 0.25; + } else if ( l >= -76.0 ) { + return 0.5; + } else if ( l >= -83.0 ) { + 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; + } else { + return 0.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; + + // cout << "diff = " << diff << " span = " << span << endl; + + if ( (dlon >= 0) || (fabs(diff) < FG_EPSILON) ) { + lon = (int)dlon; + } else { + lon = (int)dlon - 1; + } + + // 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); + } else { + // cout << " lon = " << lon + // << " tmp = " << (int)((lon-1) / span) << endl; + lon = (int)( (int)((lon + 1) / span) * span - span); + if ( lon < -180 ) { + lon = -180; + } + } + x = 0; + } + + // + // then latitude + // + diff = dlat - (double)(int)dlat; + + if ( (dlat >= 0) || (fabs(diff) < FG_EPSILON) ) { + lat = (int)dlat; + } else { + lat = (int)dlat - 1; + } + 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); +} + + +// 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; + + lat = index >> 6; + index -= lat << 6; + lat -= 90; + + y = index >> 3; + index -= y << 3; + + 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 center lon of a tile +inline double FGBucket::get_center_lon() { + double span = bucket_span( lat + y / 8.0 + FG_HALF_BUCKET_SPAN ); + + if ( span >= 1.0 ) { + return lon + span / 2.0; + } else { + return lon + x * span + span / 2.0; + } +} + + +// return the center lat of a tile +inline double FGBucket::get_center_lat() { + return lat + y / 8.0 + FG_HALF_BUCKET_SPAN; +} + + +// offset a bucket struct by the specified tile units in the X & Y +// direction +FGBucket fgBucketOffset( double dlon, double dlat, int x, int y ); + + +/* +// Given a lat/lon, fill in the local tile index array +void fgBucketGenIdxArray(fgBUCKET *p1, fgBUCKET *tiles, int width, int height); + + + +inline bool +operator== ( const fgBUCKET& b1, const fgBUCKET& b2 ) +{ + return ( b1.lon == b2.lon && + b1.lat == b2.lat && + b1.x == b2.x && + b1.y == b2.y ); +} + +inline string +fgBucketGenIndex( const fgBUCKET& p ) +{ + char index_str[256]; + sprintf( index_str, "%ld", fgBucketGenIndex( &p ) ); + return string( index_str ); +} + +inline string +fgBucketGenBasePath( const fgBUCKET& p ) +{ + char base_path[256]; + fgBucketGenBasePath( &p, base_path ); + return string( base_path ); +} + +*/ + +inline ostream& +operator<< ( ostream& out, const FGBucket& b ) +{ + return out << b.lon << ":" << b.x << ", " << b.lat << ":" << b.y; +} + + +#endif // _NEWBUCKET_HXX + + +// $Log$ +// Revision 1.1 1999/02/08 23:52:16 curt +// Added a new "newbucket.[ch]xx" FGBucket class to replace the old +// fgBUCKET struct and C routines. This FGBucket class adjusts the tile +// width towards the poles to ensure the tiles are at least 8 miles wide. +// diff --git a/Bucket/testbucket.cxx b/Bucket/testbucket.cxx new file mode 100644 index 00000000..0ffbf5d1 --- /dev/null +++ b/Bucket/testbucket.cxx @@ -0,0 +1,32 @@ +// test new bucket routines + +#include "newbucket.cxx" + +main() { + double lat = 21.9625; + double lon = -110.0 + 0.0625; + + /* + while ( lon < 180 ) { + FGBucket b1( lon, lat ); + long int index = b1.gen_index(); + FGBucket b2( index ); + + cout << lon << "," << lat << " "; + cout << b2 << " " << b2.get_center_lon() << "," + << b2.get_center_lat() << endl; + + lon += 0.125; + } + */ + + FGBucket b1; + + for ( int j = 2; j >= -2; j-- ) { + for ( int i = -2; i < 3; i++ ) { + b1 = fgBucketOffset(lon, lat, i, j); + cout << "(" << i << "," << j << ")" << b1 << "\t"; + } + cout << endl; + } +}