/*# --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Sant�) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ /*========================================================================= Program: wxMaracas Module: $RCSfile: wxImageViewerWidget.cxx,v $ Language: C++ Date: $Date: 2012/11/15 14:15:18 $ Version: $Revision: 1.2 $ Copyright: (c) 2002, 2003 License: This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "wxImageViewerWidget.h" #include "vtkRenderer.h" #include "vtkRenderWindowInteractor.h" //extremely important with VC++ don't remove ! #include "vtkCommand.h" #include "vtkPolyData.h" #include "vtkCellArray.h" #include "vtkPolyDataMapper.h" #include "vtkInteractorObserver.h" #include "vtkInteractorStyleImage.h" #include #include #include #include #include //---------------------------------------------------------------------------- // Callback for the interaction class marZoomROIObserver : public vtkCommand{ public: virtual char const *GetClassName() const { return "marZoomROIObserver";} static marZoomROIObserver *New(){ marZoomROIObserver * result; result = new marZoomROIObserver; return result; } // PS -> { return new marZoomROIObserver; } marZoomROIObserver() { this->ImageViewerWdg = NULL; } virtual void Execute(vtkObject *wdg, unsigned long event, void* calldata) { if ( this->ImageViewerWdg ) { this->ImageViewerWdg->ExecuteEvent(wdg, event, calldata); } } wxImageViewerWidget *ImageViewerWdg; }; /** Most of the class was done thanks to this mail, thank you James !! http://public.kitware.com/pipermail/vtkusers/2003-April/017063.html */ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- wxVtk2DView_TMP::wxVtk2DView_TMP(vtkImageViewer2 *imageviewer2) { _imageviewer2 = imageviewer2; } //---------------------------------------------------------------------------- wxVtk2DView_TMP::~wxVtk2DView_TMP() { } //---------------------------------------------------------------------------- vtkRenderer* wxVtk2DView_TMP::GetRenderer() { return _imageviewer2->GetRenderer(); } //---------------------------------------------------------------------------- vtkRenderWindow* wxVtk2DView_TMP::GetRenWin() { return _imageviewer2->GetRenderWindow(); } //---------------------------------------------------------------------------- void wxVtk2DView_TMP::Configure() // virtual { vtkInteractorStyleBaseView *interactorstylebaseview; interactorstylebaseview = vtkInteractorStyleBaseView2D::New(); SetInteractorStyleBaseView(interactorstylebaseview); wxVTKRenderWindowInteractor *iren = GetWxVTKRenderWindowInteractor(); interactorstylebaseview->SetInteractor ( iren ); iren->SetInteractorStyle(interactorstylebaseview); interactorstylebaseview->SetwxVtkBaseView(this); } //---------------------------------------------------------------------------- void wxVtk2DView_TMP::SetWxVTKRenderWindowInteractor( wxVTKRenderWindowInteractor *wxVTKiren) { _wxVTKiren = wxVTKiren; } //---------------------------------------------------------------------------- wxVTKRenderWindowInteractor *wxVtk2DView_TMP::GetWxVTKRenderWindowInteractor() // virtual { return _wxVTKiren; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- wxImageViewerWidget::wxImageViewerWidget(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxPanel( parent, id, pos, size, style, name ) { _manContControl = NULL; _mContourModel = NULL; _mViewContour = NULL; _Observer = NULL; _state=1; //vtkOutputWindow::GetInstance()->PromptUserOff(); _wxVTKiren = new wxVTKRenderWindowInteractorEditContour( this, -1 ); _imageViewer = vtkImageViewer2::New(); wxBoxSizer* sizer_1 = new wxBoxSizer(wxVERTICAL); sizer_1->Add(_wxVTKiren, 1, wxGROW, 0); SetAutoLayout(true); SetSizer(sizer_1); Layout(); _intVtkPanWid = NULL; } //---------------------------------------------------------------------------- wxImageViewerWidget::~wxImageViewerWidget(){ //imageViewer->GetInput()->Delete(); if ( _Observer !=NULL ) { _Observer->Delete(); } ///\todo I can't find a way to delete a renderWindow on Win32 ///\todo The following two lines shouldn't be commented if ( _imageViewer !=NULL ) { _imageViewer->Delete(); } //wxVTKiren->SetRenderWhenDisabled( false ); if ( _wxVTKiren !=NULL ) { _wxVTKiren->Delete(); } if ( _manContControl !=NULL ) { delete _manContControl; } if ( _mContourModel !=NULL ) { delete _mContourModel; } if ( _mViewContour !=NULL ) { delete _mViewContour; } } //---------------------------------------------------------------------------- void wxImageViewerWidget::ConstructVTK(vtkImageData *imageData) { _imageViewer->SetInput ( imageData ); _imageViewer->SetupInteractor ( _wxVTKiren ); vtkCamera *camera =_imageViewer->GetRenderer()->GetActiveCamera(); camera->Zoom(2.5); _imageViewer->GetRenderer()->ResetCamera (); // int ww=2000; // _imageViewer->GetRenderer()->ResetCameraClippingRange(-ww,ww,-ww,ww,-ww,ww); //imageViewer->Render(); //NEVER call it explicitely !!! //Some images have a bad range, rescale it by default: imageData->UpdateInformation(); imageData->SetUpdateExtent( imageData->GetWholeExtent()); imageData->Update(); double *range = imageData->GetScalarRange(); // _imageViewer->SetColorWindow( range[1] - range[0] ); // _imageViewer->SetColorLevel( 0.5*(range[1] + range[0]) ); _Observer = marZoomROIObserver::New(); _Observer->ImageViewerWdg = this; SetState(1); // observer 1 AddObserver_1(); _wxVTKiren->SetObserver(_Observer); /** This doesn't seems to be straight forward to overload left button mouse evtn as vtkImageViewer2 overload window Level event / which is bind to left mouse click -> as a hack use Middle mouse, (doesn't seems to usefull) */ // wxVTKiren->GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonPressEvent, _Observer); _manContControl = new manualContourControler(); _mContourModel = new manualContourModel(); _mViewContour = new manualViewContour(); _manContControl->SetZ(100); _mViewContour->SetModel(_mContourModel); wxVtk2DView_TMP *wxvtkbaseview_tmp =new wxVtk2DView_TMP(_imageViewer); _mViewContour->SetWxVtkBaseView( wxvtkbaseview_tmp ); _mViewContour->SetRange( 2 ); _manContControl->SetActive(false); _manContControl->SetModelView(_mContourModel,_mViewContour); wxvtkbaseview_tmp->SetWxVTKRenderWindowInteractor(_wxVTKiren); wxvtkbaseview_tmp->Configure(); wxvtkbaseview_tmp->GetInteractorStyleBaseView()->AddInteractorStyleMaracas( _manContControl ); _interactorStyle2DMaracas = vtkInteractorStyle2DMaracas::New(); _interactorStyle2DMaracas->SetInteractor ( _wxVTKiren ); _wxVTKiren->SetInteractorStyle(_interactorStyle2DMaracas); vtkMaracasImageViewer2Callback *cbk = vtkMaracasImageViewer2Callback::New(); cbk->IV = _imageViewer; _interactorStyle2DMaracas->AddObserver( vtkCommand::WindowLevelEvent, cbk); _interactorStyle2DMaracas->AddObserver( vtkCommand::StartWindowLevelEvent, cbk); _interactorStyle2DMaracas->AddObserver( vtkCommand::ResetWindowLevelEvent, cbk); cbk->Delete(); } //---------------------------------------------------------------------------- void wxImageViewerWidget::SetState(int state){ _state=state; _wxVTKiren->SetState(state); } //---------------------------------------------------------------------------- void wxImageViewerWidget::SetStateManualContour(int state){ _manContControl->SetState(state); } //---------------------------------------------------------------------------- void wxImageViewerWidget::CreateNewManualContour(){ _manContControl->CreateNewManualContour(); _manContControl->SetActive(true); _mViewContour->Refresh(); Refresh(); } //---------------------------------------------------------------------------- void wxImageViewerWidget::EraseManualContour(){ _manContControl->DeleteContour(); } //---------------------------------------------------------------------------- void wxImageViewerWidget::AddObserver_1(){ //wxVTKiren->AddObserver(vtkCommand::MiddleButtonPressEvent, _Observer); //use interactor style to override -for real- the default behavior _wxVTKiren->GetInteractorStyle()->AddObserver( vtkCommand::MiddleButtonPressEvent , _Observer); _wxVTKiren->AddObserver(vtkCommand::MouseMoveEvent, _Observer); //wxVTKiren->AddObserver(vtkCommand::MiddleButtonReleaseEvent, _Observer); _wxVTKiren->GetInteractorStyle()->AddObserver( vtkCommand::MiddleButtonReleaseEvent , _Observer); //EED _wxVTKiren->AddObserver(vtkCommand::MouseWheelForwardEvent, _Observer); _wxVTKiren->AddObserver( wxEVT_MOUSEWHEEL+10000 , _Observer); //EED _wxVTKiren->AddObserver(vtkCommand::MouseWheelBackwardEvent, _Observer); _wxVTKiren->AddObserver( wxEVT_MOUSEWHEEL+10001 , _Observer); } //---------------------------------------------------------------------------- void wxImageViewerWidget::AddObserver_2(){ /* // _wxVTKiren->AddObserver(vtkCommand::LeftButtonPressEvent , _Observer); // _wxVTKiren->AddObserver(vtkCommand::LeftButtonReleaseEvent, _Observer); _wxVTKiren->AddObserver(vtkCommand::MiddleButtonPressEvent , _Observer); _wxVTKiren->AddObserver(vtkCommand::MiddleButtonReleaseEvent, _Observer); // _wxVTKiren->AddObserver(vtkCommand::RightButtonPressEvent , _Observer); _wxVTKiren->AddObserver(vtkCommand::MouseMoveEvent , _Observer); */ } //---------------------------------------------------------------------------- void wxImageViewerWidget::ExecuteEvent(vtkObject *wdg, unsigned long event, void* calldata){ if (_state==1) { ExecuteEvent1(wdg,event,calldata); } if (_state==2) { ExecuteEvent2(wdg,event,calldata); } } //---------------------------------------------------------------------------- void wxImageViewerWidget::ExecuteEvent1(vtkObject *wdg, unsigned long event, void* calldata){ if ( event == vtkCommand::MiddleButtonPressEvent ){ }else if ( event == vtkCommand::MouseMoveEvent ){ } if ( event == vtkCommand::MiddleButtonReleaseEvent ){ //EED } else if ( event == vtkCommand::MouseWheelForwardEvent ){ } else if ( event == wxEVT_MOUSEWHEEL+10000 ){ wxMouseEvent mouseEvent; mouseEvent.m_wheelRotation=130; if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);} //EED }else if ( event == vtkCommand::MouseWheelBackwardEvent ){ }else if ( event == wxEVT_MOUSEWHEEL+10001 ){ wxMouseEvent mouseEvent; mouseEvent.m_wheelRotation=-130; if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);} } } //---------------------------------------------------------------------------- void wxImageViewerWidget::ExecuteEvent2(vtkObject *wdg, unsigned long event, void* calldata){ int X,Y; _wxVTKiren->GetEventPosition(X, Y); if (event==wxEVT_LEFT_DOWN ){ _manContControl->MouseClickLeft(X,Y); } if (event==wxEVT_RIGHT_DOWN ){ _manContControl->MouseClickRight(X,Y); } if (event==wxEVT_LEFT_UP){ _manContControl->MouseReleaseLeft(X,Y); } if (event==wxEVT_LEFT_DCLICK){ _manContControl->MouseDLeft(X,Y); } if (event==wxEVT_MOTION){ _manContControl->MouseMove(X,Y); } if (event==WXK_CLEAR){ _manContControl->DeleteActualMousePoint(X,Y); } } //---------------------------------------------------------------------------- void wxImageViewerWidget::SetImage(vtkImageData* imagedata){ _imageViewer->SetInput(imagedata); _imageViewer->Render( ); } //---------------------------------------------------------------------------- int wxImageViewerWidget::GetNumberOfPointsSplineManualContour(){ return _manContControl->GetNumberOfPointsSplineManualContour(); } //---------------------------------------------------------------------------- double* wxImageViewerWidget::GetVectorPointsXManualContour(){ return _manContControl->GetVectorPointsXManualContour(); } //---------------------------------------------------------------------------- double* wxImageViewerWidget::GetVectorPointsYManualContour(){ return _manContControl->GetVectorPointsYManualContour(); } //---------------------------------------------------------------------------- void wxImageViewerWidget::SetZSlice(int z){ #if (VTK_MAJOR_VERSION >= 5) _imageViewer->SetSlice( z ); #else _imageViewer->SetZSlice( z ); #endif } //---------------------------------------------------------------------------- int wxImageViewerWidget::GetZSlice(){ return _imageViewer->GetZSlice(); } //---------------------------------------------------------------------------- void wxImageViewerWidget::Render(){ _imageViewer->Render(); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- wxImageViewerWidgetRoi::wxImageViewerWidgetRoi(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxImageViewerWidget( parent, id, pos, size, style, name ) { _bboxEnabled = false; _sliceEnabled = false; _RoiSelected = false; } //---------------------------------------------------------------------------- wxImageViewerWidgetRoi::~wxImageViewerWidgetRoi() { _pts ->Delete(); _bboxActor ->Delete(); _bboxMapper ->Delete(); _pd ->Delete(); } //---------------------------------------------------------------------------- void wxImageViewerWidgetRoi::GetROI( int extent[6] ) { //retrieve a point double P[3]; double Q[3]; _pts->GetPoint(0, P); _pts->GetPoint(2, Q); if (P[0]GetInput()->GetExtent( border ); if (extent[0] < border[0]) extent[0]=border[0]; if (extent[1] > border[1]) extent[1]=border[1]; if (extent[2] < border[2]) extent[2]=border[2]; if (extent[3] > border[3]) extent[3]=border[3]; extent[4] = border[4]; extent[5] = border[5]; //grrrrr do not forget about image with spacing <> 1 !! double spacing[3]; _imageViewer->GetInput()->GetSpacing( spacing ); extent[0] = (int)( extent[0]/spacing[0] ); extent[1] = (int)( extent[1]/spacing[0] ); extent[2] = (int)( extent[2]/spacing[1] ); extent[3] = (int)( extent[3]/spacing[1] ); // extent[4] /= spacing[2]; // extent[5] /= spacing[2]; //Now we should take care of the difficult cases: //1. The user forgot to select a region, or want the whole region //2. The user only click one point (-> extent ~ x,x,y,y !!) if(extent[1]<=extent[0] || extent[3]<=extent[2]){ extent[0] = border[0]; extent[1] = border[1]; extent[2] = border[2]; extent[3] = border[3]; } } //---------------------------------------------------------------------------- void wxImageViewerWidgetRoi::TransfromeCoordViewWorld(int &X, int &Y, int &Z) { _imageViewer->GetRenderer()->SetDisplayPoint(X, Y, Z); _imageViewer->GetRenderer()->DisplayToWorld(); double fP[4]; _imageViewer->GetRenderer()->GetWorldPoint( fP ); if ( fP[3] ){ fP[0] /= fP[3]; fP[1] /= fP[3]; fP[2] /= fP[3]; } X=(int)(fP[0]); Y=(int)(fP[1]); Z=(int)(fP[2]); } //---------------------------------------------------------------------------- void wxImageViewerWidgetRoi::ExecuteEvent(vtkObject *wdg, unsigned long event, void* calldata) { int X, Y, Z=0; int XX,YY,ZZ; int slice = _imageViewer->GetZSlice(); int min,max; min = _imageViewer->GetWholeZMin(); max = _imageViewer->GetWholeZMax(); // EED Borrame if ( event == vtkCommand::MiddleButtonPressEvent ) { if ( event == vtkCommand::LeftButtonPressEvent ) { // Dans l'absolu il faudrait 2 modes, un par defaut celui de imageViewer2 qui semble pas mal // et un deuxieme pour la manipulation exclusive du polydata 2D... // if( wxVTKiren->GetShiftKey () ) { //def StartZoom(obj, event): _wxVTKiren->GetEventPosition( X, Y ); XX=X; YY=Y; ZZ=Z; TransfromeCoordViewWorld(XX,YY,ZZ); _pts->SetPoint(0, XX, YY, ZZ); _pts->SetPoint(1, XX, YY, ZZ); _pts->SetPoint(2, XX, YY, ZZ); _pts->SetPoint(3, XX, YY, ZZ); _bboxEnabled = true; _bboxActor->VisibilityOn(); _imageViewer->Render(); } } else if ( event == vtkCommand::MouseMoveEvent ){ if ( _bboxEnabled ){ _RoiSelected=true; double p0[3]; _pts->GetPoint(0, p0); _wxVTKiren->GetEventPosition(X, Y); XX=X; YY=Y; ZZ=Z; TransfromeCoordViewWorld(XX,YY,ZZ); _pts->SetPoint(1, XX , p0[1] , p0[2]); _pts->SetPoint(2, XX , YY , p0[2]); _pts->SetPoint(3, p0[0] , YY , p0[2]); _imageViewer->Render(); } } if ( event == vtkCommand::LeftButtonReleaseEvent ){ _bboxEnabled = false; //EED} else if ( event == vtkCommand::MouseWheelForwardEvent ){ } else if ( event == wxEVT_MOUSEWHEEL+10000 ){ // mouse wheel: // * if no ctrl or shift is press then 5 slices are done // * if ctrl is press -> 10 slices are done // * if shirt id press -> 1 slice is done if( _wxVTKiren->GetControlKey () ){ slice += 10; } else if( _wxVTKiren->GetShiftKey () ) { slice++; } else { //neither ctrl nor shift has been pressed: slice += 5; } slice = slice > min ? slice : min; slice = slice < max ? slice : max; #if (VTK_MAJOR_VERSION >= 5) _imageViewer->SetSlice( slice ); #else _imageViewer->SetZSlice( slice ); #endif //This is not nedeed any more since vtkImageViewer2.cxx -r1.9 //imageViewer->GetRenderer()->ResetCameraClippingRange(); wxMouseEvent mouseEvent; mouseEvent.m_wheelRotation=130; if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent); } _imageViewer->Render(); //EED } else if ( event == vtkCommand::MouseWheelBackwardEvent ){ } else if ( event == wxEVT_MOUSEWHEEL+10001 ){ // _sliceEnabled = false; if( _wxVTKiren->GetControlKey () ){ slice -= 10; } else if( _wxVTKiren->GetShiftKey () ) { slice--; } else { //neither ctrl nor shift has been pressed: slice -= 5; slice = (slice /5) * 5; } slice = slice > min ? slice : min; slice = slice < max ? slice : max; #if (VTK_MAJOR_VERSION >= 5) _imageViewer->SetSlice( slice ); #else _imageViewer->SetZSlice( slice ); #endif //This is not nedeed any more since vtkImageViewer2.cxx -r1.9 //imageViewer->GetRenderer()->ResetCameraClippingRange(); wxMouseEvent mouseEvent; mouseEvent.m_wheelRotation=-130; if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent); } _imageViewer->Render(); } } //---------------------------------------------------------------------------- void wxImageViewerWidgetRoi::ConstructVTK(vtkImageData *imageData){ wxImageViewerWidget::ConstructVTK(imageData); _interactorStyle2DMaracas->SetObserver(_Observer); //Supporting data for callbacks _pts = vtkPoints::New(); _pts->SetNumberOfPoints(4); _pts->SetPoint(0, -1000 , -1000 , -1000 ); _pts->SetPoint(1, 1000 , -1000 , 0 ); _pts->SetPoint(2, 1000 , 1000 , 1000 ); _pts->SetPoint(3, -1000 , 1000 , 0 ); vtkCellArray *lines = vtkCellArray::New(); lines->InsertNextCell(5); lines->InsertCellPoint(0); lines->InsertCellPoint(1); lines->InsertCellPoint(2); lines->InsertCellPoint(3); lines->InsertCellPoint(0); _pd = vtkPolyData::New(); _pd->SetPoints( _pts ); _pd->SetLines( lines ); lines->Delete(); //do not delete lines ?? _bboxActor = vtkActor::New(); _bboxMapper = vtkPolyDataMapper::New(); _bboxMapper->SetInput(_pd); _bboxMapper->ImmediateModeRenderingOn(); _bboxActor->SetMapper(_bboxMapper); _bboxActor->GetProperty()->BackfaceCullingOn(); _bboxActor->GetProperty()->SetDiffuseColor(1,0,0); _bboxActor->GetProperty()->SetLineWidth(2); _imageViewer->GetRenderer()->AddActor( _bboxActor ); // _imageViewer->Render( ); } //---------------------------------------------------------------------------- bool wxImageViewerWidgetRoi::GetRoiSelected(){ return _RoiSelected; }