| 1 | /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 | 
|---|
| 2 |  * Qwt Widget Library
 | 
|---|
| 3 |  * Copyright (C) 1997   Josef Wilgen
 | 
|---|
| 4 |  * Copyright (C) 2002   Uwe Rathmann
 | 
|---|
| 5 |  *
 | 
|---|
| 6 |  * This library is free software; you can redistribute it and/or
 | 
|---|
| 7 |  * modify it under the terms of the Qwt License, Version 1.0
 | 
|---|
| 8 |  *****************************************************************************/
 | 
|---|
| 9 | 
 | 
|---|
| 10 | #include "qwt_interval.h"
 | 
|---|
| 11 | #include "qwt_math.h"
 | 
|---|
| 12 | #include <qalgorithms.h>
 | 
|---|
| 13 | 
 | 
|---|
| 14 | /*!
 | 
|---|
| 15 |    \brief Normalize the limits of the interval
 | 
|---|
| 16 | 
 | 
|---|
| 17 |    If maxValue() < minValue() the limits will be inverted.
 | 
|---|
| 18 |    \return Normalized interval
 | 
|---|
| 19 | 
 | 
|---|
| 20 |    \sa isValid(), inverted()
 | 
|---|
| 21 | */
 | 
|---|
| 22 | QwtInterval QwtInterval::normalized() const
 | 
|---|
| 23 | {
 | 
|---|
| 24 |     if ( d_minValue > d_maxValue )
 | 
|---|
| 25 |     {
 | 
|---|
| 26 |         return inverted();
 | 
|---|
| 27 |     }
 | 
|---|
| 28 |     if ( d_minValue == d_maxValue && d_borderFlags == ExcludeMinimum )
 | 
|---|
| 29 |     {
 | 
|---|
| 30 |         return inverted();
 | 
|---|
| 31 |     }
 | 
|---|
| 32 | 
 | 
|---|
| 33 |     return *this;
 | 
|---|
| 34 | }
 | 
|---|
| 35 | 
 | 
|---|
| 36 | /*!
 | 
|---|
| 37 |    Invert the limits of the interval
 | 
|---|
| 38 |    \return Inverted interval
 | 
|---|
| 39 |    \sa normalized()
 | 
|---|
| 40 | */
 | 
|---|
| 41 | QwtInterval QwtInterval::inverted() const
 | 
|---|
| 42 | {
 | 
|---|
| 43 |     BorderFlags borderFlags = IncludeBorders;
 | 
|---|
| 44 |     if ( d_borderFlags & ExcludeMinimum )
 | 
|---|
| 45 |         borderFlags |= ExcludeMaximum;
 | 
|---|
| 46 |     if ( d_borderFlags & ExcludeMaximum )
 | 
|---|
| 47 |         borderFlags |= ExcludeMinimum;
 | 
|---|
| 48 | 
 | 
|---|
| 49 |     return QwtInterval( d_maxValue, d_minValue, borderFlags );
 | 
|---|
| 50 | }
 | 
|---|
| 51 | 
 | 
|---|
| 52 | /*!
 | 
|---|
| 53 |   Test if a value is inside an interval
 | 
|---|
| 54 | 
 | 
|---|
| 55 |   \param value Value
 | 
|---|
| 56 |   \return true, if value >= minValue() && value <= maxValue()
 | 
|---|
| 57 | */
 | 
|---|
| 58 | bool QwtInterval::contains( double value ) const
 | 
|---|
| 59 | {
 | 
|---|
| 60 |     if ( !isValid() )
 | 
|---|
| 61 |         return false;
 | 
|---|
| 62 | 
 | 
|---|
| 63 |     if ( value < d_minValue || value > d_maxValue )
 | 
|---|
| 64 |         return false;
 | 
|---|
| 65 | 
 | 
|---|
| 66 |     if ( value == d_minValue && d_borderFlags & ExcludeMinimum )
 | 
|---|
| 67 |         return false;
 | 
|---|
| 68 | 
 | 
|---|
| 69 |     if ( value == d_maxValue && d_borderFlags & ExcludeMaximum )
 | 
|---|
| 70 |         return false;
 | 
|---|
| 71 | 
 | 
|---|
| 72 |     return true;
 | 
|---|
| 73 | }
 | 
|---|
| 74 | 
 | 
|---|
| 75 | //! Unite 2 intervals
 | 
|---|
| 76 | QwtInterval QwtInterval::unite( const QwtInterval &other ) const
 | 
|---|
| 77 | {
 | 
|---|
| 78 |     /*
 | 
|---|
| 79 |      If one of the intervals is invalid return the other one.
 | 
|---|
| 80 |      If both are invalid return an invalid default interval
 | 
|---|
| 81 |      */
 | 
|---|
| 82 |     if ( !isValid() )
 | 
|---|
| 83 |     {
 | 
|---|
| 84 |         if ( !other.isValid() )
 | 
|---|
| 85 |             return QwtInterval();
 | 
|---|
| 86 |         else
 | 
|---|
| 87 |             return other;
 | 
|---|
| 88 |     }
 | 
|---|
| 89 |     if ( !other.isValid() )
 | 
|---|
| 90 |         return *this;
 | 
|---|
| 91 | 
 | 
|---|
| 92 |     QwtInterval united;
 | 
|---|
| 93 |     BorderFlags flags = IncludeBorders;
 | 
|---|
| 94 | 
 | 
|---|
| 95 |     // minimum
 | 
|---|
| 96 |     if ( d_minValue < other.minValue() )
 | 
|---|
| 97 |     {
 | 
|---|
| 98 |         united.setMinValue( d_minValue );
 | 
|---|
| 99 |         flags &= d_borderFlags & ExcludeMinimum;
 | 
|---|
| 100 |     }
 | 
|---|
| 101 |     else if ( other.minValue() < d_minValue )
 | 
|---|
| 102 |     {
 | 
|---|
| 103 |         united.setMinValue( other.minValue() );
 | 
|---|
| 104 |         flags &= other.borderFlags() & ExcludeMinimum;
 | 
|---|
| 105 |     }
 | 
|---|
| 106 |     else // d_minValue == other.minValue()
 | 
|---|
| 107 |     {
 | 
|---|
| 108 |         united.setMinValue( d_minValue );
 | 
|---|
| 109 |         flags &= ( d_borderFlags & other.borderFlags() ) & ExcludeMinimum;
 | 
|---|
| 110 |     }
 | 
|---|
| 111 | 
 | 
|---|
| 112 |     // maximum
 | 
|---|
| 113 |     if ( d_maxValue > other.maxValue() )
 | 
|---|
| 114 |     {
 | 
|---|
| 115 |         united.setMaxValue( d_maxValue );
 | 
|---|
| 116 |         flags &= d_borderFlags & ExcludeMaximum;
 | 
|---|
| 117 |     }
 | 
|---|
| 118 |     else if ( other.maxValue() > d_maxValue )
 | 
|---|
| 119 |     {
 | 
|---|
| 120 |         united.setMaxValue( other.maxValue() );
 | 
|---|
| 121 |         flags &= other.borderFlags() & ExcludeMaximum;
 | 
|---|
| 122 |     }
 | 
|---|
| 123 |     else // d_maxValue == other.maxValue() )
 | 
|---|
| 124 |     {
 | 
|---|
| 125 |         united.setMaxValue( d_maxValue );
 | 
|---|
| 126 |         flags &= d_borderFlags & other.borderFlags() & ExcludeMaximum;
 | 
|---|
| 127 |     }
 | 
|---|
| 128 | 
 | 
|---|
| 129 |     united.setBorderFlags( flags );
 | 
|---|
| 130 |     return united;
 | 
|---|
| 131 | }
 | 
|---|
| 132 | 
 | 
|---|
| 133 | //! Intersect 2 intervals
 | 
|---|
| 134 | QwtInterval QwtInterval::intersect( const QwtInterval &other ) const
 | 
|---|
| 135 | {
 | 
|---|
| 136 |     if ( !other.isValid() || !isValid() )
 | 
|---|
| 137 |         return QwtInterval();
 | 
|---|
| 138 | 
 | 
|---|
| 139 |     QwtInterval i1 = *this;
 | 
|---|
| 140 |     QwtInterval i2 = other;
 | 
|---|
| 141 | 
 | 
|---|
| 142 |     // swap i1/i2, so that the minimum of i1
 | 
|---|
| 143 |     // is smaller then the minimum of i2
 | 
|---|
| 144 | 
 | 
|---|
| 145 |     if ( i1.minValue() > i2.minValue() )
 | 
|---|
| 146 |     {
 | 
|---|
| 147 |         qSwap( i1, i2 );
 | 
|---|
| 148 |     }
 | 
|---|
| 149 |     else if ( i1.minValue() == i2.minValue() )
 | 
|---|
| 150 |     {
 | 
|---|
| 151 |         if ( i1.borderFlags() & ExcludeMinimum )
 | 
|---|
| 152 |             qSwap( i1, i2 );
 | 
|---|
| 153 |     }
 | 
|---|
| 154 | 
 | 
|---|
| 155 |     if ( i1.maxValue() < i2.minValue() )
 | 
|---|
| 156 |     {
 | 
|---|
| 157 |         return QwtInterval();
 | 
|---|
| 158 |     }
 | 
|---|
| 159 | 
 | 
|---|
| 160 |     if ( i1.maxValue() == i2.minValue() )
 | 
|---|
| 161 |     {
 | 
|---|
| 162 |         if ( i1.borderFlags() & ExcludeMaximum ||
 | 
|---|
| 163 |             i2.borderFlags() & ExcludeMinimum )
 | 
|---|
| 164 |         {
 | 
|---|
| 165 |             return QwtInterval();
 | 
|---|
| 166 |         }
 | 
|---|
| 167 |     }
 | 
|---|
| 168 | 
 | 
|---|
| 169 |     QwtInterval intersected;
 | 
|---|
| 170 |     BorderFlags flags = IncludeBorders;
 | 
|---|
| 171 | 
 | 
|---|
| 172 |     intersected.setMinValue( i2.minValue() );
 | 
|---|
| 173 |     flags |= i2.borderFlags() & ExcludeMinimum;
 | 
|---|
| 174 | 
 | 
|---|
| 175 |     if ( i1.maxValue() < i2.maxValue() )
 | 
|---|
| 176 |     {
 | 
|---|
| 177 |         intersected.setMaxValue( i1.maxValue() );
 | 
|---|
| 178 |         flags |= i1.borderFlags() & ExcludeMaximum;
 | 
|---|
| 179 |     }
 | 
|---|
| 180 |     else if ( i2.maxValue() < i1.maxValue() )
 | 
|---|
| 181 |     {
 | 
|---|
| 182 |         intersected.setMaxValue( i2.maxValue() );
 | 
|---|
| 183 |         flags |= i2.borderFlags() & ExcludeMaximum;
 | 
|---|
| 184 |     }
 | 
|---|
| 185 |     else // i1.maxValue() == i2.maxValue()
 | 
|---|
| 186 |     {
 | 
|---|
| 187 |         intersected.setMaxValue( i1.maxValue() );
 | 
|---|
| 188 |         flags |= i1.borderFlags() & i2.borderFlags() & ExcludeMaximum;
 | 
|---|
| 189 |     }
 | 
|---|
| 190 | 
 | 
|---|
| 191 |     intersected.setBorderFlags( flags );
 | 
|---|
| 192 |     return intersected;
 | 
|---|
| 193 | }
 | 
|---|
| 194 | 
 | 
|---|
| 195 | //! Unites this interval with the given interval.
 | 
|---|
| 196 | QwtInterval& QwtInterval::operator|=( const QwtInterval & interval )
 | 
|---|
| 197 | {
 | 
|---|
| 198 |     *this = *this | interval;
 | 
|---|
| 199 |     return *this;
 | 
|---|
| 200 | }
 | 
|---|
| 201 | 
 | 
|---|
| 202 | //! Intersects this interval with the given interval.
 | 
|---|
| 203 | QwtInterval& QwtInterval::operator&=( const QwtInterval & interval )
 | 
|---|
| 204 | {
 | 
|---|
| 205 |     *this = *this & interval;
 | 
|---|
| 206 |     return *this;
 | 
|---|
| 207 | }
 | 
|---|
| 208 | 
 | 
|---|
| 209 | /*!
 | 
|---|
| 210 |    Test if two intervals overlap
 | 
|---|
| 211 | */
 | 
|---|
| 212 | bool QwtInterval::intersects( const QwtInterval &other ) const
 | 
|---|
| 213 | {
 | 
|---|
| 214 |     if ( !isValid() || !other.isValid() )
 | 
|---|
| 215 |         return false;
 | 
|---|
| 216 | 
 | 
|---|
| 217 |     QwtInterval i1 = *this;
 | 
|---|
| 218 |     QwtInterval i2 = other;
 | 
|---|
| 219 | 
 | 
|---|
| 220 |     // swap i1/i2, so that the minimum of i1
 | 
|---|
| 221 |     // is smaller then the minimum of i2
 | 
|---|
| 222 | 
 | 
|---|
| 223 |     if ( i1.minValue() > i2.minValue() )
 | 
|---|
| 224 |     {
 | 
|---|
| 225 |         qSwap( i1, i2 );
 | 
|---|
| 226 |     }
 | 
|---|
| 227 |     else if ( i1.minValue() == i2.minValue() &&
 | 
|---|
| 228 |               i1.borderFlags() & ExcludeMinimum )
 | 
|---|
| 229 |     {
 | 
|---|
| 230 |         qSwap( i1, i2 );
 | 
|---|
| 231 |     }
 | 
|---|
| 232 | 
 | 
|---|
| 233 |     if ( i1.maxValue() > i2.minValue() )
 | 
|---|
| 234 |     {
 | 
|---|
| 235 |         return true;
 | 
|---|
| 236 |     }
 | 
|---|
| 237 |     if ( i1.maxValue() == i2.minValue() )
 | 
|---|
| 238 |     {
 | 
|---|
| 239 |         return !( ( i1.borderFlags() & ExcludeMaximum ) ||
 | 
|---|
| 240 |             ( i2.borderFlags() & ExcludeMinimum ) );
 | 
|---|
| 241 |     }
 | 
|---|
| 242 |     return false;
 | 
|---|
| 243 | }
 | 
|---|
| 244 | 
 | 
|---|
| 245 | /*!
 | 
|---|
| 246 |    Adjust the limit that is closer to value, so that value becomes
 | 
|---|
| 247 |    the center of the interval.
 | 
|---|
| 248 | 
 | 
|---|
| 249 |    \param value Center
 | 
|---|
| 250 |    \return Interval with value as center
 | 
|---|
| 251 | */
 | 
|---|
| 252 | QwtInterval QwtInterval::symmetrize( double value ) const
 | 
|---|
| 253 | {
 | 
|---|
| 254 |     if ( !isValid() )
 | 
|---|
| 255 |         return *this;
 | 
|---|
| 256 | 
 | 
|---|
| 257 |     const double delta =
 | 
|---|
| 258 |         qMax( qAbs( value - d_maxValue ), qAbs( value - d_minValue ) );
 | 
|---|
| 259 | 
 | 
|---|
| 260 |     return QwtInterval( value - delta, value + delta );
 | 
|---|
| 261 | }
 | 
|---|
| 262 | 
 | 
|---|
| 263 | /*!
 | 
|---|
| 264 |    Limit the interval, keeping the border modes
 | 
|---|
| 265 | 
 | 
|---|
| 266 |    \param lowerBound Lower limit
 | 
|---|
| 267 |    \param upperBound Upper limit
 | 
|---|
| 268 | 
 | 
|---|
| 269 |    \return Limited interval
 | 
|---|
| 270 | */
 | 
|---|
| 271 | QwtInterval QwtInterval::limited( double lowerBound, double upperBound ) const
 | 
|---|
| 272 | {
 | 
|---|
| 273 |     if ( !isValid() || lowerBound > upperBound )
 | 
|---|
| 274 |         return QwtInterval();
 | 
|---|
| 275 | 
 | 
|---|
| 276 |     double minValue = qMax( d_minValue, lowerBound );
 | 
|---|
| 277 |     minValue = qMin( minValue, upperBound );
 | 
|---|
| 278 | 
 | 
|---|
| 279 |     double maxValue = qMax( d_maxValue, lowerBound );
 | 
|---|
| 280 |     maxValue = qMin( maxValue, upperBound );
 | 
|---|
| 281 | 
 | 
|---|
| 282 |     return QwtInterval( minValue, maxValue, d_borderFlags );
 | 
|---|
| 283 | }
 | 
|---|
| 284 | 
 | 
|---|
| 285 | /*!
 | 
|---|
| 286 |    Extend the interval
 | 
|---|
| 287 | 
 | 
|---|
| 288 |    If value is below minValue, value becomes the lower limit.
 | 
|---|
| 289 |    If value is above maxValue, value becomes the upper limit.
 | 
|---|
| 290 | 
 | 
|---|
| 291 |    extend has no effect for invalid intervals
 | 
|---|
| 292 | 
 | 
|---|
| 293 |    \param value Value
 | 
|---|
| 294 |    \sa isValid()
 | 
|---|
| 295 | */
 | 
|---|
| 296 | QwtInterval QwtInterval::extend( double value ) const
 | 
|---|
| 297 | {
 | 
|---|
| 298 |     if ( !isValid() )
 | 
|---|
| 299 |         return *this;
 | 
|---|
| 300 | 
 | 
|---|
| 301 |     return QwtInterval( qMin( value, d_minValue ),
 | 
|---|
| 302 |         qMax( value, d_maxValue ), d_borderFlags );
 | 
|---|
| 303 | }
 | 
|---|
| 304 | 
 | 
|---|
| 305 | /*!
 | 
|---|
| 306 |    Extend an interval
 | 
|---|
| 307 | 
 | 
|---|
| 308 |    \param value Value
 | 
|---|
| 309 |    \return Reference of the extended interval
 | 
|---|
| 310 | 
 | 
|---|
| 311 |    \sa extend()
 | 
|---|
| 312 | */
 | 
|---|
| 313 | QwtInterval& QwtInterval::operator|=( double value )
 | 
|---|
| 314 | {
 | 
|---|
| 315 |     *this = *this | value;
 | 
|---|
| 316 |     return *this;
 | 
|---|
| 317 | }
 | 
|---|
| 318 | 
 | 
|---|
| 319 | #ifndef QT_NO_DEBUG_STREAM
 | 
|---|
| 320 | 
 | 
|---|
| 321 | QDebug operator<<( QDebug debug, const QwtInterval &interval )
 | 
|---|
| 322 | {
 | 
|---|
| 323 |     const int flags = interval.borderFlags();
 | 
|---|
| 324 | 
 | 
|---|
| 325 |     debug.nospace() << "QwtInterval("
 | 
|---|
| 326 |         << ( ( flags & QwtInterval::ExcludeMinimum ) ? "]" : "[" )
 | 
|---|
| 327 |         << interval.minValue() << "," << interval.maxValue()
 | 
|---|
| 328 |         << ( ( flags & QwtInterval::ExcludeMaximum ) ? "[" : "]" )
 | 
|---|
| 329 |         << ")";
 | 
|---|
| 330 | 
 | 
|---|
| 331 |     return debug.space();
 | 
|---|
| 332 | }
 | 
|---|
| 333 | 
 | 
|---|
| 334 | #endif
 | 
|---|