Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkSegTool2D.h"
00019 #include "mitkToolManager.h"
00020
00021 #include "mitkDataStorage.h"
00022 #include "mitkBaseRenderer.h"
00023
00024 #include "mitkPlaneGeometry.h"
00025
00026 #include "mitkExtractImageFilter.h"
00027
00028 #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
00029
00030 mitk::SegTool2D::SegTool2D(const char* type)
00031 :Tool(type),
00032 m_LastEventSender(NULL),
00033 m_LastEventSlice(0)
00034 {
00035
00036 CONNECT_ACTION( 80, OnMousePressed );
00037 CONNECT_ACTION( 90, OnMouseMoved );
00038 CONNECT_ACTION( 42, OnMouseReleased );
00039 CONNECT_ACTION( 49014, OnInvertLogic );
00040 }
00041
00042 mitk::SegTool2D::~SegTool2D()
00043 {
00044 }
00045
00046 bool mitk::SegTool2D::OnMousePressed (Action*, const StateEvent* stateEvent)
00047 {
00048 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00049 if (!positionEvent) return false;
00050
00051 if ( positionEvent->GetSender()->GetMapperID() != BaseRenderer::Standard2D ) return false;
00052
00053 m_LastEventSender = positionEvent->GetSender();
00054 m_LastEventSlice = m_LastEventSender->GetSlice();
00055
00056 return true;
00057 }
00058
00059 bool mitk::SegTool2D::OnMouseMoved (Action*, const StateEvent* stateEvent)
00060 {
00061 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00062 if (!positionEvent) return false;
00063
00064 if ( m_LastEventSender != positionEvent->GetSender() ) return false;
00065 if ( m_LastEventSlice != m_LastEventSender->GetSlice() ) return false;
00066
00067 return true;
00068 }
00069
00070 bool mitk::SegTool2D::OnMouseReleased(Action*, const StateEvent* stateEvent)
00071 {
00072 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00073 if (!positionEvent) return false;
00074
00075 if ( m_LastEventSender != positionEvent->GetSender() ) return false;
00076 if ( m_LastEventSlice != m_LastEventSender->GetSlice() ) return false;
00077
00078 return true;
00079 }
00080
00081 bool mitk::SegTool2D::OnInvertLogic(Action*, const StateEvent* stateEvent)
00082 {
00083 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00084 if (!positionEvent) return false;
00085
00086 if ( m_LastEventSender != positionEvent->GetSender() ) return false;
00087 if ( m_LastEventSlice != m_LastEventSender->GetSlice() ) return false;
00088
00089 return true;
00090 }
00091
00092 bool mitk::SegTool2D::DetermineAffectedImageSlice( const Image* image, const PlaneGeometry* plane, int& affectedDimension, int& affectedSlice )
00093 {
00094 assert(image);
00095 assert(plane);
00096
00097
00098 Vector3D normal = plane->GetNormal();
00099 Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0);
00100 Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1);
00101 Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2);
00102
00103 normal.Normalize();
00104 imageNormal0.Normalize();
00105 imageNormal1.Normalize();
00106 imageNormal2.Normalize();
00107
00108 imageNormal0.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal0.Get_vnl_vector()) );
00109 imageNormal1.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal1.Get_vnl_vector()) );
00110 imageNormal2.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal2.Get_vnl_vector()) );
00111
00112 double eps( 0.00001 );
00113
00114 if ( imageNormal2.GetNorm() <= eps )
00115 {
00116 affectedDimension = 2;
00117 }
00118
00119 else if ( imageNormal1.GetNorm() <= eps )
00120 {
00121 affectedDimension = 1;
00122 }
00123
00124 else if ( imageNormal0.GetNorm() <= eps )
00125 {
00126 affectedDimension = 0;
00127 }
00128 else
00129 {
00130 affectedDimension = -1;
00131 return false;
00132 }
00133
00134
00135 Geometry3D* imageGeometry = image->GetGeometry(0);
00136 Point3D testPoint = imageGeometry->GetCenter();
00137 Point3D projectedPoint;
00138 plane->Project( testPoint, projectedPoint );
00139
00140 Point3D indexPoint;
00141
00142 imageGeometry->WorldToIndex( projectedPoint, indexPoint );
00143 affectedSlice = ROUND( indexPoint[affectedDimension] );
00144 MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice;
00145
00146
00147 if ( affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)) ) return false;
00148
00149 return true;
00150 }
00151
00152 mitk::Image::Pointer mitk::SegTool2D::GetAffectedImageSliceAs2DImage(const PositionEvent* positionEvent, const Image* image)
00153 {
00154 if (!positionEvent) return NULL;
00155
00156 assert( positionEvent->GetSender() );
00157 unsigned int timeStep = positionEvent->GetSender()->GetTimeStep( image );
00158
00159
00160 const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
00161
00162 if ( !image || !planeGeometry ) return NULL;
00163
00164 int affectedDimension( -1 );
00165 int affectedSlice( -1 );
00166 if ( DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ) )
00167 {
00168 try
00169 {
00170
00171 ExtractImageFilter::Pointer extractor= ExtractImageFilter::New();
00172 extractor->SetInput( image );
00173 extractor->SetSliceDimension( affectedDimension );
00174 extractor->SetSliceIndex( affectedSlice );
00175 extractor->SetTimeStep( timeStep );
00176 extractor->Update();
00177
00178
00179 Image::Pointer slice = extractor->GetOutput();
00180
00181 return slice;
00182 }
00183 catch(...)
00184 {
00185
00186 return NULL;
00187 }
00188 }
00189 else
00190 {
00191 return NULL;
00192 }
00193 }
00194
00195 mitk::Image::Pointer mitk::SegTool2D::GetAffectedWorkingSlice(const PositionEvent* positionEvent)
00196 {
00197 DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
00198 if ( !workingNode ) return NULL;
00199
00200 Image* workingImage = dynamic_cast<Image*>(workingNode->GetData());
00201 if ( !workingImage ) return NULL;
00202
00203 return GetAffectedImageSliceAs2DImage( positionEvent, workingImage );
00204 }
00205
00206 mitk::Image::Pointer mitk::SegTool2D::GetAffectedReferenceSlice(const PositionEvent* positionEvent)
00207 {
00208 DataNode* referenceNode( m_ToolManager->GetReferenceData(0) );
00209 if ( !referenceNode ) return NULL;
00210
00211 Image* referenceImage = dynamic_cast<Image*>(referenceNode->GetData());
00212 if ( !referenceImage ) return NULL;
00213
00214 return GetAffectedImageSliceAs2DImage( positionEvent, referenceImage );
00215 }
00216
00217 void mitk::SegTool2D::InteractiveSegmentationBugMessage( const std::string& message )
00218 {
00219 MITK_ERROR << "********************************************************************************" << std::endl
00220 << " " << message << std::endl
00221 << "********************************************************************************" << std::endl
00222 << " " << std::endl
00223 << " If your image is rotated or the 2D views don't really contain the patient image, try to press the button next to the image selection. " << std::endl
00224 << " " << std::endl
00225 << " Please file a BUG REPORT: " << std::endl
00226 << " http://bugs.mitk.org" << std::endl
00227 << " Contain the following information:" << std::endl
00228 << " - What image were you working on?" << std::endl
00229 << " - Which region of the image?" << std::endl
00230 << " - Which tool did you use?" << std::endl
00231 << " - What did you do?" << std::endl
00232 << " - What happened (not)? What did you expect?" << std::endl;
00233 }
00234