1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <BaseGFXHelper.hxx>
21 #include <PolarLabelPositionHelper.hxx>
22 #include <PlottingPositionHelper.hxx>
23 #include <basegfx/vector/b2dvector.hxx>
24 #include <basegfx/vector/b2ivector.hxx>
26 #include <com/sun/star/chart/DataLabelPlacement.hpp>
30 using namespace ::com::sun::star
;
32 PolarLabelPositionHelper::PolarLabelPositionHelper(
33 PolarPlottingPositionHelper
* pPosHelper
34 , sal_Int32 nDimensionCount
35 , const rtl::Reference
<SvxShapeGroupAnyD
>& xLogicTarget
)
36 : LabelPositionHelper( nDimensionCount
, xLogicTarget
)
37 , m_pPosHelper(pPosHelper
)
41 PolarLabelPositionHelper::~PolarLabelPositionHelper()
45 awt::Point
PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForLogicValues(
46 LabelAlignment
& rAlignment
47 , double fLogicValueOnAngleAxis
48 , double fLogicValueOnRadiusAxis
50 , sal_Int32 nScreenValueOffsetInRadiusDirection
) const
52 double fUnitCircleAngleDegree
= m_pPosHelper
->transformToAngleDegree( fLogicValueOnAngleAxis
);
53 double fUnitCircleRadius
= m_pPosHelper
->transformToRadius( fLogicValueOnRadiusAxis
);
55 return getLabelScreenPositionAndAlignmentForUnitCircleValues(
56 rAlignment
, css::chart::DataLabelPlacement::OUTSIDE
57 , fUnitCircleAngleDegree
, 0.0
58 , fUnitCircleRadius
, fUnitCircleRadius
, fLogicZ
, nScreenValueOffsetInRadiusDirection
);
61 awt::Point
PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues(
62 LabelAlignment
& rAlignment
, sal_Int32 nLabelPlacement
63 , double fUnitCircleStartAngleDegree
, double fUnitCircleWidthAngleDegree
64 , double fUnitCircleInnerRadius
, double fUnitCircleOuterRadius
66 , sal_Int32 nScreenValueOffsetInRadiusDirection
67 , const ::basegfx::B3DVector
& aOffset
) const
69 bool bCenter
= (nLabelPlacement
!= css::chart::DataLabelPlacement::OUTSIDE
)
70 && (nLabelPlacement
!= css::chart::DataLabelPlacement::INSIDE
);
72 double fAngleDegree
= fUnitCircleStartAngleDegree
+ fUnitCircleWidthAngleDegree
/2.0;
74 if( !bCenter
) //e.g. for pure pie chart(one ring only) or for angle axis of polar coordinate system
75 fRadius
= fUnitCircleOuterRadius
;
77 fRadius
= fUnitCircleInnerRadius
+ (fUnitCircleOuterRadius
-fUnitCircleInnerRadius
)/2.0 ;
79 awt::Point
aRet( transformSceneToScreenPosition(
80 m_pPosHelper
->transformUnitCircleToScene( fAngleDegree
, fRadius
,
81 fLogicZ
+0.5, aOffset
) ) );
83 if(m_nDimensionCount
==3 && nLabelPlacement
== css::chart::DataLabelPlacement::OUTSIDE
)
85 //check whether the upper or the downer edge is more distant from the center
86 //take the farthest point to put the label to
88 awt::Point
aP0( transformSceneToScreenPosition(
89 m_pPosHelper
->transformUnitCircleToScene( 0, 0, fLogicZ
, aOffset
) ) );
91 awt::Point
aP2( transformSceneToScreenPosition(
92 m_pPosHelper
->transformUnitCircleToScene( fAngleDegree
, fRadius
,
93 fLogicZ
-0.5, aOffset
) ) );
95 ::basegfx::B2DVector
aV0( aP0
.X
, aP0
.Y
);
96 ::basegfx::B2DVector
aV1( aP1
.X
, aP1
.Y
);
97 ::basegfx::B2DVector
aV2( aP2
.X
, aP2
.Y
);
99 double fL1
= ::basegfx::B2DVector(aV1
-aV0
).getLength();
100 double fL2
= ::basegfx::B2DVector(aV2
-aV0
).getLength();
105 //calculate new angle for alignment
106 double fDX
= aRet
.X
-aP0
.X
;
107 double fDY
= aRet
.Y
-aP0
.Y
;
108 fDY
*=-1.0;//drawing layer has inverse y values
110 fAngleDegree
= basegfx::rad2deg(atan2(fDY
,fDX
));
115 // tdf#123504: both 0 and 360 are valid and different values here!
116 while (fAngleDegree
> 360.0)
117 fAngleDegree
-= 360.0;
118 while (fAngleDegree
< 0.0)
119 fAngleDegree
+= 360.0;
121 bool bOutside
= nLabelPlacement
== css::chart::DataLabelPlacement::OUTSIDE
;
123 if (fAngleDegree
<= 5 || fAngleDegree
>= 355)
124 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT
: LABEL_ALIGN_LEFT
;
125 else if (fAngleDegree
< 85)
126 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT_TOP
: LABEL_ALIGN_LEFT_BOTTOM
;
127 else if (fAngleDegree
<= 95)
128 rAlignment
= bOutside
? LABEL_ALIGN_TOP
: LABEL_ALIGN_BOTTOM
;
129 else if (fAngleDegree
< 175)
130 rAlignment
= bOutside
? LABEL_ALIGN_LEFT_TOP
: LABEL_ALIGN_RIGHT_BOTTOM
;
131 else if (fAngleDegree
<= 185)
132 rAlignment
= bOutside
? LABEL_ALIGN_LEFT
: LABEL_ALIGN_RIGHT
;
133 else if (fAngleDegree
< 265)
134 rAlignment
= bOutside
? LABEL_ALIGN_LEFT_BOTTOM
: LABEL_ALIGN_RIGHT_TOP
;
135 else if (fAngleDegree
<= 275)
136 rAlignment
= bOutside
? LABEL_ALIGN_BOTTOM
: LABEL_ALIGN_TOP
;
138 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT_BOTTOM
: LABEL_ALIGN_LEFT_TOP
;
142 rAlignment
= LABEL_ALIGN_CENTER
;
145 //add a scaling independent Offset if requested
146 if( nScreenValueOffsetInRadiusDirection
!= 0)
148 awt::Point
aOrigin( transformSceneToScreenPosition(
149 m_pPosHelper
->transformUnitCircleToScene( 0.0, 0.0, fLogicZ
+0.5,
151 basegfx::B2IVector
aDirection( aRet
.X
- aOrigin
.X
, aRet
.Y
- aOrigin
.Y
);
152 aDirection
.setLength(nScreenValueOffsetInRadiusDirection
);
153 aRet
.X
+= aDirection
.getX();
154 aRet
.Y
+= aDirection
.getY();
162 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */