Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_autoscl.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** 00002 * Qwt Widget Library 00003 * Copyright (C) 1997 Josef Wilgen 00004 * Copyright (C) 2002 Uwe Rathmann 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the Qwt License, Version 1.0 00008 *****************************************************************************/ 00009 00010 #include "qwt_math.h" 00011 #include "qwt_autoscl.h" 00012 00013 00014 static const double MinEps=1.0e-10; 00015 00017 QwtAutoScale::QwtAutoScale () 00018 { 00019 d_autoScale = TRUE; 00020 d_scaleOpt = None; 00021 00022 d_minValue = 0.0; 00023 d_maxValue = 0.0; 00024 d_scaleMin = 0.0; 00025 d_scaleMax = 0.0; 00026 d_loMargin = 0.0; 00027 d_hiMargin = 0.0; 00028 d_step = 0.0; 00029 d_maxMajor = 8; 00030 d_maxMinor = 5; 00031 d_reset = 1; 00032 d_autoRebuild = TRUE; 00033 } 00034 00035 00037 QwtAutoScale::~QwtAutoScale () 00038 { 00039 } 00040 00045 bool QwtAutoScale::autoScale() const 00046 { 00047 return d_autoScale; 00048 } 00049 00054 double QwtAutoScale::loMargin() const 00055 { 00056 return d_loMargin; 00057 } 00058 00063 double QwtAutoScale::hiMargin() const 00064 { 00065 return d_hiMargin; 00066 } 00067 00072 int QwtAutoScale::maxMajor() const 00073 { 00074 return d_maxMajor; 00075 } 00076 00081 int QwtAutoScale::maxMinor() const 00082 { 00083 return d_maxMinor; 00084 } 00085 00086 00100 void QwtAutoScale::adjust(double *x, int num, int reset) 00101 { 00102 if (d_reset || reset) 00103 d_minValue = d_maxValue = x[0]; 00104 00105 for (int i = 0; i < num; i++) 00106 { 00107 if (x[i] > d_maxValue) 00108 d_maxValue = x[i]; 00109 if (x[i] < d_minValue) 00110 d_minValue = x[i]; 00111 } 00112 d_reset = 0; 00113 00114 if (d_autoRebuild) 00115 build(); 00116 } 00117 00118 00131 void QwtAutoScale::adjust(const QwtArray<double> &x, int reset) 00132 { 00133 adjust(x.data(), x.size(), reset); 00134 } 00135 00136 00150 void QwtAutoScale::adjust(double vmin, double vmax, int reset) 00151 { 00152 double mxv = qwtMax(vmin,vmax); 00153 double mnv = qwtMin(vmin,vmax); 00154 00155 if (d_reset || reset) 00156 { 00157 d_minValue = mnv; 00158 d_maxValue = mxv; 00159 } 00160 else 00161 { 00162 if (d_minValue > mnv) 00163 d_minValue = mnv; 00164 if (d_maxValue < mxv) 00165 d_maxValue = mxv; 00166 } 00167 d_reset = 0; 00168 00169 if (d_autoRebuild) 00170 build(); 00171 } 00172 00176 void QwtAutoScale::build() 00177 { 00178 if (d_reset) 00179 return; 00180 00181 if (d_autoScale) 00182 { 00183 if (d_scaleOpt & Logarithmic) 00184 buildLogScale(); 00185 else 00186 buildLinScale(); 00187 } 00188 else 00189 { 00190 double start, stop, step; 00191 if (d_scaleOpt & Inverted) 00192 { 00193 start = d_scaleMax; 00194 stop = d_scaleMin; 00195 step = -d_step; 00196 } 00197 else 00198 { 00199 start = d_scaleMin; 00200 stop = d_scaleMax; 00201 step = d_step; 00202 } 00203 00204 d_scldiv.rebuild(start, stop, d_maxMajor, d_maxMinor, 00205 bool(d_scaleOpt & Logarithmic), step, FALSE); 00206 } 00207 } 00208 00209 00213 void QwtAutoScale::buildLinScale () 00214 { 00215 double delta; 00216 const double ticks = double (d_maxMajor); 00217 00218 // 00219 // If in Autoscale Mode, adjust minval and maxval according to 00220 // the active scale options, and add the margins 00221 // 00222 if (!d_autoScale) 00223 return; 00224 00225 double minval = d_minValue; // scale boundaries are based on the 00226 double maxval = d_maxValue; // data. 00227 00228 // 00229 // add / subtract margins 00230 // 00231 if (d_loMargin > 0.0) 00232 minval -= d_loMargin; 00233 if (d_hiMargin > 0.0) 00234 maxval += d_hiMargin; 00235 00236 // 00237 // Correct minval / maxval according to the scale options 00238 // 00239 if (d_scaleOpt & Symmetric) 00240 { 00241 delta = qwtMax(qwtAbs(d_ref - maxval), qwtAbs(d_ref - minval)); 00242 maxval = d_ref + delta; 00243 minval = d_ref - delta; 00244 } 00245 else if (d_scaleOpt & IncludeRef) 00246 { 00247 if (maxval < d_ref) 00248 maxval = d_ref; 00249 else if (minval > d_ref) 00250 minval = d_ref; 00251 } 00252 00253 // 00254 // first approximation of d_scaleMin and d_scaleMax 00255 // 00256 setRange(minval, maxval); 00257 delta = d_scaleMax - d_scaleMin; 00258 00259 00260 // dec := maximal power of ten which fits into the interval 00261 // [d_scaleMin,d_scaleMax] 00262 const double dec = pow (10.0, floor (log10 (delta))); 00263 00264 // 00265 // The following magic line calculates the step size such that 00266 // - The number of subintervals will not exceed the maximum 00267 // as specified by the user 00268 // - The step size fits {1,2,5}*10^n with a natural number n 00269 // 00270 double step = qwtCeil125(delta * 0.999999 / dec / ticks) * dec; 00271 00272 // 00273 // determine he final values of scaleMin and scaleMax 00274 // 00275 if (! (d_scaleOpt & Floating) ) 00276 { 00277 // adjust of d_scaleMin and d_scaleMax such that both are integer 00278 // multiples of the step size. 00279 d_scaleMin = step * floor ((d_scaleMin + MinEps * step) / step); 00280 d_scaleMax = step * ceil ((d_scaleMax - MinEps * step) / step); 00281 } 00282 00283 if (d_scaleOpt & Inverted) 00284 { 00285 step = -step; 00286 d_scldiv.rebuild(d_scaleMax, d_scaleMin, d_maxMajor, d_maxMinor, 00287 FALSE, step, FALSE); 00288 } 00289 else 00290 { 00291 d_scldiv.rebuild(d_scaleMin, d_scaleMax, d_maxMajor, d_maxMinor, 00292 FALSE, step, TRUE); 00293 } 00294 } 00295 00296 00300 void QwtAutoScale::buildLogScale () 00301 { 00302 if (!d_autoScale) 00303 return; 00304 00305 double minval = d_minValue; // the calculation of scale divisions 00306 double maxval = d_maxValue; // is based on the input data. 00307 00308 if (d_loMargin > 0.0) 00309 minval /= pow(10.0, d_loMargin); 00310 if (d_hiMargin > 0.0) 00311 maxval *= pow(10.0, d_hiMargin); 00312 00313 if (d_scaleOpt & Symmetric) 00314 { 00315 const double delta = qwtMax(maxval / d_lref, d_lref / minval); 00316 maxval = d_lref * delta; 00317 minval = d_lref / delta; 00318 } 00319 else if (d_scaleOpt & IncludeRef) 00320 { 00321 if (maxval < d_lref) 00322 maxval = d_lref; 00323 else if (minval > d_lref) 00324 minval = d_lref; 00325 } 00326 00327 const double ticks = (d_maxMajor > 0) ? double(d_maxMajor) : 1; 00328 00329 setRange(minval, maxval); 00330 00331 // decades included in the interval 00332 const double decades = qwtAbs(log10 (d_scaleMax / d_scaleMin)); 00333 00334 // calculate step size in decades 00335 00336 double step; 00337 if ((decades > 1.0) && (decades > ticks)) 00338 { 00339 double ipart; 00340 // One interval contains more than one decade. 00341 // The number of decades in an interval is adjusted 00342 // to be a multiple of 2,3,5, or 10. 00343 double fpart = modf (log10 (ceil (decades * 0.999999 / ticks)), &ipart); 00344 if (fpart < MinEps) 00345 fpart = 1.0; 00346 else if ((fpart - LOG10_2) < MinEps) 00347 fpart = 2.0; 00348 else if ((fpart - LOG10_3) < MinEps) 00349 fpart = 3.0; 00350 else if ((fpart - LOG10_5) < MinEps) 00351 fpart = 5.0; 00352 else 00353 fpart = 10.0; 00354 00355 step = pow (10.0, ipart) * fpart; 00356 00357 } 00358 else // The minimal step size is one decade. 00359 { 00360 step = 1.0; 00361 } 00362 00363 if (!(d_scaleOpt & Floating)) 00364 { 00365 d_scaleMin = pow (10.0, step * 00366 floor ((log10(d_scaleMin) + MinEps * step) / step)); 00367 d_scaleMax = pow (10.0, step * 00368 ceil ((log10(d_scaleMax) - MinEps * step) / step)); 00369 } 00370 00371 if (d_scaleOpt & Inverted) 00372 { 00373 step = -step; 00374 d_scldiv.rebuild(d_scaleMax, d_scaleMin, d_maxMajor, d_maxMinor, TRUE, 00375 step, FALSE); 00376 } 00377 else 00378 { 00379 d_scldiv.rebuild(d_scaleMin, d_scaleMax, d_maxMajor, d_maxMinor, 00380 TRUE, step, TRUE); 00381 } 00382 } 00383 00391 void QwtAutoScale::changeOptions(int opt, bool tf) 00392 { 00393 if (tf) 00394 d_scaleOpt |= opt; 00395 else 00396 d_scaleOpt &= (~opt); 00397 build(); 00398 } 00399 00400 00413 void QwtAutoScale::reset() 00414 { 00415 d_reset = TRUE; 00416 d_scldiv.reset(); 00417 d_minValue = 0; 00418 d_maxValue = 0; 00419 d_step = 0; 00420 } 00421 00422 00439 void QwtAutoScale::setAutoScale() 00440 { 00441 d_autoScale = TRUE; 00442 build(); 00443 } 00444 00461 void QwtAutoScale::setMargins(double mlo, double mhi) 00462 { 00463 d_loMargin = qwtMax(mlo,0.0); 00464 d_hiMargin = qwtMax(mhi,0.0); 00465 build(); 00466 } 00467 00468 00477 void QwtAutoScale::setMaxMajor(int mx) 00478 { 00479 d_maxMajor = qwtMax(mx,1); 00480 d_maxMajor = qwtMin(mx, 10000); 00481 build(); 00482 } 00483 00489 void QwtAutoScale::setMaxMinor(int mx) 00490 { 00491 d_maxMinor = qwtMin(qwtMax(mx,0), 100); 00492 build(); 00493 } 00494 00495 00510 void QwtAutoScale::setRange(double x1, double x2) 00511 { 00512 double minval = qwtMin(x1, x2); 00513 double maxval = qwtMax(x1, x2); 00514 00515 if (d_scaleOpt & Logarithmic) 00516 { 00517 minval = qwtMin(qwtMax(minval, LOG_MIN), LOG_MAX); 00518 maxval = qwtMin(qwtMax(maxval, LOG_MIN), LOG_MAX); 00519 } 00520 00521 double delta = maxval - minval; 00522 00523 if (delta <= 0.0) // all values are equal 00524 { 00525 if (minval > 0) 00526 { 00527 d_scaleMin = minval * 0.5; 00528 d_scaleMax = maxval * 1.5; 00529 } 00530 else if (minval < 0) 00531 { 00532 d_scaleMin = minval * 1.5; 00533 d_scaleMax = maxval * 0.5; 00534 } 00535 else // all values are zero 00536 { 00537 d_scaleMin = -0.5; 00538 d_scaleMax = 0.5; 00539 } 00540 00541 delta = d_scaleMax - d_scaleMin; 00542 } 00543 else // the normal case 00544 { 00545 d_scaleMin = minval; 00546 d_scaleMax = maxval; 00547 } 00548 } 00549 00576 void QwtAutoScale::setScale(double xmin, double xmax, double step) 00577 { 00578 // turn auto-scaling off and set the 00579 // scale limits to the desired values 00580 setRange(xmin,xmax); 00581 d_autoScale = FALSE; 00582 d_step = step; 00583 00584 build(); // rebuild the scale 00585 } 00586 00587 00649 void QwtAutoScale::setOptions(int opt) 00650 { 00651 d_scaleOpt = opt; 00652 build(); 00653 } 00654 00655 00670 void QwtAutoScale::setReference(double r) 00671 { 00672 d_ref = r; 00673 00674 if (r > LOG_MIN / 2) 00675 d_lref = qwtMin(r, LOG_MAX / 2); 00676 else 00677 d_lref = 1.0; 00678 00679 build(); 00680 } 00681 00686 double QwtAutoScale::reference() const 00687 { 00688 return d_ref; 00689 } 00690 00691 00697 bool QwtAutoScale::option(int opt) const 00698 { 00699 return bool(d_scaleOpt & opt); 00700 } 00701 00707 int QwtAutoScale::options() const 00708 { 00709 return d_scaleOpt; 00710 } 00711 00720 const QwtScaleDiv &QwtAutoScale::scaleDiv() const 00721 { 00722 return d_scldiv; 00723 } 00724 00730 void QwtAutoScale::setAutoRebuild(bool tf) 00731 { 00732 d_autoRebuild = tf; 00733 } 00734 00739 bool QwtAutoScale::autoRebuild() const 00740 { 00741 return d_autoRebuild; 00742 }

Generated on Tue Nov 16 21:12:20 2004 for Qwt User's Guide by doxygen 1.3.8