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