/************************************************************** * * 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 "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 #include #include #include #include #include #include #include #include // header for class SvxShape #include // header for class E3dScene #include #include //............................................................................. 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 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(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME), static_cast(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( 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( 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(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 height 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 height 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 height 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( 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(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( 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(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth()); sal_Int32 nDeltaHeight = static_cast(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight()); if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 ) nDeltaWidth = static_cast(rAvailableOuterRect.getWidth()/3 - aNewSize.Width); aNewSize.Width += nDeltaWidth; if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 ) nDeltaHeight = static_cast(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 //.............................................................................