Subversion Repositories gelsvn

Rev

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

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

Generated by GNU Enscript 1.6.6.
379

Generated by GNU Enscript 1.6.6.
380
 
380
 
381
 
381
 
382
 
382