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 "PlottingPositionHelper.hxx"
27 #include "CommonConverters.hxx"
28 #include "ViewDefines.hxx"
29 #include "Linear3DTransformation.hxx"
30 #include "VPolarTransformation.hxx"
31 #include "ShapeFactory.hxx"
32 #include "PropertyMapper.hxx"
33 #include "DateHelper.hxx"
34 
35 #include <com/sun/star/chart/TimeUnit.hpp>
36 #include <com/sun/star/chart2/AxisType.hpp>
37 #include <com/sun/star/drawing/DoubleSequence.hpp>
38 #include <com/sun/star/drawing/Position3D.hpp>
39 
40 #include <rtl/math.hxx>
41 
42 //.............................................................................
43 namespace chart
44 {
45 //.............................................................................
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::chart2;
48 
PlottingPositionHelper()49 PlottingPositionHelper::PlottingPositionHelper()
50         : m_aScales()
51         , m_aMatrixScreenToScene()
52         , m_xTransformationLogicToScene(NULL)
53         , m_bSwapXAndY( false )
54         , m_nXResolution( 1000 )
55         , m_nYResolution( 1000 )
56         , m_nZResolution( 1000 )
57         , m_bMaySkipPointsInRegressionCalculation( true )
58         , m_bDateAxis(false)
59         , m_nTimeResolution( ::com::sun::star::chart::TimeUnit::DAY )
60         , m_aNullDate(30,12,1899)
61         , m_fScaledCategoryWidth(1.0)
62         , m_bAllowShiftXAxisPos(false)
63         , m_bAllowShiftZAxisPos(false)
64 {
65 }
PlottingPositionHelper(const PlottingPositionHelper & rSource)66 PlottingPositionHelper::PlottingPositionHelper( const PlottingPositionHelper& rSource )
67         : m_aScales( rSource.m_aScales )
68         , m_aMatrixScreenToScene( rSource.m_aMatrixScreenToScene )
69         , m_xTransformationLogicToScene( NULL ) //should be recalculated
70         , m_bSwapXAndY( rSource.m_bSwapXAndY )
71         , m_nXResolution( rSource.m_nXResolution )
72         , m_nYResolution( rSource.m_nYResolution )
73         , m_nZResolution( rSource.m_nZResolution )
74         , m_bMaySkipPointsInRegressionCalculation( rSource.m_bMaySkipPointsInRegressionCalculation )
75         , m_bDateAxis( rSource.m_bDateAxis )
76         , m_nTimeResolution( rSource.m_nTimeResolution )
77         , m_aNullDate( rSource.m_aNullDate )
78         , m_fScaledCategoryWidth( rSource.m_fScaledCategoryWidth )
79         , m_bAllowShiftXAxisPos( rSource.m_bAllowShiftXAxisPos )
80         , m_bAllowShiftZAxisPos( rSource.m_bAllowShiftZAxisPos )
81 {
82 }
83 
~PlottingPositionHelper()84 PlottingPositionHelper::~PlottingPositionHelper()
85 {
86 
87 }
88 
clone() const89 PlottingPositionHelper* PlottingPositionHelper::clone() const
90 {
91     PlottingPositionHelper* pRet = new PlottingPositionHelper(*this);
92     return pRet;
93 }
94 
createSecondaryPosHelper(const ExplicitScaleData & rSecondaryScale)95 PlottingPositionHelper* PlottingPositionHelper::createSecondaryPosHelper( const ExplicitScaleData& rSecondaryScale )
96 {
97     PlottingPositionHelper* pRet = this->clone();
98     pRet->m_aScales[1]=rSecondaryScale;
99     return pRet;
100 }
101 
setTransformationSceneToScreen(const drawing::HomogenMatrix & rMatrix)102 void PlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
103 {
104     m_aMatrixScreenToScene = HomogenMatrixToB3DHomMatrix(rMatrix);
105     m_xTransformationLogicToScene = NULL;
106 }
107 
setScales(const std::vector<ExplicitScaleData> & rScales,bool bSwapXAndYAxis)108 void PlottingPositionHelper::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis )
109 {
110     m_aScales = rScales;
111     m_bSwapXAndY = bSwapXAndYAxis;
112     m_xTransformationLogicToScene = NULL;
113 }
getScales() const114 const std::vector< ExplicitScaleData >& PlottingPositionHelper::getScales() const
115 {
116     return m_aScales;
117 }
118 
getTransformationScaledLogicToScene() const119 uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScaledLogicToScene() const
120 {
121     //this is a standard transformation for a cartesian coordinate system
122 
123     //transformation from 2) to 4) //@todo 2) and 4) need a ink to a document
124 
125     //we need to apply this transformation to each geometric object because of a bug/problem
126     //of the old drawing layer (the UNO_NAME_3D_EXTRUDE_DEPTH is an integer value instead of an double )
127     if(!m_xTransformationLogicToScene.is())
128     {
129         ::basegfx::B3DHomMatrix aMatrix;
130         double MinX = getLogicMinX();
131         double MinY = getLogicMinY();
132         double MinZ = getLogicMinZ();
133         double MaxX = getLogicMaxX();
134         double MaxY = getLogicMaxY();
135         double MaxZ = getLogicMaxZ();
136 
137         AxisOrientation nXAxisOrientation = m_aScales[0].Orientation;
138         AxisOrientation nYAxisOrientation = m_aScales[1].Orientation;
139         AxisOrientation nZAxisOrientation = m_aScales[2].Orientation;
140 
141         //apply scaling
142         doUnshiftedLogicScaling( &MinX, &MinY, &MinZ );
143         doUnshiftedLogicScaling( &MaxX, &MaxY, &MaxZ);
144 
145         if(m_bSwapXAndY)
146         {
147             std::swap(MinX,MinY);
148             std::swap(MaxX,MaxY);
149             std::swap(nXAxisOrientation,nYAxisOrientation);
150         }
151 
152         double fWidthX = MaxX - MinX;
153         double fWidthY = MaxY - MinY;
154         double fWidthZ = MaxZ - MinZ;
155 
156         double fScaleDirectionX = AxisOrientation_MATHEMATICAL==nXAxisOrientation ? 1.0 : -1.0;
157         double fScaleDirectionY = AxisOrientation_MATHEMATICAL==nYAxisOrientation ? 1.0 : -1.0;
158         double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==nZAxisOrientation ? -1.0 : 1.0;
159 
160         double fScaleX = fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX;
161         double fScaleY = fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY;
162         double fScaleZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
163 
164         aMatrix.scale(fScaleX, fScaleY, fScaleZ);
165 
166         if( AxisOrientation_MATHEMATICAL==nXAxisOrientation )
167             aMatrix.translate(-MinX*fScaleX, 0.0, 0.0);
168         else
169             aMatrix.translate(-MaxX*fScaleX, 0.0, 0.0);
170         if( AxisOrientation_MATHEMATICAL==nYAxisOrientation )
171             aMatrix.translate(0.0, -MinY*fScaleY, 0.0);
172         else
173             aMatrix.translate(0.0, -MaxY*fScaleY, 0.0);
174         if( AxisOrientation_MATHEMATICAL==nZAxisOrientation )
175             aMatrix.translate(0.0, 0.0, -MaxZ*fScaleZ);//z direction in draw is reverse mathematical direction
176         else
177             aMatrix.translate(0.0, 0.0, -MinZ*fScaleZ);
178 
179         aMatrix = m_aMatrixScreenToScene*aMatrix;
180 
181         m_xTransformationLogicToScene = new Linear3DTransformation(B3DHomMatrixToHomogenMatrix( aMatrix ),m_bSwapXAndY);
182     }
183     return m_xTransformationLogicToScene;
184 }
185 
transformLogicToScene(double fX,double fY,double fZ,bool bClip) const186 drawing::Position3D PlottingPositionHelper::transformLogicToScene(
187     double fX, double fY, double fZ, bool bClip ) const
188 {
189     this->doLogicScaling( &fX,&fY,&fZ );
190     if(bClip)
191         this->clipScaledLogicValues( &fX,&fY,&fZ );
192 
193     return this->transformScaledLogicToScene( fX, fY, fZ, false );
194 }
195 
transformScaledLogicToScene(double fX,double fY,double fZ,bool bClip) const196 drawing::Position3D PlottingPositionHelper::transformScaledLogicToScene(
197     double fX, double fY, double fZ, bool bClip  ) const
198 {
199     if( bClip )
200         this->clipScaledLogicValues( &fX,&fY,&fZ );
201 
202     drawing::Position3D aPos( fX, fY, fZ);
203 
204     uno::Reference< XTransformation > xTransformation =
205         this->getTransformationScaledLogicToScene();
206     uno::Sequence< double > aSeq =
207         xTransformation->transform( Position3DToSequence(aPos) );
208     return SequenceToPosition3D(aSeq);
209 }
210 
transformSceneToScreenPosition(const drawing::Position3D & rScenePosition3D,const uno::Reference<drawing::XShapes> & xSceneTarget,ShapeFactory * pShapeFactory,sal_Int32 nDimensionCount)211 awt::Point PlottingPositionHelper::transformSceneToScreenPosition( const drawing::Position3D& rScenePosition3D
212                 , const uno::Reference< drawing::XShapes >& xSceneTarget
213                 , ShapeFactory* pShapeFactory
214                 , sal_Int32 nDimensionCount )
215 {
216     //@todo would like to have a cheaper method to do this transformation
217     awt::Point aScreenPoint( static_cast<sal_Int32>(rScenePosition3D.PositionX), static_cast<sal_Int32>(rScenePosition3D.PositionY) );
218 
219     //transformation from scene to screen (only necessary for 3D):
220     if(3==nDimensionCount)
221     {
222         //create 3D anchor shape
223         tPropertyNameMap aDummyPropertyNameMap;
224         uno::Reference< drawing::XShape > xShape3DAnchor = pShapeFactory->createCube( xSceneTarget
225                 , rScenePosition3D,drawing::Direction3D(1,1,1)
226                 , 0, 0, aDummyPropertyNameMap);
227         //get 2D position from xShape3DAnchor
228         aScreenPoint = xShape3DAnchor->getPosition();
229         xSceneTarget->remove(xShape3DAnchor);
230     }
231     return aScreenPoint;
232 }
233 
transformScaledLogicToScene(drawing::PolyPolygonShape3D & rPolygon) const234 void PlottingPositionHelper::transformScaledLogicToScene( drawing::PolyPolygonShape3D& rPolygon ) const
235 {
236     drawing::Position3D aScenePosition;
237     for( sal_Int32 nS = rPolygon.SequenceX.getLength(); nS--;)
238     {
239         drawing::DoubleSequence& xValues = rPolygon.SequenceX[nS];
240         drawing::DoubleSequence& yValues = rPolygon.SequenceY[nS];
241         drawing::DoubleSequence& zValues = rPolygon.SequenceZ[nS];
242         for( sal_Int32 nP = xValues.getLength(); nP--; )
243         {
244             double& fX = xValues[nP];
245             double& fY = yValues[nP];
246             double& fZ = zValues[nP];
247             aScenePosition = this->transformScaledLogicToScene( fX,fY,fZ,true );
248             fX = aScenePosition.PositionX;
249             fY = aScenePosition.PositionY;
250             fZ = aScenePosition.PositionZ;
251         }
252     }
253 }
254 
255 
clipScaledLogicValues(double * pX,double * pY,double * pZ) const256 void PlottingPositionHelper::clipScaledLogicValues( double* pX, double* pY, double* pZ ) const
257 {
258     //get logic clip values:
259     double MinX = getLogicMinX();
260     double MinY = getLogicMinY();
261     double MinZ = getLogicMinZ();
262     double MaxX = getLogicMaxX();
263     double MaxY = getLogicMaxY();
264     double MaxZ = getLogicMaxZ();
265 
266     //apply scaling
267     doUnshiftedLogicScaling( &MinX, &MinY, &MinZ );
268     doUnshiftedLogicScaling( &MaxX, &MaxY, &MaxZ);
269 
270     if(pX)
271     {
272         if( *pX < MinX )
273             *pX = MinX;
274         else if( *pX > MaxX )
275             *pX = MaxX;
276     }
277     if(pY)
278     {
279         if( *pY < MinY )
280             *pY = MinY;
281         else if( *pY > MaxY )
282             *pY = MaxY;
283     }
284     if(pZ)
285     {
286         if( *pZ < MinZ )
287             *pZ = MinZ;
288         else if( *pZ > MaxZ )
289             *pZ = MaxZ;
290     }
291 }
292 
getScaledLogicClipDoubleRect() const293 basegfx::B2DRectangle PlottingPositionHelper::getScaledLogicClipDoubleRect() const
294 {
295     //get logic clip values:
296     double MinX = getLogicMinX();
297     double MinY = getLogicMinY();
298     double MinZ = getLogicMinZ();
299     double MaxX = getLogicMaxX();
300     double MaxY = getLogicMaxY();
301     double MaxZ = getLogicMaxZ();
302 
303     //apply scaling
304     doUnshiftedLogicScaling( &MinX, &MinY, &MinZ );
305     doUnshiftedLogicScaling( &MaxX, &MaxY, &MaxZ);
306 
307     basegfx::B2DRectangle aRet( MinX, MaxY, MaxX, MinY );
308     return aRet;
309 }
310 
getScaledLogicWidth() const311 drawing::Direction3D PlottingPositionHelper::getScaledLogicWidth() const
312 {
313     drawing::Direction3D aRet;
314 
315     double MinX = getLogicMinX();
316     double MinY = getLogicMinY();
317     double MinZ = getLogicMinZ();
318     double MaxX = getLogicMaxX();
319     double MaxY = getLogicMaxY();
320     double MaxZ = getLogicMaxZ();
321 
322     doLogicScaling( &MinX, &MinY, &MinZ );
323     doLogicScaling( &MaxX, &MaxY, &MaxZ);
324 
325     aRet.DirectionX = MaxX - MinX;
326     aRet.DirectionY = MaxY - MinY;
327     aRet.DirectionZ = MaxZ - MinZ;
328     return aRet;
329 }
330 
331 //-----------------------------------------------------------------------------
332 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
334 
PolarPlottingPositionHelper(NormalAxis eNormalAxis)335 PolarPlottingPositionHelper::PolarPlottingPositionHelper( NormalAxis eNormalAxis )
336     : m_fRadiusOffset(0.0)
337     , m_fAngleDegreeOffset(90.0)
338     , m_aUnitCartesianToScene()
339     , m_eNormalAxis(eNormalAxis)
340 {
341     m_bMaySkipPointsInRegressionCalculation = false;
342 }
343 
PolarPlottingPositionHelper(const PolarPlottingPositionHelper & rSource)344 PolarPlottingPositionHelper::PolarPlottingPositionHelper( const PolarPlottingPositionHelper& rSource )
345     : PlottingPositionHelper(rSource)
346     , m_fRadiusOffset( rSource.m_fRadiusOffset )
347     , m_fAngleDegreeOffset( rSource.m_fAngleDegreeOffset )
348     , m_aUnitCartesianToScene( rSource.m_aUnitCartesianToScene )
349     , m_eNormalAxis( rSource.m_eNormalAxis )
350 {
351 }
352 
~PolarPlottingPositionHelper()353 PolarPlottingPositionHelper::~PolarPlottingPositionHelper()
354 {
355 }
356 
clone() const357 PlottingPositionHelper* PolarPlottingPositionHelper::clone() const
358 {
359     PolarPlottingPositionHelper* pRet = new PolarPlottingPositionHelper(*this);
360     return pRet;
361 }
362 
setTransformationSceneToScreen(const drawing::HomogenMatrix & rMatrix)363 void PolarPlottingPositionHelper::setTransformationSceneToScreen( const drawing::HomogenMatrix& rMatrix)
364 {
365     PlottingPositionHelper::setTransformationSceneToScreen( rMatrix);
366     m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene );
367 }
setScales(const std::vector<ExplicitScaleData> & rScales,bool bSwapXAndYAxis)368 void PolarPlottingPositionHelper::setScales( const std::vector< ExplicitScaleData >& rScales, bool bSwapXAndYAxis )
369 {
370     PlottingPositionHelper::setScales( rScales, bSwapXAndYAxis );
371     m_aUnitCartesianToScene =impl_calculateMatrixUnitCartesianToScene( m_aMatrixScreenToScene );
372 }
373 
impl_calculateMatrixUnitCartesianToScene(const::basegfx::B3DHomMatrix & rMatrixScreenToScene) const374 ::basegfx::B3DHomMatrix PolarPlottingPositionHelper::impl_calculateMatrixUnitCartesianToScene( const ::basegfx::B3DHomMatrix& rMatrixScreenToScene ) const
375 {
376     ::basegfx::B3DHomMatrix aRet;
377 
378     if( m_aScales.empty() )
379         return aRet;
380 
381     double fTranslate =1.0;
382     double fScale     =FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0;
383 
384     double fTranslateLogicZ =fTranslate;
385     double fScaleLogicZ     =fScale;
386     {
387         double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==m_aScales[2].Orientation ? 1.0 : -1.0;
388         double MinZ = getLogicMinZ();
389         double MaxZ = getLogicMaxZ();
390         doLogicScaling( 0, 0, &MinZ );
391         doLogicScaling( 0, 0, &MaxZ );
392         double fWidthZ = MaxZ - MinZ;
393 
394         if( AxisOrientation_MATHEMATICAL==m_aScales[2].Orientation )
395             fTranslateLogicZ=MinZ;
396         else
397             fTranslateLogicZ=MaxZ;
398         fScaleLogicZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ;
399     }
400 
401     double fTranslateX = fTranslate;
402     double fTranslateY = fTranslate;
403     double fTranslateZ = fTranslate;
404 
405     double fScaleX = fScale;
406     double fScaleY = fScale;
407     double fScaleZ = fScale;
408 
409     switch(m_eNormalAxis)
410     {
411         case NormalAxis_X:
412             {
413                 fTranslateX = fTranslateLogicZ;
414                 fScaleX = fScaleLogicZ;
415             }
416             break;
417         case NormalAxis_Y:
418             {
419                 fTranslateY = fTranslateLogicZ;
420                 fScaleY = fScaleLogicZ;
421             }
422             break;
423         default: //NormalAxis_Z:
424             {
425                 fTranslateZ = fTranslateLogicZ;
426                 fScaleZ = fScaleLogicZ;
427             }
428             break;
429     }
430 
431     aRet.translate(fTranslateX, fTranslateY, fTranslateZ);//x first
432     aRet.scale(fScaleX, fScaleY, fScaleZ);//x first
433 
434     aRet = rMatrixScreenToScene * aRet;
435     return aRet;
436 }
437 
getUnitCartesianToScene() const438 ::basegfx::B3DHomMatrix PolarPlottingPositionHelper::getUnitCartesianToScene() const
439 {
440     return m_aUnitCartesianToScene;
441 }
442 
getTransformationScaledLogicToScene() const443 uno::Reference< XTransformation > PolarPlottingPositionHelper::getTransformationScaledLogicToScene() const
444 {
445     if( !m_xTransformationLogicToScene.is() )
446         m_xTransformationLogicToScene = new VPolarTransformation(*this);
447     return m_xTransformationLogicToScene;
448 }
449 
getWidthAngleDegree(double & fStartLogicValueOnAngleAxis,double & fEndLogicValueOnAngleAxis) const450 double PolarPlottingPositionHelper::getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const
451 {
452     const ExplicitScaleData& rAngleScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0];
453     if( AxisOrientation_MATHEMATICAL != rAngleScale.Orientation )
454     {
455         double fHelp = fEndLogicValueOnAngleAxis;
456         fEndLogicValueOnAngleAxis = fStartLogicValueOnAngleAxis;
457         fStartLogicValueOnAngleAxis = fHelp;
458     }
459 
460     double fStartAngleDegree = this->transformToAngleDegree( fStartLogicValueOnAngleAxis );
461     double fEndAngleDegree   = this->transformToAngleDegree( fEndLogicValueOnAngleAxis );
462     double fWidthAngleDegree = fEndAngleDegree - fStartAngleDegree;
463 
464     if( ::rtl::math::approxEqual( fStartAngleDegree, fEndAngleDegree )
465         && !::rtl::math::approxEqual( fStartLogicValueOnAngleAxis, fEndLogicValueOnAngleAxis ) )
466         fWidthAngleDegree = 360.0;
467 
468     while(fWidthAngleDegree<0.0)
469         fWidthAngleDegree+=360.0;
470     while(fWidthAngleDegree>360.0)
471         fWidthAngleDegree-=360.0;
472 
473     return fWidthAngleDegree;
474 }
475 
transformToAngleDegree(double fLogicValueOnAngleAxis,bool bDoScaling) const476 double PolarPlottingPositionHelper::transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling ) const
477 {
478     double fRet=0.0;
479 
480     double fAxisAngleScaleDirection = 1.0;
481     {
482         const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[1] : m_aScales[0];
483         if(AxisOrientation_MATHEMATICAL != rScale.Orientation)
484             fAxisAngleScaleDirection *= -1.0;
485     }
486 
487     double MinAngleValue = 0.0;
488     double MaxAngleValue = 0.0;
489     {
490         double MinX = getLogicMinX();
491         double MinY = getLogicMinY();
492         double MaxX = getLogicMaxX();
493         double MaxY = getLogicMaxY();
494         double MinZ = getLogicMinZ();
495         double MaxZ = getLogicMaxZ();
496 
497         doLogicScaling( &MinX, &MinY, &MinZ );
498         doLogicScaling( &MaxX, &MaxY, &MaxZ);
499 
500         MinAngleValue = m_bSwapXAndY ? MinY : MinX;
501         MaxAngleValue = m_bSwapXAndY ? MaxY : MaxX;
502     }
503 
504     double fScaledLogicAngleValue = 0.0;
505     if(bDoScaling)
506     {
507         double fX = m_bSwapXAndY ? getLogicMaxX() : fLogicValueOnAngleAxis;
508         double fY = m_bSwapXAndY ? fLogicValueOnAngleAxis : getLogicMaxY();
509         double fZ = getLogicMaxZ();
510         clipLogicValues( &fX, &fY, &fZ );
511         doLogicScaling( &fX, &fY, &fZ );
512         fScaledLogicAngleValue = m_bSwapXAndY ? fY : fX;
513     }
514     else
515         fScaledLogicAngleValue = fLogicValueOnAngleAxis;
516 
517     fRet = m_fAngleDegreeOffset
518                   + fAxisAngleScaleDirection*(fScaledLogicAngleValue-MinAngleValue)*360.0
519                     /fabs(MaxAngleValue-MinAngleValue);
520     while(fRet>360.0)
521         fRet-=360.0;
522     while(fRet<0)
523         fRet+=360.0;
524     return fRet;
525 }
526 
transformToRadius(double fLogicValueOnRadiusAxis,bool bDoScaling) const527 double PolarPlottingPositionHelper::transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling ) const
528 {
529     double fNormalRadius = 0.0;
530     {
531         double fScaledLogicRadiusValue = 0.0;
532         double fX = m_bSwapXAndY ? fLogicValueOnRadiusAxis: getLogicMaxX();
533         double fY = m_bSwapXAndY ? getLogicMaxY() : fLogicValueOnRadiusAxis;
534         if(bDoScaling)
535             doLogicScaling( &fX, &fY, 0 );
536 
537         fScaledLogicRadiusValue = m_bSwapXAndY ? fX : fY;
538 
539         bool bMinIsInnerRadius = true;
540         const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
541         if(AxisOrientation_MATHEMATICAL != rScale.Orientation)
542             bMinIsInnerRadius = false;
543 
544         double fInnerScaledLogicRadius=0.0;
545         double fOuterScaledLogicRadius=0.0;
546         {
547             double MinX = getLogicMinX();
548             double MinY = getLogicMinY();
549             doLogicScaling( &MinX, &MinY, 0 );
550             double MaxX = getLogicMaxX();
551             double MaxY = getLogicMaxY();
552             doLogicScaling( &MaxX, &MaxY, 0 );
553 
554             double fMin = m_bSwapXAndY ? MinX : MinY;
555             double fMax = m_bSwapXAndY ? MaxX : MaxY;
556 
557             fInnerScaledLogicRadius = bMinIsInnerRadius ? fMin : fMax;
558             fOuterScaledLogicRadius = bMinIsInnerRadius ? fMax : fMin;
559         }
560 
561         if( bMinIsInnerRadius )
562             fInnerScaledLogicRadius -= fabs(m_fRadiusOffset);
563         else
564             fInnerScaledLogicRadius += fabs(m_fRadiusOffset);
565         fNormalRadius = (fScaledLogicRadiusValue-fInnerScaledLogicRadius)/(fOuterScaledLogicRadius-fInnerScaledLogicRadius);
566     }
567     return fNormalRadius;
568 }
569 
transformLogicToScene(double fX,double fY,double fZ,bool bClip) const570 drawing::Position3D PolarPlottingPositionHelper::transformLogicToScene( double fX, double fY, double fZ, bool bClip ) const
571 {
572     if(bClip)
573         this->clipLogicValues( &fX,&fY,&fZ );
574     double fLogicValueOnAngleAxis  = m_bSwapXAndY ? fY : fX;
575     double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY;
576     return this->transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ, true );
577 }
578 
transformScaledLogicToScene(double fX,double fY,double fZ,bool bClip) const579 drawing::Position3D PolarPlottingPositionHelper::transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const
580 {
581     if(bClip)
582         this->clipScaledLogicValues( &fX,&fY,&fZ );
583     double fLogicValueOnAngleAxis  = m_bSwapXAndY ? fY : fX;
584     double fLogicValueOnRadiusAxis = m_bSwapXAndY ? fX : fY;
585     return this->transformAngleRadiusToScene( fLogicValueOnAngleAxis, fLogicValueOnRadiusAxis, fZ, false );
586 }
transformUnitCircleToScene(double fUnitAngleDegree,double fUnitRadius,double fLogicZ,bool) const587 drawing::Position3D PolarPlottingPositionHelper::transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius
588                                                                             , double fLogicZ, bool /* bDoScaling */ ) const
589 {
590     double fAnglePi = fUnitAngleDegree*F_PI/180.0;
591 
592     double fX=fUnitRadius*rtl::math::cos(fAnglePi);
593     double fY=fUnitRadius*rtl::math::sin(fAnglePi);
594     double fZ=fLogicZ;
595 
596     switch(m_eNormalAxis)
597     {
598         case NormalAxis_X:
599             std::swap(fX,fZ);
600             break;
601         case NormalAxis_Y:
602             std::swap(fY,fZ);
603             fZ*=-1;
604             break;
605         default: //NormalAxis_Z
606             break;
607     }
608 
609     //!! applying matrix to vector does ignore translation, so it is important to use a B3DPoint here instead of B3DVector
610     ::basegfx::B3DPoint aPoint(fX,fY,fZ);
611     ::basegfx::B3DPoint aRet = m_aUnitCartesianToScene * aPoint;
612     return B3DPointToPosition3D(aRet);
613 }
614 
transformAngleRadiusToScene(double fLogicValueOnAngleAxis,double fLogicValueOnRadiusAxis,double fLogicZ,bool bDoScaling) const615 drawing::Position3D PolarPlottingPositionHelper::transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling ) const
616 {
617     double fUnitAngleDegree = this->transformToAngleDegree(fLogicValueOnAngleAxis,bDoScaling);
618     double fUnitRadius      = this->transformToRadius(fLogicValueOnRadiusAxis,bDoScaling);
619 
620     return transformUnitCircleToScene( fUnitAngleDegree, fUnitRadius, fLogicZ, bDoScaling );
621 }
622 
623 #ifdef NOTYET
getInnerLogicRadius() const624 double PolarPlottingPositionHelper::getInnerLogicRadius() const
625 {
626     const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
627     if( AxisOrientation_MATHEMATICAL==rScale.Orientation )
628         return rScale.Minimum;
629     else
630         return rScale.Maximum;
631 }
632 #endif
633 
getOuterLogicRadius() const634 double PolarPlottingPositionHelper::getOuterLogicRadius() const
635 {
636     const ExplicitScaleData& rScale = m_bSwapXAndY ? m_aScales[0] : m_aScales[1];
637     if( AxisOrientation_MATHEMATICAL==rScale.Orientation )
638         return rScale.Maximum;
639     else
640         return rScale.Minimum;
641 }
642 
isPercentY() const643 bool PlottingPositionHelper::isPercentY() const
644 {
645     return m_aScales[1].AxisType==AxisType::PERCENT;
646 }
647 
getBaseValueY() const648 double PlottingPositionHelper::getBaseValueY() const
649 {
650     return m_aScales[1].Origin;
651 }
652 
setTimeResolution(long nTimeResolution,const Date & rNullDate)653 void PlottingPositionHelper::setTimeResolution( long nTimeResolution, const Date& rNullDate )
654 {
655     m_nTimeResolution = nTimeResolution;
656     m_aNullDate = rNullDate;
657 
658     //adapt category width
659     double fCategoryWidth = 1.0;
660     if( !m_aScales.empty() )
661     {
662         if( m_aScales[0].AxisType == ::com::sun::star::chart2::AxisType::DATE )
663         {
664             m_bDateAxis = true;
665             if( nTimeResolution == ::com::sun::star::chart::TimeUnit::YEAR )
666             {
667                 const double fMonthCount = 12.0;//todo: this depends on the DateScaling and must be adjusted in case we use more generic calendars in future
668                 fCategoryWidth = fMonthCount;
669             }
670         }
671     }
672     setScaledCategoryWidth(fCategoryWidth);
673 }
674 
setScaledCategoryWidth(double fScaledCategoryWidth)675 void PlottingPositionHelper::setScaledCategoryWidth( double fScaledCategoryWidth )
676 {
677     m_fScaledCategoryWidth = fScaledCategoryWidth;
678 }
AllowShiftXAxisPos(bool bAllowShift)679 void PlottingPositionHelper::AllowShiftXAxisPos( bool bAllowShift )
680 {
681     m_bAllowShiftXAxisPos = bAllowShift;
682 }
AllowShiftZAxisPos(bool bAllowShift)683 void PlottingPositionHelper::AllowShiftZAxisPos( bool bAllowShift )
684 {
685     m_bAllowShiftZAxisPos = bAllowShift;
686 }
687 
688 /*
689 // ____ XTransformation ____
690 uno::Sequence< double > SAL_CALL PolarPlottingPositionHelper::transform(
691                         const uno::Sequence< double >& rSourceValues )
692             throw (uno::RuntimeException, lang::IllegalArgumentException)
693 {
694     uno::Sequence< double > aSourceValues(3);
695     return aSourceValues;
696 }
697 
698 sal_Int32 SAL_CALL PolarPlottingPositionHelper::getSourceDimension() throw (uno::RuntimeException)
699 {
700     return 3;
701 }
702 
703 sal_Int32 SAL_CALL PolarPlottingPositionHelper::getTargetDimension() throw (uno::RuntimeException)
704 {
705     return 3;
706 }
707 */
708 
709 //.............................................................................
710 } //namespace chart
711 //.............................................................................
712