# qwt_double_range.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 <cfloat>
    00011 #include "qwt_double_range.h"
    00012 #include "qwt_math.h"
    00013
    00014 static double MinRelStep = 1.0e-10;
    00015 static double DefaultRelStep = 1.0e-2;
    00016 static double MinEps = 1.0e-10;
    00017
    00022 QwtDoubleRange::QwtDoubleRange():
    00023     d_minValue(0.0),
    00024     d_maxValue(0.0),
    00025     d_step(1.0),
    00026     d_pageSize(1),
    00027     d_isValid(false),
    00028     d_value(0.0),
    00029     d_exactValue(0.0),
    00030     d_exactPrevValue(0.0),
    00031     d_prevValue(0.0),
    00032     d_periodic(false)
    00033 {
    00034 }
    00035
    00037 QwtDoubleRange::~QwtDoubleRange()
    00038 {
    00039 }
    00040
    00042 void QwtDoubleRange::setValid(bool isValid)
    00043 {
    00044     if ( isValid != d_isValid )
    00045     {
    00046         d_isValid = isValid;
    00047         valueChange();
    00048     }
    00049 }
    00050
    00052 bool QwtDoubleRange::isValid() const
    00053 {
    00054     return d_isValid;
    00055 }
    00056
    00065 void QwtDoubleRange::setNewValue(double x, bool align)
    00066 {
    00067     double vmin,vmax;
    00068
    00069     d_prevValue = d_value;
    00070
    00071     vmin = qwtMin(d_minValue, d_maxValue);
    00072     vmax = qwtMax(d_minValue, d_maxValue);
    00073
    00074     //
    00075     // Range check
    00076     //
    00077     if (x < vmin)
    00078     {
    00079         if ((d_periodic) && (vmin != vmax))
    00080            d_value = x + ::ceil( (vmin - x) / (vmax - vmin ) )
    00081               * (vmax - vmin);
    00082         else
    00083            d_value = vmin;
    00084     }
    00085     else if (x > vmax)
    00086     {
    00087         if ((d_periodic) && (vmin != vmax))
    00088            d_value = x - ::ceil( ( x - vmax) / (vmax - vmin ))
    00089               * (vmax - vmin);
    00090         else
    00091            d_value = vmax;
    00092     }
    00093     else
    00094        d_value = x;
    00095
    00096     d_exactPrevValue = d_exactValue;
    00097     d_exactValue = d_value;
    00098
    00099     // align to grid
    00100     if (align)
    00101     {
    00102         if (d_step != 0.0)
    00103         {
    00104            d_value = d_minValue +
    00105              qwtRound((d_value - d_minValue) / d_step) * d_step;
    00106         }
    00107         else
    00108             d_value = d_minValue;
    00109
    00110         // correct rounding error at the border
    00111         if (fabs(d_value - d_maxValue) < MinEps * qwtAbs(d_step))
    00112             d_value = d_maxValue;
    00113
    00114         // correct rounding error if value = 0
    00115         if (::fabs(d_value) < MinEps * qwtAbs(d_step))
    00116             d_value = 0.0;
    00117     }
    00118
    00119     if (!d_isValid || d_prevValue != d_value)
    00120     {
    00121         d_isValid = true;
    00122         valueChange();
    00123     }
    00124 }
    00125
    00135 void QwtDoubleRange::fitValue(double x)
    00136 {
    00137     setNewValue(x, true);
    00138 }
    00139
    00140
    00150 void QwtDoubleRange::setValue(double x)
    00151 {
    00152     setNewValue(x, false);
    00153 }
    00154
    00172 void QwtDoubleRange::setRange(double vmin, double vmax, double vstep, int pageSize)
    00173 {
    00174     bool rchg = ((d_maxValue != vmax) || (d_minValue != vmin));
    00175
    00176     if (rchg)
    00177     {
    00178         d_minValue = vmin;
    00179         d_maxValue = vmax;
    00180     }
    00181
    00182     //
    00183     // look if the step width has an acceptable
    00184     // value or otherwise change it.
    00185     //
    00186     setStep(vstep);
    00187
    00188     //
    00189     // limit page size
    00190     //
    00191     d_pageSize = qwtLim(pageSize,0,
    00192         int(qwtAbs((d_maxValue - d_minValue) / d_step)));
    00193
    00194     //
    00195     // If the value lies out of the range, it
    00196     // will be changed. Note that it will not be adjusted to
    00197     // the new step width.
    00198     setNewValue(d_value, false);
    00199
    00200     // call notifier after the step width has been
    00201     // adjusted.
    00202     if (rchg)
    00203        rangeChange();
    00204 }
    00205
    00211 void QwtDoubleRange::setStep(double vstep)
    00212 {
    00213     double intv = d_maxValue - d_minValue;
    00214
    00215     double newStep;
    00216     if (vstep == 0.0)
    00217        newStep = intv * DefaultRelStep;
    00218     else
    00219     {
    00220         if ((intv > 0) && (vstep < 0) || (intv < 0) && (vstep > 0))
    00221            newStep = -vstep;
    00222         else
    00223            newStep = vstep;
    00224
    00225         if ( fabs(newStep) < fabs(MinRelStep * intv) )
    00226            newStep = MinRelStep * intv;
    00227     }
    00228
    00229     if (newStep != d_step)
    00230     {
    00231         d_step = newStep;
    00232         stepChange();
    00233     }
    00234 }
    00235
    00236
    00251 void QwtDoubleRange::setPeriodic(bool tf)
    00252 {
    00253     d_periodic = tf;
    00254 }
    00255
    00262 void QwtDoubleRange::incValue(int nSteps)
    00263 {
    00264     if ( isValid() )
    00265         setNewValue(d_value + double(nSteps) * d_step, true);
    00266 }
    00267
    00274 void QwtDoubleRange::incPages(int nPages)
    00275 {
    00276     if ( isValid() )
    00277         setNewValue(d_value + double(nPages) * double(d_pageSize) * d_step, true);
    00278 }
    00279
    00286 void QwtDoubleRange::valueChange()
    00287 {
    00288 }
    00289
    00290
    00297 void QwtDoubleRange::rangeChange()
    00298 {
    00299 }
    00300
    00301
    00308 void QwtDoubleRange::stepChange()
    00309 {
    00310 }
    00311
    00316 double QwtDoubleRange::step() const
    00317 {
    00318     return qwtAbs(d_step);
    00319 }
    00320
    00329 double QwtDoubleRange::maxValue() const
    00330 {
    00331     return d_maxValue;
    00332 }
    00333
    00342 double QwtDoubleRange::minValue() const
    00343 {
    00344     return d_minValue;
    00345 }
    00346
    00351 bool QwtDoubleRange::periodic() const
    00352 {
    00353     return d_periodic;
    00354 }
    00355
    00357 int QwtDoubleRange::pageSize() const
    00358 {
    00359     return d_pageSize;
    00360 }
    00361
    00363 double QwtDoubleRange::value() const
    00364 {
    00365     return d_value;
    00366 }
    00367
    00377 double QwtDoubleRange::exactValue() const
    00378 {
    00379     return d_exactValue;
    00380 }
    00381
    00383 double QwtDoubleRange::exactPrevValue() const
    00384 {
    00385     return d_exactPrevValue;
    00386 }
    00387
    00389 double QwtDoubleRange::prevValue() const
    00390 {
    00391     return d_prevValue;
    00392 }