Subversion Repositories gelsvn

Rev

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