head 1.4; access; symbols; locks; strict; comment @# @; 1.4 date 2002.09.07.01.50.38; author curt; state Exp; branches; next 1.3; 1.3 date 2002.08.31.19.01.55; author curt; state Exp; branches; next 1.2; 1.2 date 2002.08.31.18.54.02; author curt; state Exp; branches; next 1.1; 1.1 date 2002.02.15.17.21.58; author curt; state Exp; branches; next ; desc @@ 1.4 log @Updated doxygen docs. @ text @
Main Page Class Hierarchy Compound List File List Compound Members File Members

# newbucket.cxx

    00001 /**************************************************************************
    00002  * newbucket.hxx -- new bucket routines for better world modeling
    00003  *
    00004  * Written by Curtis L. Olson, started February 1999.
    00005  *
    00006  * Copyright (C) 1999  Curtis L. Olson - curt@@flightgear.org
    00007  *
    00008  * This library is free software; you can redistribute it and/or
    00009  * modify it under the terms of the GNU Library General Public
    00010  * License as published by the Free Software Foundation; either
    00011  * version 2 of the License, or (at your option) any later version.
    00012  *
    00013  * This library is distributed in the hope that it will be useful,
    00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016  * Library General Public License for more details.
    00017  *
    00018  * You should have received a copy of the GNU Library General Public
    00019  * License along with this library; if not, write to the
    00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00021  * Boston, MA  02111-1307, USA.
    00022  *
    00023  * $Id: newbucket.cxx,v 1.11 2001/05/15 19:26:23 curt Exp $
    00024  **************************************************************************/
    00025
    00026
    00027 #include <math.h>
    00028
    00029 #include <simgear/misc/sg_path.hxx>
    00030
    00031 #include "newbucket.hxx"
    00032
    00033
    00034 // default constructor
    00035 SGBucket::SGBucket() {
    00036 }
    00037
    00038
    00039 // constructor for specified location
    00040 SGBucket::SGBucket(const double dlon, const double dlat) {
    00041     set_bucket(dlon, dlat);
    00042 }
    00043
    00044
    00045 // create an impossible bucket if false
    00046 SGBucket::SGBucket(const bool is_good) {
    00047     set_bucket(0.0, 0.0);
    00048     if ( !is_good ) {
    00049         lon = -1000;
    00050     }
    00051 }
    00052
    00053
    00054 // Parse a unique scenery tile index and find the lon, lat, x, and y
    00055 SGBucket::SGBucket(const long int bindex) {
    00056     long int index = bindex;
    00057
    00058     lon = index >> 14;
    00059     index -= lon << 14;
    00060     lon -= 180;
    00061
    00062     lat = index >> 6;
    00063     index -= lat << 6;
    00064     lat -= 90;
    00065
    00066     y = index >> 3;
    00067     index -= y << 3;
    00068
    00069     x = index;
    00070 }
    00071
    00072
    00073 // default destructor
    00074 SGBucket::~SGBucket() {
    00075 }
    00076
    00077
    00078 // Set the bucket params for the specified lat and lon
    00079 void SGBucket::set_bucket( double *lonlat ) {
    00080     set_bucket( lonlat[0], lonlat[1] );
    00081 }
    00082
    00083
    00084 // Set the bucket params for the specified lat and lon
    00085 void SGBucket::set_bucket( double dlon, double dlat ) {
    00086     //
    00087     // latitude first
    00088     //
    00089     double span = sg_bucket_span( dlat );
    00090     double diff = dlon - (double)(int)dlon;
    00091
    00092     // cout << "diff = " << diff << "  span = " << span << endl;
    00093
    00094     if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
    00095         lon = (int)dlon;
    00096     } else {
    00097         lon = (int)dlon - 1;
    00098     }
    00099
    00100     // find subdivision or super lon if needed
    00101     if ( span < SG_EPSILON ) {
    00102         // polar cap
    00103         lon = 0;
    00104         x = 0;
    00105     } else if ( span <= 1.0 ) {
    00106         x = (int)((dlon - lon) / span);
    00107     } else {
    00108         if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
    00109             lon = (int)( (int)(lon / span) * span);
    00110         } else {
    00111             // cout << " lon = " << lon
    00112             //  << "  tmp = " << (int)((lon-1) / span) << endl;
    00113             lon = (int)( (int)((lon + 1) / span) * span - span);
    00114             if ( lon < -180 ) {
    00115                 lon = -180;
    00116             }
    00117         }
    00118         x = 0;
    00119     }
    00120
    00121     //
    00122     // then latitude
    00123     //
    00124     diff = dlat - (double)(int)dlat;
    00125
    00126     if ( (dlat >= 0) || (fabs(diff) < SG_EPSILON) ) {
    00127         lat = (int)dlat;
    00128     } else {
    00129         lat = (int)dlat - 1;
    00130     }
    00131     y = (int)((dlat - lat) * 8);
    00132 }
    00133
    00134
    00135 // Build the path name for this bucket
    00136 string SGBucket::gen_base_path() const {
    00137     // long int index;
    00138     int top_lon, top_lat, main_lon, main_lat;
    00139     char hem, pole;
    00140     char raw_path[256];
    00141
    00142     top_lon = lon / 10;
    00143     main_lon = lon;
    00144     if ( (lon < 0) && (top_lon * 10 != lon) ) {
    00145         top_lon -= 1;
    00146     }
    00147     top_lon *= 10;
    00148     if ( top_lon >= 0 ) {
    00149         hem = 'e';
    00150     } else {
    00151         hem = 'w';
    00152         top_lon *= -1;
    00153     }
    00154     if ( main_lon < 0 ) {
    00155         main_lon *= -1;
    00156     }
    00157
    00158     top_lat = lat / 10;
    00159     main_lat = lat;
    00160     if ( (lat < 0) && (top_lat * 10 != lat) ) {
    00161         top_lat -= 1;
    00162     }
    00163     top_lat *= 10;
    00164     if ( top_lat >= 0 ) {
    00165         pole = 'n';
    00166     } else {
    00167         pole = 's';
    00168         top_lat *= -1;
    00169     }
    00170     if ( main_lat < 0 ) {
    00171         main_lat *= -1;
    00172     }
    00173
    00174     sprintf(raw_path, "%c%03d%c%02d/%c%03d%c%02d",
    00175             hem, top_lon, pole, top_lat,
    00176             hem, main_lon, pole, main_lat);
    00177
    00178     SGPath path( raw_path );
    00179
    00180     return path.str();
    00181 }
    00182
    00183
    00184 // return width of the tile in degrees
    00185 double SGBucket::get_width() const {
    00186     return sg_bucket_span( get_center_lat() );
    00187 }
    00188
    00189
    00190 // return height of the tile in degrees
    00191 double SGBucket::get_height() const {
    00192     return SG_BUCKET_SPAN;
    00193 }
    00194
    00195
    00196 // return width of the tile in meters
    00197 double SGBucket::get_width_m() const {
    00198     double clat = (int)get_center_lat();
    00199     if ( clat > 0 ) {
    00200         clat = (int)clat + 0.5;
    00201     } else {
    00202         clat = (int)clat - 0.5;
    00203     }
    00204     double clat_rad = clat * SGD_DEGREES_TO_RADIANS;
    00205     double cos_lat = cos( clat_rad );
    00206     double local_radius = cos_lat * SG_EQUATORIAL_RADIUS_M;
    00207     double local_perimeter = 2.0 * local_radius * SGD_PI;
    00208     double degree_width = local_perimeter / 360.0;
    00209
    00210     return sg_bucket_span( get_center_lat() ) * degree_width;
    00211 }
    00212
    00213
    00214 // return height of the tile in meters
    00215 double SGBucket::get_height_m() const {
    00216     double perimeter = 2.0 * SG_EQUATORIAL_RADIUS_M * SGD_PI;
    00217     double degree_height = perimeter / 360.0;
    00218
    00219     return SG_BUCKET_SPAN * degree_height;
    00220 }
    00221
    00222
    00223 // find the bucket which is offset by the specified tile units in the
    00224 // X & Y direction.  We need the current lon and lat to resolve
    00225 // ambiguities when going from a wider tile to a narrower one above or
    00226 // below.  This assumes that we are feeding in
    00227 SGBucket sgBucketOffset( double dlon, double dlat, int dx, int dy ) {
    00228     SGBucket result( dlon, dlat );
    00229     double clat = result.get_center_lat() + dy * SG_BUCKET_SPAN;
    00230
    00231     // walk dy units in the lat direction
    00232     result.set_bucket( dlon, clat );
    00233
    00234     // find the lon span for the new latitude
    00235     double span = sg_bucket_span( clat );
    00236
    00237     // walk dx units in the lon direction
    00238     double tmp = dlon + dx * span;
    00239     while ( tmp < -180.0 ) {
    00240         tmp += 360.0;
    00241     }
    00242     while ( tmp >= 180.0 ) {
    00243         tmp -= 360.0;
    00244     }
    00245     result.set_bucket( tmp, clat );
    00246
    00247     return result;
    00248 }
    00249
    00250
    00251 // calculate the offset between two buckets
    00252 void sgBucketDiff( const SGBucket& b1, const SGBucket& b2, int *dx, int *dy ) {
    00253
    00254     // Latitude difference
    00255     double c1_lat = b1.get_center_lat();
    00256     double c2_lat = b2.get_center_lat();
    00257     double diff_lat = c2_lat - c1_lat;
    00258
    00259 #ifdef HAVE_RINT
    00260     *dy = (int)rint( diff_lat / SG_BUCKET_SPAN );
    00261 #else
    00262     if ( diff_lat > 0 ) {
    00263         *dy = (int)( diff_lat / SG_BUCKET_SPAN + 0.5 );
    00264     } else {
    00265         *dy = (int)( diff_lat / SG_BUCKET_SPAN - 0.5 );
    00266     }
    00267 #endif
    00268
    00269     // longitude difference
    00270     double c1_lon = b1.get_center_lon();
    00271     double c2_lon = b2.get_center_lon();
    00272     double diff_lon = c2_lon - c1_lon;
    00273     double span;
    00274     if ( sg_bucket_span(c1_lat) <= sg_bucket_span(c2_lat) ) {
    00275         span = sg_bucket_span(c1_lat);
    00276     } else {
    00277         span = sg_bucket_span(c2_lat);
    00278     }
    00279
    00280 #ifdef HAVE_RINT
    00281     *dx = (int)rint( diff_lon / span );
    00282 #else
    00283     if ( diff_lon > 0 ) {
    00284         *dx = (int)( diff_lon / span + 0.5 );
    00285     } else {
    00286         *dx = (int)( diff_lon / span - 0.5 );
    00287     }
    00288 #endif
    00289 }
    00290
    00291

@ 1.3 log @Oops, try again. @ text @d300 1 a300 1