chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt |   10 -
 chart2/source/view/charttypes/PieChart.cxx                         |   60 
+++++++---
 chart2/source/view/charttypes/PieChart.hxx                         |    4 
 3 files changed, 55 insertions(+), 19 deletions(-)

New commits:
commit 597bc417192fd9eac58c3cca9527ce5646d9972f
Author:     Kurt Nordback <kurt.nordb...@protonmail.com>
AuthorDate: Fri Jun 3 15:19:28 2022 -0600
Commit:     Adolfo Jayme Barrientos <fit...@ubuntu.com>
CommitDate: Tue Jul 5 18:25:24 2022 +0200

    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.gran...@collabora.co.uk>
    (cherry picked from commit 9b558357a3e7a4c908084134d56770809116b4f1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136765
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt 
b/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt
index b2dfd33295a2..c1af41103de5 100644
--- a/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt
+++ b/chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt
@@ -35,15 +35,15 @@
 16728590
 /// /D=0:CS=0:CT=0:Series=0:Point=2
 // aSlicePosition.X
-8909
+9033
 // aSlicePosition.Y
-4532
+4635
 // aSliceSize.Height
-4689
+4659
 // aSliceSize.Width
-2544
+2458
 // aSliceTransformation
-2544;0;8909;0;4689;4532;0;0;1
+2458;0;9033;0;4659;4635;0;0;1
 // static_cast<sal_Int32>(aSliceFillStyle)
 1
 // static_cast<sal_Int32>(aSliceFillColor)
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.
      *

Reply via email to