0032331: Visualization - Exception when trying to display some surfaces using iVtk...
[occt.git] / src / IVtkTools / IVtkTools_SubPolyDataFilter.cxx
1 // Created on: 2011-10-27 
2 // Created by: Roman KOZLOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS 
4 // 
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <IVtkTools_SubPolyDataFilter.hxx>
17 #include <IVtkVTK_ShapeData.hxx>
18
19 // prevent disabling some MSVC warning messages by VTK headers 
20 #ifdef _MSC_VER
21 #pragma warning(push)
22 #endif
23 #include <vtkCellData.h>
24 #include <vtkFloatArray.h>
25 #include <vtkGenericCell.h>
26 #include <vtkIdList.h>
27 #include <vtkIdTypeArray.h>
28 #include <vtkInformation.h>
29 #include <vtkInformationVector.h>
30 #include <vtkObjectFactory.h>
31 #include <vtkPointData.h>
32 #ifdef _MSC_VER
33 #pragma warning(pop)
34 #endif
35
36 namespace
37 {
38   //! Modified version of vtkPolyData::CopyCells() that includes copying of normals.
39   //! How to ask vtkPolyData::CopyCells() to do that automatically?
40   static void copyCells (vtkPolyData* theDst,
41                          vtkPolyData* theSrc,
42                          vtkIdList* theIdList)
43   {
44     //theDst->CopyCells (theSrc, theIdList);
45
46     const vtkIdType aNbPts = theSrc->GetNumberOfPoints();
47     vtkDataArray* anOldNormals = theSrc->GetPointData()->GetNormals();
48
49     if (theDst->GetPoints() == NULL)
50     {
51       theDst->SetPoints (vtkSmartPointer<vtkPoints>::New());
52     }
53
54     vtkSmartPointer<vtkIdList> aNewCellPts = vtkSmartPointer<vtkIdList>::New();
55     vtkSmartPointer<vtkGenericCell> aCell  = vtkSmartPointer<vtkGenericCell>::New();
56     NCollection_Vec3<double> anXYZ;
57     vtkPointData* aNewPntData  = theDst->GetPointData();
58     vtkCellData*  aNewCellData = theDst->GetCellData();
59     vtkPoints*    aNewPoints   = theDst->GetPoints();
60     vtkSmartPointer<vtkFloatArray> aNewNormals;
61     if (anOldNormals != NULL)
62     {
63       aNewNormals = vtkSmartPointer<vtkFloatArray>::New();
64       aNewNormals->SetName ("Normals");
65       aNewNormals->SetNumberOfComponents (3);
66       theDst->GetPointData()->SetNormals (aNewNormals);
67     }
68
69     vtkSmartPointer<vtkIdList> aPntMap = vtkSmartPointer<vtkIdList>::New(); // maps old pt ids into new
70     aPntMap->SetNumberOfIds (aNbPts);
71     for (vtkIdType i = 0; i < aNbPts; ++i)
72     {
73       aPntMap->SetId (i, -1);
74     }
75
76     // Filter the cells
77     for (vtkIdType aCellIter = 0; aCellIter < theIdList->GetNumberOfIds(); ++aCellIter)
78     {
79       theSrc->GetCell (theIdList->GetId (aCellIter), aCell);
80       vtkIdList* aCellPts = aCell->GetPointIds();
81       const vtkIdType aNbCellPts = aCell->GetNumberOfPoints();
82       for (vtkIdType i = 0; i < aNbCellPts; ++i)
83       {
84         const vtkIdType aPtId = aCellPts->GetId (i);
85         vtkIdType aNewId = aPntMap->GetId (aPtId);
86         if (aNewId < 0)
87         {
88           theSrc->GetPoint (aPtId, anXYZ.ChangeData());
89
90           aNewId = aNewPoints->InsertNextPoint (anXYZ.GetData());
91           aPntMap->SetId (aPtId, aNewId);
92           aNewPntData->CopyData (theSrc->GetPointData(), aPtId, aNewId);
93
94           if (anOldNormals != NULL)
95           {
96             anOldNormals->GetTuple (aPtId, anXYZ.ChangeData());
97             aNewNormals->InsertNextTuple (anXYZ.GetData());
98           }
99         }
100         aNewCellPts->InsertId (i, aNewId);
101       }
102
103       const vtkIdType aNewCellId = theDst->InsertNextCell (aCell->GetCellType(), aNewCellPts);
104       aNewCellData->CopyData (theSrc->GetCellData(), theIdList->GetId (aCellIter), aNewCellId);
105       aNewCellPts->Reset();
106     }
107   }
108 }
109
110 vtkStandardNewMacro(IVtkTools_SubPolyDataFilter)
111
112 //================================================================
113 // Function : Constructor
114 // Purpose  :
115 //================================================================
116 IVtkTools_SubPolyDataFilter::IVtkTools_SubPolyDataFilter()
117 : myIdsArrayName (IVtkVTK_ShapeData::ARRNAME_SUBSHAPE_IDS()),
118   myDoFiltering (true),
119   myToCopyNormals (true)
120 {
121   //
122 }
123
124 //================================================================
125 // Function : Destructor
126 // Purpose  :
127 //================================================================
128 IVtkTools_SubPolyDataFilter::~IVtkTools_SubPolyDataFilter() { }
129
130 //================================================================
131 // Function : RequestData
132 // Purpose  : Filter cells according to the given set of ids.
133 //================================================================
134 int IVtkTools_SubPolyDataFilter::RequestData (vtkInformation *vtkNotUsed(theRequest),
135                                               vtkInformationVector **theInputVector,
136                                               vtkInformationVector *theOutputVector)
137 {
138   // get the input and output
139   vtkSmartPointer<vtkInformation> anInInfo = theInputVector[0]->GetInformationObject(0);
140   vtkSmartPointer<vtkInformation> anOutInfo = theOutputVector->GetInformationObject(0);
141
142   vtkSmartPointer<vtkPolyData> anInput = vtkPolyData::SafeDownCast(
143     anInInfo->Get (vtkDataObject::DATA_OBJECT()));
144
145   vtkSmartPointer<vtkPolyData> anOutput = vtkPolyData::SafeDownCast(
146     anOutInfo->Get (vtkDataObject::DATA_OBJECT()));
147
148   anInput->Modified();
149
150   if (myDoFiltering)
151   {
152     vtkSmartPointer<vtkCellData> anInputCellData  = anInput->GetCellData();
153     vtkSmartPointer<vtkCellData> anOutputCellData = anOutput->GetCellData();
154     vtkSmartPointer<vtkIdTypeArray> aDataArray = vtkIdTypeArray::SafeDownCast (anInputCellData->GetArray (myIdsArrayName));
155
156     // List of cell ids to be passed
157     vtkSmartPointer<vtkIdList> anIdList = vtkSmartPointer<vtkIdList>::New();
158     anIdList->Allocate (myIdsSet.Extent());  // Allocate the list of ids
159
160     const vtkIdType aSize = aDataArray.GetPointer() != NULL ? aDataArray->GetNumberOfTuples() : 0;
161     if (aSize != 0)
162     {
163       anIdList->Allocate (aSize);  // Allocate the list of ids
164     }
165
166     // Prepare the list of ids from the set of ids.
167     // Iterate on input cells.
168 #if (VTK_MAJOR_VERSION >= 9)
169     // Count number of different cells.
170     int aNbVerts = 0, aNbLines = 0, aNbPolys = 0, aNbStrips = 0;
171     int aNbVertPts = 0, aNbLinePts = 0, aNbPolyPts = 0, aNbStripPts = 0;
172 #endif
173     if (!myIdsSet.IsEmpty())
174     {
175       for (vtkIdType anI = 0; anI < aSize; anI++)
176       {
177         if (myIdsSet.Contains (aDataArray->GetValue (anI)))
178         {
179           // Add a cell id to output if it's value is in the set.
180           anIdList->InsertNextId (anI);
181 #if (VTK_MAJOR_VERSION >= 9)
182           switch (anInput->GetCellType(anI))
183           {
184             case VTK_VERTEX:
185               aNbVerts++;
186               aNbVertPts++;
187               break;
188             case VTK_POLY_VERTEX:
189               aNbVerts++;
190               aNbVertPts += anInput->GetCell(anI)->GetNumberOfPoints();
191               break;
192             case VTK_LINE:
193               aNbLines++;
194               aNbLinePts += 2;
195               break;
196             case VTK_POLY_LINE:
197               aNbLines++;
198               aNbLinePts += anInput->GetCell(anI)->GetNumberOfPoints();
199               break;
200             case VTK_TRIANGLE:
201               aNbPolys++;
202               aNbPolyPts += 3;
203               break;
204             case VTK_QUAD:
205               aNbPolys++;
206               aNbPolyPts += 4;
207               break;
208             case VTK_POLYGON:
209               aNbPolys++;
210               aNbPolyPts += anInput->GetCell(anI)->GetNumberOfPoints();
211               break;
212             case VTK_TRIANGLE_STRIP:
213               aNbStrips++;
214               aNbStripPts += anInput->GetCell(anI)->GetNumberOfPoints();
215               break;
216           }
217 #endif
218         }
219       }
220     }
221
222     // Copy cells with their points according to the prepared list of cell ids.
223     anOutputCellData->AllocateArrays (anInputCellData->GetNumberOfArrays());
224     // Allocate output cells
225 #if (VTK_MAJOR_VERSION >= 9)
226     anOutput->AllocateExact (aNbVerts, aNbVertPts, aNbLines, aNbLinePts, aNbPolys, aNbPolyPts, aNbStrips, aNbStripPts);
227 #else
228     anOutput->Allocate (anInput, anIdList->GetNumberOfIds());
229 #endif
230
231     // Pass data arrays.
232     // Create new arrays for output data 
233     for (Standard_Integer anI = 0; anI < anInputCellData->GetNumberOfArrays(); anI++)
234     {
235       vtkSmartPointer<vtkDataArray> anInArr  = anInputCellData->GetArray (anI);
236       vtkSmartPointer<vtkDataArray> anOutArr = vtkSmartPointer<vtkDataArray>::Take (vtkDataArray::CreateDataArray(anInArr->GetDataType()));
237
238       anOutArr->SetName (anInArr->GetName());
239       anOutArr->Allocate (anIdList->GetNumberOfIds() * anInArr->GetNumberOfComponents());
240       anOutArr->SetNumberOfTuples (anIdList->GetNumberOfIds());
241       anOutArr->SetNumberOfComponents (anInArr->GetNumberOfComponents());
242       anOutputCellData->AddArray (anOutArr);
243     }
244
245     // Copy cells with ids from our list.
246     if (myToCopyNormals)
247     {
248       copyCells (anOutput, anInput, anIdList);
249     }
250     else
251     {
252       anOutput->CopyCells (anInput, anIdList);
253     }
254
255     // Copy filtered arrays data
256     for (Standard_Integer anI = 0; anI < anInputCellData->GetNumberOfArrays(); anI++)
257     {
258       vtkSmartPointer<vtkDataArray> anInArr  = anInputCellData ->GetArray (anI);
259       vtkSmartPointer<vtkDataArray> anOutArr = anOutputCellData->GetArray (anI);
260       for (vtkIdType anOutId = 0; anOutId < anIdList->GetNumberOfIds(); anOutId++)
261       {
262         const vtkIdType anInId = anIdList->GetId (anOutId);
263         anOutArr->SetTuple (anOutId, anInId, anInArr);
264       }
265     }
266   }
267   else
268   {
269     anOutput->CopyStructure (anInput);  // Copy points and cells
270     anOutput->CopyAttributes (anInput); // Copy data arrays (sub-shapes ids)
271   }
272
273   return 1; // Return non-zero value if success and pipeline is not failed.
274 }
275
276 //================================================================
277 // Function : SetDoFiltering
278 // Purpose  :
279 //================================================================
280 void IVtkTools_SubPolyDataFilter::SetDoFiltering (const bool theDoFiltering)
281 {
282   myDoFiltering = theDoFiltering;
283 }
284
285 //================================================================
286 // Function : PrintSelf
287 // Purpose  : 
288 //================================================================
289 void IVtkTools_SubPolyDataFilter::PrintSelf (std::ostream& theOs, vtkIndent theIndent)
290 {
291   this->Superclass::PrintSelf (theOs,theIndent);
292   theOs << theIndent << "SubPolyData: " << "\n"; 
293   theOs << theIndent << "   Number of cells to pass: " << myIdsSet.Extent() << "\n";
294   theOs << theIndent << "   Cells ids to pass: {" ;
295   // Print the content of the set of ids.
296   IVtk_IdTypeMap::Iterator anIter(myIdsSet);
297   while (anIter.More())
298   {
299     theOs << " " << anIter.Value();
300     anIter.Next();
301     if (anIter.More())
302     {
303       theOs << "; ";
304     }
305   }
306   theOs << "}" << "\n";
307 }
308
309 //================================================================
310 // Function : Clear
311 // Purpose  : Clear ids set to be passed through this filter.
312 //================================================================
313 void IVtkTools_SubPolyDataFilter::Clear()
314 {
315   myIdsSet.Clear();
316 }
317
318 //================================================================
319 // Function : SetData
320 // Purpose  : Set ids to be passed through this filter.
321 //================================================================
322 void IVtkTools_SubPolyDataFilter::SetData (const IVtk_IdTypeMap theSet)
323 {
324   myIdsSet = theSet;
325 }
326
327 //================================================================
328 // Function : AddData
329 // Purpose  : Add ids to be passed through this filter.
330 //================================================================
331 void IVtkTools_SubPolyDataFilter::AddData (const IVtk_IdTypeMap theSet)
332 {
333   for (IVtk_IdTypeMap::Iterator anIt (theSet); anIt.More(); anIt.Next())
334   {
335     if (!myIdsSet.Contains (anIt.Value()))
336     {
337       myIdsSet.Add (anIt.Value());
338     }
339   }
340 }
341
342 //================================================================
343 // Function : SetData
344 // Purpose  : Set ids to be passed through this filter.
345 //================================================================
346 void IVtkTools_SubPolyDataFilter::SetData (const IVtk_ShapeIdList theIdList)
347 {
348   myIdsSet.Clear();
349   AddData (theIdList);
350 }
351
352 //================================================================
353 // Function : AddData
354 // Purpose  : Add ids to be passed through this filter.
355 //================================================================
356 void IVtkTools_SubPolyDataFilter::AddData (const IVtk_ShapeIdList theIdList)
357 {
358   for (IVtk_ShapeIdList::Iterator anIt (theIdList); anIt.More(); anIt.Next())
359   {
360     if (!myIdsSet.Contains (anIt.Value()))
361     {
362       myIdsSet.Add (anIt.Value());
363     }
364   }
365 }
366
367 //================================================================
368 // Function : SetIdsArrayName
369 // Purpose  :
370 //================================================================
371 void IVtkTools_SubPolyDataFilter::SetIdsArrayName (const char* theArrayName)
372 {
373   myIdsArrayName = theArrayName;
374 }