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 .
19 #ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX
20 #define INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX
22 #include "LabelAlignment.hxx"
23 #include "chartview/ExplicitScaleValues.hxx"
25 #include <basegfx/range/b2drectangle.hxx>
26 #include <rtl/math.hxx>
27 #include <com/sun/star/chart2/XTransformation.hpp>
28 #include <com/sun/star/drawing/Direction3D.hpp>
29 #include <com/sun/star/drawing/HomogenMatrix.hpp>
30 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
31 #include <com/sun/star/drawing/Position3D.hpp>
32 #include <com/sun/star/drawing/XShapes.hpp>
33 #include <basegfx/matrix/b3dhommatrix.hxx>
38 class AbstractShapeFactory
;
40 class PlottingPositionHelper
43 PlottingPositionHelper();
44 PlottingPositionHelper( const PlottingPositionHelper
& rSource
);
45 virtual ~PlottingPositionHelper();
47 virtual PlottingPositionHelper
* clone() const;
48 PlottingPositionHelper
* createSecondaryPosHelper( const ExplicitScaleData
& rSecondaryScale
);
50 virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix
& rMatrix
);
52 virtual void setScales( const ::std::vector
< ExplicitScaleData
>& rScales
, bool bSwapXAndYAxis
);
53 const ::std::vector
< ExplicitScaleData
>& getScales() const { return m_aScales
;}
55 //better performance for big data
56 inline void setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence
< sal_Int32
>& rCoordinateSystemResolution
);
57 inline bool isSameForGivenResolution( double fX
, double fY
, double fZ
58 , double fX2
, double fY2
, double fZ2
);
60 inline bool isStrongLowerRequested( sal_Int32 nDimensionIndex
) const;
61 inline bool isLogicVisible( double fX
, double fY
, double fZ
) const;
62 inline void doLogicScaling( double* pX
, double* pY
, double* pZ
, bool bClip
=false ) const;
63 inline void doUnshiftedLogicScaling( double* pX
, double* pY
, double* pZ
, bool bClip
=false ) const;
64 inline void clipLogicValues( double* pX
, double* pY
, double* pZ
) const;
65 void clipScaledLogicValues( double* pX
, double* pY
, double* pZ
) const;
66 inline bool clipYRange( double& rMin
, double& rMax
) const;
68 inline void doLogicScaling( ::com::sun::star::drawing::Position3D
& rPos
, bool bClip
=false ) const;
70 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::chart2::XTransformation
>
71 getTransformationScaledLogicToScene() const;
73 virtual ::com::sun::star::drawing::Position3D
74 transformLogicToScene( double fX
, double fY
, double fZ
, bool bClip
) const;
76 virtual ::com::sun::star::drawing::Position3D
77 transformScaledLogicToScene( double fX
, double fY
, double fZ
, bool bClip
) const;
79 void transformScaledLogicToScene( ::com::sun::star::drawing::PolyPolygonShape3D
& rPoly
) const;
81 static com::sun::star::awt::Point
transformSceneToScreenPosition(
82 const com::sun::star::drawing::Position3D
& rScenePosition3D
83 , const com::sun::star::uno::Reference
< com::sun::star::drawing::XShapes
>& xSceneTarget
84 , AbstractShapeFactory
* pShapeFactory
, sal_Int32 nDimensionCount
);
86 inline double getLogicMinX() const;
87 inline double getLogicMinY() const;
88 inline double getLogicMinZ() const;
89 inline double getLogicMaxX() const;
90 inline double getLogicMaxY() const;
91 inline double getLogicMaxZ() const;
93 inline bool isMathematicalOrientationX() const;
94 inline bool isMathematicalOrientationY() const;
95 inline bool isMathematicalOrientationZ() const;
97 ::basegfx::B2DRectangle
getScaledLogicClipDoubleRect() const;
98 ::com::sun::star::drawing::Direction3D
getScaledLogicWidth() const;
100 inline bool isSwapXAndY() const;
102 bool isPercentY() const;
104 double getBaseValueY() const;
106 inline bool maySkipPointsInRegressionCalculation() const;
108 void setTimeResolution( long nTimeResolution
, const Date
& rNullDate
);
109 virtual void setScaledCategoryWidth( double fScaledCategoryWidth
);
110 void AllowShiftXAxisPos( bool bAllowShift
);
111 void AllowShiftZAxisPos( bool bAllowShift
);
114 ::std::vector
< ExplicitScaleData
> m_aScales
;
115 ::basegfx::B3DHomMatrix m_aMatrixScreenToScene
;
117 //this is calculated based on m_aScales and m_aMatrixScreenToScene
118 mutable ::com::sun::star::uno::Reference
<
119 ::com::sun::star::chart2::XTransformation
> m_xTransformationLogicToScene
;
121 bool m_bSwapXAndY
;//e.g. true for bar chart and false for column chart
123 sal_Int32 m_nXResolution
;
124 sal_Int32 m_nYResolution
;
125 sal_Int32 m_nZResolution
;
127 bool m_bMaySkipPointsInRegressionCalculation
;
130 long m_nTimeResolution
;
133 double m_fScaledCategoryWidth
;
134 bool m_bAllowShiftXAxisPos
;
135 bool m_bAllowShiftZAxisPos
;
138 //describes which axis of the drawinglayer scene or sreen axis are the normal axis
146 class PolarPlottingPositionHelper
: public PlottingPositionHelper
149 PolarPlottingPositionHelper( NormalAxis eNormalAxis
=NormalAxis_Z
);
150 PolarPlottingPositionHelper( const PolarPlottingPositionHelper
& rSource
);
151 virtual ~PolarPlottingPositionHelper();
153 virtual PlottingPositionHelper
* clone() const SAL_OVERRIDE
;
155 virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix
& rMatrix
) SAL_OVERRIDE
;
156 virtual void setScales( const std::vector
< ExplicitScaleData
>& rScales
, bool bSwapXAndYAxis
) SAL_OVERRIDE
;
158 ::basegfx::B3DHomMatrix
getUnitCartesianToScene() const { return m_aUnitCartesianToScene
;}
160 virtual ::com::sun::star::uno::Reference
< ::com::sun::star::chart2::XTransformation
>
161 getTransformationScaledLogicToScene() const SAL_OVERRIDE
;
163 //the resulting values provided by the following 3 methods should be used
164 //for input to the transformation received with
165 //'getTransformationScaledLogicToScene'
167 /** Given a value in the radius axis scale range, it returns the normalized
170 double transformToRadius( double fLogicValueOnRadiusAxis
, bool bDoScaling
=true ) const;
172 /** Given a value in the angle axis scale range (e.g. [0,1] for pie charts)
173 * this method returns the related angle in degree.
175 double transformToAngleDegree( double fLogicValueOnAngleAxis
, bool bDoScaling
=true ) const;
177 /** Given 2 values in the angle axis scale range (e.g. [0,1] for pie charts)
178 * this method returns the angle between the 2 values keeping into account
179 * the correct axis orientation; (for instance, this method is used for
180 * computing the angle width of a pie slice).
182 double getWidthAngleDegree( double& fStartLogicValueOnAngleAxis
, double& fEndLogicValueOnAngleAxis
) const;
184 virtual ::com::sun::star::drawing::Position3D
185 transformLogicToScene( double fX
, double fY
, double fZ
, bool bClip
) const SAL_OVERRIDE
;
186 virtual ::com::sun::star::drawing::Position3D
187 transformScaledLogicToScene( double fX
, double fY
, double fZ
, bool bClip
) const SAL_OVERRIDE
;
188 ::com::sun::star::drawing::Position3D
189 transformAngleRadiusToScene( double fLogicValueOnAngleAxis
, double fLogicValueOnRadiusAxis
, double fLogicZ
, bool bDoScaling
=true ) const;
191 /** It returns the scene coordinates of the passed point: this point is
192 * described through a normalized cylindrical coordinate system.
193 * (For a pie chart the origin of the coordinate system is the pie center).
195 ::com::sun::star::drawing::Position3D
196 transformUnitCircleToScene( double fUnitAngleDegree
, double fUnitRadius
, double fLogicZ
, bool bDoScaling
=true ) const;
198 using PlottingPositionHelper::transformScaledLogicToScene
;
200 double getOuterLogicRadius() const;
202 inline bool isMathematicalOrientationAngle() const;
203 inline bool isMathematicalOrientationRadius() const;
205 ///m_bSwapXAndY (inherited): by default the X axis (scale[0]) represents
206 ///the angle axis and the Y axis (scale[1]) represents the radius axis;
207 ///when this parameter is true, the opposite happens (this is the case for
210 ///Offset for radius axis in absolute logic scaled values (1.0 == 1 category)
211 ///For a donut, it represents the non-normalized inner radius (see notes for
212 ///transformToRadius)
213 double m_fRadiusOffset
;
214 ///Offset for angle axis in real degree.
215 ///For a pie it represents the angle offset at which the first slice have to
217 double m_fAngleDegreeOffset
;
220 ::basegfx::B3DHomMatrix m_aUnitCartesianToScene
;
221 NormalAxis m_eNormalAxis
;
223 ::basegfx::B3DHomMatrix
impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix
& rMatrixScreenToScene
) const;
226 bool PolarPlottingPositionHelper::isMathematicalOrientationAngle() const
228 const ExplicitScaleData
& rScale
= m_bSwapXAndY
? m_aScales
[1] : m_aScales
[2];
229 if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL
==rScale
.Orientation
)
233 bool PolarPlottingPositionHelper::isMathematicalOrientationRadius() const
235 const ExplicitScaleData
& rScale
= m_bSwapXAndY
? m_aScales
[0] : m_aScales
[1];
236 if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL
==rScale
.Orientation
)
241 //better performance for big data
242 void PlottingPositionHelper::setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence
< sal_Int32
>& rCoordinateSystemResolution
)
244 m_nXResolution
= 1000;
245 m_nYResolution
= 1000;
246 m_nZResolution
= 1000;
247 if( rCoordinateSystemResolution
.getLength() > 0 )
248 m_nXResolution
= rCoordinateSystemResolution
[0];
249 if( rCoordinateSystemResolution
.getLength() > 1 )
250 m_nYResolution
= rCoordinateSystemResolution
[1];
251 if( rCoordinateSystemResolution
.getLength() > 2 )
252 m_nZResolution
= rCoordinateSystemResolution
[2];
255 bool PlottingPositionHelper::isSameForGivenResolution( double fX
, double fY
, double fZ
256 , double fX2
, double fY2
, double fZ2
/*these values are all expected tp be scaled already*/ )
258 if( !::rtl::math::isFinite(fX
) || !::rtl::math::isFinite(fY
) || !::rtl::math::isFinite(fZ
)
259 || !::rtl::math::isFinite(fX2
) || !::rtl::math::isFinite(fY2
) || !::rtl::math::isFinite(fZ2
) )
262 double fScaledMinX
= getLogicMinX();
263 double fScaledMinY
= getLogicMinY();
264 double fScaledMinZ
= getLogicMinZ();
265 double fScaledMaxX
= getLogicMaxX();
266 double fScaledMaxY
= getLogicMaxY();
267 double fScaledMaxZ
= getLogicMaxZ();
269 doLogicScaling( &fScaledMinX
, &fScaledMinY
, &fScaledMinZ
);
270 doLogicScaling( &fScaledMaxX
, &fScaledMaxY
, &fScaledMaxZ
);
272 bool bSameX
= ( static_cast<sal_Int32
>(m_nXResolution
*(fX
- fScaledMinX
)/(fScaledMaxX
-fScaledMinX
))
273 == static_cast<sal_Int32
>(m_nXResolution
*(fX2
- fScaledMinX
)/(fScaledMaxX
-fScaledMinX
)) );
275 bool bSameY
= ( static_cast<sal_Int32
>(m_nYResolution
*(fY
- fScaledMinY
)/(fScaledMaxY
-fScaledMinY
))
276 == static_cast<sal_Int32
>(m_nYResolution
*(fY2
- fScaledMinY
)/(fScaledMaxY
-fScaledMinY
)) );
278 bool bSameZ
= ( static_cast<sal_Int32
>(m_nZResolution
*(fZ
- fScaledMinZ
)/(fScaledMaxZ
-fScaledMinZ
))
279 == static_cast<sal_Int32
>(m_nZResolution
*(fZ2
- fScaledMinZ
)/(fScaledMaxZ
-fScaledMinZ
)) );
281 return (bSameX
&& bSameY
&& bSameZ
);
284 bool PlottingPositionHelper::isStrongLowerRequested( sal_Int32 nDimensionIndex
) const
286 if( m_aScales
.empty() )
288 if( 0==nDimensionIndex
)
289 return m_bAllowShiftXAxisPos
&& m_aScales
[nDimensionIndex
].ShiftedCategoryPosition
;
290 else if( 2==nDimensionIndex
)
291 return m_bAllowShiftZAxisPos
&& m_aScales
[nDimensionIndex
].ShiftedCategoryPosition
;
295 bool PlottingPositionHelper::isLogicVisible(
296 double fX
, double fY
, double fZ
) const
298 return fX
>= m_aScales
[0].Minimum
&& ( isStrongLowerRequested(0) ? fX
< m_aScales
[0].Maximum
: fX
<= m_aScales
[0].Maximum
)
299 && fY
>= m_aScales
[1].Minimum
&& fY
<= m_aScales
[1].Maximum
300 && fZ
>= m_aScales
[2].Minimum
&& ( isStrongLowerRequested(2) ? fZ
< m_aScales
[2].Maximum
: fZ
<= m_aScales
[2].Maximum
);
303 void PlottingPositionHelper::doLogicScaling( double* pX
, double* pY
, double* pZ
, bool bClip
) const
306 this->clipLogicValues( pX
,pY
,pZ
);
310 if( m_aScales
[0].Scaling
.is())
311 *pX
= m_aScales
[0].Scaling
->doScaling(*pX
);
312 if( m_bAllowShiftXAxisPos
&& m_aScales
[0].ShiftedCategoryPosition
)
313 (*pX
) += m_fScaledCategoryWidth
/2.0;
315 if(pY
&& m_aScales
[1].Scaling
.is())
316 *pY
= m_aScales
[1].Scaling
->doScaling(*pY
);
319 if( m_aScales
[2].Scaling
.is())
320 *pZ
= m_aScales
[2].Scaling
->doScaling(*pZ
);
321 if( m_bAllowShiftZAxisPos
&& m_aScales
[2].ShiftedCategoryPosition
)
326 void PlottingPositionHelper::doUnshiftedLogicScaling( double* pX
, double* pY
, double* pZ
, bool bClip
) const
329 this->clipLogicValues( pX
,pY
,pZ
);
331 if(pX
&& m_aScales
[0].Scaling
.is())
332 *pX
= m_aScales
[0].Scaling
->doScaling(*pX
);
333 if(pY
&& m_aScales
[1].Scaling
.is())
334 *pY
= m_aScales
[1].Scaling
->doScaling(*pY
);
335 if(pZ
&& m_aScales
[2].Scaling
.is())
336 *pZ
= m_aScales
[2].Scaling
->doScaling(*pZ
);
339 void PlottingPositionHelper::doLogicScaling( ::com::sun::star::drawing::Position3D
& rPos
, bool bClip
) const
341 doLogicScaling( &rPos
.PositionX
, &rPos
.PositionY
, &rPos
.PositionZ
, bClip
);
344 void PlottingPositionHelper::clipLogicValues( double* pX
, double* pY
, double* pZ
) const
348 if( *pX
< m_aScales
[0].Minimum
)
349 *pX
= m_aScales
[0].Minimum
;
350 else if( *pX
> m_aScales
[0].Maximum
)
351 *pX
= m_aScales
[0].Maximum
;
355 if( *pY
< m_aScales
[1].Minimum
)
356 *pY
= m_aScales
[1].Minimum
;
357 else if( *pY
> m_aScales
[1].Maximum
)
358 *pY
= m_aScales
[1].Maximum
;
362 if( *pZ
< m_aScales
[2].Minimum
)
363 *pZ
= m_aScales
[2].Minimum
;
364 else if( *pZ
> m_aScales
[2].Maximum
)
365 *pZ
= m_aScales
[2].Maximum
;
369 inline bool PlottingPositionHelper::clipYRange( double& rMin
, double& rMax
) const
371 //returns true if something remains
378 if( rMin
> getLogicMaxY() )
380 if( rMax
< getLogicMinY() )
382 if( rMin
< getLogicMinY() )
383 rMin
= getLogicMinY();
384 if( rMax
> getLogicMaxY() )
385 rMax
= getLogicMaxY();
389 inline double PlottingPositionHelper::getLogicMinX() const
391 return m_aScales
[0].Minimum
;
393 inline double PlottingPositionHelper::getLogicMinY() const
395 return m_aScales
[1].Minimum
;
397 inline double PlottingPositionHelper::getLogicMinZ() const
399 return m_aScales
[2].Minimum
;
402 inline double PlottingPositionHelper::getLogicMaxX() const
404 return m_aScales
[0].Maximum
;
406 inline double PlottingPositionHelper::getLogicMaxY() const
408 return m_aScales
[1].Maximum
;
410 inline double PlottingPositionHelper::getLogicMaxZ() const
412 return m_aScales
[2].Maximum
;
414 inline bool PlottingPositionHelper::isMathematicalOrientationX() const
416 return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL
== m_aScales
[0].Orientation
;
418 inline bool PlottingPositionHelper::isMathematicalOrientationY() const
420 return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL
== m_aScales
[1].Orientation
;
422 inline bool PlottingPositionHelper::isMathematicalOrientationZ() const
424 return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL
== m_aScales
[2].Orientation
;
426 inline bool PlottingPositionHelper::isSwapXAndY() const
430 inline bool PlottingPositionHelper::maySkipPointsInRegressionCalculation() const
432 return m_bMaySkipPointsInRegressionCalculation
;
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */