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 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 52 PolarLabelPositionHelper::~PolarLabelPositionHelper() 53 { 54 } 55 56 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 72 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