Subversion Repositories gelsvn

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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