[英]How to tell VTK pipeline to use new vtkPolyData updated via TimerEvent?
我寫了一個VTK應用程序,使用vtkPoints> vtkPolyLine> vtkPolyData> vtkPolyDataMapper生成螺旋並顯示它。 如果在程序初始化時靜態完成,這可以正常工作。 現在,我想動態添加新的數據點。 目的是實時顯示測量結果,因此將以特定間隔添加新數據。
目前,我剛剛實現了一個TimerEvent來更新vtkPoints和vtkPolyLine。 但是,程序只顯示在vtkRenderWindowInteractor啟動之前生成的靜態數據。 我還嘗試使用“Modified()”和“Update()”調用幾乎所有對象,嘗試刪除,重新生成並向渲染器添加新actor - 但沒有成功! 我在下面添加了我的C ++代碼......
以下郵件列表問題是關於這個問題,但給出的解決方案對我不起作用: http ://public.kitware.com/pipermail/vtkusers/2006-November/038377.html
以下問題似乎是相關的,但沒有有用的答案: VTK:在每個模擬時間步驟更新renderWindow中的數據點
我正在使用Visual Studio Community 2017和VTK 8.0.0,它們都編譯為Win32目標。
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New();
int numOfPoints = 0;
double t = 0;
void NextPoint() {
double x = t * cos(t);
double y = t * sin(t);
points->InsertNextPoint(x, y, t);
polyLine->GetPointIds()->InsertNextId(numOfPoints);
numOfPoints++;
t += 0.1;
}
vtkSmartPointer<vtkPolyData> generateEllipse() {
// Add some points so we actually see something at all...
for (int i = 0; i < 100; ++i) {
NextPoint();
}
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
cells->InsertNextCell(polyLine);
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
return polyData;
}
class vtkTimerCallback : public vtkCommand
{
public:
static vtkTimerCallback *New()
{
vtkTimerCallback *cb = new vtkTimerCallback;
cb->TimerCount = 0;
return cb;
}
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long eventId,
void *vtkNotUsed(callData))
{
if (vtkCommand::TimerEvent == eventId)
{
NextPoint(); // Add another point to polyData
++this->TimerCount;
cout << this->TimerCount << endl;
}
}
private:
int TimerCount;
};
int main(int argc, char** argv) {
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkPolyData> data = generateEllipse();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(data);
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetDiffuseColor(255, 255, 0);
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
renderer->ResetCamera();
renderWindow->Render();
// Add Timer Event...
rwi->Initialize();
vtkSmartPointer<vtkTimerCallback> cb = vtkSmartPointer<vtkTimerCallback>::New();
rwi->AddObserver(vtkCommand::TimerEvent, cb);
int timerId = rwi->CreateRepeatingTimer(100); // every 100ms
std::cout << "timerId: " << timerId << std::endl;
// Start Displaying...
rwi->Start();
return 0;
}
問題是當你調用cells->InsertNextCell(polyLine);
時,指針不存儲cells->InsertNextCell(polyLine);
數據被復制,而不是指向,以便在數組中創建單元格的有效存儲(整個實現實際上是在vtkCellArray的標題中,因此您可以檢查它)。 因此,當您更新polyLine時,它對polydata沒有影響,因為polydata有自己的副本,您沒有更新。 以下代碼適用於我(您必須公開polydata和cellArray):
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long eventId,
void *vtkNotUsed(callData))
{
if (vtkCommand::TimerEvent == eventId)
{
NextPoint(); // Add another point to polyData
cells->Initialize(); // reset the cells to remove the old spiral
cells->InsertNextCell(polyLine); // re-insert the updated spiral
cells->Modified(); // required to update
data->Modified(); // required to update
++this->TimerCount;
cout << polyLine->GetNumberOfPoints() << endl;
renderWindow->Render(); // refresh the render window after each update
}
}
昨天我使用vtkProgrammableDataObjectSource作為DataSource制定了另一種解決方案。 Tomj的解決方案是更直接和簡單的解決方案......但是,vtk.org上沒有C ++示例代碼,它解釋了如何使用vtkProgrammableDataObjectSource,我必須通過反復試驗來解決它。 所以我會在這里發布,因為它可能對其他人有所幫助:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <vtkProgrammableFilter.h>
#include <vtkCallbackCommand.h>
#include <vtkPolyDataStreamer.h>
#include <vtkProgrammableDataObjectSource.h>
vtkSmartPointer<vtkProgrammableDataObjectSource> pDOS = vtkSmartPointer<vtkProgrammableDataObjectSource>::New();
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New();
int numOfPoints = 0;
double t = 0;
void NextPoint() {
double x = t * cos(t);
double y = t * sin(t);
points->InsertNextPoint(x, y, t);
polyLine->GetPointIds()->InsertNextId(numOfPoints);
numOfPoints++;
t += 0.1;
}
void generateEllipse(void *caller) {
vtkProgrammableDataObjectSource *pDOS = vtkProgrammableDataObjectSource::SafeDownCast((vtkObjectBase*)caller);
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
cells->InsertNextCell(polyLine);
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
pDOS->SetOutput(polyData);
}
int counter2 = 0;
void TimerCallbackFunction(vtkObject* caller, long unsigned int vtkNotUsed(eventId), void* clientData, void* vtkNotUsed(callData)) {
cout << "timer callback: " << counter2 << endl;
// To avoid globals we can implement this later...
// vtkSmartPointer<vtkProgrammableDataObjectSource> pDOS =
// static_cast<vtkProgrammableDataObjectSource*>(clientData);
vtkRenderWindowInteractor *rwi =
static_cast<vtkRenderWindowInteractor*>(caller);
NextPoint();
pDOS->Modified();
rwi->Render();
renderer->ResetCamera(); // Optional: Reposition Camera, so it displays the whole object
counter2++;
}
int main(int argc, char** argv) {
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
rwi->SetRenderWindow(renderWindow);
pDOS->SetExecuteMethod(&generateEllipse, pDOS);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(pDOS->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetDiffuseColor(255, 255, 0);
renderWindow->AddRenderer(renderer);
renderer->AddActor(actor);
renderer->ResetCamera();
renderWindow->Render();
// Add Timer Event...
vtkSmartPointer<vtkCallbackCommand> timerCallback = vtkSmartPointer<vtkCallbackCommand>::New();
timerCallback->SetCallback(TimerCallbackFunction);
rwi->Initialize();
rwi->CreateRepeatingTimer(100);
rwi->AddObserver(vtkCommand::TimerEvent, timerCallback);
// Start Displaying...
rwi->Start();
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.