view src/vtkplot.cpp @ 43:8aea477c7cf8

Continue implementation of vtkplot class, only missing to move the tail of the pipeline to the Plot function.
author Jordi Gutiérrez Hermoso <jordigh@gmail.com>
date Mon, 15 Mar 2010 21:10:18 -0600 (2010-03-16)
parents 3f8311cbf602
children 4134a0f2423d
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> 

#include <boost/function.hpp>

namespace kwantix{

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 = 
      "Class vtkplot only works on interpolators whose " 
      "domain lies in R^2";
    exc.line = __LINE__;
    exc.file = __FILE__;
    throw exc;
  }
  
  SetupPipeline(u, offscreen);
}

void vtkplot::set_offscreen(bool offscreen_in)
{
  offscreen = offscreen_in;
  InitOffscreen();
}

template<typename RBF>
void vtkplot::update_values(const interp_values& vals_in)
{
  vals = vals_in;
  programmableFilter -> Modified();
}

void vtkplot::trampoline(void* this_ptr)
{
  vtkplot* instance = static_cast<vtkplot*>(this_ptr);
  instance -> AdjustPoints();
}

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

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

  //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
	ren1 =  vtkSmartPointer<vtkRenderer>::New();
	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);
 
	// add the actors to the scene
	ren1->SetBackground(0.0,0.0,0.0);
  ren1->GetActiveCamera()->SetViewUp(0,0,1);
  ren1->GetActiveCamera()->SetPosition(1, 1, 1);
  ren1->GetActiveCamera()->SetParallelProjection(1);
	ren1->AddActor(contActor);
  ren1->ResetCamera();
 
  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
  {

    // render an image (lights and cameras are created automatically)
    renWin->Render();
    //The style
    vtkSmartPointer<vtkInteractorStyleTerrain> terrain_style 
      = vtkSmartPointer<vtkInteractorStyleTerrain>::New();
 
    // Set the style
    iren -> SetInteractorStyle(terrain_style);
  
    // begin mouse interaction
    iren->Start(); 
  }
}

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

void vtkplot::AdjustPoints()
{
 
  if(vals.get_hash() != hash)
  {
    badArgument exc;
    exc.reason = 
      "Can't update vtkplot with data from a different " 
      "interpolation domain.";
    exc.line = __LINE__;
    exc.file = __FILE__;
    throw exc;
  }
  
  vtkPoints* inPts = programmableFilter->GetPolyDataInput()->GetPoints();
  vtkIdType numPts = inPts->GetNumberOfPoints();
  vtkSmartPointer<vtkPoints> newPts =
    vtkSmartPointer<vtkPoints>::New();
  newPts->SetNumberOfPoints(numPts);
 
  vtkSmartPointer<vtkDoubleArray> newScalars 
    = vtkSmartPointer<vtkDoubleArray>::New();

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

  programmableFilter->
    GetPolyDataOutput()->CopyStructure(programmableFilter->GetPolyDataInput());

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

} //namespace kwantix