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