32#include <com/sun/star/chart/DataLabelPlacement.hpp>
33#include <com/sun/star/chart2/XColorScheme.hpp>
35#include <com/sun/star/drawing/XShapes.hpp>
37#include <osl/diagnose.h>
115bool lcl_isInsidePage(
const awt::Point& rPos,
const awt::Size& rSize,
const awt::Size& rPageSize)
117 if (rPos.X < 0 || rPos.Y < 0)
119 if ((rPos.X + rSize.Width) > rPageSize.Width)
121 if ((rPos.Y + rSize.Height) > rPageSize.Height)
133 bool getInnerAndOuterRadius(
double fCategoryX,
double& fLogicInnerRadius,
double& fLogicOuterRadius,
bool bUseRings,
double fMaxOffset )
const;
141 : m_fRingDistance(0.0)
160 ,
double& fLogicInnerRadius,
double& fLogicOuterRadius
161 ,
bool bUseRings,
double fMaxOffset )
const
173 fLogicInner += fMaxOffset;
174 fLogicOuter += fMaxOffset;
187 fLogicInnerRadius = fLogicInner;
188 fLogicOuterRadius = fLogicOuter;
190 std::swap(fLogicInnerRadius,fLogicOuterRadius);
195 , sal_Int32 nDimensionCount
196 ,
bool bExcludingPositioning )
200 , m_bSizeExcludesLabelsAndExplodedSegments(bExcludingPositioning)
201 , m_fMaxOffset(
std::numeric_limits<double>::quiet_NaN())
205 m_pPosHelper->m_fRadiusOffset = 0.0;
206 m_pPosHelper->m_fRingDistance = 0.0;
208 if( !xChartTypeModel.is() )
216 m_pPosHelper->m_fRadiusOffset = 1.0;
217 if( nDimensionCount==3 )
218 m_pPosHelper->m_fRingDistance = 0.1;
221 catch(
const uno::Exception& )
233 OSL_ENSURE(
m_nDimension<=
static_cast<sal_Int32
>(rScales.size()),
"Dimension of Plotter does not fit two dimension of given scale sequence");
240 return drawing::Direction3D(1,1,0.10);
241 return drawing::Direction3D(1,1,1);
253 const sal_Int32 nPointCount,
254 const bool bConcentricExplosion)
257 drawing::Direction3D aOffset;
266 if (bConcentricExplosion) {
272 assert(fExplodedInnerRadius >= 0 && fExplodedOuterRadius > 0);
273 double fAngleRatio = (fExplodedInnerRadius + fExplodedOuterRadius) /
274 (fExplodedInnerRadius + fExplodedOuterRadius + 2 * fRadius);
276 assert(nPointCount > 0);
277 double fAngleGap = 360 * (1.0 - fAngleRatio) / nPointCount;
278 fStartAngle += fAngleGap / 2;
279 fWidthAngle -= fAngleGap;
281 fExplodedInnerRadius += fRadius;
282 fExplodedOuterRadius += fRadius;
287 double fAngle = fStartAngle + fWidthAngle/2.0;
290 drawing::Position3D aNewOrigin =
m_pPosHelper->transformUnitCircleToScene(fAngle, fRadius, rParam.
mfLogicZ);
291 aOffset = aNewOrigin - aOrigin;
300 , fStartAngle, fWidthAngle
301 , fExplodedInnerRadius, fExplodedOuterRadius
308 , fStartAngle, fWidthAngle
309 , fExplodedInnerRadius, fExplodedOuterRadius
344 double nVal = rSeries.
getYValue(nPointIndex);
346 bool bMovementAllowed = nLabelPlacement == css::chart::DataLabelPlacement::AVOID_OVERLAP
347 || nLabelPlacement == css::chart::DataLabelPlacement::CUSTOM;
348 if( bMovementAllowed )
349 nLabelPlacement = css::chart::DataLabelPlacement::CENTER;
360 sal_Int32 nScreenValueOffsetInRadiusDirection = 0 ;
361 if( nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE )
362 nScreenValueOffsetInRadiusDirection = (
m_nDimension!=3) ? 150 : 0;
363 else if( nLabelPlacement == css::chart::DataLabelPlacement::INSIDE )
364 nScreenValueOffsetInRadiusDirection = (
m_nDimension!=3) ? -150 : 0;
370 awt::Point aScreenPosition2D(
382 if( nScreenValueOffsetInRadiusDirection != 0)
385 aDirection.setLength(nScreenValueOffsetInRadiusDirection);
398 aOuterCirclePoint.X - aPieLabelInfo.
aOrigin.
getX(),
399 aOuterCirclePoint.Y - aPieLabelInfo.
aOrigin.
getY() );
400 double fSquaredPieRadius = aRadiusVector.
scalar(aRadiusVector);
401 double fPieRadius = sqrt( fSquaredPieRadius );
404 while (fAngleDegree > 360.0)
405 fAngleDegree -= 360.0;
406 while (fAngleDegree < 0.0)
407 fAngleDegree += 360.0;
415 double fTextMaximumFrameWidth = 0.8 * fPieRadius;
416 if (nLabelPlacement == css::chart::DataLabelPlacement::OUTSIDE
419 if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
420 || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
425 sal_Int32 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth);
429 xTextTarget, rSeries, nPointIndex, nVal, rParam.
mfLogicYSum,
430 aScreenPosition2D, eAlignment, 0, nTextMaximumFrameWidth);
449 == css::chart::DataLabelPlacement::CUSTOM
454 if ((fAngleDegree >= 67.5 && fAngleDegree <= 112.5)
455 || (fAngleDegree >= 247.5 && fAngleDegree <= 292.5))
458 fTextMaximumFrameWidth
460 nTextMaximumFrameWidth = ceil(fTextMaximumFrameWidth);
463 nScreenValueOffsetInRadiusDirection = (
m_nDimension != 3) ? 150 : 0;
466 eAlignment, css::chart::DataLabelPlacement::OUTSIDE,
474 if (nScreenValueOffsetInRadiusDirection != 0)
477 aScreenPosition2D.Y - aOrigin.Y);
478 aDirection.setLength(nScreenValueOffsetInRadiusDirection);
487 aScreenPosition2D, eAlignment, 0, nTextMaximumFrameWidth);
496 bool bShowLeaderLine = rSeries.
getModel()
509 awt::Point(aShapePos.X - aRect.
getMinX(), aShapePos.Y));
512 awt::Point(aShapePos.X, aShapePos.Y - aRect.
getMinY()));
513 if (aRect.
getMaxX() > nPageWidth)
515 awt::Point(aShapePos.X - (aRect.
getMaxX() - nPageWidth), aShapePos.Y));
516 if (aRect.
getMaxY() > nPageHeight)
518 awt::Point(aShapePos.X, aShapePos.Y - (aRect.
getMaxY() - nPageHeight)));
528 else if (nX1 > aRect.
getMaxX())
533 else if (nY1 > aRect.
getMaxY())
536 sal_Int32 nSquaredDistanceFromOrigin
537 = (nX2 - aOrigin.X) * (nX2 - aOrigin.X) + (nY2 - aOrigin.Y) * (nY2 - aOrigin.Y);
540 if (nSquaredDistanceFromOrigin > fSquaredPieRadius)
544 double fPageDiagonaleLength = std::hypot(nPageWidth, nPageHeight);
545 if ((aLength.
getLength() / fPageDiagonaleLength) >= 0.01)
547 drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } };
552 sal_Int32 nColor = 0;
553 aPieLabelInfo.
xTextShape->SvxShape::getPropertyValue(
"CharColor") >>= nColor;
556 aVLineProperties.
Color <<= nColor;
564 aPieLabelInfo.
fValue = nVal;
566 aPieLabelInfo.
bMoved =
false;
594 const std::vector< std::unique_ptr<VDataSeries> >& rSeriesList(
m_aZSlots.front().front().m_aSeriesVector );
595 if(rSeriesList.empty())
603 double fExplodePercentage=0.0;
604 xSeries->getPropertyValue(
"Offset") >>= fExplodePercentage;
614 for(sal_Int32 nN=aAttributedDataPointIndexList.getLength();nN--;)
619 fExplodePercentage=0.0;
620 xPointProp->getPropertyValue(
"Offset") >>= fExplodePercentage;
633 return m_aZSlots.front().size()+0.5+fMaxOffset;
634 return 1.5+fMaxOffset;
710 std::vector< VDataSeriesGroup >::iterator aXSlotIter =
m_aZSlots.front().begin();
711 const std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd =
m_aZSlots.front().end();
726 std::vector< VDataSeriesGroup >::size_type nExplodeableSlot = 0;
728 nExplodeableSlot =
m_aZSlots.front().size()-1;
731 m_fMaxOffset = std::numeric_limits<double>::quiet_NaN();
732 sal_Int32 n3DRelativeHeight = 100;
738 aAny >>= n3DRelativeHeight;
740 catch (
const uno::Exception&) { }
746 for(
double fSlotX=0; aXSlotIter != aXSlotEnd && (
m_bUseRings||fSlotX<0.5 ); ++aXSlotIter, fSlotX+=1.0 )
750 std::vector< std::unique_ptr<VDataSeries> >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
751 if(pSeriesList->empty())
766 sal_Int32 nPointIndex=0;
768 for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ )
770 double fY = pSeries->
getYValue( nPointIndex );
784 double fLogicYForNextPoint = 0.0;
786 for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ )
788 double fLogicInnerRadius, fLogicOuterRadius;
798 bool bIsVisible =
m_pPosHelper->getInnerAndOuterRadius( fSlotX+1.0, fLogicInnerRadius, fLogicOuterRadius,
m_bUseRings, fOffset );
806 double fLogicYValue = fabs(pSeries->
getYValue( nPointIndex ));
807 if( std::isnan(fLogicYValue) )
809 if(fLogicYValue==0.0)
811 double fLogicYPos = fLogicYForNextPoint;
812 fLogicYForNextPoint += fLogicYValue;
819 double fLogicStartAngleValue = fLogicYPos / aParam.
mfLogicYSum;
820 double fLogicEndAngleValue = (fLogicYPos+fLogicYValue) / aParam.
mfLogicYSum;
826 bool bDoExplode = ( nExplodeableSlot ==
static_cast< std::vector< VDataSeriesGroup >::size_type
>(fSlotX) );
831 catch(
const uno::Exception& )
850 xSeriesGroupShape_Shapes, xPointProperties, aParam, nPointCount,
851 bConcentricExplosion);
856 xPointShape->setPropertyValue(
"FillColor",
861 if(bHasFillColorMapping)
864 if(!std::isnan(nPropVal))
866 xPointShape->setPropertyValue(
"FillColor",
uno::Any(
static_cast<sal_Int32
>( nPropVal)));
899 nOffsetPercent, aMinimumPosition, aMaximumPosition )
905 catch(
const uno::Exception& )
916 , bMovementAllowed(false), bMoved(false)
917 , bShowLeaderLine(false), pPrevious(nullptr)
931 if(!bMovementAllowed)
934 const sal_Int32 nLabelDistanceX = rPageSize.Width/50;
935 const sal_Int32 nLabelDistanceY = rPageSize.Height/50;
959 bool bShiftHorizontal =
abs(aTangentialDirection.
getX()) >
abs(aTangentialDirection.
getY());
960 sal_Int32 nShift = bShiftHorizontal ?
static_cast<sal_Int32
>(aOverlap.
getWidth()) :
static_cast<sal_Int32
>(aOverlap.
getHeight());
963 nShift += (bShiftHorizontal ? nLabelDistanceX : nLabelDistanceY);
972 awt::Point aOldPos( xLabelGroupShape->getPosition() );
977 awt::Point aNewAWTPos( aNewPos.
getX(), aNewPos.
getY() );
978 if( !lcl_isInsidePage( aNewAWTPos, xLabelGroupShape->getSize(), rPageSize ) )
981 xLabelGroupShape->setPosition( aNewAWTPos );
1000 labelInfo.xLabelGroupShape->setPosition(labelInfo.aPreviousPosition);
1020 bool bOverlapFound =
false;
1032 bool bPreviousOverlap = !aPreviousOverlap.
isEmpty();
1033 bool bNextOverlap = !aNextOverlap.
isEmpty();
1034 if( bPreviousOverlap || bNextOverlap )
1035 bOverlapFound =
true;
1036 if( !bPreviousOverlap && bNextOverlap )
1038 pFirstBorder = pCurrent;
1041 pCurrent = pCurrent->
pNext;
1043 while( pCurrent != pStart );
1045 if( !bOverlapFound )
1061 pCurrent = pFirstBorder;
1071 pSecondBorder = pCurrent;
1074 pCurrent = pCurrent->
pNext;
1076 while( pCurrent != pFirstBorder );
1085 if( !pFirstBorder || !pSecondBorder )
1094 sal_Int32 nOverlapGroupCount = 1;
1095 for( pCurrent = pFirstBorder ;pCurrent != pSecondBorder; pCurrent = pCurrent->
pNext )
1096 nOverlapGroupCount++;
1097 sal_Int32 nCenterPos = nOverlapGroupCount/2;
1098 bool bSingleCenter = nOverlapGroupCount%2 != 0;
1103 pCurrent = pFirstBorder;
1104 while( --nCenterPos )
1105 pCurrent = pCurrent->
pNext;
1117 pCurrent = pCurrent->
pNext;
1119 while( pCurrent != pStart );
1139 bool bAlternativeMoveDirection =
false;
1140 if( !
tryMoveLabels( pFirstBorder, pSecondBorder, pCenter, bSingleCenter, bAlternativeMoveDirection, rPageSize ) )
1141 tryMoveLabels( pFirstBorder, pSecondBorder, pCenter, bSingleCenter, bAlternativeMoveDirection, rPageSize );
1154 ,
bool bSingleCenter,
bool& rbAlternativeMoveDirection,
const awt::Size& rPageSize )
1161 bool bLabelOrderIsAntiClockWise =
m_pPosHelper->isMathematicalOrientationAngle();
1170 for( pCurrent = p2 ;pCurrent->
pPrevious != pSecondBorder; pCurrent = pCurrent->
pNext )
1173 for( pFix = p2->
pPrevious ;pFix != pCurrent; pFix = pFix->
pNext )
1198 if( !pCurrent->
moveAwayFrom( pFix, rPageSize, !bSingleCenter && pCurrent == p2, !bLabelOrderIsAntiClockWise ) )
1200 if( !rbAlternativeMoveDirection )
1202 rbAlternativeMoveDirection =
true;
1229 for( pCurrent = p1 ;pCurrent->
pNext != pFirstBorder; pCurrent = pCurrent->
pPrevious )
1232 for( pFix = p2->
pNext ;pFix != pCurrent; pFix = pFix->
pPrevious )
1234 if( !pCurrent->
moveAwayFrom( pFix, rPageSize,
false, bLabelOrderIsAntiClockWise ) )
1236 if( !rbAlternativeMoveDirection )
1238 rbAlternativeMoveDirection =
true;
1259 bool bMoveableFound =
false;
1262 if(labelInfo.bMovementAllowed)
1264 bMoveableFound =
true;
1271 double fPageDiagonaleLength = std::hypot(rPageSize.Width, rPageSize.Height);
1272 if( fPageDiagonaleLength == 0.0 )
1278 std::vector< PieLabelInfo >::iterator aIt2 = aIt1;
1281 for( ;aIt2!=aEnd; ++aIt1, ++aIt2 )
1285 rInfo1.
pNext = &rInfo2;
1291 sal_Int32 nMaxIterations = 50;
1299 if( labelInfo.bMoved && labelInfo.bShowLeaderLine )
1301 sal_Int32 nX1 = labelInfo.aOuterPosition.getX();
1302 sal_Int32 nY1 = labelInfo.aOuterPosition.getY();
1303 sal_Int32 nX2 = nX1;
1304 sal_Int32 nY2 = nY1;
1308 else if( nX1 > aRect.
getMaxX() )
1313 else if( nY1 > aRect.
getMaxY() )
1318 if( (aLength.
getLength()/fPageDiagonaleLength) < 0.01 )
1321 drawing::PointSequenceSequence aPoints{ { {nX1, nY1}, {nX2, nY2} } };
1323 if( labelInfo.xTextShape.is() )
1325 sal_Int32 nColor = 0;
1326 labelInfo.xTextShape->SvxShape::getPropertyValue(
"CharColor") >>= nColor;
1328 aVLineProperties.
Color <<= nColor;
1413 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1414 "** PieChart::performLabelBestFitInnerPlacement invoked **" );
1419 double fHalfWidthAngleDeg = fWidthAngleDeg / 2.0;
1420 double fBisectingRayAngleDeg =
NormAngle360(fStartAngleDeg + fHalfWidthAngleDeg);
1423 double fLogicZ = rShapeParam.
mfLogicZ + 1.0;
1426 fBisectingRayAngleDeg,
1434 aMiddleArcPoint.X - aPieCenter.
getX(),
1435 aMiddleArcPoint.Y - aPieCenter.
getY() );
1436 double fSquaredPieRadius = aRadiusVector.
scalar(aRadiusVector);
1437 double fPieRadius = sqrt( fSquaredPieRadius );
1441 const double fPieBorderOffset = 0.025;
1442 fPieRadius = fPieRadius - fPieRadius * fPieBorderOffset;
1444 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1446 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1447 " start angle = " << fStartAngleDeg );
1448 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1449 " angle width = " << fWidthAngleDeg );
1450 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1451 " bisecting ray angle = " << fBisectingRayAngleDeg );
1452 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1453 " pie radius = " << fPieRadius );
1454 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1455 " pie center = " << rPieLabelInfo.
aOrigin );
1456 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1457 " middle arc point = (" << aMiddleArcPoint.X <<
","
1458 << aMiddleArcPoint.Y <<
")" );
1459 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1460 " label bounding box:" );
1461 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1465 if( fPieRadius == 0.0 )
1470 double fLabelWidth = aBb.
getWidth();
1474 double fAlphaDeg =
NormAngle360(fBisectingRayAngleDeg + 45) - 45;
1482 int nSectorIndex = floor( (fAlphaDeg + 45) / 45.0 );
1483 int nNearestEdgeIndex = nSectorIndex / 2;
1486 double fNearestEdgeLength = fLabelWidth;
1487 double fOrthogonalEdgeLength = fLabelHeight;
1490 if( nNearestEdgeIndex % 2 == 0 )
1492 fNearestEdgeLength = fLabelHeight;
1493 fOrthogonalEdgeLength = fLabelWidth;
1503 int nIndex = nSectorIndex -1;
1504 double fIndexMod2 = (
nIndex + 8) % 2;
1505 double fSgn = 2.0 * (fIndexMod2 - 0.5);
1506 double fDistanceNP = (fNearestEdgeLength / 2.0) * (1 + fSgn * ((fAlphaDeg - 45 * (
nIndex + fIndexMod2)) / 45.0));
1507 double fDistancePM = fNearestEdgeLength - fDistanceNP;
1511 double fDistancePF = std::hypot(fDistancePM, fOrthogonalEdgeLength);
1513 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1514 " width = " << fLabelWidth );
1515 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1516 " height = " << fLabelHeight );
1517 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1518 " nearest edge index = " << nNearestEdgeIndex );
1519 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1520 " alpha = " << fAlphaDeg );
1521 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1522 " distance(N,P) = " << fDistanceNP );
1523 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1524 " nIndex = " <<
nIndex );
1525 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1526 " fIndexMod2 = " << fIndexMod2 );
1527 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1528 " fSgn = " << fSgn );
1529 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1530 " distance(P,F) = " << fDistancePF );
1534 if (fDistancePF > fPieRadius)
1542 double fBetaRad = atan2( fOrthogonalEdgeLength, fDistancePM );
1555 double fAlphaMod90 = fmod( fAlphaDeg + 45, 90.0 ) - 45;
1556 double fSign = fAlphaMod90 == 0.0
1558 : ( fAlphaMod90 < 0 ) ? -1.0 : 1.0;
1559 double fThetaRad = fSign * fAlphaRad + M_PI_2 * (1 - fSign * nNearestEdgeIndex) + fBetaRad;
1560 if( fThetaRad > M_PI )
1562 fThetaRad = 2 * M_PI - fThetaRad;
1569 if( fmod(fThetaRad, M_PI) == 0.0 )
1571 fDistanceCP = fPieRadius - fDistancePF;
1585 double fSinTheta = sin( fThetaRad );
1586 double fSinDelta = fDistancePF * fSinTheta / fPieRadius;
1587 double fDeltaRad = asin( fSinDelta );
1588 double fGammaRad = M_PI - (fThetaRad + fDeltaRad);
1589 double fSinGamma = sin( fGammaRad );
1590 fDistanceCP = fPieRadius * fSinGamma / fSinTheta;
1595 aPositionalVector.
setLength(fDistanceCP);
1600 if( 90 <= fBisectingRayAngleDeg && fBisectingRayAngleDeg < 270 )
1604 if( fBisectingRayAngleDeg >= 180 )
1611 aNearestVertex.
set(eAxis, aNearestVertex.
get(eAxis) -
aDirection.get(eAxis) * fDistanceNP);
1613 aVertexM.
set(eAxis, aVertexM.
get(eAxis) +
aDirection.get(eAxis) * fNearestEdgeLength);
1615 aVertexG.
set(eOrthogonalAxis, aVertexG.
get(eOrthogonalAxis) +
aDirection.get(eOrthogonalAxis) * fOrthogonalEdgeLength);
1617 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1619 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1621 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1622 " fAlphaMod90 = " << fAlphaMod90 );
1623 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1624 " fSign = " << fSign );
1625 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1626 " distance(C,P) = " << fDistanceCP );
1627 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1629 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1630 " N = " << aNearestVertex );
1631 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1632 " M = " << aVertexM );
1633 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1634 " G = " << aVertexG );
1645 double fAngleRad = aPositionalVector.
angle(aVertexM);
1647 if( fAngleDeg > 180 )
1648 fAngleDeg = 360 - fAngleDeg;
1649 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1650 " angle between CP and CM: " << fAngleDeg );
1651 if( fAngleDeg > fHalfWidthAngleDeg )
1656 if( ( aNearestVertex.
get(eAxis) >= 0 && aVertexM.
get(eAxis) <= 0 )
1657 || ( aNearestVertex.
get(eAxis) <= 0 && aVertexM.
get(eAxis) >= 0 ) )
1660 fAngleRad = aPositionalVector.
angle(aNearestVertex);
1662 if( fAngleDeg > 180 )
1663 fAngleDeg = 360 - fAngleDeg;
1664 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1665 " angle between CP and CN: " << fAngleDeg );
1666 if( fAngleDeg > fHalfWidthAngleDeg )
1674 fAngleRad = aPositionalVector.
angle(aVertexG);
1676 if( fAngleDeg > 180 )
1677 fAngleDeg = 360 - fAngleDeg;
1678 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1679 " angle between CP and CG: " << fAngleDeg );
1680 if( fAngleDeg > fHalfWidthAngleDeg )
1688 aBBCenter.
set(eAxis, aBBCenter.
get(eAxis) +
aDirection.get(eAxis) * fNearestEdgeLength / 2);
1689 aBBCenter.
set(eOrthogonalAxis, aBBCenter.
get(eOrthogonalAxis) +
aDirection.get(eOrthogonalAxis) * fOrthogonalEdgeLength / 2);
1693 aNewAnchorPoint.
setX(aNewAnchorPoint.
getX() + floor(aBBCenter.
getX()));
1694 aNewAnchorPoint.
setY(aNewAnchorPoint.
getY() - floor(aBBCenter.
getY()));
1703 awt::Point aNewPos( aOldPos.X + aTranslationVector.
getX(),
1704 aOldPos.Y + aTranslationVector.
getY() );
1707 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1708 " center = " << aBBCenter );
1709 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1710 " new anchor point = " << aNewAnchorPoint );
1711 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1712 " translation vector = " << aTranslationVector );
1713 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1714 " old position = (" << aOldPos.X <<
"," << aOldPos.Y <<
")" );
1715 SAL_INFO(
"chart2.pie.label.bestfit.inside",
1716 " new position = (" << aNewPos.X <<
"," << aNewPos.Y <<
")" );
double angle(const B2DVector &rVec) const
B2DVector & setLength(double fLen)
double scalar(const B2IVector &rVec) const
B2IVector & setLength(double fLen)
void intersect(const Range2D &rRange)
void set(Axis2D eAxis, TYPE fValue)
css::awt::Point transformSceneToScreenPosition(const css::drawing::Position3D &rScenePosition3D) const
static OUString createPieSegmentDragParameterString(sal_Int32 nOffsetPercent, const css::awt::Point &rMinimumPosition, const css::awt::Point &rMaximumPosition)
static OUString createSeriesSubObjectStub(ObjectType eSubObjectType, std::u16string_view rSeriesParticle, std::u16string_view rDragMethodServiceName=std::u16string_view(), std::u16string_view rDragParameterString=std::u16string_view())
static OUString createPointCID(std::u16string_view rPointCID_Stub, sal_Int32 nIndex)
static const OUString & getPieSegmentDragMethodServiceName()
virtual bool isSeparateStackingForDifferentSigns(sal_Int32 nDimensionIndex) override
virtual double getMinimumX() override
bool detectLabelOverlapsAndMove(const css::awt::Size &rPageSize)
virtual void createShapes() override
This method creates all shapes needed for representing the pie chart.
virtual bool shouldSnapRectToUsedArea() override
std::vector< PieLabelInfo > m_aLabelInfoList
rtl::Reference< SvxShape > createDataPoint(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, const css::uno::Reference< css::beans::XPropertySet > &xObjectProperties, const ShapeParam &rParam, const sal_Int32 nPointCount, const bool bConcentricExplosion)
bool performLabelBestFitInnerPlacement(ShapeParam &rShapeParam, PieLabelInfo const &rPieLabelInfo)
Handle the placement of the label in the best fit case: the routine try to place the label inside the...
virtual ~PieChart() override
virtual bool isExpandBorderToIncrementRhythm(sal_Int32 nDimensionIndex) override
void resetLabelPositionsToPreviousState()
virtual bool isExpandWideValuesToZero(sal_Int32 nDimensionIndex) override
void createTextLabelShape(const rtl::Reference< SvxShapeGroupAnyD > &xTextTarget, VDataSeries &rSeries, sal_Int32 nPointIndex, ShapeParam &rParam)
This method creates a text shape for a label of a data point.
virtual double getMaximumYInRange(double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex) override
std::unique_ptr< PiePositionHelper > m_pPosHelper
virtual void addSeries(std::unique_ptr< VDataSeries > pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot) override
A new series can be positioned relative to other series in a chart.
bool tryMoveLabels(PieLabelInfo const *pFirstBorder, PieLabelInfo const *pSecondBorder, PieLabelInfo *pCenter, bool bSingleCenter, bool &rbAlternativeMoveDirection, const css::awt::Size &rPageSize)
Try to remove all overlaps that occur in the list of labels going from pFirstBorder to pSecondBorder
virtual double getMaximumX() override
virtual double getMinimumYInRange(double fMinimumX, double fMaximumX, sal_Int32 nAxisIndex) override
virtual bool isExpandNarrowValuesTowardZero(sal_Int32 nDimensionIndex) override
virtual css::drawing::Direction3D getPreferredDiagramAspectRatio() const override
a value <= 0 for a directions means that this direction can be stretched arbitrary
virtual void rearrangeLabelToAvoidOverlapIfRequested(const css::awt::Size &rPageSize) override
virtual bool isExpandIfValuesCloseToBorder(sal_Int32 nDimensionIndex) override
double getMaxOffset()
This method sets m_fMaxOffset to the maximum Offset property and returns it.
virtual void setScales(std::vector< ExplicitScaleData > &&rScales, bool bSwapXAndYAxis) override
bool m_bSizeExcludesLabelsAndExplodedSegments
bool getInnerAndOuterRadius(double fCategoryX, double &fLogicInnerRadius, double &fLogicOuterRadius, bool bUseRings, double fMaxOffset) const
Compute the outer and the inner radius for the current ring (not for the whole donut!...
PiePositionHelper(double fAngleDegreeOffset)
rtl::Reference< SvxShapeGroupAnyD > m_xLogicTarget
PlottingPositionHelper * m_pPosHelper
rtl::Reference< SvxShapeGroupAnyD > m_xFinalTarget
const sal_Int32 m_nDimension
rtl::Reference< SvxShapeGroupAnyD > createGroupShape(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, const OUString &rName=OUString())
double getLogicMaxX() const
double getLogicMinX() const
static css::awt::Point transformSceneToScreenPosition(const css::drawing::Position3D &rScenePosition3D, const rtl::Reference< SvxShapeGroupAnyD > &xSceneTarget, sal_Int32 nDimensionCount)
css::awt::Point getLabelScreenPositionAndAlignmentForUnitCircleValues(LabelAlignment &rAlignment, sal_Int32 nLabelPlacement, double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree, double fUnitCircleInnerRadius, double fUnitCircleOuterRadius, double fLogicZ, sal_Int32 nScreenValueOffsetInRadiusDirection) const
Calculate the anchor point position for a text label.
double m_fAngleDegreeOffset
Offset for angle axis in real degree.
bool isMathematicalOrientationRadius() const
double m_fRadiusOffset
m_bSwapXAndY (inherited): by default the X axis (scale[0]) represents the angle axis and the Y axis (...
static const tPropertyNameMap & getPropertyNameMapForFilledSeriesProperties()
static void setMappedProperties(const css::uno::Reference< css::beans::XPropertySet > &xTarget, const css::uno::Reference< css::beans::XPropertySet > &xSource, const tPropertyNameMap &rMap)
static void setShapeName(const rtl::Reference< SvxShape > &xShape, const OUString &rName)
static rtl::Reference< SvxShapePolyPolygon > createPieSegment2D(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree, double fUnitCircleInnerRadius, double fUnitCircleOuterRadius, const css::drawing::Direction3D &rOffset, const css::drawing::HomogenMatrix &rUnitCircleToScene)
static rtl::Reference< Svx3DExtrudeObject > createPieSegment(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree, double fUnitCircleInnerRadius, double fUnitCircleOuterRadius, const css::drawing::Direction3D &rOffset, const css::drawing::HomogenMatrix &rUnitCircleToScene, double fDepth)
static rtl::Reference< SvxShapePolyPolygon > createLine2D(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, const css::drawing::PointSequenceSequence &rPoints, const VLineProperties *pLineProperties=nullptr)
static rtl::Reference< SvxShapeGroup > createGroup2D(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, const OUString &aName=OUString())
const OUString & getPointCID_Stub() const
css::uno::Reference< css::beans::XPropertySet > getPropertiesOfPoint(sal_Int32 index) const
double getYValue(sal_Int32 index) const
double getValueByProperty(sal_Int32 index, const OUString &rPropName) const
css::chart2::DataPointLabel * getDataPointLabelIfLabel(sal_Int32 index) const
sal_Int32 getStartingAngle() const
const rtl::Reference<::chart::DataSeries > & getModel() const
bool hasPropertyMapping(const OUString &rPropName) const
sal_Int32 getLabelPlacement(sal_Int32 nPointIndex, const rtl::Reference<::chart::ChartType > &xChartType, bool bSwapXAndY) const
sal_Int32 getTotalPointCount() const
bool hasPointOwnColor(sal_Int32 index) const
bool isLabelCustomPos(sal_Int32 nPointIndex) const
const OUString & getSeriesParticle() const
double getTransformedDepth() const
rtl::Reference< SvxShapeText > createDataLabel(const rtl::Reference< SvxShapeGroupAnyD > &xTarget, VDataSeries &rDataSeries, sal_Int32 nPointIndex, double fValue, double fSumValue, const css::awt::Point &rScreenPosition2D, LabelAlignment eAlignment, sal_Int32 nOffset=0, sal_Int32 nTextWidth=0)
This method creates a text shape for a label related to a data point and append it to the root text s...
css::awt::Size m_aPageReferenceSize
css::uno::Reference< css::chart2::XColorScheme > m_xColorScheme
PlottingPositionHelper * m_pMainPosHelper
rtl::Reference< SvxShapeGroupAnyD > getSeriesGroupShape(VDataSeries *pDataSeries, const rtl::Reference< SvxShapeGroupAnyD > &xTarget)
std::vector< std::vector< VDataSeriesGroup > > m_aZSlots
rtl::Reference< ::chart::ChartType > m_xChartTypeModel
basegfx::B2IRectangle m_aAvailableOuterRect
bool m_bPieLabelsAllowToMove
virtual void addSeries(std::unique_ptr< VDataSeries > pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot)
A new series can be positioned relative to other series in a chart.
#define TOOLS_WARN_EXCEPTION(area, stream)
Reference< XInterface > xTarget
#define SAL_INFO(area, stream)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
constexpr double rad2deg(double v)
constexpr double deg2rad(double v)
OOO_DLLPUBLIC_CHARTTOOLS::basegfx::B2IRectangle makeRectangle(const css::awt::Point &rPosition, const css::awt::Size &rSize)
@ PROP_DATASERIES_SHOW_CUSTOM_LEADERLINES
@ PROP_DATASERIES_ATTRIBUTED_DATA_POINTS
@ PROP_PIECHARTTYPE_3DRELATIVEHEIGHT
@ PROP_PIECHARTTYPE_USE_RINGS
OOO_DLLPUBLIC_CHARTTOOLS css::drawing::HomogenMatrix B3DHomMatrixToHomogenMatrix(const ::basegfx::B3DHomMatrix &rM)
diverse methods for class conversions; e.g.
SwNodeOffset abs(const SwNodeOffset &a)
css::awt::Point aPreviousPosition
::basegfx::B2IVector aFirstPosition
::basegfx::B2IVector aOuterPosition
rtl::Reference< SvxShapeGroupAnyD > xLabelGroupShape
bool moveAwayFrom(const PieLabelInfo *pFix, const css::awt::Size &rPageSize, bool bMoveHalfWay, bool bMoveClockwise)
In case this label and the passed label overlap the routine moves this label in order to fix the issu...
rtl::Reference< SvxShapeGroupAnyD > xTextTarget
rtl::Reference< SvxShapeText > xTextShape
::basegfx::B2IVector aOrigin
double mfUnitCircleOuterRadius
the normalized outer radius of the ring the slice belongs to.
double mfUnitCircleStartAngleDegree
the start angle of the slice
double mfUnitCircleWidthAngleDegree
the angle width of the slice
double mfLogicZ
for 3D pie chart: label z coordinate
double mfLogicYSum
sum of all Y values in a single series
double mfUnitCircleInnerRadius
the normalized inner radius of the ring the slice belongs to
double mfDepth
for 3D pie chart: height
double mfExplodePercentage
relative distance offset of a slice from the pie center; this parameter is used for instance when the...
css::drawing::Direction3D aDirection