1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26
27 #include "PolarLabelPositionHelper.hxx"
28 #include "PlottingPositionHelper.hxx"
29 #include "CommonConverters.hxx"
30 #include <basegfx/vector/b2dvector.hxx>
31 #include <basegfx/vector/b2ivector.hxx>
32
33 #include <com/sun/star/chart/DataLabelPlacement.hpp>
34
35 //.............................................................................
36 namespace chart
37 {
38 //.............................................................................
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::chart2;
41
PolarLabelPositionHelper(PolarPlottingPositionHelper * pPosHelper,sal_Int32 nDimensionCount,const uno::Reference<drawing::XShapes> & xLogicTarget,ShapeFactory * pShapeFactory)42 PolarLabelPositionHelper::PolarLabelPositionHelper(
43 PolarPlottingPositionHelper* pPosHelper
44 , sal_Int32 nDimensionCount
45 , const uno::Reference< drawing::XShapes >& xLogicTarget
46 , ShapeFactory* pShapeFactory )
47 : LabelPositionHelper( pPosHelper, nDimensionCount, xLogicTarget, pShapeFactory )
48 , m_pPosHelper(pPosHelper)
49 {
50 }
51
~PolarLabelPositionHelper()52 PolarLabelPositionHelper::~PolarLabelPositionHelper()
53 {
54 }
55
getLabelScreenPositionAndAlignmentForLogicValues(LabelAlignment & rAlignment,double fLogicValueOnAngleAxis,double fLogicValueOnRadiusAxis,double fLogicZ,sal_Int32 nScreenValueOffsetInRadiusDirection) const56 awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForLogicValues(
57 LabelAlignment& rAlignment
58 , double fLogicValueOnAngleAxis
59 , double fLogicValueOnRadiusAxis
60 , double fLogicZ
61 , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
62 {
63 double fUnitCircleAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicValueOnAngleAxis );
64 double fUnitCircleRadius = m_pPosHelper->transformToRadius( fLogicValueOnRadiusAxis );
65
66 return getLabelScreenPositionAndAlignmentForUnitCircleValues(
67 rAlignment, ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
68 , fUnitCircleAngleDegree, 0.0
69 , fUnitCircleRadius, fUnitCircleRadius, fLogicZ, nScreenValueOffsetInRadiusDirection );
70 }
71
getLabelScreenPositionAndAlignmentForUnitCircleValues(LabelAlignment & rAlignment,sal_Int32 nLabelPlacement,double fUnitCircleStartAngleDegree,double fUnitCircleWidthAngleDegree,double fUnitCircleInnerRadius,double fUnitCircleOuterRadius,double fLogicZ,sal_Int32 nScreenValueOffsetInRadiusDirection) const72 awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues(
73 LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
74 , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
75 , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
76 , double fLogicZ
77 , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
78 {
79 bool bCenter = (nLabelPlacement != ::com::sun::star::chart::DataLabelPlacement::OUTSIDE)
80 && (nLabelPlacement != ::com::sun::star::chart::DataLabelPlacement::INSIDE);
81
82 double fAngleDegree = fUnitCircleStartAngleDegree + fUnitCircleWidthAngleDegree/2.0;
83 double fRadius = 0.0;
84 if( !bCenter ) //e.g. for pure pie chart(one ring only) or for angle axis of polyar coordinate system
85 fRadius = fUnitCircleOuterRadius;
86 else
87 fRadius = fUnitCircleInnerRadius + (fUnitCircleOuterRadius-fUnitCircleInnerRadius)/2.0 ;
88
89 awt::Point aRet( this->transformSceneToScreenPosition(
90 m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ+0.5 ) ) );
91
92 if(3==m_nDimensionCount && nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE)
93 {
94 //check wether the upper or the downer edge is more distant from the center
95 //take the farest point to put the label to
96
97 awt::Point aP0( this->transformSceneToScreenPosition(
98 m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ ) ) );
99 awt::Point aP1(aRet);
100 awt::Point aP2( this->transformSceneToScreenPosition(
101 m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ-0.5 ) ) );
102
103 ::basegfx::B2DVector aV0( aP0.X, aP0.Y );
104 ::basegfx::B2DVector aV1( aP1.X, aP1.Y );
105 ::basegfx::B2DVector aV2( aP2.X, aP2.Y );
106
107 double fL1 = ::basegfx::B2DVector(aV1-aV0).getLength();
108 double fL2 = ::basegfx::B2DVector(aV2-aV0).getLength();
109
110 if(fL2>fL1)
111 aRet = aP2;
112
113 //calculate new angle for alignment
114 double fDX = aRet.X-aP0.X;
115 double fDY = aRet.Y-aP0.Y;
116 fDY*=-1.0;//drawing layer has inverse y values
117 if( fDX != 0.0 )
118 {
119 fAngleDegree = atan(fDY/fDX)*180.0/F_PI;
120 if(fDX<0.0)
121 fAngleDegree+=180.0;
122 }
123 else
124 {
125 if(fDY>0.0)
126 fAngleDegree = 90.0;
127 else
128 fAngleDegree = 270.0;
129 }
130 }
131 //------------------------------
132 //set LabelAlignment
133 if( !bCenter )
134 {
135 while(fAngleDegree>360.0)
136 fAngleDegree-=360.0;
137 while(fAngleDegree<0.0)
138 fAngleDegree+=360.0;
139
140 bool bOutside = nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE;
141
142 if(fAngleDegree==0.0)
143 rAlignment = LABEL_ALIGN_CENTER;
144 else if(fAngleDegree<=22.5)
145 rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
146 else if(fAngleDegree<67.5)
147 rAlignment = bOutside ? LABEL_ALIGN_RIGHT_TOP : LABEL_ALIGN_LEFT_BOTTOM;
148 else if(fAngleDegree<112.5)
149 rAlignment = bOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
150 else if(fAngleDegree<=157.5)
151 rAlignment = bOutside ? LABEL_ALIGN_LEFT_TOP : LABEL_ALIGN_RIGHT_BOTTOM;
152 else if(fAngleDegree<=202.5)
153 rAlignment = bOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
154 else if(fAngleDegree<247.5)
155 rAlignment = bOutside ? LABEL_ALIGN_LEFT_BOTTOM : LABEL_ALIGN_RIGHT_TOP;
156 else if(fAngleDegree<292.5)
157 rAlignment = bOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
158 else if(fAngleDegree<337.5)
159 rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP;
160 else
161 rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
162 }
163 else
164 {
165 rAlignment = LABEL_ALIGN_CENTER;
166 }
167
168 //add a scaling independent Offset if requested
169 if( nScreenValueOffsetInRadiusDirection != 0)
170 {
171 awt::Point aOrigin( this->transformSceneToScreenPosition(
172 m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, fLogicZ+0.5 ) ) );
173 basegfx::B2IVector aDirection( aRet.X- aOrigin.X, aRet.Y- aOrigin.Y );
174 aDirection.setLength(nScreenValueOffsetInRadiusDirection);
175 aRet.X += aDirection.getX();
176 aRet.Y += aDirection.getY();
177 }
178
179 return aRet;
180 }
181
182 //.............................................................................
183 } //namespace chart
184 //.............................................................................
185