Beispiel #1
0
void SlicesRotator::RotateToPoint( SliceNavigationController *rotationPlaneSNC,
                                   SliceNavigationController *rotatedPlaneSNC,
                                   const Point3D &point, bool linked )
{
    MITK_WARN << "Deprecated function! Use SliceNavigationController::ReorientSlices() instead";

    SliceNavigationController *thirdSNC = NULL;

    SNCVector::iterator iter;
    for ( iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter )
    {
        if ( ((*iter) != rotationPlaneSNC)
                && ((*iter) != rotatedPlaneSNC) )
        {
            thirdSNC = *iter;
            break;
        }
    }

    if ( thirdSNC == NULL )
    {
        return;
    }

    const PlaneGeometry *rotationPlane = rotationPlaneSNC->GetCurrentPlaneGeometry();
    const PlaneGeometry *rotatedPlane = rotatedPlaneSNC->GetCurrentPlaneGeometry();
    const PlaneGeometry *thirdPlane = thirdSNC->GetCurrentPlaneGeometry();

    if ( (rotationPlane == NULL) || (rotatedPlane == NULL)
            || (thirdPlane == NULL) )
    {
        return;
    }

    if ( rotatedPlane->DistanceFromPlane( point ) < 0.001 )
    {
        // Skip irrelevant rotations
        return;
    }

    Point3D projectedPoint;
    Line3D intersection;
    Point3D rotationCenter;

    if ( !rotationPlane->Project( point, projectedPoint )
            || !rotationPlane->IntersectionLine( rotatedPlane, intersection )
            || !thirdPlane->IntersectionPoint( intersection, rotationCenter ) )
    {
        return;
    }

    // All pre-requirements are met; execute the rotation

    Point3D referencePoint = intersection.Project( projectedPoint );

    Vector3D toProjected = referencePoint - rotationCenter;
    Vector3D toCursor    = projectedPoint - rotationCenter;

    // cross product: | A x B | = |A| * |B| * sin(angle)
    Vector3D axisOfRotation;
    vnl_vector_fixed< ScalarType, 3 > vnlDirection =
        vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() );
    axisOfRotation.SetVnlVector( vnlDirection );

    // scalar product: A * B = |A| * |B| * cos(angle)
    // tan = sin / cos
    ScalarType angle = - atan2(
                           (double)(axisOfRotation.GetNorm()),
                           (double)(toCursor * toProjected) );
    angle *= 180.0 / vnl_math::pi;

    // create RotationOperation and apply to all SNCs that should be rotated
    RotationOperation op(OpROTATE, rotationCenter, axisOfRotation, angle);

    if ( !linked )
    {
        BaseRenderer *renderer = rotatedPlaneSNC->GetRenderer();
        if ( renderer == NULL )
        {
            return;
        }

        DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();

        Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
        displayGeometry->Map( rotationCenter, point2DWorld );
        displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );

        TimeGeometry *timeGeometry= rotatedPlaneSNC->GetCreatedWorldGeometry();
        if ( !timeGeometry )
        {
            return;
        }

        timeGeometry->ExecuteOperation( &op );

        displayGeometry->Map( rotationCenter, point2DWorld );
        displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
        Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;

        //Vector2D origin = displayGeometry->GetOriginInMM();

        displayGeometry->MoveBy( vector2DDisplayDiff );

        rotatedPlaneSNC->SendCreatedWorldGeometryUpdate();
    }
    else
    {
        SNCVector::iterator iter;
        for ( iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter )
        {
            BaseRenderer *renderer = (*iter)->GetRenderer();
            if ( renderer == NULL )
            {
                continue;
            }

            DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();

            Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
            displayGeometry->Map( rotationCenter, point2DWorld );
            displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );

            TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
            if ( !timeGeometry )
            {
                continue;
            }

            timeGeometry->ExecuteOperation( &op );

            displayGeometry->Map( rotationCenter, point2DWorld );
            displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
            Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;

            //Vector2D origin = displayGeometry->GetOriginInMM();

            displayGeometry->MoveBy( vector2DDisplayDiff );

            (*iter)->SendCreatedWorldGeometryUpdate();
        }
    }
} // end RotateToPoint
Beispiel #2
0
bool SlicesRotator::DoRotationStep(Action*, const StateEvent* e)
{
    const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(e->GetEvent());
    if (!posEvent) return false;

    Point3D cursor = posEvent->GetWorldPosition();

    Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
    Vector3D toCursor    = cursor - m_CenterOfRotation;

    // cross product: | A x B | = |A| * |B| * sin(angle)
    Vector3D axisOfRotation;
    vnl_vector_fixed< ScalarType, 3 > vnlDirection = vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() );
    axisOfRotation.SetVnlVector(vnlDirection);

    // scalar product: A * B = |A| * |B| * cos(angle)
    // tan = sin / cos
    ScalarType angle = - atan2( (double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected) );
    angle *= 180.0 / vnl_math::pi;
    m_LastCursorPosition = cursor;

    // create RotationOperation and apply to all SNCs that should be rotated
    RotationOperation rotationOperation(OpROTATE, m_CenterOfRotation, axisOfRotation, angle);

    // iterate the OTHER slice navigation controllers: these are filled in DoDecideBetweenRotationAndSliceSelection
    for (SNCVector::iterator iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
    {
        //  - remember the center of rotation on the 2D display BEFORE rotation
        //  - execute rotation
        //  - calculate new center of rotation on 2D display
        //  - move display IF the center of rotation has moved slightly before and after rotation

        // DM 2012-10: this must probably be due to rounding errors only, right?
        //             We don't have documentation on if/why this code is needed
        BaseRenderer *renderer = (*iter)->GetRenderer();
        if ( !renderer ) continue;

        DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();

        Point2D rotationCenter2DWorld, point2DDisplayPreRotation, point2DDisplayPostRotation;
        displayGeometry->Map( m_CenterOfRotation, rotationCenter2DWorld );
        displayGeometry->WorldToDisplay( rotationCenter2DWorld, point2DDisplayPreRotation );

        TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
        if (!timeGeometry) continue;

        timeGeometry->ExecuteOperation(&rotationOperation);

        displayGeometry->Map( m_CenterOfRotation, rotationCenter2DWorld );
        displayGeometry->WorldToDisplay( rotationCenter2DWorld, point2DDisplayPostRotation );
        Vector2D vector2DDisplayDiff = point2DDisplayPostRotation - point2DDisplayPreRotation;

        displayGeometry->MoveBy( vector2DDisplayDiff );

        (*iter)->SendCreatedWorldGeometryUpdate();
    }

    RenderingManager::GetInstance()->RequestUpdateAll();

    this->InvokeEvent( SliceRotationEvent() ); // notify listeners

    return true;
}