00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <mitkSlicesRotator.h>
00020 #include <mitkSliceNavigationController.h>
00021
00022 #include <mitkStateEvent.h>
00023 #include <mitkAction.h>
00024 #include <mitkInteractionConst.h>
00025 #include <mitkDisplayPositionEvent.h>
00026 #include <mitkRotationOperation.h>
00027
00028 #include <mitkBaseRenderer.h>
00029 #include <mitkRenderingManager.h>
00030
00031 #include <mitkLine.h>
00032 #include <mitkGeometry3D.h>
00033 #include <mitkGeometry2D.h>
00034 #include <mitkPlaneGeometry.h>
00035 #include <mitkDisplayGeometry.h>
00036 #include <mitkSlicedGeometry3D.h>
00037 #include <mitkTimeSlicedGeometry.h>
00038
00039 #include <vtkLinearTransform.h>
00040
00041 #include <math.h>
00042
00043 #include "rotate_cursor.xpm"
00044
00045 namespace mitk {
00046
00047 SlicesRotator::Pointer SlicesRotator::New()
00048 {
00049 return SlicesRotator::New("slices-rotator");
00050 }
00051
00052 SlicesRotator::SlicesRotator(const char* machine)
00053 : SlicesCoordinator(machine)
00054 {
00055
00056 }
00057
00058 SlicesRotator::~SlicesRotator()
00059 {
00060
00061 }
00062
00063
00064
00065 void SlicesRotator::OnSliceControllerAdded(SliceNavigationController* snc)
00066 {
00067 if (!snc) return;
00068
00069 snc->ConnectGeometrySendEvent(this);
00070 }
00071
00072
00073 void SlicesRotator::OnSliceControllerRemoved(SliceNavigationController* snc)
00074 {
00075 if (!snc) return;
00076
00077 }
00078
00081 void SlicesRotator::SetGeometry(const itk::EventObject& )
00082 {
00083
00084
00085 UpdateRelevantSNCs();
00086 }
00087
00088
00089 void SlicesRotator::RotateToPoint( SliceNavigationController *rotationPlaneSNC,
00090 SliceNavigationController *rotatedPlaneSNC,
00091 const Point3D &point, bool linked )
00092 {
00093 SliceNavigationController *thirdSNC = NULL;
00094
00095 SNCVector::iterator iter;
00096 for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter )
00097 {
00098 if ( ((*iter) != rotationPlaneSNC)
00099 && ((*iter) != rotatedPlaneSNC) )
00100 {
00101 thirdSNC = *iter;
00102 break;
00103 }
00104 }
00105
00106 if ( thirdSNC == NULL )
00107 {
00108 return;
00109 }
00110
00111 const PlaneGeometry *rotationPlane = rotationPlaneSNC->GetCurrentPlaneGeometry();
00112 const PlaneGeometry *rotatedPlane = rotatedPlaneSNC->GetCurrentPlaneGeometry();
00113 const PlaneGeometry *thirdPlane = thirdSNC->GetCurrentPlaneGeometry();
00114
00115 if ( (rotationPlane == NULL) || (rotatedPlane == NULL)
00116 || (thirdPlane == NULL) )
00117 {
00118 return;
00119 }
00120
00121 if ( rotatedPlane->DistanceFromPlane( point ) < 0.001 )
00122 {
00123
00124 return;
00125 }
00126
00127 Point3D projectedPoint;
00128 Line3D intersection;
00129 Point3D rotationCenter;
00130
00131 if ( !rotationPlane->Project( point, projectedPoint )
00132 || !rotationPlane->IntersectionLine( rotatedPlane, intersection )
00133 || !thirdPlane->IntersectionPoint( intersection, rotationCenter ) )
00134 {
00135 return;
00136 }
00137
00138
00139
00140
00141 Point3D referencePoint = intersection.Project( projectedPoint );
00142
00143
00144 Vector3D toProjected = referencePoint - rotationCenter;
00145 Vector3D toCursor = projectedPoint - rotationCenter;
00146
00147
00148 Vector3D axisOfRotation;
00149 vnl_vector_fixed< ScalarType, 3 > vnlDirection =
00150 vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() );
00151 axisOfRotation.SetVnlVector( vnlDirection );
00152
00153
00154
00155 ScalarType angle = - atan2(
00156 (double)(axisOfRotation.GetNorm()),
00157 (double)(toCursor * toProjected) );
00158 angle *= 180.0 / vnl_math::pi;
00159
00160
00161 RotationOperation op(OpROTATE, rotationCenter, axisOfRotation, angle);
00162
00163 if ( !linked )
00164 {
00165 BaseRenderer *renderer = rotatedPlaneSNC->GetRenderer();
00166 if ( renderer == NULL )
00167 {
00168 return;
00169 }
00170
00171 DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
00172
00173 Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
00174 displayGeometry->Map( rotationCenter, point2DWorld );
00175 displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );
00176
00177 const Geometry3D *geometry3D = rotatedPlaneSNC->GetCreatedWorldGeometry();
00178 const TimeSlicedGeometry *timeSlicedGeometry =
00179 dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
00180 if ( !timeSlicedGeometry )
00181 {
00182 return;
00183 }
00184
00185 const_cast< TimeSlicedGeometry * >( timeSlicedGeometry )->ExecuteOperation( &op );
00186
00187 displayGeometry->Map( rotationCenter, point2DWorld );
00188 displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
00189 Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;
00190
00191 Vector2D origin = displayGeometry->GetOriginInMM();
00192
00193 displayGeometry->MoveBy( vector2DDisplayDiff );
00194
00195 rotatedPlaneSNC->SendCreatedWorldGeometryUpdate();
00196 }
00197 else
00198 {
00199 SNCVector::iterator iter;
00200 for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter )
00201 {
00202 BaseRenderer *renderer = (*iter)->GetRenderer();
00203 if ( renderer == NULL )
00204 {
00205 continue;
00206 }
00207
00208 DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
00209
00210 Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
00211 displayGeometry->Map( rotationCenter, point2DWorld );
00212 displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );
00213
00214 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00215 const TimeSlicedGeometry *timeSlicedGeometry =
00216 dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
00217 if ( !timeSlicedGeometry )
00218 {
00219 continue;
00220 }
00221
00222 const_cast< TimeSlicedGeometry * >( timeSlicedGeometry )->ExecuteOperation( &op );
00223
00224 displayGeometry->Map( rotationCenter, point2DWorld );
00225 displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
00226 Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;
00227
00228 Vector2D origin = displayGeometry->GetOriginInMM();
00229
00230 displayGeometry->MoveBy( vector2DDisplayDiff );
00231
00232 (*iter)->SendCreatedWorldGeometryUpdate();
00233 }
00234 }
00235 }
00236
00237
00239 void SlicesRotator::UpdateRelevantSNCs()
00240 {
00241 m_RelevantSNCs.clear();
00242
00243 for (SNCVector::iterator iter = m_SliceNavigationControllers.begin(); iter != m_SliceNavigationControllers.end(); ++iter)
00244 {
00245 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00246 const TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
00247 if (!timeSlicedGeometry) continue;
00248
00249 const SlicedGeometry3D* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>( timeSlicedGeometry->GetGeometry3D(0) );
00250 if (!slicedGeometry) continue;
00251
00252 Geometry2D* firstSlice(NULL);
00253 Geometry2D* secondSlice(NULL);
00254 if (slicedGeometry->IsValidSlice(0)) firstSlice = slicedGeometry->GetGeometry2D(0);
00255 if (slicedGeometry->IsValidSlice(1)) secondSlice = slicedGeometry->GetGeometry2D(1);
00256
00257
00258 Vector3D right1 = firstSlice->GetAxisVector(0);
00259 Vector3D up1 = firstSlice->GetAxisVector(1);
00260 vnl_vector_fixed< ScalarType, 3 > vnlDirection1 = vnl_cross_3d(right1.GetVnlVector(), up1.GetVnlVector());
00261 Vector3D direction1;
00262 direction1.SetVnlVector(vnlDirection1);
00263
00264 Vector3D right2 = firstSlice->GetAxisVector(0);
00265 Vector3D up2 = firstSlice->GetAxisVector(1);
00266 vnl_vector_fixed< ScalarType, 3 > vnlDirection2 = vnl_cross_3d(right2.GetVnlVector(), up2.GetVnlVector());
00267 Vector3D direction2;
00268 direction2.SetVnlVector(vnlDirection2);
00269
00270 bool equal = true;
00271 const ScalarType eps = 0.0001;
00272 for (int i = 0; i < 3; ++i)
00273 if ( fabs(direction1[i] - direction2[i]) > eps )
00274 equal = false;
00275
00276 if (equal)
00277 {
00278 m_RelevantSNCs.push_back( *iter );
00279 }
00280 }
00281 }
00282
00283 bool SlicesRotator::ExecuteAction(Action* action, StateEvent const* stateEvent)
00284 {
00285 const ScalarType ThreshHoldDistancePixels = 12.0;
00286
00287 bool ok = false;
00288
00289 switch ( action->GetActionId() )
00290 {
00291 case AcMOVE:
00292 {
00293
00294 for (SNCVector::iterator iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter)
00295 {
00296 if ( !(*iter)->GetSliceLocked() )
00297 {
00298 (*iter)->ExecuteAction(action, stateEvent);
00299 }
00300 }
00301
00302 ok = true;
00303 break;
00304 }
00305 case AcROTATE:
00306 {
00307 const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
00308 if (!posEvent) break;
00309
00310 Point3D cursor = posEvent->GetWorldPosition();
00311
00312 Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
00313 Vector3D toCursor = cursor - m_CenterOfRotation;
00314
00315
00316 Vector3D axisOfRotation;
00317 vnl_vector_fixed< ScalarType, 3 > vnlDirection = vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() );
00318 axisOfRotation.SetVnlVector(vnlDirection);
00319
00320
00321
00322 ScalarType angle = - atan2( (double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected) );
00323 angle *= 180.0 / vnl_math::pi;
00324 m_LastCursorPosition = cursor;
00325
00326
00327 RotationOperation op(OpROTATE, m_CenterOfRotation, axisOfRotation, angle);
00328
00329
00330 int i = 0;
00331
00332 for (SNCVector::iterator iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
00333 {
00334 BaseRenderer *renderer = (*iter)->GetRenderer();
00335 if ( renderer == NULL )
00336 {
00337 continue;
00338 }
00339
00340 DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();
00341
00342
00343
00344 Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
00345 displayGeometry->Map( m_CenterOfRotation, point2DWorld );
00346 displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );
00347
00348
00349
00350 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00351 const TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>(geometry3D);
00352 if (!timeSlicedGeometry) continue;
00353
00354 const_cast<TimeSlicedGeometry*>(timeSlicedGeometry)->ExecuteOperation(&op);
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00373
00374
00375
00376
00377
00378
00379
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 displayGeometry->Map( m_CenterOfRotation, point2DWorld );
00392 displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
00393 Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;
00394
00395 Vector2D origin = displayGeometry->GetOriginInMM();
00396
00397
00398
00399 ++i;
00400
00401 displayGeometry->MoveBy( vector2DDisplayDiff );
00402
00403 (*iter)->SendCreatedWorldGeometryUpdate();
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 RenderingManager::GetInstance()->RequestUpdateAll();
00427
00428 this->InvokeEvent( SliceRotationEvent() );
00429
00430 ok = true;
00431 break;
00432 }
00433 case AcCHECKPOINT:
00434 {
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
00447 if (!posEvent) break;
00448
00449 Point3D cursor = posEvent->GetWorldPosition();
00450
00451
00452 unsigned int numNearPlanes = 0;
00453 m_SNCsToBeRotated.clear();
00454 Geometry2D* geometryToBeRotated = NULL;
00455 Geometry2D* otherGeometry = NULL;
00456 Geometry2D* clickedGeometry = NULL;
00457 SlicedGeometry3D* clickedSlicedGeometry;
00458
00459 for (SNCVector::iterator iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter)
00460 {
00461 unsigned int slice = (*iter)->GetSlice()->GetPos();
00462 unsigned int time = (*iter)->GetTime()->GetPos();
00463
00464 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00465 const TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
00466 if (!timeSlicedGeometry) continue;
00467
00468 const SlicedGeometry3D* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>( timeSlicedGeometry->GetGeometry3D(time) );
00469 if (!slicedGeometry) continue;
00470
00471 Geometry2D* geometry2D = slicedGeometry->GetGeometry2D(slice);
00472 if (!geometry2D) continue;
00473
00474 ScalarType distanceMM = geometry2D->Distance( cursor );
00475
00476 BaseRenderer* renderer = stateEvent->GetEvent()->GetSender();
00477
00478 DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry();
00479 if (!displayGeometry) continue;
00480
00481 ScalarType distancePixels = distanceMM / displayGeometry->GetScaleFactorMMPerDisplayUnit();
00482 if ( distancePixels <= ThreshHoldDistancePixels )
00483 {
00484 ++numNearPlanes;
00485 }
00486
00487 if ( *iter == renderer->GetSliceNavigationController() )
00488 {
00489 clickedGeometry = geometry2D;
00490 clickedSlicedGeometry = const_cast<SlicedGeometry3D*>(slicedGeometry);
00491 }
00492 else
00493 {
00494
00495 if ( (distancePixels <= ThreshHoldDistancePixels)
00496 && !(*iter)->GetSliceRotationLocked()
00497 && (m_SNCsToBeRotated.empty() || m_LinkPlanes) )
00498 {
00499
00500 m_SNCsToBeRotated.push_back(*iter);
00501 geometryToBeRotated = geometry2D;
00502 }
00503 else
00504 {
00505 otherGeometry = geometry2D;
00506
00507 if ( m_LinkPlanes )
00508 {
00509
00510
00511 m_SNCsToBeRotated.push_back(*iter);
00512 }
00513 }
00514 }
00515 }
00516
00517 bool move (true);
00518
00519 if ( geometryToBeRotated && otherGeometry && clickedGeometry
00520 && ( numNearPlanes == 2 ) )
00521 {
00522
00523 move = false;
00524 }
00525
00526 StateEvent *newStateEvent(NULL);
00527
00528
00529 if (move)
00530 {
00531
00532 newStateEvent = new StateEvent(EIDNO, stateEvent->GetEvent());
00533 }
00534 else
00535 {
00536
00537 PlaneGeometry* planeGeometry = dynamic_cast<PlaneGeometry*>(clickedGeometry);
00538 PlaneGeometry* planeGeometry1 = dynamic_cast<PlaneGeometry*>(geometryToBeRotated);
00539 PlaneGeometry* planeGeometry2 = dynamic_cast<PlaneGeometry*>(otherGeometry);
00540
00541 if (!planeGeometry || !planeGeometry1 || !planeGeometry2) break;
00542
00543 Line3D intersection;
00544 if (!planeGeometry->IntersectionLine( planeGeometry1, intersection )) break;
00545 m_LastCursorPosition = intersection.Project(cursor);
00546 if (!planeGeometry2->IntersectionPoint(intersection, m_CenterOfRotation)) break;
00547
00548 newStateEvent = new StateEvent(EIDYES, stateEvent->GetEvent());
00549
00550 }
00551
00552 if (!newStateEvent) MITK_ERROR << "rotation would be nice but is impossible... " << std::endl;
00553
00554 this->HandleEvent( newStateEvent );
00555 delete newStateEvent;
00556
00557 ok = true;
00558 break;
00559 }
00560 case AcROTATESTART:
00561 {
00562 this->SetMouseCursor( rotate_cursor_xpm, 0, 0 );
00563 this->InvokeEvent( SliceRotationEvent() );
00564 break;
00565 }
00566 case AcROTATEEND:
00567 {
00568 this->ResetMouseCursor();
00569 this->InvokeEvent( SliceRotationEvent() );
00570 break;
00571 }
00572 default:
00573 {
00574 break;
00575 }
00576 }
00577
00578 return ok;
00579 }
00580
00581 }
00582