Salome HOME
DCQ : Merge with Ecole_ete_a6.
[modules/kernel.git] / src / VTKViewer / VTKViewer_Utilities.cxx
1 //  SALOME VTKViewer : 
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : VTKViewer_Utilities.cxx
25 //  Author : Alexey PETROV
26 //  Module : SALOME
27 //  $Header: 
28
29 #include "VTKViewer_Utilities.h"
30 #include "utilities.h"
31 #include "SALOME_Actor.h"
32
33 // VTK Includes
34 #include <vtkMath.h>
35 #include <vtkCamera.h>
36 #include <vtkRenderer.h>
37 #include <vtkRenderWindow.h>
38
39 using namespace std;
40
41 //see vtkRenderer::ResetCamera(float bounds[6]) method
42 void ResetCamera(vtkRenderer* theRenderer, int theUsingZeroFocalPoint){  
43   if(!theRenderer) return;
44   float bounds[6];
45   int aCount = ComputeVisiblePropBounds(theRenderer,bounds);
46   if(theUsingZeroFocalPoint || aCount){
47     float aLength = bounds[1]-bounds[0];
48     aLength = max((bounds[3]-bounds[2]),aLength);
49     aLength = max((bounds[5]-bounds[4]),aLength);
50     
51     double vn[3];
52     if ( theRenderer->GetActiveCamera() != NULL )
53       theRenderer->GetActiveCamera()->GetViewPlaneNormal(vn);
54     else{
55       MESSAGE("Trying to reset non-existant camera");
56       return;
57     }
58     
59     float center[3] = {0.0, 0.0, 0.0};
60     if(!theUsingZeroFocalPoint){
61       center[0] = (bounds[0] + bounds[1])/2.0;
62       center[1] = (bounds[2] + bounds[3])/2.0;
63       center[2] = (bounds[4] + bounds[5])/2.0;
64     }
65     theRenderer->GetActiveCamera()->SetFocalPoint(center[0],center[1],center[2]);
66     
67     float width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
68                        (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
69                        (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
70     
71     double ang = theRenderer->GetActiveCamera()->GetViewAngle();
72     float distance = 2.0*width/tan(ang*vtkMath::Pi()/360.0);
73     
74     // check view-up vector against view plane normal
75     double *vup = theRenderer->GetActiveCamera()->GetViewUp();
76     if ( fabs(vtkMath::Dot(vup,vn)) > 0.999 ){
77       MESSAGE("Resetting view-up since view plane normal is parallel");
78       theRenderer->GetActiveCamera()->SetViewUp(-vup[2], vup[0], vup[1]);
79     }
80     
81     // update the camera
82     theRenderer->GetActiveCamera()->SetPosition(center[0]+distance*vn[0],
83                                                 center[1]+distance*vn[1],
84                                                 center[2]+distance*vn[2]);
85     // find size of the window
86     int* winsize = theRenderer->GetSize();
87     if(winsize[0] < winsize[1]) width *= float(winsize[1])/float(winsize[0]);
88     
89     if(theUsingZeroFocalPoint) width *= sqrt(2.0);
90     
91     theRenderer->GetActiveCamera()->SetParallelScale(width/2.0);
92   }
93   //workaround on VTK
94   //theRenderer->ResetCameraClippingRange(bounds);
95   ResetCameraClippingRange(theRenderer);
96 }
97
98
99 // Compute the bounds of the visible props
100 int ComputeVisiblePropBounds(vtkRenderer* theRenderer, float theBounds[6]){
101   vtkProp    *prop;
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(SALOME_Actor* anActor = SALOME_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
157 //see vtkRenderer::ResetCameraClippingRange(float bounds[6]) method
158 void ResetCameraClippingRange(vtkRenderer* theRenderer){
159   if(!theRenderer || !theRenderer->VisibleActorCount()) return;
160
161   vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
162   if( anActiveCamera == NULL ){
163     MESSAGE("Trying to reset clipping range of non-existant camera");
164     return;
165   }
166   
167   // Find the plane equation for the camera view plane
168   double vn[3];
169   anActiveCamera->GetViewPlaneNormal(vn);
170   double  position[3];
171   anActiveCamera->GetPosition(position);
172
173   float bounds[6];
174   theRenderer->ComputeVisiblePropBounds(bounds);
175
176   double center[3];
177   center[0] = (bounds[0] + bounds[1])/2.0;
178   center[1] = (bounds[2] + bounds[3])/2.0;
179   center[2] = (bounds[4] + bounds[5])/2.0;
180   
181   double width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
182                      (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
183                      (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
184
185   double distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
186                          (position[1]-center[1])*(position[1]-center[1]) +
187                          (position[2]-center[2])*(position[2]-center[2]));
188
189   float range[2] = {distance - width/2.0, distance + width/2.0};
190
191   // Do not let the range behind the camera throw off the calculation.
192   if (range[0] < 0.0) range[0] = 0.0;
193
194   anActiveCamera->SetClippingRange( range );
195 }