Salome HOME
Update Help for VISU module.
[modules/visu.git] / src / PIPELINE / VISU_PipeLine.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
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:    VISU_PipeLine.cxx
25 // Author:  Alexey PETROV
26 // Module : VISU
27
28
29 #include "VISU_PipeLine.hxx"
30 #include "VISU_PipeLineUtils.hxx"
31
32 #include "SALOME_ExtractGeometry.h"
33
34 #include <float.h>
35
36 #include <vtkObjectFactory.h>
37 #include <vtkDataSetMapper.h>
38 #include <vtkUnstructuredGrid.h>
39
40 #include <vtkPlane.h>
41 #include <vtkExtractGeometry.h>
42 #include <vtkImplicitBoolean.h>
43 #include <vtkImplicitFunctionCollection.h>
44 #include <vtkMath.h>
45
46 static int MYVTKDEBUG = 0;
47
48 #ifdef _DEBUG_
49 static int MYDEBUG = 0;
50 #else
51 static int MYDEBUG = 0;
52 #endif
53
54 VISU_PipeLine::VISU_PipeLine()
55 {
56   if(MYDEBUG) MESSAGE("VISU_PipeLine - "<<this);
57   // Clipping planes
58   myExtractGeometry = SALOME_ExtractGeometry::New();
59   //myExtractGeometry->SetReleaseDataFlag(true);
60   myExtractGeometry->Delete();
61   //myExtractGeometry->DebugOn();
62
63   vtkImplicitBoolean* anImplicitBoolean = vtkImplicitBoolean::New();
64   myExtractGeometry->SetImplicitBoolean(anImplicitBoolean);
65   anImplicitBoolean->SetOperationTypeToIntersection();
66   anImplicitBoolean->Delete();
67
68   // Mapper
69   myMapper = TMapper::New();
70   myInput = NULL;
71
72   myIsShrinkable = false;
73
74   SetDebug(MYVTKDEBUG);
75 }
76
77 VISU_PipeLine::~VISU_PipeLine()
78 {
79   if(MYDEBUG) MESSAGE("~VISU_PipeLine - "<<this);
80   myMapper->Delete();
81 }
82
83 void VISU_PipeLine::ShallowCopy(VISU_PipeLine *thePipeLine){
84   SetInput(thePipeLine->GetInput());
85   myMapper->ShallowCopy(thePipeLine->GetMapper());
86   myExtractGeometry->SetImplicitBoolean(thePipeLine->myExtractGeometry->GetImplicitBoolean());
87   Build();
88 }
89
90 void VISU_PipeLine::SameAs(VISU_PipeLine *thePipeLine){
91   ShallowCopy(thePipeLine);
92   myExtractGeometry->SetImplicitBoolean(vtkImplicitBoolean::New());
93   myExtractGeometry->GetImplicitBoolean()->Delete();
94 }
95
96 TInput* VISU_PipeLine::GetInput() const
97 {
98   return myInput;
99 }
100
101 TInput* VISU_PipeLine::GetInput2() const
102 {
103   vtkUnstructuredGrid* aDataSet = myExtractGeometry->GetOutput();
104   aDataSet->Update();
105   return aDataSet;
106 }
107
108 void VISU_PipeLine::SetInput(TInput* theInput)
109 {
110   myExtractGeometry->SetInput(theInput);
111   if((myInput = theInput))
112     myInput->Update();
113
114   Modified();
115 }
116
117 VISU_PipeLine::TMapper* VISU_PipeLine::GetMapper()
118 {
119   if(GetInput()){
120     if(!myMapper->GetInput()){
121       GetInput2()->Update();
122       Build();
123     }
124     myMapper->Update();
125   }
126   return myMapper;
127 }
128
129 void VISU_PipeLine::Update()
130 {
131   myMapper->Update();
132 }
133
134 int VISU_PipeLine::CheckAvailableMemory(const float& theSize)
135 {
136   try{
137     if(theSize > ULONG_MAX) return 0;
138     size_t aSize = size_t(theSize);
139     char *aCheck = new char[aSize];
140     if(aCheck) delete [] aCheck;
141     if(MYDEBUG && aCheck == NULL)
142       MESSAGE("CheckAvailableMemory("<<theSize<<") - cannot alloacate such amount of memory!!!");
143     return aCheck != NULL;
144     //return theSize < 1000*1024*1024;
145   }catch(std::bad_alloc& exc){
146     if(MYDEBUG)
147       MESSAGE("CheckAvailableMemory("<<theSize<<") " << exc.what());
148   } catch(...) {
149     if(MYDEBUG)
150       MESSAGE("CheckAvailableMemory("<<theSize<<") - unexpected exception was caught!!!");
151   }
152   return 0;
153 }
154
155 float VISU_PipeLine::GetAvailableMemory(float theSize, float theMinSize)
156 {
157   while(!CheckAvailableMemory(theSize))
158     if(theSize > theMinSize)
159       theSize /= 2;
160     else
161       return 0;
162   return theSize;
163 }
164
165 //------------------------ Clipping planes -----------------------------------
166
167 bool VISU_PipeLine::AddClippingPlane(vtkPlane* thePlane)
168 {
169   if (thePlane) {
170     if (vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()) {
171       vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
172       aFunction->AddItem(thePlane);
173
174       // Check, that at least one cell present after clipping.
175       // This check was introduced because of bug IPAL8849.
176       vtkUnstructuredGrid* aClippedGrid = GetInput2();
177       if (aClippedGrid->GetNumberOfCells() < 1) {
178         return false;
179       }
180     }
181   }
182   return true;
183 }
184
185 vtkPlane* VISU_PipeLine::GetClippingPlane(vtkIdType theID) const
186 {
187   vtkPlane* aPlane = NULL;
188   if(theID >= 0 && theID < GetNumberOfClippingPlanes()){
189     if(vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()){
190       vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
191       vtkImplicitFunction* aFun = NULL;
192       aFunction->InitTraversal();
193       for(vtkIdType anID = 0; anID <= theID; anID++)
194         aFun = aFunction->GetNextItem();
195       aPlane = dynamic_cast<vtkPlane*>(aFun);
196     }
197   }
198   return aPlane;
199 }
200
201 void VISU_PipeLine::RemoveAllClippingPlanes()
202 {
203   if(vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()){
204     vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
205     aFunction->RemoveAllItems();
206     aBoolean->Modified(); // VTK bug
207   }
208 }
209
210 vtkIdType VISU_PipeLine::GetNumberOfClippingPlanes() const
211 {
212   if(vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()){
213     vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
214     return aFunction->GetNumberOfItems();
215   }
216   return 0;
217 }
218
219 static void ComputeBoundsParam (vtkDataSet* theDataSet,
220                                 float theDirection[3], float theMinPnt[3],
221                                 float& theMaxBoundPrj, float& theMinBoundPrj)
222 {
223   float aBounds[6];
224   theDataSet->GetBounds(aBounds);
225
226   //Enlarge bounds in order to avoid conflicts of precision
227   for(int i = 0; i < 6; i += 2){
228     static double EPS = 1.0E-3;
229     float aDelta = (aBounds[i+1] - aBounds[i])*EPS;
230     aBounds[i] -= aDelta;
231     aBounds[i+1] += aDelta;
232   }
233
234   float aBoundPoints[8][3] = { {aBounds[0],aBounds[2],aBounds[4]},
235                                {aBounds[1],aBounds[2],aBounds[4]},
236                                {aBounds[0],aBounds[3],aBounds[4]},
237                                {aBounds[1],aBounds[3],aBounds[4]},
238                                {aBounds[0],aBounds[2],aBounds[5]},
239                                {aBounds[1],aBounds[2],aBounds[5]},
240                                {aBounds[0],aBounds[3],aBounds[5]},
241                                {aBounds[1],aBounds[3],aBounds[5]}};
242
243   int aMaxId = 0, aMinId = aMaxId;
244   theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]);
245   theMinBoundPrj = theMaxBoundPrj;
246   for(int i = 1; i < 8; i++){
247     float aTmp = vtkMath::Dot(theDirection,aBoundPoints[i]);
248     if(theMaxBoundPrj < aTmp){
249       theMaxBoundPrj = aTmp;
250       aMaxId = i;
251     }
252     if(theMinBoundPrj > aTmp){
253       theMinBoundPrj = aTmp;
254       aMinId = i;
255     }
256   }
257   float *aMinPnt = aBoundPoints[aMaxId];
258   theMinPnt[0] = aMinPnt[0];
259   theMinPnt[1] = aMinPnt[1];
260   theMinPnt[2] = aMinPnt[2];
261 }
262
263 static void DistanceToPosition (vtkDataSet* theDataSet,
264                                 float theDirection[3], float theDist, float thePos[3])
265 {
266   float aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
267   ComputeBoundsParam(theDataSet,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
268   float aLength = (aMaxBoundPrj-aMinBoundPrj)*theDist;
269   thePos[0] = aMinPnt[0]-theDirection[0]*aLength;
270   thePos[1] = aMinPnt[1]-theDirection[1]*aLength;
271   thePos[2] = aMinPnt[2]-theDirection[2]*aLength;
272 }
273
274 static void PositionToDistance (vtkDataSet* theDataSet,
275                                 float theDirection[3], float thePos[3], float& theDist)
276 {
277   float aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
278   ComputeBoundsParam(theDataSet,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
279   float aPrj = vtkMath::Dot(theDirection,thePos);
280   theDist = (aPrj-aMinBoundPrj)/(aMaxBoundPrj-aMinBoundPrj);
281 }
282
283 void VISU_PipeLine::SetPlaneParam (float theDir[3], float theDist, vtkPlane* thePlane)
284 {
285   thePlane->SetNormal(theDir);
286   float anOrigin[3];
287   ::DistanceToPosition(GetInput(),theDir,theDist,anOrigin);
288   thePlane->SetOrigin(anOrigin);
289 }
290
291 void VISU_PipeLine::GetPlaneParam (float theDir[3], float& theDist, vtkPlane* thePlane)
292 {
293   thePlane->GetNormal(theDir);
294
295   float anOrigin[3];
296   thePlane->GetOrigin(anOrigin);
297   ::PositionToDistance(GetInput(),theDir,anOrigin,theDist);
298 }
299
300 //=======================================================================
301 //function : IsPlanarInput
302 //purpose  :
303 //=======================================================================
304 bool VISU_PipeLine::IsPlanarInput() const
305 {
306   float aBounds[6];
307   GetInput()->GetBounds( aBounds ); // xmin,xmax, ymin,ymax, zmin,zmax
308   if (fabs( aBounds[0] - aBounds[1] ) <= FLT_MIN ||
309       fabs( aBounds[2] - aBounds[3] ) <= FLT_MIN ||
310       fabs( aBounds[4] - aBounds[5] ) <= FLT_MIN )
311     return true;
312
313   return false;
314 }