Salome HOME
79d20d81305011bed2749e846300d01dc4f6029a
[modules/smesh.git] / src / OBJECT / SMESH_DeviceActor.cxx
1 //  SMESH OBJECT : interactive object for SMESH visualization
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   : SMESH_Actor.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27 //  $Header$
28
29
30 #include "SMESH_DeviceActor.h"
31 #include "SMESH_ExtractGeometry.h"
32
33 #include "SALOME_Transform.h"
34 #include "SALOME_TransformFilter.h"
35 #include "SALOME_PassThroughFilter.h"
36 #include "SALOME_ExtractUnstructuredGrid.h"
37
38 #include "utilities.h"
39
40 // VTK Includes
41 #include <vtkObjectFactory.h>
42 #include <vtkShrinkFilter.h>
43 #include <vtkShrinkPolyData.h>
44
45 #include <vtkProperty.h>
46 #include <vtkPolyData.h>
47 #include <vtkMergeFilter.h>
48 #include <vtkPolyDataMapper.h>
49 #include <vtkUnstructuredGrid.h>
50
51 #include <vtkScalarBarActor.h>
52 #include <vtkLookupTable.h>
53 #include <vtkDoubleArray.h>
54 #include <vtkCellData.h>
55
56 #include <vtkCell.h>
57 #include <vtkIdList.h>
58 #include <vtkIntArray.h>
59 #include <vtkCellArray.h>
60 #include <vtkUnsignedCharArray.h>
61
62 #include <vtkImplicitBoolean.h>
63
64 #ifdef _DEBUG_
65 static int MYDEBUG = 0;
66 static int MYDEBUGWITHFILES = 0;
67 #else
68 static int MYDEBUG = 0;
69 static int MYDEBUGWITHFILES = 0;
70 #endif
71
72 using namespace std;
73
74
75 vtkStandardNewMacro(SMESH_DeviceActor);
76
77
78 SMESH_DeviceActor::SMESH_DeviceActor(){
79   if(MYDEBUG) MESSAGE("SMESH_DeviceActor");
80   myIsShrunk = false;
81   myIsShrinkable = false;
82   myRepresentation = eSurface;
83
84   myProperty = vtkProperty::New();
85   myMapper = vtkPolyDataMapper::New();
86
87   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(myPolygonOffsetFactor,
88                                                                  myPolygonOffsetUnits);
89
90   myMapper->UseLookupTableScalarRangeOn();
91   myMapper->SetColorModeToMapScalars();
92
93   myShrinkFilter = vtkShrinkFilter::New();
94
95   myExtractGeometry = SMESH_ExtractGeometry::New();
96   myExtractGeometry->SetStoreMapping(true);
97
98   myExtractUnstructuredGrid = SALOME_ExtractUnstructuredGrid::New();
99   myExtractUnstructuredGrid->SetStoreMapping(true);
100
101   myMergeFilter = vtkMergeFilter::New();
102
103   myStoreMapping = false;
104   myGeomFilter = SALOME_GeometryFilter::New();
105
106   myTransformFilter = SALOME_TransformFilter::New();
107
108   for(int i = 0; i < 6; i++)
109     myPassFilter.push_back(SALOME_PassThroughFilter::New());
110 }
111
112
113 SMESH_DeviceActor::~SMESH_DeviceActor(){
114   if(MYDEBUG) MESSAGE("~SMESH_DeviceActor");
115   myProperty->Delete();
116
117   myMapper->RemoveAllInputs();
118   myMapper->Delete();
119
120   myShrinkFilter->UnRegisterAllOutputs();
121   myShrinkFilter->Delete();
122
123   myExtractUnstructuredGrid->UnRegisterAllOutputs();
124   myExtractUnstructuredGrid->Delete();
125
126   myMergeFilter->UnRegisterAllOutputs();
127   myMergeFilter->Delete();
128
129   myGeomFilter->UnRegisterAllOutputs();
130   myGeomFilter->Delete();
131
132   myExtractGeometry->UnRegisterAllOutputs();
133   myExtractGeometry->Delete();
134
135   myTransformFilter->UnRegisterAllOutputs();
136   myTransformFilter->Delete();
137
138   for(int i = 0, iEnd = myPassFilter.size(); i < iEnd; i++){
139     myPassFilter[i]->UnRegisterAllOutputs(); 
140     myPassFilter[i]->Delete();
141   }
142 }
143
144
145 void SMESH_DeviceActor::SetStoreMapping(int theStoreMapping){
146   myStoreMapping = theStoreMapping;
147   Modified();
148 }
149
150
151 void SMESH_DeviceActor::Init(TVisualObjPtr theVisualObj, 
152                              vtkImplicitBoolean* theImplicitBoolean)
153 {
154   myVisualObj = theVisualObj;
155   myExtractGeometry->SetImplicitFunction(theImplicitBoolean);
156   SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
157 }
158
159
160 void SMESH_DeviceActor::SetUnstructuredGrid(vtkUnstructuredGrid* theGrid){
161   if(theGrid){
162     //myIsShrinkable = theGrid->GetNumberOfCells() > 10;
163     myIsShrinkable = true;
164
165     myExtractGeometry->SetInput(theGrid);
166
167     myExtractUnstructuredGrid->SetInput(myExtractGeometry->GetOutput());
168     myMergeFilter->SetGeometry(myExtractUnstructuredGrid->GetOutput());
169
170     theGrid = static_cast<vtkUnstructuredGrid*>(myMergeFilter->GetOutput());
171
172     int anId = 0;
173     myPassFilter[ anId ]->SetInput( theGrid );
174     myPassFilter[ anId + 1]->SetInput( myPassFilter[ anId ]->GetOutput() );
175     
176     anId++; // 1
177     myGeomFilter->SetStoreMapping( myStoreMapping );
178     myGeomFilter->SetInput( myPassFilter[ anId ]->GetOutput() );
179
180     anId++; // 2
181     myPassFilter[ anId ]->SetInput( myGeomFilter->GetOutput() ); 
182     myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
183
184     anId++; // 3
185     myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
186     myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
187
188     anId++; // 4
189     myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
190     myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
191     myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
192     myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
193
194     anId++; // 5
195     myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
196     myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
197
198     vtkLODActor::SetMapper( myMapper );
199     Modified();
200   }
201 }
202
203
204 SALOME_ExtractUnstructuredGrid* SMESH_DeviceActor::GetExtractUnstructuredGrid(){
205   return myExtractUnstructuredGrid;
206 }
207
208
209 vtkUnstructuredGrid* SMESH_DeviceActor::GetUnstructuredGrid(){
210   myExtractUnstructuredGrid->Update();
211   return myExtractUnstructuredGrid->GetOutput();
212 }
213
214
215 void SMESH_DeviceActor::SetControlMode(SMESH::Controls::FunctorPtr theFunctor,
216                                        vtkScalarBarActor* theScalarBarActor,
217                                        vtkLookupTable* theLookupTable)
218 {
219   bool anIsInitialized = theFunctor;
220   if(anIsInitialized){
221     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
222     vtkUnstructuredGrid* aGrid = myExtractUnstructuredGrid->GetOutput();
223     aDataSet->ShallowCopy(aGrid);
224     
225     vtkDoubleArray *aScalars = vtkDoubleArray::New();
226     vtkIdType aNbCells = aGrid->GetNumberOfCells();
227     aScalars->SetNumberOfComponents(1);
228     aScalars->SetNumberOfTuples(aNbCells);
229     
230     myVisualObj->UpdateFunctor(theFunctor);
231
232     using namespace SMESH::Controls;
233     if(NumericalFunctor* aNumericalFunctor = dynamic_cast<NumericalFunctor*>(theFunctor.get())){
234       for(vtkIdType i = 0; i < aNbCells; i++){
235         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
236         vtkIdType anId2 = myExtractGeometry->GetElemObjId(anId);
237         vtkIdType anObjId = myVisualObj->GetElemObjId(anId2);
238         double aValue = aNumericalFunctor->GetValue(anObjId);
239         aScalars->SetValue(i,aValue);
240       }
241     }else if(Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get())){
242       for(vtkIdType i = 0; i < aNbCells; i++){
243         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
244         vtkIdType anId2 = myExtractGeometry->GetElemObjId(anId);
245         vtkIdType anObjId = myVisualObj->GetElemObjId(anId2);
246         bool aValue = aPredicate->IsSatisfy(anObjId);
247         aScalars->SetValue(i,aValue);
248       }
249     }
250
251     aDataSet->GetCellData()->SetScalars(aScalars);
252     aScalars->Delete();
253         
254     theLookupTable->SetRange(aScalars->GetRange());
255     theLookupTable->Build();
256     
257     myMergeFilter->SetScalars(aDataSet);
258     aDataSet->Delete();
259   }
260   GetMapper()->SetScalarVisibility(anIsInitialized);
261   theScalarBarActor->SetVisibility(anIsInitialized);
262 }
263
264
265 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
266                                           SMESH_DeviceActor* theDeviceActor)
267 {
268   myExtractUnstructuredGrid->ClearRegisteredCells();
269   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
270   myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::ePassAll);
271   myVisualObj->UpdateFunctor(theFunctor);
272
273   using namespace SMESH::Controls;
274   if(FreeBorders* aFreeBorders = dynamic_cast<FreeBorders*>(theFunctor.get())){
275     myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::eAdding);
276     myExtractUnstructuredGrid->ClearRegisteredCells();
277     vtkUnstructuredGrid* aGrid = theDeviceActor->GetUnstructuredGrid();
278     vtkIdType aNbCells = aGrid->GetNumberOfCells();
279     for( vtkIdType i = 0; i < aNbCells; i++ ){
280       vtkIdType anObjId = theDeviceActor->GetElemObjId(i);
281       if(aFreeBorders->IsSatisfy(anObjId))
282         myExtractUnstructuredGrid->RegisterCell(i);
283     }
284     if(!myExtractUnstructuredGrid->IsCellsRegistered())
285       myExtractUnstructuredGrid->RegisterCell(-1);
286     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
287   }else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get())){
288     SMESH::Controls::FreeEdges::TBorders aBorders;
289     aFreeEdges->GetBoreders(aBorders);
290     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
291     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
292     aDataSet->SetPoints(aGrid->GetPoints());
293
294     vtkIdType aNbCells = aBorders.size();
295     vtkIdType aCellsSize = 3*aNbCells;
296     vtkCellArray* aConnectivity = vtkCellArray::New();
297     aConnectivity->Allocate( aCellsSize, 0 );
298     
299     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
300     aCellTypesArray->SetNumberOfComponents( 1 );
301     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
302     
303     vtkIdList *anIdList = vtkIdList::New();
304     anIdList->SetNumberOfIds(2);
305     
306     FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
307     for(vtkIdType aVtkId; anIter != aBorders.end(); anIter++){
308       const FreeEdges::Border& aBorder = *anIter;
309       int aNode[2] = {
310         myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
311         myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
312       };
313       //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
314       if(aNode[0] >= 0 && aNode[1] >= 0){
315         anIdList->SetId( 0, aNode[0] );
316         anIdList->SetId( 1, aNode[1] );
317         aConnectivity->InsertNextCell( anIdList );
318         aCellTypesArray->InsertNextValue( VTK_LINE );
319       }
320     }
321     
322     vtkIntArray* aCellLocationsArray = vtkIntArray::New();
323     aCellLocationsArray->SetNumberOfComponents( 1 );
324     aCellLocationsArray->SetNumberOfTuples( aNbCells );
325     
326     aConnectivity->InitTraversal();
327     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
328       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
329     
330     aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
331
332     SetUnstructuredGrid(aDataSet);
333     aDataSet->Delete();
334   }    
335 }
336
337
338 unsigned long int SMESH_DeviceActor::GetMTime(){
339   unsigned long mTime = this->Superclass::GetMTime();
340   mTime = max(mTime,myExtractGeometry->GetMTime());
341   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
342   mTime = max(mTime,myMergeFilter->GetMTime());
343   mTime = max(mTime,myGeomFilter->GetMTime());
344   mTime = max(mTime,myTransformFilter->GetMTime());
345   return mTime;
346 }
347
348
349 void SMESH_DeviceActor::SetTransform(SALOME_Transform* theTransform){
350   myTransformFilter->SetTransform(theTransform);
351 }
352
353
354 void SMESH_DeviceActor::SetShrink() {
355   if ( !myIsShrinkable ) return;
356   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
357   {
358     myShrinkFilter->SetInput( aDataSet );
359     myPassFilter[ 1 ]->SetInput( myShrinkFilter->GetOutput() );
360     myIsShrunk = true;
361   }
362 }
363
364 void SMESH_DeviceActor::UnShrink() {
365   if ( !myIsShrunk ) return;
366   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
367   {    
368     myPassFilter[ 1 ]->SetInput( aDataSet );
369     myPassFilter[ 1 ]->Modified();
370     myIsShrunk = false;
371     Modified();
372   }
373 }
374
375
376 void SMESH_DeviceActor::SetRepresentation(EReperesent theMode){ 
377   switch(theMode){
378   case ePoint: 
379     myGeomFilter->SetInside(true);
380     GetProperty()->SetRepresentation(0);
381     break;
382   case eInsideframe: 
383     myGeomFilter->SetInside(true);
384     GetProperty()->SetRepresentation(1);
385     break;
386   default :
387     GetProperty()->SetRepresentation(theMode);
388     myGeomFilter->SetInside(false);
389   }
390   myRepresentation = theMode;
391   GetProperty()->Modified();
392   myMapper->Modified();
393   Modified();
394 }
395
396
397 void SMESH_DeviceActor::SetVisibility(int theMode){
398   if(!myExtractUnstructuredGrid->GetInput() || GetUnstructuredGrid()->GetNumberOfCells()){
399     vtkLODActor::SetVisibility(theMode);
400   }else{
401     vtkLODActor::SetVisibility(false);
402   }
403 }
404
405
406 int SMESH_DeviceActor::GetVisibility(){
407   if(!GetUnstructuredGrid()->GetNumberOfCells()){
408     vtkLODActor::SetVisibility(false);
409   }
410   return vtkLODActor::GetVisibility();
411 }
412
413
414 int SMESH_DeviceActor::GetNodeObjId(int theVtkID){
415   vtkIdType anID = myExtractGeometry->GetNodeObjId(theVtkID);
416   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
417   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; aRetID = "<<aRetID);
418   return aRetID;
419 }
420
421 float* SMESH_DeviceActor::GetNodeCoord(int theObjID){
422   vtkDataSet* aDataSet = myExtractGeometry->GetInput();
423   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
424   float* aCoord = aDataSet->GetPoint(anID);
425   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
426   return aCoord;
427 }
428
429
430 int SMESH_DeviceActor::GetElemObjId(int theVtkID){
431   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
432   if(anId < 0) 
433     return -1;
434   vtkIdType anId2 = myExtractUnstructuredGrid->GetInputId(anId);
435   if(anId2 < 0) 
436     return -1;
437   vtkIdType anId3 = myExtractGeometry->GetElemObjId(anId2);
438   if(anId3 < 0) 
439     return -1;
440   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
441   if(MYDEBUG) 
442     MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
443   return aRetID;
444 }
445
446 vtkCell* SMESH_DeviceActor::GetElemCell(int theObjID){
447   vtkDataSet* aDataSet = myExtractGeometry->GetInput();
448   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
449   vtkCell* aCell = aDataSet->GetCell(aGridID);
450   if(MYDEBUG) 
451     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
452   return aCell;
453 }
454
455
456 float SMESH_DeviceActor::GetShrinkFactor(){
457   return myShrinkFilter->GetShrinkFactor();
458 }
459
460 void SMESH_DeviceActor::SetShrinkFactor(float theValue){
461   theValue = theValue > 0.1? theValue: 0.8;
462   myShrinkFilter->SetShrinkFactor(theValue);
463   Modified();
464 }
465
466
467 void SMESH_DeviceActor::SetHighlited(bool theIsHighlited){
468   myIsHighlited = theIsHighlited;
469   Modified();
470 }
471
472 void SMESH_DeviceActor::Render(vtkRenderer *ren, vtkMapper* m){
473   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
474   float aStoredFactor, aStoredUnit; 
475   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
476
477   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
478   float aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
479   if(myIsHighlited){
480     static float EPS = .01;
481     aUnits *= (1.0-EPS);
482   }
483   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
484   vtkLODActor::Render(ren,m);
485
486   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
487   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
488 }
489
490
491 void SMESH_DeviceActor::SetPolygonOffsetParameters(float factor, float units){
492   myPolygonOffsetFactor = factor;
493   myPolygonOffsetUnits = units;
494 }
495