Subversion Repositories gelsvn

Rev

Rev 155 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 155 Rev 158
Line 18... Line 18...
18
			Manifold keeps lists of the entities making up a halfedge mesh
18
			Manifold keeps lists of the entities making up a halfedge mesh
19
			and provides basic functions for creating new faces, halfedges
19
			and provides basic functions for creating new faces, halfedges
20
			and vertices. There are also primitive operations for editing 
20
			and vertices. There are also primitive operations for editing 
21
			such as edge collapse. */
21
			such as edge collapse. */
22
	class Manifold
22
	class Manifold
23
	{
-
 
24
		std::list<Vertex> vertex_db;
-
 
25
		std::list<Face> face_db;
-
 
26
		std::list<HalfEdge> halfedge_db;
-
 
27
 
-
 
28
		/** Remove a face if it contains only two edges.
-
 
29
				This is an auxiliary function called from collapse_halfedge. */
-
 
30
		void remove_face_if_degenerate(HalfEdgeIter);
-
 
31
 
-
 
32
		/** Empty copy constructor.
-
 
33
				Copying a manifold will not work, since faces, vertices, and
-
 
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&) {}
-
 
41
 
-
 
42
		/** Empty assignment operator.
-
 
43
				The assignment operator is private for the same reason that the
-
 
44
				copy constructor is private. */
-
 
45
		const Manifold& operator=(const Manifold&) {return *this;}
-
 
46
 
-
 
47
		public:
-
 
48
	
-
 
49
		/// Construct an empty manifold.
-
 
50
		Manifold() {}
-
 
51
 
-
 
52
  	/** Return the bounding box of the manifold. The arguments pmin and pmax
-
 
53
				will contain the extreme corners of the box when the function returns.
-
 
54
		 */
-
 
55
		void get_bbox(CGLA::Vec3f& pmin, CGLA::Vec3f& pmax);
-
 
56
 
-
 
57
		/** Get a bounding sphere. When the function returns c contains the 
-
 
58
				centre and r the radius. */ 
-
 
59
    void get_bsphere(CGLA::Vec3f& c, float& r);
-
 
60
 
-
 
61
		/// Clear the manifold - removing all data.
-
 
62
		void clear()
-
 
63
		{
-
 
64
			vertex_db.clear();
-
 
65
			face_db.clear();
-
 
66
			halfedge_db.clear();
-
 
67
		}
-
 
68
 
-
 
69
		/// Return the number of faces.
-
 
70
		size_t no_faces() const {return face_db.size();}
-
 
71
 
-
 
72
		/// Return the number of halfedges.
-
 
73
		size_t no_halfedges() const {return halfedge_db.size();}
-
 
74
 
-
 
75
		/// Return the number of vertices
-
 
76
		size_t no_vertices() const {return vertex_db.size();}
-
 
77
 
-
 
78
		/** Create a new vertex. 
-
 
79
				The argument is the position of the vertex, and the 
-
 
80
				function returns an iterator pointing to the vertex. */
-
 
81
		VertexIter create_vertex(const CGLA::Vec3f& pos)
-
 
82
		{
-
 
83
			vertex_db.push_back(Vertex(pos));
-
 
84
			return --vertex_db.end();
-
 
85
		}
-
 
86
 
-
 
87
		/** Create a new face. 
-
 
88
				An iterator to the face is returned. */
-
 
89
		FaceIter create_face()
-
 
90
		{
23
		{
-
 
24
			std::list<Vertex> vertex_db;
91
			face_db.push_back(Face());
25
			std::list<Face> face_db;
-
 
26
			std::list<HalfEdge> halfedge_db;
-
 
27
 
92
			return --face_db.end();
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
			/** Empty copy constructor.
-
 
39
					Copying a manifold will not work, since faces, vertices, and
-
 
40
					halfedges contain iterators pointing to other faces, vertices,
-
 
41
					and halfedges. These pointers would need to be changed if the 
-
 
42
					mesh were copied. In other words, we would need to walk the
-
 
43
					entire mesh. This may be required but it should not be an 
-
 
44
					operation that is easily invoked by calling the copy constructor.
-
 
45
					Hence, this operator is made private.		*/
-
 
46
			Manifold(const Manifold&) {}
93
		}
47
 
-
 
48
			/** Empty assignment operator.
-
 
49
					The assignment operator is private for the same reason that the
-
 
50
					copy constructor is private. */
-
 
51
			const Manifold& operator=(const Manifold&) {return *this;}
94
 
52
 
95
  	/** Create a new halfedge. An iterator to the halfedge is returned. */
-
 
96
		HalfEdgeIter create_halfedge()
-
 
97
		{
-
 
98
			halfedge_db.push_back(HalfEdge());
-
 
99
			return --halfedge_db.end();
-
 
100
		}
53
		public:
101
 
-
 
102
		/** Erase halfedge h. 
-
 
103
				In general, you should never call this function but use the 
-
 
104
				collapse_halfedge function instead since blindly erasing geometry
-
 
105
				is most likely to invalidate the Mesh. Quite possibly this function
-
 
106
				will be removed from the public interface. */
-
 
107
		void erase_halfedge(HalfEdgeIter h)
-
 
108
		{
-
 
109
			halfedge_db.erase(h);
-
 
110
		}
-
 
111
 
54
 
112
		/** Erase vertex v.
-
 
113
				In general, you should never call this function but use the 
-
 
114
				collapse_halfedge function to collapse the vertex away.
-
 
115
				Blindly erasing is extremely likely to invalidate the
-
 
116
				Mesh. Quite possibly this function will be removed from the
-
 
117
				public interface. */
-
 
118
		void erase_vertex(VertexIter v)
-
 
119
		{
-
 
120
			vertex_db.erase(v);
-
 
121
		}
-
 
122
	
-
 
123
		/** Erase face f. 
-
 
124
				In general, you should never call this function but use 
-
 
125
				collapse_halfedge in conjunction with other functions to
-
 
126
				remove the face through (Euler) operations which preserve
-
 
127
				the mesh in a valid state.
55
			/// Construct an empty manifold.
128
				Blindly erasing is extremely likely to invalidate the
-
 
129
				Mesh. Quite possibly this function will be removed from the
-
 
130
				public interface. */
-
 
131
		void erase_face(FaceIter f)
56
			Manifold(): erase_immediately(true) {}
132
		{
-
 
133
			face_db.erase(f);
-
 
134
		}
-
 
135
 
57
 
-
 
58
			/** Return the bounding box of the manifold. The arguments pmin and pmax
-
 
59
					will contain the extreme corners of the box when the function 
-
 
60
					returns.	*/
-
 
61
			void get_bbox(CGLA::Vec3f& pmin, CGLA::Vec3f& pmax);
-
 
62
 
-
 
63
			/** Get a bounding sphere. When the function returns c contains the
-
 
64
					centre and r the radius. */ 
-
 
65
			void get_bsphere(CGLA::Vec3f& c, float& r);
-
 
66
 
-
 
67
			/// Return the number of faces.
-
 
68
			size_t no_faces() const {return face_db.size();}
-
 
69
 
-
 
70
			/// Return the number of halfedges.
-
 
71
			size_t no_halfedges() const {return halfedge_db.size();}
-
 
72
 
-
 
73
			/// Return the number of vertices
-
 
74
			size_t no_vertices() const {return vertex_db.size();}
-
 
75
 
-
 
76
			/** Create a new vertex.
-
 
77
					The argument is the position of the vertex, and the 
-
 
78
					function returns an iterator pointing to the vertex.
-
 
79
					When a vertex v is initially created, is_used(v) will
-
 
80
					return false.
-
 
81
			*/
-
 
82
			VertexIter create_vertex(const CGLA::Vec3f& pos)
-
 
83
				{
-
 
84
					vertex_db.push_back(Vertex(pos));
-
 
85
					return --vertex_db.end();
-
 
86
				}
-
 
87
 
-
 
88
			/** Create a new face.
-
 
89
					An iterator to the face is returned. When a face f is initially
-
 
90
					created, is_used(f) will return false. */
-
 
91
			FaceIter create_face()
-
 
92
				{
-
 
93
					face_db.push_back(Face());
-
 
94
					return --face_db.end();
-
 
95
				}
-
 
96
 
-
 
97
			/** Create a new halfedge. An iterator to the halfedge is returned.
-
 
98
					When h is initially created, is_used(h) returns false. */
-
 
99
			HalfEdgeIter create_halfedge()
-
 
100
				{
-
 
101
					halfedge_db.push_back(HalfEdge());
-
 
102
					return --halfedge_db.end();
-
 
103
				}
-
 
104
 
-
 
105
			/// Clear the manifold - removing all data.
-
 
106
			void clear();
-
 
107
 
-
 
108
			/** Remove unused vertices, edges and faces from the database.
-
 
109
					If delayed_erase mode is enabled, then until this function 
-
 
110
					has been called, erased vertices, edges, and faces are just marked
-
 
111
					as unused but not removed from their respective lists. */
-
 
112
			void remove_unused();
-
 
113
 
-
 
114
 
-
 
115
			/** Delay the actual removal of vertices, faces, and edges that
-
 
116
					are erased.  In many cases, it is a problem if one cannot
-
 
117
					test whether a vertex, halfedge, or face indicated by an
-
 
118
					iterator is in use or has been removed from the mesh. One
-
 
119
					solution to this problem is to delay the actual removal of
-
 
120
					the vertex, edge or face. Instead when calling, say,
-
 
121
					erase_face(f), all the iterators of f are assigned the
-
 
122
					appropriate NULL value to indicate that they are not
-
 
123
					pointing at anything, and f is added to a vector of faces
-
 
124
					that need to be physically removed from the face_db.
-
 
125
 
-
 
126
					Since f is not erased, all iterators pointing at f remain
-
 
127
					valid! And, importantly, it is possible to test whether f is
-
 
128
					in use by calling is_used(f).
-
 
129
 
-
 
130
					When remove_unused is called, the physical removal takes
-
 
131
					place. Calling immediate_erase switches Manifold back to the
-
 
132
					state where entities are removed as soon as the appropriate
-
 
133
					erase function is called, and at the same time calls
-
 
134
					remove_unused.
-
 
135
			*/
-
 
136
			void delayed_erase()
-
 
137
				{
-
 
138
					erase_immediately = false;
-
 
139
				}
-
 
140
 
-
 
141
			/** Immediately remove erased entities.
-
 
142
					Calling immediate_erase switches Manifold back to the state
-
 
143
					where entities are removed as soon as the appropriate erase
-
 
144
					function is called.
-
 
145
 
-
 
146
					See delayed_erase for more details, and note that
-
 
147
					immediate_erase is the default mode.  */
-
 
148
			void immediate_erase()
-
 
149
				{
-
 
150
					erase_immediately = true;
-
 
151
					remove_unused();
-
 
152
				}
-
 
153
 
-
 
154
			/** Test whether the vertex indicated by the argument v is used.
-
 
155
					This function returns true if the vertex appears to have a 
-
 
156
					valid outgoing halfedge iterator. */
-
 
157
			bool is_used(VertexIter v) const
-
 
158
				{
-
 
159
					if(v->he == NULL_HALFEDGE_ITER)
-
 
160
						return false;
-
 
161
					return true;
-
 
162
				}
-
 
163
 
-
 
164
			/** Test whether the face indicated by the argument f is used.
-
 
165
					This function returns true if the face appears to have a 
-
 
166
					valid halfedge iterator. */
-
 
167
			bool is_used(FaceIter f) const
-
 
168
				{
-
 
169
					if(f->last == NULL_HALFEDGE_ITER)
-
 
170
						return false;
-
 
171
					return true;
-
 
172
				}
-
 
173
 
-
 
174
			/** Test whether the halfedge indicated by the argument h is used.
-
 
175
					This function returns true if the halfedge appears to have a 
-
 
176
					valid vertex iterator. */
-
 
177
			bool is_used(HalfEdgeIter h) const
-
 
178
				{
-
 
179
					if(h->vert == NULL_VERTEX_ITER)
-
 
180
						return false;
-
 
181
					return true;
-
 
182
				}
-
 
183
 
-
 
184
			/** Erase halfedge h. 
-
 
185
					In general, you should never call this function but use the 
-
 
186
					collapse_halfedge function instead since blindly erasing geometry
-
 
187
					is most likely to invalidate the Mesh. Quite possibly this function
-
 
188
					will be removed from the public interface. 
-
 
189
					
-
 
190
					Note that if delayed_erase has been called, this function does
-
 
191
					not immediately remove anything from the mesh. Instead the halfedge
-
 
192
					is reset to its initial state. Thus, iterators are not invalidated,
-
 
193
					and it is possible to test whether h is used calling:
-
 
194
					is_used(h). when remove_unused is called, the actual removal
-
 
195
					takes place.
-
 
196
			*/
-
 
197
			void erase_halfedge(HalfEdgeIter h);
-
 
198
 
-
 
199
			/** Erase vertex v.
-
 
200
					In general, you should never call this function but use the 
-
 
201
					collapse_halfedge function to collapse the vertex away.
-
 
202
					Blindly erasing is extremely likely to invalidate the
-
 
203
					Mesh. Quite possibly this function will be removed from the
-
 
204
					public interface. 
-
 
205
 
-
 
206
					Note that if delayed_erase has been called, this function does
-
 
207
					not immediately remove anything from the mesh. Instead the halfedge
-
 
208
					is reset to its initial state. Thus, iterators are not invalidated,
-
 
209
					and it is possible to test whether v is used calling:
-
 
210
					is_used(v). when remove_unused is called, the actual removal
-
 
211
					takes place.
-
 
212
			*/
-
 
213
			void erase_vertex(VertexIter v);
-
 
214
 
-
 
215
 
-
 
216
			/** Erase face f.
-
 
217
					In general, you should never call this function but use 
-
 
218
					collapse_halfedge in conjunction with other functions to
-
 
219
					remove the face through (Euler) operations which preserve
-
 
220
					the mesh in a valid state.
-
 
221
					Blindly erasing is extremely likely to invalidate the
-
 
222
					Mesh. Quite possibly this function will be removed from the
-
 
223
					public interface. 
-
 
224
 
-
 
225
					Note that if delayed_erase has been called, this function does
-
 
226
					not immediately remove anything from the mesh. Instead the face
-
 
227
					is reset to its initial state. Thus, iterators are not invalidated,
-
 
228
					and it is possible to test whether f is used calling:
-
 
229
					is_used(f). when remove_unused is called, the actual removal
-
 
230
					takes place.
-
 
231
			*/
-
 
232
			void erase_face(FaceIter f);
-
 
233
 
136
		/// Return iterator pointing to the first halfedge.
234
			/// Return iterator pointing to the first halfedge.
137
		HalfEdgeIter halfedges_begin() { return halfedge_db.begin();}
235
			HalfEdgeIter halfedges_begin() { return halfedge_db.begin();}
-
 
236
 
-
 
237
			/// Return iterator pointing to beyond the last halfedge.
-
 
238
			HalfEdgeIter halfedges_end() { return halfedge_db.end(); }
-
 
239
 
-
 
240
			/// Return iterator pointing to the first vertex.
-
 
241
			VertexIter vertices_begin() { return vertex_db.begin();}
-
 
242
 
-
 
243
			/// Return iterator pointing to beyond the last vertex.
-
 
244
			VertexIter vertices_end() { return vertex_db.end(); }
-
 
245
 
-
 
246
			/// Return iterator pointing to the first face.
-
 
247
			FaceIter faces_begin() { return face_db.begin();	}
-
 
248
 
-
 
249
			/// Return iterator pointing to beyond the last face.
-
 
250
			FaceIter faces_end() { return face_db.end(); }
-
 
251
 
-
 
252
			/** \brief HalfEdge collapse precondition.
-
 
253
 
-
 
254
			The argument h is the halfedge we want to collapse. 
-
 
255
 
-
 
256
			If this function does not return true, it is illegal to collapse
-
 
257
			h. The reason is that the collapse would violate the manifold property
-
 
258
			of the mesh.
-
 
259
 
-
 
260
			The test is as follows.
-
 
261
 
-
 
262
			1. For the two vertices adjacent to the edge, we generate
-
 
263
			a list of all their neighbouring vertices. We then generate a 
-
 
264
			list of the vertices that occur in both these lists. That is, 
-
 
265
			we find all vertices connected by edges to both endpoints
-
 
266
			of the edge and store these in a list.
-
 
267
 
-
 
268
			2. For both faces incident on the edge, check whether they
-
 
269
			are triangular. If this is the case, the face will be removed,
-
 
270
			and it is ok that the the third vertex is connected to both 
-
 
271
			endpoints. Thus the third vertex in such a face is removed
-
 
272
			from the list generated in 1.
-
 
273
 
-
 
274
			3. If the list is now empty, all is well. Otherwise, there
-
 
275
			would be a vertex in the new mesh with two edges connecting
-
 
276
			it to the same vertex. Return false.
-
 
277
 
-
 
278
			4. TETRAHEDRON TEST:
-
 
279
			If the valency of both vertices is 
-
 
280
			three, and the incident faces are triangles, we also disallow
-
 
281
			the operation. Reason: It introduces a vertex of valency two
-
 
282
			and if the final two polygons incident on the vertices 
-
 
283
			that are adjacent to the edge being collapsed are triangles, then
-
 
284
			the construction will collapse
-
 
285
 
-
 
286
			5. VALENCY 4 TEST:
-
 
287
			If a face adjacent to the edge being collapsed is a triangle,
-
 
288
			it will disappear, and the valency of the final vertex beloning to
-
 
289
			this edge will be reduced by one. Hence this valency should be at
-
 
290
			least 4. A valency three vertex will be reduced to a valency two
-
 
291
			vertex which is considered illegal.
-
 
292
 
-
 
293
			6. PREVENT MERGING HOLES:
-
 
294
			We do not want to collapse an edge if its end points are boundary
-
 
295
			vertices, but its two adjacent faces are not NULL faces, because
-
 
296
			in that case we create a vertex where two holes meet. A non manifold
-
 
297
			situation.	*/
-
 
298
			bool collapse_precond(HalfEdgeIter h);
-
 
299
 
-
 
300
			/** Collapse the halfedge h.
-
 
301
 
-
 
302
			The argument h is the halfedge being removed. The vertex 
-
 
303
			v=h->opp->vert is the one being removed while h->vert survives.
-
 
304
 
-
 
305
			The final argument is a boolean indicating whether the vertex
-
 
306
			that survives the collapse should have a position which is the
-
 
307
			average of its own position and the vertex that is removed.
-
 
308
			By default false meaning that the surviving vertex retains it 
-
 
309
			position.
-
 
310
 
-
 
311
			This function is not guaranteed to keep the mesh sane unless,
-
 
312
			collapse_precond has returned true !!
-
 
313
			*/
-
 
314
			void collapse_halfedge(HalfEdgeIter h, bool=false);
-
 
315
 
-
 
316
			/** Split a face.
-
 
317
					The face, f, is split by connecting two
-
 
318
					vertices v0 and v1 (the next two arguments). The vertices of
-
 
319
					the old face between v0 and v1 (in counter clockwise order) 
-
 
320
					continue to belong to f. The vertices between v1 and 
-
 
321
					v0 belong to the new face. An iterator to the new face is 
-
 
322
					returned. */
-
 
323
			FaceIter split_face(FaceIter f, VertexIter v0, VertexIter v1);
-
 
324
 
-
 
325
			/** Insert a new vertex on halfedge h.
-
 
326
					The new halfedge is insterted as the previous edge to h.
-
 
327
					An iterator to the inserted vertex is	returned. */
-
 
328
			VertexIter Manifold::split_edge(HalfEdgeIter h);
-
 
329
 
-
 
330
			/** Triangulate a polygonal face by repeatedly calling split_face.
-
 
331
					Triangulate iteratively splits triangles off a polygon. The first 
-
 
332
					triangle split off is the one connecting f->last->vert and
-
 
333
					f->last->next->next->vert.
-
 
334
			*/
-
 
335
			void triangulate(FaceIter f);
-
 
336
 
-
 
337
			/** Triangulate a polygon, f, by inserting a vertex at the barycenter.
-
 
338
					All vertices in f are connected to the new vertex.				
-
 
339
					The word "safe" means that it is less likely to create flipped
-
 
340
					triangles than the normal triangulate. On the other hand, it 
-
 
341
					introduces more vertices and probably makes the triangles more
-
 
342
					acute. This function simply calls face_insert_point.
-
 
343
 
-
 
344
					The inserted vertex is returned.
-
 
345
			*/
-
 
346
			VertexIter safe_triangulate(FaceIter f);
-
 
347
 
-
 
348
			/** Insert a new vertex, v, in a face, f.
-
 
349
					This operation splits an N-gon into N triangles.
-
 
350
					In the current implementation the original face is erased. 
-
 
351
					This means that the iterator is not valid after the function
-
 
352
					returns. 
-
 
353
			*/
-
 
354
			void face_insert_point(FaceIter f, VertexIter v);
-
 
355
 
-
 
356
			/** Merges two faces into a single polygon. The first face is f.  The
-
 
357
					second face is adjacent to f along the halfedge h. This function
-
 
358
					returns true if the merging was possible and false
-
 
359
					otherwise. Currently merge only fails if the mesh is already
-
 
360
					illegal. Thus it should, in fact, never fail. */
-
 
361
			bool merge_faces(FaceIter f, HalfEdgeIter h);
-
 
362
 
-
 
363
			/** Flip an edge h. Returns false if flipping cannot be performed.
-
 
364
					This is either because one of the two adjacent faces is not
-
 
365
					a triangle, or because either end point has valency three or
-
 
366
					because the vertices that will be connected already are. */
-
 
367
			bool flip(HalfEdgeIter h);
-
 
368
 
-
 
369
			/** Performs a series of tests to check that this is a valid manifold.
-
 
370
					This function is not rigorously constructed but seems to catch
-
 
371
					all problems so far. The function returns true if the mesh is 
-
 
372
					valid and false otherwise.
-
 
373
			*/
-
 
374
			bool is_valid();
-
 
375
 
-
 
376
			/** Give each vertex a unique id corresponding to its iterator
-
 
377
					position */
-
 
378
			void enumerate_vertices();
-
 
379
 
-
 
380
			/** Give each halfedge a unique id corresponding to its iterator
-
 
381
					position */
-
 
382
			void enumerate_halfedges();
-
 
383
 
-
 
384
			/** Give each face a unique id corresponding to its iterator
-
 
385
					position */
-
 
386
			void enumerate_faces();
138
 
387
 
139
		/// Return iterator pointing to beyond the last halfedge.
-
 
140
		HalfEdgeIter halfedges_end() { return halfedge_db.end(); }
-
 
141
	
-
 
142
		/// Return iterator pointing to the first vertex.
-
 
143
		VertexIter vertices_begin() { return vertex_db.begin();}
-
 
144
 
-
 
145
		/// Return iterator pointing to beyond the last vertex.
-
 
146
		VertexIter vertices_end() { return vertex_db.end(); }
-
 
147
 
-
 
148
		/// Return iterator pointing to the first face.
-
 
149
		FaceIter faces_begin() { return face_db.begin();	}
-
 
150
 
-
 
151
		/// Return iterator pointing to beyond the last face.
-
 
152
		FaceIter faces_end() { return face_db.end(); }
-
 
153
 
-
 
154
		/** \brief HalfEdge collapse precondition. 
-
 
155
 
-
 
156
		    The argument h is the halfedge we want to collapse. 
-
 
157
 
-
 
158
				If this function does not return true, it is illegal to collapse
-
 
159
				h. The reason is that the collapse would violate the manifold property
-
 
160
				of the mesh.
-
 
161
 
-
 
162
				The test is as follows.
-
 
163
 
-
 
164
				1. For the two vertices adjacent to the edge, we generate
-
 
165
				a list of all their neighbouring vertices. We then generate a 
-
 
166
				list of the vertices that occur in both these lists. That is, 
-
 
167
				we find all vertices connected by edges to both endpoints
-
 
168
				of the edge and store these in a list.
-
 
169
 
-
 
170
				2. For both faces incident on the edge, check whether they
-
 
171
				are triangular. If this is the case, the face will be removed,
-
 
172
				and it is ok that the the third vertex is connected to both 
-
 
173
				endpoints. Thus the third vertex in such a face is removed
-
 
174
				from the list generated in 1.
-
 
175
 
-
 
176
				3. If the list is now empty, all is well. Otherwise, there
-
 
177
				would be a vertex in the new mesh with two edges connecting
-
 
178
				it to the same vertex. Return false.
-
 
179
 
-
 
180
				4. TETRAHEDRON TEST:
-
 
181
				If the valency of both vertices is 
-
 
182
				three, and the incident faces are triangles, we also disallow
-
 
183
				the operation. Reason: It introduces a vertex of valency two
-
 
184
				and if the final two polygons incident on the vertices 
-
 
185
				that are adjacent to the edge being collapsed are triangles, then
-
 
186
				the construction will collapse
-
 
187
 
-
 
188
				5. VALENCY 4 TEST:
-
 
189
				If a face adjacent to the edge being collapsed is a triangle,
-
 
190
				it will disappear, and the valency of the final vertex beloning to
-
 
191
				this edge will be reduced by one. Hence this valency should be at
-
 
192
				least 4. A valency three vertex will be reduced to a valency two
-
 
193
				vertex which is considered illegal.
-
 
194
 
-
 
195
				6. PREVENT MERGING HOLES:
-
 
196
				We do not want to collapse an edge if its end points are boundary
-
 
197
				vertices, but its two adjacent faces are not NULL faces, because
-
 
198
				in that case we create a vertex where two holes meet. A non manifold
-
 
199
				situation.	*/
-
 
200
		bool collapse_precond(HalfEdgeIter h);
-
 
201
		
-
 
202
		/** Collapse the halfedge h.
-
 
203
 
-
 
204
		    The argument h is the halfedge being removed. The vertex 
-
 
205
				v=h->opp->vert is the one being removed while h->vert survives.
-
 
206
 
-
 
207
				The final argument is a boolean indicating whether the vertex
-
 
208
				that survives the collapse should have a position which is the
-
 
209
				average of its own position and the vertex that is removed.
-
 
210
				By default false meaning that the surviving vertex retains it 
-
 
211
				position.
-
 
212
 
-
 
213
				This function is not guaranteed to keep the mesh sane unless,
-
 
214
				collapse_precond has returned true !!
-
 
215
		*/
-
 
216
		void collapse_halfedge(HalfEdgeIter h, bool=false);
-
 
217
 
-
 
218
		/** Split a face.
-
 
219
		    The face, f, is split by connecting two
-
 
220
				vertices v0 and v1 (the next two arguments). The vertices of
-
 
221
				the old face between v0 and v1 (in counter clockwise order) 
-
 
222
				continue to belong to f. The vertices between v1 and 
-
 
223
				v0 belong to the new face. An iterator to the new face is 
-
 
224
				returned. */
-
 
225
		FaceIter split_face(FaceIter f, VertexIter v0, VertexIter v1);
-
 
226
 
-
 
227
		/** Insert a new vertex on halfedge h.
-
 
228
				The new halfedge is insterted as the previous edge to h.
-
 
229
				An iterator to the inserted vertex is	returned. */
-
 
230
		VertexIter Manifold::split_edge(HalfEdgeIter h);
-
 
231
 
-
 
232
		/** Triangulate a polygonal face by repeatedly calling split_face. 
-
 
233
				Triangulate iteratively splits triangles off a polygon. The first 
-
 
234
				triangle split off is the one connecting f->last->vert and
-
 
235
				f->last->next->next->vert.
-
 
236
		*/
-
 
237
		void triangulate(FaceIter f);
-
 
238
 
-
 
239
		/** Triangulate a polygon, f, by inserting a vertex at the barycenter.
-
 
240
				All vertices in f are connected to the new vertex.				
-
 
241
				The word "safe" means that it is less likely to create flipped
-
 
242
				triangles than the normal triangulate. On the other hand, it 
-
 
243
				introduces more vertices and probably makes the triangles more
-
 
244
				acute. This function simply calls face_insert_point.
-
 
245
 
-
 
246
				The inserted vertex is returned.
-
 
247
		*/
-
 
248
		VertexIter safe_triangulate(FaceIter f);
-
 
249
 
-
 
250
		/** Insert a new vertex, v, in a face, f.
-
 
251
				This operation splits an N-gon into N triangles.
-
 
252
				In the current implementation the original face is erased. 
-
 
253
				This means that the iterator is not valid after the function
-
 
254
				returns. 
-
 
255
		*/
-
 
256
		void face_insert_point(FaceIter f, VertexIter v);
-
 
257
 
-
 
258
		/** Merges two faces into a single polygon. The first face is f.  The
-
 
259
				second face is adjacent to f along the halfedge h. This function
-
 
260
				returns true if the merging was possible and false
-
 
261
				otherwise. Currently merge only fails if the mesh is already
-
 
262
				illegal. Thus it should, in fact, never fail. */
-
 
263
		bool merge_faces(FaceIter f, HalfEdgeIter h);
-
 
264
 
-
 
265
		/** Flip an edge h. Returns false if flipping cannot be performed.
-
 
266
				This is either because one of the two adjacent faces is not
-
 
267
				a triangle, or because either end point has valency three or
-
 
268
				because the vertices that will be connected already are. */
-
 
269
		bool flip(HalfEdgeIter h);
-
 
270
 
-
 
271
		/** Performs a series of tests to check that this is a valid manifold.
-
 
272
				This function is not rigorously constructed but seems to catch
-
 
273
				all problems so far. The function returns true if the mesh is 
-
 
274
				valid and false otherwise.
-
 
275
		*/
-
 
276
		bool is_valid();
-
 
277
 
-
 
278
		/** Give each vertex a unique id corresponding to its iterator 
-
 
279
				position */
-
 
280
		void enumerate_vertices();
-
 
281
 
-
 
282
		/** Give each halfedge a unique id corresponding to its iterator 
-
 
283
				position */
-
 
284
		void enumerate_halfedges();
-
 
285
 
-
 
286
		/** Give each face a unique id corresponding to its iterator 
-
 
287
				position */
-
 
288
		void enumerate_faces();
-
 
289
		
-
 
290
	};
388
		};
291
 
389
 
292
 
390
 
293
}
391
}
294
#endif
392
#endif