Subversion Repositories gelsvn

Rev

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

Rev 631 Rev 633
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
 
6
 
7
/**
7
/**
8
 * @file Manifold.h
8
 * @file Manifold.h
9
 * @brief The Manifold class is the main data structure of HMesh - the actual mesh.
9
 * @brief The Manifold class is the main data structure of HMesh - the actual mesh.
10
 */
10
 */
11
 
11
 
12
#pragma once
12
#pragma once
13
 
13
 
14
#include <algorithm>
14
#include <algorithm>
15
#include "../CGLA/Vec3d.h"
15
#include "../CGLA/Vec3d.h"
16
 
16
 
17
#include "ConnectivityKernel.h"
17
#include "ConnectivityKernel.h"
18
#include "Iterators.h"
18
#include "Iterators.h"
19
#include "Walker.h"
19
#include "Walker.h"
20
#include "AttributeVector.h"
20
#include "AttributeVector.h"
21
 
21
 
22
 
22
 
23
namespace Geometry
23
namespace Geometry
24
{
24
{
25
    // forward declaration
25
    // forward declaration
26
    class TriMesh;
26
    class TriMesh;
27
    class IndexedFaceSet;
27
    class IndexedFaceSet;
28
}
28
}
29
 
29
 
30
namespace HMesh
30
namespace HMesh
31
{
31
{
32
    /** The Manifold class represents a halfedge based mesh. Since meshes based on the halfedge
32
    /** The Manifold class represents a halfedge based mesh. Since meshes based on the halfedge
33
     representation must be manifold (although exceptions could be made) the class is thus named.
33
     representation must be manifold (although exceptions could be made) the class is thus named.
34
     Manifold contains many functions for mesh manipulation and associated the position attribute
34
     Manifold contains many functions for mesh manipulation and associated the position attribute
35
     with vertices.*/
35
     with vertices.*/
36
    
36
    
37
    class Manifold
37
    class Manifold
38
    {
38
    {
39
    public:
39
    public:
40
        
40
        
41
        /// Vector type used for positions of vertices.
41
        /// Vector type used for positions of vertices.
42
        typedef CGLA::Vec3d Vec;
42
        typedef CGLA::Vec3d Vec;
43
        
43
        
44
        /// Default constructor
44
        /// Default constructor
45
        Manifold();
45
        Manifold();
46
 
46
 
47
        /** \brief Build a manifold. 
47
        /** \brief Build a manifold. 
48
        The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces. 
48
        The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces. 
49
        facevecis an array where each entry indicates the number of vertices in that face. 
49
        facevecis an array where each entry indicates the number of vertices in that face. 
50
        The array indices contains all the corresponding vertex indices in one concatenated list. */
50
        The array indices contains all the corresponding vertex indices in one concatenated list. */
51
        void build( size_t no_vertices,
51
        void build( size_t no_vertices,
52
                    const float* vertvec,
52
                    const float* vertvec,
53
                    size_t no_faces,
53
                    size_t no_faces,
54
                    const int* facevec,
54
                    const int* facevec,
55
                    const int* indices);
55
                    const int* indices);
56
 
56
 
57
        /** \brief Build a manifold.
57
        /** \brief Build a manifold.
58
         This function is for vertices given in double precision.
58
         This function is for vertices given in double precision.
59
         The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces.
59
         The arguments are the number of vertices, no_vertices, the vector of vertices, vertvec, the number of faces, no_faces.
60
         facevecis an array where each entry indicates the number of vertices in that face.
60
         facevecis an array where each entry indicates the number of vertices in that face.
61
         The array indices contains all the corresponding vertex indices in one concatenated list. */
61
         The array indices contains all the corresponding vertex indices in one concatenated list. */
62
        void build( size_t no_vertices,
62
        void build( size_t no_vertices,
63
                   const double* vertvec,
63
                   const double* vertvec,
64
                   size_t no_faces,
64
                   size_t no_faces,
65
                   const int* facevec,
65
                   const int* facevec,
66
                   const int* indices);
66
                   const int* indices);
67
 
67
 
68
        /// Build a manifold from a TriMesh
68
        /// Build a manifold from a TriMesh
69
        void build(const Geometry::TriMesh& mesh);
69
        void build(const Geometry::TriMesh& mesh);
70
        
70
        
71
        /** Add a face to the Manifold.
71
        /** Add a face to the Manifold.
72
         This function is provided a vector of points in space and transforms it into a single 
72
         This function is provided a vector of points in space and transforms it into a single 
73
         polygonal face calling build. It is purely for convenience. */
73
         polygonal face calling build. It is purely for convenience. */
74
        FaceID add_face(std::vector<Manifold::Vec> points);
74
        FaceID add_face(std::vector<Manifold::Vec> points);
75
 
75
 
76
        /** Removes a face from the Manifold. If it is an interior face it is simply replaces
76
        /** Removes a face from the Manifold. If it is an interior face it is simply replaces
77
         by an InvalidFaceID. If the face contains boundary edges, these are removed. Situations
77
         by an InvalidFaceID. If the face contains boundary edges, these are removed. Situations
78
         may arise where the mesh is no longer manifold because the situation at a boundary vertex
78
         may arise where the mesh is no longer manifold because the situation at a boundary vertex
79
         is not homeomorphic to a half disk. This, we can probably ignore since from the data
79
         is not homeomorphic to a half disk. This, we can probably ignore since from the data
80
         structure point of view it is not really a problem that a vertex is incident on two holes - 
80
         structure point of view it is not really a problem that a vertex is incident on two holes - 
81
        a hole can be seen as a special type of face. The function returns false if the FaceID is 
81
        a hole can be seen as a special type of face. The function returns false if the FaceID is 
82
         not valid, otherwise the function must complete. */
82
         not valid, otherwise the function must complete. */
83
        bool remove_face(FaceID fid);
83
        bool remove_face(FaceID fid);
84
 
84
 
85
        /** Remove an edge from the Manifold.
85
        /** Remove an edge from the Manifold.
86
            This function will remove the faces on either side and the edge itself in the process. Thus,
86
            This function will remove the faces on either side and the edge itself in the process. Thus,
87
         it is a simple application of remove_face. */
87
         it is a simple application of remove_face. */
88
            bool remove_edge(HalfEdgeID hid);
88
            bool remove_edge(HalfEdgeID hid);
89
 
89
 
90
        /** Remove a vertex from the Manifold.
90
        /** Remove a vertex from the Manifold.
91
         This function merges all faces around the vertex into one and then removes 
91
         This function merges all faces around the vertex into one and then removes 
92
         this resulting face. */
92
         this resulting face. */
93
        bool remove_vertex(VertexID vid);
93
        bool remove_vertex(VertexID vid);
94
        
94
        
95
        /// number of  vertices
95
        /// number of  vertices
96
        size_t no_vertices() const { return kernel.no_vertices();}
96
        size_t no_vertices() const { return kernel.no_vertices();}
97
        /// number of active faces
97
        /// number of active faces
98
        size_t no_faces() const { return kernel.no_faces();}
98
        size_t no_faces() const { return kernel.no_faces();}
99
        /// number of active halfedges
99
        /// number of active halfedges
100
        size_t no_halfedges() const { return kernel.no_halfedges();}
100
        size_t no_halfedges() const { return kernel.no_halfedges();}
101
        
101
        
102
        /// number of total vertices in kernel
102
        /// number of total vertices in kernel
103
        size_t allocated_vertices() const { return kernel.allocated_vertices();}
103
        size_t allocated_vertices() const { return kernel.allocated_vertices();}
104
        /// number of total faces in kernel
104
        /// number of total faces in kernel
105
        size_t allocated_faces() const { return kernel.allocated_faces();}
105
        size_t allocated_faces() const { return kernel.allocated_faces();}
106
        /// number of total halfedges in kernel
106
        /// number of total halfedges in kernel
107
        size_t allocated_halfedges() const { return kernel.allocated_halfedges();}
107
        size_t allocated_halfedges() const { return kernel.allocated_halfedges();}
108
        
108
        
109
        /// check if ID of vertex is in use
109
        /// check if ID of vertex is in use
110
        bool in_use(VertexID id) const { return kernel.in_use(id);}
110
        bool in_use(VertexID id) const { return kernel.in_use(id);}
111
        /// check if ID of face is in use
111
        /// check if ID of face is in use
112
        bool in_use(FaceID id) const { return kernel.in_use(id);}
112
        bool in_use(FaceID id) const { return kernel.in_use(id);}
113
        /// check if ID of halfedge is in use
113
        /// check if ID of halfedge is in use
114
        bool in_use(HalfEdgeID id) const { return kernel.in_use(id);}
114
        bool in_use(HalfEdgeID id) const { return kernel.in_use(id);}
115
        
115
        
116
        IDIteratorPair<Vertex> vertices() const {return IDIteratorPair<Vertex>(kernel.vertices_begin(),
116
        IDIteratorPair<Vertex> vertices() const {return IDIteratorPair<Vertex>(kernel.vertices_begin(),
117
                                                                         kernel.vertices_end());}
117
                                                                         kernel.vertices_end());}
118
        IDIteratorPair<Face> faces() const {return IDIteratorPair<Face>(kernel.faces_begin(),
118
        IDIteratorPair<Face> faces() const {return IDIteratorPair<Face>(kernel.faces_begin(),
119
                                                                         kernel.faces_end());}
119
                                                                         kernel.faces_end());}
120
        IDIteratorPair<HalfEdge> halfedges() const {return IDIteratorPair<HalfEdge>(kernel.halfedges_begin(),
120
        IDIteratorPair<HalfEdge> halfedges() const {return IDIteratorPair<HalfEdge>(kernel.halfedges_begin(),
121
                                                                         kernel.halfedges_end());}
121
                                                                         kernel.halfedges_end());}
122
        
122
        
123
        /// Iterator to first VertexID, optional argument defines if unused items should be skipped
123
        /// Iterator to first VertexID, optional argument defines if unused items should be skipped
124
        VertexIDIterator vertices_begin(bool skip = true) const { return kernel.vertices_begin();}
124
        VertexIDIterator vertices_begin(bool skip = true) const { return kernel.vertices_begin();}
125
        /// Iterator to first FaceID, optional argument defines if unused items should be skipped
125
        /// Iterator to first FaceID, optional argument defines if unused items should be skipped
126
        FaceIDIterator faces_begin(bool skip = true) const { return kernel.faces_begin();}
126
        FaceIDIterator faces_begin(bool skip = true) const { return kernel.faces_begin();}
127
        /// Iterator to first HalfEdgeID, optional argument defines if unused items should be skipped
127
        /// Iterator to first HalfEdgeID, optional argument defines if unused items should be skipped
128
        HalfEdgeIDIterator halfedges_begin(bool skip = true) const { return kernel.halfedges_begin();}
128
        HalfEdgeIDIterator halfedges_begin(bool skip = true) const { return kernel.halfedges_begin();}
129
        
129
        
130
        /// Iterator to past the end VertexID
130
        /// Iterator to past the end VertexID
131
        VertexIDIterator vertices_end() const { return kernel.vertices_end();}
131
        VertexIDIterator vertices_end() const { return kernel.vertices_end();}
132
        /// Iterator topast the end FaceID
132
        /// Iterator topast the end FaceID
133
        FaceIDIterator faces_end() const { return kernel.faces_end();}
133
        FaceIDIterator faces_end() const { return kernel.faces_end();}
134
        /// Iterator to past the end HalfEdgeID
134
        /// Iterator to past the end HalfEdgeID
135
        HalfEdgeIDIterator halfedges_end() const {return kernel.halfedges_end(); }  
135
        HalfEdgeIDIterator halfedges_end() const {return kernel.halfedges_end(); }  
136
 
136
 
137
		
137
		
138
		/** \brief Bridge f0 and f1 by connecting the vertex pairs given in pairs.
138
		/** \brief Bridge f0 and f1 by connecting the vertex pairs given in pairs.
139
		 This function creates a cylindrical connection between f0 and f1. f0 and f1 are removed and the vertices 
139
		 This function creates a cylindrical connection between f0 and f1. f0 and f1 are removed and the vertices 
140
		 given in pairs are connected by edges. The result is a cylindrical connection that changes the genus of the object.
140
		 given in pairs are connected by edges. The result is a cylindrical connection that changes the genus of the object.
141
		 
141
		 
142
		 This function leaves all error chethising in the hands of the user (for now). The faces clearly should not have any 
142
		 This function leaves all error chethising in the hands of the user (for now). The faces clearly should not have any 
143
		 vertices or edges in common as this will create a non-manifold situation. Also the faces should face towards or away 
143
		 vertices or edges in common as this will create a non-manifold situation. Also the faces should face towards or away 
144
		 from each other and be in a position where it is reasonable to make the bridge. The connections should also make sense 
144
		 from each other and be in a position where it is reasonable to make the bridge. The connections should also make sense 
145
		 from a geometric point of view and should be in a counter clothiswise loop on f0 and a clothiswise loop on f1. No need to 
145
		 from a geometric point of view and should be in a counter clothiswise loop on f0 and a clothiswise loop on f1. No need to 
146
		 connect all vertices.
146
		 connect all vertices.
147
		 
147
		 
148
		 The function returns a vector of HalfEdgeIDs. Those are, of course, the connecting halfedges - also the opposite edges.
148
		 The function returns a vector of HalfEdgeIDs. Those are, of course, the connecting halfedges - also the opposite edges.
149
		 */
149
		 */
150
		std::vector<HalfEdgeID> bridge_faces(FaceID f0, FaceID f1, const std::vector<std::pair<VertexID, VertexID> >& pairs);
150
		std::vector<HalfEdgeID> bridge_faces(FaceID f0, FaceID f1, const std::vector<std::pair<VertexID, VertexID> >& pairs);
151
 
151
 
152
 
152
 
153
        /** \brief Collapse the halfedge h.
153
        /** \brief Collapse the halfedge h.
154
        The argument h is the halfedge being removed. The vertex v=h->opp->vert is the one being removed while h->vert survives.
154
        The argument h is the halfedge being removed. The vertex v=h->opp->vert is the one being removed while h->vert survives.
155
        The final argument indicates whether the surviving vertex should have the average position of the former vertices.
155
        The final argument indicates whether the surviving vertex should have the average position of the former vertices.
156
        By default false meaning that the surviving vertex retains it position.
156
        By default false meaning that the surviving vertex retains it position.
157
        This function is not guaranteed to keep the mesh sane unless, precond_collapse_edge has returned true !! */
157
        This function is not guaranteed to keep the mesh sane unless, precond_collapse_edge has returned true !! */
158
        void collapse_edge(HalfEdgeID h, bool avg_vertices = false);
158
        void collapse_edge(HalfEdgeID h, bool avg_vertices = false);
159
 
159
 
160
        /** \brief Split a face.
160
        /** \brief Split a face.
161
        The face, f, is split by creating an edge with endpoints v0 and v1 (the next two arguments). 
161
        The face, f, is split by creating an edge with endpoints v0 and v1 (the next two arguments). 
162
        The vertices of the old face between v0 and v1 (in counter clothiswise order) continue to belong to f. 
162
        The vertices of the old face between v0 and v1 (in counter clothiswise order) continue to belong to f. 
163
        The vertices between v1 and v0 belong to the new face. A handle to the new face is returned. */
163
        The vertices between v1 and v0 belong to the new face. A handle to the new face is returned. */
164
        FaceID split_face_by_edge(FaceID f, VertexID v0, VertexID v1);
164
        FaceID split_face_by_edge(FaceID f, VertexID v0, VertexID v1);
165
 
165
 
166
        /** \brief Split a polygon, f, by inserting a vertex at the barycenter.			
166
        /** \brief Split a polygon, f, by inserting a vertex at the barycenter.			
167
        This function is less likely to create flipped triangles than the split_face_triangulate function. 
167
        This function is less likely to create flipped triangles than the split_face_triangulate function. 
168
        On the other hand, it introduces more vertices and probably makes the triangles more acute.
168
        On the other hand, it introduces more vertices and probably makes the triangles more acute.
169
        A handle to the inserted vertex is returned. */
169
        A handle to the inserted vertex is returned. */
170
        VertexID split_face_by_vertex(FaceID f);
170
        VertexID split_face_by_vertex(FaceID f);
171
       // VertexID split_face_by_vertex(HalfEdgeID h);
171
       // VertexID split_face_by_vertex(HalfEdgeID h);
172
 
172
 
173
        /** \brief Insert a new vertex on halfedge h.
173
        /** \brief Insert a new vertex on halfedge h.
174
        The new halfedge is insterted as the previous edge to h.
174
        The new halfedge is insterted as the previous edge to h.
175
        A handle to the inserted vertex is returned. */
175
        A handle to the inserted vertex is returned. */
176
        VertexID split_edge(HalfEdgeID h);
176
        VertexID split_edge(HalfEdgeID h);
177
        
177
        
178
        /** \brief Stitch two halfedges.
178
        /** \brief Stitch two halfedges.
179
         Two boundary halfedges can be stitched together. This can be used to build a complex mesh
179
         Two boundary halfedges can be stitched together. This can be used to build a complex mesh
180
         from a bunch of simple faces. */
180
         from a bunch of simple faces. */
181
        bool stitch_boundary_edges(HalfEdgeID h0, HalfEdgeID h1);
181
        bool stitch_boundary_edges(HalfEdgeID h0, HalfEdgeID h1);
182
 
182
 
183
        /** \brief Merges two faces into a single polygon. 
183
        /** \brief Merges two faces into a single polygon. 
184
        The first face is f. The second face is adjacent to f along the halfedge h. 
184
        The first face is f. The second face is adjacent to f along the halfedge h. 
185
        This function returns true if the merging was possible and false otherwise. 
185
        This function returns true if the merging was possible and false otherwise. 
186
        Currently merge only fails if the mesh is already illegal. Thus it should, in fact, never fail. */
186
        Currently merge only fails if the mesh is already illegal. Thus it should, in fact, never fail. */
187
        bool merge_faces(FaceID f, HalfEdgeID h);
187
        bool merge_faces(FaceID f, HalfEdgeID h);
188
		
188
		
189
		/** \brief Merge all faces in the one ring of a vertex into a single polygon.
189
		/** \brief Merge all faces in the one ring of a vertex into a single polygon.
190
		The vertex is given by v.
190
		The vertex is given by v.
191
		 
191
		 
192
		The return value is the FaceID of the resulting polygonal face. 
192
		The return value is the FaceID of the resulting polygonal face. 
193
		InvalidFaceID is returned if 
193
		InvalidFaceID is returned if 
194
		- the input vertex is not in use or 
194
		- the input vertex is not in use or 
195
		- the input vertex has valence less than two which is a degenerate case.
195
		- the input vertex has valence less than two which is a degenerate case.
196
		- the input vertex is a boundary vertex of valence two - i.e. adjacent to just one face.
196
		- the input vertex is a boundary vertex of valence two - i.e. adjacent to just one face.
197
		- the same halfedge appears in two faces of the one ring of the input vertex: I.e.
197
		- the same halfedge appears in two faces of the one ring of the input vertex: I.e.
198
		the input vertex is twice adjacent to the same face!
198
		the input vertex is twice adjacent to the same face!
199
		 
199
		 
200
		Note that this function can create some unusual and arguably degenerate meshes. For instance, 
200
		Note that this function can create some unusual and arguably degenerate meshes. For instance, 
201
		two triangles which share all vertices is collapsed to a single pair of vertices connected by 
201
		two triangles which share all vertices is collapsed to a single pair of vertices connected by 
202
		a pair of halfedges bounding the same face. */
202
		a pair of halfedges bounding the same face. */
203
		FaceID merge_one_ring(VertexID v, float max_loop_length = FLT_MAX);
203
		FaceID merge_one_ring(VertexID v, float max_loop_length = FLT_MAX);
204
 
204
 
205
        /** \brief Close hole given by the invalid face of halfedgehandle h.
205
        /** \brief Close hole given by the invalid face of halfedgehandle h.
206
         returns FaceID of the created face or the face that is already there if the 
206
         returns FaceID of the created face or the face that is already there if the 
207
         face was not InvalidFaceID. */
207
         face was not InvalidFaceID. */
208
        FaceID close_hole(HalfEdgeID h);
208
        FaceID close_hole(HalfEdgeID h);
209
 
209
 
210
        /// \brief Flip an edge h. 
210
        /// \brief Flip an edge h. 
211
        void flip_edge(HalfEdgeID h);
211
        void flip_edge(HalfEdgeID h);
212
 
212
 
213
        /// Return reference to position given by VertexID
213
        /// Return reference to position given by VertexID
214
        Vec& pos(VertexID id);
214
        Vec& pos(VertexID id);
215
        /// Return const reference to position given by VertexID
215
        /// Return const reference to position given by VertexID
216
        const Vec& pos(VertexID id) const;
216
        const Vec& pos(VertexID id) const;
217
        
217
        
218
        /// Return a reference to the entire positions attribute vector
218
        /// Return a reference to the entire positions attribute vector
219
        VertexAttributeVector<Vec>& positions_attribute_vector();
219
        VertexAttributeVector<Vec>& positions_attribute_vector();
220
 
220
 
221
        /// Return a const reference to the entire positions attribute vector
221
        /// Return a const reference to the entire positions attribute vector
222
        const VertexAttributeVector<Vec>& positions_attribute_vector() const;
222
        const VertexAttributeVector<Vec>& positions_attribute_vector() const;
223
        
223
        
224
        /// Clear the mesh. Remove all faces, halfedges, and vertices.
224
        /// Clear the mesh. Remove all faces, halfedges, and vertices.
225
        void clear();
225
        void clear();
226
 
226
 
227
        /// Remove unused items from Mesh, map argument is to be used for attribute vector cleanups in order to maintain sync.
227
        /// Remove unused items from Mesh, map argument is to be used for attribute vector cleanups in order to maintain sync.
228
        void cleanup(IDRemap& map);
228
        void cleanup(IDRemap& map);
229
        /// Remove unused items from Mesh
229
        /// Remove unused items from Mesh
230
        void cleanup();
230
        void cleanup();
231
        
231
        
232
        /// Returns a Walker to the out halfedge of vertex given by VertexID
232
        /// Returns a Walker to the out halfedge of vertex given by VertexID
233
        Walker walker(VertexID id) const;
233
        Walker walker(VertexID id) const;
234
        /// Returns a Walker to the last halfedge of face given by FaceID
234
        /// Returns a Walker to the last halfedge of face given by FaceID
235
        Walker walker(FaceID id) const;
235
        Walker walker(FaceID id) const;
236
        /// Returns a Walker to the halfedge given by HalfEdgeID
236
        /// Returns a Walker to the halfedge given by HalfEdgeID
237
        Walker walker(HalfEdgeID id) const;
237
        Walker walker(HalfEdgeID id) const;
238
        
238
        
239
 
239
 
240
    private:
240
    private:
241
        
241
        
242
        ConnectivityKernel kernel;
242
        ConnectivityKernel kernel;
243
        
243
        
244
        VertexAttributeVector<Vec> positions;
244
        VertexAttributeVector<Vec> positions;
245
 
245
 
246
        // private template for building the manifold from various types
246
        // private template for building the manifold from various types
247
        template<typename size_type, typename float_type, typename int_type>
247
        template<typename size_type, typename float_type, typename int_type>
248
        void build_template(size_type no_vertices,
248
        void build_template(size_type no_vertices,
249
                            const float_type* vertvec,
249
                            const float_type* vertvec,
250
                            size_type no_faces,
250
                            size_type no_faces,
251
                            const int_type* facevec,
251
                            const int_type* facevec,
252
                            const int_type* indices);
252
                            const int_type* indices);
253
 
253
 
254
        /// Set the next and prev indices of the first and second argument respectively.
254
        /// Set the next and prev indices of the first and second argument respectively.
255
        void link(HalfEdgeID h0, HalfEdgeID h1);
255
        void link(HalfEdgeID h0, HalfEdgeID h1);
256
 
256
 
257
        /// Glue halfedges by letting the opp indices point to each other.
257
        /// Glue halfedges by letting the opp indices point to each other.
258
        void glue(HalfEdgeID h0, HalfEdgeID h1);
258
        void glue(HalfEdgeID h0, HalfEdgeID h1);
259
 
259
 
260
        /// Auxiliary function called from collapse
260
        /// Auxiliary function called from collapse
261
        void remove_face_if_degenerate(HalfEdgeID h);
261
        void remove_face_if_degenerate(HalfEdgeID h);
262
 
262
 
263
        /// Ensure boundary consistency.
263
        /// Ensure boundary consistency.
264
        void ensure_boundary_consistency(VertexID v);
264
        void ensure_boundary_consistency(VertexID v);
265
    };
265
    };
266
 
266
 
267
    /** \brief Verify Manifold Integrity
267
    /** \brief Verify Manifold Integrity
268
    Performs a series of tests to chethis that this is a valid manifold.
268
    Performs a series of tests to chethis that this is a valid manifold.
269
    This function is not rigorously constructed but seems to catch all problems so far. 
269
    This function is not rigorously constructed but seems to catch all problems so far. 
270
    The function returns true if the mesh is valid and false otherwise. */
270
    The function returns true if the mesh is valid and false otherwise. */
271
    bool valid(const Manifold& m);
271
    bool valid(const Manifold& m);
272
 
272
 
273
    /// Calculate the bounding box of the manifold
273
    /// Calculate the bounding box of the manifold
274
    void bbox(const Manifold& m, Manifold::Vec& pmin, Manifold::Vec& pmax);
274
    void bbox(const Manifold& m, Manifold::Vec& pmin, Manifold::Vec& pmax);
275
 
275
 
276
    /// Calculate the bounding sphere of the manifold
276
    /// Calculate the bounding sphere of the manifold
277
    void bsphere(const Manifold& m, Manifold::Vec& c, float& r);
277
    void bsphere(const Manifold& m, Manifold::Vec& c, float& r);
278
 
278
 
279
    /** \brief Test for legal edge collapse.
279
    /** \brief Test for legal edge collapse.
280
    The argument h is the halfedge we want to collapse. 
280
    The argument h is the halfedge we want to collapse. 
281
    If this function does not return true, it is illegal to collapse h. 
281
    If this function does not return true, it is illegal to collapse h. 
282
    The reason is that the collapse would violate the manifold property of the mesh.
282
    The reason is that the collapse would violate the manifold property of the mesh.
283
    The test is as follows:
283
    The test is as follows:
284
    1.  For the two vertices adjacent to the edge, we generate a list of all their neighbouring vertices. 
284
    1.  For the two vertices adjacent to the edge, we generate a list of all their neighbouring vertices. 
285
    We then generate a  list of the vertices that occur in both these lists. 
285
    We then generate a  list of the vertices that occur in both these lists. 
286
    That is, we find all vertices connected by edges to both endpoints of the edge and store these in a list.
286
    That is, we find all vertices connected by edges to both endpoints of the edge and store these in a list.
287
    2.  For both faces incident on the edge, chethis whether they are triangular. 
287
    2.  For both faces incident on the edge, chethis whether they are triangular. 
288
    If this is the case, the face will be removed, and it is ok that the the third vertex is connected to both endpoints. 
288
    If this is the case, the face will be removed, and it is ok that the the third vertex is connected to both endpoints. 
289
    Thus the third vertex in such a face is removed from the list generated in 1.
289
    Thus the third vertex in such a face is removed from the list generated in 1.
290
    3.  If the list is now empty, all is well. 
290
    3.  If the list is now empty, all is well. 
291
    Otherwise, there would be a vertex in the new mesh with two edges connecting it to the same vertex. Return false.
291
    Otherwise, there would be a vertex in the new mesh with two edges connecting it to the same vertex. Return false.
292
    4.  TETRAHEDRON TEST:
292
    4.  TETRAHEDRON TEST:
293
    If the valency of both vertices is three, and the incident faces are triangles, we also disallow the operation. 
293
    If the valency of both vertices is three, and the incident faces are triangles, we also disallow the operation. 
294
    Reason: A vertex valency of two and two triangles incident on the adjacent vertices makes the construction collapse.
294
    Reason: A vertex valency of two and two triangles incident on the adjacent vertices makes the construction collapse.
295
    5.  VALENCY 4 TEST:
295
    5.  VALENCY 4 TEST:
296
    If a triangle is adjacent to the edge being collapsed, it disappears.
296
    If a triangle is adjacent to the edge being collapsed, it disappears.
297
    This means the valency of the remaining edge vertex is decreased by one.
297
    This means the valency of the remaining edge vertex is decreased by one.
298
    A valency two vertex reduced to a valency one vertex is considered illegal.
298
    A valency two vertex reduced to a valency one vertex is considered illegal.
299
    6.  PREVENT MERGING HOLES:
299
    6.  PREVENT MERGING HOLES:
300
    Collapsing an edge with boundary endpoints and valid faces results in the creation where two holes meet.
300
    Collapsing an edge with boundary endpoints and valid faces results in the creation where two holes meet.
301
    A non manifold situation. We could relax this...
301
    A non manifold situation. We could relax this...
302
	7. New test: if the same face is in the one-ring of both vertices but not adjacent to the common edge,
302
	7. New test: if the same face is in the one-ring of both vertices but not adjacent to the common edge,
303
	then the result of a collapse would be a one ring where the same face occurs twice. This is disallowed as the resulting
303
	then the result of a collapse would be a one ring where the same face occurs twice. This is disallowed as the resulting
304
	 face would be non-simple.	*/
304
	 face would be non-simple.	*/
305
    bool precond_collapse_edge(const Manifold& m, HalfEdgeID h);
305
    bool precond_collapse_edge(const Manifold& m, HalfEdgeID h);
306
 
306
 
307
    /** \brief Test fpr legal edge flip. 
307
    /** \brief Test fpr legal edge flip. 
308
    Returns false if flipping cannot be performed. This is due to one of following: 
308
    Returns false if flipping cannot be performed. This is due to one of following: 
309
    1.  one of the two adjacent faces is not a triangle. 
309
    1.  one of the two adjacent faces is not a triangle. 
310
    2.  Either end point has valency three.
310
    2.  Either end point has valency three.
311
    3.  The vertices that will be connected already are. */
311
    3.  The vertices that will be connected already are. */
312
    bool precond_flip_edge(const Manifold& m, HalfEdgeID h);
312
    bool precond_flip_edge(const Manifold& m, HalfEdgeID h);
313
 
313
 
314
    /// Returns true if the halfedge is a boundary halfedge.
314
    /// Returns true if the halfedge is a boundary halfedge.
315
    bool boundary(const Manifold& m, HalfEdgeID h);
315
    bool boundary(const Manifold& m, HalfEdgeID h);
316
 
316
 
317
    /// Return the geometric length of a halfedge.
317
    /// Return the geometric length of a halfedge.
318
    float length(const Manifold& m, HalfEdgeID h);
318
    double length(const Manifold& m, HalfEdgeID h);
319
 
319
 
320
    /// Returns true if the vertex is a boundary vertex.
320
    /// Returns true if the vertex is a boundary vertex.
321
    bool boundary(const Manifold& m, VertexID v);
321
    bool boundary(const Manifold& m, VertexID v);
322
 
322
 
323
    /// Compute valency, i.e. number of incident edges.
323
    /// Compute valency, i.e. number of incident edges.
324
    int valency(const Manifold& m, VertexID v);
324
    int valency(const Manifold& m, VertexID v);
325
 
325
 
326
    /// Compute the vertex normal. This function computes the angle weighted sum of incident face normals.
326
    /// Compute the vertex normal. This function computes the angle weighted sum of incident face normals.
327
    Manifold::Vec normal(const Manifold& m, VertexID v);
327
    Manifold::Vec normal(const Manifold& m, VertexID v);
328
 
328
 
329
    /// Returns true if the two argument vertices are in each other's one-rings.
329
    /// Returns true if the two argument vertices are in each other's one-rings.
330
    bool connected(const Manifold& m, VertexID v0, VertexID v1);
330
    bool connected(const Manifold& m, VertexID v0, VertexID v1);
331
 
331
 
332
    /// Compute the number of edges of a face
332
    /// Compute the number of edges of a face
333
    int no_edges(const Manifold& m, FaceID f);
333
    int no_edges(const Manifold& m, FaceID f);
334
 
334
 
335
    /** Compute the normal of a face. If the face is not a triangle,
335
    /** Compute the normal of a face. If the face is not a triangle,
336
    the normal is not defined, but computed using the first three
336
    the normal is not defined, but computed using the first three
337
    vertices of the face. */
337
    vertices of the face. */
338
    Manifold::Vec normal(const Manifold& m, FaceID f);
338
    Manifold::Vec normal(const Manifold& m, FaceID f);
339
 
339
 
340
    /// Compute the area of a face. 
340
    /// Compute the area of a face. 
341
    float area(const Manifold& m, FaceID f);
341
    double area(const Manifold& m, FaceID f);
342
 
342
 
343
    /// Compute the perimeter of a face. 
343
    /// Compute the perimeter of a face. 
344
    float perimeter(const Manifold& m, FaceID f);
344
    double perimeter(const Manifold& m, FaceID f);
345
 
345
 
346
    /// Compute the centre of a face
346
    /// Compute the centre of a face
347
    Manifold::Vec centre(const Manifold& m, FaceID f);
347
    Manifold::Vec centre(const Manifold& m, FaceID f);
348
 
348
 
349
    /*******************************************************************
349
    /*******************************************************************
350
    * Manifold code
350
    * Manifold code
351
    *******************************************************************/
351
    *******************************************************************/
352
 
352
 
353
    inline Manifold::Manifold(){}
353
    inline Manifold::Manifold(){}
354
 
354
 
355
    inline Manifold::Vec& Manifold::pos(VertexID id)
355
    inline Manifold::Vec& Manifold::pos(VertexID id)
356
    { return positions[id]; }
356
    { return positions[id]; }
357
    inline const Manifold::Vec& Manifold::pos(VertexID id) const
357
    inline const Manifold::Vec& Manifold::pos(VertexID id) const
358
    { return positions[id]; }
358
    { return positions[id]; }
359
    
359
    
360
    inline VertexAttributeVector<Manifold::Vec>& Manifold::positions_attribute_vector()
360
    inline VertexAttributeVector<Manifold::Vec>& Manifold::positions_attribute_vector()
361
    {
361
    {
362
        return positions;
362
        return positions;
363
    }
363
    }
364
    
364
    
365
    inline const VertexAttributeVector<Manifold::Vec>& Manifold::positions_attribute_vector() const
365
    inline const VertexAttributeVector<Manifold::Vec>& Manifold::positions_attribute_vector() const
366
    {
366
    {
367
        return positions;    
367
        return positions;    
368
    }
368
    }
369
 
369
 
370
    inline void Manifold::clear()
370
    inline void Manifold::clear()
371
    { 
371
    { 
372
        kernel.clear();
372
        kernel.clear();
373
        positions.clear();
373
        positions.clear();
374
    }
374
    }
375
 
375
 
376
    inline Walker Manifold::walker(VertexID id) const
376
    inline Walker Manifold::walker(VertexID id) const
377
    { return Walker(kernel, kernel.out(id)); }
377
    { return Walker(kernel, kernel.out(id)); }
378
    inline Walker Manifold::walker(FaceID id) const
378
    inline Walker Manifold::walker(FaceID id) const
379
    { return Walker(kernel, kernel.last(id)); }
379
    { return Walker(kernel, kernel.last(id)); }
380
    inline Walker Manifold::walker(HalfEdgeID id) const
380
    inline Walker Manifold::walker(HalfEdgeID id) const
381
    { return Walker(kernel, id); }
381
    { return Walker(kernel, id); }
382
 
382
 
383
 
383
 
384
    inline void Manifold::cleanup(IDRemap& map)
384
    inline void Manifold::cleanup(IDRemap& map)
385
    {   
385
    {   
386
        kernel.cleanup(map);
386
        kernel.cleanup(map);
387
        positions.cleanup(map.vmap);
387
        positions.cleanup(map.vmap);
388
    }
388
    }
389
    
389
    
390
    inline void Manifold::cleanup()
390
    inline void Manifold::cleanup()
391
    {
391
    {
392
        IDRemap map;
392
        IDRemap map;
393
        Manifold::cleanup(map);
393
        Manifold::cleanup(map);
394
    }
394
    }
395
    
395
    
396
    inline void circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(Walker&)> f)
396
    inline int circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(Walker&)> f)
397
    {
397
    {
-
 
398
        Walker w = m.walker(v);
398
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_ccw())
399
        for(; !w.full_circle(); w = w.circulate_vertex_ccw()) f(w);
399
            f(w);
400
        return w.no_steps();
400
    }
401
    }
401
    inline void circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(VertexID)> f)
402
    inline int circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(VertexID)> f)
402
    {
403
    {
403
        circulate_vertex_ccw(m, v, [&](Walker& w){f(w.vertex());});
404
        return circulate_vertex_ccw(m, v, [&](Walker& w){f(w.vertex());});
404
    }
405
    }
405
    inline void circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(FaceID)> f)
406
    inline int circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(FaceID)> f)
406
    {
407
    {
407
        circulate_vertex_ccw(m, v, [&](Walker& w){f(w.face());});
408
        return circulate_vertex_ccw(m, v, [&](Walker& w){f(w.face());});
408
    }
409
    }
409
    inline void circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(HalfEdgeID)> f)
410
    inline int circulate_vertex_ccw(const Manifold& m, VertexID v, std::function<void(HalfEdgeID)> f)
410
    {
411
    {
411
        circulate_vertex_ccw(m, v, [&](Walker& w){f(w.halfedge());});
412
        return circulate_vertex_ccw(m, v, [&](Walker& w){f(w.halfedge());});
412
    }
413
    }
413
    
414
    
414
    inline void circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(Walker&)> f)
415
    inline int circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(Walker&)> f)
415
    {
416
    {
-
 
417
        Walker w = m.walker(v);
416
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_cw())
418
        for(; !w.full_circle(); w = w.circulate_vertex_cw()) f(w);
417
            f(w);
419
        return w.no_steps();
418
    }
420
    }
419
    inline void circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(VertexID)> f)
421
    inline int circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(VertexID)> f)
420
    {
422
    {
421
        circulate_vertex_cw(m, v, [&](Walker& w){f(w.vertex());});
423
        return circulate_vertex_cw(m, v, [&](Walker& w){f(w.vertex());});
422
    }
424
    }
423
    inline void circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(FaceID)> f)
425
    inline int circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(FaceID)> f)
424
    {
426
    {
425
        circulate_vertex_cw(m, v, [&](Walker& w){f(w.face());});
427
        return circulate_vertex_cw(m, v, [&](Walker& w){f(w.face());});
426
    }
428
    }
427
    inline void circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(HalfEdgeID)> f)
429
    inline int circulate_vertex_cw(const Manifold& m, VertexID v, std::function<void(HalfEdgeID)> f)
428
    {
430
    {
429
        circulate_vertex_cw(m, v, [&](Walker& w){f(w.halfedge());});
431
        return circulate_vertex_cw(m, v, [&](Walker& w){f(w.halfedge());});
430
    }
432
    }
431
    
433
    
432
    inline void circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(Walker&)> g)
434
    inline int circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(Walker&)> g)
433
    {
435
    {
-
 
436
        Walker w = m.walker(f);
434
        for(Walker w = m.walker(f); !w.full_circle(); w = w.circulate_face_ccw())
437
        for(; !w.full_circle(); w = w.circulate_face_ccw()) g(w);
435
            g(w);
438
        return w.no_steps();
436
    }
439
    }
437
    inline void circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(VertexID)> g)
440
    inline int circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(VertexID)> g)
438
    {
441
    {
439
        circulate_face_ccw(m, f, [&](Walker& w){g(w.vertex());});
442
        return circulate_face_ccw(m, f, [&](Walker& w){g(w.vertex());});
440
    }
443
    }
441
    inline void circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(FaceID)> g)
444
    inline int circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(FaceID)> g)
442
    {
445
    {
443
        circulate_face_ccw(m, f, [&](Walker& w){g(w.face());});
446
        return circulate_face_ccw(m, f, [&](Walker& w){g(w.face());});
444
    }
447
    }
445
    inline void circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(HalfEdgeID)> g)
448
    inline int circulate_face_ccw(const Manifold& m, FaceID f, std::function<void(HalfEdgeID)> g)
446
    {
449
    {
447
        circulate_face_ccw(m, f, [&](Walker& w){g(w.halfedge());});
450
        return circulate_face_ccw(m, f, [&](Walker& w){g(w.halfedge());});
448
    }
451
    }
449
    
452
    
450
    inline void circulate_face_cw(const Manifold& m, FaceID f, std::function<void(Walker&)> g)
453
    inline int circulate_face_cw(const Manifold& m, FaceID f, std::function<void(Walker&)> g)
451
    {
454
    {
-
 
455
        Walker w = m.walker(f);
452
        for(Walker w = m.walker(f); !w.full_circle(); w = w.circulate_face_cw())
456
        for(; !w.full_circle(); w = w.circulate_face_cw()) g(w);
453
            g(w);
457
        return w.no_steps();
454
    }
458
    }
455
    inline void circulate_face_cw(const Manifold& m, FaceID f, std::function<void(VertexID)> g)
459
    inline int circulate_face_cw(const Manifold& m, FaceID f, std::function<void(VertexID)> g)
456
    {
460
    {
457
        circulate_face_cw(m, f, [&](Walker& w){g(w.vertex());});
461
        return circulate_face_cw(m, f, [&](Walker& w){g(w.vertex());});
458
    }
462
    }
459
    inline void circulate_face_cw(const Manifold& m, FaceID f, std::function<void(FaceID)> g)
463
    inline int circulate_face_cw(const Manifold& m, FaceID f, std::function<void(FaceID)> g)
460
    {
464
    {
461
        circulate_face_cw(m, f, [&](Walker& w){g(w.face());});
465
        return circulate_face_cw(m, f, [&](Walker& w){g(w.face());});
462
    }
466
    }
463
    inline void circulate_face_cw(const Manifold& m, FaceID f, std::function<void(HalfEdgeID)> g)
467
    inline int circulate_face_cw(const Manifold& m, FaceID f, std::function<void(HalfEdgeID)> g)
464
    {
468
    {
465
        circulate_face_cw(m, f, [&](Walker& w){g(w.halfedge());});
469
        return circulate_face_cw(m, f, [&](Walker& w){g(w.halfedge());});
466
    }
470
    }
467
    
471
    
468
 
472
 
469
}
473
}
470
 
474