1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <MovingAverageRegressionCurveCalculator.hxx>
21 #include <RegressionCalculationHelper.hxx>
22 #include <ResId.hxx>
23 #include <strings.hrc>
24 
25 #include <rtl/math.hxx>
26 
27 #include <com/sun/star/chart2/MovingAverageType.hpp>
28 
29 using namespace ::com::sun::star;
30 using namespace ::com::sun::star::chart2;
31 
32 namespace chart
33 {
34 
MovingAverageRegressionCurveCalculator()35 MovingAverageRegressionCurveCalculator::MovingAverageRegressionCurveCalculator()
36 {}
37 
~MovingAverageRegressionCurveCalculator()38 MovingAverageRegressionCurveCalculator::~MovingAverageRegressionCurveCalculator()
39 {}
40 
41 // ____ XRegressionCurveCalculator ____
recalculateRegression(const uno::Sequence<double> & aXValues,const uno::Sequence<double> & aYValues)42 void SAL_CALL MovingAverageRegressionCurveCalculator::recalculateRegression(
43     const uno::Sequence< double >& aXValues,
44     const uno::Sequence< double >& aYValues )
45 {
46     ::rtl::math::setNan( & m_fCorrelationCoefficient );
47 
48     RegressionCalculationHelper::tDoubleVectorPair aValues(
49         RegressionCalculationHelper::cleanup(
50             aXValues, aYValues,
51             RegressionCalculationHelper::isValid()));
52 
53     aYList.clear();
54     aXList.clear();
55 
56     // For formulas, see
57     // https://docs.oasis-open.org/office/OpenDocument/v1.3/cs02/part3-schema/OpenDocument-v1.3-cs02-part3-schema.html#property-chart_regression-moving-type
58 
59     switch (mnMovingType)
60     {
61         case MovingAverageType::Central:
62         {
63 
64             calculateValuesCentral(aValues);
65             break;
66         }
67 
68         case MovingAverageType::AveragedAbscissa:
69         {
70             calculateValues(aValues, true);
71             break;
72         }
73         case MovingAverageType::Prior:
74         default:
75         {
76             calculateValues(aValues, false);
77             break;
78         }
79     }
80 }
81 
calculateValuesCentral(RegressionCalculationHelper::tDoubleVectorPair aValues)82 void MovingAverageRegressionCurveCalculator::calculateValuesCentral(
83     RegressionCalculationHelper::tDoubleVectorPair aValues)
84 {
85     const size_t aSize = aValues.first.size();
86     for (size_t i = mPeriod - 1; i < aSize; ++i)
87     {
88         double yAvg = 0.0;
89 
90         for (sal_Int32 j = 0; j < mPeriod; j++)
91         {
92             yAvg += aValues.second[i - j];
93         }
94         yAvg /= mPeriod;
95         aYList.push_back(yAvg);
96     }
97     sal_Int32 nPeriodLocal = (mPeriod % 2 == 0) ? (mPeriod / 2) : ((mPeriod - 1) / 2);
98     for (size_t i = nPeriodLocal; i < aSize - 1; ++i)
99     {
100         double x = aValues.first[i];
101         aXList.push_back(x);
102     }
103 }
104 
calculateValues(RegressionCalculationHelper::tDoubleVectorPair aValues,bool bUseXAvg)105 void MovingAverageRegressionCurveCalculator::calculateValues(
106     RegressionCalculationHelper::tDoubleVectorPair aValues, bool bUseXAvg)
107 {
108     const size_t aSize = aValues.first.size();
109     for (size_t i = mPeriod - 1; i < aSize; ++i)
110     {
111         double xAvg = 0.0;
112         double yAvg = 0.0;
113 
114         for (sal_Int32 j = 0; j < mPeriod; j++)
115         {
116             xAvg += aValues.first[i - j];
117             yAvg += aValues.second[i - j];
118         }
119         yAvg /= mPeriod;
120         xAvg /= mPeriod;
121 
122         aYList.push_back(yAvg);
123         if (bUseXAvg)
124         {
125             aXList.push_back(xAvg);
126         }
127         else
128         {
129             double x = aValues.first[i];
130             aXList.push_back(x);
131         }
132     }
133 }
134 
getCurveValue(double)135 double SAL_CALL MovingAverageRegressionCurveCalculator::getCurveValue( double /*x*/ )
136 {
137     double fResult;
138     rtl::math::setNan(&fResult);
139     return fResult;
140 }
141 
getCurveValues(double,double,sal_Int32,const uno::Reference<chart2::XScaling> &,const uno::Reference<chart2::XScaling> &,sal_Bool)142 uno::Sequence< geometry::RealPoint2D > SAL_CALL MovingAverageRegressionCurveCalculator::getCurveValues(
143     double /*min*/, double /*max*/, sal_Int32 /*nPointCount*/,
144     const uno::Reference< chart2::XScaling >& /*xScalingX*/,
145     const uno::Reference< chart2::XScaling >& /*xScalingY*/,
146     sal_Bool /*bMaySkipPointsInCalculation*/ )
147 {
148     size_t nSize = std::min(aXList.size(), aYList.size());
149     uno::Sequence< geometry::RealPoint2D > aResult( nSize );
150 
151     for( size_t i = 0; i < nSize; ++i )
152     {
153         aResult[i].X = aXList[i];
154         aResult[i].Y = aYList[i];
155     }
156     return aResult;
157 }
158 
ImplGetRepresentation(const uno::Reference<util::XNumberFormatter> &,sal_Int32,sal_Int32 *) const159 OUString MovingAverageRegressionCurveCalculator::ImplGetRepresentation(
160     const uno::Reference< util::XNumberFormatter >& /*xNumFormatter*/,
161     sal_Int32 /*nNumberFormatKey*/, sal_Int32* /*pFormulaLength = nullptr */ ) const
162 {
163     return SchResId( STR_OBJECT_MOVING_AVERAGE_WITH_PARAMETERS );
164 }
165 
166 } //  namespace chart
167 
168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
169