Salome HOME
5dcaf64f85ba8c81b69629ebce7feed941b6e3a8
[modules/smesh.git] / src / OBJECT / SMESH_DeviceActor.cxx
1 // Copyright (C) 2007-2016  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 != NULL;
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 != NULL;
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   Predicate* aPredicate = 0;
520   if (( aPredicate =  dynamic_cast<FreeBorders          *>(theFunctor.get())) ||
521       ( aPredicate =  dynamic_cast<FreeFaces            *>(theFunctor.get())) ||
522       ( aPredicate =  dynamic_cast<BareBorderVolume     *>(theFunctor.get())) ||
523       ( aPredicate =  dynamic_cast<BareBorderFace       *>(theFunctor.get())) ||
524       ( aPredicate =  dynamic_cast<OverConstrainedVolume*>(theFunctor.get())) ||
525       ( aPredicate =  dynamic_cast<CoincidentElements1D *>(theFunctor.get())) ||
526       ( aPredicate =  dynamic_cast<CoincidentElements2D *>(theFunctor.get())) ||
527       ( aPredicate =  dynamic_cast<CoincidentElements3D *>(theFunctor.get())) ||
528       ( aPredicate =  dynamic_cast<OverConstrainedFace  *>(theFunctor.get())))
529   {
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 (( aPredicate = dynamic_cast<FreeNodes      *>(theFunctor.get())) ||
592            ( aPredicate = dynamic_cast<CoincidentNodes*>(theFunctor.get())))
593   {
594     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
595     vtkIdType aNbNodes = myVisualObj->GetNbEntities(SMDSAbs_Node);
596     for( vtkIdType i = 0; i < aNbNodes; i++ ){
597       vtkIdType anObjId = myVisualObj->GetNodeObjId(i);
598       if(aPredicate->IsSatisfy(anObjId))
599         myExtractUnstructuredGrid->RegisterCell(i);
600     }
601     if(!myExtractUnstructuredGrid->IsCellsRegistered())
602       myExtractUnstructuredGrid->RegisterCell(-1);
603     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
604   }
605 }
606
607
608
609
610 unsigned long int 
611 SMESH_DeviceActor
612 ::GetMTime()
613 {
614   unsigned long mTime = this->Superclass::GetMTime();
615   mTime = max(mTime,myExtractGeometry->GetMTime());
616   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
617   mTime = max(mTime,myMergeFilter->GetMTime());
618   mTime = max(mTime,myGeomFilter->GetMTime());
619   mTime = max(mTime,myTransformFilter->GetMTime());
620   mTime = max(mTime,myFaceOrientationFilter->GetMTime());
621   return mTime;
622 }
623
624
625 void
626 SMESH_DeviceActor
627 ::SetTransform(VTKViewer_Transform* theTransform)
628 {
629   myTransformFilter->SetTransform(theTransform);
630 }
631
632
633 void
634 SMESH_DeviceActor
635 ::SetShrink() 
636 {
637   if ( !myIsShrinkable ) return;
638   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
639   {
640     myShrinkFilter->SetInputConnection( aDataSet );
641     myPassFilter[ 1 ]->SetInputConnection( myShrinkFilter->GetOutputPort() );
642     myIsShrunk = true;
643   }
644 }
645
646 void
647 SMESH_DeviceActor
648 ::UnShrink() 
649 {
650   if ( !myIsShrunk ) return;
651   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
652   {    
653     myPassFilter[ 1 ]->SetInputConnection( aDataSet );
654     myPassFilter[ 1 ]->Modified();
655     myIsShrunk = false;
656     Modified();
657   }
658 }
659
660
661 void
662 SMESH_DeviceActor
663 ::SetFacesOriented(bool theIsFacesOriented) 
664 {
665   if ( vtkAlgorithmOutput* aDataSet = myTransformFilter->GetOutputPort() )
666   {
667     myIsFacesOriented = theIsFacesOriented;
668     if( theIsFacesOriented )
669       myFaceOrientationFilter->SetInputConnection( aDataSet );
670     UpdateFaceOrientation();
671   }
672 }
673
674 void
675 SMESH_DeviceActor
676 ::SetFacesOrientationColor(double r,double g,double b)
677 {
678   myFaceOrientation->GetProperty()->SetColor( r, g, b );
679 }
680
681 void
682 SMESH_DeviceActor
683 ::GetFacesOrientationColor(double& r,double& g,double& b)
684 {
685   myFaceOrientation->GetProperty()->GetColor( r, g, b );
686 }
687
688 void
689 SMESH_DeviceActor
690 ::SetFacesOrientationScale(double theScale)
691 {
692   myFaceOrientationFilter->SetOrientationScale( theScale );
693 }
694
695 double
696 SMESH_DeviceActor
697 ::GetFacesOrientationScale()
698 {
699   return myFaceOrientationFilter->GetOrientationScale();
700 }
701
702 void
703 SMESH_DeviceActor
704 ::SetFacesOrientation3DVectors(bool theState)
705 {
706   myFaceOrientationFilter->Set3dVectors( theState );
707 }
708
709 bool
710 SMESH_DeviceActor
711 ::GetFacesOrientation3DVectors()
712 {
713   return myFaceOrientationFilter->Get3dVectors();
714 }
715
716 void
717 SMESH_DeviceActor
718 ::UpdateFaceOrientation()
719 {
720   bool aShowFaceOrientation = myIsFacesOriented;
721   aShowFaceOrientation &= GetVisibility();
722   aShowFaceOrientation &= myRepresentation == eSurface;
723   myFaceOrientation->SetVisibility(aShowFaceOrientation);
724 }
725
726
727 void
728 SMESH_DeviceActor
729 ::SetRepresentation(EReperesent theMode)
730 {
731   switch(theMode){
732   case ePoint:
733     myGeomFilter->SetInside(true);
734     myGeomFilter->SetWireframeMode(false);
735     GetProperty()->SetRepresentation(0);
736     break;
737   case eWireframe:
738     myGeomFilter->SetInside(false);
739     myGeomFilter->SetWireframeMode(true);
740     GetProperty()->SetRepresentation(theMode);
741     break;
742   case eInsideframe:
743     myGeomFilter->SetInside(true);
744     myGeomFilter->SetWireframeMode(true);
745     GetProperty()->SetRepresentation(1);
746     break;
747   case eSurface:
748     myGeomFilter->SetInside(false);
749     myGeomFilter->SetWireframeMode(false);
750     GetProperty()->SetRepresentation(theMode);
751   }
752   SetMarkerEnabled(theMode == ePoint);
753   myRepresentation = theMode;
754   UpdateFaceOrientation();
755   GetProperty()->Modified();
756   myMapper->Modified();
757   Modified();
758 }
759
760
761 void
762 SMESH_DeviceActor
763 ::SetVisibility(int theMode)
764 {
765   if(!myExtractUnstructuredGrid->GetInput() || 
766      GetUnstructuredGrid()->GetNumberOfCells())
767   {
768     vtkLODActor::SetVisibility(theMode);
769   }else{
770     vtkLODActor::SetVisibility(false);
771   }
772   UpdateFaceOrientation();
773 }
774
775
776 int
777 SMESH_DeviceActor
778 ::GetVisibility()
779 {
780   if(!GetUnstructuredGrid()->GetNumberOfCells()){
781     vtkLODActor::SetVisibility(false);
782   }
783   return vtkLODActor::GetVisibility();
784 }
785
786
787 void
788 SMESH_DeviceActor
789 ::AddToRender(vtkRenderer* theRenderer)
790 {
791   theRenderer->AddActor(this);
792   theRenderer->AddActor(myFaceOrientation);
793 }
794
795 void
796 SMESH_DeviceActor
797 ::RemoveFromRender(vtkRenderer* theRenderer)
798 {
799   theRenderer->RemoveActor(this);
800   theRenderer->RemoveActor(myFaceOrientation);
801 }
802
803
804 int
805 SMESH_DeviceActor
806 ::GetNodeObjId(int theVtkID)
807 {
808   vtkIdType anID = theVtkID;
809
810   if(IsImplicitFunctionUsed())
811     anID = myExtractGeometry->GetNodeObjId(theVtkID);
812
813   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
814   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; anID = "<<anID<<"; aRetID = "<<aRetID);
815   return aRetID;
816 }
817
818 double* 
819 SMESH_DeviceActor
820 ::GetNodeCoord(int theObjID)
821 {
822   vtkDataSet* aDataSet = myMergeFilter->GetOutput();
823   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
824   double* aCoord = (anID >=0) ? aDataSet->GetPoint(anID) : NULL;
825   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
826   return aCoord;
827 }
828
829
830 int
831 SMESH_DeviceActor
832 ::GetElemObjId(int theVtkID)
833 {
834   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
835   if(anId < 0) 
836     return -1;
837
838   vtkIdType anId2 = anId;
839   if(IsImplicitFunctionUsed())
840     anId2 = myExtractGeometry->GetElemObjId(anId);
841   if(anId2 < 0) 
842     return -1;
843
844   vtkIdType anId3 = myExtractUnstructuredGrid->GetInputId(anId2);
845   if(anId3 < 0) 
846     return -1;
847
848   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
849   if(MYDEBUG) 
850      MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
851   return aRetID;
852 }
853
854 vtkCell* 
855 SMESH_DeviceActor
856 ::GetElemCell(int theObjID)
857 {
858   vtkDataSet* aDataSet = myVisualObj->GetUnstructuredGrid();
859   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
860   vtkCell* aCell = (aGridID >= 0 ) ? aDataSet->GetCell(aGridID) : NULL;
861   if(MYDEBUG) 
862     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
863   return aCell;
864 }
865
866
867 double 
868 SMESH_DeviceActor
869 ::GetShrinkFactor()
870 {
871   return myShrinkFilter->GetShrinkFactor();
872 }
873
874 void
875 SMESH_DeviceActor
876 ::SetShrinkFactor(double theValue)
877 {
878   theValue = theValue > 0.1? theValue: 0.8;
879   myShrinkFilter->SetShrinkFactor(theValue);
880   Modified();
881 }
882
883
884 void
885 SMESH_DeviceActor
886 ::SetHighlited(bool theIsHighlited)
887 {
888   if ( myIsHighlited == theIsHighlited )
889     return;
890   myIsHighlited = theIsHighlited;
891   Modified();
892 }
893
894 void
895 SMESH_DeviceActor
896 ::Render(vtkRenderer *ren, vtkMapper* m)
897 {
898   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
899   double aStoredFactor, aStoredUnit; 
900   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
901
902   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
903   double aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
904   if(myIsHighlited){
905     static double EPS = .01;
906     aUnits *= (1.0-EPS);
907   }
908   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
909   vtkLODActor::Render(ren,m);
910
911   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
912   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
913 }
914
915
916 void
917 SMESH_DeviceActor
918 ::SetPolygonOffsetParameters(double factor, 
919                              double units)
920 {
921   myPolygonOffsetFactor = factor;
922   myPolygonOffsetUnits = units;
923 }
924
925 /*!
926  * On/Off representation 2D quadratic element as arked polygon
927  */
928 void SMESH_DeviceActor::SetQuadraticArcMode(bool theFlag){
929   myGeomFilter->SetQuadraticArcMode(theFlag);
930 }
931
932 /*!
933  * Return true if 2D quadratic element displayed as arked polygon
934  */
935 bool SMESH_DeviceActor::GetQuadraticArcMode(){
936   return myGeomFilter->GetQuadraticArcMode();
937 }
938 /*!
939  * Set Max angle for representation 2D quadratic element as arked polygon
940  */
941 void SMESH_DeviceActor::SetQuadraticArcAngle(double theMaxAngle){
942   myGeomFilter->SetQuadraticArcAngle(theMaxAngle);
943 }
944
945 /*!
946  * Return Max angle of the representation 2D quadratic element as arked polygon
947  */
948 double SMESH_DeviceActor::GetQuadraticArcAngle(){
949   return myGeomFilter->GetQuadraticArcAngle();
950 }
951
952 /*!
953  * Set point marker enabled
954  * \param theMarkerEnabled flag to enable/disable point marker
955  */
956 void SMESH_DeviceActor::SetMarkerEnabled( bool theMarkerEnabled )
957 {
958   myMapper->SetMarkerEnabled( theMarkerEnabled );
959 }
960
961 /*!
962  * Set point marker enabled
963  * \param theBallEnabled flag to enable/disable ball drawing
964  */
965 void SMESH_DeviceActor::SetBallEnabled( bool theBallEnabled ) {
966   myMapper->SetBallEnabled( theBallEnabled );
967 }
968
969 /*!
970  * Set point marker scale factor
971  * \param theBallScale double value which specifies a scale factor of ball element
972  */
973 void SMESH_DeviceActor::SetBallScale( double theBallScale )
974 {
975   myMapper->SetBallScale( theBallScale );
976   myMapper->Modified();
977 }
978
979 /*!
980  * Set standard point marker
981  * \param theMarkerType type of the marker
982  */
983 void SMESH_DeviceActor::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
984 {
985   myMapper->SetMarkerStd( theMarkerType, theMarkerScale );
986 }
987
988 /*!
989  * Set custom point marker
990  * \param theMarkerId id of the marker texture
991  * \param theMarkerTexture marker texture
992  */
993 void SMESH_DeviceActor::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
994 {
995   myMapper->SetMarkerTexture( theMarkerId, theMarkerTexture );
996 }
997
998 /*!
999  * Get type of the point marker
1000  * \return type of the point marker
1001  */
1002 VTK::MarkerType SMESH_DeviceActor::GetMarkerType()
1003 {
1004   return myMapper->GetMarkerType();
1005 }
1006
1007 /*!
1008   Get scale of the point marker
1009   \return scale of the point marker
1010 */
1011 VTK::MarkerScale SMESH_DeviceActor::GetMarkerScale()
1012 {
1013   return myMapper->GetMarkerScale();
1014 }
1015
1016 /*!
1017  * Get texture identifier of the point marker
1018  * \return texture identifier of the point marker
1019  */
1020 int SMESH_DeviceActor::GetMarkerTexture()
1021 {
1022   return myMapper->GetMarkerTexture();
1023 }
1024
1025 /*!
1026  * Get scale factor of ball element
1027  * \return scale factor of ball element
1028  */
1029 double SMESH_DeviceActor::GetBallScale()
1030 {
1031   return myMapper->GetBallScale();
1032 }
1033
1034 void SMESH_DeviceActor::SetCoincident3DAllowed(bool theFlag) {
1035   myGeomFilter->SetAppendCoincident3D(theFlag);
1036 }
1037
1038 bool SMESH_DeviceActor::IsCoincident3DAllowed() const {
1039   return myGeomFilter->GetAppendCoincident3D();
1040 }