Salome HOME
Merge remote branch 'origin/gdd/translations'
[modules/smesh.git] / src / OBJECT / SMESH_DeviceActor.cxx
1 // Copyright (C) 2007-2015  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, or (at your option) any later version.
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
23 //  SMESH OBJECT : interactive object for SMESH visualization
24 //  File   : SMESH_DeviceActor.cxx
25 //  Author : 
26 //  Module : SMESH
27 //
28 #include "SMESH_DeviceActor.h"
29 #include "SMESH_ScalarBarActor.h"
30 #include "SMESH_ExtractGeometry.h"
31 #include "SMESH_ControlsDef.hxx"
32 #include "SMESH_ActorUtils.h"
33 #include "SMESH_FaceOrientationFilter.h"
34 #include "VTKViewer_CellLocationsArray.h"
35 #include "VTKViewer_PolyDataMapper.h"
36
37 #include <VTKViewer_Transform.h>
38 #include <VTKViewer_TransformFilter.h>
39 #include <VTKViewer_ExtractUnstructuredGrid.h>
40
41 // VTK Includes
42 #include <vtkObjectFactory.h>
43 #include <vtkShrinkFilter.h>
44 #include <vtkShrinkPolyData.h>
45
46 #include <vtkProperty.h>
47 #include <vtkPolyData.h>
48 #include <vtkMergeFilter.h>
49 #include <vtkPolyDataMapper.h>
50 #include <vtkUnstructuredGrid.h>
51
52 #include <vtkLookupTable.h>
53 #include <vtkDoubleArray.h>
54 #include <vtkCellData.h>
55
56 #include <vtkCell.h>
57 #include <vtkIdList.h>
58 #include <vtkCellArray.h>
59 #include <vtkUnsignedCharArray.h>
60
61 #include <vtkImplicitBoolean.h>
62 #include <vtkPassThroughFilter.h>
63
64 #include <vtkRenderer.h>
65
66 #include <vtkPlaneCollection.h>
67
68 #include "utilities.h"
69
70 #ifdef _DEBUG_
71 static int MYDEBUG = 0;
72 #else
73 static int MYDEBUG = 0;
74 #endif
75
76 using namespace std;
77
78
79 vtkStandardNewMacro(SMESH_DeviceActor);
80
81
82 SMESH_DeviceActor
83 ::SMESH_DeviceActor()
84 {
85   if(MYDEBUG) MESSAGE("SMESH_DeviceActor - "<<this);
86
87   myIsShrinkable = false;
88   myIsShrunk = false;
89   myIsHighlited = false;
90
91   myRepresentation = eSurface;
92
93   myProperty = vtkProperty::New();
94   myMapper = VTKViewer_PolyDataMapper::New();
95   myPlaneCollection = vtkPlaneCollection::New();
96
97   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(myPolygonOffsetFactor,
98                                                                  myPolygonOffsetUnits);
99
100   myMapper->UseLookupTableScalarRangeOn();
101   myMapper->SetColorModeToMapScalars();
102
103   myShrinkFilter = vtkShrinkFilter::New();
104
105   myStoreClippingMapping = false;
106
107   myExtractGeometry = SMESH_ExtractGeometry::New();
108   myExtractGeometry->SetReleaseDataFlag(true);
109   myIsImplicitFunctionUsed = false;
110
111   myExtractUnstructuredGrid = VTKViewer_ExtractUnstructuredGrid::New();
112     
113   myMergeFilter = vtkMergeFilter::New();
114
115   myGeomFilter = VTKViewer_GeometryFilter::New();
116
117   myTransformFilter = VTKViewer_TransformFilter::New();
118
119   for(int i = 0; i < 6; i++)
120     myPassFilter.push_back(vtkPassThroughFilter::New());
121
122   // Orientation of faces
123   myIsFacesOriented = false;
124
125   double anRGB[3] = { 1, 1, 1 };
126   SMESH::GetColor( "SMESH", "orientation_color", anRGB[0], anRGB[1], anRGB[2], QColor( 255, 255, 255 ) );
127
128   myFaceOrientationFilter = SMESH_FaceOrientationFilter::New();
129
130   myFaceOrientationDataMapper = vtkPolyDataMapper::New();
131   myFaceOrientationDataMapper->SetInputConnection(myFaceOrientationFilter->GetOutputPort());
132
133   myFaceOrientation = vtkActor::New();
134   myFaceOrientation->SetMapper(myFaceOrientationDataMapper);
135   myFaceOrientation->GetProperty()->SetColor(anRGB[0], anRGB[1], anRGB[2]);
136 }
137
138
139 SMESH_DeviceActor
140 ::~SMESH_DeviceActor()
141 {
142   if(MYDEBUG) MESSAGE("~SMESH_DeviceActor - "<<this);
143
144   myMapper->Delete();
145
146   myProperty->Delete();
147
148   myExtractGeometry->Delete();
149
150   myMergeFilter->Delete();
151   myExtractUnstructuredGrid->Delete();
152
153   // Orientation of faces
154   myFaceOrientationFilter->Delete();
155   myFaceOrientationDataMapper->RemoveAllInputs();
156   myFaceOrientationDataMapper->Delete();
157   myFaceOrientation->Delete();
158
159   myGeomFilter->Delete();
160
161   myTransformFilter->Delete();
162
163   for(int i = 0, iEnd = myPassFilter.size(); i < iEnd; i++)
164     myPassFilter[i]->Delete();
165
166   myShrinkFilter->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 ]->SetInputConnection( myExtractGeometry->GetOutputPort() );
215   else
216     myPassFilter[ anId ]->SetInputConnection( myMergeFilter->GetOutputPort() );
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->SetInputData(theGrid);
232
233     myMergeFilter->SetGeometryConnection(myExtractUnstructuredGrid->GetOutputPort());
234     
235     //Pass diameters of the balls
236     if(myMapper->GetBallEnabled()) {
237       myMergeFilter->SetScalarsConnection(myExtractUnstructuredGrid->GetOutputPort());
238     }
239
240     myExtractGeometry->SetInputConnection(myMergeFilter->GetOutputPort());
241
242     int anId = 0;
243     SetImplicitFunctionUsed(myIsImplicitFunctionUsed);
244     myPassFilter[ anId + 1]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
245     
246     anId++; // 1
247     myTransformFilter->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
248
249     anId++; // 2
250     myPassFilter[ anId ]->SetInputConnection( myTransformFilter->GetOutputPort() );
251     myPassFilter[ anId + 1 ]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
252
253     anId++; // 3
254     myGeomFilter->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
255
256     anId++; // 4
257     myPassFilter[ anId ]->SetInputConnection( myGeomFilter->GetOutputPort() ); 
258     myPassFilter[ anId + 1 ]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
259
260     anId++; // 5
261     myMapper->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
262     if( myPlaneCollection->GetNumberOfItems() )
263       myMapper->SetClippingPlanes( myPlaneCollection );
264
265     vtkLODActor::SetMapper( myMapper );
266     Modified();
267   }
268 }
269
270 void
271 SMESH_DeviceActor
272 ::SetPlaneCollection( vtkPlaneCollection* theCollection )
273 {
274   myPlaneCollection = theCollection;
275 }
276
277 VTKViewer_ExtractUnstructuredGrid* 
278 SMESH_DeviceActor
279 ::GetExtractUnstructuredGrid()
280 {
281   return myExtractUnstructuredGrid;
282 }
283
284
285 vtkUnstructuredGrid* 
286 SMESH_DeviceActor
287 ::GetUnstructuredGrid()
288 {
289   myExtractUnstructuredGrid->Update();
290   return myExtractUnstructuredGrid->GetOutput();
291 }
292
293
294 void
295 SMESH_DeviceActor
296 ::SetControlMode(SMESH::Controls::FunctorPtr theFunctor,
297                  SMESH_ScalarBarActor* theScalarBarActor,
298                  vtkLookupTable* theLookupTable)
299 {
300   bool anIsInitialized = theFunctor;
301   if(anIsInitialized){
302     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
303
304     SetStoreIDMapping(true);
305     myExtractUnstructuredGrid->Update();
306     vtkUnstructuredGrid* aGrid = myExtractUnstructuredGrid->GetOutput();
307
308     aDataSet->ShallowCopy(aGrid);
309     
310     vtkDoubleArray *aScalars = vtkDoubleArray::New();
311     vtkIdType aNbCells = aGrid->GetNumberOfCells();
312     aScalars->SetNumberOfComponents(1);
313     aScalars->SetNumberOfTuples(aNbCells);
314     double* range;// = aScalars->GetRange();
315     
316     myVisualObj->UpdateFunctor(theFunctor);
317
318     using namespace SMESH::Controls;
319     if(NumericalFunctor* aNumericalFunctor = dynamic_cast<NumericalFunctor*>(theFunctor.get()))
320     {
321       for(vtkIdType i = 0; i < aNbCells; i++){
322         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
323         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
324         double aValue = aNumericalFunctor->GetValue(anObjId);
325         aScalars->SetValue(i,aValue);
326       }
327       range = aScalars->GetRange();
328       if ( range[1] - range[0] < ( qMax(qAbs(range[0]),qAbs(range[1])) + 1e-100 ) * 1e-6 )
329       {
330         range[1] = range[0];
331         for(vtkIdType i = 0; i < aNbCells; i++)
332           aScalars->SetValue(i,range[0]);
333       }
334     }
335     else if(Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get()))
336     {
337       for(vtkIdType i = 0; i < aNbCells; i++){
338         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
339         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
340         bool aValue = aPredicate->IsSatisfy(anObjId);
341         aScalars->SetValue(i,aValue);
342       }
343       range = aScalars->GetRange();
344     }
345
346     aDataSet->GetCellData()->SetScalars(aScalars);
347     aScalars->Delete();
348
349     theLookupTable->SetRange( range );
350     theLookupTable->SetNumberOfTableValues(theScalarBarActor->GetMaximumNumberOfColors());
351     theLookupTable->Build();
352     
353     myMergeFilter->SetScalarsData(aDataSet);
354     aDataSet->Delete();
355   }
356   GetMapper()->SetScalarVisibility(anIsInitialized);
357   theScalarBarActor->SetVisibility(anIsInitialized);
358 }
359
360 void
361 SMESH_DeviceActor
362 ::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
363                     SMESH_ScalarBarActor* theScalarBarActor,
364                     vtkLookupTable* theLookupTable)
365 {
366   bool anIsInitialized = theFunctor;
367   myExtractUnstructuredGrid->ClearRegisteredCells();
368   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
369   myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::ePassAll);
370   myVisualObj->UpdateFunctor(theFunctor);
371
372   using namespace SMESH::Controls;
373   if (anIsInitialized){
374     if (Length2D* aLength2D = dynamic_cast<Length2D*>(theFunctor.get())){
375       SMESH::Controls::Length2D::TValues aValues;
376
377       aLength2D->GetValues(aValues);
378       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
379       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
380
381       aDataSet->SetPoints(aGrid->GetPoints());
382       
383       vtkIdType aNbCells = aValues.size();
384       
385       vtkDoubleArray *aScalars = vtkDoubleArray::New();
386       aScalars->SetNumberOfComponents(1);
387       aScalars->SetNumberOfTuples(aNbCells);
388
389       vtkIdType aCellsSize = 3*aNbCells;
390       vtkCellArray* aConnectivity = vtkCellArray::New();
391       aConnectivity->Allocate( aCellsSize, 0 );
392       
393       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
394       aCellTypesArray->SetNumberOfComponents( 1 );
395       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
396
397       vtkIdList *anIdList = vtkIdList::New();
398       anIdList->SetNumberOfIds(2);
399
400       Length2D::TValues::const_iterator anIter = aValues.begin();
401       aNbCells = 0;
402       for(; anIter != aValues.end(); anIter++){
403         const Length2D::Value& aValue = *anIter;
404         int aNode[2] = {
405           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
406           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
407         };
408         if(aNode[0] >= 0 && aNode[1] >= 0){
409           anIdList->SetId( 0, aNode[0] );
410           anIdList->SetId( 1, aNode[1] );
411           aConnectivity->InsertNextCell( anIdList );
412           aCellTypesArray->InsertNextValue( VTK_LINE );
413           aScalars->SetValue(aNbCells,aValue.myLength);
414           aNbCells++;
415         }
416       }
417       aCellTypesArray->SetNumberOfTuples( aNbCells );
418       aScalars->SetNumberOfTuples( aNbCells );
419
420       VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
421       aCellLocationsArray->SetNumberOfComponents( 1 );
422       aCellLocationsArray->SetNumberOfTuples( aNbCells );
423
424       aConnectivity->InitTraversal();
425       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
426         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
427
428       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray, aConnectivity );
429       SetUnstructuredGrid(aDataSet);
430
431       aDataSet->GetCellData()->SetScalars(aScalars);
432       aScalars->Delete();
433
434       theLookupTable->SetRange(aScalars->GetRange());
435       theLookupTable->Build();
436
437       myMergeFilter->SetScalarsData(aDataSet);
438       aDataSet->Delete();
439     }
440     else if (MultiConnection2D* aMultiConnection2D = dynamic_cast<MultiConnection2D*>(theFunctor.get())){
441       SMESH::Controls::MultiConnection2D::MValues aValues;
442
443       aMultiConnection2D->GetValues(aValues);
444       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
445       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
446       aDataSet->SetPoints(aGrid->GetPoints());
447       
448       vtkIdType aNbCells = aValues.size();
449       vtkDoubleArray *aScalars = vtkDoubleArray::New();
450       aScalars->SetNumberOfComponents(1);
451       aScalars->SetNumberOfTuples(aNbCells);
452
453       vtkIdType aCellsSize = 3*aNbCells;
454       vtkCellArray* aConnectivity = vtkCellArray::New();
455       aConnectivity->Allocate( aCellsSize, 0 );
456
457       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
458       aCellTypesArray->SetNumberOfComponents( 1 );
459       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
460
461       vtkIdList *anIdList = vtkIdList::New();
462       anIdList->SetNumberOfIds(2);
463
464       MultiConnection2D::MValues::const_iterator anIter = aValues.begin();
465       aNbCells = 0;
466       for(; anIter != aValues.end(); anIter++){
467         const MultiConnection2D::Value& aValue = (*anIter).first;
468         int aNode[2] = {
469           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
470           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
471         };
472         if(aNode[0] >= 0 && aNode[1] >= 0){
473           anIdList->SetId( 0, aNode[0] );
474           anIdList->SetId( 1, aNode[1] );
475           aConnectivity->InsertNextCell( anIdList );
476           aCellTypesArray->InsertNextValue( VTK_LINE );
477           aScalars->SetValue( aNbCells,(*anIter).second);
478           aNbCells++;
479         }
480       }
481       aCellTypesArray->SetNumberOfTuples( aNbCells );
482       aScalars->SetNumberOfTuples( aNbCells );
483
484       VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
485       aCellLocationsArray->SetNumberOfComponents( 1 );
486       aCellLocationsArray->SetNumberOfTuples( aNbCells );
487
488       aConnectivity->InitTraversal();
489       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
490         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
491
492       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
493       SetUnstructuredGrid(aDataSet);
494
495       aDataSet->GetCellData()->SetScalars(aScalars);
496       aScalars->Delete();
497
498       theLookupTable->SetRange(aScalars->GetRange());
499       theLookupTable->Build();
500
501       myMergeFilter->SetScalarsData(aDataSet);
502       aDataSet->Delete();
503     }
504   }
505   GetMapper()->SetScalarVisibility(anIsInitialized);
506   theScalarBarActor->SetVisibility(anIsInitialized);
507 }
508
509 void
510 SMESH_DeviceActor
511 ::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor)
512 {
513   myExtractUnstructuredGrid->ClearRegisteredCells();
514   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
515   myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::ePassAll);
516   myVisualObj->UpdateFunctor(theFunctor);
517
518   using namespace SMESH::Controls;
519   if ( dynamic_cast<FreeBorders          *>(theFunctor.get()) ||
520        dynamic_cast<FreeFaces            *>(theFunctor.get()) ||
521        dynamic_cast<BareBorderVolume     *>(theFunctor.get()) ||
522        dynamic_cast<BareBorderFace       *>(theFunctor.get()) ||
523        dynamic_cast<OverConstrainedVolume*>(theFunctor.get()) ||
524        dynamic_cast<CoincidentElements1D *>(theFunctor.get()) ||
525        dynamic_cast<CoincidentElements2D *>(theFunctor.get()) ||
526        dynamic_cast<CoincidentElements3D *>(theFunctor.get()) ||
527        dynamic_cast<OverConstrainedFace  *>(theFunctor.get()))
528   {
529     Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get());
530     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
531     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
532     vtkIdType aNbCells = aGrid->GetNumberOfCells();
533     for( vtkIdType i = 0; i < aNbCells; i++ ){
534       vtkIdType anObjId = myVisualObj->GetElemObjId(i);
535       if(aPredicate->IsSatisfy(anObjId))
536         myExtractUnstructuredGrid->RegisterCell(i);
537     }
538     if(!myExtractUnstructuredGrid->IsCellsRegistered())
539       myExtractUnstructuredGrid->RegisterCell(-1);
540     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
541   }
542   else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get()))
543   {
544     SMESH::Controls::FreeEdges::TBorders aBorders;
545     aFreeEdges->GetBoreders(aBorders);
546     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
547     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
548     aDataSet->SetPoints(aGrid->GetPoints());
549
550     vtkIdType aNbCells = aBorders.size();
551     vtkIdType aCellsSize = 3*aNbCells;
552     vtkCellArray* aConnectivity = vtkCellArray::New();
553     aConnectivity->Allocate( aCellsSize, 0 );
554     
555     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
556     aCellTypesArray->SetNumberOfComponents( 1 );
557     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
558     
559     vtkIdList *anIdList = vtkIdList::New();
560     anIdList->SetNumberOfIds(2);
561     
562     FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
563     for(; anIter != aBorders.end(); anIter++){
564       const FreeEdges::Border& aBorder = *anIter;
565       int aNode[2] = {
566         myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
567         myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
568       };
569       //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
570       if(aNode[0] >= 0 && aNode[1] >= 0){
571         anIdList->SetId( 0, aNode[0] );
572         anIdList->SetId( 1, aNode[1] );
573         aConnectivity->InsertNextCell( anIdList );
574         aCellTypesArray->InsertNextValue( VTK_LINE );
575       }
576     }
577     
578     VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
579     aCellLocationsArray->SetNumberOfComponents( 1 );
580     aCellLocationsArray->SetNumberOfTuples( aNbCells );
581     
582     aConnectivity->InitTraversal();
583     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
584       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
585     
586     aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
587
588     SetUnstructuredGrid(aDataSet);
589     aDataSet->Delete();
590   }
591   else if(dynamic_cast<FreeNodes      *>(theFunctor.get()) ||
592           dynamic_cast<CoincidentNodes*>(theFunctor.get()))
593   {
594     Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get());
595     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
596     vtkIdType aNbNodes = myVisualObj->GetNbEntities(SMDSAbs_Node);
597     for( vtkIdType i = 0; i < aNbNodes; i++ ){
598       vtkIdType anObjId = myVisualObj->GetNodeObjId(i);
599       if(aPredicate->IsSatisfy(anObjId))
600         myExtractUnstructuredGrid->RegisterCell(i);
601     }
602     if(!myExtractUnstructuredGrid->IsCellsRegistered())
603       myExtractUnstructuredGrid->RegisterCell(-1);
604     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
605   }
606 }
607
608
609
610
611 unsigned long int 
612 SMESH_DeviceActor
613 ::GetMTime()
614 {
615   unsigned long mTime = this->Superclass::GetMTime();
616   mTime = max(mTime,myExtractGeometry->GetMTime());
617   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
618   mTime = max(mTime,myMergeFilter->GetMTime());
619   mTime = max(mTime,myGeomFilter->GetMTime());
620   mTime = max(mTime,myTransformFilter->GetMTime());
621   mTime = max(mTime,myFaceOrientationFilter->GetMTime());
622   return mTime;
623 }
624
625
626 void
627 SMESH_DeviceActor
628 ::SetTransform(VTKViewer_Transform* theTransform)
629 {
630   myTransformFilter->SetTransform(theTransform);
631 }
632
633
634 void
635 SMESH_DeviceActor
636 ::SetShrink() 
637 {
638   if ( !myIsShrinkable ) return;
639   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
640   {
641     myShrinkFilter->SetInputConnection( aDataSet );
642     myPassFilter[ 1 ]->SetInputConnection( myShrinkFilter->GetOutputPort() );
643     myIsShrunk = true;
644   }
645 }
646
647 void
648 SMESH_DeviceActor
649 ::UnShrink() 
650 {
651   if ( !myIsShrunk ) return;
652   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
653   {    
654     myPassFilter[ 1 ]->SetInputConnection( aDataSet );
655     myPassFilter[ 1 ]->Modified();
656     myIsShrunk = false;
657     Modified();
658   }
659 }
660
661
662 void
663 SMESH_DeviceActor
664 ::SetFacesOriented(bool theIsFacesOriented) 
665 {
666   if ( vtkAlgorithmOutput* aDataSet = myTransformFilter->GetOutputPort() )
667   {
668     myIsFacesOriented = theIsFacesOriented;
669     if( theIsFacesOriented )
670       myFaceOrientationFilter->SetInputConnection( aDataSet );
671     UpdateFaceOrientation();
672   }
673 }
674
675 void
676 SMESH_DeviceActor
677 ::SetFacesOrientationColor(double r,double g,double b)
678 {
679   myFaceOrientation->GetProperty()->SetColor( r, g, b );
680 }
681
682 void
683 SMESH_DeviceActor
684 ::GetFacesOrientationColor(double& r,double& g,double& b)
685 {
686   myFaceOrientation->GetProperty()->GetColor( r, g, b );
687 }
688
689 void
690 SMESH_DeviceActor
691 ::SetFacesOrientationScale(double theScale)
692 {
693   myFaceOrientationFilter->SetOrientationScale( theScale );
694 }
695
696 double
697 SMESH_DeviceActor
698 ::GetFacesOrientationScale()
699 {
700   return myFaceOrientationFilter->GetOrientationScale();
701 }
702
703 void
704 SMESH_DeviceActor
705 ::SetFacesOrientation3DVectors(bool theState)
706 {
707   myFaceOrientationFilter->Set3dVectors( theState );
708 }
709
710 bool
711 SMESH_DeviceActor
712 ::GetFacesOrientation3DVectors()
713 {
714   return myFaceOrientationFilter->Get3dVectors();
715 }
716
717 void
718 SMESH_DeviceActor
719 ::UpdateFaceOrientation()
720 {
721   bool aShowFaceOrientation = myIsFacesOriented;
722   aShowFaceOrientation &= GetVisibility();
723   aShowFaceOrientation &= myRepresentation == eSurface;
724   myFaceOrientation->SetVisibility(aShowFaceOrientation);
725 }
726
727
728 void
729 SMESH_DeviceActor
730 ::SetRepresentation(EReperesent theMode)
731 {
732   switch(theMode){
733   case ePoint:
734     myGeomFilter->SetInside(true);
735     myGeomFilter->SetWireframeMode(false);
736     GetProperty()->SetRepresentation(0);
737     break;
738   case eWireframe:
739     myGeomFilter->SetInside(false);
740     myGeomFilter->SetWireframeMode(true);
741     GetProperty()->SetRepresentation(theMode);
742     break;
743   case eInsideframe:
744     myGeomFilter->SetInside(true);
745     myGeomFilter->SetWireframeMode(true);
746     GetProperty()->SetRepresentation(1);
747     break;
748   case eSurface:
749     myGeomFilter->SetInside(false);
750     myGeomFilter->SetWireframeMode(false);
751     GetProperty()->SetRepresentation(theMode);
752   }
753   SetMarkerEnabled(theMode == ePoint);
754   myRepresentation = theMode;
755   UpdateFaceOrientation();
756   GetProperty()->Modified();
757   myMapper->Modified();
758   Modified();
759 }
760
761
762 void
763 SMESH_DeviceActor
764 ::SetVisibility(int theMode)
765 {
766   if(!myExtractUnstructuredGrid->GetInput() || 
767      GetUnstructuredGrid()->GetNumberOfCells())
768   {
769     vtkLODActor::SetVisibility(theMode);
770   }else{
771     vtkLODActor::SetVisibility(false);
772   }
773   UpdateFaceOrientation();
774 }
775
776
777 int
778 SMESH_DeviceActor
779 ::GetVisibility()
780 {
781   if(!GetUnstructuredGrid()->GetNumberOfCells()){
782     vtkLODActor::SetVisibility(false);
783   }
784   return vtkLODActor::GetVisibility();
785 }
786
787
788 void
789 SMESH_DeviceActor
790 ::AddToRender(vtkRenderer* theRenderer)
791 {
792   theRenderer->AddActor(this);
793   theRenderer->AddActor(myFaceOrientation);
794 }
795
796 void
797 SMESH_DeviceActor
798 ::RemoveFromRender(vtkRenderer* theRenderer)
799 {
800   theRenderer->RemoveActor(this);
801   theRenderer->RemoveActor(myFaceOrientation);
802 }
803
804
805 int
806 SMESH_DeviceActor
807 ::GetNodeObjId(int theVtkID)
808 {
809   vtkIdType anID = theVtkID;
810
811   if(IsImplicitFunctionUsed())
812     anID = myExtractGeometry->GetNodeObjId(theVtkID);
813
814   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
815   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; anID = "<<anID<<"; aRetID = "<<aRetID);
816   return aRetID;
817 }
818
819 double* 
820 SMESH_DeviceActor
821 ::GetNodeCoord(int theObjID)
822 {
823   vtkDataSet* aDataSet = myMergeFilter->GetOutput();
824   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
825   double* aCoord = (anID >=0) ? aDataSet->GetPoint(anID) : NULL;
826   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
827   return aCoord;
828 }
829
830
831 int
832 SMESH_DeviceActor
833 ::GetElemObjId(int theVtkID)
834 {
835   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
836   if(anId < 0) 
837     return -1;
838
839   vtkIdType anId2 = anId;
840   if(IsImplicitFunctionUsed())
841     anId2 = myExtractGeometry->GetElemObjId(anId);
842   if(anId2 < 0) 
843     return -1;
844
845   vtkIdType anId3 = myExtractUnstructuredGrid->GetInputId(anId2);
846   if(anId3 < 0) 
847     return -1;
848
849   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
850   if(MYDEBUG) 
851      MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
852   return aRetID;
853 }
854
855 vtkCell* 
856 SMESH_DeviceActor
857 ::GetElemCell(int theObjID)
858 {
859   vtkDataSet* aDataSet = myVisualObj->GetUnstructuredGrid();
860   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
861   vtkCell* aCell = (aGridID >= 0 ) ? aDataSet->GetCell(aGridID) : NULL;
862   if(MYDEBUG) 
863     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
864   return aCell;
865 }
866
867
868 double 
869 SMESH_DeviceActor
870 ::GetShrinkFactor()
871 {
872   return myShrinkFilter->GetShrinkFactor();
873 }
874
875 void
876 SMESH_DeviceActor
877 ::SetShrinkFactor(double theValue)
878 {
879   theValue = theValue > 0.1? theValue: 0.8;
880   myShrinkFilter->SetShrinkFactor(theValue);
881   Modified();
882 }
883
884
885 void
886 SMESH_DeviceActor
887 ::SetHighlited(bool theIsHighlited)
888 {
889   if ( myIsHighlited == theIsHighlited )
890     return;
891   myIsHighlited = theIsHighlited;
892   Modified();
893 }
894
895 void
896 SMESH_DeviceActor
897 ::Render(vtkRenderer *ren, vtkMapper* m)
898 {
899   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
900   double aStoredFactor, aStoredUnit; 
901   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
902
903   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
904   double aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
905   if(myIsHighlited){
906     static double EPS = .01;
907     aUnits *= (1.0-EPS);
908   }
909   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
910   vtkLODActor::Render(ren,m);
911
912   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
913   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
914 }
915
916
917 void
918 SMESH_DeviceActor
919 ::SetPolygonOffsetParameters(double factor, 
920                              double units)
921 {
922   myPolygonOffsetFactor = factor;
923   myPolygonOffsetUnits = units;
924 }
925
926 /*!
927  * On/Off representation 2D quadratic element as arked polygon
928  */
929 void SMESH_DeviceActor::SetQuadraticArcMode(bool theFlag){
930   myGeomFilter->SetQuadraticArcMode(theFlag);
931 }
932
933 /*!
934  * Return true if 2D quadratic element displayed as arked polygon
935  */
936 bool SMESH_DeviceActor::GetQuadraticArcMode(){
937   return myGeomFilter->GetQuadraticArcMode();
938 }
939 /*!
940  * Set Max angle for representation 2D quadratic element as arked polygon
941  */
942 void SMESH_DeviceActor::SetQuadraticArcAngle(double theMaxAngle){
943   myGeomFilter->SetQuadraticArcAngle(theMaxAngle);
944 }
945
946 /*!
947  * Return Max angle of the representation 2D quadratic element as arked polygon
948  */
949 double SMESH_DeviceActor::GetQuadraticArcAngle(){
950   return myGeomFilter->GetQuadraticArcAngle();
951 }
952
953 /*!
954  * Set point marker enabled
955  * \param theMarkerEnabled flag to enable/disable point marker
956  */
957 void SMESH_DeviceActor::SetMarkerEnabled( bool theMarkerEnabled )
958 {
959   myMapper->SetMarkerEnabled( theMarkerEnabled );
960 }
961
962 /*!
963  * Set point marker enabled
964  * \param theBallEnabled flag to enable/disable ball drawing
965  */
966 void SMESH_DeviceActor::SetBallEnabled( bool theBallEnabled ) {
967   myMapper->SetBallEnabled( theBallEnabled );
968 }
969
970 /*!
971  * Set point marker scale factor
972  * \param theBallScale double value which specifies a scale factor of ball element
973  */
974 void SMESH_DeviceActor::SetBallScale( double theBallScale )
975 {
976   myMapper->SetBallScale( theBallScale );
977   myMapper->Modified();
978 }
979
980 /*!
981  * Set standard point marker
982  * \param theMarkerType type of the marker
983  */
984 void SMESH_DeviceActor::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
985 {
986   myMapper->SetMarkerStd( theMarkerType, theMarkerScale );
987 }
988
989 /*!
990  * Set custom point marker
991  * \param theMarkerId id of the marker texture
992  * \param theMarkerTexture marker texture
993  */
994 void SMESH_DeviceActor::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
995 {
996   myMapper->SetMarkerTexture( theMarkerId, theMarkerTexture );
997 }
998
999 /*!
1000  * Get type of the point marker
1001  * \return type of the point marker
1002  */
1003 VTK::MarkerType SMESH_DeviceActor::GetMarkerType()
1004 {
1005   return myMapper->GetMarkerType();
1006 }
1007
1008 /*!
1009   Get scale of the point marker
1010   \return scale of the point marker
1011 */
1012 VTK::MarkerScale SMESH_DeviceActor::GetMarkerScale()
1013 {
1014   return myMapper->GetMarkerScale();
1015 }
1016
1017 /*!
1018  * Get texture identifier of the point marker
1019  * \return texture identifier of the point marker
1020  */
1021 int SMESH_DeviceActor::GetMarkerTexture()
1022 {
1023   return myMapper->GetMarkerTexture();
1024 }
1025
1026 /*!
1027  * Get scale factor of ball element
1028  * \return scale factor of ball element
1029  */
1030 double SMESH_DeviceActor::GetBallScale()
1031 {
1032   return myMapper->GetBallScale();
1033 }
1034
1035 void SMESH_DeviceActor::SetCoincident3DAllowed(bool theFlag) {
1036   myGeomFilter->SetAppendCoincident3D(theFlag);
1037 }
1038
1039 bool SMESH_DeviceActor::IsCoincident3DAllowed() const {
1040   return myGeomFilter->GetAppendCoincident3D();
1041 }