1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
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.
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.
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
17 // See http://www.salome-platform.org/
20 #include "VTKViewer_Utilities.h"
21 #include "VTKViewer_Actor.h"
27 #include <vtkCamera.h>
28 #include <vtkRenderer.h>
29 #include <vtkRenderWindow.h>
33 /*!@see vtkRenderer::ResetCamera(vtkFloatingPointType bounds[6]) method*/
35 ResetCamera(vtkRenderer* theRenderer,
36 int theUsingZeroFocalPoint)
41 vtkCamera* aCamera = theRenderer->GetActiveCamera();
45 vtkFloatingPointType aBounds[6];
46 int aCount = ComputeVisiblePropBounds(theRenderer,aBounds);
48 if(theUsingZeroFocalPoint || aCount){
49 static vtkFloatingPointType MIN_DISTANCE = 1.0 / VTK_LARGE_FLOAT;
51 vtkFloatingPointType aLength = aBounds[1]-aBounds[0];
52 aLength = max((aBounds[3]-aBounds[2]),aLength);
53 aLength = max((aBounds[5]-aBounds[4]),aLength);
55 if(aLength < MIN_DISTANCE)
58 vtkFloatingPointType aWidth =
59 sqrt((aBounds[1]-aBounds[0])*(aBounds[1]-aBounds[0]) +
60 (aBounds[3]-aBounds[2])*(aBounds[3]-aBounds[2]) +
61 (aBounds[5]-aBounds[4])*(aBounds[5]-aBounds[4]));
63 if(aWidth < MIN_DISTANCE)
66 vtkFloatingPointType aViewPlaneNormal[3];
67 aCamera->GetViewPlaneNormal(aViewPlaneNormal);
69 vtkFloatingPointType aCenter[3] = {0.0, 0.0, 0.0};
70 if(!theUsingZeroFocalPoint){
71 aCenter[0] = (aBounds[0] + aBounds[1])/2.0;
72 aCenter[1] = (aBounds[2] + aBounds[3])/2.0;
73 aCenter[2] = (aBounds[4] + aBounds[5])/2.0;
75 aCamera->SetFocalPoint(aCenter[0],aCenter[1],aCenter[2]);
77 vtkFloatingPointType aViewAngle = aCamera->GetViewAngle();
78 vtkFloatingPointType aDistance = 2.0*aWidth/tan(aViewAngle*vtkMath::Pi()/360.0);
80 // check view-up vector against view plane normal
81 vtkFloatingPointType aViewUp[3];
82 aCamera->GetViewUp(aViewUp);
83 if(fabs(vtkMath::Dot(aViewUp,aViewPlaneNormal)) > 0.999)
84 aCamera->SetViewUp(-aViewUp[2], aViewUp[0], aViewUp[1]);
87 aCamera->SetPosition(aCenter[0]+aDistance*aViewPlaneNormal[0],
88 aCenter[1]+aDistance*aViewPlaneNormal[1],
89 aCenter[2]+aDistance*aViewPlaneNormal[2]);
91 // find size of the window
92 int* aWinSize = theRenderer->GetSize();
93 if(aWinSize[0] < aWinSize[1])
94 aWidth *= vtkFloatingPointType(aWinSize[1])/vtkFloatingPointType(aWinSize[0]);
96 if(theUsingZeroFocalPoint)
99 aCamera->SetParallelScale(aWidth/2.0);
102 ResetCameraClippingRange(theRenderer);
105 /*! Compute the bounds of the visible props*/
107 ComputeVisiblePropBounds(vtkRenderer* theRenderer,
108 vtkFloatingPointType theBounds[6])
112 theBounds[0] = theBounds[2] = theBounds[4] = VTK_LARGE_FLOAT;
113 theBounds[1] = theBounds[3] = theBounds[5] = -VTK_LARGE_FLOAT;
115 // loop through all props
116 vtkActorCollection* aCollection = theRenderer->GetActors();
117 aCollection->InitTraversal();
118 while (vtkActor* aProp = aCollection->GetNextActor()) {
119 // if it's invisible, or has no geometry, we can skip the rest
120 if(aProp->GetVisibility() && aProp->GetMapper()){
121 if(VTKViewer_Actor* anActor = VTKViewer_Actor::SafeDownCast(aProp))
122 if(anActor->IsInfinitive())
125 vtkFloatingPointType *aBounds = aProp->GetBounds();
126 static vtkFloatingPointType MAX_DISTANCE = 0.9*VTK_LARGE_FLOAT;
127 // make sure we haven't got bogus bounds
128 if ( aBounds != NULL &&
129 aBounds[0] > -MAX_DISTANCE && aBounds[1] < MAX_DISTANCE &&
130 aBounds[2] > -MAX_DISTANCE && aBounds[3] < MAX_DISTANCE &&
131 aBounds[4] > -MAX_DISTANCE && aBounds[5] < MAX_DISTANCE )
135 theBounds[0] = min(aBounds[0],theBounds[0]);
136 theBounds[2] = min(aBounds[2],theBounds[2]);
137 theBounds[4] = min(aBounds[4],theBounds[4]);
139 theBounds[1] = max(aBounds[1],theBounds[1]);
140 theBounds[3] = max(aBounds[3],theBounds[3]);
141 theBounds[5] = max(aBounds[5],theBounds[5]);
149 /*!@see vtkRenderer::ResetCameraClippingRange(vtkFloatingPointType bounds[6]) method*/
151 ResetCameraClippingRange(vtkRenderer* theRenderer)
153 if(!theRenderer || !theRenderer->VisibleActorCount()) return;
155 vtkCamera* anActiveCamera = theRenderer->GetActiveCamera();
156 if( anActiveCamera == NULL ){
160 // Find the plane equation for the camera view plane
161 vtkFloatingPointType vn[3];
162 anActiveCamera->GetViewPlaneNormal(vn);
163 vtkFloatingPointType position[3];
164 anActiveCamera->GetPosition(position);
166 vtkFloatingPointType bounds[6];
167 theRenderer->ComputeVisiblePropBounds(bounds);
169 vtkFloatingPointType center[3];
170 center[0] = (bounds[0] + bounds[1])/2.0;
171 center[1] = (bounds[2] + bounds[3])/2.0;
172 center[2] = (bounds[4] + bounds[5])/2.0;
174 vtkFloatingPointType width = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
175 (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
176 (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
178 vtkFloatingPointType distance = sqrt((position[0]-center[0])*(position[0]-center[0]) +
179 (position[1]-center[1])*(position[1]-center[1]) +
180 (position[2]-center[2])*(position[2]-center[2]));
182 vtkFloatingPointType range[2] = {distance - width/2.0, distance + width/2.0};
184 // Do not let the range behind the camera throw off the calculation.
185 if (range[0] < 0.0) range[0] = 0.0;
187 anActiveCamera->SetClippingRange( range );
190 /*!Compute trihedron size.*/
192 ComputeTrihedronSize( vtkRenderer* theRenderer,
193 vtkFloatingPointType& theNewSize,
194 const vtkFloatingPointType theSize,
195 const vtkFloatingPointType theSizeInPercents )
197 // calculating diagonal of visible props of the renderer
198 vtkFloatingPointType bnd[ 6 ];
199 if ( ComputeVisiblePropBounds( theRenderer, bnd ) == 0 )
201 bnd[ 1 ] = bnd[ 3 ] = bnd[ 5 ] = 100;
202 bnd[ 0 ] = bnd[ 2 ] = bnd[ 4 ] = 0;
204 vtkFloatingPointType aLength = 0;
206 aLength = bnd[ 1 ]-bnd[ 0 ];
207 aLength = max( ( bnd[ 3 ] - bnd[ 2 ] ),aLength );
208 aLength = max( ( bnd[ 5 ] - bnd[ 4 ] ),aLength );
210 static vtkFloatingPointType EPS_SIZE = 5.0E-3;
211 theNewSize = aLength * theSizeInPercents / 100.0;
213 // if the new trihedron size have sufficient difference, then apply the value
214 return fabs( theNewSize - theSize) > theSize * EPS_SIZE ||
215 fabs( theNewSize-theSize ) > theNewSize * EPS_SIZE;