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