/*========================================================================= Program: wxMaracas Module: $RCSfile: vtk3DSurfaceWidget.cxx,v $ Language: C++ Date: $Date: 2008/10/31 16:32:41 $ Version: $Revision: 1.1 $ 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 "vtk3DSurfaceWidget.h" #include "../marDictionary.h" #include #include #include #include #include #include #include #include "matrix.h" #include "UtilVtk3DGeometriSelection.h" /** * Again wxVTK is an hybrid class, double click was done using wxWindows, simply * because VTK doesn't provide such facility (as opposed to wheel support that is * supposed to be merged in VTK trunk sooner or later: * * http://public.kitware.com/pipermail/vtkusers/2003-August/019548.html * http://www.creatis.insa-lyon.fr/~malaterre/vtk/wheel.patch */ //---------------------------------------------------------------------------- BEGIN_EVENT_TABLE( vtk3DSurfaceWidget, wxVTKRenderWindowInteractor ) EVT_LEFT_DCLICK( vtk3DSurfaceWidget::OnLeftDClick ) EVT_MOUSEWHEEL( vtk3DSurfaceWidget::OnMouseWheel ) END_EVENT_TABLE( ); //---------------------------------------------------------------------------- vtk3DSurfaceWidget::vtk3DSurfaceWidget( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxVTKRenderWindowInteractor( parent, id, pos, size, style, name ) { //make current interactor style be trackbal camera, asked by radiologists. /* vtkInteractorStyleSwitch *iss = dynamic_cast(this->GetInteractorStyle()); iss->SetCurrentStyleToTrackballCamera(); */ vtkInteractorStyle3DMaracas *interactorStyle3DMaracas = vtkInteractorStyle3DMaracas::New(); // interactorStyle3DMaracas->SetInteractor (this); this->SetInteractorStyle(interactorStyle3DMaracas); _pRenderer = vtkRenderer::New( ); InitialSphere = 0; _centralLine = NULL; _centralLineMapper = NULL; _centralLineActor = NULL; _axesMapper = NULL; _axesActor = NULL; for(int i=0; i<4; i++) { _spheres[ i ] = NULL; _spheresMapper[ i ] = NULL; _spheresActor[ i ] = NULL; } _axesActor = NULL; _axesMapper = NULL; _surfActor = NULL; _surfMapper = NULL; _intVtkPanWid = NULL; _outActor = NULL; _outMapper = NULL; _outLine = NULL; _mCubes = NULL; } //---------------------------------------------------------------------------- vtk3DSurfaceWidget::~vtk3DSurfaceWidget(){ //good luck: if( _outActor ) _outActor -> Delete( ); if( _outMapper ) _outMapper -> Delete( ); if( _outLine ) _outLine -> Delete( ); if( _surfActor ) _surfActor -> Delete( ); if( _surfMapper ) _surfMapper -> Delete( ); if( _mCubes ) _mCubes -> Delete( ); if( _centralLine ) _centralLine -> Delete( ); if( _centralLineMapper ) _centralLineMapper -> Delete( ); if( _centralLineActor ) _centralLineActor -> Delete( ); if( _axesActor ) _axesActor -> Delete(); if( _axesMapper ) _axesMapper -> Delete(); for(int i=0; i<4; i++) { if( _spheres[ i ] ) _spheres[ i ] ->Delete( ); if( _spheresMapper[ i ] ) _spheresMapper[ i ] ->Delete( ); if( _spheresActor[ i ] ) _spheresActor[ i ] ->Delete( ); } if( _pRenderer ) _pRenderer -> Delete( ); } //---------------------------------------------------------------------------- // virtual void vtk3DSurfaceWidget::OnMouseWheel( wxMouseEvent& event ){ if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnMouseWheel(event);} } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::OnLeftDClick( wxMouseEvent& event ){ double pp[ 3 ], cp[ 3 ]; int eventrwi[2]; vtkPointPicker* picker = vtkPointPicker::New( ); this->GetEventPosition( eventrwi ); picker->Pick( eventrwi[0], eventrwi[1], 0.0, _pRenderer ); _pRenderer->GetActiveCamera( )->GetPosition( cp ); picker->GetPickPosition( pp ); picker->Delete( ); this->SetLast3DClickPoint( pp, cp ); if (_intVtkPanWid!=NULL) { _intVtkPanWid->CallBackOnLeftDClick(event); } } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::GetLast3DClickPoint( double *pp, double *cp ){ pp[0]=_lastPickPoint[0]; pp[1]=_lastPickPoint[1]; pp[2]=_lastPickPoint[2]; cp[0]=_lastCameraPos[0]; cp[1]=_lastCameraPos[1]; cp[2]=_lastCameraPos[2]; } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetLast3DClickPoint( double *pp, double *cp ){ _lastPickPoint[0]=pp[0]; _lastPickPoint[1]=pp[1]; _lastPickPoint[2]=pp[2]; _lastCameraPos[0]=cp[0]; _lastCameraPos[1]=cp[1]; _lastCameraPos[2]=cp[2]; } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::Render( ){ _pRenderWindow->Render(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::InitCameraReset( ){ _pRenderer->ResetCameraClippingRange(); vtkCamera *cam=_pRenderer->GetActiveCamera(); cam->Zoom(1.8); // EED 31 Mai 2007 // Render(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetSurfaceColor( float red, float green, float blue ) { _surfActor->GetProperty()->SetColor(red, green, blue ); _pRenderWindow->Render(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetSurfaceVisibility( bool visible ) { _surfActor->SetVisibility( visible ); _pRenderWindow->Render(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetSurfaceIsoValue( int isoval ) { _mCubes->SetValue(0, isoval); _pRenderWindow->Render(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetSurfaceOpacity( int opaval ) { //There is no way in Win32 to specify a slider different than 0->100 _surfActor->GetProperty()->SetOpacity( (double)opaval/100.0 ); _pRenderWindow->Render(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::GetSphereCenter( double center[3] ) { _spheres[ 3 ]->GetCenter( center ); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetAxis( vtkPolyData *axis ) { _axesMapper = vtkPolyDataMapper::New( ); _axesMapper->SetInput( axis ); _axesMapper->Update(); //axis->Delete(); _axesActor = vtkActor::New( ); _axesActor->SetMapper( _axesMapper ); _axesActor->GetProperty()->SetColor( 1, 0, 0 ); _axesActor->GetProperty()->SetLineWidth( 2.0 ); _pRenderer->AddActor( _axesActor ); //Generate a new vtkwindow ??? //EED 31 Mai 2007 // _pRenderWindow->Render( ); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::RemoveAxis( ) { if (_axesActor) { _pRenderer->RemoveActor(_axesActor); _axesActor->Delete(); _axesActor = NULL; _pRenderWindow->Render( ); } } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::ShowMARACASData( marInterface* mar ){ int whd[3]; _mar = mar; _marImageData = _mar->_experiment->getDynData( )->getVolume( )->castVtk(); _marImageData->GetDimensions( whd ); _width = whd[0]; _height = whd[1]; _depth = whd[2]; _marImageData->GetScalarRange( _range ); //Outline v2: // An outline provides context around the data. _outLine = vtkOutlineFilter::New( ); _outLine->SetInput( _marImageData ); _outMapper = vtkPolyDataMapper::New( ); _outMapper->SetInput( _outLine->GetOutput( ) ); _outActor = vtkActor::New( ); _outActor->SetMapper( _outMapper ); _outActor->GetProperty( )->SetColor( 0.7, 0.0, 0.9 ); //_outActor->PickableOff( ); _pRenderer->AddActor( _outActor ); // Surface _mCubes = vtkMarchingCubes::New( ); _surfMapper = vtkPolyDataMapper::New( ); _surfActor = vtkActor::New( ); _mCubes->SetInput( _marImageData ); _mCubes->SetValue( 0, _range[1] / 4 ); vtkStripper *stripper = vtkStripper::New(); stripper->SetInput( _mCubes->GetOutput( ) ); _surfMapper->SetInput( stripper->GetOutput() ); _surfMapper->ScalarVisibilityOff( ); stripper->Delete(); _surfActor->SetMapper( _surfMapper ); _surfActor->PickableOff( ); _surfActor->GetProperty( )->SetColor( 0.9803, 0.9215, 0.8392 ); _surfActor->GetProperty( )->SetOpacity( 0.5 ); _pRenderer->AddActor( _surfActor ); // 1. ParallelProjectionOn should be set after AddActor (otherwise call vtkRenderer::ResetCameraClippingRange // 2. ParallelProjectionOn is *necessary* for the vtkImplicitSelectionLoop // otherwise this give a cone instead of a cylinder cutting. _pRenderer->GetActiveCamera()->ParallelProjectionOn(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::ShowMARACASDataCT( marInterfaceCT* mar ){ int whd[3]; _marCT = mar; _marImageData = _marCT->getDynData()->getVolume()->castVtk(); _marImageData->GetDimensions( whd ); _width = whd[0]; _height = whd[1]; _depth = whd[2]; _marImageData->GetScalarRange( _range ); int a = (_marCT->GetExperiment())->getQuantStart(); //Outline v2: // An outline provides context around the data. _outLine = vtkOutlineFilter::New( ); _outLine->SetInput( _marImageData ); _outMapper = vtkPolyDataMapper::New( ); _outMapper->SetInput( _outLine->GetOutput( ) ); _outActor = vtkActor::New( ); _outActor->SetMapper( _outMapper ); _outActor->GetProperty( )->SetColor( 0.7, 0.0, 0.9 ); //_outActor->PickableOff( ); _pRenderer->AddActor( _outActor ); // Surface _mCubes = vtkMarchingCubes::New( ); _surfMapper = vtkPolyDataMapper::New( ); _surfActor = vtkActor::New( ); _mCubes->SetInput( _marImageData ); _mCubes->SetValue( 0, _range[1] / 4 ); vtkStripper *stripper = vtkStripper::New(); stripper->SetInput( _mCubes->GetOutput( ) ); _surfMapper->SetInput( stripper->GetOutput() ); _surfMapper->ScalarVisibilityOff( ); stripper->Delete(); _surfActor->SetMapper( _surfMapper ); _surfActor->PickableOff( ); _surfActor->GetProperty( )->SetColor( 0.9803, 0.9215, 0.8392 ); _surfActor->GetProperty( )->SetOpacity( 0.5 ); _pRenderer->AddActor( _surfActor ); // 1. ParallelProjectionOn should be set after AddActor (otherwise call vtkRenderer::ResetCameraClippingRange // 2. ParallelProjectionOn is *necessary* for the vtkImplicitSelectionLoop // otherwise this give a cone instead of a cylinder cutting. _pRenderer->GetActiveCamera()->ParallelProjectionOn(); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetInitialPoint(){ this->SetInitialPoint( _lastPickPoint, _lastCameraPos ); } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::SetInitialPoint( float* pickPoint, float* cameraPos ){ marDictionary marDict; char ttmp[256]; gtm::TVector< double > pO( 3 ), pF( 3 ), pp( 3 ), cp( 3 ); gtm::TVector< double > xc( 3 ); gtm::TVector< double > x1( 3 ), n1( 3 ); gtm::TVector< double > x2( 3 ), n2( 3 ); gtm::TVector< double > tmp( 3 ); double fac; bool success = true; int notSuccessType = 0; if( _centralLineActor ) { _pRenderer->RemoveActor( _centralLineActor ); _centralLineActor->Delete( ); } // fi if( _centralLineMapper ) _centralLineMapper->Delete( ); if( _centralLine ) _centralLine->Delete( ); _centralLine = NULL; _centralLineMapper = NULL; _centralLineActor = NULL; for(int i=0; i<4; i++) { if( _spheresActor[ i ] ) { _pRenderer->RemoveActor( _spheresActor[ i ] ); _spheresActor[ i ]->Delete( ); } // fi if( _spheresMapper[ i ] ) _spheresMapper[ i ]->Delete( ); if( _spheres[ i ] ) _spheres[ i ]->Delete( ); _spheres[ i ] = NULL; _spheresMapper[ i ] = NULL; _spheresActor[ i ] = NULL; } //rof fac = GTM_MAX( _width, _height ); fac = 2 * GTM_MAX( fac, _depth ); pp( 0 ) = pickPoint[ 0 ]; pp( 1 ) = pickPoint[ 1 ]; pp( 2 ) = pickPoint[ 2 ]; cp( 0 ) = cameraPos[ 0 ]; cp( 1 ) = cameraPos[ 1 ]; cp( 2 ) = cameraPos[ 2 ]; UtilVtk3DGeometriSelection utilVtk3DGeometriSelection; utilVtk3DGeometriSelection.SetDimentions(_width,_height,_depth); utilVtk3DGeometriSelection.SetMarchingCube(_mCubes); if( utilVtk3DGeometriSelection.FindCubePointsFromPoints( pO.GetAnsiRef( ), pF.GetAnsiRef( ), pp.GetAnsiRef( ), cp.GetAnsiRef( ) ) ) { if( utilVtk3DGeometriSelection.GetPointAndNormalIntersection( x1.GetAnsiRef( ), n1.GetAnsiRef( ), pO.GetAnsiRef( ), pF.GetAnsiRef( ) ) ) { if( utilVtk3DGeometriSelection.GetPointAndNormalIntersection( x2.GetAnsiRef( ), n2.GetAnsiRef( ), ( x1 - n1 ).GetAnsiRef( ), ( x1 - ( n1 * fac ) ).GetAnsiRef( ) ) ) { xc = ( x2 + x1 ) * 0.5; double dd=12; // EED ****** ATENTION **************** if (!( (xc(0)_experiment->setStartPoint( (int)xc( 0 ), (int)xc( 1 ), (int)xc( 2 ) ); _mar->_experiment->getParameters( )->setROIStep( 2*( xc - x1 ).GetNorm( ) ); for(int i=0; i<4; i++) { _spheres[ i ] = vtkSphereSource::New( ); _spheresMapper[ i ] = vtkPolyDataMapper::New( ); _spheresMapper[ i ]->SetInput( _spheres[ i ]->GetOutput( ) ); _spheresActor[ i ] = vtkActor::New( ); _spheresActor[ i ]->SetMapper( _spheresMapper[ i ] ); _spheresActor[ i ]->PickableOff( ); _pRenderer->AddActor( _spheresActor[ i ] ); } _spheres[ 0 ]->SetCenter( x1( 0 ), x1( 1 ), x1( 2 ) ); _spheres[ 1 ]->SetCenter( x2( 0 ), x2( 1 ), x2( 2 ) ); _spheres[ 2 ]->SetCenter( xc( 0 ), xc( 1 ), xc( 2 ) ); _spheres[ 3 ]->SetCenter( xc( 0 ), xc( 1 ), xc( 2 ) ); _spheres[ 0 ]->SetRadius( 0.5 ); _spheres[ 1 ]->SetRadius( 0.5 ); _spheres[ 2 ]->SetRadius( 0.5 ); _spheres[ 3 ]->SetRadius( ( xc - x1 ).GetNorm( ) ); _spheresActor[ 0 ]->GetProperty( )->SetColor( 1.0, 0.0, 0.0 ); _spheresActor[ 1 ]->GetProperty( )->SetColor( 0.0, 1.0, 0.0 ); _spheresActor[ 2 ]->GetProperty( )->SetColor( 0.0, 0.0, 1.0 ); _spheresActor[ 3 ]->GetProperty( )->SetColor( 1.0, 0.0, 0.0 ); _spheresActor[ 3 ]->GetProperty( )->SetOpacity( 0.3 ); vtkPoints* points = vtkPoints::New( ); points->InsertNextPoint( x1.GetAnsiRef( ) ); points->InsertNextPoint( x2.GetAnsiRef( ) ); vtkCellArray* array = vtkCellArray::New( ); array->InsertNextCell( 2 ); array->InsertCellPoint( 0 ); array->InsertCellPoint( 1 ); _centralLine = vtkPolyData::New( ); _centralLine->SetPoints( points ); _centralLine->SetLines( array ); points->Delete(); array->Delete(); _centralLineMapper = vtkPolyDataMapper::New( ); _centralLineMapper->SetInput( _centralLine ); _centralLineActor = vtkActor::New( ); _centralLineActor->SetMapper( _centralLineMapper ); _centralLineActor->GetProperty( )->SetColor( 1.0, 1.0, 1.0 ); _centralLineActor->PickableOff( ); _pRenderer->AddActor( _centralLineActor ); } else {success = false; notSuccessType=1; } } // fi } else success = false; } else success = false; // Show a message, if any. if (( !success ) && (notSuccessType==0)) { strcpy( ttmp , marDict.GetString(905) ); strcat( ttmp , "\n \n" ); strcat( ttmp , marDict.GetString(910) ); wxMessageBox( wxString(ttmp, wxConvUTF8) , // "Set an initial point.\n \n (Double click over the interest artery.)" _T("DxMM : MARACAS"), wxOK | wxCENTRE | wxICON_INFORMATION, this); } if ((!success ) && (notSuccessType==1)) { strcpy( ttmp , marDict.GetString(915) ); strcat( ttmp , "\n \n" ); strcat( ttmp , marDict.GetString(920) ); wxMessageBox( wxString(ttmp, wxConvUTF8), //"The initial point should be far \n of the limits of the volume." _T("DxMM : MARACAS"), wxOK | wxCENTRE | wxICON_INFORMATION, this); } // Finish _pRenderWindow->Render( ); InitialSphere = success; } //---------------------------------------------------------------------------- void vtk3DSurfaceWidget::ConfigureVTK( ) { // get render window _pRenderWindow = this->GetRenderWindow( ); // connect renderer and render window and configure render window _pRenderWindow->AddRenderer( _pRenderer ); // configure renderer _pRenderer->SetBackground( 0.0, 0.0, 0.0 ); //_pRenderer->SetBackground( 1, 1, 0); //FIXME _pRenderer->GetActiveCamera( )->Zoom( 1.0 ); _pRenderer->GetActiveCamera( )->SetClippingRange( 1, 1000 ); _pRenderer->ResetCamera( ); //EED 22Mai2007 // AttachRenderWindow(); } //---------------------------------------------------------------------------- vtkRenderer* vtk3DSurfaceWidget::GetRenderer(){ return _pRenderer; } //----------------------------------------------------------------------------