VTK/VTKMatlab

From KitwarePublic
< VTK
Revision as of 19:54, 6 July 2006 by Domel (talk | contribs)
Jump to navigationJump to search

It is possible (and highly desirable) to provide VTK bindings for Matlab. For that to happen one has to write a C++ file to be compiled with mex compiler right from under Matlab. Worked example:


/****************************************************
(C) 2005 Dominik Szczerba <domi at vision ee ethz ch>
*****************************************************/

#include <cstdlib>
#include <cmath>

/* MEX HEADERS */
#include <mex.h>

/* VTK HEADERS */
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkPolyData.h>

#include <vtkCell.h>
#include <vtkCellData.h>
#include <vtkDataSet.h>
#include <vtkDataSetAttributes.h>
#include <vtkProperty.h>

#include <vtkDataSetMapper.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>

/* MAIN FUNCTION */
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]){

  double *v;	// Vertices
  double *f;	// Faces
  
  unsigned int nV, nF, nC=0, i, j;

  if(nrhs<2)
	 mexErrMsgTxt("2+ input args required");

  double* dcolors = 0;
  vtkDoubleArray* dcolarr = 0;
  
  nV = mxGetM(prhs[0]);
  nF = mxGetM(prhs[1]);
  v = mxGetPr(prhs[0]);
  f = (double*)mxGetPr(prhs[1]);
  if(nrhs>=3){
	 //mexPrintf("found color information\n");
	 nC = mxGetM(prhs[2]);
	 if(nC!=nF)
		mexErrMsgTxt("dimension mismatch");
	 dcolors = mxGetPr(prhs[2]);
	 dcolarr = vtkDoubleArray::New();
	 dcolarr->SetName("aCellScalar");
	 dcolarr->SetArray(dcolors,nF,0);
  }
  mexPrintf("got %d nodes, %d faces and %d colors\n",nV,nF,nC);

  // Initialize vtk variables
  vtkPolyData *surf = vtkPolyData::New();
  vtkPoints *sverts = vtkPoints::New();
  vtkCellArray *sfaces = vtkCellArray::New();

//   for (i=0; i<nV; i++) mexPrintf("%d %f %f %f\n",i,v[i],v[nV+i],v[2*nV+i]);
//   for (i=0; i<nF; i++){
// 	 for(j=0;j<3;j++)
// 		mexPrintf("%d ",f[j*nF+i]);
//  	 mexPrintf("\n");
//   }

  // Load the point, cell, and data attributes.
  //indexes in VTK are 0-based, in Matlab 1-based
  const int offset = -1;
  for(i=0; i<nV; i++) sverts->InsertPoint(i,v[i],v[nV+i],v[2*nV+i]);
  for(i=0; i<nF; i++){
	 sfaces->InsertNextCell(3);
	 for(j=0;j<3;j++){
		int idx = (unsigned int)f[j*nF+i]+offset;
		if(idx<0 || idx>=nV)
		//mexPrintf("Warning : wrong index\n");
		  mexErrMsgTxt("wrong index");
		sfaces->InsertCellPoint(vtkIdType(idx));
	 }
  }
  
  // assign the pieces to the vtkPolyData.
  surf->SetPoints(sverts);
  surf->SetPolys(sfaces);
  sverts->Delete();
  sfaces->Delete();

  if(nC>0){
	 surf->GetCellData()->SetScalars(dcolarr);
  }

  // now render
  vtkDataSetMapper::SetResolveCoincidentTopologyToPolygonOffset();
  vtkPolyDataMapper *surfMapper = vtkPolyDataMapper::New();
  vtkActor *surfActor = vtkActor::New();
  vtkRenderer *aRenderer = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  
  surfMapper->SetInput(surf);
  //surfMapper->ScalarVisibilityOff();
  if(nC>0){
	 surfMapper->ScalarVisibilityOn();
	 surfMapper->SetScalarRange(0,1);  
  }

  surfActor->SetMapper(surfMapper);
  surfActor->GetProperty()->SetAmbient(0.1);
  surfActor->GetProperty()->SetDiffuse(0.3);
  surfActor->GetProperty()->SetSpecular(1.0);
  surfActor->GetProperty()->SetSpecularPower(30.0);
  
  aRenderer->AddActor(surfActor);
  aRenderer->SetBackground(0.2,0.2,0.2);
  //needed after camera moves
  //aRenderer->ResetCameraClippingRange ();
  
  iren->SetRenderWindow(renWin);
  
  renWin->AddRenderer(aRenderer);
  renWin->SetSize(500,500);
  renWin->Render();
  
  vtkInteractorStyleTrackballCamera *style = 
 	 vtkInteractorStyleTrackballCamera::New();
  iren->SetInteractorStyle(style);

  // Start interactive rendering
  iren->Start();

  // clean up
  surfMapper->Delete();
  surfActor->Delete();
  surf->Delete();
  aRenderer->Delete();
  renWin->Delete();
  iren->Delete();
  style->Delete();

}

Compile it under matlab with:


> mex -I<includesToVtkHeaders> fileToCompile.cpp -L<libDir> -lvtkLibStuff

Under linux this is normal compiling stuff, provide includes and linking directives, see GNU GCC documentation. Under Windows this is more trouble. First off, you need a C++ compiler - I used the well known MinGW (http://www.mingw.org/). I couldnt get the Matlab C compiler to work. I used gnumex (http://gnumex.sourceforge.net/). Install and follow documentation therein. I eventually had to change the mexopts to use g++ instead of gcc Refer to mex documentation for more information.

Problems


mex -ID:\MyProjects\VTK-5.0\include\vtk-5.0 vtkPolyDataRenderer.cpp D:\MyProjects\VTK-5.0\lib\libvtkRendering.a D:\MyProjects\VTK-5.0\lib\libvtkIO.a D:\MyProjects\VTK-5.0\lib\libvtkGraphics.a D:\MyProjects\VTK-5.0\lib\libvtkImaging.a D:\MyProjects\VTK-5.0\lib\libvtkftgl.a D:\MyProjects\VTK-5.0\lib\libvtkfreetype.a C:\mingw\lib\libopengl32.a D:\MyProjects\VTK-5.0\lib\libvtkFiltering.a D:\MyProjects\VTK-5.0\lib\libvtkCommon.a D:\MyProjects\VTK-5.0\lib\libvtksys.a D:\MyProjects\VTK-5.0\lib\libvtkDICOMParser.a D:\MyProjects\VTK-5.0\lib\libvtkpng.a D:\MyProjects\VTK-5.0\lib\libvtktiff.a D:\MyProjects\VTK-5.0\lib\libvtkzlib.a D:\MyProjects\VTK-5.0\lib\libvtkjpeg.a D:\MyProjects\VTK-5.0\lib\libvtkexpat.a C:\mingw\lib\libvfw32.a D:\MyProjects\VTK-5.0\lib\libvtkMPEG2Encode.a C:\mingw\lib\libgdi32.a



[x y z v] = flow;
q = z./x.*y.^3;
mesh=isosurface(x, y, z, q, -.08, v);
[N,M]=size(mesh.faces);
scalars=[0:1:N-1]'/(N-1);
vtkPolyDataRenderer(mesh.vertices,mesh.faces,scalars);