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