[Insight-users] Mesh curvature / Node neighbours

alexandre gouaillard - Sun Microsystems - Beijing China Alexandre.Gouaillard at Sun.COM
Sun Nov 13 21:28:13 EST 2005


hi tobias, and thanks for sharing.

the way I see it, you took the "array option", which means you stock the
adjency information in additional arrays in the structure, which is
somehow similar to what itk is doing with the simplexmesh and to what
vtk is doing. It's for sure an improvement of the existing structure in
ITK.

In this case, you still need to make a buildlink everytime you are
modifying the structure, correct ? In our point of view this is ok when
you have a "static mesh", i.e. a mesh whose connectivity (thus topology)
is not going to change. This is the case for most of the original mesh
deformation algorithms which only update the geometry. But if  you wanna
use something more elaborate, let's say a deformation algorithm that
would resample the surface if edge length goes below or above a
threshold, then you would need to call buildlink everytime you are
changing the connectivity. You don't really wanna do that as buildlink
in the "array option" can be twice a complete traversal of the entire
structure ... And if you don't call buildlink then you're working with a
structure which is not consistent with your mesh. The array option will
trigger a global update for every local modification. 

If you take a look at the incremental algorithms for mesh processing,
like decimation algorithms in VTK to cite those we are using almost all
the time, you will see that the vtk-guys saw the problem and somehow
implemented an on-the-fly local structure to be able to decimate without
calling buildlink everytime.

There are a lot of other issues that could be discussed too, but you
might want to e-mail me privately for those:
we are working with surface of solid object, how do you enforce
orintability and 2-manifoldness in your structure? Do youlet the end
user (algorithm coder) check that by himself? ...

Don't take me wrong, your class is a real improvement of the itkMesh
original class in the sense that one can (finally) address some
mesh/geometry processing directly in ITK and that is missing. But I'm
sure you dfinitly wanna have a look at our work. We also are in the
process of changing it from whatever to BSD. Hope you will all ike it.

On the road map is the porting of decimation, curvature, subdividing and
other usefull basic algorithms (either in their vtk form, or from more
recent work).

cheers,

alex, for the QE team.


On Fri, 2005-11-11 at 20:40, Tobias Heimann wrote:
> Hi Alex,
> 
> Here's the code for the IndexedTriangleMesh class, documentation is in 
> source. It's derived from the standard mesh class with additional 
> indexing information for neighbourhood relations between vertices, edges 
> and triangles. The reason why it's not submitted yet is that it is part 
> of a larger collection of classes for automatic correspondence finding, 
> and some of the other classes may be infringing existing patents (we are 
> currently resolving this issue). Anyway, if you've got a class that can 
> replace the entire itk::Mesh I could also derive from that and save the 
> code for the data that's already available in your class. Including 
> CGAL  datastructures in ITK is a great idea imho, the current mesh 
> structure is very cumbersome to work with for geometric problems.
> 
> Best wishes,
> Tobias
> 
> 
> alexandre gouaillard - Sun Microsystems - Beijing China wrote:
> 
> >Dear Tobias, 
> >
> >I would be interested in taking a look at your code and at any
> >documentation draft you may have.
> >
> >I must say that we are on the verge of submitting a data structure too
> >based on a Quad edge data structure:
> >- itk native implementation, can replace itkMesh in all existing
> >applications (tested)
> >- Quad Edge data stucture ( C-GAL )
> >   * local accesses to neighboorhoods in the kernel (node, edges, facse)
> >   * local modification of the structure (no buildlinks - incredible
> >speed up)
> >   * Native support for Primal/Dual approches (triangular <-> simplex
> >for free)
> >
> >that should be anytime soon.
> >
> >We are planning to integrate all the basic processing from vtk to avoid
> >itk => vtk => itk pipelines,
> >we are also planning to had more advance features to enable better mesh
> >processing curently lacking (IMHO) in itk (subdivision framework,
> >progressive mesh, ...)
> >
> >within this school year.
> >
> >alex, for the QE team @ Creatis
> >
> >On Thu, 2005-11-10 at 03:27, Tobias Heimann wrote:
> >  
> >
> >>Hi Dominique,
> >>
> >>The standard mesh support in ITK is pretty limited, there is no 
> >>functionality to compute curvatures or even to allow easy access to 
> >>neighboorhood information. I've written an extension of the itk::Mesh 
> >>class (which I'm going to submit to the Insight Journal, too) that 
> >>provides access to neighbouring vertices and faces in a more intuitive 
> >>way. If you are interested just send me a mail and I'll send you the code.
> >>
> >>Best wishes,
> >>Tobias
> >>
> >>
> >>Dominique Zosso wrote:
> >>
> >>    
> >>
> >>>Hi,
> >>>
> >>>Im currently working on 3D surface meshes, similar to the one generated by
> >>>itkRegularSphereMeshSource.
> >>>
> >>>To get the curvature in a node, does the itk framework contain any similar
> >>>method to the "vtkCurvature" proposed in VTK?
> >>>
> >>>And is there an ITK-method that provides access to all the neighbouring
> >>>nodes of a given vertex?
> >>>
> >>>Thank you in advance
> >>>---
> >>>Dominique Zosso
> >>>
> >>>_______________________________________________
> >>>Insight-users mailing list
> >>>Insight-users at itk.org
> >>>http://www.itk.org/mailman/listinfo/insight-users
> >>>
> >>> 
> >>>
> >>>      
> >>>
> >>-- 
> >>Dipl.-Inform. Med. Tobias Heimann
> >>Deutsches Krebsforschungszentrum         (German Cancer Research Center)
> >>Div. Medical and Biological Informatics B010      Tel: (+49) 6221-423548
> >>Im Neuenheimer Feld 280                           Fax: (+49) 6221-422345
> >>D-69120 Heidelberg                              email: T.Heimann at dkfz.de
> >>Germany                       http://www.dkfz.de/mbi/people/tobiash.html
> >>
> >>_______________________________________________
> >>Insight-users mailing list
> >>Insight-users at itk.org
> >>http://www.itk.org/mailman/listinfo/insight-users
> >>    
> >>
> >
> >
> >  
> >
> 
> -- 
> Dipl.-Inform. Med. Tobias Heimann
> Deutsches Krebsforschungszentrum         (German Cancer Research Center)
> Div. Medical and Biological Informatics B010      Tel: (+49) 6221-423548
> Im Neuenheimer Feld 280                           Fax: (+49) 6221-422345
> D-69120 Heidelberg                              email: T.Heimann at dkfz.de
> Germany                       http://www.dkfz.de/mbi/people/tobiash.html
> 
> 
> ______________________________________________________________________
> #ifndef _itkIndexedTriangleMesh_h
> #define _itkIndexedTriangleMesh_h
> 
> #include "vnl/vnl_vector_fixed.h"
> #include "itkMesh.h"
> #include <vector>
> 
> 
> namespace itk
> {
>   /** \class IndexedTriangleMesh
>   *   \brief The class represents a 3D, 2-manifold mesh consisting exclusively 
>   *          of triangle cells and allows advanced queries. 
>   *
>   * The IndexedTriangleMesh stores adjacency information for points, edges and 
>   * faces. The information is calculated in BuildCellLinks(). 
>   * The template parameter TIndex specifies the type of the link indices. 
>   * To save memory, this can be set to unsigned short for meshes with less than 
>   * 65.536 faces, edges and vertices.
>   *
>   * \author Tobias Heimann. Division Medical and Biological Informatics, 
>   *         German Cancer Research Center, Heidelberg, Germany.
>   */
>   template<
>     typename TPixelType, 
>     typename TIndex = unsigned int,
>     typename TCoordRepType = double
>   >
>   class IndexedTriangleMesh : public Mesh
>     <
>     TPixelType, 
>     3, 
>     DefaultStaticMeshTraits<TPixelType, 3, 2, TCoordRepType, 
>                             TCoordRepType, TPixelType>
>     >
>   {
> 
>   public:
> 
>     /** Standard typedefs. */
>     typedef IndexedTriangleMesh                           Self;
>     typedef Mesh<TPixelType, 3, DefaultStaticMeshTraits
>       <TPixelType, 3, 2, TCoordRepType, 
>        TCoordRepType, TPixelType> >                       Superclass;
>     typedef SmartPointer<Self>                            Pointer;
>     typedef SmartPointer<const Self>                      ConstPointer;
> 
>     /** Convenient typedefs. */
>     typedef TIndex                                        IndexType;
>     typedef TCoordRepType                                 CoordRepType;
>     typedef Superclass                                    MeshType;
>     typedef Vector<CoordRepType, 3>                       VectorType;
>     typedef typename MeshType::PointType                  PointType;
>     
>     /** Method for creation through the object factory. */
>     itkNewMacro(Self);
> 
>     /** Standard part of every itk Object. */
>     itkTypeMacro(IndexedTriangleMesh, Mesh);
> 
>     /** Returns a reference to a point of the mesh. */
>     PointType& GetPoint( IndexType pointId ) 
>     { 
>       return (*(this->m_PointsContainer))[pointId]; 
>     }
> 
>     /** Inherited from itk::Mesh class. */
>     bool GetPoint( typename Superclass::PointIdentifier pointId, PointType *point ) const
>     {
>       return Superclass::GetPoint( pointId, point );
>     }
> 
>     /** Returns the number of edges in the mesh. 
>      * Adjacent faces share an edge.
>      */
>     unsigned int GetNumberOfEdges() const 
>     { 
>       return m_NumberOfEdges; 
>     }
> 
>     /** Returns a vector along the specified edge from 
>      *  local point 0 to local point 1. 
>      */
>     VectorType GetEdge( IndexType edgeId ) const 
>     { 
>       return const_cast<Self*>(this)->GetPoint( GetPointIndexForEdge( edgeId, 1 ) ) - 
>              const_cast<Self*>(this)->GetPoint( GetPointIndexForEdge( edgeId, 0 ) ); 
>     }
> 
>     /** Returns the length of the specified edge . */
>     CoordRepType GetEdgeLength( IndexType edgeId ) const 
>     { 
>       return GetEdge( edgeId ).GetNorm(); 
>     }
>     
>     /** Returns the number of edges connected to the specified point. */
>     unsigned int GetNumberOfEdgesForPoint( IndexType pointId ) const 
>     { 
>       return m_EdgesPerVertex[pointId].size(); 
>     }
> 
>     /** Returns the index of an edge connected to the specified point.
>     * A value of 0 for localEdgeId will return the first connected edge,
>     * increasing values the other ones.
>     */
>     IndexType GetEdgeIndexForPoint( IndexType pointId, IndexType localEdgeId ) 
>       const 
>     { 
>       return m_EdgesPerVertex[pointId][localEdgeId]; 
>     }
> 
>     /** Returns the point indices that form the specified edge.
>     * Valid values for localVertexId are 0 and 1.
>     */
>     IndexType GetPointIndexForEdge( IndexType edgeId, IndexType localPointId )
>       const 
>     { 
>       return m_EdgePoints[edgeId].edgeVertex[localPointId]; 
>     }
> 
>     /** Returns the number of faces/triangles in the mesh. */
>     unsigned int GetNumberOfFaces() const 
>     { 
>       return m_NumberOfFaces; 
>     }
> 
>     /** Returns the number of faces adjacent to the specified point. */
>     unsigned int GetNumberOfFacesForPoint( IndexType pointId ) const
>     { 
>       return m_FaceLinks[pointId].size(); 
>     }
> 
>     /** Returns the index of a face adjacent to the specified point. 
>     * A value of 0 for localFaceId will return the first adjacent face,
>     * increasing values the other ones. 
>     */
>     IndexType GetFaceIndexForPoint( IndexType pointId, IndexType localFaceId ) 
>       const
>     {
>       return m_FaceLinks[pointId][localFaceId];
>     }
>     
>     /** Returns the point indices that form the specified face.
>     * Since all faces are triangles, valid values for localPointId are 0..2.
>     */
>     IndexType GetPointIndexForFace( IndexType faceId, IndexType localPointId ) 
>       const 
>     { 
>       return m_FaceVertices[faceId][localPointId]; 
>     }
> 
>     /** Returns the edge indices that form the specified face.
>     * Since all faces are triangles, valid values for localEdgeId are 0..2.
>     */
>     IndexType GetEdgeIndexForFace( IndexType faceId, IndexType localEdgeId ) 
>       const;
> 
>     /** Returns the number of faces adjacent to the specified face.
>     * Adjacent means that the two faces share a common vertex,
>     * but not necessarily a common edge.
>     */
>     IndexType GetNumberOfAdjacentFaces( IndexType faceId ) const
>     {
>       return m_AdjacentFaces[faceId].size();
>     }
> 
>     /** Returns the index of a face adjacent to the specified face. 
>     * A value of 0 for localFaceId will return the first adjacent face,
>     * increasing values the other ones. 
>     */
>     IndexType GetAdjacentFaceIndex( IndexType faceId, IndexType localFaceId ) 
>       const
>     {
>       return m_AdjacentFaces[faceId][localFaceId];
>     }
> 
>     /** Returns the index of the edge connecting the two specified points.
>     * If there is no edge connecting the points, the method returns -1.
>     */
>     long int GetConnectingEdgeIndex( IndexType pointId0, IndexType pointId1 ) 
>       const;
>     
>     /** Returns the index of a point that is forming a triangular face with the specified edge. 
>     * Valid values for localFaceId are 0 and 1.
>     * If the edge is adjacent to a hole in the mesh, i.e. there is only one adjacent face,
>     * a localFaceId of 1 will return -1.
>     */
>     long int GetMissingPointIndex( IndexType edgeId, IndexType localFaceId ) 
>       const 
>     { 
>       return m_EdgePoints[edgeId].missingVertex[localFaceId]; 
>     }
> 
>     /** Returns the index of the point on the other side of the specified edge.
>     * If the edge is not connected to the specified point, 
>     * the method returns -1.
>     */
>     long int GetConnectedPointIndex( IndexType pointId, IndexType edgeId ) 
>       const;
>     
>     /** Calculates and stores the indexing information for the mesh.
>     * This function has to be called after all topological changes.
>     */
>     void BuildCellLinks();
> 
>     /** Copies all pointers of itk::Mesh (shallow copy) and all indexing 
>     * information (deep copy). 
>     */
>     Pointer operator=( ConstPointer mesh );
> 
> 
>   protected:
> 
>     /** Standard constructor. */
>     IndexedTriangleMesh();
> 
>     /** Standard destructor. */
>     ~IndexedTriangleMesh();
> 
>     /** Prints information about the object. */
>     void PrintSelf( std::ostream& os, Indent indent ) const;
> 
>     /** Inserts a new edge between vertices v1 and v2 and returns the 
>     * new edgeId.
>     */
>     IndexType InsertEdge( IndexType v1, IndexType v2 );
> 
>     /** Builds the indices for neighbouring faces. */
>     void InitializeFaceLinks();
> 
> 
>     /** Helper class which holds edge information of the mesh. */
>     class E2VStruct
>     {
>     public:
>       /** Equality operator */
>       bool operator==( const E2VStruct& o ) const 
>       { 
>         return ( ( o.edgeVertex[0]==edgeVertex[0] && 
>                    o.edgeVertex[1]==edgeVertex[1]    ) || 
>                  ( o.edgeVertex[0]==edgeVertex[1] && 
>                    o.edgeVertex[1]==edgeVertex[0]    )    ); 
>       }
> 
>       /** Indices of the two points that form the edge */
>       IndexType	edgeVertex[2];	    
>       /** Indices of the two points that form triangles which the edge is 
>       * part of (or -1 if there is no triangle)
>       */
>       long int  missingVertex[2];   
>     };
> 
> 
>   private:
> 
>     typedef std::vector<IndexType> V2EStruct;
>     typedef std::vector<IndexType> IndexVector;
>     typedef vnl_vector_fixed<IndexType,3> IndexVector3;
> 
> 
>     /** Stores the number of edges in the mesh. */
>     int						            m_NumberOfEdges;
>     /** Stores the number of faces/triangles in the mesh. */
>     int                       m_NumberOfFaces;
>     /** Contains the point indices at and nearby each edge. */
>     std::vector<E2VStruct>    m_EdgePoints;		          
>     /** Contains a vector with edge indices for each point. */
>     std::vector<V2EStruct>    m_EdgesPerVertex;	    
>     /** Stores the three point indices for each face. */
>     std::vector<IndexVector3> m_FaceVertices;       
>     /** Stores all faces a specific point is part of. */
>     std::vector<IndexVector>  m_FaceLinks;      
>     /** Contains for each face a vector with indices of adjacent faces. */
>     std::vector<IndexVector>  m_AdjacentFaces;  
> 
>   };
> 
> }
> 
> #ifndef ITK_MANUAL_INSTANTIATION
> #include "itkIndexedTriangleMesh.txx"
> #endif
> 
> #endif
> 
> ______________________________________________________________________
> #ifndef _itkIndexedTriangleMesh_txx
> #define _itkIndexedTriangleMesh_txx
> 
> #include "itkIndexedTriangleMesh.h"
> #include <itkVertexCell.h>
> 
> 
> namespace itk
> {
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::IndexedTriangleMesh()
>   {
>     m_NumberOfEdges = 0;
>     m_NumberOfFaces = 0;
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::~IndexedTriangleMesh()
>   {
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   void
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::PrintSelf( std::ostream& os, Indent indent ) const
>   {
>     Superclass::PrintSelf(os, indent);
>     os << indent << "Number Of Edges: " << m_NumberOfEdges << std::endl;
>     os << indent << "Number Of Faces: " << m_NumberOfFaces << std::endl;
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   typename IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>::IndexType
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::GetEdgeIndexForFace( IndexType faceId, IndexType localEdgeId ) const 
>   {
>     switch( localEdgeId ) 
>     {
>       case 0: return (IndexType)(this->GetConnectingEdgeIndex( 
>                       m_FaceVertices[faceId][0], m_FaceVertices[faceId][1] ));
>       case 1: return (IndexType)(this->GetConnectingEdgeIndex( 
>                       m_FaceVertices[faceId][1], m_FaceVertices[faceId][2] ));
>       case 2: return (IndexType)(this->GetConnectingEdgeIndex( 
>                       m_FaceVertices[faceId][2], m_FaceVertices[faceId][0] ));
>     }
>     return 0;
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   long int
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::GetConnectingEdgeIndex( IndexType pointId0, IndexType pointId1 ) const 
>   {
>     for (unsigned int i=0; i<this->GetNumberOfEdgesForPoint( pointId0 ); i++) 
>     {
>       IndexType edgeId = this->GetEdgeIndexForPoint( pointId0, i );
>       if (this->GetConnectedPointIndex( pointId0, edgeId ) == pointId1) 
>       { 
>         return edgeId;
>       }
>     }
>     return -1;
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   long int
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::GetConnectedPointIndex( IndexType pointId, IndexType edgeId ) const
>   { 
>     if (m_EdgePoints[edgeId].edgeVertex[0]==pointId) 
>     {
>       return m_EdgePoints[edgeId].edgeVertex[1];
>     }
>     else if (m_EdgePoints[edgeId].edgeVertex[1]==pointId) 
>     {
>       return m_EdgePoints[edgeId].edgeVertex[0];
>     }
>     return -1;
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   void
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::BuildCellLinks()
>   {
>     Superclass::BuildCellLinks();
>     if (this->GetCells().IsNull()) return;
> 
>     itkDebugMacro( "Indexing mesh data..." );
>     typedef typename MeshType::CellsContainer::ConstIterator CellIterator;
>     typedef typename MeshType::CellType CellType;
>     typedef typename CellType::CellAutoPointer CellAutoPointer;
>     typedef VertexCell<CellType> VertexType;
> 
>     m_EdgesPerVertex.resize( this->GetNumberOfPoints() );
>     // extract basic mesh edge data:
>     m_NumberOfEdges = 0;
>     typename MeshType::CellIdentifier cId = 0;
>     CellIterator cellIterator = this->GetCells()->Begin();
>     CellIterator cellEnd      = this->GetCells()->End();
>     while( cellIterator != cellEnd ) 
>     {
>       CellType *cell = cellIterator.Value();
>       if (!cell) 
>       {
>         cId++;
>         cellIterator++;
>         continue;
>       }
>       if (cell->GetType() == CellType::LINE_CELL) 
>       {
>         int vertexId[2];
>         for (int v=0; v<2;v++) 
>         {
>           typename MeshType::CellIdentifier neighbourId;
>           bool found = GetBoundaryAssignment( 0, cId, v, &neighbourId );
>           if (!found) { itkExceptionMacro( "Missing boundary information!" ); }
>           CellAutoPointer neighbourCell;
>           GetCell( neighbourId, neighbourCell );
>           typename CellType::PointIdConstIterator pntId = 
>                                                   neighbourCell->GetPointIds();
>           vertexId[v] = (*pntId);
>         }
>         // init edge struct
>         E2VStruct edgeData;
>         edgeData.edgeVertex[0] = vertexId[0];	
>         edgeData.edgeVertex[1] = vertexId[1];
>         edgeData.missingVertex[0] = -1;			
>         edgeData.missingVertex[1] = -1;
>         // check if edge already in mesh
>         bool edgeNew = true;
>         for (int i=0; i<m_NumberOfEdges; i++) 
>         {
>           if (edgeData == m_EdgePoints[i]) 
>           {
>             edgeNew = false;
>             break;
>           }
>         }
>         if (edgeNew) 
>         {
>           m_EdgePoints.push_back( edgeData );
>           m_EdgesPerVertex[vertexId[0]].push_back( m_NumberOfEdges );
>           m_EdgesPerVertex[vertexId[1]].push_back( m_NumberOfEdges );
>           m_NumberOfEdges++;
>         }
>       }
>       cId++;
>       cellIterator++;
>     }
> 
>     // missing vertex data:
>     cellIterator = this->GetCells()->Begin();
>     cellEnd      = this->GetCells()->End();
>     m_NumberOfFaces = 0;
>     while( cellIterator != cellEnd ) 
>     {
>       CellType *cell = cellIterator.Value();
>       if (cell->GetType() == CellType::TRIANGLE_CELL) 
>       {
>         int vertexId[3];
>         typename CellType::PointIdConstIterator pntId = cell->GetPointIds();
>         for (int v=0; v<3; v++) 
>         {
>           vertexId[v] = *pntId;  
>           pntId++;
>         }
>         for (int ec=0; ec<3; ec++) 
>         {
>           int v1 = vertexId[ec];
>           int v2 = vertexId[(ec+1)%3];
>           int e = GetConnectingEdgeIndex( v1, v2 );
>           if (e<0) e = InsertEdge( v1, v2 );
>           int missingId = vertexId[(ec+2)%3];
>           int missing0 = this->GetMissingPointIndex( e, 0 );
>           if ( missing0 < 0) m_EdgePoints[e].missingVertex[0] = missingId;
>           else if (missingId != missing0) 
>           {
>             int missing1 = m_EdgePoints[e].missingVertex[1];
>             if (missing1 >= 0 && missing1 != missingId)             
>             {
>               itkExceptionMacro( "Mesh geometry is non-manifold!" );
>             }
>             m_EdgePoints[e].missingVertex[1] = missingId;
>           }
>         }
>         m_NumberOfFaces++;
>       }
>       cellIterator++;
>     }
>     itkDebugMacro( "Mesh contains " << this->GetNumberOfPoints() << 
>                    " vertices, " << m_NumberOfEdges << " edges, " << 
>                    m_NumberOfFaces << " faces." << std::endl );
> 
>     this->InitializeFaceLinks();
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   typename IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>::IndexType
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::InsertEdge( IndexType v1, IndexType v2 )
>   {
>     E2VStruct edgeData;
>     edgeData.edgeVertex[0] = v1;	
>     edgeData.edgeVertex[1] = v2;
>     edgeData.missingVertex[0] = -1;			
>     edgeData.missingVertex[1] = -1;
>     m_EdgePoints.push_back( edgeData );
>     m_EdgesPerVertex[v1].push_back( m_NumberOfEdges );
>     m_EdgesPerVertex[v2].push_back( m_NumberOfEdges );
>     m_NumberOfEdges++;
>     return (IndexType)(m_NumberOfEdges-1);
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   void
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::InitializeFaceLinks()
>   {
>     itkDebugMacro( "Computing normal vectors..." );
> 
>     typedef typename MeshType::CellsContainer::ConstIterator CellIterator;
>     typedef typename MeshType::CellType CellType;
> 
>     m_FaceLinks.resize( this->GetNumberOfPoints() );
>     m_FaceVertices.resize( m_NumberOfFaces );
>     
>     // init normals for all triangles:
>     CellIterator cellIterator = this->GetCells()->Begin();
>     CellIterator cellEnd      = this->GetCells()->End();
>     int faceId = 0;
>     while( cellIterator != cellEnd ) 
>     {
>       CellType *cell = cellIterator.Value();
>       if (cell->GetType() == CellType::TRIANGLE_CELL) 
>       {
>         int vertexId[3];
>         typename CellType::PointIdConstIterator pntId = cell->GetPointIds();
>         for (int v=0; v<3; v++) 
>         {
>           vertexId[v] = *pntId;  
>           m_FaceVertices[faceId][v] = *pntId;
>           m_FaceLinks[*pntId].push_back( faceId );
>           pntId++;
>         }
>         faceId++;
>       }
>       cellIterator++;
>     }
> 
>     m_AdjacentFaces.resize( m_NumberOfFaces );
>     for (int f=0; f<m_NumberOfFaces; f++) 
>     {
>       for (int v=0; v<3; v++) 
>       {
>         int vertexId = m_FaceVertices[f][v];
>         for (int i=0; i<m_FaceLinks[vertexId].size(); i++) 
>         {
>           int adjFaceId = m_FaceLinks[vertexId][i];
>           if (adjFaceId != f) m_AdjacentFaces[f].push_back( adjFaceId );
>         }
>       }
>     }
>     itkDebugMacro( " Done!" << std::endl );
>   }
> 
> 
>   template <typename TPixelType, typename TIndex, typename TCoordRepType>
>   typename IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>::Pointer
>   IndexedTriangleMesh<TPixelType, TIndex, TCoordRepType>
>   ::operator=( ConstPointer mesh )
>   {
>     // copy PointSet data
>     this->SetPoints( const_cast<typename Self::PointsContainer*>
>                      (mesh->GetPoints()) );
>     this->SetPointData( const_cast<typename Self::PointDataContainer*>
>                         (mesh->GetPointData()) );
>     // copy Mesh data
>     this->SetCells( mesh->GetCells() );
>     this->SetCellLinks( mesh->GetCellLinks() );
>     this->SetCellData( mesh->GetCellData() );
>     this->SetCellsAllocationMethod( mesh->GetCellsAllocationMethod() );
>     for( unsigned int dim=0; dim<MeshType::MaxTopologicalDimension; dim++ )
>     {
>       this->SetBoundaryAssignments( dim, mesh->GetBoundaryAssignments( dim ) );
>     }
>     // copy IndexedTriangleMesh data
>     m_NumberOfEdges = mesh->GetNumberOfEdges();
>     m_NumberOfFaces = mesh->GetNumberOfFaces();
>     // copy EdgesPerVertex
>     m_EdgesPerVertex.resize( mesh->GetNumberOfPoints() );
>     for (int i=0; i<m_EdgesPerVertex.size(); i++)
>     {
>       m_EdgesPerVertex[i].resize( mesh->GetNumberOfEdgesForPoint( i ) );
>       for (int j=0; j<m_EdgesPerVertex[i].size(); j++)
>       {
>         m_EdgesPerVertex[i][j] = mesh->GetEdgeIndexForPoint( i, j );
>       }
>     }
>     // copy EdgePoints
>     m_EdgePoints.resize( mesh->GetNumberOfEdges() );
>     for (int i=0; i<m_EdgePoints.size(); i++)
>     {
>       m_EdgePoints[i].edgeVertex[0] = mesh->GetPointIndexForEdge( i, 0 );
>       m_EdgePoints[i].edgeVertex[1] = mesh->GetPointIndexForEdge( i, 1 );
>       m_EdgePoints[i].missingVertex[0] = mesh->GetMissingPointIndex( i, 0 );
>       m_EdgePoints[i].missingVertex[1] = mesh->GetMissingPointIndex( i, 1 );
>     }
>     // copy FaceVertices
>     m_FaceVertices.resize( mesh->GetNumberOfFaces() );
>     for (int i=0; i<m_FaceVertices.size(); i++)
>     {
>       for (int j=0; j<3; j++) 
>       {
>         m_FaceVertices[i][j] = mesh->GetPointIndexForFace( i, j );
>       }
>     }
>     // copy FaceLinks
>     m_FaceLinks.resize( mesh->GetNumberOfPoints() );
>     for (int i=0; i<m_FaceLinks.size(); i++)
>     {
>       m_FaceLinks[i].resize( mesh->GetNumberOfFacesForPoint( i ) );
>       for (int j=0; j<m_FaceLinks[i].size(); j++)
>       {
>         m_FaceLinks[i][j] = mesh->GetFaceIndexForPoint( i, j );
>       }
>     }
>     // copy AdjacentFaces
>     m_AdjacentFaces.resize( mesh->GetNumberOfFaces() );
>     for (int i=0; i<m_AdjacentFaces.size(); i++)
>     {
>       m_AdjacentFaces[i].resize( mesh->GetNumberOfAdjacentFaces( i ) );
>       for (int j=0; j<m_AdjacentFaces[i].size(); j++)
>       {
>         m_AdjacentFaces[i][j] = mesh->GetAdjacentFaceIndex( i, j );
>       }
>     }
>     return this;
>   }
> 
> }
> 
> #endif



More information about the Insight-users mailing list