chart2/source/view/charttypes/PieChart.cxx |   83 ++++++++++++++++++++++++++---
 1 file changed, 76 insertions(+), 7 deletions(-)

New commits:
commit e1573deaf1b2ecd946d23a4ce623546c08036ec7
Author:     Kurt Nordback <kurt.nordb...@protonmail.com>
AuthorDate: Mon Nov 20 11:46:10 2023 -0700
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Sun Feb 18 07:33:18 2024 +0100

    tdf#50934: Implement connector lines for pie-of-pie
    
    Change-Id: Ifca083aa07b28d5c604382decaefedfe653ff8ab
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160731
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/chart2/source/view/charttypes/PieChart.cxx 
b/chart2/source/view/charttypes/PieChart.cxx
index a946616ea5fe..9b1494596598 100644
--- a/chart2/source/view/charttypes/PieChart.cxx
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -928,20 +928,26 @@ void PieChart::createShapes()
             createOneBar(SubPieType::RIGHT, aParam, xSeriesTarget,
                     xTextTarget, pSeries, pDataSrc, n3DRelativeHeight);
 
-            // draw connecting lines
+            //
+            // Draw connecting lines
+            //
             double xl0, xl1, yl0, yl1, x0, y0, x1, y1, y2, y3;
 
-            if (m_aPosHelper.m_fAngleDegreeOffset < 90.0) {
+            // Get coordinates of "corners" of left composite wedge
+            sal_Int32 nEnd = pDataSrc->getNPoints(pSeries, SubPieType::LEFT);
+            double compFrac = pDataSrc->getData(pSeries, nEnd - 1,
+                    SubPieType::LEFT) / aParam.mfLogicYSum;
+            if (compFrac < 0.5) {
                 xl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale *
-                    cos(m_aPosHelper.m_fAngleDegreeOffset * M_PI / 180) +
-                    m_fLeftShift;
+                    cos(compFrac * M_PI) + m_fLeftShift;
                 yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale *
-                    sin(m_aPosHelper.m_fAngleDegreeOffset * M_PI / 180);
+                    sin(compFrac * M_PI);
             } else {
                 xl0 = m_fLeftShift;
                 yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale;
             }
 
+            // Coordinates of bar top left corner
             xl1 = m_fBarLeft;
             yl1 = m_fFullBarHeight / 2;
 
@@ -974,12 +980,75 @@ void PieChart::createShapes()
             break;
         }
         case PieChartSubType_PIE:
+        {
             pDataSrc = &ofPieSrc;
             createOneRing(SubPieType::LEFT, 0, aParam, xSeriesTarget,
                     xTextTarget, pSeries, pDataSrc, n3DRelativeHeight);
             createOneRing(SubPieType::RIGHT, 0, aParam, xSeriesTarget,
                     xTextTarget, pSeries, pDataSrc, n3DRelativeHeight);
+
+            //
+            // Draw connecting lines
+            //
+            double xl0, xl1, yl0, yl1, x0, y0, x1, y1, y2, y3;
+
+            // Get coordinates of "corners" of left composite wedge
+            sal_Int32 nEnd = pDataSrc->getNPoints(pSeries, SubPieType::LEFT);
+            double compFrac = pDataSrc->getData(pSeries, nEnd - 1,
+                    SubPieType::LEFT) / aParam.mfLogicYSum;
+            if (compFrac < 0.5) {
+                // Translated, per below
+                xl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale *
+                    cos(compFrac * M_PI) + m_fLeftShift - m_fRightShift;
+                yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale *
+                    sin(compFrac * M_PI);
+            } else {
+                // Translated, per below
+                xl0 = m_fLeftShift - m_fRightShift;
+                yl0 = aParam.mfUnitCircleOuterRadius * m_fLeftScale;
+            }
+
+            // Compute tangent point on the right-hand circle of the line
+            // through (xl0, yl0). If we translate things so the right-hand
+            // circle is centered on the origin, then this point (x,y)
+            // satisfies these two equations, where r is the radius of the
+            // right-hand circle:
+            // (1) x^2 + y^2 = r^2
+            // (2) (y - yl0) / (x - xl0) = -x / y
+            const double r = aParam.mfUnitCircleOuterRadius * m_fRightScale;
+
+            xl1 = (r*r * xl0 + yl0 * r * sqrt(xl0*xl0 + yl0*yl0 - r*r)) /
+                (xl0*xl0 + yl0*yl0);
+            yl1 = sqrt(r*r - xl1*xl1);
+
+            // Now translate back to the coordinates we use
+            xl0 += m_fRightShift;
+            xl1 += m_fRightShift;
+
+            x0 = m_aPosHelper.transformUnitCircleToScene(0, xl0, 0).PositionX;
+            y0 = m_aPosHelper.transformUnitCircleToScene(90, yl0, 0).PositionY;
+            x1 = m_aPosHelper.transformUnitCircleToScene(0, xl1, 0).PositionX;
+            y1 = m_aPosHelper.transformUnitCircleToScene(90, yl1, 0).PositionY;
+            y2 = m_aPosHelper.transformUnitCircleToScene(90, -yl0, 
0).PositionY;
+            y3 = m_aPosHelper.transformUnitCircleToScene(90, -yl1, 
0).PositionY;
+
+            std::vector<std::vector<css::drawing::Position3D>> linePts;
+            linePts.resize(2);
+            linePts[0].push_back(css::drawing::Position3D(x0, y0, 
aParam.mfLogicZ));
+            linePts[0].push_back(css::drawing::Position3D(x1, y1, 
aParam.mfLogicZ));
+            linePts[1].push_back(css::drawing::Position3D(x0, y2, 
aParam.mfLogicZ));
+            linePts[1].push_back(css::drawing::Position3D(x1, y3, 
aParam.mfLogicZ));
+
+            VLineProperties aVLineProperties;   // default black
+
+            //create line
+            rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes =
+                getSeriesGroupShape(pSeries, xSeriesTarget);
+            rtl::Reference<SvxShape> xShape = ShapeFactory::createLine2D(
+                    xSeriesGroupShape_Shapes, linePts, &aVLineProperties);
+
             break;
+        }
         default:
             assert(false); // this shouldn't happen
         }
@@ -1104,9 +1173,9 @@ void PieChart::createOneRing([[maybe_unused]]enum 
SubPieType eType,
                         bConcentricExplosion);
 
             // Handle coloring of the composite wedge
-            sal_Int32 nEnd = pDataSrc->getNPoints(pSeries, eType);
             const sal_Int32 nPropIdx = (
-                    eType == SubPieType::LEFT && nPointIndex == nEnd - 1 ?
+                    eType == SubPieType::LEFT &&
+                    nPointIndex == pDataSrc->getNPoints(pSeries, 
SubPieType::LEFT) - 1 ?
                     pSeries->getTotalPointCount() :
                     nPointIndex);
             ///point color:

Reply via email to