From 70afe780231dc086a07494db97a2bac2ca0a0939 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Tue, 13 Dec 2011 19:46:31 -0500 Subject: fdo#43681: Set correct auto scaling for stacked data series. With this change, the automatic y-axis scaling should be more accurate for stacked charts (i.e. stacked line, area, bar charts) with dates on the x-axis. The previous algorithm only calculated the max and min y-values of the individual data, without taking into account the stacking type when the x-axis type was date. --- chart2/source/view/charttypes/VSeriesPlotter.cxx | 57 +++++++++++++++++------- 1 file changed, 42 insertions(+), 15 deletions(-) (limited to 'chart2') diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index 9a01b9580ca6..2d1c7bba0550 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -1378,7 +1378,7 @@ void VSeriesPlotter::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, d ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotIter = m_aZSlots.begin(); const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end(); - for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ ) + for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter ) { ::std::vector< VDataSeriesGroup >::const_iterator aXSlotIter = aZSlotIter->begin(); const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end(); @@ -1499,16 +1499,24 @@ void VDataSeriesGroup::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaxi if(::rtl::math::isInf(rfMaximum)) ::rtl::math::setNan(&rfMaximum); } -void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const + +void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( + double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const { - const ::std::vector< VDataSeries* >* pSeriesList = &this->m_aSeriesVector; + ::rtl::math::setNan(&rfMinY); + ::rtl::math::setNan(&rfMaxY); - ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin(); - const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end(); + if (m_aSeriesVector.empty()) + // No data series. Bail out. + return; - ::rtl::math::setInf(&rfMinY, false); - ::rtl::math::setInf(&rfMaxY, true); + // Collect minimum y-value and accumulative maximum y-value for each + // x-value first, in case of stacked data series. + typedef boost::unordered_map > MinMaxPerXType; + MinMaxPerXType aStore; + std::vector::const_iterator aSeriesIter = m_aSeriesVector.begin(); + const std::vector::const_iterator aSeriesEnd = m_aSeriesVector.end(); for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter ) { sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount(); @@ -1525,16 +1533,35 @@ void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double fY = (*aSeriesIter)->getYValue( nN ); if( ::rtl::math::isNan(fY) ) continue; - if(rfMaxYfY) - rfMinY=fY; + + MinMaxPerXType::iterator itr = aStore.find(fX); + if (itr == aStore.end()) + aStore.insert(MinMaxPerXType::value_type(fX, std::pair(fY, fY))); + else + { + std::pair& r = itr->second; + if (fY < r.first) + r.first = fY; // min y-value + + r.second += fY; // accumulative max y-value. + } } } - if(::rtl::math::isInf(rfMinY)) - ::rtl::math::setNan(&rfMinY); - if(::rtl::math::isInf(rfMaxY)) - ::rtl::math::setNan(&rfMaxY); + + if (aStore.empty()) + // No data within the specified x range. + return; + + MinMaxPerXType::const_iterator itr = aStore.begin(), itrEnd = aStore.end(); + rfMinY = itr->second.first; + rfMaxY = itr->second.second; + for (++itr; itr != itrEnd; ++itr) + { + if (rfMinY > itr->second.first) + rfMinY = itr->second.first; + if (rfMaxY < itr->second.second) + rfMaxY = itr->second.second; + } } void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex -- cgit