Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "VDiagram.hxx"
21 : #include "PropertyMapper.hxx"
22 : #include "ViewDefines.hxx"
23 : #include "Stripe.hxx"
24 : #include "macros.hxx"
25 : #include "ObjectIdentifier.hxx"
26 : #include "DiagramHelper.hxx"
27 : #include "BaseGFXHelper.hxx"
28 : #include "CommonConverters.hxx"
29 : #include "ChartTypeHelper.hxx"
30 : #include "ThreeDHelper.hxx"
31 : #include "defines.hxx"
32 : #include <editeng/unoprnms.hxx>
33 : #include <com/sun/star/drawing/FillStyle.hpp>
34 : #include <com/sun/star/drawing/LineStyle.hpp>
35 : #include <com/sun/star/drawing/ProjectionMode.hpp>
36 : #include <com/sun/star/drawing/ShadeMode.hpp>
37 : #include <com/sun/star/lang/XUnoTunnel.hpp>
38 : #include <com/sun/star/lang/XTypeProvider.hpp>
39 : // header for class SvxShape
40 : #include <svx/unoshape.hxx>
41 : // header for class E3dScene
42 : #include <svx/scene3d.hxx>
43 : #include <svx/e3dsceneupdater.hxx>
44 :
45 : namespace chart
46 : {
47 : using namespace ::com::sun::star;
48 : using namespace ::com::sun::star::chart2;
49 :
50 617 : VDiagram::VDiagram(
51 : const uno::Reference<XDiagram> & xDiagram, const drawing::Direction3D& rPreferredAspectRatio,
52 : sal_Int32 nDimension )
53 : : m_xTarget(NULL)
54 : , m_xShapeFactory(NULL)
55 : , m_pShapeFactory(NULL)
56 : , m_xOuterGroupShape(NULL)
57 : , m_xCoordinateRegionShape(NULL)
58 : , m_xWall2D(NULL)
59 : , m_nDimensionCount(nDimension)
60 : , m_xDiagram(xDiagram)
61 : , m_aPreferredAspectRatio(rPreferredAspectRatio)
62 : , m_xAspectRatio3D()
63 : , m_fXAnglePi(0)
64 : , m_fYAnglePi(0)
65 : , m_fZAnglePi(0)
66 617 : , m_bRightAngledAxes(false)
67 : {
68 617 : if( m_nDimensionCount == 3)
69 : {
70 12 : uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY );
71 12 : ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
72 24 : if( ChartTypeHelper::isSupportingRightAngledAxes(
73 24 : DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) )
74 : {
75 11 : if(xSourceProp.is())
76 11 : xSourceProp->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes;
77 11 : if( m_bRightAngledAxes )
78 : {
79 10 : ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
80 10 : m_fZAnglePi=0.0;
81 : }
82 12 : }
83 : }
84 617 : }
85 :
86 617 : VDiagram::~VDiagram()
87 : {
88 617 : }
89 :
90 617 : void VDiagram::init(
91 : const uno::Reference< drawing::XShapes >& xTarget, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
92 : {
93 : OSL_PRECOND(xFactory.is(), "no proper initialization parameters");
94 :
95 617 : m_xTarget = xTarget;
96 617 : m_xShapeFactory = xFactory;
97 617 : m_pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(xFactory);
98 617 : }
99 :
100 617 : void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
101 : {
102 617 : m_aAvailablePosIncludingAxes = rPos;
103 617 : m_aAvailableSizeIncludingAxes = rSize;
104 :
105 617 : if( m_nDimensionCount == 3 )
106 12 : createShapes_3d();
107 : else
108 605 : createShapes_2d();
109 617 : }
110 :
111 1821 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
112 : {
113 1821 : ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
114 1821 : ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
115 1821 : aNewInnerRect.intersect( aAllowedRect );
116 :
117 1821 : if( m_nDimensionCount == 3 )
118 34 : aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
119 : else
120 1787 : aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
121 :
122 1821 : return aNewInnerRect;
123 : }
124 :
125 2392 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
126 : {
127 2392 : m_aCurrentPosWithoutAxes = rPos;
128 2392 : m_aCurrentSizeWithoutAxes = rAvailableSize;
129 2392 : if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
130 : {
131 : //do not change aspect ratio
132 28 : awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
133 56 : static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
134 : m_aCurrentSizeWithoutAxes = awt::Size( AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
135 28 : rAvailableSize, aAspectRatio ) );
136 : //center diagram position
137 : m_aCurrentPosWithoutAxes = awt::Point( AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
138 28 : rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ) );
139 :
140 : }
141 :
142 2392 : if( m_xWall2D.is() )
143 : {
144 2392 : m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
145 2392 : m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
146 : }
147 :
148 2392 : return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
149 : }
150 :
151 605 : void VDiagram::createShapes_2d()
152 : {
153 : OSL_PRECOND(m_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized");
154 605 : if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is())
155 605 : return;
156 :
157 : //create group shape
158 605 : uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xTarget);
159 605 : m_xOuterGroupShape = uno::Reference<drawing::XShape>( xOuterGroup_Shapes, uno::UNO_QUERY );
160 :
161 1210 : uno::Reference< drawing::XShapes > xGroupForWall( m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"PlotAreaExcludingAxes") );
162 :
163 : //create independent group shape as container for datapoints and such things
164 : {
165 605 : uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID");
166 605 : m_xCoordinateRegionShape = uno::Reference<drawing::XShape>( xShapes, uno::UNO_QUERY );
167 : }
168 :
169 605 : bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
170 :
171 : //add back wall
172 : {
173 605 : AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory);
174 1210 : m_xWall2D = pShapeFactory->createRectangle(
175 1210 : xGroupForWall );
176 :
177 605 : uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY );
178 605 : if( xProp.is())
179 : {
180 : try
181 : {
182 : OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
183 605 : if( m_xDiagram.is() )
184 : {
185 605 : uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
186 605 : if( xWallProp.is())
187 605 : PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
188 : }
189 605 : if( !bAddFloorAndWall )
190 : {
191 : //we always need this object as dummy object for correct scene dimensions
192 : //but it should not be visible in this case:
193 14 : AbstractShapeFactory::makeShapeInvisible( m_xWall2D );
194 : }
195 : else
196 : {
197 : //CID for selection handling
198 591 : OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model
199 591 : xProp->setPropertyValue( UNO_NAME_MISC_OBJ_NAME, uno::makeAny( aWallCID ) );
200 : }
201 : }
202 0 : catch( const uno::Exception& e )
203 : {
204 : ASSERT_EXCEPTION( e );
205 : }
206 605 : }
207 :
208 : }
209 :
210 : //position and size for diagram
211 1210 : adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
212 : }
213 :
214 70 : E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape )
215 : {
216 70 : E3dScene* pRet=NULL;
217 70 : uno::Reference< lang::XUnoTunnel > xUnoTunnel( xShape, uno::UNO_QUERY );
218 140 : uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY );
219 70 : if(xUnoTunnel.is()&&xTypeProvider.is())
220 : {
221 70 : SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
222 70 : if(pSvxShape)
223 : {
224 70 : SdrObject* pObj = pSvxShape->GetSdrObject();
225 70 : if( pObj && pObj->ISA(E3dScene) )
226 70 : pRet = (E3dScene*)pObj;
227 : }
228 : }
229 140 : return pRet;
230 : }
231 :
232 12 : void lcl_setLightSources(
233 : const uno::Reference< beans::XPropertySet > & xSource,
234 : const uno::Reference< beans::XPropertySet > & xDest )
235 : {
236 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1,
237 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1));
238 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2,
239 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2));
240 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3,
241 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3));
242 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4,
243 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4));
244 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5,
245 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5));
246 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6,
247 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6));
248 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7,
249 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7));
250 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8,
251 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8));
252 :
253 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1,
254 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1));
255 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2,
256 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2));
257 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3,
258 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3));
259 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4,
260 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4));
261 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5,
262 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5));
263 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6,
264 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6));
265 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7,
266 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7));
267 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8,
268 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8));
269 :
270 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1,
271 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1));
272 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2,
273 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2));
274 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3,
275 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3));
276 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4,
277 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4));
278 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5,
279 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5));
280 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6,
281 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6));
282 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7,
283 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7));
284 12 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8,
285 12 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8));
286 12 : }
287 :
288 : namespace
289 : {
290 :
291 44 : void lcl_ensureScaleValue( double& rfScale )
292 : {
293 : OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
294 44 : if( rfScale<0 )
295 0 : rfScale = 1.0;
296 44 : else if( rfScale<0.2 )
297 0 : rfScale = 0.2;
298 44 : else if( rfScale>5.0 )
299 0 : rfScale = 5.0;
300 44 : }
301 :
302 : }
303 :
304 46 : void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
305 : {
306 : OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
307 46 : if( m_xAspectRatio3D.is())
308 : {
309 : try
310 : {
311 46 : double fScaleX = m_aPreferredAspectRatio.DirectionX;
312 46 : double fScaleY = m_aPreferredAspectRatio.DirectionY;
313 46 : double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
314 :
315 : //normalize scale factors
316 : {
317 46 : double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
318 46 : fScaleX/=fMax;
319 46 : fScaleY/=fMax;
320 46 : fScaleZ/=fMax;
321 : }
322 :
323 46 : if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
324 : {
325 : //calculate automatic 3D aspect ratio that fits good into the given 2D area
326 44 : double fW = rAvailableSize.Width;
327 44 : double fH = rAvailableSize.Height;
328 :
329 44 : double sx = fabs(sin(m_fXAnglePi));
330 44 : double sy = fabs(sin(m_fYAnglePi));
331 44 : double cz = fabs(cos(m_fZAnglePi));
332 44 : double sz = fabs(sin(m_fZAnglePi));
333 :
334 44 : if(m_bRightAngledAxes)
335 : {
336 : //base equations:
337 : //fH*zoomfactor == sx*fScaleZ + fScaleY;
338 : //fW*zoomfactor == sy*fScaleZ + fScaleX;
339 :
340 40 : if( fScaleX>0 && fScaleZ>0 )
341 : {
342 : //calculate fScaleY:
343 64 : if( !::basegfx::fTools::equalZero(fW) )
344 : {
345 32 : fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
346 32 : lcl_ensureScaleValue( fScaleY );
347 : }
348 : else
349 0 : fScaleY = 1.0;//looking from top or bottom the height is irrelevant
350 : }
351 8 : else if( fScaleY>0 && fScaleZ>0 )
352 : {
353 : //calculate fScaleX:
354 16 : if( !::basegfx::fTools::equalZero(fH) )
355 : {
356 8 : fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
357 8 : lcl_ensureScaleValue(fScaleX);
358 : }
359 : else
360 0 : fScaleX = 1.0;//looking from top or bottom hieght is irrelevant
361 : }
362 : else
363 : {
364 : //todo
365 : OSL_FAIL("not implemented yet");
366 :
367 0 : if( fScaleX<0 )
368 0 : fScaleX = 1.0;
369 0 : if( fScaleY<0 )
370 0 : fScaleY = 1.0;
371 0 : if( fScaleZ<0 )
372 0 : fScaleZ = 1.0;
373 : }
374 : }
375 : else
376 : {
377 : //base equations:
378 : //fH*zoomfactor == cz*fScaleY + sz*fScaleX;
379 : //fW*zoomfactor == cz*fScaleX + sz*fScaleY;
380 : //==> fScaleY*(fH*sz-fW*cz) == fScaleX*(fW*sz-fH*cz);
381 4 : if( fScaleX>0 && fScaleZ>0 )
382 : {
383 : //calculate fScaleY:
384 4 : double fDivide = fH*sz-fW*cz;
385 4 : if( !::basegfx::fTools::equalZero(fDivide) )
386 : {
387 4 : fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
388 4 : lcl_ensureScaleValue(fScaleY);
389 : }
390 : else
391 0 : fScaleY = 1.0;//looking from top or bottom the height is irrelevant
392 :
393 : }
394 0 : else if( fScaleY>0 && fScaleZ>0 )
395 : {
396 : //calculate fScaleX:
397 0 : double fDivide = fW*sz-fH*cz;
398 0 : if( !::basegfx::fTools::equalZero(fDivide) )
399 : {
400 0 : fScaleX = fScaleY*(fH*sz-fW*cz) / fDivide;
401 0 : lcl_ensureScaleValue(fScaleX);
402 : }
403 : else
404 0 : fScaleX = 1.0;//looking from top or bottom hieght is irrelevant
405 : }
406 : else
407 : {
408 : //todo
409 : OSL_FAIL("not implemented yet");
410 :
411 0 : if( fScaleX<0 )
412 0 : fScaleX = 1.0;
413 0 : if( fScaleY<0 )
414 0 : fScaleY = 1.0;
415 0 : if( fScaleZ<0 )
416 0 : fScaleZ = 1.0;
417 : }
418 : }
419 : }
420 :
421 : //normalize scale factors
422 : {
423 46 : double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
424 46 : fScaleX/=fMax;
425 46 : fScaleY/=fMax;
426 46 : fScaleZ/=fMax;
427 : }
428 :
429 : // identity matrix
430 46 : ::basegfx::B3DHomMatrix aResult;
431 : aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
432 : -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
433 46 : -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
434 46 : aResult.scale( fScaleX, fScaleY, fScaleZ );
435 : aResult.translate( FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
436 : FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
437 46 : FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
438 :
439 : // To get the 3D aspect ratio's effect on the 2D scene size, the scene's 2D size needs to be adapted to
440 : // 3D content changes here. The tooling class remembers the current 3D transformation stack
441 : // and in its destructor, calculates a new 2D SnapRect for the scene and it's modified 3D geometry.
442 92 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
443 :
444 46 : m_xAspectRatio3D->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
445 92 : , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
446 : }
447 0 : catch( const uno::Exception& e )
448 : {
449 : ASSERT_EXCEPTION( e );
450 : }
451 : }
452 46 : }
453 :
454 46 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
455 : {
456 46 : adjustAspectRatio3d( rAvailableSize );
457 :
458 : //do not change aspect ratio of 3D scene with 2D bound rect
459 : m_aCurrentSizeWithoutAxes = AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
460 46 : rAvailableSize, m_xOuterGroupShape->getSize() );
461 46 : m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
462 :
463 : //center diagram position
464 : m_aCurrentPosWithoutAxes= AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
465 46 : rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
466 46 : m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
467 :
468 46 : return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
469 : }
470 :
471 12 : void VDiagram::createShapes_3d()
472 : {
473 : OSL_PRECOND(m_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized");
474 12 : if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is())
475 12 : return;
476 :
477 : //create shape
478 36 : m_xOuterGroupShape = uno::Reference< drawing::XShape >(
479 24 : m_pShapeFactory->createGroup3D( m_xTarget, "PlotAreaExcludingAxes" ), uno::UNO_QUERY);
480 :
481 : uno::Reference< drawing::XShapes > xOuterGroup_Shapes =
482 12 : uno::Reference<drawing::XShapes>( m_xOuterGroupShape, uno::UNO_QUERY );
483 :
484 : //create additional group to manipulate the aspect ratio of the whole diagram:
485 12 : xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, OUString() );
486 :
487 12 : m_xAspectRatio3D = uno::Reference< beans::XPropertySet >( xOuterGroup_Shapes, uno::UNO_QUERY );
488 :
489 12 : bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
490 :
491 12 : const bool bDoubleSided = false;
492 12 : const bool bFlatNormals = true;
493 :
494 : //add walls
495 : {
496 12 : uno::Reference< beans::XPropertySet > xWallProp( NULL );
497 12 : if( m_xDiagram.is() )
498 12 : xWallProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getWall());
499 :
500 24 : OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model
501 12 : if( !bAddFloorAndWall )
502 1 : aWallCID = OUString();
503 24 : uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) );
504 :
505 12 : CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
506 12 : CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
507 :
508 : //add left wall
509 : {
510 12 : short nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 3 : 1;
511 12 : double xPos = 0.0;
512 12 : if( CuboidPlanePosition_Right==eLeftWallPos )
513 0 : xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
514 : Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
515 : , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
516 12 : , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
517 12 : if( CuboidPlanePosition_Right==eLeftWallPos )
518 : {
519 0 : nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 2 : 0;
520 : aStripe = Stripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
521 : , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
522 0 : , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) );
523 : }
524 12 : aStripe.InvertNormal(true);
525 :
526 : uno::Reference< drawing::XShape > xShape =
527 : m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe
528 12 : , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
529 12 : if( !bAddFloorAndWall )
530 : {
531 : //we always need this object as dummy object for correct scene dimensions
532 : //but it should not be visible in this case:
533 1 : AbstractShapeFactory::makeShapeInvisible( xShape );
534 12 : }
535 : }
536 : //add back wall
537 : {
538 12 : short nRotatedTexture = 0;
539 12 : double zPos = 0.0;
540 12 : if( CuboidPlanePosition_Front==eBackWallPos )
541 0 : zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME;
542 : Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
543 : , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0)
544 12 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
545 12 : if( CuboidPlanePosition_Front==eBackWallPos )
546 : {
547 : aStripe = Stripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos)
548 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0)
549 0 : , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
550 0 : nRotatedTexture = 3;
551 : }
552 12 : aStripe.InvertNormal(true);
553 :
554 : uno::Reference< drawing::XShape > xShape =
555 : m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe
556 12 : , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
557 12 : if( !bAddFloorAndWall )
558 : {
559 : //we always need this object as dummy object for correct scene dimensions
560 : //but it should not be visible in this case:
561 1 : AbstractShapeFactory::makeShapeInvisible( xShape );
562 12 : }
563 12 : }
564 : }
565 :
566 : try
567 : {
568 12 : uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW );
569 24 : uno::Reference< beans::XPropertySet > xDestProp( m_xOuterGroupShape, uno::UNO_QUERY_THROW );
570 :
571 : //perspective
572 : {
573 : //ignore distance and focal length from file format and model completely
574 : //use vrp only to indicate the distance of the camera and thus influence the perspective
575 12 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::makeAny(
576 12 : static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp ))));
577 12 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE,
578 12 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE));
579 : }
580 :
581 : //light
582 : {
583 12 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE,
584 12 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE));
585 12 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR,
586 12 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR));
587 12 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING,
588 12 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING));
589 12 : lcl_setLightSources( xSourceProp, xDestProp );
590 : }
591 :
592 : //rotation
593 : {
594 : //set diagrams rotation is set exclusively via the transformation matrix
595 : //don't set a camera at all!
596 : //the camera's rotation is incorporated into this matrix
597 :
598 12 : ::basegfx::B3DHomMatrix aEffectiveTranformation;
599 12 : 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);
600 :
601 12 : if(!m_bRightAngledAxes)
602 2 : aEffectiveTranformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
603 : else
604 10 : aEffectiveTranformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
605 :
606 : //#i98497# 3D charts are rendered with wrong size
607 24 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
608 12 : xDestProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX,
609 24 : uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTranformation ) ) );
610 12 : }
611 : }
612 0 : catch( const uno::Exception & ex )
613 : {
614 : ASSERT_EXCEPTION( ex );
615 : }
616 :
617 : //add floor plate
618 : {
619 12 : uno::Reference< beans::XPropertySet > xFloorProp( NULL );
620 12 : if( m_xDiagram.is() )
621 12 : xFloorProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getFloor());
622 :
623 : Stripe aStripe( drawing::Position3D(0,0,0)
624 : , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME)
625 12 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
626 12 : aStripe.InvertNormal(true);
627 :
628 : uno::Reference< drawing::XShape > xShape =
629 : m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe
630 24 : , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, 0, bFlatNormals );
631 :
632 12 : CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
633 12 : if( !bAddFloorAndWall || (CuboidPlanePosition_Bottom!=eBottomPos) )
634 : {
635 : //we always need this object as dummy object for correct scene dimensions
636 : //but it should not be visible in this case:
637 1 : AbstractShapeFactory::makeShapeInvisible( xShape );
638 : }
639 : else
640 : {
641 11 : OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) );//@todo read CID from model
642 11 : AbstractShapeFactory::setShapeName( xShape, aFloorCID );
643 12 : }
644 : }
645 :
646 : //create an additional scene for the smaller inner coordinate region:
647 : {
648 12 : uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID" );
649 12 : m_xCoordinateRegionShape = uno::Reference< drawing::XShape >( xShapes, uno::UNO_QUERY );
650 :
651 24 : uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY );
652 : OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
653 12 : if( xShapeProp.is())
654 : {
655 : try
656 : {
657 12 : double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
658 12 : double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
659 12 : double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
660 :
661 12 : ::basegfx::B3DHomMatrix aM;
662 12 : aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
663 12 : aM.scale( fXScale, fYScale, fZScale );
664 24 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
665 12 : xShapeProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
666 24 : , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
667 : }
668 0 : catch( const uno::Exception& e )
669 : {
670 : ASSERT_EXCEPTION( e );
671 : }
672 12 : }
673 : }
674 :
675 12 : m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
676 12 : m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
677 12 : adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
678 : }
679 :
680 617 : uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion()
681 : {
682 617 : return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY );
683 : }
684 :
685 3070 : ::basegfx::B2IRectangle VDiagram::getCurrentRectangle()
686 : {
687 3070 : return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
688 : }
689 :
690 602 : void VDiagram::reduceToMimimumSize()
691 : {
692 602 : if( m_xOuterGroupShape.is() )
693 : {
694 602 : awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
695 602 : awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
696 :
697 602 : sal_Int32 nNewWidth = aMaxSize.Width/3;
698 602 : sal_Int32 nNewHeight = aMaxSize.Height/3;
699 602 : awt::Size aNewSize( nNewWidth, nNewHeight );
700 602 : awt::Point aNewPos( aMaxPos );
701 602 : aNewPos.X += nNewWidth;
702 602 : aNewPos.Y += nNewHeight;
703 :
704 602 : adjustPosAndSize( aNewPos, aNewSize );
705 : }
706 602 : }
707 :
708 1219 : ::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
709 : {
710 1219 : awt::Point aNewPos( m_aCurrentPosWithoutAxes );
711 1219 : awt::Size aNewSize( m_aCurrentSizeWithoutAxes );
712 :
713 : ::basegfx::B2IRectangle rAvailableOuterRect(
714 1219 : BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
715 :
716 1219 : sal_Int32 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth());
717 1219 : sal_Int32 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight());
718 1219 : if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 )
719 0 : nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth()/3 - aNewSize.Width);
720 1219 : aNewSize.Width += nDeltaWidth;
721 :
722 1219 : if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 )
723 39 : nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight()/3 - aNewSize.Height);
724 1219 : aNewSize.Height += nDeltaHeight;
725 :
726 1219 : sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - rAvailableOuterRect.getMinX();
727 1219 : sal_Int32 nDiffRight = rAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
728 1219 : if( nDiffLeft >= 0 )
729 1207 : aNewPos.X -= nDiffLeft;
730 12 : else if( nDiffRight >= 0 )
731 : {
732 12 : if( nDiffRight > -nDiffLeft )
733 3 : aNewPos.X += abs(nDiffLeft);
734 9 : else if( nDiffRight > abs(nDeltaWidth) )
735 0 : aNewPos.X += nDiffRight;
736 : else
737 9 : aNewPos.X += abs(nDeltaWidth);
738 : }
739 :
740 1219 : sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - rAvailableOuterRect.getMinY();
741 1219 : sal_Int32 nDiffDown = rAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
742 1219 : if( nDiffUp >= 0 )
743 1126 : aNewPos.Y -= nDiffUp;
744 93 : else if( nDiffDown >= 0 )
745 : {
746 76 : if( nDiffDown > -nDiffUp )
747 9 : aNewPos.Y += abs(nDiffUp);
748 67 : else if( nDiffDown > abs(nDeltaHeight) )
749 8 : aNewPos.Y += nDiffDown;
750 : else
751 59 : aNewPos.Y += abs(nDeltaHeight);
752 : }
753 :
754 1219 : return adjustPosAndSize( aNewPos, aNewSize );
755 : }
756 :
757 : } //namespace chart
758 :
759 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|