文章目录
增加边框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即可。