00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <simgear_config.h>
00028 #endif
00029
00030 #include <math.h>
00031
00032 #include <simgear/misc/sg_path.hxx>
00033
00034 #include "newbucket.hxx"
00035
00036
00037
00038 SGBucket::SGBucket() {
00039 }
00040
00041
00042
00043 SGBucket::SGBucket(const double dlon, const double dlat) {
00044 set_bucket(dlon, dlat);
00045 }
00046
00047 SGBucket::SGBucket(const SGGeod& geod) {
00048 set_bucket(geod);
00049 }
00050
00051
00052 SGBucket::SGBucket(const bool is_good) {
00053 set_bucket(0.0, 0.0);
00054 if ( !is_good ) {
00055 lon = -1000;
00056 }
00057 }
00058
00059
00060
00061 SGBucket::SGBucket(const long int bindex) {
00062 long int index = bindex;
00063
00064 lon = index >> 14;
00065 index -= lon << 14;
00066 lon -= 180;
00067
00068 lat = index >> 6;
00069 index -= lat << 6;
00070 lat -= 90;
00071
00072 y = index >> 3;
00073 index -= y << 3;
00074
00075 x = index;
00076 }
00077
00078
00079
00080 void SGBucket::set_bucket( double *lonlat ) {
00081 set_bucket( lonlat[0], lonlat[1] );
00082 }
00083
00084
00085
00086 void SGBucket::set_bucket( double dlon, double dlat ) {
00087
00088
00089
00090 double span = sg_bucket_span( dlat );
00091 double diff = dlon - (double)(int)dlon;
00092
00093
00094
00095 if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
00096 lon = (int)dlon;
00097 } else {
00098 lon = (int)dlon - 1;
00099 }
00100
00101
00102 if ( span < SG_EPSILON ) {
00103
00104 lon = 0;
00105 x = 0;
00106 } else if ( span <= 1.0 ) {
00107 x = (int)((dlon - lon) / span);
00108 } else {
00109 if ( dlon >= 0 ) {
00110 lon = (int)( (int)(lon / span) * span);
00111 } else {
00112
00113
00114 lon = (int)( (int)((lon + 1) / span) * span - span);
00115 if ( lon < -180 ) {
00116 lon = -180;
00117 }
00118 }
00119 x = 0;
00120 }
00121
00122
00123
00124
00125 diff = dlat - (double)(int)dlat;
00126
00127 if ( (dlat >= 0) || (fabs(diff) < SG_EPSILON) ) {
00128 lat = (int)dlat;
00129 } else {
00130 lat = (int)dlat - 1;
00131 }
00132 y = (int)((dlat - lat) * 8);
00133 }
00134
00135
00136 void SGBucket::set_bucket(const SGGeod& geod)
00137 {
00138 set_bucket(geod.getLongitudeDeg(), geod.getLatitudeDeg());
00139 }
00140
00141
00142 string SGBucket::gen_base_path() const {
00143
00144 int top_lon, top_lat, main_lon, main_lat;
00145 char hem, pole;
00146 char raw_path[256];
00147
00148 top_lon = lon / 10;
00149 main_lon = lon;
00150 if ( (lon < 0) && (top_lon * 10 != lon) ) {
00151 top_lon -= 1;
00152 }
00153 top_lon *= 10;
00154 if ( top_lon >= 0 ) {
00155 hem = 'e';
00156 } else {
00157 hem = 'w';
00158 top_lon *= -1;
00159 }
00160 if ( main_lon < 0 ) {
00161 main_lon *= -1;
00162 }
00163
00164 top_lat = lat / 10;
00165 main_lat = lat;
00166 if ( (lat < 0) && (top_lat * 10 != lat) ) {
00167 top_lat -= 1;
00168 }
00169 top_lat *= 10;
00170 if ( top_lat >= 0 ) {
00171 pole = 'n';
00172 } else {
00173 pole = 's';
00174 top_lat *= -1;
00175 }
00176 if ( main_lat < 0 ) {
00177 main_lat *= -1;
00178 }
00179
00180 sprintf(raw_path, "%c%03d%c%02d/%c%03d%c%02d",
00181 hem, top_lon, pole, top_lat,
00182 hem, main_lon, pole, main_lat);
00183
00184 SGPath path( raw_path );
00185
00186 return path.str();
00187 }
00188
00189
00190
00191 double SGBucket::get_width() const {
00192 return sg_bucket_span( get_center_lat() );
00193 }
00194
00195
00196
00197 double SGBucket::get_height() const {
00198 return SG_BUCKET_SPAN;
00199 }
00200
00201
00202
00203 double SGBucket::get_width_m() const {
00204 double clat = (int)get_center_lat();
00205 if ( clat > 0 ) {
00206 clat = (int)clat + 0.5;
00207 } else {
00208 clat = (int)clat - 0.5;
00209 }
00210 double clat_rad = clat * SGD_DEGREES_TO_RADIANS;
00211 double cos_lat = cos( clat_rad );
00212 double local_radius = cos_lat * SG_EQUATORIAL_RADIUS_M;
00213 double local_perimeter = local_radius * SGD_2PI;
00214 double degree_width = local_perimeter / 360.0;
00215
00216 return sg_bucket_span( get_center_lat() ) * degree_width;
00217 }
00218
00219
00220
00221 double SGBucket::get_height_m() const {
00222 double perimeter = SG_EQUATORIAL_RADIUS_M * SGD_2PI;
00223 double degree_height = perimeter / 360.0;
00224
00225 return SG_BUCKET_SPAN * degree_height;
00226 }
00227
00228
00229
00230
00231
00232
00233 SGBucket sgBucketOffset( double dlon, double dlat, int dx, int dy ) {
00234 SGBucket result( dlon, dlat );
00235 double clat = result.get_center_lat() + dy * SG_BUCKET_SPAN;
00236
00237
00238 result.set_bucket( dlon, clat );
00239
00240
00241 double span = sg_bucket_span( clat );
00242
00243
00244 double tmp = dlon + dx * span;
00245 while ( tmp < -180.0 ) {
00246 tmp += 360.0;
00247 }
00248 while ( tmp >= 180.0 ) {
00249 tmp -= 360.0;
00250 }
00251 result.set_bucket( tmp, clat );
00252
00253 return result;
00254 }
00255
00256
00257
00258 void sgBucketDiff( const SGBucket& b1, const SGBucket& b2, int *dx, int *dy ) {
00259
00260
00261 double c1_lat = b1.get_center_lat();
00262 double c2_lat = b2.get_center_lat();
00263 double diff_lat = c2_lat - c1_lat;
00264
00265 #ifdef HAVE_RINT
00266 *dy = (int)rint( diff_lat / SG_BUCKET_SPAN );
00267 #else
00268 if ( diff_lat > 0 ) {
00269 *dy = (int)( diff_lat / SG_BUCKET_SPAN + 0.5 );
00270 } else {
00271 *dy = (int)( diff_lat / SG_BUCKET_SPAN - 0.5 );
00272 }
00273 #endif
00274
00275
00276 double diff_lon=0.0;
00277 double span=0.0;
00278
00279 SGBucket tmp_bucket;
00280
00281
00282
00283 if ( sg_bucket_span(c1_lat) <= sg_bucket_span(c2_lat) )
00284 {
00285 span = sg_bucket_span(c1_lat);
00286 } else {
00287 span = sg_bucket_span(c2_lat);
00288 }
00289
00290 diff_lon = b2.get_center_lon() - b1.get_center_lon();
00291
00292 if (diff_lon <0.0)
00293 {
00294 diff_lon -= b1.get_width()*0.5 + b2.get_width()*0.5 - span;
00295 }
00296 else
00297 {
00298 diff_lon += b1.get_width()*0.5 + b2.get_width()*0.5 - span;
00299 }
00300
00301
00302 #ifdef HAVE_RINT
00303 *dx = (int)rint( diff_lon / span );
00304 #else
00305 if ( diff_lon > 0 ) {
00306 *dx = (int)( diff_lon / span + 0.5 );
00307 } else {
00308 *dx = (int)( diff_lon / span - 0.5 );
00309 }
00310 #endif
00311 }
00312
00313