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 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 98 VDiagram::~VDiagram() 99 { 100 delete m_pShapeFactory; 101 } 102 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 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 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 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 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 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 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 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 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 hieght 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 hieght 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 hieght 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 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 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 724 uno::Reference< drawing::XShapes > VDiagram::getCoordinateRegion() 725 { 726 return uno::Reference<drawing::XShapes>( m_xCoordinateRegionShape, uno::UNO_QUERY ); 727 } 728 729 ::basegfx::B2IRectangle VDiagram::getCurrentRectangle() 730 { 731 return BaseGFXHelper::makeRectangle(m_aCurrentPosWithoutAxes,m_aCurrentSizeWithoutAxes); 732 } 733 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 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