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 0 : 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 0 : , m_bRightAngledAxes(false)
67 : {
68 0 : if( m_nDimensionCount == 3)
69 : {
70 0 : uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY );
71 0 : ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
72 0 : if( ChartTypeHelper::isSupportingRightAngledAxes(
73 0 : DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) )
74 : {
75 0 : if(xSourceProp.is())
76 0 : xSourceProp->getPropertyValue("RightAngledAxes") >>= m_bRightAngledAxes;
77 0 : if( m_bRightAngledAxes )
78 : {
79 0 : ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
80 0 : m_fZAnglePi=0.0;
81 : }
82 0 : }
83 : }
84 0 : }
85 :
86 0 : VDiagram::~VDiagram()
87 : {
88 0 : }
89 :
90 0 : 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 0 : m_xTarget = xTarget;
96 0 : m_xShapeFactory = xFactory;
97 0 : m_pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(xFactory);
98 0 : }
99 :
100 0 : void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
101 : {
102 0 : m_aAvailablePosIncludingAxes = rPos;
103 0 : m_aAvailableSizeIncludingAxes = rSize;
104 :
105 0 : if( m_nDimensionCount == 3 )
106 0 : createShapes_3d();
107 : else
108 0 : createShapes_2d();
109 0 : }
110 :
111 0 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
112 : {
113 0 : ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
114 0 : ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
115 0 : aNewInnerRect.intersect( aAllowedRect );
116 :
117 0 : if( m_nDimensionCount == 3 )
118 0 : aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
119 : else
120 0 : aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
121 :
122 0 : return aNewInnerRect;
123 : }
124 :
125 0 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
126 : {
127 0 : m_aCurrentPosWithoutAxes = rPos;
128 0 : m_aCurrentSizeWithoutAxes = rAvailableSize;
129 0 : if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
130 : {
131 : //do not change aspect ratio
132 0 : awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
133 0 : static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
134 : m_aCurrentSizeWithoutAxes = awt::Size( AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
135 0 : rAvailableSize, aAspectRatio ) );
136 : //center diagram position
137 : m_aCurrentPosWithoutAxes = awt::Point( AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
138 0 : rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ) );
139 :
140 : }
141 :
142 0 : if( m_xWall2D.is() )
143 : {
144 0 : m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
145 0 : m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
146 : }
147 :
148 0 : return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
149 : }
150 :
151 0 : void VDiagram::createShapes_2d()
152 : {
153 : OSL_PRECOND(m_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized");
154 0 : if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is())
155 0 : return;
156 :
157 : //create group shape
158 0 : uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xTarget);
159 0 : m_xOuterGroupShape = uno::Reference<drawing::XShape>( xOuterGroup_Shapes, uno::UNO_QUERY );
160 :
161 0 : 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 0 : uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID");
166 0 : m_xCoordinateRegionShape = uno::Reference<drawing::XShape>( xShapes, uno::UNO_QUERY );
167 : }
168 :
169 0 : bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
170 :
171 : //add back wall
172 : {
173 0 : AbstractShapeFactory* pShapeFactory = AbstractShapeFactory::getOrCreateShapeFactory(m_xShapeFactory);
174 0 : m_xWall2D = pShapeFactory->createRectangle(
175 0 : xGroupForWall );
176 :
177 0 : uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY );
178 0 : if( xProp.is())
179 : {
180 : try
181 : {
182 : OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
183 0 : if( m_xDiagram.is() )
184 : {
185 0 : uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
186 0 : if( xWallProp.is())
187 0 : PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
188 : }
189 0 : 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 0 : AbstractShapeFactory::makeShapeInvisible( m_xWall2D );
194 : }
195 : else
196 : {
197 : //CID for selection handling
198 0 : OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model
199 0 : 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 0 : }
207 :
208 : }
209 :
210 : //position and size for diagram
211 0 : adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
212 : }
213 :
214 0 : E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape )
215 : {
216 0 : E3dScene* pRet=NULL;
217 0 : uno::Reference< lang::XUnoTunnel > xUnoTunnel( xShape, uno::UNO_QUERY );
218 0 : uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY );
219 0 : if(xUnoTunnel.is()&&xTypeProvider.is())
220 : {
221 0 : SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
222 0 : if(pSvxShape)
223 : {
224 0 : SdrObject* pObj = pSvxShape->GetSdrObject();
225 0 : if( pObj && pObj->ISA(E3dScene) )
226 0 : pRet = (E3dScene*)pObj;
227 : }
228 : }
229 0 : return pRet;
230 : }
231 :
232 0 : void lcl_setLightSources(
233 : const uno::Reference< beans::XPropertySet > & xSource,
234 : const uno::Reference< beans::XPropertySet > & xDest )
235 : {
236 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1,
237 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_1));
238 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2,
239 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_2));
240 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3,
241 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_3));
242 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4,
243 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_4));
244 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5,
245 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_5));
246 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6,
247 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_6));
248 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7,
249 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_7));
250 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8,
251 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTON_8));
252 :
253 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1,
254 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1));
255 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2,
256 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2));
257 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3,
258 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3));
259 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4,
260 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4));
261 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5,
262 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5));
263 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6,
264 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6));
265 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7,
266 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7));
267 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8,
268 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8));
269 :
270 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1,
271 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_1));
272 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2,
273 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_2));
274 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3,
275 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_3));
276 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4,
277 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_4));
278 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5,
279 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_5));
280 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6,
281 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_6));
282 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7,
283 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_7));
284 0 : xDest->setPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8,
285 0 : xSource->getPropertyValue( UNO_NAME_3D_SCENE_LIGHTCOLOR_8));
286 0 : }
287 :
288 : namespace
289 : {
290 :
291 0 : void lcl_ensureScaleValue( double& rfScale )
292 : {
293 : OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
294 0 : if( rfScale<0 )
295 0 : rfScale = 1.0;
296 0 : else if( rfScale<0.2 )
297 0 : rfScale = 0.2;
298 0 : else if( rfScale>5.0 )
299 0 : rfScale = 5.0;
300 0 : }
301 :
302 : }
303 :
304 0 : void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
305 : {
306 : OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
307 0 : if( m_xAspectRatio3D.is())
308 : {
309 : try
310 : {
311 0 : double fScaleX = m_aPreferredAspectRatio.DirectionX;
312 0 : double fScaleY = m_aPreferredAspectRatio.DirectionY;
313 0 : double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
314 :
315 : //normalize scale factors
316 : {
317 0 : double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
318 0 : fScaleX/=fMax;
319 0 : fScaleY/=fMax;
320 0 : fScaleZ/=fMax;
321 : }
322 :
323 0 : if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
324 : {
325 : //calculate automatic 3D aspect ratio that fits good into the given 2D area
326 0 : double fW = rAvailableSize.Width;
327 0 : double fH = rAvailableSize.Height;
328 :
329 0 : double sx = fabs(sin(m_fXAnglePi));
330 0 : double sy = fabs(sin(m_fYAnglePi));
331 0 : double cz = fabs(cos(m_fZAnglePi));
332 0 : double sz = fabs(sin(m_fZAnglePi));
333 :
334 0 : if(m_bRightAngledAxes)
335 : {
336 : //base equations:
337 : //fH*zoomfactor == sx*fScaleZ + fScaleY;
338 : //fW*zoomfactor == sy*fScaleZ + fScaleX;
339 :
340 0 : if( fScaleX>0 && fScaleZ>0 )
341 : {
342 : //calculate fScaleY:
343 0 : if( !::basegfx::fTools::equalZero(fW) )
344 : {
345 0 : fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
346 0 : lcl_ensureScaleValue( fScaleY );
347 : }
348 : else
349 0 : fScaleY = 1.0;//looking from top or bottom the height is irrelevant
350 : }
351 0 : else if( fScaleY>0 && fScaleZ>0 )
352 : {
353 : //calculate fScaleX:
354 0 : if( !::basegfx::fTools::equalZero(fH) )
355 : {
356 0 : fScaleX = (fW/fH)*(sx*fScaleZ+fScaleY)-(sy*fScaleZ);
357 0 : 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 0 : if( fScaleX>0 && fScaleZ>0 )
382 : {
383 : //calculate fScaleY:
384 0 : double fDivide = fH*sz-fW*cz;
385 0 : if( !::basegfx::fTools::equalZero(fDivide) )
386 : {
387 0 : fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
388 0 : 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 0 : double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
424 0 : fScaleX/=fMax;
425 0 : fScaleY/=fMax;
426 0 : fScaleZ/=fMax;
427 : }
428 :
429 : // identity matrix
430 0 : ::basegfx::B3DHomMatrix aResult;
431 : aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
432 : -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
433 0 : -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
434 0 : 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 0 : 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 0 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
443 :
444 0 : m_xAspectRatio3D->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
445 0 : , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
446 : }
447 0 : catch( const uno::Exception& e )
448 : {
449 : ASSERT_EXCEPTION( e );
450 : }
451 : }
452 0 : }
453 :
454 0 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
455 : {
456 0 : adjustAspectRatio3d( rAvailableSize );
457 :
458 : //do not change aspect ratio of 3D scene with 2D bound rect
459 : m_aCurrentSizeWithoutAxes = AbstractShapeFactory::calculateNewSizeRespectingAspectRatio(
460 0 : rAvailableSize, m_xOuterGroupShape->getSize() );
461 0 : m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
462 :
463 : //center diagram position
464 : m_aCurrentPosWithoutAxes= AbstractShapeFactory::calculateTopLeftPositionToCenterObject(
465 0 : rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
466 0 : m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
467 :
468 0 : return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
469 : }
470 :
471 0 : void VDiagram::createShapes_3d()
472 : {
473 : OSL_PRECOND(m_pShapeFactory && m_xTarget.is() && m_xShapeFactory.is(), "is not proper initialized");
474 0 : if (!m_pShapeFactory || !m_xTarget.is() || !m_xShapeFactory.is())
475 0 : return;
476 :
477 : //create shape
478 0 : m_xOuterGroupShape = uno::Reference< drawing::XShape >(
479 0 : m_pShapeFactory->createGroup3D( m_xTarget, "PlotAreaExcludingAxes" ), uno::UNO_QUERY);
480 :
481 : uno::Reference< drawing::XShapes > xOuterGroup_Shapes =
482 0 : uno::Reference<drawing::XShapes>( m_xOuterGroupShape, uno::UNO_QUERY );
483 :
484 : //create additional group to manipulate the aspect ratio of the whole diagram:
485 0 : xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, OUString() );
486 :
487 0 : m_xAspectRatio3D = uno::Reference< beans::XPropertySet >( xOuterGroup_Shapes, uno::UNO_QUERY );
488 :
489 0 : bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
490 :
491 0 : const bool bDoubleSided = false;
492 0 : const bool bFlatNormals = true;
493 :
494 : //add walls
495 : {
496 0 : uno::Reference< beans::XPropertySet > xWallProp( NULL );
497 0 : if( m_xDiagram.is() )
498 0 : xWallProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getWall());
499 :
500 0 : OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, OUString() ) );//@todo read CID from model
501 0 : if( !bAddFloorAndWall )
502 0 : aWallCID = OUString();
503 0 : uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) );
504 :
505 0 : CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
506 0 : CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
507 :
508 : //add left wall
509 : {
510 0 : short nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 3 : 1;
511 0 : double xPos = 0.0;
512 0 : 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 0 : , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
517 0 : 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 0 : aStripe.InvertNormal(true);
525 :
526 : uno::Reference< drawing::XShape > xShape =
527 : m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe
528 0 : , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
529 0 : 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 0 : AbstractShapeFactory::makeShapeInvisible( xShape );
534 0 : }
535 : }
536 : //add back wall
537 : {
538 0 : short nRotatedTexture = 0;
539 0 : double zPos = 0.0;
540 0 : 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 0 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
545 0 : 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 0 : aStripe.InvertNormal(true);
553 :
554 : uno::Reference< drawing::XShape > xShape =
555 : m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe
556 0 : , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
557 0 : 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 0 : AbstractShapeFactory::makeShapeInvisible( xShape );
562 0 : }
563 0 : }
564 : }
565 :
566 : try
567 : {
568 0 : uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW );
569 0 : 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 0 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_DISTANCE, uno::makeAny(
576 0 : static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp ))));
577 0 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE,
578 0 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_PERSPECTIVE));
579 : }
580 :
581 : //light
582 : {
583 0 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE,
584 0 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_SHADE_MODE));
585 0 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR,
586 0 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_AMBIENTCOLOR));
587 0 : xDestProp->setPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING,
588 0 : xSourceProp->getPropertyValue( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING));
589 0 : 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 0 : ::basegfx::B3DHomMatrix aEffectiveTranformation;
599 0 : 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 0 : if(!m_bRightAngledAxes)
602 0 : aEffectiveTranformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
603 : else
604 0 : aEffectiveTranformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
605 :
606 : //#i98497# 3D charts are rendered with wrong size
607 0 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
608 0 : xDestProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX,
609 0 : uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTranformation ) ) );
610 0 : }
611 : }
612 0 : catch( const uno::Exception & ex )
613 : {
614 : ASSERT_EXCEPTION( ex );
615 : }
616 :
617 : //add floor plate
618 : {
619 0 : uno::Reference< beans::XPropertySet > xFloorProp( NULL );
620 0 : if( m_xDiagram.is() )
621 0 : 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 0 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
626 0 : aStripe.InvertNormal(true);
627 :
628 : uno::Reference< drawing::XShape > xShape =
629 : m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe
630 0 : , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, 0, bFlatNormals );
631 :
632 0 : CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
633 0 : 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 0 : AbstractShapeFactory::makeShapeInvisible( xShape );
638 : }
639 : else
640 : {
641 0 : OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, OUString() ) );//@todo read CID from model
642 0 : AbstractShapeFactory::setShapeName( xShape, aFloorCID );
643 0 : }
644 : }
645 :
646 : //create an additional scene for the smaller inner coordinate region:
647 : {
648 0 : uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,"testonly;CooContainer=XXX_CID" );
649 0 : m_xCoordinateRegionShape = uno::Reference< drawing::XShape >( xShapes, uno::UNO_QUERY );
650 :
651 0 : uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY );
652 : OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
653 0 : if( xShapeProp.is())
654 : {
655 : try
656 : {
657 0 : double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
658 0 : double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
659 0 : double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
660 :
661 0 : ::basegfx::B3DHomMatrix aM;
662 0 : aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
663 0 : aM.scale( fXScale, fYScale, fZScale );
664 0 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
665 0 : xShapeProp->setPropertyValue( UNO_NAME_3D_TRANSFORM_MATRIX
666 0 : , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
667 : }
668 0 : catch( const uno::Exception& e )
669 : {
670 : ASSERT_EXCEPTION( e );
671 : }
672 0 : }
673 : }
674 :
675 0 : m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
676 0 : m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
677 0 : adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
678 : }
679 :
680 0 : uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion()
681 : {
682 0 : return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY );
683 : }
684 :
685 0 : ::basegfx::B2IRectangle VDiagram::getCurrentRectangle()
686 : {
687 0 : return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
688 : }
689 :
690 0 : void VDiagram::reduceToMimimumSize()
691 : {
692 0 : if( m_xOuterGroupShape.is() )
693 : {
694 0 : awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
695 0 : awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
696 :
697 0 : sal_Int32 nNewWidth = aMaxSize.Width/3;
698 0 : sal_Int32 nNewHeight = aMaxSize.Height/3;
699 0 : awt::Size aNewSize( nNewWidth, nNewHeight );
700 0 : awt::Point aNewPos( aMaxPos );
701 0 : aNewPos.X += nNewWidth;
702 0 : aNewPos.Y += nNewHeight;
703 :
704 0 : adjustPosAndSize( aNewPos, aNewSize );
705 : }
706 0 : }
707 :
708 0 : ::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
709 : {
710 0 : awt::Point aNewPos( m_aCurrentPosWithoutAxes );
711 0 : awt::Size aNewSize( m_aCurrentSizeWithoutAxes );
712 :
713 : ::basegfx::B2IRectangle rAvailableOuterRect(
714 0 : BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
715 :
716 0 : sal_Int32 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth());
717 0 : sal_Int32 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight());
718 0 : if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 )
719 0 : nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth()/3 - aNewSize.Width);
720 0 : aNewSize.Width += nDeltaWidth;
721 :
722 0 : if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 )
723 0 : nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight()/3 - aNewSize.Height);
724 0 : aNewSize.Height += nDeltaHeight;
725 :
726 0 : sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - rAvailableOuterRect.getMinX();
727 0 : sal_Int32 nDiffRight = rAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
728 0 : if( nDiffLeft >= 0 )
729 0 : aNewPos.X -= nDiffLeft;
730 0 : else if( nDiffRight >= 0 )
731 : {
732 0 : if( nDiffRight > -nDiffLeft )
733 0 : aNewPos.X += abs(nDiffLeft);
734 0 : else if( nDiffRight > abs(nDeltaWidth) )
735 0 : aNewPos.X += nDiffRight;
736 : else
737 0 : aNewPos.X += abs(nDeltaWidth);
738 : }
739 :
740 0 : sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - rAvailableOuterRect.getMinY();
741 0 : sal_Int32 nDiffDown = rAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
742 0 : if( nDiffUp >= 0 )
743 0 : aNewPos.Y -= nDiffUp;
744 0 : else if( nDiffDown >= 0 )
745 : {
746 0 : if( nDiffDown > -nDiffUp )
747 0 : aNewPos.Y += abs(nDiffUp);
748 0 : else if( nDiffDown > abs(nDeltaHeight) )
749 0 : aNewPos.Y += nDiffDown;
750 : else
751 0 : aNewPos.Y += abs(nDeltaHeight);
752 : }
753 :
754 0 : return adjustPosAndSize( aNewPos, aNewSize );
755 : }
756 :
757 : } //namespace chart
758 :
759 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|