chart2/source/inc/ChartType.hxx | 9 - chart2/source/inc/DataSeries.hxx | 1 chart2/source/model/main/DataSeries.cxx | 5 chart2/source/model/template/ChartType.cxx | 12 + chart2/source/model/template/HistogramChartType.cxx | 85 ++++++++++++++ chart2/source/model/template/HistogramChartType.hxx | 2 chart2/source/model/template/HistogramDataInterpreter.cxx | 71 ----------- 7 files changed, 114 insertions(+), 71 deletions(-)
New commits: commit dac249a0de613cce6c3f3de756cd1a0c8464f38c Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Aug 16 09:48:19 2024 +0200 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sat Aug 17 11:19:03 2024 +0200 chart2: move histogram calcualtion into HistogramChartType Histogram is special in the way that the input data is not the data that is being shown in the chart - it needs to be calculated separately usign the input data. First we put the calculation in the (Histogram)DataInterpreter but that is not a very good place to calculate as we don't have the access to the chart properties and can't influence the calculation with it. This change puts the calculation into (Histogram)ChartType instead and will trigger the calculation when the data is requested. This is the first case of such a thing where we calculate the data on demand from the input data, so we will probably need further changes the chart code to better support calculated data sequences. Change-Id: Ia66f9d245f7d42973c728e1dd9a406b66eb2610a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171952 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/chart2/source/inc/ChartType.hxx b/chart2/source/inc/ChartType.hxx index 302e2187aff1..7b1fccfb159e 100644 --- a/chart2/source/inc/ChartType.hxx +++ b/chart2/source/inc/ChartType.hxx @@ -109,11 +109,13 @@ public: const rtl::Reference< ::chart::DataSeries >& aDataSeries ); void setDataSeries( const std::vector< rtl::Reference< ::chart::DataSeries > >& aDataSeries ); - const std::vector< rtl::Reference< ::chart::DataSeries > > & getDataSeries2() const { return m_aDataSeries; } + + const std::vector<rtl::Reference<::chart::DataSeries>>& getDataSeries2() const; virtual rtl::Reference< ::chart::BaseCoordinateSystem > createCoordinateSystem2( sal_Int32 DimensionCount ); + virtual void createCalculatedDataSeries(); protected: // ____ XModifyListener ____ @@ -147,9 +149,8 @@ private: void impl_addDataSeriesWithoutNotification( const rtl::Reference< ::chart::DataSeries >& aDataSeries ); -private: - typedef - std::vector< rtl::Reference< ::chart::DataSeries > > tDataSeriesContainerType; +protected: + typedef std::vector<rtl::Reference<::chart::DataSeries>> tDataSeriesContainerType; // --- mutable members: the following members need mutex guard --- diff --git a/chart2/source/inc/DataSeries.hxx b/chart2/source/inc/DataSeries.hxx index 3705ea3fdab4..be4c0b5c68b4 100644 --- a/chart2/source/inc/DataSeries.hxx +++ b/chart2/source/inc/DataSeries.hxx @@ -136,6 +136,7 @@ public: void setData( const tDataSequenceContainer& aData ); const tDataSequenceContainer & getDataSequences2() const { return m_aDataSequences; } + void addDataSequence(css::uno::Reference<css::chart2::data::XLabeledDataSequence> const& rSequence); typedef std::vector< rtl::Reference< ::chart::RegressionCurveModel > > diff --git a/chart2/source/model/main/DataSeries.cxx b/chart2/source/model/main/DataSeries.cxx index cc207badd19d..2650bb69c281 100644 --- a/chart2/source/model/main/DataSeries.cxx +++ b/chart2/source/model/main/DataSeries.cxx @@ -416,6 +416,11 @@ void DataSeries::setData( const std::vector< uno::Reference< chart2::data::XLabe fireModifyEvent(); } +void DataSeries::addDataSequence(css::uno::Reference<css::chart2::data::XLabeledDataSequence> const& rSequence) +{ + m_aDataSequences.push_back(rSequence); +} + // ____ XDataSource ____ Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL DataSeries::getDataSequences() { diff --git a/chart2/source/model/template/ChartType.cxx b/chart2/source/model/template/ChartType.cxx index 7e6d0bf86a5c..e2bf5e97e61b 100644 --- a/chart2/source/model/template/ChartType.cxx +++ b/chart2/source/model/template/ChartType.cxx @@ -183,6 +183,11 @@ Sequence< Reference< chart2::XDataSeries > > SAL_CALL ChartType::getDataSeries() return comphelper::containerToSequence< Reference< chart2::XDataSeries > >( m_aDataSeries ); } +const std::vector<rtl::Reference<::chart::DataSeries>>& ChartType::getDataSeries2() const +{ + return m_aDataSeries; +} + void SAL_CALL ChartType::setDataSeries( const Sequence< Reference< chart2::XDataSeries > >& aDataSeries ) { std::vector< rtl::Reference<DataSeries> > aTmp; @@ -216,6 +221,13 @@ void ChartType::setDataSeries( const std::vector< rtl::Reference< DataSeries > > } m_bNotifyChanges = true; fireModifyEvent(); + + createCalculatedDataSeries(); +} + +void ChartType::createCalculatedDataSeries() +{ + } // ____ OPropertySet ____ diff --git a/chart2/source/model/template/HistogramChartType.cxx b/chart2/source/model/template/HistogramChartType.cxx index 51cb79960caa..91304e42e14f 100644 --- a/chart2/source/model/template/HistogramChartType.cxx +++ b/chart2/source/model/template/HistogramChartType.cxx @@ -14,6 +14,10 @@ #include <Axis.hxx> #include <AxisHelper.hxx> #include <AxisIndexDefines.hxx> +#include <DataSeries.hxx> +#include <LabeledDataSequence.hxx> +#include <HistogramDataSequence.hxx> +#include "HistogramCalculator.hxx" #include <com/sun/star/chart2/AxisType.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> #include <cppuhelper/supportsservice.hxx> @@ -199,6 +203,87 @@ css::uno::Sequence<OUString> SAL_CALL HistogramChartType::getSupportedServiceNam return { CHART2_SERVICE_NAME_CHARTTYPE_HISTOGRAM, "com.sun.star.chart2.ChartType" }; } +namespace +{ +void setRoleToTheSequence(uno::Reference<chart2::data::XDataSequence> const& xSequence, + OUString const& rRole) +{ + if (!xSequence.is()) + return; + try + { + uno::Reference<beans::XPropertySet> xProperty(xSequence, uno::UNO_QUERY_THROW); + xProperty->setPropertyValue(u"Role"_ustr, uno::Any(rRole)); + } + catch (const uno::Exception&) + { + } +} +} + +void HistogramChartType::createCalculatedDataSeries() +{ + if (m_aDataSeries.empty()) + return; + + std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> const& aDataSequences + = m_aDataSeries[0]->getDataSequences2(); + + if (aDataSequences.empty() || !aDataSequences[0].is()) + return; + + // Extract raw data from the spreadsheet + std::vector<double> rawData; + uno::Reference<chart2::data::XDataSequence> xValues = aDataSequences[0]->getValues(); + + uno::Sequence<uno::Any> aRawAnyValues = xValues->getData(); + for (const auto& aAny : aRawAnyValues) + { + double fValue = 0.0; + if (aAny >>= fValue) // Extract double from Any + { + rawData.push_back(fValue); + } + } + + // Perform histogram calculations + HistogramCalculator aHistogramCalculator; + aHistogramCalculator.computeBinFrequencyHistogram(rawData); + + // Get bin ranges and frequencies + const auto& binRanges = aHistogramCalculator.getBinRanges(); + const auto& binFrequencies = aHistogramCalculator.getBinFrequencies(); + + // Create labels and values for HistogramDataSequence + std::vector<OUString> aLabels; + std::vector<double> aValues; + for (size_t i = 0; i < binRanges.size(); ++i) + { + OUString aLabel; + if (i == 0) + { + aLabel = u"["_ustr + OUString::number(binRanges[i].first) + u"-"_ustr + + OUString::number(binRanges[i].second) + u"]"_ustr; + } + else + { + aLabel = u"("_ustr + OUString::number(binRanges[i].first) + u"-"_ustr + + OUString::number(binRanges[i].second) + u"]"_ustr; + } + aLabels.push_back(aLabel); + aValues.push_back(static_cast<double>(binFrequencies[i])); + } + + rtl::Reference<HistogramDataSequence> aValuesDataSequence = new HistogramDataSequence(); + aValuesDataSequence->setValues(comphelper::containerToSequence(aValues)); + aValuesDataSequence->setLabels(comphelper::containerToSequence(aLabels)); + + uno::Reference<chart2::data::XDataSequence> aDataSequence = aValuesDataSequence; + setRoleToTheSequence(aDataSequence, u"values-y"_ustr); + + m_aDataSeries[0]->addDataSequence(new LabeledDataSequence(aDataSequence)); +} + } // namespace chart extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* diff --git a/chart2/source/model/template/HistogramChartType.hxx b/chart2/source/model/template/HistogramChartType.hxx index fa71b4196c90..621c153a2d61 100644 --- a/chart2/source/model/template/HistogramChartType.hxx +++ b/chart2/source/model/template/HistogramChartType.hxx @@ -25,6 +25,8 @@ public: virtual rtl::Reference<ChartType> cloneChartType() const override; + void createCalculatedDataSeries() override; + protected: explicit HistogramChartType(const HistogramChartType& rOther); diff --git a/chart2/source/model/template/HistogramDataInterpreter.cxx b/chart2/source/model/template/HistogramDataInterpreter.cxx index 43ccc5ee3d92..c78f3b298b33 100644 --- a/chart2/source/model/template/HistogramDataInterpreter.cxx +++ b/chart2/source/model/template/HistogramDataInterpreter.cxx @@ -27,13 +27,14 @@ namespace chart { InterpretedData HistogramDataInterpreter::interpretDataSource( const uno::Reference<chart2::data::XDataSource>& xSource, - const uno::Sequence<beans::PropertyValue>& /*aArguments*/, - const std::vector<rtl::Reference<DataSeries>>& /*aSeriesToReUse*/) + const uno::Sequence<beans::PropertyValue>& aArguments, + const std::vector<rtl::Reference<DataSeries>>& aSeriesToReUse) { if (!xSource.is()) return InterpretedData(); - InterpretedData aInterpretedData; + InterpretedData aInterpretedData( + DataInterpreter::interpretDataSource(xSource, aArguments, aSeriesToReUse)); std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aData = DataInterpreter::getDataSequences(xSource); @@ -43,70 +44,6 @@ InterpretedData HistogramDataInterpreter::interpretDataSource( SetRole(aData[0]->getValues(), u"values-y-original"_ustr); - // Extract raw data from the spreadsheet - std::vector<double> rawData; - uno::Reference<chart2::data::XDataSequence> xValues = aData[0]->getValues(); - if (!xValues.is()) - return InterpretedData(); - - uno::Sequence<uno::Any> aRawAnyValues = xValues->getData(); - - for (const auto& aAny : aRawAnyValues) - { - double fValue = 0.0; - if (aAny >>= fValue) // Extract double from Any - { - rawData.push_back(fValue); - } - } - - // Perform histogram calculations - HistogramCalculator aHistogramCalculator; - aHistogramCalculator.computeBinFrequencyHistogram(rawData); - - // Get bin ranges and frequencies - const auto& binRanges = aHistogramCalculator.getBinRanges(); - const auto& binFrequencies = aHistogramCalculator.getBinFrequencies(); - - // Create labels and values for HistogramDataSequence - std::vector<OUString> aLabels; - std::vector<double> aValues; - for (size_t i = 0; i < binRanges.size(); ++i) - { - OUString aLabel; - if (i == 0) - { - aLabel = u"["_ustr + OUString::number(binRanges[i].first) + u"-"_ustr - + OUString::number(binRanges[i].second) + u"]"_ustr; - } - else - { - aLabel = u"("_ustr + OUString::number(binRanges[i].first) + u"-"_ustr - + OUString::number(binRanges[i].second) + u"]"_ustr; - } - aLabels.push_back(aLabel); - aValues.push_back(static_cast<double>(binFrequencies[i])); - } - - rtl::Reference<DataSeries> xSeries = new DataSeries; - std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aNewData; - aNewData.push_back(aData[0]); - - rtl::Reference<HistogramDataSequence> aValuesDataSequence = new HistogramDataSequence(); - aValuesDataSequence->setValues(comphelper::containerToSequence(aValues)); - aValuesDataSequence->setLabels(comphelper::containerToSequence(aLabels)); - - uno::Reference<chart2::data::XDataSequence> aDataSequence = aValuesDataSequence; - SetRole(aDataSequence, u"values-y"_ustr); - aNewData.push_back(new LabeledDataSequence(aDataSequence)); - - xSeries->setData(aNewData); - std::vector<rtl::Reference<DataSeries>> aSeriesVec; - aSeriesVec.push_back(xSeries); - - aInterpretedData.Series.push_back(aSeriesVec); - aInterpretedData.Categories = nullptr; - return aInterpretedData; }