chart2/source/view/charttypes/PieChart.cxx | 167 ++++++++++++++----- chart2/source/view/charttypes/PieChart.hxx | 18 +- chart2/source/view/inc/PlottingPositionHelper.hxx | 13 + chart2/source/view/inc/PolarLabelPositionHelper.hxx | 3 chart2/source/view/main/PlottingPositionHelper.cxx | 7 chart2/source/view/main/PolarLabelPositionHelper.cxx | 15 + 6 files changed, 168 insertions(+), 55 deletions(-)
New commits: commit d0092c5627f3dc2db33846e3b81ce19780372529 Author: Kurt Nordback <kurt.nordb...@protonmail.com> AuthorDate: Wed Jun 26 06:27:12 2024 -0600 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Sat Aug 17 08:19:39 2024 +0200 tdf#161230 - Pie-of-pie and bar-of-pie chart data labels are misaligned Implementing label support for of-pie charts. This involves using the existing pie label code with an added horizontal shift, and adding special (simple) handling for the bars in bar-of-pie. This also fixes tdf#161228 Change-Id: Ifc7c1f28548caf216aba5c7dc411d05a0c9d8726 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169566 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 2db56c84a5bd..4bda2129817d 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -313,14 +313,14 @@ rtl::Reference<SvxShape> PieChart::createDataPoint( aOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0, rParam.mfLogicZ); aNewOrigin = m_aPosHelper.transformUnitCircleToScene(180, 0.75, rParam.mfLogicZ); aOffset = aNewOrigin - aOrigin; - fExplodedOuterRadius *= 2.0/3; + fExplodedOuterRadius *= m_fLeftScale; break; case SubPieType::RIGHT: // Draw the sub-pie for pie-of-pie much smaller and to the right aOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0, rParam.mfLogicZ); aNewOrigin = m_aPosHelper.transformUnitCircleToScene(0, 0.75, rParam.mfLogicZ); aOffset = aNewOrigin - aOrigin; - fExplodedOuterRadius *= 1.0/3; + fExplodedOuterRadius *= m_fRightScale; break; case SubPieType::NONE: default: @@ -357,31 +357,13 @@ rtl::Reference<SvxShape> PieChart::createBarDataPoint( const ShapeParam& rParam, double fBarSegBottom, double fBarSegTop) { - drawing::Position3D aP0, aP1; - // Draw the bar for bar-of-pie small and to the right. Width and // position are hard-coded for now. -#if 0 - aP0 = cartesianPosHelper.transformLogicToScene(0.75, fBarSegBottom, - rParam.mfLogicZ, false); - aP1 = cartesianPosHelper.transformLogicToScene(1.25, fBarSegTop, - rParam.mfLogicZ, false); -#else - double x0 = m_aPosHelper.transformUnitCircleToScene(0, 0.75, 0).PositionX; - double x1 = m_aPosHelper.transformUnitCircleToScene(0, 1.25, 0).PositionX; - double y0 = m_aPosHelper.transformUnitCircleToScene( - 90, fBarSegBottom, 0).PositionY; - double y1 = m_aPosHelper.transformUnitCircleToScene( - 90, fBarSegTop, 0).PositionY; - - aP0 = drawing::Position3D(x0, y0, rParam.mfLogicZ); - aP1 = drawing::Position3D(x1, y1, rParam.mfLogicZ); -#endif + css::awt::Point aPos; + css::awt::Size aSz; - const css::awt::Point aPos(aP0.PositionX, aP1.PositionY); - const css::awt::Size aSz(fabs(aP0.PositionX - aP1.PositionX), - fabs(aP0.PositionY - aP1.PositionY)); + getBarRect(&aPos, &aSz, fBarSegBottom, fBarSegTop, rParam); const tNameSequence emptyNameSeq; const tAnySequence emptyValSeq; @@ -395,9 +377,28 @@ rtl::Reference<SvxShape> PieChart::createBarDataPoint( return xShape; } +void PieChart::getBarRect(css::awt::Point *pPos, css::awt::Size *pSz, + double fBarBottom, double fBarTop, const ShapeParam& rParam) const +{ + double x0 = m_aPosHelper.transformUnitCircleToScene(0, m_fBarLeft, 0).PositionX; + double x1 = m_aPosHelper.transformUnitCircleToScene(0, m_fBarRight, 0).PositionX; + double y0 = m_aPosHelper.transformUnitCircleToScene( + 90, fBarBottom, 0).PositionY; + double y1 = m_aPosHelper.transformUnitCircleToScene( + 90, fBarTop, 0).PositionY; + + drawing::Position3D aP0(x0, y0, rParam.mfLogicZ); + drawing::Position3D aP1(x1, y1, rParam.mfLogicZ); + + *pPos = css::awt::Point(aP0.PositionX, aP1.PositionY); + *pSz = css::awt::Size(fabs(aP0.PositionX - aP1.PositionX), + fabs(aP0.PositionY - aP1.PositionY)); +} + void PieChart::createTextLabelShape( const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, - VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam ) + VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam , + enum SubPieType eType) { if (!rSeries.getDataPointLabelIfLabel(nPointIndex)) // There is no text label for this data point. Nothing to do. @@ -449,6 +450,24 @@ void PieChart::createTextLabelShape( else if( nLabelPlacement == css::chart::DataLabelPlacement::INSIDE ) nScreenValueOffsetInRadiusDirection = (m_nDimension!=3) ? -150 : 0;//todo maybe calculate this font height dependent + double fRadiusScale; + double fXShift; + switch (eType) { + case SubPieType::LEFT: + fRadiusScale = m_fLeftScale; + fXShift = m_fLeftShift; + break; + case SubPieType::RIGHT: + fRadiusScale = m_fRightScale; + fXShift = m_fRightShift; + break; + default: + fRadiusScale = 1.0; + fXShift = 0; + } + + ::basegfx::B3DVector aShift(fXShift, 0, 0); + ///the scene position of the label anchor point is calculated (see notes for ///`PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues`), ///and immediately transformed into the screen position. @@ -456,12 +475,15 @@ void PieChart::createTextLabelShape( awt::Point aScreenPosition2D( aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues(eAlignment, nLabelPlacement , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree - , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius, rParam.mfLogicZ+0.5, 0 )); + , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius * fRadiusScale + , rParam.mfLogicZ+0.5, 0, aShift)); ///the screen position of the pie/donut center is calculated. PieLabelInfo aPieLabelInfo; aPieLabelInfo.aFirstPosition = basegfx::B2IVector( aScreenPosition2D.X, aScreenPosition2D.Y ); - awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( m_aPosHelper.transformUnitCircleToScene( 0.0, 0.0, rParam.mfLogicZ+1.0 ) ) ); + awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( + m_aPosHelper.transformUnitCircleToScene( 0.0, 0.0, + rParam.mfLogicZ+1.0, aShift ) ) ); aPieLabelInfo.aOrigin = basegfx::B2IVector( aOrigin.X, aOrigin.Y ); ///add a scaling independent Offset if requested @@ -477,8 +499,9 @@ void PieChart::createTextLabelShape( awt::Point aOuterCirclePoint = PlottingPositionHelper::transformSceneToScreenPosition( m_aPosHelper.transformUnitCircleToScene( 0, - rParam.mfUnitCircleOuterRadius, - 0 ), + rParam.mfUnitCircleOuterRadius * fRadiusScale, + 0 , + aShift), m_xLogicTarget, m_nDimension ); basegfx::B2IVector aRadiusVector( aOuterCirclePoint.X - aPieLabelInfo.aOrigin.getX(), @@ -493,7 +516,8 @@ void PieChart::createTextLabelShape( // aOuterPosition: slice midpoint on the circumference, // which is where an outside/custom label would be connected awt::Point aOuterPosition = PlottingPositionHelper::transformSceneToScreenPosition( - m_aPosHelper.transformUnitCircleToScene(fAngleDegree, rParam.mfUnitCircleOuterRadius, 0), + m_aPosHelper.transformUnitCircleToScene(fAngleDegree, + rParam.mfUnitCircleOuterRadius * fRadiusScale, 0, aShift), m_xLogicTarget, m_nDimension); aPieLabelInfo.aOuterPosition = basegfx::B2IVector(aOuterPosition.X, aOuterPosition.Y); @@ -579,7 +603,8 @@ void PieChart::createTextLabelShape( * is crucial (and currently lacking)! * TODO: * change bestFit to treat the width as a max width, and reduce if beneficial */ - if (!performLabelBestFitInnerPlacement(rParam, aPieLabelInfo)) + if (!performLabelBestFitInnerPlacement(rParam, aPieLabelInfo, + fRadiusScale, aShift)) { if (m_aAvailableOuterRect.getWidth()) { @@ -620,7 +645,8 @@ void PieChart::createTextLabelShape( eAlignment, css::chart::DataLabelPlacement::OUTSIDE, rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree, rParam.mfUnitCircleInnerRadius, - rParam.mfUnitCircleOuterRadius, rParam.mfLogicZ + 0.5, 0); + rParam.mfUnitCircleOuterRadius * fRadiusScale, + rParam.mfLogicZ + 0.5, 0, aShift); aPieLabelInfo.aFirstPosition = basegfx::B2IVector(aScreenPosition2D.X, aScreenPosition2D.Y); @@ -726,6 +752,58 @@ void PieChart::createTextLabelShape( m_aLabelInfoList.push_back(aPieLabelInfo); } +// Put labels in one bar of a bar-of-pie chart. This is quite basic and doesn't +// deal with the possibility of the bar being too small for the label text. +void PieChart::createBarLabelShape( + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, + VDataSeries& rSeries, sal_Int32 nPointIndex, double fBarBottom, + double fBarTop, ShapeParam& rParam) +{ + if (!rSeries.getDataPointLabelIfLabel(nPointIndex)) + // There is no text label for this data point. Nothing to do. + return; + + // Ignore the label placement specification, and just center all labels + const LabelAlignment eAlignment(LABEL_ALIGN_CENTER); + + css::awt::Point aPos; + css::awt::Size aSz; + + getBarRect(&aPos, &aSz, fBarBottom, fBarTop, rParam); + + // The screen position of the label anchor point is the center of the bar + awt::Point aScreenPosition2D( + aPos.X + aSz.Width/2.0, + aPos.Y + aSz.Height/2.0); + + const double fTextMaximumFrameWidth = 0.8 * (m_fBarRight - m_fBarLeft); + const sal_Int32 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth); + + ///the text shape for the label is created + PieLabelInfo aPieLabelInfo; + const double nVal = rSeries.getYValue(nPointIndex); + aPieLabelInfo.xTextShape = createDataLabel( + xTextTarget, rSeries, nPointIndex, nVal, rParam.mfLogicYSum, + aScreenPosition2D, eAlignment, 0, nTextMaximumFrameWidth); + + ///a new `PieLabelInfo` instance is initialized with all the info related to + ///the current label in order to simplify later label position rearrangement; + rtl::Reference< SvxShape > xChild = aPieLabelInfo.xTextShape; + + ///text shape could be empty; in that case there is no need to add label info + if( !xChild.is() ) + return; + + aPieLabelInfo.xLabelGroupShape = dynamic_cast<SvxShapeGroupAnyD*>(xChild->getParent().get()); + aPieLabelInfo.fValue = nVal; + aPieLabelInfo.bMovementAllowed = false; + aPieLabelInfo.bMoved = false; + aPieLabelInfo.xTextTarget = xTextTarget; + aPieLabelInfo.bShowLeaderLine = false; + + m_aLabelInfoList.push_back(aPieLabelInfo); +} + void PieChart::addSeries( std::unique_ptr<VDataSeries> pSeries, sal_Int32 /* zSlot */, sal_Int32 /* xSlot */, sal_Int32 /* ySlot */ ) { VSeriesPlotter::addSeries( std::move(pSeries), 0, -1, 0 ); @@ -1269,8 +1347,11 @@ void PieChart::createOneRing( } } - ///create label - createTextLabelShape(xTextTarget, *pSeries, nPropIdx, aParam); + ///create label, *except* for composite wedge + if (!(eType == SubPieType::LEFT && nPointIndex == pDataSrc->getNPoints(pSeries, + SubPieType::LEFT) - 1)) { + createTextLabelShape(xTextTarget, *pSeries, nPropIdx, aParam, eType); + } if(!bDoExplode) { @@ -1383,7 +1464,8 @@ void PieChart::createOneBar( } ///create label - createTextLabelShape(xTextTarget, *pSeries, nPropIdx, aParam); + createBarLabelShape(xTextTarget, *pSeries, nPropIdx, fBarBottom, + fBarTop, aParam); ShapeFactory::setShapeName( xPointShape, ObjectIdentifier::createPointCID( pSeries->getPointCID_Stub(), @@ -1879,7 +1961,9 @@ void PieChart::rearrangeLabelToAvoidOverlapIfRequested( const awt::Size& rPageSi * 4. the top edge when 225 < alpha < 315. * **/ -bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLabelInfo const & rPieLabelInfo) +bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, + PieLabelInfo const & rPieLabelInfo, double fRadiusScale, + const ::basegfx::B3DVector& aShift) { SAL_INFO( "chart2.pie.label.bestfit.inside", "** PieChart::performLabelBestFitInnerPlacement invoked **" ); @@ -1892,12 +1976,13 @@ bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLab // get the middle point of the arc representing the pie slice border double fLogicZ = rShapeParam.mfLogicZ + 1.0; - awt::Point aMiddleArcPoint = PlottingPositionHelper::transformSceneToScreenPosition( - m_aPosHelper.transformUnitCircleToScene( + drawing::Position3D aUnitCirclePt = m_aPosHelper.transformUnitCircleToScene( fBisectingRayAngleDeg, - rShapeParam.mfUnitCircleOuterRadius, - fLogicZ ), - m_xLogicTarget, m_nDimension ); + rShapeParam.mfUnitCircleOuterRadius * fRadiusScale, + fLogicZ, + aShift); + awt::Point aMiddleArcPoint = PlottingPositionHelper::transformSceneToScreenPosition( + aUnitCirclePt, m_xLogicTarget, m_nDimension ); // compute the pie radius basegfx::B2IVector aPieCenter = rPieLabelInfo.aOrigin; @@ -1910,7 +1995,7 @@ bool PieChart::performLabelBestFitInnerPlacement(ShapeParam& rShapeParam, PieLab // the bb is moved as much as possible near to the border of the pie, // anyway a small offset from the border is present (0.025 * pie radius) const double fPieBorderOffset = 0.025; - fPieRadius = fPieRadius - fPieRadius * fPieBorderOffset; + fPieRadius *= (1 - fPieBorderOffset); SAL_INFO( "chart2.pie.label.bestfit.inside", " pie sector:" ); diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx index 6f29ea7e894c..c5cb1e535cc8 100644 --- a/chart2/source/view/charttypes/PieChart.hxx +++ b/chart2/source/view/charttypes/PieChart.hxx @@ -186,7 +186,15 @@ private: //methods */ void createTextLabelShape( const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, - VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam ); + VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam , + enum SubPieType eType ); + + /** Same as createTextLabelShape(), but for bar-of-pie bar charts. + */ + void createBarLabelShape( + const rtl::Reference<SvxShapeGroupAnyD>& xTextTarget, + VDataSeries& rSeries, sal_Int32 nPointIndex, + double fBarBottom, double fBarTop, ShapeParam& rParam); /** This method sets `m_fMaxOffset` to the maximum `Offset` property and * returns it. There is a `Offset` property for each entry in a data @@ -209,7 +217,9 @@ struct PieLabelInfo; , const css::awt::Size& rPageSize ); bool performLabelBestFitInnerPlacement( ShapeParam& rShapeParam - , PieLabelInfo const & rPieLabelInfo ); + , PieLabelInfo const & rPieLabelInfo + , double fRadiusScale + , const ::basegfx::B3DVector& aShift); // A standalone pie, one pie in a pie-of-pie, or one ring of a donut void createOneRing([[maybe_unused]]enum SubPieType eType @@ -231,6 +241,9 @@ struct PieLabelInfo; const PieDataSrcBase *pDataSrc, sal_Int32 n3DRelativeHeight); + void getBarRect(css::awt::Point *pPos, css::awt::Size *pSz, + double fBarBottom, double fBarTop, const ShapeParam& rParam) const; + // Determine left endpoints of connecting lines. These will terminate either // at the corners of the composite wedge (if the wedge is small enough), or // tangent to the left pie circle (if the wedge is larger). The endpoints @@ -262,6 +275,7 @@ private: //member bool m_bUseRings; bool m_bSizeExcludesLabelsAndExplodedSegments; ::css::chart2::PieChartSubType m_eSubType; + // Number of entries in an of-pie composite wedge sal_Int32 m_nCompositeSize; struct PieLabelInfo diff --git a/chart2/source/view/inc/PlottingPositionHelper.hxx b/chart2/source/view/inc/PlottingPositionHelper.hxx index 916668dd6c14..ba2b6104bdc5 100644 --- a/chart2/source/view/inc/PlottingPositionHelper.hxx +++ b/chart2/source/view/inc/PlottingPositionHelper.hxx @@ -225,12 +225,17 @@ public: css::drawing::Position3D transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling=true ) const; - /** It returns the scene coordinates of the passed point: this point is - * described through a normalized cylindrical coordinate system. - * (For a pie chart the origin of the coordinate system is the pie center). + /** Return the scene coordinates of the passed point: this point is + * described through a normalized cylindrical coordinate system, with an + * optional offset. + * (For a standard pie chart the origin of the coordinate system is the + * pie center; for an of-pie chart the components of the aOffset + * parameter are not all zero). */ css::drawing::Position3D - transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius, double fLogicZ ) const; + transformUnitCircleToScene( double fUnitAngleDegree + , double fUnitRadius, double fLogicZ + , const ::basegfx::B3DVector& aOffset = ::basegfx::B3DVector()) const; using PlottingPositionHelper::transformScaledLogicToScene; diff --git a/chart2/source/view/inc/PolarLabelPositionHelper.hxx b/chart2/source/view/inc/PolarLabelPositionHelper.hxx index 84f4ff1dc83c..c980495f68c8 100644 --- a/chart2/source/view/inc/PolarLabelPositionHelper.hxx +++ b/chart2/source/view/inc/PolarLabelPositionHelper.hxx @@ -59,7 +59,8 @@ public: , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius , double fLogicZ - , sal_Int32 nScreenValueOffsetInRadiusDirection ) const; + , sal_Int32 nScreenValueOffsetInRadiusDirection + , const ::basegfx::B3DVector& aOffset = ::basegfx::B3DVector()) const; private: PolarPlottingPositionHelper* m_pPosHelper; diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx index dfbf38bbd90e..0f8c223537b2 100644 --- a/chart2/source/view/main/PlottingPositionHelper.cxx +++ b/chart2/source/view/main/PlottingPositionHelper.cxx @@ -622,8 +622,10 @@ drawing::Position3D PolarPlottingPositionHelper::transformScaledLogicToScene( do double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY; return transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ, false ); } -drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius - , double fLogicZ ) const +drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( + double fUnitAngleDegree, double fUnitRadius, + double fLogicZ , + const ::basegfx::B3DVector& aOffset) const { double fAnglePi = basegfx::deg2rad(fUnitAngleDegree); @@ -633,6 +635,7 @@ drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( dou //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector ::basegfx::B3DPoint aPoint(fX,fY,fZ); + aPoint += aOffset; ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint; return B3DPointToPosition3D(aRet); } diff --git a/chart2/source/view/main/PolarLabelPositionHelper.cxx b/chart2/source/view/main/PolarLabelPositionHelper.cxx index 44070603c75a..5662f8639f08 100644 --- a/chart2/source/view/main/PolarLabelPositionHelper.cxx +++ b/chart2/source/view/main/PolarLabelPositionHelper.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <BaseGFXHelper.hxx> #include <PolarLabelPositionHelper.hxx> #include <PlottingPositionHelper.hxx> #include <basegfx/vector/b2dvector.hxx> @@ -62,7 +63,8 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius , double fLogicZ - , sal_Int32 nScreenValueOffsetInRadiusDirection ) const + , sal_Int32 nScreenValueOffsetInRadiusDirection + , const ::basegfx::B3DVector& aOffset) const { bool bCenter = (nLabelPlacement != css::chart::DataLabelPlacement::OUTSIDE) && (nLabelPlacement != css::chart::DataLabelPlacement::INSIDE); @@ -75,7 +77,8 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi fRadius = fUnitCircleInnerRadius + (fUnitCircleOuterRadius-fUnitCircleInnerRadius)/2.0 ; awt::Point aRet( transformSceneToScreenPosition( - m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ+0.5 ) ) ); + m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, + fLogicZ+0.5, aOffset ) ) ); if(m_nDimensionCount==3 && nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE) { @@ -83,10 +86,11 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi //take the farthest point to put the label to awt::Point aP0( transformSceneToScreenPosition( - m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ ) ) ); + m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ, aOffset ) ) ); awt::Point aP1(aRet); awt::Point aP2( transformSceneToScreenPosition( - m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ-0.5 ) ) ); + m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, + fLogicZ-0.5, aOffset ) ) ); ::basegfx::B2DVector aV0( aP0.X, aP0.Y ); ::basegfx::B2DVector aV1( aP1.X, aP1.Y ); @@ -142,7 +146,8 @@ awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCi if( nScreenValueOffsetInRadiusDirection != 0) { awt::Point aOrigin( transformSceneToScreenPosition( - m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, fLogicZ+0.5 ) ) ); + m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, fLogicZ+0.5, + aOffset ) ) ); basegfx::B2IVector aDirection( aRet.X- aOrigin.X, aRet.Y- aOrigin.Y ); aDirection.setLength(nScreenValueOffsetInRadiusDirection); aRet.X += aDirection.getX();