Salome HOME
Bug PAL7334
[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
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 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
264                                           SMESH_DeviceActor* theDeviceActor,
265                                           vtkScalarBarActor* theScalarBarActor,
266                                           vtkLookupTable* theLookupTable)
267 {
268   bool anIsInitialized = theFunctor;
269
270   using namespace SMESH::Controls;
271   if (anIsInitialized){
272     if (Length2D* aLength2D = dynamic_cast<Length2D*>(theFunctor.get())){
273       SMESH::Controls::Length2D::TValues aValues;
274
275       myVisualObj->UpdateFunctor(theFunctor);
276
277       aLength2D->GetValues(aValues);
278       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
279       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
280
281       aDataSet->SetPoints(aGrid->GetPoints());
282       
283       vtkIdType aNbCells = aValues.size();
284       
285       vtkDoubleArray *aScalars = vtkDoubleArray::New();
286       aScalars->SetNumberOfComponents(1);
287       aScalars->SetNumberOfTuples(aNbCells);
288
289       vtkIdType aCellsSize = 3*aNbCells;
290       vtkCellArray* aConnectivity = vtkCellArray::New();
291       aConnectivity->Allocate( aCellsSize, 0 );
292       
293       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
294       aCellTypesArray->SetNumberOfComponents( 1 );
295       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
296       
297       vtkIdList *anIdList = vtkIdList::New();
298       anIdList->SetNumberOfIds(2);
299       
300       Length2D::TValues::const_iterator anIter = aValues.begin();
301       int i = 0;
302       for(vtkIdType aVtkId; anIter != aValues.end(); anIter++,i++){
303         const Length2D::Value& aValue = *anIter;
304         int aNode[2] = {
305           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
306           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
307         };
308         if(aNode[0] >= 0 && aNode[1] >= 0){
309           anIdList->SetId( 0, aNode[0] );
310           anIdList->SetId( 1, aNode[1] );
311           aConnectivity->InsertNextCell( anIdList );
312           aCellTypesArray->InsertNextValue( VTK_LINE );
313           aScalars->SetValue(i,aValue.myLength);
314         }
315       }
316       
317       vtkIntArray* aCellLocationsArray = vtkIntArray::New();
318       aCellLocationsArray->SetNumberOfComponents( 1 );
319       aCellLocationsArray->SetNumberOfTuples( aNbCells );
320       
321       aConnectivity->InitTraversal();
322       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
323         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
324       
325       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
326       SetUnstructuredGrid(aDataSet);
327
328       aDataSet->GetCellData()->SetScalars(aScalars);
329       aScalars->Delete();
330       
331       theLookupTable->SetRange(aScalars->GetRange());
332       theLookupTable->Build();
333       
334       SetUnstructuredGrid(aDataSet);
335       
336       myMergeFilter->SetScalars(aDataSet);
337       aDataSet->Delete();
338     }
339   }
340   GetMapper()->SetScalarVisibility(anIsInitialized);
341   theScalarBarActor->SetVisibility(anIsInitialized);
342 }
343
344 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
345                                           SMESH_DeviceActor* theDeviceActor)
346 {
347   myExtractUnstructuredGrid->ClearRegisteredCells();
348   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
349   myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::ePassAll);
350   myVisualObj->UpdateFunctor(theFunctor);
351
352   using namespace SMESH::Controls;
353   if(FreeBorders* aFreeBorders = dynamic_cast<FreeBorders*>(theFunctor.get())){
354     myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::eAdding);
355     myExtractUnstructuredGrid->ClearRegisteredCells();
356     vtkUnstructuredGrid* aGrid = theDeviceActor->GetUnstructuredGrid();
357     vtkIdType aNbCells = aGrid->GetNumberOfCells();
358     for( vtkIdType i = 0; i < aNbCells; i++ ){
359       vtkIdType anObjId = theDeviceActor->GetElemObjId(i);
360       if(aFreeBorders->IsSatisfy(anObjId))
361         myExtractUnstructuredGrid->RegisterCell(i);
362     }
363     if(!myExtractUnstructuredGrid->IsCellsRegistered())
364       myExtractUnstructuredGrid->RegisterCell(-1);
365     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
366   }else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get())){
367     SMESH::Controls::FreeEdges::TBorders aBorders;
368     aFreeEdges->GetBoreders(aBorders);
369     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
370     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
371     aDataSet->SetPoints(aGrid->GetPoints());
372
373     vtkIdType aNbCells = aBorders.size();
374     vtkIdType aCellsSize = 3*aNbCells;
375     vtkCellArray* aConnectivity = vtkCellArray::New();
376     aConnectivity->Allocate( aCellsSize, 0 );
377     
378     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
379     aCellTypesArray->SetNumberOfComponents( 1 );
380     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
381     
382     vtkIdList *anIdList = vtkIdList::New();
383     anIdList->SetNumberOfIds(2);
384     
385     FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
386     for(; anIter != aBorders.end(); anIter++){
387       const FreeEdges::Border& aBorder = *anIter;
388       int aNode[2] = {
389         myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
390         myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
391       };
392       //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
393       if(aNode[0] >= 0 && aNode[1] >= 0){
394         anIdList->SetId( 0, aNode[0] );
395         anIdList->SetId( 1, aNode[1] );
396         aConnectivity->InsertNextCell( anIdList );
397         aCellTypesArray->InsertNextValue( VTK_LINE );
398       }
399     }
400     
401     vtkIntArray* aCellLocationsArray = vtkIntArray::New();
402     aCellLocationsArray->SetNumberOfComponents( 1 );
403     aCellLocationsArray->SetNumberOfTuples( aNbCells );
404     
405     aConnectivity->InitTraversal();
406     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
407       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
408     
409     aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
410
411     SetUnstructuredGrid(aDataSet);
412     aDataSet->Delete();
413   }
414 }
415
416
417
418
419 unsigned long int SMESH_DeviceActor::GetMTime(){
420   unsigned long mTime = this->Superclass::GetMTime();
421   mTime = max(mTime,myExtractGeometry->GetMTime());
422   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
423   mTime = max(mTime,myMergeFilter->GetMTime());
424   mTime = max(mTime,myGeomFilter->GetMTime());
425   mTime = max(mTime,myTransformFilter->GetMTime());
426   return mTime;
427 }
428
429
430 void SMESH_DeviceActor::SetTransform(SALOME_Transform* theTransform){
431   myTransformFilter->SetTransform(theTransform);
432 }
433
434
435 void SMESH_DeviceActor::SetShrink() {
436   if ( !myIsShrinkable ) return;
437   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
438   {
439     myShrinkFilter->SetInput( aDataSet );
440     myPassFilter[ 1 ]->SetInput( myShrinkFilter->GetOutput() );
441     myIsShrunk = true;
442   }
443 }
444
445 void SMESH_DeviceActor::UnShrink() {
446   if ( !myIsShrunk ) return;
447   if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
448   {    
449     myPassFilter[ 1 ]->SetInput( aDataSet );
450     myPassFilter[ 1 ]->Modified();
451     myIsShrunk = false;
452     Modified();
453   }
454 }
455
456
457 void SMESH_DeviceActor::SetRepresentation(EReperesent theMode){ 
458   switch(theMode){
459   case ePoint: 
460     myGeomFilter->SetInside(true);
461     GetProperty()->SetRepresentation(0);
462     break;
463   case eInsideframe: 
464     myGeomFilter->SetInside(true);
465     GetProperty()->SetRepresentation(1);
466     break;
467   default :
468     GetProperty()->SetRepresentation(theMode);
469     myGeomFilter->SetInside(false);
470   }
471   myRepresentation = theMode;
472   GetProperty()->Modified();
473   myMapper->Modified();
474   Modified();
475 }
476
477
478 void SMESH_DeviceActor::SetVisibility(int theMode){
479   if(!myExtractUnstructuredGrid->GetInput() || GetUnstructuredGrid()->GetNumberOfCells()){
480     vtkLODActor::SetVisibility(theMode);
481   }else{
482     vtkLODActor::SetVisibility(false);
483   }
484 }
485
486
487 int SMESH_DeviceActor::GetVisibility(){
488   if(!GetUnstructuredGrid()->GetNumberOfCells()){
489     vtkLODActor::SetVisibility(false);
490   }
491   return vtkLODActor::GetVisibility();
492 }
493
494
495 int SMESH_DeviceActor::GetNodeObjId(int theVtkID){
496   vtkIdType anID = myExtractGeometry->GetNodeObjId(theVtkID);
497   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
498   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; aRetID = "<<aRetID);
499   return aRetID;
500 }
501
502 float* SMESH_DeviceActor::GetNodeCoord(int theObjID){
503   vtkDataSet* aDataSet = myExtractGeometry->GetInput();
504   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
505   float* aCoord = aDataSet->GetPoint(anID);
506   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
507   return aCoord;
508 }
509
510
511 int SMESH_DeviceActor::GetElemObjId(int theVtkID){
512   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
513   if(anId < 0) 
514     return -1;
515   vtkIdType anId2 = myExtractUnstructuredGrid->GetInputId(anId);
516   if(anId2 < 0) 
517     return -1;
518   vtkIdType anId3 = myExtractGeometry->GetElemObjId(anId2);
519   if(anId3 < 0) 
520     return -1;
521   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
522   if(MYDEBUG) 
523     MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
524   return aRetID;
525 }
526
527 vtkCell* SMESH_DeviceActor::GetElemCell(int theObjID){
528   vtkDataSet* aDataSet = myExtractGeometry->GetInput();
529   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
530   vtkCell* aCell = aDataSet->GetCell(aGridID);
531   if(MYDEBUG) 
532     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
533   return aCell;
534 }
535
536
537 float SMESH_DeviceActor::GetShrinkFactor(){
538   return myShrinkFilter->GetShrinkFactor();
539 }
540
541 void SMESH_DeviceActor::SetShrinkFactor(float theValue){
542   theValue = theValue > 0.1? theValue: 0.8;
543   myShrinkFilter->SetShrinkFactor(theValue);
544   Modified();
545 }
546
547
548 void SMESH_DeviceActor::SetHighlited(bool theIsHighlited){
549   myIsHighlited = theIsHighlited;
550   Modified();
551 }
552
553 void SMESH_DeviceActor::Render(vtkRenderer *ren, vtkMapper* m){
554   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
555   float aStoredFactor, aStoredUnit; 
556   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
557
558   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
559   float aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
560   if(myIsHighlited){
561     static float EPS = .01;
562     aUnits *= (1.0-EPS);
563   }
564   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
565   vtkLODActor::Render(ren,m);
566
567   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
568   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
569 }
570
571
572 void SMESH_DeviceActor::SetPolygonOffsetParameters(float factor, float units){
573   myPolygonOffsetFactor = factor;
574   myPolygonOffsetUnits = units;
575 }
576