Changeset 8127 in ntrip for trunk/BNC/qwt/qwt_scale_engine.cpp
- Timestamp:
- May 10, 2017, 3:20:54 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/qwt/qwt_scale_engine.cpp
r4271 r8127 13 13 #include <qalgorithms.h> 14 14 #include <qmath.h> 15 #include <float.h> 16 #include <limits> 15 17 16 18 #if QT_VERSION < 0x040601 … … 19 21 #endif 20 22 23 static inline double qwtLog( double base, double value ) 24 { 25 return log( value ) / log( base ); 26 } 27 28 static inline QwtInterval qwtLogInterval( double base, const QwtInterval &interval ) 29 { 30 return QwtInterval( qwtLog( base, interval.minValue() ), 31 qwtLog( base, interval.maxValue() ) ); 32 } 33 34 static inline QwtInterval qwtPowInterval( double base, const QwtInterval &interval ) 35 { 36 return QwtInterval( qPow( base, interval.minValue() ), 37 qPow( base, interval.maxValue() ) ); 38 } 39 40 static inline long double qwtIntervalWidthL( const QwtInterval &interval ) 41 { 42 if ( !interval.isValid() ) 43 return 0.0; 44 45 return static_cast<long double>( interval.maxValue() ) 46 - static_cast<long double>( interval.minValue() ); 47 } 48 49 #if 1 50 51 // this version often doesn't find the best ticks: f.e for 15: 5, 10 52 static double qwtStepSize( double intervalSize, int maxSteps, uint base ) 53 { 54 const double minStep = 55 QwtScaleArithmetic::divideInterval( intervalSize, maxSteps, base ); 56 57 if ( minStep != 0.0 ) 58 { 59 // # ticks per interval 60 const int numTicks = qCeil( qAbs( intervalSize / minStep ) ) - 1; 61 62 // Do the minor steps fit into the interval? 63 if ( qwtFuzzyCompare( ( numTicks + 1 ) * qAbs( minStep ), 64 qAbs( intervalSize ), intervalSize ) > 0 ) 65 { 66 // The minor steps doesn't fit into the interval 67 return 0.5 * intervalSize; 68 } 69 } 70 71 return minStep; 72 } 73 74 #else 75 76 static double qwtStepSize( double intervalSize, int maxSteps, uint base ) 77 { 78 if ( maxSteps <= 0 ) 79 return 0.0; 80 81 if ( maxSteps > 2 ) 82 { 83 for ( int numSteps = maxSteps; numSteps > 1; numSteps-- ) 84 { 85 const double stepSize = intervalSize / numSteps; 86 87 const double p = ::floor( ::log( stepSize ) / ::log( base ) ); 88 const double fraction = qPow( base, p ); 89 90 for ( uint n = base; n > 1; n /= 2 ) 91 { 92 if ( qFuzzyCompare( stepSize, n * fraction ) ) 93 return stepSize; 94 95 if ( n == 3 && ( base % 2 ) == 0 ) 96 { 97 if ( qFuzzyCompare( stepSize, 2 * fraction ) ) 98 return stepSize; 99 } 100 } 101 } 102 } 103 104 return intervalSize * 0.5; 105 } 106 107 #endif 108 21 109 static const double _eps = 1.0e-6; 22 110 … … 24 112 Ceil a value, relative to an interval 25 113 26 \param value Value to ceil114 \param value Value to be ceiled 27 115 \param intervalSize Interval size 116 117 \return Rounded value 28 118 29 119 \sa floorEps() … … 35 125 36 126 value = ( value - eps ) / intervalSize; 37 return qwtCeilF( value ) * intervalSize;127 return ::ceil( value ) * intervalSize; 38 128 } 39 129 … … 41 131 Floor a value, relative to an interval 42 132 43 \param value Value to floor133 \param value Value to be floored 44 134 \param intervalSize Interval size 45 135 136 \return Rounded value 46 137 \sa floorEps() 47 138 */ … … 51 142 52 143 value = ( value + eps ) / intervalSize; 53 return qwtFloorF( value ) * intervalSize;144 return ::floor( value ) * intervalSize; 54 145 } 55 146 … … 72 163 73 164 /*! 74 Find the smallest value out of {1,2,5}*10^n with an integer number n 75 which is greater than or equal to x 76 77 \param x Input value 78 */ 79 double QwtScaleArithmetic::ceil125( double x ) 80 { 81 if ( x == 0.0 ) 165 Calculate a step size for a given interval 166 167 \param intervalSize Interval size 168 \param numSteps Number of steps 169 \param base Base for the division ( usually 10 ) 170 171 \return Calculated step size 172 */ 173 double QwtScaleArithmetic::divideInterval( 174 double intervalSize, int numSteps, uint base ) 175 { 176 if ( numSteps <= 0 ) 82 177 return 0.0; 83 178 84 const double sign = ( x > 0 ) ? 1.0 : -1.0; 85 const double lx = ::log10( qFabs( x ) ); 86 const double p10 = qwtFloorF( lx ); 87 88 double fr = qPow( 10.0, lx - p10 ); 89 if ( fr <= 1.0 ) 90 fr = 1.0; 91 else if ( fr <= 2.0 ) 92 fr = 2.0; 93 else if ( fr <= 5.0 ) 94 fr = 5.0; 95 else 96 fr = 10.0; 97 98 return sign * fr * qPow( 10.0, p10 ); 99 } 100 101 /*! 102 \brief Find the largest value out of {1,2,5}*10^n with an integer number n 103 which is smaller than or equal to x 104 105 \param x Input value 106 */ 107 double QwtScaleArithmetic::floor125( double x ) 108 { 109 if ( x == 0.0 ) 179 const double v = QwtScaleArithmetic::divideEps( intervalSize, numSteps ); 180 if ( v == 0.0 ) 110 181 return 0.0; 111 182 112 double sign = ( x > 0 ) ? 1.0 : -1.0; 113 const double lx = ::log10( qFabs( x ) ); 114 const double p10 = qwtFloorF( lx ); 115 116 double fr = qPow( 10.0, lx - p10 ); 117 if ( fr >= 10.0 ) 118 fr = 10.0; 119 else if ( fr >= 5.0 ) 120 fr = 5.0; 121 else if ( fr >= 2.0 ) 122 fr = 2.0; 123 else 124 fr = 1.0; 125 126 return sign * fr * qPow( 10.0, p10 ); 183 const double lx = qwtLog( base, qFabs( v ) ); 184 const double p = ::floor( lx ); 185 186 const double fraction = qPow( base, lx - p ); 187 188 uint n = base; 189 while ( ( n > 1 ) && ( fraction <= n / 2 ) ) 190 n /= 2; 191 192 double stepSize = n * qPow( base, p ); 193 if ( v < 0 ) 194 stepSize = -stepSize; 195 196 return stepSize; 127 197 } 128 198 … … 134 204 lowerMargin( 0.0 ), 135 205 upperMargin( 0.0 ), 136 referenceValue( 0.0 ) 137 { 138 } 139 140 QwtScaleEngine::Attributes attributes; // scale attributes 141 142 double lowerMargin; // margins 206 referenceValue( 0.0 ), 207 base( 10 ), 208 transform( NULL ) 209 { 210 } 211 212 ~PrivateData() 213 { 214 delete transform; 215 } 216 217 QwtScaleEngine::Attributes attributes; 218 219 double lowerMargin; 143 220 double upperMargin; 144 221 145 double referenceValue; // reference value 146 222 double referenceValue; 223 224 uint base; 225 226 QwtTransform* transform; 147 227 }; 148 228 149 //! Constructor 150 QwtScaleEngine::QwtScaleEngine() 229 /*! 230 Constructor 231 232 \param base Base of the scale engine 233 \sa setBase() 234 */ 235 QwtScaleEngine::QwtScaleEngine( uint base ) 151 236 { 152 237 d_data = new PrivateData; 238 setBase( base ); 153 239 } 154 240 … … 158 244 { 159 245 delete d_data; 246 } 247 248 /*! 249 Assign a transformation 250 251 \param transform Transformation 252 253 The transformation object is used as factory for clones 254 that are returned by transformation() 255 256 The scale engine takes ownership of the transformation. 257 258 \sa QwtTransform::copy(), transformation() 259 260 */ 261 void QwtScaleEngine::setTransformation( QwtTransform *transform ) 262 { 263 if ( transform != d_data->transform ) 264 { 265 delete d_data->transform; 266 d_data->transform = transform; 267 } 268 } 269 270 /*! 271 Create and return a clone of the transformation 272 of the engine. When the engine has no special transformation 273 NULL is returned, indicating no transformation. 274 275 \return A clone of the transfomation 276 \sa setTransformation() 277 */ 278 QwtTransform *QwtScaleEngine::transformation() const 279 { 280 QwtTransform *transform = NULL; 281 if ( d_data->transform ) 282 transform = d_data->transform->copy(); 283 284 return transform; 160 285 } 161 286 … … 193 318 194 319 \warning 195 \li QwtLog 10ScaleEngine measures the margins in decades.320 \li QwtLogScaleEngine measures the margins in decades. 196 321 197 322 \sa upperMargin(), lowerMargin() … … 215 340 double intervalSize, int numSteps ) const 216 341 { 217 if ( numSteps <= 0 ) 218 return 0.0; 219 220 double v = QwtScaleArithmetic::divideEps( intervalSize, numSteps ); 221 return QwtScaleArithmetic::ceil125( v ); 342 return QwtScaleArithmetic::divideInterval( 343 intervalSize, numSteps, d_data->base ); 222 344 } 223 345 … … 228 350 \param value Value 229 351 230 \ sa QwtScaleArithmetic::compareEps()352 \return True, when the value is inside the interval 231 353 */ 232 354 bool QwtScaleEngine::contains( … … 275 397 276 398 /*! 277 \brief Build an interval fora value399 \brief Build an interval around a value 278 400 279 401 In case of v == 0.0 the interval is [-0.5, 0.5], 280 402 otherwide it is [0.5 * v, 1.5 * v] 281 */ 282 283 QwtInterval QwtScaleEngine::buildInterval( double v ) const 284 { 285 const double delta = ( v == 0.0 ) ? 0.5 : qAbs( 0.5 * v ); 286 return QwtInterval( v - delta, v + delta ); 403 404 \param value Initial value 405 \return Calculated interval 406 */ 407 408 QwtInterval QwtScaleEngine::buildInterval( double value ) const 409 { 410 const double delta = ( value == 0.0 ) ? 0.5 : qAbs( 0.5 * value ); 411 412 if ( DBL_MAX - delta < value ) 413 return QwtInterval( DBL_MAX - delta, DBL_MAX ); 414 415 if ( -DBL_MAX + delta > value ) 416 return QwtInterval( -DBL_MAX, -DBL_MAX + delta ); 417 418 return QwtInterval( value - delta, value + delta ); 287 419 } 288 420 … … 304 436 305 437 /*! 306 Check if a attribute is set.438 \return True, if attribute is enabled. 307 439 308 440 \param attribute Attribute to be tested … … 326 458 327 459 /*! 328 Return the scale attributes460 \return Scale attributes 329 461 \sa Attribute, setAttributes(), testAttribute() 330 462 */ … … 349 481 350 482 /*! 351 \return the reference value352 \sa setReference(), setAttribute()483 \return the reference value 484 \sa setReference(), setAttribute() 353 485 */ 354 486 double QwtScaleEngine::reference() const … … 358 490 359 491 /*! 360 Return a transformation, for linear scales 361 */ 362 QwtScaleTransformation *QwtLinearScaleEngine::transformation() const 363 { 364 return new QwtScaleTransformation( QwtScaleTransformation::Linear ); 365 } 366 367 /*! 368 Align and divide an interval 369 370 \param maxNumSteps Max. number of steps 371 \param x1 First limit of the interval (In/Out) 372 \param x2 Second limit of the interval (In/Out) 373 \param stepSize Step size (Out) 374 375 \sa setAttribute() 492 Set the base of the scale engine 493 494 While a base of 10 is what 99.9% of all applications need 495 certain scales might need a different base: f.e 2 496 497 The default setting is 10 498 499 \param base Base of the engine 500 501 \sa base() 502 */ 503 void QwtScaleEngine::setBase( uint base ) 504 { 505 d_data->base = qMax( base, 2U ); 506 } 507 508 /*! 509 \return base Base of the scale engine 510 \sa setBase() 511 */ 512 uint QwtScaleEngine::base() const 513 { 514 return d_data->base; 515 } 516 517 /*! 518 Constructor 519 520 \param base Base of the scale engine 521 \sa setBase() 522 */ 523 QwtLinearScaleEngine::QwtLinearScaleEngine( uint base ): 524 QwtScaleEngine( base ) 525 { 526 } 527 528 //! Destructor 529 QwtLinearScaleEngine::~QwtLinearScaleEngine() 530 { 531 } 532 533 /*! 534 Align and divide an interval 535 536 \param maxNumSteps Max. number of steps 537 \param x1 First limit of the interval (In/Out) 538 \param x2 Second limit of the interval (In/Out) 539 \param stepSize Step size (Out) 540 541 \sa setAttribute() 376 542 */ 377 543 void QwtLinearScaleEngine::autoScale( int maxNumSteps, … … 393 559 interval = buildInterval( interval.minValue() ); 394 560 395 stepSize = divideInterval( interval.width(), qMax( maxNumSteps, 1 ) ); 561 stepSize = QwtScaleArithmetic::divideInterval( 562 interval.width(), qMax( maxNumSteps, 1 ), base() ); 396 563 397 564 if ( !testAttribute( QwtScaleEngine::Floating ) ) … … 409 576 410 577 /*! 411 \brief Calculate a scale division 578 \brief Calculate a scale division for an interval 412 579 413 580 \param x1 First interval limit 414 581 \param x2 Second interval limit 415 \param maxMaj Steps Maximum for the number of major steps416 \param maxMin Steps Maximum number of minor steps417 \param stepSize Step size. If stepSize == 0, the scaleEngine582 \param maxMajorSteps Maximum for the number of major steps 583 \param maxMinorSteps Maximum number of minor steps 584 \param stepSize Step size. If stepSize == 0, the engine 418 585 calculates one. 419 586 420 \ sa QwtScaleEngine::stepSize(), QwtScaleEngine::subDivide()587 \return Calculated scale division 421 588 */ 422 589 QwtScaleDiv QwtLinearScaleEngine::divideScale( double x1, double x2, 423 int maxMaj Steps, int maxMinSteps, double stepSize ) const590 int maxMajorSteps, int maxMinorSteps, double stepSize ) const 424 591 { 425 592 QwtInterval interval = QwtInterval( x1, x2 ).normalized(); 593 594 if ( qwtIntervalWidthL( interval ) > std::numeric_limits<double>::max() ) 595 { 596 qWarning() << "QwtLinearScaleEngine::divideScale: overflow"; 597 return QwtScaleDiv(); 598 } 599 426 600 if ( interval.width() <= 0 ) 427 601 return QwtScaleDiv(); … … 430 604 if ( stepSize == 0.0 ) 431 605 { 432 if ( maxMajSteps < 1 ) 433 maxMajSteps = 1; 434 435 stepSize = divideInterval( interval.width(), maxMajSteps ); 606 if ( maxMajorSteps < 1 ) 607 maxMajorSteps = 1; 608 609 stepSize = QwtScaleArithmetic::divideInterval( 610 interval.width(), maxMajorSteps, base() ); 436 611 } 437 612 … … 441 616 { 442 617 QList<double> ticks[QwtScaleDiv::NTickTypes]; 443 buildTicks( interval, stepSize, maxMin Steps, ticks );618 buildTicks( interval, stepSize, maxMinorSteps, ticks ); 444 619 445 620 scaleDiv = QwtScaleDiv( interval, ticks ); … … 457 632 \param interval Interval 458 633 \param stepSize Step size 459 \param maxMin Steps Maximum number of minor steps634 \param maxMinorSteps Maximum number of minor steps 460 635 \param ticks Arrays to be filled with the calculated ticks 461 636 … … 463 638 */ 464 639 void QwtLinearScaleEngine::buildTicks( 465 const QwtInterval& interval, double stepSize, int maxMin Steps,640 const QwtInterval& interval, double stepSize, int maxMinorSteps, 466 641 QList<double> ticks[QwtScaleDiv::NTickTypes] ) const 467 642 { 468 const QwtInterval boundingInterval = 469 align( interval, stepSize ); 643 const QwtInterval boundingInterval = align( interval, stepSize ); 470 644 471 645 ticks[QwtScaleDiv::MajorTick] = 472 646 buildMajorTicks( boundingInterval, stepSize ); 473 647 474 if ( maxMin Steps > 0 )475 { 476 buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMin Steps, stepSize,648 if ( maxMinorSteps > 0 ) 649 { 650 buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize, 477 651 ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] ); 478 652 } … … 522 696 523 697 \param majorTicks Major ticks 524 \param maxMin Steps Maximum number of minor steps698 \param maxMinorSteps Maximum number of minor steps 525 699 \param stepSize Step size 526 700 \param minorTicks Array to be filled with the calculated minor ticks … … 530 704 void QwtLinearScaleEngine::buildMinorTicks( 531 705 const QList<double>& majorTicks, 532 int maxMin Steps, double stepSize,706 int maxMinorSteps, double stepSize, 533 707 QList<double> &minorTicks, 534 708 QList<double> &mediumTicks ) const 535 709 { 536 double minStep = divideInterval( stepSize, maxMinSteps);710 double minStep = qwtStepSize( stepSize, maxMinorSteps, base() ); 537 711 if ( minStep == 0.0 ) 538 712 return; 539 713 540 714 // # ticks per interval 541 int numTicks = qCeil( qAbs( stepSize / minStep ) ) - 1; 542 543 // Do the minor steps fit into the interval? 544 if ( qwtFuzzyCompare( ( numTicks + 1 ) * qAbs( minStep ), 545 qAbs( stepSize ), stepSize ) > 0 ) 546 { 547 numTicks = 1; 548 minStep = stepSize * 0.5; 549 } 715 const int numTicks = qCeil( qAbs( stepSize / minStep ) ) - 1; 550 716 551 717 int medIndex = -1; … … 588 754 const QwtInterval &interval, double stepSize ) const 589 755 { 590 double x1 = QwtScaleArithmetic::floorEps( interval.minValue(), stepSize ); 591 if ( qwtFuzzyCompare( interval.minValue(), x1, stepSize ) == 0 ) 592 x1 = interval.minValue(); 593 594 double x2 = QwtScaleArithmetic::ceilEps( interval.maxValue(), stepSize ); 595 if ( qwtFuzzyCompare( interval.maxValue(), x2, stepSize ) == 0 ) 596 x2 = interval.maxValue(); 756 double x1 = interval.minValue(); 757 double x2 = interval.maxValue(); 758 759 // when there is no rounding beside some effect, when 760 // calculating with doubles, we keep the original value 761 762 const double eps = 0.000000000001; // since Qt 4.8: qFuzzyIsNull 763 if ( -DBL_MAX + stepSize <= x1 ) 764 { 765 const double x = QwtScaleArithmetic::floorEps( x1, stepSize ); 766 if ( qAbs(x) <= eps || !qFuzzyCompare( x1, x ) ) 767 x1 = x; 768 } 769 770 if ( DBL_MAX - stepSize >= x2 ) 771 { 772 const double x = QwtScaleArithmetic::ceilEps( x2, stepSize ); 773 if ( qAbs(x) <= eps || !qFuzzyCompare( x2, x ) ) 774 x2 = x; 775 } 597 776 598 777 return QwtInterval( x1, x2 ); … … 600 779 601 780 /*! 602 Return a transformation, for logarithmic (base 10) scales 603 */ 604 QwtScaleTransformation *QwtLog10ScaleEngine::transformation() const 605 { 606 return new QwtScaleTransformation( QwtScaleTransformation::Log10 ); 781 Constructor 782 783 \param base Base of the scale engine 784 \sa setBase() 785 */ 786 QwtLogScaleEngine::QwtLogScaleEngine( uint base ): 787 QwtScaleEngine( base ) 788 { 789 setTransformation( new QwtLogTransform() ); 790 } 791 792 //! Destructor 793 QwtLogScaleEngine::~QwtLogScaleEngine() 794 { 607 795 } 608 796 … … 617 805 \sa QwtScaleEngine::setAttribute() 618 806 */ 619 void QwtLog 10ScaleEngine::autoScale( int maxNumSteps,620 807 void QwtLogScaleEngine::autoScale( int maxNumSteps, 808 double &x1, double &x2, double &stepSize ) const 621 809 { 622 810 if ( x1 > x2 ) 623 811 qSwap( x1, x2 ); 624 812 625 QwtInterval interval( x1 / qPow( 10.0, lowerMargin() ), 626 x2 * qPow( 10.0, upperMargin() ) ); 627 628 if ( interval.maxValue() / interval.minValue() < 10.0 ) 629 { 630 // scale width is less than one decade -> build linear scale 813 const double logBase = base(); 814 815 QwtInterval interval( x1 / qPow( logBase, lowerMargin() ), 816 x2 * qPow( logBase, upperMargin() ) ); 817 818 if ( interval.maxValue() / interval.minValue() < logBase ) 819 { 820 // scale width is less than one step -> try to build a linear scale 631 821 632 822 QwtLinearScaleEngine linearScaler; … … 636 826 637 827 linearScaler.autoScale( maxNumSteps, x1, x2, stepSize ); 638 stepSize = ::log10( stepSize ); 639 640 return; 828 829 QwtInterval linearInterval = QwtInterval( x1, x2 ).normalized(); 830 linearInterval = linearInterval.limited( LOG_MIN, LOG_MAX ); 831 832 if ( linearInterval.maxValue() / linearInterval.minValue() < logBase ) 833 { 834 // the aligned scale is still less than one step 835 836 #if 1 837 // this code doesn't make any sense, but for compatibility 838 // reasons we keep it until 6.2. But it will be ignored 839 // in divideScale 840 841 if ( stepSize < 0.0 ) 842 stepSize = -qwtLog( logBase, qAbs( stepSize ) ); 843 else 844 stepSize = qwtLog( logBase, stepSize ); 845 #endif 846 847 return; 848 } 641 849 } 642 850 … … 660 868 interval = buildInterval( interval.minValue() ); 661 869 662 stepSize = divideInterval( log10( interval ).width(), qMax( maxNumSteps, 1 ) ); 870 stepSize = divideInterval( qwtLogInterval( logBase, interval ).width(), 871 qMax( maxNumSteps, 1 ) ); 663 872 if ( stepSize < 1.0 ) 664 873 stepSize = 1.0; … … 678 887 679 888 /*! 680 \brief Calculate a scale division 889 \brief Calculate a scale division for an interval 681 890 682 891 \param x1 First interval limit 683 892 \param x2 Second interval limit 684 \param maxMaj Steps Maximum for the number of major steps685 \param maxMin Steps Maximum number of minor steps686 \param stepSize Step size. If stepSize == 0, the scaleEngine893 \param maxMajorSteps Maximum for the number of major steps 894 \param maxMinorSteps Maximum number of minor steps 895 \param stepSize Step size. If stepSize == 0, the engine 687 896 calculates one. 688 897 689 \ sa QwtScaleEngine::stepSize(), QwtLog10ScaleEngine::subDivide()690 */ 691 QwtScaleDiv QwtLog 10ScaleEngine::divideScale( double x1, double x2,692 int maxMaj Steps, int maxMinSteps, double stepSize ) const898 \return Calculated scale division 899 */ 900 QwtScaleDiv QwtLogScaleEngine::divideScale( double x1, double x2, 901 int maxMajorSteps, int maxMinorSteps, double stepSize ) const 693 902 { 694 903 QwtInterval interval = QwtInterval( x1, x2 ).normalized(); … … 698 907 return QwtScaleDiv(); 699 908 700 if ( interval.maxValue() / interval.minValue() < 10.0 ) 909 const double logBase = base(); 910 911 if ( interval.maxValue() / interval.minValue() < logBase ) 701 912 { 702 913 // scale width is less than one decade -> build linear scale … … 707 918 linearScaler.setMargins( lowerMargin(), upperMargin() ); 708 919 709 if ( stepSize != 0.0 )710 stepSize = qPow( 10.0, stepSize );711 712 920 return linearScaler.divideScale( x1, x2, 713 maxMaj Steps, maxMinSteps, stepSize);921 maxMajorSteps, maxMinorSteps, 0.0 ); 714 922 } 715 923 … … 717 925 if ( stepSize == 0.0 ) 718 926 { 719 if ( maxMajSteps < 1 ) 720 maxMajSteps = 1; 721 722 stepSize = divideInterval( log10( interval ).width(), maxMajSteps ); 927 if ( maxMajorSteps < 1 ) 928 maxMajorSteps = 1; 929 930 stepSize = divideInterval( 931 qwtLogInterval( logBase, interval ).width(), maxMajorSteps ); 723 932 if ( stepSize < 1.0 ) 724 933 stepSize = 1.0; // major step must be >= 1 decade … … 729 938 { 730 939 QList<double> ticks[QwtScaleDiv::NTickTypes]; 731 buildTicks( interval, stepSize, maxMin Steps, ticks );940 buildTicks( interval, stepSize, maxMinorSteps, ticks ); 732 941 733 942 scaleDiv = QwtScaleDiv( interval, ticks ); … … 744 953 745 954 \param interval Interval 746 \param maxMin Steps Maximum number of minor steps955 \param maxMinorSteps Maximum number of minor steps 747 956 \param stepSize Step size 748 957 \param ticks Arrays to be filled with the calculated ticks … … 750 959 \sa buildMajorTicks(), buildMinorTicks 751 960 */ 752 void QwtLog 10ScaleEngine::buildTicks(753 const QwtInterval& interval, double stepSize, int maxMin Steps,961 void QwtLogScaleEngine::buildTicks( 962 const QwtInterval& interval, double stepSize, int maxMinorSteps, 754 963 QList<double> ticks[QwtScaleDiv::NTickTypes] ) const 755 964 { … … 759 968 buildMajorTicks( boundingInterval, stepSize ); 760 969 761 if ( maxMin Steps > 0 )762 { 763 ticks[QwtScaleDiv::MinorTick] = buildMinorTicks(764 ticks[QwtScaleDiv::M ajorTick], maxMinSteps, stepSize);970 if ( maxMinorSteps > 0 ) 971 { 972 buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize, 973 ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] ); 765 974 } 766 975 … … 777 986 \return Calculated ticks 778 987 */ 779 QList<double> QwtLog 10ScaleEngine::buildMajorTicks(988 QList<double> QwtLogScaleEngine::buildMajorTicks( 780 989 const QwtInterval &interval, double stepSize ) const 781 990 { 782 double width = log10(interval ).width();991 double width = qwtLogInterval( base(), interval ).width(); 783 992 784 993 int numTicks = qRound( width / stepSize ) + 1; … … 806 1015 807 1016 \param majorTicks Major ticks 808 \param maxMin Steps Maximum number of minor steps1017 \param maxMinorSteps Maximum number of minor steps 809 1018 \param stepSize Step size 810 */ 811 QList<double> QwtLog10ScaleEngine::buildMinorTicks( 1019 \param minorTicks Array to be filled with the calculated minor ticks 1020 \param mediumTicks Array to be filled with the calculated medium ticks 1021 */ 1022 void QwtLogScaleEngine::buildMinorTicks( 812 1023 const QList<double> &majorTicks, 813 int maxMinSteps, double stepSize ) const 814 { 815 if ( stepSize < 1.1 ) // major step width is one decade 816 { 817 if ( maxMinSteps < 1 ) 818 return QList<double>(); 819 820 int k0, kstep, kmax; 821 822 if ( maxMinSteps >= 8 ) 1024 int maxMinorSteps, double stepSize, 1025 QList<double> &minorTicks, 1026 QList<double> &mediumTicks ) const 1027 { 1028 const double logBase = base(); 1029 1030 if ( stepSize < 1.1 ) // major step width is one base 1031 { 1032 double minStep = divideInterval( stepSize, maxMinorSteps + 1 ); 1033 if ( minStep == 0.0 ) 1034 return; 1035 1036 const int numSteps = qRound( stepSize / minStep ); 1037 1038 int mediumTickIndex = -1; 1039 if ( ( numSteps > 2 ) && ( numSteps % 2 == 0 ) ) 1040 mediumTickIndex = numSteps / 2; 1041 1042 for ( int i = 0; i < majorTicks.count() - 1; i++ ) 823 1043 { 824 k0 = 2; 825 kmax = 9; 826 kstep = 1; 1044 const double v = majorTicks[i]; 1045 const double s = logBase / numSteps; 1046 1047 if ( s >= 1.0 ) 1048 { 1049 if ( !qFuzzyCompare( s, 1.0 ) ) 1050 minorTicks += v * s; 1051 1052 for ( int j = 2; j < numSteps; j++ ) 1053 { 1054 minorTicks += v * j * s; 1055 } 1056 } 1057 else 1058 { 1059 for ( int j = 1; j < numSteps; j++ ) 1060 { 1061 const double tick = v + j * v * ( logBase - 1 ) / numSteps; 1062 if ( j == mediumTickIndex ) 1063 mediumTicks += tick; 1064 else 1065 minorTicks += tick; 1066 } 1067 } 827 1068 } 828 else if ( maxMinSteps >= 4 ) 1069 } 1070 else 1071 { 1072 double minStep = divideInterval( stepSize, maxMinorSteps ); 1073 if ( minStep == 0.0 ) 1074 return; 1075 1076 if ( minStep < 1.0 ) 1077 minStep = 1.0; 1078 1079 // # subticks per interval 1080 int numTicks = qRound( stepSize / minStep ) - 1; 1081 1082 // Do the minor steps fit into the interval? 1083 if ( qwtFuzzyCompare( ( numTicks + 1 ) * minStep, 1084 stepSize, stepSize ) > 0 ) 829 1085 { 830 k0 = 2; 831 kmax = 8; 832 kstep = 2; 1086 numTicks = 0; 833 1087 } 834 else if ( maxMinSteps >= 2 ) 835 { 836 k0 = 2; 837 kmax = 5; 838 kstep = 3; 839 } 840 else 841 { 842 k0 = 5; 843 kmax = 5; 844 kstep = 1; 845 } 846 847 QList<double> minorTicks; 1088 1089 if ( numTicks < 1 ) 1090 return; 1091 1092 int mediumTickIndex = -1; 1093 if ( ( numTicks > 2 ) && ( numTicks % 2 ) ) 1094 mediumTickIndex = numTicks / 2; 1095 1096 // substep factor = base^substeps 1097 const qreal minFactor = qMax( qPow( logBase, minStep ), qreal( logBase ) ); 848 1098 849 1099 for ( int i = 0; i < majorTicks.count(); i++ ) 850 1100 { 851 const double v = majorTicks[i]; 852 for ( int k = k0; k <= kmax; k += kstep ) 853 minorTicks += v * double( k ); 854 } 855 856 return minorTicks; 857 } 858 else // major step > one decade 859 { 860 double minStep = divideInterval( stepSize, maxMinSteps ); 861 if ( minStep == 0.0 ) 862 return QList<double>(); 863 864 if ( minStep < 1.0 ) 865 minStep = 1.0; 866 867 // # subticks per interval 868 int nMin = qRound( stepSize / minStep ) - 1; 869 870 // Do the minor steps fit into the interval? 871 872 if ( qwtFuzzyCompare( ( nMin + 1 ) * minStep, 873 qAbs( stepSize ), stepSize ) > 0 ) 874 { 875 nMin = 0; 876 } 877 878 if ( nMin < 1 ) 879 return QList<double>(); // no subticks 880 881 // substep factor = 10^substeps 882 const qreal minFactor = qMax( qPow( 10.0, minStep ), qreal( 10.0 ) ); 883 884 QList<double> minorTicks; 885 for ( int i = 0; i < majorTicks.count(); i++ ) 886 { 887 double val = majorTicks[i]; 888 for ( int k = 0; k < nMin; k++ ) 1101 double tick = majorTicks[i]; 1102 for ( int j = 0; j < numTicks; j++ ) 889 1103 { 890 val *= minFactor; 891 minorTicks += val; 1104 tick *= minFactor; 1105 1106 if ( j == mediumTickIndex ) 1107 mediumTicks += tick; 1108 else 1109 minorTicks += tick; 892 1110 } 893 1111 } 894 return minorTicks;895 1112 } 896 1113 } … … 907 1124 \return Aligned interval 908 1125 */ 909 QwtInterval QwtLog 10ScaleEngine::align(1126 QwtInterval QwtLogScaleEngine::align( 910 1127 const QwtInterval &interval, double stepSize ) const 911 1128 { 912 const QwtInterval intv = log10(interval );1129 const QwtInterval intv = qwtLogInterval( base(), interval ); 913 1130 914 1131 double x1 = QwtScaleArithmetic::floorEps( intv.minValue(), stepSize ); … … 920 1137 x2 = interval.maxValue(); 921 1138 922 return pow10( QwtInterval( x1, x2 ) ); 923 } 924 925 /*! 926 Return the interval [log10(interval.minValue(), log10(interval.maxValue] 927 */ 928 929 QwtInterval QwtLog10ScaleEngine::log10( const QwtInterval &interval ) const 930 { 931 return QwtInterval( ::log10( interval.minValue() ), 932 ::log10( interval.maxValue() ) ); 933 } 934 935 /*! 936 Return the interval [pow10(interval.minValue(), pow10(interval.maxValue] 937 */ 938 QwtInterval QwtLog10ScaleEngine::pow10( const QwtInterval &interval ) const 939 { 940 return QwtInterval( qPow( 10.0, interval.minValue() ), 941 qPow( 10.0, interval.maxValue() ) ); 942 } 1139 return qwtPowInterval( base(), QwtInterval( x1, x2 ) ); 1140 }
Note:
See TracChangeset
for help on using the changeset viewer.