Update git submodules
[LibreOffice.git] / chart2 / source / view / diagram / VDiagram.cxx
bloba7e1dfc997b1b8cbb1c1f3146c3a675e11411e63
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <ShapeFactory.hxx>
21 #include <VDiagram.hxx>
22 #include <Diagram.hxx>
23 #include <PropertyMapper.hxx>
24 #include <ViewDefines.hxx>
25 #include <Stripe.hxx>
26 #include <ObjectIdentifier.hxx>
27 #include <DiagramHelper.hxx>
28 #include <ChartType.hxx>
29 #include <BaseGFXHelper.hxx>
30 #include <ChartTypeHelper.hxx>
31 #include <ThreeDHelper.hxx>
32 #include <defines.hxx>
33 #include <editeng/unoprnms.hxx>
34 #include <svx/scene3d.hxx>
35 #include <svx/e3dsceneupdater.hxx>
36 #include <comphelper/diagnose_ex.hxx>
38 namespace chart
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::chart2;
43 VDiagram::VDiagram(
44 const rtl::Reference<Diagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio,
45 sal_Int32 nDimension )
46 : m_nDimensionCount(nDimension)
47 , m_xDiagram(xDiagram)
48 , m_aPreferredAspectRatio(rPreferredAspectRatio)
49 , m_fXAnglePi(0)
50 , m_fYAnglePi(0)
51 , m_fZAnglePi(0)
52 , m_bRightAngledAxes(false)
54 if( m_nDimensionCount != 3)
55 return;
57 xDiagram->getRotationAngle( m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
58 if( ChartTypeHelper::isSupportingRightAngledAxes(
59 m_xDiagram->getChartTypeByIndex( 0 ) ) )
61 if(xDiagram.is())
62 xDiagram->getPropertyValue(u"RightAngledAxes"_ustr) >>= m_bRightAngledAxes;
63 if( m_bRightAngledAxes )
65 ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
66 m_fZAnglePi=0.0;
71 VDiagram::~VDiagram()
75 void VDiagram::init( const rtl::Reference<SvxShapeGroupAnyD>& xTarget )
77 m_xTarget = xTarget;
80 void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
82 m_aAvailablePosIncludingAxes = rPos;
83 m_aAvailableSizeIncludingAxes = rSize;
85 if( m_nDimensionCount == 3 )
86 createShapes_3d();
87 else
88 createShapes_2d();
91 ::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
93 ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
94 ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
95 aNewInnerRect.intersect( aAllowedRect );
97 if( m_nDimensionCount == 3 )
98 aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
99 else
100 aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
102 return aNewInnerRect;
105 ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
107 m_aCurrentPosWithoutAxes = rPos;
108 m_aCurrentSizeWithoutAxes = rAvailableSize;
109 if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
111 //do not change aspect ratio
112 awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
113 static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
114 m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
115 rAvailableSize, aAspectRatio );
116 //center diagram position
117 m_aCurrentPosWithoutAxes = ShapeFactory::calculateTopLeftPositionToCenterObject(
118 rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
122 if( m_xWall2D.is() )
124 m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
125 m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
128 return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
131 void VDiagram::createShapes_2d()
133 OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
134 if (!m_xTarget.is())
135 return;
137 //create group shape
138 rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = ShapeFactory::createGroup2D(m_xTarget);
139 m_xOuterGroupShape = xOuterGroup_Shapes;
141 rtl::Reference<SvxShapeGroupAnyD> xGroupForWall( ShapeFactory::createGroup2D(xOuterGroup_Shapes,u"PlotAreaExcludingAxes"_ustr) );
143 //create independent group shape as container for datapoints and such things
144 m_xCoordinateRegionShape = ShapeFactory::createGroup2D(xOuterGroup_Shapes,u"testonly;CooContainer=XXX_CID"_ustr);
146 bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();
148 //add back wall
150 m_xWall2D = ShapeFactory::createRectangle( xGroupForWall );
154 OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
155 if( m_xDiagram.is() )
157 uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
158 if( xWallProp.is())
159 PropertyMapper::setMappedProperties( *m_xWall2D, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
161 if( !bAddFloorAndWall )
163 //we always need this object as dummy object for correct scene dimensions
164 //but it should not be visible in this case:
165 ShapeFactory::makeShapeInvisible( m_xWall2D );
167 else
169 //CID for selection handling
170 OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
171 m_xWall2D->SvxShape::setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::Any( aWallCID ) );
174 catch( const uno::Exception& )
176 TOOLS_WARN_EXCEPTION("chart2", "" );
180 //position and size for diagram
181 adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
184 static E3dScene* lcl_getE3dScene( const rtl::Reference<SvxShapeGroupAnyD>& xShape )
186 return DynCastE3dScene(xShape->GetSdrObject());
189 static void lcl_setLightSources(
190 const uno::Reference< beans::XPropertySet > & xSource,
191 const uno::Reference< beans::XPropertySet > & xDest )
193 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1,
194 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1));
195 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2,
196 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2));
197 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3,
198 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3));
199 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4,
200 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4));
201 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5,
202 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5));
203 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6,
204 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6));
205 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7,
206 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7));
207 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8,
208 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8));
210 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1,
211 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1));
212 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2,
213 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2));
214 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3,
215 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3));
216 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4,
217 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4));
218 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5,
219 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5));
220 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6,
221 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6));
222 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7,
223 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7));
224 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8,
225 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8));
227 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1,
228 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1));
229 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2,
230 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2));
231 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3,
232 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3));
233 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4,
234 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4));
235 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5,
236 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5));
237 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6,
238 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6));
239 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7,
240 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7));
241 xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8,
242 xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8));
245 namespace
248 void lcl_ensureScaleValue( double& rfScale )
250 OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
251 if( rfScale<0 )
252 rfScale = 1.0;
253 else if( rfScale<0.2 )
254 rfScale = 0.2;
255 else if( rfScale>5.0 )
256 rfScale = 5.0;
261 void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
263 OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
264 if( !m_xAspectRatio3D.is())
265 return;
269 double fScaleX = m_aPreferredAspectRatio.DirectionX;
270 double fScaleY = m_aPreferredAspectRatio.DirectionY;
271 double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
273 //normalize scale factors
275 double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
276 fScaleX/=fMax;
277 fScaleY/=fMax;
278 fScaleZ/=fMax;
281 if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
283 //calculate automatic 3D aspect ratio that fits good into the given 2D area
284 double fW = rAvailableSize.Width;
285 double fH = rAvailableSize.Height;
287 double sx = fabs(sin(m_fXAnglePi));
288 double sy = fabs(sin(m_fYAnglePi));
289 double cz = fabs(cos(m_fZAnglePi));
290 double sz = fabs(sin(m_fZAnglePi));
292 if(m_bRightAngledAxes)
294 //base equations:
295 //fH*zoomfactor == sx*fScaleZ + fScaleY;
296 //fW*zoomfactor == sy*fScaleZ + fScaleX;
298 if( fScaleX>0 && fScaleZ>0 )
300 //calculate fScaleY:
301 if( !::basegfx::fTools::equalZero(fW) )
303 fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
304 lcl_ensureScaleValue( fScaleY );
306 else
307 fScaleY = 1.0;//looking from top or bottom the height is irrelevant
309 else if( fScaleY>0 && fScaleZ>0 )
311 //calculate fScaleX:
312 if( !::basegfx::fTools::equalZero(fH) )
314 fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
315 lcl_ensureScaleValue(fScaleX);
317 else
318 fScaleX = 1.0;//looking from top or bottom height is irrelevant
320 else
322 //todo
323 OSL_FAIL("not implemented yet");
325 if( fScaleX<0 )
326 fScaleX = 1.0;
327 if( fScaleY<0 )
328 fScaleY = 1.0;
329 if( fScaleZ<0 )
330 fScaleZ = 1.0;
333 else
335 //base equations:
336 //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
337 //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
338 //==> fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
339 if( fScaleX>0 && fScaleZ>0 )
341 //calculate fScaleY:
342 double fDivide = fH*sz-fW*cz;
343 if( !::basegfx::fTools::equalZero(fDivide) )
345 fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
346 lcl_ensureScaleValue(fScaleY);
348 else
349 fScaleY = 1.0;//looking from top or bottom the height is irrelevant
352 else if( fScaleY>0 && fScaleZ>0 )
354 //calculate fScaleX:
355 double fDivide = fW*sz-fH*cz;
356 if( !::basegfx::fTools::equalZero(fDivide) )
358 fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
359 lcl_ensureScaleValue(fScaleX);
361 else
362 fScaleX = 1.0;//looking from top or bottom height is irrelevant
364 else
366 //todo
367 OSL_FAIL("not implemented yet");
369 if( fScaleX<0 )
370 fScaleX = 1.0;
371 if( fScaleY<0 )
372 fScaleY = 1.0;
373 if( fScaleZ<0 )
374 fScaleZ = 1.0;
379 //normalize scale factors
381 double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
382 fScaleX/=fMax;
383 fScaleY/=fMax;
384 fScaleZ/=fMax;
387 // identity matrix
388 ::basegfx::B3DHomMatrix aResult;
389 aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
390 -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
391 -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
392 aResult.scale( fScaleX, fScaleY, fScaleZ );
393 aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
394 FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
395 FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
397 // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
398 // 3D content changes here. The tooling class remembers the current 3D transformation stack
399 // and in its destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
400 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
402 m_xAspectRatio3D->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
403 , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
405 catch( const uno::Exception& )
407 TOOLS_WARN_EXCEPTION("chart2", "" );
411 ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
413 adjustAspectRatio3d( rAvailableSize );
415 //do not change aspect ratio of 3D scene with 2D bound rect
416 m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
417 rAvailableSize, m_xOuterGroupShape->getSize() );
418 m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
420 //center diagram position
421 m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
422 rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
423 m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
425 return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
428 void VDiagram::createShapes_3d()
430 OSL_PRECOND(m_xTarget.is(), "is not proper initialized");
431 if (!m_xTarget.is())
432 return;
434 //create shape
435 rtl::Reference<Svx3DSceneObject> xShapes = ShapeFactory::createGroup3D( m_xTarget, u"PlotAreaExcludingAxes"_ustr );
436 m_xOuterGroupShape = xShapes;
438 rtl::Reference<SvxShapeGroupAnyD> xOuterGroup_Shapes = m_xOuterGroupShape;
440 //create additional group to manipulate the aspect ratio of the whole diagram:
442 rtl::Reference<Svx3DSceneObject> xAdditionalGroup = ShapeFactory::createGroup3D( xOuterGroup_Shapes );
443 xOuterGroup_Shapes = xAdditionalGroup;
445 m_xAspectRatio3D = std::move(xAdditionalGroup);
448 bool bAddFloorAndWall = m_xDiagram->isSupportingFloorAndWall();
450 const bool bDoubleSided = false;
452 //add walls
454 uno::Reference< beans::XPropertySet > xWallProp;
455 if( m_xDiagram.is() )
456 xWallProp.set( m_xDiagram->getWall() );
458 OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, u"" ) );//@todo read CID from model
459 if( !bAddFloorAndWall )
460 aWallCID.clear();
461 rtl::Reference<Svx3DSceneObject> xWallGroup_Shapes = ShapeFactory::createGroup3D( xOuterGroup_Shapes, aWallCID );
463 CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( m_xDiagram ) );
464 CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( m_xDiagram ) );
466 //add left wall
468 short nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 3 : 1;
469 double xPos = 0.0;
470 if( eLeftWallPos==CuboidPlanePosition_Right )
471 xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
472 Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
473 , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
474 , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
475 if( eLeftWallPos==CuboidPlanePosition_Right )
477 nRotatedTexture = ( eBackWallPos==CuboidPlanePosition_Front ) ? 2 : 0;
478 aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
479 , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
480 , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
482 aStripe.InvertNormal(true);
484 rtl::Reference<Svx3DPolygonObject> xShape =
485 ShapeFactory::createStripe( xWallGroup_Shapes, aStripe
486 , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
487 if( !bAddFloorAndWall )
489 //we always need this object as dummy object for correct scene dimensions
490 //but it should not be visible in this case:
491 ShapeFactory::makeShapeInvisible( xShape );
494 //add back wall
496 short nRotatedTexture = 0;
497 double zPos = 0.0;
498 if( eBackWallPos==CuboidPlanePosition_Front )
499 zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
500 Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
501 , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
502 , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
503 if( eBackWallPos==CuboidPlanePosition_Front )
505 aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
506 , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
507 , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
508 nRotatedTexture = 3;
510 aStripe.InvertNormal(true);
512 rtl::Reference<Svx3DPolygonObject> xShape =
513 ShapeFactory::createStripe(xWallGroup_Shapes, aStripe
514 , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture );
515 if( !bAddFloorAndWall )
517 //we always need this object as dummy object for correct scene dimensions
518 //but it should not be visible in this case:
519 ShapeFactory::makeShapeInvisible( xShape );
526 //perspective
528 //ignore distance and focal length from file format and model completely
529 //use vrp only to indicate the distance of the camera and thus influence the perspective
530 m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::Any(
531 static_cast<sal_Int32>(m_xDiagram->getCameraDistance())));
532 m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE,
533 m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE));
536 //light
538 m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE,
539 m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE));
540 m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR,
541 m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR));
542 m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING,
543 m_xDiagram->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING));
544 lcl_setLightSources( m_xDiagram, m_xOuterGroupShape );
547 //rotation
549 //set diagrams rotation is set exclusively via the transformation matrix
550 //don't set a camera at all!
551 //the camera's rotation is incorporated into this matrix
553 ::basegfx::B3DHomMatrix aEffectiveTransformation;
554 aEffectiveTransformation.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);
556 if(!m_bRightAngledAxes)
557 aEffectiveTransformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
558 else
559 aEffectiveTransformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
561 //#i98497# 3D charts are rendered with wrong size
562 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
564 m_xOuterGroupShape->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX,
565 uno::Any( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTransformation ) ) );
568 catch( const uno::Exception & )
570 DBG_UNHANDLED_EXCEPTION("chart2" );
573 //add floor plate
575 uno::Reference< beans::XPropertySet > xFloorProp;
576 if( m_xDiagram.is() )
577 xFloorProp.set( m_xDiagram->getFloor() );
579 Stripe aStripe( drawing::Position3D(0,0,0)
580 , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
581 , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
582 aStripe.InvertNormal(true);
584 rtl::Reference<Svx3DPolygonObject> xShape =
585 ShapeFactory::createStripe(xOuterGroup_Shapes, aStripe
586 , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided );
588 CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( m_xDiagram ) );
589 if( !bAddFloorAndWall || (eBottomPos!=CuboidPlanePosition_Bottom) )
591 //we always need this object as dummy object for correct scene dimensions
592 //but it should not be visible in this case:
593 ShapeFactory::makeShapeInvisible( xShape );
595 else
597 OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, u"" ) );//@todo read CID from model
598 ShapeFactory::setShapeName( xShape, aFloorCID );
602 //create an additional scene for the smaller inner coordinate region:
604 rtl::Reference<Svx3DSceneObject> xShapes2 = ShapeFactory::createGroup3D( xOuterGroup_Shapes,u"testonly;CooContainer=XXX_CID"_ustr );
605 m_xCoordinateRegionShape = xShapes2;
609 double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
610 double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
611 double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
613 ::basegfx::B3DHomMatrix aM;
614 aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
615 aM.scale( fXScale, fYScale, fZScale );
616 E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene(m_xOuterGroupShape));
618 xShapes2->SvxShape::setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
619 , uno::Any(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
621 catch( const uno::Exception& )
623 TOOLS_WARN_EXCEPTION("chart2", "" );
627 m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
628 m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
629 adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
632 basegfx::B2IRectangle VDiagram::getCurrentRectangle() const
634 return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
637 void VDiagram::reduceToMinimumSize()
639 if( !m_xOuterGroupShape.is() )
640 return;
642 awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
643 awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
645 sal_Int32 nNewWidth = std::round(aMaxSize.Width/2.2);
646 sal_Int32 nNewHeight = std::round(aMaxSize.Height/2.2);
647 awt::Size aNewSize( nNewWidth, nNewHeight );
648 awt::Point aNewPos( aMaxPos );
649 aNewPos.X += nNewWidth;
650 aNewPos.Y += nNewHeight;
652 adjustPosAndSize( aNewPos, aNewSize );
655 ::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
657 awt::Point aNewPos = m_aCurrentPosWithoutAxes;
658 awt::Size aNewSize = m_aCurrentSizeWithoutAxes;
660 basegfx::B2IRectangle aAvailableOuterRect =
661 BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes);
663 sal_Int32 nDeltaWidth = aAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth();
664 sal_Int32 nDeltaHeight = aAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight();
665 if( (aNewSize.Width + nDeltaWidth) < aAvailableOuterRect.getWidth()/3 )
666 nDeltaWidth = aAvailableOuterRect.getWidth()/3 - aNewSize.Width;
667 aNewSize.Width += nDeltaWidth;
669 if( (aNewSize.Height + nDeltaHeight) < aAvailableOuterRect.getHeight()/3 )
670 nDeltaHeight = aAvailableOuterRect.getHeight()/3 - aNewSize.Height;
671 aNewSize.Height += nDeltaHeight;
673 sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - aAvailableOuterRect.getMinX();
674 sal_Int32 nDiffRight = aAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
675 if( nDiffLeft >= 0 )
676 aNewPos.X -= nDiffLeft;
677 else if( nDiffRight >= 0 )
679 if( nDiffRight > -nDiffLeft )
680 aNewPos.X += abs(nDiffLeft);
681 else if( nDiffRight > abs(nDeltaWidth) )
682 aNewPos.X += nDiffRight;
683 else
684 aNewPos.X += abs(nDeltaWidth);
687 sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - aAvailableOuterRect.getMinY();
688 sal_Int32 nDiffDown = aAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
689 if( nDiffUp >= 0 )
690 aNewPos.Y -= nDiffUp;
691 else if( nDiffDown >= 0 )
693 if( nDiffDown > -nDiffUp )
694 aNewPos.Y += abs(nDiffUp);
695 else if( nDiffDown > abs(nDeltaHeight) )
696 aNewPos.Y += nDiffDown;
697 else
698 aNewPos.Y += abs(nDeltaHeight);
701 return adjustPosAndSize( aNewPos, aNewSize );
704 } //namespace chart
706 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */