Salome HOME
[Bug PAL7763] Length 2D and Border at Multi-Connection 2D during clipping incorrect
[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$Header$
28
29
30 #include "SMESH_DeviceActor.h"
31 #include "SMESH_ExtractGeometry.h"
32 #include "SMESH_ControlsDef.hxx"
33 #include "SMESH_ActorUtils.h"
34
35 #include "SALOME_Transform.h"
36 #include "SALOME_TransformFilter.h"
37 #include "SALOME_PassThroughFilter.h"
38 #include "SALOME_ExtractUnstructuredGrid.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 #include "utilities.h"
65
66 #ifdef _DEBUG_
67 static int MYDEBUG = 0;
68 #else
69 static int MYDEBUG = 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     myExtractUnstructuredGrid->SetInput(theGrid);
166
167     myMergeFilter->SetGeometry(myExtractUnstructuredGrid->GetOutput());
168
169     myExtractGeometry->SetInput(myMergeFilter->GetOutput());
170
171     int anId = 0;
172     myPassFilter[ anId ]->SetInput( myExtractGeometry->GetOutput() );
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 anObjId = myVisualObj->GetElemObjId(anId);
236         double aValue = aNumericalFunctor->GetValue(anObjId);
237         aScalars->SetValue(i,aValue);
238       }
239     }else if(Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get())){
240       for(vtkIdType i = 0; i < aNbCells; i++){
241         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
242         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
243         bool aValue = aPredicate->IsSatisfy(anObjId);
244         aScalars->SetValue(i,aValue);
245       }
246     }
247
248     aDataSet->GetCellData()->SetScalars(aScalars);
249     aScalars->Delete();
250         
251     theLookupTable->SetRange(aScalars->GetRange());
252     theLookupTable->Build();
253     
254     myMergeFilter->SetScalars(aDataSet);
255     aDataSet->Delete();
256   }
257   GetMapper()->SetScalarVisibility(anIsInitialized);
258   theScalarBarActor->SetVisibility(anIsInitialized);
259 }
260
261 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
262                                           SMESH_DeviceActor* theDeviceActor,
263                                           vtkScalarBarActor* theScalarBarActor,
264                                           vtkLookupTable* theLookupTable)
265 {
266   bool anIsInitialized = theFunctor;
267
268   using namespace SMESH::Controls;
269   if (anIsInitialized){
270     if (Length2D* aLength2D = dynamic_cast<Length2D*>(theFunctor.get())){
271       SMESH::Controls::Length2D::TValues aValues;
272
273       myVisualObj->UpdateFunctor(theFunctor);
274
275       aLength2D->GetValues(aValues);
276       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
277       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
278
279       aDataSet->SetPoints(aGrid->GetPoints());
280       
281       vtkIdType aNbCells = aValues.size();
282       
283       vtkDoubleArray *aScalars = vtkDoubleArray::New();
284       aScalars->SetNumberOfComponents(1);
285       aScalars->SetNumberOfTuples(aNbCells);
286
287       vtkIdType aCellsSize = 3*aNbCells;
288       vtkCellArray* aConnectivity = vtkCellArray::New();
289       aConnectivity->Allocate( aCellsSize, 0 );
290       
291       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
292       aCellTypesArray->SetNumberOfComponents( 1 );
293       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
294       
295       vtkIdList *anIdList = vtkIdList::New();
296       anIdList->SetNumberOfIds(2);
297       
298       Length2D::TValues::const_iterator anIter = aValues.begin();
299       for(vtkIdType aVtkId = 0; anIter != aValues.end(); anIter++,aVtkId++){
300         const Length2D::Value& aValue = *anIter;
301         int aNode[2] = {
302           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
303           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
304         };
305         if(aNode[0] >= 0 && aNode[1] >= 0){
306           anIdList->SetId( 0, aNode[0] );
307           anIdList->SetId( 1, aNode[1] );
308           aConnectivity->InsertNextCell( anIdList );
309           aCellTypesArray->InsertNextValue( VTK_LINE );
310           aScalars->SetValue(aVtkId,aValue.myLength);
311         }
312       }
313       
314       vtkIntArray* aCellLocationsArray = vtkIntArray::New();
315       aCellLocationsArray->SetNumberOfComponents( 1 );
316       aCellLocationsArray->SetNumberOfTuples( aNbCells );
317       
318       aConnectivity->InitTraversal();
319       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
320         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
321       
322       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
323       SetUnstructuredGrid(aDataSet);
324
325       aDataSet->GetCellData()->SetScalars(aScalars);
326       aScalars->Delete();
327       
328       theLookupTable->SetRange(aScalars->GetRange());
329       theLookupTable->Build();
330       
331       myMergeFilter->SetScalars(aDataSet);
332       aDataSet->Delete();
333     }
334     else if (MultiConnection2D* aMultiConnection2D = dynamic_cast<MultiConnection2D*>(theFunctor.get())){
335       SMESH::Controls::MultiConnection2D::MValues aValues;
336
337       myVisualObj->UpdateFunctor(theFunctor);
338
339       aMultiConnection2D->GetValues(aValues);
340       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
341       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
342       aDataSet->SetPoints(aGrid->GetPoints());
343       
344       vtkIdType aNbCells = aValues.size();
345       vtkDoubleArray *aScalars = vtkDoubleArray::New();
346       aScalars->SetNumberOfComponents(1);
347       aScalars->SetNumberOfTuples(aNbCells);
348
349       vtkIdType aCellsSize = 3*aNbCells;
350       vtkCellArray* aConnectivity = vtkCellArray::New();
351       aConnectivity->Allocate( aCellsSize, 0 );
352       
353       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
354       aCellTypesArray->SetNumberOfComponents( 1 );
355       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
356       
357       vtkIdList *anIdList = vtkIdList::New();
358       anIdList->SetNumberOfIds(2);
359       
360       MultiConnection2D::MValues::const_iterator anIter = aValues.begin();
361       for(vtkIdType aVtkId = 0; anIter != aValues.end(); anIter++,aVtkId++){
362         const MultiConnection2D::Value& aValue = (*anIter).first;
363         int aNode[2] = {
364           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
365           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
366         };
367         if(aNode[0] >= 0 && aNode[1] >= 0){
368           anIdList->SetId( 0, aNode[0] );
369           anIdList->SetId( 1, aNode[1] );
370           aConnectivity->InsertNextCell( anIdList );
371           aCellTypesArray->InsertNextValue( VTK_LINE );
372           aScalars->SetValue(aVtkId,(*anIter).second);
373         }
374       }
375       
376       vtkIntArray* aCellLocationsArray = vtkIntArray::New();
377       aCellLocationsArray->SetNumberOfComponents( 1 );
378       aCellLocationsArray->SetNumberOfTuples( aNbCells );
379       
380       aConnectivity->InitTraversal();
381       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
382         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
383       
384       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
385       SetUnstructuredGrid(aDataSet);
386
387       aDataSet->GetCellData()->SetScalars(aScalars);
388       aScalars->Delete();
389       
390       theLookupTable->SetRange(aScalars->GetRange());
391       theLookupTable->Build();
392       
393       myMergeFilter->SetScalars(aDataSet);
394       aDataSet->Delete();
395     }
396   }
397   GetMapper()->SetScalarVisibility(anIsInitialized);
398   theScalarBarActor->SetVisibility(anIsInitialized);
399 }
400
401 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
402                                           SMESH_DeviceActor* theDeviceActor)
403 {
404   myExtractUnstructuredGrid->ClearRegisteredCells();
405   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
406   myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::ePassAll);
407   myVisualObj->UpdateFunctor(theFunctor);
408
409   using namespace SMESH::Controls;
410   if(FreeBorders* aFreeBorders = dynamic_cast<FreeBorders*>(theFunctor.get())){
411     myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::eAdding);
412     myExtractUnstructuredGrid->ClearRegisteredCells();
413     vtkUnstructuredGrid* aGrid = theDeviceActor->GetUnstructuredGrid();
414     vtkIdType aNbCells = aGrid->GetNumberOfCells();
415     for( vtkIdType i = 0; i < aNbCells; i++ ){
416       vtkIdType anObjId = theDeviceActor->GetElemObjId(i);
417       if(aFreeBorders->IsSatisfy(anObjId))
418         myExtractUnstructuredGrid->RegisterCell(i);
419     }
420     if(!myExtractUnstructuredGrid->IsCellsRegistered())
421       myExtractUnstructuredGrid->RegisterCell(-1);
422     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
423   }else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get())){
424     SMESH::Controls::FreeEdges::TBorders aBorders;
425     aFreeEdges->GetBoreders(aBorders);
426     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
427     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
428     aDataSet->SetPoints(aGrid->GetPoints());
429
430     vtkIdType aNbCells = aBorders.size();
431     vtkIdType aCellsSize = 3*aNbCells;
432     vtkCellArray* aConnectivity = vtkCellArray::New();
433     aConnectivity->Allocate( aCellsSize, 0 );
434     
435     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
436     aCellTypesArray->SetNumberOfComponents( 1 );
437     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
438     
439     vtkIdList *anIdList = vtkIdList::New();
440     anIdList->SetNumberOfIds(2);
441     
442     FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
443     for(; anIter != aBorders.end(); anIter++){
444       const FreeEdges::Border& aBorder = *anIter;
445       int aNode[2] = {
446         myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
447         myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
448       };
449       //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
450       if(aNode[0] >= 0 && aNode[1] >= 0){
451         anIdList->SetId( 0, aNode[0] );
452         anIdList->SetId( 1, aNode[1] );
453         aConnectivity->InsertNextCell( anIdList );
454         aCellTypesArray->InsertNextValue( VTK_LINE );
455       }
456     }
457     
458     vtkIntArray* aCellLocationsArray = vtkIntArray::New();
459     aCellLocationsArray->SetNumberOfComponents( 1 );
460     aCellLocationsArray->SetNumberOfTuples( aNbCells );
461     
462     aConnectivity->InitTraversal();
463     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
464       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
465     
466     aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
467
468     SetUnstructuredGrid(aDataSet);
469     aDataSet->Delete();
470   }
471 }
472
473
474
475
476 unsigned long int SMESH_DeviceActor::GetMTime(){
477   unsigned long mTime = this->Superclass::GetMTime();
478   mTime = max(mTime,myExtractGeometry->GetMTime());
479   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
480   mTime = max(mTime,myMergeFilter->GetMTime());
481   mTime = max(mTime,myGeomFilter->GetMTime());
482   mTime = max(mTime,myTransformFilter->GetMTime());
483   return mTime;
484 }
485
486
487 void SMESH_DeviceActor::SetTransform(SALOME_Transform* theTransform){
488   myTransformFilter->SetTransform(theTransform);
489 }
490
491
492 void SMESH_DeviceActor::SetShrink() {
493   if ( !myIsShrinkable ) return;
494   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
495   {
496     myShrinkFilter->SetInput( aDataSet );
497     myPassFilter[ 1 ]->SetInput( myShrinkFilter->GetOutput() );
498     myIsShrunk = true;
499   }
500 }
501
502 void SMESH_DeviceActor::UnShrink() {
503   if ( !myIsShrunk ) return;
504   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
505   {    
506     myPassFilter[ 1 ]->SetInput( aDataSet );
507     myPassFilter[ 1 ]->Modified();
508     myIsShrunk = false;
509     Modified();
510   }
511 }
512
513
514 void SMESH_DeviceActor::SetRepresentation(EReperesent theMode){ 
515   switch(theMode){
516   case ePoint: 
517     myGeomFilter->SetInside(true);
518     GetProperty()->SetRepresentation(0);
519     break;
520   case eInsideframe: 
521     myGeomFilter->SetInside(true);
522     GetProperty()->SetRepresentation(1);
523     break;
524   default :
525     GetProperty()->SetRepresentation(theMode);
526     myGeomFilter->SetInside(false);
527   }
528   myRepresentation = theMode;
529   GetProperty()->Modified();
530   myMapper->Modified();
531   Modified();
532 }
533
534
535 void SMESH_DeviceActor::SetVisibility(int theMode){
536   if(!myExtractUnstructuredGrid->GetInput() || GetUnstructuredGrid()->GetNumberOfCells()){
537     vtkLODActor::SetVisibility(theMode);
538   }else{
539     vtkLODActor::SetVisibility(false);
540   }
541 }
542
543
544 int SMESH_DeviceActor::GetVisibility(){
545   if(!GetUnstructuredGrid()->GetNumberOfCells()){
546     vtkLODActor::SetVisibility(false);
547   }
548   return vtkLODActor::GetVisibility();
549 }
550
551
552 int SMESH_DeviceActor::GetNodeObjId(int theVtkID){
553   vtkIdType anID = myExtractGeometry->GetNodeObjId(theVtkID);
554   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
555   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; aRetID = "<<aRetID);
556   return aRetID;
557 }
558
559 float* SMESH_DeviceActor::GetNodeCoord(int theObjID){
560   vtkDataSet* aDataSet = myExtractGeometry->GetInput();
561   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
562   float* aCoord = aDataSet->GetPoint(anID);
563   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
564   return aCoord;
565 }
566
567
568 int SMESH_DeviceActor::GetElemObjId(int theVtkID){
569   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
570   if(anId < 0) 
571     return -1;
572   vtkIdType anId2 = myExtractUnstructuredGrid->GetInputId(anId);
573   if(anId2 < 0) 
574     return -1;
575   vtkIdType anId3 = myExtractGeometry->GetElemObjId(anId2);
576   if(anId3 < 0) 
577     return -1;
578   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
579   if(MYDEBUG) 
580     MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
581   return aRetID;
582 }
583
584 vtkCell* SMESH_DeviceActor::GetElemCell(int theObjID){
585   vtkDataSet* aDataSet = myExtractGeometry->GetInput();
586   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
587   vtkCell* aCell = aDataSet->GetCell(aGridID);
588   if(MYDEBUG) 
589     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
590   return aCell;
591 }
592
593
594 float SMESH_DeviceActor::GetShrinkFactor(){
595   return myShrinkFilter->GetShrinkFactor();
596 }
597
598 void SMESH_DeviceActor::SetShrinkFactor(float theValue){
599   theValue = theValue > 0.1? theValue: 0.8;
600   myShrinkFilter->SetShrinkFactor(theValue);
601   Modified();
602 }
603
604
605 void SMESH_DeviceActor::SetHighlited(bool theIsHighlited){
606   myIsHighlited = theIsHighlited;
607   Modified();
608 }
609
610 void SMESH_DeviceActor::Render(vtkRenderer *ren, vtkMapper* m){
611   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
612   float aStoredFactor, aStoredUnit; 
613   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
614
615   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
616   float aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
617   if(myIsHighlited){
618     static float EPS = .01;
619     aUnits *= (1.0-EPS);
620   }
621   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
622   vtkLODActor::Render(ren,m);
623
624   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
625   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
626 }
627
628
629 void SMESH_DeviceActor::SetPolygonOffsetParameters(float factor, float units){
630   myPolygonOffsetFactor = factor;
631   myPolygonOffsetUnits = units;
632 }
633