728x90
1. 개요
World 에 있는 PolyData 형상과 면이 있을 때 면과 형상의 수직(normal) 벡터의 시점으로 cutting을 수행하고 cutting contour 를 해당 면으로 투영하는 기능을 수행한다.
Polydata cutting 기능은 이전에 설명하였고 추가적으로 projection에 관한 기능과 코드의 흐름은 주석을 보면 알 수 있다.
2.코드
public void TestCutterPolydataProjection()
{
// Plane 을 실시간으로 변경하여 테스트 할 수 있는 Widget 생성
var planeWidget = vtkPlaneWidget.New();
planeWidget.SetNormal(0, 0, -1);
planeWidget.SetOrigin(-1, -1, 0);
planeWidget.SetPoint1(1, -1, 0);
planeWidget.SetPoint2(-1, 1, 0);
planeWidget.SetInteractor(interactor);
planeWidget.On();
// PlaneWidget의 Plane 객체 얻기
vtkPlane projPlane = vtkPlane.New();
planeWidget.GetPlane(projPlane);
#region PolyData 그리기
// 입력할 PolyData 소스를 생성한다.
var source = VtkGeometryUtils.MakeSphereSource(new dynamic[] { 1 });
// var source = VtkGeometryUtils.MakeCubeSource(new dynamic[] { 1 });
// 임의의 공간으로 source 이동시키기
vtkTransformFilter xfmFilter = vtkTransformFilter.New();
xfmFilter.SetInputConnection(source.GetOutputPort());
vtkTransform xfmData = vtkTransform.New();
xfmData.Translate(0, 0, -10);
xfmFilter.SetTransform(xfmData);
vtkPolyDataMapper sphMapper = vtkPolyDataMapper.New();
sphMapper.SetInputConnection(xfmFilter.GetOutputPort());
vtkActor sphActor = vtkActor.New();
sphActor.SetMapper(sphMapper);
sphActor.GetProperty().SetOpacity(0.6);
#endregion
#region PolyData Source Cutting
// vtkCutter 로 절단에 사용할 면을 생성한다.
vtkPlane cutterPlane = vtkPlane.New();
cutterPlane.SetNormal(projPlane.GetNormal().ToIntPtr());
cutterPlane.SetOrigin(xfmData.GetPosition().ToIntPtr());
// Cutter 를 생성한다.
var contourCutter = vtkCutter.New();
// vtkPlane 객체를 입력하였기 때문에 cutterPlane의 속성정보만 업데이트 하면됨.
contourCutter.SetCutFunction(cutterPlane);
contourCutter.SetInputConnection(xfmFilter.GetOutputPort());
contourCutter.Update();
// cutter 에서 만든 lines 를 한개의 line으로 만든다.
vtkStripper cutterStrip = vtkStripper.New();
cutterStrip.SetInputConnection(contourCutter.GetOutputPort());
cutterStrip.Update();
// 외곽선을 위한 Mapper를 생성한다.
vtkPolyDataMapper cutterMapper = vtkPolyDataMapper.New();
cutterMapper.SetInputConnection(cutterStrip.GetOutputPort());
cutterMapper.InterpolateScalarsBeforeMappingOn();
cutterMapper.SetScalarRange(1, 1);
// 외곽선을 그릴 Actor 를 생성한다.
vtkActor cutterActor = vtkActor.New();
cutterActor.SetMapper(cutterMapper);
cutterActor.GetProperty().SetColor(VtkColorUtils.GetNamedColor3d("Blue").ToIntPtr());
cutterActor.GetProperty().SetLineWidth(3);
cutterActor.GetProperty().LightingOff(); // Normal 값에 대한 lighting 효과를 없앤다. Solid 색상을 표시하게 됨
#endregion
#region PolyData Source Cutting Projection on Plane
// vtkCutter를 통해서 얻은 contour points 데이터를 지정된 origin, normal 위치로 투영하도록 한다.
vtkProjectPointsToPlane projFilter = vtkProjectPointsToPlane.New();
projFilter.SetInputConnection(contourCutter.GetOutputPort());
projFilter.SetProjectionTypeToSpecifiedPlane();
projFilter.SetOrigin(projPlane.GetOrigin().ToIntPtr());
projFilter.SetNormal(projPlane.GetNormal().ToIntPtr());
projFilter.Update();
// cutter 에서 만든 lines 를 한개의 line으로 만든다.
vtkStripper prjContourStrip = vtkStripper.New();
prjContourStrip.SetInputConnection(projFilter.GetOutputPort());
prjContourStrip.Update();
// 외곽선을 위한 Mapper를 생성한다.
vtkPolyDataMapper prjContourMapper = vtkPolyDataMapper.New();
prjContourMapper.SetInputConnection(prjContourStrip.GetOutputPort());
prjContourMapper.InterpolateScalarsBeforeMappingOn();
prjContourMapper.SetScalarRange(1, 1);
// 외곽선을 그릴 Actor 를 생성한다.
vtkActor prjContourActor = vtkActor.New();
prjContourActor.SetMapper(prjContourMapper);
prjContourActor.GetProperty().SetColor(VtkColorUtils.GetNamedColor3d("Blue").ToIntPtr());
prjContourActor.GetProperty().SetLineWidth(3);
prjContourActor.GetProperty().LightingOff(); // Normal 값에 대한 lighting 효과를 없앤다. Solid 색상을 표시하게 됨
#endregion
#region Polygon of the Projectied contour
// Generate a Delaunay triangulation of the points
vtkDelaunay2D delaunayFilter = vtkDelaunay2D.New();
delaunayFilter.SetInputConnection(prjContourStrip.GetOutputPort());
delaunayFilter.Update();
// vtkDelaunay2D 에서 만든 triangles 를 한개의 stripper을 수행하여 메모리 최적화를 수행한다.
vtkStripper prjPolygonStrip = vtkStripper.New();
prjPolygonStrip.SetInputConnection(delaunayFilter.GetOutputPort());
prjPolygonStrip.Update();
vtkPolyDataNormals prjPolygonNormal = vtkPolyDataNormals.New();
prjPolygonNormal.SetInputConnection(prjPolygonStrip.GetOutputPort());
prjPolygonNormal.SetConsistency(0);
prjPolygonNormal.Update();
var prjPolygonMapper = vtkPolyDataMapper.New();
prjPolygonMapper.SetInputConnection(prjPolygonNormal.GetOutputPort());
prjPolygonMapper.ScalarVisibilityOff();
var prjPolygonActor = vtkActor.New();
prjPolygonActor.SetMapper(prjPolygonMapper);
prjPolygonActor.GetProperty().SetColor(VtkColorUtils.GetNamedColor3d("Pink").ToIntPtr());
#endregion
#region Interaction Update
planeWidget.InteractionEvt += (sender, args) =>
{
// PlaneWidget의 Plane 정보 얻기
planeWidget.GetPlane(projPlane);
// PolyData의 cutter normal 적용
cutterPlane.SetNormal(projPlane.GetNormal().ToIntPtr());
// Projection Plane 업데이트
// vtkObject 객체를 입력하는게 아니므로 매번 업데이트해야함.
projFilter.SetOrigin(projPlane.GetOrigin().ToIntPtr());
projFilter.SetNormal(projPlane.GetNormal().ToIntPtr());
};
#endregion
#region Renderer 추가
renderer.AddActor(sphActor);
renderer.AddActor(prjContourActor);
renderer.AddActor(cutterActor);
renderer.AddActor(prjPolygonActor);
#endregion
EnableDrawAxes = true;
}
728x90
728x90