[Insight-users] Contrib: TriangleCell with centroid and normal

Luis Ibanez luis.ibanez at kitware.com
Mon Jul 25 21:05:09 EDT 2005


Hi Gavin,

Have you had a chance to look at the SimplexMesh ?

It may be useful for what you are doing, the
Simplex Mesh is actually the dual of a triangular
Mesh and it keeps track of the normals on its
nodes, which are associated to the triangular
faces of a triangular Mesh.

If you still find your new Mesh to be more effective
then we will be happy to add it to the toolkit.

We will need a better (longer) name since we avoid
to use acronyms on the class names.


Please let us know,


   Thanks,


     Luis



------------------
Gavin Baker wrote:
> Hello all,
> 
> I needed to have the centroid and normal of the TriangleCells in a Mesh
> available for a metric.  To support this, and to avoid adding the extra
> baggage to the normal TriangleCell (where people might not want to pay for
> the extra storage) I've created a new class, imaginatively called
> TriangleCellNC.  (Suggestions for a better name welcome!)
> 
> All the TriangleCellNC class does is keep track of the extra two attributes,
> and allow them to be set and queried.  Then I've written a visitor (that
> gets attached to the mesh) and traverses all the faces, calculating the
> centroid and normal.  The normal calculation assumes the counter-clockwise
> winding rule (as in OpenGL) so the point indices need to be in CCW order for
> "outside" to be inferred correctly.
> 
> There's also a test program that creates a mesh, does the above
> calculations, then prints out the result.
> 
> I'd like to contribute this. All feedback welcome!
> 
>   :: Gavin
> 
> 
> 
> ------------------------------------------------------------------------
> 
> /*=========================================================================
> 
>   Program:   Insight Segmentation & Registration Toolkit
>   Module:    $RCSfile: $
>   Language:  C++
>   Date:      $Date: $
>   Version:   $Revision: $
> 
>   Copyright (c) 2005 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 __itkTriangleCellNC_h
> #define __itkTriangleCellNC_h
> 
> #include "itkTriangleCell.h"
> #include "itkCovariantVector.h"
> 
> namespace itk
> {
> 
> /** \class TriangleCellNC
>  * TriangleCell represents a triangle for a Mesh, with a centroid and normal.
>  *
>  * Template parameters for TriangleCell:
>  *
>  * TCellInterface =
>  *     The cell interface from the mesh
>  *
>  * This behaves identically to the TriangleCell, except extra storage is
>  * added to track the centroid and the normal.  The calculation of the
>  * centroid and normal are carried out by
>  * TriangleCellCentroidAndNormalVisitor, which needs to be applied to the
>  * mesh to update these attributes.
>  *
>  * \ingroup MeshObjects
>  *
>  * \author Gavin Baker, Complex Systems Group, The University of Melbourne
>  */
> 
> template < typename TCellInterface >
> class ITK_EXPORT TriangleCellNC: public TriangleCell<TCellInterface>
> {
> public:
>   itkTypeMacro(TriangleCellNC, TriangleCell);
> 
>   /** Standard cell class typedefs */
>   itkCellCommonTypedefs(TriangleCellNC);
>   itkCellInheritedTypedefs(TriangleCell<TCellInterface>);
> 
>   /** The triangle surface normal */
>   typedef CovariantVector<PixelType> CovariantType;
> 
>   TriangleCellNC() {}
> 
>   /* */
> 
>   void SetCentroid( const PointType& p )
>   {
>     m_Centroid = p;
>   }
> 
>   void GetCentroid( PointType* p ) const
>   {
>     *p = m_Centroid;
>   }
> 
>   void SetNormal( const CovariantType& n )
>   {
>     m_Normal = n;
>   }
>     
>   void GetNormal( CovariantType* n ) const
>   {
>     *n = m_Normal;
>   }
> 
> protected:
> 
>   /** The centroid of the cell, average position in each dimension */
>   PointType m_Centroid;
> 
>   /** The surface normal */
>   CovariantType m_Normal;
> 
> private:
>   TriangleCellNC(const Self&); //purposely not implemented
>   void operator=(const Self&); //purposely not implemented
> 
> };
> 
> 
> } // end namespace itk
> 
> #endif
> 
> 
> ------------------------------------------------------------------------
> 
> /*=========================================================================
> 
>   Program:   Insight Segmentation & Registration Toolkit
>   Module:    $RCSfile: $
>   Language:  C++
>   Date:      $Date: $
>   Version:   $Revision: $
> 
>   Copyright (c) 2005 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 __itkTriangleCellCentroidAndNormalVisitor_h
> #define __itkTriangleCellCentroidAndNormalVisitor_h
> 
> #include "itkTriangleCellNC.h"
> 
> #include <vnl/vnl_vector.h>
> #include <vnl/vnl_cross.h>
> 
> namespace itk
> {
> 
> /** \class TriangleCellCentroidAndNormalVisitor
>  * Visits a mesh, calculating the centroid and surface normal for each face.
>  *
>  * Specifically designed to work with the TriangleCellNC, since it has the
>  * added support for keeping track of its own centroid and normal.
>  *
>  * NB: Assumes the counter-clockwise (CCW) winding rule for determining the
>  * inside and outside of a face (the default in OpenGL).
>  *
>  * \ingroup MeshObjects
>  *
>  * \author Gavin Baker, Complex Systems Group, The University of Melbourne
>  */
> 
> template<typename TMeshType>
> class ITK_EXPORT TriangleCellCentroidAndNormalVisitor
> {
> public:
> 
>   typedef TMeshType                         MeshType;
>   typedef typename MeshType::CellType       CellType;
>   typedef typename MeshType::PointType      PointType;
>   typedef itk::TriangleCellNC<CellType>     TriType;
>   typedef typename TriType::CovariantType   CovariantType;
>   typedef vnl_vector<float>                 vectorf;
> 
>   /**
>    * The mesh must be supplied so we can retrieve the points.
>    */
>   void SetMesh( MeshType* mesh )
>   {
>     m_Mesh = mesh;
>   }
> 
>   /**
>    * Visit each TriangleCellNC, retrieve its points from the mesh, and
>    * calculate its centroid (by averaging in each dimension) and its normal
>    * (by taking the cross-product of vectors constructed according to the
>    * CCW winding rule).
>    */
>   void Visit( unsigned long cellid, TriType* tri )
>   {
>     if ( ! m_Mesh )
>       {
>       throw "a hissy fit";
>       }
> 
>     typename TriType::PointIdIterator pointId = tri->PointIdsBegin();
> 
>     // Centroid
> 
>     PointType p0;
>     PointType p1;
>     PointType p2;
> 
>     m_Mesh->GetPoint( *pointId++, &p0 );
>     m_Mesh->GetPoint( *pointId++, &p1 );
>     m_Mesh->GetPoint( *pointId++, &p2 );
> 
>     PointType centroid;
> 
>     centroid[0] = (p0[0]+p1[0]+p2[0])/3.0;
>     centroid[1] = (p0[1]+p1[1]+p2[1])/3.0;
>     centroid[2] = (p0[2]+p1[2]+p2[2])/3.0;
> 
>     tri->SetCentroid( centroid );
> 
>     // Face Normal
> 
>     vectorf v0 = p1.GetVnlVector() - p0.GetVnlVector();
>     vectorf v1 = p2.GetVnlVector() - p0.GetVnlVector();
> 
>     vectorf normal = vnl_cross_3d( v0, v1 );
> 
>     CovariantType cov_normal;
>     cov_normal.Set_vnl_vector( normal );
>     cov_normal.Normalize();
> 
>     tri->SetNormal( cov_normal );
>   }
> 
> protected:
> 
>   typename MeshType::Pointer m_Mesh;
> };
> 
> 
> } /* namespace itk */
> 
> #endif
> 
> 
> ------------------------------------------------------------------------
> 
> /*=========================================================================
> 
>   Program:   Insight Segmentation & Registration Toolkit
>   Module:    $RCSfile: $
>   Language:  C++
>   Date:      $Date: $
>   Version:   $Revision: $
> 
>   Copyright (c) 2005 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.
> 
> =========================================================================*/
> 
> #include "itkMesh.h"
> #include "itkTriangleCell.h"
> #include "itkTriangleCellCentroidAndNormalVisitor.h"
> 
> typedef float                             PixelType;
> typedef itk::Mesh< PixelType, 3 >         MeshType;
> 
> typedef MeshType::CellType                CellType;
> 
> typedef itk::TriangleCellNC< CellType >   TriangleType;
> 
> // Simple printing visitor
> 
> template <typename TMesh>
> class PrintingVisitor
>   {
>       typedef TMesh MeshType;
>       typedef typename TriangleType::PointType PointType;
>       typedef typename TriangleType::CovariantType CovariantType;
> 
>   public:
> 
>       void SetMesh( MeshType* mesh )
>           {
>               m_Mesh = mesh;
>           }
>       
>       void Visit(unsigned long cellId, TriangleType * tri )
>           {
>               std::cout << "Cell " << cellId << std::endl;
> 
>               PointType p;
>               tri->GetCentroid( &p );
>               std::cout << "    Centroid: " << p << std::endl;
> 
>               CovariantType n;
>               tri->GetNormal( &n );
>               std::cout << "    Normal: " << n << std::endl;
>           }
> 
>   protected:
> 
>       typename MeshType::Pointer m_Mesh;
> };
> 
> int main(int, char *[])
> {
>   MeshType::Pointer  mesh = MeshType::New();
> 
>   // Creating the points and inserting them in the mesh
>   //
>   MeshType::PointType   point0;
>   MeshType::PointType   point1;
>   MeshType::PointType   point2;
>   MeshType::PointType   point3;
> 
>   point0[0] = -1; point0[1] = -1; point0[2] = -1; 
>   point1[0] =  1; point1[1] =  1; point1[2] = -1; 
>   point2[0] =  1; point2[1] = -1; point2[2] =  1; 
>   point3[0] = -1; point3[1] =  1; point3[2] =  1; 
> 
>   mesh->SetPoint( 0, point0 );
>   mesh->SetPoint( 1, point1 );
>   mesh->SetPoint( 2, point2 );
>   mesh->SetPoint( 3, point3 );
> 
> 
>   // Creating and associating the Tetrahedron
>   //
>   CellType::CellAutoPointer cellpointer;
> 
>   // Creating and associating the Triangles
>   //
>   cellpointer.TakeOwnership( new TriangleType );
>   cellpointer->SetPointId( 0, 0 );
>   cellpointer->SetPointId( 1, 1 );
>   cellpointer->SetPointId( 2, 2 );
>   mesh->SetCell( 1, cellpointer );
> 
>   cellpointer.TakeOwnership( new TriangleType );
>   cellpointer->SetPointId( 0, 0 );
>   cellpointer->SetPointId( 1, 2 );
>   cellpointer->SetPointId( 2, 3 );
>   mesh->SetCell( 2, cellpointer );
> 
>   cellpointer.TakeOwnership( new TriangleType );
>   cellpointer->SetPointId( 0, 0 );
>   cellpointer->SetPointId( 1, 3 );
>   cellpointer->SetPointId( 2, 1 );
>   mesh->SetCell( 3, cellpointer );
> 
>   cellpointer.TakeOwnership( new TriangleType );
>   cellpointer->SetPointId( 0, 3 );
>   cellpointer->SetPointId( 1, 2 );
>   cellpointer->SetPointId( 2, 1 );
>   mesh->SetCell( 4, cellpointer );
> 
>   // Simple verification of the number of points and cells inserted
>   //
>   std::cout << "# Points= " << mesh->GetNumberOfPoints() << std::endl;
>   std::cout << "# Cell  = " << mesh->GetNumberOfCells() << std::endl;
> 
>   // Visitor - have one to calculate and the other to print
> 
>   typedef itk::TriangleCellCentroidAndNormalVisitor<MeshType> NCVisitorType;
> 
>   typedef PrintingVisitor<MeshType> PrintingVisitorType;
> 
>   typedef itk::CellInterfaceVisitorImplementation<
>       PixelType, MeshType::CellTraits, TriangleType,
>       NCVisitorType> NCTriangleVisitorType;
> 
>   typedef itk::CellInterfaceVisitorImplementation<
>       PixelType, MeshType::CellTraits, TriangleType,
>       PrintingVisitorType> PrintingTriangleVisitorType;
> 
>   NCTriangleVisitorType::Pointer triangleVisitor =
>       NCTriangleVisitorType::New();
> 
>   PrintingTriangleVisitorType::Pointer printingVisitor =
>       PrintingTriangleVisitorType::New();
> 
>   triangleVisitor->SetMesh( mesh ); 
>   printingVisitor->SetMesh( mesh ); 
> 
>   // Multi-Visitor
> 
>   typedef CellType::MultiVisitor CellMultiVisitorType;
>   CellMultiVisitorType::Pointer multiVisitor = CellMultiVisitorType::New();  
> 
>   // Process the mesh...
>   multiVisitor->AddVisitor( triangleVisitor );
>   mesh->Accept( multiVisitor );
> 
>   // Now print it (We can reuse the same multiVisitor because only one
>   // visitor for each topology is kept at a time.  It should probably use a
>   // hash map or something, so multiple visitors can actually be used.)
>   multiVisitor->AddVisitor( printingVisitor );
>   mesh->Accept( multiVisitor );
> 
>   return 0;
> }
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk.org
> http://www.itk.org/mailman/listinfo/insight-users



More information about the Insight-users mailing list