Back to index

salome-gui  6.5.0
VTKViewer_Utilities.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include "VTKViewer_Utilities.h"
00024 #include "VTKViewer_Actor.h"
00025 #include "VTKViewer_Algorithm.h"
00026 
00027 #include <algorithm>
00028 
00029 // VTK Includes
00030 #include <vtkMath.h>
00031 #include <vtkCamera.h>
00032 #include <vtkRenderer.h>
00033 #include <vtkRenderWindow.h>
00034 
00036 void 
00037 ResetCamera(vtkRenderer* theRenderer, 
00038             int theUsingZeroFocalPoint)
00039 {  
00040   if(!theRenderer)
00041     return;
00042 
00043   vtkCamera* aCamera = theRenderer->GetActiveCamera();
00044   if(!aCamera) 
00045     return;
00046 
00047   vtkFloatingPointType aBounds[6];
00048   int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
00049 
00050   if(theUsingZeroFocalPoint || aCount){
00051     static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
00052 
00053     vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
00054     aLength = std::max((aBounds[3]-aBounds[2]),aLength);
00055     aLength = std::max((aBounds[5]-aBounds[4]),aLength);
00056     
00057     if(aLength < MIN_DISTANCE)
00058       return;
00059 
00060     vtkFloatingPointType aWidth = 
00061       sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
00062            (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
00063            (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
00064     
00065     if(aWidth < MIN_DISTANCE)
00066       return;
00067 
00068     vtkFloatingPointType aViewPlaneNormal[3];
00069     aCamera->GetViewPlaneNormal(aViewPlaneNormal);
00070     
00071     vtkFloatingPointType aCenter[3] = {0.0, 0.0, 0.0};
00072     if(!theUsingZeroFocalPoint){
00073       aCenter[0] = (aBounds[0] + aBounds[1])/2.0;
00074       aCenter[1] = (aBounds[2] + aBounds[3])/2.0;
00075       aCenter[2] = (aBounds[4] + aBounds[5])/2.0;
00076     }
00077     aCamera->SetFocalPoint(aCenter[0],aCenter[1],aCenter[2]);
00078     
00079     vtkFloatingPointType aViewAngle = aCamera->GetViewAngle();
00080     vtkFloatingPointType aDistance = 2.0*aWidth/tan(aViewAngle*vtkMath::Pi()/360.0);
00081     
00082     // check view-up vector against view plane normal
00083     vtkFloatingPointType aViewUp[3];
00084     aCamera->GetViewUp(aViewUp);
00085     if(fabs(vtkMath::Dot(aViewUp,aViewPlaneNormal)) > 0.999)
00086       aCamera->SetViewUp(-aViewUp[2], aViewUp[0], aViewUp[1]);
00087     
00088     // update the camera
00089     aCamera->SetPosition(aCenter[0]+aDistance*aViewPlaneNormal[0],
00090                          aCenter[1]+aDistance*aViewPlaneNormal[1],
00091                          aCenter[2]+aDistance*aViewPlaneNormal[2]);
00092 
00093     // find size of the window
00094     int* aWinSize = theRenderer->GetSize();
00095     if(aWinSize[0] < aWinSize[1]) 
00096       aWidth *= vtkFloatingPointType(aWinSize[1])/vtkFloatingPointType(aWinSize[0]);
00097     
00098     if(theUsingZeroFocalPoint) 
00099       aWidth *= sqrt(2.0);
00100     
00101     aCamera->SetParallelScale(aWidth/2.0);
00102   }
00103 
00104   ResetCameraClippingRange(theRenderer);
00105 }
00106 
00108 int
00109 ComputeVisiblePropBounds(vtkRenderer* theRenderer, 
00110                          vtkFloatingPointType theBounds[6])
00111 {
00112   int aCount = 0;
00113   
00114   theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
00115   theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
00116   
00117   // loop through all props
00118   VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
00119   vtkActorCollection* aCollection = aCopy.GetActors();
00120   aCollection->InitTraversal();
00121   while (vtkActor* aProp = aCollection->GetNextActor()) {
00122     // if it's invisible, or has no geometry, we can skip the rest 
00123     if(aProp->GetVisibility() && aProp->GetMapper() && vtkMath::AreBoundsInitialized(aProp->GetBounds())){
00124       if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(aProp))
00125         if(anActor->IsInfinitive())
00126           continue;
00127         
00128       vtkFloatingPointType *aBounds = aProp->GetBounds();
00129       static vtkFloatingPointType MAX_DISTANCE = 0.9*VTK_LARGE_FLOAT;
00130       // make sure we haven't got bogus bounds
00131       if ( aBounds != NULL &&
00132            aBounds[0] > -MAX_DISTANCE && aBounds[1] < MAX_DISTANCE &&
00133            aBounds[2] > -MAX_DISTANCE && aBounds[3] < MAX_DISTANCE &&
00134            aBounds[4] > -MAX_DISTANCE && aBounds[5] < MAX_DISTANCE )
00135       {
00136         aCount++;
00137 
00138         theBounds[0] = std::min(aBounds[0],theBounds[0]);
00139         theBounds[2] = std::min(aBounds[2],theBounds[2]);
00140         theBounds[4] = std::min(aBounds[4],theBounds[4]);
00141 
00142         theBounds[1] = std::max(aBounds[1],theBounds[1]);
00143         theBounds[3] = std::max(aBounds[3],theBounds[3]);
00144         theBounds[5] = std::max(aBounds[5],theBounds[5]);
00145 
00146       }//not bogus
00147     }
00148   }
00149   return aCount;
00150 }
00151 
00153 void
00154 ResetCameraClippingRange(vtkRenderer* theRenderer)
00155 {
00156   if(!theRenderer || !theRenderer->VisibleActorCount()) return;
00157   
00158   vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
00159   if( anActiveCamera == NULL ){
00160     return;
00161   }
00162   
00163   // Find the plane equation for the camera view plane
00164   vtkFloatingPointType vn[3];
00165   anActiveCamera->GetViewPlaneNormal(vn);
00166   vtkFloatingPointType  position[3];
00167   anActiveCamera->GetPosition(position);
00168   
00169   vtkFloatingPointType bounds[6];
00170   theRenderer->ComputeVisiblePropBounds(bounds);
00171   
00172   vtkFloatingPointType center[3];
00173   center[0] = (bounds[0] + bounds[1])/2.0;
00174   center[1] = (bounds[2] + bounds[3])/2.0;
00175   center[2] = (bounds[4] + bounds[5])/2.0;
00176   
00177   vtkFloatingPointType width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
00178     (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
00179     (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
00180   
00181   vtkFloatingPointType distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
00182        (position[1]-center[1])*(position[1]-center[1]) +
00183        (position[2]-center[2])*(position[2]-center[2]));
00184   
00185   vtkFloatingPointType range[2] = {distance - width/2.0, distance + width/2.0};
00186   
00187   // Do not let the range behind the camera throw off the calculation.
00188   if (range[0] < 0.0) range[0] = 0.0;
00189   
00190   anActiveCamera->SetClippingRange( range );
00191 }
00192 
00194 bool
00195 ComputeTrihedronSize( vtkRenderer* theRenderer,
00196                       vtkFloatingPointType& theNewSize,
00197                       const vtkFloatingPointType theSize, 
00198                       const vtkFloatingPointType theSizeInPercents )
00199 {
00200   // calculating diagonal of visible props of the renderer
00201   vtkFloatingPointType bnd[ 6 ];
00202   if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
00203   {
00204     bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
00205     bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
00206   }
00207   vtkFloatingPointType aLength = 0;
00208 
00209   aLength = bnd[ 1 ]-bnd[ 0 ];
00210   aLength = std::max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
00211   aLength = std::max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
00212 
00213   static vtkFloatingPointType EPS_SIZE = 5.0E-3;
00214   theNewSize = aLength * theSizeInPercents / 100.0;
00215 
00216   // if the new trihedron size have sufficient difference, then apply the value
00217   return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
00218          fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;
00219 }
00220 
00221 bool IsBBEmpty(vtkRenderer* theRenderer)
00222 {
00223   if(!theRenderer)
00224     return false;
00225 
00226   vtkFloatingPointType aNewBndBox[6];
00227   aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
00228   aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
00229   
00230   // iterate through displayed objects and set size if necessary
00231   VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
00232   vtkActorCollection* anActors = aCopy.GetActors();
00233   anActors->InitTraversal();
00234   bool isAny = false;
00235   while(vtkActor* anAct = anActors->GetNextActor())
00236     //if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
00237     if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(anAct))
00238       if(anActor->GetVisibility() && !anActor->IsInfinitive())
00239       {
00240         vtkFloatingPointType *aBounds = anActor->GetBounds();
00241         if(aBounds[0] > -VTK_LARGE_FLOAT && aBounds[1] < VTK_LARGE_FLOAT &&
00242            aBounds[2] > -VTK_LARGE_FLOAT && aBounds[3] < VTK_LARGE_FLOAT &&
00243            aBounds[4] > -VTK_LARGE_FLOAT && aBounds[5] < VTK_LARGE_FLOAT)
00244           isAny = true;
00245       }
00246   
00247   return !isAny;
00248 }
00249 
00250 bool ComputeBBCenter(vtkRenderer* theRenderer, vtkFloatingPointType theCenter[3])
00251 {  
00252   theCenter[0] = theCenter[1] = theCenter[2] = 0.0;
00253   
00254   if(!theRenderer)
00255     return false;
00256 
00257   vtkFloatingPointType aNewBndBox[6];
00258   aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
00259   aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
00260 
00261   // iterate through displayed objects and set size if necessary
00262   VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
00263   vtkActorCollection* anActors = aCopy.GetActors();
00264   anActors->InitTraversal();
00265   bool isAny = false;
00266   while(vtkActor* anAct = anActors->GetNextActor())
00267   {
00268     //if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
00269     if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(anAct))
00270     {
00271       if(anActor->GetVisibility() && !anActor->IsInfinitive())
00272       {
00273         vtkFloatingPointType *aBounds = anActor->GetBounds();
00274         if(aBounds[0] > -VTK_LARGE_FLOAT && aBounds[1] < VTK_LARGE_FLOAT &&
00275            aBounds[2] > -VTK_LARGE_FLOAT && aBounds[3] < VTK_LARGE_FLOAT &&
00276            aBounds[4] > -VTK_LARGE_FLOAT && aBounds[5] < VTK_LARGE_FLOAT)
00277         {
00278           for(int i = 0; i < 5; i = i + 2){
00279             if(aBounds[i] < aNewBndBox[i]) 
00280               aNewBndBox[i] = aBounds[i];
00281             if(aBounds[i+1] > aNewBndBox[i+1]) 
00282               aNewBndBox[i+1] = aBounds[i+1];
00283           }
00284           isAny = true;
00285         }
00286       }
00287     }
00288   }
00289   
00290   if ( !isAny )
00291   {
00292     // null bounding box => the center is (0,0,0)
00293     return true;
00294   }
00295 
00296   if(aNewBndBox[0] > -VTK_LARGE_FLOAT && aNewBndBox[1] < VTK_LARGE_FLOAT &&
00297      aNewBndBox[2] > -VTK_LARGE_FLOAT && aNewBndBox[3] < VTK_LARGE_FLOAT &&
00298      aNewBndBox[4] > -VTK_LARGE_FLOAT && aNewBndBox[5] < VTK_LARGE_FLOAT)
00299   {
00300     static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
00301     
00302     vtkFloatingPointType aLength = aNewBndBox[1]-aNewBndBox[0];
00303     aLength = std::max((aNewBndBox[3]-aNewBndBox[2]),aLength);
00304     aLength = std::max((aNewBndBox[5]-aNewBndBox[4]),aLength);
00305     
00306     if(aLength < MIN_DISTANCE)
00307       return false;
00308 
00309     vtkFloatingPointType aWidth = 
00310       sqrt((aNewBndBox[1]-aNewBndBox[0])*(aNewBndBox[1]-aNewBndBox[0]) +
00311            (aNewBndBox[3]-aNewBndBox[2])*(aNewBndBox[3]-aNewBndBox[2]) +
00312            (aNewBndBox[5]-aNewBndBox[4])*(aNewBndBox[5]-aNewBndBox[4]));
00313     
00314     if(aWidth < MIN_DISTANCE)
00315       return false;
00316 
00317     theCenter[0] = (aNewBndBox[0] + aNewBndBox[1])/2.0;
00318     theCenter[1] = (aNewBndBox[2] + aNewBndBox[3])/2.0;
00319     theCenter[2] = (aNewBndBox[4] + aNewBndBox[5])/2.0;
00320     return true;
00321   }
00322 
00323   return false;
00324 
00325   /*
00326   vtkFloatingPointType aBounds[6];
00327   int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
00328   printf("aNewBndBox[0] = %f, aNewBndBox[1] = %f,\naNewBndBox[2] = %f, aNewBndBox[3] = %f,\naNewBndBox[4] = %f, aNewBndBox[5] = %f\n",
00329            aBounds[0],aBounds[1],aBounds[2],aBounds[3],aBounds[4],aBounds[5]);
00330   printf("aCount = %d\n",aCount);
00331 
00332   if(aCount){
00333     static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
00334 
00335     vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
00336     aLength = max((aBounds[3]-aBounds[2]),aLength);
00337     aLength = max((aBounds[5]-aBounds[4]),aLength);
00338     
00339     if(aLength < MIN_DISTANCE)
00340       return false;
00341 
00342     vtkFloatingPointType aWidth = 
00343       sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
00344            (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
00345            (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
00346     
00347     if(aWidth < MIN_DISTANCE)
00348       return false;
00349 
00350     theCenter[0] = (aBounds[0] + aBounds[1])/2.0;
00351     theCenter[1] = (aBounds[2] + aBounds[3])/2.0;
00352     theCenter[2] = (aBounds[4] + aBounds[5])/2.0;
00353     return true;
00354   }
00355   return false;*/
00356 }