Salome HOME
b0e9e967653092eb460f95df4f9e0e3133aac9ad
[modules/visu.git] / src / CONVERTOR / VISU_AppendFilterUtilities.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  SALOME OBJECT : kernel of SALOME component
21 //  File   : VISU_GeometryFilter.cxx
22 //  Author : 
23 //  Module : SALOME
24 //  $Header$
25 //
26 #include "VISU_AppendFilterUtilities.hxx"
27 #include "VISU_ConvertorUtils.hxx"
28
29 #include <vtkCell.h>
30 #include <vtkCellData.h>
31 #include <vtkPointData.h>
32
33 #include <vtkDataSetCollection.h>
34 #include <vtkObjectFactory.h>
35
36 #include <vtkUnstructuredGrid.h>
37 #include <vtkPolyData.h>
38
39 #include <vtkInformationVector.h>
40 #include <vtkInformation.h>
41 #include <vtkExecutive.h>
42
43 #include <vtkPoints.h>
44 #include <vtkIntArray.h>
45
46 #include <algorithm>
47 #include <vector>
48 #include <map>
49
50 namespace
51 {
52   //---------------------------------------------------------------
53   typedef vtkIdType TCellId;
54   typedef vtkIdType TInputId;
55   typedef std::pair<TInputId, TCellId> TInputCellId;
56
57   typedef std::pair<vtkIdType, vtkIdType> TObjectId; 
58   typedef std::map<TObjectId, TInputCellId> TObject2InputIdMap;
59   
60
61   //---------------------------------------------------------------
62   void
63   DoMergingInputs(vtkCellData *theCellData, 
64                   TInputId theInputId,
65                   TObject2InputIdMap& theResult)
66   {
67     if(vtkDataArray *aDataArray = theCellData->GetArray("VISU_CELLS_MAPPER")){
68       if(vtkIntArray *anIntArray = dynamic_cast<vtkIntArray*>(aDataArray)){
69         int *aPointer = anIntArray->GetPointer(0);
70         int aNbCells = anIntArray->GetNumberOfTuples();
71         for(vtkIdType aCellId = 0; aCellId < aNbCells; aCellId++){
72           int aObjId = *aPointer++;
73           int anEntity = *aPointer++;
74           TObjectId anObjectId(aObjId, anEntity);
75           TObject2InputIdMap::iterator anIter = theResult.find(anObjectId);
76           if(anIter != theResult.end())
77             continue;
78           TInputCellId anInputCellId(theInputId, aCellId);
79           theResult.insert(anIter, TObject2InputIdMap::value_type(anObjectId, anInputCellId));
80         }
81       }
82     }
83   }
84
85
86   //---------------------------------------------------------------
87   struct TFillFieldList
88   {
89     vtkDataSetAttributes::FieldList myFieldList;
90     bool myIsFirstCellData;
91
92     TFillFieldList(vtkIdType theNbInputs):
93       myFieldList(theNbInputs),
94       myIsFirstCellData(true)
95     {}
96
97     void
98     operator()(TInputId theInputId, vtkDataSet* theDataSet)
99     {
100       vtkCellData *aCellData = theDataSet->GetCellData();
101       if(myIsFirstCellData){
102         myFieldList.InitializeFieldList(aCellData);
103         myIsFirstCellData = false;
104       }else{
105         myFieldList.IntersectFieldList(aCellData);
106       }
107     }
108     
109     virtual
110     vtkIdType
111     GetNbCells() const = 0;
112   };
113   
114
115   //---------------------------------------------------------------
116   struct TCellCounter: TFillFieldList
117   {
118     vtkIdType myNbCells;
119     
120     TCellCounter(vtkIdType theNbInputs):
121       TFillFieldList(theNbInputs),
122       myNbCells(0)
123     {}
124
125     void
126     operator()(TInputId theInputId, vtkDataSet* theDataSet)
127     {
128       TFillFieldList::operator()(theInputId, theDataSet);
129       myNbCells += theDataSet->GetNumberOfCells();
130     }
131
132     virtual
133     vtkIdType
134     GetNbCells() const
135     {
136       return myNbCells;
137     }
138   };
139
140
141   //---------------------------------------------------------------
142   struct TCellIdMerger: TFillFieldList
143   {
144     TObject2InputIdMap myObject2InputIdMap;
145
146     TCellIdMerger(vtkIdType theNbInputs):
147       TFillFieldList(theNbInputs)
148     {}
149
150     void
151     operator()(TInputId theInputId, vtkDataSet* theDataSet)
152     {
153       TFillFieldList::operator()(theInputId, theDataSet);
154       vtkCellData *aCellData = theDataSet->GetCellData();
155       DoMergingInputs(aCellData, theInputId, myObject2InputIdMap);
156     }
157
158     virtual
159     vtkIdType
160     GetNbCells() const
161     {
162       return myObject2InputIdMap.size();
163     }
164   };
165
166
167   //---------------------------------------------------------------
168   template<class TFunctor>
169   void
170   ForEachInput(vtkInformationVector **theInputVector, 
171                vtkIdType theNumberOfInputConnections,
172                TFunctor& theFunctor)
173   {
174     for(vtkIdType anInputId = 0; anInputId < theNumberOfInputConnections; anInputId++)
175       if(vtkDataSet *aDataSet = VISU::GetInput(theInputVector, anInputId))
176         if(aDataSet->GetNumberOfPoints() > 0 && aDataSet->GetNumberOfCells() > 0)
177           theFunctor(anInputId, aDataSet);
178   }
179
180
181   //---------------------------------------------------------------
182   template<class TDataSet>
183   bool
184   RequestData(vtkInformationVector **theInputVector,
185               vtkIdType theNumberOfInputConnections,
186               vtkInformationVector *theOutputVector,
187               vtkPointSet* theSharedPointSet,
188               bool theIsMergingInputs,
189               bool theIsMappingInputs)
190   {
191     if ( theNumberOfInputConnections == 1 ) {
192       // get the input and ouptut
193       vtkDataSet *anInput = VISU::GetInput( theInputVector, 0 );
194       vtkDataSet* anOutput = VISU::GetOutput( theOutputVector );
195
196       if ( anInput->GetDataObjectType() != anOutput->GetDataObjectType() )
197         return false;
198
199       // This has to be here because it initialized all field datas.
200       anOutput->CopyStructure( anInput );
201   
202       // Pass all. (data object's field data is passed by the
203       // superclass after this method)
204       anOutput->GetPointData()->PassData( anInput->GetPointData() );
205       anOutput->GetCellData()->PassData( anInput->GetCellData() );
206       
207       return true;
208     }
209
210     if ( theSharedPointSet ) {
211       vtkPoints* aPoints = theSharedPointSet->GetPoints();
212       if(aPoints->GetNumberOfPoints() < 1)
213         return true;
214   
215       TDataSet* anOutput = TDataSet::SafeDownCast(VISU::GetOutput(theOutputVector));
216       vtkIdType anNbInputs = theNumberOfInputConnections;
217       if ( theIsMergingInputs ) {
218         TCellIdMerger aFunctor(anNbInputs);
219         ForEachInput<TCellIdMerger>(theInputVector, anNbInputs, aFunctor);
220
221         vtkDataSetAttributes::FieldList& aFieldList = aFunctor.myFieldList;
222         TObject2InputIdMap& anObject2InputIdMap = aFunctor.myObject2InputIdMap;
223         vtkIdType aNbCells = aFunctor.GetNbCells();
224         if(aNbCells < 1)
225           return true;
226     
227         // Now can allocate memory
228         anOutput->Allocate(aNbCells); 
229         vtkCellData *anOutputCellData = anOutput->GetCellData();
230         anOutputCellData->CopyAllocate(aFieldList, aNbCells);
231       
232         // Append each input dataset together
233         // 1.points
234         anOutput->SetPoints(theSharedPointSet->GetPoints());
235         anOutput->GetPointData()->PassData(theSharedPointSet->GetPointData());
236       
237         // 2.cells
238         vtkIdList *anIdList = vtkIdList::New(); 
239         anIdList->Allocate(VTK_CELL_SIZE);
240         TObject2InputIdMap::const_iterator anIter = anObject2InputIdMap.begin();
241         TObject2InputIdMap::const_iterator anEndIter = anObject2InputIdMap.end();
242         for(; anIter != anEndIter; anIter++){
243           //TObjectId anObjectId = anIter->first;
244           const TInputCellId& anInputCellId = anIter->second;
245           TInputId anInputId = anInputCellId.first;
246           if(vtkDataSet *aDataSet = VISU::GetInput(theInputVector, anInputId)){
247             TCellId aCellId = anInputCellId.second;
248             aDataSet->GetCellPoints(aCellId, anIdList);
249             
250             vtkIdType aCellType = aDataSet->GetCellType(aCellId);
251             vtkIdType aNewCellId = anOutput->InsertNextCell(aCellType, anIdList);
252           
253             vtkCellData *aCellData = aDataSet->GetCellData();
254             anOutputCellData->CopyData(aFieldList, aCellData, anInputId, aCellId, aNewCellId);
255           }
256         }
257         anIdList->Delete();
258
259         if(theIsMappingInputs){
260           vtkIntArray *aDataArray = vtkIntArray::New();
261           aDataArray->SetName("VISU_INPUTS_MAPPER");
262           aDataArray->SetNumberOfComponents(2);
263           aDataArray->SetNumberOfTuples(aNbCells);
264
265           vtkIdType aTupleId = 0;
266           TObject2InputIdMap::const_iterator anIter = anObject2InputIdMap.begin();
267           TObject2InputIdMap::const_iterator anEndIter = anObject2InputIdMap.end();
268           for(vtkIdType aCellId = 0; anIter != anEndIter; anIter++, aCellId++){
269             const TInputCellId& anInputCellId = anIter->second;
270             TInputId anInputId = anInputCellId.first;
271             /*TCellId*/ aCellId = anInputCellId.second;
272             aDataArray->SetValue(aTupleId++, anInputId);
273             aDataArray->SetValue(aTupleId++, aCellId);
274           }
275
276           anOutputCellData->AddArray(aDataArray);
277           aDataArray->Delete();
278         }
279
280         return true;
281       }else{
282         TCellCounter aFunctor(anNbInputs);
283         ForEachInput<TCellCounter>(theInputVector, anNbInputs, aFunctor);
284         
285         vtkDataSetAttributes::FieldList& aFieldList = aFunctor.myFieldList;
286         vtkIdType aNbCells = aFunctor.GetNbCells();
287         if(aNbCells < 1)
288           return true;
289         
290         // Now can allocate memory
291         anOutput->Allocate(aNbCells); 
292         vtkCellData *anOutputCellData = anOutput->GetCellData();
293         anOutputCellData->CopyAllocate(aFieldList, aNbCells);
294         
295         // Append each input dataset together
296         // 1.points
297         anOutput->SetPoints(theSharedPointSet->GetPoints());
298         anOutput->GetPointData()->PassData(theSharedPointSet->GetPointData());
299         
300         // 2.cells
301         vtkIdList *anIdList = vtkIdList::New(); 
302         anIdList->Allocate(VTK_CELL_SIZE);
303         for(vtkIdType anInputId = 0; anInputId < anNbInputs; anInputId++){
304           if(vtkDataSet *aDataSet = VISU::GetInput(theInputVector, anInputId)){
305             vtkIdType aNbCells = aDataSet->GetNumberOfCells(); 
306             vtkCellData *aCellData = aDataSet->GetCellData();
307             // copy cell and cell data
308             for(vtkIdType aCellId = 0; aCellId < aNbCells; aCellId++){
309               aDataSet->GetCellPoints(aCellId, anIdList);
310
311               vtkIdType aCellType = aDataSet->GetCellType(aCellId);
312               vtkIdType aNewCellId = anOutput->InsertNextCell(aCellType, anIdList);
313
314               anOutputCellData->CopyData(aFieldList, aCellData, anInputId, aCellId, aNewCellId);
315             }
316           }
317         }
318         anIdList->Delete();
319
320         if(theIsMappingInputs){
321           vtkIntArray *aDataArray = vtkIntArray::New();
322           aDataArray->SetName("VISU_INPUTS_MAPPER");
323           aDataArray->SetNumberOfComponents(2);
324           aDataArray->SetNumberOfTuples(aNbCells);
325
326           vtkIdType aTupleId = 0;
327           for(vtkIdType anInputId = 0; anInputId < anNbInputs; anInputId++){
328             if(vtkDataSet *aDataSet = VISU::GetInput(theInputVector, anInputId)){
329               vtkIdType aNbCells = aDataSet->GetNumberOfCells(); 
330               for(vtkIdType aCellId = 0; aCellId < aNbCells; aCellId++){
331                 aDataArray->SetValue(aTupleId++, aCellId);
332                 aDataArray->SetValue(aTupleId++, anInputId);
333               }
334             }
335           }
336
337           anOutputCellData->AddArray(aDataArray);
338           aDataArray->Delete();
339         }
340         return true;
341       }
342     }
343
344     return false;
345   }
346
347
348   //---------------------------------------------------------------
349 }
350
351
352 namespace VISU
353 {
354   //---------------------------------------------------------------
355   TAppendFilterHelper
356   ::TAppendFilterHelper(vtkObject* theParent):
357     myIsMergingInputs(false),
358     myIsMappingInputs(false),
359     myParent(*theParent)
360   {}
361
362
363   //---------------------------------------------------------------
364   void
365   TAppendFilterHelper
366   ::SetSharedPointSet(vtkPointSet* thePointSet)
367   {
368     if(GetSharedPointSet() == thePointSet)
369       return;
370     
371     mySharedPointSet = thePointSet;
372     
373     myParent.Modified();
374   }
375
376
377   //---------------------------------------------------------------
378   vtkPointSet*
379   TAppendFilterHelper
380   ::GetSharedPointSet()
381   {
382     return mySharedPointSet.GetPointer();
383   }
384   
385
386   //---------------------------------------------------------------
387   void
388   TAppendFilterHelper
389   ::SetMappingInputs(bool theIsMappingInputs)
390   {
391     if(myIsMappingInputs == theIsMappingInputs)
392       return;
393     
394     myIsMappingInputs = theIsMappingInputs;
395     myParent.Modified();
396   }
397   
398   
399   //---------------------------------------------------------------
400   bool
401   TAppendFilterHelper
402   ::IsMappingInputs()
403   {
404     return myIsMappingInputs;
405   }
406   
407
408   //---------------------------------------------------------------
409   void
410   TAppendFilterHelper
411   ::SetMergingInputs(bool theIsMergingInputs)
412   {
413     if(myIsMergingInputs == theIsMergingInputs)
414       return;
415     
416     myIsMergingInputs = theIsMergingInputs;
417     myParent.Modified();
418   }
419   
420   
421   //---------------------------------------------------------------
422   bool
423   TAppendFilterHelper
424   ::IsMergingInputs()
425   {
426     return myIsMergingInputs;
427   }
428   
429
430   //---------------------------------------------------------------
431   bool
432   UnstructuredGridRequestData(vtkInformationVector **theInputVector,
433                               vtkIdType theNumberOfInputConnections,
434                               vtkInformationVector *theOutputVector,
435                               vtkPointSet* theSharedPointSet,
436                               bool theIsMergingInputs,
437                               bool theIsMappingInputs)
438   {
439     return RequestData<vtkUnstructuredGrid>(theInputVector,
440                                             theNumberOfInputConnections,
441                                             theOutputVector,
442                                             theSharedPointSet,
443                                             theIsMergingInputs,
444                                             theIsMappingInputs);
445   }
446
447
448   //---------------------------------------------------------------
449   bool
450   PolyDataRequestData(vtkInformationVector **theInputVector,
451                       vtkIdType theNumberOfInputConnections,
452                       vtkInformationVector *theOutputVector,
453                       vtkPointSet* theSharedPointSet,
454                       bool theIsMergingInputs,
455                       bool theIsMappingInputs)
456   {
457     return RequestData<vtkPolyData>(theInputVector,
458                                     theNumberOfInputConnections,
459                                     theOutputVector,
460                                     theSharedPointSet,
461                                     theIsMergingInputs,
462                                     theIsMappingInputs);
463   }
464
465
466   //---------------------------------------------------------------
467 }