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