3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : VTKViewer_Utilities.cxx
25 // Author : Alexey PETROV
29 #include "VTKViewer_Utilities.h"
30 #include "utilities.h"
31 #include "SALOME_Actor.h"
35 #include <vtkCamera.h>
36 #include <vtkRenderer.h>
37 #include <vtkRenderWindow.h>
41 //see vtkRenderer::ResetCamera(float bounds[6]) method
42 void ResetCamera(vtkRenderer* theRenderer, int theUsingZeroFocalPoint){
43 if(!theRenderer) return;
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);
52 if ( theRenderer->GetActiveCamera() != NULL )
53 theRenderer->GetActiveCamera()->GetViewPlaneNormal(vn);
55 MESSAGE("Trying to reset non-existant camera");
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;
65 theRenderer->GetActiveCamera()->SetFocalPoint(center[0],center[1],center[2]);
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]));
71 double ang = theRenderer->GetActiveCamera()->GetViewAngle();
72 float distance = 2.0*width/tan(ang*vtkMath::Pi()/360.0);
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]);
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]);
89 if(theUsingZeroFocalPoint) width *= sqrt(2.0);
91 theRenderer->GetActiveCamera()->SetParallelScale(width/2.0);
94 //theRenderer->ResetCameraClippingRange(bounds);
95 ResetCameraClippingRange(theRenderer);
99 // Compute the bounds of the visible props
100 int ComputeVisiblePropBounds(vtkRenderer* theRenderer, float theBounds[6]){
105 theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
106 theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
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() )
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 )
126 if (bounds[0] < theBounds[0])
128 theBounds[0] = bounds[0];
130 if (bounds[1] > theBounds[1])
132 theBounds[1] = bounds[1];
134 if (bounds[2] < theBounds[2])
136 theBounds[2] = bounds[2];
138 if (bounds[3] > theBounds[3])
140 theBounds[3] = bounds[3];
142 if (bounds[4] < theBounds[4])
144 theBounds[4] = bounds[4];
146 if (bounds[5] > theBounds[5])
148 theBounds[5] = bounds[5];
157 //see vtkRenderer::ResetCameraClippingRange(float bounds[6]) method
158 void ResetCameraClippingRange(vtkRenderer* theRenderer){
159 if(!theRenderer || !theRenderer->VisibleActorCount()) return;
161 vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
162 if( anActiveCamera == NULL ){
163 MESSAGE("Trying to reset clipping range of non-existant camera");
167 // Find the plane equation for the camera view plane
169 anActiveCamera->GetViewPlaneNormal(vn);
171 anActiveCamera->GetPosition(position);
174 theRenderer->ComputeVisiblePropBounds(bounds);
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;
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]));
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]));
189 float range[2] = {distance - width/2.0, distance + width/2.0};
191 // Do not let the range behind the camera throw off the calculation.
192 if (range[0] < 0.0) range[0] = 0.0;
194 anActiveCamera->SetClippingRange( range );
197 bool ComputeTrihedronSize( vtkRenderer* theRenderer,double& theNewSize,
198 const double theSize, const float theSizeInPercents )
200 // calculating diagonal of visible props of the renderer
202 if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
204 bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
205 bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
209 aLength = bnd[ 1 ]-bnd[ 0 ];
210 aLength = max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
211 aLength = max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
213 static float EPS_SIZE = 5.0E-3;
214 theNewSize = aLength * theSizeInPercents / 100.0;
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;