1 // SMESH OBJECT : interactive object for SMESH visualization
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SMESH_Actor.cxx
25 // Author : Nicolas REJNERI
30 #include "SMESH_DeviceActor.h"
31 #include "SMESH_ExtractGeometry.h"
32 #include "SMESH_ControlsDef.hxx"
34 #include "SALOME_Transform.h"
35 #include "SALOME_TransformFilter.h"
36 #include "SALOME_PassThroughFilter.h"
37 #include "SALOME_ExtractUnstructuredGrid.h"
40 #include <vtkObjectFactory.h>
41 #include <vtkShrinkFilter.h>
42 #include <vtkShrinkPolyData.h>
44 #include <vtkProperty.h>
45 #include <vtkPolyData.h>
46 #include <vtkMergeFilter.h>
47 #include <vtkPolyDataMapper.h>
48 #include <vtkUnstructuredGrid.h>
50 #include <vtkScalarBarActor.h>
51 #include <vtkLookupTable.h>
52 #include <vtkDoubleArray.h>
53 #include <vtkCellData.h>
56 #include <vtkIdList.h>
57 #include <vtkIntArray.h>
58 #include <vtkCellArray.h>
59 #include <vtkUnsignedCharArray.h>
61 #include <vtkImplicitBoolean.h>
63 #include "utilities.h"
66 static int MYDEBUG = 0;
68 static int MYDEBUG = 0;
74 vtkStandardNewMacro(SMESH_DeviceActor);
77 SMESH_DeviceActor::SMESH_DeviceActor(){
78 if(MYDEBUG) MESSAGE("SMESH_DeviceActor");
80 myIsShrinkable = false;
81 myRepresentation = eSurface;
83 myProperty = vtkProperty::New();
84 myMapper = vtkPolyDataMapper::New();
86 vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(myPolygonOffsetFactor,
87 myPolygonOffsetUnits);
89 myMapper->UseLookupTableScalarRangeOn();
90 myMapper->SetColorModeToMapScalars();
92 myShrinkFilter = vtkShrinkFilter::New();
94 myExtractGeometry = SMESH_ExtractGeometry::New();
95 myExtractGeometry->SetStoreMapping(true);
97 myExtractUnstructuredGrid = SALOME_ExtractUnstructuredGrid::New();
98 myExtractUnstructuredGrid->SetStoreMapping(true);
100 myMergeFilter = vtkMergeFilter::New();
102 myStoreMapping = false;
103 myGeomFilter = SALOME_GeometryFilter::New();
105 myTransformFilter = SALOME_TransformFilter::New();
107 for(int i = 0; i < 6; i++)
108 myPassFilter.push_back(SALOME_PassThroughFilter::New());
112 SMESH_DeviceActor::~SMESH_DeviceActor(){
113 if(MYDEBUG) MESSAGE("~SMESH_DeviceActor");
114 myProperty->Delete();
116 myMapper->RemoveAllInputs();
119 myShrinkFilter->UnRegisterAllOutputs();
120 myShrinkFilter->Delete();
122 myExtractUnstructuredGrid->UnRegisterAllOutputs();
123 myExtractUnstructuredGrid->Delete();
125 myMergeFilter->UnRegisterAllOutputs();
126 myMergeFilter->Delete();
128 myGeomFilter->UnRegisterAllOutputs();
129 myGeomFilter->Delete();
131 myExtractGeometry->UnRegisterAllOutputs();
132 myExtractGeometry->Delete();
134 myTransformFilter->UnRegisterAllOutputs();
135 myTransformFilter->Delete();
137 for(int i = 0, iEnd = myPassFilter.size(); i < iEnd; i++){
138 myPassFilter[i]->UnRegisterAllOutputs();
139 myPassFilter[i]->Delete();
144 void SMESH_DeviceActor::SetStoreMapping(int theStoreMapping){
145 myStoreMapping = theStoreMapping;
150 void SMESH_DeviceActor::Init(TVisualObjPtr theVisualObj,
151 vtkImplicitBoolean* theImplicitBoolean)
153 myVisualObj = theVisualObj;
154 myExtractGeometry->SetImplicitFunction(theImplicitBoolean);
155 SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
159 void SMESH_DeviceActor::SetUnstructuredGrid(vtkUnstructuredGrid* theGrid){
161 //myIsShrinkable = theGrid->GetNumberOfCells() > 10;
162 myIsShrinkable = true;
164 myExtractGeometry->SetInput(theGrid);
166 myExtractUnstructuredGrid->SetInput(myExtractGeometry->GetOutput());
167 myMergeFilter->SetGeometry(myExtractUnstructuredGrid->GetOutput());
169 theGrid = static_cast<vtkUnstructuredGrid*>(myMergeFilter->GetOutput());
172 myPassFilter[ anId ]->SetInput( theGrid );
173 myPassFilter[ anId + 1]->SetInput( myPassFilter[ anId ]->GetOutput() );
176 myGeomFilter->SetStoreMapping( myStoreMapping );
177 myGeomFilter->SetInput( myPassFilter[ anId ]->GetOutput() );
180 myPassFilter[ anId ]->SetInput( myGeomFilter->GetOutput() );
181 myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
184 myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
185 myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
188 myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
189 myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
190 myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
191 myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
194 myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
195 myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
197 vtkLODActor::SetMapper( myMapper );
203 SALOME_ExtractUnstructuredGrid* SMESH_DeviceActor::GetExtractUnstructuredGrid(){
204 return myExtractUnstructuredGrid;
208 vtkUnstructuredGrid* SMESH_DeviceActor::GetUnstructuredGrid(){
209 myExtractUnstructuredGrid->Update();
210 return myExtractUnstructuredGrid->GetOutput();
214 void SMESH_DeviceActor::SetControlMode(SMESH::Controls::FunctorPtr theFunctor,
215 vtkScalarBarActor* theScalarBarActor,
216 vtkLookupTable* theLookupTable)
218 bool anIsInitialized = theFunctor;
220 vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
221 vtkUnstructuredGrid* aGrid = myExtractUnstructuredGrid->GetOutput();
222 aDataSet->ShallowCopy(aGrid);
224 vtkDoubleArray *aScalars = vtkDoubleArray::New();
225 vtkIdType aNbCells = aGrid->GetNumberOfCells();
226 aScalars->SetNumberOfComponents(1);
227 aScalars->SetNumberOfTuples(aNbCells);
229 myVisualObj->UpdateFunctor(theFunctor);
231 using namespace SMESH::Controls;
232 if(NumericalFunctor* aNumericalFunctor = dynamic_cast<NumericalFunctor*>(theFunctor.get())){
233 for(vtkIdType i = 0; i < aNbCells; i++){
234 vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
235 vtkIdType anId2 = myExtractGeometry->GetElemObjId(anId);
236 vtkIdType anObjId = myVisualObj->GetElemObjId(anId2);
237 double aValue = aNumericalFunctor->GetValue(anObjId);
238 aScalars->SetValue(i,aValue);
240 }else if(Predicate* aPredicate = dynamic_cast<Predicate*>(theFunctor.get())){
241 for(vtkIdType i = 0; i < aNbCells; i++){
242 vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i);
243 vtkIdType anId2 = myExtractGeometry->GetElemObjId(anId);
244 vtkIdType anObjId = myVisualObj->GetElemObjId(anId2);
245 bool aValue = aPredicate->IsSatisfy(anObjId);
246 aScalars->SetValue(i,aValue);
250 aDataSet->GetCellData()->SetScalars(aScalars);
253 theLookupTable->SetRange(aScalars->GetRange());
254 theLookupTable->Build();
256 myMergeFilter->SetScalars(aDataSet);
259 GetMapper()->SetScalarVisibility(anIsInitialized);
260 theScalarBarActor->SetVisibility(anIsInitialized);
263 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
264 SMESH_DeviceActor* theDeviceActor,
265 vtkScalarBarActor* theScalarBarActor,
266 vtkLookupTable* theLookupTable)
268 bool anIsInitialized = theFunctor;
270 using namespace SMESH::Controls;
271 if (anIsInitialized){
272 if (Length2D* aLength2D = dynamic_cast<Length2D*>(theFunctor.get())){
273 SMESH::Controls::Length2D::TValues aValues;
275 myVisualObj->UpdateFunctor(theFunctor);
277 aLength2D->GetValues(aValues);
278 vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
279 vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
281 aDataSet->SetPoints(aGrid->GetPoints());
283 vtkIdType aNbCells = aValues.size();
285 vtkDoubleArray *aScalars = vtkDoubleArray::New();
286 aScalars->SetNumberOfComponents(1);
287 aScalars->SetNumberOfTuples(aNbCells);
289 vtkIdType aCellsSize = 3*aNbCells;
290 vtkCellArray* aConnectivity = vtkCellArray::New();
291 aConnectivity->Allocate( aCellsSize, 0 );
293 vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
294 aCellTypesArray->SetNumberOfComponents( 1 );
295 aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
297 vtkIdList *anIdList = vtkIdList::New();
298 anIdList->SetNumberOfIds(2);
300 Length2D::TValues::const_iterator anIter = aValues.begin();
302 for(vtkIdType aVtkId; anIter != aValues.end(); anIter++,i++){
303 const Length2D::Value& aValue = *anIter;
305 myVisualObj->GetNodeVTKId(aValue.myPntId[0]),
306 myVisualObj->GetNodeVTKId(aValue.myPntId[1])
308 if(aNode[0] >= 0 && aNode[1] >= 0){
309 anIdList->SetId( 0, aNode[0] );
310 anIdList->SetId( 1, aNode[1] );
311 aConnectivity->InsertNextCell( anIdList );
312 aCellTypesArray->InsertNextValue( VTK_LINE );
313 aScalars->SetValue(i,aValue.myLength);
317 vtkIntArray* aCellLocationsArray = vtkIntArray::New();
318 aCellLocationsArray->SetNumberOfComponents( 1 );
319 aCellLocationsArray->SetNumberOfTuples( aNbCells );
321 aConnectivity->InitTraversal();
322 for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
323 aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
325 aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
326 SetUnstructuredGrid(aDataSet);
328 aDataSet->GetCellData()->SetScalars(aScalars);
331 theLookupTable->SetRange(aScalars->GetRange());
332 theLookupTable->Build();
334 SetUnstructuredGrid(aDataSet);
336 myMergeFilter->SetScalars(aDataSet);
340 GetMapper()->SetScalarVisibility(anIsInitialized);
341 theScalarBarActor->SetVisibility(anIsInitialized);
344 void SMESH_DeviceActor::SetExtControlMode(SMESH::Controls::FunctorPtr theFunctor,
345 SMESH_DeviceActor* theDeviceActor)
347 myExtractUnstructuredGrid->ClearRegisteredCells();
348 myExtractUnstructuredGrid->ClearRegisteredCellsWithType();
349 myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::ePassAll);
350 myVisualObj->UpdateFunctor(theFunctor);
352 using namespace SMESH::Controls;
353 if(FreeBorders* aFreeBorders = dynamic_cast<FreeBorders*>(theFunctor.get())){
354 myExtractUnstructuredGrid->SetModeOfChanging(SALOME_ExtractUnstructuredGrid::eAdding);
355 myExtractUnstructuredGrid->ClearRegisteredCells();
356 vtkUnstructuredGrid* aGrid = theDeviceActor->GetUnstructuredGrid();
357 vtkIdType aNbCells = aGrid->GetNumberOfCells();
358 for( vtkIdType i = 0; i < aNbCells; i++ ){
359 vtkIdType anObjId = theDeviceActor->GetElemObjId(i);
360 if(aFreeBorders->IsSatisfy(anObjId))
361 myExtractUnstructuredGrid->RegisterCell(i);
363 if(!myExtractUnstructuredGrid->IsCellsRegistered())
364 myExtractUnstructuredGrid->RegisterCell(-1);
365 SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid());
366 }else if(FreeEdges* aFreeEdges = dynamic_cast<FreeEdges*>(theFunctor.get())){
367 SMESH::Controls::FreeEdges::TBorders aBorders;
368 aFreeEdges->GetBoreders(aBorders);
369 vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New();
370 vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid();
371 aDataSet->SetPoints(aGrid->GetPoints());
373 vtkIdType aNbCells = aBorders.size();
374 vtkIdType aCellsSize = 3*aNbCells;
375 vtkCellArray* aConnectivity = vtkCellArray::New();
376 aConnectivity->Allocate( aCellsSize, 0 );
378 vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
379 aCellTypesArray->SetNumberOfComponents( 1 );
380 aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
382 vtkIdList *anIdList = vtkIdList::New();
383 anIdList->SetNumberOfIds(2);
385 FreeEdges::TBorders::const_iterator anIter = aBorders.begin();
386 for(; anIter != aBorders.end(); anIter++){
387 const FreeEdges::Border& aBorder = *anIter;
389 myVisualObj->GetNodeVTKId(aBorder.myPntId[0]),
390 myVisualObj->GetNodeVTKId(aBorder.myPntId[1])
392 //cout<<"aNode = "<<aBorder.myPntId[0]<<"; "<<aBorder.myPntId[1]<<endl;
393 if(aNode[0] >= 0 && aNode[1] >= 0){
394 anIdList->SetId( 0, aNode[0] );
395 anIdList->SetId( 1, aNode[1] );
396 aConnectivity->InsertNextCell( anIdList );
397 aCellTypesArray->InsertNextValue( VTK_LINE );
401 vtkIntArray* aCellLocationsArray = vtkIntArray::New();
402 aCellLocationsArray->SetNumberOfComponents( 1 );
403 aCellLocationsArray->SetNumberOfTuples( aNbCells );
405 aConnectivity->InitTraversal();
406 for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
407 aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
409 aDataSet->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
411 SetUnstructuredGrid(aDataSet);
419 unsigned long int SMESH_DeviceActor::GetMTime(){
420 unsigned long mTime = this->Superclass::GetMTime();
421 mTime = max(mTime,myExtractGeometry->GetMTime());
422 mTime = max(mTime,myExtractUnstructuredGrid->GetMTime());
423 mTime = max(mTime,myMergeFilter->GetMTime());
424 mTime = max(mTime,myGeomFilter->GetMTime());
425 mTime = max(mTime,myTransformFilter->GetMTime());
430 void SMESH_DeviceActor::SetTransform(SALOME_Transform* theTransform){
431 myTransformFilter->SetTransform(theTransform);
435 void SMESH_DeviceActor::SetShrink() {
436 if ( !myIsShrinkable ) return;
437 if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
439 myShrinkFilter->SetInput( aDataSet );
440 myPassFilter[ 1 ]->SetInput( myShrinkFilter->GetOutput() );
445 void SMESH_DeviceActor::UnShrink() {
446 if ( !myIsShrunk ) return;
447 if ( vtkDataSet* aDataSet = myPassFilter[ 0 ]->GetOutput() )
449 myPassFilter[ 1 ]->SetInput( aDataSet );
450 myPassFilter[ 1 ]->Modified();
457 void SMESH_DeviceActor::SetRepresentation(EReperesent theMode){
460 myGeomFilter->SetInside(true);
461 GetProperty()->SetRepresentation(0);
464 myGeomFilter->SetInside(true);
465 GetProperty()->SetRepresentation(1);
468 GetProperty()->SetRepresentation(theMode);
469 myGeomFilter->SetInside(false);
471 myRepresentation = theMode;
472 GetProperty()->Modified();
473 myMapper->Modified();
478 void SMESH_DeviceActor::SetVisibility(int theMode){
479 if(!myExtractUnstructuredGrid->GetInput() || GetUnstructuredGrid()->GetNumberOfCells()){
480 vtkLODActor::SetVisibility(theMode);
482 vtkLODActor::SetVisibility(false);
487 int SMESH_DeviceActor::GetVisibility(){
488 if(!GetUnstructuredGrid()->GetNumberOfCells()){
489 vtkLODActor::SetVisibility(false);
491 return vtkLODActor::GetVisibility();
495 int SMESH_DeviceActor::GetNodeObjId(int theVtkID){
496 vtkIdType anID = myExtractGeometry->GetNodeObjId(theVtkID);
497 vtkIdType aRetID = myVisualObj->GetNodeObjId(anID);
498 if(MYDEBUG) MESSAGE("GetNodeObjId - theVtkID = "<<theVtkID<<"; aRetID = "<<aRetID);
502 float* SMESH_DeviceActor::GetNodeCoord(int theObjID){
503 vtkDataSet* aDataSet = myExtractGeometry->GetInput();
504 vtkIdType anID = myVisualObj->GetNodeVTKId(theObjID);
505 float* aCoord = aDataSet->GetPoint(anID);
506 if(MYDEBUG) MESSAGE("GetNodeCoord - theObjID = "<<theObjID<<"; anID = "<<anID);
511 int SMESH_DeviceActor::GetElemObjId(int theVtkID){
512 vtkIdType anId = myGeomFilter->GetElemObjId(theVtkID);
515 vtkIdType anId2 = myExtractUnstructuredGrid->GetInputId(anId);
518 vtkIdType anId3 = myExtractGeometry->GetElemObjId(anId2);
521 vtkIdType aRetID = myVisualObj->GetElemObjId(anId3);
523 MESSAGE("GetElemObjId - theVtkID = "<<theVtkID<<"; anId2 = "<<anId2<<"; anId3 = "<<anId3<<"; aRetID = "<<aRetID);
527 vtkCell* SMESH_DeviceActor::GetElemCell(int theObjID){
528 vtkDataSet* aDataSet = myExtractGeometry->GetInput();
529 vtkIdType aGridID = myVisualObj->GetElemVTKId(theObjID);
530 vtkCell* aCell = aDataSet->GetCell(aGridID);
532 MESSAGE("GetElemCell - theObjID = "<<theObjID<<"; aGridID = "<<aGridID);
537 float SMESH_DeviceActor::GetShrinkFactor(){
538 return myShrinkFilter->GetShrinkFactor();
541 void SMESH_DeviceActor::SetShrinkFactor(float theValue){
542 theValue = theValue > 0.1? theValue: 0.8;
543 myShrinkFilter->SetShrinkFactor(theValue);
548 void SMESH_DeviceActor::SetHighlited(bool theIsHighlited){
549 myIsHighlited = theIsHighlited;
553 void SMESH_DeviceActor::Render(vtkRenderer *ren, vtkMapper* m){
554 int aResolveCoincidentTopology = vtkMapper::GetResolveCoincidentTopology();
555 float aStoredFactor, aStoredUnit;
556 vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
558 vtkMapper::SetResolveCoincidentTopologyToPolygonOffset();
559 float aFactor = myPolygonOffsetFactor, aUnits = myPolygonOffsetUnits;
561 static float EPS = .01;
564 vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aFactor,aUnits);
565 vtkLODActor::Render(ren,m);
567 vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(aStoredFactor,aStoredUnit);
568 vtkMapper::SetResolveCoincidentTopology(aResolveCoincidentTopology);
572 void SMESH_DeviceActor::SetPolygonOffsetParameters(float factor, float units){
573 myPolygonOffsetFactor = factor;
574 myPolygonOffsetUnits = units;