Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / OBJECT / SMESH_DeviceActor.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH OBJECT : interactive object for SMESH visualization
23 //  File   : SMESH_DeviceActor.cxx
24 //  Author : 
25 //  Module : SMESH
26 //
27
28 #include "SMESH_DeviceActor.h"
29 #include "SMESH_ExtractGeometry.h"
30 #include "SMESH_ControlsDef.hxx"
31 #include "SMESH_ActorUtils.h"
32 #include "SMESH_FaceOrientationFilter.h"
33 #include "VTKViewer_CellLocationsArray.h"
34
35 #include <VTKViewer_Transform.h>
36 #include <VTKViewer_TransformFilter.h>
37 #include <VTKViewer_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 <vtkCellArray.h>
58 #include <vtkUnsignedCharArray.h>
59
60 #include <vtkImplicitBoolean.h>
61 #include <vtkPassThroughFilter.h>
62
63 #include <vtkRenderer.h>
64
65 #include "utilities.h"
66
67 #ifdef _DEBUG_
68 static int MYDEBUG = 0;
69 #else
70 static int MYDEBUG = 0;
71 #endif
72
73 using namespace std;
74
75
76 vtkStandardNewMacro(SMESH_DeviceActor);
77
78
79 SMESH_DeviceActor
80 ::SMESH_DeviceActor()
81 {
82   if(MYDEBUG) MESSAGE("SMESH_DeviceActor - "<<this);
83
84   myIsShrinkable = false;
85   myIsShrunk = false;
86   myIsHighlited = false;
87
88   myRepresentation = eSurface;
89
90   myProperty = vtkProperty::New();
91   myMapper = vtkPolyDataMapper::New();
92
93   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(myPolygonOffsetFactor,
94                                                                  myPolygonOffsetUnits);
95
96   myMapper->UseLookupTableScalarRangeOn();
97   myMapper->SetColorModeToMapScalars();
98
99   myShrinkFilter = vtkShrinkFilter::New();
100
101   myStoreClippingMapping = false;
102
103   myExtractGeometry = SMESH_ExtractGeometry::New();
104   myExtractGeometry->SetReleaseDataFlag(true);
105   myIsImplicitFunctionUsed = false;
106
107   myExtractUnstructuredGrid = VTKViewer_ExtractUnstructuredGrid::New();
108     
109   myMergeFilter = vtkMergeFilter::New();
110
111   myGeomFilter = VTKViewer_GeometryFilter::New();
112
113   myTransformFilter = VTKViewer_TransformFilter::New();
114
115   for(int i = 0; i < 6; i++)
116     myPassFilter.push_back(vtkPassThroughFilter::New());
117
118   // Orientation of faces
119   myIsFacesOriented = false;
120
121   vtkFloatingPointType anRGB[3] = { 1, 1, 1 };
122   SMESH::GetColor( "SMESH", "orientation_color", anRGB[0], anRGB[1], anRGB[2], QColor( 255, 255, 255 ) );
123
124   myFaceOrientationFilter = SMESH_FaceOrientationFilter::New();
125
126   myFaceOrientationDataMapper = vtkPolyDataMapper::New();
127   myFaceOrientationDataMapper->SetInput(myFaceOrientationFilter->GetOutput());
128
129   myFaceOrientation = vtkActor::New();
130   myFaceOrientation->SetMapper(myFaceOrientationDataMapper);
131   myFaceOrientation->GetProperty()->SetColor(anRGB[0], anRGB[1], anRGB[2]);
132 }
133
134
135 SMESH_DeviceActor
136 ::~SMESH_DeviceActor()
137 {
138   if(MYDEBUG) MESSAGE("~SMESH_DeviceActor - "<<this);
139
140   myProperty->Delete();
141
142   myMapper->Delete();
143
144   myShrinkFilter->Delete();
145
146   myExtractUnstructuredGrid->Delete();
147
148   myMergeFilter->Delete();
149
150   myGeomFilter->Delete();
151
152   myExtractGeometry->Delete();
153
154   myTransformFilter->Delete();
155
156   for(int i = 0, iEnd = myPassFilter.size(); i < iEnd; i++){
157     myPassFilter[i]->Delete();
158   }
159
160   // Orientation of faces
161   myFaceOrientationFilter->Delete();
162
163   myFaceOrientationDataMapper->RemoveAllInputs();
164   myFaceOrientationDataMapper->Delete();
165
166   myFaceOrientation->Delete();
167 }
168
169
170 void
171 SMESH_DeviceActor
172 ::SetStoreGemetryMapping(bool theStoreMapping)
173 {
174   myGeomFilter->SetStoreMapping(theStoreMapping);
175   SetStoreClippingMapping(theStoreMapping);
176 }
177
178
179 void
180 SMESH_DeviceActor
181 ::SetStoreClippingMapping(bool theStoreMapping)
182 {
183   myStoreClippingMapping = theStoreMapping;
184   myExtractGeometry->SetStoreMapping(theStoreMapping && myIsImplicitFunctionUsed);
185   SetStoreIDMapping(theStoreMapping);
186 }
187
188
189 void
190 SMESH_DeviceActor
191 ::SetStoreIDMapping(bool theStoreMapping)
192 {
193   myExtractUnstructuredGrid->SetStoreMapping(theStoreMapping);
194 }
195
196
197 void 
198 SMESH_DeviceActor
199 ::Init(TVisualObjPtr theVisualObj, 
200        vtkImplicitBoolean* theImplicitBoolean)
201 {
202   myVisualObj = theVisualObj;
203   myExtractGeometry->SetImplicitFunction(theImplicitBoolean);
204   SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
205 }
206
207
208 void
209 SMESH_DeviceActor
210 ::SetImplicitFunctionUsed(bool theIsImplicitFunctionUsed)
211 {
212   int anId = 0;
213   if(theIsImplicitFunctionUsed)
214     myPassFilter[ anId ]->SetInput( myExtractGeometry->GetOutput() );
215   else
216     myPassFilter[ anId ]->SetInput( myMergeFilter->GetOutput() );
217     
218   myIsImplicitFunctionUsed = theIsImplicitFunctionUsed;
219   SetStoreClippingMapping(myStoreClippingMapping);
220 }
221
222
223 void
224 SMESH_DeviceActor
225 ::SetUnstructuredGrid(vtkUnstructuredGrid* theGrid)
226 {
227   if(theGrid){
228     //myIsShrinkable = theGrid->GetNumberOfCells() > 10;
229     myIsShrinkable = true;
230
231     myExtractUnstructuredGrid->SetInput(theGrid);
232
233     myMergeFilter->SetGeometry(myExtractUnstructuredGrid->GetOutput());
234
235     myExtractGeometry->SetInput(myMergeFilter->GetOutput());
236
237     int anId = 0;
238     SetImplicitFunctionUsed(myIsImplicitFunctionUsed);
239     myPassFilter[ anId + 1]->SetInput( myPassFilter[ anId ]->GetOutput() );
240     
241     anId++; // 1
242     myGeomFilter->SetInput( myPassFilter[ anId ]->GetOutput() );
243
244     anId++; // 2
245     myPassFilter[ anId ]->SetInput( myGeomFilter->GetOutput() ); 
246     myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
247
248     anId++; // 3
249     myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
250
251     anId++; // 4
252     myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
253     myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
254
255     anId++; // 5
256     myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
257
258     vtkLODActor::SetMapper( myMapper );
259     Modified();
260   }
261 }
262
263
264 VTKViewer_ExtractUnstructuredGrid* 
265 SMESH_DeviceActor
266 ::GetExtractUnstructuredGrid()
267 {
268   return myExtractUnstructuredGrid;
269 }
270
271
272 vtkUnstructuredGrid* 
273 SMESH_DeviceActor
274 ::GetUnstructuredGrid()
275 {
276   myExtractUnstructuredGrid->Update();
277   return myExtractUnstructuredGrid->GetOutput();
278 }
279
280
281 void
282 SMESH_DeviceActor
283 ::SetControlMode(SMESH::Controls::FunctorPtr theFunctor,
284                  vtkScalarBarActor* theScalarBarActor,
285                  vtkLookupTable* theLookupTable)
286 {
287   bool anIsInitialized = theFunctor;
288   if(anIsInitialized){
289     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
290
291     SetStoreIDMapping(true);
292     myExtractUnstructuredGrid->Update();
293     vtkUnstructuredGrid* aGrid = myExtractUnstructuredGrid->GetOutput();
294
295     aDataSet->ShallowCopy(aGrid);
296     
297     vtkDoubleArray *aScalars = vtkDoubleArray::New();
298     vtkIdType aNbCells = aGrid->GetNumberOfCells();
299     aScalars->SetNumberOfComponents(1);
300     aScalars->SetNumberOfTuples(aNbCells);
301     
302     myVisualObj->UpdateFunctor(theFunctor);
303
304     using namespace SMESH::Controls;
305     if(NumericalFunctor* aNumericalFunctor = dynamic_cast<NumericalFunctor*>(theFunctor.get())){
306       for(vtkIdType i = 0; i < aNbCells; i++){
307         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
308         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
309         double aValue = aNumericalFunctor->GetValue(anObjId);
310         aScalars->SetValue(i,aValue);
311       }
312     }else if(Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get())){
313       for(vtkIdType i = 0; i < aNbCells; i++){
314         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
315         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
316         bool aValue = aPredicate->IsSatisfy(anObjId);
317         aScalars->SetValue(i,aValue);
318       }
319     }
320
321     aDataSet->GetCellData()->SetScalars(aScalars);
322     aScalars->Delete();
323         
324     theLookupTable->SetRange(aScalars->GetRange());
325     theLookupTable->SetNumberOfTableValues(theScalarBarActor->GetMaximumNumberOfColors());
326     theLookupTable->Build();
327     
328     myMergeFilter->SetScalars(aDataSet);
329     aDataSet->Delete();
330   }
331   GetMapper()->SetScalarVisibility(anIsInitialized);
332   theScalarBarActor->SetVisibility(anIsInitialized);
333 }
334
335 void
336 SMESH_DeviceActor
337 ::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
338                     vtkScalarBarActor* theScalarBarActor,
339                     vtkLookupTable* theLookupTable)
340 {
341   bool anIsInitialized = theFunctor;
342   myExtractUnstructuredGrid->ClearRegisteredCells();
343   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
344   myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::ePassAll);
345   myVisualObj->UpdateFunctor(theFunctor);
346
347   using namespace SMESH::Controls;
348   if (anIsInitialized){
349     if (Length2D* aLength2D = dynamic_cast<Length2D*>(theFunctor.get())){
350       SMESH::Controls::Length2D::TValues aValues;
351
352       aLength2D->GetValues(aValues);
353       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
354       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
355
356       aDataSet->SetPoints(aGrid->GetPoints());
357       
358       vtkIdType aNbCells = aValues.size();
359       
360       vtkDoubleArray *aScalars = vtkDoubleArray::New();
361       aScalars->SetNumberOfComponents(1);
362       aScalars->SetNumberOfTuples(aNbCells);
363
364       vtkIdType aCellsSize = 3*aNbCells;
365       vtkCellArray* aConnectivity = vtkCellArray::New();
366       aConnectivity->Allocate( aCellsSize, 0 );
367       
368       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
369       aCellTypesArray->SetNumberOfComponents( 1 );
370       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
371       
372       vtkIdList *anIdList = vtkIdList::New();
373       anIdList->SetNumberOfIds(2);
374       
375       Length2D::TValues::const_iterator anIter = aValues.begin();
376       for(vtkIdType aVtkId = 0; anIter != aValues.end(); anIter++,aVtkId++){
377         const Length2D::Value& aValue = *anIter;
378         int aNode[2] = {
379           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
380           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
381         };
382         if(aNode[0] >= 0 && aNode[1] >= 0){
383           anIdList->SetId( 0, aNode[0] );
384           anIdList->SetId( 1, aNode[1] );
385           aConnectivity->InsertNextCell( anIdList );
386           aCellTypesArray->InsertNextValue( VTK_LINE );
387           aScalars->SetValue(aVtkId,aValue.myLength);
388         }
389       }
390       
391       VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
392       aCellLocationsArray->SetNumberOfComponents( 1 );
393       aCellLocationsArray->SetNumberOfTuples( aNbCells );
394       
395       aConnectivity->InitTraversal();
396       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
397         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
398       
399       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
400       SetUnstructuredGrid(aDataSet);
401
402       aDataSet->GetCellData()->SetScalars(aScalars);
403       aScalars->Delete();
404       
405       theLookupTable->SetRange(aScalars->GetRange());
406       theLookupTable->Build();
407       
408       myMergeFilter->SetScalars(aDataSet);
409       aDataSet->Delete();
410     }
411     else if (MultiConnection2D* aMultiConnection2D = dynamic_cast<MultiConnection2D*>(theFunctor.get())){
412       SMESH::Controls::MultiConnection2D::MValues aValues;
413
414       aMultiConnection2D->GetValues(aValues);
415       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
416       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
417       aDataSet->SetPoints(aGrid->GetPoints());
418       
419       vtkIdType aNbCells = aValues.size();
420       vtkDoubleArray *aScalars = vtkDoubleArray::New();
421       aScalars->SetNumberOfComponents(1);
422       aScalars->SetNumberOfTuples(aNbCells);
423
424       vtkIdType aCellsSize = 3*aNbCells;
425       vtkCellArray* aConnectivity = vtkCellArray::New();
426       aConnectivity->Allocate( aCellsSize, 0 );
427       
428       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
429       aCellTypesArray->SetNumberOfComponents( 1 );
430       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
431       
432       vtkIdList *anIdList = vtkIdList::New();
433       anIdList->SetNumberOfIds(2);
434       
435       MultiConnection2D::MValues::const_iterator anIter = aValues.begin();
436       for(vtkIdType aVtkId = 0; anIter != aValues.end(); anIter++,aVtkId++){
437         const MultiConnection2D::Value& aValue = (*anIter).first;
438         int aNode[2] = {
439           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
440           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
441         };
442         if(aNode[0] >= 0 && aNode[1] >= 0){
443           anIdList->SetId( 0, aNode[0] );
444           anIdList->SetId( 1, aNode[1] );
445           aConnectivity->InsertNextCell( anIdList );
446           aCellTypesArray->InsertNextValue( VTK_LINE );
447           aScalars->SetValue(aVtkId,(*anIter).second);
448         }
449       }
450       
451       VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
452       aCellLocationsArray->SetNumberOfComponents( 1 );
453       aCellLocationsArray->SetNumberOfTuples( aNbCells );
454       
455       aConnectivity->InitTraversal();
456       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
457         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
458       
459       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
460       SetUnstructuredGrid(aDataSet);
461
462       aDataSet->GetCellData()->SetScalars(aScalars);
463       aScalars->Delete();
464       
465       theLookupTable->SetRange(aScalars->GetRange());
466       theLookupTable->Build();
467       
468       myMergeFilter->SetScalars(aDataSet);
469       aDataSet->Delete();
470     }
471   }
472   GetMapper()->SetScalarVisibility(anIsInitialized);
473   theScalarBarActor->SetVisibility(anIsInitialized);
474 }
475
476 void
477 SMESH_DeviceActor
478 ::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor)
479 {
480   myExtractUnstructuredGrid->ClearRegisteredCells();
481   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
482   myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::ePassAll);
483   myVisualObj->UpdateFunctor(theFunctor);
484
485   using namespace SMESH::Controls;
486   if ( dynamic_cast<FreeBorders*>(theFunctor.get()) ||
487        dynamic_cast<FreeFaces*>(theFunctor.get()) ) {
488     Predicate* aFreePredicate = dynamic_cast<Predicate*>(theFunctor.get());
489     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
490     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
491     vtkIdType aNbCells = aGrid->GetNumberOfCells();
492     for( vtkIdType i = 0; i < aNbCells; i++ ){
493       vtkIdType anObjId = myVisualObj->GetElemObjId(i);
494       if(aFreePredicate->IsSatisfy(anObjId))
495         myExtractUnstructuredGrid->RegisterCell(i);
496     }
497     if(!myExtractUnstructuredGrid->IsCellsRegistered())
498       myExtractUnstructuredGrid->RegisterCell(-1);
499     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
500   }else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get())){
501     SMESH::Controls::FreeEdges::TBorders aBorders;
502     aFreeEdges->GetBoreders(aBorders);
503     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
504     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
505     aDataSet->SetPoints(aGrid->GetPoints());
506
507     vtkIdType aNbCells = aBorders.size();
508     vtkIdType aCellsSize = 3*aNbCells;
509     vtkCellArray* aConnectivity = vtkCellArray::New();
510     aConnectivity->Allocate( aCellsSize, 0 );
511     
512     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
513     aCellTypesArray->SetNumberOfComponents( 1 );
514     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
515     
516     vtkIdList *anIdList = vtkIdList::New();
517     anIdList->SetNumberOfIds(2);
518     
519     FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
520     for(; anIter != aBorders.end(); anIter++){
521       const FreeEdges::Border& aBorder = *anIter;
522       int aNode[2] = {
523         myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
524         myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
525       };
526       //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
527       if(aNode[0] >= 0 && aNode[1] >= 0){
528         anIdList->SetId( 0, aNode[0] );
529         anIdList->SetId( 1, aNode[1] );
530         aConnectivity->InsertNextCell( anIdList );
531         aCellTypesArray->InsertNextValue( VTK_LINE );
532       }
533     }
534     
535     VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
536     aCellLocationsArray->SetNumberOfComponents( 1 );
537     aCellLocationsArray->SetNumberOfTuples( aNbCells );
538     
539     aConnectivity->InitTraversal();
540     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
541       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
542     
543     aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
544
545     SetUnstructuredGrid(aDataSet);
546     aDataSet->Delete();
547   }else if(FreeNodes* aFreeNodes = dynamic_cast<FreeNodes*>(theFunctor.get())){
548     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
549     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
550     vtkIdType aNbCells = aGrid->GetNumberOfCells();
551     for( vtkIdType i = 0; i < aNbCells; i++ ){
552       vtkIdType anObjId = myVisualObj->GetNodeObjId(i);
553       if(aFreeNodes->IsSatisfy(anObjId))
554         myExtractUnstructuredGrid->RegisterCell(i);
555     }
556     if(!myExtractUnstructuredGrid->IsCellsRegistered())
557       myExtractUnstructuredGrid->RegisterCell(-1);
558     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
559   }
560 }
561
562
563
564
565 unsigned long int 
566 SMESH_DeviceActor
567 ::GetMTime()
568 {
569   unsigned long mTime = this->Superclass::GetMTime();
570   mTime = max(mTime,myExtractGeometry->GetMTime());
571   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
572   mTime = max(mTime,myMergeFilter->GetMTime());
573   mTime = max(mTime,myGeomFilter->GetMTime());
574   mTime = max(mTime,myTransformFilter->GetMTime());
575   mTime = max(mTime,myFaceOrientationFilter->GetMTime());
576   return mTime;
577 }
578
579
580 void
581 SMESH_DeviceActor
582 ::SetTransform(VTKViewer_Transform* theTransform)
583 {
584   myTransformFilter->SetTransform(theTransform);
585 }
586
587
588 void
589 SMESH_DeviceActor
590 ::SetShrink() 
591 {
592   if ( !myIsShrinkable ) return;
593   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
594   {
595     myShrinkFilter->SetInput( aDataSet );
596     myPassFilter[ 1 ]->SetInput( myShrinkFilter->GetOutput() );
597     myIsShrunk = true;
598   }
599 }
600
601 void
602 SMESH_DeviceActor
603 ::UnShrink() 
604 {
605   if ( !myIsShrunk ) return;
606   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
607   {    
608     myPassFilter[ 1 ]->SetInput( aDataSet );
609     myPassFilter[ 1 ]->Modified();
610     myIsShrunk = false;
611     Modified();
612   }
613 }
614
615
616 void
617 SMESH_DeviceActor
618 ::SetFacesOriented(bool theIsFacesOriented) 
619 {
620   if ( vtkDataSet* aDataSet = myPassFilter[ 1 ]->GetOutput() )
621   {
622     myIsFacesOriented = theIsFacesOriented;
623     if( theIsFacesOriented )
624       myFaceOrientationFilter->SetInput( aDataSet );
625     UpdateFaceOrientation();
626   }
627 }
628
629 void
630 SMESH_DeviceActor
631 ::UpdateFaceOrientation()
632 {
633   bool aShowFaceOrientation = myIsFacesOriented;
634   aShowFaceOrientation &= GetVisibility();
635   aShowFaceOrientation &= myRepresentation == eSurface;
636   myFaceOrientation->SetVisibility(aShowFaceOrientation);
637 }
638
639
640 void
641 SMESH_DeviceActor
642 ::SetRepresentation(EReperesent theMode)
643 {
644   switch(theMode){
645   case ePoint:
646     myGeomFilter->SetInside(true);
647     myGeomFilter->SetWireframeMode(false);
648     GetProperty()->SetRepresentation(0);
649     break;
650   case eWireframe:
651     myGeomFilter->SetInside(false);
652     myGeomFilter->SetWireframeMode(true);
653     GetProperty()->SetRepresentation(theMode);
654     break;
655   case eInsideframe:
656     myGeomFilter->SetInside(true);
657     myGeomFilter->SetWireframeMode(true);
658     GetProperty()->SetRepresentation(1);
659     break;
660   case eSurface:
661     myGeomFilter->SetInside(false);
662     myGeomFilter->SetWireframeMode(false);
663     GetProperty()->SetRepresentation(theMode);
664   }
665   myRepresentation = theMode;
666   UpdateFaceOrientation();
667   GetProperty()->Modified();
668   myMapper->Modified();
669   Modified();
670 }
671
672
673 void
674 SMESH_DeviceActor
675 ::SetVisibility(int theMode)
676 {
677   if(!myExtractUnstructuredGrid->GetInput() || 
678      GetUnstructuredGrid()->GetNumberOfCells())
679   {
680     vtkLODActor::SetVisibility(theMode);
681   }else{
682     vtkLODActor::SetVisibility(false);
683   }
684   UpdateFaceOrientation();
685 }
686
687
688 int
689 SMESH_DeviceActor
690 ::GetVisibility()
691 {
692   if(!GetUnstructuredGrid()->GetNumberOfCells()){
693     vtkLODActor::SetVisibility(false);
694   }
695   return vtkLODActor::GetVisibility();
696 }
697
698
699 void
700 SMESH_DeviceActor
701 ::AddToRender(vtkRenderer* theRenderer)
702 {
703   theRenderer->AddActor(this);
704   theRenderer->AddActor(myFaceOrientation);
705 }
706
707 void
708 SMESH_DeviceActor
709 ::RemoveFromRender(vtkRenderer* theRenderer)
710 {
711   theRenderer->RemoveActor(this);
712   theRenderer->RemoveActor(myFaceOrientation);
713 }
714
715
716 int
717 SMESH_DeviceActor
718 ::GetNodeObjId(int theVtkID)
719 {
720   vtkIdType anID = theVtkID;
721
722   if(IsImplicitFunctionUsed())
723     anID = myExtractGeometry->GetNodeObjId(theVtkID);
724
725   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
726   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; anID = "<<anID<<"; aRetID = "<<aRetID);
727   return aRetID;
728 }
729
730 vtkFloatingPointType* 
731 SMESH_DeviceActor
732 ::GetNodeCoord(int theObjID)
733 {
734   vtkDataSet* aDataSet = myMergeFilter->GetOutput();
735   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
736   vtkFloatingPointType* aCoord = (anID >=0) ? aDataSet->GetPoint(anID) : NULL;
737   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
738   return aCoord;
739 }
740
741
742 int
743 SMESH_DeviceActor
744 ::GetElemObjId(int theVtkID)
745 {
746   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
747   if(anId < 0) 
748     return -1;
749
750   vtkIdType anId2 = anId;
751   if(IsImplicitFunctionUsed())
752     anId2 = myExtractGeometry->GetElemObjId(anId);
753   if(anId2 < 0) 
754     return -1;
755
756   vtkIdType anId3 = myExtractUnstructuredGrid->GetInputId(anId2);
757   if(anId3 < 0) 
758     return -1;
759
760   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
761   if(MYDEBUG) 
762      MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
763   return aRetID;
764 }
765
766 vtkCell* 
767 SMESH_DeviceActor
768 ::GetElemCell(int theObjID)
769 {
770   vtkDataSet* aDataSet = myVisualObj->GetUnstructuredGrid();
771   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
772   vtkCell* aCell = (aGridID >= 0 ) ? aDataSet->GetCell(aGridID) : NULL;
773   if(MYDEBUG) 
774     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
775   return aCell;
776 }
777
778
779 vtkFloatingPointType 
780 SMESH_DeviceActor
781 ::GetShrinkFactor()
782 {
783   return myShrinkFilter->GetShrinkFactor();
784 }
785
786 void
787 SMESH_DeviceActor
788 ::SetShrinkFactor(vtkFloatingPointType theValue)
789 {
790   theValue = theValue > 0.1? theValue: 0.8;
791   myShrinkFilter->SetShrinkFactor(theValue);
792   Modified();
793 }
794
795
796 void
797 SMESH_DeviceActor
798 ::SetHighlited(bool theIsHighlited)
799 {
800   if ( myIsHighlited == theIsHighlited )
801     return;
802   myIsHighlited = theIsHighlited;
803   Modified();
804 }
805
806 void
807 SMESH_DeviceActor
808 ::Render(vtkRenderer *ren, vtkMapper* m)
809 {
810   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
811   vtkFloatingPointType aStoredFactor, aStoredUnit; 
812   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
813
814   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
815   vtkFloatingPointType aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
816   if(myIsHighlited){
817     static vtkFloatingPointType EPS = .01;
818     aUnits *= (1.0-EPS);
819   }
820   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
821   vtkLODActor::Render(ren,m);
822
823   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
824   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
825 }
826
827
828 void
829 SMESH_DeviceActor
830 ::SetPolygonOffsetParameters(vtkFloatingPointType factor, 
831                              vtkFloatingPointType units)
832 {
833   myPolygonOffsetFactor = factor;
834   myPolygonOffsetUnits = units;
835 }
836