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 :
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"
28 :
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>
33 :
34 : //.............................................................................
35 : namespace chart
36 : {
37 : //.............................................................................
38 : using namespace ::com::sun::star;
39 : using namespace ::com::sun::star::chart2;
40 :
41 : using ::com::sun::star::uno::Reference;
42 : using ::com::sun::star::uno::Sequence;
43 : using ::rtl::OUString;
44 : using ::rtl::math::cos;
45 : using ::rtl::math::sin;
46 : using ::rtl::math::tan;
47 :
48 : namespace
49 : {
50 :
51 0 : bool lcl_isRightAngledAxesSetAndSupported( const Reference< beans::XPropertySet >& xSceneProperties )
52 : {
53 0 : sal_Bool bRightAngledAxes = sal_False;
54 0 : if( xSceneProperties.is() )
55 : {
56 0 : xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes;
57 0 : if(bRightAngledAxes)
58 : {
59 0 : uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY );
60 0 : if( ChartTypeHelper::isSupportingRightAngledAxes(
61 0 : DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) )
62 : {
63 0 : return true;
64 0 : }
65 : }
66 : }
67 0 : return false;
68 : }
69 :
70 0 : void lcl_RotateLightSource( const Reference< beans::XPropertySet >& xSceneProperties
71 : , const OUString& rLightSourceDirection
72 : , const OUString& rLightSourceOn
73 : , const ::basegfx::B3DHomMatrix& rRotationMatrix )
74 : {
75 0 : if( xSceneProperties.is() )
76 : {
77 0 : sal_Bool bLightOn = sal_False;
78 0 : if( xSceneProperties->getPropertyValue( rLightSourceOn ) >>= bLightOn )
79 : {
80 0 : if( bLightOn )
81 : {
82 0 : drawing::Direction3D aLight;
83 0 : if( xSceneProperties->getPropertyValue( rLightSourceDirection ) >>= aLight )
84 : {
85 0 : ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) );
86 0 : aLightVector = rRotationMatrix*aLightVector;
87 :
88 0 : xSceneProperties->setPropertyValue( rLightSourceDirection
89 0 : , uno::makeAny( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) );
90 : }
91 : }
92 : }
93 : }
94 0 : }
95 :
96 0 : void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRottion, const Reference< beans::XPropertySet >& xSceneProperties )
97 : {
98 0 : if(!xSceneProperties.is())
99 0 : return;
100 :
101 0 : ::basegfx::B3DHomMatrix aLightRottion( rLightRottion );
102 0 : BaseGFXHelper::ReduceToRotationMatrix( aLightRottion );
103 :
104 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection1"), C2U("D3DSceneLightOn1"), aLightRottion );
105 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection2"), C2U("D3DSceneLightOn2"), aLightRottion );
106 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection3"), C2U("D3DSceneLightOn3"), aLightRottion );
107 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection4"), C2U("D3DSceneLightOn4"), aLightRottion );
108 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection5"), C2U("D3DSceneLightOn5"), aLightRottion );
109 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection6"), C2U("D3DSceneLightOn6"), aLightRottion );
110 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection7"), C2U("D3DSceneLightOn7"), aLightRottion );
111 0 : lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection8"), C2U("D3DSceneLightOn8"), aLightRottion );
112 : }
113 :
114 0 : ::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties )
115 : {
116 0 : ::basegfx::B3DHomMatrix aInverseRotation;
117 0 : double fXAngleRad=0.0;
118 0 : double fYAngleRad=0.0;
119 0 : double fZAngleRad=0.0;
120 : ThreeDHelper::getRotationAngleFromDiagram(
121 0 : xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
122 0 : aInverseRotation.rotate( 0.0, 0.0, -fZAngleRad );
123 0 : aInverseRotation.rotate( 0.0, -fYAngleRad, 0.0 );
124 0 : aInverseRotation.rotate( -fXAngleRad, 0.0, 0.0 );
125 0 : return aInverseRotation;
126 : }
127 :
128 0 : ::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties )
129 : {
130 0 : ::basegfx::B3DHomMatrix aCompleteRotation;
131 0 : double fXAngleRad=0.0;
132 0 : double fYAngleRad=0.0;
133 0 : double fZAngleRad=0.0;
134 : ThreeDHelper::getRotationAngleFromDiagram(
135 0 : xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
136 0 : aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
137 0 : return aCompleteRotation;
138 : }
139 :
140 0 : bool lcl_isEqual( const drawing::Direction3D& rA, const drawing::Direction3D& rB )
141 : {
142 0 : return ::rtl::math::approxEqual(rA.DirectionX, rB.DirectionX)
143 0 : && ::rtl::math::approxEqual(rA.DirectionY, rB.DirectionY)
144 0 : && ::rtl::math::approxEqual(rA.DirectionZ, rB.DirectionZ);
145 : }
146 :
147 0 : bool lcl_isLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, bool bRealistic )
148 : {
149 0 : if(!xDiagramProps.is())
150 0 : return false;
151 :
152 0 : sal_Bool bIsOn = sal_False;
153 0 : xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ) ) >>= bIsOn;
154 0 : if(!bIsOn)
155 0 : return false;
156 :
157 0 : uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY );
158 0 : uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
159 :
160 0 : sal_Int32 nColor = 0;
161 0 : xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ) ) >>= nColor;
162 0 : if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) )
163 0 : return false;
164 :
165 0 : sal_Int32 nAmbientColor = 0;
166 0 : xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ) ) >>= nAmbientColor;
167 0 : if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) )
168 0 : return false;
169 :
170 0 : drawing::Direction3D aDirection(0,0,0);
171 0 : xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ) ) >>= aDirection;
172 :
173 : drawing::Direction3D aDefaultDirection( bRealistic
174 : ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType)
175 0 : : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) );
176 :
177 : //rotate default light direction when right angled axes are off but supported
178 : {
179 0 : sal_Bool bRightAngledAxes = sal_False;
180 0 : xDiagramProps->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes;
181 0 : if(!bRightAngledAxes)
182 : {
183 0 : if( ChartTypeHelper::isSupportingRightAngledAxes(
184 0 : DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) )
185 : {
186 0 : ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) );
187 0 : BaseGFXHelper::ReduceToRotationMatrix( aRotation );
188 0 : ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) );
189 0 : aLightVector = aRotation*aLightVector;
190 0 : aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector );
191 : }
192 : }
193 : }
194 :
195 0 : return lcl_isEqual( aDirection, aDefaultDirection );
196 : }
197 :
198 0 : bool lcl_isRealisticLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps )
199 : {
200 0 : return lcl_isLightScheme( xDiagramProps, true /*bRealistic*/ );
201 : }
202 0 : bool lcl_isSimpleLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps )
203 : {
204 0 : return lcl_isLightScheme( xDiagramProps, false /*bRealistic*/ );
205 : }
206 41 : void lcl_setLightsForScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, const ThreeDLookScheme& rScheme )
207 : {
208 41 : if(!xDiagramProps.is())
209 : return;
210 41 : if( rScheme == ThreeDLookScheme_Unknown)
211 : return;
212 :
213 41 : xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ), uno::makeAny( sal_True ) );
214 :
215 41 : uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY );
216 41 : uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
217 : uno::Any aADirection( uno::makeAny( rScheme == ThreeDLookScheme_Simple
218 : ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType)
219 41 : : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) ) );
220 :
221 41 : xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ), aADirection );
222 : //rotate light direction when right angled axes are off but supported
223 : {
224 41 : sal_Bool bRightAngledAxes = sal_False;
225 41 : xDiagramProps->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes;
226 41 : if(!bRightAngledAxes)
227 : {
228 0 : if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) )
229 : {
230 0 : ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) );
231 0 : BaseGFXHelper::ReduceToRotationMatrix( aRotation );
232 0 : lcl_RotateLightSource( xDiagramProps, C2U("D3DSceneLightDirection2"), C2U("D3DSceneLightOn2"), aRotation );
233 : }
234 : }
235 : }
236 :
237 41 : sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor( rScheme==ThreeDLookScheme_Simple, xChartType );
238 41 : xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ), uno::makeAny( nColor ) );
239 :
240 41 : sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor( rScheme==ThreeDLookScheme_Simple, xChartType );
241 41 : xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ), uno::makeAny( nAmbientColor ) );
242 : }
243 :
244 0 : bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode
245 : , sal_Int32 nRoundedEdges
246 : , sal_Int32 nObjectLines )
247 : {
248 0 : if(aShadeMode!=drawing::ShadeMode_SMOOTH)
249 0 : return false;
250 0 : if(nRoundedEdges!=5)
251 0 : return false;
252 0 : if(nObjectLines!=0)
253 0 : return false;
254 0 : return true;
255 : }
256 :
257 0 : bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode
258 : , sal_Int32 nRoundedEdges
259 : , sal_Int32 nObjectLines
260 : , const uno::Reference< XDiagram >& xDiagram )
261 : {
262 0 : if(aShadeMode!=drawing::ShadeMode_FLAT)
263 0 : return false;
264 0 : if(nRoundedEdges!=0)
265 0 : return false;
266 0 : if(nObjectLines==0)
267 : {
268 0 : uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
269 0 : return ChartTypeHelper::noBordersForSimpleScheme( xChartType );
270 : }
271 0 : if(nObjectLines!=1)
272 0 : return false;
273 0 : return true;
274 : }
275 :
276 41 : void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode
277 : , sal_Int32& rnRoundedEdges
278 : , sal_Int32& rnObjectLines )
279 : {
280 41 : rShadeMode = drawing::ShadeMode_SMOOTH;
281 41 : rnRoundedEdges = 5;
282 41 : rnObjectLines = 0;
283 41 : }
284 :
285 0 : void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode
286 : , sal_Int32& rnRoundedEdges
287 : , sal_Int32& rnObjectLines
288 : , const uno::Reference< XDiagram >& xDiagram )
289 : {
290 0 : rShadeMode = drawing::ShadeMode_FLAT;
291 0 : rnRoundedEdges = 0;
292 :
293 0 : uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
294 0 : rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1;
295 0 : }
296 :
297 : } //end anonymous namespace
298 :
299 :
300 81 : drawing::CameraGeometry ThreeDHelper::getDefaultCameraGeometry( bool bPie )
301 : {
302 : // ViewReferencePoint (Point on the View plane)
303 81 : drawing::Position3D vrp(17634.6218373783, 10271.4823817647, 24594.8639082739);
304 : // ViewPlaneNormal (Normal to the View Plane)
305 81 : drawing::Direction3D vpn(0.416199821709347, 0.173649045905254, 0.892537795986984);
306 : // ViewUpVector (determines the v-axis direction on the view plane as
307 : // projection of VUP parallel to VPN onto th view pane)
308 81 : drawing::Direction3D vup(-0.0733876362771618, 0.984807599917971, -0.157379306090273);
309 :
310 81 : if( bPie )
311 : {
312 0 : vrp = drawing::Position3D( 0.0, 0.0, 87591.2408759124 );//--> 5 percent perspecitve
313 0 : vpn = drawing::Direction3D( 0.0, 0.0, 1.0 );
314 0 : vup = drawing::Direction3D( 0.0, 1.0, 0.0 );
315 : }
316 :
317 81 : return drawing::CameraGeometry( vrp, vpn, vup );
318 : }
319 :
320 : namespace
321 : {
322 0 : ::basegfx::B3DHomMatrix lcl_getCameraMatrix( const uno::Reference< beans::XPropertySet >& xSceneProperties )
323 : {
324 0 : drawing::HomogenMatrix aCameraMatrix;
325 :
326 0 : drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
327 0 : if( xSceneProperties.is() )
328 0 : xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG;
329 :
330 0 : ::basegfx::B3DVector aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG.vpn ) );
331 0 : ::basegfx::B3DVector aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG.vup ) );
332 :
333 : //normalize vectors:
334 0 : aVPN.normalize();
335 0 : aVUP.normalize();
336 :
337 0 : ::basegfx::B3DVector aCross = ::basegfx::cross( aVUP, aVPN );
338 :
339 : //first line is VUP x VPN
340 0 : aCameraMatrix.Line1.Column1 = aCross[0];
341 0 : aCameraMatrix.Line1.Column2 = aCross[1];
342 0 : aCameraMatrix.Line1.Column3 = aCross[2];
343 0 : aCameraMatrix.Line1.Column4 = 0.0;
344 :
345 : //second line is VUP
346 0 : aCameraMatrix.Line2.Column1 = aVUP[0];
347 0 : aCameraMatrix.Line2.Column2 = aVUP[1];
348 0 : aCameraMatrix.Line2.Column3 = aVUP[2];
349 0 : aCameraMatrix.Line2.Column4 = 0.0;
350 :
351 : //third line is VPN
352 0 : aCameraMatrix.Line3.Column1 = aVPN[0];
353 0 : aCameraMatrix.Line3.Column2 = aVPN[1];
354 0 : aCameraMatrix.Line3.Column3 = aVPN[2];
355 0 : aCameraMatrix.Line3.Column4 = 0.0;
356 :
357 : //fourth line is 0 0 0 1
358 0 : aCameraMatrix.Line4.Column1 = 0.0;
359 0 : aCameraMatrix.Line4.Column2 = 0.0;
360 0 : aCameraMatrix.Line4.Column3 = 0.0;
361 0 : aCameraMatrix.Line4.Column4 = 1.0;
362 :
363 0 : return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix );
364 : }
365 :
366 0 : double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad )
367 : {
368 : //valid range: ]-Pi,Pi]
369 0 : while( fAngleRad<=-F_PI )
370 0 : fAngleRad+=(2*F_PI);
371 0 : while( fAngleRad>F_PI )
372 0 : fAngleRad-=(2*F_PI);
373 0 : return fAngleRad;
374 : }
375 :
376 0 : void lcl_shiftAngleToIntervalMinus180To180( sal_Int32& rnAngleDegree )
377 : {
378 : //valid range: ]-180,180]
379 0 : while( rnAngleDegree<=-180 )
380 0 : rnAngleDegree+=360;
381 0 : while( rnAngleDegree>180 )
382 0 : rnAngleDegree-=360;
383 0 : }
384 :
385 0 : void lcl_shiftAngleToIntervalZeroTo360( sal_Int32& rnAngleDegree )
386 : {
387 : //valid range: [0,360[
388 0 : while( rnAngleDegree<0 )
389 0 : rnAngleDegree+=360;
390 0 : while( rnAngleDegree>=360 )
391 0 : rnAngleDegree-=360;
392 0 : }
393 :
394 0 : void lcl_ensureIntervalMinus1To1( double& rSinOrCos )
395 : {
396 0 : if (rSinOrCos < -1.0)
397 0 : rSinOrCos = -1.0;
398 0 : else if (rSinOrCos > 1.0)
399 0 : rSinOrCos = 1.0;
400 0 : }
401 :
402 0 : bool lcl_isSinZero( double fAngleRad )
403 : {
404 0 : return ::basegfx::fTools::equalZero( sin(fAngleRad), 0.0000001 );
405 : }
406 0 : bool lcl_isCosZero( double fAngleRad )
407 : {
408 0 : return ::basegfx::fTools::equalZero( cos(fAngleRad), 0.0000001 );
409 : }
410 :
411 : }
412 :
413 0 : void ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
414 : sal_Int32 nElevationDeg, sal_Int32 nRotationDeg,
415 : double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad)
416 : {
417 : // for a description of the algorithm see issue 72994
418 : //http://www.openoffice.org/issues/show_bug.cgi?id=72994
419 : //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt
420 :
421 0 : lcl_shiftAngleToIntervalZeroTo360( nElevationDeg );
422 0 : lcl_shiftAngleToIntervalZeroTo360( nRotationDeg );
423 :
424 0 : double& x = rfXAngleRad;
425 0 : double& y = rfYAngleRad;
426 0 : double& z = rfZAngleRad;
427 :
428 0 : double E = F_PI*nElevationDeg/180; //elevation in Rad
429 0 : double R = F_PI*nRotationDeg/180; //rotation in Rad
430 :
431 0 : if( (nRotationDeg == 0 || nRotationDeg == 180 )
432 : && ( nElevationDeg == 90 || nElevationDeg == 270 ) )
433 : {
434 : //sR==0 && cE==0
435 0 : z = 0.0;
436 : //element 23
437 0 : double f23 = cos(R)*sin(E);
438 0 : if(f23>0)
439 0 : x = F_PI/2;
440 : else
441 0 : x = -F_PI/2;
442 0 : y = R;
443 : }
444 0 : else if( ( nRotationDeg == 90 || nRotationDeg == 270 )
445 : && ( nElevationDeg == 90 || nElevationDeg == 270 ) )
446 : {
447 : //cR==0 && cE==0
448 0 : z = F_PI/2;
449 0 : if( sin(R)>0 )
450 0 : x = F_PI/2.0;
451 : else
452 0 : x = -F_PI/2.0;
453 :
454 0 : if( (sin(R)*sin(E))>0 )
455 0 : y = 0.0;
456 : else
457 0 : y = F_PI;
458 : }
459 0 : else if( (nRotationDeg == 0 || nRotationDeg == 180 )
460 : && ( nElevationDeg == 0 || nElevationDeg == 180 ) )
461 : {
462 : //sR==0 && sE==0
463 0 : z = 0.0;
464 0 : y = R;
465 0 : x = E;
466 : }
467 0 : else if( ( nRotationDeg == 90 || nRotationDeg == 270 )
468 : && ( nElevationDeg == 0 || nElevationDeg == 180 ) )
469 : {
470 : //cR==0 && sE==0
471 0 : z = 0.0;
472 :
473 0 : if( (sin(R)/cos(E))>0 )
474 0 : y = F_PI/2;
475 : else
476 0 : y = -F_PI/2;
477 :
478 0 : if( (cos(E))>0 )
479 0 : x = 0;
480 : else
481 0 : x = F_PI;
482 : }
483 0 : else if ( nElevationDeg == 0 || nElevationDeg == 180 )
484 : {
485 : //sR!=0 cR!=0 sE==0
486 0 : z = 0.0;
487 0 : x = E;
488 0 : y = R;
489 : //use element 13 for sign
490 0 : if((cos(x)*sin(y)*sin(R))<0.0)
491 0 : y *= -1.0;
492 : }
493 0 : else if ( nElevationDeg == 90 || nElevationDeg == 270 )
494 : {
495 : //sR!=0 cR!=0 cE==0
496 : //element 12 + 22 --> y=0 or F_PI and x=+-F_PI/2
497 : //-->element 13/23:
498 0 : z = atan(sin(R)/(cos(R)*sin(E)));
499 : //use element 13 for sign for x
500 0 : if( (sin(R)*sin(z))>0.0 )
501 0 : x = F_PI/2;
502 : else
503 0 : x = -F_PI/2;
504 : //use element 21 for y
505 0 : if( (sin(R)*sin(E)*sin(z))>0.0)
506 0 : y = 0.0;
507 : else
508 0 : y = F_PI;
509 : }
510 0 : else if ( nRotationDeg == 0 || nRotationDeg == 180 )
511 : {
512 : //sE!=0 cE!=0 sR==0
513 0 : z = 0.0;
514 0 : x = E;
515 0 : y = R;
516 0 : double f23 = cos(R)*sin(E);
517 0 : if( (f23 * sin(x)) < 0.0 )
518 0 : x *= -1.0; //todo ??
519 : }
520 0 : else if (nRotationDeg == 90 || nRotationDeg == 270)
521 : {
522 : //sE!=0 cE!=0 cR==0
523 : //z = +- F_PI/2;
524 : //x = +- F_PI/2;
525 0 : z = F_PI/2;
526 0 : x = F_PI/2;
527 0 : double sR = sin(R);
528 0 : if( sR<0.0 )
529 0 : x *= -1.0; //different signs for x and z
530 :
531 : //use element 21:
532 0 : double cy = sR*sin(E)/sin(z);
533 0 : lcl_ensureIntervalMinus1To1(cy);
534 0 : y = acos(cy);
535 :
536 : //use element 22 for sign:
537 0 : if( (sin(x)*sin(y)*sin(z)*cos(E))<0.0)
538 0 : y *= -1.0;
539 : }
540 : else
541 : {
542 0 : z = atan(tan(R) * sin(E));
543 0 : if(cos(z)==0.0)
544 : {
545 : OSL_FAIL("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad");
546 : return;
547 : }
548 0 : double cy = cos(R)/cos(z);
549 0 : lcl_ensureIntervalMinus1To1(cy);
550 0 : y = acos(cy);
551 :
552 : //element 12 in 23
553 0 : double fDenominator = cos(z)*(1.0-pow(sin(y),2));
554 0 : if(fDenominator==0.0)
555 : {
556 : OSL_FAIL("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad");
557 : return;
558 : }
559 0 : double sx = cos(R)*sin(E)/fDenominator;
560 0 : lcl_ensureIntervalMinus1To1(sx);
561 0 : x = asin( sx );
562 :
563 : //use element 13 for sign:
564 0 : double f13a = cos(x)*cos(z)*sin(y);
565 0 : double f13b = sin(R)-sx*sin(z);
566 0 : if( (f13b*f13a)<0.0 )
567 : {
568 : //change x or y
569 : //use element 22 for further investigations:
570 : //try
571 0 : y *= -1;
572 0 : double f22a = cos(x)*cos(z);
573 0 : double f22b = cos(E)-(sx*sin(y)*sin(z));
574 0 : if( (f22a*f22b)<0.0 )
575 : {
576 0 : y *= -1;
577 0 : x=(F_PI-x);
578 : }
579 : }
580 : else
581 : {
582 : //change nothing or both
583 : //use element 22 for further investigations:
584 0 : double f22a = cos(x)*cos(z);
585 0 : double f22b = cos(E)-(sx*sin(y)*sin(z));
586 0 : if( (f22a*f22b)<0.0 )
587 : {
588 0 : y *= -1;
589 0 : x=(F_PI-x);
590 : }
591 : }
592 : }
593 : }
594 :
595 0 : void ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
596 : sal_Int32& rnElevationDeg, sal_Int32& rnRotationDeg,
597 : double fXRad, double fYRad, double fZRad)
598 : {
599 : // for a description of the algorithm see issue 72994
600 : //http://www.openoffice.org/issues/show_bug.cgi?id=72994
601 : //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt
602 :
603 0 : double R = 0.0; //Rotation in Rad
604 0 : double E = 0.0; //Elevation in Rad
605 :
606 0 : double& x = fXRad;
607 0 : double& y = fYRad;
608 0 : double& z = fZRad;
609 :
610 0 : double f11 = cos(y)*cos(z);
611 :
612 0 : if( lcl_isSinZero(y) )
613 : {
614 : //siny == 0
615 :
616 0 : if( lcl_isCosZero(x) )
617 : {
618 : //siny == 0 && cosx == 0
619 :
620 0 : if( lcl_isSinZero(z) )
621 : {
622 : //siny == 0 && cosx == 0 && sinz == 0
623 : //example: x=+-90 y=0oder180 z=0(oder180)
624 :
625 : //element 13+11
626 0 : if( f11 > 0 )
627 0 : R = 0.0;
628 : else
629 0 : R = F_PI;
630 :
631 : //element 23
632 0 : double f23 = cos(z)*sin(x) / cos(R);
633 0 : if( f23 > 0 )
634 0 : E = F_PI/2.0;
635 : else
636 0 : E = -F_PI/2.0;
637 : }
638 0 : else if( lcl_isCosZero(z) )
639 : {
640 : //siny == 0 && cosx == 0 && cosz == 0
641 : //example: x=+-90 y=0oder180 z=+-90
642 :
643 0 : double f13 = sin(x)*sin(z);
644 : //element 13+11
645 0 : if( f13 > 0 )
646 0 : R = F_PI/2.0;
647 : else
648 0 : R = -F_PI/2.0;
649 :
650 : //element 21
651 0 : double f21 = cos(y)*sin(z) / sin(R);
652 0 : if( f21 > 0 )
653 0 : E = F_PI/2.0;
654 : else
655 0 : E = -F_PI/2.0;
656 : }
657 : else
658 : {
659 : //siny == 0 && cosx == 0 && cosz != 0 && sinz != 0
660 : //element 11 && 13
661 0 : double f13 = sin(x)*sin(z);
662 0 : R = atan( f13/f11 );
663 :
664 0 : if(f11<0)
665 0 : R+=F_PI;
666 :
667 : //element 23
668 0 : double f23 = cos(z)*sin(x);
669 0 : if( f23/cos(R) > 0 )
670 0 : E = F_PI/2.0;
671 : else
672 0 : E = -F_PI/2.0;
673 : }
674 : }
675 0 : else if( lcl_isSinZero(x) )
676 : {
677 : //sinY==0 sinX==0
678 : //element 13+11
679 0 : if( f11 > 0 )
680 0 : R = 0.0;
681 : else
682 0 : R = F_PI;
683 :
684 0 : double f22 = cos(x)*cos(z);
685 0 : if( f22 > 0 )
686 0 : E = 0.0;
687 : else
688 0 : E = F_PI;
689 : }
690 0 : else if( lcl_isSinZero(z) )
691 : {
692 : //sinY==0 sinZ==0 sinx!=0 cosx!=0
693 : //element 13+11
694 0 : if( f11 > 0 )
695 0 : R = 0.0;
696 : else
697 0 : R = F_PI;
698 :
699 : //element 22 && 23
700 0 : double f22 = cos(x)*cos(z);
701 0 : double f23 = cos(z)*sin(x);
702 0 : E = atan( f23/(f22*cos(R)) );
703 0 : if( (f22*cos(E))<0 )
704 0 : E+=F_PI;
705 : }
706 0 : else if( lcl_isCosZero(z) )
707 : {
708 : //sinY == 0 && cosZ == 0 && cosx != 0 && sinx != 0
709 0 : double f13 = sin(x)*sin(z);
710 : //element 13+11
711 0 : if( f13 > 0 )
712 0 : R = F_PI/2.0;
713 : else
714 0 : R = -F_PI/2.0;
715 :
716 : //element 21+22
717 0 : double f21 = cos(y)*sin(z);
718 0 : if( f21/sin(R) > 0 )
719 0 : E = F_PI/2.0;
720 : else
721 0 : E = -F_PI/2.0;
722 : }
723 : else
724 : {
725 : //sinY == 0 && all other !=0
726 0 : double f13 = sin(x)*sin(z);
727 0 : R = atan( f13/f11 );
728 0 : if( (f11*cos(R))<0.0 )
729 0 : R+=F_PI;
730 :
731 0 : double f22 = cos(x)*cos(z);
732 0 : if( !lcl_isCosZero(R) )
733 0 : E = atan( cos(z)*sin(x) /( f22*cos(R) ) );
734 : else
735 0 : E = atan( cos(y)*sin(z) /( f22*sin(R) ) );
736 0 : if( (f22*cos(E))<0 )
737 0 : E+=F_PI;
738 : }
739 : }
740 0 : else if( lcl_isCosZero(y) )
741 : {
742 : //cosY==0
743 :
744 0 : double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y);
745 0 : if( f13 >= 0 )
746 0 : R = F_PI/2.0;
747 : else
748 0 : R = -F_PI/2.0;
749 :
750 0 : double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z);
751 0 : if( f22 >= 0 )
752 0 : E = 0.0;
753 : else
754 0 : E = F_PI;
755 : }
756 0 : else if( lcl_isSinZero(x) )
757 : {
758 : //cosY!=0 sinY!=0 sinX=0
759 0 : if( lcl_isSinZero(z) )
760 : {
761 : //cosY!=0 sinY!=0 sinX=0 sinZ=0
762 0 : double f13 = cos(x)*cos(z)*sin(y);
763 0 : R = atan( f13/f11 );
764 : //R = asin(f13);
765 0 : if( f11<0 )
766 0 : R+=F_PI;
767 :
768 0 : double f22 = cos(x)*cos(z);
769 0 : if( f22>0 )
770 0 : E = 0.0;
771 : else
772 0 : E = F_PI;
773 : }
774 0 : else if( lcl_isCosZero(z) )
775 : {
776 : //cosY!=0 sinY!=0 sinX=0 cosZ=0
777 0 : R = x;
778 0 : E = y;//or -y
779 : //use 23 for 'signs'
780 0 : double f23 = -1.0*cos(x)*sin(y)*sin(z);
781 0 : if( (f23*cos(R)*sin(E))<0.0 )
782 : {
783 : //change R or E
784 0 : E = -y;
785 : }
786 : }
787 : else
788 : {
789 : //cosY!=0 sinY!=0 sinX=0 sinZ!=0 cosZ!=0
790 0 : double f13 = cos(x)*cos(z)*sin(y);
791 0 : R = atan( f13/f11 );
792 :
793 0 : if( f11<0 )
794 0 : R+=F_PI;
795 :
796 0 : double f21 = cos(y)*sin(z);
797 0 : double f22 = cos(x)*cos(z);
798 0 : E = atan(f21/(f22*sin(R)) );
799 :
800 0 : if( (f22*cos(E))<0.0 )
801 0 : E+=F_PI;
802 : }
803 : }
804 0 : else if( lcl_isCosZero(x) )
805 : {
806 : //cosY!=0 sinY!=0 cosX=0
807 :
808 0 : if( lcl_isSinZero(z) )
809 : {
810 : //cosY!=0 sinY!=0 cosX=0 sinZ=0
811 0 : R=0;//13 -> R=0 or F_PI
812 0 : if( f11<0.0 )
813 0 : R=F_PI;
814 0 : E=F_PI/2;//22 -> E=+-F_PI/2
815 : //use element 11 and 23 for sign
816 0 : double f23 = cos(z)*sin(x);
817 0 : if( (f11*f23*sin(E))<0.0 )
818 0 : E=-F_PI/2.0;
819 : }
820 0 : else if( lcl_isCosZero(z) )
821 : {
822 : //cosY!=0 sinY!=0 cosX=0 cosZ=0
823 : //element 11 & 13:
824 0 : if( (sin(x)*sin(z))>0.0 )
825 0 : R=F_PI/2.0;
826 : else
827 0 : R=-F_PI/2.0;
828 : //element 22:
829 0 : E=acos( sin(x)*sin(y)*sin(z));
830 : //use element 21 for sign:
831 0 : if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 )
832 0 : E*=-1.0;
833 : }
834 : else
835 : {
836 : //cosY!=0 sinY!=0 cosX=0 sinZ!=0 cosZ!=0
837 : //element 13/11
838 0 : R = atan( sin(x)*sin(z)/(cos(y)*cos(z)) );
839 : //use 13 for 'sign'
840 0 : if( (sin(x)*sin(z))<0.0 )
841 0 : R += F_PI;
842 : //element 22
843 0 : E = acos(sin(x)*sin(y)*sin(z) );
844 : //use 21 for sign
845 0 : if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 )
846 0 : E*=-1.0;
847 : }
848 : }
849 0 : else if( lcl_isSinZero(z) )
850 : {
851 : //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ=0
852 : //element 11
853 0 : R=y;
854 : //use elenment 13 for sign
855 0 : if( (cos(x)*cos(z)*sin(y)*sin(R))<0.0 )
856 0 : R*=-1.0;
857 : //element 22
858 0 : E = acos( cos(x)*cos(z) );
859 : //use element 23 for sign
860 0 : if( (cos(z)*sin(x)*cos(R)*sin(E))<0.0 )
861 0 : E*=-1.0;
862 : }
863 0 : else if( lcl_isCosZero(z) )
864 : {
865 : //cosY!=0 sinY!=0 sinX!=0 cosX!=0 cosZ=0
866 : //element 21/23
867 0 : R=atan(-cos(y)/(cos(x)*sin(y)));
868 : //use element 13 for 'sign'
869 0 : if( (sin(x)*sin(z)*sin(R))<0.0 )
870 0 : R+=F_PI;
871 : //element 21/22
872 0 : E=atan( cos(y)*sin(z)/(sin(R)*sin(x)*sin(y)*sin(z)) );
873 : //use element 23 for 'sign'
874 0 : if( (-cos(x)*sin(y)*sin(z)*cos(R)*sin(E))<0.0 )
875 0 : E+=F_PI;
876 : }
877 : else
878 : {
879 : //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ!=0 cosZ!=0
880 : //13/11:
881 0 : double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y);
882 0 : R = atan( f13/ f11 );
883 0 : if(f11<0.0)
884 0 : R+=F_PI;
885 0 : double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z);
886 0 : double f23 = cos(x)*sin(y)*sin(z)-cos(z)*sin(x);
887 : //23/22:
888 0 : E = atan( -1.0*f23/(f22*cos(R)) );
889 0 : if(f22<0.0)
890 0 : E+=F_PI;
891 : }
892 :
893 0 : rnElevationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( E ) );
894 0 : rnRotationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( R ) );
895 0 : }
896 :
897 0 : double ThreeDHelper::getValueClippedToRange( double fAngle, const double& fPositivLimit )
898 : {
899 0 : if( fAngle<-1*fPositivLimit )
900 0 : fAngle=-1*fPositivLimit;
901 0 : else if( fAngle>fPositivLimit )
902 0 : fAngle=fPositivLimit;
903 0 : return fAngle;
904 : }
905 :
906 0 : double ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()
907 : {
908 0 : return 90.0;
909 : }
910 :
911 0 : double ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()
912 : {
913 0 : return 45.0;
914 : }
915 :
916 0 : void ThreeDHelper::adaptRadAnglesForRightAngledAxes( double& rfXAngleRad, double& rfYAngleRad )
917 : {
918 0 : rfXAngleRad = ThreeDHelper::getValueClippedToRange(rfXAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()) );
919 0 : rfYAngleRad = ThreeDHelper::getValueClippedToRange(rfYAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()) );
920 0 : }
921 :
922 0 : void ThreeDHelper::getRotationAngleFromDiagram(
923 : const Reference< beans::XPropertySet >& xSceneProperties, double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad )
924 : {
925 : //takes the camera and the transformation matrix into account
926 :
927 0 : rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0;
928 :
929 0 : if( !xSceneProperties.is() )
930 0 : return;
931 :
932 : //get camera rotation
933 0 : ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( xSceneProperties ) );
934 0 : BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix );
935 :
936 : //get scene rotation
937 0 : ::basegfx::B3DHomMatrix aSceneRotation;
938 : {
939 0 : drawing::HomogenMatrix aHomMatrix;
940 0 : if( xSceneProperties->getPropertyValue( C2U("D3DTransformMatrix")) >>= aHomMatrix )
941 : {
942 0 : aSceneRotation = BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix );
943 0 : BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
944 : }
945 : }
946 :
947 0 : ::basegfx::B3DHomMatrix aResultRotation = aFixCameraRotationMatrix * aSceneRotation;
948 0 : ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation ) );
949 :
950 0 : rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getX());
951 0 : rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getY());
952 0 : rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getZ());
953 :
954 0 : if(rfZAngleRad<(-F_PI/2) || rfZAngleRad>(F_PI/2))
955 : {
956 0 : rfZAngleRad-=F_PI;
957 0 : rfXAngleRad-=F_PI;
958 0 : rfYAngleRad=(F_PI-rfYAngleRad);
959 :
960 0 : rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad);
961 0 : rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad);
962 0 : rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad);
963 0 : }
964 : }
965 :
966 0 : void ThreeDHelper::switchRightAngledAxes( const Reference< beans::XPropertySet >& xSceneProperties, sal_Bool bRightAngledAxes, bool bRotateLights )
967 : {
968 : try
969 : {
970 0 : if( xSceneProperties.is() )
971 : {
972 0 : sal_Bool bOldRightAngledAxes = sal_False;
973 0 : xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bOldRightAngledAxes;
974 0 : if( bOldRightAngledAxes!=bRightAngledAxes)
975 : {
976 0 : xSceneProperties->setPropertyValue( C2U("RightAngledAxes"), uno::makeAny( bRightAngledAxes ));
977 0 : if( bRotateLights )
978 : {
979 0 : if(bRightAngledAxes)
980 : {
981 0 : ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( xSceneProperties ) );
982 0 : lcl_rotateLights( aInverseRotation, xSceneProperties );
983 : }
984 : else
985 : {
986 0 : ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( xSceneProperties ) );
987 0 : lcl_rotateLights( aCompleteRotation, xSceneProperties );
988 : }
989 : }
990 : }
991 : }
992 : }
993 0 : catch( const uno::Exception & ex )
994 : {
995 : ASSERT_EXCEPTION( ex );
996 : }
997 0 : }
998 :
999 0 : void ThreeDHelper::setRotationAngleToDiagram(
1000 : const Reference< beans::XPropertySet >& xSceneProperties
1001 : , double fXAngleRad, double fYAngleRad, double fZAngleRad )
1002 : {
1003 : //the rotation of the camera is not touched but taken into account
1004 : //the rotation difference is applied to the transformation matrix
1005 :
1006 : //the light sources will be adapted also
1007 :
1008 0 : if( !xSceneProperties.is() )
1009 0 : return;
1010 :
1011 : try
1012 : {
1013 : //remind old rotation for adaption of light directions
1014 0 : ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( xSceneProperties ) );
1015 :
1016 0 : ::basegfx::B3DHomMatrix aInverseCameraRotation;
1017 : {
1018 : ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix(
1019 0 : lcl_getCameraMatrix( xSceneProperties ) ) );
1020 0 : aInverseCameraRotation.rotate( 0.0, 0.0, -aR.getZ() );
1021 0 : aInverseCameraRotation.rotate( 0.0, -aR.getY(), 0.0 );
1022 0 : aInverseCameraRotation.rotate( -aR.getX(), 0.0, 0.0 );
1023 : }
1024 :
1025 0 : ::basegfx::B3DHomMatrix aCumulatedRotation;
1026 0 : aCumulatedRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
1027 :
1028 : //calculate new scene matrix
1029 0 : ::basegfx::B3DHomMatrix aSceneRotation = aInverseCameraRotation*aCumulatedRotation;
1030 0 : BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation );
1031 :
1032 : //set new rotation to transformation matrix
1033 0 : xSceneProperties->setPropertyValue(
1034 0 : C2U("D3DTransformMatrix"), uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
1035 :
1036 : //rotate lights if RightAngledAxes are not set or not supported
1037 0 : sal_Bool bRightAngledAxes = sal_False;
1038 0 : xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes;
1039 0 : uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY );
1040 0 : if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes(
1041 0 : DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) )
1042 : {
1043 0 : ::basegfx::B3DHomMatrix aNewRotation;
1044 0 : aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad );
1045 0 : lcl_rotateLights( aNewRotation*aInverseOldRotation, xSceneProperties );
1046 0 : }
1047 : }
1048 0 : catch( const uno::Exception & ex )
1049 : {
1050 : ASSERT_EXCEPTION( ex );
1051 : }
1052 : }
1053 :
1054 0 : void ThreeDHelper::getRotationFromDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties
1055 : , sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree )
1056 : {
1057 : double fXAngle, fYAngle, fZAngle;
1058 0 : ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle );
1059 :
1060 0 : if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1061 : {
1062 : ThreeDHelper::convertXYZAngleRadToElevationRotationDeg(
1063 0 : rnHorizontalAngleDegree, rnVerticalAngleDegree, fXAngle, fYAngle, fZAngle);
1064 0 : rnVerticalAngleDegree*=-1;
1065 : }
1066 : else
1067 : {
1068 0 : fXAngle = BaseGFXHelper::Rad2Deg( fXAngle );
1069 0 : fYAngle = BaseGFXHelper::Rad2Deg( fYAngle );
1070 0 : fZAngle = BaseGFXHelper::Rad2Deg( fZAngle );
1071 :
1072 0 : rnHorizontalAngleDegree = ::basegfx::fround(fXAngle);
1073 0 : rnVerticalAngleDegree = ::basegfx::fround(-1.0*fYAngle);
1074 : //nZRotation = ::basegfx::fround(-1.0*fZAngle);
1075 : }
1076 :
1077 0 : lcl_shiftAngleToIntervalMinus180To180( rnHorizontalAngleDegree );
1078 0 : lcl_shiftAngleToIntervalMinus180To180( rnVerticalAngleDegree );
1079 0 : }
1080 :
1081 0 : void ThreeDHelper::setRotationToDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties
1082 : , sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree )
1083 : {
1084 : //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false
1085 0 : double fXAngle = BaseGFXHelper::Deg2Rad( nHorizontalAngleDegree );
1086 0 : double fYAngle = BaseGFXHelper::Deg2Rad( -1*nVerticalYAngleDegree );
1087 0 : double fZAngle = 0.0;
1088 :
1089 0 : if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1090 : ThreeDHelper::convertElevationRotationDegToXYZAngleRad(
1091 0 : nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle );
1092 :
1093 0 : ThreeDHelper::setRotationAngleToDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle );
1094 0 : }
1095 :
1096 0 : void ThreeDHelper::getCameraDistanceRange( double& rfMinimumDistance, double& rfMaximumDistance )
1097 : {
1098 0 : rfMinimumDistance = 3.0/4.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value
1099 0 : rfMaximumDistance = 20.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value
1100 0 : }
1101 :
1102 0 : void ThreeDHelper::ensureCameraDistanceRange( double& rfCameraDistance )
1103 : {
1104 : double fMin, fMax;
1105 0 : getCameraDistanceRange( fMin, fMax );
1106 0 : if( rfCameraDistance < fMin )
1107 0 : rfCameraDistance = fMin;
1108 0 : if( rfCameraDistance > fMax )
1109 0 : rfCameraDistance = fMax;
1110 0 : }
1111 :
1112 0 : double ThreeDHelper::getCameraDistance(
1113 : const Reference< beans::XPropertySet >& xSceneProperties )
1114 : {
1115 0 : double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
1116 :
1117 0 : if( !xSceneProperties.is() )
1118 0 : return fCameraDistance;
1119 :
1120 : try
1121 : {
1122 0 : drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
1123 0 : xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG;
1124 0 : ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
1125 0 : fCameraDistance = aVRP.getLength();
1126 :
1127 0 : ensureCameraDistanceRange( fCameraDistance );
1128 : }
1129 0 : catch( const uno::Exception & ex )
1130 : {
1131 : ASSERT_EXCEPTION( ex );
1132 : }
1133 0 : return fCameraDistance;
1134 : }
1135 :
1136 0 : void ThreeDHelper::setCameraDistance(
1137 : const Reference< beans::XPropertySet >& xSceneProperties, double fCameraDistance )
1138 : {
1139 0 : if( !xSceneProperties.is() )
1140 0 : return;
1141 :
1142 : try
1143 : {
1144 0 : if( fCameraDistance <= 0 )
1145 0 : fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME;
1146 :
1147 0 : drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() );
1148 0 : xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG;
1149 0 : ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) );
1150 0 : if( ::basegfx::fTools::equalZero( aVRP.getLength() ) )
1151 0 : aVRP = ::basegfx::B3DVector(0,0,1);
1152 0 : aVRP.setLength(fCameraDistance);
1153 0 : aCG.vrp = BaseGFXHelper::B3DVectorToPosition3D( aVRP );
1154 :
1155 0 : xSceneProperties->setPropertyValue( C2U("D3DCameraGeometry"), uno::makeAny( aCG ));
1156 : }
1157 0 : catch( const uno::Exception & ex )
1158 : {
1159 : ASSERT_EXCEPTION( ex );
1160 : }
1161 : }
1162 :
1163 0 : double ThreeDHelper::CameraDistanceToPerspective( double fCameraDistance )
1164 : {
1165 0 : double fRet = fCameraDistance;
1166 : double fMin, fMax;
1167 0 : ThreeDHelper::getCameraDistanceRange( fMin, fMax );
1168 : //fMax <-> 0; fMin <->100
1169 : //a/x + b = y
1170 0 : double a = 100.0*fMax*fMin/(fMax-fMin);
1171 0 : double b = -a/fMax;
1172 :
1173 0 : fRet = a/fCameraDistance + b;
1174 :
1175 0 : return fRet;
1176 : }
1177 :
1178 0 : double ThreeDHelper::PerspectiveToCameraDistance( double fPerspective )
1179 : {
1180 0 : double fRet = fPerspective;
1181 : double fMin, fMax;
1182 0 : ThreeDHelper::getCameraDistanceRange( fMin, fMax );
1183 : //fMax <-> 0; fMin <->100
1184 : //a/x + b = y
1185 0 : double a = 100.0*fMax*fMin/(fMax-fMin);
1186 0 : double b = -a/fMax;
1187 :
1188 0 : fRet = a/(fPerspective - b);
1189 :
1190 0 : return fRet;
1191 : }
1192 :
1193 0 : ThreeDLookScheme ThreeDHelper::detectScheme( const uno::Reference< XDiagram >& xDiagram )
1194 : {
1195 0 : ThreeDLookScheme aScheme = ThreeDLookScheme_Unknown;
1196 :
1197 : sal_Int32 nRoundedEdges;
1198 : sal_Int32 nObjectLines;
1199 0 : ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines );
1200 :
1201 : //get shade mode and light settings:
1202 0 : drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
1203 0 : uno::Reference< beans::XPropertySet > xDiagramProps( xDiagram, uno::UNO_QUERY );
1204 : try
1205 : {
1206 0 : if( xDiagramProps.is() )
1207 0 : xDiagramProps->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>= aShadeMode;
1208 : }
1209 0 : catch( const uno::Exception & ex )
1210 : {
1211 : ASSERT_EXCEPTION( ex );
1212 : }
1213 :
1214 0 : if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, xDiagram ) )
1215 : {
1216 0 : if( lcl_isSimpleLightScheme(xDiagramProps) )
1217 0 : aScheme = ThreeDLookScheme_Simple;
1218 : }
1219 0 : else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) )
1220 : {
1221 0 : if( lcl_isRealisticLightScheme(xDiagramProps) )
1222 0 : aScheme = ThreeDLookScheme_Realistic;
1223 : }
1224 :
1225 0 : return aScheme;
1226 : }
1227 :
1228 41 : void ThreeDHelper::setScheme( const uno::Reference< XDiagram >& xDiagram, ThreeDLookScheme aScheme )
1229 : {
1230 41 : if( aScheme == ThreeDLookScheme_Unknown )
1231 41 : return;
1232 :
1233 : drawing::ShadeMode aShadeMode;
1234 : sal_Int32 nRoundedEdges;
1235 : sal_Int32 nObjectLines;
1236 :
1237 41 : if( aScheme == ThreeDLookScheme_Simple )
1238 0 : lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,xDiagram);
1239 : else
1240 41 : lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines);
1241 :
1242 : try
1243 : {
1244 41 : ThreeDHelper::setRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines );
1245 :
1246 41 : uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY );
1247 41 : if( xProp.is() )
1248 : {
1249 : drawing::ShadeMode aOldShadeMode;
1250 123 : if( ! ( (xProp->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>=aOldShadeMode) &&
1251 123 : aOldShadeMode == aShadeMode ))
1252 : {
1253 0 : xProp->setPropertyValue( C2U( "D3DSceneShadeMode" ), uno::makeAny( aShadeMode ));
1254 : }
1255 : }
1256 :
1257 41 : lcl_setLightsForScheme( xProp, aScheme );
1258 : }
1259 0 : catch( const uno::Exception & ex )
1260 : {
1261 : ASSERT_EXCEPTION( ex );
1262 : }
1263 :
1264 : }
1265 :
1266 0 : void ThreeDHelper::set3DSettingsToDefault( const uno::Reference< beans::XPropertySet >& xSceneProperties )
1267 : {
1268 0 : Reference< beans::XPropertyState > xState( xSceneProperties, uno::UNO_QUERY );
1269 0 : if(xState.is())
1270 : {
1271 0 : xState->setPropertyToDefault( C2U("D3DSceneDistance"));
1272 0 : xState->setPropertyToDefault( C2U("D3DSceneFocalLength"));
1273 : }
1274 0 : ThreeDHelper::setDefaultRotation( xSceneProperties );
1275 0 : ThreeDHelper::setDefaultIllumination( xSceneProperties );
1276 0 : }
1277 :
1278 0 : void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties, bool bPieOrDonut )
1279 : {
1280 0 : if( !xSceneProperties.is() )
1281 0 : return;
1282 :
1283 0 : drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) );
1284 0 : xSceneProperties->setPropertyValue( C2U("D3DCameraGeometry"), uno::makeAny( aCameraGeo ));
1285 :
1286 0 : ::basegfx::B3DHomMatrix aSceneRotation;
1287 0 : if( bPieOrDonut )
1288 0 : aSceneRotation.rotate( -F_PI/3.0, 0, 0 );
1289 0 : xSceneProperties->setPropertyValue( C2U("D3DTransformMatrix"),
1290 0 : uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation )));
1291 : }
1292 :
1293 0 : void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties )
1294 : {
1295 0 : bool bPieOrDonut( DiagramHelper::isPieOrDonutChart( uno::Reference< XDiagram >(xSceneProperties, uno::UNO_QUERY) ) );
1296 0 : ThreeDHelper::setDefaultRotation( xSceneProperties, bPieOrDonut );
1297 0 : }
1298 :
1299 0 : void ThreeDHelper::setDefaultIllumination( const uno::Reference< beans::XPropertySet >& xSceneProperties )
1300 : {
1301 0 : if( !xSceneProperties.is() )
1302 0 : return;
1303 :
1304 0 : drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH );
1305 : try
1306 : {
1307 0 : xSceneProperties->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>= aShadeMode;
1308 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ), uno::makeAny( sal_False ) );
1309 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ), uno::makeAny( sal_False ) );
1310 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ), uno::makeAny( sal_False ) );
1311 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ), uno::makeAny( sal_False ) );
1312 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ), uno::makeAny( sal_False ) );
1313 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ), uno::makeAny( sal_False ) );
1314 0 : xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ), uno::makeAny( sal_False ) );
1315 : }
1316 0 : catch( const uno::Exception & ex )
1317 : {
1318 : ASSERT_EXCEPTION( ex );
1319 : }
1320 :
1321 0 : ThreeDLookScheme aScheme = (drawing::ShadeMode_FLAT==aShadeMode) ? ThreeDLookScheme_Simple : ThreeDLookScheme_Realistic;
1322 0 : lcl_setLightsForScheme( xSceneProperties, aScheme );
1323 : }
1324 :
1325 0 : void ThreeDHelper::getRoundedEdgesAndObjectLines(
1326 : const uno::Reference< XDiagram > & xDiagram
1327 : , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines )
1328 : {
1329 0 : rnRoundedEdges = -1;
1330 0 : rnObjectLines = -1;
1331 : try
1332 : {
1333 0 : bool bDifferentRoundedEdges = false;
1334 0 : bool bDifferentObjectLines = false;
1335 :
1336 0 : drawing::LineStyle aLineStyle( drawing::LineStyle_SOLID );
1337 :
1338 : ::std::vector< uno::Reference< XDataSeries > > aSeriesList(
1339 0 : DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1340 0 : sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() );
1341 :
1342 0 : rtl::OUString aPercentDiagonalPropertyName( C2U( "PercentDiagonal" ) );
1343 0 : rtl::OUString aBorderStylePropertyName( C2U( "BorderStyle" ) );
1344 :
1345 0 : for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS )
1346 : {
1347 0 : uno::Reference< XDataSeries > xSeries( aSeriesList[nS] );
1348 0 : uno::Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY );
1349 0 : if(!nS)
1350 : {
1351 0 : rnRoundedEdges = 0;
1352 : try
1353 : {
1354 0 : sal_Int16 nPercentDiagonal = 0;
1355 :
1356 0 : xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal;
1357 0 : rnRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal );
1358 :
1359 0 : if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1360 0 : , aPercentDiagonalPropertyName, uno::makeAny(nPercentDiagonal) ) )
1361 0 : bDifferentRoundedEdges = true;
1362 : }
1363 0 : catch( const uno::Exception& e )
1364 : {
1365 : ASSERT_EXCEPTION( e );
1366 0 : bDifferentRoundedEdges = true;
1367 : }
1368 : try
1369 : {
1370 0 : xProp->getPropertyValue( aBorderStylePropertyName ) >>= aLineStyle;
1371 :
1372 0 : if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1373 0 : , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) )
1374 0 : bDifferentObjectLines = true;
1375 : }
1376 0 : catch( const uno::Exception& e )
1377 : {
1378 : ASSERT_EXCEPTION( e );
1379 0 : bDifferentObjectLines = true;
1380 : }
1381 : }
1382 : else
1383 : {
1384 0 : if( !bDifferentRoundedEdges )
1385 : {
1386 0 : sal_Int16 nPercentDiagonal = 0;
1387 0 : xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal;
1388 0 : sal_Int32 nCurrentRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal );
1389 0 : if(nCurrentRoundedEdges!=rnRoundedEdges
1390 : || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1391 0 : , aPercentDiagonalPropertyName, uno::makeAny( static_cast< sal_Int16 >(rnRoundedEdges) ) ) )
1392 : {
1393 0 : bDifferentRoundedEdges = true;
1394 0 : nCurrentRoundedEdges = -1;
1395 : }
1396 : }
1397 :
1398 0 : if( !bDifferentObjectLines )
1399 : {
1400 : drawing::LineStyle aCurrentLineStyle;
1401 0 : xProp->getPropertyValue( aBorderStylePropertyName ) >>= aCurrentLineStyle;
1402 0 : if(aCurrentLineStyle!=aLineStyle
1403 : || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries
1404 0 : , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) )
1405 0 : bDifferentObjectLines = true;
1406 : }
1407 : }
1408 0 : if( bDifferentRoundedEdges && bDifferentObjectLines )
1409 : break;
1410 0 : }
1411 :
1412 : //set rnObjectLines
1413 0 : rnObjectLines = 0;
1414 0 : if( bDifferentObjectLines )
1415 0 : rnObjectLines = -1;
1416 0 : else if( aLineStyle == drawing::LineStyle_SOLID )
1417 0 : rnObjectLines = 1;
1418 : }
1419 0 : catch( const uno::Exception& e )
1420 : {
1421 : ASSERT_EXCEPTION( e );
1422 : }
1423 0 : }
1424 :
1425 41 : void ThreeDHelper::setRoundedEdgesAndObjectLines(
1426 : const uno::Reference< XDiagram > & xDiagram
1427 : , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines )
1428 : {
1429 41 : if( (nRoundedEdges<0||nRoundedEdges>100) && nObjectLines!=0 && nObjectLines!=1 )
1430 41 : return;
1431 :
1432 41 : drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
1433 41 : if(nObjectLines==1)
1434 0 : aLineStyle = drawing::LineStyle_SOLID;
1435 :
1436 41 : uno::Any aALineStyle( uno::makeAny(aLineStyle));
1437 41 : uno::Any aARoundedEdges( uno::makeAny( static_cast< sal_Int16 >( nRoundedEdges )));
1438 :
1439 : ::std::vector< uno::Reference< XDataSeries > > aSeriesList(
1440 41 : DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1441 41 : sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() );
1442 164 : for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS )
1443 : {
1444 123 : uno::Reference< XDataSeries > xSeries( aSeriesList[nS] );
1445 :
1446 123 : if( nRoundedEdges>=0 && nRoundedEdges<=100 )
1447 123 : DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "PercentDiagonal" ), aARoundedEdges );
1448 :
1449 123 : if( nObjectLines==0 || nObjectLines==1 )
1450 123 : DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "BorderStyle" ), aALineStyle );
1451 164 : }
1452 : }
1453 :
1454 0 : CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( const Reference< beans::XPropertySet >& xSceneProperties )
1455 : {
1456 0 : CuboidPlanePosition eRet(CuboidPlanePosition_Left);
1457 :
1458 0 : double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
1459 0 : ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
1460 0 : if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1461 : {
1462 0 : ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
1463 0 : fZAngleRad=0.0;
1464 : }
1465 0 : if( sin(fYAngleRad)>0.0 )
1466 0 : eRet = CuboidPlanePosition_Right;
1467 0 : return eRet;
1468 : }
1469 :
1470 0 : CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( const Reference< beans::XPropertySet >& xSceneProperties )
1471 : {
1472 0 : CuboidPlanePosition eRet(CuboidPlanePosition_Back);
1473 :
1474 0 : double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
1475 0 : ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
1476 0 : if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1477 : {
1478 0 : ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
1479 0 : fZAngleRad=0.0;
1480 : }
1481 0 : if( cos(fXAngleRad)*cos(fYAngleRad)<0.0 )
1482 0 : eRet = CuboidPlanePosition_Front;
1483 0 : return eRet;
1484 : }
1485 :
1486 0 : CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( const Reference< beans::XPropertySet >& xSceneProperties )
1487 : {
1488 0 : CuboidPlanePosition eRet(CuboidPlanePosition_Bottom);
1489 :
1490 0 : double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0;
1491 0 : ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad );
1492 0 : if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) )
1493 : {
1494 0 : ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad );
1495 0 : fZAngleRad=0.0;
1496 : }
1497 0 : if( sin(fXAngleRad)*cos(fYAngleRad)<0.0 )
1498 0 : eRet = CuboidPlanePosition_Top;
1499 0 : return eRet;
1500 : }
1501 :
1502 : //.............................................................................
1503 : } //namespace chart
1504 : //.............................................................................
1505 :
1506 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|