update credits
[LibreOffice.git] / chart2 / source / tools / ThreeDHelper.cxx
blob32406a57770b625c962f25a3f71fdf840176882d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "ThreeDHelper.hxx"
22 #include "macros.hxx"
23 #include "DiagramHelper.hxx"
24 #include "ChartTypeHelper.hxx"
25 #include "BaseGFXHelper.hxx"
26 #include "DataSeriesHelper.hxx"
27 #include "defines.hxx"
29 #include <editeng/unoprnms.hxx>
30 #include <com/sun/star/beans/XPropertyState.hpp>
31 #include <com/sun/star/chart2/XDiagram.hpp>
32 #include <com/sun/star/drawing/LineStyle.hpp>
34 //.............................................................................
35 namespace chart
37 //.............................................................................
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::chart2;
41 using ::com::sun::star::uno::Reference;
42 using ::com::sun::star::uno::Sequence;
43 using ::rtl::math::cos;
44 using ::rtl::math::sin;
45 using ::rtl::math::tan;
47 namespace
50 bool lcl_isRightAngledAxesSetAndSupported( const Reference< beans::XPropertySet >& xSceneProperties )
52 sal_Bool bRightAngledAxes = sal_False;
53 if( xSceneProperties.is() )
55 xSceneProperties->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes;
56 if(bRightAngledAxes)
58 uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY );
59 if( ChartTypeHelper::isSupportingRightAngledAxes(
60 DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) )
62 return true;
66 return false;
69 void lcl_RotateLightSource( const Reference< beans::XPropertySet >& xSceneProperties
70 , const OUString& rLightSourceDirection
71 , const OUString& rLightSourceOn
72 , const ::basegfx::B3DHomMatrix& rRotationMatrix )
74 if( xSceneProperties.is() )
76 sal_Bool bLightOn = sal_False;
77 if( xSceneProperties->getPropertyValue( rLightSourceOn ) >>= bLightOn )
79 if( bLightOn )
81 drawing::Direction3D aLight;
82 if( xSceneProperties->getPropertyValue( rLightSourceDirection ) >>= aLight )
84 ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) );
85 aLightVector = rRotationMatrix*aLightVector;
87 xSceneProperties->setPropertyValue( rLightSourceDirection
88 , uno::makeAny( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) );
95 void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRottion, const Reference< beans::XPropertySet >& xSceneProperties )
97 if(!xSceneProperties.is())
98 return;
100 ::basegfx::B3DHomMatrix aLightRottion( rLightRottion );
101 BaseGFXHelper::ReduceToRotationMatrix( aLightRottion );
103 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection1", "D3DSceneLightOn1", aLightRottion );
104 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection2", "D3DSceneLightOn2", aLightRottion );
105 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection3", "D3DSceneLightOn3", aLightRottion );
106 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection4", "D3DSceneLightOn4", aLightRottion );
107 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection5", "D3DSceneLightOn5", aLightRottion );
108 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection6", "D3DSceneLightOn6", aLightRottion );
109 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection7", "D3DSceneLightOn7", aLightRottion );
110 lcl_RotateLightSource( xSceneProperties, "D3DSceneLightDirection8", "D3DSceneLightOn8", aLightRottion );
113 ::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties )
115 ::basegfx::B3DHomMatrix aInverseRotation;
116 double fXAngleRad=0.0;
117 double fYAngleRad=0.0;
118 double fZAngleRad=0.0;
119 ThreeDHelper::getRotationAngleFromDiagram(
120 xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
121 aInverseRotation.rotate( 0.0, 0.0, -fZAngleRad );
122 aInverseRotation.rotate( 0.0, -fYAngleRad, 0.0 );
123 aInverseRotation.rotate( -fXAngleRad, 0.0, 0.0 );
124 return aInverseRotation;
127 ::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties )
129 ::basegfx::B3DHomMatrix aCompleteRotation;
130 double fXAngleRad=0.0;
131 double fYAngleRad=0.0;
132 double fZAngleRad=0.0;
133 ThreeDHelper::getRotationAngleFromDiagram(
134 xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
135 aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
136 return aCompleteRotation;
139 bool lcl_isEqual( const drawing::Direction3D& rA, const drawing::Direction3D& rB )
141 return ::rtl::math::approxEqual(rA.DirectionX, rB.DirectionX)
142 && ::rtl::math::approxEqual(rA.DirectionY, rB.DirectionY)
143 && ::rtl::math::approxEqual(rA.DirectionZ, rB.DirectionZ);
146 bool lcl_isLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, bool bRealistic )
148 if(!xDiagramProps.is())
149 return false;
151 sal_Bool bIsOn = sal_False;
152 xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2 ) >>= bIsOn;
153 if(!bIsOn)
154 return false;
156 uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY );
157 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
159 sal_Int32 nColor = 0;
160 xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ) >>= nColor;
161 if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) )
162 return false;
164 sal_Int32 nAmbientColor = 0;
165 xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR ) >>= nAmbientColor;
166 if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) )
167 return false;
169 drawing::Direction3D aDirection(0,0,0);
170 xDiagramProps->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ) >>= aDirection;
172 drawing::Direction3D aDefaultDirection( bRealistic
173 ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType)
174 : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) );
176 //rotate default light direction when right angled axes are off but supported
178 sal_Bool bRightAngledAxes = sal_False;
179 xDiagramProps->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes;
180 if(!bRightAngledAxes)
182 if( ChartTypeHelper::isSupportingRightAngledAxes(
183 DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) )
185 ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) );
186 BaseGFXHelper::ReduceToRotationMatrix( aRotation );
187 ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) );
188 aLightVector = aRotation*aLightVector;
189 aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector );
194 return lcl_isEqual( aDirection, aDefaultDirection );
197 bool lcl_isRealisticLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps )
199 return lcl_isLightScheme( xDiagramProps, true /*bRealistic*/ );
201 bool lcl_isSimpleLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps )
203 return lcl_isLightScheme( xDiagramProps, false /*bRealistic*/ );
205 void lcl_setLightsForScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, const ThreeDLookScheme& rScheme )
207 if(!xDiagramProps.is())
208 return;
209 if( rScheme == ThreeDLookScheme_Unknown)
210 return;
212 xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2, uno::makeAny( sal_True ) );
214 uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY );
215 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
216 uno::Any aADirection( uno::makeAny( rScheme == ThreeDLookScheme_Simple
217 ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType)
218 : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) ) );
220 xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2, aADirection );
221 //rotate light direction when right angled axes are off but supported
223 sal_Bool bRightAngledAxes = sal_False;
224 xDiagramProps->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes;
225 if(!bRightAngledAxes)
227 if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) )
229 ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) );
230 BaseGFXHelper::ReduceToRotationMatrix( aRotation );
231 lcl_RotateLightSource( xDiagramProps, "D3DSceneLightDirection2", "D3DSceneLightOn2", aRotation );
236 sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor( rScheme==ThreeDLookScheme_Simple, xChartType );
237 xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2, uno::makeAny( nColor ) );
239 sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor( rScheme==ThreeDLookScheme_Simple, xChartType );
240 xDiagramProps->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR, uno::makeAny( nAmbientColor ) );
243 bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode
244 , sal_Int32 nRoundedEdges
245 , sal_Int32 nObjectLines )
247 if(aShadeMode!=drawing::ShadeMode_SMOOTH)
248 return false;
249 if(nRoundedEdges!=5)
250 return false;
251 if(nObjectLines!=0)
252 return false;
253 return true;
256 bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode
257 , sal_Int32 nRoundedEdges
258 , sal_Int32 nObjectLines
259 , const uno::Reference< XDiagram >& xDiagram )
261 if(aShadeMode!=drawing::ShadeMode_FLAT)
262 return false;
263 if(nRoundedEdges!=0)
264 return false;
265 if(nObjectLines==0)
267 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
268 return ChartTypeHelper::noBordersForSimpleScheme( xChartType );
270 if(nObjectLines!=1)
271 return false;
272 return true;
275 void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode
276 , sal_Int32& rnRoundedEdges
277 , sal_Int32& rnObjectLines )
279 rShadeMode = drawing::ShadeMode_SMOOTH;
280 rnRoundedEdges = 5;
281 rnObjectLines = 0;
284 void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode
285 , sal_Int32& rnRoundedEdges
286 , sal_Int32& rnObjectLines
287 , const uno::Reference< XDiagram >& xDiagram )
289 rShadeMode = drawing::ShadeMode_FLAT;
290 rnRoundedEdges = 0;
292 uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
293 rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1;
296 } //end anonymous namespace
299 drawing::CameraGeometry ThreeDHelper::getDefaultCameraGeometry( bool bPie )
301 // ViewReferencePoint (Point on the View plane)
302 drawing::Position3D vrp(17634.6218373783, 10271.4823817647, 24594.8639082739);
303 // ViewPlaneNormal (Normal to the View Plane)
304 drawing::Direction3D vpn(0.416199821709347, 0.173649045905254, 0.892537795986984);
305 // ViewUpVector (determines the v-axis direction on the view plane as
306 // projection of VUP parallel to VPN onto th view pane)
307 drawing::Direction3D vup(-0.0733876362771618, 0.984807599917971, -0.157379306090273);
309 if( bPie )
311 vrp = drawing::Position3D( 0.0, 0.0, 87591.2408759124 );//--> 5 percent perspecitve
312 vpn = drawing::Direction3D( 0.0, 0.0, 1.0 );
313 vup = drawing::Direction3D( 0.0, 1.0, 0.0 );
316 return drawing::CameraGeometry( vrp, vpn, vup );
319 namespace
321 ::basegfx::B3DHomMatrix lcl_getCameraMatrix( const uno::Reference< beans::XPropertySet >& xSceneProperties )
323 drawing::HomogenMatrix aCameraMatrix;
325 drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
326 if( xSceneProperties.is() )
327 xSceneProperties->getPropertyValue( "D3DCameraGeometry" ) >>= aCG;
329 ::basegfx::B3DVector aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG.vpn ) );
330 ::basegfx::B3DVector aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG.vup ) );
332 //normalize vectors:
333 aVPN.normalize();
334 aVUP.normalize();
336 ::basegfx::B3DVector aCross = ::basegfx::cross( aVUP, aVPN );
338 //first line is VUP x VPN
339 aCameraMatrix.Line1.Column1 = aCross[0];
340 aCameraMatrix.Line1.Column2 = aCross[1];
341 aCameraMatrix.Line1.Column3 = aCross[2];
342 aCameraMatrix.Line1.Column4 = 0.0;
344 //second line is VUP
345 aCameraMatrix.Line2.Column1 = aVUP[0];
346 aCameraMatrix.Line2.Column2 = aVUP[1];
347 aCameraMatrix.Line2.Column3 = aVUP[2];
348 aCameraMatrix.Line2.Column4 = 0.0;
350 //third line is VPN
351 aCameraMatrix.Line3.Column1 = aVPN[0];
352 aCameraMatrix.Line3.Column2 = aVPN[1];
353 aCameraMatrix.Line3.Column3 = aVPN[2];
354 aCameraMatrix.Line3.Column4 = 0.0;
356 //fourth line is 0 0 0 1
357 aCameraMatrix.Line4.Column1 = 0.0;
358 aCameraMatrix.Line4.Column2 = 0.0;
359 aCameraMatrix.Line4.Column3 = 0.0;
360 aCameraMatrix.Line4.Column4 = 1.0;
362 return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix );
365 double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad )
367 //valid range: ]-Pi,Pi]
368 while( fAngleRad<=-F_PI )
369 fAngleRad+=(2*F_PI);
370 while( fAngleRad>F_PI )
371 fAngleRad-=(2*F_PI);
372 return fAngleRad;
375 void lcl_shiftAngleToIntervalMinus180To180( sal_Int32& rnAngleDegree )
377 //valid range: ]-180,180]
378 while( rnAngleDegree<=-180 )
379 rnAngleDegree+=360;
380 while( rnAngleDegree>180 )
381 rnAngleDegree-=360;
384 void lcl_shiftAngleToIntervalZeroTo360( sal_Int32& rnAngleDegree )
386 //valid range: [0,360[
387 while( rnAngleDegree<0 )
388 rnAngleDegree+=360;
389 while( rnAngleDegree>=360 )
390 rnAngleDegree-=360;
393 void lcl_ensureIntervalMinus1To1( double& rSinOrCos )
395 if (rSinOrCos < -1.0)
396 rSinOrCos = -1.0;
397 else if (rSinOrCos > 1.0)
398 rSinOrCos = 1.0;
401 bool lcl_isSinZero( double fAngleRad )
403 return ::basegfx::fTools::equalZero( sin(fAngleRad), 0.0000001 );
405 bool lcl_isCosZero( double fAngleRad )
407 return ::basegfx::fTools::equalZero( cos(fAngleRad), 0.0000001 );
412 void ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
413 sal_Int32 nElevationDeg, sal_Int32 nRotationDeg,
414 double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad)
416 // for a description of the algorithm see issue 72994
417 //http://www.openoffice.org/issues/show_bug.cgi?id=72994
418 //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt
420 lcl_shiftAngleToIntervalZeroTo360( nElevationDeg );
421 lcl_shiftAngleToIntervalZeroTo360( nRotationDeg );
423 double& x = rfXAngleRad;
424 double& y = rfYAngleRad;
425 double& z = rfZAngleRad;
427 double E = F_PI*nElevationDeg/180; //elevation in Rad
428 double R = F_PI*nRotationDeg/180; //rotation in Rad
430 if( (nRotationDeg == 0 || nRotationDeg == 180 )
431 && ( nElevationDeg == 90 || nElevationDeg == 270 ) )
433 //sR==0 && cE==0
434 z = 0.0;
435 //element 23
436 double f23 = cos(R)*sin(E);
437 if(f23>0)
438 x = F_PI/2;
439 else
440 x = -F_PI/2;
441 y = R;
443 else if( ( nRotationDeg == 90 || nRotationDeg == 270 )
444 && ( nElevationDeg == 90 || nElevationDeg == 270 ) )
446 //cR==0 && cE==0
447 z = F_PI/2;
448 if( sin(R)>0 )
449 x = F_PI/2.0;
450 else
451 x = -F_PI/2.0;
453 if( (sin(R)*sin(E))>0 )
454 y = 0.0;
455 else
456 y = F_PI;
458 else if( (nRotationDeg == 0 || nRotationDeg == 180 )
459 && ( nElevationDeg == 0 || nElevationDeg == 180 ) )
461 //sR==0 && sE==0
462 z = 0.0;
463 y = R;
464 x = E;
466 else if( ( nRotationDeg == 90 || nRotationDeg == 270 )
467 && ( nElevationDeg == 0 || nElevationDeg == 180 ) )
469 //cR==0 && sE==0
470 z = 0.0;
472 if( (sin(R)/cos(E))>0 )
473 y = F_PI/2;
474 else
475 y = -F_PI/2;
477 if( (cos(E))>0 )
478 x = 0;
479 else
480 x = F_PI;
482 else if ( nElevationDeg == 0 || nElevationDeg == 180 )
484 //sR!=0 cR!=0 sE==0
485 z = 0.0;
486 x = E;
487 y = R;
488 //use element 13 for sign
489 if((cos(x)*sin(y)*sin(R))<0.0)
490 y *= -1.0;
492 else if ( nElevationDeg == 90 || nElevationDeg == 270 )
494 //sR!=0 cR!=0 cE==0
495 //element 12 + 22 --> y=0 or F_PI and x=+-F_PI/2
496 //-->element 13/23:
497 z = atan(sin(R)/(cos(R)*sin(E)));
498 //use element 13 for sign for x
499 if( (sin(R)*sin(z))>0.0 )
500 x = F_PI/2;
501 else
502 x = -F_PI/2;
503 //use element 21 for y
504 if( (sin(R)*sin(E)*sin(z))>0.0)
505 y = 0.0;
506 else
507 y = F_PI;
509 else if ( nRotationDeg == 0 || nRotationDeg == 180 )
511 //sE!=0 cE!=0 sR==0
512 z = 0.0;
513 x = E;
514 y = R;
515 double f23 = cos(R)*sin(E);
516 if( (f23 * sin(x)) < 0.0 )
517 x *= -1.0; //todo ??
519 else if (nRotationDeg == 90 || nRotationDeg == 270)
521 //sE!=0 cE!=0 cR==0
522 //z = +- F_PI/2;
523 //x = +- F_PI/2;
524 z = F_PI/2;
525 x = F_PI/2;
526 double sR = sin(R);
527 if( sR<0.0 )
528 x *= -1.0; //different signs for x and z
530 //use element 21:
531 double cy = sR*sin(E)/sin(z);
532 lcl_ensureIntervalMinus1To1(cy);
533 y = acos(cy);
535 //use element 22 for sign:
536 if( (sin(x)*sin(y)*sin(z)*cos(E))<0.0)
537 y *= -1.0;
539 else
541 z = atan(tan(R) * sin(E));
542 if(cos(z)==0.0)
544 OSL_FAIL("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad");
545 return;
547 double cy = cos(R)/cos(z);
548 lcl_ensureIntervalMinus1To1(cy);
549 y = acos(cy);
551 //element 12 in 23
552 double fDenominator = cos(z)*(1.0-pow(sin(y),2));
553 if(fDenominator==0.0)
555 OSL_FAIL("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad");
556 return;
558 double sx = cos(R)*sin(E)/fDenominator;
559 lcl_ensureIntervalMinus1To1(sx);
560 x = asin( sx );
562 //use element 13 for sign:
563 double f13a = cos(x)*cos(z)*sin(y);
564 double f13b = sin(R)-sx*sin(z);
565 if( (f13b*f13a)<0.0 )
567 //change x or y
568 //use element 22 for further investigations:
569 //try
570 y *= -1;
571 double f22a = cos(x)*cos(z);
572 double f22b = cos(E)-(sx*sin(y)*sin(z));
573 if( (f22a*f22b)<0.0 )
575 y *= -1;
576 x=(F_PI-x);
579 else
581 //change nothing or both
582 //use element 22 for further investigations:
583 double f22a = cos(x)*cos(z);
584 double f22b = cos(E)-(sx*sin(y)*sin(z));
585 if( (f22a*f22b)<0.0 )
587 y *= -1;
588 x=(F_PI-x);
594 void ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
595 sal_Int32& rnElevationDeg, sal_Int32& rnRotationDeg,
596 double fXRad, double fYRad, double fZRad)
598 // for a description of the algorithm see issue 72994
599 //http://www.openoffice.org/issues/show_bug.cgi?id=72994
600 //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt
602 double R = 0.0; //Rotation in Rad
603 double E = 0.0; //Elevation in Rad
605 double& x = fXRad;
606 double& y = fYRad;
607 double& z = fZRad;
609 double f11 = cos(y)*cos(z);
611 if( lcl_isSinZero(y) )
613 //siny == 0
615 if( lcl_isCosZero(x) )
617 //siny == 0 && cosx == 0
619 if( lcl_isSinZero(z) )
621 //siny == 0 && cosx == 0 && sinz == 0
622 //example: x=+-90 y=0oder180 z=0(oder180)
624 //element 13+11
625 if( f11 > 0 )
626 R = 0.0;
627 else
628 R = F_PI;
630 //element 23
631 double f23 = cos(z)*sin(x) / cos(R);
632 if( f23 > 0 )
633 E = F_PI/2.0;
634 else
635 E = -F_PI/2.0;
637 else if( lcl_isCosZero(z) )
639 //siny == 0 && cosx == 0 && cosz == 0
640 //example: x=+-90 y=0oder180 z=+-90
642 double f13 = sin(x)*sin(z);
643 //element 13+11
644 if( f13 > 0 )
645 R = F_PI/2.0;
646 else
647 R = -F_PI/2.0;
649 //element 21
650 double f21 = cos(y)*sin(z) / sin(R);
651 if( f21 > 0 )
652 E = F_PI/2.0;
653 else
654 E = -F_PI/2.0;
656 else
658 //siny == 0 && cosx == 0 && cosz != 0 && sinz != 0
659 //element 11 && 13
660 double f13 = sin(x)*sin(z);
661 R = atan( f13/f11 );
663 if(f11<0)
664 R+=F_PI;
666 //element 23
667 double f23 = cos(z)*sin(x);
668 if( f23/cos(R) > 0 )
669 E = F_PI/2.0;
670 else
671 E = -F_PI/2.0;
674 else if( lcl_isSinZero(x) )
676 //sinY==0 sinX==0
677 //element 13+11
678 if( f11 > 0 )
679 R = 0.0;
680 else
681 R = F_PI;
683 double f22 = cos(x)*cos(z);
684 if( f22 > 0 )
685 E = 0.0;
686 else
687 E = F_PI;
689 else if( lcl_isSinZero(z) )
691 //sinY==0 sinZ==0 sinx!=0 cosx!=0
692 //element 13+11
693 if( f11 > 0 )
694 R = 0.0;
695 else
696 R = F_PI;
698 //element 22 && 23
699 double f22 = cos(x)*cos(z);
700 double f23 = cos(z)*sin(x);
701 E = atan( f23/(f22*cos(R)) );
702 if( (f22*cos(E))<0 )
703 E+=F_PI;
705 else if( lcl_isCosZero(z) )
707 //sinY == 0 && cosZ == 0 && cosx != 0 && sinx != 0
708 double f13 = sin(x)*sin(z);
709 //element 13+11
710 if( f13 > 0 )
711 R = F_PI/2.0;
712 else
713 R = -F_PI/2.0;
715 //element 21+22
716 double f21 = cos(y)*sin(z);
717 if( f21/sin(R) > 0 )
718 E = F_PI/2.0;
719 else
720 E = -F_PI/2.0;
722 else
724 //sinY == 0 && all other !=0
725 double f13 = sin(x)*sin(z);
726 R = atan( f13/f11 );
727 if( (f11*cos(R))<0.0 )
728 R+=F_PI;
730 double f22 = cos(x)*cos(z);
731 if( !lcl_isCosZero(R) )
732 E = atan( cos(z)*sin(x) /( f22*cos(R) ) );
733 else
734 E = atan( cos(y)*sin(z) /( f22*sin(R) ) );
735 if( (f22*cos(E))<0 )
736 E+=F_PI;
739 else if( lcl_isCosZero(y) )
741 //cosY==0
743 double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y);
744 if( f13 >= 0 )
745 R = F_PI/2.0;
746 else
747 R = -F_PI/2.0;
749 double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z);
750 if( f22 >= 0 )
751 E = 0.0;
752 else
753 E = F_PI;
755 else if( lcl_isSinZero(x) )
757 //cosY!=0 sinY!=0 sinX=0
758 if( lcl_isSinZero(z) )
760 //cosY!=0 sinY!=0 sinX=0 sinZ=0
761 double f13 = cos(x)*cos(z)*sin(y);
762 R = atan( f13/f11 );
763 //R = asin(f13);
764 if( f11<0 )
765 R+=F_PI;
767 double f22 = cos(x)*cos(z);
768 if( f22>0 )
769 E = 0.0;
770 else
771 E = F_PI;
773 else if( lcl_isCosZero(z) )
775 //cosY!=0 sinY!=0 sinX=0 cosZ=0
776 R = x;
777 E = y;//or -y
778 //use 23 for 'signs'
779 double f23 = -1.0*cos(x)*sin(y)*sin(z);
780 if( (f23*cos(R)*sin(E))<0.0 )
782 //change R or E
783 E = -y;
786 else
788 //cosY!=0 sinY!=0 sinX=0 sinZ!=0 cosZ!=0
789 double f13 = cos(x)*cos(z)*sin(y);
790 R = atan( f13/f11 );
792 if( f11<0 )
793 R+=F_PI;
795 double f21 = cos(y)*sin(z);
796 double f22 = cos(x)*cos(z);
797 E = atan(f21/(f22*sin(R)) );
799 if( (f22*cos(E))<0.0 )
800 E+=F_PI;
803 else if( lcl_isCosZero(x) )
805 //cosY!=0 sinY!=0 cosX=0
807 if( lcl_isSinZero(z) )
809 //cosY!=0 sinY!=0 cosX=0 sinZ=0
810 R=0;//13 -> R=0 or F_PI
811 if( f11<0.0 )
812 R=F_PI;
813 E=F_PI/2;//22 -> E=+-F_PI/2
814 //use element 11 and 23 for sign
815 double f23 = cos(z)*sin(x);
816 if( (f11*f23*sin(E))<0.0 )
817 E=-F_PI/2.0;
819 else if( lcl_isCosZero(z) )
821 //cosY!=0 sinY!=0 cosX=0 cosZ=0
822 //element 11 & 13:
823 if( (sin(x)*sin(z))>0.0 )
824 R=F_PI/2.0;
825 else
826 R=-F_PI/2.0;
827 //element 22:
828 E=acos( sin(x)*sin(y)*sin(z));
829 //use element 21 for sign:
830 if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 )
831 E*=-1.0;
833 else
835 //cosY!=0 sinY!=0 cosX=0 sinZ!=0 cosZ!=0
836 //element 13/11
837 R = atan( sin(x)*sin(z)/(cos(y)*cos(z)) );
838 //use 13 for 'sign'
839 if( (sin(x)*sin(z))<0.0 )
840 R += F_PI;
841 //element 22
842 E = acos(sin(x)*sin(y)*sin(z) );
843 //use 21 for sign
844 if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 )
845 E*=-1.0;
848 else if( lcl_isSinZero(z) )
850 //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ=0
851 //element 11
852 R=y;
853 //use elenment 13 for sign
854 if( (cos(x)*cos(z)*sin(y)*sin(R))<0.0 )
855 R*=-1.0;
856 //element 22
857 E = acos( cos(x)*cos(z) );
858 //use element 23 for sign
859 if( (cos(z)*sin(x)*cos(R)*sin(E))<0.0 )
860 E*=-1.0;
862 else if( lcl_isCosZero(z) )
864 //cosY!=0 sinY!=0 sinX!=0 cosX!=0 cosZ=0
865 //element 21/23
866 R=atan(-cos(y)/(cos(x)*sin(y)));
867 //use element 13 for 'sign'
868 if( (sin(x)*sin(z)*sin(R))<0.0 )
869 R+=F_PI;
870 //element 21/22
871 E=atan( cos(y)*sin(z)/(sin(R)*sin(x)*sin(y)*sin(z)) );
872 //use element 23 for 'sign'
873 if( (-cos(x)*sin(y)*sin(z)*cos(R)*sin(E))<0.0 )
874 E+=F_PI;
876 else
878 //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ!=0 cosZ!=0
879 //13/11:
880 double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y);
881 R = atan( f13/ f11 );
882 if(f11<0.0)
883 R+=F_PI;
884 double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z);
885 double f23 = cos(x)*sin(y)*sin(z)-cos(z)*sin(x);
886 //23/22:
887 E = atan( -1.0*f23/(f22*cos(R)) );
888 if(f22<0.0)
889 E+=F_PI;
892 rnElevationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( E ) );
893 rnRotationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( R ) );
896 double ThreeDHelper::getValueClippedToRange( double fAngle, const double& fPositivLimit )
898 if( fAngle<-1*fPositivLimit )
899 fAngle=-1*fPositivLimit;
900 else if( fAngle>fPositivLimit )
901 fAngle=fPositivLimit;
902 return fAngle;
905 double ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()
907 return 90.0;
910 double ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()
912 return 45.0;
915 void ThreeDHelper::adaptRadAnglesForRightAngledAxes( double& rfXAngleRad, double& rfYAngleRad )
917 rfXAngleRad = ThreeDHelper::getValueClippedToRange(rfXAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()) );
918 rfYAngleRad = ThreeDHelper::getValueClippedToRange(rfYAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()) );
921 void ThreeDHelper::getRotationAngleFromDiagram(
922 const Reference< beans::XPropertySet >& xSceneProperties, double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad )
924 //takes the camera and the transformation matrix into account
926 rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0;
928 if( !xSceneProperties.is() )
929 return;
931 //get camera rotation
932 ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( xSceneProperties ) );
933 BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix );
935 //get scene rotation
936 ::basegfx::B3DHomMatrix aSceneRotation;
938 drawing::HomogenMatrix aHomMatrix;
939 if( xSceneProperties->getPropertyValue( "D3DTransformMatrix") >>= aHomMatrix )
941 aSceneRotation = BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix );
942 BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
946 ::basegfx::B3DHomMatrix aResultRotation = aFixCameraRotationMatrix * aSceneRotation;
947 ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation ) );
949 rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getX());
950 rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getY());
951 rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getZ());
953 if(rfZAngleRad<(-F_PI/2) || rfZAngleRad>(F_PI/2))
955 rfZAngleRad-=F_PI;
956 rfXAngleRad-=F_PI;
957 rfYAngleRad=(F_PI-rfYAngleRad);
959 rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad);
960 rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad);
961 rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad);
965 void ThreeDHelper::switchRightAngledAxes( const Reference< beans::XPropertySet >& xSceneProperties, sal_Bool bRightAngledAxes, bool bRotateLights )
969 if( xSceneProperties.is() )
971 sal_Bool bOldRightAngledAxes = sal_False;
972 xSceneProperties->getPropertyValue( "RightAngledAxes") >>= bOldRightAngledAxes;
973 if( bOldRightAngledAxes!=bRightAngledAxes)
975 xSceneProperties->setPropertyValue( "RightAngledAxes", uno::makeAny( bRightAngledAxes ));
976 if( bRotateLights )
978 if(bRightAngledAxes)
980 ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( xSceneProperties ) );
981 lcl_rotateLights( aInverseRotation, xSceneProperties );
983 else
985 ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( xSceneProperties ) );
986 lcl_rotateLights( aCompleteRotation, xSceneProperties );
992 catch( const uno::Exception & ex )
994 ASSERT_EXCEPTION( ex );
998 void ThreeDHelper::setRotationAngleToDiagram(
999 const Reference< beans::XPropertySet >& xSceneProperties
1000 , double fXAngleRad, double fYAngleRad, double fZAngleRad )
1002 //the rotation of the camera is not touched but taken into account
1003 //the rotation difference is applied to the transformation matrix
1005 //the light sources will be adapted also
1007 if( !xSceneProperties.is() )
1008 return;
1012 //remind old rotation for adaption of light directions
1013 ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( xSceneProperties ) );
1015 ::basegfx::B3DHomMatrix aInverseCameraRotation;
1017 ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix(
1018 lcl_getCameraMatrix( xSceneProperties ) ) );
1019 aInverseCameraRotation.rotate( 0.0, 0.0, -aR.getZ() );
1020 aInverseCameraRotation.rotate( 0.0, -aR.getY(), 0.0 );
1021 aInverseCameraRotation.rotate( -aR.getX(), 0.0, 0.0 );
1024 ::basegfx::B3DHomMatrix aCumulatedRotation;
1025 aCumulatedRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
1027 //calculate new scene matrix
1028 ::basegfx::B3DHomMatrix aSceneRotation = aInverseCameraRotation*aCumulatedRotation;
1029 BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
1031 //set new rotation to transformation matrix
1032 xSceneProperties->setPropertyValue(
1033 "D3DTransformMatrix", uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
1035 //rotate lights if RightAngledAxes are not set or not supported
1036 sal_Bool bRightAngledAxes = sal_False;
1037 xSceneProperties->getPropertyValue( "RightAngledAxes") >>= bRightAngledAxes;
1038 uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY );
1039 if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes(
1040 DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) )
1042 ::basegfx::B3DHomMatrix aNewRotation;
1043 aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
1044 lcl_rotateLights( aNewRotation*aInverseOldRotation, xSceneProperties );
1047 catch( const uno::Exception & ex )
1049 ASSERT_EXCEPTION( ex );
1053 void ThreeDHelper::getRotationFromDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties
1054 , sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree )
1056 double fXAngle, fYAngle, fZAngle;
1057 ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle );
1059 if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1061 ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
1062 rnHorizontalAngleDegree, rnVerticalAngleDegree, fXAngle, fYAngle, fZAngle);
1063 rnVerticalAngleDegree*=-1;
1065 else
1067 fXAngle = BaseGFXHelper::Rad2Deg( fXAngle );
1068 fYAngle = BaseGFXHelper::Rad2Deg( fYAngle );
1069 fZAngle = BaseGFXHelper::Rad2Deg( fZAngle );
1071 rnHorizontalAngleDegree = ::basegfx::fround(fXAngle);
1072 rnVerticalAngleDegree = ::basegfx::fround(-1.0*fYAngle);
1073 //nZRotation = ::basegfx::fround(-1.0*fZAngle);
1076 lcl_shiftAngleToIntervalMinus180To180( rnHorizontalAngleDegree );
1077 lcl_shiftAngleToIntervalMinus180To180( rnVerticalAngleDegree );
1080 void ThreeDHelper::setRotationToDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties
1081 , sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree )
1083 //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false
1084 double fXAngle = BaseGFXHelper::Deg2Rad( nHorizontalAngleDegree );
1085 double fYAngle = BaseGFXHelper::Deg2Rad( -1*nVerticalYAngleDegree );
1086 double fZAngle = 0.0;
1088 if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1089 ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
1090 nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle );
1092 ThreeDHelper::setRotationAngleToDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle );
1095 void ThreeDHelper::getCameraDistanceRange( double& rfMinimumDistance, double& rfMaximumDistance )
1097 rfMinimumDistance = 3.0/4.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value
1098 rfMaximumDistance = 20.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value
1101 void ThreeDHelper::ensureCameraDistanceRange( double& rfCameraDistance )
1103 double fMin, fMax;
1104 getCameraDistanceRange( fMin, fMax );
1105 if( rfCameraDistance < fMin )
1106 rfCameraDistance = fMin;
1107 if( rfCameraDistance > fMax )
1108 rfCameraDistance = fMax;
1111 double ThreeDHelper::getCameraDistance(
1112 const Reference< beans::XPropertySet >& xSceneProperties )
1114 double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
1116 if( !xSceneProperties.is() )
1117 return fCameraDistance;
1121 drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
1122 xSceneProperties->getPropertyValue( "D3DCameraGeometry" ) >>= aCG;
1123 ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
1124 fCameraDistance = aVRP.getLength();
1126 ensureCameraDistanceRange( fCameraDistance );
1128 catch( const uno::Exception & ex )
1130 ASSERT_EXCEPTION( ex );
1132 return fCameraDistance;
1135 void ThreeDHelper::setCameraDistance(
1136 const Reference< beans::XPropertySet >& xSceneProperties, double fCameraDistance )
1138 if( !xSceneProperties.is() )
1139 return;
1143 if( fCameraDistance <= 0 )
1144 fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
1146 drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
1147 xSceneProperties->getPropertyValue( "D3DCameraGeometry" ) >>= aCG;
1148 ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
1149 if( ::basegfx::fTools::equalZero( aVRP.getLength() ) )
1150 aVRP = ::basegfx::B3DVector(0,0,1);
1151 aVRP.setLength(fCameraDistance);
1152 aCG.vrp = BaseGFXHelper::B3DVectorToPosition3D( aVRP );
1154 xSceneProperties->setPropertyValue( "D3DCameraGeometry", uno::makeAny( aCG ));
1156 catch( const uno::Exception & ex )
1158 ASSERT_EXCEPTION( ex );
1162 double ThreeDHelper::CameraDistanceToPerspective( double fCameraDistance )
1164 double fRet = fCameraDistance;
1165 double fMin, fMax;
1166 ThreeDHelper::getCameraDistanceRange( fMin, fMax );
1167 //fMax <-> 0; fMin <->100
1168 //a/x + b = y
1169 double a = 100.0*fMax*fMin/(fMax-fMin);
1170 double b = -a/fMax;
1172 fRet = a/fCameraDistance + b;
1174 return fRet;
1177 double ThreeDHelper::PerspectiveToCameraDistance( double fPerspective )
1179 double fRet = fPerspective;
1180 double fMin, fMax;
1181 ThreeDHelper::getCameraDistanceRange( fMin, fMax );
1182 //fMax <-> 0; fMin <->100
1183 //a/x + b = y
1184 double a = 100.0*fMax*fMin/(fMax-fMin);
1185 double b = -a/fMax;
1187 fRet = a/(fPerspective - b);
1189 return fRet;
1192 ThreeDLookScheme ThreeDHelper::detectScheme( const uno::Reference< XDiagram >& xDiagram )
1194 ThreeDLookScheme aScheme = ThreeDLookScheme_Unknown;
1196 sal_Int32 nRoundedEdges;
1197 sal_Int32 nObjectLines;
1198 ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines );
1200 //get shade mode and light settings:
1201 drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
1202 uno::Reference< beans::XPropertySet > xDiagramProps( xDiagram, uno::UNO_QUERY );
1205 if( xDiagramProps.is() )
1206 xDiagramProps->getPropertyValue( "D3DSceneShadeMode" )>>= aShadeMode;
1208 catch( const uno::Exception & ex )
1210 ASSERT_EXCEPTION( ex );
1213 if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, xDiagram ) )
1215 if( lcl_isSimpleLightScheme(xDiagramProps) )
1216 aScheme = ThreeDLookScheme_Simple;
1218 else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) )
1220 if( lcl_isRealisticLightScheme(xDiagramProps) )
1221 aScheme = ThreeDLookScheme_Realistic;
1224 return aScheme;
1227 void ThreeDHelper::setScheme( const uno::Reference< XDiagram >& xDiagram, ThreeDLookScheme aScheme )
1229 if( aScheme == ThreeDLookScheme_Unknown )
1230 return;
1232 drawing::ShadeMode aShadeMode;
1233 sal_Int32 nRoundedEdges;
1234 sal_Int32 nObjectLines;
1236 if( aScheme == ThreeDLookScheme_Simple )
1237 lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,xDiagram);
1238 else
1239 lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines);
1243 ThreeDHelper::setRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines );
1245 uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY );
1246 if( xProp.is() )
1248 drawing::ShadeMode aOldShadeMode;
1249 if( ! ( (xProp->getPropertyValue( "D3DSceneShadeMode" )>>=aOldShadeMode) &&
1250 aOldShadeMode == aShadeMode ))
1252 xProp->setPropertyValue( "D3DSceneShadeMode", uno::makeAny( aShadeMode ));
1256 lcl_setLightsForScheme( xProp, aScheme );
1258 catch( const uno::Exception & ex )
1260 ASSERT_EXCEPTION( ex );
1265 void ThreeDHelper::set3DSettingsToDefault( const uno::Reference< beans::XPropertySet >& xSceneProperties )
1267 Reference< beans::XPropertyState > xState( xSceneProperties, uno::UNO_QUERY );
1268 if(xState.is())
1270 xState->setPropertyToDefault( "D3DSceneDistance");
1271 xState->setPropertyToDefault( "D3DSceneFocalLength");
1273 ThreeDHelper::setDefaultRotation( xSceneProperties );
1274 ThreeDHelper::setDefaultIllumination( xSceneProperties );
1277 void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties, bool bPieOrDonut )
1279 if( !xSceneProperties.is() )
1280 return;
1282 drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) );
1283 xSceneProperties->setPropertyValue( "D3DCameraGeometry", uno::makeAny( aCameraGeo ));
1285 ::basegfx::B3DHomMatrix aSceneRotation;
1286 if( bPieOrDonut )
1287 aSceneRotation.rotate( -F_PI/3.0, 0, 0 );
1288 xSceneProperties->setPropertyValue( "D3DTransformMatrix",
1289 uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
1292 void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties )
1294 bool bPieOrDonut( DiagramHelper::isPieOrDonutChart( uno::Reference< XDiagram >(xSceneProperties, uno::UNO_QUERY) ) );
1295 ThreeDHelper::setDefaultRotation( xSceneProperties, bPieOrDonut );
1298 void ThreeDHelper::setDefaultIllumination( const uno::Reference< beans::XPropertySet >& xSceneProperties )
1300 if( !xSceneProperties.is() )
1301 return;
1303 drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
1306 xSceneProperties->getPropertyValue( "D3DSceneShadeMode" )>>= aShadeMode;
1307 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1, uno::makeAny( sal_False ) );
1308 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3, uno::makeAny( sal_False ) );
1309 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4, uno::makeAny( sal_False ) );
1310 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5, uno::makeAny( sal_False ) );
1311 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6, uno::makeAny( sal_False ) );
1312 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7, uno::makeAny( sal_False ) );
1313 xSceneProperties->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8, uno::makeAny( sal_False ) );
1315 catch( const uno::Exception & ex )
1317 ASSERT_EXCEPTION( ex );
1320 ThreeDLookScheme aScheme = (drawing::ShadeMode_FLAT==aShadeMode) ? ThreeDLookScheme_Simple : ThreeDLookScheme_Realistic;
1321 lcl_setLightsForScheme( xSceneProperties, aScheme );
1324 void ThreeDHelper::getRoundedEdgesAndObjectLines(
1325 const uno::Reference< XDiagram > & xDiagram
1326 , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines )
1328 rnRoundedEdges = -1;
1329 rnObjectLines = -1;
1332 bool bDifferentRoundedEdges = false;
1333 bool bDifferentObjectLines = false;
1335 drawing::LineStyle aLineStyle( drawing::LineStyle_SOLID );
1337 ::std::vector< uno::Reference< XDataSeries > > aSeriesList(
1338 DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1339 sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() );
1341 OUString aPercentDiagonalPropertyName( "PercentDiagonal" );
1342 OUString aBorderStylePropertyName( "BorderStyle" );
1344 for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS )
1346 uno::Reference< XDataSeries > xSeries( aSeriesList[nS] );
1347 uno::Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
1348 if(!nS)
1350 rnRoundedEdges = 0;
1353 sal_Int16 nPercentDiagonal = 0;
1355 xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal;
1356 rnRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal );
1358 if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1359 , aPercentDiagonalPropertyName, uno::makeAny(nPercentDiagonal) ) )
1360 bDifferentRoundedEdges = true;
1362 catch( const uno::Exception& e )
1364 ASSERT_EXCEPTION( e );
1365 bDifferentRoundedEdges = true;
1369 xProp->getPropertyValue( aBorderStylePropertyName ) >>= aLineStyle;
1371 if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1372 , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) )
1373 bDifferentObjectLines = true;
1375 catch( const uno::Exception& e )
1377 ASSERT_EXCEPTION( e );
1378 bDifferentObjectLines = true;
1381 else
1383 if( !bDifferentRoundedEdges )
1385 sal_Int16 nPercentDiagonal = 0;
1386 xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal;
1387 sal_Int32 nCurrentRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal );
1388 if(nCurrentRoundedEdges!=rnRoundedEdges
1389 || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1390 , aPercentDiagonalPropertyName, uno::makeAny( static_cast< sal_Int16 >(rnRoundedEdges) ) ) )
1392 bDifferentRoundedEdges = true;
1393 nCurrentRoundedEdges = -1;
1397 if( !bDifferentObjectLines )
1399 drawing::LineStyle aCurrentLineStyle;
1400 xProp->getPropertyValue( aBorderStylePropertyName ) >>= aCurrentLineStyle;
1401 if(aCurrentLineStyle!=aLineStyle
1402 || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1403 , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) )
1404 bDifferentObjectLines = true;
1407 if( bDifferentRoundedEdges && bDifferentObjectLines )
1408 break;
1411 //set rnObjectLines
1412 rnObjectLines = 0;
1413 if( bDifferentObjectLines )
1414 rnObjectLines = -1;
1415 else if( aLineStyle == drawing::LineStyle_SOLID )
1416 rnObjectLines = 1;
1418 catch( const uno::Exception& e )
1420 ASSERT_EXCEPTION( e );
1424 void ThreeDHelper::setRoundedEdgesAndObjectLines(
1425 const uno::Reference< XDiagram > & xDiagram
1426 , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines )
1428 if( (nRoundedEdges<0||nRoundedEdges>100) && nObjectLines!=0 && nObjectLines!=1 )
1429 return;
1431 drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
1432 if(nObjectLines==1)
1433 aLineStyle = drawing::LineStyle_SOLID;
1435 uno::Any aALineStyle( uno::makeAny(aLineStyle));
1436 uno::Any aARoundedEdges( uno::makeAny( static_cast< sal_Int16 >( nRoundedEdges )));
1438 ::std::vector< uno::Reference< XDataSeries > > aSeriesList(
1439 DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1440 sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() );
1441 for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS )
1443 uno::Reference< XDataSeries > xSeries( aSeriesList[nS] );
1445 if( nRoundedEdges>=0 && nRoundedEdges<=100 )
1446 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "PercentDiagonal", aARoundedEdges );
1448 if( nObjectLines==0 || nObjectLines==1 )
1449 DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, "BorderStyle", aALineStyle );
1453 CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( const Reference< beans::XPropertySet >& xSceneProperties )
1455 CuboidPlanePosition eRet(CuboidPlanePosition_Left);
1457 double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
1458 ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
1459 if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1461 ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
1462 fZAngleRad=0.0;
1464 if( sin(fYAngleRad)>0.0 )
1465 eRet = CuboidPlanePosition_Right;
1466 return eRet;
1469 CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( const Reference< beans::XPropertySet >& xSceneProperties )
1471 CuboidPlanePosition eRet(CuboidPlanePosition_Back);
1473 double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
1474 ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
1475 if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1477 ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
1478 fZAngleRad=0.0;
1480 if( cos(fXAngleRad)*cos(fYAngleRad)<0.0 )
1481 eRet = CuboidPlanePosition_Front;
1482 return eRet;
1485 CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( const Reference< beans::XPropertySet >& xSceneProperties )
1487 CuboidPlanePosition eRet(CuboidPlanePosition_Bottom);
1489 double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
1490 ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
1491 if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1493 ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
1494 fZAngleRad=0.0;
1496 if( sin(fXAngleRad)*cos(fYAngleRad)<0.0 )
1497 eRet = CuboidPlanePosition_Top;
1498 return eRet;
1501 //.............................................................................
1502 } //namespace chart
1503 //.............................................................................
1505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */