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: vtk3DSurfaceWidget.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 =========================================================================*/
42 #include "vtk3DSurfaceWidget.h"
43 #include "../marDictionary.h"
44 #include <vtkInteractorStyleSwitch.h>
45 #include <vtkPointPicker.h>
46 #include <vtkPointData.h>
47 #include <vtkCellLocator.h>
48 #include <vtkCellArray.h>
49 #include <vtkStripper.h>
50 #include <vtkCamera.h>
54 #include "UtilVtk3DGeometriSelection.h"
59 * Again wxVTK is an hybrid class, double click was done using wxWindows, simply
60 * because VTK doesn't provide such facility (as opposed to wheel support that is
61 * supposed to be merged in VTK trunk sooner or later:
63 * http://public.kitware.com/pipermail/vtkusers/2003-August/019548.html
64 * http://www.creatis.insa-lyon.fr/~malaterre/vtk/wheel.patch
67 //----------------------------------------------------------------------------
68 BEGIN_EVENT_TABLE( vtk3DSurfaceWidget, wxVTKRenderWindowInteractor )
69 EVT_LEFT_DCLICK( vtk3DSurfaceWidget::OnLeftDClick )
70 EVT_MOUSEWHEEL( vtk3DSurfaceWidget::OnMouseWheel )
73 //----------------------------------------------------------------------------
74 vtk3DSurfaceWidget::vtk3DSurfaceWidget( wxWindow* parent, wxWindowID id,
75 const wxPoint& pos, const wxSize& size,
76 long style, const wxString& name)
77 : wxVTKRenderWindowInteractor( parent, id, pos, size, style, name )
79 //make current interactor style be trackbal camera, asked by radiologists.
82 vtkInteractorStyleSwitch *iss = dynamic_cast<vtkInteractorStyleSwitch*>(this->GetInteractorStyle());
83 iss->SetCurrentStyleToTrackballCamera();
87 vtkInteractorStyle3DMaracas *interactorStyle3DMaracas = vtkInteractorStyle3DMaracas::New();
88 // interactorStyle3DMaracas->SetInteractor (this);
89 this->SetInteractorStyle(interactorStyle3DMaracas);
92 _pRenderer = vtkRenderer::New( );
95 _centralLineMapper = NULL;
96 _centralLineActor = NULL;
99 for(int i=0; i<4; i++) {
100 _spheres[ i ] = NULL;
101 _spheresMapper[ i ] = NULL;
102 _spheresActor[ i ] = NULL;
108 _intVtkPanWid = NULL;
114 //----------------------------------------------------------------------------
115 vtk3DSurfaceWidget::~vtk3DSurfaceWidget(){
118 if( _outActor ) _outActor -> Delete( );
119 if( _outMapper ) _outMapper -> Delete( );
120 if( _outLine ) _outLine -> Delete( );
121 if( _surfActor ) _surfActor -> Delete( );
122 if( _surfMapper ) _surfMapper -> Delete( );
123 if( _mCubes ) _mCubes -> Delete( );
124 if( _centralLine ) _centralLine -> Delete( );
125 if( _centralLineMapper ) _centralLineMapper -> Delete( );
126 if( _centralLineActor ) _centralLineActor -> Delete( );
127 if( _axesActor ) _axesActor -> Delete();
128 if( _axesMapper ) _axesMapper -> Delete();
129 for(int i=0; i<4; i++)
131 if( _spheres[ i ] ) _spheres[ i ] ->Delete( );
132 if( _spheresMapper[ i ] ) _spheresMapper[ i ] ->Delete( );
133 if( _spheresActor[ i ] ) _spheresActor[ i ] ->Delete( );
135 if( _pRenderer ) _pRenderer -> Delete( );
140 //----------------------------------------------------------------------------
142 void vtk3DSurfaceWidget::OnMouseWheel( wxMouseEvent& event ){
143 if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(event);}
145 //----------------------------------------------------------------------------
146 void vtk3DSurfaceWidget::OnLeftDClick( wxMouseEvent& event ){
147 double pp[ 3 ], cp[ 3 ];
149 vtkPointPicker* picker = vtkPointPicker::New( );
150 this->GetEventPosition( eventrwi );
151 picker->Pick( eventrwi[0], eventrwi[1], 0.0, _pRenderer );
152 _pRenderer->GetActiveCamera( )->GetPosition( cp );
153 picker->GetPickPosition( pp );
156 this->SetLast3DClickPoint( pp, cp );
157 if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnLeftDClick(event); }
159 //----------------------------------------------------------------------------
160 void vtk3DSurfaceWidget::GetLast3DClickPoint( double *pp, double *cp ){
161 pp[0]=_lastPickPoint[0];
162 pp[1]=_lastPickPoint[1];
163 pp[2]=_lastPickPoint[2];
164 cp[0]=_lastCameraPos[0];
165 cp[1]=_lastCameraPos[1];
166 cp[2]=_lastCameraPos[2];
168 //----------------------------------------------------------------------------
169 void vtk3DSurfaceWidget::SetLast3DClickPoint( double *pp, double *cp ){
170 _lastPickPoint[0]=pp[0];
171 _lastPickPoint[1]=pp[1];
172 _lastPickPoint[2]=pp[2];
173 _lastCameraPos[0]=cp[0];
174 _lastCameraPos[1]=cp[1];
175 _lastCameraPos[2]=cp[2];
177 //----------------------------------------------------------------------------
178 void vtk3DSurfaceWidget::Render( ){
179 _pRenderWindow->Render();
181 //----------------------------------------------------------------------------
182 void vtk3DSurfaceWidget::InitCameraReset( ){
183 _pRenderer->ResetCameraClippingRange();
184 vtkCamera *cam=_pRenderer->GetActiveCamera();
189 //----------------------------------------------------------------------------
190 void vtk3DSurfaceWidget::SetSurfaceColor( float red, float green, float blue )
192 _surfActor->GetProperty()->SetColor(red, green, blue );
193 _pRenderWindow->Render();
195 //----------------------------------------------------------------------------
196 void vtk3DSurfaceWidget::SetSurfaceVisibility( bool visible )
198 _surfActor->SetVisibility( visible );
199 _pRenderWindow->Render();
201 //----------------------------------------------------------------------------
202 void vtk3DSurfaceWidget::SetSurfaceIsoValue( int isoval )
204 _mCubes->SetValue(0, isoval);
205 _pRenderWindow->Render();
207 //----------------------------------------------------------------------------
208 void vtk3DSurfaceWidget::SetSurfaceOpacity( int opaval )
210 //There is no way in Win32 to specify a slider different than 0->100
211 _surfActor->GetProperty()->SetOpacity( (double)opaval/100.0 );
212 _pRenderWindow->Render();
214 //----------------------------------------------------------------------------
215 void vtk3DSurfaceWidget::GetSphereCenter( double center[3] )
217 _spheres[ 3 ]->GetCenter( center );
219 //----------------------------------------------------------------------------
220 void vtk3DSurfaceWidget::SetAxis( vtkPolyData *axis )
222 _axesMapper = vtkPolyDataMapper::New( );
223 _axesMapper->SetInput( axis );
224 _axesMapper->Update();
227 _axesActor = vtkActor::New( );
228 _axesActor->SetMapper( _axesMapper );
229 _axesActor->GetProperty()->SetColor( 1, 0, 0 );
230 _axesActor->GetProperty()->SetLineWidth( 2.0 );
231 _pRenderer->AddActor( _axesActor );
233 //Generate a new vtkwindow ???
235 // _pRenderWindow->Render( );
237 //----------------------------------------------------------------------------
238 void vtk3DSurfaceWidget::RemoveAxis( )
242 _pRenderer->RemoveActor(_axesActor);
243 _axesActor->Delete();
245 _pRenderWindow->Render( );
248 //----------------------------------------------------------------------------
249 void vtk3DSurfaceWidget::ShowMARACASData( marInterface* mar ){
253 _marImageData = _mar->_experiment->getDynData( )->getVolume( )->castVtk();
254 _marImageData->GetDimensions( whd );
259 _marImageData->GetScalarRange( _range );
262 // An outline provides context around the data.
263 _outLine = vtkOutlineFilter::New( );
264 _outLine->SetInput( _marImageData );
265 _outMapper = vtkPolyDataMapper::New( );
266 _outMapper->SetInput( _outLine->GetOutput( ) );
267 _outActor = vtkActor::New( );
268 _outActor->SetMapper( _outMapper );
269 _outActor->GetProperty( )->SetColor( 0.7, 0.0, 0.9 );
270 //_outActor->PickableOff( );
271 _pRenderer->AddActor( _outActor );
274 _mCubes = vtkMarchingCubes::New( );
275 _surfMapper = vtkPolyDataMapper::New( );
276 _surfActor = vtkActor::New( );
278 _mCubes->SetInput( _marImageData );
279 _mCubes->SetValue( 0, _range[1] / 4 );
281 vtkStripper *stripper = vtkStripper::New();
282 stripper->SetInput( _mCubes->GetOutput( ) );
284 _surfMapper->SetInput( stripper->GetOutput() );
285 _surfMapper->ScalarVisibilityOff( );
288 _surfActor->SetMapper( _surfMapper );
289 _surfActor->PickableOff( );
290 _surfActor->GetProperty( )->SetColor( 0.9803, 0.9215, 0.8392 );
291 _surfActor->GetProperty( )->SetOpacity( 0.5 );
292 _pRenderer->AddActor( _surfActor );
294 // 1. ParallelProjectionOn should be set after AddActor (otherwise call vtkRenderer::ResetCameraClippingRange
295 // 2. ParallelProjectionOn is *necessary* for the vtkImplicitSelectionLoop
296 // otherwise this give a cone instead of a cylinder cutting.
297 _pRenderer->GetActiveCamera()->ParallelProjectionOn();
300 //----------------------------------------------------------------------------
301 void vtk3DSurfaceWidget::ShowMARACASDataCT( marInterfaceCT* mar ){
306 _marImageData = _marCT->getDynData()->getVolume()->castVtk();
307 _marImageData->GetDimensions( whd );
312 _marImageData->GetScalarRange( _range );
314 int a = (_marCT->GetExperiment())->getQuantStart();
316 // An outline provides context around the data.
317 _outLine = vtkOutlineFilter::New( );
318 _outLine->SetInput( _marImageData );
319 _outMapper = vtkPolyDataMapper::New( );
320 _outMapper->SetInput( _outLine->GetOutput( ) );
321 _outActor = vtkActor::New( );
322 _outActor->SetMapper( _outMapper );
323 _outActor->GetProperty( )->SetColor( 0.7, 0.0, 0.9 );
324 //_outActor->PickableOff( );
325 _pRenderer->AddActor( _outActor );
328 _mCubes = vtkMarchingCubes::New( );
329 _surfMapper = vtkPolyDataMapper::New( );
330 _surfActor = vtkActor::New( );
332 _mCubes->SetInput( _marImageData );
333 _mCubes->SetValue( 0, _range[1] / 4 );
335 vtkStripper *stripper = vtkStripper::New();
336 stripper->SetInput( _mCubes->GetOutput( ) );
338 _surfMapper->SetInput( stripper->GetOutput() );
339 _surfMapper->ScalarVisibilityOff( );
342 _surfActor->SetMapper( _surfMapper );
343 _surfActor->PickableOff( );
344 _surfActor->GetProperty( )->SetColor( 0.9803, 0.9215, 0.8392 );
345 _surfActor->GetProperty( )->SetOpacity( 0.5 );
346 _pRenderer->AddActor( _surfActor );
348 // 1. ParallelProjectionOn should be set after AddActor (otherwise call vtkRenderer::ResetCameraClippingRange
349 // 2. ParallelProjectionOn is *necessary* for the vtkImplicitSelectionLoop
350 // otherwise this give a cone instead of a cylinder cutting.
351 _pRenderer->GetActiveCamera()->ParallelProjectionOn();
354 //----------------------------------------------------------------------------
355 void vtk3DSurfaceWidget::SetInitialPoint(){
356 this->SetInitialPoint( _lastPickPoint, _lastCameraPos );
358 //----------------------------------------------------------------------------
359 void vtk3DSurfaceWidget::SetInitialPoint( float* pickPoint, float* cameraPos ){
360 marDictionary marDict;
363 gtm::TVector< double > pO( 3 ), pF( 3 ), pp( 3 ), cp( 3 );
364 gtm::TVector< double > xc( 3 );
365 gtm::TVector< double > x1( 3 ), n1( 3 );
366 gtm::TVector< double > x2( 3 ), n2( 3 );
367 gtm::TVector< double > tmp( 3 );
370 int notSuccessType = 0;
372 if( _centralLineActor )
374 _pRenderer->RemoveActor( _centralLineActor );
375 _centralLineActor->Delete( );
377 if( _centralLineMapper ) _centralLineMapper->Delete( );
378 if( _centralLine ) _centralLine->Delete( );
381 _centralLineMapper = NULL;
382 _centralLineActor = NULL;
384 for(int i=0; i<4; i++)
386 if( _spheresActor[ i ] )
388 _pRenderer->RemoveActor( _spheresActor[ i ] );
389 _spheresActor[ i ]->Delete( );
391 if( _spheresMapper[ i ] ) _spheresMapper[ i ]->Delete( );
392 if( _spheres[ i ] ) _spheres[ i ]->Delete( );
393 _spheres[ i ] = NULL;
394 _spheresMapper[ i ] = NULL;
395 _spheresActor[ i ] = NULL;
398 fac = GTM_MAX( _width, _height );
399 fac = 2 * GTM_MAX( fac, _depth );
400 pp( 0 ) = pickPoint[ 0 ]; pp( 1 ) = pickPoint[ 1 ]; pp( 2 ) = pickPoint[ 2 ];
401 cp( 0 ) = cameraPos[ 0 ]; cp( 1 ) = cameraPos[ 1 ]; cp( 2 ) = cameraPos[ 2 ];
404 UtilVtk3DGeometriSelection utilVtk3DGeometriSelection;
405 utilVtk3DGeometriSelection.SetDimentions(_width,_height,_depth);
406 utilVtk3DGeometriSelection.SetMarchingCube(_mCubes);
408 if( utilVtk3DGeometriSelection.FindCubePointsFromPoints(
409 pO.GetAnsiRef( ), pF.GetAnsiRef( ),
410 pp.GetAnsiRef( ), cp.GetAnsiRef( )
413 if( utilVtk3DGeometriSelection.GetPointAndNormalIntersection(
414 x1.GetAnsiRef( ), n1.GetAnsiRef( ),
415 pO.GetAnsiRef( ), pF.GetAnsiRef( )
418 if( utilVtk3DGeometriSelection.GetPointAndNormalIntersection(
419 x2.GetAnsiRef( ), n2.GetAnsiRef( ),
420 ( x1 - n1 ).GetAnsiRef( ), ( x1 - ( n1 * fac ) ).GetAnsiRef( )
423 xc = ( x2 + x1 ) * 0.5;
426 double dd=12; // EED ****** ATENTION ****************
429 (xc(0)<dd) || (xc(1)<dd) || (xc(2)<dd) ||
430 (fabs(xc(0)-_width)<dd) || (fabs(xc(1)-_height)<dd) || (fabs(xc(2)-_depth)<dd)
433 _mar->_experiment->setStartPoint( (int)xc( 0 ), (int)xc( 1 ), (int)xc( 2 ) );
434 _mar->_experiment->getParameters( )->setROIStep( 2*( xc - x1 ).GetNorm( ) );
436 for(int i=0; i<4; i++)
438 _spheres[ i ] = vtkSphereSource::New( );
439 _spheresMapper[ i ] = vtkPolyDataMapper::New( );
440 _spheresMapper[ i ]->SetInput( _spheres[ i ]->GetOutput( ) );
441 _spheresActor[ i ] = vtkActor::New( );
442 _spheresActor[ i ]->SetMapper( _spheresMapper[ i ] );
443 _spheresActor[ i ]->PickableOff( );
444 _pRenderer->AddActor( _spheresActor[ i ] );
447 _spheres[ 0 ]->SetCenter( x1( 0 ), x1( 1 ), x1( 2 ) );
448 _spheres[ 1 ]->SetCenter( x2( 0 ), x2( 1 ), x2( 2 ) );
449 _spheres[ 2 ]->SetCenter( xc( 0 ), xc( 1 ), xc( 2 ) );
450 _spheres[ 3 ]->SetCenter( xc( 0 ), xc( 1 ), xc( 2 ) );
452 _spheres[ 0 ]->SetRadius( 0.5 );
453 _spheres[ 1 ]->SetRadius( 0.5 );
454 _spheres[ 2 ]->SetRadius( 0.5 );
455 _spheres[ 3 ]->SetRadius( ( xc - x1 ).GetNorm( ) );
457 _spheresActor[ 0 ]->GetProperty( )->SetColor( 1.0, 0.0, 0.0 );
458 _spheresActor[ 1 ]->GetProperty( )->SetColor( 0.0, 1.0, 0.0 );
459 _spheresActor[ 2 ]->GetProperty( )->SetColor( 0.0, 0.0, 1.0 );
460 _spheresActor[ 3 ]->GetProperty( )->SetColor( 1.0, 0.0, 0.0 );
461 _spheresActor[ 3 ]->GetProperty( )->SetOpacity( 0.3 );
463 vtkPoints* points = vtkPoints::New( );
464 points->InsertNextPoint( x1.GetAnsiRef( ) );
465 points->InsertNextPoint( x2.GetAnsiRef( ) );
467 vtkCellArray* array = vtkCellArray::New( );
468 array->InsertNextCell( 2 );
469 array->InsertCellPoint( 0 );
470 array->InsertCellPoint( 1 );
472 _centralLine = vtkPolyData::New( );
473 _centralLine->SetPoints( points );
474 _centralLine->SetLines( array );
478 _centralLineMapper = vtkPolyDataMapper::New( );
479 _centralLineMapper->SetInput( _centralLine );
481 _centralLineActor = vtkActor::New( );
482 _centralLineActor->SetMapper( _centralLineMapper );
483 _centralLineActor->GetProperty( )->SetColor( 1.0, 1.0, 1.0 );
484 _centralLineActor->PickableOff( );
485 _pRenderer->AddActor( _centralLineActor );
488 } else {success = false; notSuccessType=1; }
492 } else success = false;
494 } else success = false;
496 // Show a message, if any.
497 if (( !success ) && (notSuccessType==0)) {
498 strcpy( ttmp , marDict.GetString(905) ); strcat( ttmp , "\n \n" ); strcat( ttmp , marDict.GetString(910) );
499 wxMessageBox( wxString(ttmp, wxConvUTF8) , // "Set an initial point.\n \n (Double click over the interest artery.)"
500 _T("DxMM : MARACAS"), wxOK | wxCENTRE | wxICON_INFORMATION, this);
502 if ((!success ) && (notSuccessType==1)) {
503 strcpy( ttmp , marDict.GetString(915) ); strcat( ttmp , "\n \n" ); strcat( ttmp , marDict.GetString(920) );
504 wxMessageBox( wxString(ttmp, wxConvUTF8), //"The initial point should be far \n of the limits of the volume."
505 _T("DxMM : MARACAS"), wxOK | wxCENTRE | wxICON_INFORMATION, this);
508 _pRenderWindow->Render( );
509 InitialSphere = success;
512 //----------------------------------------------------------------------------
513 void vtk3DSurfaceWidget::ConfigureVTK( )
516 _pRenderWindow = this->GetRenderWindow( );
518 // connect renderer and render window and configure render window
519 _pRenderWindow->AddRenderer( _pRenderer );
521 // configure renderer
522 _pRenderer->SetBackground( 0.0, 0.0, 0.0 );
523 //_pRenderer->SetBackground( 1, 1, 0); //FIXME
524 _pRenderer->GetActiveCamera( )->Zoom( 1.0 );
525 _pRenderer->GetActiveCamera( )->SetClippingRange( 1, 1000 );
526 _pRenderer->ResetCamera( );
529 // AttachRenderWindow();
534 //----------------------------------------------------------------------------
535 vtkRenderer* vtk3DSurfaceWidget::GetRenderer(){
538 //----------------------------------------------------------------------------