diff options
author | Kurt Nordback <kurt.nordback@protonmail.com> | 2022-06-03 15:19:28 -0600 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-07-05 11:52:43 +0200 |
commit | 9b558357a3e7a4c908084134d56770809116b4f1 (patch) | |
tree | 9d130282d578d6b2545b09b9b9595b23a010a670 /chart2/source | |
parent | db63000ea7805ddd762521a7cf39de203dbe6c3f (diff) |
tdf#104428 Improve rendering of exploded donut charts
This bug shows an exploded donut chart with more than one series. The
concern is that the standard pie/donut' explosion' rendering, with the shape
of the pieces unchanged but the pieces translated outward, gives
unsatisfactory results in the case of a donut with more than one series,
where the translated 'exploded' pieces can overlap with the inner ring.
This proposed fix renders this case differently, by increasing the radius
of the exploded ring but keeping the pieces concentric with the inner ring.
This commit also modifies the unit test values for donut_chart.ods.
Change-Id: I713b1f3ce4697d46d29914410056f0aa83c6aa8b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135394
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'chart2/source')
-rw-r--r-- | chart2/source/view/charttypes/PieChart.cxx | 60 | ||||
-rw-r--r-- | chart2/source/view/charttypes/PieChart.hxx | 4 |
2 files changed, 50 insertions, 14 deletions
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 806bc468414c..a81428c24c15 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -246,17 +246,47 @@ bool PieChart::shouldSnapRectToUsedArea() rtl::Reference<SvxShape> PieChart::createDataPoint( const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const uno::Reference<beans::XPropertySet>& xObjectProperties, - const ShapeParam& rParam ) + const ShapeParam& rParam, + const sal_Int32 nPointCount, + const bool bConcentricExplosion) { //transform position: drawing::Direction3D aOffset; - if (rParam.mfExplodePercentage != 0.0) - { - double fAngle = rParam.mfUnitCircleStartAngleDegree + rParam.mfUnitCircleWidthAngleDegree/2.0; - double fRadius = (rParam.mfUnitCircleOuterRadius-rParam.mfUnitCircleInnerRadius)*rParam.mfExplodePercentage; - drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene(0, 0, rParam.mfLogicZ); - drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene(fAngle, fRadius, rParam.mfLogicZ); - aOffset = aNewOrigin - aOrigin; + double fExplodedInnerRadius = rParam.mfUnitCircleInnerRadius; + double fExplodedOuterRadius = rParam.mfUnitCircleOuterRadius; + double fStartAngle = rParam.mfUnitCircleStartAngleDegree; + double fWidthAngle = rParam.mfUnitCircleWidthAngleDegree; + + if (rParam.mfExplodePercentage != 0.0) { + double fRadius = (fExplodedOuterRadius-fExplodedInnerRadius)*rParam.mfExplodePercentage; + + if (bConcentricExplosion) { + + // For concentric explosion, increase the radius but retain the original + // arc length of all ring segments together. This results in a gap + // that's evenly divided among all segments, assuming they all have + // the same explosion percentage + assert(fExplodedInnerRadius >= 0 && fExplodedOuterRadius > 0); + double fAngleRatio = (fExplodedInnerRadius + fExplodedOuterRadius) / + (fExplodedInnerRadius + fExplodedOuterRadius + 2 * fRadius); + + assert(nPointCount > 0); + double fAngleGap = 360 * (1.0 - fAngleRatio) / nPointCount; + fStartAngle += fAngleGap / 2; + fWidthAngle -= fAngleGap; + + fExplodedInnerRadius += fRadius; + fExplodedOuterRadius += fRadius; + + } else { + // For the non-concentric explosion case, keep the original radius + // but shift the circle origin + double fAngle = fStartAngle + fWidthAngle/2.0; + + drawing::Position3D aOrigin = m_pPosHelper->transformUnitCircleToScene(0, 0, rParam.mfLogicZ); + drawing::Position3D aNewOrigin = m_pPosHelper->transformUnitCircleToScene(fAngle, fRadius, rParam.mfLogicZ); + aOffset = aNewOrigin - aOrigin; + } } //create point @@ -264,16 +294,16 @@ rtl::Reference<SvxShape> PieChart::createDataPoint( if(m_nDimension==3) { xShape = ShapeFactory::createPieSegment( xTarget - , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree - , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius + , fStartAngle, fWidthAngle + , fExplodedInnerRadius, fExplodedOuterRadius , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) , rParam.mfDepth ); } else { xShape = ShapeFactory::createPieSegment2D( xTarget - , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree - , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius + , fStartAngle, fWidthAngle + , fExplodedInnerRadius, fExplodedOuterRadius , aOffset, B3DHomMatrixToHomogenMatrix( m_pPosHelper->getUnitCartesianToScene() ) ); } PropertyMapper::setMappedProperties( *xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); @@ -808,9 +838,13 @@ void PieChart::createShapes() ///create data point aParam.mfLogicZ = -1.0; // For 3D pie chart label position + + // Do concentric explosion if it's a donut chart with more than one series + const bool bConcentricExplosion = m_bUseRings && (m_aZSlots.front().size() > 1); rtl::Reference<SvxShape> xPointShape = createDataPoint( - xSeriesGroupShape_Shapes, xPointProperties, aParam); + xSeriesGroupShape_Shapes, xPointProperties, aParam, nPointCount, + bConcentricExplosion); ///point color: if (!pSeries->hasPointOwnColor(nPointIndex) && m_xColorScheme.is()) diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx index c990cc6e4a13..9a5b7fb4c9d6 100644 --- a/chart2/source/view/charttypes/PieChart.hxx +++ b/chart2/source/view/charttypes/PieChart.hxx @@ -67,7 +67,9 @@ private: //methods createDataPoint( const rtl::Reference<SvxShapeGroupAnyD>& xTarget, const css::uno::Reference<css::beans::XPropertySet>& xObjectProperties, - const ShapeParam& rParam ); + const ShapeParam& rParam, + const sal_Int32 nPointCount, + const bool bConcentricExplosion); /** This method creates a text shape for a label of a data point. * |