VTK -更新vtkPolyData在renderWindow没有阻塞交互
VTK - update vtkPolyData in renderWindow without blocking interaction
我使用VTK来显示点云并在循环中更新它。第一次显示云时,窗口可以通过鼠标进行交互,如果我想更新云,我必须按"q",窗口将显示更新的云。然而,虽然云被更新并正确地显示在窗口中,但我失去了对窗口的控制(即不能使用鼠标移动或旋转窗口中的点云)。
下面是我重新创建问题的最小代码。我有一个可视化类来处理这个,它的初始化列表:
points(vtkSmartPointer<vtkPoints>::New())
, vertices(vtkSmartPointer<vtkCellArray>::New())
, pointsPolyData(vtkSmartPointer<vtkPolyData>::New())
, mapper(vtkSmartPointer<vtkPolyDataMapper>::New())
, actor(vtkSmartPointer<vtkActor>::New())
, renderer(vtkSmartPointer<vtkRenderer>::New())
, renderWindow(vtkSmartPointer<vtkRenderWindow>::New())
, renderWindowInteractor(vtkSmartPointer<vtkRenderWindowInteractor>::New())
init函数:
void Visualization::init(const cv::Mat &point_cloud){
noPoints = point_cloud.cols * point_cloud.rows;
// Preallocate memory
points->SetNumberOfPoints(noPoints);
// Copy
int element_stripe = sizeof(float) * point_cloud.channels();
for (unsigned i = 0; i < noPoints; i++)
{
float x = point_cloud.at<cv::Vec3f>(i)[0];
float y = point_cloud.at<cv::Vec3f>(i)[1];
float z = point_cloud.at<cv::Vec3f>(i)[2];
vtkIdType pid[1] = {i};
points->SetPoint(i, x, y, z);
vertices->InsertNextCell(1, pid);
}
// Push data to polydata
pointsPolyData->SetPoints(points);
pointsPolyData->SetVerts(vertices);
// Set visualization pipeline
mapper->SetInputData(pointsPolyData);
actor->SetMapper(mapper);
actor->GetProperty()->SetPointSize(2);
renderWindow->AddRenderer(renderer);
renderer->SetBackground(.3,.6,.3);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
isPipelineInit = true;
renderWindow->Render();
renderWindowInteractor->Start();
}
下面是display函数:
void Visualization::display(const cv::Mat &point_cloud){
if(!isPipelineInit)
init(point_cloud);
else
{
// Copy
int element_stripe = sizeof(float) * point_cloud.channels();
for (unsigned i = 0; i < noPoints; i++)
{
points->SetPoint(i, (float*)(point_cloud.data + i*element_stripe));
}
pointsPolyData->Modified();
mapper->Update();
renderWindowInteractor->GetRenderWindow()->Render();
}
}
我还有一个函数在线程中运行一个无限循环:
void Visualization::run()
{
while (1) // infinite while loop
{
// Update m_clouds and display
display(m_clouds);
}
}
更新:正如mirni提醒我,"q"键基本上退出当前的renderWindow,我后来看到的实际上是来自display
函数,而不是init
。在display
中,我没有调用renderWindowInteractor->Start()
,因此我不能与窗口交互。然而,renderWindowInteractor->Start()
卡住了我当前的线程,因此我不能继续我的程序并更新我的vtkPolyData。
我想问题变成了:如何同时显示和更新?我是否应该在不同的线程中做,一个用于显示,另一个用于更新?
谢谢!
您的问题的答案是:您只需更新数据并调用vtkRenderWindow::Render()
方法。VTK渲染管道自己发现数据已经改变,需要更新。
你的代码真的需要重新设计——当数据改变(只有一次)时更新可视化更有意义,而不是一直探测数据"有任何改变吗?"(每一毫秒)。
此外,通常您不需要为VTK可视化管道单独的线程。保持简洁:
- 不要让可视化对象成为线程。(如果你有100个对象呢?您会创建100个单独的线程吗?
- 去掉无限循环。
- 将
display(...)
方法重命名为
void Visualization::update(const cv::Mat &point_cloud);
使其公开,并在数据更改时从外部调用它,以适合您的场景的任何方式(回调?Qt的信号吗?口信吗?……)。确保在最后保留vtkRenderWindow::Render()调用。
-
您可能想要考虑直接从cv::Mat结构中复制数据,使用原始指针指向
vtkPoints::GetVoidPointer(int)
暴露的点数据,并执行memcopy而不是for循环,但是在您有事情并且您的测量显示需要优化之前不要这样做。(过早优化是根…) -
vtkRenderWindowInteractor::Start()
启动事件循环并劫持线程。而不是Start()
,只需调用Initialize()
来启用交互器,但让控制流继续。
HTH,米罗
- Qt VTK交互风格的信号到小部件
- Qt Quick-如何仅从c++代码与qml属性交互
- SFML RenderWindow打开窗口需要很长时间
- 复制和交换习惯用法与移动操作之间的交互
- 初学者问题:如何使用这些晦涩难懂的命令,例如C++中的'RenderWindow'
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- Qt QGraphicsProxyWidget 与 QGraphicsScene 的交互
- 使用 Python 事件并与 C++ 交互
- 函数-本地枚举声明和 ADL 的交互
- 如何在扩展的QQuickItem中与模型交互
- 如何将sf::RenderWindow传递给另一个函数
- 寻找C++中数组和cout交互的解决方案
- C++继承和"常量"交互的问题
- 以太坊与外部 c++ 库的交互稳定性
- 玩家移动和碰撞之间的交互问题
- C++ 和 Lua 函数之间的交互与 3D 矢量参数
- 内存分配究竟是如何发生的,Java和C如何交互以跟踪同一对象?
- 如何包装对象,使它们成为无法交互的单独类型?
- 通过交互器获取向量中的索引
- VTK -更新vtkPolyData在renderWindow没有阻塞交互