update dev300-m58
[ooovba.git] / chart2 / source / view / diagram / VDiagram.cxx
blob31e3408722b2d734279b3a5ff644d3cfa56dadfb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: VDiagram.cxx,v $
10 * $Revision: 1.18.60.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "VDiagram.hxx"
34 #include "PropertyMapper.hxx"
35 #include "ViewDefines.hxx"
36 #include "Stripe.hxx"
37 #include "macros.hxx"
38 #include "ObjectIdentifier.hxx"
39 #include "DiagramHelper.hxx"
40 #include "BaseGFXHelper.hxx"
41 #include "CommonConverters.hxx"
42 #include "ChartTypeHelper.hxx"
43 #include "ThreeDHelper.hxx"
44 #include <svx/unoprnms.hxx>
45 #include <tools/color.hxx>
46 #include <tools/debug.hxx>
47 #include <com/sun/star/drawing/FillStyle.hpp>
48 #include <com/sun/star/drawing/LineStyle.hpp>
49 #include <com/sun/star/drawing/ProjectionMode.hpp>
50 #include <com/sun/star/drawing/ShadeMode.hpp>
51 #include <com/sun/star/lang/XUnoTunnel.hpp>
52 #include <com/sun/star/lang/XTypeProvider.hpp>
53 // header for class SvxShape
54 #include <svx/unoshape.hxx>
55 // header for class E3dScene
56 #include <svx/scene3d.hxx>
57 #include <rtl/math.hxx>
58 #include <svx/e3dsceneupdater.hxx>
60 //.............................................................................
61 namespace chart
63 //.............................................................................
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::chart2;
67 VDiagram::VDiagram(
68 const uno::Reference< XDiagram > & xDiagram
69 , const drawing::Direction3D& rPreferredAspectRatio
70 , sal_Int32 nDimension, sal_Bool bPolar )
71 : m_xLogicTarget(NULL)
72 , m_xFinalTarget(NULL)
73 , m_xShapeFactory(NULL)
74 , m_pShapeFactory(NULL)
75 , m_xOuterGroupShape(NULL)
76 , m_xCoordinateRegionShape(NULL)
77 , m_xWall2D(NULL)
78 , m_nDimensionCount(nDimension)
79 , m_bPolar(bPolar)
80 , m_xDiagram(xDiagram)
81 , m_aPreferredAspectRatio(rPreferredAspectRatio)
82 , m_xAspectRatio3D()
83 , m_fXAnglePi(0)
84 , m_fYAnglePi(0)
85 , m_fZAnglePi(0)
86 , m_bRightAngledAxes(sal_False)
88 if( m_nDimensionCount == 3)
90 uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY );
91 ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
92 if( ChartTypeHelper::isSupportingRightAngledAxes(
93 DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) )
95 if(xSourceProp.is())
96 xSourceProp->getPropertyValue(C2U( "RightAngledAxes" )) >>= m_bRightAngledAxes;
97 if( m_bRightAngledAxes )
99 ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
100 m_fZAnglePi=0.0;
106 VDiagram::~VDiagram()
108 delete m_pShapeFactory;
111 void SAL_CALL VDiagram::init(
112 const uno::Reference< drawing::XShapes >& xLogicTarget
113 , const uno::Reference< drawing::XShapes >& xFinalTarget
114 , const uno::Reference< lang::XMultiServiceFactory >& xFactory )
116 DBG_ASSERT(xLogicTarget.is()&&xFinalTarget.is()&&xFactory.is(),"no proper initialization parameters");
118 m_xLogicTarget = xLogicTarget;
119 m_xFinalTarget = xFinalTarget;
120 m_xShapeFactory = xFactory;
121 m_pShapeFactory = new ShapeFactory(xFactory);
124 void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
126 m_aAvailablePosIncludingAxes = rPos;
127 m_aAvailableSizeIncludingAxes = rSize;
129 if( m_nDimensionCount == 3 )
130 createShapes_3d();
131 else
132 createShapes_2d();
135 ::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
137 ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
138 ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
139 aNewInnerRect.intersect( aAllowedRect );
141 if( m_nDimensionCount == 3 )
142 aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
143 else
144 aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
146 return aNewInnerRect;
149 ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
151 m_aCurrentPosWithoutAxes = rPos;
152 m_aCurrentSizeWithoutAxes = rAvailableSize;
153 if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
155 //do not change aspect ratio
156 awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
157 static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
158 m_aCurrentSizeWithoutAxes = awt::Size( ShapeFactory::calculateNewSizeRespectingAspectRatio(
159 rAvailableSize, aAspectRatio ) );
160 //center diagram position
161 m_aCurrentPosWithoutAxes = awt::Point( ShapeFactory::calculateTopLeftPositionToCenterObject(
162 rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ) );
166 if( m_xWall2D.is() )
168 m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
169 m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
172 return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
175 void VDiagram::createShapes_2d()
177 DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized");
178 if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is()))
179 return;
181 //create group shape
182 uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xLogicTarget);
183 m_xOuterGroupShape = uno::Reference<drawing::XShape>( xOuterGroup_Shapes, uno::UNO_QUERY );
185 //create independent group shape as container for datapoints and such things
187 uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID"));
188 m_xCoordinateRegionShape = uno::Reference<drawing::XShape>( xShapes, uno::UNO_QUERY );
191 //---------------------------
192 bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
194 //add back wall
196 m_xWall2D = uno::Reference< drawing::XShape >(
197 m_xShapeFactory->createInstance( C2U(
198 "com.sun.star.drawing.RectangleShape" ) ), uno::UNO_QUERY );
199 //m_xWall2D->setPosition(m_aAvailablePosIncludingAxes);
200 //m_xWall2D->setSize(m_aAvailableSizeIncludingAxes);
201 uno::Reference< drawing::XShapes > xShapes( m_xCoordinateRegionShape, uno::UNO_QUERY );
202 xShapes->add(m_xWall2D);
203 uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY );
204 if( xProp.is())
208 DBG_ASSERT( m_xDiagram.is(), "Invalid Diagram model" );
209 if( m_xDiagram.is() )
211 uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
212 if( xWallProp.is())
213 PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
215 if( !bAddFloorAndWall )
217 //we always need this object as dummy object for correct scene dimensions
218 //but it should not be visible in this case:
219 ShapeFactory::makeShapeInvisible( m_xWall2D );
221 else
223 //CID for selection handling
224 rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
225 xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ), uno::makeAny( aWallCID ) );
228 catch( uno::Exception& e )
230 ASSERT_EXCEPTION( e );
236 //---------------------------
237 //position and size for diagram
238 adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
241 E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape )
243 E3dScene* pRet=NULL;
244 uno::Reference< lang::XUnoTunnel > xUnoTunnel( xShape, uno::UNO_QUERY );
245 uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY );
246 if(xUnoTunnel.is()&&xTypeProvider.is())
248 SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
249 if(pSvxShape)
251 SdrObject* pObj = pSvxShape->GetSdrObject();
252 if( pObj && pObj->ISA(E3dScene) )
253 pRet = (E3dScene*)pObj;
256 return pRet;
259 void lcl_setLightSources(
260 const uno::Reference< beans::XPropertySet > & xSource,
261 const uno::Reference< beans::XPropertySet > & xDest )
263 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ),
264 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 )));
265 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ),
266 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 )));
267 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ),
268 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 )));
269 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ),
270 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 )));
271 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ),
272 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 )));
273 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ),
274 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 )));
275 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ),
276 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 )));
277 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ),
278 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 )));
280 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 ),
281 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 )));
282 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ),
283 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 )));
284 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 ),
285 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 )));
286 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 ),
287 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 )));
288 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 ),
289 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 )));
290 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 ),
291 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 )));
292 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 ),
293 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 )));
294 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 ),
295 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 )));
297 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 ),
298 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 )));
299 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ),
300 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 )));
301 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 ),
302 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 )));
303 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 ),
304 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 )));
305 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 ),
306 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 )));
307 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 ),
308 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 )));
309 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 ),
310 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 )));
311 xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 ),
312 xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 )));
315 namespace
318 void lcl_ensureScaleValue( double& rfScale )
320 DBG_ASSERT(rfScale>0, "calculation error for automatic 3D height in chart");
321 if( rfScale<0 )
322 rfScale = 1.0;
323 else if( rfScale<0.2 )
324 rfScale = 0.2;
325 else if( rfScale>5.0 )
326 rfScale = 5.0;
331 void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
333 DBG_ASSERT(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
334 if( m_xAspectRatio3D.is())
338 double fScaleX = m_aPreferredAspectRatio.DirectionX;
339 double fScaleY = m_aPreferredAspectRatio.DirectionY;
340 double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
342 //normalize scale factors
344 double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
345 fScaleX/=fMax;
346 fScaleY/=fMax;
347 fScaleZ/=fMax;
350 if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
352 //calculate automatic 3D aspect ratio that fits good into the given 2D area
353 double fW = rAvailableSize.Width;
354 double fH = rAvailableSize.Height;
356 // double cx = fabs(cos(m_fXAnglePi));
357 double sx = fabs(sin(m_fXAnglePi));
358 // double cy = fabs(cos(m_fYAnglePi));
359 double sy = fabs(sin(m_fYAnglePi));
360 double cz = fabs(cos(m_fZAnglePi));
361 double sz = fabs(sin(m_fZAnglePi));
363 if(m_bRightAngledAxes)
365 //base equations:
366 //fH*zoomfactor == sx*fScaleZ + fScaleY;
367 //fW*zoomfactor == sy*fScaleZ + fScaleX;
369 if( fScaleX>0 && fScaleZ>0 )
371 //calculate fScaleY:
372 if( !::basegfx::fTools::equalZero(fW) )
374 fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
375 lcl_ensureScaleValue( fScaleY );
377 else
378 fScaleY = 1.0;//looking from top or bottom the height is irrelevant
380 else if( fScaleY>0 && fScaleZ>0 )
382 //calculate fScaleX:
383 if( !::basegfx::fTools::equalZero(fH) )
385 fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
386 lcl_ensureScaleValue(fScaleX);
388 else
389 fScaleX = 1.0;//looking from top or bottom hieght is irrelevant
391 else
393 //todo
394 DBG_ASSERT(false, "not implemented yet");
396 if( fScaleX<0 )
397 fScaleX = 1.0;
398 if( fScaleY<0 )
399 fScaleY = 1.0;
400 if( fScaleZ<0 )
401 fScaleZ = 1.0;
404 else
406 //base equations:
407 //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
408 //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
409 //==> fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
410 if( fScaleX>0 && fScaleZ>0 )
412 //calculate fScaleY:
413 double fDivide = fH*sz-fW*cz;
414 if( !::basegfx::fTools::equalZero(fDivide) )
416 fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
417 lcl_ensureScaleValue(fScaleY);
419 else
420 fScaleY = 1.0;//looking from top or bottom the height is irrelevant
423 //fW*zoomfactor == fScaleX*cy*cz + fScaleY*sz*cy + fScaleZ*sy*cx;
424 //fH*zoomfactor == fScaleY*cx*cz + fScaleX*sz*cy + fScaleZ*sx*cz;
425 //==> fScaleY*(sz*cy*fH -cx*cz*fW) = fScaleX*(sz*cy*fW - cy*cz*fH) + fScaleZ*(sx*cz*fW - sy*cx*fH);
426 double fDivide = sz*cy*fH -cx*cz*fW;
427 if( !::basegfx::fTools::equalZero(fDivide) )
429 fScaleY = ( fScaleX*(sz*cy*fW - cy*cz*fH)
430 + fScaleZ*(sx*cz*fW - sy*cx*fH) ) / fDivide;
431 lcl_ensureScaleValue(fScaleY);
433 else
434 fScaleY = 1.0;//looking from top or bottom hieght is irrelevant
437 else if( fScaleY>0 && fScaleZ>0 )
439 //calculate fScaleX:
440 double fDivide = fW*sz-fH*cz;
441 if( !::basegfx::fTools::equalZero(fDivide) )
443 fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
444 lcl_ensureScaleValue(fScaleX);
446 else
447 fScaleX = 1.0;//looking from top or bottom hieght is irrelevant
449 else
451 //todo
452 DBG_ASSERT(false, "not implemented yet");
454 if( fScaleX<0 )
455 fScaleX = 1.0;
456 if( fScaleY<0 )
457 fScaleY = 1.0;
458 if( fScaleZ<0 )
459 fScaleZ = 1.0;
464 //normalize scale factors
466 double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
467 fScaleX/=fMax;
468 fScaleY/=fMax;
469 fScaleZ/=fMax;
472 // identity matrix
473 ::basegfx::B3DHomMatrix aResult;
474 aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
475 -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
476 -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
477 aResult.scale( fScaleX, fScaleY, fScaleZ );
478 aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
479 FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
480 FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
482 // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
483 // 3D content changes here. The tooling class remembers the current 3D transformation stack
484 // and in it's destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
485 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
487 m_xAspectRatio3D->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
488 , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
490 catch( uno::Exception& e )
492 ASSERT_EXCEPTION( e );
497 ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
499 adjustAspectRatio3d( rAvailableSize );
501 //do not change aspect ratio of 3D scene with 2D bound rect
502 m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
503 rAvailableSize, m_xOuterGroupShape->getSize() );
504 m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
506 //center diagram position
507 m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
508 rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
509 m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
511 return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
514 void VDiagram::createShapes_3d()
516 DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized");
517 if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is()))
518 return;
520 //create shape
521 m_xOuterGroupShape = uno::Reference< drawing::XShape >(
522 m_xShapeFactory->createInstance( C2U(
523 "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY );
524 m_xLogicTarget->add(m_xOuterGroupShape);
526 uno::Reference< drawing::XShapes > xOuterGroup_Shapes =
527 uno::Reference<drawing::XShapes>( m_xOuterGroupShape, uno::UNO_QUERY );
530 //-------------------------------------------------------------------------
531 //create additional group to manipulate the aspect ratio of the whole diagram:
532 xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, rtl::OUString() );
534 m_xAspectRatio3D = uno::Reference< beans::XPropertySet >( xOuterGroup_Shapes, uno::UNO_QUERY );
536 //---------------------------
538 bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
540 //add walls
542 uno::Reference< beans::XPropertySet > xWallProp( NULL );
543 if( m_xDiagram.is() )
544 xWallProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getWall());
546 rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
547 if( !bAddFloorAndWall )
548 aWallCID = rtl::OUString();
549 uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) );
550 //add left wall
552 double xPos = 0.0;
553 CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
554 if( CuboidPlanePosition_Right==eLeftWallPos )
555 xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
556 Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
557 , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
558 , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
560 uno::Reference< drawing::XShape > xShape =
561 m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe
562 , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), true, true );
563 if( !bAddFloorAndWall )
565 //we always need this object as dummy object for correct scene dimensions
566 //but it should not be visible in this case:
567 ShapeFactory::makeShapeInvisible( xShape );
570 //add back wall
572 double zPos = 0.0;
573 CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
574 if( CuboidPlanePosition_Front==eBackWallPos )
575 zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
576 Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
577 , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
578 , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
580 uno::Reference< drawing::XShape > xShape =
581 m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe
582 , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), true );
583 if( !bAddFloorAndWall )
585 //we always need this object as dummy object for correct scene dimensions
586 //but it should not be visible in this case:
587 ShapeFactory::makeShapeInvisible( xShape );
594 uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW );
595 uno::Reference< beans::XPropertySet > xDestProp( m_xOuterGroupShape, uno::UNO_QUERY_THROW );
597 //perspective
599 //ignore distance and focal length from file format and model comcpletely
600 //use vrp only to indicate the distance of the camera and thus influence the perspecitve
601 xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_DISTANCE ), uno::makeAny(
602 static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp ))));
603 xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE ),
604 xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE )));
607 //light
609 xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE ),
610 xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE )));
611 xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ),
612 xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR )));
613 xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING ),
614 xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING )));
615 lcl_setLightSources( xSourceProp, xDestProp );
618 //rotation
620 //set diagrams rotation is set exclusively vie the transformation matrix
621 //don't set a camera at all!
622 //the cameras rotation is incorporated into this matrix
624 ::basegfx::B3DHomMatrix aEffectiveTranformation;
625 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);
627 if(!m_bRightAngledAxes)
628 aEffectiveTranformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
629 else
630 aEffectiveTranformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
632 //#i98497# 3D charts are rendered with wrong size
633 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
634 xDestProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX ),
635 uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTranformation ) ) );
638 catch( const uno::Exception & ex )
640 ASSERT_EXCEPTION( ex );
643 //add floor plate
645 uno::Reference< beans::XPropertySet > xFloorProp( NULL );
646 if( m_xDiagram.is() )
647 xFloorProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getFloor());
649 uno::Reference< drawing::XShape > xShape(
650 m_xShapeFactory->createInstance( C2U(
651 "com.sun.star.drawing.Shape3DExtrudeObject") ), uno::UNO_QUERY );
652 xOuterGroup_Shapes->add(xShape);
653 uno::Reference< beans::XPropertySet > xShapeProp( xShape, uno::UNO_QUERY );
654 if( xShapeProp.is())
656 //depth
657 xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_EXTRUDE_DEPTH )
658 , uno::makeAny((sal_Int32)FLOOR_THICKNESS) );
659 //PercentDiagonal
660 xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_PERCENT_DIAGONAL )
661 , uno::makeAny( sal_Int32(0) ) );
663 drawing::Direction3D aSize(FIXED_SIZE_FOR_3D_CHART_VOLUME,FIXED_SIZE_FOR_3D_CHART_VOLUME,FLOOR_THICKNESS);
665 //Polygon
666 drawing::PolyPolygonShape3D aPoly;
667 AddPointToPoly( aPoly, drawing::Position3D(0,0,0) );
668 AddPointToPoly( aPoly, drawing::Position3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
669 AddPointToPoly( aPoly, drawing::Position3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
670 AddPointToPoly( aPoly, drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
671 AddPointToPoly( aPoly, drawing::Position3D(0,0,0) );
672 xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_POLYPOLYGON3D ), uno::makeAny( aPoly ) );
674 //Matrix for position
676 ::basegfx::B3DHomMatrix aM;
677 aM.rotate(F_PI/2.0,0.0,0.0);
678 aM.translate(0.0,FLOOR_THICKNESS, 0.0);
679 drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
680 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
681 xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
682 , uno::makeAny(aHM) );
685 PropertyMapper::setMappedProperties( xShapeProp, xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
688 CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
689 if( !bAddFloorAndWall || (CuboidPlanePosition_Bottom!=eBottomPos) )
691 //we always need this object as dummy object for correct scene dimensions
692 //but it should not be visible in this case:
693 ShapeFactory::makeShapeInvisible( xShape );
695 else
697 rtl::OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) );//@todo read CID from model
698 ShapeFactory::setShapeName( xShape, aFloorCID );
701 //---------------------------
703 //create an additional scene for the smaller inner coordinate region:
705 uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID") );
706 m_xCoordinateRegionShape = uno::Reference< drawing::XShape >( xShapes, uno::UNO_QUERY );
708 uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY );
709 DBG_ASSERT(xShapeProp.is(), "created shape offers no XPropertySet");
710 if( xShapeProp.is())
714 double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
715 double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -FLOOR_THICKNESS-GRID_TO_WALL_DISTANCE ) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
716 double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
718 ::basegfx::B3DHomMatrix aM;
719 aM.translate(GRID_TO_WALL_DISTANCE/fXScale, (FLOOR_THICKNESS+GRID_TO_WALL_DISTANCE)/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
720 aM.scale( fXScale, fYScale, fZScale );
721 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
722 xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
723 , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
725 catch( uno::Exception& e )
727 ASSERT_EXCEPTION( e );
732 m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
733 m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
734 adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
737 uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion()
739 return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY );
742 ::basegfx::B2IRectangle VDiagram::getCurrentRectangle()
744 return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
747 void VDiagram::reduceToMimimumSize()
749 if( m_xOuterGroupShape.is() )
751 awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
752 awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
754 sal_Int32 nNewWidth = aMaxSize.Width/3;
755 sal_Int32 nNewHeight = aMaxSize.Height/3;
756 awt::Size aNewSize( nNewWidth, nNewHeight );
757 awt::Point aNewPos( aMaxPos );
758 aNewPos.X += nNewWidth;
759 aNewPos.Y += nNewHeight;
761 adjustPosAndSize( aNewPos, aNewSize );
765 ::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
767 awt::Point aNewPos( m_aCurrentPosWithoutAxes );
768 awt::Size aNewSize( m_aCurrentSizeWithoutAxes );
770 ::basegfx::B2IRectangle rAvailableOuterRect(
771 BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
773 sal_Int32 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth());
774 sal_Int32 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight());
775 if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 )
776 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth()/3 - aNewSize.Width);
777 aNewSize.Width += nDeltaWidth;
779 if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 )
780 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight()/3 - aNewSize.Height);
781 aNewSize.Height += nDeltaHeight;
783 sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - rAvailableOuterRect.getMinX();
784 sal_Int32 nDiffRight = rAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
785 if( nDiffLeft >= 0 )
786 aNewPos.X -= nDiffLeft;
787 else if( nDiffRight >= 0 )
789 if( nDiffRight > -nDiffLeft )
790 aNewPos.X += abs(nDiffLeft);
791 else if( nDiffRight > abs(nDeltaWidth) )
792 aNewPos.X += nDiffRight;
793 else
794 aNewPos.X += abs(nDeltaWidth);
797 sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - rAvailableOuterRect.getMinY();
798 sal_Int32 nDiffDown = rAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
799 if( nDiffUp >= 0 )
800 aNewPos.Y -= nDiffUp;
801 else if( nDiffDown >= 0 )
803 if( nDiffDown > -nDiffUp )
804 aNewPos.Y += abs(nDiffUp);
805 else if( nDiffDown > abs(nDeltaHeight) )
806 aNewPos.Y += nDiffDown;
807 else
808 aNewPos.Y += abs(nDeltaHeight);
811 return adjustPosAndSize( aNewPos, aNewSize );
814 //.............................................................................
815 } //namespace chart
816 //.............................................................................