00001
00012 #include "HammerAito.h"
00013
00014 #include "UnaryTransform.h"
00015
00016 #include "axes/AxisModelBase.h"
00017 #include "axes/AxisTick.h"
00018 #include "graphics/Rectangle.h"
00019
00020 #include <cmath>
00021 #include <cstdio>
00022
00023 #include <cassert>
00024
00025 using namespace hippodraw;
00026
00027 using std::max;
00028 using std::abs;
00029 using std::vector;
00030
00031 HammerAito::HammerAito ( UnaryTransform * z )
00032 : PeriodicBinaryTransform ( z, true, true, false, true,
00033 -180.0, +180.0,
00034 - 90.0, + 90.0 )
00035 {
00036 m_name = "HammerAito";
00037 }
00038
00039 HammerAito::HammerAito ( const HammerAito & t )
00040 : PeriodicBinaryTransform ( t )
00041 {
00042 }
00043
00044 HammerAito::~HammerAito ()
00045 {
00046 }
00047
00048 #ifdef CLONE_DEFECT
00049 TransformBase * HammerAito::clone () const
00050 #else
00051 HammerAito * HammerAito::clone () const
00052 #endif
00053 {
00054 return new HammerAito ( *this );
00055 }
00056
00057 bool
00058 HammerAito::
00059 isLinearInXY () const
00060 {
00061 return false;
00062 }
00063
00064
00065 void
00066 HammerAito::
00067 transform ( double & lon, double & lat ) const
00068 {
00069
00070
00071
00072
00073 double lon_r_2 = M_PI * lon / 360.0;
00074 double lat_r = M_PI * lat / 180.0;
00075
00076
00077 double cos_lat = cos ( lat_r );
00078 double t = sqrt ( 2.0 / ( 1.0 + cos_lat * cos ( lon_r_2 ) ) );
00079
00080 lon = ( 180.0 / M_PI ) * 2.0 * t * cos_lat * sin ( lon_r_2 );
00081 lat = ( 180.0 / M_PI ) * t * sin ( lat_r );
00082 }
00083
00084 void
00085 HammerAito::
00086 inverseTransform ( double & lon, double & lat ) const
00087 {
00088
00089
00090
00091
00092 double lon_r = lon * M_PI / 180.0;
00093 double lat_r = lat * M_PI / 180.0;
00094
00095 double lon_q = 0.25 * lon_r;
00096 double lat_h = 0.50 * lat_r;
00097
00098
00099 double z = sqrt ( 1.0 - lon_q * lon_q - lat_h * lat_h );
00100
00101 lon = ( 180.0 / M_PI ) * 2.0 * atan ( ( z * lon_r ) /
00102 ( 4.0 * z * z - 2.0 ) );
00103 lat = ( 180.0 / M_PI ) * asin ( lat_r * z );
00104 }
00105
00106
00107 void
00108 HammerAito::
00109 transform ( std::vector< double > & lon,
00110 std::vector< double > & lat ) const
00111 {
00112 assert ( lat.size() == lon.size() );
00113
00114 std::vector < double >:: iterator it_lat = lat.begin ();
00115 std::vector < double >:: iterator it_lon = lon.begin ();
00116
00117 for ( ; it_lat != lat.end(); ++it_lat, ++it_lon ) {
00118 transform ( *it_lon, *it_lat );
00119 }
00120 }
00121
00122
00123 double HammerAito::aspectRatio () const
00124 {
00125 return 2.0;
00126 }
00127
00128 HippoRectangle HammerAito::calcRectangle ( const Range & lat,
00129 const Range & lon )
00130 {
00131 double x_lo = lat.low ();
00132 double x_hi = lat.high ();
00133
00134 double y_lo = lon.low ();
00135 double y_hi = lon.high ();
00136
00137 double x, y;
00138
00139 double x_min = 1000;
00140 double x_max = -1000;
00141 double y_min = 1000;
00142 double y_max = -1000;
00143
00144 int n = 50;
00145 double dx = ( x_hi - x_lo ) / n;
00146 double dy = ( y_hi - y_lo ) / n;
00147
00148
00149
00150 for ( int i = 0; i <= n; i++)
00151 {
00152 x = x_lo + i * dx;
00153 y = y_lo;
00154 transform ( x, y );
00155 x_min = ( x_min < x ) ? x_min : x;
00156 x_max = ( x_max > x ) ? x_max : x;
00157 y_min = ( y_min < y ) ? y_min : y;
00158 y_max = ( y_max > y ) ? y_max : y;
00159 }
00160
00161
00162 for ( int i = 0; i <= n; i++)
00163 {
00164 x = x_lo + i * dx;
00165 y = y_hi;
00166 transform ( x, y );
00167 x_min = ( x_min < x ) ? x_min : x;
00168 x_max = ( x_max > x ) ? x_max : x;
00169 y_min = ( y_min < y ) ? y_min : y;
00170 y_max = ( y_max > y ) ? y_max : y;
00171 }
00172
00173
00174 for ( int i = 0; i <= n; i++)
00175 {
00176 x = x_lo;
00177 y = y_lo + i * dy;
00178 transform ( x, y );
00179 x_min = ( x_min < x ) ? x_min : x;
00180 x_max = ( x_max > x ) ? x_max : x;
00181 y_min = ( y_min < y ) ? y_min : y;
00182 y_max = ( y_max > y ) ? y_max : y;
00183 }
00184
00185
00186 for ( int i = 0; i <= n; i++)
00187 {
00188 x = x_hi;
00189 y = y_lo + i * dy;
00190 transform ( x, y );
00191 x_min = ( x_min < x ) ? x_min : x;
00192 x_max = ( x_max > x ) ? x_max : x;
00193 y_min = ( y_min < y ) ? y_min : y;
00194 y_max = ( y_max > y ) ? y_max : y;
00195 }
00196
00197 return HippoRectangle ( x_min, y_min, x_max - x_min, y_max - y_min );
00198 }
00199
00200
00201
00202 void HammerAito::validate ( Range & lat, Range & lon ) const
00203 {
00204 if ( lat.low () < -180.0 ) lat.setLow ( -180.0 );
00205 if ( lat.high () > 180.0 ) lat.setHigh ( 180.0 );
00206
00207 if ( lon.low () < -90.0 ) lon.setLow ( -90.0 );
00208 if ( lon.high () > 90.0 ) lon.setHigh ( 90.0 );
00209 }
00210
00214 const vector < AxisTick > &
00215 HammerAito::
00216 setTicks ( AxisModelBase & model, hippodraw::Axes::Type axis )
00217 {
00218 if ( axis == Axes::Z ) {
00219 return m_z -> setTicks ( model );
00220 }
00221
00222 setTickStep ( model );
00223 setFirstTick ( model );
00224 return genTicks ( model, axis );
00225 }
00226
00228 void
00229 HammerAito::
00230 adjustValues ( AxisModelBase & model,
00231 hippodraw::Axes::Type,
00232 const Range & limit )
00233 {
00234
00235 return;
00236 }
00237
00238 inline double FLT_EQUAL( double x, double y )
00239 {
00240 return ( (double)abs( x - y ) <= 2.0 * ( y * FLT_EPSILON + FLT_MIN ) );
00241 }
00242
00243
00244 void HammerAito::setTickStep( AxisModelBase & axis )
00245 {
00246 const Range & range = axis.getRange(false);
00247 double rangeLength = range.length();
00248
00249 double scale_factor = axis.getScaleFactor();
00250 rangeLength *= scale_factor;
00251
00252
00253 double rmag = floor( log10( rangeLength ) );
00254 axis.setRMag( rmag );
00255
00256 double scalelow = range.low() * scale_factor;
00257 double scalehigh = range.high() * scale_factor;
00258
00259
00260 double pmag = max( floor( log10( abs ( scalehigh ) ) ),
00261 floor( log10( abs ( scalelow ) ) ) );
00262 axis.setPMag( pmag );
00263
00264 axis.setTickStep( rangeLength / 4.0 );
00265 }
00266
00267 void HammerAito::setFirstTick( AxisModelBase & axis )
00268 {
00269 const Range & range = axis.getRange(false);
00270
00271 axis.setFirstTick ( range.low() );
00272 }
00273
00274
00277 const vector < AxisTick > &
00278 HammerAito::
00279 genTicks( AxisModelBase & axis, hippodraw::Axes::Type axistype )
00280 {
00281 double y = 0.0, ylabel;
00282
00283 int num_ticks = 0;
00284 m_ticks.clear();
00285 double pmag = axis.getPMag();
00286 double rmag = axis.getRMag();
00287 double first_tick = axis.getFirstTick();
00288 double tick_step = axis.getTickStep();
00289 double scale_factor = axis.getScaleFactor();
00290
00291
00292
00293
00294
00295
00296 bool use_pmag = abs ( pmag ) > 3.0;
00297
00298 axis.setUsePMag ( use_pmag );
00299
00300 char pstr[10];
00301 char labl[10];
00302
00303 int decimals = 0;
00304
00305
00306
00307
00308
00309 if ( use_pmag ) {
00310
00311
00312
00313
00314 decimals = static_cast<int>( pmag - rmag );
00315
00316
00317 if( !decimals ) decimals++;
00318
00319 } else {
00320
00321 if( rmag > 0.0 ){
00322
00323
00324
00325
00326 decimals = 0;
00327
00328 } else {
00329
00330
00331
00332
00333
00334 decimals = static_cast<int>( abs( rmag ) );
00335
00336 }
00337
00338 }
00339
00340
00341
00342 if (decimals < 0)
00343 decimals = 0;
00344
00345 sprintf( pstr, "%%1.%df", decimals );
00346
00347 y = first_tick;
00348 const Range & range = axis.getRange(false);
00349 double range_high = range.high();
00350 range_high *= scale_factor;
00351
00352 while( y <= range_high || FLT_EQUAL( range_high, y ) )
00353 {
00354 double value = 0.0;
00355
00356 if ( axistype == Axes::X ) {
00357 value = moduloAddX( y, xOffset() );
00358 }
00359 else if ( axistype == Axes::Y ) {
00360 value = moduloAddY( y, yOffset() );
00361 }
00362
00363
00364
00365
00366 if ( use_pmag ) ylabel = value / pow( 10.0, pmag );
00367 else ylabel = value;
00368
00369 value /= scale_factor;
00370 sprintf( labl, pstr, ylabel );
00371 m_ticks.push_back( AxisTick ( y, labl ) );
00372
00373 num_ticks++;
00374 if ( tick_step == 0.0 ) break;
00375 y += tick_step;
00376
00377 }
00378
00379 return m_ticks;
00380 }