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