]> SALOME platform Git repositories - modules/gui.git/blob - src/VTKViewer/VTKViewer_Utilities.cxx
Salome HOME
cc8fec734ecaa0808d9acb96bccbde4c8d281ba7
[modules/gui.git] / src / VTKViewer / VTKViewer_Utilities.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "VTKViewer_Utilities.h"
24 #include "VTKViewer_Actor.h"
25 #include "VTKViewer_Algorithm.h"
26
27 #include <algorithm>
28
29 // VTK Includes
30 #include <vtkMath.h>
31 #include <vtkCamera.h>
32 #include <vtkRenderer.h>
33 #include <vtkRenderWindow.h>
34
35 /*!@see vtkRenderer::ResetCamera(vtkFloatingPointType bounds[6]) method*/
36 void 
37 ResetCamera(vtkRenderer* theRenderer, 
38             int theUsingZeroFocalPoint)
39 {  
40   if(!theRenderer)
41     return;
42
43   vtkCamera* aCamera = theRenderer->GetActiveCamera();
44   if(!aCamera) 
45     return;
46
47   vtkFloatingPointType aBounds[6];
48   int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
49
50   if(theUsingZeroFocalPoint || aCount){
51     static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
52
53     vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
54     aLength = std::max((aBounds[3]-aBounds[2]),aLength);
55     aLength = std::max((aBounds[5]-aBounds[4]),aLength);
56     
57     if(aLength < MIN_DISTANCE)
58       return;
59
60     vtkFloatingPointType aWidth = 
61       sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
62            (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
63            (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
64     
65     if(aWidth < MIN_DISTANCE)
66       return;
67
68     vtkFloatingPointType aViewPlaneNormal[3];
69     aCamera->GetViewPlaneNormal(aViewPlaneNormal);
70     
71     vtkFloatingPointType aCenter[3] = {0.0, 0.0, 0.0};
72     if(!theUsingZeroFocalPoint){
73       aCenter[0] = (aBounds[0] + aBounds[1])/2.0;
74       aCenter[1] = (aBounds[2] + aBounds[3])/2.0;
75       aCenter[2] = (aBounds[4] + aBounds[5])/2.0;
76     }
77     aCamera->SetFocalPoint(aCenter[0],aCenter[1],aCenter[2]);
78     
79     vtkFloatingPointType aViewAngle = aCamera->GetViewAngle();
80     vtkFloatingPointType aDistance = 2.0*aWidth/tan(aViewAngle*vtkMath::Pi()/360.0);
81     
82     // check view-up vector against view plane normal
83     vtkFloatingPointType aViewUp[3];
84     aCamera->GetViewUp(aViewUp);
85     if(fabs(vtkMath::Dot(aViewUp,aViewPlaneNormal)) > 0.999)
86       aCamera->SetViewUp(-aViewUp[2], aViewUp[0], aViewUp[1]);
87     
88     // update the camera
89     aCamera->SetPosition(aCenter[0]+aDistance*aViewPlaneNormal[0],
90                          aCenter[1]+aDistance*aViewPlaneNormal[1],
91                          aCenter[2]+aDistance*aViewPlaneNormal[2]);
92
93     // find size of the window
94     int* aWinSize = theRenderer->GetSize();
95     if(aWinSize[0] < aWinSize[1]) 
96       aWidth *= vtkFloatingPointType(aWinSize[1])/vtkFloatingPointType(aWinSize[0]);
97     
98     if(theUsingZeroFocalPoint) 
99       aWidth *= sqrt(2.0);
100     
101     aCamera->SetParallelScale(aWidth/2.0);
102   }
103
104   ResetCameraClippingRange(theRenderer);
105 }
106
107 /*! Compute the bounds of the visible props*/
108 int
109 ComputeVisiblePropBounds(vtkRenderer* theRenderer, 
110                          vtkFloatingPointType theBounds[6])
111 {
112   int aCount = 0;
113   
114   theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
115   theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
116   
117   // loop through all props
118   VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
119   vtkActorCollection* aCollection = aCopy.GetActors();
120   aCollection->InitTraversal();
121   while (vtkActor* aProp = aCollection->GetNextActor()) {
122     // if it's invisible, or has no geometry, we can skip the rest 
123     if(aProp->GetVisibility() && aProp->GetMapper() && vtkMath::AreBoundsInitialized(aProp->GetBounds())){
124       if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(aProp))
125         if(anActor->IsInfinitive())
126           continue;
127       vtkFloatingPointType *aBounds = aProp->GetBounds();
128       static vtkFloatingPointType MIN_DISTANCE = 1./VTK_LARGE_FLOAT;
129       static vtkFloatingPointType MAX_DISTANCE = 0.9*VTK_LARGE_FLOAT;
130
131       if(abs(aBounds[1] - aBounds[0]) < MIN_DISTANCE) {
132         aBounds[0]-=0.001;
133         aBounds[1]+=0.001;
134       }
135
136       if(abs(aBounds[3] - aBounds[2]) < MIN_DISTANCE) {
137         aBounds[2]-=0.001;
138         aBounds[3]+=0.001;
139       }
140
141       if(abs(aBounds[5] - aBounds[4]) < MIN_DISTANCE) {
142         aBounds[4]-=0.001;
143         aBounds[5]+=0.001;
144       }
145       
146       // make sure we haven't got bogus bounds
147       if ( aBounds != NULL &&
148            aBounds[0] > -MAX_DISTANCE && aBounds[1] < MAX_DISTANCE &&
149            aBounds[2] > -MAX_DISTANCE && aBounds[3] < MAX_DISTANCE &&
150            aBounds[4] > -MAX_DISTANCE && aBounds[5] < MAX_DISTANCE)           
151       {
152         aCount++;
153
154         theBounds[0] = std::min(aBounds[0],theBounds[0]);
155         theBounds[2] = std::min(aBounds[2],theBounds[2]);
156         theBounds[4] = std::min(aBounds[4],theBounds[4]);
157
158         theBounds[1] = std::max(aBounds[1],theBounds[1]);
159         theBounds[3] = std::max(aBounds[3],theBounds[3]);
160         theBounds[5] = std::max(aBounds[5],theBounds[5]);
161
162       }//not bogus
163     }
164   }
165   return aCount;
166 }
167
168 /*!@see vtkRenderer::ResetCameraClippingRange(vtkFloatingPointType bounds[6]) method*/
169 void
170 ResetCameraClippingRange(vtkRenderer* theRenderer)
171 {
172   if(!theRenderer || !theRenderer->VisibleActorCount()) return;
173   
174   vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
175   if( anActiveCamera == NULL ){
176     return;
177   }
178   
179   // Find the plane equation for the camera view plane
180   vtkFloatingPointType vn[3];
181   anActiveCamera->GetViewPlaneNormal(vn);
182   vtkFloatingPointType  position[3];
183   anActiveCamera->GetPosition(position);
184   
185   vtkFloatingPointType bounds[6];
186   theRenderer->ComputeVisiblePropBounds(bounds);
187   
188   vtkFloatingPointType center[3];
189   center[0] = (bounds[0] + bounds[1])/2.0;
190   center[1] = (bounds[2] + bounds[3])/2.0;
191   center[2] = (bounds[4] + bounds[5])/2.0;
192   
193   vtkFloatingPointType width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
194     (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
195     (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
196   
197   vtkFloatingPointType distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
198        (position[1]-center[1])*(position[1]-center[1]) +
199        (position[2]-center[2])*(position[2]-center[2]));
200   
201   vtkFloatingPointType range[2] = {distance - width/2.0, distance + width/2.0};
202   
203   // Do not let the range behind the camera throw off the calculation.
204   if (range[0] < 0.0) range[0] = 0.0;
205   
206   anActiveCamera->SetClippingRange( range );
207 }
208
209 /*!Compute trihedron size.*/
210 bool
211 ComputeTrihedronSize( vtkRenderer* theRenderer,
212                       vtkFloatingPointType& theNewSize,
213                       const vtkFloatingPointType theSize, 
214                       const vtkFloatingPointType theSizeInPercents )
215 {
216   // calculating diagonal of visible props of the renderer
217   vtkFloatingPointType bnd[ 6 ];
218   if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
219   {
220     bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
221     bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
222   }
223   vtkFloatingPointType aLength = 0;
224
225   aLength = bnd[ 1 ]-bnd[ 0 ];
226   aLength = std::max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
227   aLength = std::max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
228
229   static vtkFloatingPointType EPS_SIZE = 5.0E-3;
230   theNewSize = aLength * theSizeInPercents / 100.0;
231
232   // if the new trihedron size have sufficient difference, then apply the value
233   return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
234          fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;
235 }
236
237 bool IsBBEmpty(vtkRenderer* theRenderer)
238 {
239   if(!theRenderer)
240     return false;
241
242   vtkFloatingPointType aNewBndBox[6];
243   aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
244   aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
245   
246   // iterate through displayed objects and set size if necessary
247   VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
248   vtkActorCollection* anActors = aCopy.GetActors();
249   anActors->InitTraversal();
250   bool isAny = false;
251   while(vtkActor* anAct = anActors->GetNextActor())
252     //if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
253     if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(anAct))
254       if(anActor->GetVisibility() && !anActor->IsInfinitive())
255       {
256         vtkFloatingPointType *aBounds = anActor->GetBounds();
257         if(aBounds[0] > -VTK_LARGE_FLOAT && aBounds[1] < VTK_LARGE_FLOAT &&
258            aBounds[2] > -VTK_LARGE_FLOAT && aBounds[3] < VTK_LARGE_FLOAT &&
259            aBounds[4] > -VTK_LARGE_FLOAT && aBounds[5] < VTK_LARGE_FLOAT)
260           isAny = true;
261       }
262   
263   return !isAny;
264 }
265
266 bool ComputeBBCenter(vtkRenderer* theRenderer, vtkFloatingPointType theCenter[3])
267 {  
268   theCenter[0] = theCenter[1] = theCenter[2] = 0.0;
269   
270   if(!theRenderer)
271     return false;
272
273   vtkFloatingPointType aNewBndBox[6];
274   aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
275   aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
276
277   // iterate through displayed objects and set size if necessary
278   VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
279   vtkActorCollection* anActors = aCopy.GetActors();
280   anActors->InitTraversal();
281   bool isAny = false;
282   while(vtkActor* anAct = anActors->GetNextActor())
283   {
284     //if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
285     if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(anAct))
286     {
287       if(anActor->GetVisibility() && !anActor->IsInfinitive())
288       {
289         vtkFloatingPointType *aBounds = anActor->GetBounds();
290         if(aBounds[0] > -VTK_LARGE_FLOAT && aBounds[1] < VTK_LARGE_FLOAT &&
291            aBounds[2] > -VTK_LARGE_FLOAT && aBounds[3] < VTK_LARGE_FLOAT &&
292            aBounds[4] > -VTK_LARGE_FLOAT && aBounds[5] < VTK_LARGE_FLOAT)
293         {
294           for(int i = 0; i < 5; i = i + 2){
295             if(aBounds[i] < aNewBndBox[i]) 
296               aNewBndBox[i] = aBounds[i];
297             if(aBounds[i+1] > aNewBndBox[i+1]) 
298               aNewBndBox[i+1] = aBounds[i+1];
299           }
300           isAny = true;
301         }
302       }
303     }
304   }
305   
306   if ( !isAny )
307   {
308     // null bounding box => the center is (0,0,0)
309     return true;
310   }
311
312   if(aNewBndBox[0] > -VTK_LARGE_FLOAT && aNewBndBox[1] < VTK_LARGE_FLOAT &&
313      aNewBndBox[2] > -VTK_LARGE_FLOAT && aNewBndBox[3] < VTK_LARGE_FLOAT &&
314      aNewBndBox[4] > -VTK_LARGE_FLOAT && aNewBndBox[5] < VTK_LARGE_FLOAT)
315   {
316     static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
317     
318     vtkFloatingPointType aLength = aNewBndBox[1]-aNewBndBox[0];
319     aLength = std::max((aNewBndBox[3]-aNewBndBox[2]),aLength);
320     aLength = std::max((aNewBndBox[5]-aNewBndBox[4]),aLength);
321     
322     if(aLength < MIN_DISTANCE)
323       return false;
324
325     vtkFloatingPointType aWidth = 
326       sqrt((aNewBndBox[1]-aNewBndBox[0])*(aNewBndBox[1]-aNewBndBox[0]) +
327            (aNewBndBox[3]-aNewBndBox[2])*(aNewBndBox[3]-aNewBndBox[2]) +
328            (aNewBndBox[5]-aNewBndBox[4])*(aNewBndBox[5]-aNewBndBox[4]));
329     
330     if(aWidth < MIN_DISTANCE)
331       return false;
332
333     theCenter[0] = (aNewBndBox[0] + aNewBndBox[1])/2.0;
334     theCenter[1] = (aNewBndBox[2] + aNewBndBox[3])/2.0;
335     theCenter[2] = (aNewBndBox[4] + aNewBndBox[5])/2.0;
336     return true;
337   }
338
339   return false;
340
341   /*
342   vtkFloatingPointType aBounds[6];
343   int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
344   printf("aNewBndBox[0] = %f, aNewBndBox[1] = %f,\naNewBndBox[2] = %f, aNewBndBox[3] = %f,\naNewBndBox[4] = %f, aNewBndBox[5] = %f\n",
345            aBounds[0],aBounds[1],aBounds[2],aBounds[3],aBounds[4],aBounds[5]);
346   printf("aCount = %d\n",aCount);
347
348   if(aCount){
349     static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
350
351     vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
352     aLength = max((aBounds[3]-aBounds[2]),aLength);
353     aLength = max((aBounds[5]-aBounds[4]),aLength);
354     
355     if(aLength < MIN_DISTANCE)
356       return false;
357
358     vtkFloatingPointType aWidth = 
359       sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
360            (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
361            (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
362     
363     if(aWidth < MIN_DISTANCE)
364       return false;
365
366     theCenter[0] = (aBounds[0] + aBounds[1])/2.0;
367     theCenter[1] = (aBounds[2] + aBounds[3])/2.0;
368     theCenter[2] = (aBounds[4] + aBounds[5])/2.0;
369     return true;
370   }
371   return false;*/
372 }