1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "VTKViewer_RenderWindowInteractor.h"
23 #include "VTKViewer_RenderWindow.h"
24 #include "VTKViewer_InteractorStyle.h"
25 #include "SUIT_ViewModel.h"
26 #include "VTKViewer_ViewWindow.h"
28 //#include "SUIT_Application.h"
29 //#include "SUIT_Desktop.h"
31 //#include "SALOME_Selection.h"
32 #include "VTKViewer_Actor.h"
33 #include "VTKViewer_Algorithm.h"
34 #include "VTKViewer_Functor.h"
42 #include <vtkAssemblyNode.h>
44 #include <vtkInteractorStyle.h>
45 #include <vtkObjectFactory.h>
46 #include <vtkPicker.h>
47 #include <vtkCellPicker.h>
48 #include <vtkPointPicker.h>
49 #include <vtkUnstructuredGrid.h>
50 #include <vtkPolyDataMapper.h>
51 #include <vtkSphereSource.h>
52 #include <vtkDataSet.h>
53 #include <vtkMaskPoints.h>
54 #include <vtkVertex.h>
55 #include <vtkRendererCollection.h>
56 #include <vtkPolyDataWriter.h>
57 #include <vtkProperty.h>
61 #include <QMouseEvent>
63 #include <QContextMenuEvent>
65 /*! Create new instance of VTKViewer_RenderWindowInteractor*/
66 VTKViewer_RenderWindowInteractor* VTKViewer_RenderWindowInteractor::New()
68 vtkObject *ret = vtkObjectFactory::CreateInstance("VTKViewer_RenderWindowInteractor") ;
70 return dynamic_cast<VTKViewer_RenderWindowInteractor *>(ret) ;
72 return new VTKViewer_RenderWindowInteractor;
76 VTKViewer_RenderWindowInteractor::VTKViewer_RenderWindowInteractor()
79 this->mTimer = new QTimer( this ) ;
82 myBasicPicker = vtkPicker::New();
83 myCellPicker = vtkCellPicker::New();
84 myPointPicker = vtkPointPicker::New();
86 myCellActor = VTKViewer_Actor::New();
87 myCellActor->PickableOff();
88 myCellActor->GetProperty()->SetColor(1,1,0);
89 myCellActor->GetProperty()->SetLineWidth(5);
90 myCellActor->GetProperty()->SetRepresentationToSurface();
92 myEdgeActor = VTKViewer_Actor::New();
93 myEdgeActor->PickableOff();
94 myEdgeActor->GetProperty()->SetColor(1,0,0);
95 myEdgeActor->GetProperty()->SetLineWidth(5);
96 myEdgeActor->GetProperty()->SetRepresentationToWireframe();
98 myPointActor = VTKViewer_Actor::New();
99 myPointActor->PickableOff();
100 myPointActor->GetProperty()->SetColor(1,1,0);
101 myPointActor->GetProperty()->SetPointSize(5);
102 myPointActor->GetProperty()->SetRepresentationToPoints();
104 connect(mTimer, SIGNAL(timeout()), this, SLOT(TimerFunc())) ;
108 VTKViewer_RenderWindowInteractor::~VTKViewer_RenderWindowInteractor()
112 if ( GetRenderWindow() ) {
113 myViewWnd->RemoveActor(myCellActor);
114 myViewWnd->RemoveActor(myEdgeActor);
115 myViewWnd->RemoveActor(myPointActor);
118 myCellActor->Delete();
119 myEdgeActor->Delete();
120 myPointActor->Delete();
122 myBasicPicker->Delete();
123 myCellPicker->Delete();
124 myPointPicker->Delete();
128 Print interactor to stream
132 void VTKViewer_RenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
134 vtkRenderWindowInteractor::PrintSelf(os, indent) ;
136 // :NOTE: Fri Apr 21 21:51:05 2000 Pagey
137 // QGL specific stuff goes here. One should add output
138 // lines here if any protected members are added to
144 * Initializes the event handlers without an XtAppContext. This is \n
145 * good for when you don`t have a user interface, but you still \n
146 * want to have mouse interaction.\n
147 * We never allow the VTKViewer_RenderWindowInteractor to control \n
148 * the event loop. The application always has the control.
150 void VTKViewer_RenderWindowInteractor::Initialize()
153 // We cannot do much unless there is a render window
154 // associated with this interactor.
156 if( ! RenderWindow ) {
157 vtkErrorMacro(<< "VTKViewer_RenderWindowInteractor::Initialize(): No render window attached!") ;
162 // We cannot hand a render window which is not a VTKViewer_RenderWindow.
163 // One way to force this is to use dynamic_cast and hope that
164 // it works. If the dynamic_cast does not work, we flag an error
165 // and get the hell out.
167 vtkRenderWindow *my_render_win = dynamic_cast<vtkRenderWindow *>(RenderWindow) ;
168 if( !my_render_win ) {
169 vtkErrorMacro(<< "VTKViewer_RenderWindowInteractor::Initialize() can only handle VTKViewer_RenderWindow.") ;
174 // If the render window has zero size, then set it to a default
177 int* aSize = my_render_win->GetSize();
178 this->Size[0] = ((aSize[0] > 0) ? aSize[0] : 300);
179 this->Size[1] = ((aSize[1] > 0) ? aSize[1] : 300);
181 this->SetPicker(myBasicPicker);
183 SetSelectionTolerance();
186 // Enable the interactor.
191 // Start the rendering of the window.
193 my_render_win->Start() ;
196 // The interactor has been initialized.
198 this->Initialized = 1 ;
203 /*!Sets view window and add to it selection actors.*/
204 void VTKViewer_RenderWindowInteractor::setViewWindow(VTKViewer_ViewWindow* theViewWnd){
205 myViewWnd = theViewWnd;
208 myViewWnd->InsertActor(myCellActor);
209 myViewWnd->InsertActor(myEdgeActor);
210 myViewWnd->InsertActor(myPointActor);
214 /*!Move selection actors to view window.*/
215 void VTKViewer_RenderWindowInteractor::MoveInternalActors()
217 myViewWnd->MoveActor(myCellActor);
218 myViewWnd->MoveActor(myEdgeActor);
219 myViewWnd->MoveActor(myPointActor);
222 /*!Sets interactor style.*/
223 void VTKViewer_RenderWindowInteractor::SetInteractorStyle(vtkInteractorObserver *theInteractor){
224 myInteractorStyle = dynamic_cast<VTKViewer_InteractorStyle*>(theInteractor);
225 vtkRenderWindowInteractor::SetInteractorStyle(theInteractor);
228 /*!Sets selection properties.
229 *\param theRed - red component of color
230 *\param theGreen - green component of color
231 *\param theBlue - blue component of color
232 *\param theWidth - point size and line width
234 void VTKViewer_RenderWindowInteractor::SetSelectionProp(const double& theRed, const double& theGreen,
235 const double& theBlue, const int& theWidth)
237 myCellActor->GetProperty()->SetColor(theRed, theGreen, theBlue);
238 myCellActor->GetProperty()->SetLineWidth(theWidth);
240 myPointActor->GetProperty()->SetColor(theRed, theGreen, theBlue);
241 myPointActor->GetProperty()->SetPointSize(theWidth);
244 /*!Sets selection tolerance
245 *\param theTolNodes - nodes selection tolerance
246 *\param theTolItems - selection tolerance for basic and cell pickers.
248 void VTKViewer_RenderWindowInteractor::SetSelectionTolerance(const double& theTolNodes, const double& theTolItems)
250 myTolNodes = theTolNodes;
251 myTolItems = theTolItems;
253 myBasicPicker->SetTolerance(myTolItems);
254 myCellPicker->SetTolerance(myTolItems);
255 myPointPicker->SetTolerance(myTolNodes);
260 * Enable/Disable interactions. By default interactors are enabled when \n
261 * initialized. Initialize() must be called prior to enabling/disabling \n
262 * interaction. These methods are used when a window/widget is being \n
263 * shared by multiple renderers and interactors. This allows a "modal" \n
264 * display where one interactor is active when its data is to be displayed \n
265 * and all other interactors associated with the widget are disabled \n
266 * when their data is not displayed.
268 void VTKViewer_RenderWindowInteractor::Enable()
271 // Do not need to do anything if already enabled.
273 if( this->Enabled ) {
282 void VTKViewer_RenderWindowInteractor::Disable()
284 if( ! this->Enabled ) {
293 * This will start up the X event loop and never return. If you \n
294 * call this method it will loop processing X events until the \n
295 * application is exited.
297 void VTKViewer_RenderWindowInteractor::Start()
300 // We do not allow this interactor to control the
301 // event loop. Only the QtApplication objects are
302 // allowed to do that.
304 vtkErrorMacro(<<"VTKViewer_RenderWindowInteractor::Start() not allowed to start event loop.") ;
308 * Event loop notification member for Window size change
310 void VTKViewer_RenderWindowInteractor::UpdateSize(int w, int h)
312 // if the size changed send this on to the RenderWindow
313 if ((w != this->Size[0])||(h != this->Size[1])) {
316 this->RenderWindow->SetSize(w,h);
321 * Timer methods must be overridden by platform dependent subclasses.
322 * flag is passed to indicate if this is first timer set or an update
323 * as Win32 uses repeating timers, whereas X uses One shot more timer
324 * if flag == VTKXI_TIMER_FIRST Win32 and X should createtimer
325 * otherwise Win32 should exit and X should perform AddTimeOut
328 int VTKViewer_RenderWindowInteractor::CreateTimer(int vtkNotUsed(timertype))
331 /// Start a one-shot timer for 10ms.
333 mTimer->setSingleShot(TRUE) ;
339 \sa CreateTimer(int )
342 int VTKViewer_RenderWindowInteractor::DestroyTimer(void)
345 // :TRICKY: Tue May 2 00:17:32 2000 Pagey
347 /*! QTimer will automatically expire after 10ms. So
348 * we do not need to do anything here. In fact, we
349 * should not even Stop() the QTimer here because doing
350 * this will skip some of the processing that the TimerFunc()
351 * does and will result in undesirable effects. For
352 * example, this will result in vtkLODActor to leave
353 * the models in low-res mode after the mouse stops
359 /*! Not all of these slots are needed in VTK_MAJOR_VERSION=3,\n
360 * but moc does not understand "#if VTK_MAJOR_VERSION". Hence, \n
361 * we have to include all of these for the time being. Once,\n
362 * this bug in MOC is fixed, we can separate these.
364 void VTKViewer_RenderWindowInteractor::TimerFunc()
366 if( ! this->Enabled ) {
370 ((vtkInteractorStyle*)this->InteractorStyle)->OnTimer() ;
371 emit RenderWindowModified() ;
374 /*!Emit render window modified on mouse move,\n
375 *if interactor style needs redrawing and render window enabled.*/
376 void VTKViewer_RenderWindowInteractor::MouseMove(QMouseEvent *event) {
377 if( ! this->Enabled ) {
380 myInteractorStyle->OnMouseMove(0, 0, event->x(), event->y()/*this->Size[1] - event->y() - 1*/) ;
381 if (myInteractorStyle->needsRedrawing() )
382 emit RenderWindowModified() ;
385 /*!Reaction on left button pressed.\n
386 *Same as left button down for interactor style.\n
387 *If render window enabled.
389 void VTKViewer_RenderWindowInteractor::LeftButtonPressed(const QMouseEvent *event) {
390 if( ! this->Enabled ) {
393 myInteractorStyle->OnLeftButtonDown((event->modifiers() & Qt::ControlModifier),
394 (event->modifiers() & Qt::ShiftModifier),
395 event->x(), event->y());
398 /*!Reaction on left button releases.\n
399 *Same as left button up for interactor style.\n
400 *If render window enabled.
402 void VTKViewer_RenderWindowInteractor::LeftButtonReleased(const QMouseEvent *event) {
403 if( ! this->Enabled ) {
406 myInteractorStyle->OnLeftButtonUp( (event->modifiers() & Qt::ControlModifier),
407 (event->modifiers() & Qt::ShiftModifier),
408 event->x(), event->y() ) ;
411 /*!Reaction on middle button pressed.\n
412 *Same as middle button down for interactor style.\n
413 *If render window enabled.
415 void VTKViewer_RenderWindowInteractor::MiddleButtonPressed(const QMouseEvent *event) {
416 if( ! this->Enabled ) {
419 myInteractorStyle->OnMiddleButtonDown((event->modifiers() & Qt::ControlModifier),
420 (event->modifiers() & Qt::ShiftModifier),
421 event->x(), event->y() ) ;
424 /*!Reaction on middle button released.\n
425 *Same as middle button up for interactor style.\n
426 *If render window enabled.
428 void VTKViewer_RenderWindowInteractor::MiddleButtonReleased(const QMouseEvent *event) {
429 if( ! this->Enabled ) {
432 myInteractorStyle->OnMiddleButtonUp( (event->modifiers() & Qt::ControlModifier),
433 (event->modifiers() & Qt::ShiftModifier),
434 event->x(), event->y() ) ;
437 /*!Reaction on right button pressed.\n
438 *Same as right button down for interactor style.\n
439 *If render window enabled.
441 void VTKViewer_RenderWindowInteractor::RightButtonPressed(const QMouseEvent *event) {
442 if( ! this->Enabled ) {
445 myInteractorStyle->OnRightButtonDown( (event->modifiers() & Qt::ControlModifier),
446 (event->modifiers() & Qt::ShiftModifier),
447 event->x(), event->y() ) ;
450 /*!Reaction on right button released.\n
451 *Same as right button up for interactor style.If render window enabled.\n
452 *Emit context menu requested, if interactor style state equal VTK_INTERACTOR_STYLE_CAMERA_NONE.
454 void VTKViewer_RenderWindowInteractor::RightButtonReleased(const QMouseEvent *event) {
455 if( ! this->Enabled ) {
458 bool isOperation = myInteractorStyle->CurrentState() != VTK_INTERACTOR_STYLE_CAMERA_NONE;
459 myInteractorStyle->OnRightButtonUp( (event->modifiers() & Qt::ControlModifier),
460 (event->modifiers() & Qt::ShiftModifier),
461 event->x(), event->y() );
464 QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
465 event->pos(), event->globalPos() );
466 emit contextMenuRequested( &aEvent );
470 /*!Reaction on button pressed.
471 *\warning Do nothing.
473 void VTKViewer_RenderWindowInteractor::ButtonPressed(const QMouseEvent *event) {
477 /*!Reaction on button released..
478 *\warning Do nothing.
480 void VTKViewer_RenderWindowInteractor::ButtonReleased(const QMouseEvent *event) {
484 /*!Gets display mode.*/
485 int VTKViewer_RenderWindowInteractor::GetDisplayMode() {
486 return myDisplayMode;
489 /*!Sets display mode.*/
490 void VTKViewer_RenderWindowInteractor::SetDisplayMode(int theMode) {
492 ChangeRepresentationToWireframe();
494 ChangeRepresentationToSurface();
495 myDisplayMode = theMode;
498 /*!Change all actors to wireframe*/
499 void VTKViewer_RenderWindowInteractor::ChangeRepresentationToWireframe()
501 ChangeRepresentationToWireframe(GetRenderer()->GetActors());
504 /*!Change all actors to surface*/
505 void VTKViewer_RenderWindowInteractor::ChangeRepresentationToSurface()
507 ChangeRepresentationToSurface(GetRenderer()->GetActors());
510 /*!Change all actors from \a theCollection to wireframe and
511 * emit render window modified.
513 void VTKViewer_RenderWindowInteractor::ChangeRepresentationToWireframe(vtkActorCollection* theCollection)
516 ForEach<VTKViewer_Actor>(theCollection,
517 TSetFunction<VTKViewer_Actor,int>
518 (&VTKViewer_Actor::setDisplayMode,0));
519 emit RenderWindowModified();
522 /*!Change all actors from \a theCollection to surface and
523 * emit render window modified.
525 void VTKViewer_RenderWindowInteractor::ChangeRepresentationToSurface(vtkActorCollection* theCollection)
528 ForEach<VTKViewer_Actor>(theCollection,
529 TSetFunction<VTKViewer_Actor,int>
530 (&VTKViewer_Actor::setDisplayMode,1));
531 emit RenderWindowModified();
535 vtkRenderer* VTKViewer_RenderWindowInteractor::GetRenderer()
537 vtkRendererCollection * theRenderers = this->RenderWindow->GetRenderers();
538 theRenderers->InitTraversal();
539 return theRenderers->GetNextItem();
543 void VTKViewer_RenderWindowInteractor::EraseAll()
547 /*!Display all actors.
548 *Sets visible for all actors from renderer collection and emit render window modified.
550 void VTKViewer_RenderWindowInteractor::DisplayAll()
553 vtkActorCollection* aCollection = GetRenderer()->GetActors();
554 ForEach<VTKViewer_Actor>(aCollection,TSetVisibility<VTKViewer_Actor>(true));
556 emit RenderWindowModified() ;
560 void VTKViewer_RenderWindowInteractor::Erase( VTKViewer_Actor* SActor, bool update)
564 /*!Remove \a SActor from renderer and emit update window, if \a updateViewer - true*/
565 void VTKViewer_RenderWindowInteractor::Remove( VTKViewer_Actor* SActor, bool updateViewer )
569 GetRenderer()->RemoveProp( SActor );
571 emit RenderWindowModified();
575 /*!Remove actors from render window collection(not implemented).
576 *Emit render window modified, if \a updateViewer - true.
578 void VTKViewer_RenderWindowInteractor::RemoveAll( const bool updateViewer )
580 vtkRenderer* aRenderer = GetRenderer();
581 vtkActorCollection* anActors = aRenderer->GetActors();
584 anActors->InitTraversal();
585 while ( vtkActor *anAct = anActors->GetNextActor() )
587 if ( anAct->IsA( "VTKViewer_Actor" ) )
593 emit RenderWindowModified();
597 /*!\brief Display the \a theActor.*/
598 /*! Add actor to renderer and set visibility to true.
599 * Emit render window modified, if \a update - true.
601 void VTKViewer_RenderWindowInteractor::Display( VTKViewer_Actor* theActor, bool update)
603 GetRenderer()->AddActor(theActor);
604 theActor->SetVisibility(true);
607 emit RenderWindowModified();
611 default key press event (empty implementation)
613 void VTKViewer_RenderWindowInteractor::KeyPressed(QKeyEvent *event)
618 /*!Structure with one function "operator()", which call apply properties for actor.*/
619 struct TUpdateAction{
620 /*!Apply properties for \a theActor.*/
621 void operator()(vtkActor* theActor){
622 theActor->ApplyProperties();
626 /*!Update all actors from renderer and emit render window modified.*/
627 void VTKViewer_RenderWindowInteractor::Update() {
629 vtkRenderer* aRen = GetRenderer();
630 ForEach<vtkActor>(aRen->GetActors(),TUpdateAction());
634 emit RenderWindowModified();
637 /*!Unhighlight all selection actors.*/
638 void VTKViewer_RenderWindowInteractor::unHighlightSubSelection(){
639 myPointActor->SetVisibility(false);
640 myEdgeActor->SetVisibility(false);
641 myCellActor->SetVisibility(false);
644 /*!@see unHighlightSubSelection()
645 * Also emit render window modified.
647 bool VTKViewer_RenderWindowInteractor::unHighlightAll(){
648 unHighlightSubSelection();
650 emit RenderWindowModified() ;
655 /*! \li Sets actors data and sets visibility to true, if flag \a hilight - true,
656 * else sets visibility to false.
657 * \li Emit render window modified, if flag \a update - true.
659 bool VTKViewer_RenderWindowInteractor::highlight(const TColStd_IndexedMapOfInteger& theMapIndex,
660 VTKViewer_Actor* theMapActor, VTKViewer_Actor* theActor,
661 TUpdateActor theFun, bool hilight, bool update)
663 if(theMapIndex.Extent() == 0) return false;
666 setActorData(theMapIndex,theMapActor,theActor,theFun);
667 theActor->SetVisibility(true);
670 theActor->SetVisibility(false);
674 this->RenderWindow->Render();
675 emit RenderWindowModified() ;
681 /*!Sets actors data.*/
682 void VTKViewer_RenderWindowInteractor::setActorData(const TColStd_IndexedMapOfInteger& theMapIndex,
683 VTKViewer_Actor * theMapActor,
684 VTKViewer_Actor * theActor,
687 (*theFun)(theMapIndex,theMapActor,theActor);
688 vtkFloatingPointType aPos[3];
689 theMapActor->GetPosition(aPos);
690 theActor->SetPosition(aPos);