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