Easy3D 2.5.3
surface_mesh.h
1/********************************************************************
2 * Copyright (C) 2015-2021 by Liangliang Nan <liangliang.nan@gmail.com>
3 * Copyright (C) 2011-2013 by Graphics & Geometry Group, Bielefeld University
4 * Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
5 *
6 * The code in this file is partly from Surface_mesh (v1.1) with
7 * modifications and enhancement:
8 * https://opensource.cit-ec.de/projects/surface_mesh
9 * The original code was distributed under the GNU GPL License.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public License
13 * as published by the Free Software Foundation, version 2.
14 *
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 ********************************************************************/
24
25#ifndef EASY3D_CORE_SURFACE_MESH_H
26#define EASY3D_CORE_SURFACE_MESH_H
27
28#include <easy3d/core/model.h>
29#include <easy3d/core/types.h>
30#include <easy3d/core/property.h>
31
32namespace easy3d {
33
51 class SurfaceMesh : public virtual Model
52 {
53
54 public: //------------------------------------------------------ topology types
55
56
60 {
61 public:
62
64 explicit BaseHandle(int _idx=-1) : idx_(_idx) {}
65
67 int idx() const { return idx_; }
68
70 void reset() { idx_=-1; }
71
73 bool is_valid() const { return idx_ != -1; }
74
76 bool operator==(const BaseHandle& _rhs) const {
77 return idx_ == _rhs.idx_;
78 }
79
81 bool operator!=(const BaseHandle& _rhs) const {
82 return idx_ != _rhs.idx_;
83 }
84
86 bool operator<(const BaseHandle& _rhs) const {
87 return idx_ < _rhs.idx_;
88 }
89
91 struct Hash {
92 std::size_t operator()(const BaseHandle& h) const { return h.idx(); }
93 };
94
95 private:
96 friend class SurfaceMesh;
97 int idx_;
98 };
99
100
103 struct Vertex : public BaseHandle
104 {
106 explicit Vertex(int _idx=-1) : BaseHandle(_idx) {}
107 std::ostream& operator<<(std::ostream& os) const { return os << 'v' << idx(); }
108 };
109
110
113 struct Halfedge : public BaseHandle
114 {
116 explicit Halfedge(int _idx=-1) : BaseHandle(_idx) {}
117 std::ostream& operator<<(std::ostream& os) const { return os << 'h' << idx(); }
118 };
119
120
123 struct Edge : public BaseHandle
124 {
126 explicit Edge(int _idx=-1) : BaseHandle(_idx) {}
127 std::ostream& operator<<(std::ostream& os) const { return os << 'e' << idx(); }
128 };
129
130
133 struct Face : public BaseHandle
134 {
136 explicit Face(int _idx=-1) : BaseHandle(_idx) {}
137 std::ostream& operator<<(std::ostream& os) const { return os << 'f' << idx(); }
138 };
139
140
141
142
143 public: //-------------------------------------------------- connectivity types
144
148 {
151 };
152
153
157 {
166 };
167
168
172 {
175 };
176
177
178
179
180 public: //------------------------------------------------------ property types
181
184 template <class T> class VertexProperty : public Property<T>
185 {
186 public:
187
189 VertexProperty() = default;
190 explicit VertexProperty(Property<T> p) : Property<T>(p) {}
191
193 typename Property<T>::reference operator[](Vertex v)
194 {
195 return Property<T>::operator[](v.idx());
196 }
197
199 typename Property<T>::const_reference operator[](Vertex v) const
200 {
201 return Property<T>::operator[](v.idx());
202 }
203 };
204
205
208 template <class T> class HalfedgeProperty : public Property<T>
209 {
210 public:
211
213 HalfedgeProperty() = default;
214 explicit HalfedgeProperty(Property<T> p) : Property<T>(p) {}
215
217 typename Property<T>::reference operator[](Halfedge h)
218 {
219 return Property<T>::operator[](h.idx());
220 }
221
223 typename Property<T>::const_reference operator[](Halfedge h) const
224 {
225 return Property<T>::operator[](h.idx());
226 }
227 };
228
229
232 template <class T> class EdgeProperty : public Property<T>
233 {
234 public:
235
237 EdgeProperty() = default;
238 explicit EdgeProperty(Property<T> p) : Property<T>(p) {}
239
241 typename Property<T>::reference operator[](Edge e)
242 {
243 return Property<T>::operator[](e.idx());
244 }
245
247 typename Property<T>::const_reference operator[](Edge e) const
248 {
249 return Property<T>::operator[](e.idx());
250 }
251 };
252
253
256 template <class T> class FaceProperty : public Property<T>
257 {
258 public:
259
261 FaceProperty() = default;
262 explicit FaceProperty(Property<T> p) : Property<T>(p) {}
263
265 typename Property<T>::reference operator[](Face f)
266 {
267 return Property<T>::operator[](f.idx());
268 }
269
271 typename Property<T>::const_reference operator[](Face f) const
272 {
273 return Property<T>::operator[](f.idx());
274 }
275 };
276
277
280 template <class T> class ModelProperty : public Property<T>
281 {
282 public:
283
285 ModelProperty() = default;
286 explicit ModelProperty(Property<T> p) : Property<T>(p) {}
287
289 typename Property<T>::reference operator[](size_t idx)
290 {
291 return Property<T>::operator[](idx);
292 }
293
295 typename Property<T>::const_reference operator[](size_t idx) const
296 {
297 return Property<T>::operator[](idx);
298 }
299 };
300
301
302
303 public: //------------------------------------------------------ iterator types
304
309 {
310 public:
311
313 explicit VertexIterator(Vertex v=Vertex(), const SurfaceMesh* m=nullptr) : hnd_(v), mesh_(m)
314 {
315 if (mesh_ && mesh_->has_garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
316 }
317
319 Vertex operator*() const { return hnd_; }
320
322 bool operator==(const VertexIterator& rhs) const
323 {
324 return (hnd_==rhs.hnd_);
325 }
326
328 bool operator!=(const VertexIterator& rhs) const
329 {
330 return !operator==(rhs);
331 }
332
335 {
336 ++hnd_.idx_;
337 assert(mesh_);
338 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
339 return *this;
340 }
341
344 {
345 --hnd_.idx_;
346 assert(mesh_);
347 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
348 return *this;
349 }
350
351 private:
352 Vertex hnd_;
353 const SurfaceMesh* mesh_;
354 };
355
356
361 {
362 public:
363
365 explicit HalfedgeIterator(Halfedge h=Halfedge(), const SurfaceMesh* m=nullptr) : hnd_(h), mesh_(m)
366 {
367 if (mesh_ && mesh_->has_garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
368 }
369
371 Halfedge operator*() const { return hnd_; }
372
374 bool operator==(const HalfedgeIterator& rhs) const
375 {
376 return (hnd_==rhs.hnd_);
377 }
378
380 bool operator!=(const HalfedgeIterator& rhs) const
381 {
382 return !operator==(rhs);
383 }
384
387 {
388 ++hnd_.idx_;
389 assert(mesh_);
390 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
391 return *this;
392 }
393
396 {
397 --hnd_.idx_;
398 assert(mesh_);
399 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
400 return *this;
401 }
402
403 private:
404 Halfedge hnd_;
405 const SurfaceMesh* mesh_;
406 };
407
408
413 {
414 public:
415
417 explicit EdgeIterator(Edge e=Edge(), const SurfaceMesh* m=nullptr) : hnd_(e), mesh_(m)
418 {
419 if (mesh_ && mesh_->has_garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
420 }
421
423 Edge operator*() const { return hnd_; }
424
426 bool operator==(const EdgeIterator& rhs) const
427 {
428 return (hnd_==rhs.hnd_);
429 }
430
432 bool operator!=(const EdgeIterator& rhs) const
433 {
434 return !operator==(rhs);
435 }
436
439 {
440 ++hnd_.idx_;
441 assert(mesh_);
442 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
443 return *this;
444 }
445
448 {
449 --hnd_.idx_;
450 assert(mesh_);
451 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
452 return *this;
453 }
454
455 private:
456 Edge hnd_;
457 const SurfaceMesh* mesh_;
458 };
459
460
465 {
466 public:
467
469 explicit FaceIterator(Face f=Face(), const SurfaceMesh* m=nullptr) : hnd_(f), mesh_(m)
470 {
471 if (mesh_ && mesh_->has_garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
472 }
473
475 Face operator*() const { return hnd_; }
476
478 bool operator==(const FaceIterator& rhs) const
479 {
480 return (hnd_==rhs.hnd_);
481 }
482
484 bool operator!=(const FaceIterator& rhs) const
485 {
486 return !operator==(rhs);
487 }
488
491 {
492 ++hnd_.idx_;
493 assert(mesh_);
494 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
495 return *this;
496 }
497
500 {
501 --hnd_.idx_;
502 assert(mesh_);
503 while (mesh_->has_garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
504 return *this;
505 }
506
507 private:
508 Face hnd_;
509 const SurfaceMesh* mesh_;
510 };
511
512
513
514 public: //-------------------------- containers for C++11 range-based for loops
515
520 {
521 public:
522 VertexContainer(VertexIterator _begin, VertexIterator _end) : begin_(_begin), end_(_end) {}
523 VertexIterator begin() const { return begin_; }
524 VertexIterator end() const { return end_; }
525 private:
526 VertexIterator begin_, end_;
527 };
528
529
530
535 {
536 public:
537 HalfedgeContainer(HalfedgeIterator _begin, HalfedgeIterator _end) : begin_(_begin), end_(_end) {}
538 HalfedgeIterator begin() const { return begin_; }
539 HalfedgeIterator end() const { return end_; }
540 private:
541 HalfedgeIterator begin_, end_;
542 };
543
544
545
550 {
551 public:
552 EdgeContainer(EdgeIterator _begin, EdgeIterator _end) : begin_(_begin), end_(_end) {}
553 EdgeIterator begin() const { return begin_; }
554 EdgeIterator end() const { return end_; }
555 private:
556 EdgeIterator begin_, end_;
557 };
558
559
560
565 {
566 public:
567 FaceContainer(FaceIterator _begin, FaceIterator _end) : begin_(_begin), end_(_end) {}
568 FaceIterator begin() const { return begin_; }
569 FaceIterator end() const { return end_; }
570 private:
571 FaceIterator begin_, end_;
572 };
573
574
575
576 public: //---------------------------------------------------- circulator types
577
595 {
596 public:
597
600 : mesh_(m), active_(true)
601 {
602 if (mesh_) halfedge_ = mesh_->out_halfedge(v);
603 }
604
607 {
608 assert(mesh_);
609 return (active_ && (mesh_==rhs.mesh_) && (halfedge_==rhs.halfedge_));
610 }
611
614 {
615 return !operator==(rhs);
616 }
617
620 {
621 assert(mesh_);
622 halfedge_ = mesh_->prev_around_source(halfedge_);
623 active_ = true;
624 return *this;
625 }
626
629 {
630 assert(mesh_);
631 halfedge_ = mesh_->next_around_source(halfedge_);
632 return *this;
633 }
634
637 {
638 assert(mesh_);
639 return mesh_->target(halfedge_);
640 }
641
643 operator bool() const { return halfedge_.is_valid(); }
644
646 Halfedge halfedge() const { return halfedge_; }
647
648 // helper for C++11 range-based for-loops
649 VertexAroundVertexCirculator& begin() { active_=!halfedge_.is_valid(); return *this; }
650 // helper for C++11 range-based for-loops
651 VertexAroundVertexCirculator& end() { active_=true; return *this; }
652
653 private:
654 const SurfaceMesh* mesh_;
655 Halfedge halfedge_;
656 // helper for C++11 range-based for-loops
657 bool active_;
658 };
659
660
678 {
679 public:
680
683 : mesh_(m), active_(true)
684 {
685 if (mesh_) halfedge_ = mesh_->out_halfedge(v);
686 }
687
690 {
691 assert(mesh_);
692 return (active_ && (mesh_==rhs.mesh_) && (halfedge_==rhs.halfedge_));
693 }
694
697 {
698 return !operator==(rhs);
699 }
700
703 {
704 assert(mesh_);
705 halfedge_ = mesh_->prev_around_source(halfedge_);
706 active_ = true;
707 return *this;
708 }
709
712 {
713 assert(mesh_);
714 halfedge_ = mesh_->next_around_source(halfedge_);
715 return *this;
716 }
717
719 Halfedge operator*() const { return halfedge_; }
720
722 operator bool() const { return halfedge_.is_valid(); }
723
724 // helper for C++11 range-based for-loops
725 HalfedgeAroundVertexCirculator& begin() { active_=!halfedge_.is_valid(); return *this; }
726 // helper for C++11 range-based for-loops
727 HalfedgeAroundVertexCirculator& end() { active_=true; return *this; }
728
729 private:
730 const SurfaceMesh* mesh_;
731 Halfedge halfedge_;
732 // helper for C++11 range-based for-loops
733 bool active_;
734 };
735
736
754 {
755 public:
756
758 explicit FaceAroundVertexCirculator(const SurfaceMesh* m=nullptr, Vertex v=Vertex())
759 : mesh_(m), active_(true)
760 {
761 if (mesh_)
762 {
763 halfedge_ = mesh_->out_halfedge(v);
764 if (halfedge_.is_valid() && mesh_->is_border(halfedge_))
765 operator++();
766 }
767 }
768
771 {
772 assert(mesh_);
773 return (active_ && (mesh_==rhs.mesh_) && (halfedge_==rhs.halfedge_));
774 }
775
778 {
779 return !operator==(rhs);
780 }
781
784 {
785 assert(mesh_ && halfedge_.is_valid());
786 do {
787 halfedge_ = mesh_->prev_around_source(halfedge_);
788 } while (mesh_->is_border(halfedge_));
789 active_ = true;
790 return *this;
791 }
792
795 {
796 assert(mesh_ && halfedge_.is_valid());
797 do
798 halfedge_ = mesh_->next_around_source(halfedge_);
799 while (mesh_->is_border(halfedge_));
800 return *this;
801 }
802
805 {
806 assert(mesh_ && halfedge_.is_valid());
807 return mesh_->face(halfedge_);
808 }
809
811 operator bool() const { return halfedge_.is_valid(); }
812
813 // helper for C++11 range-based for-loops
814 FaceAroundVertexCirculator& begin() { active_=!halfedge_.is_valid(); return *this; }
815 // helper for C++11 range-based for-loops
816 FaceAroundVertexCirculator& end() { active_=true; return *this; }
817
818 private:
819 const SurfaceMesh* mesh_;
820 Halfedge halfedge_;
821 // helper for C++11 range-based for-loops
822 bool active_;
823 };
824
825
843 {
844 public:
845
847 explicit VertexAroundFaceCirculator(const SurfaceMesh* m=nullptr, Face f=Face())
848 : mesh_(m), active_(true)
849 {
850 if (mesh_) halfedge_ = mesh_->halfedge(f);
851 }
852
855 {
856 assert(mesh_);
857 return (active_ && (mesh_==rhs.mesh_) && (halfedge_==rhs.halfedge_));
858 }
859
862 {
863 return !operator==(rhs);
864 }
865
868 {
869 assert(mesh_ && halfedge_.is_valid());
870 halfedge_ = mesh_->next(halfedge_);
871 active_ = true;
872 return *this;
873 }
874
877 {
878 assert(mesh_ && halfedge_.is_valid());
879 halfedge_ = mesh_->prev(halfedge_);
880 return *this;
881 }
882
885 {
886 assert(mesh_ && halfedge_.is_valid());
887 return mesh_->target(halfedge_);
888 }
889
890 // helper for C++11 range-based for-loops
891 VertexAroundFaceCirculator& begin() { active_=false; return *this; }
892 // helper for C++11 range-based for-loops
893 VertexAroundFaceCirculator& end() { active_=true; return *this; }
894
895 private:
896 const SurfaceMesh* mesh_;
897 Halfedge halfedge_;
898 // helper for C++11 range-based for-loops
899 bool active_;
900 };
901
902
920 {
921 public:
922
924 explicit HalfedgeAroundFaceCirculator(const SurfaceMesh* m=nullptr, Face f=Face())
925 : mesh_(m), active_(true)
926 {
927 if (mesh_) halfedge_ = mesh_->halfedge(f);
928 }
929
932 {
933 assert(mesh_);
934 return (active_ && (mesh_==rhs.mesh_) && (halfedge_==rhs.halfedge_));
935 }
936
939 {
940 return !operator==(rhs);
941 }
942
945 {
946 assert(mesh_ && halfedge_.is_valid());
947 halfedge_ = mesh_->next(halfedge_);
948 active_ = true;
949 return *this;
950 }
951
954 {
955 assert(mesh_ && halfedge_.is_valid());
956 halfedge_ = mesh_->prev(halfedge_);
957 return *this;
958 }
959
961 Halfedge operator*() const { return halfedge_; }
962
963 // helper for C++11 range-based for-loops
964 HalfedgeAroundFaceCirculator& begin() { active_=false; return *this; }
965 // helper for C++11 range-based for-loops
966 HalfedgeAroundFaceCirculator& end() { active_=true; return *this; }
967
968 private:
969 const SurfaceMesh* mesh_;
970 Halfedge halfedge_;
971 // helper for C++11 range-based for-loops
972 bool active_;
973 };
974
975
976
977 public: //-------------------------------------------- constructor / destructor
978
980
981
983 SurfaceMesh();
984
986 ~SurfaceMesh() override = default;
987
989 SurfaceMesh(const SurfaceMesh& rhs) { operator=(rhs); }
990
992 SurfaceMesh& operator=(const SurfaceMesh& rhs);
993
1000 SurfaceMesh& operator+=(const SurfaceMesh& other) { join(other); return *this; }
1001
1008 SurfaceMesh& join(const SurfaceMesh& other);
1009
1011 SurfaceMesh& assign(const SurfaceMesh& rhs);
1013
1016
1020 bool read(const std::string& filename);
1021
1025 bool write(const std::string& filename) const;
1027
1028 public: //----------------------------------------------- add new vertex / face
1029
1031
1032
1034 Vertex add_vertex(const vec3& p) { Vertex v = new_vertex(); vpoint_[v] = p; return v; }
1035
1039 Face add_face(const std::vector<Vertex>& vertices);
1040
1044 Face add_triangle(Vertex v1, Vertex v2, Vertex v3);
1045
1049 Face add_quad(Vertex v1, Vertex v2, Vertex v3, Vertex v4);
1050
1052
1053
1054 public: //--------------------------------------------------- memory management
1055
1057
1058
1060 unsigned int vertices_size() const { return (unsigned int) vprops_.size(); }
1062 unsigned int halfedges_size() const { return (unsigned int) hprops_.size(); }
1064 unsigned int edges_size() const { return (unsigned int) eprops_.size(); }
1066 unsigned int faces_size() const { return (unsigned int) fprops_.size(); }
1067
1068
1070 unsigned int n_vertices() const { return vertices_size() - deleted_vertices_; }
1072 unsigned int n_halfedges() const { return halfedges_size() - 2*deleted_edges_; }
1074 unsigned int n_edges() const { return edges_size() - deleted_edges_; }
1076 unsigned int n_faces() const { return faces_size() - deleted_faces_; }
1077
1081 void clear();
1082
1084 void reserve(unsigned int nvertices,
1085 unsigned int nedges,
1086 unsigned int nfaces );
1087
1091 void resize(unsigned int nv, unsigned int ne, unsigned int nf) {
1092 vprops_.resize(nv);
1093 hprops_.resize(2 * ne);
1094 eprops_.resize(ne);
1095 fprops_.resize(nf);
1096 }
1097
1099 bool has_garbage() const { return garbage_; }
1100
1102 void collect_garbage();
1103
1104
1107 bool is_deleted(Vertex v) const
1108 {
1109 return vdeleted_[v];
1110 }
1113 bool is_deleted(Halfedge h) const
1114 {
1115 return edeleted_[edge(h)];
1116 }
1119 bool is_deleted(Edge e) const
1120 {
1121 return edeleted_[e];
1122 }
1125 bool is_deleted(Face f) const
1126 {
1127 return fdeleted_[f];
1128 }
1129
1130
1132 bool is_valid(Vertex v) const
1133 {
1134 return (0 <= v.idx()) && (v.idx() < (int)vertices_size());
1135 }
1137 bool is_valid(Halfedge h) const
1138 {
1139 return (0 <= h.idx()) && (h.idx() < (int)halfedges_size());
1140 }
1142 bool is_valid(Edge e) const
1143 {
1144 return (0 <= e.idx()) && (e.idx() < (int)edges_size());
1145 }
1147 bool is_valid(Face f) const
1148 {
1149 return (0 <= f.idx()) && (f.idx() < (int)faces_size());
1150 }
1151
1153
1154
1155
1156
1157 public: //---------------------------------------------- low-level connectivity
1158
1160
1161
1165 {
1166 return vconn_[v].halfedge_;
1167 }
1168
1171 {
1172 vconn_[v].halfedge_ = h;
1173 }
1174
1176 bool is_border(Vertex v) const
1177 {
1178 Halfedge h(out_halfedge(v));
1179 return (!(h.is_valid() && face(h).is_valid()));
1180 }
1181
1183 bool is_isolated(Vertex v) const
1184 {
1185 return !out_halfedge(v).is_valid();
1186 }
1187
1189 bool is_manifold(Vertex v) const
1190 {
1191 // [Liangliang: I doubt. It should also check if more than 1 cones meet at the same vertex.
1192 // See the "resolve_non_manifold_vertices()" in manifold_builder.cpp
1193
1194 // The vertex is non-manifold if more than one gap exists, i.e.
1195 // more than one outgoing boundary halfedge.
1196 int n(0);
1197 HalfedgeAroundVertexCirculator hit = halfedges(v), hend=hit;
1198 if (hit) do
1199 {
1200 if (is_border(*hit))
1201 ++n;
1202 }
1203 while (++hit!=hend);
1204 return n<2;
1205 }
1206
1208 bool is_degenerate(Face f) const;
1209
1212 {
1213 return hconn_[h].vertex_;
1214 }
1215
1218 {
1219 return target(opposite(h));
1220 }
1221
1224 {
1225 hconn_[h].vertex_ = v;
1226 }
1227
1230 {
1231 return hconn_[h].face_;
1232 }
1233
1236 {
1237 hconn_[h].face_ = f;
1238 }
1239
1242 {
1243 return hconn_[h].next_;
1244 }
1245
1248 {
1249 hconn_[h].next_ = nh;
1250 hconn_[nh].prev_ = h;
1251 }
1252
1255 {
1256 return hconn_[h].prev_;
1257 }
1258
1261 {
1262 return Halfedge((h.idx() & 1) ? h.idx()-1 : h.idx()+1);
1263 }
1264
1268 {
1269 return opposite(prev(h));
1270 }
1271
1275 {
1276 return next(opposite(h));
1277 }
1278
1282 {
1283 return prev(opposite(h));
1284 }
1285
1289 {
1290 return opposite(next(h));
1291 }
1292
1295 {
1296 return Edge(h.idx() >> 1);
1297 }
1298
1300 bool is_border(Halfedge h) const
1301 {
1302 return !face(h).is_valid();
1303 }
1304
1305
1307 Halfedge halfedge(Edge e, unsigned int i) const
1308 {
1309 assert(i<=1);
1310 return Halfedge(static_cast<int>((e.idx() << 1) + i));
1311 }
1312
1314 Vertex vertex(Edge e, unsigned int i) const
1315 {
1316 assert(i<=1);
1317 return target(halfedge(e, i));
1318 }
1319
1321 Face face(Edge e, unsigned int i) const
1322 {
1323 assert(i<=1);
1324 return face(halfedge(e, i));
1325 }
1326
1329 bool is_border(Edge e) const
1330 {
1331 return (is_border(halfedge(e, 0)) || is_border(halfedge(e, 1)));
1332 }
1333
1336 {
1337 return fconn_[f].halfedge_;
1338 }
1339
1342 {
1343 fconn_[f].halfedge_ = h;
1344 }
1345
1347 bool is_border(Face f) const
1348 {
1349 Halfedge h = halfedge(f);
1350 Halfedge hh = h;
1351 do
1352 {
1353 if (is_border(opposite(h)))
1354 return true;
1355 h = next(h);
1356 }
1357 while (h != hh);
1358 return false;
1359 }
1360
1362
1363
1364
1365
1366 public: //--------------------------------------------------- property handling
1367
1369
1370
1374 template <class T> VertexProperty<T> add_vertex_property(const std::string& name, const T t=T())
1375 {
1376 return VertexProperty<T>(vprops_.add<T>(name, t));
1377 }
1381 template <class T> HalfedgeProperty<T> add_halfedge_property(const std::string& name, const T t=T())
1382 {
1383 return HalfedgeProperty<T>(hprops_.add<T>(name, t));
1384 }
1388 template <class T> EdgeProperty<T> add_edge_property(const std::string& name, const T t=T())
1389 {
1390 return EdgeProperty<T>(eprops_.add<T>(name, t));
1391 }
1395 template <class T> FaceProperty<T> add_face_property(const std::string& name, const T t=T())
1396 {
1397 return FaceProperty<T>(fprops_.add<T>(name, t));
1398 }
1409 template <class T> ModelProperty<T> add_model_property(const std::string& name, const T t=T())
1410 {
1411 return ModelProperty<T>(mprops_.add<T>(name, t));
1412 }
1413
1414
1417 template <class T> VertexProperty<T> get_vertex_property(const std::string& name) const
1418 {
1419 return VertexProperty<T>(vprops_.get<T>(name));
1420 }
1423 template <class T> HalfedgeProperty<T> get_halfedge_property(const std::string& name) const
1424 {
1425 return HalfedgeProperty<T>(hprops_.get<T>(name));
1426 }
1429 template <class T> EdgeProperty<T> get_edge_property(const std::string& name) const
1430 {
1431 return EdgeProperty<T>(eprops_.get<T>(name));
1432 }
1435 template <class T> FaceProperty<T> get_face_property(const std::string& name) const
1436 {
1437 return FaceProperty<T>(fprops_.get<T>(name));
1438 }
1449 template <class T> ModelProperty<T> get_model_property(const std::string& name) const
1450 {
1451 return ModelProperty<T>(mprops_.get<T>(name));
1452 }
1453
1454
1457 template <class T> VertexProperty<T> vertex_property(const std::string& name, const T t=T())
1458 {
1459 return VertexProperty<T>(vprops_.get_or_add<T>(name, t));
1460 }
1463 template <class T> HalfedgeProperty<T> halfedge_property(const std::string& name, const T t=T())
1464 {
1465 return HalfedgeProperty<T>(hprops_.get_or_add<T>(name, t));
1466 }
1469 template <class T> EdgeProperty<T> edge_property(const std::string& name, const T t=T())
1470 {
1471 return EdgeProperty<T>(eprops_.get_or_add<T>(name, t));
1472 }
1475 template <class T> FaceProperty<T> face_property(const std::string& name, const T t=T())
1476 {
1477 return FaceProperty<T>(fprops_.get_or_add<T>(name, t));
1478 }
1479
1482 template <class T> ModelProperty<T> model_property(const std::string& name, const T t=T())
1483 {
1484 return ModelProperty<T>(mprops_.get_or_add<T>(name, t));
1485 }
1486
1487
1489 template<class T>
1490 bool remove_vertex_property(VertexProperty<T> &p) { return vprops_.remove(p); }
1491
1493 bool remove_vertex_property(const std::string &n) { return vprops_.remove(n); }
1494
1496 template<class T>
1497 bool remove_halfedge_property(HalfedgeProperty<T> &p) { return hprops_.remove(p); }
1498
1500 bool remove_halfedge_property(const std::string &n) { return hprops_.remove(n); }
1501
1503 template<class T>
1504 bool remove_edge_property(EdgeProperty<T> &p) { return eprops_.remove(p); }
1505
1507 bool remove_edge_property(const std::string &n) { return eprops_.remove(n); }
1508
1510 template<class T>
1511 bool remove_face_property(FaceProperty<T> &p) { return fprops_.remove(p); }
1512
1514 bool remove_face_property(const std::string &n) { return fprops_.remove(n); }
1515
1517 template<class T>
1518 bool remove_model_property(ModelProperty<T> &p) { return mprops_.remove(p); }
1519
1521 bool remove_model_property(const std::string &n) { return mprops_.remove(n); }
1522
1524 bool rename_vertex_property(const std::string &old_name, const std::string &new_name) {
1525 return vprops_.rename(old_name, new_name);
1526 }
1527
1529 bool rename_face_property(const std::string &old_name, const std::string &new_name) {
1530 return fprops_.rename(old_name, new_name);
1531 }
1532
1534 bool rename_edge_property(const std::string &old_name, const std::string &new_name) {
1535 return eprops_.rename(old_name, new_name);
1536 }
1537
1539 bool rename_halfedge_property(const std::string &old_name, const std::string &new_name) {
1540 return hprops_.rename(old_name, new_name);
1541 }
1542
1544 bool rename_model_property(const std::string &old_name, const std::string &new_name) {
1545 return mprops_.rename(old_name, new_name);
1546 }
1547
1548
1551 const std::type_info& get_vertex_property_type(const std::string& name) const
1552 {
1553 return vprops_.get_type(name);
1554 }
1557 const std::type_info& get_halfedge_property_type(const std::string& name) const
1558 {
1559 return hprops_.get_type(name);
1560 }
1563 const std::type_info& get_edge_property_type(const std::string& name) const
1564 {
1565 return eprops_.get_type(name);
1566 }
1569 const std::type_info& get_face_property_type(const std::string& name) const
1570 {
1571 return fprops_.get_type(name);
1572 }
1575 const std::type_info& get_model_property_type(const std::string& name) const
1576 {
1577 return mprops_.get_type(name);
1578 }
1579
1580
1582 std::vector<std::string> vertex_properties() const
1583 {
1584 return vprops_.properties();
1585 }
1587 std::vector<std::string> halfedge_properties() const
1588 {
1589 return hprops_.properties();
1590 }
1592 std::vector<std::string> edge_properties() const
1593 {
1594 return eprops_.properties();
1595 }
1597 std::vector<std::string> face_properties() const
1598 {
1599 return fprops_.properties();
1600 }
1602 std::vector<std::string> model_properties() const
1603 {
1604 return mprops_.properties();
1605 }
1606
1608 void property_stats(std::ostream &output) const override;
1609
1611
1612
1613 public: //--------------------------------------------- iterators & circulators
1614
1616
1617
1620 {
1621 return VertexIterator(Vertex(0), this);
1622 }
1623
1626 {
1627 return VertexIterator(Vertex(static_cast<int>(vertices_size())), this);
1628 }
1629
1632 {
1634 }
1635
1638 {
1639 return HalfedgeIterator(Halfedge(0), this);
1640 }
1641
1644 {
1645 return HalfedgeIterator(Halfedge(static_cast<int>(halfedges_size())), this);
1646 }
1647
1650 {
1652 }
1653
1656 {
1657 return EdgeIterator(Edge(0), this);
1658 }
1659
1662 {
1663 return EdgeIterator(Edge(static_cast<int>(edges_size())), this);
1664 }
1665
1668 {
1669 return EdgeContainer(edges_begin(), edges_end());
1670 }
1671
1674 {
1675 return FaceIterator(Face(0), this);
1676 }
1677
1680 {
1681 return FaceIterator(Face(static_cast<int>(faces_size())), this);
1682 }
1683
1686 {
1687 return FaceContainer(faces_begin(), faces_end());
1688 }
1689
1692 {
1693 return VertexAroundVertexCirculator(this, v);
1694 }
1695
1698 {
1699 return HalfedgeAroundVertexCirculator(this, v);
1700 }
1701
1704 {
1705 return FaceAroundVertexCirculator(this, v);
1706 }
1707
1710 {
1711 return VertexAroundFaceCirculator(this, f);
1712 }
1713
1716 {
1717 return HalfedgeAroundFaceCirculator(this, f);
1718 }
1719
1721
1722
1723 public: //--------------------------------------------- higher-level operations
1724
1726
1727
1729 bool is_closed() const;
1730
1734 bool is_triangle_mesh() const;
1735
1738 bool is_quad_mesh() const;
1739
1742 void triangulate();
1743
1746 void triangulate(Face f);
1747
1751 void reverse_orientation();
1752
1755 bool is_collapse_ok(Halfedge h) const;
1756
1767 void collapse(Halfedge h);
1768
1769
1775 Vertex split(Face f, const vec3& p) { Vertex v=add_vertex(p); split(f,v); return v; }
1776
1781 void split(Face f, Vertex v);
1782
1783
1792 Halfedge split(Edge e, const vec3& p) { return split(e, add_vertex(p)); }
1793
1794
1803 Halfedge split(Edge e, Vertex v);
1804
1805
1815 {
1816 return insert_vertex(halfedge(e,0), add_vertex(p));
1817 }
1818
1827 {
1828 return insert_vertex(halfedge(e,0), v);
1829 }
1830
1838 Halfedge insert_vertex(Halfedge h, Vertex v);
1839
1847 bool join_edges(Vertex v);
1852 bool can_join_edges(Vertex v) const;
1853
1854
1858 Halfedge insert_edge(Halfedge h0, Halfedge h1);
1859
1860
1866 bool is_flip_ok(Edge e) const;
1867
1873 void flip(Edge e);
1874
1875
1880 bool is_stitch_ok(Halfedge h0, Halfedge h1);
1881
1888 void stitch(Halfedge h0, Halfedge h1);
1889
1890
1893 unsigned int valence(Vertex v) const;
1894
1896 unsigned int valence(Face f) const;
1897
1899 Halfedge find_halfedge(Vertex start, Vertex end) const;
1900
1902 Edge find_edge(Vertex a, Vertex b) const;
1903
1907 void delete_vertex(Vertex v);
1908
1912 void delete_edge(Edge e);
1913
1917 void delete_face(Face f);
1918
1920
1921
1922 public: //------------------------------------------ geometry-related functions
1923
1925
1926
1928 const vec3& position(Vertex v) const { return vpoint_[v]; }
1929
1931 vec3& position(Vertex v) { return vpoint_[v]; }
1932
1934 const std::vector<vec3>& points() const override { return vpoint_.vector(); }
1935
1937 std::vector<vec3>& points() override { return vpoint_.vector(); }
1938
1940 void update_face_normals();
1941
1943 vec3 compute_face_normal(Face f) const;
1944
1946 void update_vertex_normals();
1947
1950 vec3 compute_vertex_normal(Vertex v) const;
1951
1953 float edge_length(Edge e) const;
1955 float edge_length(Halfedge h) const;
1956
1958
1959
1960 private: //---------------------------------------------- allocate new elements
1961
1963 Vertex new_vertex()
1964 {
1965 vprops_.push_back();
1966 return Vertex(static_cast<int>(vertices_size()-1));
1967 }
1968
1970 Halfedge new_edge(Vertex start, Vertex end)
1971 {
1972 assert(start != end);
1973
1974 eprops_.push_back();
1975 hprops_.push_back();
1976 hprops_.push_back();
1977
1978 Halfedge h0(static_cast<int>(halfedges_size()-2));
1979 Halfedge h1(static_cast<int>(halfedges_size()-1));
1980
1981 set_target(h0, end);
1982 set_target(h1, start);
1983
1984 return h0;
1985 }
1986
1988 Face new_face()
1989 {
1990 fprops_.push_back();
1991 return Face(static_cast<int>(faces_size()-1));
1992 }
1993
1994
1995 private: //--------------------------------------------------- helper functions
1996
2003 void adjust_outgoing_halfedges();
2004
2007 void adjust_outgoing_halfedge(Vertex v);
2008
2010 void remove_edge(Halfedge h);
2011
2013 void remove_loop(Halfedge h);
2014
2017 bool can_merge_vertices(Halfedge h0, Halfedge h1) const;
2018
2019 private: //------------------------------------------------------- private data
2020
2021 PropertyContainer vprops_;
2022 PropertyContainer hprops_;
2023 PropertyContainer eprops_;
2024 PropertyContainer fprops_;
2025 PropertyContainer mprops_;
2026
2027 VertexProperty<VertexConnectivity> vconn_;
2028 HalfedgeProperty<HalfedgeConnectivity> hconn_;
2029 FaceProperty<FaceConnectivity> fconn_;
2030
2031 VertexProperty<bool> vdeleted_;
2032 EdgeProperty<bool> edeleted_;
2033 FaceProperty<bool> fdeleted_;
2034
2035 VertexProperty<vec3> vpoint_;
2036 VertexProperty<vec3> vnormal_;
2037 FaceProperty<vec3> fnormal_;
2038
2039 unsigned int deleted_vertices_;
2040 unsigned int deleted_edges_;
2041 unsigned int deleted_faces_;
2042 bool garbage_;
2043
2044 // helper data for add_face()
2045 typedef std::pair<Halfedge, Halfedge> NextCacheEntry;
2046 typedef std::vector<NextCacheEntry> NextCache;
2047 std::vector<Vertex> add_face_vertices_;
2048 std::vector<Halfedge> add_face_halfedges_;
2049 std::vector<bool> add_face_is_new_;
2050 std::vector<bool> add_face_needs_adjust_;
2051 NextCache add_face_next_cache_;
2052
2053 friend class SurfaceMeshBuilder;
2054 };
2055
2056
2057 //------------------------------------------------------------ output operators
2058
2060 inline std::ostream& operator<<(std::ostream& os, SurfaceMesh::Vertex v)
2061 {
2062 return (os << 'v' << v.idx());
2063 }
2064
2066 inline std::ostream& operator<<(std::ostream& os, SurfaceMesh::Halfedge h)
2067 {
2068 return (os << 'h' << h.idx());
2069 }
2070
2072 inline std::ostream& operator<<(std::ostream& os, SurfaceMesh::Edge e)
2073 {
2074 return (os << 'e' << e.idx());
2075 }
2076
2078 inline std::ostream& operator<<(std::ostream& os, SurfaceMesh::Face f)
2079 {
2080 return (os << 'f' << f.idx());
2081 }
2082
2083} // namespace easy3d
2084
2085#endif // EASY3D_CORE_SURFACE_MESH_H
The base class of renderable 3D models.
Definition: model.h:49
const std::string & name() const
The name of a model.
Definition: model.h:60
Implementation of a generic property.
Definition: property.h:253
Definition: surface_mesh.h:60
bool operator!=(const BaseHandle &_rhs) const
are two handles different?
Definition: surface_mesh.h:81
bool is_valid() const
return whether the handle is valid, i.e., the index is not equal to -1.
Definition: surface_mesh.h:73
int idx() const
Get the underlying index of this handle.
Definition: surface_mesh.h:67
bool operator<(const BaseHandle &_rhs) const
compare operator useful for sorting handles
Definition: surface_mesh.h:86
bool operator==(const BaseHandle &_rhs) const
are two handles equal?
Definition: surface_mesh.h:76
void reset()
reset handle to be invalid (index=-1)
Definition: surface_mesh.h:70
BaseHandle(int _idx=-1)
constructor
Definition: surface_mesh.h:64
Definition: surface_mesh.h:550
Definition: surface_mesh.h:413
bool operator!=(const EdgeIterator &rhs) const
are two iterators different?
Definition: surface_mesh.h:432
EdgeIterator & operator++()
pre-increment iterator
Definition: surface_mesh.h:438
Edge operator*() const
get the edge the iterator refers to
Definition: surface_mesh.h:423
bool operator==(const EdgeIterator &rhs) const
are two iterators equal?
Definition: surface_mesh.h:426
EdgeIterator(Edge e=Edge(), const SurfaceMesh *m=nullptr)
Default constructor.
Definition: surface_mesh.h:417
EdgeIterator & operator--()
pre-decrement iterator
Definition: surface_mesh.h:447
Definition: surface_mesh.h:233
EdgeProperty()=default
default constructor
Property< T >::reference operator[](Edge e)
access the data stored for edge e
Definition: surface_mesh.h:241
Property< T >::const_reference operator[](Edge e) const
access the data stored for edge e
Definition: surface_mesh.h:247
bool operator!=(const FaceAroundVertexCirculator &rhs) const
are two circulators different?
Definition: surface_mesh.h:777
bool operator==(const FaceAroundVertexCirculator &rhs) const
are two circulators equal?
Definition: surface_mesh.h:770
FaceAroundVertexCirculator & operator++()
pre-increment (rotates counter-clockwise)
Definition: surface_mesh.h:783
Face operator*() const
get the face the circulator refers to
Definition: surface_mesh.h:804
FaceAroundVertexCirculator(const SurfaceMesh *m=nullptr, Vertex v=Vertex())
construct with mesh and vertex (vertex should not be isolated!)
Definition: surface_mesh.h:758
FaceAroundVertexCirculator & operator--()
pre-decrement (rotate clockwise)
Definition: surface_mesh.h:794
Definition: surface_mesh.h:565
Definition: surface_mesh.h:465
bool operator!=(const FaceIterator &rhs) const
are two iterators different?
Definition: surface_mesh.h:484
bool operator==(const FaceIterator &rhs) const
are two iterators equal?
Definition: surface_mesh.h:478
FaceIterator & operator--()
pre-decrement iterator
Definition: surface_mesh.h:499
FaceIterator(Face f=Face(), const SurfaceMesh *m=nullptr)
Default constructor.
Definition: surface_mesh.h:469
Face operator*() const
get the face the iterator refers to
Definition: surface_mesh.h:475
FaceIterator & operator++()
pre-increment iterator
Definition: surface_mesh.h:490
Definition: surface_mesh.h:257
Property< T >::reference operator[](Face f)
access the data stored for face f
Definition: surface_mesh.h:265
FaceProperty()=default
default constructor
Property< T >::const_reference operator[](Face f) const
access the data stored for face f
Definition: surface_mesh.h:271
Halfedge operator*() const
get the halfedge the circulator refers to
Definition: surface_mesh.h:961
HalfedgeAroundFaceCirculator & operator--()
pre-decrement (rotates clockwise)
Definition: surface_mesh.h:953
bool operator==(const HalfedgeAroundFaceCirculator &rhs) const
are two circulators equal?
Definition: surface_mesh.h:931
bool operator!=(const HalfedgeAroundFaceCirculator &rhs) const
are two circulators different?
Definition: surface_mesh.h:938
HalfedgeAroundFaceCirculator(const SurfaceMesh *m=nullptr, Face f=Face())
default constructor
Definition: surface_mesh.h:924
HalfedgeAroundFaceCirculator & operator++()
pre-increment (rotates counter-clockwise)
Definition: surface_mesh.h:944
bool operator==(const HalfedgeAroundVertexCirculator &rhs) const
are two circulators equal?
Definition: surface_mesh.h:689
Halfedge operator*() const
get the halfedge the circulator refers to
Definition: surface_mesh.h:719
HalfedgeAroundVertexCirculator & operator++()
pre-increment (rotate counter-clockwise)
Definition: surface_mesh.h:702
bool operator!=(const HalfedgeAroundVertexCirculator &rhs) const
are two circulators different?
Definition: surface_mesh.h:696
HalfedgeAroundVertexCirculator & operator--()
pre-decrement (rotate clockwise)
Definition: surface_mesh.h:711
HalfedgeAroundVertexCirculator(const SurfaceMesh *m=nullptr, Vertex v=Vertex())
default constructor
Definition: surface_mesh.h:682
Definition: surface_mesh.h:535
Definition: surface_mesh.h:361
HalfedgeIterator & operator--()
pre-decrement iterator
Definition: surface_mesh.h:395
Halfedge operator*() const
get the halfedge the iterator refers to
Definition: surface_mesh.h:371
HalfedgeIterator(Halfedge h=Halfedge(), const SurfaceMesh *m=nullptr)
Default constructor.
Definition: surface_mesh.h:365
HalfedgeIterator & operator++()
pre-increment iterator
Definition: surface_mesh.h:386
bool operator==(const HalfedgeIterator &rhs) const
are two iterators equal?
Definition: surface_mesh.h:374
bool operator!=(const HalfedgeIterator &rhs) const
are two iterators different?
Definition: surface_mesh.h:380
Definition: surface_mesh.h:209
Property< T >::reference operator[](Halfedge h)
access the data stored for halfedge h
Definition: surface_mesh.h:217
Property< T >::const_reference operator[](Halfedge h) const
access the data stored for halfedge h
Definition: surface_mesh.h:223
HalfedgeProperty()=default
default constructor
Definition: surface_mesh.h:281
ModelProperty()=default
default constructor
Property< T >::const_reference operator[](size_t idx) const
access the data stored for the mesh
Definition: surface_mesh.h:295
Property< T >::reference operator[](size_t idx)
access the data stored for the mesh
Definition: surface_mesh.h:289
VertexAroundFaceCirculator(const SurfaceMesh *m=nullptr, Face f=Face())
default constructor
Definition: surface_mesh.h:847
bool operator!=(const VertexAroundFaceCirculator &rhs) const
are two circulators different?
Definition: surface_mesh.h:861
Vertex operator*() const
get the vertex the circulator refers to
Definition: surface_mesh.h:884
bool operator==(const VertexAroundFaceCirculator &rhs) const
are two circulators equal?
Definition: surface_mesh.h:854
VertexAroundFaceCirculator & operator--()
pre-decrement (rotates clockwise)
Definition: surface_mesh.h:876
VertexAroundFaceCirculator & operator++()
pre-increment (rotates counter-clockwise)
Definition: surface_mesh.h:867
bool operator!=(const VertexAroundVertexCirculator &rhs) const
are two circulators different?
Definition: surface_mesh.h:613
VertexAroundVertexCirculator & operator++()
pre-increment (rotate counter-clockwise)
Definition: surface_mesh.h:619
Vertex operator*() const
get the vertex the circulator refers to
Definition: surface_mesh.h:636
VertexAroundVertexCirculator(const SurfaceMesh *m=nullptr, Vertex v=Vertex())
default constructor
Definition: surface_mesh.h:599
bool operator==(const VertexAroundVertexCirculator &rhs) const
are two circulators equal?
Definition: surface_mesh.h:606
VertexAroundVertexCirculator & operator--()
pre-decrement (rotate clockwise)
Definition: surface_mesh.h:628
Halfedge halfedge() const
return current halfedge
Definition: surface_mesh.h:646
Definition: surface_mesh.h:520
Definition: surface_mesh.h:309
Vertex operator*() const
get the vertex the iterator refers to
Definition: surface_mesh.h:319
bool operator==(const VertexIterator &rhs) const
are two iterators equal?
Definition: surface_mesh.h:322
VertexIterator & operator--()
pre-decrement iterator
Definition: surface_mesh.h:343
bool operator!=(const VertexIterator &rhs) const
are two iterators different?
Definition: surface_mesh.h:328
VertexIterator(Vertex v=Vertex(), const SurfaceMesh *m=nullptr)
Default constructor.
Definition: surface_mesh.h:313
VertexIterator & operator++()
pre-increment iterator
Definition: surface_mesh.h:334
Definition: surface_mesh.h:185
Property< T >::const_reference operator[](Vertex v) const
access the data stored for vertex v
Definition: surface_mesh.h:199
Property< T >::reference operator[](Vertex v)
access the data stored for vertex v
Definition: surface_mesh.h:193
VertexProperty()=default
default constructor
A halfedge data structure for polygonal meshes of 2-manifold.
Definition: surface_mesh.h:52
const vec3 & position(Vertex v) const
position of a vertex (read only)
Definition: surface_mesh.h:1928
bool is_border(Vertex v) const
returns whether v is a boundary vertex
Definition: surface_mesh.h:1176
bool is_quad_mesh() const
Definition: surface_mesh.cpp:896
EdgeContainer edges() const
returns edge container for C++11 range-based for-loops
Definition: surface_mesh.h:1667
const std::type_info & get_vertex_property_type(const std::string &name) const
Definition: surface_mesh.h:1551
Vertex source(Halfedge h) const
returns the vertex the halfedge h emanates from
Definition: surface_mesh.h:1217
unsigned int n_faces() const
returns number of faces in the mesh
Definition: surface_mesh.h:1076
bool remove_vertex_property(const std::string &n)
remove the vertex property named n
Definition: surface_mesh.h:1493
EdgeIterator edges_end() const
returns end iterator for edges
Definition: surface_mesh.h:1661
unsigned int n_halfedges() const
returns number of halfedge in the mesh
Definition: surface_mesh.h:1072
unsigned int halfedges_size() const
returns number of (deleted and valid)halfedge in the mesh
Definition: surface_mesh.h:1062
void set_next(Halfedge h, Halfedge nh)
sets the next halfedge of h within the face to nh
Definition: surface_mesh.h:1247
VertexAroundVertexCirculator vertices(Vertex v) const
returns circulator for vertices around vertex v
Definition: surface_mesh.h:1691
bool is_valid(Halfedge h) const
return whether halfedge h is valid, i.e. the index is stores it within the array bounds.
Definition: surface_mesh.h:1137
HalfedgeAroundFaceCirculator halfedges(Face f) const
returns circulator for halfedges of face f
Definition: surface_mesh.h:1715
unsigned int n_edges() const
returns number of edges in the mesh
Definition: surface_mesh.h:1074
bool is_valid(Edge e) const
return whether edge e is valid, i.e. the index is stores it within the array bounds.
Definition: surface_mesh.h:1142
void triangulate()
Definition: surface_mesh.cpp:908
bool rename_vertex_property(const std::string &old_name, const std::string &new_name)
rename a vertex property given its name
Definition: surface_mesh.h:1524
unsigned int valence(Vertex v) const
Definition: surface_mesh.cpp:834
HalfedgeProperty< T > add_halfedge_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1381
Face add_face(const std::vector< Vertex > &vertices)
Definition: surface_mesh.cpp:518
bool remove_halfedge_property(HalfedgeProperty< T > &p)
remove the halfedge property p
Definition: surface_mesh.h:1497
VertexContainer vertices() const
returns vertex container for C++11 range-based for-loops
Definition: surface_mesh.h:1631
void stitch(Halfedge h0, Halfedge h1)
Stitch two halfedges h0 and h1. Precondition: h0 and h1 are both on the border and point in reversed ...
Definition: surface_mesh.cpp:1651
Halfedge opposite(Halfedge h) const
returns the opposite halfedge of h
Definition: surface_mesh.h:1260
FaceProperty< T > get_face_property(const std::string &name) const
Definition: surface_mesh.h:1435
const std::type_info & get_edge_property_type(const std::string &name) const
Definition: surface_mesh.h:1563
bool is_collapse_ok(Halfedge h) const
Definition: surface_mesh.cpp:1759
const std::type_info & get_halfedge_property_type(const std::string &name) const
Definition: surface_mesh.h:1557
void delete_face(Face f)
Definition: surface_mesh.cpp:1999
bool has_garbage() const
are there deleted vertices, edges or faces?
Definition: surface_mesh.h:1099
Halfedge halfedge(Edge e, unsigned int i) const
returns the i'th halfedge of edge e. i has to be 0 or 1.
Definition: surface_mesh.h:1307
Halfedge insert_vertex(Edge e, Vertex v)
Definition: surface_mesh.h:1826
bool rename_face_property(const std::string &old_name, const std::string &new_name)
rename a face property given its name
Definition: surface_mesh.h:1529
Edge find_edge(Vertex a, Vertex b) const
find the edge (a, b)
Definition: surface_mesh.cpp:436
VertexProperty< T > vertex_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1457
unsigned int edges_size() const
returns number of (deleted and valid)edges in the mesh
Definition: surface_mesh.h:1064
std::vector< std::string > face_properties() const
returns the names of all face properties
Definition: surface_mesh.h:1597
bool is_flip_ok(Edge e) const
Definition: surface_mesh.cpp:1488
FaceContainer faces() const
returns face container for C++11 range-based for-loops
Definition: surface_mesh.h:1685
ModelProperty< T > get_model_property(const std::string &name) const
Gets the model property named name of type T.
Definition: surface_mesh.h:1449
~SurfaceMesh() override=default
destructor (is virtual, since we inherit from Geometry_representation)
std::vector< std::string > vertex_properties() const
returns the names of all vertex properties
Definition: surface_mesh.h:1582
void update_face_normals()
compute face normals by calling compute_face_normal(Face) for each face.
Definition: surface_mesh.cpp:1011
vec3 compute_face_normal(Face f) const
compute normal vector of face f.
Definition: surface_mesh.cpp:1035
SurfaceMesh(const SurfaceMesh &rhs)
copy constructor: copies rhs to *this. performs a deep copy of all properties.
Definition: surface_mesh.h:989
Halfedge insert_vertex(Edge e, const vec3 &p)
Definition: surface_mesh.h:1814
EdgeProperty< T > get_edge_property(const std::string &name) const
Definition: surface_mesh.h:1429
void set_halfedge(Face f, Halfedge h)
sets the halfedge of face f to h
Definition: surface_mesh.h:1341
const std::type_info & get_face_property_type(const std::string &name) const
Definition: surface_mesh.h:1569
EdgeIterator edges_begin() const
returns start iterator for edges
Definition: surface_mesh.h:1655
VertexAroundFaceCirculator vertices(Face f) const
returns circulator for vertices of face f
Definition: surface_mesh.h:1709
FaceIterator faces_begin() const
returns start iterator for faces
Definition: surface_mesh.h:1673
Halfedge find_halfedge(Vertex start, Vertex end) const
find the halfedge from start to end
Definition: surface_mesh.cpp:411
VertexProperty< T > get_vertex_property(const std::string &name) const
Definition: surface_mesh.h:1417
bool remove_face_property(const std::string &n)
remove the face property named n
Definition: surface_mesh.h:1514
bool is_stitch_ok(Halfedge h0, Halfedge h1)
Definition: surface_mesh.cpp:1609
Vertex split(Face f, const vec3 &p)
Definition: surface_mesh.h:1775
void reverse_orientation()
Reverses the orientation of the entire mesh.
Definition: surface_mesh.cpp:923
std::vector< std::string > edge_properties() const
returns the names of all edge properties
Definition: surface_mesh.h:1592
bool read(const std::string &filename)
Read mesh from a SM file filename. Mainly for quick debug purposes. Client code should use SurfaceMes...
Definition: surface_mesh.cpp:203
bool is_deleted(Vertex v) const
Definition: surface_mesh.h:1107
void set_face(Halfedge h, Face f)
sets the incident face to halfedge h to f
Definition: surface_mesh.h:1235
SurfaceMesh()
default constructor
Definition: surface_mesh.cpp:33
std::vector< std::string > model_properties() const
returns the names of all model properties
Definition: surface_mesh.h:1602
Vertex target(Halfedge h) const
returns the vertex the halfedge h points to
Definition: surface_mesh.h:1211
Halfedge halfedge(Face f) const
returns a halfedge of face f
Definition: surface_mesh.h:1335
bool is_deleted(Face f) const
Definition: surface_mesh.h:1125
HalfedgeContainer halfedges() const
returns halfedge container for C++11 range-based for-loops
Definition: surface_mesh.h:1649
void collect_garbage()
remove deleted vertices/edges/faces
Definition: surface_mesh.cpp:2113
SurfaceMesh & operator=(const SurfaceMesh &rhs)
assign rhs to *this. performs a deep copy of all properties.
Definition: surface_mesh.cpp:55
bool rename_edge_property(const std::string &old_name, const std::string &new_name)
rename an edge property given its name
Definition: surface_mesh.h:1534
void resize(unsigned int nv, unsigned int ne, unsigned int nf)
Definition: surface_mesh.h:1091
bool is_deleted(Edge e) const
Definition: surface_mesh.h:1119
Halfedge split(Edge e, const vec3 &p)
Definition: surface_mesh.h:1792
Halfedge prev_around_source(Halfedge h) const
Definition: surface_mesh.h:1267
Halfedge insert_edge(Halfedge h0, Halfedge h1)
Definition: surface_mesh.cpp:1447
const std::type_info & get_model_property_type(const std::string &name) const
Definition: surface_mesh.h:1575
Halfedge prev(Halfedge h) const
returns the previous halfedge within the incident face
Definition: surface_mesh.h:1254
void set_target(Halfedge h, Vertex v)
sets the vertex the halfedge h points to to v
Definition: surface_mesh.h:1223
Halfedge next_around_target(Halfedge h) const
Definition: surface_mesh.h:1288
std::vector< vec3 > & points() override
vector of vertex positions
Definition: surface_mesh.h:1937
SurfaceMesh & join(const SurfaceMesh &other)
Merges another surface mesh into the current one. Shifts the indices of vertices of the other mesh by...
Definition: surface_mesh.cpp:93
bool is_closed() const
returns whether the mesh closed (i.e., no boundary edges)
Definition: surface_mesh.cpp:869
bool remove_face_property(FaceProperty< T > &p)
remove the face property p
Definition: surface_mesh.h:1511
bool remove_edge_property(const std::string &n)
remove the edge property named n
Definition: surface_mesh.h:1507
ModelProperty< T > model_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1482
Face add_quad(Vertex v1, Vertex v2, Vertex v3, Vertex v4)
Definition: surface_mesh.cpp:504
VertexProperty< T > add_vertex_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1374
bool remove_model_property(ModelProperty< T > &p)
remove the model property p
Definition: surface_mesh.h:1518
FaceProperty< T > face_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1475
FaceProperty< T > add_face_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1395
FaceAroundVertexCirculator faces(Vertex v) const
returns circulator for faces around vertex v
Definition: surface_mesh.h:1703
std::vector< std::string > halfedge_properties() const
returns the names of all halfedge properties
Definition: surface_mesh.h:1587
Face add_triangle(Vertex v1, Vertex v2, Vertex v3)
Definition: surface_mesh.cpp:491
bool rename_model_property(const std::string &old_name, const std::string &new_name)
rename a model property given its name
Definition: surface_mesh.h:1544
bool is_triangle_mesh() const
Definition: surface_mesh.cpp:882
ModelProperty< T > add_model_property(const std::string &name, const T t=T())
Adds a model property of type T with name name and default value t.
Definition: surface_mesh.h:1409
bool can_join_edges(Vertex v) const
Definition: surface_mesh.cpp:2324
HalfedgeIterator halfedges_begin() const
returns start iterator for halfedges
Definition: surface_mesh.h:1637
vec3 compute_vertex_normal(Vertex v) const
Definition: surface_mesh.cpp:1170
HalfedgeProperty< T > get_halfedge_property(const std::string &name) const
Definition: surface_mesh.h:1423
bool write(const std::string &filename) const
Write mesh to a SM file filename. Mainly for quick debug purposes. Client code should use SurfaceMesh...
Definition: surface_mesh.cpp:250
SurfaceMesh & operator+=(const SurfaceMesh &other)
Merges another surface mesh into the current one. Shifts the indices of vertices of the other mesh by...
Definition: surface_mesh.h:1000
Vertex add_vertex(const vec3 &p)
add a new vertex with position p
Definition: surface_mesh.h:1034
bool is_valid(Face f) const
return whether face f is valid, i.e. the index is stores it within the array bounds.
Definition: surface_mesh.h:1147
bool is_border(Face f) const
returns whether f is a boundary face, i.e., it one of its edges is a boundary edge.
Definition: surface_mesh.h:1347
EdgeProperty< T > edge_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1469
Halfedge prev_around_target(Halfedge h) const
Definition: surface_mesh.h:1281
Face face(Halfedge h) const
returns the face incident to halfedge h
Definition: surface_mesh.h:1229
bool remove_edge_property(EdgeProperty< T > &p)
remove the edge property p
Definition: surface_mesh.h:1504
void property_stats(std::ostream &output) const override
prints the names of all properties to an output stream (e.g., std::cout).
Definition: surface_mesh.cpp:354
void delete_edge(Edge e)
Definition: surface_mesh.cpp:1985
void update_vertex_normals()
compute vertex normals by calling compute_vertex_normal(Vertex) for each vertex.
Definition: surface_mesh.cpp:1093
FaceIterator faces_end() const
returns end iterator for faces
Definition: surface_mesh.h:1679
SurfaceMesh & assign(const SurfaceMesh &rhs)
assign rhs to *this. does not copy custom properties.
Definition: surface_mesh.cpp:149
void collapse(Halfedge h)
Definition: surface_mesh.cpp:1821
void flip(Edge e)
Definition: surface_mesh.cpp:1514
HalfedgeProperty< T > halfedge_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1463
bool is_manifold(Vertex v) const
returns whether v is a manifold vertex (not incident to several patches)
Definition: surface_mesh.h:1189
void clear()
Removes all vertices, edges, faces, and properties (and resets garbage state).
Definition: surface_mesh.cpp:302
Halfedge next_around_source(Halfedge h) const
Definition: surface_mesh.h:1274
bool rename_halfedge_property(const std::string &old_name, const std::string &new_name)
rename a halfedge property given its name
Definition: surface_mesh.h:1539
bool remove_halfedge_property(const std::string &n)
remove the halfedge property named n
Definition: surface_mesh.h:1500
bool is_isolated(Vertex v) const
returns whether v is isolated, i.e., not incident to any face
Definition: surface_mesh.h:1183
vec3 & position(Vertex v)
position of a vertex
Definition: surface_mesh.h:1931
bool is_deleted(Halfedge h) const
Definition: surface_mesh.h:1113
HalfedgeAroundVertexCirculator halfedges(Vertex v) const
returns circulator for outgoing halfedges around vertex v
Definition: surface_mesh.h:1697
unsigned int vertices_size() const
returns number of (deleted and valid) vertices in the mesh
Definition: surface_mesh.h:1060
Edge edge(Halfedge h) const
return the edge that contains halfedge h as one of its two halfedges.
Definition: surface_mesh.h:1294
bool remove_model_property(const std::string &n)
remove the model property named n
Definition: surface_mesh.h:1521
float edge_length(Edge e) const
compute the length of edge e.
Definition: surface_mesh.cpp:1228
EdgeProperty< T > add_edge_property(const std::string &name, const T t=T())
Definition: surface_mesh.h:1388
unsigned int faces_size() const
returns number of (deleted and valid)faces in the mesh
Definition: surface_mesh.h:1066
Halfedge next(Halfedge h) const
returns the next halfedge within the incident face
Definition: surface_mesh.h:1241
Face face(Edge e, unsigned int i) const
returns the face incident to the i'th halfedge of edge e. i has to be 0 or 1.
Definition: surface_mesh.h:1321
Halfedge out_halfedge(Vertex v) const
Definition: surface_mesh.h:1164
void delete_vertex(Vertex v)
Definition: surface_mesh.cpp:1951
bool is_border(Edge e) const
Definition: surface_mesh.h:1329
VertexIterator vertices_begin() const
returns start iterator for vertices
Definition: surface_mesh.h:1619
HalfedgeIterator halfedges_end() const
returns end iterator for halfedges
Definition: surface_mesh.h:1643
bool remove_vertex_property(VertexProperty< T > &p)
remove the vertex property p
Definition: surface_mesh.h:1490
bool is_degenerate(Face f) const
returns whether f is degenerate
Definition: surface_mesh.cpp:2260
VertexIterator vertices_end() const
returns end iterator for vertices
Definition: surface_mesh.h:1625
bool is_valid(Vertex v) const
return whether vertex v is valid, i.e. the index is stores it within the array bounds.
Definition: surface_mesh.h:1132
Vertex vertex(Edge e, unsigned int i) const
returns the i'th vertex of edge e. i has to be 0 or 1.
Definition: surface_mesh.h:1314
bool is_border(Halfedge h) const
returns whether h is a boundary halfedge, i.e., if its face does not exist.
Definition: surface_mesh.h:1300
void reserve(unsigned int nvertices, unsigned int nedges, unsigned int nfaces)
reserves memory (mainly used in file readers)
Definition: surface_mesh.cpp:339
bool join_edges(Vertex v)
Definition: surface_mesh.cpp:2340
const std::vector< vec3 > & points() const override
vector of vertex positions (read only)
Definition: surface_mesh.h:1934
unsigned int n_vertices() const
returns number of vertices in the mesh
Definition: surface_mesh.h:1070
void set_out_halfedge(Vertex v, Halfedge h)
set the outgoing halfedge of vertex v to h
Definition: surface_mesh.h:1170
Definition: collider.cpp:182
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Definition: graph.h:920
helper structure to be able to use std::unordered_map
Definition: surface_mesh.h:91
Definition: surface_mesh.h:124
Edge(int _idx=-1)
default constructor (with invalid index)
Definition: surface_mesh.h:126
Definition: surface_mesh.h:172
Halfedge halfedge_
a halfedge that is part of the face
Definition: surface_mesh.h:174
Definition: surface_mesh.h:134
Face(int _idx=-1)
default constructor (with invalid index)
Definition: surface_mesh.h:136
Definition: surface_mesh.h:157
Vertex vertex_
vertex the halfedge points to
Definition: surface_mesh.h:161
Halfedge next_
next halfedge within a face (or along a boundary)
Definition: surface_mesh.h:163
Face face_
face incident to halfedge
Definition: surface_mesh.h:159
Halfedge prev_
previous halfedge within a face (or along a boundary)
Definition: surface_mesh.h:165
Definition: surface_mesh.h:114
Halfedge(int _idx=-1)
default constructor (with invalid index)
Definition: surface_mesh.h:116
Definition: surface_mesh.h:148
Halfedge halfedge_
an outgoing halfedge per vertex (it will be a boundary halfedge for boundary vertices)
Definition: surface_mesh.h:150
Definition: surface_mesh.h:104
Vertex(int _idx=-1)
default constructor (with invalid index)
Definition: surface_mesh.h:106