1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "VTKViewer_Utilities.h"
24 #include "VTKViewer_Actor.h"
25 #include "VTKViewer_Algorithm.h"
31 #include <vtkCamera.h>
32 #include <vtkRenderer.h>
33 #include <vtkRenderWindow.h>
35 /*!@see vtkRenderer::ResetCamera(vtkFloatingPointType bounds[6]) method*/
37 ResetCamera(vtkRenderer* theRenderer,
38 int theUsingZeroFocalPoint)
43 vtkCamera* aCamera = theRenderer->GetActiveCamera();
47 vtkFloatingPointType aBounds[6];
48 int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
50 if(theUsingZeroFocalPoint || aCount){
51 static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
53 vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
54 aLength = std::max((aBounds[3]-aBounds[2]),aLength);
55 aLength = std::max((aBounds[5]-aBounds[4]),aLength);
57 if(aLength < MIN_DISTANCE)
60 vtkFloatingPointType aWidth =
61 sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
62 (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
63 (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
65 if(aWidth < MIN_DISTANCE)
68 vtkFloatingPointType aViewPlaneNormal[3];
69 aCamera->GetViewPlaneNormal(aViewPlaneNormal);
71 vtkFloatingPointType aCenter[3] = {0.0, 0.0, 0.0};
72 if(!theUsingZeroFocalPoint){
73 aCenter[0] = (aBounds[0] + aBounds[1])/2.0;
74 aCenter[1] = (aBounds[2] + aBounds[3])/2.0;
75 aCenter[2] = (aBounds[4] + aBounds[5])/2.0;
77 aCamera->SetFocalPoint(aCenter[0],aCenter[1],aCenter[2]);
79 vtkFloatingPointType aViewAngle = aCamera->GetViewAngle();
80 vtkFloatingPointType aDistance = 2.0*aWidth/tan(aViewAngle*vtkMath::Pi()/360.0);
82 // check view-up vector against view plane normal
83 vtkFloatingPointType aViewUp[3];
84 aCamera->GetViewUp(aViewUp);
85 if(fabs(vtkMath::Dot(aViewUp,aViewPlaneNormal)) > 0.999)
86 aCamera->SetViewUp(-aViewUp[2], aViewUp[0], aViewUp[1]);
89 aCamera->SetPosition(aCenter[0]+aDistance*aViewPlaneNormal[0],
90 aCenter[1]+aDistance*aViewPlaneNormal[1],
91 aCenter[2]+aDistance*aViewPlaneNormal[2]);
93 // find size of the window
94 int* aWinSize = theRenderer->GetSize();
95 if(aWinSize[0] < aWinSize[1])
96 aWidth *= vtkFloatingPointType(aWinSize[1])/vtkFloatingPointType(aWinSize[0]);
98 if(theUsingZeroFocalPoint)
101 aCamera->SetParallelScale(aWidth/2.0);
104 ResetCameraClippingRange(theRenderer);
107 /*! Compute the bounds of the visible props*/
109 ComputeVisiblePropBounds(vtkRenderer* theRenderer,
110 vtkFloatingPointType theBounds[6])
114 theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
115 theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
117 // loop through all props
118 VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
119 vtkActorCollection* aCollection = aCopy.GetActors();
120 aCollection->InitTraversal();
121 while (vtkActor* aProp = aCollection->GetNextActor()) {
122 // if it's invisible, or has no geometry, we can skip the rest
123 if(aProp->GetVisibility() && aProp->GetMapper() && vtkMath::AreBoundsInitialized(aProp->GetBounds())){
124 if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(aProp))
125 if(anActor->IsInfinitive())
127 vtkFloatingPointType *aBounds = aProp->GetBounds();
128 static vtkFloatingPointType MIN_DISTANCE = 1./VTK_LARGE_FLOAT;
129 static vtkFloatingPointType MAX_DISTANCE = 0.9*VTK_LARGE_FLOAT;
131 if(abs(aBounds[1] - aBounds[0]) < MIN_DISTANCE) {
136 if(abs(aBounds[3] - aBounds[2]) < MIN_DISTANCE) {
141 if(abs(aBounds[5] - aBounds[4]) < MIN_DISTANCE) {
146 // make sure we haven't got bogus bounds
147 if ( aBounds != NULL &&
148 aBounds[0] > -MAX_DISTANCE && aBounds[1] < MAX_DISTANCE &&
149 aBounds[2] > -MAX_DISTANCE && aBounds[3] < MAX_DISTANCE &&
150 aBounds[4] > -MAX_DISTANCE && aBounds[5] < MAX_DISTANCE)
154 theBounds[0] = std::min(aBounds[0],theBounds[0]);
155 theBounds[2] = std::min(aBounds[2],theBounds[2]);
156 theBounds[4] = std::min(aBounds[4],theBounds[4]);
158 theBounds[1] = std::max(aBounds[1],theBounds[1]);
159 theBounds[3] = std::max(aBounds[3],theBounds[3]);
160 theBounds[5] = std::max(aBounds[5],theBounds[5]);
168 /*!@see vtkRenderer::ResetCameraClippingRange(vtkFloatingPointType bounds[6]) method*/
170 ResetCameraClippingRange(vtkRenderer* theRenderer)
172 if(!theRenderer || !theRenderer->VisibleActorCount()) return;
174 vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
175 if( anActiveCamera == NULL ){
179 // Find the plane equation for the camera view plane
180 vtkFloatingPointType vn[3];
181 anActiveCamera->GetViewPlaneNormal(vn);
182 vtkFloatingPointType position[3];
183 anActiveCamera->GetPosition(position);
185 vtkFloatingPointType bounds[6];
186 theRenderer->ComputeVisiblePropBounds(bounds);
188 vtkFloatingPointType center[3];
189 center[0] = (bounds[0] + bounds[1])/2.0;
190 center[1] = (bounds[2] + bounds[3])/2.0;
191 center[2] = (bounds[4] + bounds[5])/2.0;
193 vtkFloatingPointType width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
194 (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
195 (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
197 vtkFloatingPointType distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
198 (position[1]-center[1])*(position[1]-center[1]) +
199 (position[2]-center[2])*(position[2]-center[2]));
201 vtkFloatingPointType range[2] = {distance - width/2.0, distance + width/2.0};
203 // Do not let the range behind the camera throw off the calculation.
204 if (range[0] < 0.0) range[0] = 0.0;
206 anActiveCamera->SetClippingRange( range );
209 /*!Compute trihedron size.*/
211 ComputeTrihedronSize( vtkRenderer* theRenderer,
212 vtkFloatingPointType& theNewSize,
213 const vtkFloatingPointType theSize,
214 const vtkFloatingPointType theSizeInPercents )
216 // calculating diagonal of visible props of the renderer
217 vtkFloatingPointType bnd[ 6 ];
218 if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
220 bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
221 bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
223 vtkFloatingPointType aLength = 0;
225 aLength = bnd[ 1 ]-bnd[ 0 ];
226 aLength = std::max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
227 aLength = std::max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
229 static vtkFloatingPointType EPS_SIZE = 5.0E-3;
230 theNewSize = aLength * theSizeInPercents / 100.0;
232 // if the new trihedron size have sufficient difference, then apply the value
233 return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
234 fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;
237 bool IsBBEmpty(vtkRenderer* theRenderer)
242 vtkFloatingPointType aNewBndBox[6];
243 aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
244 aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
246 // iterate through displayed objects and set size if necessary
247 VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
248 vtkActorCollection* anActors = aCopy.GetActors();
249 anActors->InitTraversal();
251 while(vtkActor* anAct = anActors->GetNextActor())
252 //if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
253 if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(anAct))
254 if(anActor->GetVisibility() && !anActor->IsInfinitive())
256 vtkFloatingPointType *aBounds = anActor->GetBounds();
257 if(aBounds[0] > -VTK_LARGE_FLOAT && aBounds[1] < VTK_LARGE_FLOAT &&
258 aBounds[2] > -VTK_LARGE_FLOAT && aBounds[3] < VTK_LARGE_FLOAT &&
259 aBounds[4] > -VTK_LARGE_FLOAT && aBounds[5] < VTK_LARGE_FLOAT)
266 bool ComputeBBCenter(vtkRenderer* theRenderer, vtkFloatingPointType theCenter[3])
268 theCenter[0] = theCenter[1] = theCenter[2] = 0.0;
273 vtkFloatingPointType aNewBndBox[6];
274 aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
275 aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
277 // iterate through displayed objects and set size if necessary
278 VTK::ActorCollectionCopy aCopy(theRenderer->GetActors());
279 vtkActorCollection* anActors = aCopy.GetActors();
280 anActors->InitTraversal();
282 while(vtkActor* anAct = anActors->GetNextActor())
284 //if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct))
285 if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(anAct))
287 if(anActor->GetVisibility() && !anActor->IsInfinitive())
289 vtkFloatingPointType *aBounds = anActor->GetBounds();
290 if(aBounds[0] > -VTK_LARGE_FLOAT && aBounds[1] < VTK_LARGE_FLOAT &&
291 aBounds[2] > -VTK_LARGE_FLOAT && aBounds[3] < VTK_LARGE_FLOAT &&
292 aBounds[4] > -VTK_LARGE_FLOAT && aBounds[5] < VTK_LARGE_FLOAT)
294 for(int i = 0; i < 5; i = i + 2){
295 if(aBounds[i] < aNewBndBox[i])
296 aNewBndBox[i] = aBounds[i];
297 if(aBounds[i+1] > aNewBndBox[i+1])
298 aNewBndBox[i+1] = aBounds[i+1];
308 // null bounding box => the center is (0,0,0)
312 if(aNewBndBox[0] > -VTK_LARGE_FLOAT && aNewBndBox[1] < VTK_LARGE_FLOAT &&
313 aNewBndBox[2] > -VTK_LARGE_FLOAT && aNewBndBox[3] < VTK_LARGE_FLOAT &&
314 aNewBndBox[4] > -VTK_LARGE_FLOAT && aNewBndBox[5] < VTK_LARGE_FLOAT)
316 static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
318 vtkFloatingPointType aLength = aNewBndBox[1]-aNewBndBox[0];
319 aLength = std::max((aNewBndBox[3]-aNewBndBox[2]),aLength);
320 aLength = std::max((aNewBndBox[5]-aNewBndBox[4]),aLength);
322 if(aLength < MIN_DISTANCE)
325 vtkFloatingPointType aWidth =
326 sqrt((aNewBndBox[1]-aNewBndBox[0])*(aNewBndBox[1]-aNewBndBox[0]) +
327 (aNewBndBox[3]-aNewBndBox[2])*(aNewBndBox[3]-aNewBndBox[2]) +
328 (aNewBndBox[5]-aNewBndBox[4])*(aNewBndBox[5]-aNewBndBox[4]));
330 if(aWidth < MIN_DISTANCE)
333 theCenter[0] = (aNewBndBox[0] + aNewBndBox[1])/2.0;
334 theCenter[1] = (aNewBndBox[2] + aNewBndBox[3])/2.0;
335 theCenter[2] = (aNewBndBox[4] + aNewBndBox[5])/2.0;
342 vtkFloatingPointType aBounds[6];
343 int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
344 printf("aNewBndBox[0] = %f, aNewBndBox[1] = %f,\naNewBndBox[2] = %f, aNewBndBox[3] = %f,\naNewBndBox[4] = %f, aNewBndBox[5] = %f\n",
345 aBounds[0],aBounds[1],aBounds[2],aBounds[3],aBounds[4],aBounds[5]);
346 printf("aCount = %d\n",aCount);
349 static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
351 vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
352 aLength = max((aBounds[3]-aBounds[2]),aLength);
353 aLength = max((aBounds[5]-aBounds[4]),aLength);
355 if(aLength < MIN_DISTANCE)
358 vtkFloatingPointType aWidth =
359 sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
360 (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
361 (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
363 if(aWidth < MIN_DISTANCE)
366 theCenter[0] = (aBounds[0] + aBounds[1])/2.0;
367 theCenter[1] = (aBounds[2] + aBounds[3])/2.0;
368 theCenter[2] = (aBounds[4] + aBounds[5])/2.0;