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(); -- it is vtkSmartPointer
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   // for optimization, switch the mapping explicitly in each filter/algorithm
176   //SetStoreClippingMapping(theStoreMapping);
177 }
178
179
180 void
181 SMESH_DeviceActor
182 ::SetStoreClippingMapping(bool theStoreMapping)
183 {
184   myStoreClippingMapping = theStoreMapping;
185   myExtractGeometry->SetStoreMapping(theStoreMapping && myIsImplicitFunctionUsed);
186   // EAP, 23315
187   // Mapping in myExtractUnstructuredGrid and myGeomFilter is ON in the pickable DeviceActor only.
188   // To show labels, the mapping is computed explicitly via myExtractUnstructuredGrid->BuildOut2InMap();
189   //SetStoreIDMapping(theStoreMapping);
190 }
191
192
193 void
194 SMESH_DeviceActor
195 ::SetStoreIDMapping(bool theStoreMapping)
196 {
197   myExtractUnstructuredGrid->SetStoreMapping(theStoreMapping);
198 }
199
200
201 void 
202 SMESH_DeviceActor
203 ::Init(TVisualObjPtr theVisualObj, 
204        vtkImplicitBoolean* theImplicitBoolean)
205 {
206   myVisualObj = theVisualObj;
207   myExtractGeometry->SetImplicitFunction(theImplicitBoolean);
208   SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
209 }
210
211 void
212 SMESH_DeviceActor
213 ::SetImplicitFunctionUsed(bool theIsImplicitFunctionUsed)
214 {
215   int anId = 0;
216   if(theIsImplicitFunctionUsed)
217     myPassFilter[ anId ]->SetInputConnection( myExtractGeometry->GetOutputPort() );
218   else
219     myPassFilter[ anId ]->SetInputConnection( myMergeFilter->GetOutputPort() );
220     
221   myIsImplicitFunctionUsed = theIsImplicitFunctionUsed;
222   SetStoreClippingMapping(myStoreClippingMapping);
223 }
224
225
226 void
227 SMESH_DeviceActor
228 ::SetUnstructuredGrid(vtkUnstructuredGrid* theGrid)
229 {
230   myExtractUnstructuredGrid->SetInputData(theGrid);
231
232   if ( theGrid )
233   {
234     myIsShrinkable = true;
235
236     myMergeFilter->SetGeometryConnection(myExtractUnstructuredGrid->GetOutputPort());
237
238     //Pass diameters of the balls
239     if(myMapper->GetBallEnabled()) {
240       myMergeFilter->SetScalarsConnection(myExtractUnstructuredGrid->GetOutputPort());
241     }
242
243     myExtractGeometry->SetInputConnection(myMergeFilter->GetOutputPort());
244
245     int anId = 0;
246     SetImplicitFunctionUsed(myIsImplicitFunctionUsed);
247     myPassFilter[ anId + 1]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
248
249     anId++; // 1
250     myTransformFilter->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
251
252     anId++; // 2
253     myPassFilter[ anId ]->SetInputConnection( myTransformFilter->GetOutputPort() );
254     myPassFilter[ anId + 1 ]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
255
256     anId++; // 3
257     myGeomFilter->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
258
259     anId++; // 4
260     myPassFilter[ anId ]->SetInputConnection( myGeomFilter->GetOutputPort() );
261     myPassFilter[ anId + 1 ]->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
262
263     anId++; // 5
264     myMapper->SetInputConnection( myPassFilter[ anId ]->GetOutputPort() );
265     if( myPlaneCollection->GetNumberOfItems() )
266       myMapper->SetClippingPlanes( myPlaneCollection );
267
268     vtkLODActor::SetMapper( myMapper );
269   }
270   Modified();
271 }
272
273 void
274 SMESH_DeviceActor
275 ::SetPlaneCollection( vtkPlaneCollection* theCollection )
276 {
277   myPlaneCollection = theCollection;
278 }
279
280 VTKViewer_ExtractUnstructuredGrid* 
281 SMESH_DeviceActor
282 ::GetExtractUnstructuredGrid()
283 {
284   return myExtractUnstructuredGrid;
285 }
286
287 #include "SMDS_Mesh.hxx"
288
289 vtkUnstructuredGrid* 
290 SMESH_DeviceActor
291 ::GetUnstructuredGrid()
292 {
293   myExtractUnstructuredGrid->Update();
294   return myExtractUnstructuredGrid->GetOutput();
295 }
296
297
298 void
299 SMESH_DeviceActor
300 ::SetControlMode(SMESH::Controls::FunctorPtr theFunctor,
301                  SMESH_ScalarBarActor* theScalarBarActor,
302                  vtkLookupTable* theLookupTable)
303 {
304   bool anIsInitialized = theFunctor != NULL;
305   if(anIsInitialized){
306     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
307
308     // SetStoreIDMapping(true);
309     // myExtractUnstructuredGrid->Update();
310     vtkUnstructuredGrid* aGrid = myExtractUnstructuredGrid->GetOutput();
311
312     aDataSet->ShallowCopy(aGrid);
313     
314     vtkDoubleArray *aScalars = vtkDoubleArray::New();
315     vtkIdType aNbCells = aGrid->GetNumberOfCells();
316     aScalars->SetNumberOfComponents(1);
317     aScalars->SetNumberOfTuples(aNbCells);
318     double* range = 0;// = aScalars->GetRange();
319     
320     myVisualObj->UpdateFunctor(theFunctor);
321
322     using namespace SMESH::Controls;
323     if(NumericalFunctor* aNumericalFunctor = dynamic_cast<NumericalFunctor*>(theFunctor.get()))
324     {
325       myExtractUnstructuredGrid->BuildOut2InMap();
326       for(vtkIdType i = 0; i < aNbCells; i++)
327       {
328         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
329         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
330         double aValue = aNumericalFunctor->GetValue(anObjId);
331         aScalars->SetValue(i,aValue);
332       }
333       range = aScalars->GetRange();
334       if ( range[1] - range[0] < ( qMax(qAbs(range[0]),qAbs(range[1])) + 1e-100 ) * 1e-6 )
335       {
336         range[1] = range[0];
337         for(vtkIdType i = 0; i < aNbCells; i++)
338           aScalars->SetValue(i,range[0]);
339       }
340     }
341     else if(Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get()))
342     {
343       myExtractUnstructuredGrid->BuildOut2InMap();
344       for(vtkIdType i = 0; i < aNbCells; i++)
345       {
346         vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
347         vtkIdType anObjId = myVisualObj->GetElemObjId(anId);
348         bool aValue = aPredicate->IsSatisfy(anObjId);
349         aScalars->SetValue(i,aValue);
350       }
351       range = aScalars->GetRange();
352     }
353
354     aDataSet->GetCellData()->SetScalars(aScalars);
355     aScalars->Delete();
356
357     theLookupTable->SetRange( range );
358     theLookupTable->SetNumberOfTableValues(theScalarBarActor->GetMaximumNumberOfColors());
359     theLookupTable->Build();
360     
361     myMergeFilter->SetScalarsData(aDataSet);
362     aDataSet->Delete();
363   }
364   GetMapper()->SetScalarVisibility(anIsInitialized);
365   theScalarBarActor->SetVisibility(anIsInitialized);
366 }
367
368 void
369 SMESH_DeviceActor
370 ::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
371                     SMESH_ScalarBarActor* theScalarBarActor,
372                     vtkLookupTable* theLookupTable)
373 {
374   bool anIsInitialized = theFunctor != NULL;
375   myExtractUnstructuredGrid->ClearRegisteredCells();
376   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
377   myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::ePassAll);
378   myVisualObj->UpdateFunctor(theFunctor);
379
380   using namespace SMESH::Controls;
381   if (anIsInitialized){
382     if (Length2D* aLength2D = dynamic_cast<Length2D*>(theFunctor.get())){
383       SMESH::Controls::Length2D::TValues aValues;
384
385       aLength2D->GetValues(aValues);
386       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
387       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
388
389       aDataSet->SetPoints(aGrid->GetPoints());
390       
391       vtkIdType aNbCells = aValues.size();
392       
393       vtkDoubleArray *aScalars = vtkDoubleArray::New();
394       aScalars->SetNumberOfComponents(1);
395       aScalars->SetNumberOfTuples(aNbCells);
396
397       vtkIdType aCellsSize = 3*aNbCells;
398       vtkCellArray* aConnectivity = vtkCellArray::New();
399       aConnectivity->Allocate( aCellsSize, 0 );
400       
401       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
402       aCellTypesArray->SetNumberOfComponents( 1 );
403       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
404
405       vtkIdList *anIdList = vtkIdList::New();
406       anIdList->SetNumberOfIds(2);
407
408       Length2D::TValues::const_iterator anIter = aValues.begin();
409       aNbCells = 0;
410       for(; anIter != aValues.end(); anIter++){
411         const Length2D::Value& aValue = *anIter;
412         int aNode[2] = {
413           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
414           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
415         };
416         if(aNode[0] >= 0 && aNode[1] >= 0){
417           anIdList->SetId( 0, aNode[0] );
418           anIdList->SetId( 1, aNode[1] );
419           aConnectivity->InsertNextCell( anIdList );
420           aCellTypesArray->InsertNextValue( VTK_LINE );
421           aScalars->SetValue(aNbCells,aValue.myLength);
422           aNbCells++;
423         }
424       }
425       aCellTypesArray->SetNumberOfTuples( aNbCells );
426       aScalars->SetNumberOfTuples( aNbCells );
427
428       VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
429       aCellLocationsArray->SetNumberOfComponents( 1 );
430       aCellLocationsArray->SetNumberOfTuples( aNbCells );
431
432       aConnectivity->InitTraversal();
433       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
434         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
435
436       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray, aConnectivity );
437       SetUnstructuredGrid(aDataSet);
438
439       aDataSet->GetCellData()->SetScalars(aScalars);
440       aScalars->Delete();
441
442       theLookupTable->SetRange(aScalars->GetRange());
443       theLookupTable->Build();
444
445       myMergeFilter->SetScalarsData(aDataSet);
446       aDataSet->Delete();
447     }
448     else if (MultiConnection2D* aMultiConnection2D = dynamic_cast<MultiConnection2D*>(theFunctor.get())){
449       SMESH::Controls::MultiConnection2D::MValues aValues;
450
451       aMultiConnection2D->GetValues(aValues);
452       vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
453       vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
454       aDataSet->SetPoints(aGrid->GetPoints());
455       
456       vtkIdType aNbCells = aValues.size();
457       vtkDoubleArray *aScalars = vtkDoubleArray::New();
458       aScalars->SetNumberOfComponents(1);
459       aScalars->SetNumberOfTuples(aNbCells);
460
461       vtkIdType aCellsSize = 3*aNbCells;
462       vtkCellArray* aConnectivity = vtkCellArray::New();
463       aConnectivity->Allocate( aCellsSize, 0 );
464
465       vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
466       aCellTypesArray->SetNumberOfComponents( 1 );
467       aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
468
469       vtkIdList *anIdList = vtkIdList::New();
470       anIdList->SetNumberOfIds(2);
471
472       MultiConnection2D::MValues::const_iterator anIter = aValues.begin();
473       aNbCells = 0;
474       for(; anIter != aValues.end(); anIter++){
475         const MultiConnection2D::Value& aValue = (*anIter).first;
476         int aNode[2] = {
477           myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
478           myVisualObj->GetNodeVTKId(aValue.myPntId[1])
479         };
480         if(aNode[0] >= 0 && aNode[1] >= 0){
481           anIdList->SetId( 0, aNode[0] );
482           anIdList->SetId( 1, aNode[1] );
483           aConnectivity->InsertNextCell( anIdList );
484           aCellTypesArray->InsertNextValue( VTK_LINE );
485           aScalars->SetValue( aNbCells,(*anIter).second);
486           aNbCells++;
487         }
488       }
489       aCellTypesArray->SetNumberOfTuples( aNbCells );
490       aScalars->SetNumberOfTuples( aNbCells );
491
492       VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
493       aCellLocationsArray->SetNumberOfComponents( 1 );
494       aCellLocationsArray->SetNumberOfTuples( aNbCells );
495
496       aConnectivity->InitTraversal();
497       for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
498         aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
499
500       aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
501       SetUnstructuredGrid(aDataSet);
502
503       aDataSet->GetCellData()->SetScalars(aScalars);
504       aScalars->Delete();
505
506       theLookupTable->SetRange(aScalars->GetRange());
507       theLookupTable->Build();
508
509       myMergeFilter->SetScalarsData(aDataSet);
510       aDataSet->Delete();
511     }
512   }
513   GetMapper()->SetScalarVisibility(anIsInitialized);
514   theScalarBarActor->SetVisibility(anIsInitialized);
515 }
516
517 void
518 SMESH_DeviceActor
519 ::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor)
520 {
521   myExtractUnstructuredGrid->ClearRegisteredCells();
522   myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
523   myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::ePassAll);
524   myVisualObj->UpdateFunctor(theFunctor);
525
526   using namespace SMESH::Controls;
527   Predicate* aPredicate = 0;
528   if (( aPredicate =  dynamic_cast<FreeBorders          *>(theFunctor.get())) ||
529       ( aPredicate =  dynamic_cast<FreeFaces            *>(theFunctor.get())) ||
530       ( aPredicate =  dynamic_cast<BareBorderVolume     *>(theFunctor.get())) ||
531       ( aPredicate =  dynamic_cast<BareBorderFace       *>(theFunctor.get())) ||
532       ( aPredicate =  dynamic_cast<OverConstrainedVolume*>(theFunctor.get())) ||
533       ( aPredicate =  dynamic_cast<CoincidentElements1D *>(theFunctor.get())) ||
534       ( aPredicate =  dynamic_cast<CoincidentElements2D *>(theFunctor.get())) ||
535       ( aPredicate =  dynamic_cast<CoincidentElements3D *>(theFunctor.get())) ||
536       ( aPredicate =  dynamic_cast<OverConstrainedFace  *>(theFunctor.get())))
537   {
538     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
539     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
540     vtkIdType aNbCells = aGrid->GetNumberOfCells();
541     for( vtkIdType i = 0; i < aNbCells; i++ ){
542       vtkIdType anObjId = myVisualObj->GetElemObjId(i);
543       if(aPredicate->IsSatisfy(anObjId))
544         myExtractUnstructuredGrid->RegisterCell(i);
545     }
546     if(!myExtractUnstructuredGrid->IsCellsRegistered())
547       myExtractUnstructuredGrid->RegisterCell(-1);
548     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
549   }
550   else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get()))
551   {
552     SMESH::Controls::FreeEdges::TBorders aBorders;
553     aFreeEdges->GetBoreders(aBorders);
554     vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
555     vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
556     aDataSet->SetPoints(aGrid->GetPoints());
557
558     vtkIdType aNbCells = aBorders.size();
559     vtkIdType aCellsSize = 3*aNbCells;
560     vtkCellArray* aConnectivity = vtkCellArray::New();
561     aConnectivity->Allocate( aCellsSize, 0 );
562     
563     vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
564     aCellTypesArray->SetNumberOfComponents( 1 );
565     aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
566     
567     vtkIdList *anIdList = vtkIdList::New();
568     anIdList->SetNumberOfIds(2);
569     
570     FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
571     for(; anIter != aBorders.end(); anIter++){
572       const FreeEdges::Border& aBorder = *anIter;
573       int aNode[2] = {
574         myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
575         myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
576       };
577       //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
578       if(aNode[0] >= 0 && aNode[1] >= 0){
579         anIdList->SetId( 0, aNode[0] );
580         anIdList->SetId( 1, aNode[1] );
581         aConnectivity->InsertNextCell( anIdList );
582         aCellTypesArray->InsertNextValue( VTK_LINE );
583       }
584     }
585     
586     VTKViewer_CellLocationsArray* aCellLocationsArray = VTKViewer_CellLocationsArray::New();
587     aCellLocationsArray->SetNumberOfComponents( 1 );
588     aCellLocationsArray->SetNumberOfTuples( aNbCells );
589     
590     aConnectivity->InitTraversal();
591     for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
592       aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
593     
594     aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
595
596     SetUnstructuredGrid(aDataSet);
597     aDataSet->Delete();
598   }
599   else if (( aPredicate = dynamic_cast<FreeNodes      *>(theFunctor.get())) ||
600            ( aPredicate = dynamic_cast<CoincidentNodes*>(theFunctor.get())))
601   {
602     myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding);
603     vtkIdType aNbNodes = myVisualObj->GetNbEntities(SMDSAbs_Node);
604     for( vtkIdType i = 0; i < aNbNodes; i++ ){
605       vtkIdType anObjId = myVisualObj->GetNodeObjId(i);
606       if(aPredicate->IsSatisfy(anObjId))
607         myExtractUnstructuredGrid->RegisterCell(i);
608     }
609     if(!myExtractUnstructuredGrid->IsCellsRegistered())
610       myExtractUnstructuredGrid->RegisterCell(-1);
611     SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
612   }
613 }
614
615
616
617
618 unsigned long int
619 SMESH_DeviceActor
620 ::GetMTime()
621 {
622   // cout << this->myExtractUnstructuredGrid
623   //      << " " << this->Superclass::GetMTime()
624   //      << " " << myExtractGeometry->GetMTime()
625   //      << " " << myExtractUnstructuredGrid->GetMTime()
626   //      << " " << myMergeFilter->GetMTime()
627   //      << " " << myGeomFilter->GetMTime()
628   //      << " " << myTransformFilter->GetMTime()
629   //      << " " << myFaceOrientationFilter->GetMTime() << endl;
630
631   unsigned long mTime = this->Superclass::GetMTime();
632   mTime = max(mTime,myExtractGeometry->GetMTime());
633   mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
634   mTime = max(mTime,myMergeFilter->GetMTime());
635   mTime = max(mTime,myGeomFilter->GetMTime());
636   mTime = max(mTime,myTransformFilter->GetMTime());
637   mTime = max(mTime,myFaceOrientationFilter->GetMTime());
638   return mTime;
639 }
640
641
642 void
643 SMESH_DeviceActor
644 ::SetTransform(VTKViewer_Transform* theTransform)
645 {
646   myTransformFilter->SetTransform(theTransform);
647 }
648
649
650 void
651 SMESH_DeviceActor
652 ::SetShrink() 
653 {
654   if ( !myIsShrinkable ) return;
655   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
656   {
657     myShrinkFilter->SetInputConnection( aDataSet );
658     myPassFilter[ 1 ]->SetInputConnection( myShrinkFilter->GetOutputPort() );
659     myIsShrunk = true;
660   }
661 }
662
663 void
664 SMESH_DeviceActor
665 ::UnShrink() 
666 {
667   if ( !myIsShrunk ) return;
668   if ( vtkAlgorithmOutput* aDataSet = myPassFilter[ 0 ]->GetOutputPort() )
669   {    
670     myPassFilter[ 1 ]->SetInputConnection( aDataSet );
671     myPassFilter[ 1 ]->Modified();
672     myIsShrunk = false;
673     Modified();
674   }
675 }
676
677
678 void
679 SMESH_DeviceActor
680 ::SetFacesOriented(bool theIsFacesOriented) 
681 {
682   if ( vtkAlgorithmOutput* aDataSet = myTransformFilter->GetOutputPort() )
683   {
684     myIsFacesOriented = theIsFacesOriented;
685     if( theIsFacesOriented )
686       myFaceOrientationFilter->SetInputConnection( aDataSet );
687     UpdateFaceOrientation();
688   }
689 }
690
691 void
692 SMESH_DeviceActor
693 ::SetFacesOrientationColor(double r,double g,double b)
694 {
695   myFaceOrientation->GetProperty()->SetColor( r, g, b );
696 }
697
698 void
699 SMESH_DeviceActor
700 ::GetFacesOrientationColor(double& r,double& g,double& b)
701 {
702   myFaceOrientation->GetProperty()->GetColor( r, g, b );
703 }
704
705 void
706 SMESH_DeviceActor
707 ::SetFacesOrientationScale(double theScale)
708 {
709   myFaceOrientationFilter->SetOrientationScale( theScale );
710 }
711
712 double
713 SMESH_DeviceActor
714 ::GetFacesOrientationScale()
715 {
716   return myFaceOrientationFilter->GetOrientationScale();
717 }
718
719 void
720 SMESH_DeviceActor
721 ::SetFacesOrientation3DVectors(bool theState)
722 {
723   myFaceOrientationFilter->Set3dVectors( theState );
724 }
725
726 bool
727 SMESH_DeviceActor
728 ::GetFacesOrientation3DVectors()
729 {
730   return myFaceOrientationFilter->Get3dVectors();
731 }
732
733 void
734 SMESH_DeviceActor
735 ::UpdateFaceOrientation()
736 {
737   bool aShowFaceOrientation = myIsFacesOriented;
738   aShowFaceOrientation &= vtkLODActor::GetVisibility(); //GetVisibility(); -- avoid calling GetUnstructuredGrid()  
739   aShowFaceOrientation &= myRepresentation == eSurface;
740   myFaceOrientation->SetVisibility(aShowFaceOrientation);
741 }
742
743
744 void
745 SMESH_DeviceActor
746 ::SetRepresentation(EReperesent theMode)
747 {
748   switch(theMode){
749   case ePoint:
750     myGeomFilter->SetInside(true);
751     myGeomFilter->SetWireframeMode(false);
752     GetProperty()->SetRepresentation(0);
753     break;
754   case eWireframe:
755     myGeomFilter->SetInside(false);
756     myGeomFilter->SetWireframeMode(true);
757     GetProperty()->SetRepresentation(theMode);
758     break;
759   case eInsideframe:
760     myGeomFilter->SetInside(true);
761     myGeomFilter->SetWireframeMode(true);
762     GetProperty()->SetRepresentation(1);
763     break;
764   case eSurface:
765     myGeomFilter->SetInside(false);
766     myGeomFilter->SetWireframeMode(false);
767     GetProperty()->SetRepresentation(theMode);
768   }
769   SetMarkerEnabled(theMode == ePoint);
770   myRepresentation = theMode;
771   UpdateFaceOrientation();
772   GetProperty()->Modified();
773   myMapper->Modified();
774   Modified();
775 }
776
777
778 void
779 SMESH_DeviceActor
780 ::SetVisibility(int theMode)
781 {
782   if(( theMode ) &&
783      ( !myExtractUnstructuredGrid->GetInput() || 
784        GetUnstructuredGrid()->GetNumberOfCells()))
785   {
786     vtkLODActor::SetVisibility(theMode);
787   }else{
788     vtkLODActor::SetVisibility(false);
789   }
790   UpdateFaceOrientation();
791 }
792
793
794 int
795 SMESH_DeviceActor
796 ::GetVisibility()
797 {
798   int visibi = vtkLODActor::GetVisibility();
799   if(visibi && !GetUnstructuredGrid()->GetNumberOfCells()){
800     vtkLODActor::SetVisibility(false);
801     visibi = 0;
802   }
803   return visibi;
804 }
805
806
807 void
808 SMESH_DeviceActor
809 ::AddToRender(vtkRenderer* theRenderer)
810 {
811   theRenderer->AddActor(this);
812   theRenderer->AddActor(myFaceOrientation);
813 }
814
815 void
816 SMESH_DeviceActor
817 ::RemoveFromRender(vtkRenderer* theRenderer)
818 {
819   theRenderer->RemoveActor(this);
820   theRenderer->RemoveActor(myFaceOrientation);
821 }
822
823
824 int
825 SMESH_DeviceActor
826 ::GetNodeObjId(int theVtkID)
827 {
828   vtkIdType anID = theVtkID;
829
830   if(IsImplicitFunctionUsed())
831     anID = myExtractGeometry->GetNodeObjId(theVtkID);
832
833   vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
834   if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; anID = "<<anID<<"; aRetID = "<<aRetID);
835   return aRetID;
836 }
837
838 double* 
839 SMESH_DeviceActor
840 ::GetNodeCoord(int theObjID)
841 {
842   vtkDataSet* aDataSet = myMergeFilter->GetOutput();
843   vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
844   double* aCoord = (anID >=0 && anID < aDataSet->GetNumberOfPoints()) ? aDataSet->GetPoint(anID) : NULL;
845   if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
846   return aCoord;
847 }
848
849
850 int
851 SMESH_DeviceActor
852 ::GetElemObjId(int theVtkID)
853 {
854   vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
855   if(anId < 0) 
856     return -1;
857
858   vtkIdType anId2 = anId;
859   if(IsImplicitFunctionUsed())
860     anId2 = myExtractGeometry->GetElemObjId(anId);
861   if(anId2 < 0) 
862     return -1;
863
864   vtkIdType anId3 = myExtractUnstructuredGrid->GetInputId(anId2);
865   if(anId3 < 0) 
866     return -1;
867
868   vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
869   if(MYDEBUG) 
870      MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
871   return aRetID;
872 }
873
874 vtkCell* 
875 SMESH_DeviceActor
876 ::GetElemCell(int theObjID)
877 {
878   vtkDataSet* aDataSet = myVisualObj->GetUnstructuredGrid();
879   vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
880   vtkCell* aCell = (aGridID >= 0 ) ? aDataSet->GetCell(aGridID) : NULL;
881   if(MYDEBUG) 
882     MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
883   return aCell;
884 }
885
886
887 double 
888 SMESH_DeviceActor
889 ::GetShrinkFactor()
890 {
891   return myShrinkFilter->GetShrinkFactor();
892 }
893
894 void
895 SMESH_DeviceActor
896 ::SetShrinkFactor(double theValue)
897 {
898   theValue = theValue > 0.1? theValue: 0.8;
899   myShrinkFilter->SetShrinkFactor(theValue);
900   Modified();
901 }
902
903
904 void
905 SMESH_DeviceActor
906 ::SetHighlited(bool theIsHighlited)
907 {
908   if ( myIsHighlited == theIsHighlited )
909     return;
910   myIsHighlited = theIsHighlited;
911   Modified();
912 }
913
914 void
915 SMESH_DeviceActor
916 ::Render(vtkRenderer *ren, vtkMapper* m)
917 {
918   int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
919   double aStoredFactor, aStoredUnit; 
920   vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
921
922   vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
923   double aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
924   if(myIsHighlited){
925     static double EPS = .01;
926     aUnits *= (1.0-EPS);
927   }
928   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
929   vtkLODActor::Render(ren,m);
930
931   vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
932   vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
933 }
934
935
936 void
937 SMESH_DeviceActor
938 ::SetPolygonOffsetParameters(double factor, 
939                              double units)
940 {
941   myPolygonOffsetFactor = factor;
942   myPolygonOffsetUnits = units;
943 }
944
945 /*!
946  * On/Off representation 2D quadratic element as arked polygon
947  */
948 void SMESH_DeviceActor::SetQuadraticArcMode(bool theFlag){
949   myGeomFilter->SetQuadraticArcMode(theFlag);
950 }
951
952 /*!
953  * Return true if 2D quadratic element displayed as arked polygon
954  */
955 bool SMESH_DeviceActor::GetQuadraticArcMode(){
956   return myGeomFilter->GetQuadraticArcMode();
957 }
958 /*!
959  * Set Max angle for representation 2D quadratic element as arked polygon
960  */
961 void SMESH_DeviceActor::SetQuadraticArcAngle(double theMaxAngle){
962   myGeomFilter->SetQuadraticArcAngle(theMaxAngle);
963 }
964
965 /*!
966  * Return Max angle of the representation 2D quadratic element as arked polygon
967  */
968 double SMESH_DeviceActor::GetQuadraticArcAngle(){
969   return myGeomFilter->GetQuadraticArcAngle();
970 }
971
972 /*!
973  * Set point marker enabled
974  * \param theMarkerEnabled flag to enable/disable point marker
975  */
976 void SMESH_DeviceActor::SetMarkerEnabled( bool theMarkerEnabled )
977 {
978   myMapper->SetMarkerEnabled( theMarkerEnabled );
979 }
980
981 /*!
982  * Set point marker enabled
983  * \param theBallEnabled flag to enable/disable ball drawing
984  */
985 void SMESH_DeviceActor::SetBallEnabled( bool theBallEnabled ) {
986   myMapper->SetBallEnabled( theBallEnabled );
987 }
988
989 /*!
990  * Set point marker scale factor
991  * \param theBallScale double value which specifies a scale factor of ball element
992  */
993 void SMESH_DeviceActor::SetBallScale( double theBallScale )
994 {
995   myMapper->SetBallScale( theBallScale );
996   myMapper->Modified();
997 }
998
999 /*!
1000  * Set standard point marker
1001  * \param theMarkerType type of the marker
1002  */
1003 void SMESH_DeviceActor::SetMarkerStd( VTK::MarkerType theMarkerType, VTK::MarkerScale theMarkerScale )
1004 {
1005   myMapper->SetMarkerStd( theMarkerType, theMarkerScale );
1006 }
1007
1008 /*!
1009  * Set custom point marker
1010  * \param theMarkerId id of the marker texture
1011  * \param theMarkerTexture marker texture
1012  */
1013 void SMESH_DeviceActor::SetMarkerTexture( int theMarkerId, VTK::MarkerTexture theMarkerTexture )
1014 {
1015   myMapper->SetMarkerTexture( theMarkerId, theMarkerTexture );
1016 }
1017
1018 /*!
1019  * Get type of the point marker
1020  * \return type of the point marker
1021  */
1022 VTK::MarkerType SMESH_DeviceActor::GetMarkerType()
1023 {
1024   return myMapper->GetMarkerType();
1025 }
1026
1027 /*!
1028   Get scale of the point marker
1029   \return scale of the point marker
1030 */
1031 VTK::MarkerScale SMESH_DeviceActor::GetMarkerScale()
1032 {
1033   return myMapper->GetMarkerScale();
1034 }
1035
1036 /*!
1037  * Get texture identifier of the point marker
1038  * \return texture identifier of the point marker
1039  */
1040 int SMESH_DeviceActor::GetMarkerTexture()
1041 {
1042   return myMapper->GetMarkerTexture();
1043 }
1044
1045 /*!
1046  * Get scale factor of ball element
1047  * \return scale factor of ball element
1048  */
1049 double SMESH_DeviceActor::GetBallScale()
1050 {
1051   return myMapper->GetBallScale();
1052 }
1053
1054 void SMESH_DeviceActor::SetCoincident3DAllowed(bool theFlag) {
1055   myGeomFilter->SetAppendCoincident3D(theFlag);
1056 }
1057
1058 bool SMESH_DeviceActor::IsCoincident3DAllowed() const {
1059   return myGeomFilter->GetAppendCoincident3D();
1060 }