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