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 41 : 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 41 : , m_bRightAngledAxes(sal_False)
72 : {
73 41 : if( m_nDimensionCount == 3)
74 : {
75 0 : uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY );
76 0 : ThreeDHelper::getRotationAngleFromDiagram( xSourceProp, m_fXAnglePi, m_fYAnglePi, m_fZAnglePi );
77 0 : if( ChartTypeHelper::isSupportingRightAngledAxes(
78 0 : DiagramHelper::getChartTypeByIndex( m_xDiagram, 0 ) ) )
79 : {
80 0 : if(xSourceProp.is())
81 0 : xSourceProp->getPropertyValue(C2U( "RightAngledAxes" )) >>= m_bRightAngledAxes;
82 0 : if( m_bRightAngledAxes )
83 : {
84 0 : ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fXAnglePi, m_fYAnglePi );
85 0 : m_fZAnglePi=0.0;
86 : }
87 0 : }
88 : }
89 41 : }
90 :
91 82 : VDiagram::~VDiagram()
92 : {
93 41 : delete m_pShapeFactory;
94 41 : }
95 :
96 41 : 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 41 : m_xLogicTarget = xLogicTarget;
104 41 : m_xFinalTarget = xFinalTarget;
105 41 : m_xShapeFactory = xFactory;
106 41 : m_pShapeFactory = new ShapeFactory(xFactory);
107 41 : }
108 :
109 41 : void VDiagram::createShapes( const awt::Point& rPos, const awt::Size& rSize )
110 : {
111 41 : m_aAvailablePosIncludingAxes = rPos;
112 41 : m_aAvailableSizeIncludingAxes = rSize;
113 :
114 41 : if( m_nDimensionCount == 3 )
115 0 : createShapes_3d();
116 : else
117 41 : createShapes_2d();
118 41 : }
119 :
120 123 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize( const awt::Point& rPos, const awt::Size& rSize )
121 : {
122 123 : ::basegfx::B2IRectangle aAllowedRect( BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
123 123 : ::basegfx::B2IRectangle aNewInnerRect( BaseGFXHelper::makeRectangle(rPos,rSize) );
124 123 : aNewInnerRect.intersect( aAllowedRect );
125 :
126 123 : if( m_nDimensionCount == 3 )
127 0 : aNewInnerRect = adjustPosAndSize_3d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
128 : else
129 123 : aNewInnerRect = adjustPosAndSize_2d( BaseGFXHelper::B2IRectangleToAWTPoint(aNewInnerRect), BaseGFXHelper::B2IRectangleToAWTSize(aNewInnerRect) );
130 :
131 123 : return aNewInnerRect;
132 : }
133 :
134 164 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_2d( const awt::Point& rPos, const awt::Size& rAvailableSize )
135 : {
136 164 : m_aCurrentPosWithoutAxes = rPos;
137 164 : m_aCurrentSizeWithoutAxes = rAvailableSize;
138 164 : if( m_aPreferredAspectRatio.DirectionX > 0 && m_aPreferredAspectRatio.DirectionY > 0)
139 : {
140 : //do not change aspect ratio
141 : awt::Size aAspectRatio( static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME),
142 0 : static_cast<sal_Int32>(m_aPreferredAspectRatio.DirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME ));
143 : m_aCurrentSizeWithoutAxes = awt::Size( ShapeFactory::calculateNewSizeRespectingAspectRatio(
144 0 : rAvailableSize, aAspectRatio ) );
145 : //center diagram position
146 : m_aCurrentPosWithoutAxes = awt::Point( ShapeFactory::calculateTopLeftPositionToCenterObject(
147 0 : rPos, rAvailableSize, m_aCurrentSizeWithoutAxes ) );
148 :
149 : }
150 :
151 164 : if( m_xWall2D.is() )
152 : {
153 164 : m_xWall2D->setSize( m_aCurrentSizeWithoutAxes);
154 164 : m_xWall2D->setPosition(m_aCurrentPosWithoutAxes);
155 : }
156 :
157 164 : return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
158 : }
159 :
160 41 : void VDiagram::createShapes_2d()
161 : {
162 : OSL_PRECOND(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized");
163 41 : if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is()))
164 41 : return;
165 :
166 : //create group shape
167 41 : uno::Reference< drawing::XShapes > xOuterGroup_Shapes = m_pShapeFactory->createGroup2D(m_xLogicTarget);
168 41 : m_xOuterGroupShape = uno::Reference<drawing::XShape>( xOuterGroup_Shapes, uno::UNO_QUERY );
169 :
170 41 : uno::Reference< drawing::XShapes > xGroupForWall( m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("PlotAreaExcludingAxes")) );
171 :
172 : //create independent group shape as container for datapoints and such things
173 : {
174 41 : uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup2D(xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID"));
175 41 : m_xCoordinateRegionShape = uno::Reference<drawing::XShape>( xShapes, uno::UNO_QUERY );
176 : }
177 :
178 : //---------------------------
179 41 : bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
180 :
181 : //add back wall
182 : {
183 : m_xWall2D = uno::Reference< drawing::XShape >(
184 41 : m_xShapeFactory->createInstance( C2U(
185 41 : "com.sun.star.drawing.RectangleShape" ) ), uno::UNO_QUERY );
186 :
187 41 : xGroupForWall->add(m_xWall2D);
188 41 : uno::Reference< beans::XPropertySet > xProp( m_xWall2D, uno::UNO_QUERY );
189 41 : if( xProp.is())
190 : {
191 : try
192 : {
193 : OSL_ENSURE( m_xDiagram.is(), "Invalid Diagram model" );
194 41 : if( m_xDiagram.is() )
195 : {
196 41 : uno::Reference< beans::XPropertySet > xWallProp( m_xDiagram->getWall());
197 41 : if( xWallProp.is())
198 41 : PropertyMapper::setMappedProperties( xProp, xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties() );
199 : }
200 41 : 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 0 : ShapeFactory::makeShapeInvisible( m_xWall2D );
205 : }
206 : else
207 : {
208 : //CID for selection handling
209 41 : rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
210 41 : xProp->setPropertyValue( C2U( UNO_NAME_MISC_OBJ_NAME ), uno::makeAny( aWallCID ) );
211 : }
212 : }
213 0 : catch( const uno::Exception& e )
214 : {
215 : ASSERT_EXCEPTION( e );
216 : }
217 41 : }
218 :
219 : }
220 :
221 : //---------------------------
222 : //position and size for diagram
223 41 : adjustPosAndSize_2d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
224 : }
225 :
226 0 : E3dScene* lcl_getE3dScene( const uno::Reference< drawing::XShape >& xShape )
227 : {
228 0 : E3dScene* pRet=NULL;
229 0 : uno::Reference< lang::XUnoTunnel > xUnoTunnel( xShape, uno::UNO_QUERY );
230 0 : uno::Reference< lang::XTypeProvider > xTypeProvider( xShape, uno::UNO_QUERY );
231 0 : if(xUnoTunnel.is()&&xTypeProvider.is())
232 : {
233 0 : SvxShape* pSvxShape = reinterpret_cast<SvxShape*>(xUnoTunnel->getSomething( SvxShape::getUnoTunnelId() ));
234 0 : if(pSvxShape)
235 : {
236 0 : SdrObject* pObj = pSvxShape->GetSdrObject();
237 0 : if( pObj && pObj->ISA(E3dScene) )
238 0 : pRet = (E3dScene*)pObj;
239 : }
240 : }
241 0 : return pRet;
242 : }
243 :
244 0 : void lcl_setLightSources(
245 : const uno::Reference< beans::XPropertySet > & xSource,
246 : const uno::Reference< beans::XPropertySet > & xDest )
247 : {
248 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 ),
249 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_1 )));
250 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 ),
251 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_2 )));
252 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 ),
253 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_3 )));
254 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 ),
255 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_4 )));
256 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 ),
257 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_5 )));
258 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 ),
259 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_6 )));
260 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 ),
261 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_7 )));
262 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 ),
263 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTON_8 )));
264 :
265 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 ),
266 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_1 )));
267 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 ),
268 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_2 )));
269 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 ),
270 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_3 )));
271 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 ),
272 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_4 )));
273 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 ),
274 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_5 )));
275 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 ),
276 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_6 )));
277 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 ),
278 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_7 )));
279 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 ),
280 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTDIRECTION_8 )));
281 :
282 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 ),
283 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_1 )));
284 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 ),
285 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_2 )));
286 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 ),
287 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_3 )));
288 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 ),
289 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_4 )));
290 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 ),
291 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_5 )));
292 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 ),
293 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_6 )));
294 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 ),
295 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_7 )));
296 0 : xDest->setPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 ),
297 0 : xSource->getPropertyValue( C2U( UNO_NAME_3D_SCENE_LIGHTCOLOR_8 )));
298 0 : }
299 :
300 : namespace
301 : {
302 :
303 0 : void lcl_ensureScaleValue( double& rfScale )
304 : {
305 : OSL_ENSURE(rfScale>0, "calculation error for automatic 3D height in chart");
306 0 : if( rfScale<0 )
307 0 : rfScale = 1.0;
308 0 : else if( rfScale<0.2 )
309 0 : rfScale = 0.2;
310 0 : else if( rfScale>5.0 )
311 0 : rfScale = 5.0;
312 0 : }
313 :
314 : }
315 :
316 0 : void VDiagram::adjustAspectRatio3d( const awt::Size& rAvailableSize )
317 : {
318 : OSL_PRECOND(m_xAspectRatio3D.is(), "created shape offers no XPropertySet");
319 0 : if( m_xAspectRatio3D.is())
320 : {
321 : try
322 : {
323 0 : double fScaleX = m_aPreferredAspectRatio.DirectionX;
324 0 : double fScaleY = m_aPreferredAspectRatio.DirectionY;
325 0 : double fScaleZ = m_aPreferredAspectRatio.DirectionZ;
326 :
327 : //normalize scale factors
328 : {
329 0 : double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
330 0 : fScaleX/=fMax;
331 0 : fScaleY/=fMax;
332 0 : fScaleZ/=fMax;
333 : }
334 :
335 0 : if( fScaleX<0 || fScaleY<0 || fScaleZ<0 )
336 : {
337 : //calculate automatic 3D aspect ratio that fits good into the given 2D area
338 0 : double fW = rAvailableSize.Width;
339 0 : double fH = rAvailableSize.Height;
340 :
341 0 : double sx = fabs(sin(m_fXAnglePi));
342 0 : double sy = fabs(sin(m_fYAnglePi));
343 0 : double cz = fabs(cos(m_fZAnglePi));
344 0 : double sz = fabs(sin(m_fZAnglePi));
345 :
346 0 : if(m_bRightAngledAxes)
347 : {
348 : //base equations:
349 : //fH*zoomfactor == sx*fScaleZ + fScaleY;
350 : //fW*zoomfactor == sy*fScaleZ + fScaleX;
351 :
352 0 : if( fScaleX>0 && fScaleZ>0 )
353 : {
354 : //calculate fScaleY:
355 0 : if( !::basegfx::fTools::equalZero(fW) )
356 : {
357 0 : fScaleY = (fH/fW)*(sy*fScaleZ+fScaleX)-(sx*fScaleZ);
358 0 : 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 0 : if( fScaleX>0 && fScaleZ>0 )
394 : {
395 : //calculate fScaleY:
396 0 : double fDivide = fH*sz-fW*cz;
397 0 : if( !::basegfx::fTools::equalZero(fDivide) )
398 : {
399 0 : fScaleY = fScaleX*(fW*sz-fH*cz) / fDivide;
400 0 : 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 0 : double fMax = std::max( std::max( fScaleX, fScaleY) , fScaleZ );
436 0 : fScaleX/=fMax;
437 0 : fScaleY/=fMax;
438 0 : fScaleZ/=fMax;
439 : }
440 :
441 : // identity matrix
442 0 : ::basegfx::B3DHomMatrix aResult;
443 : aResult.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
444 : -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0,
445 0 : -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 );
446 0 : 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 0 : 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 0 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
455 :
456 0 : m_xAspectRatio3D->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
457 0 : , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aResult )) );
458 : }
459 0 : catch( const uno::Exception& e )
460 : {
461 : ASSERT_EXCEPTION( e );
462 : }
463 : }
464 0 : }
465 :
466 0 : ::basegfx::B2IRectangle VDiagram::adjustPosAndSize_3d( const awt::Point& rPos, const awt::Size& rAvailableSize )
467 : {
468 0 : adjustAspectRatio3d( rAvailableSize );
469 :
470 : //do not change aspect ratio of 3D scene with 2D bound rect
471 : m_aCurrentSizeWithoutAxes = ShapeFactory::calculateNewSizeRespectingAspectRatio(
472 0 : rAvailableSize, m_xOuterGroupShape->getSize() );
473 0 : m_xOuterGroupShape->setSize( m_aCurrentSizeWithoutAxes );
474 :
475 : //center diagram position
476 : m_aCurrentPosWithoutAxes= ShapeFactory::calculateTopLeftPositionToCenterObject(
477 0 : rPos, rAvailableSize, m_aCurrentSizeWithoutAxes );
478 0 : m_xOuterGroupShape->setPosition(m_aCurrentPosWithoutAxes);
479 :
480 0 : return ::basegfx::B2IRectangle( BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes) );
481 : }
482 :
483 0 : void VDiagram::createShapes_3d()
484 : {
485 : OSL_PRECOND(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is(),"is not proper initialized");
486 0 : if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()&&m_xShapeFactory.is()))
487 0 : return;
488 :
489 : //create shape
490 : m_xOuterGroupShape = uno::Reference< drawing::XShape >(
491 0 : m_xShapeFactory->createInstance( C2U(
492 0 : "com.sun.star.drawing.Shape3DSceneObject" ) ), uno::UNO_QUERY );
493 0 : ShapeFactory::setShapeName( m_xOuterGroupShape, C2U("PlotAreaExcludingAxes") );
494 0 : m_xLogicTarget->add(m_xOuterGroupShape);
495 :
496 : uno::Reference< drawing::XShapes > xOuterGroup_Shapes =
497 0 : 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 0 : xOuterGroup_Shapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, rtl::OUString() );
503 :
504 0 : m_xAspectRatio3D = uno::Reference< beans::XPropertySet >( xOuterGroup_Shapes, uno::UNO_QUERY );
505 :
506 : //---------------------------
507 :
508 0 : bool bAddFloorAndWall = DiagramHelper::isSupportingFloorAndWall( m_xDiagram );
509 :
510 0 : const bool bDoubleSided = false;
511 0 : const bool bFlatNormals = true;
512 :
513 : //add walls
514 : {
515 0 : uno::Reference< beans::XPropertySet > xWallProp( NULL );
516 0 : if( m_xDiagram.is() )
517 0 : xWallProp=uno::Reference< beans::XPropertySet >( m_xDiagram->getWall());
518 :
519 0 : rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model
520 0 : if( !bAddFloorAndWall )
521 0 : aWallCID = rtl::OUString();
522 0 : uno::Reference< drawing::XShapes > xWallGroup_Shapes( m_pShapeFactory->createGroup3D( xOuterGroup_Shapes, aWallCID ) );
523 :
524 0 : CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
525 0 : CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
526 :
527 : //add left wall
528 : {
529 0 : short nRotatedTexture = ( CuboidPlanePosition_Front==eBackWallPos ) ? 3 : 1;
530 0 : double xPos = 0.0;
531 0 : 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 0 : , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) );
536 0 : 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 0 : aStripe.InvertNormal(true);
544 :
545 : uno::Reference< drawing::XShape > xShape =
546 : m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe
547 0 : , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
548 0 : 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 0 : }
554 : }
555 : //add back wall
556 : {
557 0 : short nRotatedTexture = 0;
558 0 : double zPos = 0.0;
559 0 : 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 0 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
564 0 : 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 0 : aStripe.InvertNormal(true);
572 :
573 : uno::Reference< drawing::XShape > xShape =
574 : m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe
575 0 : , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, nRotatedTexture, bFlatNormals );
576 0 : 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 0 : }
582 0 : }
583 : }
584 :
585 : try
586 : {
587 0 : uno::Reference< beans::XPropertySet > xSourceProp( m_xDiagram, uno::UNO_QUERY_THROW );
588 0 : 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 0 : xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_DISTANCE ), uno::makeAny(
595 0 : static_cast<sal_Int32>(ThreeDHelper::getCameraDistance( xSourceProp ))));
596 0 : xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE ),
597 0 : xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_PERSPECTIVE )));
598 : }
599 :
600 : //light
601 : {
602 0 : xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE ),
603 0 : xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_SHADE_MODE )));
604 0 : xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR ),
605 0 : xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_AMBIENTCOLOR )));
606 0 : xDestProp->setPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING ),
607 0 : xSourceProp->getPropertyValue( C2U( UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING )));
608 0 : 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 0 : ::basegfx::B3DHomMatrix aEffectiveTranformation;
618 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);
619 :
620 0 : if(!m_bRightAngledAxes)
621 0 : aEffectiveTranformation.rotate(m_fXAnglePi,m_fYAnglePi,m_fZAnglePi);
622 : else
623 0 : aEffectiveTranformation.shearXY(m_fYAnglePi,-m_fXAnglePi);
624 :
625 : //#i98497# 3D charts are rendered with wrong size
626 0 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
627 0 : xDestProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX ),
628 0 : uno::makeAny( BaseGFXHelper::B3DHomMatrixToHomogenMatrix( aEffectiveTranformation ) ) );
629 0 : }
630 : }
631 0 : catch( const uno::Exception & ex )
632 : {
633 : ASSERT_EXCEPTION( ex );
634 : }
635 :
636 : //add floor plate
637 : {
638 0 : uno::Reference< beans::XPropertySet > xFloorProp( NULL );
639 0 : if( m_xDiagram.is() )
640 0 : 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 0 : , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) );
645 0 : aStripe.InvertNormal(true);
646 :
647 : uno::Reference< drawing::XShape > xShape =
648 : m_pShapeFactory->createStripe(xOuterGroup_Shapes, aStripe
649 0 : , xFloorProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), bDoubleSided, 0, bFlatNormals );
650 :
651 0 : CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) );
652 0 : 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 0 : rtl::OUString aFloorCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) );//@todo read CID from model
661 0 : ShapeFactory::setShapeName( xShape, aFloorCID );
662 0 : }
663 : }
664 : //---------------------------
665 :
666 : //create an additional scene for the smaller inner coordinate region:
667 : {
668 0 : uno::Reference< drawing::XShapes > xShapes = m_pShapeFactory->createGroup3D( xOuterGroup_Shapes,C2U("testonly;CooContainer=XXX_CID") );
669 0 : m_xCoordinateRegionShape = uno::Reference< drawing::XShape >( xShapes, uno::UNO_QUERY );
670 :
671 0 : uno::Reference< beans::XPropertySet > xShapeProp( m_xCoordinateRegionShape, uno::UNO_QUERY );
672 : OSL_ENSURE(xShapeProp.is(), "created shape offers no XPropertySet");
673 0 : if( xShapeProp.is())
674 : {
675 : try
676 : {
677 0 : double fXScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
678 0 : double fYScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
679 0 : double fZScale = (FIXED_SIZE_FOR_3D_CHART_VOLUME -GRID_TO_WALL_DISTANCE) /FIXED_SIZE_FOR_3D_CHART_VOLUME;
680 :
681 0 : ::basegfx::B3DHomMatrix aM;
682 0 : aM.translate(GRID_TO_WALL_DISTANCE/fXScale, GRID_TO_WALL_DISTANCE/fYScale, GRID_TO_WALL_DISTANCE/fZScale);
683 0 : aM.scale( fXScale, fYScale, fZScale );
684 0 : E3DModifySceneSnapRectUpdater aUpdater(lcl_getE3dScene( m_xOuterGroupShape ));
685 0 : xShapeProp->setPropertyValue( C2U( UNO_NAME_3D_TRANSFORM_MATRIX )
686 0 : , uno::makeAny(BaseGFXHelper::B3DHomMatrixToHomogenMatrix(aM)) );
687 : }
688 0 : catch( const uno::Exception& e )
689 : {
690 : ASSERT_EXCEPTION( e );
691 : }
692 0 : }
693 : }
694 :
695 0 : m_aCurrentPosWithoutAxes = m_aAvailablePosIncludingAxes;
696 0 : m_aCurrentSizeWithoutAxes = m_aAvailableSizeIncludingAxes;
697 0 : adjustPosAndSize_3d( m_aAvailablePosIncludingAxes, m_aAvailableSizeIncludingAxes );
698 : }
699 :
700 41 : uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion()
701 : {
702 41 : return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY );
703 : }
704 :
705 205 : ::basegfx::B2IRectangle VDiagram::getCurrentRectangle()
706 : {
707 205 : return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes);
708 : }
709 :
710 41 : void VDiagram::reduceToMimimumSize()
711 : {
712 41 : if( m_xOuterGroupShape.is() )
713 : {
714 41 : awt::Size aMaxSize( m_aAvailableSizeIncludingAxes );
715 41 : awt::Point aMaxPos( m_aAvailablePosIncludingAxes );
716 :
717 41 : sal_Int32 nNewWidth = aMaxSize.Width/3;
718 41 : sal_Int32 nNewHeight = aMaxSize.Height/3;
719 41 : awt::Size aNewSize( nNewWidth, nNewHeight );
720 41 : awt::Point aNewPos( aMaxPos );
721 41 : aNewPos.X += nNewWidth;
722 41 : aNewPos.Y += nNewHeight;
723 :
724 41 : adjustPosAndSize( aNewPos, aNewSize );
725 : }
726 41 : }
727 :
728 82 : ::basegfx::B2IRectangle VDiagram::adjustInnerSize( const ::basegfx::B2IRectangle& rConsumedOuterRect )
729 : {
730 82 : awt::Point aNewPos( m_aCurrentPosWithoutAxes );
731 82 : awt::Size aNewSize( m_aCurrentSizeWithoutAxes );
732 :
733 : ::basegfx::B2IRectangle rAvailableOuterRect(
734 82 : BaseGFXHelper::makeRectangle(m_aAvailablePosIncludingAxes,m_aAvailableSizeIncludingAxes) );
735 :
736 82 : sal_Int32 nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth() - rConsumedOuterRect.getWidth());
737 82 : sal_Int32 nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight() - rConsumedOuterRect.getHeight());
738 82 : if( (aNewSize.Width + nDeltaWidth) < rAvailableOuterRect.getWidth()/3 )
739 0 : nDeltaWidth = static_cast<sal_Int32>(rAvailableOuterRect.getWidth()/3 - aNewSize.Width);
740 82 : aNewSize.Width += nDeltaWidth;
741 :
742 82 : if( (aNewSize.Height + nDeltaHeight) < rAvailableOuterRect.getHeight()/3 )
743 0 : nDeltaHeight = static_cast<sal_Int32>(rAvailableOuterRect.getHeight()/3 - aNewSize.Height);
744 82 : aNewSize.Height += nDeltaHeight;
745 :
746 82 : sal_Int32 nDiffLeft = rConsumedOuterRect.getMinX() - rAvailableOuterRect.getMinX();
747 82 : sal_Int32 nDiffRight = rAvailableOuterRect.getMaxX() - rConsumedOuterRect.getMaxX();
748 82 : if( nDiffLeft >= 0 )
749 82 : aNewPos.X -= nDiffLeft;
750 0 : else if( nDiffRight >= 0 )
751 : {
752 0 : if( nDiffRight > -nDiffLeft )
753 0 : aNewPos.X += abs(nDiffLeft);
754 0 : else if( nDiffRight > abs(nDeltaWidth) )
755 0 : aNewPos.X += nDiffRight;
756 : else
757 0 : aNewPos.X += abs(nDeltaWidth);
758 : }
759 :
760 82 : sal_Int32 nDiffUp = rConsumedOuterRect.getMinY() - rAvailableOuterRect.getMinY();
761 82 : sal_Int32 nDiffDown = rAvailableOuterRect.getMaxY() - rConsumedOuterRect.getMaxY();
762 82 : if( nDiffUp >= 0 )
763 77 : aNewPos.Y -= nDiffUp;
764 5 : else if( nDiffDown >= 0 )
765 : {
766 5 : if( nDiffDown > -nDiffUp )
767 5 : aNewPos.Y += abs(nDiffUp);
768 0 : else if( nDiffDown > abs(nDeltaHeight) )
769 0 : aNewPos.Y += nDiffDown;
770 : else
771 0 : aNewPos.Y += abs(nDeltaHeight);
772 : }
773 :
774 82 : return adjustPosAndSize( aNewPos, aNewSize );
775 : }
776 :
777 : //.............................................................................
778 : } //namespace chart
779 : //.............................................................................
780 :
781 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|