tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / chart2 / source / tools / StatisticsHelper.cxx
blobe853f1ce49d1cb1379494a3c6df18620372e8e1e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <StatisticsHelper.hxx>
21 #include <DataSeries.hxx>
22 #include <DataSeriesHelper.hxx>
23 #include <ErrorBar.hxx>
24 #include <unonames.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
29 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
30 #include <com/sun/star/chart2/data/XDataProvider.hpp>
31 #include <com/sun/star/chart2/data/XDataSink.hpp>
32 #include <com/sun/star/chart/ErrorBarStyle.hpp>
33 #include <comphelper/diagnose_ex.hxx>
35 #include <cmath>
36 #include <limits>
38 using ::com::sun::star::uno::Sequence;
39 using ::com::sun::star::uno::Reference;
40 using namespace ::com::sun::star;
42 namespace
45 double lcl_getVariance( const Sequence< double > & rData, sal_Int32 & rOutValidCount )
47 const sal_Int32 nCount = rData.getLength();
48 rOutValidCount = nCount;
50 double fSum = 0.0;
51 double fQuadSum = 0.0;
53 for( sal_Int32 i = 0; i < nCount; ++i )
55 const double fData = rData[i];
56 if( std::isnan( fData ))
57 --rOutValidCount;
58 else
60 fSum += fData;
61 fQuadSum += fData * fData;
65 if( rOutValidCount == 0 )
66 return std::numeric_limits<double>::quiet_NaN();
68 const double fN = static_cast< double >( rOutValidCount );
69 return (fQuadSum - fSum*fSum/fN) / fN;
72 uno::Reference< chart2::data::XLabeledDataSequence > lcl_getErrorBarLabeledSequence(
73 const Reference< chart2::data::XDataSource > & xDataSource,
74 bool bPositiveValue, bool bYError,
75 OUString & rOutRoleNameUsed )
77 OUStringBuffer aRole( "error-bars-");
78 if( bYError )
79 aRole.append( 'y');
80 else
81 aRole.append( 'x');
83 OUString aPlainRole = aRole.makeStringAndClear();
84 aRole.append( aPlainRole + "-" );
86 if( bPositiveValue )
87 aRole.append( "positive" );
88 else
89 aRole.append( "negative" );
91 OUString aLongRole = aRole.makeStringAndClear();
92 uno::Reference< chart2::data::XLabeledDataSequence > xLSeq =
93 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aLongRole );
94 // try role without "-negative" or "-positive" postfix
95 if( xLSeq.is())
96 rOutRoleNameUsed = aLongRole;
97 else
99 xLSeq = ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource, aPlainRole );
100 if( xLSeq.is())
101 rOutRoleNameUsed = aPlainRole;
102 else
103 rOutRoleNameUsed = aLongRole;
106 return xLSeq;
109 void lcl_setRole(
110 const Reference< chart2::data::XDataSequence > & xNewSequence,
111 const OUString & rRole )
113 Reference< beans::XPropertySet > xSeqProp( xNewSequence, uno::UNO_QUERY );
114 if( xSeqProp.is())
115 xSeqProp->setPropertyValue( u"Role"_ustr, uno::Any( rRole ));
118 void lcl_addSequenceToDataSource(
119 const Reference< chart2::data::XDataSource > & xDataSource,
120 const Reference< chart2::data::XDataSequence > & xNewSequence,
121 const OUString & rRole )
123 Reference< chart2::data::XDataSink > xSink( xDataSource, uno::UNO_QUERY );
124 const Reference< uno::XComponentContext >& xContext( comphelper::getProcessComponentContext() );
125 if( ! xSink.is() )
126 return;
128 Reference< chart2::data::XLabeledDataSequence > xLSeq( chart2::data::LabeledDataSequence::create(xContext), uno::UNO_QUERY_THROW );
130 lcl_setRole( xNewSequence, rRole );
131 xLSeq->setValues( xNewSequence );
132 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
133 xDataSource->getDataSequences());
134 aSequences.realloc( aSequences.getLength() + 1 );
135 auto pSequences = aSequences.getArray();
136 pSequences[ aSequences.getLength() - 1 ] = std::move(xLSeq);
137 xSink->setData( aSequences );
140 void lcl_setXMLRangePropertyAtDataSequence(
141 const Reference< chart2::data::XDataSequence > & xDataSequence,
142 const OUString & rXMLRange )
146 static constexpr OUString aXMLRangePropName( u"CachedXMLRange"_ustr);
147 Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY_THROW );
148 Reference< beans::XPropertySetInfo > xInfo( xProp->getPropertySetInfo());
149 if( xInfo.is() && xInfo->hasPropertyByName( aXMLRangePropName ))
150 xProp->setPropertyValue( aXMLRangePropName, uno::Any( rXMLRange ));
152 catch( const uno::Exception & )
154 DBG_UNHANDLED_EXCEPTION("chart2");
158 } // anonymous namespace
160 namespace chart
163 double StatisticsHelper::getVariance(
164 const Sequence< double > & rData )
166 sal_Int32 nValCount;
167 return lcl_getVariance( rData, nValCount );
170 double StatisticsHelper::getStandardDeviation( const Sequence< double > & rData )
172 double fResult = getVariance( rData );
173 if( ! std::isnan( fResult ))
174 fResult = sqrt( fResult );
176 return fResult;
179 double StatisticsHelper::getStandardError( const Sequence< double > & rData )
181 sal_Int32 nValCount;
182 double fVar = lcl_getVariance( rData, nValCount );
184 if( nValCount == 0 || std::isnan( fVar ))
185 return std::numeric_limits<double>::quiet_NaN();
186 // standard-deviation / sqrt(n)
187 return sqrt( fVar ) / sqrt( double(nValCount) );
190 uno::Reference< chart2::data::XLabeledDataSequence > StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
191 const Reference< chart2::data::XDataSource > & xDataSource,
192 bool bPositiveValue,
193 bool bYError /* = true */ )
195 uno::Reference< chart2::data::XLabeledDataSequence > xResult;
196 if( !xDataSource.is())
197 return xResult;
199 OUString aRole;
200 uno::Reference< chart2::data::XLabeledDataSequence > xLSeq =
201 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole );
202 if( xLSeq.is())
203 xResult = std::move(xLSeq);
205 return xResult;
208 Reference< chart2::data::XDataSequence > StatisticsHelper::getErrorDataSequenceFromDataSource(
209 const Reference< chart2::data::XDataSource > & xDataSource,
210 bool bPositiveValue,
211 bool bYError /* = true */ )
213 uno::Reference< chart2::data::XLabeledDataSequence > xLSeq =
214 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
215 xDataSource, bPositiveValue,
216 bYError );
217 if( !xLSeq.is())
218 return Reference< chart2::data::XDataSequence >();
220 return xLSeq->getValues();
223 double StatisticsHelper::getErrorFromDataSource(
224 const Reference< chart2::data::XDataSource > & xDataSource,
225 sal_Int32 nIndex,
226 bool bPositiveValue,
227 bool bYError /* = true */ )
229 double fResult = std::numeric_limits<double>::quiet_NaN();
231 Reference< chart2::data::XDataSequence > xValues(
232 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource, bPositiveValue, bYError ));
234 Reference< chart2::data::XNumericalDataSequence > xNumValues( xValues, uno::UNO_QUERY );
235 if( xNumValues.is())
237 Sequence< double > aData( xNumValues->getNumericalData());
238 if( nIndex < aData.getLength())
239 fResult = aData[nIndex];
241 else if( xValues.is())
243 Sequence< uno::Any > aData( xValues->getData());
244 if( nIndex < aData.getLength())
245 aData[nIndex] >>= fResult;
248 return fResult;
251 void StatisticsHelper::setErrorDataSequence(
252 const Reference< chart2::data::XDataSource > & xDataSource,
253 const Reference< chart2::data::XDataProvider > & xDataProvider,
254 const OUString & rNewRange,
255 bool bPositiveValue,
256 bool bYError /* = true */,
257 OUString const * pXMLRange /* = 0 */ )
259 Reference< chart2::data::XDataSink > xDataSink( xDataSource, uno::UNO_QUERY );
260 if( ! ( xDataSink.is() && xDataProvider.is()))
261 return;
263 OUString aRole;
264 Reference< chart2::data::XLabeledDataSequence > xLSeq(
265 lcl_getErrorBarLabeledSequence( xDataSource, bPositiveValue, bYError, aRole ));
266 Reference< chart2::data::XDataSequence > xNewSequence(
267 xDataProvider->createDataSequenceByRangeRepresentation( rNewRange ));
268 if( xNewSequence.is())
270 if( pXMLRange )
271 lcl_setXMLRangePropertyAtDataSequence( xNewSequence, *pXMLRange );
272 if( xLSeq.is())
274 lcl_setRole( xNewSequence, aRole );
275 xLSeq->setValues( xNewSequence );
277 else
278 lcl_addSequenceToDataSource( xDataSource, xNewSequence, aRole );
282 Reference< beans::XPropertySet > StatisticsHelper::addErrorBars(
283 const rtl::Reference< DataSeries > & xDataSeries,
284 sal_Int32 nStyle,
285 bool bYError /* = true */ )
287 Reference< beans::XPropertySet > xErrorBar;
288 if( !xDataSeries.is())
289 return xErrorBar;
291 const OUString aPropName(
292 bYError ? CHART_UNONAME_ERRORBAR_Y : CHART_UNONAME_ERRORBAR_X);
293 if( !( xDataSeries->getPropertyValue( aPropName ) >>= xErrorBar ) ||
294 !xErrorBar.is())
296 xErrorBar.set( new ErrorBar );
299 OSL_ASSERT( xErrorBar.is());
300 if( xErrorBar.is())
302 xErrorBar->setPropertyValue( u"ErrorBarStyle"_ustr, uno::Any( nStyle ));
305 xDataSeries->setPropertyValue( aPropName, uno::Any( xErrorBar ));
307 return xErrorBar;
310 Reference< beans::XPropertySet > StatisticsHelper::getErrorBars(
311 const rtl::Reference< DataSeries > & xDataSeries,
312 bool bYError /* = true */ )
314 Reference< beans::XPropertySet > xErrorBar;
315 const OUString aPropName(
316 bYError ? CHART_UNONAME_ERRORBAR_Y : CHART_UNONAME_ERRORBAR_X);
318 if ( xDataSeries.is())
319 xDataSeries->getPropertyValue( aPropName ) >>= xErrorBar;
321 return xErrorBar;
324 bool StatisticsHelper::hasErrorBars(
325 const rtl::Reference< DataSeries > & xDataSeries,
326 bool bYError /* = true */ )
328 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
329 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
331 return ( xErrorBar.is() &&
332 ( xErrorBar->getPropertyValue( u"ErrorBarStyle"_ustr) >>= nStyle ) &&
333 nStyle != css::chart::ErrorBarStyle::NONE );
336 void StatisticsHelper::removeErrorBars(
337 const rtl::Reference< DataSeries > & xDataSeries,
338 bool bYError /* = true */ )
340 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
341 if ( xErrorBar.is())
342 xErrorBar->setPropertyValue( u"ErrorBarStyle"_ustr, uno::Any(
343 css::chart::ErrorBarStyle::NONE ));
346 bool StatisticsHelper::usesErrorBarRanges(
347 const rtl::Reference< DataSeries > & xDataSeries,
348 bool bYError /* = true */ )
350 Reference< beans::XPropertySet > xErrorBar( getErrorBars( xDataSeries, bYError ));
351 sal_Int32 nStyle = css::chart::ErrorBarStyle::NONE;
353 return ( xErrorBar.is() &&
354 ( xErrorBar->getPropertyValue( u"ErrorBarStyle"_ustr) >>= nStyle ) &&
355 nStyle == css::chart::ErrorBarStyle::FROM_DATA );
358 } // namespace chart
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */