Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 : #ifndef INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX
20 : #define INCLUDED_CHART2_SOURCE_VIEW_INC_PLOTTINGPOSITIONHELPER_HXX
21 :
22 : #include "LabelAlignment.hxx"
23 : #include "chartview/ExplicitScaleValues.hxx"
24 :
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>
34 :
35 : namespace chart
36 : {
37 :
38 : class AbstractShapeFactory;
39 :
40 : class PlottingPositionHelper
41 : {
42 : public:
43 : PlottingPositionHelper();
44 : PlottingPositionHelper( const PlottingPositionHelper& rSource );
45 : virtual ~PlottingPositionHelper();
46 :
47 : virtual PlottingPositionHelper* clone() const;
48 : PlottingPositionHelper* createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale );
49 :
50 : virtual void setTransformationSceneToScreen( const ::com::sun::star::drawing::HomogenMatrix& rMatrix);
51 :
52 : virtual void setScales( const ::std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis );
53 84 : const ::std::vector< ExplicitScaleData >& getScales() const { return m_aScales;}
54 :
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 );
59 :
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;
67 :
68 : inline void doLogicScaling( ::com::sun::star::drawing::Position3D& rPos, bool bClip=false ) const;
69 :
70 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >
71 : getTransformationScaledLogicToScene() const;
72 :
73 : virtual ::com::sun::star::drawing::Position3D
74 : transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
75 :
76 : virtual ::com::sun::star::drawing::Position3D
77 : transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const;
78 :
79 : void transformScaledLogicToScene( ::com::sun::star::drawing::PolyPolygonShape3D& rPoly ) const;
80 :
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 );
85 :
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;
92 :
93 : inline bool isMathematicalOrientationX() const;
94 : inline bool isMathematicalOrientationY() const;
95 : inline bool isMathematicalOrientationZ() const;
96 :
97 : ::basegfx::B2DRectangle getScaledLogicClipDoubleRect() const;
98 : ::com::sun::star::drawing::Direction3D getScaledLogicWidth() const;
99 :
100 : inline bool isSwapXAndY() const;
101 :
102 : bool isPercentY() const;
103 :
104 : double getBaseValueY() const;
105 :
106 : inline bool maySkipPointsInRegressionCalculation() const;
107 :
108 : void setTimeResolution( long nTimeResolution, const Date& rNullDate );
109 : virtual void setScaledCategoryWidth( double fScaledCategoryWidth );
110 : void AllowShiftXAxisPos( bool bAllowShift );
111 : void AllowShiftZAxisPos( bool bAllowShift );
112 :
113 : protected: //member
114 : ::std::vector< ExplicitScaleData > m_aScales;
115 : ::basegfx::B3DHomMatrix m_aMatrixScreenToScene;
116 :
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;
120 :
121 : bool m_bSwapXAndY;//e.g. true for bar chart and false for column chart
122 :
123 : sal_Int32 m_nXResolution;
124 : sal_Int32 m_nYResolution;
125 : sal_Int32 m_nZResolution;
126 :
127 : bool m_bMaySkipPointsInRegressionCalculation;
128 :
129 : bool m_bDateAxis;
130 : long m_nTimeResolution;
131 : Date m_aNullDate;
132 :
133 : double m_fScaledCategoryWidth;
134 : bool m_bAllowShiftXAxisPos;
135 : bool m_bAllowShiftZAxisPos;
136 : };
137 :
138 : //describes which axis of the drawinglayer scene or sreen axis are the normal axis
139 : enum NormalAxis
140 : {
141 : NormalAxis_X
142 : , NormalAxis_Y
143 : , NormalAxis_Z
144 : };
145 :
146 : class PolarPlottingPositionHelper : public PlottingPositionHelper
147 : {
148 : public:
149 : PolarPlottingPositionHelper( NormalAxis eNormalAxis=NormalAxis_Z );
150 : PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource );
151 : virtual ~PolarPlottingPositionHelper();
152 :
153 : virtual PlottingPositionHelper* clone() const SAL_OVERRIDE;
154 :
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;
157 :
158 336 : ::basegfx::B3DHomMatrix getUnitCartesianToScene() const { return m_aUnitCartesianToScene;}
159 :
160 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation >
161 : getTransformationScaledLogicToScene() const SAL_OVERRIDE;
162 :
163 : //the resulting values provided by the following 3 methods should be used
164 : //for input to the transformation received with
165 : //'getTransformationScaledLogicToScene'
166 :
167 : /** Given a value in the radius axis scale range, it returns the normalized
168 : * value.
169 : */
170 : double transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling=true ) const;
171 :
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.
174 : */
175 : double transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling=true ) const;
176 :
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).
181 : */
182 : double getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const;
183 :
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;
190 :
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).
194 : */
195 : ::com::sun::star::drawing::Position3D
196 : transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius, double fLogicZ, bool bDoScaling=true ) const;
197 :
198 : using PlottingPositionHelper::transformScaledLogicToScene;
199 :
200 : double getOuterLogicRadius() const;
201 :
202 : inline bool isMathematicalOrientationAngle() const;
203 : inline bool isMathematicalOrientationRadius() const;
204 : public:
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
208 : ///pie charts).
209 :
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
216 : ///start;
217 : double m_fAngleDegreeOffset;
218 :
219 : private:
220 : ::basegfx::B3DHomMatrix m_aUnitCartesianToScene;
221 : NormalAxis m_eNormalAxis;
222 :
223 : ::basegfx::B3DHomMatrix impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const;
224 : };
225 :
226 11 : bool PolarPlottingPositionHelper::isMathematicalOrientationAngle() const
227 : {
228 11 : const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[2];
229 11 : if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation )
230 0 : return true;
231 11 : return false;
232 : }
233 746 : bool PolarPlottingPositionHelper::isMathematicalOrientationRadius() const
234 : {
235 746 : const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
236 746 : if( ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL==rScale.Orientation )
237 494 : return true;
238 252 : return false;
239 : }
240 :
241 : //better performance for big data
242 12626 : void PlottingPositionHelper::setCoordinateSystemResolution( const ::com::sun::star::uno::Sequence< sal_Int32 >& rCoordinateSystemResolution )
243 : {
244 12626 : m_nXResolution = 1000;
245 12626 : m_nYResolution = 1000;
246 12626 : m_nZResolution = 1000;
247 12626 : if( rCoordinateSystemResolution.getLength() > 0 )
248 12626 : m_nXResolution = rCoordinateSystemResolution[0];
249 12626 : if( rCoordinateSystemResolution.getLength() > 1 )
250 12626 : m_nYResolution = rCoordinateSystemResolution[1];
251 12626 : if( rCoordinateSystemResolution.getLength() > 2 )
252 796 : m_nZResolution = rCoordinateSystemResolution[2];
253 12626 : }
254 :
255 12868 : 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*/ )
257 : {
258 35628 : if( !::rtl::math::isFinite(fX) || !::rtl::math::isFinite(fY) || !::rtl::math::isFinite(fZ)
259 22760 : || !::rtl::math::isFinite(fX2) || !::rtl::math::isFinite(fY2) || !::rtl::math::isFinite(fZ2) )
260 2976 : return false;
261 :
262 9892 : double fScaledMinX = getLogicMinX();
263 9892 : double fScaledMinY = getLogicMinY();
264 9892 : double fScaledMinZ = getLogicMinZ();
265 9892 : double fScaledMaxX = getLogicMaxX();
266 9892 : double fScaledMaxY = getLogicMaxY();
267 9892 : double fScaledMaxZ = getLogicMaxZ();
268 :
269 9892 : doLogicScaling( &fScaledMinX, &fScaledMinY, &fScaledMinZ );
270 9892 : doLogicScaling( &fScaledMaxX, &fScaledMaxY, &fScaledMaxZ);
271 :
272 9892 : bool bSameX = ( static_cast<sal_Int32>(m_nXResolution*(fX - fScaledMinX)/(fScaledMaxX-fScaledMinX))
273 9892 : == static_cast<sal_Int32>(m_nXResolution*(fX2 - fScaledMinX)/(fScaledMaxX-fScaledMinX)) );
274 :
275 9892 : bool bSameY = ( static_cast<sal_Int32>(m_nYResolution*(fY - fScaledMinY)/(fScaledMaxY-fScaledMinY))
276 9892 : == static_cast<sal_Int32>(m_nYResolution*(fY2 - fScaledMinY)/(fScaledMaxY-fScaledMinY)) );
277 :
278 9892 : bool bSameZ = ( static_cast<sal_Int32>(m_nZResolution*(fZ - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ))
279 9892 : == static_cast<sal_Int32>(m_nZResolution*(fZ2 - fScaledMinZ)/(fScaledMaxZ-fScaledMinZ)) );
280 :
281 9892 : return (bSameX && bSameY && bSameZ);
282 : }
283 :
284 15736 : bool PlottingPositionHelper::isStrongLowerRequested( sal_Int32 nDimensionIndex ) const
285 : {
286 15736 : if( m_aScales.empty() )
287 0 : return false;
288 15736 : if( 0==nDimensionIndex )
289 13266 : return m_bAllowShiftXAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition;
290 2470 : else if( 2==nDimensionIndex )
291 2470 : return m_bAllowShiftZAxisPos && m_aScales[nDimensionIndex].ShiftedCategoryPosition;
292 0 : return false;
293 : }
294 :
295 2653 : bool PlottingPositionHelper::isLogicVisible(
296 : double fX, double fY, double fZ ) const
297 : {
298 5519 : return fX >= m_aScales[0].Minimum && ( isStrongLowerRequested(0) ? fX < m_aScales[0].Maximum : fX <= m_aScales[0].Maximum )
299 2653 : && fY >= m_aScales[1].Minimum && fY <= m_aScales[1].Maximum
300 7776 : && fZ >= m_aScales[2].Minimum && ( isStrongLowerRequested(2) ? fZ < m_aScales[2].Maximum : fZ <= m_aScales[2].Maximum );
301 : }
302 :
303 129958 : void PlottingPositionHelper::doLogicScaling( double* pX, double* pY, double* pZ, bool bClip ) const
304 : {
305 129958 : if(bClip)
306 0 : this->clipLogicValues( pX,pY,pZ );
307 :
308 129958 : if(pX)
309 : {
310 94074 : if( m_aScales[0].Scaling.is())
311 5864 : *pX = m_aScales[0].Scaling->doScaling(*pX);
312 94074 : if( m_bAllowShiftXAxisPos && m_aScales[0].ShiftedCategoryPosition )
313 26577 : (*pX) += m_fScaledCategoryWidth/2.0;
314 : }
315 129958 : if(pY && m_aScales[1].Scaling.is())
316 108606 : *pY = m_aScales[1].Scaling->doScaling(*pY);
317 129958 : if(pZ)
318 : {
319 84475 : if( m_aScales[2].Scaling.is())
320 0 : *pZ = m_aScales[2].Scaling->doScaling(*pZ);
321 84475 : if( m_bAllowShiftZAxisPos && m_aScales[2].ShiftedCategoryPosition)
322 2530 : (*pZ) += 0.5;
323 : }
324 129958 : }
325 :
326 232408 : void PlottingPositionHelper::doUnshiftedLogicScaling( double* pX, double* pY, double* pZ, bool bClip ) const
327 : {
328 232408 : if(bClip)
329 0 : this->clipLogicValues( pX,pY,pZ );
330 :
331 232408 : if(pX && m_aScales[0].Scaling.is())
332 10338 : *pX = m_aScales[0].Scaling->doScaling(*pX);
333 232408 : if(pY && m_aScales[1].Scaling.is())
334 220404 : *pY = m_aScales[1].Scaling->doScaling(*pY);
335 232408 : if(pZ && m_aScales[2].Scaling.is())
336 0 : *pZ = m_aScales[2].Scaling->doScaling(*pZ);
337 232408 : }
338 :
339 2125 : void PlottingPositionHelper::doLogicScaling( ::com::sun::star::drawing::Position3D& rPos, bool bClip ) const
340 : {
341 2125 : doLogicScaling( &rPos.PositionX, &rPos.PositionY, &rPos.PositionZ, bClip );
342 2125 : }
343 :
344 1608 : void PlottingPositionHelper::clipLogicValues( double* pX, double* pY, double* pZ ) const
345 : {
346 1608 : if(pX)
347 : {
348 1408 : if( *pX < m_aScales[0].Minimum )
349 0 : *pX = m_aScales[0].Minimum;
350 1408 : else if( *pX > m_aScales[0].Maximum )
351 0 : *pX = m_aScales[0].Maximum;
352 : }
353 1608 : if(pY)
354 : {
355 1604 : if( *pY < m_aScales[1].Minimum )
356 0 : *pY = m_aScales[1].Minimum;
357 1604 : else if( *pY > m_aScales[1].Maximum )
358 0 : *pY = m_aScales[1].Maximum;
359 : }
360 1608 : if(pZ)
361 : {
362 1400 : if( *pZ < m_aScales[2].Minimum )
363 0 : *pZ = m_aScales[2].Minimum;
364 1400 : else if( *pZ > m_aScales[2].Maximum )
365 0 : *pZ = m_aScales[2].Maximum;
366 : }
367 1608 : }
368 :
369 10588 : inline bool PlottingPositionHelper::clipYRange( double& rMin, double& rMax ) const
370 : {
371 : //returns true if something remains
372 10588 : if( rMin > rMax )
373 : {
374 152 : double fHelp = rMin;
375 152 : rMin = rMax;
376 152 : rMax = fHelp;
377 : }
378 10588 : if( rMin > getLogicMaxY() )
379 0 : return false;
380 10588 : if( rMax < getLogicMinY() )
381 87 : return false;
382 10501 : if( rMin < getLogicMinY() )
383 2241 : rMin = getLogicMinY();
384 10501 : if( rMax > getLogicMaxY() )
385 0 : rMax = getLogicMaxY();
386 10501 : return true;
387 : }
388 :
389 167153 : inline double PlottingPositionHelper::getLogicMinX() const
390 : {
391 167153 : return m_aScales[0].Minimum;
392 : }
393 178057 : inline double PlottingPositionHelper::getLogicMinY() const
394 : {
395 178057 : return m_aScales[1].Minimum;
396 : }
397 155087 : inline double PlottingPositionHelper::getLogicMinZ() const
398 : {
399 155087 : return m_aScales[2].Minimum;
400 : }
401 :
402 192234 : inline double PlottingPositionHelper::getLogicMaxX() const
403 : {
404 192234 : return m_aScales[0].Maximum;
405 : }
406 187932 : inline double PlottingPositionHelper::getLogicMaxY() const
407 : {
408 187932 : return m_aScales[1].Maximum;
409 : }
410 156695 : inline double PlottingPositionHelper::getLogicMaxZ() const
411 : {
412 156695 : return m_aScales[2].Maximum;
413 : }
414 25925 : inline bool PlottingPositionHelper::isMathematicalOrientationX() const
415 : {
416 25925 : return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[0].Orientation;
417 : }
418 26324 : inline bool PlottingPositionHelper::isMathematicalOrientationY() const
419 : {
420 26324 : return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[1].Orientation;
421 : }
422 25925 : inline bool PlottingPositionHelper::isMathematicalOrientationZ() const
423 : {
424 25925 : return ::com::sun::star::chart2::AxisOrientation_MATHEMATICAL == m_aScales[2].Orientation;
425 : }
426 53515 : inline bool PlottingPositionHelper::isSwapXAndY() const
427 : {
428 53515 : return m_bSwapXAndY;
429 : }
430 3005 : inline bool PlottingPositionHelper::maySkipPointsInRegressionCalculation() const
431 : {
432 3005 : return m_bMaySkipPointsInRegressionCalculation;
433 : }
434 :
435 : } //namespace chart
436 : #endif
437 :
438 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|