summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKurt Nordback <kurt.nordback@protonmail.com>2022-06-03 15:19:28 -0600
committerAdolfo Jayme Barrientos <fitojb@ubuntu.com>2022-07-05 18:25:24 +0200
commit597bc417192fd9eac58c3cca9527ce5646d9972f (patch)
treec36a8d5d3ea8abf29a0e1118401e3408f99a805b
parenttdf#117646: Clone Formatting not working for connector lines (diff)
downloadcore-597bc417192fd9eac58c3cca9527ce5646d9972f.tar.gz
core-597bc417192fd9eac58c3cca9527ce5646d9972f.zip
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> (cherry picked from commit 9b558357a3e7a4c908084134d56770809116b4f1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136765 Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
-rw-r--r--chart2/qa/extras/chart2dump/reference/piecharttest/donut_chart.txt10
-rw-r--r--chart2/source/view/charttypes/PieChart.cxx60
-rw-r--r--chart2/source/view/charttypes/PieChart.hxx4
3 files changed, 55 insertions, 19 deletions
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.
*