如何告诉VTK管道使用通过TimerEvent更新的新vtkPolyData?

时间:2017-07-11 13:54:31

标签: c++ vtk

意图

我写了一个使用vtkPoints>生成螺旋的VTK应用程序。 vtkPolyLine> vtkPolyData> vtkPolyDataMapper并显示它。如果在程序初始化时静态完成,这可以正常工作。 现在,我想动态添加新的数据点。目的是实时显示测量结果,因此将以特定间隔添加新数据。

问题

目前,我刚刚实现了一个TimerEvent来更新vtkPoints和vtkPolyLine。但是,程序只显示在vtkRenderWindowInteractor启动之前生成的静态数据。我也尝试使用" Modified()"和"更新()"调用几乎所有对象,尝试删除,重新生成并向渲染器添加新actor - 但没有成功!我在下面添加了我的C ++代码......

相关-问题

以下邮件列表问题是关于这个问题,但给出的解决方案对我有用: http://public.kitware.com/pipermail/vtkusers/2006-November/038377.html

以下问题似乎有关,但没有有用的答案: VTK: update data points in renderWindow at every simulation timestep

问题

  1. 如何告诉VTK vtkPolyData对象已更改?
  2. 我应该仔细研究一下VTK用户指南?
  3. 详细信息/源代码

    我使用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;
    }
    

2 个答案:

答案 0 :(得分:2)

问题是单元格不是由指针存储的 - 当你调用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
    }
}

答案 1 :(得分:1)

昨天我使用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;
}