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
00019 #include "mitkSlicesSwiveller.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 <math.h>
00040
00041
00042 namespace mitk {
00043
00044 SlicesSwiveller::Pointer SlicesSwiveller::New()
00045 {
00046 return SlicesSwiveller::New("slices-rotator");
00047 }
00048
00049 SlicesSwiveller::SlicesSwiveller(const char* machine)
00050 : SlicesCoordinator(machine),
00051 m_PreviousRotationAngle( 0.0 )
00052 {
00053 }
00054
00055 SlicesSwiveller::~SlicesSwiveller()
00056 {
00057
00058 }
00059
00060
00061
00062 void SlicesSwiveller::OnSliceControllerAdded(SliceNavigationController* snc)
00063 {
00064 if (!snc) return;
00065
00066
00067 snc->ConnectGeometrySendEvent(this);
00068 }
00069
00070
00071 void SlicesSwiveller::OnSliceControllerRemoved(SliceNavigationController* snc)
00072 {
00073 if (!snc) return;
00074
00075 }
00076
00078
00079 void SlicesSwiveller::SetGeometry(const itk::EventObject& )
00080 {
00081
00082
00083 UpdateRelevantSNCs();
00084 }
00085
00087 void SlicesSwiveller::UpdateRelevantSNCs()
00088 {
00089 m_RelevantSNCs.clear();
00090
00091 SNCVector::iterator iter;
00092 for ( iter = m_SliceNavigationControllers.begin();
00093 iter != m_SliceNavigationControllers.end();
00094 ++iter)
00095 {
00096 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00097 const TimeSlicedGeometry* timeSlicedGeometry =
00098 dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
00099
00100 if (!timeSlicedGeometry) continue;
00101
00102 const SlicedGeometry3D* slicedGeometry =
00103 dynamic_cast<const SlicedGeometry3D*>(
00104 timeSlicedGeometry->GetGeometry3D(0) );
00105 if (!slicedGeometry) continue;
00106
00107 Geometry2D *firstSlice( NULL );
00108 Geometry2D *secondSlice( NULL );
00109
00110 if (slicedGeometry->IsValidSlice(0))
00111 {
00112 firstSlice = slicedGeometry->GetGeometry2D(0);
00113 }
00114 if (slicedGeometry->IsValidSlice(1))
00115 {
00116 secondSlice = slicedGeometry->GetGeometry2D(1);
00117 }
00118
00119
00120
00121 Vector3D right1 = firstSlice->GetAxisVector(0);
00122 Vector3D up1 = firstSlice->GetAxisVector(1);
00123 vnl_vector_fixed< ScalarType, 3 > vnlDirection1 =
00124 vnl_cross_3d(right1.GetVnlVector(), up1.GetVnlVector());
00125 Vector3D direction1;
00126 direction1.SetVnlVector(vnlDirection1);
00127
00128 Vector3D right2 = firstSlice->GetAxisVector(0);
00129 Vector3D up2 = firstSlice->GetAxisVector(1);
00130 vnl_vector_fixed< ScalarType, 3 > vnlDirection2 =
00131 vnl_cross_3d(right2.GetVnlVector(), up2.GetVnlVector());
00132 Vector3D direction2;
00133 direction2.SetVnlVector(vnlDirection2);
00134
00135 bool equal = true;
00136 const ScalarType eps = 0.0001;
00137 for (int i = 0; i < 3; ++i)
00138 {
00139 if ( fabs(direction1[i] - direction2[i]) > eps )
00140 {
00141 equal = false;
00142 }
00143 }
00144
00145 if (equal)
00146 {
00147 m_RelevantSNCs.push_back( *iter );
00148 }
00149 }
00150 }
00151
00152 bool SlicesSwiveller
00153 ::ExecuteAction(Action* action, StateEvent const* stateEvent)
00154 {
00155 const ScalarType ThresholdDistancePixels = 6.0;
00156
00157 bool ok = false;
00158
00159 switch ( action->GetActionId() )
00160 {
00161 case AcMOVE:
00162 {
00163
00164 SNCVector::iterator iter;
00165 for ( iter = m_RelevantSNCs.begin();
00166 iter != m_RelevantSNCs.end();
00167 ++iter )
00168 {
00169 if ( !(*iter)->GetSliceRotationLocked() )
00170 {
00171 (*iter)->ExecuteAction(action, stateEvent);
00172 }
00173 }
00174
00175 ok = true;
00176 break;
00177 }
00178 case AcROTATE:
00179 {
00180 const DisplayPositionEvent *posEvent =
00181 dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
00182
00183 if (!posEvent) break;
00184
00185
00186 Point2D cursor = posEvent->GetDisplayPosition();
00187 Vector2D relativeCursor = cursor - m_ReferenceCursor;
00188 Vector3D relativeCursorAxis =
00189 m_RotationPlaneXVector * relativeCursor[0]
00190 + m_RotationPlaneYVector * relativeCursor[1];
00191
00192
00193
00194 Vector3D rotationAxis = itk::CrossProduct(
00195 m_RotationPlaneNormal, relativeCursorAxis );
00196
00197 ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0;
00198
00199
00200
00201 RotationOperation op( OpROTATE, m_CenterOfRotation,
00202 m_PreviousRotationAxis, -m_PreviousRotationAngle );
00203
00204 SNCVector::iterator iter;
00205 for ( iter = m_SNCsToBeRotated.begin();
00206 iter != m_SNCsToBeRotated.end();
00207 ++iter )
00208 {
00209 if ( !(*iter)->GetSliceRotationLocked() )
00210 {
00211 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00212 const TimeSlicedGeometry* timeSlicedGeometry =
00213 dynamic_cast<const TimeSlicedGeometry*>(geometry3D);
00214 if (!timeSlicedGeometry) continue;
00215
00216 const_cast<TimeSlicedGeometry*>(timeSlicedGeometry)
00217 ->ExecuteOperation(&op);
00218
00219 (*iter)->SendCreatedWorldGeometryUpdate();
00220 }
00221 }
00222
00223
00224 RotationOperation op2( OpROTATE, m_CenterOfRotation,
00225 rotationAxis, rotationAngle );
00226
00227 for ( iter = m_SNCsToBeRotated.begin();
00228 iter != m_SNCsToBeRotated.end();
00229 ++iter)
00230 {
00231 if ( !(*iter)->GetSliceRotationLocked() )
00232 {
00236
00237
00238
00239
00240
00241
00242
00243
00244 const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
00245 const TimeSlicedGeometry* timeSlicedGeometry =
00246 dynamic_cast<const TimeSlicedGeometry*>(geometry3D);
00247 if (!timeSlicedGeometry) continue;
00248
00249
00250 const_cast<TimeSlicedGeometry*>(timeSlicedGeometry)
00251 ->ExecuteOperation(&op2);
00252
00254
00255
00256
00257
00260
00261
00262
00263
00264
00265 (*iter)->SendCreatedWorldGeometryUpdate();
00266 }
00267 }
00268
00269 m_PreviousRotationAxis = rotationAxis;
00270 m_PreviousRotationAngle = rotationAngle;
00271
00272
00273 RenderingManager::GetInstance()->RequestUpdateAll();
00274
00275 this->InvokeEvent( SliceRotationEvent() );
00276
00277 ok = true;
00278 break;
00279 }
00280 case AcCHECKPOINT:
00281 {
00282
00283
00284
00285 const DisplayPositionEvent *posEvent =
00286 dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
00287
00288 BaseRenderer *renderer = stateEvent->GetEvent()->GetSender();
00289
00290 if ( !posEvent || !renderer )
00291 {
00292 break;
00293 }
00294
00295
00296 const Point3D &cursor = posEvent->GetWorldPosition();
00297
00298 m_SNCsToBeRotated.clear();
00299
00300 const PlaneGeometry *clickedGeometry( NULL );
00301 const PlaneGeometry *otherGeometry1( NULL );
00302 const PlaneGeometry *otherGeometry2( NULL );
00303
00304 SNCVector::iterator iter;
00305 for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter )
00306 {
00307
00308
00309
00310 const PlaneGeometry *planeGeometry = (*iter)->GetCurrentPlaneGeometry();
00311 if ( !planeGeometry ) continue;
00312
00313 if ( *iter == renderer->GetSliceNavigationController() )
00314 {
00315 clickedGeometry = planeGeometry;
00316 m_SNCsToBeRotated.push_back(*iter);
00317 }
00318 else
00319 {
00320 if ( otherGeometry1 == NULL )
00321 {
00322 otherGeometry1 = planeGeometry;
00323 }
00324 else
00325 {
00326 otherGeometry2 = planeGeometry;
00327 }
00328 if ( m_LinkPlanes )
00329 {
00330
00331 m_SNCsToBeRotated.push_back(*iter);
00332 }
00333 }
00334 }
00335
00336 StateEvent *newStateEvent( NULL );
00337
00338 mitk::Line3D line;
00339 mitk::Point3D point;
00340 if ( (clickedGeometry != NULL) && (otherGeometry1 != NULL)
00341 && (otherGeometry2 != NULL)
00342 && clickedGeometry->IntersectionLine( otherGeometry1, line )
00343 && otherGeometry2->IntersectionPoint( line, point ))
00344 {
00345 m_CenterOfRotation = point;
00346 if ( m_CenterOfRotation.EuclideanDistanceTo( cursor )
00347 < ThresholdDistancePixels )
00348 {
00349 newStateEvent = new StateEvent(EIDNO, stateEvent->GetEvent());
00350 }
00351 else
00352 {
00353 m_ReferenceCursor = posEvent->GetDisplayPosition();
00354
00355
00356 m_RotationPlaneNormal = clickedGeometry->GetNormal();
00357
00358 ScalarType xVector[] = { 1.0, 0.0, 0.0 };
00359 ScalarType yVector[] = { 0.0, 1.0, 0.0 };
00360 clickedGeometry->Geometry3D::IndexToWorld(
00361 Point3D(), Vector3D( xVector), m_RotationPlaneXVector );
00362 clickedGeometry->Geometry3D::IndexToWorld(
00363 Point3D(), Vector3D( yVector), m_RotationPlaneYVector );
00364
00365 m_RotationPlaneNormal.Normalize();
00366 m_RotationPlaneXVector.Normalize();
00367 m_RotationPlaneYVector.Normalize();
00368
00369 m_PreviousRotationAxis.Fill( 0.0 );
00370 m_PreviousRotationAxis[2] = 1.0;
00371 m_PreviousRotationAngle = 0.0;
00372
00373 newStateEvent = new StateEvent(EIDYES, stateEvent->GetEvent());
00374 }
00375 }
00376 else
00377 {
00378 newStateEvent = new StateEvent(EIDNO, stateEvent->GetEvent());
00379 }
00380
00381 this->HandleEvent( newStateEvent );
00382 delete newStateEvent;
00383
00384 ok = true;
00385 break;
00386 }
00387 case AcROTATESTART:
00388 {
00389 this->InvokeEvent( SliceRotationEvent() );
00390 break;
00391 }
00392 case AcROTATEEND:
00393 {
00394 this->InvokeEvent( SliceRotationEvent() );
00395 break;
00396 }
00397 default:
00398 {
00399 break;
00400 }
00401 }
00402
00403 return ok;
00404 }
00405
00406 }
00407