1 /*# ---------------------------------------------------------------------
3 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
6 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
7 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 # This software is governed by the CeCILL-B license under French law and
10 # abiding by the rules of distribution of free software. You can use,
11 # modify and/ or redistribute the software under the terms of the CeCILL-B
12 # license as circulated by CEA, CNRS and INRIA at the following URL
13 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
14 # or in the file LICENSE.txt.
16 # As a counterpart to the access to the source code and rights to copy,
17 # modify and redistribute granted by the license, users are provided only
18 # with a limited warranty and the software's author, the holder of the
19 # economic rights, and the successive licensors have only limited
22 # The fact that you are presently reading this means that you have had
23 # knowledge of the CeCILL-B license and that you accept its terms.
24 # ------------------------------------------------------------------------ */
26 /*=========================================================================
29 Module: $RCSfile: wxImageViewerWidget.cxx,v $
31 Date: $Date: 2012/11/15 14:15:18 $
32 Version: $Revision: 1.2 $
34 Copyright: (c) 2002, 2003
37 This software is distributed WITHOUT ANY WARRANTY; without even
38 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
39 PURPOSE. See the above copyright notice for more information.
41 =========================================================================*/
43 #include "wxImageViewerWidget.h"
45 #include "vtkRenderer.h"
46 #include "vtkRenderWindowInteractor.h" //extremely important with VC++ don't remove !
47 #include "vtkCommand.h"
48 #include "vtkPolyData.h"
49 #include "vtkCellArray.h"
50 #include "vtkPolyDataMapper.h"
51 #include "vtkInteractorObserver.h"
52 #include "vtkInteractorStyleImage.h"
54 #include <vtkCamera.h>
55 #include <vtkPolyLine.h>
56 #include <vtkDataSetMapper.h>
57 #include <vtkUnstructuredGrid.h>
59 #include <wx/tglbtn.h>
60 //----------------------------------------------------------------------------
61 // Callback for the interaction
62 class marZoomROIObserver : public vtkCommand{
64 virtual char const *GetClassName() const { return "marZoomROIObserver";}
65 static marZoomROIObserver *New(){
66 marZoomROIObserver * result;
67 result = new marZoomROIObserver;
70 // PS -> { return new marZoomROIObserver; }
72 marZoomROIObserver() { this->ImageViewerWdg = NULL; }
73 virtual void Execute(vtkObject *wdg, unsigned long event, void* calldata) {
74 if ( this->ImageViewerWdg ) {
75 this->ImageViewerWdg->ExecuteEvent(wdg, event, calldata);
78 wxImageViewerWidget *ImageViewerWdg;
81 Most of the class was done thanks to this mail, thank you James !!
82 http://public.kitware.com/pipermail/vtkusers/2003-April/017063.html
87 //----------------------------------------------------------------------------
88 //----------------------------------------------------------------------------
89 //----------------------------------------------------------------------------
91 wxVtk2DView_TMP::wxVtk2DView_TMP(vtkImageViewer2 *imageviewer2)
93 _imageviewer2 = imageviewer2;
95 //----------------------------------------------------------------------------
96 wxVtk2DView_TMP::~wxVtk2DView_TMP()
99 //----------------------------------------------------------------------------
100 vtkRenderer* wxVtk2DView_TMP::GetRenderer()
102 return _imageviewer2->GetRenderer();
104 //----------------------------------------------------------------------------
105 vtkRenderWindow* wxVtk2DView_TMP::GetRenWin()
107 return _imageviewer2->GetRenderWindow();
109 //----------------------------------------------------------------------------
110 void wxVtk2DView_TMP::Configure() // virtual
112 vtkInteractorStyleBaseView *interactorstylebaseview;
113 interactorstylebaseview = vtkInteractorStyleBaseView2D::New();
115 SetInteractorStyleBaseView(interactorstylebaseview);
116 wxVTKRenderWindowInteractor *iren = GetWxVTKRenderWindowInteractor();
117 interactorstylebaseview->SetInteractor ( iren );
118 iren->SetInteractorStyle(interactorstylebaseview);
119 interactorstylebaseview->SetwxVtkBaseView(this);
121 //----------------------------------------------------------------------------
122 void wxVtk2DView_TMP::SetWxVTKRenderWindowInteractor( wxVTKRenderWindowInteractor *wxVTKiren)
124 _wxVTKiren = wxVTKiren;
126 //----------------------------------------------------------------------------
127 wxVTKRenderWindowInteractor *wxVtk2DView_TMP::GetWxVTKRenderWindowInteractor() // virtual
132 //----------------------------------------------------------------------------
133 //----------------------------------------------------------------------------
134 //----------------------------------------------------------------------------
136 wxImageViewerWidget::wxImageViewerWidget(wxWindow* parent,
141 const wxString& name) :
142 wxPanel( parent, id, pos, size, style, name )
144 _manContControl = NULL;
145 _mContourModel = NULL;
146 _mViewContour = NULL;
150 //vtkOutputWindow::GetInstance()->PromptUserOff();
151 _wxVTKiren = new wxVTKRenderWindowInteractorEditContour( this, -1 );
152 _imageViewer = vtkImageViewer2::New();
154 wxBoxSizer* sizer_1 = new wxBoxSizer(wxVERTICAL);
155 sizer_1->Add(_wxVTKiren, 1, wxGROW, 0);
160 _intVtkPanWid = NULL;
165 //----------------------------------------------------------------------------
166 wxImageViewerWidget::~wxImageViewerWidget(){
168 //imageViewer->GetInput()->Delete();
169 if ( _Observer !=NULL ) { _Observer->Delete(); }
171 ///\todo I can't find a way to delete a renderWindow on Win32
172 ///\todo The following two lines shouldn't be commented
174 if ( _imageViewer !=NULL ) { _imageViewer->Delete(); }
175 //wxVTKiren->SetRenderWhenDisabled( false );
177 if ( _wxVTKiren !=NULL ) { _wxVTKiren->Delete(); }
180 if ( _manContControl !=NULL ) { delete _manContControl; }
181 if ( _mContourModel !=NULL ) { delete _mContourModel; }
182 if ( _mViewContour !=NULL ) { delete _mViewContour; }
186 //----------------------------------------------------------------------------
187 void wxImageViewerWidget::ConstructVTK(vtkImageData *imageData)
189 _imageViewer->SetInput ( imageData );
190 _imageViewer->SetupInteractor ( _wxVTKiren );
191 vtkCamera *camera =_imageViewer->GetRenderer()->GetActiveCamera();
193 _imageViewer->GetRenderer()->ResetCamera ();
196 // _imageViewer->GetRenderer()->ResetCameraClippingRange(-ww,ww,-ww,ww,-ww,ww);
198 //imageViewer->Render(); //NEVER call it explicitely !!!
200 //Some images have a bad range, rescale it by default:
201 imageData->UpdateInformation();
202 imageData->SetUpdateExtent( imageData->GetWholeExtent());
204 double *range = imageData->GetScalarRange();
205 // _imageViewer->SetColorWindow( range[1] - range[0] );
206 // _imageViewer->SetColorLevel( 0.5*(range[1] + range[0]) );
208 _Observer = marZoomROIObserver::New();
209 _Observer->ImageViewerWdg = this;
211 SetState(1); // observer 1
213 _wxVTKiren->SetObserver(_Observer);
216 This doesn't seems to be straight forward to overload left button mouse evtn
217 as vtkImageViewer2 overload window Level event / which is bind to left
218 mouse click -> as a hack use Middle mouse, (doesn't seems to usefull)
221 // wxVTKiren->GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonPressEvent, _Observer);
224 _manContControl = new manualContourControler();
225 _mContourModel = new manualContourModel();
226 _mViewContour = new manualViewContour();
228 _manContControl->SetZ(100);
229 _mViewContour->SetModel(_mContourModel);
230 wxVtk2DView_TMP *wxvtkbaseview_tmp =new wxVtk2DView_TMP(_imageViewer);
231 _mViewContour->SetWxVtkBaseView( wxvtkbaseview_tmp );
232 _mViewContour->SetRange( 2 );
233 _manContControl->SetActive(false);
234 _manContControl->SetModelView(_mContourModel,_mViewContour);
235 wxvtkbaseview_tmp->SetWxVTKRenderWindowInteractor(_wxVTKiren);
236 wxvtkbaseview_tmp->Configure();
237 wxvtkbaseview_tmp->GetInteractorStyleBaseView()->AddInteractorStyleMaracas( _manContControl );
239 _interactorStyle2DMaracas = vtkInteractorStyle2DMaracas::New();
240 _interactorStyle2DMaracas->SetInteractor ( _wxVTKiren );
241 _wxVTKiren->SetInteractorStyle(_interactorStyle2DMaracas);
242 vtkMaracasImageViewer2Callback *cbk = vtkMaracasImageViewer2Callback::New();
243 cbk->IV = _imageViewer;
244 _interactorStyle2DMaracas->AddObserver( vtkCommand::WindowLevelEvent, cbk);
245 _interactorStyle2DMaracas->AddObserver( vtkCommand::StartWindowLevelEvent, cbk);
246 _interactorStyle2DMaracas->AddObserver( vtkCommand::ResetWindowLevelEvent, cbk);
251 //----------------------------------------------------------------------------
252 void wxImageViewerWidget::SetState(int state){
254 _wxVTKiren->SetState(state);
256 //----------------------------------------------------------------------------
257 void wxImageViewerWidget::SetStateManualContour(int state){
258 _manContControl->SetState(state);
260 //----------------------------------------------------------------------------
261 void wxImageViewerWidget::CreateNewManualContour(){
262 _manContControl->CreateNewManualContour();
263 _manContControl->SetActive(true);
264 _mViewContour->Refresh();
267 //----------------------------------------------------------------------------
268 void wxImageViewerWidget::EraseManualContour(){
269 _manContControl->DeleteContour();
271 //----------------------------------------------------------------------------
273 void wxImageViewerWidget::AddObserver_1(){
275 //wxVTKiren->AddObserver(vtkCommand::MiddleButtonPressEvent, _Observer);
276 //use interactor style to override -for real- the default behavior
277 _wxVTKiren->GetInteractorStyle()->AddObserver( vtkCommand::MiddleButtonPressEvent , _Observer);
278 _wxVTKiren->AddObserver(vtkCommand::MouseMoveEvent, _Observer);
279 //wxVTKiren->AddObserver(vtkCommand::MiddleButtonReleaseEvent, _Observer);
280 _wxVTKiren->GetInteractorStyle()->AddObserver( vtkCommand::MiddleButtonReleaseEvent , _Observer);
282 //EED _wxVTKiren->AddObserver(vtkCommand::MouseWheelForwardEvent, _Observer);
283 _wxVTKiren->AddObserver( wxEVT_MOUSEWHEEL+10000 , _Observer);
285 //EED _wxVTKiren->AddObserver(vtkCommand::MouseWheelBackwardEvent, _Observer);
286 _wxVTKiren->AddObserver( wxEVT_MOUSEWHEEL+10001 , _Observer);
291 //----------------------------------------------------------------------------
293 void wxImageViewerWidget::AddObserver_2(){
295 // _wxVTKiren->AddObserver(vtkCommand::LeftButtonPressEvent , _Observer);
296 // _wxVTKiren->AddObserver(vtkCommand::LeftButtonReleaseEvent, _Observer);
298 _wxVTKiren->AddObserver(vtkCommand::MiddleButtonPressEvent , _Observer);
299 _wxVTKiren->AddObserver(vtkCommand::MiddleButtonReleaseEvent, _Observer);
301 // _wxVTKiren->AddObserver(vtkCommand::RightButtonPressEvent , _Observer);
302 _wxVTKiren->AddObserver(vtkCommand::MouseMoveEvent , _Observer);
306 //----------------------------------------------------------------------------
308 void wxImageViewerWidget::ExecuteEvent(vtkObject *wdg, unsigned long event, void* calldata){
309 if (_state==1) { ExecuteEvent1(wdg,event,calldata); }
310 if (_state==2) { ExecuteEvent2(wdg,event,calldata); }
313 //----------------------------------------------------------------------------
315 void wxImageViewerWidget::ExecuteEvent1(vtkObject *wdg, unsigned long event, void* calldata){
317 if ( event == vtkCommand::MiddleButtonPressEvent ){
318 }else if ( event == vtkCommand::MouseMoveEvent ){
321 if ( event == vtkCommand::MiddleButtonReleaseEvent ){
322 //EED } else if ( event == vtkCommand::MouseWheelForwardEvent ){
323 } else if ( event == wxEVT_MOUSEWHEEL+10000 ){
324 wxMouseEvent mouseEvent;
325 mouseEvent.m_wheelRotation=130;
326 if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);}
327 //EED }else if ( event == vtkCommand::MouseWheelBackwardEvent ){
328 }else if ( event == wxEVT_MOUSEWHEEL+10001 ){
329 wxMouseEvent mouseEvent;
330 mouseEvent.m_wheelRotation=-130;
331 if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);}
335 //----------------------------------------------------------------------------
337 void wxImageViewerWidget::ExecuteEvent2(vtkObject *wdg, unsigned long event, void* calldata){
339 _wxVTKiren->GetEventPosition(X, Y);
340 if (event==wxEVT_LEFT_DOWN ){
341 _manContControl->MouseClickLeft(X,Y);
344 if (event==wxEVT_RIGHT_DOWN ){
345 _manContControl->MouseClickRight(X,Y);
348 if (event==wxEVT_LEFT_UP){
349 _manContControl->MouseReleaseLeft(X,Y);
352 if (event==wxEVT_LEFT_DCLICK){
353 _manContControl->MouseDLeft(X,Y);
356 if (event==wxEVT_MOTION){
357 _manContControl->MouseMove(X,Y);
360 if (event==WXK_CLEAR){
361 _manContControl->DeleteActualMousePoint(X,Y);
365 //----------------------------------------------------------------------------
367 void wxImageViewerWidget::SetImage(vtkImageData* imagedata){
368 _imageViewer->SetInput(imagedata);
369 _imageViewer->Render( );
372 //----------------------------------------------------------------------------
373 int wxImageViewerWidget::GetNumberOfPointsSplineManualContour(){
374 return _manContControl->GetNumberOfPointsSplineManualContour();
376 //----------------------------------------------------------------------------
377 double* wxImageViewerWidget::GetVectorPointsXManualContour(){
378 return _manContControl->GetVectorPointsXManualContour();
380 //----------------------------------------------------------------------------
381 double* wxImageViewerWidget::GetVectorPointsYManualContour(){
382 return _manContControl->GetVectorPointsYManualContour();
384 //----------------------------------------------------------------------------
385 void wxImageViewerWidget::SetZSlice(int z){
386 #if (VTK_MAJOR_VERSION >= 5)
387 _imageViewer->SetSlice( z );
389 _imageViewer->SetZSlice( z );
393 //----------------------------------------------------------------------------
394 int wxImageViewerWidget::GetZSlice(){
395 return _imageViewer->GetZSlice();
397 //----------------------------------------------------------------------------
398 void wxImageViewerWidget::Render(){
399 _imageViewer->Render();
402 //----------------------------------------------------------------------------
403 //----------------------------------------------------------------------------
404 //----------------------------------------------------------------------------
405 //----------------------------------------------------------------------------
408 wxImageViewerWidgetRoi::wxImageViewerWidgetRoi(wxWindow* parent,
413 const wxString& name) :
414 wxImageViewerWidget( parent, id, pos, size, style, name )
416 _bboxEnabled = false;
417 _sliceEnabled = false;
418 _RoiSelected = false;
420 //----------------------------------------------------------------------------
421 wxImageViewerWidgetRoi::~wxImageViewerWidgetRoi()
424 _bboxActor ->Delete();
425 _bboxMapper ->Delete();
428 //----------------------------------------------------------------------------
429 void wxImageViewerWidgetRoi::GetROI( int extent[6] )
434 _pts->GetPoint(0, P);
435 _pts->GetPoint(2, Q);
436 if (P[0]<Q[0]) { extent[0]=(int)(P[0]); extent[1]=(int)(Q[0]); } else { extent[0]=(int)(Q[0]); extent[1]=(int)(P[0]); }
437 if (P[1]<Q[1]) { extent[2]=(int)(P[1]); extent[3]=(int)(Q[1]); } else { extent[2]=(int)(Q[1]); extent[3]=(int)(P[1]); }
438 //In case the user selects outside of the image but still in the render window
440 _imageViewer->GetInput()->GetExtent( border );
442 if (extent[0] < border[0]) extent[0]=border[0];
443 if (extent[1] > border[1]) extent[1]=border[1];
444 if (extent[2] < border[2]) extent[2]=border[2];
445 if (extent[3] > border[3]) extent[3]=border[3];
446 extent[4] = border[4];
447 extent[5] = border[5];
449 //grrrrr do not forget about image with spacing <> 1 !!
451 _imageViewer->GetInput()->GetSpacing( spacing );
452 extent[0] = (int)( extent[0]/spacing[0] );
453 extent[1] = (int)( extent[1]/spacing[0] );
454 extent[2] = (int)( extent[2]/spacing[1] );
455 extent[3] = (int)( extent[3]/spacing[1] );
456 // extent[4] /= spacing[2];
457 // extent[5] /= spacing[2];
459 //Now we should take care of the difficult cases:
460 //1. The user forgot to select a region, or want the whole region
461 //2. The user only click one point (-> extent ~ x,x,y,y !!)
463 if(extent[1]<=extent[0] || extent[3]<=extent[2]){
464 extent[0] = border[0];
465 extent[1] = border[1];
466 extent[2] = border[2];
467 extent[3] = border[3];
470 //----------------------------------------------------------------------------
471 void wxImageViewerWidgetRoi::TransfromeCoordViewWorld(int &X, int &Y, int &Z)
473 _imageViewer->GetRenderer()->SetDisplayPoint(X, Y, Z);
474 _imageViewer->GetRenderer()->DisplayToWorld();
476 _imageViewer->GetRenderer()->GetWorldPoint( fP );
486 //----------------------------------------------------------------------------
487 void wxImageViewerWidgetRoi::ExecuteEvent(vtkObject *wdg, unsigned long event, void* calldata)
491 int slice = _imageViewer->GetZSlice();
493 min = _imageViewer->GetWholeZMin();
494 max = _imageViewer->GetWholeZMax();
496 // EED Borrame if ( event == vtkCommand::MiddleButtonPressEvent ) {
497 if ( event == vtkCommand::LeftButtonPressEvent ) {
498 // Dans l'absolu il faudrait 2 modes, un par defaut celui de imageViewer2 qui semble pas mal
499 // et un deuxieme pour la manipulation exclusive du polydata 2D...
501 // if( wxVTKiren->GetShiftKey () )
503 //def StartZoom(obj, event):
504 _wxVTKiren->GetEventPosition( X, Y );
506 TransfromeCoordViewWorld(XX,YY,ZZ);
507 _pts->SetPoint(0, XX, YY, ZZ);
508 _pts->SetPoint(1, XX, YY, ZZ);
509 _pts->SetPoint(2, XX, YY, ZZ);
510 _pts->SetPoint(3, XX, YY, ZZ);
513 _bboxActor->VisibilityOn();
515 _imageViewer->Render();
517 } else if ( event == vtkCommand::MouseMoveEvent ){
521 _pts->GetPoint(0, p0);
522 _wxVTKiren->GetEventPosition(X, Y);
524 TransfromeCoordViewWorld(XX,YY,ZZ);
525 _pts->SetPoint(1, XX , p0[1] , p0[2]);
526 _pts->SetPoint(2, XX , YY , p0[2]);
527 _pts->SetPoint(3, p0[0] , YY , p0[2]);
528 _imageViewer->Render();
531 if ( event == vtkCommand::LeftButtonReleaseEvent ){
532 _bboxEnabled = false;
533 //EED} else if ( event == vtkCommand::MouseWheelForwardEvent ){
534 } else if ( event == wxEVT_MOUSEWHEEL+10000 ){
537 // * if no ctrl or shift is press then 5 slices are done
538 // * if ctrl is press -> 10 slices are done
539 // * if shirt id press -> 1 slice is done
541 if( _wxVTKiren->GetControlKey () ){
543 } else if( _wxVTKiren->GetShiftKey () ) {
546 //neither ctrl nor shift has been pressed:
550 slice = slice > min ? slice : min;
551 slice = slice < max ? slice : max;
553 #if (VTK_MAJOR_VERSION >= 5)
554 _imageViewer->SetSlice( slice );
556 _imageViewer->SetZSlice( slice );
560 //This is not nedeed any more since vtkImageViewer2.cxx -r1.9
561 //imageViewer->GetRenderer()->ResetCameraClippingRange();
563 wxMouseEvent mouseEvent;
564 mouseEvent.m_wheelRotation=130;
565 if (_intVtkPanWid!=NULL) {
566 _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);
568 _imageViewer->Render();
570 //EED } else if ( event == vtkCommand::MouseWheelBackwardEvent ){
571 } else if ( event == wxEVT_MOUSEWHEEL+10001 ){
573 // _sliceEnabled = false;
574 if( _wxVTKiren->GetControlKey () ){
576 } else if( _wxVTKiren->GetShiftKey () ) {
579 //neither ctrl nor shift has been pressed:
581 slice = (slice /5) * 5;
584 slice = slice > min ? slice : min;
585 slice = slice < max ? slice : max;
588 #if (VTK_MAJOR_VERSION >= 5)
589 _imageViewer->SetSlice( slice );
591 _imageViewer->SetZSlice( slice );
595 //This is not nedeed any more since vtkImageViewer2.cxx -r1.9
596 //imageViewer->GetRenderer()->ResetCameraClippingRange();
598 wxMouseEvent mouseEvent;
599 mouseEvent.m_wheelRotation=-130;
600 if (_intVtkPanWid!=NULL) {
601 _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);
603 _imageViewer->Render();
608 //----------------------------------------------------------------------------
609 void wxImageViewerWidgetRoi::ConstructVTK(vtkImageData *imageData){
611 wxImageViewerWidget::ConstructVTK(imageData);
612 _interactorStyle2DMaracas->SetObserver(_Observer);
614 //Supporting data for callbacks
615 _pts = vtkPoints::New();
616 _pts->SetNumberOfPoints(4);
617 _pts->SetPoint(0, -1000 , -1000 , -1000 );
618 _pts->SetPoint(1, 1000 , -1000 , 0 );
619 _pts->SetPoint(2, 1000 , 1000 , 1000 );
620 _pts->SetPoint(3, -1000 , 1000 , 0 );
623 vtkCellArray *lines = vtkCellArray::New();
624 lines->InsertNextCell(5);
625 lines->InsertCellPoint(0);
626 lines->InsertCellPoint(1);
627 lines->InsertCellPoint(2);
628 lines->InsertCellPoint(3);
629 lines->InsertCellPoint(0);
631 _pd = vtkPolyData::New();
632 _pd->SetPoints( _pts );
633 _pd->SetLines( lines );
634 lines->Delete(); //do not delete lines ??
637 _bboxActor = vtkActor::New();
638 _bboxMapper = vtkPolyDataMapper::New();
640 _bboxMapper->SetInput(_pd);
641 _bboxMapper->ImmediateModeRenderingOn();
642 _bboxActor->SetMapper(_bboxMapper);
643 _bboxActor->GetProperty()->BackfaceCullingOn();
644 _bboxActor->GetProperty()->SetDiffuseColor(1,0,0);
645 _bboxActor->GetProperty()->SetLineWidth(2);
647 _imageViewer->GetRenderer()->AddActor( _bboxActor );
648 // _imageViewer->Render( );
652 //----------------------------------------------------------------------------
653 bool wxImageViewerWidgetRoi::GetRoiSelected(){