Subversion Repositories gelsvn

Rev

Rev 336 | Rev 600 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
448 jab 1
#ifndef __HMESH_MANIFOLD_H
2
#define __HMESH_MANIFOLD_H
39 bj 3
 
4
#include <vector>
5
#include <list>
6
#include <map>
7
 
8
#include "Vertex.h"
9
#include "HalfEdge.h"
10
#include "Face.h"
11
 
12
namespace HMesh
13
{
14
	class VertexCirculator;
15
	class FaceCirculator;
16
 
89 jab 17
	/** \brief A Data structure representing an open or closed manifold.
39 bj 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. */
178 bj 22
	class Manifold
23
		{
24
			std::list<Vertex> vertex_db;
25
			std::list<Face> face_db;
26
			std::list<HalfEdge> halfedge_db;
39 bj 27
 
178 bj 28
			bool erase_immediately;
29
			std::vector<VertexIter> unused_vertices;
30
			std::vector<FaceIter> unused_faces;
31
			std::vector<HalfEdgeIter> unused_halfedges;
39 bj 32
 
33
 
178 bj 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);
39 bj 37
 
178 bj 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
 
39 bj 53
		public:
54
 
55
 
178 bj 56
			Manifold(): erase_immediately(true) {}
57
			///< Construct an empty manifold.
39 bj 58
 
178 bj 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.	*/
39 bj 64
 
178 bj 65
			void enumerate_vertices();
66
			/**< Give each vertex a unique id corresponding to its iterator
336 jab 67
				 position. Value is stored in the touched attribute. */
39 bj 68
 
178 bj 69
			void enumerate_halfedges();
70
			/**< Give each halfedge a unique id corresponding to its iterator
336 jab 71
				 position. Value is stored in the touched attribute. */
39 bj 72
 
178 bj 73
			void enumerate_faces();
74
			/**< Give each face a unique id corresponding to its iterator
336 jab 75
				 position. Value is stored in the touched attribute. */
76
 
178 bj 77
			size_t no_faces() const {return face_db.size();}
78
			///< Return the number of faces.
39 bj 79
 
178 bj 80
			size_t no_halfedges() const {return halfedge_db.size();}
81
			///< Return the number of halfedges.
39 bj 82
 
178 bj 83
			size_t no_vertices() const {return vertex_db.size();}
84
			///< Return the number of vertices
39 bj 85
 
178 bj 86
			VertexIter create_vertex(const CGLA::Vec3f& pos);
87
			///< Create a new vertex.
39 bj 88
 
178 bj 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. */
39 bj 93
 
178 bj 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. */
39 bj 97
 
178 bj 98
			void clear();
99
			///< Clear the manifold, removing all data.
39 bj 100
 
178 bj 101
			void remove_unused();
102
			/**< Remove unused vertices, edges and faces from the database.
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. */
39 bj 106
 
178 bj 107
			void delayed_erase();
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.
39 bj 118
 
178 bj 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).
39 bj 122
 
178 bj 123
				 When remove_unused is called, the physical removal takes
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.
128
			*/
113 jab 129
 
178 bj 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
134
				 function is called.
136 jab 135
 
178 bj 136
				 See delayed_erase for more details, and note that
137
				 immediate_erase is the default mode.  */
113 jab 138
 
178 bj 139
			bool is_used(VertexIter v) 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 
142
				 valid outgoing halfedge iterator. */
113 jab 143
 
178 bj 144
			bool is_used(FaceIter f) 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. */
113 jab 148
 
178 bj 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 
152
				 valid vertex iterator. */
113 jab 153
 
178 bj 154
			void erase_halfedge(HalfEdgeIter h);			
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
			*/
113 jab 168
 
178 bj 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. 
113 jab 176
 
178 bj 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
			*/
113 jab 184
 
185
 
178 bj 186
			void erase_face(FaceIter f);
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. 
136 jab 195
 
178 bj 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
			*/
133 jab 203
 
178 bj 204
			HalfEdgeIter halfedges_begin();
205
			///< Return iterator pointing to the first halfedge.
39 bj 206
 
178 bj 207
			HalfEdgeIter halfedges_end();
208
			///< Return iterator pointing to beyond the last halfedge.
39 bj 209
 
178 bj 210
			VertexIter vertices_begin();
211
			///< Return iterator pointing to the first vertex.
39 bj 212
 
178 bj 213
			VertexIter vertices_end();
214
			///< Return iterator pointing to beyond the last vertex.
39 bj 215
 
178 bj 216
			FaceIter faces_begin();
217
			///< Return iterator pointing to the first face.
136 jab 218
 
178 bj 219
			FaceIter faces_end();
220
			///< Return iterator pointing to beyond the last face.
39 bj 221
 
178 bj 222
			bool collapse_precond(HalfEdgeIter h);
223
			/**< \brief HalfEdge collapse precondition.
39 bj 224
 
178 bj 225
			The argument h is the halfedge we want to collapse. 
39 bj 226
 
178 bj 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.
39 bj 230
 
178 bj 231
			The test is as follows.
39 bj 232
 
178 bj 233
			1. For the two vertices adjacent to the edge, we generate
234
			a list of all their neighbouring vertices. We then generate a 
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.
39 bj 238
 
178 bj 239
			2. For both faces incident on the edge, check whether they
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.
39 bj 244
 
178 bj 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.
39 bj 248
 
178 bj 249
			4. TETRAHEDRON TEST:
250
			If the valency of both vertices is 
251
			three, and the incident faces are triangles, we also disallow
252
			the operation. Reason: It introduces a vertex of valency two
253
			and if the final two polygons incident on the vertices 
254
			that are adjacent to the edge being collapsed are triangles, then
255
			the construction will collapse
39 bj 256
 
178 bj 257
			5. VALENCY 4 TEST:
258
			If a face adjacent to the edge being collapsed is a triangle,
259
			it will disappear, and the valency of the final vertex beloning to
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
262
			vertex which is considered illegal.
263
 
264
			6. PREVENT MERGING HOLES:
265
			We do not want to collapse an edge if its end points are boundary
266
			vertices, but its two adjacent faces are not NULL faces, because
267
			in that case we create a vertex where two holes meet. A non manifold
268
			situation.	*/
269
 
270
 
271
			void collapse_halfedge(HalfEdgeIter h, bool=false);
272
			/**< Collapse the halfedge h.
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
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
 
283
			This function is not guaranteed to keep the mesh sane unless,
284
			collapse_precond has returned true !!
285
			*/
286
 
287
			FaceIter split_face(FaceIter f, VertexIter v0, VertexIter v1);
288
			/**< Split a face.
289
				 The face, f, is split by connecting two
290
				 vertices v0 and v1 (the next two arguments). The vertices of
291
				 the old face between v0 and v1 (in counter clockwise order) 
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 
294
				 returned. */
295
 
296
			VertexIter split_edge(HalfEdgeIter h);
297
			/**< Insert a new vertex on halfedge h.
298
				 The new halfedge is insterted as the previous edge to h.
299
				 An iterator to the inserted vertex is	returned. */
300
 
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 
304
				 triangle split off is the one connecting f->last->vert and
305
				 f->last->next->next->vert.
306
			*/
307
 
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.				
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.
315
 
316
				 The inserted vertex is returned.
317
			*/
318
 
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. 
323
				 This means that the iterator is not valid after the function
324
				 returns. 
325
			*/
326
 
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
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 
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
 
350
 
351
	inline HalfEdgeIter Manifold::halfedges_begin() 
352
		{
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
 
431
 
39 bj 432
}
433
#endif