Salome HOME
723eea3fcc6cded3798b7ea3b5c3ce6b394c20b6
[modules/gui.git] / src / VTKViewer / VTKViewer_Utilities.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
2 // 
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either 
6 // version 2.1 of the License.
7 // 
8 // This library is distributed in the hope that it will be useful 
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public  
14 // License along with this library; if not, write to the Free Software 
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/
18 //
19 #include "VTKViewer_Actor.h"
20
21 // VTK Includes
22 #include <vtkMath.h>
23 #include <vtkCamera.h>
24 #include <vtkRenderer.h>
25 #include <vtkRenderWindow.h>
26 #include "VTKViewer_Utilities.h"
27
28
29 /*!@see vtkRenderer::ResetCamera(float bounds[6]) method*/
30 void ResetCamera(vtkRenderer* theRenderer, int theUsingZeroFocalPoint)
31 {  
32   if(!theRenderer)
33     return;
34
35   vtkCamera* aCamera = theRenderer->GetActiveCamera();
36   if(!aCamera) 
37     return;
38
39   float aBounds[6];
40   int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
41
42   if(theUsingZeroFocalPoint || aCount){
43     static float MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
44
45     float aLength = aBounds[1]-aBounds[0];
46     aLength = max((aBounds[3]-aBounds[2]),aLength);
47     aLength = max((aBounds[5]-aBounds[4]),aLength);
48     
49     if(aLength < MIN_DISTANCE)
50       return;
51
52     float aWidth = 
53       sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
54            (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
55            (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
56     
57     if(aWidth < MIN_DISTANCE)
58       return;
59
60     double aViewPlaneNormal[3];
61     aCamera->GetViewPlaneNormal(aViewPlaneNormal);
62     
63     float aCenter[3] = {0.0, 0.0, 0.0};
64     if(!theUsingZeroFocalPoint){
65       aCenter[0] = (aBounds[0] + aBounds[1])/2.0;
66       aCenter[1] = (aBounds[2] + aBounds[3])/2.0;
67       aCenter[2] = (aBounds[4] + aBounds[5])/2.0;
68     }
69     aCamera->SetFocalPoint(aCenter[0],aCenter[1],aCenter[2]);
70     
71     double aViewAngle = aCamera->GetViewAngle();
72     float aDistance = 2.0*aWidth/tan(aViewAngle*vtkMath::Pi()/360.0);
73     
74     // check view-up vector against view plane normal
75     double aViewUp[3];
76     aCamera->GetViewUp(aViewUp);
77     if(fabs(vtkMath::Dot(aViewUp,aViewPlaneNormal)) > 0.999)
78       aCamera->SetViewUp(-aViewUp[2], aViewUp[0], aViewUp[1]);
79     
80     // update the camera
81     aCamera->SetPosition(aCenter[0]+aDistance*aViewPlaneNormal[0],
82                          aCenter[1]+aDistance*aViewPlaneNormal[1],
83                          aCenter[2]+aDistance*aViewPlaneNormal[2]);
84
85     // find size of the window
86     int* aWinSize = theRenderer->GetSize();
87     if(aWinSize[0] < aWinSize[1]) 
88       aWidth *= float(aWinSize[1])/float(aWinSize[0]);
89     
90     if(theUsingZeroFocalPoint) 
91       aWidth *= sqrt(2.0);
92     
93     aCamera->SetParallelScale(aWidth/2.0);
94   }
95
96   ResetCameraClippingRange(theRenderer);
97 }
98
99 /*! Compute the bounds of the visible props*/
100 int ComputeVisiblePropBounds(vtkRenderer* theRenderer, float theBounds[6])
101 {
102   float      *bounds;
103   int        aCount=0;
104   
105   theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
106   theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
107   
108   // loop through all props
109   vtkActorCollection* aCollection = theRenderer->GetActors();
110   aCollection->InitTraversal();
111   while (vtkActor* prop = aCollection->GetNextActor()) {
112     // if it's invisible, or has no geometry, we can skip the rest 
113     if ( prop->GetVisibility() )
114     {
115       if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(prop))
116         if(anActor->IsInfinitive()) continue;
117         bounds = prop->GetBounds();
118         // make sure we haven't got bogus bounds
119         if ( bounds != NULL &&
120           bounds[0] > -VTK_LARGE_FLOAT && bounds[1] < VTK_LARGE_FLOAT &&
121           bounds[2] > -VTK_LARGE_FLOAT && bounds[3] < VTK_LARGE_FLOAT &&
122           bounds[4] > -VTK_LARGE_FLOAT && bounds[5] < VTK_LARGE_FLOAT )
123         {
124           aCount++;
125           
126           if (bounds[0] < theBounds[0])
127           {
128             theBounds[0] = bounds[0]; 
129           }
130           if (bounds[1] > theBounds[1])
131           {
132             theBounds[1] = bounds[1]; 
133           }
134           if (bounds[2] < theBounds[2])
135           {
136             theBounds[2] = bounds[2]; 
137           }
138           if (bounds[3] > theBounds[3])
139           {
140             theBounds[3] = bounds[3]; 
141           }
142           if (bounds[4] < theBounds[4])
143           {
144             theBounds[4] = bounds[4]; 
145           }
146           if (bounds[5] > theBounds[5])
147           {
148             theBounds[5] = bounds[5]; 
149           }
150         }//not bogus
151     }
152   }
153   return aCount;
154 }
155
156 /*!@see vtkRenderer::ResetCameraClippingRange(float bounds[6]) method*/
157 void ResetCameraClippingRange(vtkRenderer* theRenderer)
158 {
159   if(!theRenderer || !theRenderer->VisibleActorCount()) return;
160   
161   vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
162   if( anActiveCamera == NULL ){
163     return;
164   }
165   
166   // Find the plane equation for the camera view plane
167   double vn[3];
168   anActiveCamera->GetViewPlaneNormal(vn);
169   double  position[3];
170   anActiveCamera->GetPosition(position);
171   
172   float bounds[6];
173   theRenderer->ComputeVisiblePropBounds(bounds);
174   
175   double center[3];
176   center[0] = (bounds[0] + bounds[1])/2.0;
177   center[1] = (bounds[2] + bounds[3])/2.0;
178   center[2] = (bounds[4] + bounds[5])/2.0;
179   
180   double width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
181     (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
182     (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
183   
184   double distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
185        (position[1]-center[1])*(position[1]-center[1]) +
186        (position[2]-center[2])*(position[2]-center[2]));
187   
188   float range[2] = {distance - width/2.0, distance + width/2.0};
189   
190   // Do not let the range behind the camera throw off the calculation.
191   if (range[0] < 0.0) range[0] = 0.0;
192   
193   anActiveCamera->SetClippingRange( range );
194 }
195
196 /*!Compute trihedron size.*/
197 bool ComputeTrihedronSize( vtkRenderer* theRenderer,double& theNewSize,
198                            const double theSize, const float theSizeInPercents )
199 {
200   // calculating diagonal of visible props of the renderer
201   float bnd[ 6 ];
202   if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
203   {
204     bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
205     bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
206   }
207   float aLength = 0;
208
209   aLength = bnd[ 1 ]-bnd[ 0 ];
210   aLength = max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
211   aLength = max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
212
213   static float EPS_SIZE = 5.0E-3;
214   theNewSize = aLength * theSizeInPercents / 100.0;
215
216   // if the new trihedron size have sufficient difference, then apply the value
217   return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
218          fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;
219 }