1 /*=========================================================================
4 Module: $RCSfile: wxImageViewerWidget.cxx,v $
6 Date: $Date: 2008/10/31 16:32:42 $
7 Version: $Revision: 1.1 $
9 Copyright: (c) 2002, 2003
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notice for more information.
16 =========================================================================*/
18 #include "wxImageViewerWidget.h"
20 #include "vtkRenderer.h"
21 #include "vtkRenderWindowInteractor.h" //extremely important with VC++ don't remove !
22 #include "vtkCommand.h"
23 #include "vtkPolyData.h"
24 #include "vtkCellArray.h"
25 #include "vtkPolyDataMapper.h"
26 #include "vtkInteractorObserver.h"
27 #include "vtkInteractorStyleImage.h"
29 #include <vtkCamera.h>
30 #include <vtkPolyLine.h>
31 #include <vtkDataSetMapper.h>
32 #include <vtkUnstructuredGrid.h>
34 #include <wx/tglbtn.h>
35 //----------------------------------------------------------------------------
36 // Callback for the interaction
37 class marZoomROIObserver : public vtkCommand{
39 virtual char const *GetClassName() const { return "marZoomROIObserver";}
40 static marZoomROIObserver *New(){
41 marZoomROIObserver * result;
42 result = new marZoomROIObserver;
45 // PS -> { return new marZoomROIObserver; }
47 marZoomROIObserver() { this->ImageViewerWdg = NULL; }
48 virtual void Execute(vtkObject *wdg, unsigned long event, void* calldata) {
49 if ( this->ImageViewerWdg ) {
50 this->ImageViewerWdg->ExecuteEvent(wdg, event, calldata);
53 wxImageViewerWidget *ImageViewerWdg;
56 Most of the class was done thanks to this mail, thank you James !!
57 http://public.kitware.com/pipermail/vtkusers/2003-April/017063.html
62 //----------------------------------------------------------------------------
63 //----------------------------------------------------------------------------
64 //----------------------------------------------------------------------------
66 wxVtk2DView_TMP::wxVtk2DView_TMP(vtkImageViewer2 *imageviewer2)
68 _imageviewer2 = imageviewer2;
70 //----------------------------------------------------------------------------
71 wxVtk2DView_TMP::~wxVtk2DView_TMP()
74 //----------------------------------------------------------------------------
75 vtkRenderer* wxVtk2DView_TMP::GetRenderer()
77 return _imageviewer2->GetRenderer();
79 //----------------------------------------------------------------------------
80 vtkRenderWindow* wxVtk2DView_TMP::GetRenWin()
82 return _imageviewer2->GetRenderWindow();
84 //----------------------------------------------------------------------------
85 void wxVtk2DView_TMP::Configure() // virtual
87 vtkInteractorStyleBaseView *interactorstylebaseview;
88 interactorstylebaseview = vtkInteractorStyleBaseView2D::New();
90 SetInteractorStyleBaseView(interactorstylebaseview);
91 wxVTKRenderWindowInteractor *iren = GetWxVTKRenderWindowInteractor();
92 interactorstylebaseview->SetInteractor ( iren );
93 iren->SetInteractorStyle(interactorstylebaseview);
94 interactorstylebaseview->SetwxVtkBaseView(this);
96 //----------------------------------------------------------------------------
97 void wxVtk2DView_TMP::SetWxVTKRenderWindowInteractor( wxVTKRenderWindowInteractor *wxVTKiren)
99 _wxVTKiren = wxVTKiren;
101 //----------------------------------------------------------------------------
102 wxVTKRenderWindowInteractor *wxVtk2DView_TMP::GetWxVTKRenderWindowInteractor() // virtual
107 //----------------------------------------------------------------------------
108 //----------------------------------------------------------------------------
109 //----------------------------------------------------------------------------
111 wxImageViewerWidget::wxImageViewerWidget(wxWindow* parent,
116 const wxString& name) :
117 wxPanel( parent, id, pos, size, style, name )
119 _manContControl = NULL;
120 _mContourModel = NULL;
121 _mViewContour = NULL;
125 //vtkOutputWindow::GetInstance()->PromptUserOff();
126 _wxVTKiren = new wxVTKRenderWindowInteractorEditContour( this, -1 );
127 _imageViewer = vtkImageViewer2::New();
129 wxBoxSizer* sizer_1 = new wxBoxSizer(wxVERTICAL);
130 sizer_1->Add(_wxVTKiren, 1, wxGROW, 0);
135 _intVtkPanWid = NULL;
140 //----------------------------------------------------------------------------
141 wxImageViewerWidget::~wxImageViewerWidget(){
143 //imageViewer->GetInput()->Delete();
144 if ( _Observer !=NULL ) { _Observer->Delete(); }
146 ///\todo I can't find a way to delete a renderWindow on Win32
147 ///\todo The following two lines shouldn't be commented
149 if ( _imageViewer !=NULL ) { _imageViewer->Delete(); }
150 //wxVTKiren->SetRenderWhenDisabled( false );
152 if ( _wxVTKiren !=NULL ) { _wxVTKiren->Delete(); }
155 if ( _manContControl !=NULL ) { delete _manContControl; }
156 if ( _mContourModel !=NULL ) { delete _mContourModel; }
157 if ( _mViewContour !=NULL ) { delete _mViewContour; }
161 //----------------------------------------------------------------------------
162 void wxImageViewerWidget::ConstructVTK(vtkImageData *imageData)
164 _imageViewer->SetInput ( imageData );
165 _imageViewer->SetupInteractor ( _wxVTKiren );
166 vtkCamera *camera =_imageViewer->GetRenderer()->GetActiveCamera();
168 _imageViewer->GetRenderer()->ResetCamera ();
171 // _imageViewer->GetRenderer()->ResetCameraClippingRange(-ww,ww,-ww,ww,-ww,ww);
173 //imageViewer->Render(); //NEVER call it explicitely !!!
175 //Some images have a bad range, rescale it by default:
176 imageData->UpdateInformation();
177 imageData->SetUpdateExtent( imageData->GetWholeExtent());
179 double *range = imageData->GetScalarRange();
180 // _imageViewer->SetColorWindow( range[1] - range[0] );
181 // _imageViewer->SetColorLevel( 0.5*(range[1] + range[0]) );
183 _Observer = marZoomROIObserver::New();
184 _Observer->ImageViewerWdg = this;
186 SetState(1); // observer 1
188 _wxVTKiren->SetObserver(_Observer);
191 This doesn't seems to be straight forward to overload left button mouse evtn
192 as vtkImageViewer2 overload window Level event / which is bind to left
193 mouse click -> as a hack use Middle mouse, (doesn't seems to usefull)
196 // wxVTKiren->GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonPressEvent, _Observer);
199 _manContControl = new manualContourControler();
200 _mContourModel = new manualContourModel();
201 _mViewContour = new manualViewContour();
203 _manContControl->SetZ(100);
204 _mViewContour->SetModel(_mContourModel);
205 wxVtk2DView_TMP *wxvtkbaseview_tmp =new wxVtk2DView_TMP(_imageViewer);
206 _mViewContour->SetWxVtkBaseView( wxvtkbaseview_tmp );
207 _mViewContour->SetRange( 2 );
208 _manContControl->SetActive(false);
209 _manContControl->SetModelView(_mContourModel,_mViewContour);
210 wxvtkbaseview_tmp->SetWxVTKRenderWindowInteractor(_wxVTKiren);
211 wxvtkbaseview_tmp->Configure();
212 wxvtkbaseview_tmp->GetInteractorStyleBaseView()->AddInteractorStyleMaracas( _manContControl );
214 _interactorStyle2DMaracas = vtkInteractorStyle2DMaracas::New();
215 _interactorStyle2DMaracas->SetInteractor ( _wxVTKiren );
216 _wxVTKiren->SetInteractorStyle(_interactorStyle2DMaracas);
217 vtkMaracasImageViewer2Callback *cbk = vtkMaracasImageViewer2Callback::New();
218 cbk->IV = _imageViewer;
219 _interactorStyle2DMaracas->AddObserver( vtkCommand::WindowLevelEvent, cbk);
220 _interactorStyle2DMaracas->AddObserver( vtkCommand::StartWindowLevelEvent, cbk);
221 _interactorStyle2DMaracas->AddObserver( vtkCommand::ResetWindowLevelEvent, cbk);
226 //----------------------------------------------------------------------------
227 void wxImageViewerWidget::SetState(int state){
229 _wxVTKiren->SetState(state);
231 //----------------------------------------------------------------------------
232 void wxImageViewerWidget::SetStateManualContour(int state){
233 _manContControl->SetState(state);
235 //----------------------------------------------------------------------------
236 void wxImageViewerWidget::CreateNewManualContour(){
237 _manContControl->CreateNewManualContour();
238 _manContControl->SetActive(true);
239 _mViewContour->Refresh();
242 //----------------------------------------------------------------------------
243 void wxImageViewerWidget::EraseManualContour(){
244 _manContControl->DeleteContour();
246 //----------------------------------------------------------------------------
248 void wxImageViewerWidget::AddObserver_1(){
250 //wxVTKiren->AddObserver(vtkCommand::MiddleButtonPressEvent, _Observer);
251 //use interactor style to override -for real- the default behavior
252 _wxVTKiren->GetInteractorStyle()->AddObserver( vtkCommand::MiddleButtonPressEvent , _Observer);
253 _wxVTKiren->AddObserver(vtkCommand::MouseMoveEvent, _Observer);
254 //wxVTKiren->AddObserver(vtkCommand::MiddleButtonReleaseEvent, _Observer);
255 _wxVTKiren->GetInteractorStyle()->AddObserver( vtkCommand::MiddleButtonReleaseEvent , _Observer);
257 //EED _wxVTKiren->AddObserver(vtkCommand::MouseWheelForwardEvent, _Observer);
258 _wxVTKiren->AddObserver( wxEVT_MOUSEWHEEL+10000 , _Observer);
260 //EED _wxVTKiren->AddObserver(vtkCommand::MouseWheelBackwardEvent, _Observer);
261 _wxVTKiren->AddObserver( wxEVT_MOUSEWHEEL+10001 , _Observer);
266 //----------------------------------------------------------------------------
268 void wxImageViewerWidget::AddObserver_2(){
270 // _wxVTKiren->AddObserver(vtkCommand::LeftButtonPressEvent , _Observer);
271 // _wxVTKiren->AddObserver(vtkCommand::LeftButtonReleaseEvent, _Observer);
273 _wxVTKiren->AddObserver(vtkCommand::MiddleButtonPressEvent , _Observer);
274 _wxVTKiren->AddObserver(vtkCommand::MiddleButtonReleaseEvent, _Observer);
276 // _wxVTKiren->AddObserver(vtkCommand::RightButtonPressEvent , _Observer);
277 _wxVTKiren->AddObserver(vtkCommand::MouseMoveEvent , _Observer);
281 //----------------------------------------------------------------------------
283 void wxImageViewerWidget::ExecuteEvent(vtkObject *wdg, unsigned long event, void* calldata){
284 if (_state==1) { ExecuteEvent1(wdg,event,calldata); }
285 if (_state==2) { ExecuteEvent2(wdg,event,calldata); }
288 //----------------------------------------------------------------------------
290 void wxImageViewerWidget::ExecuteEvent1(vtkObject *wdg, unsigned long event, void* calldata){
292 if ( event == vtkCommand::MiddleButtonPressEvent ){
293 }else if ( event == vtkCommand::MouseMoveEvent ){
296 if ( event == vtkCommand::MiddleButtonReleaseEvent ){
297 //EED } else if ( event == vtkCommand::MouseWheelForwardEvent ){
298 } else if ( event == wxEVT_MOUSEWHEEL+10000 ){
299 wxMouseEvent mouseEvent;
300 mouseEvent.m_wheelRotation=130;
301 if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);}
302 //EED }else if ( event == vtkCommand::MouseWheelBackwardEvent ){
303 }else if ( event == wxEVT_MOUSEWHEEL+10001 ){
304 wxMouseEvent mouseEvent;
305 mouseEvent.m_wheelRotation=-130;
306 if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);}
310 //----------------------------------------------------------------------------
312 void wxImageViewerWidget::ExecuteEvent2(vtkObject *wdg, unsigned long event, void* calldata){
314 _wxVTKiren->GetEventPosition(X, Y);
315 if (event==wxEVT_LEFT_DOWN ){
316 _manContControl->MouseClickLeft(X,Y);
319 if (event==wxEVT_RIGHT_DOWN ){
320 _manContControl->MouseClickRight(X,Y);
323 if (event==wxEVT_LEFT_UP){
324 _manContControl->MouseReleaseLeft(X,Y);
327 if (event==wxEVT_LEFT_DCLICK){
328 _manContControl->MouseDLeft(X,Y);
331 if (event==wxEVT_MOTION){
332 _manContControl->MouseMove(X,Y);
335 if (event==WXK_CLEAR){
336 _manContControl->DeleteActualMousePoint(X,Y);
340 //----------------------------------------------------------------------------
342 void wxImageViewerWidget::SetImage(vtkImageData* imagedata){
343 _imageViewer->SetInput(imagedata);
344 _imageViewer->Render( );
347 //----------------------------------------------------------------------------
348 int wxImageViewerWidget::GetNumberOfPointsSplineManualContour(){
349 return _manContControl->GetNumberOfPointsSplineManualContour();
351 //----------------------------------------------------------------------------
352 double* wxImageViewerWidget::GetVectorPointsXManualContour(){
353 return _manContControl->GetVectorPointsXManualContour();
355 //----------------------------------------------------------------------------
356 double* wxImageViewerWidget::GetVectorPointsYManualContour(){
357 return _manContControl->GetVectorPointsYManualContour();
359 //----------------------------------------------------------------------------
360 void wxImageViewerWidget::SetZSlice(int z){
361 #if (VTK_MAJOR_VERSION >= 5)
362 _imageViewer->SetSlice( z );
364 _imageViewer->SetZSlice( z );
368 //----------------------------------------------------------------------------
369 int wxImageViewerWidget::GetZSlice(){
370 return _imageViewer->GetZSlice();
372 //----------------------------------------------------------------------------
373 void wxImageViewerWidget::Render(){
374 _imageViewer->Render();
377 //----------------------------------------------------------------------------
378 //----------------------------------------------------------------------------
379 //----------------------------------------------------------------------------
380 //----------------------------------------------------------------------------
383 wxImageViewerWidgetRoi::wxImageViewerWidgetRoi(wxWindow* parent,
388 const wxString& name) :
389 wxImageViewerWidget( parent, id, pos, size, style, name )
391 _bboxEnabled = false;
392 _sliceEnabled = false;
393 _RoiSelected = false;
395 //----------------------------------------------------------------------------
396 wxImageViewerWidgetRoi::~wxImageViewerWidgetRoi()
399 _bboxActor ->Delete();
400 _bboxMapper ->Delete();
403 //----------------------------------------------------------------------------
404 void wxImageViewerWidgetRoi::GetROI( int extent[6] )
409 _pts->GetPoint(0, P);
410 _pts->GetPoint(2, Q);
411 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]); }
412 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]); }
413 //In case the user selects outside of the image but still in the render window
415 _imageViewer->GetInput()->GetExtent( border );
417 if (extent[0] < border[0]) extent[0]=border[0];
418 if (extent[1] > border[1]) extent[1]=border[1];
419 if (extent[2] < border[2]) extent[2]=border[2];
420 if (extent[3] > border[3]) extent[3]=border[3];
421 extent[4] = border[4];
422 extent[5] = border[5];
424 //grrrrr do not forget about image with spacing <> 1 !!
426 _imageViewer->GetInput()->GetSpacing( spacing );
427 extent[0] = (int)( extent[0]/spacing[0] );
428 extent[1] = (int)( extent[1]/spacing[0] );
429 extent[2] = (int)( extent[2]/spacing[1] );
430 extent[3] = (int)( extent[3]/spacing[1] );
431 // extent[4] /= spacing[2];
432 // extent[5] /= spacing[2];
434 //Now we should take care of the difficult cases:
435 //1. The user forgot to select a region, or want the whole region
436 //2. The user only click one point (-> extent ~ x,x,y,y !!)
438 if(extent[1]<=extent[0] || extent[3]<=extent[2]){
439 extent[0] = border[0];
440 extent[1] = border[1];
441 extent[2] = border[2];
442 extent[3] = border[3];
445 //----------------------------------------------------------------------------
446 void wxImageViewerWidgetRoi::TransfromeCoordViewWorld(int &X, int &Y, int &Z)
448 _imageViewer->GetRenderer()->SetDisplayPoint(X, Y, Z);
449 _imageViewer->GetRenderer()->DisplayToWorld();
451 _imageViewer->GetRenderer()->GetWorldPoint( fP );
461 //----------------------------------------------------------------------------
462 void wxImageViewerWidgetRoi::ExecuteEvent(vtkObject *wdg, unsigned long event, void* calldata)
466 int slice = _imageViewer->GetZSlice();
468 min = _imageViewer->GetWholeZMin();
469 max = _imageViewer->GetWholeZMax();
471 // EED Borrame if ( event == vtkCommand::MiddleButtonPressEvent ) {
472 if ( event == vtkCommand::LeftButtonPressEvent ) {
473 // Dans l'absolu il faudrait 2 modes, un par defaut celui de imageViewer2 qui semble pas mal
474 // et un deuxieme pour la manipulation exclusive du polydata 2D...
476 // if( wxVTKiren->GetShiftKey () )
478 //def StartZoom(obj, event):
479 _wxVTKiren->GetEventPosition( X, Y );
481 TransfromeCoordViewWorld(XX,YY,ZZ);
482 _pts->SetPoint(0, XX, YY, ZZ);
483 _pts->SetPoint(1, XX, YY, ZZ);
484 _pts->SetPoint(2, XX, YY, ZZ);
485 _pts->SetPoint(3, XX, YY, ZZ);
488 _bboxActor->VisibilityOn();
490 _imageViewer->Render();
492 } else if ( event == vtkCommand::MouseMoveEvent ){
496 _pts->GetPoint(0, p0);
497 _wxVTKiren->GetEventPosition(X, Y);
499 TransfromeCoordViewWorld(XX,YY,ZZ);
500 _pts->SetPoint(1, XX , p0[1] , p0[2]);
501 _pts->SetPoint(2, XX , YY , p0[2]);
502 _pts->SetPoint(3, p0[0] , YY , p0[2]);
503 _imageViewer->Render();
506 if ( event == vtkCommand::LeftButtonReleaseEvent ){
507 _bboxEnabled = false;
508 //EED} else if ( event == vtkCommand::MouseWheelForwardEvent ){
509 } else if ( event == wxEVT_MOUSEWHEEL+10000 ){
512 // * if no ctrl or shift is press then 5 slices are done
513 // * if ctrl is press -> 10 slices are done
514 // * if shirt id press -> 1 slice is done
516 if( _wxVTKiren->GetControlKey () ){
518 } else if( _wxVTKiren->GetShiftKey () ) {
521 //neither ctrl nor shift has been pressed:
525 slice = slice > min ? slice : min;
526 slice = slice < max ? slice : max;
528 #if (VTK_MAJOR_VERSION >= 5)
529 _imageViewer->SetSlice( slice );
531 _imageViewer->SetZSlice( slice );
535 //This is not nedeed any more since vtkImageViewer2.cxx -r1.9
536 //imageViewer->GetRenderer()->ResetCameraClippingRange();
538 wxMouseEvent mouseEvent;
539 mouseEvent.m_wheelRotation=130;
540 if (_intVtkPanWid!=NULL) {
541 _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);
543 _imageViewer->Render();
545 //EED } else if ( event == vtkCommand::MouseWheelBackwardEvent ){
546 } else if ( event == wxEVT_MOUSEWHEEL+10001 ){
548 // _sliceEnabled = false;
549 if( _wxVTKiren->GetControlKey () ){
551 } else if( _wxVTKiren->GetShiftKey () ) {
554 //neither ctrl nor shift has been pressed:
556 slice = (slice /5) * 5;
559 slice = slice > min ? slice : min;
560 slice = slice < max ? slice : max;
563 #if (VTK_MAJOR_VERSION >= 5)
564 _imageViewer->SetSlice( slice );
566 _imageViewer->SetZSlice( slice );
570 //This is not nedeed any more since vtkImageViewer2.cxx -r1.9
571 //imageViewer->GetRenderer()->ResetCameraClippingRange();
573 wxMouseEvent mouseEvent;
574 mouseEvent.m_wheelRotation=-130;
575 if (_intVtkPanWid!=NULL) {
576 _intVtkPanWid->CallBackOnMouseWheel(mouseEvent);
578 _imageViewer->Render();
583 //----------------------------------------------------------------------------
584 void wxImageViewerWidgetRoi::ConstructVTK(vtkImageData *imageData){
586 wxImageViewerWidget::ConstructVTK(imageData);
587 _interactorStyle2DMaracas->SetObserver(_Observer);
589 //Supporting data for callbacks
590 _pts = vtkPoints::New();
591 _pts->SetNumberOfPoints(4);
592 _pts->SetPoint(0, -1000 , -1000 , -1000 );
593 _pts->SetPoint(1, 1000 , -1000 , 0 );
594 _pts->SetPoint(2, 1000 , 1000 , 1000 );
595 _pts->SetPoint(3, -1000 , 1000 , 0 );
598 vtkCellArray *lines = vtkCellArray::New();
599 lines->InsertNextCell(5);
600 lines->InsertCellPoint(0);
601 lines->InsertCellPoint(1);
602 lines->InsertCellPoint(2);
603 lines->InsertCellPoint(3);
604 lines->InsertCellPoint(0);
606 _pd = vtkPolyData::New();
607 _pd->SetPoints( _pts );
608 _pd->SetLines( lines );
609 lines->Delete(); //do not delete lines ??
612 _bboxActor = vtkActor::New();
613 _bboxMapper = vtkPolyDataMapper::New();
615 _bboxMapper->SetInput(_pd);
616 _bboxMapper->ImmediateModeRenderingOn();
617 _bboxActor->SetMapper(_bboxMapper);
618 _bboxActor->GetProperty()->BackfaceCullingOn();
619 _bboxActor->GetProperty()->SetDiffuseColor(1,0,0);
620 _bboxActor->GetProperty()->SetLineWidth(2);
622 _imageViewer->GetRenderer()->AddActor( _bboxActor );
623 // _imageViewer->Render( );
627 //----------------------------------------------------------------------------
628 bool wxImageViewerWidgetRoi::GetRoiSelected(){