Salome HOME
Copyrights update
[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) return;
33   float bounds[6];
34   int aCount = ComputeVisiblePropBounds(theRenderer,bounds);
35   if(theUsingZeroFocalPoint || aCount){
36     float aLength = bounds[1]-bounds[0];
37     aLength = max((bounds[3]-bounds[2]),aLength);
38     aLength = max((bounds[5]-bounds[4]),aLength);
39     
40     double vn[3];
41     if ( theRenderer->GetActiveCamera() != NULL )
42       theRenderer->GetActiveCamera()->GetViewPlaneNormal(vn);
43     else{
44       return;
45     }
46     
47     float center[3] = {0.0, 0.0, 0.0};
48     if(!theUsingZeroFocalPoint){
49       center[0] = (bounds[0] + bounds[1])/2.0;
50       center[1] = (bounds[2] + bounds[3])/2.0;
51       center[2] = (bounds[4] + bounds[5])/2.0;
52     }
53     theRenderer->GetActiveCamera()->SetFocalPoint(center[0],center[1],center[2]);
54     
55     float width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
56       (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
57       (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
58     
59     double ang = theRenderer->GetActiveCamera()->GetViewAngle();
60     float distance = 2.0*width/tan(ang*vtkMath::Pi()/360.0);
61     
62     // check view-up vector against view plane normal
63     double *vup = theRenderer->GetActiveCamera()->GetViewUp();
64     if ( fabs(vtkMath::Dot(vup,vn)) > 0.999 ){
65       theRenderer->GetActiveCamera()->SetViewUp(-vup[2], vup[0], vup[1]);
66     }
67     
68     // update the camera
69     theRenderer->GetActiveCamera()->SetPosition(center[0]+distance*vn[0],
70                                                 center[1]+distance*vn[1],
71                                                 center[2]+distance*vn[2]);
72     // find size of the window
73     int* winsize = theRenderer->GetSize();
74     if(winsize[0] < winsize[1]) width *= float(winsize[1])/float(winsize[0]);
75     
76     if(theUsingZeroFocalPoint) width *= sqrt(2.0);
77     
78     theRenderer->GetActiveCamera()->SetParallelScale(width/2.0);
79   }
80   //workaround on VTK
81   //theRenderer->ResetCameraClippingRange(bounds);
82   ResetCameraClippingRange(theRenderer);
83 }
84
85 /*! Compute the bounds of the visible props*/
86 int ComputeVisiblePropBounds(vtkRenderer* theRenderer, float theBounds[6])
87 {
88   float      *bounds;
89   int        aCount=0;
90   
91   theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
92   theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
93   
94   // loop through all props
95   vtkActorCollection* aCollection = theRenderer->GetActors();
96   aCollection->InitTraversal();
97   while (vtkActor* prop = aCollection->GetNextActor()) {
98     // if it's invisible, or has no geometry, we can skip the rest 
99     if ( prop->GetVisibility() )
100     {
101       if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(prop))
102         if(anActor->IsInfinitive()) continue;
103         bounds = prop->GetBounds();
104         // make sure we haven't got bogus bounds
105         if ( bounds != NULL &&
106           bounds[0] > -VTK_LARGE_FLOAT && bounds[1] < VTK_LARGE_FLOAT &&
107           bounds[2] > -VTK_LARGE_FLOAT && bounds[3] < VTK_LARGE_FLOAT &&
108           bounds[4] > -VTK_LARGE_FLOAT && bounds[5] < VTK_LARGE_FLOAT )
109         {
110           aCount++;
111           
112           if (bounds[0] < theBounds[0])
113           {
114             theBounds[0] = bounds[0]; 
115           }
116           if (bounds[1] > theBounds[1])
117           {
118             theBounds[1] = bounds[1]; 
119           }
120           if (bounds[2] < theBounds[2])
121           {
122             theBounds[2] = bounds[2]; 
123           }
124           if (bounds[3] > theBounds[3])
125           {
126             theBounds[3] = bounds[3]; 
127           }
128           if (bounds[4] < theBounds[4])
129           {
130             theBounds[4] = bounds[4]; 
131           }
132           if (bounds[5] > theBounds[5])
133           {
134             theBounds[5] = bounds[5]; 
135           }
136         }//not bogus
137     }
138   }
139   return aCount;
140 }
141
142 /*!@see vtkRenderer::ResetCameraClippingRange(float bounds[6]) method*/
143 void ResetCameraClippingRange(vtkRenderer* theRenderer)
144 {
145   if(!theRenderer || !theRenderer->VisibleActorCount()) return;
146   
147   vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
148   if( anActiveCamera == NULL ){
149     return;
150   }
151   
152   // Find the plane equation for the camera view plane
153   double vn[3];
154   anActiveCamera->GetViewPlaneNormal(vn);
155   double  position[3];
156   anActiveCamera->GetPosition(position);
157   
158   float bounds[6];
159   theRenderer->ComputeVisiblePropBounds(bounds);
160   
161   double center[3];
162   center[0] = (bounds[0] + bounds[1])/2.0;
163   center[1] = (bounds[2] + bounds[3])/2.0;
164   center[2] = (bounds[4] + bounds[5])/2.0;
165   
166   double width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
167     (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
168     (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
169   
170   double distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
171        (position[1]-center[1])*(position[1]-center[1]) +
172        (position[2]-center[2])*(position[2]-center[2]));
173   
174   float range[2] = {distance - width/2.0, distance + width/2.0};
175   
176   // Do not let the range behind the camera throw off the calculation.
177   if (range[0] < 0.0) range[0] = 0.0;
178   
179   anActiveCamera->SetClippingRange( range );
180 }
181
182 /*!Compute trihedron size.*/
183 bool ComputeTrihedronSize( vtkRenderer* theRenderer,double& theNewSize,
184                            const double theSize, const float theSizeInPercents )
185 {
186   // calculating diagonal of visible props of the renderer
187   float bnd[ 6 ];
188   if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
189   {
190     bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
191     bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
192   }
193   float aLength = 0;
194
195   aLength = bnd[ 1 ]-bnd[ 0 ];
196   aLength = max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
197   aLength = max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
198
199   static float EPS_SIZE = 5.0E-3;
200   theNewSize = aLength * theSizeInPercents / 100.0;
201
202   // if the new trihedron size have sufficient difference, then apply the value
203   return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
204          fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;
205 }