Emre Turkoz
Emre Turkoz

Reputation: 868

How to make the code flow without closing the VTK render window?

I'm using Visual Studio 2010, VTK 5.6 and configure my projects without using CMake.

I'm dealing with numerical computing and want to generate several plots during the runtime using VTK. Starting with the line plot example given in the VTK web page I managed to generate the plot that I want. The problem is that the code doesn't continue without closing the plot window.

From my "main.cpp" file, I send the command to a header file, where the VTK procedure is initiated.

residualPlotter(x,xdim1d);

"residualPlotter" is the function that generates the plot. It's given below:

int residualPlotter(double* res, int size)
{

  // Create a table with some points in it
  vtkSmartPointer<vtkTable> table = 
    vtkSmartPointer<vtkTable>::New();

  vtkSmartPointer<vtkFloatArray> arrX = 
    vtkSmartPointer<vtkFloatArray>::New();
  arrX->SetName("X Axis");
  table->AddColumn(arrX);

  vtkSmartPointer<vtkFloatArray> arrF = 
    vtkSmartPointer<vtkFloatArray>::New();
  arrF->SetName("Function");
  table->AddColumn(arrF);

  // Fill in the table with some example values
  table->SetNumberOfRows(size);
  for (int i = 0; i < size; ++i)
  {
    table->SetValue(i, 0, i);
    table->SetValue(i, 1, res[i]);
  }

  // Set up the view
  vtkSmartPointer<vtkContextView> view = 
    vtkSmartPointer<vtkContextView>::New();
  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
  view->GetRenderWindow()->SetSize(800,600);

  // Add multiple line plots, setting the colors etc
  vtkSmartPointer<vtkChartXY> chart = 
    vtkSmartPointer<vtkChartXY>::New();
  view->GetScene()->AddItem(chart);
  vtkPlot *line = chart->AddPlot(vtkChart::LINE);
  line->SetInput(table, 0, 1);
  line->SetColor(0, 100, 0, 255);
  line->SetWidth(1.75);


  // Set up an interactor and start
  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = 
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  renderWindowInteractor->SetRenderWindow(view->GetRenderWindow());
  renderWindowInteractor->Initialize();
  renderWindowInteractor->Start();


  return EXIT_SUCCESS;

}

So, I want the code to continue without the need to close the window. How should I modify the code?

Thank you all.

Upvotes: 2

Views: 3675

Answers (3)

Cloud Cho
Cloud Cho

Reputation: 1774

Marcus D. Hanwell mentioned a timer event at the comment. There is a code at a VTK example section. For me, I modified the snippet;

// Initialize must be called prior to creating timer events.
renderWindowInteractor->Initialize();

// Sign up to receive TimerEvent
vtkSmartPointer<vtkTimerCallback> cb = vtkSmartPointer<vtkTimerCallback>::New();
renderWindowInteractor->AddObserver(vtkCommand::TimerEvent, cb);

int timerId = renderWindowInteractor->CreateRepeatingTimer(100);
std::cout << "timerId: " << timerId << std::endl;


renderWindowInteractor->Start();

and I changed the vtkTimerCallback class at the sample code (in here, the background color keep being changed);

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)
    {
        ++this->TimerCount;
    }
    /* this section will be excuted */
    cout << this->TimerCount << " " << "This is from vtkTimerCallback" << endl;
    background_color = (double) rand() / RAND_MAX;
    cout << background_color << endl;
    renderer->SetBackground(background_color, background_color, background_color); 
    renderWindow->AddRenderer(renderer);
    renderWindow->Render();
    /* ----- */
}
private:
    int TimerCount;
};

I declared the renderer and renderWindow as global variable, so the window change the window in the main section.

Upvotes: 2

gishara
gishara

Reputation: 845

I added the grid to a vtkActor as follow:

vtkSmartPointer actor_grid = vtkSmartPointer::New();

vtkSmartPointer chart = vtkSmartPointer::New();

renderer->AddActor(actor_grid);

This works well since it is not associated with an interactor.

Thanks.

Upvotes: -1

Marcus D. Hanwell
Marcus D. Hanwell

Reputation: 6855

If you just want to render the plot, do something else, update and render again you can skip the renderWindowInteractor code, and simply call

view->Render();

This will render the plot with the data you supplied, and control will return to your code. You can continue doing this and call Render() on the view whenever you want to see an updated chart.

Upvotes: 4

Related Questions