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