Salome HOME
Update copyright information
[modules/visu.git] / src / PIPELINE / VISU_ElnoDisassembleFilter.cxx
1 // Copyright (C) 2007-2012  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 #include "VISU_ElnoDisassembleFilter.hxx"
21 #include "VISU_PipeLineUtils.hxx"
22 #include "VISU_ElnoMeshValue.hxx"
23
24 #include <vtkCellData.h>
25 #include <vtkInformation.h>
26 #include <vtkInformationVector.h>
27 #include <vtkObjectFactory.h>
28 #include <vtkPointData.h>
29 #include <vtkUnstructuredGrid.h>
30 #include <vtkPoints.h>
31 #include <vtkCellArray.h>
32
33
34 //----------------------------------------------------------------------------
35 vtkStandardNewMacro( VISU_ElnoDisassembleFilter );
36
37
38 //----------------------------------------------------------------------------
39 VISU_ElnoDisassembleFilter::VISU_ElnoDisassembleFilter()
40 {
41   this->SetInputArrayToProcess( 0, // idx
42                                 0, // port
43                                 0, // connection
44                                 vtkDataObject::FIELD_ASSOCIATION_CELLS, // field association
45                                 "ELNO_FIELD" ); // name
46
47   this->SetInputArrayToProcess( 1, // idx
48                                 0, // port
49                                 0, // connection
50                                 vtkDataObject::FIELD_ASSOCIATION_CELLS, // field association
51                                 "ELNO_COMPONENT_MAPPER" ); // name
52
53   this->myShrinkFactor = -0.999;
54 }
55
56
57 //----------------------------------------------------------------------------
58 VISU_ElnoDisassembleFilter::~VISU_ElnoDisassembleFilter()
59 {}
60
61
62 //----------------------------------------------------------------------------
63 void VISU_ElnoDisassembleFilter::SetShrinkFactor( vtkFloatingPointType theValue )
64 {
65   if ( VISU::CheckIsSameValue( theValue, myShrinkFactor ) )
66     return;
67
68   myShrinkFactor = theValue;
69   this->Modified();
70 }
71
72
73 //----------------------------------------------------------------------------
74 vtkFloatingPointType VISU_ElnoDisassembleFilter::GetShrinkFactor()
75 {
76   return myShrinkFactor;
77 }
78
79
80 //----------------------------------------------------------------------------
81 namespace
82 {
83   //----------------------------------------------------------------------------
84   template < int points_type, int elno_type >
85   struct TExecute2
86   {
87     vtkUnstructuredGrid *myInput;
88     vtkUnstructuredGrid *myOutput;
89     vtkDataArray *myElnoDataArray;
90     vtkDataArray *myElnoDataMapper;
91     vtkFloatingPointType myShrinkFactor;
92
93     typedef typename VISU::TL::TEnum2VTKArrayType< points_type >::TResult TPointsDataArray;
94     typedef typename VISU::TL::TEnum2VTKBasicType< points_type >::TResult TPointsDataType;
95
96     typedef typename VISU::TL::TEnum2VTKArrayType< elno_type >::TResult TElnoDataArray;
97     typedef typename VISU::TL::TEnum2VTKBasicType< elno_type >::TResult TElnoDataType;
98
99     VISU::TGetElnoNodeData< elno_type > myGetElnoNodeData;
100     vtkCellArray *myConnectivity;
101     vtkPointData *myInputPointData;
102     vtkPointData *myOutputPointData;
103     TPointsDataArray *myInputPointsArray;
104     TPointsDataArray *myOutputPointsArray;
105     TElnoDataArray* myElnoFullDataArray;
106     TElnoDataArray* myElnoPartialDataArray;
107     TPointsDataArray *myElnoPointCoords;
108     vtkIntArray* myInputPointsMapper;
109     vtkIntArray* myOutputPointsMapper;
110
111     //----------------------------------------------------------------------------
112     TExecute2( vtkUnstructuredGrid *theInput, 
113                vtkUnstructuredGrid *theOutput, 
114                vtkDataArray *theElnoDataArray,
115                vtkDataArray *theElnoDataMapper,
116                vtkFloatingPointType theShrinkFactor )
117       : myGetElnoNodeData( theElnoDataArray, theElnoDataMapper )
118       , myInput( theInput )
119       , myOutput( theOutput )
120       , myElnoDataArray( theElnoDataArray )
121       , myElnoDataMapper( theElnoDataMapper )
122       , myShrinkFactor( theShrinkFactor )
123     {
124       myConnectivity = vtkCellArray::New();
125       myConnectivity->DeepCopy( theInput->GetCells() );
126     
127       vtkPoints *anInputPoints = theInput->GetPoints();
128       vtkPoints *aPoints = anInputPoints->New( anInputPoints->GetDataType() );
129       vtkIdType aNbCells = myConnectivity->GetNumberOfCells();
130       vtkIdType aNbPoints = myConnectivity->GetNumberOfConnectivityEntries() - aNbCells;
131       aPoints->Allocate( aNbPoints );
132     
133       myInputPointsArray = TPointsDataArray::SafeDownCast( anInputPoints->GetData() );
134       myOutputPointsArray = TPointsDataArray::SafeDownCast( aPoints->GetData() );
135     
136       myInputPointData = theInput->GetPointData();
137       myOutputPointData = theOutput->GetPointData();
138       myOutputPointData->Allocate( aNbPoints );
139     
140       vtkCellData *anInputCellData = theInput->GetCellData();
141
142       // To create a new copy of initial data for output
143       myElnoFullDataArray = TElnoDataArray::New();
144       myElnoFullDataArray->SetName( "VISU_FIELD" );
145       myElnoFullDataArray->SetNumberOfComponents( myGetElnoNodeData.getNbComp() );
146       myElnoFullDataArray->SetNumberOfTuples( aNbPoints );
147
148       // To create a new copy of partial initial data for output
149       myElnoPartialDataArray = TElnoDataArray::New();
150       // This partial data can be represented as in terms of vectors as scalars
151       if ( anInputCellData->GetVectors() != NULL ) 
152         myElnoPartialDataArray->SetNumberOfComponents( 3 );
153       else
154         myElnoPartialDataArray->SetNumberOfComponents( 1 );
155       myElnoPartialDataArray->SetNumberOfTuples( aNbPoints );
156
157       myElnoPointCoords = TPointsDataArray::New();
158       myElnoPointCoords->SetName( "ELNO_POINT_COORDS" );
159       myElnoPointCoords->SetNumberOfComponents( 3 );
160       myElnoPointCoords->SetNumberOfTuples( aNbPoints );
161
162       vtkDataArray* anArray = myInputPointData->GetArray( "VISU_POINTS_MAPPER" );
163       myInputPointsMapper = vtkIntArray::SafeDownCast( anArray );
164       
165       myOutputPointsMapper = vtkIntArray::New();
166       myOutputPointsMapper->SetName( myInputPointsMapper->GetName() );
167       myOutputPointsMapper->SetNumberOfComponents( myInputPointsMapper->GetNumberOfComponents() );
168       myOutputPointsMapper->SetNumberOfTuples( aNbPoints );
169
170       if ( theShrinkFactor > 0.0 )
171         this->ShrinkExecute();
172       else
173         this->SimpleExecute();
174
175       theOutput->SetPoints( aPoints );
176       
177       theOutput->SetCells( theInput->GetCellTypesArray(), 
178                            theInput->GetCellLocationsArray(),
179                            myConnectivity );
180
181       myConnectivity->Delete();
182       
183       vtkCellData *anOutputCellData = theOutput->GetCellData();
184       anOutputCellData->PassData( anInputCellData );
185       
186       anOutputCellData->RemoveArray( "ELNO_COMPONENT_MAPPER" );
187       anOutputCellData->RemoveArray( "ELNO_FIELD" );
188       anOutputCellData->RemoveArray( "VISU_FIELD" );
189       anOutputCellData->SetVectors( NULL );
190       
191       //anOutputPointData->PassData( anInputPointData );
192       
193       myOutputPointData->AddArray( myElnoFullDataArray );
194       myElnoFullDataArray->Delete();
195       
196       if ( anInputCellData->GetVectors() != NULL ) 
197         myOutputPointData->SetVectors( myElnoPartialDataArray );
198       else
199         myOutputPointData->SetScalars( myElnoPartialDataArray );
200       myElnoPartialDataArray->Delete();
201       
202       myOutputPointData->AddArray( myElnoPointCoords );
203       myElnoPointCoords->Delete();
204       
205       myOutputPointData->AddArray( myOutputPointsMapper );
206       myOutputPointsMapper->Delete();
207     }
208
209     //----------------------------------------------------------------------------
210     void SimpleExecute()
211     {
212       // To reserve a temproary value holder
213       vtkIdType aNbComp = std::max( 3, myGetElnoNodeData.getNbComp() );
214       std::vector< TElnoDataType > anElnoDataValues( aNbComp ); 
215
216       std::vector< int > anPointsMapperValues( myInputPointsMapper->GetNumberOfComponents() ); 
217    
218       myConnectivity->InitTraversal();
219       vtkIdType aNbPts = 0, *aPts = 0;
220       for ( vtkIdType aCellId = 0; myConnectivity->GetNextCell( aNbPts, aPts ); aCellId++ ) {
221         for ( vtkIdType aPntId = 0; aPntId < aNbPts; aPntId++ ) {
222           TPointsDataType aCoords[ 3 ];
223           vtkIdType aCurrentPntId = aPts[ aPntId ];
224           myInputPointsArray->GetTupleValue( aCurrentPntId, aCoords );
225           
226           aPts[ aPntId ] = myOutputPointsArray->InsertNextTupleValue( aCoords );
227           vtkIdType aNewPntId = aPts[ aPntId ];
228           
229           myElnoPointCoords->SetTupleValue( aNewPntId, aCoords );
230           
231           myOutputPointData->CopyData( myInputPointData, aCurrentPntId, aNewPntId );
232           
233           TElnoDataType* anElnoData = myGetElnoNodeData( aCellId, aPntId );
234           myElnoFullDataArray->SetTupleValue( aNewPntId,  anElnoData );
235           
236           myElnoFullDataArray->GetTupleValue( aNewPntId, &anElnoDataValues[ 0 ] );
237           myElnoPartialDataArray->SetTupleValue( aNewPntId, &anElnoDataValues[ 0 ] );
238
239           myInputPointsMapper->GetTupleValue( aCurrentPntId, &anPointsMapperValues[ 0 ] );
240           myOutputPointsMapper->SetTupleValue( aNewPntId, &anPointsMapperValues[ 0 ] );
241         }
242       }
243     }
244
245     //----------------------------------------------------------------------------
246     void ShrinkExecute()
247     {
248       // To reserve a temproary value holder
249       vtkIdType aNbComp = std::max( 3, myGetElnoNodeData.getNbComp() );
250       std::vector< TElnoDataType > anElnoDataValues( aNbComp ); 
251       
252       std::vector< int > anPointsMapperValues( myInputPointsMapper->GetNumberOfComponents() ); 
253    
254       myConnectivity->InitTraversal();
255       vtkIdType aNbPts = 0, *aPts = 0;
256       for ( vtkIdType aCellId = 0; myConnectivity->GetNextCell( aNbPts, aPts ); aCellId++ ) {
257         
258         TPointsDataType aCenter[ 3 ] = { TPointsDataType(), TPointsDataType(), TPointsDataType() };
259         
260         for ( vtkIdType aPntId = 0; aPntId < aNbPts; aPntId++ ) {
261           TPointsDataType aCoords[ 3 ];
262           myInputPointsArray->GetTupleValue( aPts[ aPntId ], aCoords );
263           
264           aCenter[ 0 ] += aCoords[ 0 ];
265           aCenter[ 1 ] += aCoords[ 1 ];
266           aCenter[ 2 ] += aCoords[ 2 ];
267         }
268         
269         aCenter[ 0 ] /= aNbPts;
270         aCenter[ 1 ] /= aNbPts;
271         aCenter[ 2 ] /= aNbPts;
272         
273         for ( vtkIdType aPntId = 0; aPntId < aNbPts; aPntId++ ) {
274           TPointsDataType aCoords[ 3 ];
275           vtkIdType aCurrentPntId = aPts[ aPntId ];
276           myInputPointsArray->GetTupleValue( aCurrentPntId, aCoords );
277           
278           TPointsDataType aNewCoords[ 3 ];
279           
280           aNewCoords[ 0 ] = aCenter[ 0 ]  + 
281             TPointsDataType( myShrinkFactor * ( aCoords[ 0 ] - aCenter[ 0 ] ) );
282           aNewCoords[ 1 ] = aCenter[ 1 ]  + 
283             TPointsDataType( myShrinkFactor * ( aCoords[ 1 ] - aCenter[ 1 ] ) );
284           aNewCoords[ 2 ] = aCenter[ 2 ]  + 
285             TPointsDataType( myShrinkFactor * ( aCoords[ 2 ] - aCenter[ 2 ] ) );
286           
287           aPts[ aPntId ] = myOutputPointsArray->InsertNextTupleValue( aNewCoords );
288           vtkIdType aNewPntId = aPts[ aPntId ];
289           
290           myElnoPointCoords->SetTupleValue( aNewPntId, aCoords );
291           
292           myOutputPointData->CopyData( myInputPointData, aCurrentPntId, aNewPntId );
293           
294           TElnoDataType* anElnoData = myGetElnoNodeData( aCellId, aPntId );
295           myElnoFullDataArray->SetTupleValue( aNewPntId, anElnoData );
296           
297           myElnoFullDataArray->GetTupleValue( aNewPntId, &anElnoDataValues[ 0 ] );
298           myElnoPartialDataArray->SetTupleValue( aNewPntId, &anElnoDataValues[ 0 ] );
299
300           myInputPointsMapper->GetTupleValue( aCurrentPntId, &anPointsMapperValues[ 0 ] );
301           myOutputPointsMapper->SetTupleValue( aNewPntId, &anPointsMapperValues[ 0 ] );
302         }
303       }
304     }
305   };
306
307
308   //----------------------------------------------------------------------------
309   template < int points_type, int elno_type >
310   int Execute2( vtkUnstructuredGrid *theInput, 
311                 vtkUnstructuredGrid *theOutput, 
312                 vtkDataArray *theElnoDataArray,
313                 vtkDataArray *theElnoDataMapper,
314                 vtkFloatingPointType theShrinkFactor )
315   {
316     TExecute2< points_type, elno_type >( theInput, 
317                                          theOutput, 
318                                          theElnoDataArray, 
319                                          theElnoDataMapper, 
320                                          theShrinkFactor );
321         
322     return 1;
323   }
324           
325
326   //----------------------------------------------------------------------------
327   template < int points_type >
328   int Execute( vtkUnstructuredGrid *theInput, 
329                vtkUnstructuredGrid *theOutput, 
330                vtkDataArray *theElnoDataArray,
331                vtkDataArray *theElnoDataMapper,
332                vtkFloatingPointType theShrinkFactor )
333   {
334     switch( theElnoDataArray->GetDataType() ){
335     case VTK_DOUBLE:
336       return Execute2< points_type, VTK_DOUBLE >
337         ( theInput, theOutput, theElnoDataArray, theElnoDataMapper, theShrinkFactor );
338     case VTK_FLOAT:
339       return Execute2< points_type, VTK_FLOAT >
340         ( theInput, theOutput, theElnoDataArray, theElnoDataMapper, theShrinkFactor );
341     case VTK_INT:
342       return Execute2< points_type, VTK_INT >
343         ( theInput, theOutput, theElnoDataArray, theElnoDataMapper, theShrinkFactor );
344     case VTK_LONG:
345       return Execute2< points_type, VTK_LONG >
346         ( theInput, theOutput, theElnoDataArray, theElnoDataMapper, theShrinkFactor );
347     default:
348       break;
349     }
350     
351     return 0;
352   } 
353
354
355   //----------------------------------------------------------------------------
356 }
357
358
359 //----------------------------------------------------------------------------
360 int VISU_ElnoDisassembleFilter::RequestData( vtkInformation *vtkNotUsed(request),
361                                              vtkInformationVector **inputVector,
362                                              vtkInformationVector *outputVector )
363 {
364   // get the info objects
365   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
366   vtkInformation *outInfo = outputVector->GetInformationObject(0);
367
368   // get the input and ouptut
369   vtkUnstructuredGrid *anInput =
370     vtkUnstructuredGrid::SafeDownCast( inInfo->Get( vtkDataObject::DATA_OBJECT() ) );
371   vtkUnstructuredGrid *anOutput = 
372     vtkUnstructuredGrid::SafeDownCast( outInfo->Get( vtkDataObject::DATA_OBJECT() ) );
373
374   vtkDataArray *anElnoDataArray = this->GetInputArrayToProcess( 0, inputVector );
375   vtkDataArray *anElnoDataMapper = this->GetInputArrayToProcess( 1, inputVector );
376
377   if ( !anElnoDataArray ) {
378     anOutput->ShallowCopy( anInput );
379     return 1;
380   }
381
382   vtkPoints *aPoints = anInput->GetPoints();
383   switch( aPoints->GetDataType() ){
384   case VTK_DOUBLE:
385     return ::Execute< VTK_DOUBLE >( anInput, anOutput, anElnoDataArray, anElnoDataMapper, myShrinkFactor );
386   case VTK_FLOAT:
387     return ::Execute< VTK_FLOAT >( anInput, anOutput, anElnoDataArray, anElnoDataMapper, myShrinkFactor );
388   case VTK_INT:
389     return ::Execute< VTK_INT >( anInput, anOutput, anElnoDataArray, anElnoDataMapper, myShrinkFactor );
390   case VTK_LONG:
391     return ::Execute< VTK_LONG >( anInput, anOutput, anElnoDataArray, anElnoDataMapper, myShrinkFactor );
392   default:
393     break;
394   }  
395   
396   return 0;
397 }
398
399
400 //----------------------------------------------------------------------------