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