2013-09-23 1 views
1

Я пытаюсь вращать 3D-объект с помощью VTK при вращении регулятора. Вот как я его реализовал (в C#). Однако, когда я поворачиваю ручки управления, 3D-объект на экране исчез. Я не уверен, что произошло, но с тех пор, как был добавлен vtkImageReslice, все было в порядке, я полагаю, это был преступник.vtkImageReslice Вопросы о 3D-ротации

Часть кода Я думаю, отношение:

private vtkAxesActor axes; 
     private vtkCamera camera; 
     private List<vtkImageChangeInformation> changeFilters; 

     //private vtkTIFFReader reader; 
     private vtkImageAppendComponents componentAdaptor; 
     private List<vtkStringArray> fileNameArrays; 
     private List<vtkImageFlip> flippers; 
     private vtkRenderWindowInteractor iren; 

     // these two arrays specify the color range for the components specified by the array indexes 
     private int[] lowerThreshold = { 0, 0, 0, 0 }; 
     private List<vtkTIFFReader> readers; 
     private vtkRenderer renderer; 
     private vtkRenderWindow renderWindow; 
     private RenderWindowControl renWindowControl; 
     private int[] upperThreshold = { MaxGrayScaleLevel, MaxGrayScaleLevel, MaxGrayScaleLevel, MaxGrayScaleLevel}; 
     private vtkVolumeProperty volProperty; 
     private vtkVolume volume; 
     private vtkFixedPointVolumeRayCastMapper volumeMapper; 
     private vtkOrientationMarkerWidget widget; 


     public void setDefaultColorMapping() 
     { 
      if (volume == null) 
      { 
       MessageBox.Show("No volume exist"); 
       return; 
      } 
       // vtkVolumeProperty volProperty = volume.GetProperty(); 

      vtkColorTransferFunction colorFunctionA = vtkColorTransferFunction.New(); 
      colorFunctionA.AddRGBSegment(0, 0, 0, 0, MaxGrayScaleLevel, 1, 0, 0); 
      volProperty.SetColor(0, colorFunctionA); 

      vtkColorTransferFunction colorFunctionB = vtkColorTransferFunction.New(); 
      colorFunctionB.AddRGBSegment(0, 0, 0, 0, MaxGrayScaleLevel, 0, 1, 0); 
      volProperty.SetColor(1, colorFunctionB); 

      vtkColorTransferFunction colorFunctionC = vtkColorTransferFunction.New(); 
      colorFunctionC.AddRGBSegment(0, 0, 0, 0, MaxGrayScaleLevel, 0, 0, 1); 
      volProperty.SetColor(2, colorFunctionC); 

      vtkColorTransferFunction colorFunctionD = vtkColorTransferFunction.New(); 
      colorFunctionD.AddRGBSegment(0, 0, 0, 0, MaxGrayScaleLevel, 0.5, 0.5, 0); 
      volProperty.SetColor(3, colorFunctionD); 

      //volProperty.SetInterpolationTypeToNearest(); 
      //renWindowControl.RenderWindow.Render(); 
     } 

     public void setToDefault() 
     { 
      if (null == renWindowControl.RenderWindow) 
       return; 

      volumeMapper.SetBlendModeToMaximumIntensity(); 
      volumeMapper.SetCropping(1); 
      volumeMapper.SetCroppingRegionFlagsToSubVolume(); 

      //setDefaultColorMapping(); 
      //setDefaultOpacityfunction(); 

      widget.SetOutlineColor(0.93, 0.57, 0.13); 
      widget.SetOrientationMarker(axes); 
      widget.SetInteractor(renWindowControl.RenderWindow.GetInteractor()); 
      widget.SetEnabled(1); 

      double[] rotX = { 1.0, 0.0, 0.0 }; 
      double[] rotY = { 0.0, 1.0, 0.0 }; 
      double[] rotZ = { 0.0, 0.0, 1.0 }; 
      double[] center = { 0.0, 0.0, 0.0 }; 

      _reslicer.SetResliceAxesDirectionCosines(DoubleArrayToIntPtr(rotX), DoubleArrayToIntPtr(rotY), DoubleArrayToIntPtr(rotZ)); 
      _reslicer.SetResliceAxesOrigin(DoubleArrayToIntPtr(center)); 
      _reslicer.SetInterpolationModeToLinear(); 
      _reslicer.SetOutputDimensionality(3); 

      iren = renWindowControl.RenderWindow.GetInteractor(); 
     } 

     private void SetupScene() 
     { 
      renderer = renWindowControl.RenderWindow.GetRenderers().GetFirstRenderer(); 
      renderer.RemoveAllViewProps(); 

      if (_isZStackDataExist == true) 
      { 
       // volumeMapper.SetInputConnection(componentAdaptor.GetOutputPort());   
       _reslicer.SetInputConnection(componentAdaptor.GetOutputPort());    

       volumeMapper.SetInputConnection(_reslicer.GetOutputPort()); 
       //volumeMapper.Update(); 

       volume.SetMapper(volumeMapper); 
       //volume.SetOrigin(DataExtentX/2, DataExtentY/2, DataExtentZ/2); 

       renderer.AddVolume(volume); 
       renderer.ResetCamera(); 
       camera = renderer.GetActiveCamera(); 
      } 

      renderer.SetBackground(0, 0, 0); 
      //renderer.GetActiveCamera().Zoom(3); 
      //deleteAllVTKObjects(); 
     } 

     //--------------------------------------------------------------------------------------------------------------- 
     public void updateXRotation() 
     { 
      if (false == IsVolumeRendererReady) 
       return; 

      if (null != _reslicer) 
      { 
       double[] rotX = { 1.0, 0.0, 0.0}; 
       double[] rotY = { 0.0, Math.Cos(DataXRotationDegrees), -Math.Sin(DataXRotationDegrees)}; 
       double[] rotZ = { 0.0, Math.Sin(DataXRotationDegrees), Math.Cos(DataXRotationDegrees)}; 
       double[] center = { 0.0, 0.0, 0.0 }; 

       _reslicer.SetResliceAxesDirectionCosines(DoubleArrayToIntPtr(rotX), DoubleArrayToIntPtr(rotY), DoubleArrayToIntPtr(rotZ)); 
       _reslicer.SetResliceAxesOrigin(DoubleArrayToIntPtr(center)); 
       _reslicer.SetInterpolationModeToLinear(); 
       _reslicer.Update(); 
      } 

     } 

     static IntPtr DoubleArrayToIntPtr(double[] rotDoubleArr) 
     { 
      // Initialize unmanaged memory to hold the array. 
      int size = Marshal.SizeOf(rotDoubleArr[0]) * rotDoubleArr.Length; 

      IntPtr rotIntPtr = Marshal.AllocHGlobal(size); 

      try 
      { 
       // Copy the array to unmanaged memory. 
       Marshal.Copy(rotDoubleArr, 0, rotIntPtr, rotDoubleArr.Length); 
      } 
      catch 
      { 
      } 

      return rotIntPtr; 

      //finally 
      //{ 
      // // Free the unmanaged memory. 
      // Marshal.FreeHGlobal(rotIntPtr); 
      //} 
     } 

Любой из них имеет какие-либо идеи, как я могу сделать эту работу? Чтобы повернуть 3D-объект с помощью vtkImageReslice, или я должен пойти на что-то еще? Кажется, не так много примеров C#, как повернуть 3D. Большое спасибо.

+0

Вы пытаетесь повернуть объект на экране, или вращать воксели внутри данных изображения? То, что вы пытаетесь сделать, - это второе. Если вы просто хотите визуально повернуть, вы можете просто использовать актерские преобразования. – shash

ответ

2

Если вы хотите только просматривать объект с разных сторон, то изменить вид камеры является одним из вариантов. Ниже приведен пример вращения 3D объекта вокруг своей оси у для -угола:

public void RotateToRight() 
{   
     double cos = Math.Cos(angle); 
     double sin = Math.Sin(angle); 

     double[] rot = { cos, 0, -sin, 0, 
          0, 1, 0, 0, 
         sin, 0, cos, 0, 
          0, 0, 0, 1}; 

     transform.SetMatrix(DoubleArrayToIntPtr(rot)); 
     camera.ApplyTransform(transform); 
     renderer.ResetCamera(); 
     renderer.GetActiveCamera(); 
     ForceWindowToRender(); 
} 

Вот оригинал вид: enter image description here

Вот вид после того, как функция выполняется один раз, и в этом случае объект вращается вокруг своей оси у для -угола (- означает отсчет по часовой стрелке) enter image description here

0

Легче и более интуитивный, может быть, заключается в использовании методов RotateX, RotateY и RotateZ класса vtkTransform.

Пример кода в Java:

private void rotate(double angle, int axis) { 
    vtkTransform t = new vtkTransform(); 
    bw.GetTransform(t); 

    switch(axis) { 
     case X: 
      t.RotateX(-angle); 
      break; 
     case Y: 
      t.RotateY(-angle); 
      break; 
     case Z: 
      t.RotateZ(-angle); 
      break; 
    } 

    ren.GetActiveCamera().ApplyTransform(t); 
}