Subversion Repositories gelsvn

Rev

Rev 662 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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