[Insight-users] Visualization of Mesh from DeformableMesh3DFilter with VTK

Luis Ibanez luis.ibanez@kitware.com
Fri, 27 Sep 2002 09:07:48 -0400


This is a multi-part message in MIME format.
--------------050805090907010007020500
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: quoted-printable


Hi Samuel,

Yes, it is possible to convert a "double" mesh into
a "float" mesh.

If fact, since you are using the example code provided
in vtk2itk.cxx, you will only have to make some
modifications in order to cast values to float.

Please find attached the modified file that will perform
conversions between a vtkUnstructuredGrid and an
itkMesh<double>.


The basic changes are:

1) All the type declarations related to the itk::Mesh
    are now using "double" instead of "float"

2) it is no longer possible to pass point coordinates
    using a (float *) between itk and vtk.
    Point coordinates are now copied one by one in
    order to allow the float/double casting to be done.

Please let us know if you find any problems running
the attached file, or adapting your code.

Thanks

    Luis


=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D

Samuel Rodr=EDguez Bescos wrote:

> Hello everybody,
>=20
> =20
>=20
> I'm tryin to visualize a Mesh resulted from a deformableMeshFilter. I'm=
=20
> using the vtk2itk.cxx code. The problem is that the output of my filter=
=20
> is a Double Mesh and I think that the  vtkUnstructuredGrid can't suppor=
t=20
> this type (only float).
>=20
> Could anybody give any information about that?.
>=20
>  Is it posible convert a doubleMesh  in a float Mesh in ITK?.
>=20
> the deformableMesh3DFilter is only for DoubleMesh types or is it posibl=
e=20
> to generate a floatMesh as output?
>=20
> =20
>=20
> Maybe there are so much questions, Sorry=20
>=20
> =20
>=20
> Thanks a lot in advance.
>=20
> =20
>=20
> Sam
>=20



--------------050805090907010007020500
Content-Type: text/plain;
 name="itkMeshToVTKUnstructuredGrid.cxx"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="itkMeshToVTKUnstructuredGrid.cxx"

/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: vtk2itk.cxx,v $
  Language:  C++
  Date:      $Date: 2002/06/20 02:35:19 $
  Version:   $Revision: 1.10 $

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
// Disable warning for long symbol names in this file only
#ifdef _MSC_VER
#pragma warning ( disable : 4786 )
#endif
#include <iostream>
#include "itkMesh.h"
#include "itkTriangleCell.h"
#include "itkQuadrilateralCell.h"
#include "vtkDataSetWriter.h"
#include "vtkDataSetMapper.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkActor.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkDataSetReader.h"
#include "vtkUnstructuredGrid.h"
#include "vtkDataSet.h"

typedef itk::Mesh<double, 3,
  itk::DefaultStaticMeshTraits< double, 3, 3, double, double > > doubleMesh;

void Display(vtkUnstructuredGrid* itkgrid, vtkUnstructuredGrid* vtkgrid)
{
// Create the renderer and window stuff
  vtkRenderer* ren1 = vtkRenderer::New();
  vtkRenderer* ren2 = vtkRenderer::New();
  vtkRenderWindow* renWin = vtkRenderWindow::New();
  renWin->AddRenderer(ren1);
  renWin->AddRenderer(ren2);
  vtkRenderWindowInteractor* inter = vtkRenderWindowInteractor::New();
  inter->SetRenderWindow(renWin);

  vtkDataSetMapper* mapper = vtkDataSetMapper::New();
  mapper->SetInput(itkgrid);
  vtkActor* actor = vtkActor::New();
  actor->SetMapper(mapper);
  vtkDataSetMapper* mapper2 = vtkDataSetMapper::New();
  mapper2->SetInput(vtkgrid);
  vtkActor* actor2 = vtkActor::New();
  actor2->SetMapper(mapper2);
  ren1->SetViewport(0.0, 0.0, 0.5, 1.0);
  ren2->SetViewport(0.5, 0.0, 1.0, 1.0);
  ren2->AddActor(actor2);
  // add the actor and start the render loop
  ren1->AddActor(actor);
  renWin->Render();
  inter->Start();
  
  mapper->Delete();
  actor->Delete();
  ren1->Delete();
  mapper2->Delete();
  actor2->Delete();
  ren2->Delete();
  renWin->Delete();
}

#ifndef VTK_HAS_ID_TYPE
// if you get a syntax error hear, then your VTK
// has vtkIdType already defined
typedef long vtkIdType;
#endif


doubleMesh::Pointer MeshFromUnstructuredGrid(vtkUnstructuredGrid* grid)
{
  // Create a new mesh
  doubleMesh::Pointer mesh(doubleMesh::New());
  // Get the points from vtk
  vtkPoints* vtkpoints = grid->GetPoints();
  int numPoints = vtkpoints->GetNumberOfPoints();
  // Create a compatible point container for the mesh
  // the mesh is created with a null points container
  doubleMesh::PointsContainer::Pointer points = 
    doubleMesh::PointsContainer::New();
  // Resize the point container to be able to fit the vtk points
  points->Reserve(numPoints);
  // Set the point container on the mesh
  mesh->SetPoints(points);
  for(int i =0; i < numPoints; i++)
    {
    float* apoint = vtkpoints->GetPoint(i);
    doubleMesh::PointType p;
    p[0] = apoint[0];
    p[1] = apoint[1];
    p[2] = apoint[2];
    mesh->SetPoint( i, p );
    }
  vtkCellArray* vtkcells = grid->GetCells();
  doubleMesh::CellsContainerPointer cells = doubleMesh::CellsContainer::New();
  mesh->SetCells(cells);
  // extract the cell id's from the vtkUnstructuredGrid
  int numcells = vtkcells->GetNumberOfCells();
  int* vtkCellTypes = new int[numcells];
  int cellId =0;
  for(; cellId < numcells; cellId++)
    {
    vtkCellTypes[cellId] = grid->GetCellType(cellId);
    }
  
  cells->Reserve(numcells);
  vtkIdType npts;
  vtkIdType* pts;
  cellId = 0;
  for(vtkcells->InitTraversal(); vtkcells->GetNextCell(npts, pts); cellId++)
    {
    doubleMesh::CellAutoPointer c;
    switch(vtkCellTypes[cellId])
      {
      case VTK_TRIANGLE:
        {
        typedef itk::CellInterface<double, doubleMesh::CellTraits> CellInterfaceType;
        typedef itk::TriangleCell<CellInterfaceType> TriangleCellType;
        TriangleCellType * t = new TriangleCellType;
        t->SetPointIds((unsigned long*)pts);
        c.TakeOwnership( t );
        break;
        }  
      case VTK_QUAD:
        {
        typedef itk::CellInterface<double, doubleMesh::CellTraits> CellInterfaceType;
        typedef itk::QuadrilateralCell<CellInterfaceType> QuadrilateralCellType;
        QuadrilateralCellType * t = new QuadrilateralCellType;
        t->SetPointIds((unsigned long*)pts);
        c.TakeOwnership( t );
        break;
        }  
      case VTK_EMPTY_CELL:
      case VTK_VERTEX:
      case VTK_POLY_VERTEX:
      case VTK_LINE:
      case VTK_POLY_LINE:
      case VTK_TRIANGLE_STRIP:
      case VTK_POLYGON:
      case VTK_PIXEL:
      case VTK_TETRA:
      case VTK_VOXEL:
      case VTK_HEXAHEDRON:
      case VTK_WEDGE:
      case VTK_PYRAMID:
      case VTK_PARAMETRIC_CURVE:
      case VTK_PARAMETRIC_SURFACE:
      default:
        std::cerr << "Warning unhandled cell type " 
                  << vtkCellTypes[cellId] << std::endl;
        ;
      }
    mesh->SetCell(cellId, c);
    }

  mesh->Print(std::cout);
  return mesh;
}




class VistVTKCellsClass
{
  vtkCellArray* m_Cells;
  int* m_LastCell;
  int* m_TypeArray;
public:
  // typedef the itk cells we are interested in
  typedef itk::CellInterface<
                      doubleMesh::PixelType, 
                      doubleMesh::CellTraits >  CellInterfaceType;

  typedef itk::TriangleCell<CellInterfaceType>      doubleTriangleCell;
  typedef itk::QuadrilateralCell<CellInterfaceType> doubleQuadrilateralCell;

  // Set the vtkCellArray that will be constructed
  void SetCellArray(vtkCellArray* a) 
    {
      m_Cells = a;
    }
  // Set the cell counter pointer
  void SetCellCounter(int* i)
    {
      m_LastCell = i;
    }
  // Set the type array for storing the vtk cell types
  void SetTypeArray(int* i)
    {
      m_TypeArray = i;
    }
  // Visit a triangle and create the VTK_TRIANGLE cell 
  void Visit(unsigned long cellId, doubleTriangleCell* t)
    {
      m_Cells->InsertNextCell(3,  (vtkIdType*)t->PointIdsBegin());
      m_TypeArray[*m_LastCell] = VTK_TRIANGLE;
      (*m_LastCell)++;
    }
  // Visit a triangle and create the VTK_QUAD cell 
  void Visit(unsigned long cellId, doubleQuadrilateralCell* t)
    {
      m_Cells->InsertNextCell(4,  (vtkIdType*)t->PointIdsBegin());
      m_TypeArray[*m_LastCell] = VTK_QUAD;
      (*m_LastCell)++;
    }
};
  
typedef itk::CellInterfaceVisitorImplementation<
double, doubleMesh::CellTraits,
  itk::TriangleCell< itk::CellInterface<doubleMesh::PixelType, doubleMesh::CellTraits > >, 
  VistVTKCellsClass> TriangleVisitor;


typedef itk::CellInterfaceVisitorImplementation<
double, doubleMesh::CellTraits,
  itk::QuadrilateralCell< itk::CellInterface<doubleMesh::PixelType, doubleMesh::CellTraits > >, 
  VistVTKCellsClass> QuadrilateralVisitor;


vtkUnstructuredGrid* MeshToUnstructuredGrid(doubleMesh* mesh)
{
  // Get the number of points in the mesh
  int numPoints = mesh->GetNumberOfPoints();
  if(numPoints == 0)
    {
    mesh->Print(std::cerr);
    std::cerr << "no points in Grid " << std::endl;
    exit(-1);
    }
  // Create a vtkUnstructuredGrid
  vtkUnstructuredGrid* vgrid = vtkUnstructuredGrid::New();

  // Create the vtkPoints object and set the number of points
  vtkPoints* vpoints = vtkPoints::New();
  vpoints->SetNumberOfPoints(numPoints);
  // iterate over all the points in the itk mesh filling in
  // the vtkPoints object as we go
  doubleMesh::PointsContainer::Pointer points = mesh->GetPoints();
  for(doubleMesh::PointsContainer::Iterator i = points->Begin();
      i != points->End(); ++i)
    {
    // Get the point index from the point container iterator
    int idx = i->Index();
    // Set the vtk point at the index with the the coord array from itk
    // itk returns a const pointer, but vtk is not const correct, so
    // we have to use a const cast to get rid of the const
    doubleMesh::PointType & pp = i->Value();
    float pcoordinates[3]; 
    pcoordinates[0] = pp[0];
    pcoordinates[1] = pp[1];
    pcoordinates[2] = pp[2];
    vpoints->SetPoint(idx, pcoordinates);
    }
  // Set the points on the vtk grid
  vgrid->SetPoints(vpoints);
  
  // Now create the cells using the MulitVisitor
  // 1. Create a MultiVisitor
  doubleMesh::CellType::MultiVisitor::Pointer mv =
    doubleMesh::CellType::MultiVisitor::New();
  // 2. Create a triangle and quadrilateral visitor
  TriangleVisitor::Pointer tv = TriangleVisitor::New();
  QuadrilateralVisitor::Pointer qv =  QuadrilateralVisitor::New();
  // 3. Set up the visitors
  int vtkCellCount = 0; // running counter for current cell being inserted into vtk
  int numCells = mesh->GetNumberOfCells();
  int *types = new int[numCells]; // type array for vtk 
  // create vtk cells and estimate the size
  vtkCellArray* cells = vtkCellArray::New();
  cells->EstimateSize(numCells, 4);
  // Set the TypeArray CellCount and CellArray for both visitors
  tv->SetTypeArray(types);
  tv->SetCellCounter(&vtkCellCount);
  tv->SetCellArray(cells);
  qv->SetTypeArray(types);
  qv->SetCellCounter(&vtkCellCount);
  qv->SetCellArray(cells);
  // add the visitors to the multivisitor
  mv->AddVisitor(tv);
  mv->AddVisitor(qv);
  // Now ask the mesh to accept the multivisitor which
  // will Call Visit for each cell in the mesh that matches the
  // cell types of the visitors added to the MultiVisitor
  mesh->Accept(mv);
  
  // Now set the cells on the vtk grid with the type array and cell array
  vgrid->SetCells(types, cells);
  
  // Clean up vtk objects (no vtkSmartPointer ... )
  cells->Delete();
  vpoints->Delete();
  // return the vtkUnstructuredGrid
  return vgrid;
}


int main(int ac, char** av)
{
  const char* fname = "blow.vtk";
  if(ac > 1 )
    {
    fname = av[1];
    }
  
  
  vtkDataSetReader* reader = vtkDataSetReader::New();
  reader->SetFileName(fname);
  reader->SetScalarsName("thickness9");
  reader->SetVectorsName("displacement9");
  std::cerr << "Begin reading vtk data " << std::endl;
  reader->Update();
  std::cerr << "End reading vtk data " << std::endl;
  vtkDataSet* data = reader->GetOutput();
  if( !data )
    {
    std::cerr << "Data is null" << std::endl;
    }
  // Convert from vtk to itk
  std::cerr << "Begin conversion to itkMesh " << std::endl;
  doubleMesh::Pointer m = 
    MeshFromUnstructuredGrid(reader->GetUnstructuredGridOutput());
  std::cerr << "End conversion to itkMesh " << std::endl;
  // Convert back from itk to vtk
  std::cerr << "Begin conversion to vtkUnstructuredGrid " << std::endl;
  vtkUnstructuredGrid* grid = MeshToUnstructuredGrid(m);
  std::cerr << "End conversion to vtkUnstructuredGrid " << std::endl;
  
  std::cerr << "Begin vtk dispaly of both grids " << std::endl;
  Display(grid, reader->GetUnstructuredGridOutput());
  vtkDataSetWriter* writer = vtkDataSetWriter::New();
  writer->SetInput(grid);
  writer->SetFileName("./itkblow.vtk");
  writer->Update();
#ifdef VTK_USE_ANSI_STDLIB  
  grid->Print(std::cout);
#endif
  reader->Delete();
  grid->Delete();
  return 0;
}


--------------050805090907010007020500--