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 "mitkPaintbrushTool.h"
00019
00020 #include "mitkToolManager.h"
00021 #include "mitkOverwriteSliceImageFilter.h"
00022 #include "mitkBaseRenderer.h"
00023 #include "ipSegmentation.h"
00024
00025 #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
00026
00027 int mitk::PaintbrushTool::m_Size = 1;
00028
00029 mitk::PaintbrushTool::PaintbrushTool(int paintingPixelValue)
00030 :FeedbackContourTool("PressMoveReleaseWithCTRLInversionAllMouseMoves"),
00031 m_PaintingPixelValue(paintingPixelValue),
00032 m_LastContourSize(0)
00033 {
00034 m_MasterContour = Contour::New();
00035 m_MasterContour->Initialize();
00036
00037 }
00038
00039 mitk::PaintbrushTool::~PaintbrushTool()
00040 {
00041 }
00042
00043 void mitk::PaintbrushTool::Activated()
00044 {
00045 Superclass::Activated();
00046 FeedbackContourTool::SetFeedbackContourVisible(true);
00047 SizeChanged.Send(m_Size);
00048 }
00049
00050 void mitk::PaintbrushTool::Deactivated()
00051 {
00052 FeedbackContourTool::SetFeedbackContourVisible(false);
00053 Superclass::Deactivated();
00054 }
00055
00056 void mitk::PaintbrushTool::SetSize(int value)
00057 {
00058 m_Size = value;
00059 }
00060
00061 void mitk::PaintbrushTool::UpdateContour(const StateEvent* stateEvent)
00062 {
00063
00064 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00065 if (!positionEvent) return;
00066
00067 Image::Pointer m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
00068 if (m_WorkingSlice.IsNull()) return;
00069
00070
00071
00072
00073 itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
00074 CastToItkImage( m_WorkingSlice, correctPixelTypeImage );
00075 assert (correctPixelTypeImage.IsNotNull() );
00076
00077 itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection;
00078 imageDirection.SetIdentity();
00079 correctPixelTypeImage->SetDirection(imageDirection);
00080
00081 Image::Pointer temporarySlice = Image::New();
00082 CastToMitkImage( correctPixelTypeImage, temporarySlice );
00083
00084 mitkIpPicDescriptor* stupidClone = mitkIpPicClone( temporarySlice->GetSliceData()->GetPicDescriptor() );
00085 unsigned int pixelWidth = m_Size + 1;
00086 unsigned int pixelHeight = m_Size + 1;
00087
00088 if ( stupidClone->n[0] <= pixelWidth || stupidClone->n[1] <= pixelHeight )
00089 {
00090 MITK_INFO << "Brush size is bigger than your working image. Reconsider this...\n"
00091 "(Or tell your progammer until (s)he fixes this message.)" << std::endl;
00092 mitkIpPicFree( stupidClone );
00093 return;
00094 }
00095
00096 unsigned int lineLength( stupidClone->n[0] );
00097 unsigned int oneContourOffset(0);
00098 float circleCenterX = (float)m_Size / 2.0;
00099 float circleCenterY = (float)m_Size / 2.0;
00100 for (unsigned int x = 0; x <= pixelWidth; ++x)
00101 {
00102 for (unsigned int y = 0; y <= pixelHeight; ++y)
00103 {
00104 unsigned int offset = lineLength * y + x;
00105 ipMITKSegmentationTYPE* current = (ipMITKSegmentationTYPE*)stupidClone->data + offset;
00106
00107 float pixelCenterX = x + 0.5;
00108 float pixelCenterY = y + 0.5;
00109
00110 float xoff = pixelCenterX - circleCenterX;
00111 float yoff = pixelCenterY - circleCenterY;
00112
00113 bool inside = xoff * xoff + yoff * yoff < (m_Size * m_Size) / 4.0;
00114 if (inside)
00115 {
00116 *current = 1;
00117 oneContourOffset = offset;
00118 }
00119 else
00120 {
00121 *current = 0;
00122 }
00123 }
00124 }
00125
00126 int numberOfContourPoints( 0 );
00127 int newBufferSize( 0 );
00128 float* contourPoints = ipMITKSegmentationGetContour8N( stupidClone, oneContourOffset, numberOfContourPoints, newBufferSize );
00129 if (!contourPoints)
00130 {
00131 mitkIpPicFree( stupidClone );
00132 return;
00133 }
00134
00135
00136 Contour::Pointer contourInImageIndexCoordinates = Contour::New();
00137 contourInImageIndexCoordinates->Initialize();
00138 Point3D newPoint;
00139
00140
00141 for (int index = 0; index < numberOfContourPoints-1; ++index)
00142 {
00143 newPoint[0] = contourPoints[ 2 * index + 0 ] - circleCenterX;
00144 newPoint[1] = contourPoints[ 2 * index + 1] - circleCenterY;
00145 newPoint[2] = 0.0;
00146 MITK_DEBUG << "Point [" << index << "] (" << newPoint[0] << ", " << newPoint[1] << ")" << std::endl;
00147
00148 contourInImageIndexCoordinates->AddVertex( newPoint );
00149 }
00150
00151 free(contourPoints);
00152
00153 m_MasterContour = contourInImageIndexCoordinates;
00154
00155 mitkIpPicFree( stupidClone );
00156 }
00157
00158
00162 bool mitk::PaintbrushTool::OnMousePressed (Action* action, const StateEvent* stateEvent)
00163 {
00164 if (FeedbackContourTool::OnMousePressed( action, stateEvent ))
00165 {
00166 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00167 if (positionEvent)
00168 {
00169 UpdateContour( stateEvent );
00170 }
00171 }
00172
00173 return this->OnMouseMoved(action, stateEvent);
00174
00175
00176
00177
00178 }
00179
00180
00184 bool mitk::PaintbrushTool::OnMouseMoved (Action* itkNotUsed(action), const StateEvent* stateEvent)
00185 {
00186 bool leftMouseButtonPressed(
00187 stateEvent->GetId() == 530
00188 || stateEvent->GetId() == 1
00189 || stateEvent->GetId() == 5
00190 );
00191
00192 const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
00193 if (!positionEvent) return false;
00194
00195 if ( m_LastContourSize != m_Size )
00196 {
00197 UpdateContour( stateEvent );
00198 m_LastContourSize = m_Size;
00199 }
00200
00201 DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
00202 if (!workingNode) return false;
00203
00204 Image* image = dynamic_cast<Image*>(workingNode->GetData());
00205 const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
00206 if ( !image || !planeGeometry ) return false;
00207
00208 int affectedDimension( -1 );
00209 int affectedSlice( -1 );
00210 if ( !SegTool2D::DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ) ) return false;
00211
00212 Point3D worldCoordinates = positionEvent->GetWorldPosition();
00213 Point3D indexCoordinates;
00214 image->GetGeometry()->WorldToIndex( worldCoordinates, indexCoordinates );
00215 MITK_DEBUG << "Mouse at W " << worldCoordinates << std::endl;
00216 MITK_DEBUG << "Mouse at I " << indexCoordinates << std::endl;
00217
00218 unsigned int firstDimension(0);
00219 unsigned int secondDimension(1);
00220 switch( affectedDimension )
00221 {
00222 case 2:
00223 default:
00224 firstDimension = 0;
00225 secondDimension = 1;
00226 break;
00227 case 1:
00228 firstDimension = 0;
00229 secondDimension = 2;
00230 break;
00231 case 0:
00232 firstDimension = 1;
00233 secondDimension = 2;
00234 break;
00235 }
00236
00237
00238 if ( m_Size % 2 == 0 )
00239 {
00240 indexCoordinates[firstDimension] = ROUND( indexCoordinates[firstDimension] + 0.5 );
00241 indexCoordinates[secondDimension] = ROUND( indexCoordinates[secondDimension] + 0.5 );
00242 }
00243 else
00244 {
00245 indexCoordinates[firstDimension] = ROUND( indexCoordinates[firstDimension] ) ;
00246 indexCoordinates[secondDimension] = ROUND( indexCoordinates[secondDimension] );
00247 }
00248
00249 static Point3D lastPos;
00250 static bool lastLeftMouseButtonPressed(false);
00251 if ( fabs(indexCoordinates[0] - lastPos[0]) > mitk::eps ||
00252 fabs(indexCoordinates[1] - lastPos[1]) > mitk::eps ||
00253 fabs(indexCoordinates[2] - lastPos[2]) > mitk::eps ||
00254 leftMouseButtonPressed != lastLeftMouseButtonPressed
00255 )
00256 {
00257 lastPos = indexCoordinates;
00258 lastLeftMouseButtonPressed = leftMouseButtonPressed;
00259 }
00260 else
00261 {
00262 MITK_DEBUG << "." << std::flush;
00263 return false;
00264 }
00265
00266 MITK_DEBUG << "Mouse at C " << indexCoordinates;
00267
00268 Contour::Pointer contour = Contour::New();
00269 contour->Initialize();
00270 for (unsigned int index = 0; index < m_MasterContour->GetNumberOfPoints(); ++index)
00271 {
00272 Point3D point = m_MasterContour->GetPoints()->ElementAt(index);
00273 point[0] += indexCoordinates[ firstDimension ];
00274 point[1] += indexCoordinates[ secondDimension ];
00275
00276 MITK_DEBUG << "Contour point [" << index << "] :" << point;
00277 contour->AddVertex( point );
00278 }
00279
00280 Image::Pointer slice = SegTool2D::GetAffectedImageSliceAs2DImage( positionEvent, image );
00281 if ( slice.IsNull() ) return false;
00282
00283 if (leftMouseButtonPressed)
00284 {
00285 FeedbackContourTool::FillContourInSlice( contour, slice, m_PaintingPixelValue );
00286
00287 OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New();
00288 slicewriter->SetInput( image );
00289 slicewriter->SetCreateUndoInformation( true );
00290 slicewriter->SetSliceImage( slice );
00291 slicewriter->SetSliceDimension( affectedDimension );
00292 slicewriter->SetSliceIndex( affectedSlice );
00293 slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) );
00294 slicewriter->Update();
00295 }
00296
00297
00298 Contour::Pointer displayContour = Contour::New();
00299 displayContour->Initialize();
00300 for (unsigned int index = 0; index < contour->GetNumberOfPoints(); ++index)
00301 {
00302 Point3D point = contour->GetPoints()->ElementAt(index);
00303 if ( m_Size % 2 != 0 )
00304 {
00305 point[0] += 0.5;
00306 point[1] += 0.5;
00307 }
00308 displayContour->AddVertex( point );
00309 }
00310
00311 displayContour = FeedbackContourTool::BackProjectContourFrom2DSlice( slice, displayContour );
00312 SetFeedbackContour( *displayContour );
00313 assert( positionEvent->GetSender()->GetRenderWindow() );
00314
00315 RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
00316
00317 return true;
00318 }
00319
00320
00321 bool mitk::PaintbrushTool::OnMouseReleased(Action* , const StateEvent* )
00322 {
00323
00324
00325 return true;
00326 }
00327
00331 bool mitk::PaintbrushTool::OnInvertLogic(Action* action, const StateEvent* stateEvent)
00332 {
00333 if (!FeedbackContourTool::OnInvertLogic(action, stateEvent)) return false;
00334
00335
00336 if (m_PaintingPixelValue == 1)
00337 {
00338 m_PaintingPixelValue = 0;
00339 FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 );
00340 }
00341 else if (m_PaintingPixelValue == 0)
00342 {
00343 m_PaintingPixelValue = 1;
00344 FeedbackContourTool::SetFeedbackContourColorDefault();
00345 }
00346
00347 return true;
00348 }
00349