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 #include "Tickmarks.hxx" 27 #include "Tickmarks_Equidistant.hxx" 28 #include "Tickmarks_Dates.hxx" 29 #include "ViewDefines.hxx" 30 #include <rtl/math.hxx> 31 #include <tools/debug.hxx> 32 #include <memory> 33 34 //............................................................................. 35 namespace chart 36 { 37 //............................................................................. 38 using namespace ::com::sun::star; 39 using namespace ::com::sun::star::chart2; 40 using namespace ::rtl::math; 41 using ::basegfx::B2DVector; 42 43 TickInfo::TickInfo( const ::com::sun::star::uno::Reference< 44 ::com::sun::star::chart2::XScaling >& xInverse ) 45 : fScaledTickValue( 0.0 ) 46 , xInverseScaling( xInverse ) 47 , aTickScreenPosition(0.0,0.0) 48 , bPaintIt( true ) 49 , xTextShape( NULL ) 50 , nFactorForLimitedTextWidth(1) 51 { 52 } 53 54 double TickInfo::getUnscaledTickValue() const 55 { 56 if( xInverseScaling.is() ) 57 return xInverseScaling->doScaling( fScaledTickValue ); 58 else 59 return fScaledTickValue; 60 } 61 62 sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const 63 { 64 //return the positive distance between the two first tickmarks in screen values 65 66 B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition; 67 sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength()); 68 if(nRet<0) 69 nRet *= -1; 70 return nRet; 71 } 72 73 PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ) 74 : m_rTickVector(rTickInfoVector) 75 , m_aTickIter(m_rTickVector.begin()) 76 { 77 } 78 PureTickIter::~PureTickIter() 79 { 80 } 81 TickInfo* PureTickIter::firstInfo() 82 { 83 m_aTickIter = m_rTickVector.begin(); 84 if(m_aTickIter!=m_rTickVector.end()) 85 return &*m_aTickIter; 86 return 0; 87 } 88 TickInfo* PureTickIter::nextInfo() 89 { 90 if(m_aTickIter!=m_rTickVector.end()) 91 { 92 m_aTickIter++; 93 if(m_aTickIter!=m_rTickVector.end()) 94 return &*m_aTickIter; 95 } 96 return 0; 97 } 98 99 //----------------------------------------------------------------------------- 100 //----------------------------------------------------------------------------- 101 //----------------------------------------------------------------------------- 102 103 TickFactory::TickFactory( 104 const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) 105 : m_rScale( rScale ) 106 , m_rIncrement( rIncrement ) 107 , m_xInverseScaling(NULL) 108 { 109 //@todo: make sure that the scale is valid for the scaling 110 111 if( m_rScale.Scaling.is() ) 112 { 113 m_xInverseScaling = m_rScale.Scaling->getInverseScaling(); 114 DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" ); 115 } 116 117 m_fScaledVisibleMin = m_rScale.Minimum; 118 if( m_xInverseScaling.is() ) 119 m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin); 120 121 m_fScaledVisibleMax = m_rScale.Maximum; 122 if( m_xInverseScaling.is() ) 123 m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax); 124 } 125 126 TickFactory::~TickFactory() 127 { 128 } 129 130 bool TickFactory::isDateAxis() const 131 { 132 return m_rScale.AxisType == AxisType::DATE; 133 } 134 135 void TickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const 136 { 137 if( isDateAxis() ) 138 DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos ); 139 else 140 EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos ); 141 } 142 143 void TickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const 144 { 145 if( isDateAxis() ) 146 DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos ); 147 else 148 EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos ); 149 } 150 151 //----------------------------------------------------------------------------- 152 // ___TickFactory_2D___ 153 //----------------------------------------------------------------------------- 154 TickFactory_2D::TickFactory_2D( 155 const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement 156 //, double fStrech_SceneToScreen, double fOffset_SceneToScreen ) 157 , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos 158 , const B2DVector& rAxisLineToLabelLineShift ) 159 : TickFactory( rScale, rIncrement ) 160 , m_aAxisStartScreenPosition2D(rStartScreenPos) 161 , m_aAxisEndScreenPosition2D(rEndScreenPos) 162 , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift) 163 , m_fStrech_LogicToScreen(1.0) 164 , m_fOffset_LogicToScreen(0.0) 165 { 166 double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin; 167 if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation ) 168 { 169 m_fStrech_LogicToScreen = 1.0/fWidthY; 170 m_fOffset_LogicToScreen = -m_fScaledVisibleMin; 171 } 172 else 173 { 174 B2DVector aSwap(m_aAxisStartScreenPosition2D); 175 m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D; 176 m_aAxisEndScreenPosition2D = aSwap; 177 178 m_fStrech_LogicToScreen = -1.0/fWidthY; 179 m_fOffset_LogicToScreen = -m_fScaledVisibleMax; 180 } 181 } 182 183 TickFactory_2D::~TickFactory_2D() 184 { 185 } 186 187 bool TickFactory_2D::isHorizontalAxis() const 188 { 189 return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() ); 190 } 191 bool TickFactory_2D::isVerticalAxis() const 192 { 193 return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() ); 194 } 195 196 //static 197 sal_Int32 TickFactory_2D::getTickScreenDistance( TickIter& rIter ) 198 { 199 //return the positive distance between the two first tickmarks in screen values 200 //if there are less than two tickmarks -1 is returned 201 202 const TickInfo* pFirstTickInfo = rIter.firstInfo(); 203 const TickInfo* pSecondTickInfo = rIter.nextInfo(); 204 if(!pSecondTickInfo || !pFirstTickInfo) 205 return -1; 206 207 return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo ); 208 } 209 210 B2DVector TickFactory_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const 211 { 212 B2DVector aRet(m_aAxisStartScreenPosition2D); 213 aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D) 214 *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen); 215 return aRet; 216 } 217 218 void TickFactory_2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints 219 , sal_Int32 nSequenceIndex 220 , double fScaledLogicTickValue, double fInnerDirectionSign 221 , const TickmarkProperties& rTickmarkProperties 222 , bool bPlaceAtLabels ) const 223 { 224 if( fInnerDirectionSign==0.0 ) 225 fInnerDirectionSign = 1.0; 226 227 B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue); 228 if( bPlaceAtLabels ) 229 aTickScreenPosition += m_aAxisLineToLabelLineShift; 230 231 B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D; 232 aMainDirection.normalize(); 233 B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX()); 234 aOrthoDirection *= fInnerDirectionSign; 235 aOrthoDirection.normalize(); 236 237 B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos; 238 B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length; 239 240 rPoints[nSequenceIndex].realloc(2); 241 rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX()); 242 rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY()); 243 rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX()); 244 rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY()); 245 } 246 247 B2DVector TickFactory_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const 248 { 249 bool bFarAwayLabels = false; 250 if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos 251 || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos ) 252 bFarAwayLabels = true; 253 254 double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign; 255 if( fInnerDirectionSign==0.0 ) 256 fInnerDirectionSign = 1.0; 257 258 B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D; 259 aMainDirection.normalize(); 260 B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX()); 261 aOrthoDirection *= fInnerDirectionSign; 262 aOrthoDirection.normalize(); 263 264 B2DVector aStart(0,0), aEnd(0,0); 265 if( bFarAwayLabels ) 266 { 267 TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() ); 268 aStart = aOrthoDirection*aProps.RelativePos; 269 aEnd = aStart - aOrthoDirection*aProps.Length; 270 } 271 else 272 { 273 for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;) 274 { 275 const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN]; 276 B2DVector aNewStart = aOrthoDirection*rProps.RelativePos; 277 B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length; 278 if(aNewStart.getLength()>aStart.getLength()) 279 aStart=aNewStart; 280 if(aNewEnd.getLength()>aEnd.getLength()) 281 aEnd=aNewEnd; 282 } 283 } 284 285 B2DVector aLabelDirection(aStart); 286 if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) 287 aLabelDirection = aEnd; 288 289 B2DVector aOrthoLabelDirection(aOrthoDirection); 290 if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) 291 aOrthoLabelDirection*=-1.0; 292 aOrthoLabelDirection.normalize(); 293 if( bIncludeSpaceBetweenTickAndText ) 294 aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; 295 if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo ) 296 aLabelDirection += m_aAxisLineToLabelLineShift; 297 return aLabelDirection; 298 } 299 300 void TickFactory_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const 301 { 302 rPoints[0].realloc(2); 303 rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX()); 304 rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY()); 305 rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX()); 306 rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY()); 307 } 308 309 void TickFactory_2D::updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const 310 { 311 //get the transformed screen values for all tickmarks in rAllTickInfos 312 ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); 313 const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); 314 for( ; aDepthIter != aDepthEnd; aDepthIter++ ) 315 { 316 ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin(); 317 const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); 318 for( ; aTickIter != aTickEnd; aTickIter++ ) 319 { 320 TickInfo& rTickInfo = (*aTickIter); 321 rTickInfo.aTickScreenPosition = 322 this->getTickScreenPosition2D( rTickInfo.fScaledTickValue ); 323 } 324 } 325 } 326 327 //............................................................................. 328 } //namespace chart 329 //............................................................................. 330