Salome HOME
Merge from branch CCRT_Port_V220.
[modules/kernel.git] / src / VTKFilter / SALOME_GeometryFilter.cxx
1 //  SALOME OBJECT : kernel of SALOME component
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   : SALOME_GeometryFilter.cxx
25 //  Author : Michael ZORIN
26 //  Module : SALOME
27 //  $Header$
28
29 #include "SALOME_GeometryFilter.h"
30
31 #include <vtkCellArray.h>
32 #include <vtkCellData.h>
33 #include <vtkGenericCell.h>
34 #include <vtkHexahedron.h>
35 #include <vtkMergePoints.h>
36 #include <vtkObjectFactory.h>
37 #include <vtkPointData.h>
38 #include <vtkPolyData.h>
39 #include <vtkPyramid.h>
40 #include <vtkStructuredGrid.h>
41 #include <vtkTetra.h>
42 #include <vtkUnsignedCharArray.h>
43 #include <vtkUnstructuredGrid.h>
44 #include <vtkVoxel.h>
45 #include <vtkWedge.h>
46 using namespace std;
47
48 #ifdef _DEBUG_
49 static int MYDEBUG = 0;
50 static int MYDEBUGWITHFILES = 0;
51 #else
52 static int MYDEBUG = 0;
53 static int MYDEBUGWITHFILES = 0;
54 #endif
55
56 #if defined __GNUC__
57   #if __GNUC__ == 2
58     #define __GNUC_2__
59   #endif
60 #endif
61
62 vtkCxxRevisionMacro(SALOME_GeometryFilter, "$Revision$");
63 vtkStandardNewMacro(SALOME_GeometryFilter);
64
65
66 SALOME_GeometryFilter::SALOME_GeometryFilter(): 
67   myShowInside(0),
68   myStoreMapping(0)
69 {}
70
71
72 SALOME_GeometryFilter::~SALOME_GeometryFilter()
73 {}
74
75
76 void SALOME_GeometryFilter::Execute()
77 {
78   vtkDataSet *input= this->GetInput();
79   vtkIdType numCells=input->GetNumberOfCells();
80
81   if (numCells == 0)
82     {
83       return;
84     }
85   
86   if (input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID){
87     this->UnstructuredGridExecute();
88     return;
89   }else
90     vtkGeometryFilter::Execute();
91 }
92
93
94 void SALOME_GeometryFilter::SetStoreMapping(int theStoreMapping){
95   myStoreMapping = theStoreMapping;
96   this->Modified();
97 }
98
99
100 vtkIdType SALOME_GeometryFilter::GetElemObjId(int theVtkID){
101   if(myVTK2ObjIds.empty() || theVtkID > myVTK2ObjIds.size()) return -1;
102 #if defined __GNUC_2__
103   return myVTK2ObjIds[theVtkID];
104 #else
105   return myVTK2ObjIds.at(theVtkID);
106 #endif
107 }
108
109
110 void SALOME_GeometryFilter::UnstructuredGridExecute()
111 {
112   vtkUnstructuredGrid *input= (vtkUnstructuredGrid *)this->GetInput();
113   vtkCellArray *Connectivity = input->GetCells();
114   if (Connectivity == NULL) {return;}
115   vtkIdType cellId;
116   int i;
117   int allVisible;
118   vtkIdType npts = 0;
119   vtkIdType *pts = 0;
120   vtkPoints *p = input->GetPoints();
121   vtkIdType numCells=input->GetNumberOfCells();
122   vtkPointData *pd = input->GetPointData();
123   vtkCellData *cd = input->GetCellData();
124   vtkPolyData *output = this->GetOutput();
125   vtkPointData *outputPD = output->GetPointData();
126   
127   vtkCellData *outputCD = output->GetCellData();
128   vtkCellArray *Verts, *Lines, *Polys, *Strips;
129   vtkIdList *cellIds, *faceIds;
130   char *cellVis;
131   vtkIdType newCellId;
132   int faceId, *faceVerts, numFacePts;
133   float *x;
134   int PixelConvert[4], aNewPts[VTK_CELL_SIZE];
135   // ghost cell stuff
136   unsigned char  updateLevel = (unsigned char)(output->GetUpdateGhostLevel());
137   unsigned char  *cellGhostLevels = 0;  
138   
139   PixelConvert[0] = 0;
140   PixelConvert[1] = 1;
141   PixelConvert[2] = 3;
142   PixelConvert[3] = 2;
143   
144   vtkDebugMacro(<<"Executing geometry filter for unstructured grid input");
145
146   vtkDataArray* temp = 0;
147   if (cd)
148     {
149     temp = cd->GetArray("vtkGhostLevels");
150     }
151   if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR)
152     || (temp->GetNumberOfComponents() != 1))
153     {
154     vtkDebugMacro("No appropriate ghost levels field available.");
155     }
156   else
157     {
158     cellGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0);
159     }
160   
161   // Check input
162   if ( Connectivity == NULL )
163     {
164     vtkDebugMacro(<<"Nothing to extract");
165     return;
166     }
167
168   // Determine nature of what we have to do
169   cellIds = vtkIdList::New();
170   faceIds = vtkIdList::New();
171   if ( (!this->CellClipping) && (!this->PointClipping) &&
172        (!this->ExtentClipping) )
173     {
174     allVisible = 1;
175     cellVis = NULL;
176     }
177   else
178     {
179     allVisible = 0;
180     cellVis = new char[numCells];
181     }
182
183   // Just pass points through, never merge
184   output->SetPoints(input->GetPoints());
185   outputPD->PassData(pd);
186
187   outputCD->CopyAllocate(cd,numCells,numCells/2);
188
189   output->Allocate(numCells/4+1,numCells);
190   //Verts = vtkCellArray::New();
191   //Verts->Allocate(numCells/4+1,numCells);
192   //Lines = vtkCellArray::New();
193   //Lines->Allocate(numCells/4+1,numCells);
194   //Polys = vtkCellArray::New();
195   //Polys->Allocate(numCells/4+1,numCells);
196   //Strips = vtkCellArray::New();
197   //Strips->Allocate(numCells/4+1,numCells);
198   
199   // Loop over the cells determining what's visible
200   if (!allVisible)
201     {
202     for (cellId=0, Connectivity->InitTraversal(); 
203          Connectivity->GetNextCell(npts,pts); 
204          cellId++)
205       {
206       cellVis[cellId] = 1;
207       if ( this->CellClipping && cellId < this->CellMinimum ||
208            cellId > this->CellMaximum )
209         {
210         cellVis[cellId] = 0;
211         }
212       else
213         {
214         for (i=0; i < npts; i++) 
215           {
216           x = p->GetPoint(pts[i]);
217           if ( (this->PointClipping && (pts[i] < this->PointMinimum ||
218                                         pts[i] > this->PointMaximum) ) ||
219                (this->ExtentClipping && 
220                 (x[0] < this->Extent[0] || x[0] > this->Extent[1] ||
221                  x[1] < this->Extent[2] || x[1] > this->Extent[3] ||
222                  x[2] < this->Extent[4] || x[2] > this->Extent[5] )) )
223             {
224             cellVis[cellId] = 0;
225             break;
226             }//point/extent clipping
227           }//for each point
228         }//if point clipping needs checking
229       }//for all cells
230     }//if not all visible
231   
232   // Loop over all cells now that visibility is known
233   // (Have to compute visibility first for 3D cell boundarys)
234   int progressInterval = numCells/20 + 1;
235   if(myStoreMapping){
236     myVTK2ObjIds.clear();
237     myVTK2ObjIds.reserve(numCells);
238   }
239   for (cellId=0, Connectivity->InitTraversal(); 
240        Connectivity->GetNextCell(npts,pts); 
241        cellId++)
242     {
243     //Progress and abort method support
244     if ( !(cellId % progressInterval) )
245       {
246       vtkDebugMacro(<<"Process cell #" << cellId);
247       this->UpdateProgress ((float)cellId/numCells);
248       }
249
250     // Handle ghost cells here.  Another option was used cellVis array.
251     if (cellGhostLevels && cellGhostLevels[cellId] > updateLevel)
252       { // Do not create surfaces in outer ghost cells.
253       continue;
254       }
255     
256     if (allVisible || cellVis[cellId])  //now if visible extract geometry
257       {
258       //special code for nonlinear cells - rarely occurs, so right now it
259       //is slow.
260       vtkIdType aCellType = input->GetCellType(cellId);
261       switch (aCellType)
262         {
263         case VTK_EMPTY_CELL:
264           break;
265
266         case VTK_VERTEX:
267         case VTK_POLY_VERTEX:
268           newCellId = output->InsertNextCell(aCellType,npts,pts);
269           if(myStoreMapping){
270             myVTK2ObjIds.push_back(cellId); //apo
271           }
272           outputCD->CopyData(cd,cellId,newCellId);
273           break;
274
275         case VTK_LINE: 
276         case VTK_POLY_LINE:
277           newCellId = output->InsertNextCell(VTK_LINE,npts,pts);
278           if(myStoreMapping){
279             myVTK2ObjIds.push_back(cellId); //apo
280           }
281           outputCD->CopyData(cd,cellId,newCellId);
282           break;
283
284         case VTK_TRIANGLE:
285         case VTK_QUAD:
286         case VTK_POLYGON:
287           newCellId = output->InsertNextCell(aCellType,npts,pts);
288           if(myStoreMapping){
289             myVTK2ObjIds.push_back(cellId); //apo
290           }
291           outputCD->CopyData(cd,cellId,newCellId);
292           break;
293
294         case VTK_TRIANGLE_STRIP:
295           newCellId = output->InsertNextCell(aCellType,npts,pts);
296           if(myStoreMapping){
297             myVTK2ObjIds.push_back(cellId); //apo
298           }
299           outputCD->CopyData(cd,cellId,newCellId);
300           break;
301
302         case VTK_PIXEL:
303           newCellId = output->InsertNextCell(aCellType,npts,pts);
304           if(myStoreMapping){
305             myVTK2ObjIds.push_back(cellId); //apo
306           }
307           outputCD->CopyData(cd,cellId,newCellId);
308           break;
309
310         case VTK_TETRA: {
311           for (faceId = 0; faceId < 4; faceId++)
312             {
313             faceIds->Reset();
314             faceVerts = vtkTetra::GetFaceArray(faceId);
315             faceIds->InsertNextId(pts[faceVerts[0]]);
316             faceIds->InsertNextId(pts[faceVerts[1]]);
317             faceIds->InsertNextId(pts[faceVerts[2]]);
318             numFacePts = 3;
319             aCellType = VTK_TRIANGLE;
320             input->GetCellNeighbors(cellId, faceIds, cellIds);
321             if ( cellIds->GetNumberOfIds() <= 0 || myShowInside == 1 ||
322                  (!allVisible && !cellVis[cellIds->GetId(0)]) )
323               {
324               for ( i=0; i < numFacePts; i++)
325                 {
326                 aNewPts[i] = pts[faceVerts[i]];
327                 }
328               newCellId = output->InsertNextCell(aCellType,numFacePts,aNewPts);
329               if(myStoreMapping){
330                 myVTK2ObjIds.push_back(cellId); //apo
331               }
332               outputCD->CopyData(cd,cellId,newCellId);
333               }
334             }
335           break;
336         }
337         case VTK_VOXEL: {
338           for (faceId = 0; faceId < 6; faceId++)
339             {
340             faceIds->Reset();
341             faceVerts = vtkVoxel::GetFaceArray(faceId);
342             faceIds->InsertNextId(pts[faceVerts[0]]);
343             faceIds->InsertNextId(pts[faceVerts[1]]);
344             faceIds->InsertNextId(pts[faceVerts[2]]);
345             faceIds->InsertNextId(pts[faceVerts[3]]);
346             numFacePts = 4;
347             aCellType = VTK_QUAD;
348             input->GetCellNeighbors(cellId, faceIds, cellIds);
349             if ( cellIds->GetNumberOfIds() <= 0 || myShowInside == 1 || 
350                  (!allVisible && !cellVis[cellIds->GetId(0)]) )
351               {
352               for ( i=0; i < numFacePts; i++)
353                 {
354                 aNewPts[i] = pts[faceVerts[PixelConvert[i]]];
355                 }
356               newCellId = output->InsertNextCell(aCellType,numFacePts,aNewPts);
357               if(myStoreMapping){
358                 myVTK2ObjIds.push_back(cellId); //apo
359               }
360               outputCD->CopyData(cd,cellId,newCellId);
361               }
362             }
363           break;
364         }
365         case VTK_HEXAHEDRON: {
366           for (faceId = 0; faceId < 6; faceId++)
367             {
368             faceIds->Reset();
369             faceVerts = vtkHexahedron::GetFaceArray(faceId);
370             faceIds->InsertNextId(pts[faceVerts[0]]);
371             faceIds->InsertNextId(pts[faceVerts[1]]);
372             faceIds->InsertNextId(pts[faceVerts[2]]);
373             faceIds->InsertNextId(pts[faceVerts[3]]);
374             numFacePts = 4;
375             aCellType = VTK_QUAD;
376             input->GetCellNeighbors(cellId, faceIds, cellIds);
377             if ( cellIds->GetNumberOfIds() <= 0 || myShowInside == 1 ||
378                  (!allVisible && !cellVis[cellIds->GetId(0)]) )
379               {
380               for ( i=0; i < numFacePts; i++)
381                 {
382                 aNewPts[i] = pts[faceVerts[i]];
383                 }
384               newCellId = output->InsertNextCell(aCellType,numFacePts,aNewPts);
385               if(myStoreMapping){
386                 myVTK2ObjIds.push_back(cellId); //apo
387               }
388               outputCD->CopyData(cd,cellId,newCellId);
389               }
390             }
391           break;
392         }
393         case VTK_WEDGE: {
394           for (faceId = 0; faceId < 5; faceId++)
395             {
396             faceIds->Reset();
397             faceVerts = vtkWedge::GetFaceArray(faceId);
398             faceIds->InsertNextId(pts[faceVerts[0]]);
399             faceIds->InsertNextId(pts[faceVerts[1]]);
400             faceIds->InsertNextId(pts[faceVerts[2]]);
401             numFacePts = 3;
402             aCellType = VTK_TRIANGLE;
403             if (faceVerts[3] >= 0)
404               {
405               faceIds->InsertNextId(pts[faceVerts[3]]);
406               numFacePts = 4;
407               aCellType = VTK_QUAD;
408               }
409             input->GetCellNeighbors(cellId, faceIds, cellIds);
410             if ( cellIds->GetNumberOfIds() <= 0 || myShowInside == 1 || 
411                  (!allVisible && !cellVis[cellIds->GetId(0)]) )
412               {
413               for ( i=0; i < numFacePts; i++)
414                 {
415                 aNewPts[i] = pts[faceVerts[i]];
416                 }
417               newCellId = output->InsertNextCell(aCellType,numFacePts,aNewPts);
418               if(myStoreMapping){
419                 myVTK2ObjIds.push_back(cellId); //apo
420               }
421               outputCD->CopyData(cd,cellId,newCellId);
422               }
423             }
424           break;
425         }
426         case VTK_PYRAMID: {
427           for (faceId = 0; faceId < 5; faceId++)
428             {
429             faceIds->Reset();
430             faceVerts = vtkPyramid::GetFaceArray(faceId);
431             faceIds->InsertNextId(pts[faceVerts[0]]);
432             faceIds->InsertNextId(pts[faceVerts[1]]);
433             faceIds->InsertNextId(pts[faceVerts[2]]);
434             numFacePts = 3;
435             aCellType = VTK_TRIANGLE;
436             if (faceVerts[3] >= 0)
437               {
438               faceIds->InsertNextId(pts[faceVerts[3]]);
439               numFacePts = 4;
440               aCellType = VTK_QUAD;
441               }
442             input->GetCellNeighbors(cellId, faceIds, cellIds);
443             if ( cellIds->GetNumberOfIds() <= 0 || myShowInside == 1 || 
444                  (!allVisible && !cellVis[cellIds->GetId(0)]) )
445               {
446               for ( i=0; i < numFacePts; i++)
447                 {
448                 aNewPts[i] = pts[faceVerts[i]];
449                 }
450               newCellId = output->InsertNextCell(aCellType,numFacePts,aNewPts);
451               if(myStoreMapping){
452                 myVTK2ObjIds.push_back(cellId); //apo
453               }
454               outputCD->CopyData(cd,cellId,newCellId);
455               }
456             }
457           break;
458         }
459         //Quadratic cells
460         case VTK_QUADRATIC_EDGE:
461         case VTK_QUADRATIC_TRIANGLE:
462         case VTK_QUADRATIC_QUAD:
463         case VTK_QUADRATIC_TETRA:
464         case VTK_QUADRATIC_HEXAHEDRON:
465           
466           break; //done with quadratic cells
467           
468         } //switch
469       } //if visible
470     } //for all cells
471   
472   if(MYDEBUG && myStoreMapping){
473     for(int i = 0, iEnd = myVTK2ObjIds.size(); i < iEnd; i++){
474       cout<<myVTK2ObjIds[i]<<", ";
475     }
476     cout<<"\n";
477   }
478
479   // Update ourselves and release memory
480   //
481   //output->SetVerts(Verts);
482   //Verts->Delete();
483   //output->SetLines(Lines);
484   //Lines->Delete();
485   //output->SetPolys(Polys);
486   //Polys->Delete();
487   //output->SetStrips(Strips);
488   //Strips->Delete();
489   
490   output->Squeeze();
491
492   vtkDebugMacro(<<"Extracted " << input->GetNumberOfPoints() << " points,"
493   << output->GetNumberOfCells() << " cells.");
494
495   cellIds->Delete();
496   faceIds->Delete();
497   if ( cellVis )
498     {
499     delete [] cellVis;
500     }
501 }
502
503
504 void SALOME_GeometryFilter::SetInside(int theShowInside){
505   if(myShowInside == theShowInside) return;
506   myShowInside = theShowInside;
507   this->Modified();
508 }
509 int SALOME_GeometryFilter::GetInside(){
510   return myShowInside;
511 }