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 #ifndef _CHART2_PLOTTINGPOSITIONHELPER_HXX 28 #define _CHART2_PLOTTINGPOSITIONHELPER_HXX 29 30 #include "LabelAlignment.hxx" 31 #include "chartview/ExplicitScaleValues.hxx" 32 33 #include <basegfx/range/b2drectangle.hxx> 34 #include <rtl/math.hxx> 35 #include <com/sun/star/chart2/XTransformation.hpp> 36 #include <com/sun/star/drawing/Direction3D.hpp> 37 #include <com/sun/star/drawing/HomogenMatrix.hpp> 38 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp> 39 #include <com/sun/star/drawing/Position3D.hpp> 40 #include <com/sun/star/drawing/XShapes.hpp> 41 #include <basegfx/matrix/b3dhommatrix.hxx> 42 43 /* 44 //for WeakImplHelper1 45 #include <cppuhelper/implbase1.hxx> 46 */ 47 //............................................................................. 48 namespace chart 49 { 50 //............................................................................. 51 52 class ShapeFactory; 53 54 //----------------------------------------------------------------------------- 55 /** 56 */ 57 58 class PlottingPositionHelper 59 { 60 public: 61 PlottingPositionHelper(); 62 PlottingPositionHelper( const PlottingPositionHelper& rSource ); 63 virtual ~PlottingPositionHelper(); 64 65 virtual PlottingPositionHelper* clone() const; 66 virtual PlottingPositionHelper* createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale ); 67 68 virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix); 69 70 virtual void setScales( const ::std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ); 71 const ::std::vector< ExplicitScaleData >& getScales() const; 72 73 //better performance for big data 74 inline void setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution ); 75 inline bool isSameForGivenResolution( double fX, double fY, double fZ 76 , double fX2, double fY2, double fZ2 ); 77 78 inline bool isStrongLowerRequested( sal_Int32 nDimensionIndex ) const; 79 inline bool isLogicVisible( double fX, double fY, double fZ ) const; 80 inline void doLogicScaling( double* pX, double* pY, double* pZ, bool bClip=false ) const; 81 inline void doUnshiftedLogicScaling( double* pX, double* pY, double* pZ, bool bClip=false ) const; 82 inline void clipLogicValues( double* pX, double* pY, double* pZ ) const; 83 void clipScaledLogicValues( double* pX, double* pY, double* pZ ) const; 84 inline bool clipYRange( double& rMin, double& rMax ) const; 85 86 inline void doLogicScaling( ::com::sun::star::drawing::Position3D& rPos, bool bClip=false ) const; 87 88 virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation > 89 getTransformationScaledLogicToScene() const; 90 91 virtual ::com::sun::star::drawing::Position3D 92 transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const; 93 94 virtual ::com::sun::star::drawing::Position3D 95 transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const; 96 97 void transformScaledLogicToScene( ::com::sun::star::drawing::PolyPolygonShape3D& rPoly ) const; 98 99 static com::sun::star::awt::Point transformSceneToScreenPosition( 100 const com::sun::star::drawing::Position3D& rScenePosition3D 101 , const com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& xSceneTarget 102 , ShapeFactory* pShapeFactory, sal_Int32 nDimensionCount ); 103 104 inline double getLogicMinX() const; 105 inline double getLogicMinY() const; 106 inline double getLogicMinZ() const; 107 inline double getLogicMaxX() const; 108 inline double getLogicMaxY() const; 109 inline double getLogicMaxZ() const; 110 111 inline bool isMathematicalOrientationX() const; 112 inline bool isMathematicalOrientationY() const; 113 inline bool isMathematicalOrientationZ() const; 114 115 ::basegfx::B2DRectangle getScaledLogicClipDoubleRect() const; 116 ::com::sun::star::drawing::Direction3D getScaledLogicWidth() const; 117 118 inline bool isSwapXAndY() const; 119 120 bool isPercentY() const; 121 122 double getBaseValueY() const; 123 124 inline bool maySkipPointsInRegressionCalculation() const; 125 126 void setTimeResolution( long nTimeResolution, const Date& rNullDate ); 127 virtual void setScaledCategoryWidth( double fScaledCategoryWidth ); 128 void AllowShiftXAxisPos( bool bAllowShift ); 129 void AllowShiftZAxisPos( bool bAllowShift ); 130 131 protected: //member 132 ::std::vector< ExplicitScaleData > m_aScales; 133 ::basegfx::B3DHomMatrix m_aMatrixScreenToScene; 134 135 //this is calculated based on m_aScales and m_aMatrixScreenToScene 136 mutable ::com::sun::star::uno::Reference< 137 ::com::sun::star::chart2::XTransformation > m_xTransformationLogicToScene; 138 139 bool m_bSwapXAndY;//e.g. true for bar chart and false for column chart 140 141 sal_Int32 m_nXResolution; 142 sal_Int32 m_nYResolution; 143 sal_Int32 m_nZResolution; 144 145 bool m_bMaySkipPointsInRegressionCalculation; 146 147 bool m_bDateAxis; 148 long m_nTimeResolution; 149 Date m_aNullDate; 150 151 double m_fScaledCategoryWidth; 152 bool m_bAllowShiftXAxisPos; 153 bool m_bAllowShiftZAxisPos; 154 }; 155 156 //describes wich axis of the drawinglayer scene or sreen axis are the normal axis 157 enum NormalAxis 158 { 159 NormalAxis_X 160 , NormalAxis_Y 161 , NormalAxis_Z 162 }; 163 164 class PolarPlottingPositionHelper : public PlottingPositionHelper 165 /* 166 , public ::cppu::WeakImplHelper1< 167 ::com::sun::star::chart2::XTransformation > 168 */ 169 { 170 public: 171 PolarPlottingPositionHelper( NormalAxis eNormalAxis=NormalAxis_Z ); 172 PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource ); 173 virtual ~PolarPlottingPositionHelper(); 174 175 virtual PlottingPositionHelper* clone() const; 176 177 virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix); 178 virtual void setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis ); 179 180 ::basegfx::B3DHomMatrix getUnitCartesianToScene() const; 181 182 virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation > 183 getTransformationScaledLogicToScene() const; 184 185 //the resulting values should be used for input to the transformation 186 //received with 'getTransformationScaledLogicToScene' 187 double transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling=true ) const; 188 double transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling=true ) const; 189 double getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const; 190 // 191 192 virtual ::com::sun::star::drawing::Position3D 193 transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const; 194 virtual ::com::sun::star::drawing::Position3D 195 transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const; 196 ::com::sun::star::drawing::Position3D 197 transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling=true ) const; 198 ::com::sun::star::drawing::Position3D 199 transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius, double fLogicZ, bool bDoScaling=true ) const; 200 201 using PlottingPositionHelper::transformScaledLogicToScene; 202 203 #ifdef NOTYET 204 double getInnerLogicRadius() const; 205 #endif 206 double getOuterLogicRadius() const; 207 208 inline bool isMathematicalOrientationAngle() const; 209 inline bool isMathematicalOrientationRadius() const; 210 211 /* 212 // ____ XTransformation ____ 213 /// @see ::com::sun::star::chart2::XTransformation 214 virtual ::com::sun::star::uno::Sequence< double > SAL_CALL transform( 215 const ::com::sun::star::uno::Sequence< double >& rSourceValues ) 216 throw (::com::sun::star::lang::IllegalArgumentException, 217 ::com::sun::star::uno::RuntimeException); 218 /// @see ::com::sun::star::chart2::XTransformation 219 virtual sal_Int32 SAL_CALL getSourceDimension() 220 throw (::com::sun::star::uno::RuntimeException); 221 /// @see ::com::sun::star::chart2::XTransformation 222 virtual sal_Int32 SAL_CALL getTargetDimension() 223 throw (::com::sun::star::uno::RuntimeException); 224 */ 225 public: 226 //Offset for radius axis in absolute logic scaled values (1.0 == 1 category) 227 double m_fRadiusOffset; 228 //Offset for angle axis in real degree 229 double m_fAngleDegreeOffset; 230 231 private: 232 ::basegfx::B3DHomMatrix m_aUnitCartesianToScene; 233 NormalAxis m_eNormalAxis; 234 235 ::basegfx::B3DHomMatrix impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const; 236 }; 237 238 bool PolarPlottingPositionHelper::isMathematicalOrientationAngle() const 239 { 240 const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[2]; 241 if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation ) 242 return true; 243 return false; 244 } 245 bool PolarPlottingPositionHelper::isMathematicalOrientationRadius() const 246 { 247 const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1]; 248 if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation ) 249 return true; 250 return false; 251 } 252 253 //better performance for big data 254 void PlottingPositionHelper::setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution ) 255 { 256 m_nXResolution = 1000; 257 m_nYResolution = 1000; 258 m_nZResolution = 1000; 259 if( rCoordinateSystemResolution.getLength() > 0 ) 260 m_nXResolution = rCoordinateSystemResolution[0]; 261 if( rCoordinateSystemResolution.getLength() > 1 ) 262 m_nYResolution = rCoordinateSystemResolution[1]; 263 if( rCoordinateSystemResolution.getLength() > 2 ) 264 m_nZResolution = rCoordinateSystemResolution[2]; 265 } 266 267 bool PlottingPositionHelper::isSameForGivenResolution( double fX, double fY, double fZ 268 , double fX2, double fY2, double fZ2 /*these values are all expected tp be scaled already*/ ) 269 { 270 if( !::rtl::math::isFinite(fX) || !::rtl::math::isFinite(fY) || !::rtl::math::isFinite(fZ) 271 || !::rtl::math::isFinite(fX2) || !::rtl::math::isFinite(fY2) || !::rtl::math::isFinite(fZ2) ) 272 return false; 273 274 double fScaledMinX = getLogicMinX(); 275 double fScaledMinY = getLogicMinY(); 276 double fScaledMinZ = getLogicMinZ(); 277 double fScaledMaxX = getLogicMaxX(); 278 double fScaledMaxY = getLogicMaxY(); 279 double fScaledMaxZ = getLogicMaxZ(); 280 281 doLogicScaling( &fScaledMinX, &fScaledMinY, &fScaledMinZ ); 282 doLogicScaling( &fScaledMaxX, &fScaledMaxY, &fScaledMaxZ); 283 284 bool bSameX = ( static_cast<sal_Int32>(m_nXResolution*(fX - fScaledMinX)/(fScaledMaxX-fScaledMinX)) 285 == static_cast<sal_Int32>(m_nXResolution*(fX2 - fScaledMinX)/(fScaledMaxX-fScaledMinX)) ); 286 287 bool bSameY = ( static_cast<sal_Int32>(m_nYResolution*(fY - fScaledMinY)/(fScaledMaxY-fScaledMinY)) 288 == static_cast<sal_Int32>(m_nYResolution*(fY2 - fScaledMinY)/(fScaledMaxY-fScaledMinY)) ); 289 290 bool bSameZ = ( static_cast<sal_Int32>(m_nZResolution*(fZ - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ)) 291 == static_cast<sal_Int32>(m_nZResolution*(fZ2 - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ)) ); 292 293 return (bSameX && bSameY && bSameZ); 294 } 295 296 bool PlottingPositionHelper::isStrongLowerRequested( sal_Int32 nDimensionIndex ) const 297 { 298 if( m_aScales.empty() ) 299 return false; 300 if( 0==nDimensionIndex ) 301 return m_bAllowShiftXAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition; 302 else if( 2==nDimensionIndex ) 303 return m_bAllowShiftZAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition; 304 return false; 305 } 306 307 bool PlottingPositionHelper::isLogicVisible( 308 double fX, double fY, double fZ ) const 309 { 310 return fX >= m_aScales[0].Minimum && ( isStrongLowerRequested(0) ? fX < m_aScales[0].Maximum : fX <= m_aScales[0].Maximum ) 311 && fY >= m_aScales[1].Minimum && fY <= m_aScales[1].Maximum 312 && fZ >= m_aScales[2].Minimum && ( isStrongLowerRequested(2) ? fZ < m_aScales[2].Maximum : fZ <= m_aScales[2].Maximum ); 313 } 314 315 void PlottingPositionHelper::doLogicScaling( double* pX, double* pY, double* pZ, bool bClip ) const 316 { 317 if(bClip) 318 this->clipLogicValues( pX,pY,pZ ); 319 320 if(pX) 321 { 322 if( m_aScales[0].Scaling.is()) 323 *pX = m_aScales[0].Scaling->doScaling(*pX); 324 if( m_bAllowShiftXAxisPos && m_aScales[0].ShiftedCategoryPosition ) 325 (*pX) += m_fScaledCategoryWidth/2.0; 326 } 327 if(pY && m_aScales[1].Scaling.is()) 328 *pY = m_aScales[1].Scaling->doScaling(*pY); 329 if(pZ) 330 { 331 if( m_aScales[2].Scaling.is()) 332 *pZ = m_aScales[2].Scaling->doScaling(*pZ); 333 if( m_bAllowShiftZAxisPos && m_aScales[2].ShiftedCategoryPosition) 334 (*pZ) += 0.5; 335 } 336 } 337 338 void PlottingPositionHelper::doUnshiftedLogicScaling( double* pX, double* pY, double* pZ, bool bClip ) const 339 { 340 if(bClip) 341 this->clipLogicValues( pX,pY,pZ ); 342 343 if(pX && m_aScales[0].Scaling.is()) 344 *pX = m_aScales[0].Scaling->doScaling(*pX); 345 if(pY && m_aScales[1].Scaling.is()) 346 *pY = m_aScales[1].Scaling->doScaling(*pY); 347 if(pZ && m_aScales[2].Scaling.is()) 348 *pZ = m_aScales[2].Scaling->doScaling(*pZ); 349 } 350 351 void PlottingPositionHelper::doLogicScaling( ::com::sun::star::drawing::Position3D& rPos, bool bClip ) const 352 { 353 doLogicScaling( &rPos.PositionX, &rPos.PositionY, &rPos.PositionZ, bClip ); 354 } 355 356 void PlottingPositionHelper::clipLogicValues( double* pX, double* pY, double* pZ ) const 357 { 358 if(pX) 359 { 360 if( *pX < m_aScales[0].Minimum ) 361 *pX = m_aScales[0].Minimum; 362 else if( *pX > m_aScales[0].Maximum ) 363 *pX = m_aScales[0].Maximum; 364 } 365 if(pY) 366 { 367 if( *pY < m_aScales[1].Minimum ) 368 *pY = m_aScales[1].Minimum; 369 else if( *pY > m_aScales[1].Maximum ) 370 *pY = m_aScales[1].Maximum; 371 } 372 if(pZ) 373 { 374 if( *pZ < m_aScales[2].Minimum ) 375 *pZ = m_aScales[2].Minimum; 376 else if( *pZ > m_aScales[2].Maximum ) 377 *pZ = m_aScales[2].Maximum; 378 } 379 } 380 381 inline bool PlottingPositionHelper::clipYRange( double& rMin, double& rMax ) const 382 { 383 //returns true if something remains 384 if( rMin > rMax ) 385 { 386 double fHelp = rMin; 387 rMin = rMax; 388 rMax = fHelp; 389 } 390 if( rMin > getLogicMaxY() ) 391 return false; 392 if( rMax < getLogicMinY() ) 393 return false; 394 if( rMin < getLogicMinY() ) 395 rMin = getLogicMinY(); 396 if( rMax > getLogicMaxY() ) 397 rMax = getLogicMaxY(); 398 return true; 399 } 400 401 inline double PlottingPositionHelper::getLogicMinX() const 402 { 403 return m_aScales[0].Minimum; 404 } 405 inline double PlottingPositionHelper::getLogicMinY() const 406 { 407 return m_aScales[1].Minimum; 408 } 409 inline double PlottingPositionHelper::getLogicMinZ() const 410 { 411 return m_aScales[2].Minimum; 412 } 413 414 inline double PlottingPositionHelper::getLogicMaxX() const 415 { 416 return m_aScales[0].Maximum; 417 } 418 inline double PlottingPositionHelper::getLogicMaxY() const 419 { 420 return m_aScales[1].Maximum; 421 } 422 inline double PlottingPositionHelper::getLogicMaxZ() const 423 { 424 return m_aScales[2].Maximum; 425 } 426 inline bool PlottingPositionHelper::isMathematicalOrientationX() const 427 { 428 return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[0].Orientation; 429 } 430 inline bool PlottingPositionHelper::isMathematicalOrientationY() const 431 { 432 return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[1].Orientation; 433 } 434 inline bool PlottingPositionHelper::isMathematicalOrientationZ() const 435 { 436 return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[2].Orientation; 437 } 438 inline bool PlottingPositionHelper::isSwapXAndY() const 439 { 440 return m_bSwapXAndY; 441 } 442 inline bool PlottingPositionHelper::maySkipPointsInRegressionCalculation() const 443 { 444 return m_bMaySkipPointsInRegressionCalculation; 445 } 446 447 //............................................................................. 448 } //namespace chart 449 //............................................................................. 450 #endif 451