box widget

还记得之前写过的文章:【VTK】绘制Bounding Box
当时,在cone的外边生成了boundBox,这是根据原有的cone画出outline的。只要cone的位置变化,在pipe line的工作流程下,bounding box也会发生相应的改变。




接着,来看看一个场景:



这里的box是使用boxWidget画出来的。
想要实现联动的效果,需要我们自己人为控制cone,设置新的Transform:

# the obj here is our boxWidget
def boxCallback(obj, event):
    t = vtk.vtkTransform()
    obj.GetTransform(t)
    obj.GetProp3D().SetUserTransform(t)
# ...
boxWidget.AddObserver("InteractionEvent", boxCallback)




完整代码:

import vtk

# the obj here is our boxWidget
def boxCallback(obj, event):
    t = vtk.vtkTransform()
    obj.GetTransform(t)
    obj.GetProp3D().SetUserTransform(t)


# Create a Cone
cone = vtk.vtkConeSource()
cone.SetResolution(10)
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone.GetOutputPort())
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)

# A renderer and render window
renderer = vtk.vtkRenderer()
renderer.SetBackground(0, 0, 0)
renderer.AddActor(coneActor)

renwin = vtk.vtkRenderWindow()
renwin.AddRenderer(renderer)

# An interactor
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renwin)

# A Box widget
boxWidget = vtk.vtkBoxWidget()
boxWidget.SetInteractor(interactor)
boxWidget.SetProp3D(coneActor)
boxWidget.SetPlaceFactor(1)
boxWidget.PlaceWidget()
boxWidget.On()

# Connect the event to a function
boxWidget.AddObserver("InteractionEvent", boxCallback)

# Start
interactor.Initialize()
interactor.Start()

关于自定义InteractionEvent回掉函数的部分,CPP实现起来可能比较复杂:

class boxCallback : public vtkCommand
{
public:
    static boxCallback *New()
    {
        return new boxCallback;
    }
    void Execute(vtkObject *caller, unsigned long eventId, void* callData ) override
    {
        vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
        vtkBoxWidget* box = dynamic_cast<vtkBoxWidget*>( caller );
        box->GetTransform( transform );
        box->GetProp3D()->SetUserTransform( transform );
    }
};
// ...
boxCallback cb;
boxWidget->AddObserver("InteractionEvent", &cb);

3D widget的工作流程

下面的话出自:VTKUsersGuide.pdf

1_ Instantiatethewidget.
2_ Specify the vtkRenderWindow Interactor to observe. The vtkRender WindowInteractor invokes events that the widget may process.
3_ Create callbacks(i.e.,commands) as necessary using the Command / Observer mechanism — see “User Methods, Observers, and Commands” on page 29. The widgets invoke the events StartInteractionEvent, InteractionEvent, and EndInteractionEvent.
4_ Most widgets require “placing” – positioning in the scene. This typically entails specifying an instance of vtkProp3D, a dataset, or explicitly specifying a bounding box, and then invoking the PlaceWidget() method.
5_ Finally, the widget must be enabled. By default, a keypress i will enable the widget and it will appear in the scene.

注意到最后一句,i按键可以使得widget可视化。在widget如果没有调用On(),那么用户可以通过按键i激活它。

分类: python

发表评论

电子邮件地址不会被公开。 必填项已用*标注