[VTK]设置vtkImplicitPlaneWidget2切割平面的初始化位置

在完成任意平面切割后经常需要通过计算机设置切割平面位置,不然就需要一直使用手去拖动比较繁琐。

其实可以通过设置vtkImplicitPlaneWidget2的vtkImplicitPlaneRepresentation的值即可:

    // set up representation for vtkImplicitPlaneWidget2 
    // you could set the normal and origin with the value you want 
    vtkSmartPointer<vtkImplicitPlaneRepresentation> rep = 
    vtkSmartPointer<vtkImplicitPlaneRepresentation>::New();
    rep->SetPlaceFactor(1.25); // This must be set prior to placing the widget
    rep->PlaceWidget(coneSkinActor->GetBounds());
#ifndef SET_VALUE
    rep->SetNormal(measureNormal);
    rep->SetOrigin(point3);
#endif
    vtkSmartPointer<vtkImplicitPlaneWidget2> implicitPlaneWidget = vtkImplicitPlaneWidget2::New();
    implicitPlaneWidget->SetInteractor(iren);
    // this set the representation for the widget thus the normal and origin is transfer to the widget
    implicitPlaneWidget->SetRepresentation(rep);

结果如下图:第一图是没有设置法向量和初始点;第二图是初始化切割平面

完整代码:

// GitPro.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <vtkCommand.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkSphereSource.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkClipPolyData.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkPlane.h>
#include <vtkImageActor.h>
#include <vtkImplicitPlaneWidget2.h>
#include <vtkAngleWidget.h>
#include <vtkPlaneWidget.h>
#include <vtkSmartPointer.h>
#include <vtkImplicitPlaneRepresentation.h>
#include <vtkAngleRepresentation3D.h>
#include <vtkPointHandleRepresentation3D.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkJPEGReader.h>
#include <vtkContourFilter.h>
#include <vtkImageFlip.h>
#include <vtkSmoothPolyDataFilter.h>
#include <vtkPolyDataNormals.h>
#include <vtkStripper.h>
#include <vtkProperty.h>
#include <vtkOutlineFilter.h>
#include <vtkCamera.h>
#include <vtkTriangle.h>
#include <vtkImageViewer2.h>
#include <vtkImageData.h>


class VTKImplicitPlaneWidget2Callback : public vtkCommand
{
public:
 static VTKImplicitPlaneWidget2Callback *New()
 {
      return new VTKImplicitPlaneWidget2Callback;
 }
public:
 virtual void Execute(vtkObject *caller, unsigned long eventId, void *callData)
 {
     vtkImplicitPlaneWidget2 *pWidget = reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
     if (pWidget)
     {
         vtkImplicitPlaneRepresentation *rep = 
         reinterpret_cast<vtkImplicitPlaneRepresentation*>(pWidget->GetRepresentation());
         vtkSmartPointer<vtkPlane> planeNew = vtkPlane::New();
         rep->GetPlane(planeNew);
#ifdef GET_VALUE
         double origin[3];
         double normal[3];
         planeNew->GetNormal(normal);
         planeNew->GetOrigin(origin);
#endif
         cliper->SetClipFunction(planeNew);
         cliper->Update();
         
         vtkSmartPointer<vtkPolyData> clipedData = vtkPolyData::New();
         clipedData->DeepCopy(cliper->GetOutput());

         vtkSmartPointer<vtkPolyDataMapper> coneMapper = vtkPolyDataMapper::New();
         coneMapper->SetInput(clipedData);
         coneMapper->ScalarVisibilityOff();    
         actor->SetMapper(coneMapper);
     }
 }
 void setCliper(vtkSmartPointer<vtkClipPolyData> other){cliper = other;}
 void setPlane(vtkSmartPointer<vtkPlane> other){pPlane = other;}
 void setActor(vtkSmartPointer<vtkActor> other){actor = other;}
private:
     vtkSmartPointer<vtkPlane> pPlane;
     vtkSmartPointer<vtkActor> actor;
     vtkSmartPointer<vtkClipPolyData> cliper;
};

void build3DViewBackup()
{
    vtkSmartPointer<vtkRenderer> aRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    vtkSmartPointer<vtkRenderWindow> renWin =
        vtkSmartPointer<vtkRenderWindow>::New();

    vtkSmartPointer<vtkRenderWindowInteractor> iren =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    
    vtkSmartPointer<vtkRenderer> rRenderer = 
    vtkSmartPointer<vtkRenderer>::New();
    
    renWin->AddRenderer(aRenderer);
    renWin->AddRenderer(rRenderer);
    iren->SetRenderWindow(renWin);

    rRenderer->SetBackground( 0.2, 0.3, 0.5 );
    rRenderer->SetViewport(0.5, 0.0, 1.0, 1.0);

    vtkSmartPointer<vtkJPEGReader> dicomReader =
        vtkSmartPointer<vtkJPEGReader>::New();  

    dicomReader->SetFilePrefix("C:/Users/DawnWind/Desktop/004LR/");
    dicomReader->SetFilePattern("%s%d.jpg");
    dicomReader->SetDataByteOrderToLittleEndian();
    dicomReader->SetDataSpacing(2.0 / 3, 2.0 / 3, 1); 
    dicomReader->SetFileNameSliceSpacing(1); 
#ifndef CT_004
    dicomReader->SetDataExtent(0, 511, 0, 209, 0, 37);
#endif
#ifdef CT_000
    dicomReader->SetDataExtent(0, 209, 0, 209, 0, 83);
#endif
    dicomReader->Update();  

    vtkSmartPointer<vtkContourFilter> skinExtractor =
        vtkSmartPointer<vtkContourFilter>::New();

    vtkSmartPointer<vtkImageFlip> flip = vtkSmartPointer<vtkImageFlip>::New();
    // with #include <vtkImageData.h> to translate the type
    flip->SetInput(dicomReader->GetOutput());
    flip->SetFilteredAxes(1);
    skinExtractor->SetInputConnection(flip->GetOutputPort());
    //skinExtractor->SetInputConnection(dicomReader->GetOutputPort());
    skinExtractor->SetValue(0, 100);    


    vtkSmartPointer<vtkSmoothPolyDataFilter> smooth = vtkSmoothPolyDataFilter::New();
    smooth->SetInput( skinExtractor->GetOutput());
    smooth->SetNumberOfIterations( 500 );

    vtkSmartPointer<vtkPolyDataNormals> skinNormals =
        vtkSmartPointer<vtkPolyDataNormals>::New();

    skinNormals->SetInputConnection(smooth->GetOutputPort());
    skinNormals->SetFeatureAngle(60.0);        

    vtkSmartPointer<vtkStripper> skinStripper =        //create triangle strips and/or poly-lines 为了更快的显示速度
        vtkSmartPointer<vtkStripper>::New();
    skinStripper->SetInputConnection(skinNormals->GetOutputPort()); 

    vtkSmartPointer<vtkPolyDataMapper> skinMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    skinMapper->SetInputConnection(skinStripper->GetOutputPort());
    skinMapper->ScalarVisibilityOff();    

    vtkSmartPointer<vtkActor> skin =
        vtkSmartPointer<vtkActor>::New();
    skin->SetMapper(skinMapper); 
    vtkSmartPointer<vtkProperty> backProp = vtkSmartPointer<vtkProperty>::New();
    backProp->SetDiffuseColor(1.0, 0.8, 0.85);
    skin->SetBackfaceProperty(backProp);

    vtkSmartPointer<vtkOutlineFilter> outlineData =
        vtkSmartPointer<vtkOutlineFilter>::New();
    outlineData->SetInputConnection(flip->GetOutputPort());

    vtkSmartPointer<vtkPolyDataMapper> mapOutline =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    mapOutline->SetInputConnection(outlineData->GetOutputPort());

    vtkSmartPointer<vtkActor> outline =
        vtkSmartPointer<vtkActor>::New();
    outline->SetMapper(mapOutline);
    outline->GetProperty()->SetColor(0, 0, 0);
    
    vtkSmartPointer<vtkCamera> aCamera =
        vtkSmartPointer<vtkCamera>::New();
    aCamera->SetViewUp (0, 0, 1);
    aCamera->SetPosition (0, 1, 0);
    aCamera->SetFocalPoint (0, 0, 0);
    aCamera->ComputeViewPlaneNormal();
    aCamera->Azimuth(30.0);
    aCamera->Elevation(30.0);

    aRenderer->AddActor(outline);
    aRenderer->AddActor(skin);
    aRenderer->SetActiveCamera(aCamera);
    aRenderer->ResetCamera();
    aCamera->Dolly(1.5);

    aRenderer->SetBackground(.2, .3, .4);
    renWin->SetSize(640, 480);

    aRenderer->ResetCameraClippingRange ();
    
    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = 
    vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    iren->SetInteractorStyle( style );
 
    //Use vtkTriangle::ComputeNormal() to compute the plane normal. 
    //Then use the first point as the Origin of the plane.
    double point1[3] = {60, 61, 0};
    double point2[3] = {51, 65, 55};
    double point3[3] = {78, 45, 114};
    double normal[3];
    double verticalPlaneNormal[3] = {0, 0, -1};
    double frontalPlaneNoraml[3]  = {0, 1, 0};  
    // measureNormal = normal
    double measureNormal[3] = {0, 1, 0};

    // calculate the normal with 3 points and set up for a plane
    vtkSmartPointer<vtkPlane> planeNew = vtkPlane::New();
    vtkTriangle::ComputeNormal(point1, point2, point3, normal);
    planeNew->SetOrigin(point1);
    planeNew->SetNormal(normal);

#ifndef Render_2
    vtkSmartPointer<vtkConeSource> cone = vtkConeSource::New();
    cone->SetHeight( 3.0 );
    cone->SetRadius( 1.0 );
    cone->SetResolution( 10 );
    vtkSmartPointer<vtkPolyDataMapper> coneMapper = vtkPolyDataMapper::New();
    coneMapper->SetInputConnection(skinStripper->GetOutputPort());
    coneMapper->ScalarVisibilityOff();    
    vtkSmartPointer<vtkActor> coneSkinActor = vtkActor::New();
    coneSkinActor->SetMapper( coneMapper );
    coneSkinActor->SetBackfaceProperty(backProp);

    vtkSmartPointer<vtkActor> coneOutline =
    vtkSmartPointer<vtkActor>::New();
    coneOutline->SetMapper(mapOutline);
    coneOutline->GetProperty()->SetColor(0,0,0); 

    rRenderer->AddActor(outline);
    rRenderer->AddActor(coneSkinActor);
        
    vtkSmartPointer<vtkCamera> rCamera =
    vtkSmartPointer<vtkCamera>::New();
    rCamera->SetViewUp (0, 0, 1);
    rCamera->SetPosition (0, -1, 0);
    rCamera->SetFocalPoint (0, 0, 0);
    rCamera->ComputeViewPlaneNormal();
    rCamera->Azimuth(30.0);
    rCamera->Elevation(30.0);
    rRenderer->SetActiveCamera(rCamera);
    rRenderer->ResetCamera();

    vtkSmartPointer<vtkClipPolyData> cliper = vtkClipPolyData::New();
    cliper->SetInput(skinStripper->GetOutput());
    cliper->SetClipFunction(planeNew);
    cliper->Update();

    // set up representation for vtkImplicitPlaneWidget2 
    // you could set the normal and origin with the value you want 
    vtkSmartPointer<vtkImplicitPlaneRepresentation> rep = 
    vtkSmartPointer<vtkImplicitPlaneRepresentation>::New();
    rep->SetPlaceFactor(1.25); // This must be set prior to placing the widget
    rep->PlaceWidget(coneSkinActor->GetBounds());
#ifndef SET_VALUE
    rep->SetNormal(measureNormal);
    rep->SetOrigin(point3);
#endif
    vtkSmartPointer<vtkImplicitPlaneWidget2> implicitPlaneWidget = vtkImplicitPlaneWidget2::New();
    implicitPlaneWidget->SetInteractor(iren);
    // this set the representation for the widget thus the normal and origin is transfer to the widget
    implicitPlaneWidget->SetRepresentation(rep);

    vtkSmartPointer<VTKImplicitPlaneWidget2Callback> pCall = VTKImplicitPlaneWidget2Callback::New();
    pCall->setPlane(planeNew);
    pCall->setActor(coneSkinActor);
    pCall->setCliper(cliper);

    implicitPlaneWidget->AddObserver(vtkCommand::EndInteractionEvent, pCall);
    implicitPlaneWidget->On();
#endif
    // Render
    renWin->Render();
    // Initialize the event loop and then start it.
    iren->Initialize();
    
    iren->Start();
}


int _tmain(int argc, _TCHAR* argv[])
{
    build3DViewBackup();
    return 0;
}

 

posted @ 2013-05-04 10:53  小兵传奇  阅读(4410)  评论(2编辑  收藏  举报