[vtkusers] Displaying a poly line using an existing array of doubles
David Doria
daviddoria+vtk at gmail.com
Wed May 19 07:48:03 EDT 2010
On Tue, May 18, 2010 at 11:27 PM, Anton Deguet <anton.deguet at jhu.edu> wrote:
> Hello,
>
> I have been able to display a polyline using an existing array of doubles along with a set of point IDs. I am now trying to do the following:
> - change the data (direct access to the array of doubles)
> - refresh the point IDs (the array is a circular buffer)
> At that point, I can't seem to get VTK to refresh the poly line.
>
> My test code looks like this for setup:
>
> // use vctDynamicVector of 3D points (vct3)
> actualData.SetSize(10);
> actualData[0] = vct3(1.0, 0.0, 0.0);
> actualData[1] = vct3(1.0, 2.0, 0.0);
> actualData[2] = vct3(4.0, 1.0, 0.0);
> actualData[3] = vct3(1.0, 0.0, 2.0);
> actualData[4] = vct3(3.0, 1.0, 2.0);
> actualData[5] = vct3(0.0, 0.0, 0.0);
> actualData[6] = vct3(1.0, 0.0, 0.0);
> actualData[7] = vct3(0.0, 1.0, 0.0);
> actualData[8] = vct3(0.0, 1.0, 2.0);
> actualData[9] = vct3(1.0, 2.0, 3.0);
>
> // create a VTK array that points to the cisst vector data
> dataArray = vtkDoubleArray::New();
> dataArray->SetNumberOfComponents(vct3::SIZE); // we set the number of components
> dataArray->SetArray(actualData[0].Pointer(), actualData.size(), 1); // number of points, last parameter tells VTK to not free the memory
>
> // points use this data
> points = vtkPoints::New();
> points->SetData(dataArray);
>
> // polyline is mostly a list of indices
> polyLine = vtkPolyLine::New();
> polyLine->GetPointIds()->SetNumberOfIds(5);
> for (unsigned int i = 0; i < 5; i++) {
> polyLine->GetPointIds()->SetId(i, 5 + i);
> }
>
> // Create a cell array to store the lines in and add the lines to it
> cells = vtkCellArray::New();
> cells->InsertNextCell(polyLine);
>
> // Create a polydata to store everything in
> polyData = vtkPolyData::New();
> polyData->SetPoints(points);
> polyData->SetLines(cells);
>
> // setup actor and mapper
> mapper = vtkPolyDataMapper::New();
> mapper->SetInput(polyData);
>
> actor = vtkActor::New();
> actor->SetMapper(mapper);
>
> The initial render works fine. Then in refresh (in a loop), I tried:
>
> // refresh which points to use
> Counter++;
> if (Counter > 5) {
> Counter = 0;
> }
> for (unsigned int i = 0; i < 5; i++) {
> polyLine->GetPointIds()->SetId(i, Counter + i);
> }
>
> // all following are attempts to tell VTK to refresh
> dataArray->SetArray(actualData[0].Pointer(), actualData.size(), 1);
> points->Modified();
> dataArray->Modified();
> polyData->Modified();
> polyLine->Modified();
> cells->Modified();
> mapper->Modified();
>
> FYI, Initially my refresh happened in a different thread but it now happens in the same thread that creates all the VTK objects. What is the obvious thing I am missing?
>
> Anton
>
I don't know what the problem is, but here is a compilable piece of
code that I think is trying to do what you want that folks can play
with to try to help you:
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkDoubleArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
int main(int, char *[])
{
vtkSmartPointer<vtkDoubleArray> dataArray =
vtkSmartPointer<vtkDoubleArray>::New();
dataArray->SetNumberOfComponents(3);
dataArray->InsertNextTuple3(1.0, 0.0, 0.0);
dataArray->InsertNextTuple3(1.0, 2.0, 0.0);
dataArray->InsertNextTuple3(4.0, 1.0, 0.0);
dataArray->InsertNextTuple3(1.0, 0.0, 2.0);
dataArray->InsertNextTuple3(3.0, 1.0, 2.0);
dataArray->InsertNextTuple3(0.0, 0.0, 0.0);
dataArray->InsertNextTuple3(1.0, 0.0, 0.0);
dataArray->InsertNextTuple3(0.0, 1.0, 0.0);
dataArray->InsertNextTuple3(0.0, 1.0, 2.0);
dataArray->InsertNextTuple3(1.0, 2.0, 3.0);
// points use this data
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
points->SetData(dataArray);
// polyline is mostly a list of indices
vtkSmartPointer<vtkPolyLine> polyLine =
vtkSmartPointer<vtkPolyLine>::New();
polyLine->GetPointIds()->SetNumberOfIds(5);
for (unsigned int i = 0; i < 5; i++)
{
polyLine->GetPointIds()->SetId(i, i);
}
// Create a cell array to store the lines in and add the lines to it
vtkSmartPointer<vtkCellArray> cells =
vtkSmartPointer<vtkCellArray>::New();
cells->InsertNextCell(polyLine);
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData =
vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
// setup actor and mapper
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInput(polyData);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
//Create a renderer, render window, and interactor
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
//Add the actor to the scene
renderer->AddActor(actor);
renderer->SetBackground(.3, .6, .3); // Background color green
//Render and interact
renderWindow->Render();
renderWindowInteractor->Start();
//change the data and refresh
int offset = 5;
for (unsigned int i = 0; i < 5; i++)
{
polyLine->GetPointIds()->SetId(i, offset + i);
}
points->Modified();
dataArray->Modified();
polyData->Modified();
polyLine->Modified();
cells->Modified();
mapper->Modified();
std::cout << "Modified." << std::endl;
renderWindow->Render();
renderer->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
Thanks,
David
More information about the vtkusers
mailing list