Subversion Repositories gelsvn

Rev

Rev 113 | Rev 136 | Go to most recent revision | 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. */
22
	struct Manifold
23
	{
24
		std::list<Vertex> vertex_db;
25
		std::list<Face> face_db;
26
		std::list<HalfEdge> halfedge_db;
27
 
89 jab 28
		/** Remove a face if it contains only two edges.
133 jab 29
				This is an auxiliary function called from collapse_halfedge. */
39 bj 30
		void remove_face_if_degenerate(HalfEdgeIter fi);
31
 
89 jab 32
		/** Empty copy constructor.
133 jab 33
				Copying a manifold will not work, since faces, vertices, and
39 bj 34
				halfedges contain iterators pointing to other faces, vertices,
35
				and halfedges. These pointers would need to be changed if the 
36
				mesh were copied. In other words, we would need to walk the
37
				entire mesh. This may be required but it should not be an 
38
				operation that is easily invoked by calling the copy constructor.
39
				Hence, this operator is made private.		*/
40
		Manifold(const Manifold& m2) {}
41
 
89 jab 42
		/** Empty assignment operator.
133 jab 43
				The assignment operator is private for the same reason that the
39 bj 44
				copy constructor is private. */
45
		const Manifold& operator=(const Manifold& m2) {}
46
 
47
		public:
48
 
49
		/// Construct an empty manifold.
50
		Manifold() {}
51
 
52
		/// Return the bounding box of the manifold.
53
		void get_bbox(CGLA::Vec3f&, CGLA::Vec3f&);
54
 
55
		/// Get a bounding sphere
56
    void get_bsphere(CGLA::Vec3f& c, float& r);
57
 
58
		/// Clear the manifold - removing all data.
59
		void clear()
60
		{
61
			vertex_db.clear();
62
			face_db.clear();
63
			halfedge_db.clear();
64
		}
65
 
66
		/// Return the number of faces.
67
		int no_faces() const {return face_db.size();}
68
 
69
		/// Return the number of halfedges.
70
		int no_halfedges() const {return halfedge_db.size();}
71
 
72
		/// Return the number of vertices
73
		int no_vertices() const {return vertex_db.size();}
74
 
75
		/// Create a new vertex at a given position.
76
		VertexIter create_vertex(const CGLA::Vec3f& pos)
77
		{
78
			vertex_db.push_back(Vertex(pos));
79
			return --vertex_db.end();
80
		}
81
 
82
		/// Create a new face 
83
		FaceIter create_face()
84
		{
85
			face_db.push_back(Face());
86
			return --face_db.end();
87
		}
88
 
89
		/// Create a new halfedge.
90
		HalfEdgeIter create_halfedge()
91
		{
92
			halfedge_db.push_back(HalfEdge());
93
			return --halfedge_db.end();
94
		}
95
 
96
		/// Erase halfedge. Assumes it is safe to do so. Use with care.
97
		void erase_halfedge(HalfEdgeIter he)
98
		{
99
			halfedge_db.erase(he);
100
		}
101
 
102
		/// Erase vertex. Assumes it is safe to do so. Use with care.
103
		void erase_vertex(VertexIter v)
104
		{
105
			vertex_db.erase(v);
106
		}
107
 
108
		/// Erase face. Assumes it is safe to do so. Use with care.
109
		void erase_face(FaceIter f)
110
		{
111
			face_db.erase(f);
112
		}
113
 
114
		/// Return iterator pointing to the first halfedge.
115
		HalfEdgeIter halfedges_begin() { return halfedge_db.begin();}
116
 
117
		/// Return iterator pointing to beyond the last halfedge.
118
		HalfEdgeIter halfedges_end() { return halfedge_db.end(); }
119
 
120
		/// Return iterator pointing to the first vertex.
121
		VertexIter vertices_begin() { return vertex_db.begin();}
122
 
123
		/// Return iterator pointing to beyond the last vertex.
124
		VertexIter vertices_end() { return vertex_db.end(); }
125
 
126
		/// Return iterator pointing to the first face.
127
		FaceIter faces_begin() { return face_db.begin();	}
128
 
129
		/// Return iterator pointing to beyond the last face.
130
		FaceIter faces_end() { return face_db.end(); }
131
 
113 jab 132
		/** \brief HalfEdge collapse precondition. 
133
 
39 bj 134
				If this function does not return true, it is illegal to collapse
135
				the halfedge given as second arg. The reason is that the collapse
113 jab 136
				would violate the manifold property of the mesh.
137
 
138
				The test is as follows.
139
 
140
				1. For the two vertices adjacent to the edge, we generate
141
				a list of all their neighbouring vertices. We then generate a 
142
				list of the vertices that occur in both these lists. That is, 
143
				we find all vertices connected by edges to both endpoints
144
				of the edge and store these in a list.
145
 
146
				2. For both faces incident on the edge, check whether they
147
				are triangular. If this is the case, the face will be removed,
148
				and it is ok that the the third vertex is connected to both 
149
				endpoints. Thus the third vertex in such a face is removed
150
				from the list generated in 1.
151
 
152
				3. If the list is now empty, all is well. Otherwise, there
153
				would be a vertex in the new mesh with two edges connecting
154
				it to the same vertex. Return false.
155
 
156
				4. TETRAHEDRON TEST:
157
				If the valency of both vertices is 
158
				three, and the incident faces are triangles, we also disallow
159
				the operation. Reason: It introduces a vertex of valency two
160
				and if the final two polygons incident on the vertices 
161
				that are adjacent to the edge being collapsed are triangles, then
162
				the construction will collapse
163
 
164
				5. VALENCY 4 TEST:
165
				If a face adjacent to the edge being collapsed is a triangle,
166
				it will disappear, and the valency of the final vertex beloning to
167
				this edge will be reduced by one. Hence this valency should be at
168
				least 4. A valency three vertex will be reduced to a valency two
169
				vertex which is considered illegal.
170
 
171
				6. PREVENT MERGING HOLES:
172
				We do not want to collapse an edge if its end points are boundary
173
				vertices, but its two adjacent faces are not NULL faces, because
174
				in that case we create a vertex where two holes meet. A non manifold
175
				situation.	*/
39 bj 176
		bool collapse_precond(VertexIter, HalfEdgeIter);
177
 
113 jab 178
		/** Collapse the halfedge given as second argument. 
133 jab 179
				The first argument is the vertex that is being removed. The
180
				second is a halfedge pointing away from that vertex.
113 jab 181
 
133 jab 182
				The final argument is a boolean indicating whether the vertex
183
				that survives the collapse should have a position which is the
184
				average of its own position and the vertex that is removed.
185
				By default false.
186
 
187
				This function is not guaranteed to keep the mesh sane unless,
188
				collapse_precond has returned true.
189
		*/
39 bj 190
		void collapse_halfedge(VertexIter, HalfEdgeIter, bool=false);
191
 
133 jab 192
		/** Split a face.
193
		    The face given as first argument is split by connecting two
194
				vertices (the next two arguments). */
39 bj 195
		FaceIter split_face(FaceIter, VertexIter, VertexIter);
196
 
133 jab 197
		/** Insert a new vertex on the halfedge given as argument.
198
				The new halfedge is insterted as the previous edge to the one
199
				given as argument.
200
		*/
39 bj 201
		VertexIter Manifold::split_edge(HalfEdgeIter h);
202
 
133 jab 203
		/** Triangulate a polygonal face by repeatedly calling split_face. 
204
				Triangulate iteratively splits triangles off a polygon. The first 
205
				triangle split off is the one connecting f->last->vert and
206
				f->last->next->next->vert.
207
		*/
39 bj 208
		void triangulate(FaceIter);
209
 
210
		/** Triangulate a polygon by inserting a vertex at the barycenter and 
133 jab 211
				connecting all vertices to this vertex. 
212
 
213
				The word "safe" means that it is less likely to create flipped
214
				triangles than the normal triangulate. On the other hand, it 
215
				introduces more vertices and probably makes the triangles more
216
				acute.
217
 
218
				This function simply calls face_insert_point.
219
		*/
39 bj 220
		VertexIter safe_triangulate(FaceIter f);
221
 
222
		/** Insert a new vertex (second arg.) in a face (first arg.).
133 jab 223
				This operation splits an N-gon into N triangles.
224
				In the current implementation the original face is erased. 
225
				This means that the iterator is not valid after the function
226
				returns. 
227
		*/
39 bj 228
		void face_insert_point(FaceIter f, VertexIter);
229
 
230
		/** Merges two faces into a single polygon. The first face is the first
231
				argument. The second face is adjacent to the first along the
232
				halfedge given as second argument. */
233
		bool merge_faces(FaceIter f, HalfEdgeIter h);
234
 
133 jab 235
		/** Flip an edge. Returns false if flipping cannot be performed.
39 bj 236
				This is either because one of the two adjacent faces is not
237
				a triangle, or because either end point has valency three or
238
				because the vertices that will be connected already are. */
239
		bool flip(HalfEdgeIter);
240
 
241
		/** Performs a series of tests to check that this is a valid manifold.
242
				This function is not rigorously constructed but seems to catch
243
				all problems so far. */
244
		bool is_valid();
245
 
246
		/** Give each vertex a unique id corresponding to its iterator 
247
				position */
248
		void enumerate_vertices();
249
 
250
		/** Give each halfedge a unique id corresponding to its iterator 
251
				position */
252
		void enumerate_halfedges();
253
 
254
		/** Give each face a unique id corresponding to its iterator 
255
				position */
256
		void enumerate_faces();
257
 
258
	};
259
 
260
 
261
}
262
#endif