1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: itkQuadEdgeMeshNormalFilter.h
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Insight Software 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.
=========================================================================*/
#ifndef __itkQuadEdgeMeshNormalFilter_h
#define __itkQuadEdgeMeshNormalFilter_h
#include <itkQuadEdgeMeshToQuadEdgeMeshFilter.h>
#include <itkQuadEdgeMeshPolygonCell.h>
#include "itkTriangleHelper.h"
namespace itk
{
/** \class QuadEdgeMeshNormalFilter
*
* \brief Filter which computes normals to faces and vertices and store it in
* the output mesh.
* Normals to face are first computed, then normals to vertices are computed
* as linear combination of neighbor face normals, i.e.
* $f[
* n_v = \frac{\sum_{i=0}^{#f} \omega_i \cdot n_i}{\| \sum_{k=0}^{#f} \omega_x \cdot n_k\|}
* $f]
*
* The difference between each method relies in the definition of the weight
* \f$ \omega_i \f$ that you can specify by the method SetWeight.
*
* GOURAUD \f$ \omega_i = 1\f$ [1]
* THURMER \f$ \omega_i = \text{Angle of the considered triangle at the given vertex \f$ [2]
* AREA \f$ \omega_i = \text{Area}(t_i)$ [3]
*
* These weights are defined in the literature:
* [1] Henri Gouraud.
* Continuous shading of curved surfaces.
* IEEE Transaction on Computers, 20(6):623-629, 1971
* [2] Shuangshuang Jin, Robert R. Lewis, and David West.
* A comparison of algorithms for vertex normal computation.
* The Visual Computer, 21(1-2):71–82, 2005.
* [3] Grit Thurmer and Charles A. Wuthrich.
* Computing vertex normals from polygonal facets.
* Journal of Graphic Tools, 3(1):43–46, 1998.
*
* \note By default the weight is set to the TURMER weight.
*
* \todo Fix run-time issues regarding the difference between the Traits of
* TInputMesh and the one of TOutputMesh. Right now, it only works if
* TInputMesh::MeshTraits == TOutputMesh::MeshTraits
* (and of course it requires that the output have some itk::Vector for point
* data and cell data.
*
*
*/
template< class TInputMesh, class TOutputMesh >
class QuadEdgeMeshNormalFilter :
public QuadEdgeMeshToQuadEdgeMeshFilter< TInputMesh, TOutputMesh >
{
public:
typedef QuadEdgeMeshNormalFilter Self;
typedef QuadEdgeMeshToQuadEdgeMeshFilter<
TInputMesh, TOutputMesh > Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
itkNewMacro ( Self );
itkTypeMacro ( QuadEdgeMeshNormalFilter,
QuadEdgeMeshToQuadEdgeMeshFilter );
typedef TInputMesh InputMeshType;
typedef typename InputMeshType::Pointer InputMeshPointer;
typedef typename InputMeshType::PointIdentifier InputPointIdentifier;
typedef typename InputMeshType::PointType InputPointType;
typedef typename InputMeshType::VectorType InputVectorType;
typedef typename InputMeshType::QEType InputQEType;
typedef TOutputMesh OutputMeshType;
typedef typename OutputMeshType::Pointer OutputMeshPointer;
typedef typename OutputMeshType::PointType OutputPointType;
typedef typename OutputPointType::VectorType OutputVectorType;
typedef typename OutputMeshType::QEType OutputQEType;
typedef typename OutputMeshType::PointIdentifier OutputPointIdentifier;
typedef typename OutputMeshType::PointIdIterator OutputPointIdIterator;
typedef typename OutputMeshType::PointsContainerPointer
OutputPointsContainerPointer;
typedef typename OutputMeshType::PointsContainerIterator
OutputPointsContainerIterator;
typedef typename OutputMeshType::CellType OutputCellType;
typedef typename OutputMeshType::CellIdentifier OutputCellIdentifier;
typedef typename OutputMeshType::CellAutoPointer OutputCellAutoPointer;
typedef typename OutputMeshType::CellsContainerConstIterator
OutputCellsContainerPointer;
typedef typename OutputMeshType::CellsContainerConstIterator
OutputCellsContainerConstIterator;
typedef TriangleHelper< OutputPointType > TriangleType;
typedef QuadEdgeMeshPolygonCell< OutputCellType > OutputPolygonType;
typedef typename OutputPolygonType::SelfAutoPointer OutputPolygonAutoPointer;
typedef typename OutputMeshType::CellDataContainer OutputCellDataContainer;
typedef typename OutputMeshType::PointDataContainer OutputPointDataContainer;
typedef typename OutputMeshType::MeshTraits OutputMeshTraits;
typedef typename OutputMeshTraits::PixelType OutputVertexNormalType;
typedef typename OutputVertexNormalType::ValueType OutputVertexNormalComponentType;
typedef typename OutputMeshTraits::CellPixelType OutputFaceNormalType;
typedef typename OutputFaceNormalType::ValueType OutputFaceNormalComponentType;
enum WeightType
{
GOURAUD = 0, // Uniform weights
THURMER, // Angle on a triangle at the given vertex
AREA
};
itkSetMacro ( Weight, WeightType );
itkGetConstMacro ( Weight, WeightType );
protected:
QuadEdgeMeshNormalFilter( );
~QuadEdgeMeshNormalFilter( );
WeightType m_Weight;
/** \brief Compute the normal to a face iPoly. It assumes that iPoly != 0
* and
* iPoly is a Triangle, i.e. 3 points only.
* \note The normal computation itself can be further improved by making
* possible to cast a CellType into a TriangleType.
*/
OutputFaceNormalType ComputeFaceNormal ( OutputPolygonType* iPoly );
/** \brief Compute the normal to all faces on the mesh.
* \note This method should be implemented in a multi-thread way in order
* to reduce the processing time.
*/
void ComputeAllFaceNormals( );
/** \brief Compute the normal to all vertices on the mesh.
* \note This method should be implemented in a multi-thread way in order
* to reduce the processing time.
*/
void ComputeAllVertexNormals( );
/** \brief Compute the normal to one vertex by a weighted sum of the faces
* normal in the 0-ring.
* \note The weight is chosen by the member m_Weight.
*/
OutputVertexNormalType ComputeVertexNormal (
const OutputPointIdentifier& iId );
/** \brief Definition of the weight in the 0-ring used for the vertex
* normal computation. By default m_Weight = THURMER;
*/
OutputVertexNormalComponentType Weight ( const OutputPointIdentifier& iPId,
const OutputCellIdentifier& iCId );
/** \note Calling Superclass::GenerateData( ) is the longest part in the
* filter! Something must be done in the class
* itkQuadEdgeMeshToQuadEdgeMeshFilter.
*/
void GenerateData( );
private:
QuadEdgeMeshNormalFilter ( const Self& );
void operator = ( const Self& );
};
}
#include "itkQuadEdgeMeshNormalFilter.txx"
#endif
|