00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mitkSliceNavigationController.h"
00020 #include "mitkBaseRenderer.h"
00021 #include "mitkSlicedGeometry3D.h"
00022 #include "mitkPlaneGeometry.h"
00023 #include "mitkOperation.h"
00024 #include "mitkOperationActor.h"
00025 #include "mitkStateEvent.h"
00026 #include "mitkPositionEvent.h"
00027 #include "mitkInteractionConst.h"
00028 #include "mitkAction.h"
00029 #include "mitkGlobalInteraction.h"
00030 #include "mitkEventMapper.h"
00031 #include "mitkFocusManager.h"
00032 #include "mitkVtkPropRenderer.h"
00033 #include "mitkRenderingManager.h"
00034
00035 #include "mitkInteractionConst.h"
00036 #include "mitkPointOperation.h"
00037 #include "mitkPlaneOperation.h"
00038 #include "mitkUndoController.h"
00039 #include "mitkOperationEvent.h"
00040 #include "mitkNodePredicateDataType.h"
00041 #include "mitkStatusBar.h"
00042 #include <mitkIpPicTypeMultiplex.h>
00043
00044 #include "mitkMemoryUtilities.h"
00045
00046
00047 #include <itkCommand.h>
00048
00049 namespace mitk {
00050
00051 SliceNavigationController::SliceNavigationController( const char *type )
00052 : BaseController( type ),
00053 m_InputWorldGeometry( NULL ),
00054 m_CreatedWorldGeometry( NULL ),
00055 m_ViewDirection( Transversal ),
00056 m_DefaultViewDirection( Transversal ),
00057 m_RenderingManager( NULL ),
00058 m_Renderer( NULL ),
00059 m_Top( false ),
00060 m_FrontSide( false ),
00061 m_Rotated( false ),
00062 m_BlockUpdate( false ),
00063 m_SliceLocked( false ),
00064 m_SliceRotationLocked( false ),
00065 m_OldPos(0)
00066 {
00067 typedef itk::SimpleMemberCommand< SliceNavigationController > SNCCommandType;
00068 SNCCommandType::Pointer sliceStepperChangedCommand, timeStepperChangedCommand;
00069
00070 sliceStepperChangedCommand = SNCCommandType::New();
00071 timeStepperChangedCommand = SNCCommandType::New();
00072
00073 sliceStepperChangedCommand->SetCallbackFunction(
00074 this, &SliceNavigationController::SendSlice );
00075
00076 timeStepperChangedCommand->SetCallbackFunction(
00077 this, &SliceNavigationController::SendTime );
00078
00079 m_Slice->AddObserver( itk::ModifiedEvent(), sliceStepperChangedCommand );
00080 m_Time->AddObserver( itk::ModifiedEvent(), timeStepperChangedCommand );
00081
00082 m_Slice->SetUnitName( "mm" );
00083 m_Time->SetUnitName( "ms" );
00084
00085 m_Top = false;
00086 m_FrontSide = false;
00087 m_Rotated = false;
00088 }
00089
00090
00091 SliceNavigationController::~SliceNavigationController()
00092 {
00093 }
00094
00095
00096 void
00097 SliceNavigationController::SetInputWorldGeometry( const Geometry3D *geometry )
00098 {
00099 if ( geometry != NULL )
00100 {
00101 if ( const_cast< BoundingBox * >( geometry->GetBoundingBox())
00102 ->GetDiagonalLength2() < eps )
00103 {
00104 itkWarningMacro( "setting an empty bounding-box" );
00105 geometry = NULL;
00106 }
00107 }
00108 if ( m_InputWorldGeometry != geometry )
00109 {
00110 m_InputWorldGeometry = geometry;
00111 this->Modified();
00112 }
00113 }
00114
00115 RenderingManager *
00116 SliceNavigationController::GetRenderingManager() const
00117 {
00118 mitk::RenderingManager* renderingManager = m_RenderingManager.GetPointer();
00119
00120 if (renderingManager != NULL)
00121 return renderingManager;
00122
00123 if ( m_Renderer != NULL )
00124 {
00125 renderingManager = m_Renderer->GetRenderingManager();
00126
00127 if (renderingManager != NULL)
00128 return renderingManager;
00129 }
00130
00131 return mitk::RenderingManager::GetInstance();
00132 }
00133
00134
00135 void SliceNavigationController::SetViewDirectionToDefault()
00136 {
00137 m_ViewDirection = m_DefaultViewDirection;
00138 }
00139
00140 void SliceNavigationController::Update()
00141 {
00142 if ( !m_BlockUpdate )
00143 {
00144 if ( m_ViewDirection == Transversal )
00145 {
00146 this->Update( Transversal, false, false, true );
00147 }
00148 else
00149 {
00150 this->Update( m_ViewDirection );
00151 }
00152 }
00153 }
00154
00155 void
00156 SliceNavigationController::Update(
00157 SliceNavigationController::ViewDirection viewDirection,
00158 bool top, bool frontside, bool rotated )
00159 {
00160 const TimeSlicedGeometry* worldTimeSlicedGeometry =
00161 dynamic_cast< const TimeSlicedGeometry * >(
00162 m_InputWorldGeometry.GetPointer() );
00163
00164 if( m_BlockUpdate ||
00165 m_InputWorldGeometry.IsNull() ||
00166 ( (worldTimeSlicedGeometry != NULL) && (worldTimeSlicedGeometry->GetTimeSteps() == 0) )
00167 )
00168 {
00169 return;
00170 }
00171
00172 m_BlockUpdate = true;
00173
00174 if ( m_LastUpdateTime < m_InputWorldGeometry->GetMTime() )
00175 {
00176 Modified();
00177 }
00178
00179 this->SetViewDirection( viewDirection );
00180 this->SetTop( top );
00181 this->SetFrontSide( frontside );
00182 this->SetRotated( rotated );
00183
00184 if ( m_LastUpdateTime < GetMTime() )
00185 {
00186 m_LastUpdateTime = GetMTime();
00187
00188
00189 SlicedGeometry3D::Pointer slicedWorldGeometry = NULL;
00190
00191 m_CreatedWorldGeometry = NULL;
00192 switch ( viewDirection )
00193 {
00194 case Original:
00195 if ( worldTimeSlicedGeometry != NULL )
00196 {
00197 m_CreatedWorldGeometry = static_cast< TimeSlicedGeometry * >(
00198 m_InputWorldGeometry->Clone().GetPointer() );
00199
00200 worldTimeSlicedGeometry = m_CreatedWorldGeometry.GetPointer();
00201
00202 slicedWorldGeometry = dynamic_cast< SlicedGeometry3D * >(
00203 m_CreatedWorldGeometry->GetGeometry3D( this->GetTime()->GetPos() ) );
00204
00205 if ( slicedWorldGeometry.IsNotNull() )
00206 {
00207 break;
00208 }
00209 }
00210 else
00211 {
00212 const SlicedGeometry3D *worldSlicedGeometry =
00213 dynamic_cast< const SlicedGeometry3D * >(
00214 m_InputWorldGeometry.GetPointer());
00215
00216 if ( worldSlicedGeometry != NULL )
00217 {
00218 slicedWorldGeometry = static_cast< SlicedGeometry3D * >(
00219 m_InputWorldGeometry->Clone().GetPointer());
00220 break;
00221 }
00222 }
00223
00224
00225 case Transversal:
00226 slicedWorldGeometry = SlicedGeometry3D::New();
00227 slicedWorldGeometry->InitializePlanes(
00228 m_InputWorldGeometry, PlaneGeometry::Transversal,
00229 top, frontside, rotated );
00230 slicedWorldGeometry->SetSliceNavigationController( this );
00231 break;
00232
00233 case Frontal:
00234 slicedWorldGeometry = SlicedGeometry3D::New();
00235 slicedWorldGeometry->InitializePlanes( m_InputWorldGeometry,
00236 PlaneGeometry::Frontal, top, frontside, rotated );
00237 slicedWorldGeometry->SetSliceNavigationController( this );
00238 break;
00239
00240 case Sagittal:
00241 slicedWorldGeometry = SlicedGeometry3D::New();
00242 slicedWorldGeometry->InitializePlanes( m_InputWorldGeometry,
00243 PlaneGeometry::Sagittal, top, frontside, rotated );
00244 slicedWorldGeometry->SetSliceNavigationController( this );
00245 break;
00246 default:
00247 itkExceptionMacro("unknown ViewDirection");
00248 }
00249
00250 m_Slice->SetPos( 0 );
00251 m_Slice->SetSteps( (int)slicedWorldGeometry->GetSlices() );
00252
00253 if ( m_CreatedWorldGeometry.IsNull() )
00254 {
00255
00256 m_CreatedWorldGeometry = TimeSlicedGeometry::New();
00257 }
00258 if ( worldTimeSlicedGeometry == NULL )
00259 {
00260 m_CreatedWorldGeometry->InitializeEvenlyTimed( slicedWorldGeometry, 1 );
00261 m_Time->SetSteps( 0 );
00262 m_Time->SetPos( 0 );
00263 m_Time->InvalidateRange();
00264 }
00265 else
00266 {
00267 m_BlockUpdate = true;
00268 m_Time->SetSteps( worldTimeSlicedGeometry->GetTimeSteps() );
00269 m_Time->SetPos( 0 );
00270
00271 const TimeBounds &timeBounds = worldTimeSlicedGeometry->GetTimeBounds();
00272 m_Time->SetRange( timeBounds[0], timeBounds[1] );
00273
00274 m_BlockUpdate = false;
00275
00276 assert( worldTimeSlicedGeometry->GetGeometry3D( this->GetTime()->GetPos() ) != NULL );
00277
00278 slicedWorldGeometry->SetTimeBounds(
00279 worldTimeSlicedGeometry->GetGeometry3D( this->GetTime()->GetPos() )->GetTimeBounds() );
00280
00281
00282 m_CreatedWorldGeometry->InitializeEvenlyTimed(
00283 slicedWorldGeometry, worldTimeSlicedGeometry->GetTimeSteps() );
00284 }
00285 }
00286
00287
00288
00289 m_BlockUpdate = false;
00290
00291
00292
00293 this->SendCreatedWorldGeometry();
00294 this->SendSlice();
00295 this->SendTime();
00296
00297
00298 this->AdjustSliceStepperRange();
00299 }
00300
00301 void
00302 SliceNavigationController::SendCreatedWorldGeometry()
00303 {
00304
00305
00306 if ( !m_BlockUpdate )
00307 {
00308 this->InvokeEvent( GeometrySendEvent(m_CreatedWorldGeometry, 0) );
00309 }
00310 }
00311
00312 void
00313 SliceNavigationController::SendCreatedWorldGeometryUpdate()
00314 {
00315 if ( !m_BlockUpdate )
00316 {
00317 this->InvokeEvent(
00318 GeometryUpdateEvent(m_CreatedWorldGeometry, m_Slice->GetPos()) );
00319 }
00320 }
00321
00322 void
00323 SliceNavigationController::SendSlice()
00324 {
00325 if ( !m_BlockUpdate )
00326 {
00327 if ( m_CreatedWorldGeometry.IsNotNull() )
00328 {
00329 this->InvokeEvent(
00330 GeometrySliceEvent(m_CreatedWorldGeometry, m_Slice->GetPos()) );
00331
00332
00333 this->GetRenderingManager()->RequestUpdateAll();
00334 }
00335 }
00336 }
00337
00338 void
00339 SliceNavigationController::SendTime()
00340 {
00341 if ( !m_BlockUpdate )
00342 {
00343 if ( m_CreatedWorldGeometry.IsNotNull() )
00344 {
00345 this->InvokeEvent(
00346 GeometryTimeEvent(m_CreatedWorldGeometry, m_Time->GetPos()) );
00347
00348
00349 this->GetRenderingManager()->RequestUpdateAll();
00350 }
00351 }
00352 }
00353
00354 void
00355 SliceNavigationController::SetGeometry( const itk::EventObject & )
00356 {
00357 }
00358
00359 void
00360 SliceNavigationController
00361 ::SetGeometryTime( const itk::EventObject &geometryTimeEvent )
00362 {
00363 const SliceNavigationController::GeometryTimeEvent *timeEvent =
00364 dynamic_cast< const SliceNavigationController::GeometryTimeEvent * >(
00365 &geometryTimeEvent);
00366
00367 assert( timeEvent != NULL );
00368
00369 TimeSlicedGeometry *timeSlicedGeometry = timeEvent->GetTimeSlicedGeometry();
00370 assert( timeSlicedGeometry != NULL );
00371
00372 if ( m_CreatedWorldGeometry.IsNotNull() )
00373 {
00374 int timeStep = (int) timeEvent->GetPos();
00375 ScalarType timeInMS;
00376 timeInMS = timeSlicedGeometry->TimeStepToMS( timeStep );
00377 timeStep = m_CreatedWorldGeometry->MSToTimeStep( timeInMS );
00378 this->GetTime()->SetPos( timeStep );
00379 }
00380 }
00381
00382 void
00383 SliceNavigationController
00384 ::SetGeometrySlice(const itk::EventObject & geometrySliceEvent)
00385 {
00386 const SliceNavigationController::GeometrySliceEvent* sliceEvent =
00387 dynamic_cast<const SliceNavigationController::GeometrySliceEvent *>(
00388 &geometrySliceEvent);
00389 assert(sliceEvent!=NULL);
00390
00391 this->GetSlice()->SetPos(sliceEvent->GetPos());
00392 }
00393
00394 void
00395 SliceNavigationController::SelectSliceByPoint( const Point3D &point )
00396 {
00397
00398 SlicedGeometry3D* slicedWorldGeometry = dynamic_cast< SlicedGeometry3D * >(
00399 m_CreatedWorldGeometry->GetGeometry3D( this->GetTime()->GetPos() ) );
00400
00401 if ( slicedWorldGeometry )
00402 {
00403 int bestSlice = -1;
00404 double bestDistance = itk::NumericTraits<double>::max();
00405
00406 int s, slices;
00407 slices = slicedWorldGeometry->GetSlices();
00408 if ( slicedWorldGeometry->GetEvenlySpaced() )
00409 {
00410 mitk::Geometry2D *plane = slicedWorldGeometry->GetGeometry2D( 0 );
00411
00412 const Vector3D &direction = slicedWorldGeometry->GetDirectionVector();
00413
00414 Point3D projectedPoint;
00415 plane->Project( point, projectedPoint );
00416
00417
00418
00419 if ( direction[0] * (point[0] - projectedPoint[0])
00420 + direction[1] * (point[1] - projectedPoint[1])
00421 + direction[2] * (point[2] - projectedPoint[2]) >= 0 )
00422 {
00423 bestSlice = (int)(plane->Distance( point )
00424 / slicedWorldGeometry->GetSpacing()[2] + 0.5);
00425 }
00426 }
00427 else
00428 {
00429 Point3D projectedPoint;
00430 for ( s = 0; s < slices; ++s )
00431 {
00432 slicedWorldGeometry->GetGeometry2D( s )->Project( point, projectedPoint );
00433 Vector3D distance = projectedPoint - point;
00434 ScalarType currentDistance = distance.GetSquaredNorm();
00435
00436 if ( currentDistance < bestDistance )
00437 {
00438 bestDistance = currentDistance;
00439 bestSlice = s;
00440 }
00441 }
00442 }
00443 if ( bestSlice >= 0 )
00444 {
00445 this->GetSlice()->SetPos( bestSlice );
00446 }
00447 else
00448 {
00449 this->GetSlice()->SetPos( 0 );
00450 }
00451 this->SendCreatedWorldGeometryUpdate();
00452 }
00453 }
00454
00455
00456 void
00457 SliceNavigationController::ReorientSlices( const Point3D &point,
00458 const Vector3D &normal )
00459 {
00460 PlaneOperation op( OpORIENT, point, normal );
00461
00462 m_CreatedWorldGeometry->ExecuteOperation( &op );
00463
00464 this->SendCreatedWorldGeometryUpdate();
00465 }
00466
00467
00468 const mitk::TimeSlicedGeometry *
00469 SliceNavigationController::GetCreatedWorldGeometry()
00470 {
00471 return m_CreatedWorldGeometry;
00472 }
00473
00474
00475 const mitk::Geometry3D *
00476 SliceNavigationController::GetCurrentGeometry3D()
00477 {
00478 if ( m_CreatedWorldGeometry.IsNotNull() )
00479 {
00480 return m_CreatedWorldGeometry->GetGeometry3D( this->GetTime()->GetPos() );
00481 }
00482 else
00483 {
00484 return NULL;
00485 }
00486 }
00487
00488
00489 const mitk::PlaneGeometry *
00490 SliceNavigationController::GetCurrentPlaneGeometry()
00491 {
00492 const mitk::SlicedGeometry3D *slicedGeometry =
00493 dynamic_cast< const mitk::SlicedGeometry3D * >
00494 ( this->GetCurrentGeometry3D() );
00495
00496 if ( slicedGeometry )
00497 {
00498 const mitk::PlaneGeometry *planeGeometry =
00499 dynamic_cast< mitk::PlaneGeometry * >
00500 ( slicedGeometry->GetGeometry2D(this->GetSlice()->GetPos()) );
00501 return planeGeometry;
00502 }
00503 else
00504 {
00505 return NULL;
00506 }
00507 }
00508
00509
00510 void
00511 SliceNavigationController::SetRenderer( BaseRenderer *renderer )
00512 {
00513 m_Renderer = renderer;
00514 }
00515
00516 BaseRenderer *
00517 SliceNavigationController::GetRenderer() const
00518 {
00519 return m_Renderer;
00520 }
00521
00522
00523
00524 void
00525 SliceNavigationController::AdjustSliceStepperRange()
00526 {
00527 const mitk::SlicedGeometry3D *slicedGeometry =
00528 dynamic_cast< const mitk::SlicedGeometry3D * >
00529 ( this->GetCurrentGeometry3D() );
00530
00531 const Vector3D &direction = slicedGeometry->GetDirectionVector();
00532
00533 int c = 0;
00534 int i, k = 0;
00535 for ( i = 0; i < 3; ++i )
00536 {
00537 if ( fabs( (float) direction[i] ) < 0.000000001 ) { ++c; }
00538 else { k = i; }
00539 }
00540
00541 if ( c == 2 )
00542 {
00543 ScalarType min = m_InputWorldGeometry->GetOrigin()[k];
00544 ScalarType max = min + m_InputWorldGeometry->GetExtentInMM( k );
00545
00546 m_Slice->SetRange( min, max );
00547 }
00548 else
00549 {
00550 m_Slice->InvalidateRange();
00551 }
00552
00553 }
00554
00555
00556 void
00557 SliceNavigationController::ExecuteOperation( Operation *operation )
00558 {
00559
00560
00561
00562 if ( !operation )
00563 {
00564 return;
00565 }
00566
00567 switch ( operation->GetOperationType() )
00568 {
00569 case OpMOVE:
00570 {
00571 if ( !m_SliceLocked )
00572 {
00573
00574 PointOperation *po = dynamic_cast< PointOperation * >( operation );
00575 if ( po && po->GetIndex() == -1 )
00576 {
00577 this->SelectSliceByPoint( po->GetPoint() );
00578 }
00579 else if ( po && po->GetIndex() != -1 )
00580 {
00581 this->GetSlice()->SetPos( po->GetIndex() );
00582 }
00583 }
00584 break;
00585 }
00586 default:
00587 {
00588
00589 break;
00590 }
00591 }
00592 }
00593
00594
00595
00596
00597 bool
00598 SliceNavigationController
00599 ::ExecuteAction( Action* action, StateEvent const* stateEvent )
00600 {
00601 bool ok = false;
00602
00603 const PositionEvent* posEvent = dynamic_cast< const PositionEvent * >(
00604 stateEvent->GetEvent() );
00605 if ( posEvent != NULL )
00606 {
00607 if ( m_CreatedWorldGeometry.IsNull() )
00608 {
00609 return true;
00610 }
00611 switch (action->GetActionId())
00612 {
00613 case AcMOVE:
00614 {
00615 BaseRenderer *baseRenderer = posEvent->GetSender();
00616 if ( !baseRenderer )
00617 {
00618 baseRenderer = const_cast<BaseRenderer *>(
00619 GlobalInteraction::GetInstance()->GetFocus() );
00620 }
00621 if ( baseRenderer )
00622 if ( baseRenderer->GetMapperID() == 1 )
00623 {
00624 PointOperation* doOp = new mitk::PointOperation(OpMOVE, posEvent->GetWorldPosition());
00625 if (m_UndoEnabled)
00626 {
00627 m_OldPos = this->GetSlice()->GetPos();
00628
00629 PointOperation* undoOp = new mitk::PointOperation(OpMOVE, posEvent->GetWorldPosition(), m_OldPos);
00630 OperationEvent *operationEvent = new mitk::OperationEvent(this, doOp, undoOp, "Move slices");
00631 m_UndoController->SetOperationEvent(operationEvent);
00632 }
00633
00634 this->ExecuteOperation( doOp );
00635
00636
00637 if(baseRenderer == m_Renderer)
00638 {
00639 {
00640 std::string statusText;
00641 TNodePredicateDataType<mitk::Image>::Pointer isImageData = TNodePredicateDataType<mitk::Image>::New();
00642
00643 mitk::DataStorage::SetOfObjects::ConstPointer nodes = baseRenderer->GetDataStorage()->GetSubset(isImageData).GetPointer();
00644 mitk::Point3D worldposition = posEvent->GetWorldPosition();
00645 int maxlayer = -32768;
00646 mitk::Image::Pointer image3D;
00647
00648 for (unsigned int x = 0; x < nodes->size(); x++)
00649 {
00650 if(nodes->at(x)->GetData()->GetGeometry()->IsInside(worldposition))
00651 {
00652 int layer = 0;
00653 if(!(nodes->at(x)->GetIntProperty("layer", layer))) continue;
00654 if(layer > maxlayer)
00655 {
00656 if(static_cast<mitk::DataNode::Pointer>(nodes->at(x))->IsVisible(m_Renderer))
00657 {
00658 image3D = dynamic_cast<mitk::Image*>(nodes->at(x)->GetData());
00659 maxlayer = layer;
00660 }
00661 }
00662 }
00663 }
00664
00665 std::stringstream stream;
00666
00667
00668 if(image3D.IsNotNull())
00669 {
00670 Index3D p;
00671 image3D->GetGeometry()->WorldToIndex(worldposition, p);
00672 stream.precision(2);
00673 stream<<"Position: <" << std::fixed <<worldposition[0] << ", " << std::fixed << worldposition[1] << ", " << std::fixed << worldposition[2] << "> mm";
00674 stream<<"; Index: <"<<p[0] << ", " << p[1] << ", " << p[2] << "> ";
00675 stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: "<<image3D->GetPixelValueByIndex(p, baseRenderer->GetTimeStep())<<" ";
00676 }
00677 else
00678 {
00679 stream << "No image information at this position!";
00680 }
00681
00682 statusText = stream.str();
00683 mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str());
00684
00685 }
00686
00687 }
00688 ok = true;
00689 break;
00690 }
00691 }
00692 default:
00693 ok = true;
00694 break;
00695 }
00696 return ok;
00697 }
00698
00699 const DisplayPositionEvent *displPosEvent =
00700 dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() );
00701
00702 if ( displPosEvent != NULL )
00703 {
00704 return true;
00705 }
00706
00707 return false;
00708 }
00709
00710 }
00711