Subversion Repositories gelsvn

Rev

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