Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
39 bj 1
#include <iostream>
2
 
3
#include "Manifold.h"
4
#include "VertexCirculator.h"
5
#include "FaceCirculator.h"
6
 
7
 
8
namespace HMesh
9
{
10
	using namespace std;
11
	using namespace CGLA;
12
 
13
	void Manifold::get_bbox(Vec3f& pmin, Vec3f& pmax) 
14
	{
15
		VertexIter vi = vertices_begin();
16
		pmin = pmax = vi->get_pos();
17
		for(++vi;vi != vertices_end(); ++vi)
18
			{
19
				pmin = v_min(vi->get_pos(), pmin);
20
				pmax = v_max(vi->get_pos(), pmax);
21
			}
22
	}
23
 
24
  void Manifold::get_bsphere(CGLA::Vec3f& c, float& r) 
25
  {
26
    Vec3f p0,p7;
27
    get_bbox(p0, p7);
28
    Vec3f rad = (p7 - p0)/2.0;
29
    c = p0 + rad;
30
    r = rad.length();
31
  }
32
 
33
 
34
	VertexIter Manifold::split_edge(HalfEdgeIter h)
35
	{
36
		HalfEdgeIter ho = h->opp;
37
		VertexIter v  = h->vert;
38
		VertexIter vo = ho->vert;
39
		Vec3f np = (v->get_pos()+vo->get_pos())/2.0f;
40
 
41
		VertexIter vn = create_vertex(np);
42
		vn->he = h;
43
 
44
		HalfEdgeIter hn = create_halfedge();
45
		HalfEdgeIter hno = create_halfedge();
46
 
47
		vo->he = hn;
48
		v->he = ho;
49
 
50
		glue(hn,hno);
51
		link(h->prev, hn);
52
		link(hn,h);
53
		hn->vert = vn;
54
 
55
		link(hno,ho->next);
56
		link(ho, hno);
57
		hno->vert = vo;
58
		ho->vert = vn;
59
 
59 jab 60
 		h->face->last = hn;
61
 		ho->face->last = ho;
39 bj 62
		hn->face = h->face;
63
		hno->face = ho->face;
64
 
65
		vn->check_boundary_consistency();
66
		v->check_boundary_consistency();
67
		vo->check_boundary_consistency();
68
		return vn;
69
	}
70
 
71
 
72
	void Manifold::remove_face_if_degenerate(HalfEdgeIter h0)
73
	{
74
		if(h0->next->next == h0)
75
			{
76
				HalfEdgeIter h1 = h0->next;
77
 
78
				HalfEdgeIter h0o = h0->opp;
79
				HalfEdgeIter h1o = h1->opp;
80
 
81
				glue(h0o, h1o);
82
 
83
				VertexIter v0 = h1->vert;
84
				VertexIter v1 = h0->vert;
85
				v0->he = h1o;
86
				v1->he = h0o;
87
 
88
				if(h0->face != NULL_FACE_ITER)
89
					erase_face(h0->face);
90
				erase_halfedge(h0);
91
				erase_halfedge(h1);
92
 
93
				v0->check_boundary_consistency();
94
				v1->check_boundary_consistency();
95
 
96
			}
97
	}
98
 
99
	bool Manifold::collapse_precond(VertexIter v1, HalfEdgeIter h)
100
	{
101
		/* The goal of this (fiendishly complex) function is to test
102
			 whether an edge is collapsible. The test is as follows.
103
 
104
			 1. For the two vertices adjacent to the edge, we generate
105
			 a list of all their neighbouring vertices. We then generate a 
106
			 list of the vertices that occur in both these lists. That is, 
107
			 we find all vertices connected by edges to both endpoints
108
			 of the edge and store these in a list.
109
 
110
			 2. For both faces incident on the edge, check whether they
111
			 are triangular. If this is the case, the face will be removed,
112
			 and it is ok that the the third vertex is connected to both 
113
			 endpoints. Thus the third vertex in such a face is removed
114
			 from the list generated in 1.
115
 
116
			 3. If the list is now empty, all is well. Otherwise, there
117
			 would be a vertex in the new mesh with two edges connecting
118
			 it to the same vertex. Return false.
119
 
120
			 4. TETRAHEDRON TEST:
121
			 If the valency of both vertices is 
122
			 three, and the incident faces are triangles, we also disallow
123
			 the operation. Reason: It introduces a vertex of valency two
124
			 and if the final two polygons incident on the vertices 
125
			 that are adjacent to the edge being collapsed are triangles, then
126
			 the construction will collapse
127
 
128
			 5. VALENCY 4 TEST:
129
			 If a face adjacent to the edge being collapsed is a triangle,
130
			 it will disappear, and the valency of the final vertex beloning to
131
			 this edge will be reduced by one. Hence this valency should be at
132
			 least 4. A valency three vertex will be reduced to a valency two
133
			 vertex which is considered illegal.
134
 
135
			 6. PREVENT MERGING HOLES:
136
			 We do not want to collapse an edge if its end points are boundary
137
			 vertices, but its two adjacent faces are not NULL faces, because
138
			 in that case we create a vertex where two holes meet. A non manifold
139
			 situation.
140
 
141
		*/
142
 
143
		VertexIter v2 = h->vert;
144
 
145
		std::vector<int> link1;
146
		VertexCirculator vc1(v1);
147
		for(;!vc1.end();++vc1)
148
			link1.push_back(reinterpret_cast<int>(&(*vc1.get_vertex())));
149
		assert(link1.size()>=2);
150
 
151
		std::vector<int> link2;
152
		VertexCirculator vc2(v2);
153
		for(;!vc2.end();++vc2)
154
			link2.push_back(reinterpret_cast<int>(&(*vc2.get_vertex())));
155
		assert(link2.size()>=2);
156
 
157
		sort(link1.begin(),link1.end());
158
		sort(link2.begin(),link2.end());
159
 
160
		vector<int> lisect;
161
		back_insert_iterator<vector<int> > lii(lisect);
162
 
163
		set_intersection(link1.begin(), link1.end(),
164
										 link2.begin(), link2.end(),
165
										 lii);
166
 
167
 
168
		// If the adjacent face is a triangle (see 2)
169
		int k=0;
170
		if(h->next->next->next == h)
171
		{
172
			// VALENCY 4 TEST
173
			if(valency(h->next->vert)<4)
174
				return false;
175
 
176
			vector<int>::iterator iter;
177
			iter = find(lisect.begin(),	lisect.end(),
178
									reinterpret_cast<int>(&(*h->next->vert)));
179
			assert(iter != lisect.end());
180
			lisect.erase(iter);
181
			++k;
182
 
183
		}
184
		// If the adjacent face is a triangle (see 2)
185
		if(h->opp->next->next->next == h->opp)
186
		{
187
			// VALENCY 4 TEST
188
			if(valency(h->opp->next->vert)<4)
189
				return false;
190
 
191
			vector<int>::iterator iter;
192
			iter = find(lisect.begin(),	lisect.end(),
193
									reinterpret_cast<int>(&(*h->opp->next->vert)));
194
			assert(iter != lisect.end());
195
			lisect.erase(iter);
196
			++k;
197
 
198
		}
199
		if(lisect.size() !=0) // See 3.
200
			return false;
201
 
202
		// TETRAHEDRON TEST
203
		if(k==2 && (link1.size()+link2.size()==6)) 
204
			return false;
205
 
206
		// Test that we are not merging holes (see 6)
207
		if(v1->is_boundary() && v2->is_boundary() &&
208
			 (h->face != NULL_FACE_ITER) &&
209
			 (h->opp->face != NULL_FACE_ITER))
210
			return false;
211
 
212
 
213
		return true;
214
	}
215
 
216
 
217
 	void Manifold::collapse_halfedge(VertexIter v, HalfEdgeIter h, 
218
																	 bool avg_vertices)
219
	{
220
		HalfEdgeIter ho = h->opp;
221
		VertexIter n = h->vert;
222
 
223
		if(avg_vertices)
224
			n->set_pos((v->get_pos() + n->get_pos()) / 2.0f);
225
 
226
		HalfEdgeIter hn = h->next;
227
		HalfEdgeIter hp = h->prev;
228
		HalfEdgeIter hon = ho->next;
229
		HalfEdgeIter hop = ho->prev;
230
 
231
		bool neighbour_is_boundary = n->is_boundary();
232
 
233
		VertexCirculator vc(v);
234
		for(;!vc.end();++vc)
235
			vc.get_opp_halfedge()->vert = n;
236
 
237
		n->he = h->next;
238
 
239
		link(hp, hn);
240
		if(h->face != NULL_FACE_ITER)
241
			h->face->last = hn;
242
 
243
		link(hop, hon);
244
		if(ho->face != NULL_FACE_ITER)
245
			ho->face->last = hon;
246
 
247
 
248
 
249
		erase_vertex(v);
250
 		erase_halfedge(h);
251
 		erase_halfedge(ho);
252
 
253
		remove_face_if_degenerate(hn);
254
		remove_face_if_degenerate(hon);
255
 
256
		n->check_boundary_consistency();
257
	}
258
 
259
	bool Manifold::is_valid()
260
	{
261
		HalfEdgeIter he0 = halfedges_begin();
262
		while(he0 != halfedges_end())
263
			{
264
				if(he0->prev == NULL_HALFEDGE_ITER)
265
					{
266
						cout << "Halfedge lacks previous" << endl;
267
						return false;
268
					}
269
				if(he0->next == NULL_HALFEDGE_ITER)
270
					{
271
						cout << "Halfedge lacks next" << endl;
272
						return false;
273
					}
274
				if(he0->opp == NULL_HALFEDGE_ITER)
275
					{
276
						cout << "Halfedge lacks opposite" << endl;
277
						return false;
278
					}
279
				if(he0->vert == NULL_VERTEX_ITER)
280
					{
281
						cout << "Halfedge lacks vertex" << endl;
282
						return false;
283
					}				
284
				++he0;
285
			}
286
 
287
		VertexIter vi = vertices_begin();
288
		while(vi != vertices_end())
289
			{
290
				std::vector<int> link;
291
				VertexCirculator vc(vi);
292
				int k=0;
293
				for(;!vc.end();++vc,++k)
294
					{
295
						if(vc.get_halfedge() == NULL_HALFEDGE_ITER)
296
							{
297
								cout << "Vertex has null outgoing he" << endl;
298
								return false;
299
							}
300
						int x = reinterpret_cast<int>(&(*vc.get_vertex()));
301
						if(find(link.begin(), link.end(), x) != link.end())
302
							{
303
								cout << "Vertex appears two times in one-ring of other vertex" << endl;
304
 								return false;
305
							}
306
						link.push_back(x);
307
						if(k==1e6) 
308
							{
309
								cout << "infin. loop around vertex" << endl;
310
								return false;
311
							}
312
					}
313
				if(link.size()==2)
314
					{
315
						cout << "Warning: A vertex with only two incident edges" << endl;
316
					}
317
				assert(link.size()>=2);
318
				++vi;
319
			}
320
 
321
		HMesh::FaceIter f = faces_begin();
322
			for(;f != faces_end(); ++f)
323
				{
324
					if(no_edges(f)<3)
325
						{
326
							cout << "Degenerate face" << endl;
327
						}
328
					FaceCirculator fc(f);
329
					int k=0;
330
					while(!fc.end())
331
						{
332
							if(fc.get_halfedge()->face != f)
333
								{
334
									cout << "Inconsistent face" << endl;
335
									return false;
336
								}
337
							if(++k==1e6) cout << "infin. loop around face" << endl;
338
							++fc;
339
						}
340
				}
341
		return true;
342
	}
343
 
344
	FaceIter Manifold::split_face(FaceIter f, VertexIter v0, VertexIter v1)
345
	{
346
		// Make sure this is not a triangle 
347
		assert(no_edges(f)>3);
348
 
349
		// Make sure we are not trying to connect a vertex to itself.
350
		assert(v0 != v1);
351
 
352
		// Find the halfedge emanating from v0 which belongs to the
353
		// face, we need to split. 
354
		VertexCirculator vc0(v0);
355
		while(vc0.get_halfedge()->face != f && !vc0.end()) vc0++;
356
		assert(!vc0.end());
357
		HalfEdgeIter h0 = vc0.get_halfedge();
358
		assert(h0->face == f); // Sanity check.
359
 
360
		// The halfedge belonging to f, going out from v0, is denoted h.
361
		// Move along h until we hit v1. Now we have the halfedge which
362
		// belongs to f and points to v1.
363
		HalfEdgeIter h = h0;
364
		while(h->vert != v1) 
365
			h = h->next;
366
 
367
		// Create a new halfedge ha which connects v1 and v0 closing the first
368
		// loop. This new halfedge becomes f->last
369
		assert(h != h0);
370
		HalfEdgeIter h1 = h->next;
371
		HalfEdgeIter ha = create_halfedge();
372
		link(h,ha);
373
		link(ha, h0);
374
		ha->face = f;
375
		ha->vert = v0;
376
		f->last = ha;
377
 
378
		// Create a new face, f2, and set all halfedges in the remaining part of 
379
		// the polygon to point to this face. 
380
		h = h1;
381
		FaceIter f2 = create_face();
382
		while(h->vert != v0) 
383
			{
384
				h->face = f2;
385
				h = h->next;
386
			}
387
		h->face = f2;
388
		assert(h != h1);
389
 
390
		// Create a new halfedge hb to connect v0 and v1. this new halfedge 
391
		// becomes f2->last
392
		HalfEdgeIter hb = create_halfedge();
393
		link(h,hb);
394
		link(hb, h1);
395
		hb->face = f2;
396
		hb->vert = v1;
397
		f2->last = hb;
398
 
399
		// Complete the operation by gluing the two new halfedges.
400
		glue(ha, hb);
401
 
402
		// Assert that the pointers are sane :-)
403
		assert(h1->prev->opp->next == h0);
404
		assert(h0->prev->opp->next == h1);
405
		assert(hb->next->face == f2);
406
		assert(hb->next->next->face == f2);
407
		assert(hb->face == f2);
408
 
409
		// Return the newly created face
410
		return f2;
411
	}
412
 
413
	void Manifold::triangulate(FaceIter f)
414
	{
415
		// Assert sanity of pointers
416
		assert(f->last->next->next != f->last);
417
		assert(f->last->next != f->last);
418
		assert(--(++f) == f);
419
		// As long as f is not a triangle.
420
		while(f->last->next->next->next != f->last)
421
			{
422
				assert(no_edges(f) != 3);
423
				// Call split face to split f into a triangle
424
				// from the first three vertices and a polygon
425
				// containing the rest of the vertices. In the
426
				// next iteration, f becomes this polygon.
427
 
428
				assert(f->last->next->next != f->last);
429
				VertexIter v0 = f->last->vert;
430
				VertexIter v1 = f->last->next->next->vert;
431
				assert(v0 != v1);
432
				f = split_face(f, v0, v1);
433
			}
434
	}
435
 
436
	bool Manifold::merge_faces(FaceIter f1, HalfEdgeIter h)
437
	{
438
		assert(h->face == f1);
439
 
440
		HalfEdgeIter ho = h->opp;
441
		FaceIter f2 = ho->face;
442
		HalfEdgeIter hn = h->next;
443
		HalfEdgeIter hon = ho->next;
444
 
445
		if(hn->vert == hon->vert) return false;
446
 
447
		HalfEdgeIter hp = h->prev;
448
		HalfEdgeIter hop = ho->prev;
449
		VertexIter v  = h->vert;
450
		VertexIter vo = ho->vert;
451
 
452
		link(hop, hn);
453
		v->he = hn;
454
 
455
		link(hp, hon);
456
		vo->he = hon;
457
 
458
		f1->last = hn;
459
		HalfEdgeIter hx = hon;
460
		assert(hx->face == f2);
461
		while(hx->face != f1)
462
			{
463
				hx->face = f1;
464
				hx = hx->next;
465
			}
466
 
467
		v->check_boundary_consistency();
468
		vo->check_boundary_consistency();
469
 
470
 		erase_halfedge(h);
471
 		erase_halfedge(ho);
472
		erase_face(f2);
473
 
474
		return true;
475
	}
476
 
477
 
478
	VertexIter Manifold::safe_triangulate(FaceIter f)
479
	{
480
		Vec3f p;
481
		FaceCirculator fc(f);
482
		for(;!fc.end(); ++fc)
483
			p += fc.get_vertex()->get_pos();
484
		int n = fc.no_steps();
485
		p /= n;
486
		VertexIter v = create_vertex(p);
487
		face_insert_point(f,v);
488
		return v;
489
	}
490
 
491
 
492
	void Manifold::face_insert_point(FaceIter f, VertexIter v)
493
	{
494
		vector<HalfEdgeIter> eout;
495
		vector<HalfEdgeIter> ein;
496
 
497
		HalfEdgeIter hlast = f->last;
498
		HalfEdgeIter h = hlast;
499
 
500
		do
501
			{
502
				HalfEdgeIter hn = h->next;
503
 
504
				HalfEdgeIter o = create_halfedge();
505
				HalfEdgeIter i = create_halfedge();
506
 
507
				FaceIter fn = create_face();
508
				i->face = fn;
509
				i->vert = v;
510
				o->face = fn;
511
				o->vert = h->opp->vert;
512
				h->face = fn;
513
				fn->last = o;
514
 
515
				link(i,o);
516
				link(o,h);
517
				link(h,i);
518
 
519
				eout.push_back(o);
520
				ein.push_back(i);
521
 
522
				h = hn;
523
			}
524
		while(h != hlast);
525
 
526
		int N = eout.size();
527
		for(int i=0;i<N;++i)
528
			glue(ein[i],eout[(i+1)%N]);
529
 
530
		v->he = eout[0];
531
		erase_face(f);
532
	}
533
 
534
 
535
	bool Manifold::flip(HalfEdgeIter h1)
536
	{
537
		FaceIter f1 = h1->face;
538
		HalfEdgeIter h2 = h1->opp;
539
		FaceIter f2 = h2->face;
540
 
541
		if(f1 == NULL_FACE_ITER || f2 == NULL_FACE_ITER)
542
			return false;
543
 
544
		// We can only flip an edge if both incident polygons
545
		// are triangles. Otherwise, this operation makes no sense.
546
		if(no_edges(f1) != 3)
547
			return false;
548
		if(no_edges(f2) !=3)
549
			return false;
550
 
551
		// If the valency of either vertex incident on the edge
552
		// being flipped is three, we cannot perform this operation.
553
		// That is because the vertex would then have valency two
554
		// after the operation which means it would be degenerate.
555
		VertexIter va = h1->vert;
556
		VertexIter vb = h2->vert;
557
		int vala = valency(va);
558
		int valb = valency(vb);
559
		if((vala <= 3) || (valb <= 3))
560
			return false;
561
 
562
		// If the two vertices being connected by the flip are already
563
		// connected, the mesh would become degenerate, so we disallow
564
		// the operation.
565
		VertexIter vc = h1->next->vert;
566
		VertexIter vd = h2->next->vert;
567
		if(is_connected(vc,vd))
568
			return false;
569
 
570
		HalfEdgeIter ha = h1->next;
571
		HalfEdgeIter hb = h1->prev;
572
		HalfEdgeIter hc = h2->next;
573
		HalfEdgeIter hd = h2->prev;
574
 
575
		hd->face = f1;
576
		hb->face = f2;
577
		f1->last = h1;
578
		f2->last = h2;
579
 
580
		link(ha,h1);
581
		link(h1,hd);
582
		link(hd,ha);
583
 
584
		link(hc,h2);
585
		link(h2,hb);
586
		link(hb,hc);
587
 
588
		h1->vert = vd;
589
		h2->vert = vc;
590
 
591
		va->he = ha;
592
		vb->he = hc;
593
 
594
		va->check_boundary_consistency();
595
		vb->check_boundary_consistency();
596
		return true;
597
	}
598
 
599
		/** Give each vertex a unique id corresponding to its iterator 
600
				position */
601
		void Manifold::enumerate_vertices()
602
		{
603
			int i=0;
604
			for(VertexIter vi=vertices_begin(); vi != vertices_end(); ++vi)
605
				vi->touched = i++;
606
		}
607
 
608
		/** Give each halfedge a unique id corresponding to its iterator 
609
				position */
610
		void Manifold::enumerate_halfedges()
611
		{
612
			int i=0;
613
			for(HalfEdgeIter h=halfedges_begin(); h != halfedges_end(); ++h)
614
				h->touched = i++;
615
		}
616
 
617
		/** Give each face a unique id corresponding to its iterator 
618
				position */
619
		void Manifold::enumerate_faces()
620
		{
621
			int i=0;
622
			for(FaceIter f=faces_begin(); f != faces_end(); ++f)
623
				f->touched = i++;
624
		}
625
 
626
 
627
}
628