From 6789b828a8f0ff52e21947f1e805746504b89ca7 Mon Sep 17 00:00:00 2001 From: ouv Date: Thu, 18 Apr 2013 14:25:16 +0000 Subject: [PATCH] Issue 0001626: External 20643: 2d plot axis logarithmic. --- src/Plot2d/Plot2d_Curve.cxx | 40 +++++++++++++ src/Plot2d/Plot2d_Curve.h | 6 ++ src/Plot2d/Plot2d_ViewFrame.cxx | 82 +++++++++++++++++++++++++-- src/Plot2d/Plot2d_ViewFrame.h | 2 + src/Plot2d/resources/Plot2d_msg_en.ts | 14 ++++- 5 files changed, 138 insertions(+), 6 deletions(-) diff --git a/src/Plot2d/Plot2d_Curve.cxx b/src/Plot2d/Plot2d_Curve.cxx index fec976268..d1ab1755c 100755 --- a/src/Plot2d/Plot2d_Curve.cxx +++ b/src/Plot2d/Plot2d_Curve.cxx @@ -23,6 +23,8 @@ #include "Plot2d_Curve.h" #include +#include + /*! Constructor */ @@ -214,6 +216,14 @@ pointList Plot2d_Curve::getPointList() const return myPoints; } +/*! + Gets curve's data : abscissas of points +*/ +pointList& Plot2d_Curve::getPointList() +{ + return myPoints; +} + /*! Sets curve's data. */ @@ -442,6 +452,36 @@ double Plot2d_Curve::getMaxY() const return aMaxY; } +/*! + Gets curve's minimal positive abscissa +*/ +double Plot2d_Curve::getMinPositiveX() const +{ + pointList::const_iterator aIt; + double aMinX = 1e150; + //int aCurrent = 0; + for(aIt = myPoints.begin(); aIt != myPoints.end(); ++aIt) { + if ( (*aIt).x < aMinX && (*aIt).x > DBL_MIN ) + aMinX = (*aIt).x; + } + return aMinX; +} + +/*! + Gets curve's minimal positive ordinate +*/ +double Plot2d_Curve::getMinPositiveY() const +{ + pointList::const_iterator aIt; + double aMinY = 1e150; + //int aCurrent = 0; + for(aIt = myPoints.begin(); aIt != myPoints.end(); ++aIt) { + if ( (*aIt).y < aMinY && (*aIt).y > DBL_MIN ) + aMinY = (*aIt).y; + } + return aMinY; +} + /*! Changes text assigned to point of curve \param ind -- index of point diff --git a/src/Plot2d/Plot2d_Curve.h b/src/Plot2d/Plot2d_Curve.h index 8692be8c9..0b9819971 100755 --- a/src/Plot2d/Plot2d_Curve.h +++ b/src/Plot2d/Plot2d_Curve.h @@ -64,6 +64,7 @@ public: void deletePoint( int ); void clearAllPoints(); pointList getPointList() const; + pointList& getPointList(); void setData( const double*, const double*, long, const QStringList& = QStringList() ); @@ -106,6 +107,11 @@ public: double getMaxX() const; double getMaxY() const; + // Values required for calculating a "negligible" value, by which the non-positive + // values will be replaced during switch to logarithmic scale mode + double getMinPositiveX() const; + double getMinPositiveY() const; + protected: bool myAutoAssign; QString myHorTitle; diff --git a/src/Plot2d/Plot2d_ViewFrame.cxx b/src/Plot2d/Plot2d_ViewFrame.cxx index e397b6326..cfe758f60 100755 --- a/src/Plot2d/Plot2d_ViewFrame.cxx +++ b/src/Plot2d/Plot2d_ViewFrame.cxx @@ -57,6 +57,7 @@ #include #include +#include #include #include @@ -69,6 +70,8 @@ #define FITALL_EVENT ( QEvent::User + 9999 ) +#define NEGLIGIBLE_VALUE 1e-6 + const char* imageZoomCursor[] = { "32 32 3 1", ". c None", @@ -1503,6 +1506,63 @@ void Plot2d_ViewFrame::setFont( const QFont& font, ObjectType type, bool update) if ( update ) myPlot->replot(); } +/*! + Remove the curve's non-positive values or replace them by a negligible small value + (to make it possible to enable logarithmic scale mode). +*/ +void Plot2d_ViewFrame::cutCurveNonPositiveValues( const bool theIsXAxis, + const bool theIsReplaceWithSmallValues ) +{ + const CurveDict& aCurves = myPlot->getCurves(); + CurveDict::ConstIterator it, itEnd = aCurves.end(); + + double aSmallValue = NEGLIGIBLE_VALUE; + if( theIsReplaceWithSmallValues ) + { + // first, calculate the value the non-positive values will be cut to + for( it = aCurves.begin(); it != itEnd; it++ ) + { + if( Plot2d_Curve* aCurve = it.value() ) + { + double aMinPositiveValue = theIsXAxis ? + aCurve->getMinPositiveX() : aCurve->getMinPositiveY(); + + if( aMinPositiveValue < aSmallValue ) + { + double aLog = log10( aMinPositiveValue ); + double aFloor = floor( aLog ); + aSmallValue = pow( 10, aFloor ); + } + } + } + } + + for( it = aCurves.begin(); it != itEnd; it++ ) + { + if( Plot2d_Curve* aCurve = it.value() ) + { + pointList& aPointList = aCurve->getPointList(); + pointList::iterator pIt, pItEnd = aPointList.end(); + for( pIt = aPointList.begin(); pIt != pItEnd; ) + { + Plot2d_Point& aPoint = *pIt; + double& value = theIsXAxis ? aPoint.x : aPoint.y; + if( value < DBL_MIN ) + { + if( theIsReplaceWithSmallValues ) + value = aSmallValue; + else // remove value + { + pIt = aPointList.erase( pIt ); + continue; // do not increment the iterator + } + } + pIt++; + } + updateCurve( aCurve, false ); + } + } +} /*! Sets scale mode for horizontal axis: 0 - linear, 1 - logarithmic */ @@ -1515,8 +1575,15 @@ void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update ) // it crashes if switched to X/Y logarithmic mode, when one or more points have // non-positive X/Y coordinate if ( mode && !isXLogEnabled() ){ - SUIT_MessageBox::warning(this, tr("WARNING"), tr("WRN_XLOG_NOT_ALLOWED")); - return; + int answer = SUIT_MessageBox::question(this, tr("WARNING"), tr("WRN_XLOG_NOT_ALLOWED"), + tr("REMOVE_POINTS"), tr("REPLACE_VALUES"), + tr("CANCEL"), 2, 2); + if( answer == 0 ) + cutCurveNonPositiveValues( true, false ); + else if( answer == 1 ) + cutCurveNonPositiveValues( true, true ); + else + return; } myXMode = mode; @@ -1539,8 +1606,15 @@ void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update ) // it crashes if switched to X/Y logarithmic mode, when one or more points have // non-positive X/Y coordinate if ( mode && !isYLogEnabled() ){ - SUIT_MessageBox::warning(this, tr("WARNING"), tr("WRN_YLOG_NOT_ALLOWED")); - return; + int answer = SUIT_MessageBox::question(this, tr("WARNING"), tr("WRN_YLOG_NOT_ALLOWED"), + tr("REMOVE_POINTS"), tr("REPLACE_VALUES"), + tr("CANCEL"), 2, 2); + if( answer == 0 ) + cutCurveNonPositiveValues( false, false ); + else if( answer == 1 ) + cutCurveNonPositiveValues( false, true ); + else + return; } myYMode = mode; diff --git a/src/Plot2d/Plot2d_ViewFrame.h b/src/Plot2d/Plot2d_ViewFrame.h index 3d585bbfa..620a3c81d 100755 --- a/src/Plot2d/Plot2d_ViewFrame.h +++ b/src/Plot2d/Plot2d_ViewFrame.h @@ -152,6 +152,8 @@ protected: QwtPlotCurve* getPlotCurve( Plot2d_Curve* curve ); bool hasPlotCurve( Plot2d_Curve* curve ); void setCurveType( QwtPlotCurve* curve, int curveType ); + void cutCurveNonPositiveValues( const bool theIsXAxis, + const bool theIsReplaceWithSmallValues ); public slots: void onViewPan(); diff --git a/src/Plot2d/resources/Plot2d_msg_en.ts b/src/Plot2d/resources/Plot2d_msg_en.ts index 41983b772..ab6fcd6ec 100644 --- a/src/Plot2d/resources/Plot2d_msg_en.ts +++ b/src/Plot2d/resources/Plot2d_msg_en.ts @@ -284,12 +284,22 @@ WRN_XLOG_NOT_ALLOWED Some points with non-positive abscissa values have been detected. -Logarithmic scale for abscissa axis is not allowed. +Do you want to remove these points from the curve presentation or +to replace the non-positive values with negligible positive values? WRN_YLOG_NOT_ALLOWED Some points with non-positive ordinate values have been detected. -Logarithmic scale for ordinate axis is not allowed. +Do you want to remove these points from the curve presentation or +to replace the non-positive values with negligible positive values? + + + REMOVE_POINTS + Remove points + + + REPLACE_VALUES + Replace values DSC_FITRECT -- 2.39.2