-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMesh3D.h
524 lines (445 loc) · 13.4 KB
/
Mesh3D.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
#ifndef MESH3D_H
#define MESH3D_H
#include <vector>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <iostream>
#include <fstream>
#include <cassert>
#include <iomanip>
#include <queue>
#include <array>
#include <cstdlib>
#include "TinyVector.h"
/** \defgroup MeshCore Mesh data structure */
namespace MeshLib
{
//declare classes for the compiler
template <typename Real> class HE_vert;
template <typename Real> class HE_face;
template <typename Real> class HE_edge;
//! vertex class \ingroup MeshCore
/*!
* The basic vertex class for half-edge structure.
*/
template <typename Real>
class HE_vert
{
public:
TinyVector<Real, 3> pos; //!< 3D coordinate
HE_edge<Real> *edge; //!< one of the half-edges_list emanating from the vertex
TinyVector<Real, 3> normal; //!< vertex normal
ptrdiff_t id; //!< index
unsigned int degree; //!< the degree of vertex
bool tag; //!< tag for programming easily
public:
//! constructor
HE_vert(const TinyVector<Real, 3> &v)
: pos(v), edge(0), id(-1), degree(0), tag(false)
{
}
//destructor
~HE_vert()
{
}
};
//! edge class \ingroup MeshCore
/*!
* The basic edge class for half-edge structure.
*/
template <typename Real>
class HE_edge
{
public:
HE_vert<Real> *vert; //!< vertex at the end of the half-edge
HE_edge<Real> *pair; //!< oppositely oriented adjacent half-edge
HE_face<Real> *face; //!< face the half-edge borders
HE_edge<Real> *next; //!< next half-edge around the face
HE_edge<Real> *prev; //!< prev half-edge around the face
ptrdiff_t id; //!< index
bool tag; //!< tag for programming easily
public:
//!constructor
HE_edge()
: vert(0), pair(0), face(0), next(0), prev(0), id(-1), tag(false)
{
}
//!destructor
~HE_edge()
{
}
//! compute the middle point
inline TinyVector<Real, 3> GetMidPoint()
{
return (Real)0.5 * (vert->pos + pair->vert->pos);
}
};
//! face class \ingroup MeshCore
/*!
* The basic face class for half-edge structure.
*/
template <typename Real>
class HE_face
{
public:
HE_edge<Real> *edge; //!< one of the half-edges_list bordering the face
unsigned int valence; //!< the number of edges_list
TinyVector<Real, 3> normal; //!< face normal
int id; //!< index
bool tag; //!< tag for programming easily
std::vector<ptrdiff_t> texture_indices; //! texture indices
std::vector<ptrdiff_t> normal_indices; //! texture indices
int groupid;
public:
//!constructor
HE_face()
: edge(0), id(-1), tag(false), groupid(-1)
{
}
//!destructor
~HE_face()
{
}
//! compute the barycenter
inline TinyVector<Real, 3> GetCentroid()
{
TinyVector<Real, 3> V(0, 0, 0);
HE_edge<Real> *he = edge;
int i = 0;
do
{
V += he->vert->pos;
he = he->next;
i++;
}
while(he != edge);
return V / Real(i);
}
//! whether texture_indices exists
bool has_texture_map()
{
return (!texture_indices.empty()) && (texture_indices.size() == (size_t)valence);
}
//! whether normal_indices exists
bool has_normal_map()
{
return (!normal_indices.empty()) && (normal_indices.size() == (size_t)valence);
}
};
//////////////////////////////////////////////////////////////////////////
template <typename Real>
bool CompareEdgeID (HE_edge<Real> *he1, HE_edge<Real> *he2 )
{
return he1->id < he2->id;
}
template <typename Real>
bool CompareVertexID (HE_vert<Real> *hv1, HE_vert<Real> *hv2 )
{
return hv1->id < hv2->id;
}
template <typename Real>
bool CompareFaceID (HE_face<Real> *hf1, HE_face<Real> *hf2 )
{
return hf1->id < hf2->id;
}
//////////////////////////////////////////////////////////////////////////
//! Mesh3D class: Half edge data structure \ingroup MeshCore
/*!
* a half-edge based mesh data structure
* For understanding half-edge structure,
* please read the article in http://www.flipcode.com/articles/article_halfedge.shtml
*/
template <typename Real>
class Mesh3D
{
public:
// type definition
typedef std::vector<HE_vert<Real>* > VERTEX_LIST;
typedef std::vector<HE_face<Real>* > FACE_LIST;
typedef std::vector<HE_edge<Real>* > EDGE_LIST;
typedef VERTEX_LIST *PTR_VERTEX_LIST;
typedef FACE_LIST *PTR_FACE_LIST;
typedef EDGE_LIST *PTR_EDGE_LIST;
typedef typename VERTEX_LIST::iterator VERTEX_ITER;
typedef typename FACE_LIST::iterator FACE_ITER;
typedef typename EDGE_LIST::iterator EDGE_ITER;
typedef typename VERTEX_LIST::reverse_iterator VERTEX_RITER;
typedef typename FACE_LIST::reverse_iterator FACE_RITER;
typedef typename EDGE_LIST::reverse_iterator EDGE_RITER;
typedef std::pair<HE_vert<Real>*, HE_vert<Real>* > PAIR_VERTEX;
protected:
// mesh data
PTR_VERTEX_LIST vertices_list; //!< store vertices
PTR_EDGE_LIST edges_list; //!< store edges
PTR_FACE_LIST faces_list; //!< store faces
std::vector<TinyVector<float, 2> > texture_array;
std::vector<TinyVector<float, 3> > normal_array;
// mesh type
bool m_closed; //!< indicate whether the mesh is closed
bool m_quad; //!< indicate whether the mesh is quadrilateral
bool m_tri; //!< indicate whether the mesh is triangular
bool m_hex; //!< indicate whether the mesh is hexagonal
bool m_pentagon; //!< indicate whether the mesh is pentagonal
//! associate two end vertices with its edge: only useful in creating mesh
std::map<PAIR_VERTEX, HE_edge<Real>*> m_edgemap;
// mesh info
int m_num_components; //!< number of components
int m_num_boundaries; //!< number of boundaries
int m_genus; //!< the genus value
bool m_encounter_non_manifold;
public:
//! values for the bounding box
Real xmax, xmin, ymax, ymin, zmax, zmin;
//! store all the boundary vertices, each vector corresponds to one boundary
std::vector<std::vector<HE_vert<Real>*> > boundaryvertices;
std::vector<std::string> groupname;
public:
//! constructor
Mesh3D(void);
//! destructor
~Mesh3D(void);
//! get the pointer of vertices list
inline PTR_VERTEX_LIST get_vertices_list()
{
return vertices_list;
}
//! get the pointer of edges list
inline PTR_EDGE_LIST get_edges_list()
{
return edges_list;
}
//! get the pointer of faces list
inline PTR_FACE_LIST get_faces_list()
{
return faces_list;
}
//! get the total number of vertices
inline ptrdiff_t get_num_of_vertices()
{
return vertices_list ? (ptrdiff_t)vertices_list->size() : 0;
}
//! get the total number of faces
inline ptrdiff_t get_num_of_faces()
{
return faces_list ? (ptrdiff_t)faces_list->size() : 0;
}
//! get the total number of half-edges
inline ptrdiff_t get_num_of_edges()
{
return edges_list ? (ptrdiff_t)edges_list->size() : 0;
}
//! get the pointer of the id-th vertex
inline HE_vert<Real> *get_vertex(ptrdiff_t id)
{
return id >= get_num_of_vertices() || id < 0 ? NULL : (*vertices_list)[id];
}
//! get the pointer of the id-th edge
inline HE_edge<Real> *get_edge(ptrdiff_t id)
{
return id >= get_num_of_edges() || id < 0 ? NULL : (*edges_list)[id];
}
//! get the pointer of the id-th face
inline HE_face<Real> *get_face(ptrdiff_t id)
{
return id >= get_num_of_faces() || id < 0 ? NULL : (*faces_list)[id];
}
//! get the number of components
inline int get_num_of_components()
{
return m_num_components;
}
//! get the number of boundaries
inline int get_num_of_boundaries()
{
return m_num_boundaries;
}
//! get the genus
inline int genus()
{
return m_genus;
}
//! check whether the mesh is valid
inline bool is_valid()
{
if( get_num_of_vertices() == 0 || get_num_of_faces() == 0 )
{ return false; }
return true;
}
//! check whether the mesh is closed
inline bool is_closed()
{
return m_closed;
}
//! check whether the mesh is triangular
inline bool is_tri()
{
return m_tri;
}
//! check whether the mesh is quadrilateral
inline bool is_quad()
{
return m_quad;
}
//! check whether the mesh is hexgaonal
inline bool is_hex()
{
return m_hex;
}
//! check whether the mesh is pentagonal
inline bool is_pentagon()
{
return m_pentagon;
}
//! insert a vertex
/*!
* \param v a 3d point
* \return a pointer to the created vertex
*/
HE_vert<Real> *insert_vertex(const TinyVector<Real, 3> &v);
//! insert a face
/*!
* \param vec_hv the vertices list of a face
* \param texture the pointer of texture vector
* \param normal the normal of texture vector
* \return a pointer to the created face
*/
HE_face<Real> *insert_face(VERTEX_LIST &vec_hv, std::vector<ptrdiff_t> *texture = 0, std::vector<ptrdiff_t> *normal = 0);
//! check whether the vertex is on border
bool is_on_boundary(HE_vert<Real> *hv);
//! check whether the face is on border
bool is_on_boundary(HE_face<Real> *hf);
//! check whether the edge is on border
bool is_on_boundary(HE_edge<Real> *he);
//FILE IO
//! load a 3D mesh from an OFF format file
bool load_off(const char *fins);
//modified by haoxiang on 03/10/2021
void load_mesh(const std::vector<std::array<double, 3>>& pos, const std::vector<std::vector<size_t>>& indices);
//! export the current mesh to an OFF format file
void write_off(const char *fouts);
//! load a 3D mesh from an OBJ format file
bool load_obj(const char *fins);
//! export the current mesh to an OBJ format file
void write_obj(const char *fouts);
//! export to a VTK format file
void write_vtk(const char *fouts);
//! update mesh:
/*!
* call it when you have created the mesh
*/
void update_mesh();
//! update normal
/*!
* compute all the normals of vertices and faces
*/
void update_normal(bool onlyupdate_facenormal = false);
//! compute the bounding box
void compute_boundingbox();
//! get a copy of the current
Mesh3D<Real> *make_copy();
//! return a face-orientation-changed mesh
Mesh3D<Real> *reverse_orientation();
//! init edge tags
/*!
* for a pair of edges, only one of them is tagged to be true.
*/
void init_edge_tag();
//! reset all the vertices' tag
void reset_vertices_tag(bool tag_status);
//! reset all the faces' tag
void reset_faces_tag(bool tag_status);
//! reset all the edges' tag
void reset_edges_tag(bool tag_status);
//! reset all tag exclude edges' tag2
void reset_all_tag(bool tag_status);
//! translate the mesh with tran_V
void translate(const TinyVector<Real, 3> &tran_V);
//! scale the mesh
void scale(Real factorx, Real factory, Real factorz);
//! check whether there is any non-manifold case
inline bool is_encounter_nonmanifold()
{
return m_encounter_non_manifold;
}
//! set texture array
void set_texture_array(const std::vector< TinyVector<float, 2> > &textures)
{
texture_array.assign(textures.begin(), textures.end());
}
//! set normal array
void set_normal_array(const std::vector< TinyVector<float, 3> > &normals)
{
normal_array.assign(normals.begin(), normals.end());
}
//! get texture array
std::vector< TinyVector<float, 2> > &get_texture_array()
{
return texture_array;
}
//! get texture array
const std::vector< TinyVector<float, 2> > &get_texture_array() const
{
return texture_array;
}
//! get normal array
std::vector< TinyVector<float, 3> > &get_normal_array()
{
return normal_array;
}
//! get normal array
const std::vector< TinyVector<float, 3> > &get_normal_array() const
{
return normal_array;
}
//! swap edge
/*!
* \param triedge an edge between two triangular faces
*/
void swap_edge(HE_edge<Real> *triedge, bool update_vertex_normal = true);
private:
//! insert an edge
HE_edge<Real> *insert_edge(HE_vert<Real> *vstart, HE_vert<Real> *vend);
//! clear all the data
void clear_data();
//! clear vertices
void clear_vertices();
//! clear edges
void clear_edges();
//! clear faces
void clear_faces();
//! check whether the mesh is closed
void check_closed();
//! check the mesh type
void check_meshtype();
//! compute all the normals of faces
void compute_faces_list_normal();
//! compute the normal of a face
void compute_perface_normal(HE_face<Real> *hf);
//! compute all the normals of vertices
void compute_vertices_list_normal();
//! compute the normal of a vertex
void compute_pervertex_normal(HE_vert<Real> *hv);
//! compute the number of components
void compute_num_components();
//! compute the number of boundaries
void compute_num_boundaries();
//! compute the genus
void compute_genus();
//! handle the boundary half edges specially
void set_nextedge_for_border_vertices();
//! remove the vertices which have no connection to others.
void remove_hanged_vertices();
//! align edges's id
/*!
set mesh's edge(vertex(startid), vertex(endid)->id = edgeid.
only used in make_copy
*/
void copy_edge_id(ptrdiff_t edgeid, ptrdiff_t startid, ptrdiff_t endid, Mesh3D<Real> *mesh);
};
} //end of namespace
//typedef MeshLib::Mesh3D<float> Mesh3f;
typedef MeshLib::Mesh3D<double> Mesh3d;
#endif //MESH3D_H