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