1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "RegressionCurveHelper.hxx"
21 #include "MeanValueRegressionCurveCalculator.hxx"
22 #include "LinearRegressionCurveCalculator.hxx"
23 #include "LogarithmicRegressionCurveCalculator.hxx"
24 #include "ExponentialRegressionCurveCalculator.hxx"
25 #include "PotentialRegressionCurveCalculator.hxx"
26 #include "CommonConverters.hxx"
27 #include "RegressionCurveModel.hxx"
28 #include "ChartTypeHelper.hxx"
29 #include "ChartModelHelper.hxx"
31 #include "PropertyHelper.hxx"
33 #include "Strings.hrc"
34 #include "DiagramHelper.hxx"
35 #include <com/sun/star/chart2/XChartDocument.hpp>
37 using namespace ::com::sun::star
;
38 using namespace ::com::sun::star::chart2
;
40 using ::com::sun::star::uno::Reference
;
41 using ::com::sun::star::uno::Sequence
;
42 using ::com::sun::star::uno::XComponentContext
;
43 using ::com::sun::star::lang::XServiceName
;
44 using ::com::sun::star::beans::XPropertySet
;
45 using ::com::sun::star::uno::Exception
;
49 OUString
lcl_getServiceNameForType( ::chart::RegressionCurveHelper::tRegressionType eType
)
51 OUString aServiceName
;
54 case ::chart::RegressionCurveHelper::REGRESSION_TYPE_LINEAR
:
55 aServiceName
= "com.sun.star.chart2.LinearRegressionCurve";
57 case ::chart::RegressionCurveHelper::REGRESSION_TYPE_LOG
:
58 aServiceName
= "com.sun.star.chart2.LogarithmicRegressionCurve";
60 case ::chart::RegressionCurveHelper::REGRESSION_TYPE_EXP
:
61 aServiceName
= "com.sun.star.chart2.ExponentialRegressionCurve";
63 case ::chart::RegressionCurveHelper::REGRESSION_TYPE_POWER
:
64 aServiceName
= "com.sun.star.chart2.PotentialRegressionCurve";
67 OSL_FAIL("unknown regression curve type - use linear instead");
68 aServiceName
= "com.sun.star.chart2.LinearRegressionCurve";
73 } // anonymous namespace
75 //.............................................................................
78 //.............................................................................
80 Reference
< XRegressionCurve
> RegressionCurveHelper::createMeanValueLine(
81 const Reference
< XComponentContext
> & xContext
)
83 return Reference
< XRegressionCurve
>(
84 new MeanValueRegressionCurve( xContext
));
87 Reference
< XRegressionCurve
> RegressionCurveHelper::createRegressionCurveByServiceName(
88 const Reference
< XComponentContext
> & xContext
,
89 OUString aServiceName
)
91 Reference
< XRegressionCurve
> xResult
;
93 // todo: use factory methods with service name
94 if( aServiceName
== "com.sun.star.chart2.LinearRegressionCurve" )
96 xResult
.set( new LinearRegressionCurve( xContext
) );
98 else if( aServiceName
== "com.sun.star.chart2.LogarithmicRegressionCurve" )
100 xResult
.set( new LogarithmicRegressionCurve( xContext
) );
102 else if( aServiceName
== "com.sun.star.chart2.ExponentialRegressionCurve" )
104 xResult
.set( new ExponentialRegressionCurve( xContext
) );
106 else if( aServiceName
== "com.sun.star.chart2.PotentialRegressionCurve" )
108 xResult
.set( new PotentialRegressionCurve( xContext
) );
114 // ------------------------------------------------------------
116 Reference
< XRegressionCurveCalculator
> RegressionCurveHelper::createRegressionCurveCalculatorByServiceName(
117 OUString aServiceName
)
119 Reference
< XRegressionCurveCalculator
> xResult
;
121 // todo: use factory methods with service name
122 if( aServiceName
== "com.sun.star.chart2.MeanValueRegressionCurve" )
124 xResult
.set( new MeanValueRegressionCurveCalculator() );
126 if( aServiceName
== "com.sun.star.chart2.LinearRegressionCurve" )
128 xResult
.set( new LinearRegressionCurveCalculator() );
130 else if( aServiceName
== "com.sun.star.chart2.LogarithmicRegressionCurve" )
132 xResult
.set( new LogarithmicRegressionCurveCalculator() );
134 else if( aServiceName
== "com.sun.star.chart2.ExponentialRegressionCurve" )
136 xResult
.set( new ExponentialRegressionCurveCalculator() );
138 else if( aServiceName
== "com.sun.star.chart2.PotentialRegressionCurve" )
140 xResult
.set( new PotentialRegressionCurveCalculator() );
146 void RegressionCurveHelper::initializeCurveCalculator(
147 const Reference
< XRegressionCurveCalculator
> & xOutCurveCalculator
,
148 const Reference
< data::XDataSource
> & xSource
,
149 bool bUseXValuesIfAvailable
/* = true */ )
151 if( ! (xOutCurveCalculator
.is() &&
155 Sequence
< double > aXValues
, aYValues
;
156 bool bXValuesFound
= false, bYValuesFound
= false;
158 Sequence
< Reference
< data::XLabeledDataSequence
> > aDataSeqs( xSource
->getDataSequences());
161 ! (bXValuesFound
&& bYValuesFound
) && i
<aDataSeqs
.getLength();
166 Reference
< data::XDataSequence
> xSeq( aDataSeqs
[i
]->getValues());
167 Reference
< XPropertySet
> xProp( xSeq
, uno::UNO_QUERY_THROW
);
169 if( xProp
->getPropertyValue( "Role" ) >>= aRole
)
171 if( bUseXValuesIfAvailable
&& !bXValuesFound
&& aRole
== "values-x" )
173 aXValues
= DataSequenceToDoubleSequence( xSeq
);
174 bXValuesFound
= true;
176 else if( !bYValuesFound
&& aRole
== "values-y" )
178 aYValues
= DataSequenceToDoubleSequence( xSeq
);
179 bYValuesFound
= true;
183 catch( const Exception
& ex
)
185 ASSERT_EXCEPTION( ex
);
189 if( ! bXValuesFound
&&
192 // initialize with 1, 2, ...
193 //first category (index 0) matches with real number 1.0
194 aXValues
.realloc( aYValues
.getLength());
195 for( i
=0; i
<aXValues
.getLength(); ++i
)
197 bXValuesFound
= true;
200 if( bXValuesFound
&& bYValuesFound
&&
201 aXValues
.getLength() > 0 &&
202 aYValues
.getLength() > 0 )
203 xOutCurveCalculator
->recalculateRegression( aXValues
, aYValues
);
206 void RegressionCurveHelper::initializeCurveCalculator(
207 const Reference
< XRegressionCurveCalculator
> & xOutCurveCalculator
,
208 const Reference
< XDataSeries
> & xSeries
,
209 const Reference
< frame::XModel
> & xModel
)
211 sal_Int32 nAxisType
= ChartTypeHelper::getAxisType(
212 ChartModelHelper::getChartTypeOfSeries( xModel
, xSeries
), 0 ); // x-axis
214 initializeCurveCalculator( xOutCurveCalculator
,
215 uno::Reference
< data::XDataSource
>( xSeries
, uno::UNO_QUERY
),
216 (nAxisType
== AxisType::REALNUMBER
) );
219 // ----------------------------------------
221 bool RegressionCurveHelper::hasMeanValueLine(
222 const uno::Reference
< XRegressionCurveContainer
> & xRegCnt
)
229 uno::Sequence
< uno::Reference
< XRegressionCurve
> > aCurves(
230 xRegCnt
->getRegressionCurves());
231 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
233 if( isMeanValueLine( aCurves
[i
] ))
237 catch( const Exception
& ex
)
239 ASSERT_EXCEPTION( ex
);
245 bool RegressionCurveHelper::isMeanValueLine(
246 const uno::Reference
< chart2::XRegressionCurve
> & xRegCurve
)
248 uno::Reference
< XServiceName
> xServName( xRegCurve
, uno::UNO_QUERY
);
249 if( xServName
.is() &&
250 xServName
->getServiceName().equals(
251 "com.sun.star.chart2.MeanValueRegressionCurve"))
256 uno::Reference
< chart2::XRegressionCurve
>
257 RegressionCurveHelper::getMeanValueLine(
258 const uno::Reference
< chart2::XRegressionCurveContainer
> & xRegCnt
)
264 uno::Sequence
< uno::Reference
< XRegressionCurve
> > aCurves(
265 xRegCnt
->getRegressionCurves());
266 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
268 if( isMeanValueLine( aCurves
[i
] ))
272 catch( const Exception
& ex
)
274 ASSERT_EXCEPTION( ex
);
278 return uno::Reference
< chart2::XRegressionCurve
>();
281 void RegressionCurveHelper::addMeanValueLine(
282 uno::Reference
< XRegressionCurveContainer
> & xRegCnt
,
283 const uno::Reference
< XComponentContext
> & xContext
,
284 const uno::Reference
< XPropertySet
> & xSeriesProp
)
287 ::chart::RegressionCurveHelper::hasMeanValueLine( xRegCnt
) )
290 // todo: use a valid context
291 uno::Reference
< XRegressionCurve
> xCurve( createMeanValueLine( xContext
));
292 xRegCnt
->addRegressionCurve( xCurve
);
294 if( xSeriesProp
.is())
296 uno::Reference
< XPropertySet
> xProp( xCurve
, uno::UNO_QUERY
);
299 xProp
->setPropertyValue( "LineColor",
300 xSeriesProp
->getPropertyValue( "Color"));
305 void RegressionCurveHelper::removeMeanValueLine(
306 Reference
< XRegressionCurveContainer
> & xRegCnt
)
313 Sequence
< Reference
< XRegressionCurve
> > aCurves(
314 xRegCnt
->getRegressionCurves());
315 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
317 if( isMeanValueLine( aCurves
[i
] ))
319 xRegCnt
->removeRegressionCurve( aCurves
[i
] );
320 // attention: the iterator i has become invalid now
322 // note: assume that there is only one mean-value curve
323 // to remove multiple mean-value curves remove the break
328 catch( const Exception
& ex
)
330 ASSERT_EXCEPTION( ex
);
334 void RegressionCurveHelper::addRegressionCurve(
335 tRegressionType eType
,
336 uno::Reference
< XRegressionCurveContainer
> & xRegCnt
,
337 const uno::Reference
< XComponentContext
> & /* xContext */,
338 const uno::Reference
< beans::XPropertySet
>& xPropertySource
,
339 const uno::Reference
< beans::XPropertySet
>& xEquationProperties
)
344 if( eType
== REGRESSION_TYPE_NONE
)
346 OSL_FAIL("don't create a regression curve of type none");
350 uno::Reference
< chart2::XRegressionCurve
> xCurve
;
351 OUString
aServiceName( lcl_getServiceNameForType( eType
));
353 if( !aServiceName
.isEmpty())
355 // todo: use a valid context
356 xCurve
.set( createRegressionCurveByServiceName(
357 uno::Reference
< uno::XComponentContext
>(), aServiceName
));
359 if( xEquationProperties
.is())
360 xCurve
->setEquationProperties( xEquationProperties
);
362 uno::Reference
< beans::XPropertySet
> xProp( xCurve
, uno::UNO_QUERY
);
365 if( xPropertySource
.is())
366 comphelper::copyProperties( xPropertySource
, xProp
);
369 uno::Reference
< XPropertySet
> xSeriesProp( xRegCnt
, uno::UNO_QUERY
);
370 if( xSeriesProp
.is())
372 xProp
->setPropertyValue( "LineColor",
373 xSeriesProp
->getPropertyValue( "Color"));
375 // xProp->setPropertyValue( "LineWidth", uno::makeAny( sal_Int32( 100 )));
379 xRegCnt
->addRegressionCurve( xCurve
);
382 /** removes all regression curves that are not of type mean value
383 and returns true, if anything was removed
385 bool RegressionCurveHelper::removeAllExceptMeanValueLine(
386 uno::Reference
< chart2::XRegressionCurveContainer
> & xRegCnt
)
388 bool bRemovedSomething
= false;
393 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > aCurves(
394 xRegCnt
->getRegressionCurves());
395 ::std::vector
< uno::Reference
< chart2::XRegressionCurve
> > aCurvesToDelete
;
396 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
398 if( ! isMeanValueLine( aCurves
[i
] ))
400 aCurvesToDelete
.push_back( aCurves
[ i
] );
404 for( ::std::vector
< uno::Reference
< chart2::XRegressionCurve
> >::const_iterator aIt
= aCurvesToDelete
.begin();
405 aIt
!= aCurvesToDelete
.end(); ++aIt
)
407 xRegCnt
->removeRegressionCurve( *aIt
);
408 bRemovedSomething
= true;
411 catch( const uno::Exception
& ex
)
413 ASSERT_EXCEPTION( ex
);
416 return bRemovedSomething
;
419 void RegressionCurveHelper::removeEquations(
420 uno::Reference
< chart2::XRegressionCurveContainer
> & xRegCnt
)
426 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > aCurves(
427 xRegCnt
->getRegressionCurves());
428 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
430 if( !isMeanValueLine( aCurves
[i
] ) )
432 uno::Reference
< chart2::XRegressionCurve
> xRegCurve( aCurves
[ i
] );
435 uno::Reference
< beans::XPropertySet
> xEqProp( xRegCurve
->getEquationProperties() ) ;
438 xEqProp
->setPropertyValue( "ShowEquation", uno::makeAny( false ));
439 xEqProp
->setPropertyValue( "ShowCorrelationCoefficient", uno::makeAny( false ));
445 catch( const uno::Exception
& ex
)
447 ASSERT_EXCEPTION( ex
);
452 void RegressionCurveHelper::replaceOrAddCurveAndReduceToOne(
453 tRegressionType eType
,
454 uno::Reference
< XRegressionCurveContainer
> & xRegCnt
,
455 const uno::Reference
< XComponentContext
> & xContext
)
457 uno::Reference
< chart2::XRegressionCurve
> xRegressionCurve( getFirstCurveNotMeanValueLine( xRegCnt
));
458 if( ! xRegressionCurve
.is())
459 RegressionCurveHelper::addRegressionCurve( eType
, xRegCnt
, xContext
);
462 OUString
aServiceName( lcl_getServiceNameForType( eType
));
463 if( !aServiceName
.isEmpty())
465 RegressionCurveHelper::removeAllExceptMeanValueLine( xRegCnt
);
466 RegressionCurveHelper::addRegressionCurve(
467 eType
, xRegCnt
, xContext
,
468 Reference
< beans::XPropertySet
>( xRegressionCurve
, uno::UNO_QUERY
),
469 xRegressionCurve
->getEquationProperties());
474 uno::Reference
< chart2::XRegressionCurve
> RegressionCurveHelper::getFirstCurveNotMeanValueLine(
475 const Reference
< XRegressionCurveContainer
> & xRegCnt
)
482 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > aCurves(
483 xRegCnt
->getRegressionCurves());
484 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
486 if( ! isMeanValueLine( aCurves
[i
] ))
492 catch( const Exception
& ex
)
494 ASSERT_EXCEPTION( ex
);
500 RegressionCurveHelper::tRegressionType
RegressionCurveHelper::getRegressionType(
501 const Reference
< XRegressionCurve
> & xCurve
)
503 tRegressionType eResult
= REGRESSION_TYPE_UNKNOWN
;
507 Reference
< lang::XServiceName
> xServName( xCurve
, uno::UNO_QUERY
);
510 OUString
aServiceName( xServName
->getServiceName() );
512 if( aServiceName
== "com.sun.star.chart2.LinearRegressionCurve" )
514 eResult
= REGRESSION_TYPE_LINEAR
;
516 else if( aServiceName
== "com.sun.star.chart2.LogarithmicRegressionCurve" )
518 eResult
= REGRESSION_TYPE_LOG
;
520 else if( aServiceName
== "com.sun.star.chart2.ExponentialRegressionCurve" )
522 eResult
= REGRESSION_TYPE_EXP
;
524 else if( aServiceName
== "com.sun.star.chart2.PotentialRegressionCurve" )
526 eResult
= REGRESSION_TYPE_POWER
;
528 else if( aServiceName
== "com.sun.star.chart2.MeanValueRegressionCurve" )
530 eResult
= REGRESSION_TYPE_MEAN_VALUE
;
534 catch( const Exception
& ex
)
536 ASSERT_EXCEPTION( ex
);
542 RegressionCurveHelper::tRegressionType
RegressionCurveHelper::getFirstRegressTypeNotMeanValueLine(
543 const Reference
< XRegressionCurveContainer
> & xRegCnt
)
545 tRegressionType eResult
= REGRESSION_TYPE_NONE
;
549 Sequence
< Reference
< XRegressionCurve
> > aCurves(
550 xRegCnt
->getRegressionCurves());
551 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
553 tRegressionType eType
= getRegressionType( aCurves
[i
] );
554 if( eType
!= REGRESSION_TYPE_MEAN_VALUE
&&
555 eType
!= REGRESSION_TYPE_UNKNOWN
)
566 OUString
RegressionCurveHelper::getUINameForRegressionCurve( const Reference
< XRegressionCurve
>& xRegressionCurve
)
569 Reference
< lang::XServiceName
> xServiceName( xRegressionCurve
, uno::UNO_QUERY
);
570 if( ! xServiceName
.is())
573 OUString
aServiceName( xServiceName
->getServiceName());
574 if( aServiceName
== "com.sun.star.chart2.MeanValueRegressionCurve" )
576 aResult
= SCH_RESSTR(STR_REGRESSION_MEAN
);
578 else if( aServiceName
== "com.sun.star.chart2.LinearRegressionCurve" )
580 aResult
= SCH_RESSTR(STR_REGRESSION_LINEAR
);
582 else if( aServiceName
== "com.sun.star.chart2.LogarithmicRegressionCurve" )
584 aResult
= SCH_RESSTR(STR_REGRESSION_LOG
);
586 else if( aServiceName
== "com.sun.star.chart2.ExponentialRegressionCurve" )
588 aResult
= SCH_RESSTR(STR_REGRESSION_EXP
);
590 else if( aServiceName
== "com.sun.star.chart2.PotentialRegressionCurve" )
592 aResult
= SCH_RESSTR(STR_REGRESSION_POWER
);
598 ::std::vector
< Reference
< chart2::XRegressionCurve
> >
599 RegressionCurveHelper::getAllRegressionCurvesNotMeanValueLine(
600 const Reference
< chart2::XDiagram
> & xDiagram
)
602 ::std::vector
< Reference
< chart2::XRegressionCurve
> > aResult
;
603 ::std::vector
< Reference
< chart2::XDataSeries
> > aSeries( DiagramHelper::getDataSeriesFromDiagram( xDiagram
));
604 for( ::std::vector
< Reference
< chart2::XDataSeries
> >::iterator
aIt( aSeries
.begin());
605 aIt
!= aSeries
.end(); ++aIt
)
607 Reference
< chart2::XRegressionCurveContainer
> xCurveCnt( *aIt
, uno::UNO_QUERY
);
610 uno::Sequence
< uno::Reference
< chart2::XRegressionCurve
> > aCurves(
611 xCurveCnt
->getRegressionCurves());
612 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
614 if( ! isMeanValueLine( aCurves
[i
] ))
615 aResult
.push_back( aCurves
[i
] );
623 void RegressionCurveHelper::resetEquationPosition(
624 const Reference
< chart2::XRegressionCurve
> & xCurve
)
630 const OUString
aPosPropertyName( "RelativePosition" );
631 Reference
< beans::XPropertySet
> xEqProp( xCurve
->getEquationProperties()); // since m233: , uno::UNO_SET_THROW );
632 if( xEqProp
->getPropertyValue( aPosPropertyName
).hasValue())
633 xEqProp
->setPropertyValue( aPosPropertyName
, uno::Any());
635 catch( const uno::Exception
& ex
)
637 ASSERT_EXCEPTION( ex
);
642 sal_Int32
RegressionCurveHelper::getRegressionCurveIndex(
643 const Reference
< chart2::XRegressionCurveContainer
> & xContainer
,
644 const Reference
< chart2::XRegressionCurve
> & xCurve
)
648 uno::Sequence
< uno::Reference
< XRegressionCurve
> > aCurves(
649 xContainer
->getRegressionCurves());
650 for( sal_Int32 i
= 0; i
< aCurves
.getLength(); ++i
)
652 if( xCurve
== aCurves
[i
] )
659 bool RegressionCurveHelper::hasEquation( const Reference
< chart2::XRegressionCurve
> & xCurve
)
661 bool bHasEquation
= false;
664 uno::Reference
< beans::XPropertySet
> xEquationProp( xCurve
->getEquationProperties());
665 if( xEquationProp
.is())
667 bool bShowEquation
= false;
668 bool bShowCoefficient
= false;
669 xEquationProp
->getPropertyValue( "ShowEquation") >>= bShowEquation
;
670 xEquationProp
->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowCoefficient
;
671 bHasEquation
= bShowEquation
|| bShowCoefficient
;
677 //.............................................................................
679 //.............................................................................
681 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */