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 "PolarLabelPositionHelper.hxx"
21 #include "PlottingPositionHelper.hxx"
22 #include "CommonConverters.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
;
31 using namespace ::com::sun::star::chart2
;
33 PolarLabelPositionHelper::PolarLabelPositionHelper(
34 PolarPlottingPositionHelper
* pPosHelper
35 , sal_Int32 nDimensionCount
36 , const uno::Reference
< drawing::XShapes
>& xLogicTarget
37 , AbstractShapeFactory
* pShapeFactory
)
38 : LabelPositionHelper( pPosHelper
, nDimensionCount
, xLogicTarget
, pShapeFactory
)
39 , m_pPosHelper(pPosHelper
)
43 PolarLabelPositionHelper::~PolarLabelPositionHelper()
47 awt::Point
PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForLogicValues(
48 LabelAlignment
& rAlignment
49 , double fLogicValueOnAngleAxis
50 , double fLogicValueOnRadiusAxis
52 , sal_Int32 nScreenValueOffsetInRadiusDirection
) const
54 double fUnitCircleAngleDegree
= m_pPosHelper
->transformToAngleDegree( fLogicValueOnAngleAxis
);
55 double fUnitCircleRadius
= m_pPosHelper
->transformToRadius( fLogicValueOnRadiusAxis
);
57 return getLabelScreenPositionAndAlignmentForUnitCircleValues(
58 rAlignment
, ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
59 , fUnitCircleAngleDegree
, 0.0
60 , fUnitCircleRadius
, fUnitCircleRadius
, fLogicZ
, nScreenValueOffsetInRadiusDirection
);
63 awt::Point
PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues(
64 LabelAlignment
& rAlignment
, sal_Int32 nLabelPlacement
65 , double fUnitCircleStartAngleDegree
, double fUnitCircleWidthAngleDegree
66 , double fUnitCircleInnerRadius
, double fUnitCircleOuterRadius
68 , sal_Int32 nScreenValueOffsetInRadiusDirection
) const
70 bool bCenter
= (nLabelPlacement
!= ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
)
71 && (nLabelPlacement
!= ::com::sun::star::chart::DataLabelPlacement::INSIDE
);
73 double fAngleDegree
= fUnitCircleStartAngleDegree
+ fUnitCircleWidthAngleDegree
/2.0;
75 if( !bCenter
) //e.g. for pure pie chart(one ring only) or for angle axis of polyar coordinate system
76 fRadius
= fUnitCircleOuterRadius
;
78 fRadius
= fUnitCircleInnerRadius
+ (fUnitCircleOuterRadius
-fUnitCircleInnerRadius
)/2.0 ;
80 awt::Point
aRet( this->transformSceneToScreenPosition(
81 m_pPosHelper
->transformUnitCircleToScene( fAngleDegree
, fRadius
, fLogicZ
+0.5 ) ) );
83 if(3==m_nDimensionCount
&& nLabelPlacement
== ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
)
85 //check whether the upper or the downer edge is more distant from the center
86 //take the farest point to put the label to
88 awt::Point
aP0( this->transformSceneToScreenPosition(
89 m_pPosHelper
->transformUnitCircleToScene( 0, 0, fLogicZ
) ) );
91 awt::Point
aP2( this->transformSceneToScreenPosition(
92 m_pPosHelper
->transformUnitCircleToScene( fAngleDegree
, fRadius
, fLogicZ
-0.5 ) ) );
94 ::basegfx::B2DVector
aV0( aP0
.X
, aP0
.Y
);
95 ::basegfx::B2DVector
aV1( aP1
.X
, aP1
.Y
);
96 ::basegfx::B2DVector
aV2( aP2
.X
, aP2
.Y
);
98 double fL1
= ::basegfx::B2DVector(aV1
-aV0
).getLength();
99 double fL2
= ::basegfx::B2DVector(aV2
-aV0
).getLength();
104 //calculate new angle for alignment
105 double fDX
= aRet
.X
-aP0
.X
;
106 double fDY
= aRet
.Y
-aP0
.Y
;
107 fDY
*=-1.0;//drawing layer has inverse y values
110 fAngleDegree
= atan(fDY
/fDX
)*180.0/F_PI
;
119 fAngleDegree
= 270.0;
125 while(fAngleDegree
>360.0)
127 while(fAngleDegree
<0.0)
130 bool bOutside
= nLabelPlacement
== ::com::sun::star::chart::DataLabelPlacement::OUTSIDE
;
132 if(fAngleDegree
==0.0)
133 rAlignment
= LABEL_ALIGN_CENTER
;
134 else if(fAngleDegree
<=22.5)
135 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT
: LABEL_ALIGN_LEFT
;
136 else if(fAngleDegree
<67.5)
137 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT_TOP
: LABEL_ALIGN_LEFT_BOTTOM
;
138 else if(fAngleDegree
<112.5)
139 rAlignment
= bOutside
? LABEL_ALIGN_TOP
: LABEL_ALIGN_BOTTOM
;
140 else if(fAngleDegree
<=157.5)
141 rAlignment
= bOutside
? LABEL_ALIGN_LEFT_TOP
: LABEL_ALIGN_RIGHT_BOTTOM
;
142 else if(fAngleDegree
<=202.5)
143 rAlignment
= bOutside
? LABEL_ALIGN_LEFT
: LABEL_ALIGN_RIGHT
;
144 else if(fAngleDegree
<247.5)
145 rAlignment
= bOutside
? LABEL_ALIGN_LEFT_BOTTOM
: LABEL_ALIGN_RIGHT_TOP
;
146 else if(fAngleDegree
<292.5)
147 rAlignment
= bOutside
? LABEL_ALIGN_BOTTOM
: LABEL_ALIGN_TOP
;
148 else if(fAngleDegree
<337.5)
149 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT_BOTTOM
: LABEL_ALIGN_LEFT_TOP
;
151 rAlignment
= bOutside
? LABEL_ALIGN_RIGHT
: LABEL_ALIGN_LEFT
;
155 rAlignment
= LABEL_ALIGN_CENTER
;
158 //add a scaling independent Offset if requested
159 if( nScreenValueOffsetInRadiusDirection
!= 0)
161 awt::Point
aOrigin( this->transformSceneToScreenPosition(
162 m_pPosHelper
->transformUnitCircleToScene( 0.0, 0.0, fLogicZ
+0.5 ) ) );
163 basegfx::B2IVector
aDirection( aRet
.X
- aOrigin
.X
, aRet
.Y
- aOrigin
.Y
);
164 aDirection
.setLength(nScreenValueOffsetInRadiusDirection
);
165 aRet
.X
+= aDirection
.getX();
166 aRet
.Y
+= aDirection
.getY();
174 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */