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