summaryrefslogtreecommitdiff
path: root/chart2/source
diff options
context:
space:
mode:
authorKurt Nordback <kurt.nordback@protonmail.com>2022-06-03 15:19:28 -0600
committerNoel Grandin <noel.grandin@collabora.co.uk>2022-07-05 11:52:43 +0200
commit9b558357a3e7a4c908084134d56770809116b4f1 (patch)
tree9d130282d578d6b2545b09b9b9595b23a010a670 /chart2/source
parentdb63000ea7805ddd762521a7cf39de203dbe6c3f (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.cxx60
-rw-r--r--chart2/source/view/charttypes/PieChart.hxx4
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.
*