Subversion Repositories gelsvn

Rev

Rev 657 | Rev 662 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 657 Rev 658
1
/* ----------------------------------------------------------------------- *
1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
5
 * ----------------------------------------------------------------------- */
6
#include <iterator>
6
#include <iterator>
7
#include "Manifold.h"
7
#include "Manifold.h"
8
 
8
 
9
#include <iostream>
9
#include <iostream>
10
#include <vector>
10
#include <vector>
11
#include <map>
11
#include <map>
12
#include <iterator>
12
#include <iterator>
13
 
13
 
14
#include "../Geometry/TriMesh.h"
14
#include "../Geometry/TriMesh.h"
15
 
15
 
16
namespace HMesh
16
namespace HMesh
17
{
17
{
18
	
18
	
19
    using namespace std;
19
    using namespace std;
20
    using namespace Geometry;
20
    using namespace Geometry;
21
    using namespace CGLA;
21
    using namespace CGLA;
22
	
22
	
23
    namespace
23
    namespace
24
    {
24
    {
25
        /************************************************************
25
        /************************************************************
26
		 * Edgekeys and Edges for halfedge identification during build
26
		 * Edgekeys and Edges for halfedge identification during build
27
		 ************************************************************/
27
		 ************************************************************/
28
        class EdgeKey
28
        class EdgeKey
29
        {
29
        {
30
        public:
30
        public:
31
            EdgeKey(VertexID va, VertexID vb)
31
            EdgeKey(VertexID va, VertexID vb)
32
            {
32
            {
33
                if(va < vb){
33
                if(va < vb){
34
                    v0 = va;
34
                    v0 = va;
35
                    v1 = vb;
35
                    v1 = vb;
36
                }
36
                }
37
                else{
37
                else{
38
                    v0 = vb;
38
                    v0 = vb;
39
                    v1 = va;
39
                    v1 = va;
40
                }
40
                }
41
            }
41
            }
42
			
42
			
43
            bool operator<(const EdgeKey& k2) const
43
            bool operator<(const EdgeKey& k2) const
44
            {
44
            {
45
                if(v0 < k2.v0){
45
                if(v0 < k2.v0){
46
                    return true;
46
                    return true;
47
                }
47
                }
48
                else if( k2.v0 < v0){
48
                else if( k2.v0 < v0){
49
                    return false;
49
                    return false;
50
                }
50
                }
51
                else{
51
                else{
52
                    return v1 < k2.v1;
52
                    return v1 < k2.v1;
53
                }
53
                }
54
            }
54
            }
55
        private:
55
        private:
56
            VertexID v0;
56
            VertexID v0;
57
            VertexID v1;
57
            VertexID v1;
58
        };
58
        };
59
		
59
		
60
        struct Edge
60
        struct Edge
61
        {
61
        {
62
            HalfEdgeID h0;
62
            HalfEdgeID h0;
63
            HalfEdgeID h1;
63
            HalfEdgeID h1;
64
            int count;
64
            int count;
65
            Edge() : count(0){}
65
            Edge() : count(0){}
66
        };
66
        };
67
    }
67
    }
68
	
68
	
69
    /*********************************************
69
    /*********************************************
70
	 * Public functions
70
	 * Public functions
71
	 *********************************************/
71
	 *********************************************/
72
    void Manifold::build(const TriMesh& mesh)
72
    void Manifold::build(const TriMesh& mesh)
73
    {
73
    {
74
        // A vector of 3's - used to tell build how many indices each face consists of
74
        // A vector of 3's - used to tell build how many indices each face consists of
75
        vector<int> faces(mesh.geometry.no_faces(), 3);
75
        vector<int> faces(mesh.geometry.no_faces(), 3);
76
		
76
		
77
        build_template( static_cast<size_t>(mesh.geometry.no_vertices()),
77
        build_template( static_cast<size_t>(mesh.geometry.no_vertices()),
78
					   reinterpret_cast<const float*>(&mesh.geometry.vertex(0)),
78
					   reinterpret_cast<const float*>(&mesh.geometry.vertex(0)),
79
					   static_cast<size_t>(faces.size()),
79
					   static_cast<size_t>(faces.size()),
80
					   static_cast<const int*>(&faces[0]),
80
					   static_cast<const int*>(&faces[0]),
81
					   reinterpret_cast<const int*>(&mesh.geometry.face(0)));
81
					   reinterpret_cast<const int*>(&mesh.geometry.face(0)));
82
    }
82
    }
83
    
83
    
84
    void Manifold::build(   size_t no_vertices,
84
    void Manifold::build(   size_t no_vertices,
85
						 const float* vertvec,
85
						 const float* vertvec,
86
						 size_t no_faces,
86
						 size_t no_faces,
87
						 const int* facevec,
87
						 const int* facevec,
88
						 const int* indices)
88
						 const int* indices)
89
    {
89
    {
90
        build_template(no_vertices, vertvec, no_faces, facevec, indices);
90
        build_template(no_vertices, vertvec, no_faces, facevec, indices);
91
    }
91
    }
92
    
92
    
93
    void Manifold::build(   size_t no_vertices,
93
    void Manifold::build(   size_t no_vertices,
94
						 const double* vertvec,
94
						 const double* vertvec,
95
						 size_t no_faces,
95
						 size_t no_faces,
96
						 const int* facevec,
96
						 const int* facevec,
97
						 const int* indices)
97
						 const int* indices)
98
    {
98
    {
99
        build_template(no_vertices, vertvec, no_faces, facevec, indices);
99
        build_template(no_vertices, vertvec, no_faces, facevec, indices);
100
    }
100
    }
101
    
101
    
102
    FaceID Manifold::add_face(std::vector<Manifold::Vec> points)
102
    FaceID Manifold::add_face(std::vector<Manifold::Vec> points)
103
    {
103
    {
104
        int F = points.size();
104
        int F = points.size();
105
        vector<int> indices;
105
        vector<int> indices;
106
        for(size_t i=0;i<points.size(); ++i)
106
        for(size_t i=0;i<points.size(); ++i)
107
            indices.push_back(i);
107
            indices.push_back(i);
108
        FaceID fid = *faces_end();
108
        FaceID fid = *faces_end();
109
        build(points.size(), reinterpret_cast<double*>(&points[0]), 1, &F, &indices[0]);
109
        build(points.size(), reinterpret_cast<double*>(&points[0]), 1, &F, &indices[0]);
110
        return fid;
110
        return fid;
111
    }
111
    }
112
    
112
    
113
    bool Manifold::remove_face(FaceID fid)
113
    bool Manifold::remove_face(FaceID fid)
114
    {
114
    {
115
        if(!in_use(fid))
115
        if(!in_use(fid))
116
            return false;
116
            return false;
117
        
117
        
118
        HalfEdgeID he = kernel.last(fid);
118
        HalfEdgeID he = kernel.last(fid);
119
        HalfEdgeID last = he;
119
        HalfEdgeID last = he;
120
        
120
        
121
        vector<HalfEdgeID> halfedges;
121
        vector<HalfEdgeID> halfedges;
122
        do
122
        do
123
        {
123
        {
124
            halfedges.push_back(he);
124
            halfedges.push_back(he);
125
            kernel.set_face(he, InvalidFaceID);
125
            kernel.set_face(he, InvalidFaceID);
126
            he = kernel.next(he);
126
            he = kernel.next(he);
127
        }
127
        }
128
        while(he != last);
128
        while(he != last);
129
        
129
        
130
        vector<HalfEdgeID> halfedges_garbage;
130
        vector<HalfEdgeID> halfedges_garbage;
131
        vector<VertexID> vertices_garbage;
131
        vector<VertexID> vertices_garbage;
132
        for(size_t i=0;i<halfedges.size(); ++i)
132
        for(size_t i=0;i<halfedges.size(); ++i)
133
        {
133
        {
134
            HalfEdgeID h = halfedges[i];
134
            HalfEdgeID h = halfedges[i];
135
            HalfEdgeID hopp = kernel.opp(h);
135
            HalfEdgeID hopp = kernel.opp(h);
136
            if(kernel.face(hopp) == InvalidFaceID)
136
            if(kernel.face(hopp) == InvalidFaceID)
137
            {
137
            {
138
                halfedges_garbage.push_back(h);
138
                halfedges_garbage.push_back(h);
139
                VertexID v0 = kernel.vert(hopp);
139
                VertexID v0 = kernel.vert(hopp);
140
                if(valency(*this, v0) <= 2 )
140
                if(valency(*this, v0) <= 2 )
141
                    vertices_garbage.push_back(v0);
141
                    vertices_garbage.push_back(v0);
142
                else {
142
                else {
143
                    link(kernel.prev(h), kernel.next(hopp));
143
                    link(kernel.prev(h), kernel.next(hopp));
144
                    kernel.set_out(v0, kernel.opp(kernel.prev(h)));
144
                    kernel.set_out(v0, kernel.opp(kernel.prev(h)));
145
                }
145
                }
146
                VertexID v1 = kernel.vert(h);
146
                VertexID v1 = kernel.vert(h);
147
                if(valency(*this, v1)>2)
147
                if(valency(*this, v1)>2)
148
                {
148
                {
149
                    link(kernel.prev(hopp),kernel.next(h));
149
                    link(kernel.prev(hopp),kernel.next(h));
150
                    kernel.set_out(v1, kernel.opp(kernel.prev(hopp)));
150
                    kernel.set_out(v1, kernel.opp(kernel.prev(hopp)));
151
                }
151
                }
152
                
152
                
153
            }
153
            }
154
        }
154
        }
155
        for(size_t i=0;i<halfedges_garbage.size();++i){
155
        for(size_t i=0;i<halfedges_garbage.size();++i){
156
            kernel.remove_halfedge(kernel.opp(halfedges_garbage[i]));
156
            kernel.remove_halfedge(kernel.opp(halfedges_garbage[i]));
157
            kernel.remove_halfedge(halfedges_garbage[i]);
157
            kernel.remove_halfedge(halfedges_garbage[i]);
158
        }
158
        }
159
        for(size_t i=0;i<vertices_garbage.size(); ++i)
159
        for(size_t i=0;i<vertices_garbage.size(); ++i)
160
            kernel.remove_vertex(vertices_garbage[i]);
160
            kernel.remove_vertex(vertices_garbage[i]);
161
        
161
        
162
        kernel.remove_face(fid);
162
        kernel.remove_face(fid);
163
        return true;
163
        return true;
164
    }
164
    }
165
    
165
    
166
 
166
 
167
    bool Manifold::remove_edge(HalfEdgeID hid)
167
    bool Manifold::remove_edge(HalfEdgeID hid)
168
    {
168
    {
169
        if(!in_use(hid))
169
        if(!in_use(hid))
170
            return false;
170
            return false;
171
        
171
        
172
        FaceID f0 = kernel.face(hid);
172
        FaceID f0 = kernel.face(hid);
173
        FaceID f1 = kernel.face(kernel.opp(hid));
173
        FaceID f1 = kernel.face(kernel.opp(hid));
174
        
174
        
175
        remove_face(f0);
175
        remove_face(f0);
176
        remove_face(f1);
176
        remove_face(f1);
177
 
177
 
178
        return true;
178
        return true;
179
    }
179
    }
180
 
180
 
181
    
181
    
182
    
182
    
183
    bool Manifold::remove_vertex(VertexID vid)
183
    bool Manifold::remove_vertex(VertexID vid)
184
    {
184
    {
185
        if(!in_use(vid))
185
        if(!in_use(vid))
186
            return false;
186
            return false;
187
    
187
    
188
        vector<FaceID> faces;
188
        vector<FaceID> faces;
189
        int N = circulate_vertex_ccw(*this, vid, (std::function<void(FaceID)>)[&](FaceID f) {
189
        int N = circulate_vertex_ccw(*this, vid, (std::function<void(FaceID)>)[&](FaceID f) {
190
            faces.push_back(f);
190
            faces.push_back(f);
191
        });
191
        });
192
        for(size_t i=0;i<N;++i)
192
        for(size_t i=0;i<N;++i)
193
            remove_face(faces[i]);
193
            remove_face(faces[i]);
194
            
194
            
195
        return true;
195
        return true;
196
    }
196
    }
197
 
197
 
198
 
198
 
199
	
199
	
200
    void Manifold::collapse_edge(HalfEdgeID h, bool avg_vertices)
200
    void Manifold::collapse_edge(HalfEdgeID h, bool avg_vertices)
201
    {
201
    {
202
        HalfEdgeID ho = kernel.opp(h);
202
        HalfEdgeID ho = kernel.opp(h);
203
        VertexID hv = kernel.vert(h);
203
        VertexID hv = kernel.vert(h);
204
        VertexID hov = kernel.vert(ho);
204
        VertexID hov = kernel.vert(ho);
205
        HalfEdgeID hn = kernel.next(h);
205
        HalfEdgeID hn = kernel.next(h);
206
        HalfEdgeID hp = kernel.prev(h);
206
        HalfEdgeID hp = kernel.prev(h);
207
        HalfEdgeID hon = kernel.next(ho);
207
        HalfEdgeID hon = kernel.next(ho);
208
        HalfEdgeID hop = kernel.prev(ho);
208
        HalfEdgeID hop = kernel.prev(ho);
209
		FaceID f = kernel.face(h);
209
		FaceID f = kernel.face(h);
210
		FaceID fo = kernel.face(ho);
210
		FaceID fo = kernel.face(ho);
211
		
211
		
212
        // average the vertex positions
212
        // average the vertex positions
213
        pos(hv) = avg_vertices ? (0.5f * (pos(hov) + pos(hv))) : pos(hv);
213
        pos(hv) = avg_vertices ? (0.5f * (pos(hov) + pos(hv))) : pos(hv);
214
		
214
		
215
        // update all halfedges pointing to hov to point to hv, effectively removing hov from all loops
215
        // update all halfedges pointing to hov to point to hv, effectively removing hov from all loops
216
        HalfEdgeID he = kernel.out(hov);
216
        HalfEdgeID he = kernel.out(hov);
217
        HalfEdgeID last = he;
217
        HalfEdgeID last = he;
218
		do {
218
		do {
219
			assert(kernel.vert(kernel.opp(he)) == hov);
219
			assert(kernel.vert(kernel.opp(he)) == hov);
220
            kernel.set_vert(kernel.opp(he), hv);
220
            kernel.set_vert(kernel.opp(he), hv);
221
            he = kernel.next(kernel.opp(he));
221
            he = kernel.next(kernel.opp(he));
222
        }
222
        }
223
		while(he != last);
223
		while(he != last);
224
        kernel.set_out(hv, hn);
224
        kernel.set_out(hv, hn);
225
		
225
		
226
        // link hp and hn, effectively removing h from opposite loop
226
        // link hp and hn, effectively removing h from opposite loop
227
        link(hp, hn);
227
        link(hp, hn);
228
        // make face owning h own hn instead
228
        // make face owning h own hn instead
229
        if(kernel.face(h) != InvalidFaceID)
229
        if(kernel.face(h) != InvalidFaceID)
230
            kernel.set_last(f, hn);
230
            kernel.set_last(f, hn);
231
		
231
		
232
        // link hop and hon, effectively removing h from opposite face loop
232
        // link hop and hon, effectively removing h from opposite face loop
233
        link(hop, hon);
233
        link(hop, hon);
234
        // make opposite face owning h own hon instead
234
        // make opposite face owning h own hon instead
235
        if(kernel.face(ho) != InvalidFaceID)
235
        if(kernel.face(ho) != InvalidFaceID)
236
            kernel.set_last(fo, hon);
236
            kernel.set_last(fo, hon);
237
		
237
		
238
        // remove the obsolete entities
238
        // remove the obsolete entities
239
        kernel.remove_vertex(hov);
239
        kernel.remove_vertex(hov);
240
        kernel.remove_halfedge(h);
240
        kernel.remove_halfedge(h);
241
        kernel.remove_halfedge(ho);
241
        kernel.remove_halfedge(ho);
242
		
242
		
243
        // verify that remaining faces haven't become degenerate because of collapse
243
        // verify that remaining faces haven't become degenerate because of collapse
244
        remove_face_if_degenerate(hn);
244
        remove_face_if_degenerate(hn);
245
        remove_face_if_degenerate(hon);
245
        remove_face_if_degenerate(hon);
246
		
246
		
247
        // verify that v is sane after collapse
247
        // verify that v is sane after collapse
248
        ensure_boundary_consistency(hv);
248
        ensure_boundary_consistency(hv);
249
    }
249
    }
250
	
250
	
251
    FaceID Manifold::split_face_by_edge(FaceID f, VertexID v0, VertexID v1)
251
    FaceID Manifold::split_face_by_edge(FaceID f, VertexID v0, VertexID v1)
252
    {
252
    {
253
		assert(!connected(*this, v0, v1));
253
		assert(!connected(*this, v0, v1));
254
        HalfEdgeID he = kernel.last(f);
254
        HalfEdgeID he = kernel.last(f);
255
        HalfEdgeID last = he;
255
        HalfEdgeID last = he;
256
        int steps = 0;
256
        int steps = 0;
257
        while(he != last || steps == 0){
257
        while(he != last || steps == 0){
258
            ++steps;
258
            ++steps;
259
            he = kernel.next(he);
259
            he = kernel.next(he);
260
        }
260
        }
261
		
261
		
262
        // make sure this is not a triangle
262
        // make sure this is not a triangle
263
        assert(steps > 3);
263
        assert(steps > 3);
264
        // make sure we are not trying to connect a vertex to itself
264
        // make sure we are not trying to connect a vertex to itself
265
        assert(v0 != v1);
265
        assert(v0 != v1);
266
		
266
		
267
		HalfEdgeID h0 = kernel.out(v0);
267
		HalfEdgeID h0 = kernel.out(v0);
268
		for(Walker w = walker(v0); !w.full_circle(); w = w.circulate_vertex_cw()){
268
		for(Walker w = walker(v0); !w.full_circle(); w = w.circulate_vertex_cw()){
269
			if(w.face() == f){
269
			if(w.face() == f){
270
				h0 = w.halfedge();
270
				h0 = w.halfedge();
271
				break;
271
				break;
272
			}
272
			}
273
		}
273
		}
274
		assert(kernel.face(h0) != InvalidFaceID);
274
		assert(kernel.face(h0) != InvalidFaceID);
275
        assert(kernel.face(h0) == f);
275
        assert(kernel.face(h0) == f);
276
		
276
		
277
        // the halfedge belonging to f, going out from v0, is denoted h. Move along h until we hit v1.
277
        // the halfedge belonging to f, going out from v0, is denoted h. Move along h until we hit v1.
278
        // now we have the halfedge which belongs to f and points to v1.
278
        // now we have the halfedge which belongs to f and points to v1.
279
        HalfEdgeID h = h0;
279
        HalfEdgeID h = h0;
280
        while(kernel.vert(h) != v1){
280
        while(kernel.vert(h) != v1){
281
            h = kernel.next(h);
281
            h = kernel.next(h);
282
        }
282
        }
283
        assert(h != h0);
283
        assert(h != h0);
284
		
284
		
285
        // create a new halfedge ha which connects v1 and v0 closing the first loop.
285
        // create a new halfedge ha which connects v1 and v0 closing the first loop.
286
        HalfEdgeID h1 = kernel.next(h);
286
        HalfEdgeID h1 = kernel.next(h);
287
        HalfEdgeID ha = kernel.add_halfedge();
287
        HalfEdgeID ha = kernel.add_halfedge();
288
        link(h, ha);
288
        link(h, ha);
289
        link(ha, h0);
289
        link(ha, h0);
290
        kernel.set_face(ha, f);
290
        kernel.set_face(ha, f);
291
        kernel.set_vert(ha, v0);
291
        kernel.set_vert(ha, v0);
292
        kernel.set_last(f, ha);
292
        kernel.set_last(f, ha);
293
		
293
		
294
        // create a new face, f2, and set all halfedges in the remaining part of the polygon to point to this face.
294
        // create a new face, f2, and set all halfedges in the remaining part of the polygon to point to this face.
295
        h = h1;
295
        h = h1;
296
        FaceID f2 = kernel.add_face();
296
        FaceID f2 = kernel.add_face();
297
        while(kernel.vert(h) != v0){
297
        while(kernel.vert(h) != v0){
298
            kernel.set_face(h, f2);
298
            kernel.set_face(h, f2);
299
            h = kernel.next(h);
299
            h = kernel.next(h);
300
        }
300
        }
301
        kernel.set_face(h, f2);
301
        kernel.set_face(h, f2);
302
        assert(h != h1);
302
        assert(h != h1);
303
		
303
		
304
        // create a new halfedge hb to connect v0 and v1.
304
        // create a new halfedge hb to connect v0 and v1.
305
        HalfEdgeID hb = kernel.add_halfedge();
305
        HalfEdgeID hb = kernel.add_halfedge();
306
        link(h, hb);
306
        link(h, hb);
307
        link(hb, h1);
307
        link(hb, h1);
308
        kernel.set_face(hb, f2);
308
        kernel.set_face(hb, f2);
309
        kernel.set_vert(hb, v1);
309
        kernel.set_vert(hb, v1);
310
        kernel.set_last(f2, hb);
310
        kernel.set_last(f2, hb);
311
		
311
		
312
        // complete the operation by gluing the two new halfedges
312
        // complete the operation by gluing the two new halfedges
313
        glue(ha, hb);
313
        glue(ha, hb);
314
		
314
		
315
        // assert sanity of operation
315
        // assert sanity of operation
316
        assert(kernel.next(kernel.opp(kernel.prev(h1))) == h0);
316
        assert(kernel.next(kernel.opp(kernel.prev(h1))) == h0);
317
        assert(kernel.next(kernel.opp(kernel.prev(h0))) == h1);
317
        assert(kernel.next(kernel.opp(kernel.prev(h0))) == h1);
318
        assert(kernel.face(kernel.next(hb)) == f2);
318
        assert(kernel.face(kernel.next(hb)) == f2);
319
        assert(kernel.face(kernel.next(kernel.next(hb))) == f2);
319
        assert(kernel.face(kernel.next(kernel.next(hb))) == f2);
320
        assert(kernel.face(hb) == f2);
320
        assert(kernel.face(hb) == f2);
321
		
321
		
322
        // return handle to newly created face
322
        // return handle to newly created face
323
        return f2;
323
        return f2;
324
    }
324
    }
325
	
325
	
326
    VertexID Manifold::split_face_by_vertex(FaceID f)
326
    VertexID Manifold::split_face_by_vertex(FaceID f)
327
    {
327
    {
328
        //create the new vertex, with the barycenter of the face as position
328
        //create the new vertex, with the barycenter of the face as position
329
        Manifold::Vec p(0.0f);
329
        Manifold::Vec p(0.0f);
330
        HalfEdgeID last_he = kernel.last(f);
330
        HalfEdgeID last_he = kernel.last(f);
331
        HalfEdgeID he = last_he;
331
        HalfEdgeID he = last_he;
332
        int steps = 0;
332
        int steps = 0;
333
		
333
		
334
        while(he != last_he || steps == 0){
334
        while(he != last_he || steps == 0){
335
            p += positions[kernel.vert(he)];
335
            p += positions[kernel.vert(he)];
336
            ++steps;
336
            ++steps;
337
            he = kernel.next(he);
337
            he = kernel.next(he);
338
        }
338
        }
339
		
339
		
340
        p /= steps;
340
        p /= steps;
341
		
341
		
342
        VertexID v = kernel.add_vertex();
342
        VertexID v = kernel.add_vertex();
343
        positions[v]  = p;
343
        positions[v]  = p;
344
		
344
		
345
        //circulate the face, create halfedges and connect to vertex
345
        //circulate the face, create halfedges and connect to vertex
346
        vector<HalfEdgeID> eout;
346
        vector<HalfEdgeID> eout;
347
        vector<HalfEdgeID> ein;
347
        vector<HalfEdgeID> ein;
348
        last_he = kernel.last(f);
348
        last_he = kernel.last(f);
349
        he = last_he;
349
        he = last_he;
350
		
350
		
351
        do{
351
        do{
352
            HalfEdgeID hn = kernel.next(he);
352
            HalfEdgeID hn = kernel.next(he);
353
			
353
			
354
            HalfEdgeID ho = kernel.add_halfedge();
354
            HalfEdgeID ho = kernel.add_halfedge();
355
            HalfEdgeID hi = kernel.add_halfedge();
355
            HalfEdgeID hi = kernel.add_halfedge();
356
			
356
			
357
            FaceID fn = kernel.add_face();
357
            FaceID fn = kernel.add_face();
358
            kernel.set_face(hi, fn);
358
            kernel.set_face(hi, fn);
359
            kernel.set_vert(hi, v);
359
            kernel.set_vert(hi, v);
360
            kernel.set_face(ho, fn);
360
            kernel.set_face(ho, fn);
361
            kernel.set_vert(ho, kernel.vert(kernel.opp(he)));
361
            kernel.set_vert(ho, kernel.vert(kernel.opp(he)));
362
            kernel.set_face(he, fn);
362
            kernel.set_face(he, fn);
363
            kernel.set_last(fn, ho);
363
            kernel.set_last(fn, ho);
364
			
364
			
365
            link(hi, ho);
365
            link(hi, ho);
366
            link(ho, he);
366
            link(ho, he);
367
            link(he, hi);
367
            link(he, hi);
368
			
368
			
369
            eout.push_back(ho);
369
            eout.push_back(ho);
370
            ein.push_back(hi);
370
            ein.push_back(hi);
371
			
371
			
372
            he = hn;
372
            he = hn;
373
        }
373
        }
374
        while(he != last_he);
374
        while(he != last_he);
375
		
375
		
376
        // glue new halfedges together
376
        // glue new halfedges together
377
        size_t N = eout.size();
377
        size_t N = eout.size();
378
        for(size_t i = 0; i < N; ++i){
378
        for(size_t i = 0; i < N; ++i){
379
            glue(ein[i], eout[(i+1)%N]);
379
            glue(ein[i], eout[(i+1)%N]);
380
        }
380
        }
381
        kernel.set_out(v, eout[0]);
381
        kernel.set_out(v, eout[0]);
382
		
382
		
383
        //remove the now replaced face
383
        //remove the now replaced face
384
        kernel.remove_face(f);
384
        kernel.remove_face(f);
385
		
385
		
386
        return v;
386
        return v;
387
    }
387
    }
388
    VertexID Manifold::split_edge(HalfEdgeID h)
388
    VertexID Manifold::split_edge(HalfEdgeID h)
389
    {
389
    {
390
        HalfEdgeID ho = kernel.opp(h);
390
        HalfEdgeID ho = kernel.opp(h);
391
        VertexID v = kernel.vert(h);
391
        VertexID v = kernel.vert(h);
392
        VertexID vo = kernel.vert(ho);
392
        VertexID vo = kernel.vert(ho);
393
		
393
		
394
        //create the new vertex with middle of edge as position and update connectivity
394
        //create the new vertex with middle of edge as position and update connectivity
395
        VertexID vn = kernel.add_vertex();
395
        VertexID vn = kernel.add_vertex();
396
        positions[vn] = .5f * (positions[v] + positions[vo]);
396
        positions[vn] = .5f * (positions[v] + positions[vo]);
397
        kernel.set_out(vn, h);
397
        kernel.set_out(vn, h);
398
		
398
		
399
        //create two necessary halfedges, and update connectivity
399
        //create two necessary halfedges, and update connectivity
400
        HalfEdgeID hn = kernel.add_halfedge();
400
        HalfEdgeID hn = kernel.add_halfedge();
401
        HalfEdgeID hno = kernel.add_halfedge();
401
        HalfEdgeID hno = kernel.add_halfedge();
402
		
402
		
403
        kernel.set_out(vo, hn);
403
        kernel.set_out(vo, hn);
404
        kernel.set_out(v, hno);
404
        kernel.set_out(v, hno);
405
		
405
		
406
        glue(h, hno);
406
        glue(h, hno);
407
        glue(hn, ho);
407
        glue(hn, ho);
408
		
408
		
409
        link(kernel.prev(h), hn);
409
        link(kernel.prev(h), hn);
410
        link(hn, h);
410
        link(hn, h);
411
        kernel.set_vert(hn, vn);
411
        kernel.set_vert(hn, vn);
412
		
412
		
413
        link(kernel.prev(ho), hno);
413
        link(kernel.prev(ho), hno);
414
        link(hno, ho);
414
        link(hno, ho);
415
        kernel.set_vert(hno, vn);
415
        kernel.set_vert(hno, vn);
416
		
416
		
417
        // update faces in case of non boundary edge
417
        // update faces in case of non boundary edge
418
        if(kernel.face(h) != InvalidFaceID)
418
        if(kernel.face(h) != InvalidFaceID)
419
            kernel.set_last(kernel.face(h), hn);
419
            kernel.set_last(kernel.face(h), hn);
420
		
420
		
421
        if(kernel.face(ho) != InvalidFaceID)
421
        if(kernel.face(ho) != InvalidFaceID)
422
            kernel.set_last(kernel.face(ho), ho);
422
            kernel.set_last(kernel.face(ho), ho);
423
		
423
		
424
        // update new edge with faces from existing edge
424
        // update new edge with faces from existing edge
425
        kernel.set_face(hn, kernel.face(h));
425
        kernel.set_face(hn, kernel.face(h));
426
        kernel.set_face(hno, kernel.face(ho));
426
        kernel.set_face(hno, kernel.face(ho));
427
		
427
		
428
        //if split occurs on a boundary, consistency must be ensured.
428
        //if split occurs on a boundary, consistency must be ensured.
429
        ensure_boundary_consistency(vn);
429
        ensure_boundary_consistency(vn);
430
        ensure_boundary_consistency(v);
430
        ensure_boundary_consistency(v);
431
        ensure_boundary_consistency(vo);
431
        ensure_boundary_consistency(vo);
432
		
432
		
433
        return vn;
433
        return vn;
434
    }
434
    }
435
    
435
    
436
    size_t link_intersection(const Manifold& m, VertexID v0, VertexID v1, vector<VertexID>& lisect)
436
    size_t link_intersection(const Manifold& m, VertexID v0, VertexID v1, vector<VertexID>& lisect)
437
    {
437
    {
438
        // get the one-ring of v0
438
        // get the one-ring of v0
439
        vector<VertexID> link0;
439
        vector<VertexID> link0;
440
        circulate_vertex_ccw(m, v0, (std::function<void(VertexID)>)[&](VertexID vn) {
440
        circulate_vertex_ccw(m, v0, (std::function<void(VertexID)>)[&](VertexID vn) {
441
            link0.push_back(vn);
441
            link0.push_back(vn);
442
        });
442
        });
443
		
443
		
444
        // get the one-ring of v1
444
        // get the one-ring of v1
445
        vector<VertexID> link1;
445
        vector<VertexID> link1;
446
        circulate_vertex_ccw(m, v1, (std::function<void(VertexID)>)[&](VertexID vn) {
446
        circulate_vertex_ccw(m, v1, (std::function<void(VertexID)>)[&](VertexID vn) {
447
            link1.push_back(vn);
447
            link1.push_back(vn);
448
        });
448
        });
449
		
449
		
450
        // sort the vertices of the two rings
450
        // sort the vertices of the two rings
451
        sort(link0.begin(), link0.end());
451
        sort(link0.begin(), link0.end());
452
        sort(link1.begin(), link1.end());
452
        sort(link1.begin(), link1.end());
453
		
453
		
454
        // get the intersection of the shared vertices from both rings
454
        // get the intersection of the shared vertices from both rings
455
        std::back_insert_iterator<vector<VertexID> > lii(lisect);
455
        std::back_insert_iterator<vector<VertexID> > lii(lisect);
456
        set_intersection(link0.begin(), link0.end(),
456
        set_intersection(link0.begin(), link0.end(),
457
						 link1.begin(), link1.end(),
457
						 link1.begin(), link1.end(),
458
						 lii);
458
						 lii);
459
        
459
        
460
        return lisect.size();
460
        return lisect.size();
461
    }
461
    }
462
    
462
    
463
    bool Manifold::stitch_boundary_edges(HalfEdgeID h0, HalfEdgeID h1)
463
    bool Manifold::stitch_boundary_edges(HalfEdgeID h0, HalfEdgeID h1)
464
    {
464
    {
465
        // Cannot stitch an edge with itself
465
        // Cannot stitch an edge with itself
466
        if(h0 == h1)
466
        if(h0 == h1)
467
            return false;
467
            return false;
468
        
468
        
469
        // Only stitch a pair of boundary edges.
469
        // Only stitch a pair of boundary edges.
470
        if(kernel.face(h0) == InvalidFaceID && kernel.face(h1) == InvalidFaceID)
470
        if(kernel.face(h0) == InvalidFaceID && kernel.face(h1) == InvalidFaceID)
471
        {
471
        {
472
            HalfEdgeID h0o = kernel.opp(h0);
472
            HalfEdgeID h0o = kernel.opp(h0);
473
            HalfEdgeID h1o = kernel.opp(h1);
473
            HalfEdgeID h1o = kernel.opp(h1);
474
            VertexID v0a = kernel.vert(h0);
474
            VertexID v0a = kernel.vert(h0);
475
            VertexID v0b = kernel.vert(kernel.opp(h1));
475
            VertexID v0b = kernel.vert(kernel.opp(h1));
476
            VertexID v1b = kernel.vert(h1);
476
            VertexID v1b = kernel.vert(h1);
477
            VertexID v1a = kernel.vert(kernel.opp(h0));
477
            VertexID v1a = kernel.vert(kernel.opp(h0));
478
            
478
            
479
            // Case below implies that h0 and h1 are the same edge with different ID
479
            // Case below implies that h0 and h1 are the same edge with different ID
480
            // That should not happen.
480
            // That should not happen.
481
            assert(!(v0a == v0b && v1a == v1b));
481
            assert(!(v0a == v0b && v1a == v1b));
482
            
482
            
483
            if(connected(*this, v0a, v0b))
483
            if(connected(*this, v0a, v0b))
484
                return false;
484
                return false;
485
            if(connected(*this, v1a, v1b))
485
            if(connected(*this, v1a, v1b))
486
                return false;
486
                return false;
487
            
487
            
488
            
488
            
489
            if(v0b != v0a)
489
            if(v0b != v0a)
490
            {
490
            {
491
                
491
                
492
                // Check the link intersection v0a and v0b are welded together
492
                // Check the link intersection v0a and v0b are welded together
493
                // if they share a neighbouring vertex, it will appear twice in the combined
493
                // if they share a neighbouring vertex, it will appear twice in the combined
494
                // one ring unless it v1a and v1a==v1b
494
                // one ring unless it v1a and v1a==v1b
495
                vector<VertexID> lisect;
495
                vector<VertexID> lisect;
496
                if(link_intersection(*this, v0a, v0b, lisect))
496
                if(link_intersection(*this, v0a, v0b, lisect))
497
                {
497
                {
498
                    vector<VertexID>::iterator iter;
498
                    vector<VertexID>::iterator iter;
499
                    
499
                    
500
                    if(v1a == v1b)
500
                    if(v1a == v1b)
501
                    {
501
                    {
502
                        iter = find(lisect.begin(), lisect.end(), v1a);
502
                        iter = find(lisect.begin(), lisect.end(), v1a);
503
                        if(iter != lisect.end())
503
                        if(iter != lisect.end())
504
                            lisect.erase(iter);
504
                            lisect.erase(iter);
505
                    }
505
                    }
506
                    iter = find(lisect.begin(), lisect.end(), kernel.vert(kernel.next(h0)));
506
                    iter = find(lisect.begin(), lisect.end(), kernel.vert(kernel.next(h0)));
507
                    if(iter != lisect.end())
507
                    if(iter != lisect.end())
508
                        lisect.erase(iter);
508
                        lisect.erase(iter);
509
                    if(lisect.size() > 0)
509
                    if(lisect.size() > 0)
510
                        return false;
510
                        return false;
511
                }
511
                }
512
            }
512
            }
513
            
513
            
514
            if(v1a != v1b)
514
            if(v1a != v1b)
515
            {
515
            {
516
                // Check the same for the other endpoints.
516
                // Check the same for the other endpoints.
517
                vector<VertexID> lisect;
517
                vector<VertexID> lisect;
518
                if(link_intersection(*this, v1a, v1b, lisect))
518
                if(link_intersection(*this, v1a, v1b, lisect))
519
                {
519
                {
520
                    vector<VertexID>::iterator iter;
520
                    vector<VertexID>::iterator iter;
521
                    
521
                    
522
                    if(v0a == v0b)
522
                    if(v0a == v0b)
523
                    {
523
                    {
524
                        iter = find(lisect.begin(), lisect.end(), v1a);
524
                        iter = find(lisect.begin(), lisect.end(), v1a);
525
                        if(iter != lisect.end())
525
                        if(iter != lisect.end())
526
                            lisect.erase(iter);
526
                            lisect.erase(iter);
527
                    }
527
                    }
528
                    iter = find(lisect.begin(), lisect.end(), kernel.vert(kernel.next(h1)));
528
                    iter = find(lisect.begin(), lisect.end(), kernel.vert(kernel.next(h1)));
529
                    if(iter != lisect.end())
529
                    if(iter != lisect.end())
530
                        lisect.erase(iter);
530
                        lisect.erase(iter);
531
                    if(lisect.size() > 0)
531
                    if(lisect.size() > 0)
532
                        return false;
532
                        return false;
533
                }
533
                }
534
            }
534
            }
535
            
535
            
536
            
536
            
537
            if(v0b != v0a)
537
            if(v0b != v0a)
538
                circulate_vertex_ccw(*this, v0b, (std::function<void(Walker&)>)[&](Walker hew) {
538
                circulate_vertex_ccw(*this, v0b, (std::function<void(Walker&)>)[&](Walker hew) {
539
                    kernel.set_vert(hew.opp().halfedge(), v0a);
539
                    kernel.set_vert(hew.opp().halfedge(), v0a);
540
                });
540
                });
541
            
541
            
542
            if(v1b != v1a)
542
            if(v1b != v1a)
543
                circulate_vertex_ccw(*this, v1b, (std::function<void(Walker&)>)[&](Walker hew) {
543
                circulate_vertex_ccw(*this, v1b, (std::function<void(Walker&)>)[&](Walker hew) {
544
                    kernel.set_vert(hew.opp().halfedge(), v1a);
544
                    kernel.set_vert(hew.opp().halfedge(), v1a);
545
                });
545
                });
546
            
546
            
547
            if(v0a != v0b)
547
            if(v0a != v0b)
548
            {
548
            {
549
                HalfEdgeID h1p = kernel.prev(h1);
549
                HalfEdgeID h1p = kernel.prev(h1);
550
                HalfEdgeID h0n = kernel.next(h0);
550
                HalfEdgeID h0n = kernel.next(h0);
551
                
551
                
552
                if(kernel.next(h0n) == h1p)
552
                if(kernel.next(h0n) == h1p)
553
                {
553
                {
554
                    glue(kernel.opp(h0n), kernel.opp(h1p));
554
                    glue(kernel.opp(h0n), kernel.opp(h1p));
555
                    kernel.set_out(kernel.vert(h0n),kernel.opp(h0n));
555
                    kernel.set_out(kernel.vert(h0n),kernel.opp(h0n));
556
                    kernel.remove_halfedge(h0n);
556
                    kernel.remove_halfedge(h0n);
557
                    kernel.remove_halfedge(h1p);
557
                    kernel.remove_halfedge(h1p);
558
                }
558
                }
559
                else
559
                else
560
                    link(h1p, h0n);
560
                    link(h1p, h0n);
561
                kernel.remove_vertex(v0b);
561
                kernel.remove_vertex(v0b);
562
            }
562
            }
563
            
563
            
564
            if(v1a != v1b)
564
            if(v1a != v1b)
565
            {
565
            {
566
                HalfEdgeID h0p = kernel.prev(h0);
566
                HalfEdgeID h0p = kernel.prev(h0);
567
                HalfEdgeID h1n = kernel.next(h1);
567
                HalfEdgeID h1n = kernel.next(h1);
568
                if(kernel.next(h1n) == h0p)
568
                if(kernel.next(h1n) == h0p)
569
                {
569
                {
570
                    glue(kernel.opp(h0p), kernel.opp(h1n));
570
                    glue(kernel.opp(h0p), kernel.opp(h1n));
571
                    kernel.set_out(kernel.vert(h1n), kernel.opp(h1n));
571
                    kernel.set_out(kernel.vert(h1n), kernel.opp(h1n));
572
                    kernel.remove_halfedge(h0p);
572
                    kernel.remove_halfedge(h0p);
573
                    kernel.remove_halfedge(h1n);
573
                    kernel.remove_halfedge(h1n);
574
                }
574
                }
575
                else
575
                else
576
                    link(h0p, h1n);
576
                    link(h0p, h1n);
577
                kernel.remove_vertex(v1b);
577
                kernel.remove_vertex(v1b);
578
            }
578
            }
579
            glue(h0o, h1o);
579
            glue(h0o, h1o);
580
            
580
            
581
            kernel.remove_halfedge(h0);
581
            kernel.remove_halfedge(h0);
582
            kernel.remove_halfedge(h1);
582
            kernel.remove_halfedge(h1);
583
            
583
            
584
            kernel.set_out(v1a, h1o);
584
            kernel.set_out(v1a, h1o);
585
            kernel.set_out(v0a, h0o);
585
            kernel.set_out(v0a, h0o);
586
            
586
            
587
            ensure_boundary_consistency(v1a);
587
            ensure_boundary_consistency(v1a);
588
            ensure_boundary_consistency(v0a);
588
            ensure_boundary_consistency(v0a);
589
            
589
            
590
            return true;
590
            return true;
591
        }
591
        }
592
        return false;
592
        return false;
593
    }
593
    }
594
    
594
    
595
    
595
    
596
    
596
    
597
    FaceID Manifold::merge_one_ring(VertexID v, float max_loop_length)
597
    FaceID Manifold::merge_one_ring(VertexID v, float max_loop_length)
598
    {
598
    {
599
        // If the vertex is either not in use or has just
599
        // If the vertex is either not in use or has just
600
        // one incident edge (or less), bail out.
600
        // one incident edge (or less), bail out.
601
        int val = valency(*this,v);
601
        int val = valency(*this,v);
602
        if(!in_use(v) || val<2)
602
        if(!in_use(v) || val<2)
603
            return InvalidFaceID;
603
            return InvalidFaceID;
604
        
604
        
605
        // If the vertex is  a boundary vertex, we preparte the walker so that the
605
        // If the vertex is  a boundary vertex, we preparte the walker so that the
606
        // first face visited is not the invalid face outside the boundary. If the boundary
606
        // first face visited is not the invalid face outside the boundary. If the boundary
607
        // vertex is adjacent to only one vertex, there is little to do and we bail out.
607
        // vertex is adjacent to only one vertex, there is little to do and we bail out.
608
        bool vertex_is_boundary = false;
608
        bool vertex_is_boundary = false;
609
        Walker hew = walker(v);
609
        Walker hew = walker(v);
610
        if(boundary(*this, v))
610
        if(boundary(*this, v))
611
        {
611
        {
612
            if(val==2) return InvalidFaceID;
612
            if(val==2) return InvalidFaceID;
613
            vertex_is_boundary = true;
613
            vertex_is_boundary = true;
614
            hew = hew.circulate_vertex_ccw();
614
            hew = hew.circulate_vertex_ccw();
615
        }
615
        }
616
        
616
        
617
        // Prepare some vectors for taking out the trash: We remove all old faces and all orphaned edges
617
        // Prepare some vectors for taking out the trash: We remove all old faces and all orphaned edges
618
        // and vertices
618
        // and vertices
619
        vector<HalfEdgeID> garbage_halfedges;
619
        vector<HalfEdgeID> garbage_halfedges;
620
        vector<FaceID> garbage_faces;
620
        vector<FaceID> garbage_faces;
621
        vector<VertexID> garbage_vertices;
621
        vector<VertexID> garbage_vertices;
622
        
622
        
623
        vector<HalfEdgeID> loop; // The halfedges which form the outer loop of the merged one ring.
623
        vector<HalfEdgeID> loop; // The halfedges which form the outer loop of the merged one ring.
624
        
624
        
625
        // Below we loop over all faces adjacent to the vertex and add their halfedges to a big loop
625
        // Below we loop over all faces adjacent to the vertex and add their halfedges to a big loop
626
        // which will form the loop of the new merged face. Below we remove from the loop edges
626
        // which will form the loop of the new merged face. Below we remove from the loop edges
627
        // that appear twice (as each other's opposite).
627
        // that appear twice (as each other's opposite).
628
        for(;!hew.full_circle(); hew = hew.circulate_vertex_ccw())
628
        for(;!hew.full_circle(); hew = hew.circulate_vertex_ccw())
629
        {
629
        {
630
            garbage_faces.push_back(hew.face());
630
            garbage_faces.push_back(hew.face());
631
            for(Walker hew2 = walker(hew.halfedge());
631
            for(Walker hew2 = walker(hew.halfedge());
632
                !hew2.full_circle(); hew2 = hew2.circulate_face_ccw())
632
                !hew2.full_circle(); hew2 = hew2.circulate_face_ccw())
633
                loop.push_back(hew2.halfedge());
633
                loop.push_back(hew2.halfedge());
634
        }
634
        }
635
        
635
        
636
        
636
        
637
        // Now merge the loops. We iteratively remove pairs of adjacent halfedges from the loop
637
        // Now merge the loops. We iteratively remove pairs of adjacent halfedges from the loop
638
        // if we find that the second is the opposite of the first since this is a degenerate
638
        // if we find that the second is the opposite of the first since this is a degenerate
639
        // situation. However, we stop at four remaining halfedges since otherwise the loop degenerates
639
        // situation. However, we stop at four remaining halfedges since otherwise the loop degenerates
640
        // to zero after the next step if these four are also pairwise each other's opposites.
640
        // to zero after the next step if these four are also pairwise each other's opposites.
641
        int did_work;
641
        int did_work;
642
        do
642
        do
643
        {
643
        {
644
            did_work = 0;
644
            did_work = 0;
645
            vector<HalfEdgeID> loop_tmp(0);
645
            vector<HalfEdgeID> loop_tmp(0);
646
            for(size_t i=0;i<loop.size();++i)
646
            for(size_t i=0;i<loop.size();++i)
647
                if(walker(loop[i]).opp().halfedge() == loop[(i+1)%loop.size()])
647
                if(walker(loop[i]).opp().halfedge() == loop[(i+1)%loop.size()])
648
                {
648
                {
649
                    VertexID vid = walker(loop[i]).vertex();
649
                    VertexID vid = walker(loop[i]).vertex();
650
                    if(vid != v)
650
                    if(vid != v)
651
                        garbage_vertices.push_back(walker(loop[i]).vertex());
651
                        garbage_vertices.push_back(walker(loop[i]).vertex());
652
                    garbage_halfedges.push_back(loop[i]);
652
                    garbage_halfedges.push_back(loop[i]);
653
                    garbage_halfedges.push_back(loop[(i+1)%loop.size()]);
653
                    garbage_halfedges.push_back(loop[(i+1)%loop.size()]);
654
                    loop[i] = InvalidHalfEdgeID;
654
                    loop[i] = InvalidHalfEdgeID;
655
                    loop[(i+1)%loop.size()] = InvalidHalfEdgeID;
655
                    loop[(i+1)%loop.size()] = InvalidHalfEdgeID;
656
                    ++did_work;
656
                    ++did_work;
657
                    ++i;
657
                    ++i;
658
                }
658
                }
659
            for(size_t i=0;i<loop.size();++i)
659
            for(size_t i=0;i<loop.size();++i)
660
                if(loop[i] != InvalidHalfEdgeID)
660
                if(loop[i] != InvalidHalfEdgeID)
661
                    loop_tmp.push_back(loop[i]);
661
                    loop_tmp.push_back(loop[i]);
662
            loop = loop_tmp;
662
            loop = loop_tmp;
663
        } while(did_work > 0 && loop.size() > 4);
663
        } while(did_work > 0 && loop.size() > 4);
664
        
664
        
665
        // Check whether the loop is too long
665
        // Check whether the loop is too long
666
        float loop_len=0.0;
666
        float loop_len=0.0;
667
        for(size_t i=0;i<loop.size();++i)
667
        for(size_t i=0;i<loop.size();++i)
668
            loop_len += length(*this, loop[i]);
668
            loop_len += length(*this, loop[i]);
669
        if(loop_len > max_loop_length)
669
        if(loop_len > max_loop_length)
670
            return InvalidFaceID;
670
            return InvalidFaceID;
671
        
671
        
672
        // The following block checks wheteher the same halfedge appears twice. In this
672
        // The following block checks wheteher the same halfedge appears twice. In this
673
        // case we fail since it means that the one ring contains the same face twice.
673
        // case we fail since it means that the one ring contains the same face twice.
674
        vector<HalfEdgeID> loop_tmp = loop;
674
        vector<HalfEdgeID> loop_tmp = loop;
675
        sort(loop_tmp.begin(), loop_tmp.end());
675
        sort(loop_tmp.begin(), loop_tmp.end());
676
        vector<HalfEdgeID>::iterator end_iter = unique(loop_tmp.begin(), loop_tmp.end());
676
        vector<HalfEdgeID>::iterator end_iter = unique(loop_tmp.begin(), loop_tmp.end());
677
        if(end_iter != loop_tmp.end())
677
        if(end_iter != loop_tmp.end())
678
            return InvalidFaceID;
678
            return InvalidFaceID;
679
        
679
        
680
        // Remove all faces and connected halfedges and the original vertex v.
680
        // Remove all faces and connected halfedges and the original vertex v.
681
        for(size_t i=0;i<garbage_vertices.size(); ++i)
681
        for(size_t i=0;i<garbage_vertices.size(); ++i)
682
            kernel.remove_vertex(garbage_vertices[i]);
682
            kernel.remove_vertex(garbage_vertices[i]);
683
        for(size_t i=0;i<garbage_faces.size(); ++i)
683
        for(size_t i=0;i<garbage_faces.size(); ++i)
684
            kernel.remove_face(garbage_faces[i]);
684
            kernel.remove_face(garbage_faces[i]);
685
        for(size_t i=0;i<garbage_halfedges.size(); ++i)
685
        for(size_t i=0;i<garbage_halfedges.size(); ++i)
686
            kernel.remove_halfedge(garbage_halfedges[i]);
686
            kernel.remove_halfedge(garbage_halfedges[i]);
687
        if(!vertex_is_boundary)
687
        if(!vertex_is_boundary)
688
            kernel.remove_vertex(v);
688
            kernel.remove_vertex(v);
689
        
689
        
690
        // Create a new face for the merged one ring and link up all the halfedges
690
        // Create a new face for the merged one ring and link up all the halfedges
691
        // in the loop
691
        // in the loop
692
        FaceID f = kernel.add_face();
692
        FaceID f = kernel.add_face();
693
        kernel.set_last(f,loop[0]);
693
        kernel.set_last(f,loop[0]);
694
        for(size_t i=0;i<loop.size(); ++i)
694
        for(size_t i=0;i<loop.size(); ++i)
695
        {
695
        {
696
            kernel.set_face(loop[i], f);
696
            kernel.set_face(loop[i], f);
697
            Walker hw = walker(loop[i]);
697
            Walker hw = walker(loop[i]);
698
            kernel.set_out(hw.vertex(),hw.opp().halfedge());
698
            kernel.set_out(hw.vertex(),hw.opp().halfedge());
699
            link(loop[i],loop[(i+1)%loop.size()]);
699
            link(loop[i],loop[(i+1)%loop.size()]);
700
            assert(hw.vertex() == walker(loop[(i+1)%loop.size()]).opp().vertex());
700
            assert(hw.vertex() == walker(loop[(i+1)%loop.size()]).opp().vertex());
701
        }
701
        }
702
        
702
        
703
        // Finally, we ensure boundary consitency for all vertices in the loop.
703
        // Finally, we ensure boundary consitency for all vertices in the loop.
704
        for(size_t i=0;i<loop.size(); ++i)
704
        for(size_t i=0;i<loop.size(); ++i)
705
        {
705
        {
706
            Walker hw = walker(loop[i]);
706
            Walker hw = walker(loop[i]);
707
            ensure_boundary_consistency(hw.vertex());
707
            ensure_boundary_consistency(hw.vertex());
708
        }
708
        }
709
        
709
        
710
        // Return the brand new merged face.
710
        // Return the brand new merged face.
711
        return f;
711
        return f;
712
    }
712
    }
713
    
713
    
714
    
714
    
715
    
715
    
716
    bool Manifold::merge_faces(FaceID f, HalfEdgeID h)
716
    bool Manifold::merge_faces(FaceID f, HalfEdgeID h)
717
    {
717
    {
718
        //assert that we're merging a valid face with the corresponding halfedge
718
        //assert that we're merging a valid face with the corresponding halfedge
719
        assert(kernel.face(h) == f);
719
        assert(kernel.face(h) == f);
720
        
720
        
721
        HalfEdgeID ho = kernel.opp(h);
721
        HalfEdgeID ho = kernel.opp(h);
722
        FaceID fo = kernel.face(ho);
722
        FaceID fo = kernel.face(ho);
723
        HalfEdgeID hn = kernel.next(h);
723
        HalfEdgeID hn = kernel.next(h);
724
        HalfEdgeID hon = kernel.next(ho);
724
        HalfEdgeID hon = kernel.next(ho);
725
        
725
        
726
        if(fo == f)
726
        if(fo == f)
727
            return false;
727
            return false;
728
        
728
        
729
        //boundary case
729
        //boundary case
730
        if(kernel.vert(hn) == kernel.vert(hon))
730
        if(kernel.vert(hn) == kernel.vert(hon))
731
            return false;
731
            return false;
732
        
732
        
733
        HalfEdgeID hp = kernel.prev(h);
733
        HalfEdgeID hp = kernel.prev(h);
734
        HalfEdgeID hop = kernel.prev(ho);
734
        HalfEdgeID hop = kernel.prev(ho);
735
        VertexID v = kernel.vert(h);
735
        VertexID v = kernel.vert(h);
736
        VertexID vo = kernel.vert(ho);
736
        VertexID vo = kernel.vert(ho);
737
        
737
        
738
        if(valency(*this, v) < 3 || valency(*this, vo) < 3)
738
        if(valency(*this, v) < 3 || valency(*this, vo) < 3)
739
            return false;
739
            return false;
740
        
740
        
741
        link(hop, hn);
741
        link(hop, hn);
742
        link(hp, hon);
742
        link(hp, hon);
743
        kernel.set_out(vo, hon);
743
        kernel.set_out(vo, hon);
744
        kernel.set_out(v, hn);
744
        kernel.set_out(v, hn);
745
        kernel.set_last(f, hn);
745
        kernel.set_last(f, hn);
746
        
746
        
747
        HalfEdgeID hx = hon;
747
        HalfEdgeID hx = hon;
748
        
748
        
749
        assert(kernel.face(hx) == fo);
749
        assert(kernel.face(hx) == fo);
750
        while(kernel.face(hx) != f){
750
        while(kernel.face(hx) != f){
751
            kernel.set_face(hx, f);
751
            kernel.set_face(hx, f);
752
            hx = kernel.next(hx);
752
            hx = kernel.next(hx);
753
        }
753
        }
754
        
754
        
755
        ensure_boundary_consistency(v);
755
        ensure_boundary_consistency(v);
756
        ensure_boundary_consistency(vo);
756
        ensure_boundary_consistency(vo);
757
        
757
        
758
        kernel.remove_halfedge(h);
758
        kernel.remove_halfedge(h);
759
        kernel.remove_halfedge(ho);
759
        kernel.remove_halfedge(ho);
760
        kernel.remove_face(fo);
760
        kernel.remove_face(fo);
761
        
761
        
762
        return true;
762
        return true;
763
    }
763
    }
764
    
764
    
765
    FaceID Manifold::close_hole(HalfEdgeID h)
765
    FaceID Manifold::close_hole(HalfEdgeID h)
766
    {
766
    {
767
        // invalid face is a hole
767
        // invalid face is a hole
768
        if(kernel.face(h) == InvalidFaceID){
768
        if(kernel.face(h) == InvalidFaceID){
769
            FaceID f = kernel.add_face();
769
            FaceID f = kernel.add_face();
770
            kernel.set_last(f, h);
770
            kernel.set_last(f, h);
771
            do{
771
            do{
772
                kernel.set_face(h, f);
772
                kernel.set_face(h, f);
773
                h = kernel.next(h);
773
                h = kernel.next(h);
774
            }
774
            }
775
            while(kernel.face(h) != f);
775
            while(kernel.face(h) != f);
776
            return f;
776
            return f;
777
        }
777
        }
778
        return kernel.face(h);
778
        return kernel.face(h);
779
    }
779
    }
780
    
780
    
781
    VertexID Manifold::slit_vertex(VertexID v, HalfEdgeID h_in, HalfEdgeID h_out)
781
    VertexID Manifold::slit_vertex(VertexID v, HalfEdgeID h_in, HalfEdgeID h_out)
782
    {
782
    {
783
        assert(kernel.face(h_in) != InvalidFaceID);
783
        assert(kernel.face(h_in) != InvalidFaceID);
784
        assert(kernel.face(h_out) != InvalidFaceID);
784
        assert(kernel.face(h_out) != InvalidFaceID);
785
        assert(kernel.opp(h_out) != h_in);
785
        assert(kernel.opp(h_out) != h_in);
786
        
786
        
787
        VertexID v_new = kernel.add_vertex();
787
        VertexID v_new = kernel.add_vertex();
788
        pos(v_new) = pos(v);
788
        pos(v_new) = pos(v);
789
        HalfEdgeID h = kernel.prev(h_out);
789
        HalfEdgeID h = kernel.prev(h_out);
790
        kernel.set_vert(h, v_new);
790
        kernel.set_vert(h, v_new);
791
        while ( h != h_in) {
791
        while ( h != h_in) {
792
            h = kernel.prev(kernel.opp(h));
792
            h = kernel.prev(kernel.opp(h));
793
            kernel.set_vert(h, v_new);
793
            kernel.set_vert(h, v_new);
794
        }
794
        }
795
        
795
        
796
        HalfEdgeID h_in_opp = kernel.opp(h_in);
796
        HalfEdgeID h_in_opp = kernel.opp(h_in);
797
        HalfEdgeID hn_in, hn_in_opp;
797
        HalfEdgeID hn_in, hn_in_opp;
798
        if(kernel.face(h_in_opp) != InvalidFaceID)
798
        if(kernel.face(h_in_opp) != InvalidFaceID)
799
        {
799
        {
800
            hn_in = kernel.add_halfedge();
800
            hn_in = kernel.add_halfedge();
801
            kernel.set_face(hn_in, InvalidFaceID);
801
            kernel.set_face(hn_in, InvalidFaceID);
802
            glue(h_in_opp, hn_in);
802
            glue(h_in_opp, hn_in);
803
            
803
            
804
            hn_in_opp = kernel.add_halfedge();
804
            hn_in_opp = kernel.add_halfedge();
805
            kernel.set_face(hn_in_opp, InvalidFaceID);
805
            kernel.set_face(hn_in_opp, InvalidFaceID);
806
            glue(h_in, hn_in_opp);
806
            glue(h_in, hn_in_opp);
807
            
807
            
808
            link(hn_in_opp, hn_in);
808
            link(hn_in_opp, hn_in);
809
            
809
            
810
            VertexID v_i = kernel.vert(h_in_opp);
810
            VertexID v_i = kernel.vert(h_in_opp);
811
            kernel.set_vert(hn_in_opp, v_i);
811
            kernel.set_vert(hn_in_opp, v_i);
812
            kernel.set_out(v_i, hn_in);
812
            kernel.set_out(v_i, hn_in);
813
        }
813
        }
814
        else
814
        else
815
        {
815
        {
816
            hn_in_opp = h_in_opp;
816
            hn_in_opp = h_in_opp;
817
            hn_in = kernel.prev(hn_in_opp);
817
            hn_in = kernel.prev(hn_in_opp);
818
            h_in_opp = kernel.opp(hn_in);
818
            h_in_opp = kernel.opp(hn_in);
819
        }
819
        }
820
        
820
        
821
        HalfEdgeID h_out_opp = kernel.opp(h_out);
821
        HalfEdgeID h_out_opp = kernel.opp(h_out);
822
        HalfEdgeID hn_out,hn_out_opp;
822
        HalfEdgeID hn_out,hn_out_opp;
823
        if(kernel.face(h_out_opp) != InvalidFaceID)
823
        if(kernel.face(h_out_opp) != InvalidFaceID)
824
        {
824
        {
825
            hn_out = kernel.add_halfedge();
825
            hn_out = kernel.add_halfedge();
826
            kernel.set_face(hn_out, InvalidFaceID);
826
            kernel.set_face(hn_out, InvalidFaceID);
827
            glue(h_out_opp, hn_out);
827
            glue(h_out_opp, hn_out);
828
            
828
            
829
            hn_out_opp = kernel.add_halfedge();
829
            hn_out_opp = kernel.add_halfedge();
830
            kernel.set_face(hn_out_opp, InvalidFaceID);
830
            kernel.set_face(hn_out_opp, InvalidFaceID);
831
            glue(h_out, hn_out_opp);
831
            glue(h_out, hn_out_opp);
832
 
832
 
833
            link(hn_out, hn_out_opp);
833
            link(hn_out, hn_out_opp);
834
 
834
 
835
            VertexID v_o = kernel.vert(h_out);
835
            VertexID v_o = kernel.vert(h_out);
836
            kernel.set_vert(hn_out, v_o);
836
            kernel.set_vert(hn_out, v_o);
837
            kernel.set_out(v_o, hn_out_opp);
837
            kernel.set_out(v_o, hn_out_opp);
838
        }
838
        }
839
        else
839
        else
840
        {
840
        {
841
            hn_out_opp = h_out_opp;
841
            hn_out_opp = h_out_opp;
842
            hn_out = kernel.next(hn_out_opp);
842
            hn_out = kernel.next(hn_out_opp);
843
            h_out_opp = kernel.opp(hn_out);
843
            h_out_opp = kernel.opp(hn_out);
844
        }
844
        }
845
        
845
        
846
        link(hn_out_opp, hn_in_opp);
846
        link(hn_out_opp, hn_in_opp);
847
        link(hn_in, hn_out);
847
        link(hn_in, hn_out);
848
        
848
        
849
        kernel.set_vert(hn_in, v);
849
        kernel.set_vert(hn_in, v);
850
        kernel.set_vert(hn_out_opp, v_new);
850
        kernel.set_vert(hn_out_opp, v_new);
851
        
851
        
852
        kernel.set_out(v, hn_out);
852
        kernel.set_out(v, hn_out);
853
        kernel.set_out(v_new, hn_in_opp);
853
        kernel.set_out(v_new, hn_in_opp);
854
        
854
        
855
        return v_new;
855
        return v_new;
856
    }
856
    }
857
 
857
 
858
    
858
    
859
    HalfEdgeID Manifold::slit_edges(VertexAttributeVector<int>& insel)
859
    HalfEdgeID Manifold::slit_edges(VertexAttributeVector<int>& insel)
860
    {
860
    {
-
 
861
        HalfEdgeID h;
861
        for(auto vid : vertices())
862
        for(auto vid : vertices())
862
        {
863
        {
863
            if(insel[vid])
864
            if(insel[vid])
864
            {
865
            {
865
                HalfEdgeID h_in = InvalidHalfEdgeID, h_out = InvalidHalfEdgeID;
866
                HalfEdgeID h_in = InvalidHalfEdgeID, h_out = InvalidHalfEdgeID;
866
                Walker w = walker(vid);
867
                Walker w = walker(vid);
867
                while(!w.full_circle())
868
                while(!w.full_circle())
868
                {
869
                {
869
                    if(insel[w.vertex()]) {
870
                    if(insel[w.vertex()]) {
870
                        if(h_in == InvalidHalfEdgeID) {
871
                        if(h_in == InvalidHalfEdgeID) {
871
                            if(w.opp().face() == InvalidFaceID)
872
                            if(w.opp().face() == InvalidFaceID)
872
                                h_in = w.opp().next().opp().halfedge();
873
                                h_in = w.opp().next().opp().halfedge();
873
                            else
874
                            else
874
                                h_in = w.opp().halfedge();
875
                                h_in = w.opp().halfedge();
875
                        }
876
                        }
876
                        else {
877
                        else {
877
                            if(w.face() == InvalidFaceID)
878
                            if(w.face() == InvalidFaceID)
878
                                h_out = w.prev().opp().halfedge();
879
                                h_out = w.prev().opp().halfedge();
879
                            else
880
                            else
880
                                h_out = w.halfedge();
881
                                h_out = w.halfedge();
881
                            break;
882
                            break;
882
                        }
883
                        }
883
                    }
884
                    }
884
                    w = w.circulate_vertex_ccw();
885
                    w = w.circulate_vertex_ccw();
885
                }
886
                }
886
                if(h_in != InvalidHalfEdgeID &&
887
                if(h_in != InvalidHalfEdgeID &&
887
                   h_out != InvalidHalfEdgeID) {
888
                   h_out != InvalidHalfEdgeID) {
888
                    VertexID v_new = slit_vertex(vid, h_in, h_out);
889
                    VertexID v_new = slit_vertex(vid, h_in, h_out);
-
 
890
                    h = walker(v_new).halfedge();
889
                    	}
891
                }
890
            }
892
            }
891
        }
893
        }
-
 
894
        return h;
892
    }
895
    }
893
 
896
 
894
    
897
    
895
    void Manifold::flip_edge(HalfEdgeID h)
898
    void Manifold::flip_edge(HalfEdgeID h)
896
    {
899
    {
897
        HalfEdgeID hn = kernel.next(h);
900
        HalfEdgeID hn = kernel.next(h);
898
        HalfEdgeID hp = kernel.prev(h);
901
        HalfEdgeID hp = kernel.prev(h);
899
        HalfEdgeID ho = kernel.opp(h);
902
        HalfEdgeID ho = kernel.opp(h);
900
        HalfEdgeID hon = kernel.next(ho);
903
        HalfEdgeID hon = kernel.next(ho);
901
        HalfEdgeID hop = kernel.prev(ho);
904
        HalfEdgeID hop = kernel.prev(ho);
902
        
905
        
903
        FaceID hf = kernel.face(h);
906
        FaceID hf = kernel.face(h);
904
        FaceID hof = kernel.face(ho);
907
        FaceID hof = kernel.face(ho);
905
        
908
        
906
        VertexID hv = kernel.vert(h);
909
        VertexID hv = kernel.vert(h);
907
        VertexID hnv = kernel.vert(hn);
910
        VertexID hnv = kernel.vert(hn);
908
        VertexID hov = kernel.vert(ho);
911
        VertexID hov = kernel.vert(ho);
909
        VertexID honv = kernel.vert(hon);
912
        VertexID honv = kernel.vert(hon);
910
        
913
        
911
        // update face connectivity of halfedges changing face
914
        // update face connectivity of halfedges changing face
912
        kernel.set_face(hop, hf);
915
        kernel.set_face(hop, hf);
913
        kernel.set_face(hp, hof);
916
        kernel.set_face(hp, hof);
914
        
917
        
915
        // connectivity of faces with halfedges of flipped edge
918
        // connectivity of faces with halfedges of flipped edge
916
        kernel.set_last(hf, h);
919
        kernel.set_last(hf, h);
917
        kernel.set_last(hof, ho);
920
        kernel.set_last(hof, ho);
918
        
921
        
919
        // connectivity of halfedges of first face after flip
922
        // connectivity of halfedges of first face after flip
920
        link(hn, h);
923
        link(hn, h);
921
        link(h, hop);
924
        link(h, hop);
922
        link(hop, hn);
925
        link(hop, hn);
923
        
926
        
924
        // connectivity of halfedges of second face after flip
927
        // connectivity of halfedges of second face after flip
925
        link(hon, ho);
928
        link(hon, ho);
926
        link(ho, hp);
929
        link(ho, hp);
927
        link(hp, hon);
930
        link(hp, hon);
928
        
931
        
929
        // connectivity of flipped edge and corresponding vertices
932
        // connectivity of flipped edge and corresponding vertices
930
        kernel.set_vert(h, honv);
933
        kernel.set_vert(h, honv);
931
        kernel.set_vert(ho, hnv);
934
        kernel.set_vert(ho, hnv);
932
        
935
        
933
        if(kernel.out(hv) == ho)
936
        if(kernel.out(hv) == ho)
934
            kernel.set_out(hv, hn);
937
            kernel.set_out(hv, hn);
935
        if(kernel.out(hov) == h)
938
        if(kernel.out(hov) == h)
936
            kernel.set_out(hov, hon);
939
            kernel.set_out(hov, hon);
937
        
940
        
938
        //
941
        //
939
        //        // if the flip occurs next to a boundary, ensure the boundary consistency
942
        //        // if the flip occurs next to a boundary, ensure the boundary consistency
940
        //        ensure_boundary_consistency(hv);
943
        //        ensure_boundary_consistency(hv);
941
        //        ensure_boundary_consistency(hov);
944
        //        ensure_boundary_consistency(hov);
942
    }
945
    }
943
    
946
    
944
    
947
    
945
    /**********************************************
948
    /**********************************************
946
     * Private functions
949
     * Private functions
947
     **********************************************/
950
     **********************************************/
948
    
951
    
949
    template<typename size_type, typename float_type, typename int_type>
952
    template<typename size_type, typename float_type, typename int_type>
950
    void Manifold::build_template(  size_type no_vertices,
953
    void Manifold::build_template(  size_type no_vertices,
951
                                  const float_type* vertvec,
954
                                  const float_type* vertvec,
952
                                  size_type no_faces,
955
                                  size_type no_faces,
953
                                  const int_type* facevec,
956
                                  const int_type* facevec,
954
                                  const int_type* indices)
957
                                  const int_type* indices)
955
    {
958
    {
956
        vector<VertexID> vids(no_vertices);
959
        vector<VertexID> vids(no_vertices);
957
        
960
        
958
        // create vertices corresponding to positions stored in vertvec
961
        // create vertices corresponding to positions stored in vertvec
959
        for(size_t i=0;i<no_vertices;++i)
962
        for(size_t i=0;i<no_vertices;++i)
960
        {
963
        {
961
            const float_type* v0 = &vertvec[i*3];
964
            const float_type* v0 = &vertvec[i*3];
962
            pos(vids[i] = kernel.add_vertex()) = Manifold::Vec(v0[0], v0[1], v0[2]);
965
            pos(vids[i] = kernel.add_vertex()) = Manifold::Vec(v0[0], v0[1], v0[2]);
963
        }
966
        }
964
        
967
        
965
        //map over the created edges - needed to preserve edge uniqueness
968
        //map over the created edges - needed to preserve edge uniqueness
966
        typedef map<EdgeKey, Edge> EdgeMap;
969
        typedef map<EdgeKey, Edge> EdgeMap;
967
        EdgeMap edge_map;
970
        EdgeMap edge_map;
968
        
971
        
969
        // counter that jumps between faces in indices vector
972
        // counter that jumps between faces in indices vector
970
        int_type n  = 0;
973
        int_type n  = 0;
971
        
974
        
972
        // create faces correspponding to faces stored in facevec
975
        // create faces correspponding to faces stored in facevec
973
        for(size_type i = 0; i < no_faces; ++i){
976
        for(size_type i = 0; i < no_faces; ++i){
974
            //amount of vertices in current face
977
            //amount of vertices in current face
975
            size_type N = facevec[i];
978
            size_type N = facevec[i];
976
            vector<HalfEdgeID> fh;
979
            vector<HalfEdgeID> fh;
977
            
980
            
978
            //each face indice results corresponds to 1 edge, 2 halfedges
981
            //each face indice results corresponds to 1 edge, 2 halfedges
979
            for(size_type j = 0; j < N; ++j){
982
            for(size_type j = 0; j < N; ++j){
980
                // ensure indice integrity
983
                // ensure indice integrity
981
                
984
                
982
                assert(static_cast<size_type>(indices[j + n]) < no_vertices);
985
                assert(static_cast<size_type>(indices[j + n]) < no_vertices);
983
                assert(static_cast<size_type>(indices[(j + 1) % N + n]) < no_vertices);
986
                assert(static_cast<size_type>(indices[(j + 1) % N + n]) < no_vertices);
984
                
987
                
985
                
988
                
986
                // each iteration uses two indices from the face
989
                // each iteration uses two indices from the face
987
                VertexID v0 = vids[static_cast<size_type>(indices[j + n])];
990
                VertexID v0 = vids[static_cast<size_type>(indices[j + n])];
988
                VertexID v1 = vids[static_cast<size_type>(indices[(j + 1) % N + n])];
991
                VertexID v1 = vids[static_cast<size_type>(indices[(j + 1) % N + n])];
989
                
992
                
990
                // create key and search map for edge
993
                // create key and search map for edge
991
                EdgeKey ek(v0, v1);
994
                EdgeKey ek(v0, v1);
992
                EdgeMap::iterator em_iter = edge_map.find(ek);
995
                EdgeMap::iterator em_iter = edge_map.find(ek);
993
                
996
                
994
                // current edge has not been created
997
                // current edge has not been created
995
                if(em_iter == edge_map.end()){
998
                if(em_iter == edge_map.end()){
996
                    // create edge for map
999
                    // create edge for map
997
                    Edge e;
1000
                    Edge e;
998
                    e.h0 = kernel.add_halfedge();
1001
                    e.h0 = kernel.add_halfedge();
999
                    e.h1 = kernel.add_halfedge();
1002
                    e.h1 = kernel.add_halfedge();
1000
                    e.count = 1;
1003
                    e.count = 1;
1001
                    
1004
                    
1002
                    // glue operation: 1 edge = 2 glued halfedges
1005
                    // glue operation: 1 edge = 2 glued halfedges
1003
                    glue(e.h0, e.h1);
1006
                    glue(e.h0, e.h1);
1004
                    
1007
                    
1005
                    // update vertices with their outgoing halfedges
1008
                    // update vertices with their outgoing halfedges
1006
                    kernel.set_out(v0, e.h0);
1009
                    kernel.set_out(v0, e.h0);
1007
                    kernel.set_out(v1, e.h1);
1010
                    kernel.set_out(v1, e.h1);
1008
                    
1011
                    
1009
                    // update halfedges with the vertices they point to
1012
                    // update halfedges with the vertices they point to
1010
                    kernel.set_vert(e.h0, v1);
1013
                    kernel.set_vert(e.h0, v1);
1011
                    kernel.set_vert(e.h1, v0);
1014
                    kernel.set_vert(e.h1, v0);
1012
                    
1015
                    
1013
                    // update map
1016
                    // update map
1014
                    edge_map[ek] = e;
1017
                    edge_map[ek] = e;
1015
                    
1018
                    
1016
                    // update vector of halfedges belonging to current face
1019
                    // update vector of halfedges belonging to current face
1017
                    fh.push_back(e.h0);
1020
                    fh.push_back(e.h0);
1018
                }
1021
                }
1019
                else{
1022
                else{
1020
                    // update current face with halfedge from edge
1023
                    // update current face with halfedge from edge
1021
                    fh.push_back(em_iter->second.h1);
1024
                    fh.push_back(em_iter->second.h1);
1022
                    
1025
                    
1023
                    // asserting that a halfedge is visited exactly twice;
1026
                    // asserting that a halfedge is visited exactly twice;
1024
                    // once for each face on either side of the edge.
1027
                    // once for each face on either side of the edge.
1025
                    em_iter->second.count++;
1028
                    em_iter->second.count++;
1026
                    assert(em_iter->second.count == 2);
1029
                    assert(em_iter->second.count == 2);
1027
                }
1030
                }
1028
            }
1031
            }
1029
            
1032
            
1030
            FaceID fid = kernel.add_face();
1033
            FaceID fid = kernel.add_face();
1031
            for(size_type j = 0; j < N; ++j){
1034
            for(size_type j = 0; j < N; ++j){
1032
                // update halfedge with face
1035
                // update halfedge with face
1033
                kernel.set_face(fh[j], fid);
1036
                kernel.set_face(fh[j], fid);
1034
                
1037
                
1035
                // link operation: link two halfedges in the same face
1038
                // link operation: link two halfedges in the same face
1036
                link(fh[j], fh[(j + 1) % N]);
1039
                link(fh[j], fh[(j + 1) % N]);
1037
            }
1040
            }
1038
            //update face with the first halfedge created
1041
            //update face with the first halfedge created
1039
            kernel.set_last(fid, fh[0]);
1042
            kernel.set_last(fid, fh[0]);
1040
            
1043
            
1041
            // step to first index of next face
1044
            // step to first index of next face
1042
            n += N;
1045
            n += N;
1043
        }
1046
        }
1044
        
1047
        
1045
        // test for unused vertices
1048
        // test for unused vertices
1046
        for(VertexIDIterator v = vertices_begin(); v != vertices_end(); ++v){
1049
        for(VertexIDIterator v = vertices_begin(); v != vertices_end(); ++v){
1047
            assert( (*v) != InvalidVertexID);
1050
            assert( (*v) != InvalidVertexID);
1048
            if(kernel.out(*v) == InvalidHalfEdgeID)
1051
            if(kernel.out(*v) == InvalidHalfEdgeID)
1049
                kernel.remove_vertex(*v);
1052
                kernel.remove_vertex(*v);
1050
        }
1053
        }
1051
        
1054
        
1052
        // boundary check while avoiding unused vertices
1055
        // boundary check while avoiding unused vertices
1053
        for(VertexIDIterator v = vertices_begin(); v != vertices_end(); ++v){
1056
        for(VertexIDIterator v = vertices_begin(); v != vertices_end(); ++v){
1054
            if((*v) != InvalidVertexID)
1057
            if((*v) != InvalidVertexID)
1055
                ensure_boundary_consistency(*v);
1058
                ensure_boundary_consistency(*v);
1056
        }
1059
        }
1057
    }
1060
    }
1058
    void Manifold::link(HalfEdgeID h0, HalfEdgeID h1)
1061
    void Manifold::link(HalfEdgeID h0, HalfEdgeID h1)
1059
    {
1062
    {
1060
        kernel.set_next(h0, h1);
1063
        kernel.set_next(h0, h1);
1061
        kernel.set_prev(h1, h0);
1064
        kernel.set_prev(h1, h0);
1062
    }
1065
    }
1063
    void Manifold::glue(HalfEdgeID h0, HalfEdgeID h1)
1066
    void Manifold::glue(HalfEdgeID h0, HalfEdgeID h1)
1064
    {
1067
    {
1065
        kernel.set_opp(h0, h1);
1068
        kernel.set_opp(h0, h1);
1066
        kernel.set_opp(h1, h0);
1069
        kernel.set_opp(h1, h0);
1067
    }
1070
    }
1068
    void Manifold::ensure_boundary_consistency(VertexID v)
1071
    void Manifold::ensure_boundary_consistency(VertexID v)
1069
    {
1072
    {
1070
        // boundary consistency check by performing two vertex circulations
1073
        // boundary consistency check by performing two vertex circulations
1071
        HalfEdgeID h = kernel.out(v);
1074
        HalfEdgeID h = kernel.out(v);
1072
        HalfEdgeID last = h;
1075
        HalfEdgeID last = h;
1073
        
1076
        
1074
        // step 1: circle through edges pointing away from vertex until reaching a null face
1077
        // step 1: circle through edges pointing away from vertex until reaching a null face
1075
        while(kernel.face(h) != InvalidFaceID){
1078
        while(kernel.face(h) != InvalidFaceID){
1076
            h = kernel.opp(kernel.prev(h));
1079
            h = kernel.opp(kernel.prev(h));
1077
            if(h == last) // We came full circle - vertex not boundary - return.
1080
            if(h == last) // We came full circle - vertex not boundary - return.
1078
                return;
1081
                return;
1079
        }
1082
        }
1080
        // null face encountered, we update our vertex with half edge index and prepare for step 2
1083
        // null face encountered, we update our vertex with half edge index and prepare for step 2
1081
        kernel.set_out(v, h);
1084
        kernel.set_out(v, h);
1082
        HalfEdgeID ho = kernel.opp(h);
1085
        HalfEdgeID ho = kernel.opp(h);
1083
        
1086
        
1084
        // step 2: circle through edges pointing towards vertex until reaching a null face
1087
        // step 2: circle through edges pointing towards vertex until reaching a null face
1085
        while(kernel.face(ho) != InvalidFaceID){
1088
        while(kernel.face(ho) != InvalidFaceID){
1086
            ho = kernel.opp(kernel.next(ho));
1089
            ho = kernel.opp(kernel.next(ho));
1087
        }
1090
        }
1088
        // null face encountered again, we update our edge with vertex index
1091
        // null face encountered again, we update our edge with vertex index
1089
        kernel.set_vert(ho, v);
1092
        kernel.set_vert(ho, v);
1090
        
1093
        
1091
        // remaining step is to make the in and out going edges link to each other
1094
        // remaining step is to make the in and out going edges link to each other
1092
        link(ho, h);
1095
        link(ho, h);
1093
    }
1096
    }
1094
    void Manifold::remove_face_if_degenerate(HalfEdgeID h)
1097
    void Manifold::remove_face_if_degenerate(HalfEdgeID h)
1095
    {
1098
    {
1096
        // face is degenerate if there is only two halfedges in face loop
1099
        // face is degenerate if there is only two halfedges in face loop
1097
        if(kernel.next(kernel.next(h)) == h)
1100
        if(kernel.next(kernel.next(h)) == h)
1098
        {
1101
        {
1099
            HalfEdgeID hn = kernel.next(h);
1102
            HalfEdgeID hn = kernel.next(h);
1100
            HalfEdgeID ho = kernel.opp(h);
1103
            HalfEdgeID ho = kernel.opp(h);
1101
            HalfEdgeID hno = kernel.opp(hn);
1104
            HalfEdgeID hno = kernel.opp(hn);
1102
            VertexID hv = kernel.vert(h);
1105
            VertexID hv = kernel.vert(h);
1103
            VertexID hnv = kernel.vert(hn);
1106
            VertexID hnv = kernel.vert(hn);
1104
            FaceID f = kernel.face(h);
1107
            FaceID f = kernel.face(h);
1105
            
1108
            
1106
            assert(ho != hn);
1109
            assert(ho != hn);
1107
            assert(h != hno);
1110
            assert(h != hno);
1108
            assert(hv != hnv);
1111
            assert(hv != hnv);
1109
            
1112
            
1110
            // glue opposite halfedge to halfedge opposite next halfedge, obsoleting h and hn from loop
1113
            // glue opposite halfedge to halfedge opposite next halfedge, obsoleting h and hn from loop
1111
            glue(ho, hno);
1114
            glue(ho, hno);
1112
            
1115
            
1113
            // make v and vn point to opposite and next opposite halfedge, obsoleting h and hn from loop
1116
            // make v and vn point to opposite and next opposite halfedge, obsoleting h and hn from loop
1114
            kernel.set_out(hnv, hno);
1117
            kernel.set_out(hnv, hno);
1115
            kernel.set_out(hv, ho);
1118
            kernel.set_out(hv, ho);
1116
            
1119
            
1117
            // if face owning h is valid, remove face
1120
            // if face owning h is valid, remove face
1118
            if(f != InvalidFaceID)
1121
            if(f != InvalidFaceID)
1119
                kernel.remove_face(f);
1122
                kernel.remove_face(f);
1120
            // remove the two invalid halfedges and the invalid face loop
1123
            // remove the two invalid halfedges and the invalid face loop
1121
            kernel.remove_halfedge(h);
1124
            kernel.remove_halfedge(h);
1122
            kernel.remove_halfedge(hn);
1125
            kernel.remove_halfedge(hn);
1123
            
1126
            
1124
            // verify that v and vn is sane after removing the degenerate face
1127
            // verify that v and vn is sane after removing the degenerate face
1125
            ensure_boundary_consistency(hv);
1128
            ensure_boundary_consistency(hv);
1126
            ensure_boundary_consistency(hnv);
1129
            ensure_boundary_consistency(hnv);
1127
        }
1130
        }
1128
    }
1131
    }
1129
    
1132
    
1130
    vector<HalfEdgeID> Manifold::bridge_faces(FaceID f0, FaceID f1, const vector<pair<VertexID, VertexID> >& pairs)
1133
    vector<HalfEdgeID> Manifold::bridge_faces(FaceID f0, FaceID f1, const vector<pair<VertexID, VertexID> >& pairs)
1131
    {
1134
    {
1132
        // Let N be the number of vertex pairs to connect by edges
1135
        // Let N be the number of vertex pairs to connect by edges
1133
        size_t N = pairs.size();
1136
        size_t N = pairs.size();
1134
        
1137
        
1135
        // We now create N pairs of edges, glue each pair and let them point to the appropriate
1138
        // We now create N pairs of edges, glue each pair and let them point to the appropriate
1136
        // vertices.
1139
        // vertices.
1137
        vector<HalfEdgeID> new_halfedges(N);
1140
        vector<HalfEdgeID> new_halfedges(N);
1138
        vector<HalfEdgeID> new_halfedges_opp(N);
1141
        vector<HalfEdgeID> new_halfedges_opp(N);
1139
        for(size_t i=0;i<N; ++i)
1142
        for(size_t i=0;i<N; ++i)
1140
        {
1143
        {
1141
            new_halfedges[i] = kernel.add_halfedge();
1144
            new_halfedges[i] = kernel.add_halfedge();
1142
            new_halfedges_opp[i] = kernel.add_halfedge();
1145
            new_halfedges_opp[i] = kernel.add_halfedge();
1143
            glue(new_halfedges[i], new_halfedges_opp[i]);
1146
            glue(new_halfedges[i], new_halfedges_opp[i]);
1144
            kernel.set_vert(new_halfedges[i], pairs[i].second);
1147
            kernel.set_vert(new_halfedges[i], pairs[i].second);
1145
            kernel.set_vert(new_halfedges_opp[i], pairs[i].first);
1148
            kernel.set_vert(new_halfedges_opp[i], pairs[i].first);
1146
        }
1149
        }
1147
        
1150
        
1148
        // We now maintain some halfedge indices to right before
1151
        // We now maintain some halfedge indices to right before
1149
        // and right after the point we are trying to connect on
1152
        // and right after the point we are trying to connect on
1150
        // each of the two loops.
1153
        // each of the two loops.
1151
        HalfEdgeID h0p = kernel.last(f0);
1154
        HalfEdgeID h0p = kernel.last(f0);
1152
        HalfEdgeID h1n = kernel.last(f1);
1155
        HalfEdgeID h1n = kernel.last(f1);
1153
        
1156
        
1154
        // loop over all connections and link the new halfedges with the old
1157
        // loop over all connections and link the new halfedges with the old
1155
        // ones.
1158
        // ones.
1156
        for(size_t i=0;i<N; ++i)
1159
        for(size_t i=0;i<N; ++i)
1157
        {
1160
        {
1158
            while(kernel.vert(h0p) != pairs[i].first)
1161
            while(kernel.vert(h0p) != pairs[i].first)
1159
                h0p = kernel.next(h0p);
1162
                h0p = kernel.next(h0p);
1160
            while(kernel.vert(kernel.prev(h1n)) != pairs[i].second)
1163
            while(kernel.vert(kernel.prev(h1n)) != pairs[i].second)
1161
                h1n = kernel.prev(h1n);
1164
                h1n = kernel.prev(h1n);
1162
            
1165
            
1163
            HalfEdgeID h0n = kernel.next(h0p);
1166
            HalfEdgeID h0n = kernel.next(h0p);
1164
            HalfEdgeID h1p = kernel.prev(h1n);
1167
            HalfEdgeID h1p = kernel.prev(h1n);
1165
            
1168
            
1166
            link(h0p, new_halfedges[i]);
1169
            link(h0p, new_halfedges[i]);
1167
            link(new_halfedges[i],h1n);
1170
            link(new_halfedges[i],h1n);
1168
            link(h1p, new_halfedges_opp[i]);
1171
            link(h1p, new_halfedges_opp[i]);
1169
            link(new_halfedges_opp[i],h0n);
1172
            link(new_halfedges_opp[i],h0n);
1170
            
1173
            
1171
            h0p = new_halfedges_opp[i];
1174
            h0p = new_halfedges_opp[i];
1172
            h1n = new_halfedges_opp[i];
1175
            h1n = new_halfedges_opp[i];
1173
        }
1176
        }
1174
        
1177
        
1175
        // Create the faces and their connections
1178
        // Create the faces and their connections
1176
        for(size_t i=0;i<N; ++i)
1179
        for(size_t i=0;i<N; ++i)
1177
        {
1180
        {
1178
            HalfEdgeID last = new_halfedges[i];
1181
            HalfEdgeID last = new_halfedges[i];
1179
            FaceID f = kernel.add_face();
1182
            FaceID f = kernel.add_face();
1180
            kernel.set_last(f, last);
1183
            kernel.set_last(f, last);
1181
            HalfEdgeID h = last;
1184
            HalfEdgeID h = last;
1182
            do
1185
            do
1183
            {
1186
            {
1184
                kernel.set_face(h, f);
1187
                kernel.set_face(h, f);
1185
                h = kernel.next(h);
1188
                h = kernel.next(h);
1186
            } while(h != last);
1189
            } while(h != last);
1187
        }
1190
        }
1188
        
1191
        
1189
        // Delete the old faces that were bridged.
1192
        // Delete the old faces that were bridged.
1190
        kernel.remove_face(f0);
1193
        kernel.remove_face(f0);
1191
        kernel.remove_face(f1);
1194
        kernel.remove_face(f1);
1192
        
1195
        
1193
        new_halfedges.insert(new_halfedges.end(), new_halfedges_opp.begin(), new_halfedges_opp.end());
1196
        new_halfedges.insert(new_halfedges.end(), new_halfedges_opp.begin(), new_halfedges_opp.end());
1194
        return new_halfedges;
1197
        return new_halfedges;
1195
    }
1198
    }
1196
    
1199
    
1197
    /***************************************************
1200
    /***************************************************
1198
     * Namespace functions
1201
     * Namespace functions
1199
     ***************************************************/
1202
     ***************************************************/
1200
    bool valid(const Manifold& m)
1203
    bool valid(const Manifold& m)
1201
    {
1204
    {
1202
        // Verify components of halfedges
1205
        // Verify components of halfedges
1203
        for(HalfEdgeIDIterator h = m.halfedges_begin(); h != m.halfedges_end(); ++h){
1206
        for(HalfEdgeIDIterator h = m.halfedges_begin(); h != m.halfedges_end(); ++h){
1204
            Walker j = m.walker(*h);
1207
            Walker j = m.walker(*h);
1205
            
1208
            
1206
            if(j.vertex() == InvalidVertexID){
1209
            if(j.vertex() == InvalidVertexID){
1207
                cout << "Halfedge lacks vert" << endl;
1210
                cout << "Halfedge lacks vert" << endl;
1208
                return false;
1211
                return false;
1209
            }
1212
            }
1210
            if(j.next().halfedge() == InvalidHalfEdgeID){
1213
            if(j.next().halfedge() == InvalidHalfEdgeID){
1211
                cout << "Halfedge lacks next" << endl;
1214
                cout << "Halfedge lacks next" << endl;
1212
                return false;
1215
                return false;
1213
            }
1216
            }
1214
            if(j.prev().halfedge() == InvalidHalfEdgeID){
1217
            if(j.prev().halfedge() == InvalidHalfEdgeID){
1215
                cout << "Halfedge lacks prev" << endl;
1218
                cout << "Halfedge lacks prev" << endl;
1216
                return false;
1219
                return false;
1217
            }
1220
            }
1218
            if(j.opp().halfedge() == InvalidHalfEdgeID){
1221
            if(j.opp().halfedge() == InvalidHalfEdgeID){
1219
                cout << "Halfedge lacks opp" << endl;
1222
                cout << "Halfedge lacks opp" << endl;
1220
                return false;
1223
                return false;
1221
            }
1224
            }
1222
            
1225
            
1223
        }
1226
        }
1224
        // Verify components of vertices
1227
        // Verify components of vertices
1225
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
1228
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
1226
            vector<VertexID> link;
1229
            vector<VertexID> link;
1227
            
1230
            
1228
            // circulate the halfedges of vertex
1231
            // circulate the halfedges of vertex
1229
            for(Walker j = m.walker(*v); !j.full_circle(); j = j.circulate_vertex_cw()){
1232
            for(Walker j = m.walker(*v); !j.full_circle(); j = j.circulate_vertex_cw()){
1230
                // test halfedges around v
1233
                // test halfedges around v
1231
                if(j.halfedge() == InvalidHalfEdgeID){
1234
                if(j.halfedge() == InvalidHalfEdgeID){
1232
                    cout << "Vertex circulation produced invalid halfedge" << endl;
1235
                    cout << "Vertex circulation produced invalid halfedge" << endl;
1233
                    return false;
1236
                    return false;
1234
                }
1237
                }
1235
                VertexID ring_v = j.vertex();
1238
                VertexID ring_v = j.vertex();
1236
                
1239
                
1237
                // test one-ring for multiple occurences of vertex
1240
                // test one-ring for multiple occurences of vertex
1238
                if(find(link.begin(), link.end(), ring_v) != link.end()){
1241
                if(find(link.begin(), link.end(), ring_v) != link.end()){
1239
                    cout << "Vertex appears two times in one-ring of vertex" << endl;
1242
                    cout << "Vertex appears two times in one-ring of vertex" << endl;
1240
                    return false;
1243
                    return false;
1241
                }
1244
                }
1242
                link.push_back(ring_v);
1245
                link.push_back(ring_v);
1243
                
1246
                
1244
                // test for infinite loop around vertex
1247
                // test for infinite loop around vertex
1245
                if(static_cast<size_t>(j.no_steps()) > m.no_vertices()){
1248
                if(static_cast<size_t>(j.no_steps()) > m.no_vertices()){
1246
                    cout << "Vertex loop contains more vertices than manifold" << endl;
1249
                    cout << "Vertex loop contains more vertices than manifold" << endl;
1247
                    return false;
1250
                    return false;
1248
                }
1251
                }
1249
            }
1252
            }
1250
            
1253
            
1251
            // test one_ring size for boundary consistency
1254
            // test one_ring size for boundary consistency
1252
            if(link.size() <= 2){
1255
            if(link.size() <= 2){
1253
                Walker j = m.walker(*v);
1256
                Walker j = m.walker(*v);
1254
                
1257
                
1255
                if(j.face() != InvalidFaceID && j.opp().face() != InvalidFaceID)
1258
                if(j.face() != InvalidFaceID && j.opp().face() != InvalidFaceID)
1256
                {
1259
                {
1257
                    if(link.size()==1)
1260
                    if(link.size()==1)
1258
                        cout << "Vertex contains only a single incident edge" << endl;
1261
                        cout << "Vertex contains only a single incident edge" << endl;
1259
                    //
1262
                    //
1260
                    //                    cout << "Vertex contains only " << link.size() <<" incident edges" << endl;
1263
                    //                    cout << "Vertex contains only " << link.size() <<" incident edges" << endl;
1261
                }
1264
                }
1262
                else
1265
                else
1263
                    cout << "Boundary vertex contains only " << link.size() <<" incident edges" << endl;
1266
                    cout << "Boundary vertex contains only " << link.size() <<" incident edges" << endl;
1264
            }
1267
            }
1265
        }
1268
        }
1266
        // verify components of faces
1269
        // verify components of faces
1267
        for(FaceIDIterator f = m.faces_begin(); f != m.faces_end(); ++f){
1270
        for(FaceIDIterator f = m.faces_begin(); f != m.faces_end(); ++f){
1268
            // count edges on face
1271
            // count edges on face
1269
            Walker j = m.walker(*f);
1272
            Walker j = m.walker(*f);
1270
            
1273
            
1271
            for(; !j.full_circle(); j = j.circulate_face_cw()){
1274
            for(; !j.full_circle(); j = j.circulate_face_cw()){
1272
                // test that all halfedges in faces bind properly to their face
1275
                // test that all halfedges in faces bind properly to their face
1273
                if(j.face() != *f){
1276
                if(j.face() != *f){
1274
                    cout << "Face is inconsistent, halfedge is not bound to face" << endl;
1277
                    cout << "Face is inconsistent, halfedge is not bound to face" << endl;
1275
                    return false;
1278
                    return false;
1276
                }
1279
                }
1277
            }
1280
            }
1278
            // test faces for valid geometrical properties
1281
            // test faces for valid geometrical properties
1279
            if(j.no_steps() < 3){
1282
            if(j.no_steps() < 3){
1280
                cout << "Face contains less than 3 edges" << endl;
1283
                cout << "Face contains less than 3 edges" << endl;
1281
                return false;
1284
                return false;
1282
            }
1285
            }
1283
            // test for infinite loop around face
1286
            // test for infinite loop around face
1284
            if(j.no_steps() > m.no_halfedges() * 0.5f){
1287
            if(j.no_steps() > m.no_halfedges() * 0.5f){
1285
                cout << "Face loop contains more halfedges than manifold" << endl;
1288
                cout << "Face loop contains more halfedges than manifold" << endl;
1286
                return false;
1289
                return false;
1287
            }
1290
            }
1288
        }
1291
        }
1289
        return true;
1292
        return true;
1290
    }
1293
    }
1291
    
1294
    
1292
    void bbox(const Manifold& m, Manifold::Vec& pmin, Manifold::Vec& pmax)
1295
    void bbox(const Manifold& m, Manifold::Vec& pmin, Manifold::Vec& pmax)
1293
    {
1296
    {
1294
        if(m.no_vertices()==0)
1297
        if(m.no_vertices()==0)
1295
            return;
1298
            return;
1296
        VertexIDIterator v = m.vertices_begin();
1299
        VertexIDIterator v = m.vertices_begin();
1297
        pmin = pmax = m.pos(*v);
1300
        pmin = pmax = m.pos(*v);
1298
        ++v;
1301
        ++v;
1299
        for(; v != m.vertices_end(); ++v){
1302
        for(; v != m.vertices_end(); ++v){
1300
            pmin = v_min(m.pos(*v), pmin);
1303
            pmin = v_min(m.pos(*v), pmin);
1301
            pmax = v_max(m.pos(*v), pmax);
1304
            pmax = v_max(m.pos(*v), pmax);
1302
        }
1305
        }
1303
    }
1306
    }
1304
    
1307
    
1305
    void bsphere(const Manifold& m, Manifold::Vec& c, float& r)
1308
    void bsphere(const Manifold& m, Manifold::Vec& c, float& r)
1306
    {
1309
    {
1307
        Manifold::Vec p0, p7;
1310
        Manifold::Vec p0, p7;
1308
        bbox(m, p0, p7);
1311
        bbox(m, p0, p7);
1309
        Manifold::Vec rad = (p7 - p0) * 0.5f;
1312
        Manifold::Vec rad = (p7 - p0) * 0.5f;
1310
        c = p0 + rad;
1313
        c = p0 + rad;
1311
        r = rad.length();
1314
        r = rad.length();
1312
    }
1315
    }
1313
    
1316
    
1314
    
1317
    
1315
    
1318
    
1316
    bool precond_collapse_edge(const Manifold& m, HalfEdgeID h)
1319
    bool precond_collapse_edge(const Manifold& m, HalfEdgeID h)
1317
    {
1320
    {
1318
        Walker hew = m.walker(h);
1321
        Walker hew = m.walker(h);
1319
        HalfEdgeID ho = hew.opp().halfedge();
1322
        HalfEdgeID ho = hew.opp().halfedge();
1320
        VertexID v0 = hew.opp().vertex();
1323
        VertexID v0 = hew.opp().vertex();
1321
        VertexID v1 = hew.vertex();
1324
        VertexID v1 = hew.vertex();
1322
        
1325
        
1323
        // get the one-ring of v0
1326
        // get the one-ring of v0
1324
        vector<VertexID> link0;
1327
        vector<VertexID> link0;
1325
        vector<FaceID> faces0;
1328
        vector<FaceID> faces0;
1326
        for(Walker vj = m.walker(h);
1329
        for(Walker vj = m.walker(h);
1327
            !vj.full_circle(); vj = vj.circulate_vertex_ccw()){
1330
            !vj.full_circle(); vj = vj.circulate_vertex_ccw()){
1328
            link0.push_back(vj.vertex());
1331
            link0.push_back(vj.vertex());
1329
            if(vj.halfedge() != h)
1332
            if(vj.halfedge() != h)
1330
                faces0.push_back(vj.face());
1333
                faces0.push_back(vj.face());
1331
        }
1334
        }
1332
        assert(link0.size() > 1);
1335
        assert(link0.size() > 1);
1333
        
1336
        
1334
        // get the one-ring of v1
1337
        // get the one-ring of v1
1335
        vector<VertexID> link1;
1338
        vector<VertexID> link1;
1336
        vector<FaceID> faces1;
1339
        vector<FaceID> faces1;
1337
        for(Walker vj = m.walker(ho);
1340
        for(Walker vj = m.walker(ho);
1338
            !vj.full_circle(); vj = vj.circulate_vertex_ccw()){
1341
            !vj.full_circle(); vj = vj.circulate_vertex_ccw()){
1339
            link1.push_back(vj.vertex());
1342
            link1.push_back(vj.vertex());
1340
            if(vj.halfedge() != ho)
1343
            if(vj.halfedge() != ho)
1341
                faces1.push_back(vj.face());
1344
                faces1.push_back(vj.face());
1342
        }
1345
        }
1343
        assert(link1.size() > 1);
1346
        assert(link1.size() > 1);
1344
        
1347
        
1345
        // sort the vertices of the two rings
1348
        // sort the vertices of the two rings
1346
        sort(link0.begin(), link0.end());
1349
        sort(link0.begin(), link0.end());
1347
        sort(link1.begin(), link1.end());
1350
        sort(link1.begin(), link1.end());
1348
        
1351
        
1349
        // get the intersection of the shared vertices from both rings
1352
        // get the intersection of the shared vertices from both rings
1350
        vector<VertexID> lisect;
1353
        vector<VertexID> lisect;
1351
        std::back_insert_iterator<vector<VertexID> > lii(lisect);
1354
        std::back_insert_iterator<vector<VertexID> > lii(lisect);
1352
        set_intersection(link0.begin(), link0.end(),
1355
        set_intersection(link0.begin(), link0.end(),
1353
                         link1.begin(), link1.end(),
1356
                         link1.begin(), link1.end(),
1354
                         lii);
1357
                         lii);
1355
        
1358
        
1356
        // sort the faces of the two rings
1359
        // sort the faces of the two rings
1357
        sort(faces0.begin(), faces0.end());
1360
        sort(faces0.begin(), faces0.end());
1358
        sort(faces1.begin(), faces1.end());
1361
        sort(faces1.begin(), faces1.end());
1359
        
1362
        
1360
        // get the intersection of the shared faces from both rings
1363
        // get the intersection of the shared faces from both rings
1361
        vector<FaceID> fisect;
1364
        vector<FaceID> fisect;
1362
        std::back_insert_iterator<vector<FaceID> > fii(fisect);
1365
        std::back_insert_iterator<vector<FaceID> > fii(fisect);
1363
        set_intersection(faces0.begin(), faces0.end(),
1366
        set_intersection(faces0.begin(), faces0.end(),
1364
                         faces1.begin(), faces1.end(),
1367
                         faces1.begin(), faces1.end(),
1365
                         fii);
1368
                         fii);
1366
        if(fisect.size() > 0)
1369
        if(fisect.size() > 0)
1367
            return false;
1370
            return false;
1368
        
1371
        
1369
        int k = 0;
1372
        int k = 0;
1370
        // if the adjacent face is a triangle (see 2)
1373
        // if the adjacent face is a triangle (see 2)
1371
        if(hew.next().next().next().halfedge() == h){
1374
        if(hew.next().next().next().halfedge() == h){
1372
            VertexID v = hew.next().vertex();
1375
            VertexID v = hew.next().vertex();
1373
            
1376
            
1374
            // valency test (see 5)
1377
            // valency test (see 5)
1375
            if(valency(m, v) < 3)
1378
            if(valency(m, v) < 3)
1376
                return false;
1379
                return false;
1377
            
1380
            
1378
            // remove the vertex shared by the two rings from the intersection
1381
            // remove the vertex shared by the two rings from the intersection
1379
            vector<VertexID>::iterator iter;
1382
            vector<VertexID>::iterator iter;
1380
            iter = find(lisect.begin(), lisect.end(), v);
1383
            iter = find(lisect.begin(), lisect.end(), v);
1381
            assert(iter != lisect.end());
1384
            assert(iter != lisect.end());
1382
            lisect.erase(iter);
1385
            lisect.erase(iter);
1383
            ++k;
1386
            ++k;
1384
        }
1387
        }
1385
        // if the adjacent face is a triangle (see 2)
1388
        // if the adjacent face is a triangle (see 2)
1386
        if(hew.opp().next().next().next().halfedge() == hew.opp().halfedge()){
1389
        if(hew.opp().next().next().next().halfedge() == hew.opp().halfedge()){
1387
            VertexID v = hew.opp().next().vertex();
1390
            VertexID v = hew.opp().next().vertex();
1388
            
1391
            
1389
            // valency test (see 5)
1392
            // valency test (see 5)
1390
            if(valency(m, v) < 3)
1393
            if(valency(m, v) < 3)
1391
                return false;
1394
                return false;
1392
            
1395
            
1393
            // remove the vertex shared by the two rings from the intersection
1396
            // remove the vertex shared by the two rings from the intersection
1394
            vector<VertexID>::iterator iter;
1397
            vector<VertexID>::iterator iter;
1395
            iter = find(lisect.begin(), lisect.end(), v);
1398
            iter = find(lisect.begin(), lisect.end(), v);
1396
            assert(iter != lisect.end());
1399
            assert(iter != lisect.end());
1397
            lisect.erase(iter);
1400
            lisect.erase(iter);
1398
            ++k;
1401
            ++k;
1399
        }
1402
        }
1400
        // double edge test (see 3)
1403
        // double edge test (see 3)
1401
        if(lisect.size() != 0)
1404
        if(lisect.size() != 0)
1402
            return false;
1405
            return false;
1403
        
1406
        
1404
        // tetrahedon test (see 4)
1407
        // tetrahedon test (see 4)
1405
        if(k == 2 && (link0.size() + link1.size() == 6))
1408
        if(k == 2 && (link0.size() + link1.size() == 6))
1406
            return false;
1409
            return false;
1407
        
1410
        
1408
        // test that we do not merge holes (see 6)
1411
        // test that we do not merge holes (see 6)
1409
        if(boundary(m, v0) && boundary(m, v1) && hew.face() != InvalidFaceID && hew.opp().face() != InvalidFaceID)
1412
        if(boundary(m, v0) && boundary(m, v1) && hew.face() != InvalidFaceID && hew.opp().face() != InvalidFaceID)
1410
            return false;
1413
            return false;
1411
        
1414
        
1412
        return true;
1415
        return true;
1413
    }
1416
    }
1414
    
1417
    
1415
    bool precond_flip_edge(const Manifold& m, HalfEdgeID h)
1418
    bool precond_flip_edge(const Manifold& m, HalfEdgeID h)
1416
    {
1419
    {
1417
        Walker j = m.walker(h);
1420
        Walker j = m.walker(h);
1418
        
1421
        
1419
        FaceID hf = j.face();
1422
        FaceID hf = j.face();
1420
        FaceID hof = j.opp().face();
1423
        FaceID hof = j.opp().face();
1421
        
1424
        
1422
        // boundary case
1425
        // boundary case
1423
        if(hf == InvalidFaceID || hof == InvalidFaceID)
1426
        if(hf == InvalidFaceID || hof == InvalidFaceID)
1424
           return false;
1427
           return false;
1425
        
1428
        
1426
        
1429
        
1427
        // We can only flip an edge if both incident polygons are triangles.
1430
        // We can only flip an edge if both incident polygons are triangles.
1428
        if(no_edges(m, hf) != 3 || no_edges(m, hof) !=3)
1431
        if(no_edges(m, hf) != 3 || no_edges(m, hof) !=3)
1429
            return false;
1432
            return false;
1430
        
1433
        
1431
 
1434
 
1432
        // non boundary vertices with a valency of less than 4(less than 3 after operation) degenerates mesh.
1435
        // non boundary vertices with a valency of less than 4(less than 3 after operation) degenerates mesh.
1433
        VertexID hv = j.vertex();
1436
        VertexID hv = j.vertex();
1434
        VertexID hov = j.opp().vertex();
1437
        VertexID hov = j.opp().vertex();
1435
        if((valency(m, hv) < 4 && !boundary(m, hv)) || (valency(m, hov) < 4 && !boundary(m, hov))){
1438
        if((valency(m, hv) < 4 && !boundary(m, hv)) || (valency(m, hov) < 4 && !boundary(m, hov))){
1436
            return false;
1439
            return false;
1437
        }
1440
        }
1438
        
1441
        
1439
        // Disallow flip if vertices being connected already are.
1442
        // Disallow flip if vertices being connected already are.
1440
        VertexID hnv = j.next().vertex();
1443
        VertexID hnv = j.next().vertex();
1441
        VertexID honv = j.opp().next().vertex();
1444
        VertexID honv = j.opp().next().vertex();
1442
        if(connected(m, hnv, honv)){
1445
        if(connected(m, hnv, honv)){
1443
           return false;
1446
           return false;
1444
        }
1447
        }
1445
        
1448
        
1446
        return true;
1449
        return true;
1447
    }
1450
    }
1448
    
1451
    
1449
    bool boundary(const Manifold& m, VertexID v)
1452
    bool boundary(const Manifold& m, VertexID v)
1450
    {
1453
    {
1451
        Walker j  = m.walker(v);
1454
        Walker j  = m.walker(v);
1452
        return boundary(m, j.halfedge());
1455
        return boundary(m, j.halfedge());
1453
    }
1456
    }
1454
 
1457
 
1455
    int valency(const Manifold& m, VertexID v)
1458
    int valency(const Manifold& m, VertexID v)
1456
    {
1459
    {
1457
        return circulate_vertex_ccw(m,v, (std::function<void(Walker&)>)[](Walker){});
1460
        return circulate_vertex_ccw(m,v, (std::function<void(Walker&)>)[](Walker){});
1458
    }
1461
    }
1459
    
1462
    
1460
    Manifold::Vec normal(const Manifold& m, VertexID v)
1463
    Manifold::Vec normal(const Manifold& m, VertexID v)
1461
    {
1464
    {
1462
        Manifold::Vec p0 = m.pos(v);
1465
        Manifold::Vec p0 = m.pos(v);
1463
        vector<Manifold::Vec> one_ring;
1466
        vector<Manifold::Vec> one_ring;
1464
        
1467
        
1465
        // run through outgoing edges, and store them normalized
1468
        // run through outgoing edges, and store them normalized
1466
        circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID vn) {
1469
        circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID vn) {
1467
            Manifold::Vec edge = m.pos(vn) - p0;
1470
            Manifold::Vec edge = m.pos(vn) - p0;
1468
            double l = length(edge);
1471
            double l = length(edge);
1469
            if(l > 0.0)
1472
            if(l > 0.0)
1470
                one_ring.push_back(edge/l);
1473
                one_ring.push_back(edge/l);
1471
        });
1474
        });
1472
        int N = one_ring.size();
1475
        int N = one_ring.size();
1473
        if(N<2)
1476
        if(N<2)
1474
            return Manifold::Vec(0);
1477
            return Manifold::Vec(0);
1475
        
1478
        
1476
        size_t N_count = N;
1479
        size_t N_count = N;
1477
        size_t N_start = 0;
1480
        size_t N_start = 0;
1478
        if(boundary(m, v))
1481
        if(boundary(m, v))
1479
            N_start = 1;
1482
            N_start = 1;
1480
        
1483
        
1481
        // sum up the normals of each face surrounding the vertex
1484
        // sum up the normals of each face surrounding the vertex
1482
        Manifold::Vec n(0);
1485
        Manifold::Vec n(0);
1483
        for(size_t i = N_start; i < N_count; ++i){
1486
        for(size_t i = N_start; i < N_count; ++i){
1484
            Manifold::Vec e0 = one_ring[i];
1487
            Manifold::Vec e0 = one_ring[i];
1485
            Manifold::Vec e1 = one_ring[(i+1) % N];
1488
            Manifold::Vec e1 = one_ring[(i+1) % N];
1486
            
1489
            
1487
            Manifold::Vec n_part = normalize(cross(e0, e1));
1490
            Manifold::Vec n_part = normalize(cross(e0, e1));
1488
            n += n_part * acos(max(-1.0, min(1.0, dot(e0, e1))));
1491
            n += n_part * acos(max(-1.0, min(1.0, dot(e0, e1))));
1489
        }
1492
        }
1490
        
1493
        
1491
        // normalize and return the normal
1494
        // normalize and return the normal
1492
        float sqr_l = sqr_length(n);
1495
        float sqr_l = sqr_length(n);
1493
        if(sqr_l > 0.0f) return n / sqrt(sqr_l);
1496
        if(sqr_l > 0.0f) return n / sqrt(sqr_l);
1494
        
1497
        
1495
        return n;
1498
        return n;
1496
    }
1499
    }
1497
    
1500
    
1498
    
1501
    
1499
    bool connected(const Manifold& m, VertexID v0, VertexID v1)
1502
    bool connected(const Manifold& m, VertexID v0, VertexID v1)
1500
    {
1503
    {
1501
        bool c=false;
1504
        bool c=false;
1502
        circulate_vertex_ccw(m, v0, (std::function<void(VertexID)>)[&](VertexID v){ c |= (v==v1);});
1505
        circulate_vertex_ccw(m, v0, (std::function<void(VertexID)>)[&](VertexID v){ c |= (v==v1);});
1503
        return c;
1506
        return c;
1504
    }
1507
    }
1505
 
1508
 
1506
    
1509
    
1507
    int no_edges(const Manifold& m, FaceID f)
1510
    int no_edges(const Manifold& m, FaceID f)
1508
    {
1511
    {
1509
        return circulate_face_ccw(m, f, (std::function<void(Walker&)>)[](Walker w){});
1512
        return circulate_face_ccw(m, f, (std::function<void(Walker&)>)[](Walker w){});
1510
    }
1513
    }
1511
    
1514
    
1512
    Manifold::Vec normal(const Manifold& m, FaceID f)
1515
    Manifold::Vec normal(const Manifold& m, FaceID f)
1513
    {
1516
    {
1514
        vector<Manifold::Vec> v;
1517
        vector<Manifold::Vec> v;
1515
        
1518
        
1516
        int k= circulate_face_ccw(m, f, (std::function<void(VertexID)>)[&](VertexID vid) {
1519
        int k= circulate_face_ccw(m, f, (std::function<void(VertexID)>)[&](VertexID vid) {
1517
            v.push_back(m.pos(vid));
1520
            v.push_back(m.pos(vid));
1518
        });
1521
        });
1519
        
1522
        
1520
        Manifold::Vec norm(0);
1523
        Manifold::Vec norm(0);
1521
        for(int i=0;i<k;++i)
1524
        for(int i=0;i<k;++i)
1522
        {
1525
        {
1523
            norm[0] += (v[i][1]-v[(i+1)%k][1])*(v[i][2]+v[(i+1)%k][2]);
1526
            norm[0] += (v[i][1]-v[(i+1)%k][1])*(v[i][2]+v[(i+1)%k][2]);
1524
            norm[1] += (v[i][2]-v[(i+1)%k][2])*(v[i][0]+v[(i+1)%k][0]);
1527
            norm[1] += (v[i][2]-v[(i+1)%k][2])*(v[i][0]+v[(i+1)%k][0]);
1525
            norm[2] += (v[i][0]-v[(i+1)%k][0])*(v[i][1]+v[(i+1)%k][1]);
1528
            norm[2] += (v[i][0]-v[(i+1)%k][0])*(v[i][1]+v[(i+1)%k][1]);
1526
        }
1529
        }
1527
        float l = sqr_length(norm);
1530
        float l = sqr_length(norm);
1528
        if(l>0.0f)
1531
        if(l>0.0f)
1529
            norm /= sqrt(l);
1532
            norm /= sqrt(l);
1530
        return norm;
1533
        return norm;
1531
    }
1534
    }
1532
    
1535
    
1533
    
1536
    
1534
    double area(const Manifold& m, FaceID fid)
1537
    double area(const Manifold& m, FaceID fid)
1535
    {
1538
    {
1536
        // Get all projected vertices
1539
        // Get all projected vertices
1537
        vector<Manifold::Vec> vertices;
1540
        vector<Manifold::Vec> vertices;
1538
        int N = circulate_face_ccw(m, fid, (std::function<void(VertexID)>)[&](VertexID vid) {
1541
        int N = circulate_face_ccw(m, fid, (std::function<void(VertexID)>)[&](VertexID vid) {
1539
            vertices.push_back(m.pos(vid));
1542
            vertices.push_back(m.pos(vid));
1540
        });
1543
        });
1541
 
1544
 
1542
        
1545
        
1543
        double area = 0;
1546
        double area = 0;
1544
        Manifold::Vec norm = normal(m,fid);
1547
        Manifold::Vec norm = normal(m,fid);
1545
        for(int i = 1; i < N-1; ++i)
1548
        for(int i = 1; i < N-1; ++i)
1546
            area += 0.5 * dot(norm,cross(vertices[i]-vertices[0], vertices[(i+1 )]-vertices[0]));
1549
            area += 0.5 * dot(norm,cross(vertices[i]-vertices[0], vertices[(i+1 )]-vertices[0]));
1547
        return area;
1550
        return area;
1548
    }
1551
    }
1549
    
1552
    
1550
    Manifold::Vec centre(const Manifold& m, FaceID f)
1553
    Manifold::Vec centre(const Manifold& m, FaceID f)
1551
    {
1554
    {
1552
        Manifold::Vec c(0);
1555
        Manifold::Vec c(0);
1553
        int n = circulate_face_ccw(m, f, (std::function<void(VertexID)>)[&](VertexID v) {c+=m.pos(v);});
1556
        int n = circulate_face_ccw(m, f, (std::function<void(VertexID)>)[&](VertexID v) {c+=m.pos(v);});
1554
        return c / n;
1557
        return c / n;
1555
    }
1558
    }
1556
    
1559
    
1557
    double perimeter(const Manifold& m, FaceID f)
1560
    double perimeter(const Manifold& m, FaceID f)
1558
    {
1561
    {
1559
        double l=0.0;
1562
        double l=0.0;
1560
        circulate_face_ccw(m, f, (std::function<void(HalfEdgeID)>)[&](HalfEdgeID h) { l+= length(m, h);});
1563
        circulate_face_ccw(m, f, (std::function<void(HalfEdgeID)>)[&](HalfEdgeID h) { l+= length(m, h);});
1561
        return l;
1564
        return l;
1562
    }
1565
    }
1563
    
1566
    
1564
    bool boundary(const Manifold& m, HalfEdgeID h)
1567
    bool boundary(const Manifold& m, HalfEdgeID h)
1565
    {
1568
    {
1566
        Walker w = m.walker(h);
1569
        Walker w = m.walker(h);
1567
        return w.face() == InvalidFaceID || w.opp().face() == InvalidFaceID;
1570
        return w.face() == InvalidFaceID || w.opp().face() == InvalidFaceID;
1568
    }
1571
    }
1569
    
1572
    
1570
    double length(const Manifold& m, HalfEdgeID h)
1573
    double length(const Manifold& m, HalfEdgeID h)
1571
    {
1574
    {
1572
        Walker w = m.walker(h);
1575
        Walker w = m.walker(h);
1573
        return (m.pos(w.vertex()) - m.pos(w.opp().vertex())).length();
1576
        return (m.pos(w.vertex()) - m.pos(w.opp().vertex())).length();
1574
    }
1577
    }
1575
}
1578
}
1576
 
1579