Salome HOME
Initial version
[modules/gui.git] / src / VTKViewer / VTKViewer_Utilities.cxx
1 #include "VTKViewer_Actor.h"
2
3 // VTK Includes
4 #include <vtkMath.h>
5 #include <vtkCamera.h>
6 #include <vtkRenderer.h>
7 #include <vtkRenderWindow.h>
8 #include "VTKViewer_Utilities.h"
9
10
11 //****************************************************************
12 //see vtkRenderer::ResetCamera(float bounds[6]) method
13 void ResetCamera(vtkRenderer* theRenderer, int theUsingZeroFocalPoint)
14 {  
15   if(!theRenderer) return;
16   float bounds[6];
17   int aCount = ComputeVisiblePropBounds(theRenderer,bounds);
18   if(theUsingZeroFocalPoint || aCount){
19     float aLength = bounds[1]-bounds[0];
20     aLength = max((bounds[3]-bounds[2]),aLength);
21     aLength = max((bounds[5]-bounds[4]),aLength);
22     
23     double vn[3];
24     if ( theRenderer->GetActiveCamera() != NULL )
25       theRenderer->GetActiveCamera()->GetViewPlaneNormal(vn);
26     else{
27       return;
28     }
29     
30     float center[3] = {0.0, 0.0, 0.0};
31     if(!theUsingZeroFocalPoint){
32       center[0] = (bounds[0] + bounds[1])/2.0;
33       center[1] = (bounds[2] + bounds[3])/2.0;
34       center[2] = (bounds[4] + bounds[5])/2.0;
35     }
36     theRenderer->GetActiveCamera()->SetFocalPoint(center[0],center[1],center[2]);
37     
38     float width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
39       (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
40       (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
41     
42     double ang = theRenderer->GetActiveCamera()->GetViewAngle();
43     float distance = 2.0*width/tan(ang*vtkMath::Pi()/360.0);
44     
45     // check view-up vector against view plane normal
46     double *vup = theRenderer->GetActiveCamera()->GetViewUp();
47     if ( fabs(vtkMath::Dot(vup,vn)) > 0.999 ){
48       theRenderer->GetActiveCamera()->SetViewUp(-vup[2], vup[0], vup[1]);
49     }
50     
51     // update the camera
52     theRenderer->GetActiveCamera()->SetPosition(center[0]+distance*vn[0],
53                                                 center[1]+distance*vn[1],
54                                                 center[2]+distance*vn[2]);
55     // find size of the window
56     int* winsize = theRenderer->GetSize();
57     if(winsize[0] < winsize[1]) width *= float(winsize[1])/float(winsize[0]);
58     
59     if(theUsingZeroFocalPoint) width *= sqrt(2.0);
60     
61     theRenderer->GetActiveCamera()->SetParallelScale(width/2.0);
62   }
63   //workaround on VTK
64   //theRenderer->ResetCameraClippingRange(bounds);
65   ResetCameraClippingRange(theRenderer);
66 }
67
68 //****************************************************************
69 // Compute the bounds of the visible props
70 int ComputeVisiblePropBounds(vtkRenderer* theRenderer, float theBounds[6])
71 {
72   float      *bounds;
73   int        aCount=0;
74   
75   theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
76   theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
77   
78   // loop through all props
79   vtkActorCollection* aCollection = theRenderer->GetActors();
80   aCollection->InitTraversal();
81   while (vtkActor* prop = aCollection->GetNextActor()) {
82     // if it's invisible, or has no geometry, we can skip the rest 
83     if ( prop->GetVisibility() )
84     {
85       if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(prop))
86         if(anActor->IsInfinitive()) continue;
87         bounds = prop->GetBounds();
88         // make sure we haven't got bogus bounds
89         if ( bounds != NULL &&
90           bounds[0] > -VTK_LARGE_FLOAT && bounds[1] < VTK_LARGE_FLOAT &&
91           bounds[2] > -VTK_LARGE_FLOAT && bounds[3] < VTK_LARGE_FLOAT &&
92           bounds[4] > -VTK_LARGE_FLOAT && bounds[5] < VTK_LARGE_FLOAT )
93         {
94           aCount++;
95           
96           if (bounds[0] < theBounds[0])
97           {
98             theBounds[0] = bounds[0]; 
99           }
100           if (bounds[1] > theBounds[1])
101           {
102             theBounds[1] = bounds[1]; 
103           }
104           if (bounds[2] < theBounds[2])
105           {
106             theBounds[2] = bounds[2]; 
107           }
108           if (bounds[3] > theBounds[3])
109           {
110             theBounds[3] = bounds[3]; 
111           }
112           if (bounds[4] < theBounds[4])
113           {
114             theBounds[4] = bounds[4]; 
115           }
116           if (bounds[5] > theBounds[5])
117           {
118             theBounds[5] = bounds[5]; 
119           }
120         }//not bogus
121     }
122   }
123   return aCount;
124 }
125
126 //****************************************************************
127 //see vtkRenderer::ResetCameraClippingRange(float bounds[6]) method
128 void ResetCameraClippingRange(vtkRenderer* theRenderer)
129 {
130   if(!theRenderer || !theRenderer->VisibleActorCount()) return;
131   
132   vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
133   if( anActiveCamera == NULL ){
134     return;
135   }
136   
137   // Find the plane equation for the camera view plane
138   double vn[3];
139   anActiveCamera->GetViewPlaneNormal(vn);
140   double  position[3];
141   anActiveCamera->GetPosition(position);
142   
143   float bounds[6];
144   theRenderer->ComputeVisiblePropBounds(bounds);
145   
146   double center[3];
147   center[0] = (bounds[0] + bounds[1])/2.0;
148   center[1] = (bounds[2] + bounds[3])/2.0;
149   center[2] = (bounds[4] + bounds[5])/2.0;
150   
151   double width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
152     (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
153     (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
154   
155   double distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
156        (position[1]-center[1])*(position[1]-center[1]) +
157        (position[2]-center[2])*(position[2]-center[2]));
158   
159   float range[2] = {distance - width/2.0, distance + width/2.0};
160   
161   // Do not let the range behind the camera throw off the calculation.
162   if (range[0] < 0.0) range[0] = 0.0;
163   
164   anActiveCamera->SetClippingRange( range );
165 }