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