Subversion Repositories gelsvn

Rev

Rev 589 | Details | Compare with Previous | Last modification | View Log | RSS feed

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