Subversion Repositories gelsvn

Rev

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