[Insight-users] Mesh curvature / Node neighbours

Tobias Heimann t.heimann at dkfz-heidelberg.de
Fri Nov 11 07:40:35 EST 2005


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

-------------- next part --------------
#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
-------------- next part --------------
#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