Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[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 <vtkImplicitFunction.h>
44 #include <vtkImplicitFunctionCollection.h>
45 #include <vtkMath.h>
46
47 static int MYVTKDEBUG = 0;
48
49 #ifdef _DEBUG_
50 static int MYDEBUG = 0;
51 #else
52 static int MYDEBUG = 0;
53 #endif
54
55 VISU_PipeLine
56 ::VISU_PipeLine():
57   myMapper(vtkDataSetMapper::New()),
58   myExtractGeometry(SALOME_ExtractGeometry::New())
59 {
60   if(MYDEBUG) MESSAGE("VISU_PipeLine::VISU_PipeLine - "<<this);
61   SetDebug(MYVTKDEBUG);
62
63   myMapper->Delete();
64
65   // Clipping planes
66   myExtractGeometry->Delete();
67   myExtractGeometry->SetStoreMapping(true);
68
69   vtkImplicitBoolean* anImplicitBoolean = vtkImplicitBoolean::New();
70   myExtractGeometry->SetImplicitFunction(anImplicitBoolean);
71   anImplicitBoolean->SetOperationTypeToIntersection();
72   anImplicitBoolean->Delete();
73
74   myIsShrinkable = false;
75
76 }
77
78 VISU_PipeLine
79 ::~VISU_PipeLine()
80 {
81   if(MYDEBUG) MESSAGE("VISU_PipeLine::~VISU_PipeLine - "<<this);
82 }
83
84 // Turn debugging output on.
85 void
86 VISU_PipeLine
87 ::DebugOn()
88 {
89   myExtractGeometry->DebugOn();
90   Superclass::DebugOn();
91 }
92
93 // Turn debugging output off.
94 void
95 VISU_PipeLine
96 ::DebugOff()
97 {
98   myExtractGeometry->DebugOff();
99   Superclass::DebugOff();
100 }
101
102 void 
103 VISU_PipeLine
104 ::ShallowCopy(VISU_PipeLine *thePipeLine)
105 {
106   SetImplicitFunction(thePipeLine->GetImplicitFunction());
107
108   // To restore mapper input from pipeline
109   vtkDataSet* aDatsSet = myMapper->GetInput();
110   GetMapper()->ShallowCopy(thePipeLine->GetMapper());
111   myMapper->SetInput(aDatsSet);
112
113   Build();
114 }
115
116 void
117 VISU_PipeLine
118 ::SameAs(VISU_PipeLine *thePipeLine)
119 {
120   ShallowCopy(thePipeLine);
121   SetImplicitFunction(vtkImplicitBoolean::New());
122   GetImplicitFunction()->Delete();
123 }
124
125 TInput* 
126 VISU_PipeLine
127 ::GetInput() const
128 {
129   return myInput.GetPointer();
130 }
131
132 vtkDataSet* 
133 VISU_PipeLine
134 ::GetOutput()
135 {
136   return GetMapper()->GetInput();
137 }
138
139 TInput* 
140 VISU_PipeLine
141 ::GetInput2() const
142 {
143   vtkUnstructuredGrid* aDataSet = myExtractGeometry->GetOutput();
144   aDataSet->Update();
145   return aDataSet;
146 }
147
148 void
149 VISU_PipeLine
150 ::SetInput(TInput* theInput)
151 {
152   if(theInput)
153     theInput->Update();
154
155   myExtractGeometry->SetInput(theInput);
156   myInput = theInput;
157
158   Modified();
159 }
160
161 VISU_PipeLine::TMapper* 
162 VISU_PipeLine
163 ::GetMapper()
164 {
165   if(GetInput()){
166     if(!myMapper->GetInput()){
167       GetInput2()->Update();
168       Build();
169     }
170     myMapper->Update();
171   }
172   return myMapper.GetPointer();
173 }
174
175 void 
176 VISU_PipeLine
177 ::Update()
178 {
179   myMapper->Update();
180 }
181
182 int
183 VISU_PipeLine
184 ::CheckAvailableMemory(const vtkFloatingPointType& theSize)
185 {
186   try{
187     if(theSize > ULONG_MAX) return 0;
188     size_t aSize = size_t(theSize);
189     char *aCheck = new char[aSize];
190     if(aCheck) delete [] aCheck;
191     if(MYDEBUG && aCheck == NULL)
192       MESSAGE("CheckAvailableMemory("<<theSize<<") - cannot alloacate such amount of memory!!!");
193     return aCheck != NULL;
194     //return theSize < 1000*1024*1024;
195   }catch(std::bad_alloc& exc){
196     if(MYDEBUG)
197       MESSAGE("CheckAvailableMemory("<<theSize<<") " << exc.what());
198   } catch(...) {
199     if(MYDEBUG)
200       MESSAGE("CheckAvailableMemory("<<theSize<<") - unexpected exception was caught!!!");
201   }
202   return 0;
203 }
204
205 vtkFloatingPointType
206 VISU_PipeLine
207 ::GetAvailableMemory(vtkFloatingPointType theSize, 
208                      vtkFloatingPointType theMinSize)
209 {
210   while(!CheckAvailableMemory(theSize))
211     if(theSize > theMinSize)
212       theSize /= 2;
213     else
214       return 0;
215   return theSize;
216 }
217
218 //------------------------ Clipping planes -----------------------------------
219 bool 
220 VISU_PipeLine
221 ::AddClippingPlane(vtkPlane* thePlane)
222 {
223   if (thePlane) {
224     if (vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()) {
225       vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
226       aFunction->AddItem(thePlane);
227
228       // Check, that at least one cell present after clipping.
229       // This check was introduced because of bug IPAL8849.
230       vtkUnstructuredGrid* aClippedGrid = GetInput2();
231       if (aClippedGrid->GetNumberOfCells() < 1) {
232         return false;
233       }
234     }
235   }
236   return true;
237 }
238
239 vtkPlane* 
240 VISU_PipeLine
241 ::GetClippingPlane(vtkIdType theID) const
242 {
243   vtkPlane* aPlane = NULL;
244   if(theID >= 0 && theID < GetNumberOfClippingPlanes()){
245     if(vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()){
246       vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
247       vtkImplicitFunction* aFun = NULL;
248       aFunction->InitTraversal();
249       for(vtkIdType anID = 0; anID <= theID; anID++)
250         aFun = aFunction->GetNextItem();
251       aPlane = dynamic_cast<vtkPlane*>(aFun);
252     }
253   }
254   return aPlane;
255 }
256
257 void
258 VISU_PipeLine
259 ::RemoveAllClippingPlanes()
260 {
261   if(vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()){
262     vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
263     aFunction->RemoveAllItems();
264     aBoolean->Modified(); // VTK bug
265   }
266 }
267
268 vtkIdType
269 VISU_PipeLine
270 ::GetNumberOfClippingPlanes() const
271 {
272   if(vtkImplicitBoolean* aBoolean = myExtractGeometry->GetImplicitBoolean()){
273     vtkImplicitFunctionCollection* aFunction = aBoolean->GetFunction();
274     return aFunction->GetNumberOfItems();
275   }
276   return 0;
277 }
278
279 static
280 void
281 ComputeBoundsParam (vtkDataSet* theDataSet,
282                     vtkFloatingPointType theDirection[3], 
283                     vtkFloatingPointType theMinPnt[3],
284                     vtkFloatingPointType& theMaxBoundPrj, 
285                     vtkFloatingPointType& theMinBoundPrj)
286 {
287   vtkFloatingPointType aBounds[6];
288   theDataSet->GetBounds(aBounds);
289
290   //Enlarge bounds in order to avoid conflicts of precision
291   for(int i = 0; i < 6; i += 2){
292     static double EPS = 1.0E-3;
293     vtkFloatingPointType aDelta = (aBounds[i+1] - aBounds[i])*EPS;
294     aBounds[i] -= aDelta;
295     aBounds[i+1] += aDelta;
296   }
297
298   vtkFloatingPointType aBoundPoints[8][3] = { {aBounds[0],aBounds[2],aBounds[4]},
299                                               {aBounds[1],aBounds[2],aBounds[4]},
300                                               {aBounds[0],aBounds[3],aBounds[4]},
301                                               {aBounds[1],aBounds[3],aBounds[4]},
302                                               {aBounds[0],aBounds[2],aBounds[5]},
303                                               {aBounds[1],aBounds[2],aBounds[5]},
304                                               {aBounds[0],aBounds[3],aBounds[5]},
305                                               {aBounds[1],aBounds[3],aBounds[5]}};
306
307   int aMaxId = 0, aMinId = aMaxId;
308   theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]);
309   theMinBoundPrj = theMaxBoundPrj;
310   for(int i = 1; i < 8; i++){
311     vtkFloatingPointType aTmp = vtkMath::Dot(theDirection,aBoundPoints[i]);
312     if(theMaxBoundPrj < aTmp){
313       theMaxBoundPrj = aTmp;
314       aMaxId = i;
315     }
316     if(theMinBoundPrj > aTmp){
317       theMinBoundPrj = aTmp;
318       aMinId = i;
319     }
320   }
321   vtkFloatingPointType *aMinPnt = aBoundPoints[aMaxId];
322   theMinPnt[0] = aMinPnt[0];
323   theMinPnt[1] = aMinPnt[1];
324   theMinPnt[2] = aMinPnt[2];
325 }
326
327 static
328 void
329 DistanceToPosition(vtkDataSet* theDataSet,
330                    vtkFloatingPointType theDirection[3], 
331                    vtkFloatingPointType theDist, 
332                    vtkFloatingPointType thePos[3])
333 {
334   vtkFloatingPointType aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
335   ComputeBoundsParam(theDataSet,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
336   vtkFloatingPointType aLength = (aMaxBoundPrj-aMinBoundPrj)*theDist;
337   thePos[0] = aMinPnt[0]-theDirection[0]*aLength;
338   thePos[1] = aMinPnt[1]-theDirection[1]*aLength;
339   thePos[2] = aMinPnt[2]-theDirection[2]*aLength;
340 }
341
342 static
343 void
344 PositionToDistance (vtkDataSet* theDataSet,
345                     vtkFloatingPointType theDirection[3], 
346                     vtkFloatingPointType thePos[3], 
347                     vtkFloatingPointType& theDist)
348 {
349   vtkFloatingPointType aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
350   ComputeBoundsParam(theDataSet,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
351   vtkFloatingPointType aPrj = vtkMath::Dot(theDirection,thePos);
352   theDist = (aPrj-aMinBoundPrj)/(aMaxBoundPrj-aMinBoundPrj);
353 }
354
355 void
356 VISU_PipeLine
357 ::SetPlaneParam(vtkFloatingPointType theDir[3], 
358                 vtkFloatingPointType theDist, 
359                 vtkPlane* thePlane)
360 {
361   thePlane->SetNormal(theDir);
362   vtkFloatingPointType anOrigin[3];
363   ::DistanceToPosition(GetInput(),theDir,theDist,anOrigin);
364   thePlane->SetOrigin(anOrigin);
365 }
366
367 void
368 VISU_PipeLine
369 ::GetPlaneParam(vtkFloatingPointType theDir[3], 
370                 vtkFloatingPointType& theDist, 
371                 vtkPlane* thePlane)
372 {
373   thePlane->GetNormal(theDir);
374
375   vtkFloatingPointType anOrigin[3];
376   thePlane->GetOrigin(anOrigin);
377   ::PositionToDistance(GetInput(),theDir,anOrigin,theDist);
378 }
379
380 //=======================================================================
381 //function : IsPlanarInput
382 //purpose  :
383 //=======================================================================
384 bool
385 VISU_PipeLine
386 ::IsPlanarInput() const
387 {
388   vtkFloatingPointType aBounds[6];
389   GetInput()->GetBounds( aBounds ); // xmin,xmax, ymin,ymax, zmin,zmax
390   if (fabs( aBounds[0] - aBounds[1] ) <= FLT_MIN ||
391       fabs( aBounds[2] - aBounds[3] ) <= FLT_MIN ||
392       fabs( aBounds[4] - aBounds[5] ) <= FLT_MIN )
393     return true;
394
395   return false;
396 }
397
398 //=======================================================================
399 vtkIdType 
400 VISU_PipeLine
401 ::GetNodeObjID(vtkIdType theID)
402 {
403   vtkIdType anID = myExtractGeometry->GetNodeObjId(theID);
404   return myIDMapper->GetNodeObjID(anID);
405 }
406
407 vtkIdType 
408 VISU_PipeLine
409 ::GetNodeVTKID(vtkIdType theID)
410 {
411   vtkIdType anID = myIDMapper->GetNodeVTKID(theID);
412   return myExtractGeometry->GetNodeVTKId(anID);
413 }
414
415 vtkFloatingPointType* 
416 VISU_PipeLine
417 ::GetNodeCoord(int theObjID)
418 {
419   return myIDMapper->GetNodeCoord(theObjID);
420 }
421
422 //=======================================================================
423 vtkIdType 
424 VISU_PipeLine
425 ::GetElemObjID(vtkIdType theID)
426 {
427   vtkIdType anID = myExtractGeometry->GetElemObjId(theID);
428   return myIDMapper->GetElemObjID(anID);
429 }
430
431 vtkIdType
432 VISU_PipeLine
433 ::GetElemVTKID(vtkIdType theID)
434 {
435   vtkIdType anID = myIDMapper->GetElemVTKID(theID);
436   return myExtractGeometry->GetElemVTKId(anID);
437 }
438
439 vtkCell* 
440 VISU_PipeLine
441 ::GetElemCell(vtkIdType  theObjID)
442 {
443   return myIDMapper->GetElemCell(theObjID);
444 }
445
446 //=======================================================================
447 void
448 VISU_PipeLine
449 ::SetIDMapper(const VISU::PIDMapper& theIDMapper)
450 {
451   myIDMapper = theIDMapper;
452   SetInput(myIDMapper->GetVTKOutput());
453 }
454
455 const VISU::PIDMapper&  
456 VISU_PipeLine
457 ::GetIDMapper() const
458 {
459   return myIDMapper;
460 }
461
462 //=======================================================================
463 void
464 VISU_PipeLine
465 ::SetImplicitFunction(vtkImplicitFunction *theFunction)
466 {
467   myExtractGeometry->SetImplicitFunction(theFunction);
468
469
470 vtkImplicitFunction * 
471 VISU_PipeLine
472 ::GetImplicitFunction()
473 {
474   return myExtractGeometry->GetImplicitFunction();
475 }
476
477 SALOME_ExtractGeometry*
478 VISU_PipeLine
479 ::GetExtractGeometryFilter()
480 {
481   return myExtractGeometry.GetPointer();
482