view src/vtkplot.cpp @ 42:3f8311cbf602

Setup initial class for vtkplot; cleanup interpolator to use C++1x's auto and untabify
author Jordi Gutiérrez Hermoso <jordigh@gmail.com>
date Sat, 13 Mar 2010 15:55:11 -0600 (2010-03-13)
parents 834f8e778a65
children 8aea477c7cf8
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> 

namespace kwantix{

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

template<typename RBF>
void vtkplot::AdjustPoints(void* arguments)
{
  vtkProgrammableFilter* programmableFilter = 
    static_cast<vtkProgrammableFilter*>(arguments);
  arguments = programmableFilter + 1;
  
  auto u = static_cast< const interpolator<RBF>& > (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;

  //auto& vals = u.at();

  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);
}

template<typename RBF>
vtkplot::vtkplot(const interpolator<RBF>& u, 
                 bool offscreen_in)
  :hash(u.rbfs_hash), offscreen(offscreen)
{
  if(u.thebvp -> get_domain() -> get_dimension() != 2)
  {
    badArgument exc;
    exc.reason = "This class only works on interpolators whose domain lies in R^2";
    exc.line = __LINE__;
    exc.file = __FILE__;
    throw exc;
  }
  SetupPipeline(u, offscreen);
}

template<typename RBF>
void vtkplot::SetupPipeline(const interpolator<RBF>& u)
{

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

  for(auto i = u.thebvp -> get_domain() -> get_interior().begin();
      i != u.thebvp -> get_domain() -> get_interior().end(); i++)
  {
    double z = 0;
    vtkIdType idx = points -> InsertNextPoint( *i(1), *i(2), 0);
    scalars -> InsertTuple(idx, &z);
  }
  for(auto i = u.thebvp -> get_domain() -> get_boundary().begin();
      i != u.thebvp -> get_domain() -> get_boundary().end(); i++)
  {
    double z = 0;
    vtkIdType idx = points -> InsertNextPoint( *i(1), *i(2), 0);
    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();

  InitOffscreen();

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


  //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++)
    {
      using namespace std;
      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;
}

void vtkplot::InitOffscreen()
{
  // 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 );
}


} //namespace kwantix