diff options
Diffstat (limited to 'chart2/source/view/diagram/VDiagram.cxx')
-rw-r--r-- | chart2/source/view/diagram/VDiagram.cxx | 811 |
1 files changed, 811 insertions, 0 deletions
diff --git a/chart2/source/view/diagram/VDiagram.cxx b/chart2/source/view/diagram/VDiagram.cxx new file mode 100644 index 000000000000..4174226b6f62 --- /dev/null +++ b/chart2/source/view/diagram/VDiagram.cxx @@ -0,0 +1,811 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "VDiagram.hxx" +#include "PropertyMapper.hxx" +#include "ViewDefines.hxx" +#include "Stripe.hxx" +#include "macros.hxx" +#include "ObjectIdentifier.hxx" +#include "DiagramHelper.hxx" +#include "BaseGFXHelper.hxx" +#include "CommonConverters.hxx" +#include "ChartTypeHelper.hxx" +#include "ThreeDHelper.hxx" +#include <editeng/unoprnms.hxx> +#include <tools/color.hxx> +#include <tools/debug.hxx> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include <com/sun/star/drawing/ShadeMode.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +// header for class SvxShape +#include <svx/unoshape.hxx> +// header for GetSdrObjectFromXShape +#include <svx/unoapi.hxx> +// header for class E3dScene +#include <svx/scene3d.hxx> +#include <rtl/math.hxx> +#include <svx/e3dsceneupdater.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +VDiagram::VDiagram( + const uno::Reference< XDiagram > & xDiagram + , const drawing::Direction3D& rPreferredAspectRatio + , sal_Int32 nDimension, sal_Bool bPolar ) + : m_xLogicTarget(NULL) + , m_xFinalTarget(NULL) + , m_xShapeFactory(NULL) + , m_pShapeFactory(NULL) + , m_xOuterGroupShape(NULL) + , m_xCoordinateRegionShape(NULL) + , m_xWall2D(NULL) + , m_nDimensionCount(nDimension) + , m_bPolar(bPolar) + , m_xDiagram(xDiagram) + , m_aPreferredAspectRatio(rPreferredAspectRatio) + , m_xAspectRatio3D() + , m_fXAnglePi(0) + , m_fYAnglePi(0) + , m_fZAnglePi(0) + , m_bRightAngledAxes(sal_False) +{ + if( m_nDimensionCount == 3) + { + uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY ); + ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi ); + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) ) + { + if(xSourceProp.is()) + xSourceProp->getPropertyValue(C2U( "RightAngledAxes" )) >>= m_bRightAngledAxes; + if( m_bRightAngledAxes ) + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi ); + m_fZAnglePi=0.0; + } + } + } +} + +VDiagram::~VDiagram() +{ + delete m_pShapeFactory; +} + +void SAL_CALL VDiagram::init( + const uno::Reference< drawing::XShapes >& xLogicTarget + , const uno::Reference< drawing::XShapes >& xFinalTarget + , const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + DBG_ASSERT(xLogicTarget.is()&&xFinalTarget.is()&&xFactory.is(),"no proper initialization parameters"); + + m_xLogicTarget = xLogicTarget; + m_xFinalTarget = xFinalTarget; + m_xShapeFactory = xFactory; + m_pShapeFactory = new ShapeFactory(xFactory); +} + +void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize ) +{ + m_aAvailablePosIncludingAxes = rPos; + m_aAvailableSizeIncludingAxes = rSize; + + if( m_nDimensionCount == 3 ) + createShapes_3d(); + else + createShapes_2d(); +} + +::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize ) +{ + ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) ); + ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) ); + aNewInnerRect.intersect( aAllowedRect ); + + if( m_nDimensionCount == 3 ) + aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) ); + else + aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) ); + + return aNewInnerRect; +} + +::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize ) +{ + m_aCurrentPosWithoutAxes = rPos; + m_aCurrentSizeWithoutAxes = rAvailableSize; + if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0) + { + //do not change aspect ratio + awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME), + static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME )); + m_aCurrentSizeWithoutAxes = awt::Size( ShapeFactory::calculateNewSizeRespectingAspectRatio( + rAvailableSize, aAspectRatio ) ); + //center diagram position + m_aCurrentPosWithoutAxes = awt::Point( ShapeFactory::calculateTopLeftPositionToCenterObject( + rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ) ); + + } + + if( m_xWall2D.is() ) + { + m_xWall2D->setSize( m_aCurrentSizeWithoutAxes); + m_xWall2D->setPosition(m_aCurrentPosWithoutAxes); + } + + return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) ); +} + +void VDiagram::createShapes_2d() +{ + DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized"); + if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is())) + return; + + //create group shape + uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xLogicTarget); + m_xOuterGroupShape = uno::Reference<drawing::XShape>( xOuterGroup_Shapes, uno::UNO_QUERY ); + + uno::Reference< drawing::XShapes > xGroupForWall( m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("PlotAreaExcludingAxes")) ); + + //create independent group shape as container for datapoints and such things + { + uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID")); + m_xCoordinateRegionShape = uno::Reference<drawing::XShape>( xShapes, uno::UNO_QUERY ); + } + + //--------------------------- + bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram ); + + //add back wall + { + m_xWall2D = uno::Reference< drawing::XShape >( + m_xShapeFactory->createInstance( C2U( + "com.sun.star.drawing.RectangleShape" ) ), uno::UNO_QUERY ); + //m_xWall2D->setPosition(m_aAvailablePosIncludingAxes); + //m_xWall2D->setSize(m_aAvailableSizeIncludingAxes); + xGroupForWall->add(m_xWall2D); + uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY ); + if( xProp.is()) + { + try + { + DBG_ASSERT( m_xDiagram.is(), "Invalid Diagram model" ); + if( m_xDiagram.is() ) + { + uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall()); + if( xWallProp.is()) + PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() ); + } + if( !bAddFloorAndWall ) + { + //we always need this object as dummy object for correct scene dimensions + //but it should not be visible in this case: + ShapeFactory::makeShapeInvisible( m_xWall2D ); + } + else + { + //CID for selection handling + rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model + xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ), uno::makeAny( aWallCID ) ); + } + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + } + + } + + //--------------------------- + //position and size for diagram + adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes ); +} + +E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape ) +{ + E3dScene* pRet=NULL; + uno::Reference< lang::XUnoTunnel > xUnoTunnel( xShape, uno::UNO_QUERY ); + uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY ); + if(xUnoTunnel.is()&&xTypeProvider.is()) + { + SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() )); + if(pSvxShape) + { + SdrObject* pObj = pSvxShape->GetSdrObject(); + if( pObj && pObj->ISA(E3dScene) ) + pRet = (E3dScene*)pObj; + } + } + return pRet; +} + +void lcl_setLightSources( + const uno::Reference< beans::XPropertySet > & xSource, + const uno::Reference< beans::XPropertySet > & xDest ) +{ + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ))); + + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 ))); + + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 ))); + xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 ), + xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 ))); +} + +namespace +{ + +void lcl_ensureScaleValue( double& rfScale ) +{ + DBG_ASSERT(rfScale>0, "calculation error for automatic 3D height in chart"); + if( rfScale<0 ) + rfScale = 1.0; + else if( rfScale<0.2 ) + rfScale = 0.2; + else if( rfScale>5.0 ) + rfScale = 5.0; +} + +} + +void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize ) +{ + DBG_ASSERT(m_xAspectRatio3D.is(), "created shape offers no XPropertySet"); + if( m_xAspectRatio3D.is()) + { + try + { + double fScaleX = m_aPreferredAspectRatio.DirectionX; + double fScaleY = m_aPreferredAspectRatio.DirectionY; + double fScaleZ = m_aPreferredAspectRatio.DirectionZ; + + //normalize scale factors + { + double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ ); + fScaleX/=fMax; + fScaleY/=fMax; + fScaleZ/=fMax; + } + + if( fScaleX<0 || fScaleY<0 || fScaleZ<0 ) + { + //calculate automatic 3D aspect ratio that fits good into the given 2D area + double fW = rAvailableSize.Width; + double fH = rAvailableSize.Height; + +// double cx = fabs(cos(m_fXAnglePi)); + double sx = fabs(sin(m_fXAnglePi)); +// double cy = fabs(cos(m_fYAnglePi)); + double sy = fabs(sin(m_fYAnglePi)); + double cz = fabs(cos(m_fZAnglePi)); + double sz = fabs(sin(m_fZAnglePi)); + + if(m_bRightAngledAxes) + { + //base equations: + //fH*zoomfactor == sx*fScaleZ + fScaleY; + //fW*zoomfactor == sy*fScaleZ + fScaleX; + + if( fScaleX>0 && fScaleZ>0 ) + { + //calculate fScaleY: + if( !::basegfx::fTools::equalZero(fW) ) + { + fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ); + lcl_ensureScaleValue( fScaleY ); + } + else + fScaleY = 1.0;//looking from top or bottom the height is irrelevant + } + else if( fScaleY>0 && fScaleZ>0 ) + { + //calculate fScaleX: + if( !::basegfx::fTools::equalZero(fH) ) + { + fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ); + lcl_ensureScaleValue(fScaleX); + } + else + fScaleX = 1.0;//looking from top or bottom hieght is irrelevant + } + else + { + //todo + DBG_ASSERT(false, "not implemented yet"); + + if( fScaleX<0 ) + fScaleX = 1.0; + if( fScaleY<0 ) + fScaleY = 1.0; + if( fScaleZ<0 ) + fScaleZ = 1.0; + } + } + else + { + //base equations: + //fH*zoomfactor == cz*fScaleY + sz*fScaleX; + //fW*zoomfactor == cz*fScaleX + sz*fScaleY; + //==> fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz); + if( fScaleX>0 && fScaleZ>0 ) + { + //calculate fScaleY: + double fDivide = fH*sz-fW*cz; + if( !::basegfx::fTools::equalZero(fDivide) ) + { + fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide; + lcl_ensureScaleValue(fScaleY); + } + else + fScaleY = 1.0;//looking from top or bottom the height is irrelevant + + /* + //fW*zoomfactor == fScaleX*cy*cz + fScaleY*sz*cy + fScaleZ*sy*cx; + //fH*zoomfactor == fScaleY*cx*cz + fScaleX*sz*cy + fScaleZ*sx*cz; + //==> fScaleY*(sz*cy*fH -cx*cz*fW) = fScaleX*(sz*cy*fW - cy*cz*fH) + fScaleZ*(sx*cz*fW - sy*cx*fH); + double fDivide = sz*cy*fH -cx*cz*fW; + if( !::basegfx::fTools::equalZero(fDivide) ) + { + fScaleY = ( fScaleX*(sz*cy*fW - cy*cz*fH) + + fScaleZ*(sx*cz*fW - sy*cx*fH) ) / fDivide; + lcl_ensureScaleValue(fScaleY); + } + else + fScaleY = 1.0;//looking from top or bottom hieght is irrelevant + */ + } + else if( fScaleY>0 && fScaleZ>0 ) + { + //calculate fScaleX: + double fDivide = fW*sz-fH*cz; + if( !::basegfx::fTools::equalZero(fDivide) ) + { + fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide; + lcl_ensureScaleValue(fScaleX); + } + else + fScaleX = 1.0;//looking from top or bottom hieght is irrelevant + } + else + { + //todo + DBG_ASSERT(false, "not implemented yet"); + + if( fScaleX<0 ) + fScaleX = 1.0; + if( fScaleY<0 ) + fScaleY = 1.0; + if( fScaleZ<0 ) + fScaleZ = 1.0; + } + } + } + + //normalize scale factors + { + double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ ); + fScaleX/=fMax; + fScaleY/=fMax; + fScaleZ/=fMax; + } + + // identity matrix + ::basegfx::B3DHomMatrix aResult; + aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, + -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, + -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 ); + aResult.scale( fScaleX, fScaleY, fScaleZ ); + aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, + FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, + FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 ); + + // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to + // 3D content changes here. The tooling class remembers the current 3D transformation stack + // and in it's destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry. + E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape )); + + m_xAspectRatio3D->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX ) + , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) ); + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + } +} + +::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize ) +{ + adjustAspectRatio3d( rAvailableSize ); + + //do not change aspect ratio of 3D scene with 2D bound rect + m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio( + rAvailableSize, m_xOuterGroupShape->getSize() ); + m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes ); + + //center diagram position + m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject( + rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ); + m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes); + + return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) ); +} + +void VDiagram::createShapes_3d() +{ + DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized"); + if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is())) + return; + + //create shape + m_xOuterGroupShape = uno::Reference< drawing::XShape >( + m_xShapeFactory->createInstance( C2U( + "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY ); + ShapeFactory::setShapeName( m_xOuterGroupShape, C2U("PlotAreaExcludingAxes") ); + m_xLogicTarget->add(m_xOuterGroupShape); + + uno::Reference< drawing::XShapes > xOuterGroup_Shapes = + uno::Reference<drawing::XShapes>( m_xOuterGroupShape, uno::UNO_QUERY ); + + + //------------------------------------------------------------------------- + //create additional group to manipulate the aspect ratio of the whole diagram: + xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, rtl::OUString() ); + + m_xAspectRatio3D = uno::Reference< beans::XPropertySet >( xOuterGroup_Shapes, uno::UNO_QUERY ); + + //--------------------------- + + bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram ); + + const bool bDoubleSided = false; + const bool bFlatNormals = true; + + //add walls + { + uno::Reference< beans::XPropertySet > xWallProp( NULL ); + if( m_xDiagram.is() ) + xWallProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getWall()); + + rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model + if( !bAddFloorAndWall ) + aWallCID = rtl::OUString(); + uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) ); + + CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + + //add left wall + { + short nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 3 : 1; + double xPos = 0.0; + if( CuboidPlanePosition_Right==eLeftWallPos ) + xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME; + Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) + , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) + , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) ); + if( CuboidPlanePosition_Right==eLeftWallPos ) + { + nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 2 : 0; + aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) + , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) + , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) ); + } + aStripe.InvertNormal(true); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe + , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals ); + if( !bAddFloorAndWall ) + { + //we always need this object as dummy object for correct scene dimensions + //but it should not be visible in this case: + ShapeFactory::makeShapeInvisible( xShape ); + } + } + //add back wall + { + short nRotatedTexture = 0; + double zPos = 0.0; + if( CuboidPlanePosition_Front==eBackWallPos ) + zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME; + Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos) + , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) + , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) ); + if( CuboidPlanePosition_Front==eBackWallPos ) + { + aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos) + , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) + , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) ); + nRotatedTexture = 3; + } + aStripe.InvertNormal(true); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe + , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals ); + if( !bAddFloorAndWall ) + { + //we always need this object as dummy object for correct scene dimensions + //but it should not be visible in this case: + ShapeFactory::makeShapeInvisible( xShape ); + } + } + } + + try + { + uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xDestProp( m_xOuterGroupShape, uno::UNO_QUERY_THROW ); + + //perspective + { + //ignore distance and focal length from file format and model comcpletely + //use vrp only to indicate the distance of the camera and thus influence the perspecitve + xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_DISTANCE ), uno::makeAny( + static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp )))); + xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE ), + xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE ))); + } + + //light + { + xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE ), + xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE ))); + xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ), + xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ))); + xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING ), + xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING ))); + lcl_setLightSources( xSourceProp, xDestProp ); + } + + //rotation + { + //set diagrams rotation is set exclusively vie the transformation matrix + //don't set a camera at all! + //the cameras rotation is incorporated into this matrix + + ::basegfx::B3DHomMatrix aEffectiveTranformation; + aEffectiveTranformation.translate(-FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0); + + if(!m_bRightAngledAxes) + aEffectiveTranformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi); + else + aEffectiveTranformation.shearXY(m_fYAnglePi,-m_fXAnglePi); + + //#i98497# 3D charts are rendered with wrong size + E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape )); + xDestProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX ), + uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTranformation ) ) ); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + //add floor plate + { + uno::Reference< beans::XPropertySet > xFloorProp( NULL ); + if( m_xDiagram.is() ) + xFloorProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getFloor()); + + Stripe aStripe( drawing::Position3D(0,0,0) + , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) + , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) ); + aStripe.InvertNormal(true); + + uno::Reference< drawing::XShape > xShape = + m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe + , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, 0, bFlatNormals ); + + CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); + if( !bAddFloorAndWall || (CuboidPlanePosition_Bottom!=eBottomPos) ) + { + //we always need this object as dummy object for correct scene dimensions + //but it should not be visible in this case: + ShapeFactory::makeShapeInvisible( xShape ); + } + else + { + rtl::OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) );//@todo read CID from model + ShapeFactory::setShapeName( xShape, aFloorCID ); + } + } + //--------------------------- + + //create an additional scene for the smaller inner coordinate region: + { + uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID") ); + m_xCoordinateRegionShape = uno::Reference< drawing::XShape >( xShapes, uno::UNO_QUERY ); + + uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY ); + DBG_ASSERT(xShapeProp.is(), "created shape offers no XPropertySet"); + if( xShapeProp.is()) + { + try + { + double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; + double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; + double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME; + + ::basegfx::B3DHomMatrix aM; + aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale); + aM.scale( fXScale, fYScale, fZScale ); + E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape )); + xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX ) + , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) ); + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + } + } + + m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes; + m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes; + adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes ); +} + +uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion() +{ + return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY ); +} + +::basegfx::B2IRectangle VDiagram::getCurrentRectangle() +{ + return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes); +} + +void VDiagram::reduceToMimimumSize() +{ + if( m_xOuterGroupShape.is() ) + { + awt::Size aMaxSize( m_aAvailableSizeIncludingAxes ); + awt::Point aMaxPos( m_aAvailablePosIncludingAxes ); + + sal_Int32 nNewWidth = aMaxSize.Width/3; + sal_Int32 nNewHeight = aMaxSize.Height/3; + awt::Size aNewSize( nNewWidth, nNewHeight ); + awt::Point aNewPos( aMaxPos ); + aNewPos.X += nNewWidth; + aNewPos.Y += nNewHeight; + + adjustPosAndSize( aNewPos, aNewSize ); + } +} + +::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect ) +{ + awt::Point aNewPos( m_aCurrentPosWithoutAxes ); + awt::Size aNewSize( m_aCurrentSizeWithoutAxes ); + + ::basegfx::B2IRectangle rAvailableOuterRect( + BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) ); + + sal_Int32 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth()); + sal_Int32 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight()); + if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 ) + nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth()/3 - aNewSize.Width); + aNewSize.Width += nDeltaWidth; + + if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 ) + nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight()/3 - aNewSize.Height); + aNewSize.Height += nDeltaHeight; + + sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - rAvailableOuterRect.getMinX(); + sal_Int32 nDiffRight = rAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX(); + if( nDiffLeft >= 0 ) + aNewPos.X -= nDiffLeft; + else if( nDiffRight >= 0 ) + { + if( nDiffRight > -nDiffLeft ) + aNewPos.X += abs(nDiffLeft); + else if( nDiffRight > abs(nDeltaWidth) ) + aNewPos.X += nDiffRight; + else + aNewPos.X += abs(nDeltaWidth); + } + + sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - rAvailableOuterRect.getMinY(); + sal_Int32 nDiffDown = rAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY(); + if( nDiffUp >= 0 ) + aNewPos.Y -= nDiffUp; + else if( nDiffDown >= 0 ) + { + if( nDiffDown > -nDiffUp ) + aNewPos.Y += abs(nDiffUp); + else if( nDiffDown > abs(nDeltaHeight) ) + aNewPos.Y += nDiffDown; + else + aNewPos.Y += abs(nDeltaHeight); + } + + return adjustPosAndSize( aNewPos, aNewSize ); +} + +//............................................................................. +} //namespace chart +//............................................................................. + |