VTK|结合qt创建通用按钮控制显隐(边框、坐标轴、点线面)

增加边框BoundingBox

增加边框BoundingBox并通过按钮控制显隐
需要的全局变量

    // 显示场景
    QVTKOpenGLWidget *m_pScene;
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow_;
    vtkSmartPointer<vtkRenderer> renderer_;
    // 边框显示
    vtkSmartPointer<vtkActor> boundingBoxActor_; // 用于存储BoundingBox的Actor
    bool isBoundingBoxVisible_;                  // 控制BoundingBox的显隐状态
    vtkSmartPointer<vtkTextActor> boundingBoxButtonActor_; 

添加addBoundingBox

void ThreeDimensionalDisplayPage::addBoundingBox(vtkSmartPointer<vtkPolyData> polyData)
{
    if (boundingBoxActor_)
    {
        renderer_->RemoveActor(boundingBoxActor_);
        boundingBoxActor_ = nullptr;
    }

    vtkNew<vtkOutlineFilter> outlineFilter;
    outlineFilter->SetInputData(polyData);
    outlineFilter->Update();

    vtkNew<vtkPolyDataMapper> outlineMapper;
    outlineMapper->SetInputConnection(outlineFilter->GetOutputPort());

    boundingBoxActor_ = vtkSmartPointer<vtkActor>::New();
    boundingBoxActor_->SetMapper(outlineMapper);
    boundingBoxActor_->GetProperty()->SetColor(1.0, 0.0, 0.0);
    boundingBoxActor_->GetProperty()->SetLineWidth(2.0);
    boundingBoxActor_->SetVisibility(isBoundingBoxVisible_); // 根据状态决定是否显示

    renderer_->AddActor(boundingBoxActor_);
}

添加BoundingBox控制按钮

void ThreeDimensionalDisplayPage::addBoundingBoxControlButton()
{
    // 避免重复添加
    if (boundingBoxButtonActor_ && renderer_->HasViewProp(boundingBoxButtonActor_))
        return;

    vtkNew<vtkTextActor> textActor;
    textActor->SetInput("Hide Bounding Box");

    vtkTextProperty *textProp = textActor->GetTextProperty();
    textProp->SetFontSize(24);
    textProp->SetColor(0.0, 0.0, 0.0);           // 黑色文字
    textProp->SetBackgroundColor(0.8, 0.8, 0.8); // 灰色背景
    textProp->SetBackgroundOpacity(1.0);
    textProp->SetFrame(1);
    textProp->SetFrameColor(0.0, 0.0, 0.0);

    textActor->SetDisplayPosition(10, 10);
    renderer_->AddActor2D(textActor);
    boundingBoxButtonActor_ = textActor;

    // 注册鼠标点击事件(只注册一次)
    static bool observerAdded = false;
    if (!observerAdded)
    {
        vtkNew<vtkCallbackCommand> clickCallback;
        clickCallback->SetClientData(this);
        clickCallback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *)
                                   {
            auto *self = static_cast<ThreeDimensionalDisplayPage *>(clientData);
            int *clickPos = static_cast<vtkRenderWindowInteractor *>(caller)->GetEventPosition();

            int x = clickPos[0];
            int y = clickPos[1];

            // 判断是否点击在按钮上(近似判断)
            int *pos = self->boundingBoxButtonActor_->GetPositionCoordinate()->GetComputedDisplayValue(self->renderer_);
            int btnX = pos[0];
            int btnY = pos[1];
            int width = 220, height = 40;

            if (x >= btnX && x <= btnX + width &&
                y >= btnY && y <= btnY + height)
            {
                self->OnBoundingBoxButtonClicked();
            } });
        interactor_->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
        observerAdded = true;
    }

    isBoundingBoxVisible_ = true;
}

点击按钮之后的槽函数


void ThreeDimensionalDisplayPage::OnBoundingBoxButtonClicked()
{
    if (!boundingBoxActor_)
        return;

    isBoundingBoxVisible_ = !isBoundingBoxVisible_;
    boundingBoxActor_->SetVisibility(isBoundingBoxVisible_);

    if (boundingBoxButtonActor_)
    {
        boundingBoxButtonActor_->SetInput(isBoundingBoxVisible_ ? "Hide Bounding Box" : "Show Bounding Box");
    }

    renderWindow_->Render();
}

添加坐标轴

需要的全局变量,防止重复创建

    // 坐标轴显示
    vtkSmartPointer<vtkAxesActor> axes_;
    vtkSmartPointer<vtkOrientationMarkerWidget> marker_;

创建坐标轴

void ThreeDimensionalDisplayPage::addCoordinateAxes()
{
    if (!axes_)
        axes_ = vtkSmartPointer<vtkAxesActor>::New();
    axes_->SetTotalLength(10.0, 10.0, 10.0);

    if (!marker_)
        marker_ = vtkSmartPointer<vtkOrientationMarkerWidget>::New();

    marker_->SetOrientationMarker(axes_);
    marker_->SetOutlineColor(0.9300, 0.5700, 0.1300);
    marker_->SetInteractor(m_pScene->GetInteractor());
    marker_->SetDefaultRenderer(renderer_);
    marker_->SetViewport(0.8, 0.0, 1.0, 0.2);
    marker_->SetEnabled(1);
    marker_->InteractiveOn();
}

增加点线面显隐控制按钮

需要的全局变量,防止重复创建

    // 添加控制点线面显隐的按钮到三维显示界面
    void addObjVisibilityControlButtons();
    // 控制面显示槽函数
    void toggleSurfaceVisibility();
    // 控制线显示槽函数
    void toggleWireframeVisibility();
    // 控制点显示槽函数
    void togglePointsVisibility();
    // 控制obj点线面的显隐
    vtkSmartPointer<vtkActor> surfaceActor_;
    vtkSmartPointer<vtkActor> wireframeActor_;
    vtkSmartPointer<vtkActor> pointsActor_;
    // 控制obj点线面显隐的按钮
    vtkSmartPointer<vtkTextActor> surfaceToggleButton_;
    vtkSmartPointer<vtkTextActor> wireframeToggleButton_;
    vtkSmartPointer<vtkTextActor> pointsToggleButton_;

添加控制点线面显隐的按钮到三维显示界面

void ThreeDimensionalDisplayPage::addObjVisibilityControlButtons()
{
    // 如果已经创建过按钮,则直接重新添加到 renderer_
    if (surfaceToggleButton_)
    {
        surfaceToggleButton_->SetInput("Hide Surface");
        wireframeToggleButton_->SetInput("Hide Wireframe");
        pointsToggleButton_->SetInput("Hide Points");
        renderer_->AddActor2D(surfaceToggleButton_);
        renderer_->AddActor2D(wireframeToggleButton_);
        renderer_->AddActor2D(pointsToggleButton_);
        return;
    }

    // 按钮文字及初始状态
    std::vector<std::pair<std::string, vtkSmartPointer<vtkTextActor> *>> buttons = {
        {"Hide Surface", &surfaceToggleButton_},
        {"Hide Wireframe", &wireframeToggleButton_},
        {"Hide Points", &pointsToggleButton_}};

    int startY = 60; // 初始 Y 位置
    for (auto &[text, actorPtr] : buttons)
    {
        auto textActor = vtkSmartPointer<vtkTextActor>::New();
        textActor->SetInput(text.c_str());
        auto *textProp = textActor->GetTextProperty();
        textProp->SetFontSize(20);
        textProp->SetColor(0.0, 0.0, 0.0);
        textProp->SetBackgroundColor(0.9, 0.9, 0.9);
        textProp->SetBackgroundOpacity(1.0);
        textProp->SetFrame(1);
        textProp->SetFrameColor(0.0, 0.0, 0.0);
        textActor->SetDisplayPosition(10, startY);
        renderer_->AddActor2D(textActor);
        *actorPtr = textActor;
        startY += 50; // 下一个按钮向下偏移
    }

    // 注册鼠标事件(只注册一次)
    static bool observerAdded = false;
    if (!observerAdded)
    {
        vtkNew<vtkCallbackCommand> clickCallback;
        clickCallback->SetClientData(this);
        clickCallback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *)
                                   {
            auto* self = static_cast<ThreeDimensionalDisplayPage*>(clientData);
            int* clickPos = static_cast<vtkRenderWindowInteractor*>(caller)->GetEventPosition();
            int x = clickPos[0];
            int y = clickPos[1];

            std::vector<std::pair<vtkSmartPointer<vtkTextActor>, std::function<void()>>> buttons = {
                {self->surfaceToggleButton_, [&]() { self->toggleSurfaceVisibility(); }},
                {self->wireframeToggleButton_, [&]() { self->toggleWireframeVisibility(); }},
                {self->pointsToggleButton_, [&]() { self->togglePointsVisibility(); }}
            };

            for (auto& [actor, func] : buttons)
            {
                int* pos = actor->GetPositionCoordinate()->GetComputedDisplayValue(self->renderer_);
                int bx = pos[0];
                int by = pos[1];
                int width = 200, height = 40;

                if (x >= bx && x <= bx + width &&
                    y >= by && y <= by + height)
                {
                    func();
                    break;
                }
            } });

        interactor_->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
        observerAdded = true;
    }
}

控制面显示槽函数


void ThreeDimensionalDisplayPage::toggleSurfaceVisibility()
{
    if (surfaceActor_)
    {
        bool visible = surfaceActor_->GetVisibility();
        surfaceActor_->SetVisibility(!visible);
        if (surfaceToggleButton_)
            surfaceToggleButton_->SetInput(visible ? "Show Surface" : "Hide Surface");
        renderWindow_->Render();
    }
}

控制线显示槽函数

void ThreeDimensionalDisplayPage::toggleWireframeVisibility()
{
    if (wireframeActor_)
    {
        bool visible = wireframeActor_->GetVisibility();
        wireframeActor_->SetVisibility(!visible);
        if (wireframeToggleButton_)
            wireframeToggleButton_->SetInput(visible ? "Show Wireframe" : "Hide Wireframe");
        renderWindow_->Render();
    }
}

控制点显示槽函数


void ThreeDimensionalDisplayPage::togglePointsVisibility()
{
    if (pointsActor_)
    {
        bool visible = pointsActor_->GetVisibility();
        pointsActor_->SetVisibility(!visible);
        if (pointsToggleButton_)
            pointsToggleButton_->SetInput(visible ? "Show Points" : "Hide Points");
        renderWindow_->Render();
    }
}

也可以使用qpushbutton进行控制,逻辑更加简单,不需要场景里添加按钮了,创建按钮后直接连接toggleSurfaceVisibility即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奇树谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值