Subversion Repositories gelsvn

Rev

Rev 89 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#ifndef __MANIFOLD_H
#define __MANIFOLD_H

#include <vector>
#include <list>
#include <map>

#include "Vertex.h"
#include "HalfEdge.h"
#include "Face.h"



namespace HMesh
{
        class VertexCirculator;
        class FaceCirculator;

        /** A Data structure representing an open or closed manifold.
                        Manifold keeps lists of the entities making up a halfedge mesh
                        and provides basic functions for creating new faces, halfedges
                        and vertices. There are also primitive operations for editing 
                        such as edge collapse. */
        
        struct Manifold
        {
                std::list<Vertex> vertex_db;
                std::list<Face> face_db;
                std::list<HalfEdge> halfedge_db;

                /** Remove a face if it contains only two edges. This is an auxiliary
                                function called from collapse_halfedge. */
                void remove_face_if_degenerate(HalfEdgeIter fi);

                /** Copying a manifold will not work, since faces, vertices, and
                                halfedges contain iterators pointing to other faces, vertices,
                                and halfedges. These pointers would need to be changed if the 
                                mesh were copied. In other words, we would need to walk the
                                entire mesh. This may be required but it should not be an 
                                operation that is easily invoked by calling the copy constructor.
                                Hence, this operator is made private.           */
                Manifold(const Manifold& m2) {}

                /** The assignment operator is private for the same reason that the
                                copy constructor is private. */
                const Manifold& operator=(const Manifold& m2) {}

                public:
        
                /// Construct an empty manifold.
                Manifold() {}

                /// Return the bounding box of the manifold.
                void get_bbox(CGLA::Vec3f&, CGLA::Vec3f&);

                /// Get a bounding sphere
    void get_bsphere(CGLA::Vec3f& c, float& r);

                /// Clear the manifold - removing all data.
                void clear()
                {
                        vertex_db.clear();
                        face_db.clear();
                        halfedge_db.clear();
                }

                /// Return the number of faces.
                int no_faces() const {return face_db.size();}

                /// Return the number of halfedges.
                int no_halfedges() const {return halfedge_db.size();}

                /// Return the number of vertices
                int no_vertices() const {return vertex_db.size();}

                /// Create a new vertex at a given position.
                VertexIter create_vertex(const CGLA::Vec3f& pos)
                {
                        vertex_db.push_back(Vertex(pos));
                        return --vertex_db.end();
                }

                /// Create a new face 
                FaceIter create_face()
                {
                        face_db.push_back(Face());
                        return --face_db.end();
                }

                /// Create a new halfedge.
                HalfEdgeIter create_halfedge()
                {
                        halfedge_db.push_back(HalfEdge());
                        return --halfedge_db.end();
                }

                /// Erase halfedge. Assumes it is safe to do so. Use with care.
                void erase_halfedge(HalfEdgeIter he)
                {
                        halfedge_db.erase(he);
                }

                /// Erase vertex. Assumes it is safe to do so. Use with care.
                void erase_vertex(VertexIter v)
                {
                        vertex_db.erase(v);
                }
        
                /// Erase face. Assumes it is safe to do so. Use with care.
                void erase_face(FaceIter f)
                {
                        face_db.erase(f);
                }

                /// Return iterator pointing to the first halfedge.
                HalfEdgeIter halfedges_begin() { return halfedge_db.begin();}

                /// Return iterator pointing to beyond the last halfedge.
                HalfEdgeIter halfedges_end() { return halfedge_db.end(); }
        
                /// Return iterator pointing to the first vertex.
                VertexIter vertices_begin() { return vertex_db.begin();}

                /// Return iterator pointing to beyond the last vertex.
                VertexIter vertices_end() { return vertex_db.end(); }

                /// Return iterator pointing to the first face.
                FaceIter faces_begin() { return face_db.begin();        }

                /// Return iterator pointing to beyond the last face.
                FaceIter faces_end() { return face_db.end(); }

                /** HalfEdge collapse precondition. 
                                If this function does not return true, it is illegal to collapse
                                the halfedge given as second arg. The reason is that the collapse
                                would violate the manifold property of the mesh. */
                bool collapse_precond(VertexIter, HalfEdgeIter);
                
                /** Collapse the halfedge given as second argument. The first argument
                                is the vertex that is being removed. This function is not guaranteed
                                to keep the mesh sane unless, collapse_precond has returned true. */
                void collapse_halfedge(VertexIter, HalfEdgeIter, bool=false);

                /** Split a face (first argument) by connecting two vertices (the
                                next two arguments). */
                FaceIter split_face(FaceIter, VertexIter, VertexIter);

                /** Insert a new vertex on the halfedge given as argument. */
                VertexIter Manifold::split_edge(HalfEdgeIter h);

                /** Triangulate a polygonal face by repeatedly calling splitface. */
                void triangulate(FaceIter);

                /** Triangulate a polygon by inserting a vertex at the barycenter and 
                                connecting all vertices to this vertex. */
                VertexIter safe_triangulate(FaceIter f);

                /** Insert a new vertex (second arg.) in a face (first arg.).
                                This operation splits an N-gon into N triangles. */
                void face_insert_point(FaceIter f, VertexIter);

                /** Merges two faces into a single polygon. The first face is the first
                                argument. The second face is adjacent to the first along the
                                halfedge given as second argument. */
                bool merge_faces(FaceIter f, HalfEdgeIter h);

                /** flips an edge. Returns false if flipping cannot be performed.
                                This is either because one of the two adjacent faces is not
                                a triangle, or because either end point has valency three or
                                because the vertices that will be connected already are. */
                bool flip(HalfEdgeIter);

                /** Performs a series of tests to check that this is a valid manifold.
                                This function is not rigorously constructed but seems to catch
                                all problems so far. */
                bool is_valid();

                /** Give each vertex a unique id corresponding to its iterator 
                                position */
                void enumerate_vertices();

                /** Give each halfedge a unique id corresponding to its iterator 
                                position */
                void enumerate_halfedges();

                /** Give each face a unique id corresponding to its iterator 
                                position */
                void enumerate_faces();
                
        };


}
#endif