Subversion Repositories gelsvn

Rev

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