Salome HOME
23315: [CEA 1929] Too much memory used to display a mesh in shading and wireframe
[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   myPlaneCollection->Delete();
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 void
208 SMESH_DeviceActor
209 ::SetImplicitFunctionUsed(bool theIsImplicitFunctionUsed)
210 {
211   int anId = 0;
212   if(theIsImplicitFunctionUsed)
213     myPassFilter[ anId ]->SetInputConnection( myExtractGeometry->GetOutputPort() );
214   else
215     myPassFilter[ anId ]->SetInputConnection( myMergeFilter->GetOutputPort() );
216     
217   myIsImplicitFunctionUsed = theIsImplicitFunctionUsed;
218   SetStoreClippingMapping(myStoreClippingMapping);
219 }
220
221
222 void
223 SMESH_DeviceActor
224 ::SetUnstructuredGrid(vtkUnstructuredGrid* theGrid)
225 {
226   myExtractUnstructuredGrid->SetInputData(theGrid);
227
228   if ( theGrid )
229   {
230     myIsShrinkable = true;
231
232     myMergeFilter->SetGeometryConnection(myExtractUnstructuredGrid->GetOutputPort());
233
234     //Pass diameters of the balls
235     if(myMapper->GetBallEnabled()) {
236       myMergeFilter->SetScalarsConnection(myExtractUnstructuredGrid->GetOutputPort());
237     }
238
239     myExtractGeometry->SetInputConnection(myMergeFilter->GetOutputPort());
240
241     int anId = 0;
242     SetImplicitFunctionUsed(myIsImplicitFunctionUsed);
243     myPassFilter[ anId + 1]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
244
245     anId++; // 1
246     myTransformFilter->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
247
248     anId++; // 2
249     myPassFilter[ anId ]->SetInputConnection( myTransformFilter->GetOutputPort() );
250     myPassFilter[ anId + 1 ]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
251
252     anId++; // 3
253     myGeomFilter->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
254
255     anId++; // 4
256     myPassFilter[ anId ]->SetInputConnection( myGeomFilter->GetOutputPort() );
257     myPassFilter[ anId + 1 ]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
258
259     anId++; // 5
260     myMapper->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
261     if( myPlaneCollection->GetNumberOfItems() )
262       myMapper->SetClippingPlanes( myPlaneCollection );
263
264     vtkLODActor::SetMapper( myMapper );
265   }
266   Modified();
267 }
268
269 void
270 SMESH_DeviceActor
271 ::SetPlaneCollection( vtkPlaneCollection* theCollection )
272 {
273   myPlaneCollection = theCollection;
274 }
275
276 VTKViewer_ExtractUnstructuredGrid* 
277 SMESH_DeviceActor
278 ::GetExtractUnstructuredGrid()
279 {
280   return myExtractUnstructuredGrid;
281 }
282
283 #include "SMDS_Mesh.hxx"
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 = 0;// = 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   // cout << this->myExtractUnstructuredGrid
615   //      << " " << this->Superclass::GetMTime()
616   //      << " " << myExtractGeometry->GetMTime()
617   //      << " " << myExtractUnstructuredGrid->GetMTime()
618   //      << " " << myMergeFilter->GetMTime()
619   //      << " " << myGeomFilter->GetMTime()
620   //      << " " << myTransformFilter->GetMTime()
621   //      << " " << myFaceOrientationFilter->GetMTime() << endl;
622
623   unsigned long mTime = this->Superclass::GetMTime();
624   mTime = max(mTime,myExtractGeometry->GetMTime());
625   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
626   mTime = max(mTime,myMergeFilter->GetMTime());
627   mTime = max(mTime,myGeomFilter->GetMTime());
628   mTime = max(mTime,myTransformFilter->GetMTime());
629   mTime = max(mTime,myFaceOrientationFilter->GetMTime());
630   return mTime;
631 }
632
633
634 void
635 SMESH_DeviceActor
636 ::SetTransform(VTKViewer_Transform* theTransform)
637 {
638   myTransformFilter->SetTransform(theTransform);
639 }
640
641
642 void
643 SMESH_DeviceActor
644 ::SetShrink() 
645 {
646   if ( !myIsShrinkable ) return;
647   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
648   {
649     myShrinkFilter->SetInputConnection( aDataSet );
650     myPassFilter[ 1 ]->SetInputConnection( myShrinkFilter->GetOutputPort() );
651     myIsShrunk = true;
652   }
653 }
654
655 void
656 SMESH_DeviceActor
657 ::UnShrink() 
658 {
659   if ( !myIsShrunk ) return;
660   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
661   {    
662     myPassFilter[ 1 ]->SetInputConnection( aDataSet );
663     myPassFilter[ 1 ]->Modified();
664     myIsShrunk = false;
665     Modified();
666   }
667 }
668
669
670 void
671 SMESH_DeviceActor
672 ::SetFacesOriented(bool theIsFacesOriented) 
673 {
674   if ( vtkAlgorithmOutput* aDataSet = myTransformFilter->GetOutputPort() )
675   {
676     myIsFacesOriented = theIsFacesOriented;
677     if( theIsFacesOriented )
678       myFaceOrientationFilter->SetInputConnection( aDataSet );
679     UpdateFaceOrientation();
680   }
681 }
682
683 void
684 SMESH_DeviceActor
685 ::SetFacesOrientationColor(double r,double g,double b)
686 {
687   myFaceOrientation->GetProperty()->SetColor( r, g, b );
688 }
689
690 void
691 SMESH_DeviceActor
692 ::GetFacesOrientationColor(double& r,double& g,double& b)
693 {
694   myFaceOrientation->GetProperty()->GetColor( r, g, b );
695 }
696
697 void
698 SMESH_DeviceActor
699 ::SetFacesOrientationScale(double theScale)
700 {
701   myFaceOrientationFilter->SetOrientationScale( theScale );
702 }
703
704 double
705 SMESH_DeviceActor
706 ::GetFacesOrientationScale()
707 {
708   return myFaceOrientationFilter->GetOrientationScale();
709 }
710
711 void
712 SMESH_DeviceActor
713 ::SetFacesOrientation3DVectors(bool theState)
714 {
715   myFaceOrientationFilter->Set3dVectors( theState );
716 }
717
718 bool
719 SMESH_DeviceActor
720 ::GetFacesOrientation3DVectors()
721 {
722   return myFaceOrientationFilter->Get3dVectors();
723 }
724
725 void
726 SMESH_DeviceActor
727 ::UpdateFaceOrientation()
728 {
729   bool aShowFaceOrientation = myIsFacesOriented;
730   aShowFaceOrientation &= vtkLODActor::GetVisibility(); //GetVisibility(); -- avoid calling GetUnstructuredGrid()  
731   aShowFaceOrientation &= myRepresentation == eSurface;
732   myFaceOrientation->SetVisibility(aShowFaceOrientation);
733 }
734
735
736 void
737 SMESH_DeviceActor
738 ::SetRepresentation(EReperesent theMode)
739 {
740   switch(theMode){
741   case ePoint:
742     myGeomFilter->SetInside(true);
743     myGeomFilter->SetWireframeMode(false);
744     GetProperty()->SetRepresentation(0);
745     break;
746   case eWireframe:
747     myGeomFilter->SetInside(false);
748     myGeomFilter->SetWireframeMode(true);
749     GetProperty()->SetRepresentation(theMode);
750     break;
751   case eInsideframe:
752     myGeomFilter->SetInside(true);
753     myGeomFilter->SetWireframeMode(true);
754     GetProperty()->SetRepresentation(1);
755     break;
756   case eSurface:
757     myGeomFilter->SetInside(false);
758     myGeomFilter->SetWireframeMode(false);
759     GetProperty()->SetRepresentation(theMode);
760   }
761   SetMarkerEnabled(theMode == ePoint);
762   myRepresentation = theMode;
763   UpdateFaceOrientation();
764   GetProperty()->Modified();
765   myMapper->Modified();
766   Modified();
767 }
768
769
770 void
771 SMESH_DeviceActor
772 ::SetVisibility(int theMode)
773 {
774   if(( theMode ) &&
775      ( !myExtractUnstructuredGrid->GetInput() || 
776        GetUnstructuredGrid()->GetNumberOfCells()))
777   {
778     vtkLODActor::SetVisibility(theMode);
779   }else{
780     vtkLODActor::SetVisibility(false);
781   }
782   UpdateFaceOrientation();
783 }
784
785
786 int
787 SMESH_DeviceActor
788 ::GetVisibility()
789 {
790   int visibi = vtkLODActor::GetVisibility();
791   if(visibi && !GetUnstructuredGrid()->GetNumberOfCells()){
792     vtkLODActor::SetVisibility(false);
793     visibi = 0;
794   }
795   return visibi;
796 }
797
798
799 void
800 SMESH_DeviceActor
801 ::AddToRender(vtkRenderer* theRenderer)
802 {
803   theRenderer->AddActor(this);
804   theRenderer->AddActor(myFaceOrientation);
805 }
806
807 void
808 SMESH_DeviceActor
809 ::RemoveFromRender(vtkRenderer* theRenderer)
810 {
811   theRenderer->RemoveActor(this);
812   theRenderer->RemoveActor(myFaceOrientation);
813 }
814
815
816 int
817 SMESH_DeviceActor
818 ::GetNodeObjId(int theVtkID)
819 {
820   vtkIdType anID = theVtkID;
821
822   if(IsImplicitFunctionUsed())
823     anID = myExtractGeometry->GetNodeObjId(theVtkID);
824
825   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
826   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; anID = "<<anID<<"; aRetID = "<<aRetID);
827   return aRetID;
828 }
829
830 double* 
831 SMESH_DeviceActor
832 ::GetNodeCoord(int theObjID)
833 {
834   vtkDataSet* aDataSet = myMergeFilter->GetOutput();
835   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
836   double* aCoord = (anID >=0 && anID < aDataSet->GetNumberOfPoints()) ? aDataSet->GetPoint(anID) : NULL;
837   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
838   return aCoord;
839 }
840
841
842 int
843 SMESH_DeviceActor
844 ::GetElemObjId(int theVtkID)
845 {
846   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
847   if(anId < 0) 
848     return -1;
849
850   vtkIdType anId2 = anId;
851   if(IsImplicitFunctionUsed())
852     anId2 = myExtractGeometry->GetElemObjId(anId);
853   if(anId2 < 0) 
854     return -1;
855
856   vtkIdType anId3 = myExtractUnstructuredGrid->GetInputId(anId2);
857   if(anId3 < 0) 
858     return -1;
859
860   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
861   if(MYDEBUG) 
862      MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
863   return aRetID;
864 }
865
866 vtkCell* 
867 SMESH_DeviceActor
868 ::GetElemCell(int theObjID)
869 {
870   vtkDataSet* aDataSet = myVisualObj->GetUnstructuredGrid();
871   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
872   vtkCell* aCell = (aGridID >= 0 ) ? aDataSet->GetCell(aGridID) : NULL;
873   if(MYDEBUG) 
874     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
875   return aCell;
876 }
877
878
879 double 
880 SMESH_DeviceActor
881 ::GetShrinkFactor()
882 {
883   return myShrinkFilter->GetShrinkFactor();
884 }
885
886 void
887 SMESH_DeviceActor
888 ::SetShrinkFactor(double theValue)
889 {
890   theValue = theValue > 0.1? theValue: 0.8;
891   myShrinkFilter->SetShrinkFactor(theValue);
892   Modified();
893 }
894
895
896 void
897 SMESH_DeviceActor
898 ::SetHighlited(bool theIsHighlited)
899 {
900   if ( myIsHighlited == theIsHighlited )
901     return;
902   myIsHighlited = theIsHighlited;
903   Modified();
904 }
905
906 void
907 SMESH_DeviceActor
908 ::Render(vtkRenderer *ren, vtkMapper* m)
909 {
910   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
911   double aStoredFactor, aStoredUnit; 
912   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
913
914   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
915   double aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
916   if(myIsHighlited){
917     static double EPS = .01;
918     aUnits *= (1.0-EPS);
919   }
920   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
921   vtkLODActor::Render(ren,m);
922
923   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
924   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
925 }
926
927
928 void
929 SMESH_DeviceActor
930 ::SetPolygonOffsetParameters(double factor, 
931                              double units)
932 {
933   myPolygonOffsetFactor = factor;
934   myPolygonOffsetUnits = units;
935 }
936
937 /*!
938  * On/Off representation 2D quadratic element as arked polygon
939  */
940 void SMESH_DeviceActor::SetQuadraticArcMode(bool theFlag){
941   myGeomFilter->SetQuadraticArcMode(theFlag);
942 }
943
944 /*!
945  * Return true if 2D quadratic element displayed as arked polygon
946  */
947 bool SMESH_DeviceActor::GetQuadraticArcMode(){
948   return myGeomFilter->GetQuadraticArcMode();
949 }
950 /*!
951  * Set Max angle for representation 2D quadratic element as arked polygon
952  */
953 void SMESH_DeviceActor::SetQuadraticArcAngle(double theMaxAngle){
954   myGeomFilter->SetQuadraticArcAngle(theMaxAngle);
955 }
956
957 /*!
958  * Return Max angle of the representation 2D quadratic element as arked polygon
959  */
960 double SMESH_DeviceActor::GetQuadraticArcAngle(){
961   return myGeomFilter->GetQuadraticArcAngle();
962 }
963
964 /*!
965  * Set point marker enabled
966  * \param theMarkerEnabled flag to enable/disable point marker
967  */
968 void SMESH_DeviceActor::SetMarkerEnabled( bool theMarkerEnabled )
969 {
970   myMapper->SetMarkerEnabled( theMarkerEnabled );
971 }
972
973 /*!
974  * Set point marker enabled
975  * \param theBallEnabled flag to enable/disable ball drawing
976  */
977 void SMESH_DeviceActor::SetBallEnabled( bool theBallEnabled ) {
978   myMapper->SetBallEnabled( theBallEnabled );
979 }
980
981 /*!
982  * Set point marker scale factor
983  * \param theBallScale double value which specifies a scale factor of ball element
984  */
985 void SMESH_DeviceActor::SetBallScale( double theBallScale )
986 {
987   myMapper->SetBallScale( theBallScale );
988   myMapper->Modified();
989 }
990
991 /*!
992  * Set standard point marker
993  * \param theMarkerType type of the marker
994  */
995 void SMESH_DeviceActor::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
996 {
997   myMapper->SetMarkerStd( theMarkerType, theMarkerScale );
998 }
999
1000 /*!
1001  * Set custom point marker
1002  * \param theMarkerId id of the marker texture
1003  * \param theMarkerTexture marker texture
1004  */
1005 void SMESH_DeviceActor::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
1006 {
1007   myMapper->SetMarkerTexture( theMarkerId, theMarkerTexture );
1008 }
1009
1010 /*!
1011  * Get type of the point marker
1012  * \return type of the point marker
1013  */
1014 VTK::MarkerType SMESH_DeviceActor::GetMarkerType()
1015 {
1016   return myMapper->GetMarkerType();
1017 }
1018
1019 /*!
1020   Get scale of the point marker
1021   \return scale of the point marker
1022 */
1023 VTK::MarkerScale SMESH_DeviceActor::GetMarkerScale()
1024 {
1025   return myMapper->GetMarkerScale();
1026 }
1027
1028 /*!
1029  * Get texture identifier of the point marker
1030  * \return texture identifier of the point marker
1031  */
1032 int SMESH_DeviceActor::GetMarkerTexture()
1033 {
1034   return myMapper->GetMarkerTexture();
1035 }
1036
1037 /*!
1038  * Get scale factor of ball element
1039  * \return scale factor of ball element
1040  */
1041 double SMESH_DeviceActor::GetBallScale()
1042 {
1043   return myMapper->GetBallScale();
1044 }
1045
1046 void SMESH_DeviceActor::SetCoincident3DAllowed(bool theFlag) {
1047   myGeomFilter->SetAppendCoincident3D(theFlag);
1048 }
1049
1050 bool SMESH_DeviceActor::IsCoincident3DAllowed() const {
1051   return myGeomFilter->GetAppendCoincident3D();
1052 }