Salome HOME
Fix for Bug IPAL8945
[modules/visu.git] / src / OBJECT / VISU_Actor.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : 
25 //  Author : 
26 //  Module : VISU
27 //  $Header$
28
29 #include "VISU_Actor.h"
30 #include "VISU_PipeLine.hxx"
31 #include "VTKViewer_ShrinkFilter.h"
32 #include "VTKViewer_GeometryFilter.h"
33 #include "VTKViewer_PassThroughFilter.h"
34  
35 #include <stdexcept>
36 #include <sstream>
37
38 // VTK Includes
39 #include <vtkProperty.h>
40 #include <vtkSmartPointer.h>
41 #include <vtkTextMapper.h>
42 #include <vtkTextActor.h>
43 #include <vtkProperty2D.h>
44 #include <vtkRenderer.h>
45 #include <vtkCellPicker.h>
46 #include <vtkCell.h>
47 #include <vtkPointPicker.h>
48 #include <vtkPoints.h>
49 #include <vtkInteractorStyle.h>
50 #include <vtkDataSet.h>
51 #include <vtkPolyData.h>
52 #include <vtkUnstructuredGrid.h>
53
54 #include <vtkShrinkFilter.h>
55 #include <vtkShrinkPolyData.h>
56
57 #include <vtkDataSetMapper.h>
58 #include <vtkGeometryFilter.h>
59 #include <vtkObjectFactory.h>
60
61 #include <boost/bind.hpp>
62
63 #include "utilities.h"
64
65 using namespace std;
66
67 static int MYVTKDEBUG = 0;
68
69 #ifdef _DEBUG_
70 static int MYDEBUG = 1;
71 #else
72 static int MYDEBUG = 0;
73 #endif
74
75 //#define ENABLE_ANNOTATION
76
77 //----------------------------------------------------------------------------
78 vtkStandardNewMacro(VISU_Actor);
79
80 //----------------------------------------------------------------------------
81 VISU_Actor
82 ::VISU_Actor():
83   myIsVTKMapping(false),
84   myPrs3d(NULL),
85   myActorFactory(NULL),
86   myMapper(vtkDataSetMapper::New()),
87   myIsShrunk(false),
88   myIsShrinkable(false),
89   myShrinkFilter(VTKViewer_ShrinkFilter::New()),
90   myAnnotationMapper(vtkTextMapper::New()),
91   myAnnotationActor(vtkTextActor::New())
92 {
93   if(MYDEBUG) MESSAGE("VISU_Actor::VISU_Actor - this = "<<this);
94
95   myMapper->Delete();
96   myShrinkFilter->Delete();
97
98   myStoreMapping = true;
99
100   myShrinkFilter->SetStoreMapping(true);
101
102   myAnnotationMapper->Delete();
103   myAnnotationActor->SetMapper(myAnnotationMapper.GetPointer());
104
105   myAnnotationActor->Delete();
106   myAnnotationActor->SetVisibility(0);
107 }
108
109 //----------------------------------------------------------------------------
110 void
111 VISU_Actor
112 ::ShallowCopy(vtkProp *prop)
113 {
114   VISU_Actor *anActor = VISU_Actor::SafeDownCast(prop);
115   if(anActor != NULL){
116     setName(anActor->getName());
117     if(anActor->hasIO()) setIO(anActor->getIO());
118   }
119   Superclass::ShallowCopy(prop);
120 }
121
122 void
123 VISU_Actor
124 ::ShallowCopyPL(VISU_PipeLine* thePipeLine)
125 {
126   myPipeLine->ShallowCopy(thePipeLine);
127
128   vtkDataSet* aDatsSet = myMapper->GetInput();
129   GetMapper()->ShallowCopy(thePipeLine->GetMapper());
130
131   // To restore mapper input from pipeline
132   myMapper->SetInput(aDatsSet);
133 }
134
135 //----------------------------------------------------------------------------
136 VISU_Actor
137 ::~VISU_Actor()
138 {
139   if(MYDEBUG) MESSAGE("~VISU_Actor() - this = "<<this);
140   Superclass::SetProperty(NULL);
141   SetDebug(MYVTKDEBUG);
142 }
143
144 //----------------------------------------------------------------------------
145 void 
146 VISU_Actor
147 ::setIO(const Handle(SALOME_InteractiveObject)& theIO)
148 {
149   Superclass::setIO(theIO); 
150   myName = theIO->getName(); 
151 }
152
153 //----------------------------------------------------------------------------
154 void 
155 VISU_Actor
156 ::SetPrs3d(VISU::Prs3d_i* thePrs3d)
157
158   myPrs3d = thePrs3d;
159 }
160
161 VISU::Prs3d_i* 
162 VISU_Actor
163 ::GetPrs3d()
164
165   return myPrs3d;
166 }
167
168 //----------------------------------------------------------------------------
169 VISU::TActorFactory* 
170 VISU_Actor
171 ::GetFactory()
172
173   return myActorFactory;
174 }
175
176 void
177 VISU_Actor
178 ::SetFactory(VISU::TActorFactory* theActorFactory)
179
180   using namespace VISU;
181
182   if(myActorFactory == theActorFactory)
183     return;
184   
185   if(theActorFactory)
186     myDestroySignal.connect(boost::bind(&TActorFactory::RemoveActor,
187                                         theActorFactory,
188                                         _1));
189
190   myActorFactory = theActorFactory;
191 }
192
193 //----------------------------------------------------------------------------
194 void
195 VISU_Actor
196 ::UpdateFromFactory()
197 {
198   myActorFactory->UpdateActor(this);
199   Update();
200 }
201
202 void
203 VISU_Actor
204 ::RemoveFromRender()
205 {
206   RemoveFromRender(GetRenderer());
207 }
208
209 //----------------------------------------------------------------------------
210 void
211 VISU_Actor
212 ::SetMapperInput(vtkDataSet* theDataSet) 
213 {
214   myMapper->SetInput(theDataSet);
215   SetMapper(myMapper.GetPointer());
216 }
217
218 void
219 VISU_Actor
220 ::SetPipeLine(VISU_PipeLine* thePipeLine) 
221 {
222   myPipeLine = thePipeLine;
223   if(thePipeLine){
224     if(vtkMapper *aMapper = myPipeLine->GetMapper()){
225       if(vtkDataSet *aDataSet = aMapper->GetInput()){
226         SetShrinkable(thePipeLine->IsShrinkable());
227
228         SetMapperInput(aDataSet);
229       }
230     }
231   }
232   this->Modified();
233 }
234
235 VISU_PipeLine* 
236 VISU_Actor
237 ::GetPipeLine() 
238
239   return myPipeLine.GetPointer();
240 }
241
242 VISU_PipeLine* 
243 VISU_Actor
244 ::GetCurrentPL() 
245
246   return GetPipeLine();
247 }
248
249
250 //----------------------------------------------------------------------------
251 void
252 VISU_Actor
253 ::SetRepresentation(int theMode) 
254
255   Superclass::SetRepresentation(theMode);
256   if(myRepresentation == VTK_POINTS)
257     UnShrink();
258 }
259
260
261 //----------------------------------------------------------------------------
262 void
263 VISU_Actor
264 ::SetShrink()
265 {
266   if(!myIsShrinkable) 
267     return;
268   if(vtkDataSet* aDataSet = myPassFilter[0]->GetOutput()){
269     myShrinkFilter->SetInput(aDataSet);
270     myPassFilter[1]->SetInput(myShrinkFilter->GetOutput());
271     myIsShrunk = true;
272   }
273 }
274
275 void
276 VISU_Actor
277 ::UnShrink()
278 {
279   if(!myIsShrunk) 
280     return;
281   if(vtkDataSet* aDataSet = myPassFilter[0]->GetOutput()){
282     myPassFilter[1]->SetInput(aDataSet);
283     myPassFilter[1]->Modified();
284     myIsShrunk = false;
285     Modified();
286   }
287 }
288
289 bool
290 VISU_Actor
291 ::IsShrunk()
292 {
293   return myIsShrunk;
294 }
295
296 void
297 VISU_Actor
298 ::SetShrinkable(bool theIsShrinkable)
299 {
300   myIsShrinkable = theIsShrinkable;
301 }
302
303 bool
304 VISU_Actor
305 ::IsShrunkable() 
306
307   return myIsShrinkable;
308 }
309
310 void
311 VISU_Actor
312 ::SetShrinkFactor(float theValue)
313 {
314   myShrinkFilter->SetShrinkFactor(theValue);
315   Modified();
316 }
317
318 float
319 VISU_Actor
320 ::GetShrinkFactor()
321 {
322   return myShrinkFilter->GetShrinkFactor();
323 }
324
325
326 //----------------------------------------------------------------------------
327 void
328 VISU_Actor
329 ::SetOpacity(float theValue)
330 {
331   GetProperty()->SetOpacity(theValue);
332 }
333
334 float
335 VISU_Actor
336 ::GetOpacity()
337
338   return GetProperty()->GetOpacity();
339 }
340
341 void
342 VISU_Actor
343 ::SetLineWidth(float theLineWidth)
344 {
345   GetProperty()->SetLineWidth(theLineWidth);
346 }
347
348 float
349 VISU_Actor
350 ::GetLineWidth()
351 {
352   return GetProperty()->GetLineWidth();
353 }
354
355 //==================================================================
356 // function: AddToRender
357 // purpose :
358 //==================================================================
359 void
360 VISU_Actor
361 ::AddToRender(vtkRenderer* theRenderer)
362 {
363   Superclass::AddToRender(theRenderer);
364   theRenderer->AddActor(myAnnotationActor.GetPointer());
365 }
366
367 //==================================================================
368 // function: RemoveFromRender
369 // purpose :
370 //==================================================================
371 void
372 VISU_Actor
373 ::RemoveFromRender(vtkRenderer* theRenderer)
374 {
375   theRenderer->RemoveActor(myAnnotationActor.GetPointer());
376   Superclass::RemoveFromRender(theRenderer); 
377   myDestroySignal(this);
378 }
379
380 //----------------------------------------------------------------------------
381 void 
382 VISU_Actor
383 ::SetVTKMapping(bool theIsVTKMapping)
384 {
385   myIsVTKMapping = theIsVTKMapping;
386 }
387
388 bool 
389 VISU_Actor
390 ::IsVTKMapping() const
391 {
392   return myIsVTKMapping;
393 }
394
395 //----------------------------------------------------------------------------
396 vtkDataSet* 
397 VISU_Actor
398 ::GetInput()
399 {
400   if(myIsVTKMapping)
401     return Superclass::GetInput();
402
403   return GetCurrentPL()->GetOutput();
404 }
405
406 //----------------------------------------------------------------------------
407 vtkIdType
408 VISU_Actor
409 ::GetNodeObjId(vtkIdType theID)
410 {
411   if(myIsVTKMapping)
412     return Superclass::GetNodeObjId(theID);
413
414   vtkIdType anID = myGeomFilter->GetNodeObjId(theID);
415
416   if(myIsShrunk)
417    anID = myShrinkFilter->GetNodeObjId(anID);
418
419   return GetCurrentPL()->GetNodeObjID(anID);
420 }
421
422 vtkIdType
423 VISU_Actor
424 ::GetNodeVTKID(vtkIdType theID)
425 {
426   if(myIsVTKMapping)
427     return theID;
428
429   return GetCurrentPL()->GetNodeVTKID(theID);
430 }
431
432 float*
433 VISU_Actor
434 ::GetNodeCoord(int theObjID)
435 {
436   if(myIsVTKMapping)
437     return Superclass::GetNodeCoord(theObjID);
438
439   return GetCurrentPL()->GetNodeCoord(theObjID);
440 }
441
442
443 //----------------------------------------------------------------------------
444 vtkIdType
445 VISU_Actor
446 ::GetElemObjId(vtkIdType theID)
447 {
448   if(myIsVTKMapping)
449     return Superclass::GetElemObjId(theID);
450
451   vtkIdType anID = myGeomFilter->GetElemObjId(theID);
452
453   if(myIsShrunk)
454    anID = myShrinkFilter->GetElemObjId(anID);
455
456   return GetCurrentPL()->GetElemObjID(anID);
457 }
458
459 vtkIdType
460 VISU_Actor
461 ::GetElemVTKID(vtkIdType theID)
462 {
463   if(myIsVTKMapping)
464     return theID;
465
466   return GetCurrentPL()->GetElemVTKID(theID);
467 }
468
469 vtkCell* 
470 VISU_Actor
471 ::GetElemCell(vtkIdType theObjID)
472 {
473   if(myIsVTKMapping)
474     return Superclass::GetElemCell(theObjID);
475
476   return GetCurrentPL()->GetElemCell(theObjID);
477 }
478
479
480 //----------------------------------------------------------------------------
481 bool
482 VISU_Actor
483 ::PreHighlight(vtkInteractorStyle* theInteractorStyle, 
484                SVTK_SelectionEvent* theSelectionEvent,
485                bool theIsHighlight)
486 {
487   bool aRet = Superclass::PreHighlight(theInteractorStyle,
488                                        theSelectionEvent,
489                                        theIsHighlight);
490 #ifndef ENABLE_ANNOTATION
491   return aRet;
492 #endif    
493   //
494   myAnnotationActor->SetVisibility(0);
495   if(theIsHighlight){
496     switch(mySelectionMode){
497     case CellSelection:{ 
498       vtkRenderer* aRenderer = theInteractorStyle->GetCurrentRenderer();
499       myCellPicker->Pick(theSelectionEvent->myX, 
500                          theSelectionEvent->myY, 
501                          0.0, 
502                          aRenderer);
503
504       if(myCellPicker->GetActor() != this)
505         return false;
506       
507       vtkIdType aVTKId = myCellPicker->GetCellId();
508       if(aVTKId >= 0  && mySelector->IsValid(this,aVTKId,true) && hasIO()){
509         vtkIdType anObjId = GetElemObjId(aVTKId);
510         if(vtkCell* aCell = GetElemCell(anObjId)){
511           vtkPoints* aPts = aCell->GetPoints();
512           if(int aNbPts = aCell->GetNumberOfPoints()){
513             float aCoord[3] = {0.0, 0.0, 0.0};
514             for(int i = 0; i < aNbPts; i++){
515               float *aPntCoord = aPts->GetPoint(i); 
516               aCoord[0] += aPntCoord[0];
517               aCoord[1] += aPntCoord[1];
518               aCoord[2] += aPntCoord[2];
519             }
520             // Display coordinates
521             float aWorldCoord[4] = {aCoord[0]/aNbPts, aCoord[1]/aNbPts, aCoord[2]/aNbPts, 1.0};
522             aRenderer->SetWorldPoint(aWorldCoord);
523             aRenderer->WorldToDisplay();
524             float aSelectionPoint[3];
525             aRenderer->GetDisplayPoint(aSelectionPoint);
526             myAnnotationActor->SetPosition(aSelectionPoint);
527             //
528             // To prepare the annotation text
529             std::ostringstream aStr;
530             aStr<<"Cell ID: "<< anObjId;
531             std::string aString = aStr.str();
532             myAnnotationMapper->SetInput(aString.c_str());
533             
534             myAnnotationActor->SetVisibility(1);
535             return true;
536           }
537         }
538       }
539       break;
540     }
541     case NodeSelection:{ 
542       vtkRenderer* aRenderer = theInteractorStyle->GetCurrentRenderer();
543       myPointPicker->Pick(theSelectionEvent->myX, 
544                           theSelectionEvent->myY, 
545                           0.0, 
546                           aRenderer);
547       
548       if(myPointPicker->GetActor() != this)
549         return false;
550
551       vtkIdType aVtkId = myPointPicker->GetPointId();
552       if(aVtkId >= 0  && mySelector->IsValid(this,aVtkId,true) && hasIO()){
553         vtkIdType anObjId = GetNodeObjId( aVtkId );
554         if(float* aCoord = GetNodeCoord(anObjId)){
555           // Display coordinates
556           float aWorldCoord[4] = {aCoord[0], aCoord[1], aCoord[2], 1.0};
557           aRenderer->SetWorldPoint(aWorldCoord);
558           aRenderer->WorldToDisplay();
559           float aSelectionPoint[3];
560           aRenderer->GetDisplayPoint(aSelectionPoint);
561           myAnnotationActor->SetPosition(aSelectionPoint);
562           //
563           // To prepare the annotation text
564           std::ostringstream aStr;
565           aStr<<"Node ID: "<< anObjId;
566           std::string aString = aStr.str();
567           myAnnotationMapper->SetInput(aString.c_str());
568           
569           myAnnotationActor->SetVisibility(1);
570           return true;
571         }
572       }
573       break;
574     }
575     case EdgeOfCellSelection:
576       break;
577     default:
578       break;
579     }
580   }
581
582   return aRet;
583 }