Subversion Repositories gelsvn

Rev

Rev 158 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
39 bj 1
#ifndef __MANIFOLD_H
2
#define __MANIFOLD_H
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. */
155 jab 22
	class Manifold
158 jab 23
		{
24
			std::list<Vertex> vertex_db;
25
			std::list<Face> face_db;
26
			std::list<HalfEdge> halfedge_db;
39 bj 27
 
158 jab 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
 
158 jab 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
 
158 jab 38
			Manifold(const Manifold&) {}
159 jab 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.		*/
158 jab 47
 
48
			const Manifold& operator=(const Manifold&) {return *this;}
159 jab 49
			/**< Empty assignment operator.
50
				 The assignment operator is private for the same reason that the
51
				 copy constructor is private. */
158 jab 52
 
39 bj 53
		public:
54
 
159 jab 55
 
158 jab 56
			Manifold(): erase_immediately(true) {}
159 jab 57
			///< Construct an empty manifold.
39 bj 58
 
159 jab 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
 
159 jab 65
			void enumerate_vertices();
66
			/**< Give each vertex a unique id corresponding to its iterator
67
				 position */
39 bj 68
 
159 jab 69
			void enumerate_halfedges();
70
			/**< Give each halfedge a unique id corresponding to its iterator
71
				 position */
72
 
73
			void enumerate_faces();
74
			/**< Give each face a unique id corresponding to its iterator
75
				 position */
76
 
158 jab 77
			size_t no_faces() const {return face_db.size();}
159 jab 78
			///< Return the number of faces.
39 bj 79
 
158 jab 80
			size_t no_halfedges() const {return halfedge_db.size();}
159 jab 81
			///< Return the number of halfedges.
39 bj 82
 
158 jab 83
			size_t no_vertices() const {return vertex_db.size();}
159 jab 84
			///< Return the number of vertices
39 bj 85
 
159 jab 86
			VertexIter create_vertex(const CGLA::Vec3f& pos);
87
			///< Create a new vertex.
39 bj 88
 
159 jab 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
 
159 jab 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
 
158 jab 98
			void clear();
159 jab 99
			///< Clear the manifold, removing all data.
39 bj 100
 
158 jab 101
			void remove_unused();
159 jab 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
 
159 jab 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
 
159 jab 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
 
159 jab 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.
158 jab 128
			*/
39 bj 129
 
159 jab 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.
39 bj 135
 
159 jab 136
				 See delayed_erase for more details, and note that
137
				 immediate_erase is the default mode.  */
113 jab 138
 
159 jab 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. */
136 jab 143
 
159 jab 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
 
159 jab 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
 
159 jab 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. 
158 jab 160
 
159 jab 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.
158 jab 167
			*/
113 jab 168
 
159 jab 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
 
159 jab 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.
158 jab 183
			*/
113 jab 184
 
185
 
159 jab 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. 
113 jab 195
 
159 jab 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.
158 jab 202
			*/
113 jab 203
 
159 jab 204
			HalfEdgeIter halfedges_begin();
205
			///< Return iterator pointing to the first halfedge.
136 jab 206
 
159 jab 207
			HalfEdgeIter halfedges_end();
208
			///< Return iterator pointing to beyond the last halfedge.
133 jab 209
 
159 jab 210
			VertexIter vertices_begin();
211
			///< Return iterator pointing to the first vertex.
39 bj 212
 
159 jab 213
			VertexIter vertices_end();
214
			///< Return iterator pointing to beyond the last vertex.
39 bj 215
 
159 jab 216
			FaceIter faces_begin();
217
			///< Return iterator pointing to the first face.
39 bj 218
 
159 jab 219
			FaceIter faces_end();
220
			///< Return iterator pointing to beyond the last face.
39 bj 221
 
159 jab 222
			bool collapse_precond(HalfEdgeIter h);
223
			/**< \brief HalfEdge collapse precondition.
136 jab 224
 
158 jab 225
			The argument h is the halfedge we want to collapse. 
39 bj 226
 
158 jab 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
 
158 jab 231
			The test is as follows.
39 bj 232
 
158 jab 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
 
158 jab 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
 
158 jab 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
 
158 jab 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
 
158 jab 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.
39 bj 263
 
158 jab 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.	*/
39 bj 269
 
158 jab 270
 
159 jab 271
			void collapse_halfedge(HalfEdgeIter h, bool=false);
272
			/**< Collapse the halfedge h.
273
 
158 jab 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);
159 jab 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. */
158 jab 295
 
159 jab 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. */
158 jab 300
 
159 jab 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.
158 jab 306
			*/
307
 
159 jab 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.
158 jab 315
 
159 jab 316
				 The inserted vertex is returned.
158 jab 317
			*/
318
 
159 jab 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. 
158 jab 325
			*/
326
 
327
			bool merge_faces(FaceIter f, HalfEdgeIter h);
159 jab 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. */
158 jab 333
 
334
			bool flip(HalfEdgeIter h);
159 jab 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. */
158 jab 339
 
159 jab 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.	*/
158 jab 344
 
159 jab 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
 
158 jab 350
 
159 jab 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
		}
158 jab 360
 
159 jab 361
	inline VertexIter Manifold::vertices_begin() 
362
		{
363
			return vertex_db.begin();
364
		}
158 jab 365
 
159 jab 366
	inline VertexIter Manifold::vertices_end()
367
		{
368
			return vertex_db.end(); 
369
		}
158 jab 370
 
159 jab 371
	inline FaceIter Manifold::faces_begin()
372
		{
373
			return face_db.begin();	
374
		}
158 jab 375
 
159 jab 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