view src/vtkplot.cpp @ 41:834f8e778a65

Setup initial interface to vtkplot
author Jordi Gutiérrez Hermoso <jordigh@gmail.com>
date Fri, 12 Mar 2010 09:24:31 -0600
parents eaa99e09607d
children 3f8311cbf602
line wrap: on
line source

#include "include/vtkplot.hpp"

#include <vtkPoints.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
#include <vtkLookupTable.h>

#include <vtkPolyData.h>
#include <vtkPolyDataNormals.h>
#include <vtkPolyDataMapper.h>

#include <vtkWarpScalar.h>

#include <vtkCamera.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>

#include <vtkInteractorStyleTerrain.h>

#include <vtkSmartPointer.h>
#include <vtkDoubleArray.h>

#include <vtkGraphicsFactory.h>
#include <vtkImagingFactory.h>
#include <vtkWindowToImageFilter.h>
#include <vtkPNGWriter.h>


#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProgrammableFilter.h>
#include <vtkCommand.h>
#include <vtkCamera.h>

#include <string>
#include <sstream>
#include <iomanip> 

// *************** move this stuff into a class ************************

unsigned int GridSize = 50;

using namespace std;

double F(double x, double y, double t)
{
  return sin(y)*cos(x)*sin(t);
}

class CommandSubclass : public vtkCommand
{
public:
  vtkTypeRevisionMacro(CommandSubclass, vtkCommand);
  static CommandSubclass *New()
  {
    return new CommandSubclass;
  }
 
  void Execute(vtkObject *caller, unsigned long eventId, 
               void *callData)
  {
    cout << "timer callback" << endl;
 
    vtkRenderWindowInteractor *iren = 
      static_cast<vtkRenderWindowInteractor*>(caller);
 
    this->ProgrammableFilter->Modified();
 
    iren->Render();
 
  }
 
  vtkSmartPointer<vtkProgrammableFilter> ProgrammableFilter;
 
};

vtkCxxRevisionMacro(CommandSubclass, "$Revision: 1.1 $");
 
void AdjustPoints(void* arguments)
{
  cout << "AdjustPoints" << endl;
  vtkProgrammableFilter* programmableFilter = 
    static_cast<vtkProgrammableFilter*>(arguments);
 
  vtkPoints* inPts = programmableFilter->GetPolyDataInput()->GetPoints();
  vtkIdType numPts = inPts->GetNumberOfPoints();
  vtkSmartPointer<vtkPoints> newPts =
    vtkSmartPointer<vtkPoints>::New();
  newPts->SetNumberOfPoints(numPts);
 
  vtkSmartPointer<vtkDoubleArray> newScalars 
    = vtkSmartPointer<vtkDoubleArray>::New();

  static double t = 0;

  for(vtkIdType i = 0; i < numPts; i++)
  {
    double p[3];
    inPts -> GetPoint(i,p);
    p[2] = F(p[0],p[1],t);
    newPts -> SetPoint(i,p);
    newScalars -> InsertTuple(i, &p[2]);
	}

  t += 0.05;
 
  programmableFilter->
    GetPolyDataOutput()->CopyStructure(programmableFilter->GetPolyDataInput());

  programmableFilter->GetPolyDataOutput()->SetPoints(newPts);
  programmableFilter
    ->GetPolyDataOutput()
    ->GetPointData() -> SetScalars(newScalars);
}

typedef double (*Func3d)(double, double, double);

void InitOffscreen(bool offscreen);

vtkSmartPointer<vtkDelaunay2D> TriangulateTerrain(Func3d func);

void PlotPoints(vtkSmartPointer<vtkDelaunay2D> delaunay, 
                bool offscreen);

void InitOffscreen(bool offscreen)
{
  // Graphics Factory
  vtkSmartPointer<vtkGraphicsFactory> graphics_factory
    = vtkSmartPointer<vtkGraphicsFactory>::New();
  graphics_factory->SetOffScreenOnlyMode( offscreen );
  graphics_factory->SetUseMesaClasses( offscreen );

  // Imaging Factory
  vtkSmartPointer<vtkImagingFactory>  imaging_factory
    = vtkSmartPointer<vtkImagingFactory>::New();
  imaging_factory->SetUseMesaClasses( offscreen );
}

vtkSmartPointer<vtkDelaunay2D> TriangulateTerrain(Func3d func)
{

	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  vtkSmartPointer<vtkDoubleArray> scalars = vtkSmartPointer<vtkDoubleArray>::New();
 

	for(double x = -3; x < 3; x += 6.0/GridSize)
	{
		for(double y = -3; y < 3; y += 6.0/GridSize)
		{
      double r = sqrt(9-y*y)*sqrt(9-x*x)/3;
      double z = func(x,r,0);
			vtkIdType idx = points->InsertNextPoint(x,r, z);
      scalars -> InsertTuple(idx, &z);
		}
	}
 
	//add the grid points to a polydata object
	vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
	polydata->SetPoints(points);
  polydata->GetPointData() -> SetScalars(scalars);

	//triangulate the grid points
	vtkSmartPointer<vtkDelaunay2D> delaunay 
    = vtkSmartPointer<vtkDelaunay2D>::New();
	delaunay->SetInput(polydata);
	delaunay->Update();

  bool offscreen = false;
  InitOffscreen(offscreen);

  vtkSmartPointer<vtkProgrammableFilter> programmableFilter = 
    vtkSmartPointer<vtkProgrammableFilter>::New();
  programmableFilter->SetInput(delaunay -> GetOutput());
  programmableFilter->SetExecuteMethod(AdjustPoints, programmableFilter);


  //Normals for Gourad shading
  vtkSmartPointer<vtkPolyDataNormals> normals 
    =  vtkSmartPointer<vtkPolyDataNormals>::New();
  normals -> SetInputConnection(programmableFilter -> GetOutputPort() );
  normals -> SetFeatureAngle(60);

  //Set the colours for the rendering
  vtkSmartPointer<vtkLookupTable> lut 
    = vtkSmartPointer<vtkLookupTable>::New();
  lut -> SetHueRange(0.66667, 0.0);
  lut -> SetNumberOfColors(256);
  lut -> SetRampToLinear();
  lut -> Build();

  
	// map the contours to graphical primitives
	vtkSmartPointer<vtkPolyDataMapper> contMapper 
    = vtkSmartPointer<vtkPolyDataMapper>::New();
  contMapper->SetInput(normals -> GetOutput() );
  contMapper->SetScalarRange(0,1);
  contMapper->SetLookupTable(lut);
  contMapper->ImmediateModeRenderingOn();

 
  // create an actor for the contours
	vtkSmartPointer<vtkActor> contActor 
    = vtkSmartPointer<vtkActor>::New();
	contActor->SetMapper(contMapper);
 
  // a renderer and render window
	vtkSmartPointer<vtkRenderer> ren1 =
    vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderWindow> renWin 
    = vtkSmartPointer<vtkRenderWindow>::New();
  if(offscreen)
  {
    renWin->SetOffScreenRendering(1);
  }
	renWin->AddRenderer(ren1);

  // an interactor
  vtkSmartPointer<vtkRenderWindowInteractor> iren 
    = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renWin);  

  // Initialize must be called prior to creating timer events.
  iren->Initialize();
  iren->CreateRepeatingTimer(10);
 
  vtkSmartPointer<CommandSubclass> timerCallback = 
    vtkSmartPointer<CommandSubclass>::New();
  timerCallback->ProgrammableFilter = programmableFilter;
 
  iren->AddObserver ( vtkCommand::TimerEvent, timerCallback );

	// add the actors to the scene
	ren1->SetBackground(0.0,0.0,0.0);
  ren1->GetActiveCamera()->SetViewUp(0,0,1);
  ren1->GetActiveCamera()->SetPosition(1, 0, 1);
  ren1->GetActiveCamera()->SetParallelProjection(1);
	ren1->AddActor(contActor);
  ren1->ResetCamera();
 
  // render an image (lights and cameras are created automatically)
	renWin->Render();

  if(offscreen)
  {
    for(size_t i = 0; i < 1000; i++)
    {
      string filename = "foo";
      stringstream ss; string i_str;
      ss << setw(4) << setfill('0')  << i;
      ss >> i_str;
      filename += i_str + ".png";
   
      // Write to file
      vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = 
        vtkSmartPointer<vtkWindowToImageFilter>::New();
      windowToImageFilter->SetInput(renWin);
      windowToImageFilter->Update();
 
      vtkSmartPointer<vtkPNGWriter> writer 
        = vtkSmartPointer<vtkPNGWriter>::New();
      writer->SetFileName(filename.c_str() );
      writer->SetInput(windowToImageFilter->GetOutput());
      writer->Write();

      programmableFilter -> Modified();
    }
  }
  else
  {
    //The style
    vtkSmartPointer<vtkInteractorStyleTerrain> terrain_style 
      = vtkSmartPointer<vtkInteractorStyleTerrain>::New();
 
    // Set the style
    iren -> SetInteractorStyle(terrain_style);
  
    // begin mouse interaction
    iren->Start(); 
  }
  return delaunay;
}