Rev 506 | Rev 508 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#ifndef __HMESH_MANIFOLD_H__
#define __HMESH_MANIFOLD_H__
#include "entities.h"
#include "EntityVector.h"
namespace CGLA
{
// forward declaration
class Vec3f;
}
namespace Geometry
{
// forward declaration
class TriMesh;
class IndexedFaceSet;
}
namespace HMesh
{
// forward declarations
class ConstVertexHandle;
class ConstHalfEdgeHandle;
class ConstFaceHandle;
class VertexHandle;
class HalfEdgeHandle;
class FaceHandle;
class Manifold
{
public:
/// Default constructor
Manifold();
/** \brief Build a manifold.
The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces.
facevecis an array where each entry indicates the number of vertices in that face.
The array indices contains all the corresponding vertex indices in one concatenated list. */
void build( unsigned int no_vertices,
const float* vertvec,
unsigned int no_faces,
const unsigned int* facevec,
const unsigned int* indices,
const int* touch = NULL);
/// Build a manifold from a TriMesh
void build(const Geometry::TriMesh& mesh);
/** \brief Collapse the halfedge h.
The argument h is the halfedge being removed. The vertex v=h->opp->vert is the one being removed while h->vert survives.
The final argument indicates whether the surviving vertex should have the average position of the former vertices.
By default false meaning that the surviving vertex retains it position.
This function is not guaranteed to keep the mesh sane unless, collapse_halfedge_test has returned true !! */
void collapse_halfedge(HalfEdgeHandle h, bool avg_vertices = false);
/** \brief Split a face.
The face, f, is split by creating an edge with endpoints v0 and v1 (the next two arguments).
The vertices of the old face between v0 and v1 (in counter clockwise order) continue to belong to f.
The vertices between v1 and v0 belong to the new face. A handle to the new face is returned. */
FaceHandle split_face_by_edge(FaceHandle f, VertexHandle v0, VertexHandle v1);
/** \brief Split a polygon, f, by inserting a vertex at the barycenter.
This function is less likely to create flipped triangles than the split_face_triangulate function.
On the other hand, it introduces more vertices and probably makes the triangles more acute.
A handle to the inserted vertex is returned. */
VertexHandle split_face_by_vertex(FaceHandle f);
/** \brief Insert a new vertex on halfedge h.
The new halfedge is insterted as the previous edge to h.
An iterator to the inserted vertex is returned. */
VertexHandle split_edge(HalfEdgeHandle h);
/** \brief Merges two faces into a single polygon.
The first face is f. The second face is adjacent to f along the halfedge h.
This function returns true if the merging was possible and false otherwise.
Currently merge only fails if the mesh is already illegal. Thus it should, in fact, never fail. */
bool merge_faces(FaceHandle f, HalfEdgeHandle h);
/// \brief Close hole given by the invalid face of halfedgehandle h.
void close_hole(HalfEdgeHandle h);
/** \brief Flip an edge h.
Returns false if flipping cannot be performed. This is due to one of following:
1. one of the two adjacent faces is not a triangle.
2. Either end point has valency three.
3. The vertices that will be connected already are. */
bool flip(HalfEdgeHandle h);
/// Calculate the bounding box of the manifold
void bbox(CGLA::Vec3f& pmin, CGLA::Vec3f& pmax);
/// Calculate the bounding sphere of the manifold
void bsphere(CGLA::Vec3f& c, float& r);
VertexHandle vhandles_begin();
HalfEdgeHandle hhandles_begin();
FaceHandle fhandles_begin();
ConstVertexHandle vhandles_begin() const;
ConstHalfEdgeHandle hhandles_begin() const;
ConstFaceHandle fhandles_begin() const;
VertexHandle vhandles_end();
HalfEdgeHandle hhandles_end();
FaceHandle fhandles_end();
ConstVertexHandle vhandles_end() const;
ConstHalfEdgeHandle hhandles_end() const;
ConstFaceHandle fhandles_end() const;
/// Get number of vertices
IndexType no_vertices() const;
/// Get number of halfedges
IndexType no_halfedges() const;
/// Get number of faces
IndexType no_faces() const;
/// Store index in touched attribute of vertex
void enumerate_vertices();
/// Store index in touched attribute of halfedge
void enumerate_halfedges();
/// Store index in touched attribute of face
void enumerate_faces();
/// Clear the mesh
void clear();
/// Clean up unused space in vectors - WARNING! Invalidates existing handles!
void cleanup();
private:
EntityVector<Vertex> vertices;
EntityVector<HalfEdge> halfedges;
EntityVector<Face> faces;
// Only handles can access and modify the data directly
friend class VertexHandle;
friend class HalfEdgeHandle;
friend class FaceHandle;
friend class ConstVertexHandle;
friend class ConstHalfEdgeHandle;
friend class ConstFaceHandle;
// private template for building the manifold from various types
template<typename float_type, typename int_type>
void build_template(int_type no_vertices,
const float_type* vertvec,
int_type no_faces,
const int_type* facevec,
const int_type* indices,
const int* touch = NULL);
/// Set the next and prev indices of the first and second argument respectively.
void link(HalfEdgeIndex h0, HalfEdgeIndex h1);
/// Glue halfedges by letting the opp indices point to each other.
void glue(HalfEdgeIndex h0, HalfEdgeIndex h1);
/// Auxiliary function called from collapse
void remove_face_if_degenerate(HalfEdgeIndex h);
/// Ensure boundary consistency.
void ensure_boundary_consistency(VertexIndex v);
VertexIndex add_vertex(const Vertex& v);
FaceIndex add_face(const Face& f);
HalfEdgeIndex add_halfedge(const HalfEdge& h);
void remove_vertex(VertexIndex vi);
void remove_halfedge(HalfEdgeIndex hi);
void remove_face(FaceIndex fi);
};
inline Manifold::Manifold(){}
inline IndexType Manifold::no_vertices() const{ return vertices.size(); }
inline IndexType Manifold::no_halfedges() const{ return halfedges.size(); }
inline IndexType Manifold::no_faces() const{ return faces.size(); }
inline void Manifold::remove_vertex(VertexIndex v){ vertices.remove(v); }
inline void Manifold::remove_halfedge(HalfEdgeIndex h){ halfedges.remove(h); }
inline void Manifold::remove_face(FaceIndex f){ faces.remove(f); }
inline VertexIndex Manifold::add_vertex(const Vertex& v){ return vertices.add(v); }
inline HalfEdgeIndex Manifold::add_halfedge(const HalfEdge& h){ return halfedges.add(h); }
inline FaceIndex Manifold::add_face(const Face& f){ return faces.add(f);}
/** \brief Verify Manifold Integrity
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.
The function returns true if the mesh is valid and false otherwise. */
bool valid(const Manifold& m);
}
#endif __HMESH_MANIFOLD_H__