예제 #1
0
bool mitk::SegTool2D::DetermineAffectedImageSlice( const Image* image, const PlaneGeometry* plane, int& affectedDimension, int& affectedSlice )
{
  assert(image);
  assert(plane);

  // compare normal of plane to the three axis vectors of the image
  Vector3D normal       = plane->GetNormal();
  Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0);
  Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1);
  Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2);

  normal.Normalize();
  imageNormal0.Normalize();
  imageNormal1.Normalize();
  imageNormal2.Normalize();

  imageNormal0.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal0.Get_vnl_vector()) );
  imageNormal1.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal1.Get_vnl_vector()) );
  imageNormal2.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal2.Get_vnl_vector()) );

  double eps( 0.00001 );
  // axial
  if ( imageNormal2.GetNorm() <= eps )
  {
    affectedDimension = 2;
  }
  // sagittal
  else if ( imageNormal1.GetNorm() <= eps )
  {
    affectedDimension = 1;
  }
  // frontal
  else if ( imageNormal0.GetNorm() <= eps )
  {
    affectedDimension = 0;
  }
  else
  {
    affectedDimension = -1; // no idea
    return false;
  }

  // determine slice number in image
  Geometry3D* imageGeometry = image->GetGeometry(0);
  Point3D testPoint = imageGeometry->GetCenter();
  Point3D projectedPoint;
  plane->Project( testPoint, projectedPoint );

  Point3D indexPoint;

  imageGeometry->WorldToIndex( projectedPoint, indexPoint );
  affectedSlice = ROUND( indexPoint[affectedDimension] );
  MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice;

  // check if this index is still within the image
  if ( affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)) ) return false;

  return true;
}
예제 #2
0
bool mitk::AffineInteractor::ExecuteAction(Action* action, mitk::StateEvent const* stateEvent)
{
  bool ok = false;

  TimeSlicedGeometry* inputtimegeometry = GetData()->GetTimeSlicedGeometry();
  if (inputtimegeometry == NULL)
    return false;

  Geometry3D* geometry = inputtimegeometry->GetGeometry3D(m_TimeStep);

  mitk::DisplayPositionEvent const *event = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
  switch (action->GetActionId())
  {
  case AcCHECKELEMENT:
    {
      mitk::Point3D worldPoint = event->GetWorldPosition();
      /* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */
      mitk::BoolProperty::Pointer selected;
      mitk::ColorProperty::Pointer color;
      std::auto_ptr<StateEvent> newStateEvent;

      selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));

      if ( selected.IsNull() ) {
        selected = mitk::BoolProperty::New();
        m_DataNode->GetPropertyList()->SetProperty("selected", selected);
      }

      color = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("color"));

      if ( color.IsNull() ) {
        color = mitk::ColorProperty::New();
        m_DataNode->GetPropertyList()->SetProperty("color", color);
      }

      if (this->CheckSelected(worldPoint, m_TimeStep))
      {
        newStateEvent.reset(new mitk::StateEvent(EIDYES, stateEvent->GetEvent()));
        selected->SetValue(true);
        color->SetColor(1.0, 1.0, 0.0);
      }
      else
      {
        newStateEvent.reset(new mitk::StateEvent(EIDNO, stateEvent->GetEvent()));
        selected = mitk::BoolProperty::New(false);
        color->SetColor(0.0, 0.0, 1.0);

        /*
        mitk::BoundingObject* b = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
        if(b != NULL)
        {
          color = (b->GetPositive())? mitk::ColorProperty::New(0.0, 0.0, 1.0) : mitk::ColorProperty::New(1.0, 0.0, 0.0);  // if deselected, a boundingobject is colored according to its positive/negative state
        }
        else
          color = mitk::ColorProperty::New(1.0, 1.0, 1.0);   // if deselcted and no bounding object, color is white
        */
      }

      /* write new state (selected/not selected) to the property */
      this->HandleEvent( newStateEvent.get() );
      ok = true;
      break;
    }
  case AcADD:
    {
      mitk::Point3D worldPoint = event->GetWorldPosition();
      std::auto_ptr<StateEvent> newStateEvent;
      if (this->CheckSelected(worldPoint, m_TimeStep))
      {
        newStateEvent.reset(new mitk::StateEvent(EIDYES, event));
        m_DataNode->GetPropertyList()->SetProperty("selected", mitk::BoolProperty::New(true));  // TODO: Generate an Select Operation and send it to the undo controller ?
      }
      else  // if not selected, do nothing (don't deselect)
      {
        newStateEvent.reset(new mitk::StateEvent(EIDNO, event));
      }
      //call HandleEvent to leave the guard-state
      this->HandleEvent( newStateEvent.get() );
      ok = true;
      break;
    }
  case AcTRANSLATESTART:
  case AcROTATESTART:
  case AcSCALESTART:
    {
      m_LastMousePosition = event->GetWorldPosition();
      ok = true;
      break;
    }
  case AcTRANSLATE:
    {
      mitk::Point3D newPosition;
      newPosition = event->GetWorldPosition();
      newPosition -=  m_LastMousePosition.GetVectorFromOrigin();        // compute difference between actual and last mouse position
      m_LastMousePosition = event->GetWorldPosition();               // save current mouse position as last position

      /* create operation with position difference */
      mitk::PointOperation* doOp = new mitk::PointOperation(OpMOVE, newPosition, 0); // Index is not used here
      if (m_UndoEnabled)  //write to UndoMechanism
      {
        mitk::Point3D oldPosition=geometry->GetCornerPoint(0);

        PointOperation* undoOp = new mitk::PointOperation(OpMOVE, oldPosition, 0);
        OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
        m_UndoController->SetOperationEvent(operationEvent);
      }
      /* execute the Operation */
      geometry->ExecuteOperation(doOp);

      if (!m_UndoEnabled)
        delete doOp;

      ok = true;
      break;
    }
  case AcTRANSLATEEND:
    {
      m_UndoController->SetOperationEvent(new UndoStackItem("Move object"));
      m_DataNode->InvokeEvent(TranslateEvent());
      break;
    }
  case AcROTATE:
    {
      mitk::Point3D p = event->GetWorldPosition();

      mitk::Vector3D newPosition = p.GetVectorFromOrigin();

      mitk::Point3D dataPosition = geometry->GetCenter();

      newPosition = newPosition - dataPosition.GetVectorFromOrigin();  // calculate vector from center of the data object to the current mouse position

      mitk::Vector3D startPosition = m_LastMousePosition.GetVectorFromOrigin() - dataPosition.GetVectorFromOrigin();  // calculate vector from center of the data object to the last mouse position

      /* calculate rotation axis (by calculating the cross produkt of the vectors) */
      mitk::Vector3D rotationaxis;
      rotationaxis[0] =  startPosition[1] * newPosition[2] - startPosition[2] * newPosition[1];
      rotationaxis[1] =  startPosition[2] * newPosition[0] - startPosition[0] * newPosition[2];
      rotationaxis[2] =  startPosition[0] * newPosition[1] - startPosition[1] * newPosition[0];

      /* calculate rotation angle in degrees */
      mitk::ScalarType angle = atan2((mitk::ScalarType)rotationaxis.GetNorm(), (mitk::ScalarType) (newPosition * startPosition)) * (180/vnl_math::pi);
      m_LastMousePosition = p; // save current mouse position as last mouse position

      /* create operation with center of rotation, angle and axis and send it to the geometry and Undo controller */
      mitk::RotationOperation* doOp = new mitk::RotationOperation(OpROTATE, dataPosition, rotationaxis, angle);

      if (m_UndoEnabled)  //write to UndoMechanism
      {
        RotationOperation* undoOp = new mitk::RotationOperation(OpROTATE, dataPosition, rotationaxis, -angle);
        OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
        m_UndoController->SetOperationEvent(operationEvent);
      }
      /* execute the Operation */
      geometry->ExecuteOperation(doOp);

      if(!m_UndoEnabled)
        delete doOp;

      ok = true;
      break;
    }
  case AcROTATEEND:
    {
      m_UndoController->SetOperationEvent(new UndoStackItem("Rotate object"));
      m_DataNode->InvokeEvent(RotateEvent());
      break;
    }
  case AcSCALE:
    {
      mitk::Point3D p = event->GetWorldPosition();

      mitk::Vector3D v = p - m_LastMousePosition;
      /* calculate scale changes */
      mitk::Point3D newScale;
      newScale[0] = (geometry->GetAxisVector(0) * v) / geometry->GetExtentInMM(0);  // Scalarprodukt of normalized Axis
      newScale[1] = (geometry->GetAxisVector(1) * v) / geometry->GetExtentInMM(1);  // and direction vector of mouse movement
      newScale[2] = (geometry->GetAxisVector(2) * v) / geometry->GetExtentInMM(2);  // is the length of the movement vectors
      // projection onto the axis
      /* convert movement to local object coordinate system and mirror it to the positive quadrant */
      Vector3D start;
      Vector3D end;
      mitk::ScalarType convert[3];
      itk2vtk(m_LastMousePosition, convert);
      geometry->GetVtkTransform()->GetInverse()->TransformPoint(convert, convert);  // transform start point to local object coordinates
      start[0] = fabs(convert[0]);  start[1] = fabs(convert[1]);  start[2] = fabs(convert[2]);  // mirror it to the positive quadrant
      itk2vtk(p, convert);
      geometry->GetVtkTransform()->GetInverse()->TransformPoint(convert, convert);  // transform end point to local object coordinates
      end[0] = fabs(convert[0]);  end[1] = fabs(convert[1]);  end[2] = fabs(convert[2]);  // mirror it to the positive quadrant

      /* check if mouse movement is towards or away from the objects axes and adjust scale factors accordingly */
      Vector3D vLocal = start - end;
      newScale[0] = (vLocal[0] > 0.0) ? -fabs(newScale[0]) : +fabs(newScale[0]);
      newScale[1] = (vLocal[1] > 0.0) ? -fabs(newScale[1]) : +fabs(newScale[1]);
      newScale[2] = (vLocal[2] > 0.0) ? -fabs(newScale[2]) : +fabs(newScale[2]);

      m_LastMousePosition = p;  // update lastPosition for next mouse move

      /* generate Operation and send it to the receiving geometry */
      PointOperation* doOp = new mitk::PointOperation(OpSCALE, newScale, 0); // Index is not used here
      if (m_UndoEnabled)  //write to UndoMechanism
      {
        mitk::Point3D oldScaleData;
        oldScaleData[0] = -newScale[0];
        oldScaleData[1] = -newScale[1];
        oldScaleData[2] = -newScale[2];

        PointOperation* undoOp = new mitk::PointOperation(OpSCALE, oldScaleData, 0);
        OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
        m_UndoController->SetOperationEvent(operationEvent);
      }
      /* execute the Operation */
      geometry->ExecuteOperation(doOp);

      if(!m_UndoEnabled)
        delete doOp;

      /* Update Volume Property with new value */
      /*
      mitk::BoundingObject* b = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
      if (b != NULL)
      {
        m_DataNode->GetPropertyList()->SetProperty("volume", FloatProperty::New(b->GetVolume()));
        //MITK_INFO << "Volume of Boundingobject is " << b->GetVolume()/1000.0 << " ml" << std::endl;
      }
      */
      ok = true;
      break;
    }
  case AcSCALEEND:
    {
      m_UndoController->SetOperationEvent(new UndoStackItem("Scale object"));
      m_DataNode->InvokeEvent(ScaleEvent());
      break;
    }
  default:
    ok = Superclass::ExecuteAction(action, stateEvent);//, objectEventId, groupEventId);
  }
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  return ok;
}