diff options
author | Tomaž Vajngerl <quikee@gmail.com> | 2013-06-28 19:49:25 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2013-07-03 21:46:43 +0200 |
commit | 6085bd15740eb38de5f4c1079d11e8dd38fc166c (patch) | |
tree | dbb41f82e02f3e70988b4cf055095e7b0d66f81a /chart2 | |
parent | Added new regression curve properties as ODT 1.2 extended. (diff) | |
download | core-6085bd15740eb38de5f4c1079d11e8dd38fc166c.tar.gz core-6085bd15740eb38de5f4c1079d11e8dd38fc166c.zip |
Force intercept for polynomial regression & dialog improvements
Change-Id: I2f712d8b95b5fdeb05b93b5247aab9772a00cc70
Diffstat (limited to 'chart2')
14 files changed, 389 insertions, 116 deletions
diff --git a/chart2/source/controller/dialogs/dlg_InsertTrendline.src b/chart2/source/controller/dialogs/dlg_InsertTrendline.src index baf7dd90d1dc..2b8b621fc812 100644 --- a/chart2/source/controller/dialogs/dlg_InsertTrendline.src +++ b/chart2/source/controller/dialogs/dlg_InsertTrendline.src @@ -31,7 +31,7 @@ ModalDialog DLG_DATA_TRENDLINE HelpID = HID_INSERT_STATISTICS ; OutputSize = TRUE ; SVLook = TRUE ; - Size = MAP_APPFONT( DLG_DATA_TRENDLINE_RES_WIDTH + DLG_DATA_TRENDLINE_ADD_TO_RES, 172 ); + Size = MAP_APPFONT( DLG_DATA_TRENDLINE_RES_WIDTH + DLG_DATA_TRENDLINE_ADD_TO_RES, 220 ); Moveable = TRUE ; BUTTONS_OK_CANCEL_HELP_STACKED( DLG_DATA_TRENDLINE_RES_WIDTH + DLG_DATA_TRENDLINE_ADD_TO_RES ) RESOURCE_TRENDLINE( DLG_DATA_TRENDLINE_RES_WIDTH, 22 ) diff --git a/chart2/source/controller/dialogs/res_Trendline.cxx b/chart2/source/controller/dialogs/res_Trendline.cxx index 803c0606fe19..316282c63394 100644 --- a/chart2/source/controller/dialogs/res_Trendline.cxx +++ b/chart2/source/controller/dialogs/res_Trendline.cxx @@ -78,11 +78,15 @@ TrendlineResources::TrendlineResources( Window * pParent, const SfxItemSet& rInA m_aFIPolynomial( pParent, SchResId( FI_POLYNOMIAL )), m_aFIMovingAverage( pParent, SchResId( FI_MOVING_AVERAGE )), + m_aFT_Degree( pParent, SchResId( FT_DEGREE )), m_aNF_Degree( pParent, SchResId( NF_DEGREE )), + m_aFT_Period( pParent, SchResId( FT_PERIOD )), m_aNF_Period( pParent, SchResId( NF_PERIOD )), + m_aFT_ExtrapolateForward( pParent, SchResId( FT_EXTRAPOLATE_FORWARD )), m_aNF_ExtrapolateForward( pParent, SchResId( NF_EXTRAPOLATE_FORWARD )), - m_aNF_ExtrapolateBackward( pParent, SchResId( NF_EXTRAPOLATE_BACKWARD )), + m_aFT_ExtrapolateBackward( pParent, SchResId( FT_EXTRAPOLATE_BACKWARD )), + m_aNF_ExtrapolateBackward( pParent, SchResId( NF_EXTRAPOLATE_BACKWARD )), m_aCB_SetIntercept( pParent, SchResId( CB_SET_INTERCEPT )), m_aNF_InterceptValue( pParent, SchResId( NF_INTERCEPT_VALUE )), @@ -121,7 +125,7 @@ TrendlineResources::~TrendlineResources() long TrendlineResources::adjustControlSizes() { // calculate right edge - ::std::vector< long > aControlRightEdges; + std::vector< long > aControlRightEdges; aControlRightEdges.push_back( lcl_getRightEdge( m_aRBNone )); aControlRightEdges.push_back( lcl_getRightEdge( m_aRBLinear )); aControlRightEdges.push_back( lcl_getRightEdge( m_aRBLogarithmic )); @@ -129,9 +133,18 @@ long TrendlineResources::adjustControlSizes() aControlRightEdges.push_back( lcl_getRightEdge( m_aRBPower )); aControlRightEdges.push_back( lcl_getRightEdge( m_aRBPolynomial )); aControlRightEdges.push_back( lcl_getRightEdge( m_aRBMovingAverage )); + + aControlRightEdges.push_back( lcl_getRightEdge( m_aNF_Degree )); + aControlRightEdges.push_back( lcl_getRightEdge( m_aNF_Period )); + aControlRightEdges.push_back( lcl_getRightEdge( m_aNF_ExtrapolateForward )); + aControlRightEdges.push_back( lcl_getRightEdge( m_aNF_ExtrapolateBackward )); + aControlRightEdges.push_back( lcl_getRightEdge( m_aNF_InterceptValue )); + aControlRightEdges.push_back( lcl_getRightEdge( m_aCB_SetIntercept )); + aControlRightEdges.push_back( lcl_getRightEdge( m_aCBShowEquation )); aControlRightEdges.push_back( lcl_getRightEdge( m_aCBShowCorrelationCoeff )); + lcl_AdjustControlSize( m_aRBNone ); lcl_AdjustControlSize( m_aRBLinear ); lcl_AdjustControlSize( m_aRBLogarithmic ); @@ -139,6 +152,14 @@ long TrendlineResources::adjustControlSizes() lcl_AdjustControlSize( m_aRBPower ); lcl_AdjustControlSize( m_aRBPolynomial ); lcl_AdjustControlSize( m_aRBMovingAverage ); + + lcl_AdjustControlSize( m_aNF_Degree ); + lcl_AdjustControlSize( m_aNF_Period ); + lcl_AdjustControlSize( m_aNF_ExtrapolateForward ); + lcl_AdjustControlSize( m_aNF_ExtrapolateBackward ); + lcl_AdjustControlSize( m_aNF_InterceptValue ); + lcl_AdjustControlSize( m_aCB_SetIntercept ); + lcl_AdjustControlSize( m_aCBShowEquation ); lcl_AdjustControlSize( m_aCBShowCorrelationCoeff ); @@ -240,6 +261,29 @@ void TrendlineResources::Reset( const SfxItemSet& rInAttrs ) m_aNF_ExtrapolateBackward.SetValue( 0 ); } + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_INTERCEPT_VALUE, sal_True, &pPoolItem ) == SFX_ITEM_SET ) + { + double nValue = static_cast< const SvxDoubleItem * >( pPoolItem )->GetValue() * 10000; + m_aNF_InterceptValue.SetValue( (sal_Int64) nValue ); + } + else + { + m_aNF_InterceptValue.SetValue( 0 ); + } + + aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SET_INTERCEPT, sal_True, &pPoolItem ); + if( aState == SFX_ITEM_DONTCARE ) + { + m_aCB_SetIntercept.EnableTriState( sal_True ); + m_aCB_SetIntercept.SetState( STATE_DONTKNOW ); + } + else + { + m_aCB_SetIntercept.EnableTriState( sal_False ); + if( aState == SFX_ITEM_SET ) + m_aCB_SetIntercept.Check( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + } + aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_EQUATION, sal_True, &pPoolItem ); if( aState == SFX_ITEM_DONTCARE ) { @@ -300,8 +344,10 @@ sal_Bool TrendlineResources::FillItemSet(SfxItemSet& rOutAttrs) const { if( m_bTrendLineUnique ) rOutAttrs.Put( SvxChartRegressItem( m_eTrendLineType, SCHATTR_REGRESSION_TYPE )); + if( m_aCBShowEquation.GetState() != STATE_DONTKNOW ) rOutAttrs.Put( SfxBoolItem( SCHATTR_REGRESSION_SHOW_EQUATION, m_aCBShowEquation.IsChecked() )); + if( m_aCBShowCorrelationCoeff.GetState() != STATE_DONTKNOW ) rOutAttrs.Put( SfxBoolItem( SCHATTR_REGRESSION_SHOW_COEFF, m_aCBShowCorrelationCoeff.IsChecked() )); @@ -317,6 +363,12 @@ sal_Bool TrendlineResources::FillItemSet(SfxItemSet& rOutAttrs) const double aExtrapolateBackwardValue = m_aNF_ExtrapolateBackward.GetValue() / 100.0; rOutAttrs.Put(SvxDoubleItem( aExtrapolateBackwardValue, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD ) ); + if( m_aCB_SetIntercept.GetState() != STATE_DONTKNOW ) + rOutAttrs.Put( SfxBoolItem( SCHATTR_REGRESSION_SET_INTERCEPT, m_aCB_SetIntercept.IsChecked() )); + + double aInterceptValue = m_aNF_InterceptValue.GetValue() / 10000.0; + rOutAttrs.Put(SvxDoubleItem( aInterceptValue, SCHATTR_REGRESSION_INTERCEPT_VALUE ) ); + return sal_True; } diff --git a/chart2/source/controller/dialogs/res_Trendline.hxx b/chart2/source/controller/dialogs/res_Trendline.hxx index bbabc7b82cfa..1ff8ca0adaf6 100644 --- a/chart2/source/controller/dialogs/res_Trendline.hxx +++ b/chart2/source/controller/dialogs/res_Trendline.hxx @@ -60,11 +60,17 @@ private: FixedImage m_aFIPolynomial; FixedImage m_aFIMovingAverage; + FixedText m_aFT_Degree; NumericField m_aNF_Degree; + FixedText m_aFT_Period; NumericField m_aNF_Period; + FixedText m_aFT_ExtrapolateForward; NumericField m_aNF_ExtrapolateForward; + + FixedText m_aFT_ExtrapolateBackward; NumericField m_aNF_ExtrapolateBackward; + CheckBox m_aCB_SetIntercept; NumericField m_aNF_InterceptValue; diff --git a/chart2/source/controller/dialogs/res_Trendline_IDs.hrc b/chart2/source/controller/dialogs/res_Trendline_IDs.hrc index aa545690ea64..cb9e8d8e6d21 100644 --- a/chart2/source/controller/dialogs/res_Trendline_IDs.hrc +++ b/chart2/source/controller/dialogs/res_Trendline_IDs.hrc @@ -34,6 +34,11 @@ #define NF_EXTRAPOLATE_BACKWARD 4 #define NF_INTERCEPT_VALUE 5 +#define FT_DEGREE 1 +#define FT_PERIOD 2 +#define FT_EXTRAPOLATE_FORWARD 3 +#define FT_EXTRAPOLATE_BACKWARD 4 + #define RB_NONE 1 #define RB_LINEAR 2 #define RB_LOGARITHMIC 3 diff --git a/chart2/source/controller/dialogs/res_Trendline_tmpl.hrc b/chart2/source/controller/dialogs/res_Trendline_tmpl.hrc index 950726d25c56..ff6498c031c8 100644 --- a/chart2/source/controller/dialogs/res_Trendline_tmpl.hrc +++ b/chart2/source/controller/dialogs/res_Trendline_tmpl.hrc @@ -111,10 +111,16 @@ FixedImage FI_MOVING_AVERAGE \ Pos = MAP_APPFONT( 110, 62 + yoffset ); \ Size = MAP_APPFONT( 18, 18 ); \ }; \ +FixedText FT_DEGREE \ +{ \ + Pos = MAP_APPFONT ( 110, 44 + yoffset ) ; \ + Size = MAP_APPFONT ( 20 , 12 ) ; \ + Text [ en-US ] = "Degree"; \ +}; \ NumericField NF_DEGREE \ { \ Border = TRUE ; \ - Pos = MAP_APPFONT ( 110, 44 + yoffset ) ; \ + Pos = MAP_APPFONT ( 132, 42 + yoffset ) ; \ Size = MAP_APPFONT ( 28 , 12 ) ; \ TabStop = TRUE ; \ Repeat = TRUE ; \ @@ -124,10 +130,16 @@ NumericField NF_DEGREE \ Minimum = 2 ; \ Maximum = 100 ; \ }; \ +FixedText FT_PERIOD \ +{ \ + Pos = MAP_APPFONT ( 110, 88 + yoffset ) ; \ + Size = MAP_APPFONT ( 20 , 12 ) ; \ + Text [ en-US ] = "Period"; \ +}; \ NumericField NF_PERIOD \ { \ Border = TRUE ; \ - Pos = MAP_APPFONT ( 110, 88 + yoffset ) ; \ + Pos = MAP_APPFONT ( 132, 86 + yoffset ) ; \ Size = MAP_APPFONT ( 28 , 12 ) ; \ TabStop = TRUE ; \ Repeat = TRUE ; \ @@ -143,11 +155,17 @@ FixedLine FL_EQUATION \ Size = MAP_APPFONT( availablewidth - 12, 8 ); \ Text[ en-US ] = "Options"; \ }; \ +FixedText FT_EXTRAPOLATE_FORWARD \ +{ \ + Pos = MAP_APPFONT ( 10, 120 + yoffset ) ; \ + Size = MAP_APPFONT ( 70 , 12 ) ; \ + Text [ en-US ] = "Extrapolate ~forward"; \ +}; \ NumericField NF_EXTRAPOLATE_FORWARD \ { \ Border = TRUE ; \ - Pos = MAP_APPFONT ( 20, 120 + yoffset ) ; \ - Size = MAP_APPFONT ( 28 , 12 ) ; \ + Pos = MAP_APPFONT ( 80, 118 + yoffset ) ; \ + Size = MAP_APPFONT ( 40 , 12 ) ; \ TabStop = TRUE ; \ Repeat = TRUE ; \ Spin = TRUE ; \ @@ -157,11 +175,17 @@ NumericField NF_EXTRAPOLATE_FORWARD \ Maximum = 10000 ; \ DecimalDigits = 2 ; \ }; \ +FixedText FT_EXTRAPOLATE_BACKWARD \ +{ \ + Pos = MAP_APPFONT ( 10, 134 + yoffset ) ; \ + Size = MAP_APPFONT ( 70 , 12 ) ; \ + Text [ en-US ] = "Extrapolate ~backward"; \ +}; \ NumericField NF_EXTRAPOLATE_BACKWARD \ { \ Border = TRUE ; \ - Pos = MAP_APPFONT ( 20, 134 + yoffset ) ; \ - Size = MAP_APPFONT ( 28 , 12 ) ; \ + Pos = MAP_APPFONT ( 80, 132 + yoffset ) ; \ + Size = MAP_APPFONT ( 40 , 12 ) ; \ TabStop = TRUE ; \ Repeat = TRUE ; \ Spin = TRUE ; \ @@ -175,17 +199,18 @@ CheckBox CB_SET_INTERCEPT \ { \ HelpId = HID_SCH_TRENDLINE_SHOW_EQUATION; \ Pos = MAP_APPFONT( 10, 148 + yoffset ); \ - Size = MAP_APPFONT( 60, 10 ); \ + Size = MAP_APPFONT( 60, 12 ); \ TabStop = TRUE; \ - Text[ en-US ] = "Set ~intercept"; \ + Text[ en-US ] = "Force ~intercept"; \ }; \ NumericField NF_INTERCEPT_VALUE \ { \ Border = TRUE ; \ - Pos = MAP_APPFONT ( 75, 148 + yoffset ) ; \ + Pos = MAP_APPFONT ( 80, 146 + yoffset ) ; \ Size = MAP_APPFONT ( 40 , 12 ) ; \ TabStop = TRUE ; \ - Spin = FALSE ; \ + Spin = TRUE ; \ + SpinSize = 1000 ; \ DecimalDigits = 4 ; \ }; \ CheckBox CB_SHOW_EQUATION \ diff --git a/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx b/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx index 3ea1c0dd4363..011853ff1561 100644 --- a/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/RegressionCurveItemConverter.cxx @@ -261,11 +261,49 @@ bool RegressionCurveItemConverter::ApplySpecialItem( case SCHATTR_REGRESSION_SET_INTERCEPT: { + if( xCurve.is()) + { + sal_Bool bNewValue = static_cast< sal_Bool >( + static_cast< const SfxBoolItem & >( + rItemSet.Get( nWhichId )).GetValue()); + + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + OSL_ASSERT( xProperties.is()); + sal_Bool bOldValue = false; + if( xProperties.is() ) + { + xProperties->getPropertyValue( "ForceIntercept" ) >>= bOldValue; + if (bOldValue != bNewValue) + { + xProperties->setPropertyValue( "ForceIntercept" , uno::makeAny( bNewValue )); + bChanged = true; + } + } + } } break; case SCHATTR_REGRESSION_INTERCEPT_VALUE: { + if( xCurve.is()) + { + double aValue = static_cast< double >( + static_cast< const SvxDoubleItem & >( + rItemSet.Get( nWhichId )).GetValue()); + + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + OSL_ASSERT( xProperties.is()); + double aOldValue = 0.0; + if( xProperties.is() ) + { + xProperties->getPropertyValue( "InterceptValue" ) >>= aOldValue; + if (aOldValue != aValue) + { + xProperties->setPropertyValue( "InterceptValue" , uno::makeAny( aValue )); + bChanged = true; + } + } + } } break; @@ -407,6 +445,40 @@ void RegressionCurveItemConverter::FillSpecialItem( } break; + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + OSL_ASSERT( xCurve.is()); + if( xCurve.is()) + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + OSL_ASSERT( xProperties.is()); + sal_Bool bForceIntercept = false; + if( xProperties.is() && + (xProperties->getPropertyValue( "ForceIntercept" ) >>= bForceIntercept)) + { + rOutItemSet.Put( SfxBoolItem( nWhichId, bForceIntercept )); + } + } + } + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + OSL_ASSERT( xCurve.is()); + if( xCurve.is()) + { + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + OSL_ASSERT( xProperties.is()); + double aValue = 0.0; + if( xProperties.is() && + (xProperties->getPropertyValue( "InterceptValue" ) >>= aValue)) + { + rOutItemSet.Put( SvxDoubleItem( aValue, nWhichId )); + } + } + } + break; + case SCHATTR_REGRESSION_SHOW_EQUATION: { OSL_ASSERT( xCurve.is()); diff --git a/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx b/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx index 16ce0ceac0e1..c4b6896fd507 100644 --- a/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/StatisticsItemConverter.cxx @@ -511,6 +511,43 @@ bool StatisticsItemConverter::ApplySpecialItem( } break; + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + if( xProperties.is()) + { + sal_Bool aSetInterceptValue = false; + xProperties->getPropertyValue( "ForceIntercept" ) >>= aSetInterceptValue; + sal_Bool bNewValue = + static_cast< const SfxBoolItem & >( rItemSet.Get( nWhichId )).GetValue(); + if( aSetInterceptValue != bNewValue ) + { + xProperties->setPropertyValue( "ForceIntercept" , uno::makeAny( bNewValue )); + bChanged = true; + } + } + } + break; + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), &rItemSet )); + if( xProperties.is()) + { + double aInterceptValue = 0.0; + xProperties->getPropertyValue( "InterceptValue" ) >>= aInterceptValue; + double aNewValue = + static_cast< const SvxDoubleItem& >( rItemSet.Get( nWhichId )).GetValue(); + if( aInterceptValue != aNewValue ) + { + xProperties->setPropertyValue( "InterceptValue" , uno::makeAny( aNewValue )); + bChanged = true; + } + } + } + break; + case SCHATTR_REGRESSION_SHOW_EQUATION: { uno::Reference< beans::XPropertySet > xEqProp( lcl_getEquationProperties( GetPropertySet(), &rItemSet )); @@ -793,6 +830,26 @@ void StatisticsItemConverter::FillSpecialItem( } break; + case SCHATTR_REGRESSION_SET_INTERCEPT: + { + sal_Bool bForceIntercept = false; + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), 0 )); + if( xProperties.is()) + xProperties->getPropertyValue( "ForceIntercept" ) >>= bForceIntercept; + rOutItemSet.Put( SfxBoolItem( nWhichId, bForceIntercept )); + } + break; + + case SCHATTR_REGRESSION_INTERCEPT_VALUE: + { + double aValue = 0.0; + uno::Reference< beans::XPropertySet > xProperties( lcl_getCurveProperties( GetPropertySet(), 0 )); + if( xProperties.is()) + xProperties->getPropertyValue( "InterceptValue" ) >>= aValue; + rOutItemSet.Put( SvxDoubleItem( aValue, nWhichId )); + } + break; + case SCHATTR_REGRESSION_SHOW_EQUATION: { bool bShowEq = false; diff --git a/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx b/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx index b3b38a9d7eb7..803abb69f91b 100644 --- a/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx +++ b/chart2/source/inc/PolynomialRegressionCurveCalculator.hxx @@ -33,32 +33,30 @@ public: protected: virtual OUString ImplGetRepresentation( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& xNumFormatter, - ::sal_Int32 nNumberFormatKey ) const; + const com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatter >& xNumFormatter, + sal_Int32 nNumberFormatKey ) const; private: // ____ XRegressionCurveCalculator ____ virtual void SAL_CALL recalculateRegression( - const ::com::sun::star::uno::Sequence< double >& aXValues, - const ::com::sun::star::uno::Sequence< double >& aYValues ) - throw (::com::sun::star::uno::RuntimeException); + const com::sun::star::uno::Sequence< double >& aXValues, + const com::sun::star::uno::Sequence< double >& aYValues ) + throw (com::sun::star::uno::RuntimeException); virtual double SAL_CALL getCurveValue( double x ) - throw (::com::sun::star::lang::IllegalArgumentException, - ::com::sun::star::uno::RuntimeException); + throw (com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException); - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > SAL_CALL getCurveValues( + virtual ::com::sun::star::uno::Sequence< com::sun::star::geometry::RealPoint2D > SAL_CALL getCurveValues( double min, double max, - ::sal_Int32 nPointCount, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >& xScalingX, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >& xScalingY, - ::sal_Bool bMaySkipPointsInCalculation ) - throw (::com::sun::star::lang::IllegalArgumentException, - ::com::sun::star::uno::RuntimeException); + sal_Int32 nPointCount, + const com::sun::star::uno::Reference< com::sun::star::chart2::XScaling >& xScalingX, + const com::sun::star::uno::Reference< com::sun::star::chart2::XScaling >& xScalingY, + sal_Bool bMaySkipPointsInCalculation ) + throw (com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException); - double m_fSlope; - double m_fIntercept; std::vector<double> mResult; }; diff --git a/chart2/source/inc/RegressionCurveCalculator.hxx b/chart2/source/inc/RegressionCurveCalculator.hxx index 0829543dfb5d..a8cf124fbd97 100644 --- a/chart2/source/inc/RegressionCurveCalculator.hxx +++ b/chart2/source/inc/RegressionCurveCalculator.hxx @@ -28,64 +28,71 @@ namespace chart { class RegressionCurveCalculator : public - ::cppu::WeakImplHelper1< ::com::sun::star::chart2::XRegressionCurveCalculator > + cppu::WeakImplHelper1< com::sun::star::chart2::XRegressionCurveCalculator > { public: RegressionCurveCalculator(); virtual ~RegressionCurveCalculator(); static bool isLinearScaling( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling > & xScaling ); + const com::sun::star::uno::Reference< com::sun::star::chart2::XScaling >& xScaling ); + static bool isLogarithmicScaling( - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling > & xScaling ); + const com::sun::star::uno::Reference< com::sun::star::chart2::XScaling >& xScaling ); protected: virtual OUString ImplGetRepresentation( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& xNumFormatter, - ::sal_Int32 nNumberFormatKey ) const = 0; + const com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatter >& xNumFormatter, + sal_Int32 nNumberFormatKey ) const = 0; OUString getFormattedString( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >& xNumFormatter, - ::sal_Int32 nNumberFormatKey, + const com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatter >& xNumFormatter, + sal_Int32 nNumberFormatKey, double fNumber ) const; double m_fCorrelationCoeffitient; - sal_Int32 mDegree; - double mIntercept; - sal_Int32 mPeriod; + sal_Int32 mDegree; + sal_Bool mForceIntercept; + double mInterceptValue; + sal_Int32 mPeriod; // ____ XRegressionCurveCalculator ____ virtual void SAL_CALL setRegressionProperties( sal_Int32 aDegree, - double aIntercept, + sal_Bool aForceIntercept, + double aInterceptValue, sal_Int32 aPeriod); virtual void SAL_CALL recalculateRegression( - const ::com::sun::star::uno::Sequence< double >& aXValues, - const ::com::sun::star::uno::Sequence< double >& aYValues ) - throw (::com::sun::star::uno::RuntimeException) = 0; + const com::sun::star::uno::Sequence< double >& aXValues, + const com::sun::star::uno::Sequence< double >& aYValues ) + throw (com::sun::star::uno::RuntimeException) = 0; + virtual double SAL_CALL getCurveValue( double x ) - throw (::com::sun::star::lang::IllegalArgumentException, - ::com::sun::star::uno::RuntimeException) = 0; + throw (com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException) = 0; - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > SAL_CALL getCurveValues( + virtual com::sun::star::uno::Sequence< com::sun::star::geometry::RealPoint2D > SAL_CALL getCurveValues( double min, double max, - ::sal_Int32 nPointCount, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >& xScalingX, - const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XScaling >& xScalingY, - ::sal_Bool bMaySkipPointsInCalculation ) - throw (::com::sun::star::lang::IllegalArgumentException, - ::com::sun::star::uno::RuntimeException); + sal_Int32 nPointCount, + const com::sun::star::uno::Reference< com::sun::star::chart2::XScaling >& xScalingX, + const com::sun::star::uno::Reference< com::sun::star::chart2::XScaling >& xScalingY, + sal_Bool bMaySkipPointsInCalculation ) + throw (com::sun::star::lang::IllegalArgumentException, + com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getCorrelationCoefficient() - throw (::com::sun::star::uno::RuntimeException); + throw (com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getRepresentation() - throw (::com::sun::star::uno::RuntimeException); + throw (com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getFormattedRepresentation( - const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumFmtSupplier, - ::sal_Int32 nNumberFormatKey ) - throw (::com::sun::star::uno::RuntimeException); + const com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier >& xNumFmtSupplier, + sal_Int32 nNumberFormatKey ) + throw (com::sun::star::uno::RuntimeException); }; } // namespace chart diff --git a/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx index f5717ab0b333..0d3d4d1dbc7f 100644 --- a/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx +++ b/chart2/source/tools/PolynomialRegressionCurveCalculator.cxx @@ -25,7 +25,7 @@ #include <rtl/ustrbuf.hxx> #include "gauss.hxx" -using namespace ::com::sun::star; +using namespace com::sun::star; namespace chart @@ -43,66 +43,76 @@ void SAL_CALL PolynomialRegressionCurveCalculator::recalculateRegression( const uno::Sequence< double >& aYValues ) throw (uno::RuntimeException) { - ::rtl::math::setNan( & m_fCorrelationCoeffitient ); + rtl::math::setNan(&m_fCorrelationCoeffitient); RegressionCalculationHelper::tDoubleVectorPair aValues( RegressionCalculationHelper::cleanup( aXValues, aYValues, RegressionCalculationHelper::isValid())); - const double EPSILON( 1.0e-20 ); - - int aNumberOfPolyElements = mDegree + 1; - int aNumberOfPowers = 2 * aNumberOfPolyElements - 1; + int aNoElements = mForceIntercept ? mDegree : mDegree + 1; + int aNumberOfPowers = 2 * aNoElements - 1; std::vector<double> aPowers; aPowers.resize(aNumberOfPowers, 0.0); - int aNumberOfColumns = aNumberOfPolyElements; - int aNumberOfRows = aNumberOfPolyElements + 1; + int aNoColumns = aNoElements; + int aNoRows = aNoElements + 1; std::vector<double> aMatrix; - aMatrix.resize(aNumberOfColumns*aNumberOfRows, 0.0); + aMatrix.resize(aNoColumns * aNoRows, 0.0); - const size_t aSizeOfValues = aValues.first.size(); + const size_t aNoValues = aValues.first.size(); double yAverage = 0.0; - aPowers[0] += aSizeOfValues; - - for( size_t i = 0; i < aSizeOfValues; ++i ) + for( size_t i = 0; i < aNoValues; ++i ) { double x = aValues.first[i]; double y = aValues.second[i]; - for (int j = 1; j < aNumberOfPowers; j++) { - aPowers[j] += pow(x, j); + for (int j = 0; j < aNumberOfPowers; j++) + { + if (mForceIntercept) + aPowers[j] += std::pow(x, j + 2); + else + aPowers[j] += std::pow(x, j); } - for (int j = 0; j < aNumberOfPolyElements; j++) { - aMatrix[j * aNumberOfRows + aNumberOfPolyElements] += pow(x, j) * y; + for (int j = 0; j < aNoElements; j++) + { + if (mForceIntercept) + aMatrix[j * aNoRows + aNoElements] += std::pow(x, j + 1) * ( y - mInterceptValue ); + else + aMatrix[j * aNoRows + aNoElements] += std::pow(x, j) * y; } yAverage += y; } - yAverage = yAverage / aSizeOfValues; + yAverage = yAverage / aNoValues; - for (int y = 0; y < aNumberOfPolyElements; y++) { - for (int x = 0; x < aNumberOfPolyElements; x++) { - aMatrix[y * aNumberOfRows + x] = aPowers[y + x]; + for (int y = 0; y < aNoElements; y++) + { + for (int x = 0; x < aNoElements; x++) + { + aMatrix[y * aNoRows + x] = aPowers[y + x]; } } mResult.clear(); - mResult.resize(aNumberOfPolyElements, 0.0); + mResult.resize(aNoElements, 0.0); - solve(aMatrix, aNumberOfColumns, aNumberOfRows, mResult, EPSILON); + solve(aMatrix, aNoColumns, aNoRows, mResult, 1.0e-20); - // Calculate correlation coeffitient + // Set intercept value if force intercept is enabled + if (mForceIntercept) { + mResult.insert( mResult.begin(), mInterceptValue ); + } + // Calculate correlation coeffitient double aSumError = 0.0; double aSumTotal = 0.0; - for( size_t i = 0; i < aSizeOfValues; ++i ) + for( size_t i = 0; i < aNoValues; ++i ) { double x = aValues.first[i]; double yActual = aValues.second[i]; @@ -111,8 +121,11 @@ void SAL_CALL PolynomialRegressionCurveCalculator::recalculateRegression( aSumError += (yActual - yPredicted) * (yActual - yPredicted); } - m_fCorrelationCoeffitient = sqrt(1 - (aSumError / aSumTotal)); - + double aRSquared = 1.0 - (aSumError / aSumTotal); + if (aRSquared > 0.0) + m_fCorrelationCoeffitient = std::sqrt(aRSquared); + else + m_fCorrelationCoeffitient = 0.0; } double SAL_CALL PolynomialRegressionCurveCalculator::getCurveValue( double x ) @@ -130,7 +143,7 @@ double SAL_CALL PolynomialRegressionCurveCalculator::getCurveValue( double x ) fResult = 0.0; for (size_t i = 0; i<mResult.size(); i++) { - fResult += mResult[i]*pow(x,i); + fResult += mResult[i] * std::pow(x, i); } return fResult; } @@ -149,17 +162,34 @@ uno::Sequence< geometry::RealPoint2D > SAL_CALL PolynomialRegressionCurveCalcula OUString PolynomialRegressionCurveCalculator::ImplGetRepresentation( const uno::Reference< util::XNumberFormatter >& xNumFormatter, - ::sal_Int32 nNumberFormatKey ) const + sal_Int32 nNumberFormatKey ) const { OUStringBuffer aBuf( "f(x) = "); - for (int i=mResult.size()-1; i>=0; i--) + int aLastIndex = mResult.size() - 1; + for (int i = aLastIndex; i >= 0; i--) { - aBuf.append(getFormattedString( xNumFormatter, nNumberFormatKey, mResult[i] )); - if(i > 0) { + double aValue = mResult[i]; + if (aValue == 0.0) + { + continue; + } + else if (aValue < 0.0) + { + aBuf.appendAscii( " - " ); + } + else + { + if (i != aLastIndex) + aBuf.appendAscii( " + " ); + } + + aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, std::abs( aValue ) ) ); + + if(i > 0) + { aBuf.appendAscii( "x^" ); aBuf.append(i); - aBuf.append(" + "); } } diff --git a/chart2/source/tools/RegressionCurveCalculator.cxx b/chart2/source/tools/RegressionCurveCalculator.cxx index 461e504c074e..8337d95581bf 100644 --- a/chart2/source/tools/RegressionCurveCalculator.cxx +++ b/chart2/source/tools/RegressionCurveCalculator.cxx @@ -37,13 +37,14 @@ namespace chart { RegressionCurveCalculator::RegressionCurveCalculator() : - m_fCorrelationCoeffitient( 0.0 ), + m_fCorrelationCoeffitient(0.0), mDegree(2), - mIntercept(0.0), + mForceIntercept(false), + mInterceptValue(0.0), mPeriod(2) { - ::rtl::math::setNan( &m_fCorrelationCoeffitient ); - ::rtl::math::setNan( &mIntercept ); + rtl::math::setNan( &m_fCorrelationCoeffitient ); + rtl::math::setNan( &mInterceptValue ); } RegressionCurveCalculator::~RegressionCurveCalculator() @@ -70,17 +71,19 @@ bool RegressionCurveCalculator::isLogarithmicScaling( void RegressionCurveCalculator::setRegressionProperties( sal_Int32 aDegree, - double aIntercept, + sal_Bool aForceIntercept, + double aInterceptValue, sal_Int32 aPeriod) { - mDegree = aDegree; - mIntercept = aIntercept; - mPeriod = aPeriod; + mDegree = aDegree; + mForceIntercept = aForceIntercept; + mInterceptValue = aInterceptValue; + mPeriod = aPeriod; } OUString RegressionCurveCalculator::getFormattedString( const Reference< util::XNumberFormatter >& xNumFormatter, - ::sal_Int32 nNumberFormatKey, + sal_Int32 nNumberFormatKey, double fNumber ) const { OUString aResult; @@ -97,9 +100,8 @@ Sequence< geometry::RealPoint2D > SAL_CALL RegressionCurveCalculator::getCurveVa double min, double max, ::sal_Int32 nPointCount, const Reference< chart2::XScaling >& xScalingX, const Reference< chart2::XScaling >& /* xScalingY */, - ::sal_Bool /* bMaySkipPointsInCalculation */ ) - throw (lang::IllegalArgumentException, - uno::RuntimeException) + sal_Bool /* bMaySkipPointsInCalculation */ ) + throw (lang::IllegalArgumentException, uno::RuntimeException) { if( nPointCount < 2 ) throw lang::IllegalArgumentException(); @@ -148,7 +150,7 @@ OUString SAL_CALL RegressionCurveCalculator::getRepresentation() OUString SAL_CALL RegressionCurveCalculator::getFormattedRepresentation( const Reference< util::XNumberFormatsSupplier > & xNumFmtSupplier, - ::sal_Int32 nNumberFormatKey ) + sal_Int32 nNumberFormatKey ) throw (uno::RuntimeException) { // create and prepare a number formatter diff --git a/chart2/source/tools/RegressionCurveModel.cxx b/chart2/source/tools/RegressionCurveModel.cxx index cd9b143d7cc6..c98d59226289 100644 --- a/chart2/source/tools/RegressionCurveModel.cxx +++ b/chart2/source/tools/RegressionCurveModel.cxx @@ -60,7 +60,9 @@ enum PROPERTY_DEGREE, PROPERTY_PERIOD, PROPERTY_EXTRAPOLATE_FORWARD, - PROPERTY_EXTRAPOLATE_BACKWARD + PROPERTY_EXTRAPOLATE_BACKWARD, + PROPERTY_FORCE_INTERCEPT, + PROPERTY_INTERCEPT_VALUE }; void lcl_AddPropertiesToVector( @@ -93,6 +95,20 @@ void lcl_AddPropertiesToVector( ::getCppuType( reinterpret_cast< const double* >(0) ), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( "ForceIntercept", + PROPERTY_FORCE_INTERCEPT, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( "InterceptValue", + PROPERTY_INTERCEPT_VALUE, + ::getCppuType( reinterpret_cast< const double* >(0) ), + beans::PropertyAttribute::BOUND | + beans::PropertyAttribute::MAYBEDEFAULT )); } struct StaticXXXDefaults_Initializer diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index d5ba36f9bae6..8bceb4cc3481 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -985,8 +985,9 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries& rVDataSeries sal_Int32 aPeriod = 2; double aExtrapolateForward = 0.0; double aExtrapolateBackward = 0.0; - double aIntercept; - rtl::math::setNan(&aIntercept); + sal_Bool aForceIntercept = false; + double aInterceptValue; + rtl::math::setNan(&aInterceptValue); if ( xProperties.is() ) { @@ -994,10 +995,12 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries& rVDataSeries xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod; xProperties->getPropertyValue( "ExtrapolateForward") >>= aExtrapolateForward; xProperties->getPropertyValue( "ExtrapolateBackward") >>= aExtrapolateBackward; + xProperties->getPropertyValue( "ForceIntercept") >>= aForceIntercept; + if (aForceIntercept) + xProperties->getPropertyValue( "InterceptValue") >>= aInterceptValue; } - uno::Reference< XRegressionCurveCalculator > xRegressionCurveCalculator( - aCurveList[nN]->getCalculator() ); + uno::Reference< XRegressionCurveCalculator > xRegressionCurveCalculator( aCurveList[nN]->getCalculator() ); if( ! xRegressionCurveCalculator.is()) continue; @@ -1009,7 +1012,7 @@ void VSeriesPlotter::createRegressionCurvesShapes( VDataSeries& rVDataSeries fMaxX += aExtrapolateForward; fMinX -= aExtrapolateBackward; - xRegressionCurveCalculator->setRegressionProperties(aDegree, aIntercept, aPeriod); + xRegressionCurveCalculator->setRegressionProperties(aDegree, aForceIntercept, aInterceptValue, aPeriod); xRegressionCurveCalculator->recalculateRegression( rVDataSeries.getAllX(), rVDataSeries.getAllY() ); sal_Int32 nRegressionPointCount = 100; //@todo find a more optimal solution if more complicated curve types are introduced diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx index bfae31e1ff7c..6057d0f262d2 100644 --- a/chart2/source/view/main/ChartItemPool.cxx +++ b/chart2/source/view/main/ChartItemPool.cxx @@ -74,7 +74,7 @@ ChartItemPool::ChartItemPool(): ppPoolDefaults[SCHATTR_STAT_INDICATE - SCHATTR_START] = new SvxChartIndicateItem (CHINDICATE_NONE, SCHATTR_STAT_INDICATE); ppPoolDefaults[SCHATTR_STAT_RANGE_POS - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_POS, String()); ppPoolDefaults[SCHATTR_STAT_RANGE_NEG - SCHATTR_START] = new SfxStringItem (SCHATTR_STAT_RANGE_NEG, String()); - ppPoolDefaults[SCHATTR_STAT_ERRORBAR_TYPE - SCHATTR_START] = new SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE, true); + ppPoolDefaults[SCHATTR_STAT_ERRORBAR_TYPE - SCHATTR_START] = new SfxBoolItem(SCHATTR_STAT_ERRORBAR_TYPE, true); ppPoolDefaults[SCHATTR_STYLE_DEEP - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_DEEP, 0); ppPoolDefaults[SCHATTR_STYLE_3D - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_3D, 0); @@ -83,7 +83,7 @@ ChartItemPool::ChartItemPool(): ppPoolDefaults[SCHATTR_STYLE_LINES - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_LINES, 0); ppPoolDefaults[SCHATTR_STYLE_PERCENT - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_PERCENT, 0); ppPoolDefaults[SCHATTR_STYLE_STACKED - SCHATTR_START] = new SfxBoolItem (SCHATTR_STYLE_STACKED, 0); - ppPoolDefaults[SCHATTR_STYLE_SPLINES - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SPLINES, 0); //Bug: was Bool! test ->Fileformat (touches only 5's) + ppPoolDefaults[SCHATTR_STYLE_SPLINES - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SPLINES, 0); //Bug: was Bool! test ->Fileformat (touches only 5's) ppPoolDefaults[SCHATTR_STYLE_SYMBOL - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SYMBOL, 0); ppPoolDefaults[SCHATTR_STYLE_SHAPE - SCHATTR_START] = new SfxInt32Item (SCHATTR_STYLE_SHAPE, 0); @@ -152,11 +152,11 @@ ChartItemPool::ChartItemPool(): ppPoolDefaults[SCHATTR_REGRESSION_TYPE - SCHATTR_START] = new SvxChartRegressItem (CHREGRESS_NONE, SCHATTR_REGRESSION_TYPE); ppPoolDefaults[SCHATTR_REGRESSION_SHOW_EQUATION - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_EQUATION, 0); ppPoolDefaults[SCHATTR_REGRESSION_SHOW_COEFF - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SHOW_COEFF, 0); - ppPoolDefaults[SCHATTR_REGRESSION_DEGREE - SCHATTR_START] = new SfxInt32Item( SCHATTR_REGRESSION_DEGREE, 2 ); - ppPoolDefaults[SCHATTR_REGRESSION_PERIOD - SCHATTR_START] = new SfxInt32Item( SCHATTR_REGRESSION_PERIOD, 2 ); - ppPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD - SCHATTR_START] = new SvxDoubleItem( 0.0, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD ); - ppPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD - SCHATTR_START] = new SvxDoubleItem( 0.0, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD ); - ppPoolDefaults[SCHATTR_REGRESSION_SET_INTERCEPT - SCHATTR_START] = new SfxBoolItem( SCHATTR_REGRESSION_SET_INTERCEPT, false ); + ppPoolDefaults[SCHATTR_REGRESSION_DEGREE - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_DEGREE, 2); + ppPoolDefaults[SCHATTR_REGRESSION_PERIOD - SCHATTR_START] = new SfxInt32Item(SCHATTR_REGRESSION_PERIOD, 2); + ppPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD); + ppPoolDefaults[SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD - SCHATTR_START] = new SvxDoubleItem(0.0, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD); + ppPoolDefaults[SCHATTR_REGRESSION_SET_INTERCEPT - SCHATTR_START] = new SfxBoolItem(SCHATTR_REGRESSION_SET_INTERCEPT, sal_False); ppPoolDefaults[SCHATTR_REGRESSION_INTERCEPT_VALUE - SCHATTR_START] = new SvxDoubleItem( 0.0, SCHATTR_REGRESSION_INTERCEPT_VALUE); /************************************************************************** |