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