Subversion Repositories gelsvn

Rev

Rev 448 | Rev 600 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 448 Rev 595
Line -... Line 1...
-
 
1
/* ----------------------------------------------------------------------- *
-
 
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
-
 
3
 * Copyright (C) the authors and DTU Informatics
-
 
4
 * For license and list of authors, see ../../doc/intro.pdf
-
 
5
 * ----------------------------------------------------------------------- */
-
 
6
 
-
 
7
/**
-
 
8
 * @file Manifold.h
-
 
9
 * @brief The Manifold class is the main data structure of HMesh - the actual mesh.
-
 
10
 */
-
 
11
 
1
#ifndef __HMESH_MANIFOLD_H
12
#ifndef __HMESH_MANIFOLD_H__
2
#define __HMESH_MANIFOLD_H
13
#define __HMESH_MANIFOLD_H__
-
 
14
 
-
 
15
#include <algorithm>
-
 
16
#include <CGLA/Vec3d.h>
-
 
17
 
-
 
18
#include "ConnectivityKernel.h"
-
 
19
#include "Iterators.h"
-
 
20
#include "Walker.h"
-
 
21
#include "AttributeVector.h"
3
 
22
 
-
 
23
 
4
#include <vector>
24
namespace Geometry
5
#include <list>
-
 
6
#include <map>
-
 
7
 
25
{
8
#include "Vertex.h"
26
    // forward declaration
9
#include "HalfEdge.h"
27
    class TriMesh;
10
#include "Face.h"
28
    class IndexedFaceSet;
-
 
29
}
11
 
30
 
12
namespace HMesh
31
namespace HMesh
13
{
32
{
14
	class VertexCirculator;
33
    /** The Manifold class represents a halfedge based mesh. Since meshes based on the halfedge
-
 
34
     representation must be manifold (although exceptions could be made) the class is thus named.
-
 
35
     Manifold contains many functions for mesh manipulation and associated the position attribute
15
	class FaceCirculator;
36
     with vertices.*/
16
 
37
    
17
	/** \brief A Data structure representing an open or closed manifold.
-
 
18
			Manifold keeps lists of the entities making up a halfedge mesh
-
 
19
			and provides basic functions for creating new faces, halfedges
-
 
20
			and vertices. There are also primitive operations for editing 
-
 
21
			such as edge collapse. */
-
 
22
	class Manifold
38
    class Manifold
23
		{
39
    {
24
			std::list<Vertex> vertex_db;
-
 
25
			std::list<Face> face_db;
-
 
26
			std::list<HalfEdge> halfedge_db;
-
 
27
 
-
 
28
			bool erase_immediately;
-
 
29
			std::vector<VertexIter> unused_vertices;
-
 
30
			std::vector<FaceIter> unused_faces;
-
 
31
			std::vector<HalfEdgeIter> unused_halfedges;
-
 
32
 
-
 
33
 
-
 
34
			/** Remove a face if it contains only two edges.
-
 
35
					This is an auxiliary function called from collapse_halfedge. */
-
 
36
			void remove_face_if_degenerate(HalfEdgeIter);
-
 
37
 
-
 
38
			Manifold(const Manifold&) {}
-
 
39
			/**< Empty copy constructor.
-
 
40
				 Copying a manifold will not work, since faces, vertices, and
-
 
41
				 halfedges contain iterators pointing to other faces, vertices,
-
 
42
				 and halfedges. These pointers would need to be changed if the 
-
 
43
				 mesh were copied. In other words, we would need to walk the
-
 
44
				 entire mesh. This may be required but it should not be an 
-
 
45
				 operation that is easily invoked by calling the copy constructor.
-
 
46
				 Hence, this operator is made private.		*/
-
 
47
 
-
 
48
			const Manifold& operator=(const Manifold&) {return *this;}
-
 
49
			/**< Empty assignment operator.
-
 
50
				 The assignment operator is private for the same reason that the
-
 
51
				 copy constructor is private. */
-
 
52
 
-
 
53
		public:
40
    public:
54
 
41
        
-
 
42
        /// Vector type used for positions of vertices.
-
 
43
        typedef CGLA::Vec3d Vec;
-
 
44
        
-
 
45
        /// Default constructor
-
 
46
        Manifold();
55
 
47
 
-
 
48
        /** \brief Build a manifold. 
-
 
49
        The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces. 
-
 
50
        facevecis an array where each entry indicates the number of vertices in that face. 
-
 
51
        The array indices contains all the corresponding vertex indices in one concatenated list. */
-
 
52
        void build( size_t no_vertices,
-
 
53
                    const float* vertvec,
-
 
54
                    size_t no_faces,
-
 
55
                    const int* facevec,
-
 
56
                    const int* indices);
-
 
57
 
-
 
58
        /** \brief Build a manifold.
-
 
59
         This function is for vertices given in double precision.
-
 
60
         The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces.
-
 
61
         facevecis an array where each entry indicates the number of vertices in that face.
-
 
62
         The array indices contains all the corresponding vertex indices in one concatenated list. */
-
 
63
        void build( size_t no_vertices,
-
 
64
                   const double* vertvec,
-
 
65
                   size_t no_faces,
-
 
66
                   const int* facevec,
-
 
67
                   const int* indices);
-
 
68
 
-
 
69
        /// Build a manifold from a TriMesh
-
 
70
        void build(const Geometry::TriMesh& mesh);
-
 
71
        
-
 
72
        /// Add a face to the Manifold
-
 
73
        FaceID add_face(std::vector<Manifold::Vec> points);
-
 
74
 
-
 
75
//        /** Removes a face from the Manifold. If it is an interior face it is simply replaces
-
 
76
//         by an InvalidFaceID. If the face contains boundary edges, these go away. */
56
			Manifold(): erase_immediately(true) {}
77
//        bool remove_face(FaceID fid);
-
 
78
//
57
			///< Construct an empty manifold.
79
//        /** Remove an edge from the Manifold.
-
 
80
//         This function will remove the faces on either side and the edge itself in the process. */
-
 
81
//        bool remove_edge(HalfEdgeID hid);
-
 
82
//
-
 
83
//        /** Remove a vertex from the Manifold.
-
 
84
//         This function merges all faces around the vertex into one and then removes 
-
 
85
//         this resulting face. */
-
 
86
//        bool remove_vertex(VertexID vid);
-
 
87
        
-
 
88
        /// number of  vertices
-
 
89
        size_t no_vertices() const { return kernel.no_vertices();}
-
 
90
        /// number of active faces
-
 
91
        size_t no_faces() const { return kernel.no_faces();}
-
 
92
        /// number of active halfedges
-
 
93
        size_t no_halfedges() const { return kernel.no_halfedges();}
-
 
94
        
-
 
95
        /// number of total vertices in kernel
-
 
96
        size_t allocated_vertices() const { return kernel.allocated_vertices();}
-
 
97
        /// number of total faces in kernel
-
 
98
        size_t allocated_faces() const { return kernel.allocated_faces();}
-
 
99
        /// number of total halfedges in kernel
-
 
100
        size_t allocated_halfedges() const { return kernel.allocated_halfedges();}
-
 
101
        
-
 
102
        /// check if ID of vertex is in use
-
 
103
        bool in_use(VertexID id) const { return kernel.in_use(id);}
-
 
104
        /// check if ID of face is in use
-
 
105
        bool in_use(FaceID id) const { return kernel.in_use(id);}
-
 
106
        /// check if ID of halfedge is in use
-
 
107
        bool in_use(HalfEdgeID id) const { return kernel.in_use(id);}
-
 
108
        
-
 
109
        /// Iterator to first VertexID, optional argument defines if unused items should be skipped
-
 
110
        VertexIDIterator vertices_begin(bool skip = true) const { return kernel.vertices_begin();}
-
 
111
        /// Iterator to first FaceID, optional argument defines if unused items should be skipped
-
 
112
        FaceIDIterator faces_begin(bool skip = true) const { return kernel.faces_begin();}
-
 
113
        /// Iterator to first HalfEdgeID, optional argument defines if unused items should be skipped
-
 
114
        HalfEdgeIDIterator halfedges_begin(bool skip = true) const { return kernel.halfedges_begin();}
-
 
115
        
-
 
116
        /// Iterator to past the end VertexID
-
 
117
        VertexIDIterator vertices_end() const { return kernel.vertices_end();}
-
 
118
        /// Iterator topast the end FaceID
-
 
119
        FaceIDIterator faces_end() const { return kernel.faces_end();}
-
 
120
        /// Iterator to past the end HalfEdgeID
-
 
121
        HalfEdgeIDIterator halfedges_end() const {return kernel.halfedges_end(); }  
-
 
122
 
-
 
123
		
-
 
124
		/** \brief Bridge f0 and f1 by connecting the vertex pairs given in pairs.
-
 
125
		 This function creates a cylindrical connection between f0 and f1. f0 and f1 are removed and the vertices 
-
 
126
		 given in pairs are connected by edges. The result is a cylindrical connection that changes the genus of the object.
-
 
127
		 
-
 
128
		 This function leaves all error chethising in the hands of the user (for now). The faces clearly should not have any 
-
 
129
		 vertices or edges in common as this will create a non-manifold situation. Also the faces should face towards or away 
-
 
130
		 from each other and be in a position where it is reasonable to make the bridge. The connections should also make sense 
-
 
131
		 from a geometric point of view and should be in a counter clothiswise loop on f0 and a clothiswise loop on f1. No need to 
-
 
132
		 connect all vertices.
-
 
133
		 
-
 
134
		 The function returns a vector of HalfEdgeIDs. Those are, of course, the connecting halfedges - also the opposite edges.
-
 
135
		 */
-
 
136
		std::vector<HalfEdgeID> bridge_faces(FaceID f0, FaceID f1, const std::vector<std::pair<VertexID, VertexID> >& pairs);
58
 
137
 
59
			bool is_valid();
-
 
60
			/**< Performs a series of tests to check that this is a valid manifold.
-
 
61
				 This function is not rigorously constructed but seems to catch
-
 
62
				 all problems so far. The function returns true if the mesh is 
-
 
63
				 valid and false otherwise.	*/
-
 
64
 
-
 
65
			void enumerate_vertices();
-
 
66
			/**< Give each vertex a unique id corresponding to its iterator
-
 
67
				 position. Value is stored in the touched attribute. */
-
 
68
 
-
 
69
			void enumerate_halfedges();
-
 
70
			/**< Give each halfedge a unique id corresponding to its iterator
-
 
71
				 position. Value is stored in the touched attribute. */
-
 
72
 
-
 
73
			void enumerate_faces();
-
 
74
			/**< Give each face a unique id corresponding to its iterator
-
 
75
				 position. Value is stored in the touched attribute. */
-
 
76
				 
-
 
77
			size_t no_faces() const {return face_db.size();}
-
 
78
			///< Return the number of faces.
-
 
79
 
-
 
80
			size_t no_halfedges() const {return halfedge_db.size();}
-
 
81
			///< Return the number of halfedges.
-
 
82
 
-
 
83
			size_t no_vertices() const {return vertex_db.size();}
-
 
84
			///< Return the number of vertices
-
 
85
 
-
 
86
			VertexIter create_vertex(const CGLA::Vec3f& pos);
-
 
87
			///< Create a new vertex.
-
 
88
 
-
 
89
			FaceIter create_face();
-
 
90
			/**< Create a new face.
-
 
91
				 An iterator to the face is returned. When a face f is initially
-
 
92
				 created, is_used(f) will return false. */
-
 
93
 
-
 
94
			HalfEdgeIter create_halfedge();
-
 
95
			/**< Create a new halfedge. An iterator to the halfedge is returned.
-
 
96
				 When h is initially created, is_used(h) returns false. */
-
 
97
 
138
 
-
 
139
        /** \brief Collapse the halfedge h.
-
 
140
        The argument h is the halfedge being removed. The vertex v=h->opp->vert is the one being removed while h->vert survives.
-
 
141
        The final argument indicates whether the surviving vertex should have the average position of the former vertices.
-
 
142
        By default false meaning that the surviving vertex retains it position.
-
 
143
        This function is not guaranteed to keep the mesh sane unless, precond_collapse_edge has returned true !! */
-
 
144
        void collapse_edge(HalfEdgeID h, bool avg_vertices = false);
-
 
145
 
-
 
146
        /** \brief Split a face.
-
 
147
        The face, f, is split by creating an edge with endpoints v0 and v1 (the next two arguments). 
-
 
148
        The vertices of the old face between v0 and v1 (in counter clothiswise order) continue to belong to f. 
-
 
149
        The vertices between v1 and v0 belong to the new face. A handle to the new face is returned. */
-
 
150
        FaceID split_face_by_edge(FaceID f, VertexID v0, VertexID v1);
-
 
151
 
-
 
152
        /** \brief Split a polygon, f, by inserting a vertex at the barycenter.			
-
 
153
        This function is less likely to create flipped triangles than the split_face_triangulate function. 
-
 
154
        On the other hand, it introduces more vertices and probably makes the triangles more acute.
-
 
155
        A handle to the inserted vertex is returned. */
-
 
156
        VertexID split_face_by_vertex(FaceID f);
-
 
157
       // VertexID split_face_by_vertex(HalfEdgeID h);
-
 
158
 
-
 
159
        /** \brief Insert a new vertex on halfedge h.
-
 
160
        The new halfedge is insterted as the previous edge to h.
-
 
161
        A handle to the inserted vertex is returned. */
-
 
162
        VertexID split_edge(HalfEdgeID h);
-
 
163
        
-
 
164
        /** \brief Stitch two halfedges.
-
 
165
         Two boundary halfedges can be stitched together. This can be used to build a complex mesh
-
 
166
         from a bunch of simple faces. */
-
 
167
        bool stitch_boundary_edges(HalfEdgeID h0, HalfEdgeID h1);
-
 
168
 
-
 
169
        /** \brief Merges two faces into a single polygon. 
-
 
170
        The first face is f. The second face is adjacent to f along the halfedge h. 
-
 
171
        This function returns true if the merging was possible and false otherwise. 
-
 
172
        Currently merge only fails if the mesh is already illegal. Thus it should, in fact, never fail. */
-
 
173
        bool merge_faces(FaceID f, HalfEdgeID h);
-
 
174
		
-
 
175
		/** \brief Merge all faces in the one ring of a vertex into a single polygon.
-
 
176
		The vertex is given by v.
-
 
177
		 
-
 
178
		The return value is the FaceID of the resulting polygonal face. 
-
 
179
		InvalidFaceID is returned if 
-
 
180
		- the input vertex is not in use or 
-
 
181
		- the input vertex has valence less than two which is a degenerate case.
-
 
182
		- the input vertex is a boundary vertex of valence two - i.e. adjacent to just one face.
-
 
183
		- the same halfedge appears in two faces of the one ring of the input vertex: I.e.
-
 
184
		the input vertex is twice adjacent to the same face!
-
 
185
		 
-
 
186
		Note that this function can create some unusual and arguably degenerate meshes. For instance, 
-
 
187
		two triangles which share all vertices is collapsed to a single pair of vertices connected by 
-
 
188
		a pair of halfedges bounding the same face. */
-
 
189
		FaceID merge_one_ring(VertexID v, float max_loop_length = FLT_MAX);
-
 
190
 
-
 
191
        /** \brief Close hole given by the invalid face of halfedgehandle h.
-
 
192
         returns FaceID of the created face or the face that is already there if the 
-
 
193
         face was not InvalidFaceID. */
-
 
194
        FaceID close_hole(HalfEdgeID h);
-
 
195
 
-
 
196
        /// \brief Flip an edge h. 
-
 
197
        void flip_edge(HalfEdgeID h);
-
 
198
 
-
 
199
        /// Return reference to position given by VertexID
-
 
200
        Vec& pos(VertexID id);
-
 
201
        /// Return const reference to position given by VertexID
-
 
202
        const Vec& pos(VertexID id) const;
-
 
203
 
-
 
204
        /// Clear the mesh. Remove all faces, halfedges, and vertices.
98
			void clear();
205
        void clear();
99
			///< Clear the manifold, removing all data.
-
 
100
 
206
 
101
			void remove_unused();
-
 
102
			/**< Remove unused vertices, edges and faces from the database.
207
        /// Remove unused items from Mesh, map argument is to be used for attribute vector cleanups in order to maintain sync.
103
				 If delayed_erase mode is enabled, then until this function 
-
 
104
				 has been called, erased vertices, edges, and faces are just marked
-
 
105
				 as unused but not removed from their respective lists. */
-
 
106
 
-
 
107
			void delayed_erase();
208
        void cleanup(IDRemap& map);
108
			/**< Delay the actual removal of vertices, faces, and edges that
-
 
109
				 are erased.  In many cases, it is a problem if one cannot
-
 
110
				 test whether a vertex, halfedge, or face indicated by an
-
 
111
				 iterator is in use or has been removed from the mesh. One
-
 
112
				 solution to this problem is to delay the actual removal of
-
 
113
				 the vertex, edge or face. Instead when calling, say,
-
 
114
				 erase_face(f), all the iterators of f are assigned the
-
 
115
				 appropriate NULL value to indicate that they are not
-
 
116
				 pointing at anything, and f is added to a vector of faces
-
 
117
				 that need to be physically removed from the face_db.
-
 
118
 
-
 
119
				 Since f is not erased, all iterators pointing at f remain
-
 
120
				 valid! And, importantly, it is possible to test whether f is
-
 
121
				 in use by calling is_used(f).
-
 
122
 
-
 
123
				 When remove_unused is called, the physical removal takes
209
        /// Remove unused items from Mesh
124
				 place. Calling immediate_erase switches Manifold back to the
-
 
125
				 state where entities are removed as soon as the appropriate
-
 
126
				 erase function is called, and at the same time calls
-
 
127
				 remove_unused.
210
        void cleanup();
128
			*/
-
 
129
 
211
        
130
			void immediate_erase();
-
 
131
			/**< Immediately remove erased entities.
-
 
132
				 Calling immediate_erase switches Manifold back to the state
-
 
133
				 where entities are removed as soon as the appropriate erase
212
        /// Returns a Walker to the out halfedge of vertex given by VertexID
134
				 function is called.
-
 
135
 
-
 
136
				 See delayed_erase for more details, and note that
-
 
137
				 immediate_erase is the default mode.  */
-
 
138
 
-
 
139
			bool is_used(VertexIter v) const;
213
        Walker walker(VertexID id) const;
140
			/**< Test whether the vertex indicated by the argument v is used.
-
 
141
				 This function returns true if the vertex appears to have a 
214
        /// Returns a Walker to the last halfedge of face given by FaceID
142
				 valid outgoing halfedge iterator. */
-
 
143
 
-
 
144
			bool is_used(FaceIter f) const;
215
        Walker walker(FaceID id) const;
145
			/**< Test whether the face indicated by the argument f is used.
-
 
146
				 This function returns true if the face appears to have a 
-
 
147
				 valid halfedge iterator. */
-
 
148
 
-
 
149
			bool is_used(HalfEdgeIter h) const;
-
 
150
			/**< Test whether the halfedge indicated by the argument h is used.
-
 
151
				 This function returns true if the halfedge appears to have a 
216
        /// Returns a Walker to the halfedge given by HalfEdgeID
152
				 valid vertex iterator. */
-
 
153
 
-
 
154
			void erase_halfedge(HalfEdgeIter h);			
217
        Walker walker(HalfEdgeID id) const;
155
			/**< Erase halfedge h. 
-
 
156
				 In general, you should never call this function but use the 
-
 
157
				 collapse_halfedge function instead since blindly erasing geometry
-
 
158
				 is most likely to invalidate the Mesh. Quite possibly this function
-
 
159
				 will be removed from the public interface. 
-
 
160
					
-
 
161
				 Note that if delayed_erase has been called, this function does
-
 
162
				 not immediately remove anything from the mesh. Instead the halfedge
-
 
163
				 is reset to its initial state. Thus, iterators are not invalidated,
-
 
164
				 and it is possible to test whether h is used calling:
-
 
165
				 is_used(h). when remove_unused is called, the actual removal
-
 
166
				 takes place.
-
 
167
			*/
-
 
168
 
218
        
169
			void erase_vertex(VertexIter v);
-
 
170
			/**< Erase vertex v.
-
 
171
				 In general, you should never call this function but use the 
-
 
172
				 collapse_halfedge function to collapse the vertex away.
-
 
173
				 Blindly erasing is extremely likely to invalidate the
-
 
174
				 Mesh. Quite possibly this function will be removed from the
-
 
175
				 public interface. 
-
 
176
 
-
 
177
				 Note that if delayed_erase has been called, this function does
-
 
178
				 not immediately remove anything from the mesh. Instead the halfedge
-
 
179
				 is reset to its initial state. Thus, iterators are not invalidated,
-
 
180
				 and it is possible to test whether v is used calling:
-
 
181
				 is_used(v). when remove_unused is called, the actual removal
-
 
182
				 takes place.
-
 
183
			*/
-
 
184
 
219
 
-
 
220
    private:
185
 
221
        
186
			void erase_face(FaceIter f);
222
        ConnectivityKernel kernel;
187
			/**< Erase face f.
-
 
188
				 In general, you should never call this function but use 
-
 
189
				 collapse_halfedge in conjunction with other functions to
-
 
190
				 remove the face through (Euler) operations which preserve
-
 
191
				 the mesh in a valid state.
-
 
192
				 Blindly erasing is extremely likely to invalidate the
-
 
193
				 Mesh. Quite possibly this function will be removed from the
-
 
194
				 public interface. 
-
 
195
 
-
 
196
				 Note that if delayed_erase has been called, this function does
-
 
197
				 not immediately remove anything from the mesh. Instead the face
-
 
198
				 is reset to its initial state. Thus, iterators are not invalidated,
-
 
199
				 and it is possible to test whether f is used calling:
-
 
200
				 is_used(f). when remove_unused is called, the actual removal
-
 
201
				 takes place.
-
 
202
			*/
-
 
203
 
223
        
204
			HalfEdgeIter halfedges_begin();
-
 
205
			///< Return iterator pointing to the first halfedge.
224
        VertexAttributeVector<Vec> positions;
206
 
225
 
-
 
226
        // private template for building the manifold from various types
-
 
227
        template<typename size_type, typename float_type, typename int_type>
207
			HalfEdgeIter halfedges_end();
228
        void build_template(size_type no_vertices,
-
 
229
                            const float_type* vertvec,
-
 
230
                            size_type no_faces,
208
			///< Return iterator pointing to beyond the last halfedge.
231
                            const int_type* facevec,
-
 
232
                            const int_type* indices);
209
 
233
 
210
			VertexIter vertices_begin();
234
        /// Set the next and prev indices of the first and second argument respectively.
211
			///< Return iterator pointing to the first vertex.
235
        void link(HalfEdgeID h0, HalfEdgeID h1);
212
 
236
 
213
			VertexIter vertices_end();
237
        /// Glue halfedges by letting the opp indices point to each other.
214
			///< Return iterator pointing to beyond the last vertex.
238
        void glue(HalfEdgeID h0, HalfEdgeID h1);
215
 
239
 
216
			FaceIter faces_begin();
240
        /// Auxiliary function called from collapse
217
			///< Return iterator pointing to the first face.
241
        void remove_face_if_degenerate(HalfEdgeID h);
218
 
242
 
219
			FaceIter faces_end();
243
        /// Ensure boundary consistency.
220
			///< Return iterator pointing to beyond the last face.
244
        void ensure_boundary_consistency(VertexID v);
-
 
245
    };
221
 
246
 
222
			bool collapse_precond(HalfEdgeIter h);
247
    /** \brief Verify Manifold Integrity
-
 
248
    Performs a series of tests to chethis that this is a valid manifold.
-
 
249
    This function is not rigorously constructed but seems to catch all problems so far. 
-
 
250
    The function returns true if the mesh is valid and false otherwise. */
223
			/**< \brief HalfEdge collapse precondition.
251
    bool valid(const Manifold& m);
224
 
252
 
225
			The argument h is the halfedge we want to collapse. 
253
    /// Calculate the bounding box of the manifold
-
 
254
    void bbox(const Manifold& m, Manifold::Vec& pmin, Manifold::Vec& pmax);
226
 
255
 
227
			If this function does not return true, it is illegal to collapse
-
 
228
			h. The reason is that the collapse would violate the manifold property
-
 
229
			of the mesh.
-
 
230
 
-
 
231
			The test is as follows.
-
 
232
 
-
 
233
			1. For the two vertices adjacent to the edge, we generate
-
 
234
			a list of all their neighbouring vertices. We then generate a 
256
    /// Calculate the bounding sphere of the manifold
235
			list of the vertices that occur in both these lists. That is, 
-
 
236
			we find all vertices connected by edges to both endpoints
-
 
237
			of the edge and store these in a list.
-
 
238
 
-
 
239
			2. For both faces incident on the edge, check whether they
257
    void bsphere(const Manifold& m, Manifold::Vec& c, float& r);
240
			are triangular. If this is the case, the face will be removed,
-
 
241
			and it is ok that the the third vertex is connected to both 
-
 
242
			endpoints. Thus the third vertex in such a face is removed
-
 
243
			from the list generated in 1.
-
 
244
 
-
 
245
			3. If the list is now empty, all is well. Otherwise, there
-
 
246
			would be a vertex in the new mesh with two edges connecting
-
 
247
			it to the same vertex. Return false.
-
 
248
 
258
 
-
 
259
    /** \brief Test for legal edge collapse.
-
 
260
    The argument h is the halfedge we want to collapse. 
-
 
261
    If this function does not return true, it is illegal to collapse h. 
-
 
262
    The reason is that the collapse would violate the manifold property of the mesh.
-
 
263
    The test is as follows:
-
 
264
    1.  For the two vertices adjacent to the edge, we generate a list of all their neighbouring vertices. 
-
 
265
    We then generate a  list of the vertices that occur in both these lists. 
-
 
266
    That is, we find all vertices connected by edges to both endpoints of the edge and store these in a list.
-
 
267
    2.  For both faces incident on the edge, chethis whether they are triangular. 
-
 
268
    If this is the case, the face will be removed, and it is ok that the the third vertex is connected to both endpoints. 
-
 
269
    Thus the third vertex in such a face is removed from the list generated in 1.
-
 
270
    3.  If the list is now empty, all is well. 
-
 
271
    Otherwise, there would be a vertex in the new mesh with two edges connecting it to the same vertex. Return false.
249
			4. TETRAHEDRON TEST:
272
    4.  TETRAHEDRON TEST:
250
			If the valency of both vertices is 
-
 
251
			three, and the incident faces are triangles, we also disallow
273
    If the valency of both vertices is three, and the incident faces are triangles, we also disallow the operation. 
252
			the operation. Reason: It introduces a vertex of valency two
-
 
253
			and if the final two polygons incident on the vertices 
274
    Reason: A vertex valency of two and two triangles incident on the adjacent vertices makes the construction collapse.
254
			that are adjacent to the edge being collapsed are triangles, then
-
 
255
			the construction will collapse
-
 
256
 
-
 
257
			5. VALENCY 4 TEST:
275
    5.  VALENCY 4 TEST:
258
			If a face adjacent to the edge being collapsed is a triangle,
276
    If a triangle is adjacent to the edge being collapsed, it disappears.
259
			it will disappear, and the valency of the final vertex beloning to
277
    This means the valency of the remaining edge vertex is decreased by one.
260
			this edge will be reduced by one. Hence this valency should be at
-
 
261
			least 4. A valency three vertex will be reduced to a valency two
278
    A valency two vertex reduced to a valency one vertex is considered illegal.
262
			vertex which is considered illegal.
-
 
263
 
-
 
264
			6. PREVENT MERGING HOLES:
279
    6.  PREVENT MERGING HOLES:
265
			We do not want to collapse an edge if its end points are boundary
280
    Collapsing an edge with boundary endpoints and valid faces results in the creation where two holes meet.
266
			vertices, but its two adjacent faces are not NULL faces, because
281
    A non manifold situation. We could relax this...
267
			in that case we create a vertex where two holes meet. A non manifold
282
	7. New test: if the same face is in the one-ring of both vertices but not adjacent to the common edge,
268
			situation.	*/
-
 
269
 
-
 
270
 
-
 
271
			void collapse_halfedge(HalfEdgeIter h, bool=false);
283
	then the result of a collapse would be a one ring where the same face occurs twice. This is disallowed as the resulting
272
			/**< Collapse the halfedge h.
284
	 face would be non-simple.	*/
273
 
-
 
274
			The argument h is the halfedge being removed. The vertex 
-
 
275
			v=h->opp->vert is the one being removed while h->vert survives.
-
 
276
 
-
 
277
			The final argument is a boolean indicating whether the vertex
-
 
278
			that survives the collapse should have a position which is the
285
    bool precond_collapse_edge(const Manifold& m, HalfEdgeID h);
279
			average of its own position and the vertex that is removed.
-
 
280
			By default false meaning that the surviving vertex retains it 
-
 
281
			position.
-
 
282
 
286
 
283
			This function is not guaranteed to keep the mesh sane unless,
-
 
284
			collapse_precond has returned true !!
287
    /** \brief Test fpr legal edge flip. 
285
			*/
-
 
286
 
-
 
287
			FaceIter split_face(FaceIter f, VertexIter v0, VertexIter v1);
288
    Returns false if flipping cannot be performed. This is due to one of following: 
288
			/**< Split a face.
-
 
289
				 The face, f, is split by connecting two
289
    1.  one of the two adjacent faces is not a triangle. 
290
				 vertices v0 and v1 (the next two arguments). The vertices of
290
    2.  Either end point has valency three.
291
				 the old face between v0 and v1 (in counter clockwise order) 
291
    3.  The vertices that will be connected already are. */
292
				 continue to belong to f. The vertices between v1 and 
-
 
293
				 v0 belong to the new face. An iterator to the new face is 
292
    bool precond_flip_edge(const Manifold& m, HalfEdgeID h);
294
				 returned. */
-
 
295
 
293
 
296
			VertexIter split_edge(HalfEdgeIter h);
-
 
297
			/**< Insert a new vertex on halfedge h.
294
    /// Returns true if the halfedge is a boundary halfedge.
298
				 The new halfedge is insterted as the previous edge to h.
295
    bool boundary(const Manifold& m, HalfEdgeID h);
299
				 An iterator to the inserted vertex is	returned. */
-
 
300
 
296
 
301
			void triangulate(FaceIter f);
-
 
302
			/**< Triangulate a polygonal face by repeatedly calling split_face.
-
 
303
				 Triangulate iteratively splits triangles off a polygon. The first 
297
    /// Return the geometric length of a halfedge.
304
				 triangle split off is the one connecting f->last->vert and
298
    float length(const Manifold& m, HalfEdgeID h);
305
				 f->last->next->next->vert.
-
 
306
			*/
-
 
307
 
299
 
308
			VertexIter safe_triangulate(FaceIter f);
-
 
309
			/**< Triangulate a polygon, f, by inserting a vertex at the barycenter.
-
 
310
				 All vertices in f are connected to the new vertex.				
300
    /// Returns true if the vertex is a boundary vertex.
311
				 The word "safe" means that it is less likely to create flipped
-
 
312
				 triangles than the normal triangulate. On the other hand, it 
-
 
313
				 introduces more vertices and probably makes the triangles more
-
 
314
				 acute. This function simply calls face_insert_point.
301
    bool boundary(const Manifold& m, VertexID v);
315
 
302
 
316
				 The inserted vertex is returned.
303
    /// Compute valency, i.e. number of incident edges.
317
			*/
-
 
-
 
304
    int valency(const Manifold& m, VertexID v);
318
 
305
 
319
			void face_insert_point(FaceIter f, VertexIter v);
-
 
320
			/**< Insert a new vertex, v, in a face, f.
-
 
321
				 This operation splits an N-gon into N triangles.
-
 
322
				 In the current implementation the original face is erased. 
306
    /// Compute the vertex normal. This function computes the angle weighted sum of incident face normals.
323
				 This means that the iterator is not valid after the function
307
    Manifold::Vec normal(const Manifold& m, VertexID v);
324
				 returns. 
-
 
325
			*/
-
 
326
 
308
 
327
			bool merge_faces(FaceIter f, HalfEdgeIter h);
-
 
328
			/**< Merges two faces into a single polygon. The first face is f.  The
-
 
329
				 second face is adjacent to f along the halfedge h. This function
-
 
330
				 returns true if the merging was possible and false
309
    /// Returns true if the two argument vertices are in each other's one-rings.
331
				 otherwise. Currently merge only fails if the mesh is already
-
 
332
				 illegal. Thus it should, in fact, never fail. */
-
 
333
 
-
 
334
			bool flip(HalfEdgeIter h);
-
 
335
			/**< Flip an edge h. Returns false if flipping cannot be performed.
-
 
336
				 This is either because one of the two adjacent faces is not
-
 
337
				 a triangle, or because either end point has valency three or
-
 
338
				 because the vertices that will be connected already are. */
-
 
339
 
-
 
340
			void get_bbox(CGLA::Vec3f& pmin, CGLA::Vec3f& pmax);
-
 
341
			/**< Return the bounding box of the manifold. The arguments pmin and pmax
-
 
342
				 will contain the extreme corners of the box when the function 
310
    bool connected(const Manifold& m, VertexID v0, VertexID v1);
343
				 returns.	*/
-
 
344
 
-
 
345
			void get_bsphere(CGLA::Vec3f& c, float& r);
-
 
346
			/**< Get a bounding sphere. When the function returns, c contains the
-
 
347
				 centre and r the radius. */ 
-
 
348
		};
-
 
349
			
311
 
-
 
312
    /// Compute the number of edges of a face
-
 
313
    int no_edges(const Manifold& m, FaceID f);
350
 
314
 
-
 
315
    /** Compute the normal of a face. If the face is not a triangle,
351
	inline HalfEdgeIter Manifold::halfedges_begin() 
316
    the normal is not defined, but computed using the first three
352
		{
-
 
353
			return halfedge_db.begin();
317
    vertices of the face. */
354
		}
-
 
-
 
318
    Manifold::Vec normal(const Manifold& m, FaceID f);
355
	
319
 
356
	inline HalfEdgeIter Manifold::halfedges_end() 
320
    /// Compute the area of a face. 
357
		{
-
 
358
			return halfedge_db.end(); 
321
    float area(const Manifold& m, FaceID f);
359
		}
-
 
360
 
322
 
361
	inline VertexIter Manifold::vertices_begin() 
323
    /// Compute the perimeter of a face. 
362
		{
-
 
363
			return vertex_db.begin();
324
    float perimeter(const Manifold& m, FaceID f);
364
		}
-
 
365
 
325
 
366
	inline VertexIter Manifold::vertices_end()
326
    /// Compute the centre of a face
367
		{
-
 
368
			return vertex_db.end(); 
327
    Manifold::Vec centre(const Manifold& m, FaceID f);
369
		}
-
 
370
 
328
 
371
	inline FaceIter Manifold::faces_begin()
329
    /*******************************************************************
372
		{
-
 
373
			return face_db.begin();	
330
    * Manifold code
374
		}
-
 
-
 
331
    *******************************************************************/
375
 
332
 
376
	inline FaceIter Manifold::faces_end() 
333
    inline Manifold::Manifold(){}
377
		{ 
-
 
378
			return face_db.end(); 
-
 
379
		}
-
 
380
 
334
 
381
	inline VertexIter Manifold::create_vertex(const CGLA::Vec3f& pos)
335
    inline Manifold::Vec& Manifold::pos(VertexID id)
382
		{
336
    { return positions[id]; }
383
			vertex_db.push_back(Vertex(pos));
337
    inline const Manifold::Vec& Manifold::pos(VertexID id) const
384
			return --vertex_db.end();
338
    { return positions[id]; }
385
		}
-
 
386
 
339
 
387
	inline FaceIter Manifold::create_face()
-
 
388
		{
-
 
389
			face_db.push_back(Face());
-
 
390
			return --face_db.end();
-
 
391
		}
-
 
392
 
340
 
393
	inline HalfEdgeIter Manifold::create_halfedge()
341
    inline void Manifold::clear()
394
		{
342
    { 
395
			halfedge_db.push_back(HalfEdge());
343
        kernel.clear();
396
			return --halfedge_db.end();
344
        positions.clear();
397
		}
345
    }
398
 
346
 
-
 
347
    inline Walker Manifold::walker(VertexID id) const
-
 
348
    { return Walker(kernel, kernel.out(id)); }
399
	inline void Manifold::delayed_erase()
349
    inline Walker Manifold::walker(FaceID id) const
400
		{
-
 
-
 
350
    { return Walker(kernel, kernel.last(id)); }
-
 
351
    inline Walker Manifold::walker(HalfEdgeID id) const
401
			erase_immediately = false;
352
    { return Walker(kernel, id); }
402
		}
-
 
403
 
353
 
404
	inline void Manifold::immediate_erase()
-
 
405
		{
-
 
406
			erase_immediately = true;
-
 
407
			remove_unused();
-
 
408
		}
-
 
409
 
354
 
410
	inline bool Manifold::is_used(VertexIter v) const
355
    inline void Manifold::cleanup(IDRemap& map)
411
		{
356
    {   
412
			if(v->he == NULL_HALFEDGE_ITER)
357
        kernel.cleanup(map);
413
				return false;
358
        positions.cleanup(map.vmap);
414
			return true;
-
 
415
		}
359
    }
416
 
360
    
417
	inline bool Manifold::is_used(FaceIter f) const
361
    inline void Manifold::cleanup()
418
		{
362
    {
419
			if(f->last == NULL_HALFEDGE_ITER)
-
 
420
				return false;
363
        IDRemap map;
421
			return true;
364
        Manifold::cleanup(map);
422
		}
365
    }
423
 
-
 
424
	inline bool Manifold::is_used(HalfEdgeIter h) const
-
 
425
		{
-
 
426
			if(h->vert == NULL_VERTEX_ITER)
-
 
427
				return false;
-
 
428
			return true;
-
 
429
		}
366
}
430
 
367
 
431
 
368
 
432
}
-
 
433
#endif
369
#endif