blob: e4917ff47fa231c02486ca9edc8bfe707bca1455 [file] [log] [blame]
/**************************************************************
*
* 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
//.............................................................................