- First version of a VTK vtkImageData to vtkPolyData filter: mesh an

iso-value in a 3D image.
This commit is contained in:
Laurent Rineau 2008-05-21 22:16:03 +00:00
parent 4ed2298896
commit 271df19d73
4 changed files with 321 additions and 0 deletions

1
.gitignore vendored
View File

@ -293,6 +293,7 @@ Surface_mesher/demo/Surface_mesher/.*.deps
Surface_mesher/demo/Surface_mesher/VTK/*.exe
Surface_mesher/demo/Surface_mesher/VTK/Makefile
Surface_mesher/demo/Surface_mesher/VTK/mesh_a_3D_image
Surface_mesher/demo/Surface_mesher/VTK/mesh_a_VTK_3D_image
Surface_mesher/demo/Surface_mesher/dump.ff
Surface_mesher/demo/Surface_mesher/implicit_surface_mesher
Surface_mesher/demo/Surface_mesher/my_makefile

View File

@ -45,6 +45,10 @@ SET (SRCS
mesh_a_3D_image.cpp
)
SET (SRCS_VTK
mesh_a_VTK_3D_image.cpp
)
# Use the include path and library for Qt that is used by VTK.
INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR}
${QT_QTCORE_INCLUDE_DIR})
@ -62,4 +66,22 @@ TARGET_LINK_LIBRARIES( mesh_a_3D_image
CGAL-ImageIO
)
SET (SRCS_VTK
mesh_a_VTK_3D_image.cpp
)
ADD_EXECUTABLE( mesh_a_VTK_3D_image MACOSX_BUNDLE ${SRCS_VTK})
TARGET_LINK_LIBRARIES( mesh_a_VTK_3D_image
QVTK
${QT_LIBRARIES}
vtkRendering
vtkGraphics
vtkIO
vtkCommon
CGAL
CGAL-ImageIO
)

View File

@ -0,0 +1,142 @@
/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: Medical1.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/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 notice for more information.
=========================================================================*/
//
// This example reads a volume dataset, extracts an isosurface that
// represents the skin and displays it.
//
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkVolume16Reader.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkPolyDataNormals.h"
#include <CGAL/vtkSurfaceMesherContourFilter.h>
int main (int argc, char **argv)
{
if (argc < 2)
{
cout << "Usage: " << argv[0] << " DATADIR/headsq/quarter" << endl;
return 1;
}
// Create the renderer, the render window, and the interactor. The renderer
// draws into the render window, the interactor enables mouse- and
// keyboard-based interaction with the data within the render window.
//
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
// The following reader is used to read a series of 2D slices (images)
// that compose the volume. The slice dimensions are set, and the
// pixel spacing. The data Endianness must also be specified. The reader
// usese the FilePrefix in combination with the slice number to construct
// filenames using the format FilePrefix.%d. (In this case the FilePrefix
// is the root name of the file: quarter.)
vtkVolume16Reader *v16 = vtkVolume16Reader::New();
v16->SetDataDimensions (64,64);
v16->SetImageRange (1,93);
v16->SetDataByteOrderToLittleEndian();
v16->SetFilePrefix (argv[1]);
v16->SetDataSpacing (3.2, 3.2, 1.5);
// An isosurface, or contour value of 500 is known to correspond to the
// skin of the patient. Once generated, a vtkPolyDataNormals filter is
// is used to create normals for smooth surface shading during rendering.
vtkCGALSurfaceMesherContourFilter *skinExtractor = vtkCGALSurfaceMesherContourFilter::New();
skinExtractor->SetInputConnection(v16->GetOutputPort());
skinExtractor->SetValue(500);
vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInputConnection(skinExtractor->GetOutputPort());
skinNormals->SetFeatureAngle(60.0);
vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInputConnection(skinNormals->GetOutputPort());
skinMapper->ScalarVisibilityOff();
vtkActor *skin = vtkActor::New();
skin->SetMapper(skinMapper);
// An outline provides context around the data.
//
vtkOutlineFilter *outlineData = vtkOutlineFilter::New();
outlineData->SetInputConnection(v16->GetOutputPort());
vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
mapOutline->SetInputConnection(outlineData->GetOutputPort());
vtkActor *outline = vtkActor::New();
outline->SetMapper(mapOutline);
outline->GetProperty()->SetColor(0,0,0);
// It is convenient to create an initial view of the data. The FocalPoint
// and Position form a vector direction. Later on (ResetCamera() method)
// this vector is used to position the camera to look at the data in
// this direction.
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp (0, 0, -1);
aCamera->SetPosition (0, 1, 0);
aCamera->SetFocalPoint (0, 0, 0);
aCamera->ComputeViewPlaneNormal();
// Actors are added to the renderer. An initial camera view is created.
// The Dolly() method moves the camera towards the FocalPoint,
// thereby enlarging the image.
aRenderer->AddActor(outline);
aRenderer->AddActor(skin);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera ();
aCamera->Dolly(1.5);
// Set a background color for the renderer and set the size of the
// render window (expressed in pixels).
aRenderer->SetBackground(1,1,1);
renWin->SetSize(640, 480);
// Note that when camera movement occurs (as it does in the Dolly()
// method), the clipping planes often need adjusting. Clipping planes
// consist of two planes: near and far along the view direction. The
// near plane clips out objects in front of the plane; the far plane
// clips out objects behind the plane. This way only what is drawn
// between the planes is actually rendered.
aRenderer->ResetCameraClippingRange ();
// Initialize the event loop and then start it.
iren->Initialize();
iren->Start();
// It is important to delete all objects created previously to prevent
// memory leaks. In this case, since the program is on its way to
// exiting, it is not so important. But in applications it is
// essential.
v16->Delete();
skinExtractor->Delete();
skinNormals->Delete();
skinMapper->Delete();
skin->Delete();
outlineData->Delete();
mapOutline->Delete();
outline->Delete();
aCamera->Delete();
iren->Delete();
renWin->Delete();
aRenderer->Delete();
return 0;
}

View File

@ -0,0 +1,156 @@
// Copyright (c) 2008 GeometryFactory, Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Laurent Rineau
#ifndef CGAL_VTK_SURFACE_MESHER_CONTOUR_FILTER_H
#define CGAL_VTK_SURFACE_MESHER_CONTOUR_FILTER_H
#include <vtkPolyDataAlgorithm.h>
class vtkCGALSurfaceMesherContourFilter : public vtkPolyDataAlgorithm
{
public:
static vtkCGALSurfaceMesherContourFilter *New();
vtkTypeMacro(vtkCGALSurfaceMesherContourFilter,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
// Methods to set contour values
vtkSetMacro(Value,double);
vtkGetMacro(Value,double);
protected:
vtkCGALSurfaceMesherContourFilter();
~vtkCGALSurfaceMesherContourFilter();
virtual int FillInputPortInformation(int port, vtkInformation *info);
virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
double Value;
private:
vtkCGALSurfaceMesherContourFilter(const vtkCGALSurfaceMesherContourFilter&); // Not implemented.
void operator=(const vtkCGALSurfaceMesherContourFilter&); // Not implemented.
};
// IMPLEMENTATION
#include "vtkCellArray.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#ifndef CGAL_USE_VTK
# define CGAL_USE_VTK
#endif
#include <CGAL/Image_3.h>
#include <CGAL/Surface_mesh_default_triangulation_3.h>
#include <CGAL/Surface_mesh_default_criteria_3.h>
#include <CGAL/Complex_2_in_triangulation_3.h>
#include <CGAL/IO/Complex_2_in_triangulation_3_file_writer.h>
#include <CGAL/IO/Complex_2_in_triangulation_3_to_vtk.h>
#include <CGAL/make_surface_mesh.h>
#include <CGAL/Gray_level_image_3.h>
#include <CGAL/Implicit_surface_3.h>
vtkStandardNewMacro(vtkCGALSurfaceMesherContourFilter);
vtkCGALSurfaceMesherContourFilter::vtkCGALSurfaceMesherContourFilter()
{
Value = 0.;
}
vtkCGALSurfaceMesherContourFilter::~vtkCGALSurfaceMesherContourFilter()
{
}
int
vtkCGALSurfaceMesherContourFilter::
FillInputPortInformation(int, vtkInformation *info)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
return 1;
}
void vtkCGALSurfaceMesherContourFilter::PrintSelf(ostream& os,
vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Value: " << this->Value << "\n";
}
int vtkCGALSurfaceMesherContourFilter::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
// get the input and ouptut
vtkImageData *inData = vtkImageData::SafeDownCast(
inInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkPolyData *output = vtkPolyData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
typedef CGAL::Surface_mesh_default_triangulation_3 Tr;
// c2t3
typedef CGAL::Complex_2_in_triangulation_3<Tr> C2t3;
typedef Tr::Geom_traits GT;
typedef CGAL::Gray_level_image_3<GT::FT, GT::Point_3> Gray_level_image;
typedef CGAL::Implicit_surface_3<GT, Gray_level_image> Surface_3;
Tr tr; // 3D-Delaunay triangulation
C2t3 c2t3 (tr); // 2D-complex in 3D-Delaunay triangulation
CGAL::Image_3 image;
if(!image.read_vtk_image_data(inData))
return 0;
Gray_level_image gray_level_image(image, Value);
GT::FT radius = std::max(image.xdim() * image.vx(),
std::max(image.ydim() * image.vy(),
image.zdim() * image.vz())
);
GT::Sphere_3 bounding_sphere(GT::Point_3(image.xdim() * image.vx()/2.,
image.ydim() * image.vy()/2.,
image.zdim() * image.vz()/2.),
radius*radius);
// definition of the surface, with 10^-2 as relative precision
Surface_3 surface(gray_level_image, bounding_sphere, 1e-5);
CGAL::Surface_mesh_default_criteria_3<Tr> criteria(30.,
radius/100.,
radius/500.);
// meshing surface, with the "manifold without boundary" algorithm
CGAL::make_surface_mesh(c2t3, surface, criteria, CGAL::Manifold_tag());
CGAL::output_c2t3_to_vtk_polydata(c2t3, output);
output->Squeeze();
return 1;
}
#endif // CGAL_VTK_SURFACE_MESHER_CONTOUR_FILTER_H