| /************************************************************** |
| * |
| * 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 <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 class E3dScene |
| #include <svx/scene3d.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 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 |
| //............................................................................. |
| |