Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / OBJECT / SMESH_ExtractGeometry.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "SMESH_ExtractGeometry.h"
23
24 #include <vtkCell.h>
25 #include <vtkCellData.h>
26 #include <vtkFloatArray.h>
27 #include <vtkIdList.h>
28 #include <vtkImplicitFunction.h>
29 #include <vtkObjectFactory.h>
30 #include <vtkPointData.h>
31 #include <vtkUnstructuredGrid.h>
32 #include <vtkInformation.h>
33 #include <vtkInformationVector.h>
34
35 using namespace std;
36
37 #ifdef _DEBUG_
38 static int MYDEBUG = 0;
39 #else
40 static int MYDEBUG = 0;
41 #endif
42
43 #if defined __GNUC__
44   #if __GNUC__ == 2
45     #define __GNUC_2__
46   #endif
47 #endif
48
49
50 vtkStandardNewMacro(SMESH_ExtractGeometry);
51
52
53 SMESH_ExtractGeometry::SMESH_ExtractGeometry()
54 {}
55
56
57 SMESH_ExtractGeometry::~SMESH_ExtractGeometry(){}
58
59
60 vtkIdType SMESH_ExtractGeometry::GetElemObjId(int theVtkID){
61   if(myElemVTK2ObjIds.empty() || theVtkID > myElemVTK2ObjIds.size()) return -1;
62 #if defined __GNUC_2__
63   return myElemVTK2ObjIds[theVtkID];
64 #else
65   return myElemVTK2ObjIds.at(theVtkID);
66 #endif
67 }
68
69
70 vtkIdType SMESH_ExtractGeometry::GetNodeObjId(int theVtkID){
71   if(myNodeVTK2ObjIds.empty() || theVtkID > myNodeVTK2ObjIds.size()) return -1;
72 #if defined __GNUC_2__
73   return myNodeVTK2ObjIds[theVtkID];
74 #else
75   return myNodeVTK2ObjIds.at(theVtkID);
76 #endif
77 }
78
79
80 int SMESH_ExtractGeometry::RequestData(
81   vtkInformation *vtkNotUsed(request),
82   vtkInformationVector **inputVector,
83   vtkInformationVector *outputVector)
84 {
85   // get the info objects
86   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
87   vtkInformation *outInfo = outputVector->GetInformationObject(0);
88
89   // get the input and ouptut
90   vtkDataSet *input = vtkDataSet::SafeDownCast(
91     inInfo->Get(vtkDataObject::DATA_OBJECT()));
92   vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
93     outInfo->Get(vtkDataObject::DATA_OBJECT()));
94
95   vtkIdType ptId, numPts, numCells, i, cellId, newCellId, newId, *pointMap;
96   vtkIdList *cellPts;
97   vtkCell *cell;
98   int numCellPts;
99   vtkFloatingPointType *x;
100   vtkFloatingPointType multiplier;
101   vtkPoints *newPts;
102   vtkIdList *newCellPts;
103   vtkPointData *pd = input->GetPointData();
104   vtkCellData *cd = input->GetCellData();
105   vtkPointData *outputPD = output->GetPointData();
106   vtkCellData *outputCD = output->GetCellData();
107   int npts;
108   numCells = input->GetNumberOfCells();
109   numPts = input->GetNumberOfPoints();
110   
111   vtkDebugMacro(<< "Extracting geometry");
112
113   if ( ! this->ImplicitFunction )
114     {
115     vtkErrorMacro(<<"No implicit function specified");
116     return 0;
117     }
118
119   newCellPts = vtkIdList::New();
120   newCellPts->Allocate(VTK_CELL_SIZE);
121
122   if ( this->ExtractInside )
123     {
124     multiplier = 1.0;
125     }
126   else 
127     {
128     multiplier = -1.0;
129     }
130
131   // Loop over all points determining whether they are inside the
132   // implicit function. Copy the points and point data if they are.
133   //
134   pointMap = new vtkIdType[numPts]; // maps old point ids into new
135   for (i=0; i < numPts; i++)
136     {
137     pointMap[i] = -1;
138     }
139
140   output->Allocate(numCells/4); //allocate storage for geometry/topology
141   newPts = vtkPoints::New();
142   newPts->Allocate(numPts/4,numPts);
143   outputPD->CopyAllocate(pd);
144   outputCD->CopyAllocate(cd);
145   vtkFloatArray *newScalars = NULL;
146   
147   if(myStoreMapping){
148     myElemVTK2ObjIds.clear();
149     myElemVTK2ObjIds.reserve(numCells);
150     myNodeVTK2ObjIds.clear();
151     myNodeVTK2ObjIds.reserve(numPts);
152   }
153
154   if ( ! this->ExtractBoundaryCells )
155     {
156     for ( ptId=0; ptId < numPts; ptId++ )
157       {
158       x = input->GetPoint(ptId);
159       if ( (this->ImplicitFunction->FunctionValue(x)*multiplier) < 0.0 )
160         {
161         newId = newPts->InsertNextPoint(x);
162         pointMap[ptId] = newId;
163         myNodeVTK2ObjIds.push_back(ptId);
164         outputPD->CopyData(pd,ptId,newId);
165         }
166       }
167     }
168   else
169     {
170     // To extract boundary cells, we have to create supplemental information
171     if ( this->ExtractBoundaryCells )
172       {
173       vtkFloatingPointType val;
174       newScalars = vtkFloatArray::New();
175       newScalars->SetNumberOfValues(numPts);
176
177       for (ptId=0; ptId < numPts; ptId++ )
178         {
179         x = input->GetPoint(ptId);
180         val = this->ImplicitFunction->FunctionValue(x) * multiplier;
181         newScalars->SetValue(ptId, val);
182         if ( val < 0.0 )
183           {
184           newId = newPts->InsertNextPoint(x);
185           pointMap[ptId] = newId;
186           myNodeVTK2ObjIds.push_back(ptId);
187           outputPD->CopyData(pd,ptId,newId);
188           }
189         }
190       }
191     }
192
193   // Now loop over all cells to see whether they are inside implicit
194   // function (or on boundary if ExtractBoundaryCells is on).
195   //
196   for (cellId=0; cellId < numCells; cellId++)
197     {
198     cell = input->GetCell(cellId);
199     cellPts = cell->GetPointIds();
200     numCellPts = cell->GetNumberOfPoints();
201
202     newCellPts->Reset();
203     if ( ! this->ExtractBoundaryCells ) //requires less work
204       {
205       for ( npts=0, i=0; i < numCellPts; i++, npts++)
206         {
207         ptId = cellPts->GetId(i);
208         if ( pointMap[ptId] < 0 )
209           {
210           break; //this cell won't be inserted
211           }
212         else
213           {
214           newCellPts->InsertId(i,pointMap[ptId]);
215           }
216         }
217       } //if don't want to extract boundary cells
218     
219     else //want boundary cells
220       {
221       for ( npts=0, i=0; i < numCellPts; i++ )
222         {
223         ptId = cellPts->GetId(i);
224         if ( newScalars->GetValue(ptId) <= 0.0 )
225           {
226           npts++;
227           }
228         }
229       if ( npts > 0 )
230         {
231         for ( i=0; i < numCellPts; i++ )
232           {
233           ptId = cellPts->GetId(i);
234           if ( pointMap[ptId] < 0 )
235             {
236             x = input->GetPoint(ptId);
237             newId = newPts->InsertNextPoint(x);
238             pointMap[ptId] = newId;
239             myNodeVTK2ObjIds.push_back(ptId);
240             outputPD->CopyData(pd,ptId,newId);
241             }
242           newCellPts->InsertId(i,pointMap[ptId]);
243           }
244         }//a boundary or interior cell
245       }//if mapping boundary cells
246       
247     if ( npts >= numCellPts || (this->ExtractBoundaryCells && npts > 0) )
248       {
249       newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts);
250       myElemVTK2ObjIds.push_back(cellId);
251       outputCD->CopyData(cd,cellId,newCellId);
252       }
253     }//for all cells
254
255   // Update ourselves and release memory
256   //
257   delete [] pointMap;
258   newCellPts->Delete();
259   output->SetPoints(newPts);
260   newPts->Delete();
261   
262   if ( this->ExtractBoundaryCells )
263     {
264     newScalars->Delete();
265     }
266
267   output->Squeeze();
268   return 1;
269 }