]> Creatis software - cpMesh.git/blobdiff - lib/cpm/DataStructures/QuadEdge.h
QuadEdgeMesh ported to cpPlugins/Extensions
[cpMesh.git] / lib / cpm / DataStructures / QuadEdge.h
diff --git a/lib/cpm/DataStructures/QuadEdge.h b/lib/cpm/DataStructures/QuadEdge.h
deleted file mode 100644 (file)
index f383d5e..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-#ifndef __CPM__DATASTRUCTURES__QUADEDGE__H__
-#define __CPM__DATASTRUCTURES__QUADEDGE__H__
-
-#include <itkLightObject.h>
-#include <cpm/DataStructures/QuadEdgeIterators.h>
-
-namespace cpm
-{
-  namespace DataStructures
-  {
-    /**
-     */
-    template< typename P, typename D, bool IsPrimal = true >
-    class QuadEdge
-      : public itk::LightObject
-    {
-    public:
-      typedef QuadEdge                        Self;
-      typedef itk::LightObject                Superclass;
-      typedef itk::SmartPointer< Self >       Pointer;
-      typedef itk::SmartPointer< const Self > ConstPointer;
-
-      /// Vertices and faces types
-      typedef P TPrimalGeometry;
-      typedef D TDualGeometry;
-
-      /**
-       * Dual type, basically the same type with swapped template
-       * parameters.
-       */
-      typedef QuadEdge< D, P, !IsPrimal > TDual;
-      typedef Self                        TPrimal;
-      typedef typename TDual::Pointer     PtrDual;
-      friend TDual;
-
-      /// Iterators
-      typedef QuadEdgeIterator< TPrimal >           Iterator;
-      typedef QuadEdgeConstIterator< TPrimal >      ConstIterator;
-      typedef QuadEdgePointIterator< TPrimal >      PointIterator;
-      typedef QuadEdgePointConstIterator< TPrimal > PointConstIterator;
-
-    public:
-      itkNewMacro( Self );
-      itkTypeMacro( QuadEdge, itkLightObject );
-
-      cpmDataStructuresQEAllIteratorsMacro( Onext );
-      cpmDataStructuresQEAllIteratorsMacro( Lnext );
-      cpmDataStructuresQEAllIteratorsMacro( Rnext );
-      cpmDataStructuresQEAllIteratorsMacro( Dnext );
-      cpmDataStructuresQEAllIteratorsMacro( Oprev );
-      cpmDataStructuresQEAllIteratorsMacro( Lprev );
-      cpmDataStructuresQEAllIteratorsMacro( Rprev );
-      cpmDataStructuresQEAllIteratorsMacro( Dprev );
-
-    public:
-      void CreateRings( );
-
-      /// First order access methods
-      inline TPrimal* GetOnext( )
-        { return( this->m_Onext ); }
-      inline TDual* GetRot( )
-        { return( this->m_Rot ); }
-      inline const TPrimal* GetOnext( ) const
-        { return( this->m_Onext ); }
-      inline const TDual* GetRot( ) const
-        { return( this->m_Rot ); }
-
-      /// First order configuration methods
-      inline void SetOnext( TPrimal* e )
-        { this->m_Onext = e; }
-      inline void SetRot( TDual* e )
-        { this->m_Rot = e; }
-
-      /// Second order accessors: around base rings
-      inline TPrimal* GetSym( )
-        { return( this->m_Rot->m_Rot ); }
-      inline TDual* GetInvRot( )
-        { return( this->m_Rot->m_Rot->m_Rot ); }
-
-      /// Second order accessors: neighboring topology
-      inline TPrimal* GetLnext( )
-        { return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot ); }
-      inline TPrimal* GetRnext( )
-        { return( this->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); }
-      inline TPrimal* GetDnext( )
-        { return( this->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot ); }
-      inline TPrimal* GetOprev( )
-        { return( this->m_Rot->m_Onext->m_Rot ); }
-      inline TPrimal* GetLprev( )
-        { return( this->m_Onext->m_Rot->m_Rot ); }
-      inline TPrimal* GetRprev( )
-        { return( this->m_Rot->m_Rot->m_Onext ); }
-      inline TPrimal* GetDprev( )
-        { return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); }
-
-      /// Second order accessors: around base rings (const versions)
-      inline const TPrimal* GetSym( ) const
-        { return( this->m_Rot->m_Rot ); }
-      inline const TDual* GetInvRot( ) const
-        { return( this->m_Rot->m_Rot->m_Rot ); }
-
-      /// Second order accessors: neighboring topology (const versions)
-      inline const TPrimal* GetLnext( ) const
-        { return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot ); }
-      inline const TPrimal* GetRnext( ) const
-        { return( this->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); }
-      inline const TPrimal* GetDnext( ) const
-        { return( this->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot ); }
-      inline const TPrimal* GetOprev( ) const
-        { return( this->m_Rot->m_Onext->m_Rot ); }
-      inline const TPrimal* GetLprev( ) const
-        { return( this->m_Onext->m_Rot->m_Rot ); }
-      inline const TPrimal* GetRprev( ) const
-        { return( this->m_Rot->m_Rot->m_Onext ); }
-      inline const TPrimal* GetDprev( ) const
-        { return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); }
-
-      /// Get geometry methods
-      inline P& GetOrigin( )
-        { return ( this->m_Origin ); }
-      inline P& GetDestination( )
-        { return ( this->m_Rot->m_Rot->m_Origin ); }
-      inline D& GetRight( )
-        { return ( this->m_Rot->m_Origin ); }
-      inline D& GetLeft( )
-        { return ( this->m_Rot->m_Rot->m_Rot->m_Origin ); }
-
-      /// Get geometry methods (const versions)
-      inline const P& GetOrigin( ) const
-        { return ( this->m_Origin ); }
-      inline const P& GetDestination( ) const
-        { return ( this->m_Rot->m_Rot->m_Origin ); }
-      inline const D& GetRight( ) const
-        { return ( this->m_Rot->m_Origin ); }
-      inline const D& GetLeft( ) const
-        { return ( this->m_Rot->m_Rot->m_Rot->m_Origin ); }
-
-      /// Set geometry methods
-      inline void SetOrigin( const P& v )
-        { this->m_Origin = v; }
-      inline void SetDestination( const P& v )
-        { this->m_Rot->m_Rot->m_Origin = v; }
-      inline void SetRight( const D& v )
-        { this->m_Rot->m_Origin = v; }
-      inline void SetLeft( const D& v )
-        { this->m_Rot->m_Rot->m_Rot->m_Origin = v; }
-      inline void UnsetOrigin( )
-        { this->m_Origin = TPrimal::NoGeometry; }
-      inline void UnsetDestination( )
-        { this->m_Rot->m_Rot->m_Origin = TPrimal::NoGeometry; }
-      inline void UnsetRight( )
-        { this->m_Rot->m_Origin = TDual::NoGeometry; }
-      inline void UnsetLeft( )
-        { this->m_Rot->m_Rot->m_Rot->m_Origin = TDual::NoGeometry; }
-
-      /**
-       * Set the Left( ) of all the edges in the Lnext( ) ring of "this"
-       * with the same given geometrical information.
-       * @param  faceGeom Looks at most maxSize edges in the Lnext( ) ring.
-       * @return Returns true on success. False otherwise.
-       */
-      void SetLnextRingGeometry( const D& v );
-      void UnsetLnextRingGeometry( );
-
-      /// Topological queries
-      inline bool IsIsolated( ) const
-        { return( this == this->m_Onext ); }
-      bool IsEdgeInOnextRing( const TPrimal* e ) const;
-      bool IsEdgeInLnextRing( const TPrimal* e ) const;
-      unsigned int GetOnextRingSize( ) const;
-      unsigned int GetLnextRingSize( ) const;
-
-      /**
-       * @return Returns true when "this" has no faces set on both sides.
-       *         Return false otherwise.
-       */
-      inline bool IsWire( )
-        { return( !( this->IsLeftSet( ) ) && !( this->IsRightSet( ) ) ); }
-
-      /**
-       * @return Returns true when "this" is on the boundary i.e.
-       *         one and only one of the faces is set. Return false
-       *         otherwise.
-       */
-      inline bool IsAtBorder( ) const;
-
-      /**
-       * @return Returns true when "this" has faces set on both sides.
-       *         Return false otherwise.
-       */
-      inline bool IsInternal( ) const
-        { return ( this->IsLeftSet( ) && this->IsRightSet( ) ); }
-
-      /// Geometrical queries
-      inline bool IsOriginSet( ) const
-        { return ( this->m_Origin != Self::NoGeometry ); }
-      inline bool IsDestinationSet( ) const
-        { return ( this->m_Rot->m_Rot->IsOriginSet( ) ); }
-      inline bool IsRightSet( ) const
-        { return ( this->m_Rot->IsOriginSet( ) ); }
-      inline bool IsLeftSet( ) const
-        { return ( this->m_Rot->m_Rot->m_Rot->IsOriginSet( ) ); }
-
-      /**
-       * \brief Check wether edge's Origin is internal to the mesh (as
-       * opposed to being on the boundary) by looking if all the edges
-       * in the Onext() ring have a face set on both their Left() and
-       * Right() side.
-       */
-      bool IsOriginInternal( ) const;
-
-      /**
-       * Definition: an edge is said to be a boundary edge when it is
-       * adjacent to i.e. when at least one of the faces edge->GetLeft() or
-       * edge->GetRight() is unset.  Definition: an point is said to be a
-       * boundary point when at least one of the edges of it's Onext() ring
-       * is a boundary edge.
-       *
-       * Assume "this" edge belongs to a triangulation (i.e. it belongs to a
-       * QEMesh which represents a 2-manifold) which possesses a boundary.
-       * Assume "this" edge instance is a boundary edge. Let us denote by P
-       * the point which is the origin of "this" edge i.e. P is
-       * this->Origin().  By definition P is a boundary point.  Then AT
-       * LEAST two [see the note below] edges of the Onext() ring of P
-       * [which all have the point P as Origin()] are themselves boundary
-       * edges. And among those boundary edges AT LEAST one has it's Left()
-       * face unset.  By iterating over the Onext() ring (which defines a
-       * local ordering on edges) this method searches for the first edge
-       * whose Left() face is unset AND which is encountered AFTER edgeTest.
-       *
-       * @param edgeTest When present, this edge will be considered as
-       *        the entry edge in the Onext() ring. When absent it shall
-       *        be defaulted to "this" edge. (see the warning below).
-       * @return When "this" edge is a boundary edge, return the first
-       *         edge in "this" Onext() ring whose Left() face is unset
-       *         AND located after edgeTest.
-       *         When "this" edge is NOT a boundary edge the 0 is
-       *         returned.
-       * @warning When the Mesh possessing "this" edge is a 2-manifold
-       *          then result of this method is unique in the sense that
-       *          it is independent from the edgeTest parameter.
-       *          But when the Mesh is not 2-manifold (this state can
-       *          happen at intermediary stages of the building process,
-       *          or during "surgical" operations on the Mesh, and
-       *          even though the Mesh represents a triangulation)
-       *          the result of this method is not unique in the sense
-       *          that the result depends on the edgeTest parameter.
-       *          Let us illusatre this dependence by considering a
-       *          Mesh (which is a triangulation) which is not a 2-manifold.
-       *          Assume the point P (the origin of "this" edge i.e.
-       *          P = this->Originv()) is TWICE on the border i.e. it
-       *          is adjacent twice to noface. We can consider the situation
-       *          of the following diagram, which depicts some Onext()
-       *          ring around point P:
-       *
-       *                       \         /                               //
-       *                        \   *   /                                //
-       *                        i3     b2              counter-clockwise //
-       *                  *       \   /   NO FACE      Onext() order.    //
-       *                           \ /                                   //
-       *                 ----b4-----P----b1------                        //
-       *                           /|\                                   //
-       *               NO FACE    / | \                                  //
-       *                         /  |  \    *  <------ a * indicates the //
-       *                        /   |   \         the presence of a face //
-       *                       /    |    \                               //
-       *                     b5    i6     i7                             //
-       *                     /   *  |  *   \                             //
-       *                    /       |       \                            //
-       *
-       *          On this example, and if we assume the Onext() oder is
-       *          represented counter-clockwise, the edges are ordered as
-       *          follows:
-       *             b1, b2, i3, b4, b5, i6, i7
-       *          (when arbitrarily starting at edge b1).
-       *          We have four Boundary edges labeled b1, b2, b4, b5 and
-       *          we have three internal edges (i.e. non boundary edges)
-       *          labeled i3, i6 and i7.
-       *          Depending on edgeTest, the result of this method
-       *          will NOT return the same edge:
-       *            - when edgeTest == b5 (or i6 or i7 or b1) then the edge
-       *              b1 will be returned,
-       *            - when edgeTest == b2 (or i3 or b4) then the edge
-       *              b4 will be returned,
-       *          Eventually, when edgeTest is absent, the result shall
-       *          depend on the position of "this" in the Onext() ring().
-       *
-       */
-      TPrimal* GetNextBorderEdgeWithUnsetLeft( TPrimal* edge = NULL ) const;
-
-      /**
-       * Assume "this->Originv()" is a boundary point P that is thrice adjacent
-       * to noface and consider the given situation is the one depicted by
-       * the following diagram where:
-       *   - P is "this->Originv()" instance,
-       *   - the * (star) indicates the presence of a face,
-       *   - b1, b2, b3, b4, b5, b6 denote boundary edges,
-       *   - p denotes some generic point,
-       *   - A and B denote some specific points we want to discuss,
-       *   - the Onext() ring order is represented counter-clockwise
-       *     [which is coherent with the definition of edge->GetRigth()]
-       *     i.e. the ordering of the edges is:
-       *          b1, b2, b3, b4, b5, b6, b1...
-       *
-       *                    p       N       p
-       *                   / \      O      / \                            //
-       *                  /   \           /   \                           //
-       *                 /     \    F    /     \       counter-clockwise  //
-       *                /      b3   A   b2      \      Onext() ring order //
-       *               /         \  C  /         \                        //
-       *              /     *     \ E /     *     \                       //
-       *             /             \ /             \                      //
-       *             A------b4------P------b1-------B                     //
-       *                           / \                                    //
-       *                          /   \                                   //
-       *             NO FACE     /     \      NO FACE                     //
-       *                        /       \                                 //
-       *                      b5         b6                               //
-       *                      /     *     \                               //
-       *                     /             \                              //
-       *                    p---------------p                             //
-       *
-       * At P this Mesh doesn't represent a 2-manifold (since we are thrice
-       * on the boundary). Nevertheless such a situation could arise in
-       * intermediary stages (e.g. when building the Mesh, or during
-       * surgical changes on the Mesh).
-       *    Now, assume we are asked to build the triangle [P, A, B]. Note
-       * that this request is not absurd since the current situation at
-       * P isn't the one of a 2-manifold: hence when building the current
-       * Onext() ring of P, we had not enough information to decide
-       * wheter b4.Onext() should be b5 or b1. It is ONLY when we are
-       * required to build the triangle [P, A, B] that we have the
-       * additional information that b4.Onext() is indeed b1.
-       *    When we are required to build triangle [P, A, B], we hence
-       * need to change the Onext() ring order at P, i.e. we need to deal
-       * with the triangle [P, b5, b6] which currently prevents
-       * b4.Onext() to be b1. In other terms, when considering the
-       * additional information that b4.Onext() is b1, and before
-       * building the triangle [P, A, B], we need to reorder
-       * the Onext() ring of P from it's current state
-       *    b1, b2, b3, b4, b5, b6, b1...
-       * to an order coherent with the [P, A, B] request, i.e.
-       *     b1, b2, b5, b6, b3, b4, b1...
-       *
-       * In order to establish the "proper" Onext() ring at P we use
-       * two Splice operations. The algorithm goes:
-       *   - first disconnect the piece of the surface containing the edge
-       *     [PB] (it would be the same process if we chose [PA]) from
-       *     the Onext() ring at P.
-       *   - second, re-integrate the disconnected piece at the desired
-       *     location i.e. side by side with [PA] (respectively [PB] if
-       *     we chose [PA] at first stage).
-       * By "piece of surface containing the edge [PB]" we mean [all]
-       * the triangle[s] starting at [PB] in the Onext() order and
-       * having a left face set.
-       *
-       * We can illustrate this process on bit more general diagram than
-       * the last case (where the "piece of surface containing the edge
-       * [PB]" is constituted by two triangles) and when using
-       * the arguments of this method (i.e. [PA] = this and [PB] = second).
-       * The initial stage is the following (we note first=this=[PA] and
-       * second=[PB]) where the Onext() ring order is:
-       *     first, b2, b3, second, b5, bsplice, b7, first...
-       *
-       *                    p       N       A                            //
-       *                   / \      O      / \                           //
-       *                  /   \           /   \                          //
-       *                 /     \    F    /     \     counter-clockwise   //
-       *                /      b2   A  first    \    Onext() ring order  //
-       *               /         \  C  /         \                       //
-       *              /     *     \ E /     *     \                      //
-       *             /             \ /             \                     //
-       *            p-------b3------P------b7-------p                    //
-       *                           /|\                                   //
-       *                          / | \                                  //
-       *          NO FACE        /  |  \      NO FACE                    //
-       *                        /   |   \                                //
-       *                  second   b5   bsplice                          //
-       *                      /  *  |  *  \                              //
-       *                     /      |      \                             //
-       *                    B-------p-------p                            //
-       *
-       * The first stage, implemented as
-       *     second->Oprev()->Splice( bsplice ),
-       * yields the following diagram:
-       *
-       *                    p       N       A                            //
-       *                   / \      O      / \                           //
-       *                  /   \     F     /   \                          //
-       *                 /     \    A    /     \      counter-clockwise  //
-       *                /      b2   C  first    \     Onext() ring order //
-       *               /         \  E  /         \                       //
-       *              /     *     \   /     *     \                      //
-       *             /             \ /             \                     //
-       *            p-------b3------P------b7-------p                    //
-       *                                                                 //
-       *                         NO FACE                                 //
-       *                                                                 //
-       *                           /|\                                   //
-       *                          / | \                                  //
-       *                         /  |  \                                 //
-       *                        /   |   \                                //
-       *                  second   b5   bsplice                          //
-       *                      /  *  |  *  \                              //
-       *                     /      |      \                             //
-       *                    B-------p-------p                            //
-       *
-       * and the second stage, implemented as
-       *      first->Splice( bsplice ),
-       * yields the following diagram:
-       *
-       *                                    A                            //
-       *         B__        NO FACE        / \                           //
-       *         |  \__                   /   \                          //
-       *         |     \__               /     \       counter-          //
-       *         |      second         first    \      clockwise for all //
-       *         |           \__       /         \                       //
-       *         |     *        \__   /     *     \                      //
-       *         |                 \ /             \                     //
-       *         p-------b5---------P------b7-------p                    //
-       *         |               __/|\                                   //
-       *         |     *      __/   | \                                  //
-       *         |           /      |  \      NO FACE                    //
-       *         |     bsplice      |   \                                //
-       *         |   __/           b2    b3                              //
-       *         p__/               |  *  \                              //
-       *                NO FACE     |      \                             //
-       *                            p-------p                            //
-       *
-       */
-      inline static bool ReorderOnextRing( TPrimal* first, TPrimal* second );
-
-      /**
-       * \brief Basic quad-edge topological method.
-       *
-       * This method describes all possible topological operations on an
-       * edge since it is its own inverse. It works in two ways:
-       *
-       *   1. If this->m_Org != b->m_Org, it slice a face in two.
-       *   2. If this->m_Org == b->m_Org, it unifies two faces.
-       */
-      inline static void Splice( TPrimal* a, TPrimal* b );
-
-    protected:
-      QuadEdge( );
-      virtual ~QuadEdge( );
-
-    public:
-      static const TPrimalGeometry NoGeometry;
-
-    protected:
-      Pointer         m_Onext;  /**< Onext ring */
-      PtrDual         m_Rot;    /**< Rot ring */
-      TPrimalGeometry m_Origin; /**< Geometry attached to edge's origin */
-    };
-
-  } // ecapseman
-
-} // ecapseman
-
-#include <cpm/DataStructures/QuadEdge.hxx>
-
-#endif // __CPM__DATASTRUCTURES__QUADEDGE__H__
-
-// eof - $RCSfile$