|  | /************************************************************** | 
|  | * | 
|  | * Licensed to the Apache Software Foundation (ASF) under one | 
|  | * or more contributor license agreements.  See the NOTICE file | 
|  | * distributed with this work for additional information | 
|  | * regarding copyright ownership.  The ASF licenses this file | 
|  | * to you under the Apache License, Version 2.0 (the | 
|  | * "License"); you may not use this file except in compliance | 
|  | * with the License.  You may obtain a copy of the License at | 
|  | * | 
|  | *   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, | 
|  | * software distributed under the License is distributed on an | 
|  | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | * KIND, either express or implied.  See the License for the | 
|  | * specific language governing permissions and limitations | 
|  | * under the License. | 
|  | * | 
|  | *************************************************************/ | 
|  |  | 
|  |  | 
|  |  | 
|  | // MARKER(update_precomp.py): autogen include statement, do not remove | 
|  | #include "precompiled_chart2.hxx" | 
|  |  | 
|  | #include "ThreeDHelper.hxx" | 
|  | #include "macros.hxx" | 
|  | #include "DiagramHelper.hxx" | 
|  | #include "ChartTypeHelper.hxx" | 
|  | #include "BaseGFXHelper.hxx" | 
|  | #include "DataSeriesHelper.hxx" | 
|  | #include <editeng/unoprnms.hxx> | 
|  | #include <com/sun/star/beans/XPropertyState.hpp> | 
|  | #include <com/sun/star/chart2/XDiagram.hpp> | 
|  | #include <com/sun/star/drawing/LineStyle.hpp> | 
|  |  | 
|  | #include <tools/debug.hxx> | 
|  |  | 
|  | //............................................................................. | 
|  | namespace chart | 
|  | { | 
|  | //............................................................................. | 
|  | using namespace ::com::sun::star; | 
|  | using namespace ::com::sun::star::chart2; | 
|  |  | 
|  | using ::com::sun::star::uno::Reference; | 
|  | using ::com::sun::star::uno::Sequence; | 
|  | using ::rtl::OUString; | 
|  | using ::rtl::math::cos; | 
|  | using ::rtl::math::sin; | 
|  | using ::rtl::math::tan; | 
|  |  | 
|  | #define FIXED_SIZE_FOR_3D_CHART_VOLUME (10000.0) | 
|  |  | 
|  | namespace | 
|  | { | 
|  |  | 
|  | bool lcl_isRightAngledAxesSetAndSupported( const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | sal_Bool bRightAngledAxes = sal_False; | 
|  | if( xSceneProperties.is() ) | 
|  | { | 
|  | xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; | 
|  | if(bRightAngledAxes) | 
|  | { | 
|  | uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY ); | 
|  | if( ChartTypeHelper::isSupportingRightAngledAxes( | 
|  | DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) | 
|  | { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void lcl_RotateLightSource( const Reference< beans::XPropertySet >& xSceneProperties | 
|  | , const OUString& rLightSourceDirection | 
|  | , const OUString& rLightSourceOn | 
|  | , const ::basegfx::B3DHomMatrix& rRotationMatrix ) | 
|  | { | 
|  | if( xSceneProperties.is() ) | 
|  | { | 
|  | sal_Bool bLightOn = sal_False; | 
|  | if( xSceneProperties->getPropertyValue( rLightSourceOn ) >>= bLightOn ) | 
|  | { | 
|  | if( bLightOn ) | 
|  | { | 
|  | drawing::Direction3D aLight; | 
|  | if( xSceneProperties->getPropertyValue( rLightSourceDirection ) >>= aLight ) | 
|  | { | 
|  | ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aLight ) ); | 
|  | aLightVector = rRotationMatrix*aLightVector; | 
|  |  | 
|  | xSceneProperties->setPropertyValue( rLightSourceDirection | 
|  | , uno::makeAny( BaseGFXHelper::B3DVectorToDirection3D( aLightVector ) ) ); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void lcl_rotateLights( const ::basegfx::B3DHomMatrix& rLightRottion, const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | if(!xSceneProperties.is()) | 
|  | return; | 
|  |  | 
|  | ::basegfx::B3DHomMatrix aLightRottion( rLightRottion ); | 
|  | BaseGFXHelper::ReduceToRotationMatrix( aLightRottion ); | 
|  |  | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection1"), C2U("D3DSceneLightOn1"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection2"), C2U("D3DSceneLightOn2"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection3"), C2U("D3DSceneLightOn3"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection4"), C2U("D3DSceneLightOn4"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection5"), C2U("D3DSceneLightOn5"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection6"), C2U("D3DSceneLightOn6"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection7"), C2U("D3DSceneLightOn7"), aLightRottion ); | 
|  | lcl_RotateLightSource( xSceneProperties, C2U("D3DSceneLightDirection8"), C2U("D3DSceneLightOn8"), aLightRottion ); | 
|  | } | 
|  |  | 
|  | ::basegfx::B3DHomMatrix lcl_getInverseRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aInverseRotation; | 
|  | double fXAngleRad=0.0; | 
|  | double fYAngleRad=0.0; | 
|  | double fZAngleRad=0.0; | 
|  | ThreeDHelper::getRotationAngleFromDiagram( | 
|  | xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | aInverseRotation.rotate( 0.0, 0.0, -fZAngleRad ); | 
|  | aInverseRotation.rotate( 0.0, -fYAngleRad, 0.0 ); | 
|  | aInverseRotation.rotate( -fXAngleRad, 0.0, 0.0 ); | 
|  | return aInverseRotation; | 
|  | } | 
|  |  | 
|  | ::basegfx::B3DHomMatrix lcl_getCompleteRotationMatrix( const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aCompleteRotation; | 
|  | double fXAngleRad=0.0; | 
|  | double fYAngleRad=0.0; | 
|  | double fZAngleRad=0.0; | 
|  | ThreeDHelper::getRotationAngleFromDiagram( | 
|  | xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | aCompleteRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | return aCompleteRotation; | 
|  | } | 
|  |  | 
|  | bool lcl_isEqual( const drawing::Direction3D& rA, const drawing::Direction3D& rB ) | 
|  | { | 
|  | return ::rtl::math::approxEqual(rA.DirectionX, rB.DirectionX) | 
|  | && ::rtl::math::approxEqual(rA.DirectionY, rB.DirectionY) | 
|  | && ::rtl::math::approxEqual(rA.DirectionZ, rB.DirectionZ); | 
|  | } | 
|  |  | 
|  | bool lcl_isLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, bool bRealistic ) | 
|  | { | 
|  | if(!xDiagramProps.is()) | 
|  | return false; | 
|  |  | 
|  | sal_Bool bIsOn = sal_False; | 
|  | xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ) ) >>= bIsOn; | 
|  | if(!bIsOn) | 
|  | return false; | 
|  |  | 
|  | uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY ); | 
|  | uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); | 
|  |  | 
|  | sal_Int32 nColor = 0; | 
|  | xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ) ) >>= nColor; | 
|  | if( nColor != ::chart::ChartTypeHelper::getDefaultDirectLightColor( !bRealistic, xChartType ) ) | 
|  | return false; | 
|  |  | 
|  | sal_Int32 nAmbientColor = 0; | 
|  | xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ) ) >>= nAmbientColor; | 
|  | if( nAmbientColor != ::chart::ChartTypeHelper::getDefaultAmbientLightColor( !bRealistic, xChartType ) ) | 
|  | return false; | 
|  |  | 
|  | drawing::Direction3D aDirection(0,0,0); | 
|  | xDiagramProps->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ) ) >>= aDirection; | 
|  |  | 
|  | drawing::Direction3D aDefaultDirection( bRealistic | 
|  | ? ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) | 
|  | : ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) ); | 
|  |  | 
|  | //rotate default light direction when right angled axes are off but supported | 
|  | { | 
|  | sal_Bool bRightAngledAxes = sal_False; | 
|  | xDiagramProps->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; | 
|  | if(!bRightAngledAxes) | 
|  | { | 
|  | if( ChartTypeHelper::isSupportingRightAngledAxes( | 
|  | DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) ); | 
|  | BaseGFXHelper::ReduceToRotationMatrix( aRotation ); | 
|  | ::basegfx::B3DVector aLightVector( BaseGFXHelper::Direction3DToB3DVector( aDefaultDirection ) ); | 
|  | aLightVector = aRotation*aLightVector; | 
|  | aDefaultDirection = BaseGFXHelper::B3DVectorToDirection3D( aLightVector ); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return lcl_isEqual( aDirection, aDefaultDirection ); | 
|  | } | 
|  |  | 
|  | bool lcl_isRealisticLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps ) | 
|  | { | 
|  | return lcl_isLightScheme( xDiagramProps, true /*bRealistic*/ ); | 
|  | } | 
|  | bool lcl_isSimpleLightScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps ) | 
|  | { | 
|  | return lcl_isLightScheme( xDiagramProps, false /*bRealistic*/ ); | 
|  | } | 
|  | void lcl_setLightsForScheme( const uno::Reference< beans::XPropertySet >& xDiagramProps, const ThreeDLookScheme& rScheme ) | 
|  | { | 
|  | if(!xDiagramProps.is()) | 
|  | return; | 
|  | if( rScheme == ThreeDLookScheme_Unknown) | 
|  | return; | 
|  |  | 
|  | xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ), uno::makeAny( sal_True ) ); | 
|  |  | 
|  | uno::Reference< chart2::XDiagram > xDiagram( xDiagramProps, uno::UNO_QUERY ); | 
|  | uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); | 
|  | uno::Any aADirection( uno::makeAny( rScheme == ThreeDLookScheme_Simple | 
|  | ? ChartTypeHelper::getDefaultSimpleLightDirection(xChartType) | 
|  | : ChartTypeHelper::getDefaultRealisticLightDirection(xChartType) ) ); | 
|  |  | 
|  | xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ), aADirection ); | 
|  | //rotate light direction when right angled axes are off but supported | 
|  | { | 
|  | sal_Bool bRightAngledAxes = sal_False; | 
|  | xDiagramProps->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; | 
|  | if(!bRightAngledAxes) | 
|  | { | 
|  | if( ChartTypeHelper::isSupportingRightAngledAxes( xChartType ) ) | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aRotation( lcl_getCompleteRotationMatrix( xDiagramProps ) ); | 
|  | BaseGFXHelper::ReduceToRotationMatrix( aRotation ); | 
|  | lcl_RotateLightSource( xDiagramProps, C2U("D3DSceneLightDirection2"), C2U("D3DSceneLightOn2"), aRotation ); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | sal_Int32 nColor = ::chart::ChartTypeHelper::getDefaultDirectLightColor( rScheme==ThreeDLookScheme_Simple, xChartType ); | 
|  | xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ), uno::makeAny( nColor ) ); | 
|  |  | 
|  | sal_Int32 nAmbientColor = ::chart::ChartTypeHelper::getDefaultAmbientLightColor( rScheme==ThreeDLookScheme_Simple, xChartType ); | 
|  | xDiagramProps->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ), uno::makeAny( nAmbientColor ) ); | 
|  | } | 
|  |  | 
|  | bool lcl_isRealisticScheme( drawing::ShadeMode aShadeMode | 
|  | , sal_Int32 nRoundedEdges | 
|  | , sal_Int32 nObjectLines ) | 
|  | { | 
|  | if(aShadeMode!=drawing::ShadeMode_SMOOTH) | 
|  | return false; | 
|  | if(nRoundedEdges!=5) | 
|  | return false; | 
|  | if(nObjectLines!=0) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool lcl_isSimpleScheme( drawing::ShadeMode aShadeMode | 
|  | , sal_Int32 nRoundedEdges | 
|  | , sal_Int32 nObjectLines | 
|  | , const uno::Reference< XDiagram >& xDiagram ) | 
|  | { | 
|  | if(aShadeMode!=drawing::ShadeMode_FLAT) | 
|  | return false; | 
|  | if(nRoundedEdges!=0) | 
|  | return false; | 
|  | if(nObjectLines==0) | 
|  | { | 
|  | uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); | 
|  | return ChartTypeHelper::noBordersForSimpleScheme( xChartType ); | 
|  | } | 
|  | if(nObjectLines!=1) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void lcl_setRealisticScheme( drawing::ShadeMode& rShadeMode | 
|  | , sal_Int32& rnRoundedEdges | 
|  | , sal_Int32& rnObjectLines ) | 
|  | { | 
|  | rShadeMode = drawing::ShadeMode_SMOOTH; | 
|  | rnRoundedEdges = 5; | 
|  | rnObjectLines = 0; | 
|  | } | 
|  |  | 
|  | void lcl_setSimpleScheme( drawing::ShadeMode& rShadeMode | 
|  | , sal_Int32& rnRoundedEdges | 
|  | , sal_Int32& rnObjectLines | 
|  | , const uno::Reference< XDiagram >& xDiagram ) | 
|  | { | 
|  | rShadeMode = drawing::ShadeMode_FLAT; | 
|  | rnRoundedEdges = 0; | 
|  |  | 
|  | uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); | 
|  | rnObjectLines = ChartTypeHelper::noBordersForSimpleScheme( xChartType ) ? 0 : 1; | 
|  | } | 
|  |  | 
|  | } //end anonymous namespace | 
|  |  | 
|  |  | 
|  | drawing::CameraGeometry ThreeDHelper::getDefaultCameraGeometry( bool bPie ) | 
|  | { | 
|  | // ViewReferencePoint (Point on the View plane) | 
|  | drawing::Position3D vrp(17634.6218373783, 10271.4823817647, 24594.8639082739); | 
|  | // ViewPlaneNormal (Normal to the View Plane) | 
|  | drawing::Direction3D vpn(0.416199821709347, 0.173649045905254, 0.892537795986984); | 
|  | // ViewUpVector (determines the v-axis direction on the view plane as | 
|  | // projection of VUP parallel to VPN onto th view pane) | 
|  | drawing::Direction3D vup(-0.0733876362771618, 0.984807599917971, -0.157379306090273); | 
|  |  | 
|  | if( bPie ) | 
|  | { | 
|  | vrp = drawing::Position3D( 0.0, 0.0, 87591.2408759124 );//--> 5 percent perspecitve | 
|  | vpn = drawing::Direction3D( 0.0, 0.0, 1.0 ); | 
|  | vup = drawing::Direction3D( 0.0, 1.0, 0.0 ); | 
|  | } | 
|  |  | 
|  | return drawing::CameraGeometry( vrp, vpn, vup ); | 
|  | } | 
|  |  | 
|  | namespace | 
|  | { | 
|  | ::basegfx::B3DHomMatrix lcl_getCameraMatrix( const uno::Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | drawing::HomogenMatrix aCameraMatrix; | 
|  |  | 
|  | drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); | 
|  | if( xSceneProperties.is() ) | 
|  | xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG; | 
|  |  | 
|  | ::basegfx::B3DVector aVPN( BaseGFXHelper::Direction3DToB3DVector( aCG.vpn ) ); | 
|  | ::basegfx::B3DVector aVUP( BaseGFXHelper::Direction3DToB3DVector( aCG.vup ) ); | 
|  |  | 
|  | //normalize vectors: | 
|  | aVPN.normalize(); | 
|  | aVUP.normalize(); | 
|  |  | 
|  | ::basegfx::B3DVector aCross = ::basegfx::cross( aVUP, aVPN ); | 
|  |  | 
|  | //first line is VUP x VPN | 
|  | aCameraMatrix.Line1.Column1 = aCross[0]; | 
|  | aCameraMatrix.Line1.Column2 = aCross[1]; | 
|  | aCameraMatrix.Line1.Column3 = aCross[2]; | 
|  | aCameraMatrix.Line1.Column4 = 0.0; | 
|  |  | 
|  | //second line is VUP | 
|  | aCameraMatrix.Line2.Column1 = aVUP[0]; | 
|  | aCameraMatrix.Line2.Column2 = aVUP[1]; | 
|  | aCameraMatrix.Line2.Column3 = aVUP[2]; | 
|  | aCameraMatrix.Line2.Column4 = 0.0; | 
|  |  | 
|  | //third line is VPN | 
|  | aCameraMatrix.Line3.Column1 = aVPN[0]; | 
|  | aCameraMatrix.Line3.Column2 = aVPN[1]; | 
|  | aCameraMatrix.Line3.Column3 = aVPN[2]; | 
|  | aCameraMatrix.Line3.Column4 = 0.0; | 
|  |  | 
|  | //fourth line is 0 0 0 1 | 
|  | aCameraMatrix.Line4.Column1 = 0.0; | 
|  | aCameraMatrix.Line4.Column2 = 0.0; | 
|  | aCameraMatrix.Line4.Column3 = 0.0; | 
|  | aCameraMatrix.Line4.Column4 = 1.0; | 
|  |  | 
|  | return BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aCameraMatrix ); | 
|  | } | 
|  |  | 
|  | double lcl_shiftAngleToIntervalMinusPiToPi( double fAngleRad ) | 
|  | { | 
|  | //valid range:  ]-Pi,Pi] | 
|  | while( fAngleRad<=-F_PI ) | 
|  | fAngleRad+=(2*F_PI); | 
|  | while( fAngleRad>F_PI ) | 
|  | fAngleRad-=(2*F_PI); | 
|  | return fAngleRad; | 
|  | } | 
|  |  | 
|  | void lcl_shiftAngleToIntervalMinus180To180( sal_Int32& rnAngleDegree ) | 
|  | { | 
|  | //valid range:  ]-180,180] | 
|  | while( rnAngleDegree<=-180 ) | 
|  | rnAngleDegree+=360; | 
|  | while( rnAngleDegree>180 ) | 
|  | rnAngleDegree-=360; | 
|  | } | 
|  |  | 
|  | void lcl_shiftAngleToIntervalZeroTo360( sal_Int32& rnAngleDegree ) | 
|  | { | 
|  | //valid range:  [0,360[ | 
|  | while( rnAngleDegree<0 ) | 
|  | rnAngleDegree+=360; | 
|  | while( rnAngleDegree>=360 ) | 
|  | rnAngleDegree-=360; | 
|  | } | 
|  |  | 
|  | void lcl_ensureIntervalMinus1To1( double& rSinOrCos ) | 
|  | { | 
|  | if (rSinOrCos < -1.0) | 
|  | rSinOrCos = -1.0; | 
|  | else if (rSinOrCos > 1.0) | 
|  | rSinOrCos = 1.0; | 
|  | } | 
|  |  | 
|  | bool lcl_isSinZero( double fAngleRad ) | 
|  | { | 
|  | return ::basegfx::fTools::equalZero( sin(fAngleRad), 0.0000001 ); | 
|  | } | 
|  | bool lcl_isCosZero( double fAngleRad ) | 
|  | { | 
|  | return ::basegfx::fTools::equalZero( cos(fAngleRad), 0.0000001 ); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::convertElevationRotationDegToXYZAngleRad( | 
|  | sal_Int32 nElevationDeg, sal_Int32 nRotationDeg, | 
|  | double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad) | 
|  | { | 
|  | // for a description of the algorithm see issue 72994 | 
|  | //http://www.openoffice.org/issues/show_bug.cgi?id=72994 | 
|  | //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt | 
|  |  | 
|  | lcl_shiftAngleToIntervalZeroTo360( nElevationDeg ); | 
|  | lcl_shiftAngleToIntervalZeroTo360( nRotationDeg ); | 
|  |  | 
|  | double& x = rfXAngleRad; | 
|  | double& y = rfYAngleRad; | 
|  | double& z = rfZAngleRad; | 
|  |  | 
|  | double E = F_PI*nElevationDeg/180; //elevation in Rad | 
|  | double R = F_PI*nRotationDeg/180; //rotation in Rad | 
|  |  | 
|  | if( (nRotationDeg == 0 || nRotationDeg == 180 ) | 
|  | && ( nElevationDeg == 90 || nElevationDeg == 270 ) ) | 
|  | { | 
|  | //sR==0 && cE==0 | 
|  | z = 0.0; | 
|  | //element 23 | 
|  | double f23 = cos(R)*sin(E); | 
|  | if(f23>0) | 
|  | x = F_PI/2; | 
|  | else | 
|  | x = -F_PI/2; | 
|  | y = R; | 
|  | } | 
|  | else if( ( nRotationDeg == 90 || nRotationDeg == 270 ) | 
|  | && ( nElevationDeg == 90 || nElevationDeg == 270 ) ) | 
|  | { | 
|  | //cR==0 && cE==0 | 
|  | z = F_PI/2; | 
|  | if( sin(R)>0 ) | 
|  | x = F_PI/2.0; | 
|  | else | 
|  | x = -F_PI/2.0; | 
|  |  | 
|  | if( (sin(R)*sin(E))>0 ) | 
|  | y = 0.0; | 
|  | else | 
|  | y = F_PI; | 
|  | } | 
|  | else if( (nRotationDeg == 0 || nRotationDeg == 180 ) | 
|  | && ( nElevationDeg == 0 || nElevationDeg == 180 ) ) | 
|  | { | 
|  | //sR==0 && sE==0 | 
|  | z = 0.0; | 
|  | y = R; | 
|  | x = E; | 
|  | } | 
|  | else if( ( nRotationDeg == 90 || nRotationDeg == 270 ) | 
|  | && ( nElevationDeg == 0 || nElevationDeg == 180 ) ) | 
|  | { | 
|  | //cR==0 && sE==0 | 
|  | z = 0.0; | 
|  |  | 
|  | if( (sin(R)/cos(E))>0 ) | 
|  | y = F_PI/2; | 
|  | else | 
|  | y = -F_PI/2; | 
|  |  | 
|  | if( (cos(E))>0 ) | 
|  | x = 0; | 
|  | else | 
|  | x = F_PI; | 
|  | } | 
|  | else if ( nElevationDeg == 0 || nElevationDeg == 180 ) | 
|  | { | 
|  | //sR!=0 cR!=0 sE==0 | 
|  | z = 0.0; | 
|  | x = E; | 
|  | y = R; | 
|  | //use element 13 for sign | 
|  | if((cos(x)*sin(y)*sin(R))<0.0) | 
|  | y *= -1.0; | 
|  | } | 
|  | else if ( nElevationDeg == 90 || nElevationDeg == 270 ) | 
|  | { | 
|  | //sR!=0 cR!=0 cE==0 | 
|  | //element 12 + 22 --> y=0 or F_PI and x=+-F_PI/2 | 
|  | //-->element 13/23: | 
|  | z = atan(sin(R)/(cos(R)*sin(E))); | 
|  | //use element 13 for sign for x | 
|  | if( (sin(R)*sin(z))>0.0 ) | 
|  | x = F_PI/2; | 
|  | else | 
|  | x = -F_PI/2; | 
|  | //use element 21 for y | 
|  | if( (sin(R)*sin(E)*sin(z))>0.0) | 
|  | y = 0.0; | 
|  | else | 
|  | y = F_PI; | 
|  | } | 
|  | else if ( nRotationDeg == 0 || nRotationDeg == 180 ) | 
|  | { | 
|  | //sE!=0 cE!=0 sR==0 | 
|  | z = 0.0; | 
|  | x = E; | 
|  | y = R; | 
|  | double f23 = cos(R)*sin(E); | 
|  | if( (f23 * sin(x)) < 0.0 ) | 
|  | x *= -1.0; //todo ?? | 
|  | } | 
|  | else if (nRotationDeg == 90 || nRotationDeg == 270) | 
|  | { | 
|  | //sE!=0 cE!=0 cR==0 | 
|  | //z = +- F_PI/2; | 
|  | //x = +- F_PI/2; | 
|  | z = F_PI/2; | 
|  | x = F_PI/2; | 
|  | double sR = sin(R); | 
|  | if( sR<0.0 ) | 
|  | x *= -1.0; //different signs for x and z | 
|  |  | 
|  | //use element 21: | 
|  | double cy = sR*sin(E)/sin(z); | 
|  | lcl_ensureIntervalMinus1To1(cy); | 
|  | y = acos(cy); | 
|  |  | 
|  | //use element 22 for sign: | 
|  | if( (sin(x)*sin(y)*sin(z)*cos(E))<0.0) | 
|  | y *= -1.0; | 
|  | } | 
|  | else | 
|  | { | 
|  | z = atan(tan(R) * sin(E)); | 
|  | if(cos(z)==0.0) | 
|  | { | 
|  | DBG_ERROR("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad"); | 
|  | return; | 
|  | } | 
|  | double cy = cos(R)/cos(z); | 
|  | lcl_ensureIntervalMinus1To1(cy); | 
|  | y = acos(cy); | 
|  |  | 
|  | //element 12 in 23 | 
|  | double fDenominator = cos(z)*(1.0-pow(sin(y),2)); | 
|  | if(fDenominator==0.0) | 
|  | { | 
|  | DBG_ERROR("calculation error in ThreeDHelper::convertElevationRotationDegToXYZAngleRad"); | 
|  | return; | 
|  | } | 
|  | double sx = cos(R)*sin(E)/fDenominator; | 
|  | lcl_ensureIntervalMinus1To1(sx); | 
|  | x = asin( sx ); | 
|  |  | 
|  | //use element 13 for sign: | 
|  | double f13a = cos(x)*cos(z)*sin(y); | 
|  | double f13b = sin(R)-sx*sin(z); | 
|  | if( (f13b*f13a)<0.0 ) | 
|  | { | 
|  | //change x or y | 
|  | //use element 22 for further investigations: | 
|  | //try | 
|  | y *= -1; | 
|  | double f22a = cos(x)*cos(z); | 
|  | double f22b = cos(E)-(sx*sin(y)*sin(z)); | 
|  | if( (f22a*f22b)<0.0 ) | 
|  | { | 
|  | y *= -1; | 
|  | x=(F_PI-x); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | //change nothing or both | 
|  | //use element 22 for further investigations: | 
|  | double f22a = cos(x)*cos(z); | 
|  | double f22b = cos(E)-(sx*sin(y)*sin(z)); | 
|  | if( (f22a*f22b)<0.0 ) | 
|  | { | 
|  | y *= -1; | 
|  | x=(F_PI-x); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::convertXYZAngleRadToElevationRotationDeg( | 
|  | sal_Int32& rnElevationDeg, sal_Int32& rnRotationDeg, | 
|  | double fXRad, double fYRad, double fZRad) | 
|  | { | 
|  | // for a description of the algorithm see issue 72994 | 
|  | //http://www.openoffice.org/issues/show_bug.cgi?id=72994 | 
|  | //http://www.openoffice.org/nonav/issues/showattachment.cgi/50608/DescriptionCorrected.odt | 
|  |  | 
|  | double R = 0.0; //Rotation in Rad | 
|  | double E = 0.0; //Elevation in Rad | 
|  |  | 
|  | double& x = fXRad; | 
|  | double& y = fYRad; | 
|  | double& z = fZRad; | 
|  |  | 
|  | double f11 = cos(y)*cos(z); | 
|  |  | 
|  | if( lcl_isSinZero(y) ) | 
|  | { | 
|  | //siny == 0 | 
|  |  | 
|  | if( lcl_isCosZero(x) ) | 
|  | { | 
|  | //siny == 0 && cosx == 0 | 
|  |  | 
|  | if( lcl_isSinZero(z) ) | 
|  | { | 
|  | //siny == 0 && cosx == 0 && sinz == 0 | 
|  | //example: x=+-90 y=0oder180 z=0(oder180) | 
|  |  | 
|  | //element 13+11 | 
|  | if( f11 > 0 ) | 
|  | R = 0.0; | 
|  | else | 
|  | R = F_PI; | 
|  |  | 
|  | //element 23 | 
|  | double f23 = cos(z)*sin(x) / cos(R); | 
|  | if( f23 > 0 ) | 
|  | E = F_PI/2.0; | 
|  | else | 
|  | E = -F_PI/2.0; | 
|  | } | 
|  | else if( lcl_isCosZero(z) ) | 
|  | { | 
|  | //siny == 0 && cosx == 0 && cosz == 0 | 
|  | //example: x=+-90 y=0oder180 z=+-90 | 
|  |  | 
|  | double f13 = sin(x)*sin(z); | 
|  | //element 13+11 | 
|  | if( f13 > 0 ) | 
|  | R = F_PI/2.0; | 
|  | else | 
|  | R = -F_PI/2.0; | 
|  |  | 
|  | //element 21 | 
|  | double f21 = cos(y)*sin(z) / sin(R); | 
|  | if( f21 > 0 ) | 
|  | E = F_PI/2.0; | 
|  | else | 
|  | E = -F_PI/2.0; | 
|  | } | 
|  | else | 
|  | { | 
|  | //siny == 0 && cosx == 0 && cosz != 0 && sinz != 0 | 
|  | //element 11 && 13 | 
|  | double f13 = sin(x)*sin(z); | 
|  | R = atan( f13/f11 ); | 
|  |  | 
|  | if(f11<0) | 
|  | R+=F_PI; | 
|  |  | 
|  | //element 23 | 
|  | double f23 = cos(z)*sin(x); | 
|  | if( f23/cos(R) > 0 ) | 
|  | E = F_PI/2.0; | 
|  | else | 
|  | E = -F_PI/2.0; | 
|  | } | 
|  | } | 
|  | else if( lcl_isSinZero(x) ) | 
|  | { | 
|  | //sinY==0 sinX==0 | 
|  | //element 13+11 | 
|  | if( f11 > 0 ) | 
|  | R = 0.0; | 
|  | else | 
|  | R = F_PI; | 
|  |  | 
|  | double f22 = cos(x)*cos(z); | 
|  | if( f22 > 0 ) | 
|  | E = 0.0; | 
|  | else | 
|  | E = F_PI; | 
|  | } | 
|  | else if( lcl_isSinZero(z) ) | 
|  | { | 
|  | //sinY==0 sinZ==0 sinx!=0 cosx!=0 | 
|  | //element 13+11 | 
|  | if( f11 > 0 ) | 
|  | R = 0.0; | 
|  | else | 
|  | R = F_PI; | 
|  |  | 
|  | //element 22 && 23 | 
|  | double f22 = cos(x)*cos(z); | 
|  | double f23 = cos(z)*sin(x); | 
|  | E = atan( f23/(f22*cos(R)) ); | 
|  | if( (f22*cos(E))<0 ) | 
|  | E+=F_PI; | 
|  | } | 
|  | else if( lcl_isCosZero(z) ) | 
|  | { | 
|  | //sinY == 0 && cosZ == 0 && cosx != 0 && sinx != 0 | 
|  | double f13 = sin(x)*sin(z); | 
|  | //element 13+11 | 
|  | if( f13 > 0 ) | 
|  | R = F_PI/2.0; | 
|  | else | 
|  | R = -F_PI/2.0; | 
|  |  | 
|  | //element 21+22 | 
|  | double f21 = cos(y)*sin(z); | 
|  | if( f21/sin(R) > 0 ) | 
|  | E = F_PI/2.0; | 
|  | else | 
|  | E = -F_PI/2.0; | 
|  | } | 
|  | else | 
|  | { | 
|  | //sinY == 0 && all other !=0 | 
|  | double f13 = sin(x)*sin(z); | 
|  | R = atan( f13/f11 ); | 
|  | if( (f11*cos(R))<0.0 ) | 
|  | R+=F_PI; | 
|  |  | 
|  | double f22 = cos(x)*cos(z); | 
|  | if( !lcl_isCosZero(R) ) | 
|  | E = atan( cos(z)*sin(x) /( f22*cos(R) ) ); | 
|  | else | 
|  | E = atan( cos(y)*sin(z) /( f22*sin(R) ) ); | 
|  | if( (f22*cos(E))<0 ) | 
|  | E+=F_PI; | 
|  | } | 
|  | } | 
|  | else if( lcl_isCosZero(y) ) | 
|  | { | 
|  | //cosY==0 | 
|  |  | 
|  | double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y); | 
|  | if( f13 >= 0 ) | 
|  | R = F_PI/2.0; | 
|  | else | 
|  | R = -F_PI/2.0; | 
|  |  | 
|  | double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z); | 
|  | if( f22 >= 0 ) | 
|  | E = 0.0; | 
|  | else | 
|  | E = F_PI; | 
|  | } | 
|  | else if( lcl_isSinZero(x) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX=0 | 
|  | if( lcl_isSinZero(z) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX=0 sinZ=0 | 
|  | double f13 = cos(x)*cos(z)*sin(y); | 
|  | R = atan( f13/f11 ); | 
|  | //R = asin(f13); | 
|  | if( f11<0 ) | 
|  | R+=F_PI; | 
|  |  | 
|  | double f22 = cos(x)*cos(z); | 
|  | if( f22>0 ) | 
|  | E = 0.0; | 
|  | else | 
|  | E = F_PI; | 
|  | } | 
|  | else if( lcl_isCosZero(z) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX=0 cosZ=0 | 
|  | R = x; | 
|  | E = y;//or -y | 
|  | //use 23 for 'signs' | 
|  | double f23 =  -1.0*cos(x)*sin(y)*sin(z); | 
|  | if( (f23*cos(R)*sin(E))<0.0 ) | 
|  | { | 
|  | //change R or E | 
|  | E = -y; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX=0 sinZ!=0 cosZ!=0 | 
|  | double f13 = cos(x)*cos(z)*sin(y); | 
|  | R = atan( f13/f11 ); | 
|  |  | 
|  | if( f11<0 ) | 
|  | R+=F_PI; | 
|  |  | 
|  | double f21 = cos(y)*sin(z); | 
|  | double f22 = cos(x)*cos(z); | 
|  | E = atan(f21/(f22*sin(R)) ); | 
|  |  | 
|  | if( (f22*cos(E))<0.0 ) | 
|  | E+=F_PI; | 
|  | } | 
|  | } | 
|  | else if( lcl_isCosZero(x) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 cosX=0 | 
|  |  | 
|  | if( lcl_isSinZero(z) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 cosX=0 sinZ=0 | 
|  | R=0;//13 -> R=0 or F_PI | 
|  | if( f11<0.0 ) | 
|  | R=F_PI; | 
|  | E=F_PI/2;//22 -> E=+-F_PI/2 | 
|  | //use element 11 and 23 for sign | 
|  | double f23 = cos(z)*sin(x); | 
|  | if( (f11*f23*sin(E))<0.0 ) | 
|  | E=-F_PI/2.0; | 
|  | } | 
|  | else if( lcl_isCosZero(z) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 cosX=0 cosZ=0 | 
|  | //element 11 & 13: | 
|  | if( (sin(x)*sin(z))>0.0 ) | 
|  | R=F_PI/2.0; | 
|  | else | 
|  | R=-F_PI/2.0; | 
|  | //element 22: | 
|  | E=acos( sin(x)*sin(y)*sin(z)); | 
|  | //use element 21 for sign: | 
|  | if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 ) | 
|  | E*=-1.0; | 
|  | } | 
|  | else | 
|  | { | 
|  | //cosY!=0 sinY!=0 cosX=0 sinZ!=0 cosZ!=0 | 
|  | //element 13/11 | 
|  | R = atan( sin(x)*sin(z)/(cos(y)*cos(z)) ); | 
|  | //use 13 for 'sign' | 
|  | if( (sin(x)*sin(z))<0.0 ) | 
|  | R += F_PI; | 
|  | //element 22 | 
|  | E = acos(sin(x)*sin(y)*sin(z) ); | 
|  | //use 21 for sign | 
|  | if( (cos(y)*sin(z)*sin(R)*sin(E))<0.0 ) | 
|  | E*=-1.0; | 
|  | } | 
|  | } | 
|  | else if( lcl_isSinZero(z) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ=0 | 
|  | //element 11 | 
|  | R=y; | 
|  | //use elenment 13 for sign | 
|  | if( (cos(x)*cos(z)*sin(y)*sin(R))<0.0 ) | 
|  | R*=-1.0; | 
|  | //element 22 | 
|  | E = acos( cos(x)*cos(z) ); | 
|  | //use element 23 for sign | 
|  | if( (cos(z)*sin(x)*cos(R)*sin(E))<0.0 ) | 
|  | E*=-1.0; | 
|  | } | 
|  | else if( lcl_isCosZero(z) ) | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX!=0 cosX!=0 cosZ=0 | 
|  | //element 21/23 | 
|  | R=atan(-cos(y)/(cos(x)*sin(y))); | 
|  | //use element 13 for 'sign' | 
|  | if( (sin(x)*sin(z)*sin(R))<0.0 ) | 
|  | R+=F_PI; | 
|  | //element 21/22 | 
|  | E=atan( cos(y)*sin(z)/(sin(R)*sin(x)*sin(y)*sin(z)) ); | 
|  | //use element 23 for 'sign' | 
|  | if( (-cos(x)*sin(y)*sin(z)*cos(R)*sin(E))<0.0 ) | 
|  | E+=F_PI; | 
|  | } | 
|  | else | 
|  | { | 
|  | //cosY!=0 sinY!=0 sinX!=0 cosX!=0 sinZ!=0 cosZ!=0 | 
|  | //13/11: | 
|  | double f13 = sin(x)*sin(z)+cos(x)*cos(z)*sin(y); | 
|  | R = atan( f13/ f11 ); | 
|  | if(f11<0.0) | 
|  | R+=F_PI; | 
|  | double f22 = cos(x)*cos(z)+sin(x)*sin(y)*sin(z); | 
|  | double f23 = cos(x)*sin(y)*sin(z)-cos(z)*sin(x); | 
|  | //23/22: | 
|  | E = atan( -1.0*f23/(f22*cos(R)) ); | 
|  | if(f22<0.0) | 
|  | E+=F_PI; | 
|  | } | 
|  |  | 
|  | rnElevationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( E ) ); | 
|  | rnRotationDeg = ::basegfx::fround( BaseGFXHelper::Rad2Deg( R ) ); | 
|  | } | 
|  |  | 
|  | double ThreeDHelper::getValueClippedToRange( double fAngle, const double& fPositivLimit ) | 
|  | { | 
|  | if( fAngle<-1*fPositivLimit ) | 
|  | fAngle=-1*fPositivLimit; | 
|  | else if( fAngle>fPositivLimit ) | 
|  | fAngle=fPositivLimit; | 
|  | return fAngle; | 
|  | } | 
|  |  | 
|  | double ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes() | 
|  | { | 
|  | return 90.0; | 
|  | } | 
|  |  | 
|  | double ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes() | 
|  | { | 
|  | return 45.0; | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::adaptRadAnglesForRightAngledAxes( double& rfXAngleRad, double& rfYAngleRad ) | 
|  | { | 
|  | rfXAngleRad = ThreeDHelper::getValueClippedToRange(rfXAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes()) ); | 
|  | rfYAngleRad = ThreeDHelper::getValueClippedToRange(rfYAngleRad, BaseGFXHelper::Deg2Rad(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes()) ); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::getRotationAngleFromDiagram( | 
|  | const Reference< beans::XPropertySet >& xSceneProperties, double& rfXAngleRad, double& rfYAngleRad, double& rfZAngleRad ) | 
|  | { | 
|  | //takes the camera and the transformation matrix into account | 
|  |  | 
|  | rfXAngleRad = rfYAngleRad = rfZAngleRad = 0.0; | 
|  |  | 
|  | if( !xSceneProperties.is() ) | 
|  | return; | 
|  |  | 
|  | //get camera rotation | 
|  | ::basegfx::B3DHomMatrix aFixCameraRotationMatrix( lcl_getCameraMatrix( xSceneProperties ) ); | 
|  | BaseGFXHelper::ReduceToRotationMatrix( aFixCameraRotationMatrix ); | 
|  |  | 
|  | //get scene rotation | 
|  | ::basegfx::B3DHomMatrix aSceneRotation; | 
|  | { | 
|  | drawing::HomogenMatrix aHomMatrix; | 
|  | if( xSceneProperties->getPropertyValue( C2U("D3DTransformMatrix")) >>= aHomMatrix ) | 
|  | { | 
|  | aSceneRotation = BaseGFXHelper::HomogenMatrixToB3DHomMatrix( aHomMatrix ); | 
|  | BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation ); | 
|  | } | 
|  | } | 
|  |  | 
|  | ::basegfx::B3DHomMatrix aResultRotation = aFixCameraRotationMatrix * aSceneRotation; | 
|  | ::basegfx::B3DTuple aRotation( BaseGFXHelper::GetRotationFromMatrix( aResultRotation ) ); | 
|  |  | 
|  | rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getX()); | 
|  | rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getY()); | 
|  | rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(aRotation.getZ()); | 
|  |  | 
|  | if(rfZAngleRad<(-F_PI/2) || rfZAngleRad>(F_PI/2)) | 
|  | { | 
|  | rfZAngleRad-=F_PI; | 
|  | rfXAngleRad-=F_PI; | 
|  | rfYAngleRad=(F_PI-rfYAngleRad); | 
|  |  | 
|  | rfXAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfXAngleRad); | 
|  | rfYAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfYAngleRad); | 
|  | rfZAngleRad = lcl_shiftAngleToIntervalMinusPiToPi(rfZAngleRad); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::switchRightAngledAxes( const Reference< beans::XPropertySet >& xSceneProperties, sal_Bool bRightAngledAxes, bool bRotateLights ) | 
|  | { | 
|  | try | 
|  | { | 
|  | if( xSceneProperties.is() ) | 
|  | { | 
|  | sal_Bool bOldRightAngledAxes = sal_False; | 
|  | xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bOldRightAngledAxes; | 
|  | if( bOldRightAngledAxes!=bRightAngledAxes) | 
|  | { | 
|  | xSceneProperties->setPropertyValue( C2U("RightAngledAxes"), uno::makeAny( bRightAngledAxes )); | 
|  | if( bRotateLights ) | 
|  | { | 
|  | if(bRightAngledAxes) | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aInverseRotation( lcl_getInverseRotationMatrix( xSceneProperties ) ); | 
|  | lcl_rotateLights( aInverseRotation, xSceneProperties ); | 
|  | } | 
|  | else | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aCompleteRotation( lcl_getCompleteRotationMatrix( xSceneProperties ) ); | 
|  | lcl_rotateLights( aCompleteRotation, xSceneProperties ); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | catch( const uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setRotationAngleToDiagram( | 
|  | const Reference< beans::XPropertySet >& xSceneProperties | 
|  | , double fXAngleRad, double fYAngleRad, double fZAngleRad ) | 
|  | { | 
|  | //the rotation of the camera is not touched but taken into account | 
|  | //the rotation difference is applied to the transformation matrix | 
|  |  | 
|  | //the light sources will be adapted also | 
|  |  | 
|  | if( !xSceneProperties.is() ) | 
|  | return; | 
|  |  | 
|  | try | 
|  | { | 
|  | //remind old rotation for adaption of light directions | 
|  | ::basegfx::B3DHomMatrix aInverseOldRotation( lcl_getInverseRotationMatrix( xSceneProperties ) ); | 
|  |  | 
|  | ::basegfx::B3DHomMatrix aInverseCameraRotation; | 
|  | { | 
|  | ::basegfx::B3DTuple aR( BaseGFXHelper::GetRotationFromMatrix( | 
|  | lcl_getCameraMatrix( xSceneProperties ) ) ); | 
|  | aInverseCameraRotation.rotate( 0.0, 0.0, -aR.getZ() ); | 
|  | aInverseCameraRotation.rotate( 0.0, -aR.getY(), 0.0 ); | 
|  | aInverseCameraRotation.rotate( -aR.getX(), 0.0, 0.0 ); | 
|  | } | 
|  |  | 
|  | ::basegfx::B3DHomMatrix aCumulatedRotation; | 
|  | aCumulatedRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  |  | 
|  | //calculate new scene matrix | 
|  | ::basegfx::B3DHomMatrix aSceneRotation = aInverseCameraRotation*aCumulatedRotation; | 
|  | BaseGFXHelper::ReduceToRotationMatrix( aSceneRotation ); | 
|  |  | 
|  | //set new rotation to transformation matrix | 
|  | xSceneProperties->setPropertyValue( | 
|  | C2U("D3DTransformMatrix"), uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation ))); | 
|  |  | 
|  | //rotate lights if RightAngledAxes are not set or not supported | 
|  | sal_Bool bRightAngledAxes = sal_False; | 
|  | xSceneProperties->getPropertyValue( C2U("RightAngledAxes")) >>= bRightAngledAxes; | 
|  | uno::Reference< chart2::XDiagram > xDiagram( xSceneProperties, uno::UNO_QUERY ); | 
|  | if(!bRightAngledAxes || !ChartTypeHelper::isSupportingRightAngledAxes( | 
|  | DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) | 
|  | { | 
|  | ::basegfx::B3DHomMatrix aNewRotation; | 
|  | aNewRotation.rotate( fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | lcl_rotateLights( aNewRotation*aInverseOldRotation, xSceneProperties ); | 
|  | } | 
|  | } | 
|  | catch( const uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::getRotationFromDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties | 
|  | , sal_Int32& rnHorizontalAngleDegree, sal_Int32& rnVerticalAngleDegree ) | 
|  | { | 
|  | double fXAngle, fYAngle, fZAngle; | 
|  | ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle ); | 
|  |  | 
|  | if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) | 
|  | { | 
|  | ThreeDHelper::convertXYZAngleRadToElevationRotationDeg( | 
|  | rnHorizontalAngleDegree, rnVerticalAngleDegree, fXAngle, fYAngle, fZAngle); | 
|  | rnVerticalAngleDegree*=-1; | 
|  | } | 
|  | else | 
|  | { | 
|  | fXAngle = BaseGFXHelper::Rad2Deg( fXAngle ); | 
|  | fYAngle = BaseGFXHelper::Rad2Deg( fYAngle ); | 
|  | fZAngle = BaseGFXHelper::Rad2Deg( fZAngle ); | 
|  |  | 
|  | rnHorizontalAngleDegree = ::basegfx::fround(fXAngle); | 
|  | rnVerticalAngleDegree = ::basegfx::fround(-1.0*fYAngle); | 
|  | //nZRotation = ::basegfx::fround(-1.0*fZAngle); | 
|  | } | 
|  |  | 
|  | lcl_shiftAngleToIntervalMinus180To180( rnHorizontalAngleDegree ); | 
|  | lcl_shiftAngleToIntervalMinus180To180( rnVerticalAngleDegree ); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setRotationToDiagram( const uno::Reference< beans::XPropertySet >& xSceneProperties | 
|  | , sal_Int32 nHorizontalAngleDegree, sal_Int32 nVerticalYAngleDegree ) | 
|  | { | 
|  | //todo: x and y is not equal to horz and vert in case of RightAngledAxes==false | 
|  | double fXAngle = BaseGFXHelper::Deg2Rad( nHorizontalAngleDegree ); | 
|  | double fYAngle = BaseGFXHelper::Deg2Rad( -1*nVerticalYAngleDegree ); | 
|  | double fZAngle = 0.0; | 
|  |  | 
|  | if( !lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) | 
|  | ThreeDHelper::convertElevationRotationDegToXYZAngleRad( | 
|  | nHorizontalAngleDegree, -1*nVerticalYAngleDegree, fXAngle, fYAngle, fZAngle ); | 
|  |  | 
|  | ThreeDHelper::setRotationAngleToDiagram( xSceneProperties, fXAngle, fYAngle, fZAngle ); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::getCameraDistanceRange( double& rfMinimumDistance, double& rfMaximumDistance ) | 
|  | { | 
|  | rfMinimumDistance = 3.0/4.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value | 
|  | rfMaximumDistance = 20.0*FIXED_SIZE_FOR_3D_CHART_VOLUME;//empiric value | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::ensureCameraDistanceRange( double& rfCameraDistance ) | 
|  | { | 
|  | double fMin, fMax; | 
|  | getCameraDistanceRange( fMin, fMax ); | 
|  | if( rfCameraDistance < fMin ) | 
|  | rfCameraDistance = fMin; | 
|  | if( rfCameraDistance > fMax ) | 
|  | rfCameraDistance = fMax; | 
|  | } | 
|  |  | 
|  | double ThreeDHelper::getCameraDistance( | 
|  | const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | double fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME; | 
|  |  | 
|  | if( !xSceneProperties.is() ) | 
|  | return fCameraDistance; | 
|  |  | 
|  | try | 
|  | { | 
|  | drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); | 
|  | xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG; | 
|  | ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) ); | 
|  | fCameraDistance = aVRP.getLength(); | 
|  |  | 
|  | ensureCameraDistanceRange( fCameraDistance ); | 
|  | } | 
|  | catch( const uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  | return fCameraDistance; | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setCameraDistance( | 
|  | const Reference< beans::XPropertySet >& xSceneProperties, double fCameraDistance ) | 
|  | { | 
|  | if( !xSceneProperties.is() ) | 
|  | return; | 
|  |  | 
|  | try | 
|  | { | 
|  | if( fCameraDistance <= 0 ) | 
|  | fCameraDistance = FIXED_SIZE_FOR_3D_CHART_VOLUME; | 
|  |  | 
|  | drawing::CameraGeometry aCG( ThreeDHelper::getDefaultCameraGeometry() ); | 
|  | xSceneProperties->getPropertyValue( C2U( "D3DCameraGeometry" ) ) >>= aCG; | 
|  | ::basegfx::B3DVector aVRP( BaseGFXHelper::Position3DToB3DVector( aCG.vrp ) ); | 
|  | if( ::basegfx::fTools::equalZero( aVRP.getLength() ) ) | 
|  | aVRP = ::basegfx::B3DVector(0,0,1); | 
|  | aVRP.setLength(fCameraDistance); | 
|  | aCG.vrp = BaseGFXHelper::B3DVectorToPosition3D( aVRP ); | 
|  |  | 
|  | xSceneProperties->setPropertyValue( C2U("D3DCameraGeometry"), uno::makeAny( aCG )); | 
|  | } | 
|  | catch( const uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  | } | 
|  |  | 
|  | double ThreeDHelper::CameraDistanceToPerspective( double fCameraDistance ) | 
|  | { | 
|  | double fRet = fCameraDistance; | 
|  | double fMin, fMax; | 
|  | ThreeDHelper::getCameraDistanceRange( fMin, fMax ); | 
|  | //fMax <-> 0; fMin <->100 | 
|  | //a/x + b = y | 
|  | double a = 100.0*fMax*fMin/(fMax-fMin); | 
|  | double b = -a/fMax; | 
|  |  | 
|  | fRet = a/fCameraDistance + b; | 
|  |  | 
|  | return fRet; | 
|  | } | 
|  |  | 
|  | double ThreeDHelper::PerspectiveToCameraDistance( double fPerspective ) | 
|  | { | 
|  | double fRet = fPerspective; | 
|  | double fMin, fMax; | 
|  | ThreeDHelper::getCameraDistanceRange( fMin, fMax ); | 
|  | //fMax <-> 0; fMin <->100 | 
|  | //a/x + b = y | 
|  | double a = 100.0*fMax*fMin/(fMax-fMin); | 
|  | double b = -a/fMax; | 
|  |  | 
|  | fRet = a/(fPerspective - b); | 
|  |  | 
|  | return fRet; | 
|  | } | 
|  |  | 
|  | ThreeDLookScheme ThreeDHelper::detectScheme( const uno::Reference< XDiagram >& xDiagram ) | 
|  | { | 
|  | ThreeDLookScheme aScheme = ThreeDLookScheme_Unknown; | 
|  |  | 
|  | sal_Int32 nRoundedEdges; | 
|  | sal_Int32 nObjectLines; | 
|  | ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines ); | 
|  |  | 
|  | //get shade mode and light settings: | 
|  | drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH ); | 
|  | uno::Reference< beans::XPropertySet > xDiagramProps( xDiagram, uno::UNO_QUERY ); | 
|  | try | 
|  | { | 
|  | if( xDiagramProps.is() ) | 
|  | xDiagramProps->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>= aShadeMode; | 
|  | } | 
|  | catch( uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  |  | 
|  | if( lcl_isSimpleScheme( aShadeMode, nRoundedEdges, nObjectLines, xDiagram ) ) | 
|  | { | 
|  | if( lcl_isSimpleLightScheme(xDiagramProps) ) | 
|  | aScheme = ThreeDLookScheme_Simple; | 
|  | } | 
|  | else if( lcl_isRealisticScheme( aShadeMode, nRoundedEdges, nObjectLines ) ) | 
|  | { | 
|  | if( lcl_isRealisticLightScheme(xDiagramProps) ) | 
|  | aScheme = ThreeDLookScheme_Realistic; | 
|  | } | 
|  |  | 
|  | return aScheme; | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setScheme( const uno::Reference< XDiagram >& xDiagram, ThreeDLookScheme aScheme ) | 
|  | { | 
|  | if( aScheme == ThreeDLookScheme_Unknown ) | 
|  | return; | 
|  |  | 
|  | drawing::ShadeMode aShadeMode; | 
|  | sal_Int32 nRoundedEdges; | 
|  | sal_Int32 nObjectLines; | 
|  |  | 
|  | if( aScheme == ThreeDLookScheme_Simple ) | 
|  | lcl_setSimpleScheme(aShadeMode,nRoundedEdges,nObjectLines,xDiagram); | 
|  | else | 
|  | lcl_setRealisticScheme(aShadeMode,nRoundedEdges,nObjectLines); | 
|  |  | 
|  | try | 
|  | { | 
|  | ThreeDHelper::setRoundedEdgesAndObjectLines( xDiagram, nRoundedEdges, nObjectLines ); | 
|  |  | 
|  | uno::Reference< beans::XPropertySet > xProp( xDiagram, uno::UNO_QUERY ); | 
|  | if( xProp.is() ) | 
|  | { | 
|  | drawing::ShadeMode aOldShadeMode; | 
|  | if( ! ( (xProp->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>=aOldShadeMode) && | 
|  | aOldShadeMode == aShadeMode )) | 
|  | { | 
|  | xProp->setPropertyValue( C2U( "D3DSceneShadeMode" ), uno::makeAny( aShadeMode )); | 
|  | } | 
|  | } | 
|  |  | 
|  | lcl_setLightsForScheme( xProp, aScheme ); | 
|  | } | 
|  | catch( uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::set3DSettingsToDefault( const uno::Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | Reference< beans::XPropertyState > xState( xSceneProperties, uno::UNO_QUERY ); | 
|  | if(xState.is()) | 
|  | { | 
|  | xState->setPropertyToDefault( C2U("D3DSceneDistance")); | 
|  | xState->setPropertyToDefault( C2U("D3DSceneFocalLength")); | 
|  | } | 
|  | ThreeDHelper::setDefaultRotation( xSceneProperties ); | 
|  | ThreeDHelper::setDefaultIllumination( xSceneProperties ); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties, bool bPieOrDonut ) | 
|  | { | 
|  | if( !xSceneProperties.is() ) | 
|  | return; | 
|  |  | 
|  | drawing::CameraGeometry aCameraGeo( ThreeDHelper::getDefaultCameraGeometry( bPieOrDonut ) ); | 
|  | xSceneProperties->setPropertyValue( C2U("D3DCameraGeometry"), uno::makeAny( aCameraGeo )); | 
|  |  | 
|  | ::basegfx::B3DHomMatrix aSceneRotation; | 
|  | if( bPieOrDonut ) | 
|  | aSceneRotation.rotate( -F_PI/3.0, 0, 0 ); | 
|  | xSceneProperties->setPropertyValue( C2U("D3DTransformMatrix"), | 
|  | uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aSceneRotation ))); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setDefaultRotation( const uno::Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | bool bPieOrDonut( DiagramHelper::isPieOrDonutChart( uno::Reference< XDiagram >(xSceneProperties, uno::UNO_QUERY) ) ); | 
|  | ThreeDHelper::setDefaultRotation( xSceneProperties, bPieOrDonut ); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::setDefaultIllumination( const uno::Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | if( !xSceneProperties.is() ) | 
|  | return; | 
|  |  | 
|  | drawing::ShadeMode aShadeMode( drawing::ShadeMode_SMOOTH ); | 
|  | try | 
|  | { | 
|  | xSceneProperties->getPropertyValue( C2U( "D3DSceneShadeMode" ) )>>= aShadeMode; | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ), uno::makeAny( sal_False ) ); | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ), uno::makeAny( sal_False ) ); | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ), uno::makeAny( sal_False ) ); | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ), uno::makeAny( sal_False ) ); | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ), uno::makeAny( sal_False ) ); | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ), uno::makeAny( sal_False ) ); | 
|  | xSceneProperties->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ), uno::makeAny( sal_False ) ); | 
|  | } | 
|  | catch( uno::Exception & ex ) | 
|  | { | 
|  | ASSERT_EXCEPTION( ex ); | 
|  | } | 
|  |  | 
|  | ThreeDLookScheme aScheme = (drawing::ShadeMode_FLAT==aShadeMode) ? ThreeDLookScheme_Simple : ThreeDLookScheme_Realistic; | 
|  | lcl_setLightsForScheme( xSceneProperties, aScheme ); | 
|  | } | 
|  |  | 
|  | void ThreeDHelper::getRoundedEdgesAndObjectLines( | 
|  | const uno::Reference< XDiagram > & xDiagram | 
|  | , sal_Int32& rnRoundedEdges, sal_Int32& rnObjectLines ) | 
|  | { | 
|  | rnRoundedEdges = -1; | 
|  | rnObjectLines = -1; | 
|  | try | 
|  | { | 
|  | bool bDifferentRoundedEdges = false; | 
|  | bool bDifferentObjectLines = false; | 
|  |  | 
|  | drawing::LineStyle aLineStyle( drawing::LineStyle_SOLID ); | 
|  |  | 
|  | ::std::vector< uno::Reference< XDataSeries > > aSeriesList( | 
|  | DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); | 
|  | sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() ); | 
|  |  | 
|  | rtl::OUString aPercentDiagonalPropertyName( C2U( "PercentDiagonal" ) ); | 
|  | rtl::OUString aBorderStylePropertyName( C2U( "BorderStyle" ) ); | 
|  |  | 
|  | for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS ) | 
|  | { | 
|  | uno::Reference< XDataSeries > xSeries( aSeriesList[nS] ); | 
|  | uno::Reference< beans::XPropertySet > xProp( xSeries, uno::UNO_QUERY ); | 
|  | if(!nS) | 
|  | { | 
|  | rnRoundedEdges = 0; | 
|  | try | 
|  | { | 
|  | sal_Int16 nPercentDiagonal = 0; | 
|  |  | 
|  | xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal; | 
|  | rnRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal ); | 
|  |  | 
|  | if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries | 
|  | , aPercentDiagonalPropertyName, uno::makeAny(nPercentDiagonal) ) ) | 
|  | bDifferentRoundedEdges = true; | 
|  | } | 
|  | catch( uno::Exception& e ) | 
|  | { | 
|  | ASSERT_EXCEPTION( e ); | 
|  | bDifferentRoundedEdges = true; | 
|  | } | 
|  | try | 
|  | { | 
|  | xProp->getPropertyValue( aBorderStylePropertyName ) >>= aLineStyle; | 
|  |  | 
|  | if( DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries | 
|  | , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) ) | 
|  | bDifferentObjectLines = true; | 
|  | } | 
|  | catch( uno::Exception& e ) | 
|  | { | 
|  | ASSERT_EXCEPTION( e ); | 
|  | bDifferentObjectLines = true; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if( !bDifferentRoundedEdges ) | 
|  | { | 
|  | sal_Int16 nPercentDiagonal = 0; | 
|  | xProp->getPropertyValue( aPercentDiagonalPropertyName ) >>= nPercentDiagonal; | 
|  | sal_Int32 nCurrentRoundedEdges = static_cast< sal_Int32 >( nPercentDiagonal ); | 
|  | if(nCurrentRoundedEdges!=rnRoundedEdges | 
|  | || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries | 
|  | , aPercentDiagonalPropertyName, uno::makeAny( static_cast< sal_Int16 >(rnRoundedEdges) ) ) ) | 
|  | { | 
|  | bDifferentRoundedEdges = true; | 
|  | nCurrentRoundedEdges = -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if( !bDifferentObjectLines ) | 
|  | { | 
|  | drawing::LineStyle aCurrentLineStyle; | 
|  | xProp->getPropertyValue( aBorderStylePropertyName ) >>= aCurrentLineStyle; | 
|  | if(aCurrentLineStyle!=aLineStyle | 
|  | || DataSeriesHelper::hasAttributedDataPointDifferentValue( xSeries | 
|  | , aBorderStylePropertyName, uno::makeAny(aLineStyle) ) ) | 
|  | bDifferentObjectLines = true; | 
|  | } | 
|  | } | 
|  | if( bDifferentRoundedEdges && bDifferentObjectLines ) | 
|  | break; | 
|  | } | 
|  |  | 
|  | //set rnObjectLines | 
|  | rnObjectLines = 0; | 
|  | if( bDifferentObjectLines ) | 
|  | rnObjectLines = -1; | 
|  | else if( aLineStyle == drawing::LineStyle_SOLID ) | 
|  | rnObjectLines = 1; | 
|  | } | 
|  | catch( uno::Exception& e ) | 
|  | { | 
|  | ASSERT_EXCEPTION( e ); | 
|  | } | 
|  | } | 
|  | void ThreeDHelper::setRoundedEdgesAndObjectLines( | 
|  | const uno::Reference< XDiagram > & xDiagram | 
|  | , sal_Int32 nRoundedEdges, sal_Int32 nObjectLines ) | 
|  | { | 
|  | if( (nRoundedEdges<0||nRoundedEdges>100) && nObjectLines!=0 && nObjectLines!=1 ) | 
|  | return; | 
|  |  | 
|  | drawing::LineStyle aLineStyle( drawing::LineStyle_NONE ); | 
|  | if(nObjectLines==1) | 
|  | aLineStyle = drawing::LineStyle_SOLID; | 
|  |  | 
|  | uno::Any aALineStyle( uno::makeAny(aLineStyle)); | 
|  | uno::Any aARoundedEdges( uno::makeAny( static_cast< sal_Int16 >( nRoundedEdges ))); | 
|  |  | 
|  | ::std::vector< uno::Reference< XDataSeries > > aSeriesList( | 
|  | DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); | 
|  | sal_Int32 nSeriesCount = static_cast<sal_Int32>( aSeriesList.size() ); | 
|  | for( sal_Int32 nS = 0; nS < nSeriesCount; ++nS ) | 
|  | { | 
|  | uno::Reference< XDataSeries > xSeries( aSeriesList[nS] ); | 
|  |  | 
|  | if( nRoundedEdges>=0 && nRoundedEdges<=100 ) | 
|  | DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "PercentDiagonal" ), aARoundedEdges ); | 
|  |  | 
|  | if( nObjectLines==0 || nObjectLines==1 ) | 
|  | DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "BorderStyle" ), aALineStyle ); | 
|  | } | 
|  | } | 
|  |  | 
|  | CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | CuboidPlanePosition eRet(CuboidPlanePosition_Left); | 
|  |  | 
|  | double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; | 
|  | ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) | 
|  | { | 
|  | ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); | 
|  | fZAngleRad=0.0; | 
|  | } | 
|  | if( sin(fYAngleRad)>0.0 ) | 
|  | eRet = CuboidPlanePosition_Right; | 
|  | return eRet; | 
|  | } | 
|  |  | 
|  | CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | CuboidPlanePosition eRet(CuboidPlanePosition_Back); | 
|  |  | 
|  | double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; | 
|  | ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) | 
|  | { | 
|  | ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); | 
|  | fZAngleRad=0.0; | 
|  | } | 
|  | if( cos(fXAngleRad)*cos(fYAngleRad)<0.0 ) | 
|  | eRet = CuboidPlanePosition_Front; | 
|  | return eRet; | 
|  | } | 
|  |  | 
|  | CuboidPlanePosition ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( const Reference< beans::XPropertySet >& xSceneProperties ) | 
|  | { | 
|  | CuboidPlanePosition eRet(CuboidPlanePosition_Bottom); | 
|  |  | 
|  | double fXAngleRad=0.0; double fYAngleRad=0.0; double fZAngleRad=0.0; | 
|  | ThreeDHelper::getRotationAngleFromDiagram( xSceneProperties, fXAngleRad, fYAngleRad, fZAngleRad ); | 
|  | if( lcl_isRightAngledAxesSetAndSupported( xSceneProperties ) ) | 
|  | { | 
|  | ThreeDHelper::adaptRadAnglesForRightAngledAxes( fXAngleRad, fYAngleRad ); | 
|  | fZAngleRad=0.0; | 
|  | } | 
|  | if( sin(fXAngleRad)*cos(fYAngleRad)<0.0 ) | 
|  | eRet = CuboidPlanePosition_Top; | 
|  | return eRet; | 
|  | } | 
|  |  | 
|  | //............................................................................. | 
|  | } //namespace chart | 
|  | //............................................................................. |