我正在尝试使用VTK旋转3D对象,因为我旋转旋钮控件。这是我实现它的方式(在C#中)。但是,当我旋转控制旋钮时,屏幕中的3D对象消失了。我不确定发生了什么,但自从添加vtkImageReslice之前,一切都很好,我想这是罪魁祸首。
我认为相关的一些代码:
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);
//}
}
任何人都知道如何才能使这项工作成功?要用vtkImageReslice旋转3D对象,还是应该去寻找其他东西?似乎没有很多C#示例如何旋转3D。非常感谢。
答案 0 :(得分:2)
如果您只想从不同角度查看对象,则更改摄像机视图是其中一个选项。下面是围绕y轴旋转3D对象的示例:#angle:
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();
}
这是原始视图:
这是函数执行一次后的视图,在这种情况下,对象围绕其y轴旋转为-angle( - 表示顺时针计数)
答案 1 :(得分:0)
更容易和更直观的可能是使用类vtkTransform的RotateX,RotateY和RotateZ方法。
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);
}