xref: /trunk/main/chart2/source/view/main/PolarLabelPositionHelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 
31 #include "PolarLabelPositionHelper.hxx"
32 #include "PlottingPositionHelper.hxx"
33 #include "CommonConverters.hxx"
34 #include <basegfx/vector/b2dvector.hxx>
35 #include <basegfx/vector/b2ivector.hxx>
36 
37 #include <com/sun/star/chart/DataLabelPlacement.hpp>
38 
39 //.............................................................................
40 namespace chart
41 {
42 //.............................................................................
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::chart2;
45 
46 PolarLabelPositionHelper::PolarLabelPositionHelper(
47                     PolarPlottingPositionHelper* pPosHelper
48                     , sal_Int32 nDimensionCount
49                     , const uno::Reference< drawing::XShapes >& xLogicTarget
50                     , ShapeFactory* pShapeFactory )
51                     : LabelPositionHelper( pPosHelper, nDimensionCount, xLogicTarget, pShapeFactory )
52                     , m_pPosHelper(pPosHelper)
53 {
54 }
55 
56 PolarLabelPositionHelper::~PolarLabelPositionHelper()
57 {
58 }
59 
60 awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForLogicValues(
61         LabelAlignment& rAlignment
62         , double fLogicValueOnAngleAxis
63         , double fLogicValueOnRadiusAxis
64         , double fLogicZ
65         , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
66 {
67     double fUnitCircleAngleDegree = m_pPosHelper->transformToAngleDegree( fLogicValueOnAngleAxis );
68     double fUnitCircleRadius = m_pPosHelper->transformToRadius( fLogicValueOnRadiusAxis );
69 
70     return getLabelScreenPositionAndAlignmentForUnitCircleValues(
71            rAlignment, ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
72            , fUnitCircleAngleDegree, 0.0
73            , fUnitCircleRadius, fUnitCircleRadius, fLogicZ, nScreenValueOffsetInRadiusDirection );
74 }
75 
76 awt::Point PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues(
77         LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
78         , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree
79         , double fUnitCircleInnerRadius, double fUnitCircleOuterRadius
80         , double fLogicZ
81         , sal_Int32 nScreenValueOffsetInRadiusDirection ) const
82 {
83     bool bCenter = (nLabelPlacement != ::com::sun::star::chart::DataLabelPlacement::OUTSIDE)
84                 && (nLabelPlacement != ::com::sun::star::chart::DataLabelPlacement::INSIDE);
85 
86     double fAngleDegree = fUnitCircleStartAngleDegree + fUnitCircleWidthAngleDegree/2.0;
87     double fRadius = 0.0;
88     if( !bCenter ) //e.g. for pure pie chart(one ring only) or for angle axis of polyar coordinate system
89         fRadius = fUnitCircleOuterRadius;
90     else
91         fRadius = fUnitCircleInnerRadius + (fUnitCircleOuterRadius-fUnitCircleInnerRadius)/2.0 ;
92 
93     awt::Point aRet( this->transformSceneToScreenPosition(
94         m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ+0.5 ) ) );
95 
96     if(3==m_nDimensionCount && nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE)
97     {
98         //check wether the upper or the downer edge is more distant from the center
99         //take the farest point to put the label to
100 
101         awt::Point aP0( this->transformSceneToScreenPosition(
102             m_pPosHelper->transformUnitCircleToScene( 0, 0, fLogicZ ) ) );
103         awt::Point aP1(aRet);
104         awt::Point aP2( this->transformSceneToScreenPosition(
105             m_pPosHelper->transformUnitCircleToScene( fAngleDegree, fRadius, fLogicZ-0.5 ) ) );
106 
107         ::basegfx::B2DVector aV0( aP0.X, aP0.Y );
108         ::basegfx::B2DVector aV1( aP1.X, aP1.Y );
109         ::basegfx::B2DVector aV2( aP2.X, aP2.Y );
110 
111         double fL1 = ::basegfx::B2DVector(aV1-aV0).getLength();
112         double fL2 = ::basegfx::B2DVector(aV2-aV0).getLength();
113 
114         if(fL2>fL1)
115             aRet = aP2;
116 
117         //calculate new angle for alignment
118         double fDX = aRet.X-aP0.X;
119         double fDY = aRet.Y-aP0.Y;
120         fDY*=-1.0;//drawing layer has inverse y values
121         if( fDX != 0.0 )
122         {
123             fAngleDegree = atan(fDY/fDX)*180.0/F_PI;
124             if(fDX<0.0)
125                 fAngleDegree+=180.0;
126         }
127         else
128         {
129             if(fDY>0.0)
130                 fAngleDegree = 90.0;
131             else
132                 fAngleDegree = 270.0;
133         }
134     }
135     //------------------------------
136     //set LabelAlignment
137     if( !bCenter )
138     {
139         while(fAngleDegree>360.0)
140             fAngleDegree-=360.0;
141         while(fAngleDegree<0.0)
142             fAngleDegree+=360.0;
143 
144         bool bOutside = nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE;
145 
146         if(fAngleDegree==0.0)
147             rAlignment = LABEL_ALIGN_CENTER;
148         else if(fAngleDegree<=22.5)
149             rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
150         else if(fAngleDegree<67.5)
151             rAlignment = bOutside ? LABEL_ALIGN_RIGHT_TOP : LABEL_ALIGN_LEFT_BOTTOM;
152         else if(fAngleDegree<112.5)
153             rAlignment = bOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
154         else if(fAngleDegree<=157.5)
155             rAlignment = bOutside ? LABEL_ALIGN_LEFT_TOP : LABEL_ALIGN_RIGHT_BOTTOM;
156         else if(fAngleDegree<=202.5)
157             rAlignment = bOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
158         else if(fAngleDegree<247.5)
159             rAlignment = bOutside ? LABEL_ALIGN_LEFT_BOTTOM : LABEL_ALIGN_RIGHT_TOP;
160         else if(fAngleDegree<292.5)
161             rAlignment = bOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
162         else if(fAngleDegree<337.5)
163             rAlignment = bOutside ? LABEL_ALIGN_RIGHT_BOTTOM : LABEL_ALIGN_LEFT_TOP;
164         else
165             rAlignment = bOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
166     }
167     else
168     {
169         rAlignment = LABEL_ALIGN_CENTER;
170     }
171 
172     //add a scaling independent Offset if requested
173     if( nScreenValueOffsetInRadiusDirection != 0)
174     {
175         awt::Point aOrigin( this->transformSceneToScreenPosition(
176             m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, fLogicZ+0.5 ) ) );
177         basegfx::B2IVector aDirection( aRet.X- aOrigin.X, aRet.Y- aOrigin.Y );
178         aDirection.setLength(nScreenValueOffsetInRadiusDirection);
179         aRet.X += aDirection.getX();
180         aRet.Y += aDirection.getY();
181     }
182 
183     return aRet;
184 }
185 
186 //.............................................................................
187 } //namespace chart
188 //.............................................................................
189