Graphite Version 3
An experimental 3D geometry processing program
Loading...
Searching...
No Matches
mesh.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef GEOGRAM_MESH_MESH
41#define GEOGRAM_MESH_MESH
42
44#include <geogram/basic/range.h>
46#include <geogram/basic/vector_attribute.h>
48#include <tuple>
49
50// GOMGEN (Graphite's pre-processor) does not understand
51// modern C++ (but it is not a big drama since it is just
52// used to generate the GUI).
53#ifdef GOMGEN
54#define MESH_NO_SYNTAXIC_SUGAR
55#endif
56
62namespace GEO {
63
64 class Mesh;
65
66 static constexpr index_t NO_VERTEX = NO_INDEX;
67 static constexpr index_t NO_EDGE = NO_INDEX;
68 static constexpr index_t NO_FACET = NO_INDEX;
69 static constexpr index_t NO_CELL = NO_INDEX;
70 static constexpr index_t NO_CORNER = NO_INDEX;
71
79 class GEOGRAM_API MeshSubElementsStore {
80 public:
81
88
93
98 index_t nb() const {
99 return nb_;
100 }
101
110 return attributes_;
111 }
112
118 return index_as_iterator(0);
119 }
120
126 return index_as_iterator(nb());
127 }
128
129 protected:
130
140 virtual void clear_store(
141 bool keep_attributes, bool keep_memory = false
142 );
143
150 virtual void resize_store(index_t new_size);
151
152
157 void reserve_store(index_t nb_to_reserve) {
158 index_t nb = this->nb();
159 resize_store(nb + nb_to_reserve);
160 resize_store(nb);
161 }
162
169 index_t result = nb_;
170 if(nb_ + nb > attributes_.size()) {
171 index_t new_capacity=nb_ + nb;
172 if(nb < 128) {
173 new_capacity = std::max(index_t(16),attributes_.capacity());
174 while(new_capacity < nb_ + nb) {
175 new_capacity *= 2;
176 }
177 }
178 attributes_.reserve(new_capacity);
179 }
180 nb_ += nb;
181 attributes_.resize(nb_);
182 return result;
183 }
184
190 index_t result = nb_;
191 ++nb_;
192 if(attributes_.capacity() < nb_) {
193 index_t new_capacity =
194 std::max(index_t(16),attributes_.capacity()*2);
195 attributes_.reserve(new_capacity);
196 }
197 attributes_.resize(nb_);
198 return result;
199 }
200
211 attributes_.resize(nb_);
212 }
213
223 void copy(
224 const MeshSubElementsStore& rhs,
225 bool copy_attributes = true
226 ) {
227 nb_ = rhs.nb();
228 if(copy_attributes) {
229 attributes_.copy(rhs.attributes_);
230 } else {
231 attributes_.clear(false,false);
232 attributes_.resize(rhs.attributes_.size());
233 }
234 }
235
236 protected:
237 Mesh& mesh_;
238 mutable AttributesManager attributes_;
239 index_t nb_;
240 };
241
242
243 /**************************************************************************/
244
252 class GEOGRAM_API MeshElements {
253 public:
254 MeshElements();
255 virtual ~MeshElements();
256
266 virtual void delete_elements(
267 vector<index_t>& to_delete,
268 bool remove_isolated_vertices=true
269 ) = 0;
270
283 virtual void permute_elements(vector<index_t>& permutation) = 0;
284
294 virtual void clear(
295 bool keep_attributes=true, bool keep_memory=false
296 ) = 0;
297
301 virtual void pop() = 0;
302
303 protected:
311 static bool has_non_zero(const GEO::vector<index_t>& I) {
312 for(index_t i = 0; i < I.size(); i++) {
313 if(I[i] != 0) {
314 return true;
315 }
316 }
317 return false;
318 }
319 };
320
321 /**************************************************************************/
322
323 class MeshEdges;
324 class MeshFacetCornersStore;
325 class MeshCellCornersStore;
326
331 class GEOGRAM_API MeshVertices :
332 public MeshSubElementsStore, public MeshElements {
333 public:
334 MeshVertices(Mesh& mesh);
335 ~MeshVertices() override;
336
342
344 vector<index_t>& to_delete, bool remove_isolated_vertices=true
345 ) override;
346
347 void permute_elements(vector<index_t>& permutation) override;
348
354 return MeshSubElementsStore::create_sub_element();
355 }
356
362 index_t create_vertex(const double* coords) {
363 // Sanity check:
364 // It is not correct to call create_vertex(point_ptr(v)) since
365 // create_vertex may realloc the points coordinates vector, thus
366 // invalidate point_ptr(v).
368 nb() == 0 ||
369 coords < point_ptr(0) ||
370 coords >= point_ptr(0) + nb() * dimension()
371 );
372 index_t result = create_vertex();
373 for(index_t c=0; c<dimension(); ++c) {
374 point_ptr(result)[c] = coords[c];
375 }
376 return result;
377 }
378
385 template <index_t DIM> index_t create_vertex(
386 const vecng<DIM,double>& p
387 ) {
388 geo_debug_assert(dimension() == DIM);
389 return create_vertex(p.data());
390 }
391
398 return MeshSubElementsStore::create_sub_elements(nb);
399 }
400
401 void clear(
402 bool keep_attributes=true, bool keep_memory=false
403 ) override;
404
413
423
430 bool single_precision() const {
431 return point_fp32_.is_bound();
432 }
433
441 bool double_precision() const {
442 return point_.is_bound();
443 }
444
450 return
451 single_precision() ?
452 point_fp32_.dimension() :
453 point_.dimension() ;
454 }
455
463 if(single_precision()) {
464 point_fp32_.redim(dim);
465 } else {
466 point_.redim(dim);
467 }
468 }
469
477 const double* point_ptr(index_t v) const {
478 geo_debug_assert(v < nb());
479 geo_debug_assert(!single_precision());
480 return &point_[v*point_.dimension()];
481 }
482
490 double* point_ptr(index_t v) {
491 geo_debug_assert(v < nb());
492 geo_debug_assert(!single_precision());
493 return &point_[v*point_.dimension()];
494 }
495
496
504 template<index_t DIM=3> vecng<DIM,double>& point(index_t v) {
505 geo_debug_assert(v < nb());
506 geo_debug_assert(!single_precision());
507 geo_debug_assert(dimension() >= DIM);
508 return Memory::pointer_as_reference<vecng<DIM,double>>(
509 &point_[v*point_.dimension()]
510 );
511 }
512
520 template <index_t DIM=3> const vecng<DIM,double>& point(
521 index_t v
522 ) const {
523 geo_debug_assert(v < nb());
524 geo_debug_assert(!single_precision());
525 geo_debug_assert(dimension() >= DIM);
526 return Memory::pointer_as_reference<vecng<DIM,double>>(
527 &point_[v*point_.dimension()]
528 );
529 }
530
538 const float* single_precision_point_ptr(index_t v) const {
539 geo_debug_assert(v < nb());
540 geo_debug_assert(single_precision());
541 return &point_fp32_[v*point_fp32_.dimension()];
542 }
543
552 geo_debug_assert(v < nb());
553 geo_debug_assert(single_precision());
554 return &point_fp32_[v*point_fp32_.dimension()];
555 }
556
567 geo_debug_assert(!single_precision());
568 return point_.get_vector();
569 }
570
578 geo_debug_assert(!single_precision());
579 return point_.get_vector();
580 }
581
582
593 vector<double>& points, index_t dim, bool steal_arg
594 );
595
605 const double* points, index_t dim, index_t nb_pts
606 );
607
608 void pop() override;
609
610#ifndef MESH_NO_SYNTAXIC_SUGAR
611
616 template <index_t DIM = 3> auto points() const {
617 typedef vecng<DIM,double> vecn;
618 return transform_range_ref(
619 index_range(0, nb()),
620 [this](index_t v)->const vecn& {
621 // for MSVC that cannot chose among const/non-const versions
622 return Memory::pointer_as_reference<vecn>(point_ptr(v));
623 // return point<DIM>(v); // MSVC does not understand this one
624 }
625 );
626 }
627
632 template <index_t DIM = 3> auto points() {
633 typedef vecng<DIM,double> vecn;
634 return transform_range_ref(
635 index_range(0, nb()),
636 [this](index_t v)->vecn& {
637 // for MSVC that cannot chose among const/non-const versions
638 return Memory::pointer_as_reference<vecn>(point_ptr(v));
639 // return point<DIM>(v); //MSVC does not understand this one
640 }
641 );
642 }
643
644#endif
645
646 protected:
647
649 bool keep_attributes, bool keep_memory = false
650 ) override;
651
652 void resize_store(index_t new_size) override;
653
654 void bind_point_attribute(index_t dim, bool single_precision=false);
655
656 void copy(const MeshVertices& rhs, bool copy_attributes=true) {
657 index_t dim = rhs.dimension();
658 if(point_fp32_.is_bound()) {
659 point_fp32_.destroy();
660 }
661 if(point_.is_bound()) {
662 point_.destroy();
663 }
664 MeshSubElementsStore::copy(rhs, copy_attributes);
665 if(rhs.single_precision()) {
666 point_fp32_.bind_if_is_defined(attributes(),"point_fp32");
667 if(!point_fp32_.is_bound()) {
668 point_fp32_.create_vector_attribute(
669 attributes(), "point_fp32", dim
670 );
671 }
672 } else {
673 point_.bind_if_is_defined(attributes(),"point");
674 if(!point_.is_bound()) {
675 point_.create_vector_attribute(
676 attributes(), "point", dim
677 );
678 }
679 }
680 // Even if we do not copy the attributes, we need at least
681 // to copy the coordinates of the points !!
682 if(!copy_attributes) {
683 if(rhs.single_precision()) {
684 Memory::copy(
685 single_precision_point_ptr(0),
687 rhs.dimension()*rhs.nb()*sizeof(float)
688 );
689 } else {
690 Memory::copy(
691 point_ptr(0),
692 rhs.point_ptr(0),
693 rhs.dimension()*rhs.nb()*sizeof(double)
694 );
695 }
696 }
697 }
698
699 MeshEdges& edges_;
700 MeshFacetCornersStore& facet_corners_;
701 MeshCellCornersStore& cell_corners_;
702 Attribute<double> point_;
703 Attribute<float> point_fp32_;
704
705 friend class Mesh;
706 friend class GeogramIOHandler;
707 };
708
709 /*************************************************************************/
710
715 class GEOGRAM_API MeshEdges :
716 public MeshSubElementsStore, public MeshElements {
717 public:
718 MeshEdges(Mesh& mesh);
719 ~MeshEdges() override;
720
728 geo_debug_assert(e < nb());
729 geo_debug_assert(lv < 2);
730 return edge_vertex_[2*e+lv];
731 }
732
740 geo_debug_assert(e < nb());
741 geo_debug_assert(lv < 2);
742 edge_vertex_[2*e+lv] = v;
743 }
744
745
753 geo_debug_assert(c < 2*nb());
754 return &(edge_vertex_[c]);
755 }
756
764 geo_debug_assert(c < 2*nb());
765 return &(edge_vertex_[c]);
766 }
767
773 return create_sub_element();
774 }
775
782 return create_sub_elements(nb);
783 }
784
791 index_t result = create_edge();
792 set_vertex(result,0,v1);
793 set_vertex(result,1,v2);
794 return result;
795 }
796
798 vector<index_t>& to_delete, bool remove_isolated_vertices=true
799 ) override;
800
801 void permute_elements(vector<index_t>& permutation) override;
802
803 void clear(
804 bool keep_attributes=true, bool keep_memory=false
805 ) override;
806
807 void pop() override;
808
813 void flip(index_t e);
814
815 protected:
817 bool keep_attributes, bool keep_memory = false
818 ) override;
819
820 void resize_store(index_t new_size) override;
821
822 index_t create_sub_element() {
823 edge_vertex_.push_back(NO_VERTEX);
824 edge_vertex_.push_back(NO_VERTEX);
825 return MeshSubElementsStore::create_sub_element();
826 }
827
828 index_t create_sub_elements(index_t nb_in) {
829 edge_vertex_.resize(2*(nb()+nb_in),NO_VERTEX);
830 return MeshSubElementsStore::create_sub_elements(nb_in);
831 }
832
833 void copy(const MeshEdges& rhs, bool copy_attributes=true) {
834 MeshSubElementsStore::copy(rhs, copy_attributes);
835 edge_vertex_ = rhs.edge_vertex_;
836 }
837
838 vector<index_t> edge_vertex_;
839 friend class Mesh;
840 friend class GeogramIOHandler;
841 };
842
843 /**************************************************************************/
844
849 class GEOGRAM_API MeshFacetsStore : public MeshSubElementsStore {
850 public:
851 MeshFacetsStore(Mesh& mesh);
852
860 geo_debug_assert(f < nb());
861 return (is_simplicial_ ? 3*f : facet_ptr_[f]);
862 }
863
871 geo_debug_assert(f < nb());
872 return (is_simplicial_ ? 3*(f+1): facet_ptr_[f+1]);
873 }
874
881 geo_debug_assert(f < nb());
882 return (is_simplicial_ ? 3 : facet_ptr_[f+1] - facet_ptr_[f]);
883 }
884
893 geo_debug_assert(f < nb());
894 geo_debug_assert(lv < nb_corners(f));
895 return corners_begin(f)+lv;
896 }
897
905 bool are_simplices() const {
906 return is_simplicial_;
907 }
908
916 geo_debug_assert(!is_simplicial_);
917 geo_debug_assert(f < nb());
918 return &facet_ptr_[f];
919 }
920
928 geo_debug_assert(!is_simplicial_);
929 geo_debug_assert(f < nb());
930 return &facet_ptr_[f];
931 }
932
933
934 protected:
936 bool keep_attributes, bool keep_memory = false
937 ) override;
938
939 void resize_store(index_t new_size) override;
940
941 index_t create_sub_element() {
942 if(!is_simplicial_) {
943 facet_ptr_.push_back(NO_CORNER);
944 }
945 return MeshSubElementsStore::create_sub_element();
946 }
947
948 index_t create_sub_elements(index_t nb) {
949 if(!is_simplicial_) {
950 for(index_t i=0; i<nb; ++i) {
951 facet_ptr_.push_back(NO_CORNER);
952 }
953 }
954 return MeshSubElementsStore::create_sub_elements(nb);
955 }
956
957 void copy(const MeshFacetsStore& rhs, bool copy_attributes=true) {
958 MeshSubElementsStore::copy(rhs,copy_attributes);
959 is_simplicial_ = rhs.is_simplicial_;
960 facet_ptr_ = rhs.facet_ptr_;
961 }
962
963 protected:
964 bool is_simplicial_;
965 vector<index_t> facet_ptr_;
966 friend class Mesh;
967 friend class GeogramIOHandler;
968 };
969
970 /*************************************************************************/
971
976 class GEOGRAM_API MeshFacetCornersStore : public MeshSubElementsStore {
977 public:
979
986 geo_debug_assert(c < nb());
987 return corner_vertex_[c];
988 }
989
997 geo_debug_assert(c < nb());
998 return corner_adjacent_facet_[c];
999 }
1000
1009 geo_debug_assert(c < nb());
1010 return &corner_adjacent_facet_[c];
1011 }
1012
1013
1022 geo_debug_assert(c < nb());
1023 return &corner_adjacent_facet_[c];
1024 }
1025
1033 geo_debug_assert(c < nb());
1034 geo_debug_assert(v < vertices_.nb());
1035 corner_vertex_[c] = v;
1036 }
1037
1049 geo_debug_assert(c < nb());
1050 corner_vertex_[c] = v;
1051 }
1052
1060 geo_debug_assert(c < nb());
1061 geo_debug_assert(f == NO_FACET || f < facets_.nb());
1062 corner_adjacent_facet_[c] = f;
1063 }
1064
1073 geo_debug_assert(c < nb());
1074 return &(corner_vertex_[c]);
1075 }
1076
1085 geo_debug_assert(c < nb());
1086 return &(corner_vertex_[c]);
1087 }
1088
1097 return corner_vertex_;
1098 }
1099
1106 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
1107 geo_debug_assert(c < nb());
1108 return vertices_.point<DIM>(vertex(c));
1109 }
1110
1118 template <index_t DIM=3> const vecng<DIM,double>& point(
1119 index_t c
1120 ) const {
1121 geo_debug_assert(c < nb());
1122 return vertices_.point(vertex(c));
1123 }
1124
1125 protected:
1127 bool keep_attributes, bool keep_memory = false
1128 ) override;
1129
1130 void resize_store(index_t new_size) override;
1131
1132 index_t create_sub_element(index_t v, index_t f = NO_FACET) {
1133 corner_vertex_.push_back(v);
1134 corner_adjacent_facet_.push_back(f);
1135 return MeshSubElementsStore::create_sub_element();
1136 }
1137
1138 index_t create_sub_elements(index_t nb) {
1139 for(index_t i=0; i<nb; ++i) {
1140 corner_vertex_.push_back(NO_VERTEX);
1141 }
1142 for(index_t i=0; i<nb; ++i) {
1143 corner_adjacent_facet_.push_back(NO_FACET);
1144 }
1145 return MeshSubElementsStore::create_sub_elements(nb);
1146 }
1147
1148 void copy(
1149 const MeshFacetCornersStore& rhs, bool copy_attributes=true
1150 ) {
1151 MeshSubElementsStore::copy(rhs, copy_attributes);
1152 corner_vertex_ = rhs.corner_vertex_;
1153 corner_adjacent_facet_ = rhs.corner_adjacent_facet_;
1154 }
1155
1156 protected:
1157 MeshVertices& vertices_;
1158 MeshFacetsStore& facets_;
1159 vector<index_t> corner_vertex_;
1160 vector<index_t> corner_adjacent_facet_;
1161
1162 friend class MeshFacets;
1163 friend class Mesh;
1164 friend class GeogramIOHandler;
1165 };
1166
1167 /*************************************************************************/
1168
1173 class GEOGRAM_API MeshFacets : public MeshFacetsStore, public MeshElements {
1174 public:
1175
1182
1189 return nb_corners(f);
1190 }
1191
1200 return facet_corners_.vertex(corner(f,lv));
1201 }
1202
1203
1212 template <index_t DIM=3> const vecng<DIM,double>& point(
1213 index_t f, index_t lv
1214 ) const {
1215 return vertices_.point<DIM>(vertex(f,lv));
1216 }
1217
1226 template <index_t DIM=3> vecng<DIM,double>& point(
1227 index_t f, index_t lv
1228 ) {
1229 return vertices_.point<DIM>(vertex(f,lv));
1230 }
1231
1240 facet_corners_.set_vertex(corner(f,lv),v);
1241 }
1242
1251 for(index_t lv=0; lv<nb_vertices(f); ++lv) {
1252 if(vertex(f,lv) == v) {
1253 return lv;
1254 }
1255 }
1256 return NO_VERTEX;
1257 }
1258
1266 for(index_t lv=0; lv<nb_vertices(f1); ++lv) {
1267 index_t v = vertex(f1,lv);
1268 if(find_vertex(f2,v) != NO_VERTEX) {
1269 return lv;
1270 }
1271 }
1272 return NO_VERTEX;
1273 }
1274
1283 return facet_corners_.adjacent_facet(corner(f,le));
1284 }
1285
1294 for(index_t le=0; le<nb_vertices(f); ++le) {
1295 if(adjacent(f,le) == f2) {
1296 return le;
1297 }
1298 }
1299 return NO_INDEX;
1300 }
1301
1310 facet_corners_.set_adjacent_facet(corner(f,le),f2);
1311 }
1312
1321 geo_debug_assert(f < nb());
1322 geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1323 return c + 1 == corners_end(f) ? corners_begin(f) : c + 1;
1324 }
1325
1334 geo_debug_assert(f < nb());
1335 geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1336 return c == corners_begin(f) ? corners_end(f) - 1 : c - 1;
1337 }
1338
1347 for(index_t c1 = corners_begin(f); c1 != corners_end(f); ++c1) {
1348 index_t c2 = next_corner_around_facet(f,c1);
1349 if(
1350 facet_corners_.vertex(c1) == v1 &&
1351 facet_corners_.vertex(c2) == v2
1352 ) {
1353 return c1 - corners_begin(f);
1354 }
1355 }
1356 return NO_INDEX;
1357 }
1358
1360 vector<index_t>& to_delete,
1361 bool remove_isolated_vertices=true
1362 ) override;
1363
1364 void permute_elements(vector<index_t>& permutation) override;
1365
1366 void clear(
1367 bool keep_attributes=true, bool keep_memory=false
1368 ) override;
1369
1378 index_t nb_facets, index_t nb_vertices_per_polygon
1379 ) {
1380 if(nb_vertices_per_polygon != 3) {
1381 is_not_simplicial();
1382 }
1383
1384 index_t first_facet = nb();
1385 index_t co = facet_corners_.nb();
1386 facet_corners_.create_sub_elements(
1387 nb_facets*nb_vertices_per_polygon
1388 );
1389 index_t result = create_sub_elements(nb_facets);
1390
1391 if(!is_simplicial_) {
1392 for(index_t f=first_facet; f<=first_facet+nb_facets; ++f) {
1393 facet_ptr_[f] = co;
1394 co += nb_vertices_per_polygon;
1395 }
1396 geo_debug_assert(facet_ptr_.size() == nb()+1);
1397 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1398 }
1399 return result;
1400 }
1401
1407 void reserve(index_t nb_to_reserve) {
1408 facet_corners_.reserve_store(nb_to_reserve*3);
1409 this->reserve_store(nb_to_reserve);
1410 }
1411
1418 return create_facets(nb_triangles, 3);
1419 }
1420
1427 return create_facets(nb_quads, 4);
1428 }
1429
1436 geo_debug_assert(v1 != v2);
1437 geo_debug_assert(v2 != v3);
1438 geo_debug_assert(v3 != v1);
1439 facet_corners_.create_sub_element(v1);
1440 facet_corners_.create_sub_element(v2);
1441 facet_corners_.create_sub_element(v3);
1442 index_t result = create_sub_element();
1443 if(!is_simplicial_) {
1444 facet_ptr_[result+1] = facet_corners_.nb();
1445 geo_debug_assert(facet_ptr_.size() == nb()+1);
1446 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1447 }
1448 return result;
1449 }
1450
1457 is_not_simplicial();
1458 facet_corners_.create_sub_element(v1);
1459 facet_corners_.create_sub_element(v2);
1460 facet_corners_.create_sub_element(v3);
1461 facet_corners_.create_sub_element(v4);
1462 index_t result = create_sub_element();
1463 facet_ptr_[result+1] = facet_corners_.nb();
1464 geo_debug_assert(facet_ptr_.size() == nb()+1);
1465 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1466 return result;
1467 }
1468
1475 if(nb_vertices != 3) {
1476 is_not_simplicial();
1477 }
1478 for(index_t i=0; i<nb_vertices; ++i) {
1479 facet_corners_.create_sub_element(NO_VERTEX);
1480 }
1481 index_t result = create_sub_element();
1482 if(!is_simplicial_) {
1483 facet_ptr_[result+1] = facet_corners_.nb();
1484 geo_debug_assert(facet_ptr_.size() == nb()+1);
1485 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1486 }
1487 return result;
1488 }
1489
1496 index_t create_polygon(index_t nb_vertices, const index_t* vertices) {
1497 if(nb_vertices != 3) {
1498 is_not_simplicial();
1499 }
1500 for(index_t i=0; i<nb_vertices; ++i) {
1501 facet_corners_.create_sub_element(vertices[i]);
1502 }
1503 index_t result = create_sub_element();
1504 if(!is_simplicial_) {
1505 facet_ptr_[result+1] = facet_corners_.nb();
1506 geo_debug_assert(facet_ptr_.size() == nb()+1);
1507 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1508 }
1509 return result;
1510 }
1511
1519 return create_polygon(vertices.size(), vertices.data());
1520 }
1521
1526 void connect();
1527
1534 void connect(index_t facets_begin, index_t facets_end);
1535
1541
1547 void flip(index_t f);
1548
1554
1567 coord_index_t dim,
1568 vector<double>& vertices,
1569 vector<index_t>& triangles,
1570 bool steal_args
1571 );
1572
1573 /*
1574 * \brief Copies a triangle mesh into this Mesh.
1575 * \details Facet adjacence are not computed.
1576 * Facet and corner attributes are zeroed.
1577 * \param[in] triangles facet to vertex links
1578 * \param[in] steal_args if set, vertices and triangles
1579 * are 'stolen' from the arguments
1580 * (using vector::swap).
1581 */
1582 void assign_triangle_mesh(
1583 vector<index_t>& triangles,
1584 bool steal_args
1585 );
1586
1587 void pop() override;
1588
1595 geo_debug_assert(f < nb());
1596 return index_range(
1597 index_as_iterator(corners_begin(f)),
1598 index_as_iterator(corners_end(f))
1599 );
1600 }
1601
1602#ifndef MESH_NO_SYNTAXIC_SUGAR
1603
1609 auto vertices(index_t f) const {
1610 geo_debug_assert(f < nb());
1611 return transform_range(
1612 corners(f), [this](index_t c)->index_t {
1613 return facet_corners_.vertex(c);
1614 }
1615 );
1616 }
1617
1625 auto adjacent(index_t f) const {
1626 geo_debug_assert(f < nb());
1627 return transform_range(
1628 corners(f), [this](index_t c)->index_t {
1629 return facet_corners_.adjacent_facet(c);
1630 }
1631 );
1632 }
1633
1640 template <index_t DIM=3> auto points(index_t f) const {
1641 geo_debug_assert(f < nb());
1642 typedef vecng<DIM,double> vecn;
1643 return transform_range_ref(
1644 corners(f), [this](index_t c)->const vecn& {
1645 index_t v = facet_corners_.vertex(c);
1646 return vertices_.point<DIM>(v);
1647 }
1648 );
1649 }
1650
1657 template <index_t DIM=3> auto points(index_t f) {
1658 geo_debug_assert(f < nb());
1659 typedef vecng<DIM,double> vecn;
1660 return transform_range_ref(
1661 corners(f), [this](index_t c)->vecn& {
1662 index_t v = facet_corners_.vertex(c);
1663 return vertices_.point<DIM>(v);
1664 }
1665 );
1666 }
1667
1674 auto triangles(index_t f) const {
1675 geo_debug_assert(f < nb());
1676 index_t v0 = facet_corners_.vertex(corners_begin(f));
1677 return transform_range(
1679 index_as_iterator(corners_begin(f)+1),
1680 index_as_iterator(corners_end(f)-1)
1681 ),
1682 [this,v0](index_t c)->std::tuple<index_t, index_t, index_t> {
1683 return std::make_tuple(
1684 v0,
1685 facet_corners_.vertex(c),
1686 facet_corners_.vertex(c+1)
1687 );
1688 }
1689 );
1690 }
1691
1700 template <index_t DIM=3> auto triangle_points(index_t f) const {
1701 geo_debug_assert(f < nb());
1702 typedef vecng<DIM,double> vecn;
1703 return transform_range(
1704 triangles(f),
1705 [this](std::tuple<index_t, index_t, index_t> T)
1706 ->std::tuple<const vecn&, const vecn&, const vecn&> {
1707 return std::tuple<const vecn&, const vecn&, const vecn&>(
1708 vertices_.point<DIM>(std::get<0>(T)),
1709 vertices_.point<DIM>(std::get<1>(T)),
1710 vertices_.point<DIM>(std::get<2>(T))
1711 );
1712 }
1713 );
1714 }
1715
1724 template <index_t DIM=3> auto triangle_points(index_t f) {
1725 geo_debug_assert(f < nb());
1726 typedef vecng<DIM,double> vecn;
1727 return transform_range(
1728 triangles(f),
1729 [this](std::tuple<index_t, index_t, index_t> T)
1730 ->std::tuple<vecn&, vecn&, vecn&> {
1731 return std::tuple<vecn&, vecn&, vecn&>(
1732 vertices_.point(std::get<0>(T)),
1733 vertices_.point(std::get<1>(T)),
1734 vertices_.point(std::get<2>(T))
1735 );
1736 }
1737 );
1738 }
1739
1740#endif
1741
1742 protected:
1743
1748 if(!is_simplicial_) {
1749 is_simplicial_ = true;
1750 facet_ptr_.resize(1);
1751 facet_ptr_[0] = 0;
1752 }
1753 }
1754
1762 if(is_simplicial_) {
1763 is_simplicial_ = false;
1764 facet_ptr_.resize(nb()+1);
1765 for(index_t f=0; f<facet_ptr_.size(); ++f) {
1766 facet_ptr_[f] = 3*f;
1767 }
1768 }
1769 }
1770
1771 protected:
1772 MeshVertices& vertices_;
1773 MeshFacetCornersStore& facet_corners_;
1774 friend class Mesh;
1775 friend class GeogramIOHandler;
1776 friend void GEOGRAM_API tessellate_facets(
1777 Mesh& M, index_t max_nb_vertices
1778 );
1779 };
1780
1781 /*************************************************************************/
1782
1783 enum MeshCellType {
1784 MESH_TET = 0,
1785 MESH_HEX = 1,
1786 MESH_PRISM = 2,
1787 MESH_PYRAMID = 3,
1788 MESH_CONNECTOR = 4,
1789 MESH_NB_CELL_TYPES = 5
1790 };
1791
1826
1827
1834 namespace MeshCellDescriptors {
1838 GEOGRAM_API extern CellDescriptor*
1839 cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES];
1840
1841 GEOGRAM_API extern CellDescriptor tet_descriptor;
1842 GEOGRAM_API extern CellDescriptor hex_descriptor;
1843 GEOGRAM_API extern CellDescriptor prism_descriptor;
1844 GEOGRAM_API extern CellDescriptor pyramid_descriptor;
1845 GEOGRAM_API extern CellDescriptor connector_descriptor;
1846 }
1847
1852 class GEOGRAM_API MeshCellsStore : public MeshSubElementsStore {
1853 public:
1854 MeshCellsStore(Mesh& mesh);
1855
1863 bool are_simplices() const {
1864 return is_simplicial_;
1865 }
1866
1873 MeshCellType type(index_t c) const {
1874 geo_debug_assert(c < nb());
1875 return is_simplicial_ ? MESH_TET : MeshCellType(cell_type_[c]);
1876 }
1877
1887
1898 MeshCellType t
1899 );
1900
1907 geo_debug_assert(c < nb());
1908 return descriptor(c).nb_vertices;
1909 }
1910
1918 geo_debug_assert(c < nb());
1919 return is_simplicial_ ? 4*c : cell_ptr_[c];
1920 }
1921
1929 geo_debug_assert(c < nb());
1930 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_corners(c);
1931 }
1932
1940 geo_debug_assert(c < nb());
1941 // There seems to be a linkage problem under MSVC for the
1942 // following assertion check...
1943#ifndef GEO_OS_WINDOWS
1944 geo_debug_assert(lv < nb_corners(c));
1945#endif
1946 return corners_begin(c) + lv;
1947 }
1948
1955 geo_debug_assert(c < nb());
1956 return descriptor(c).nb_facets;
1957 }
1958
1966 geo_debug_assert(c < nb());
1967 return is_simplicial_ ? 4*c : cell_ptr_[c];
1968 }
1969
1977 geo_debug_assert(c < nb());
1978 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_facets(c);
1979 }
1980
1988 geo_debug_assert(c < nb());
1989 geo_debug_assert(lf < nb_facets(c));
1990 return facets_begin(c) + lf;
1991 }
1992
1999 return descriptor(c).nb_edges;
2000 }
2001
2009 geo_debug_assert(!is_simplicial_);
2010 return &cell_ptr_[c];
2011 }
2012
2019 const index_t* cell_ptr_ptr(index_t c) const {
2020 geo_debug_assert(!is_simplicial_);
2021 return &cell_ptr_[c];
2022 }
2023
2031 geo_debug_assert(!is_simplicial_);
2032 return &cell_type_[c];
2033 }
2034
2042 geo_debug_assert(!is_simplicial_);
2043 return &cell_type_[c];
2044 }
2045
2046
2047 protected:
2049 bool keep_attributes, bool keep_memory = false
2050 ) override;
2051
2052 void resize_store(index_t new_size) override;
2053
2054 index_t create_sub_element(MeshCellType type) {
2055 if(!is_simplicial_) {
2056 cell_ptr_.push_back(NO_CORNER);
2057 cell_type_.push_back(Numeric::uint8(type));
2058 }
2059 return MeshSubElementsStore::create_sub_element();
2060 }
2061
2062 index_t create_sub_elements(index_t nb, MeshCellType type) {
2063 if(!is_simplicial_) {
2064 for(index_t i=0; i<nb; ++i) {
2065 cell_ptr_.push_back(NO_CORNER);
2066 cell_type_.push_back(Numeric::uint8(type));
2067 }
2068 }
2069 return MeshSubElementsStore::create_sub_elements(nb);
2070 }
2071
2072 void copy(
2073 const MeshCellsStore& rhs, bool copy_attributes=true
2074 ) {
2075 MeshSubElementsStore::copy(rhs, copy_attributes);
2076 is_simplicial_ = rhs.is_simplicial_;
2077 cell_type_ = rhs.cell_type_;
2078 cell_ptr_ = rhs.cell_ptr_;
2079 }
2080
2081 protected:
2082 bool is_simplicial_;
2083 vector<Numeric::uint8> cell_type_;
2084 vector<index_t> cell_ptr_;
2085
2086 protected:
2087 friend class Mesh;
2088 friend class GeogramIOHandler;
2089 };
2090
2091 /*************************************************************************/
2092
2097 class GEOGRAM_API MeshCellCornersStore : public MeshSubElementsStore {
2098 public:
2100
2107 geo_debug_assert(c < nb());
2108 return corner_vertex_[c];
2109 }
2110
2117 geo_debug_assert(c < nb());
2118 geo_debug_assert(v < vertices_.nb());
2119 corner_vertex_[c] = v;
2120 }
2121
2130 geo_debug_assert(c < nb());
2131 return &(corner_vertex_[c]);
2132 }
2133
2142 geo_debug_assert(c < nb());
2143 return &(corner_vertex_[c]);
2144 }
2145
2152 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
2153 geo_debug_assert(c < nb());
2154 return vertices_.point<DIM>(vertex(c));
2155 }
2156
2164 template <index_t DIM=3> const vecng<DIM,double>& point(
2165 index_t c
2166 ) const {
2167 geo_debug_assert(c < nb());
2168 return vertices_.point(vertex(c));
2169 }
2170
2171 protected:
2173 bool keep_attributes, bool keep_memory = false
2174 ) override;
2175
2176 void resize_store(index_t new_size) override;
2177
2178 index_t create_sub_element(index_t v) {
2179 corner_vertex_.push_back(v);
2180 return MeshSubElementsStore::create_sub_element();
2181 }
2182
2183 index_t create_sub_elements(index_t nb) {
2184 for(index_t i=0; i<nb; ++i) {
2185 corner_vertex_.push_back(NO_VERTEX);
2186 }
2187 return MeshSubElementsStore::create_sub_elements(nb);
2188 }
2189
2190 void copy(
2191 const MeshCellCornersStore& rhs, bool copy_attributes=true
2192 ) {
2193 MeshSubElementsStore::copy(rhs, copy_attributes);
2194 corner_vertex_ = rhs.corner_vertex_;
2195 }
2196
2197 protected:
2198 MeshVertices& vertices_;
2199 vector<index_t> corner_vertex_;
2200
2201 friend class MeshCells;
2202 friend class Mesh;
2203 friend class GeogramIOHandler;
2204 };
2205
2206 /*************************************************************************/
2207
2212 class GEOGRAM_API MeshCellFacetsStore : public MeshSubElementsStore {
2213 public:
2219
2227 geo_debug_assert(f < nb());
2228 return adjacent_cell_[f];
2229 }
2230
2239 geo_debug_assert(f < nb());
2240 geo_debug_assert(c == NO_CELL || c < cells_.nb());
2241 adjacent_cell_[f] = c;
2242 }
2243
2251 geo_debug_assert(f < nb());
2252 return &adjacent_cell_[f];
2253 }
2254
2262 geo_debug_assert(f < nb());
2263 return &adjacent_cell_[f];
2264 }
2265
2266 protected:
2268 bool keep_attributes, bool keep_memory = false
2269 ) override;
2270
2271 void resize_store(index_t new_size) override;
2272
2273 index_t create_sub_element(index_t c = NO_CELL) {
2274 adjacent_cell_.push_back(c);
2275 return MeshSubElementsStore::create_sub_element();
2276 }
2277
2278 index_t create_sub_elements(index_t nb) {
2279 for(index_t i=0; i<nb; ++i) {
2280 adjacent_cell_.push_back(NO_CELL);
2281 }
2282 return MeshSubElementsStore::create_sub_elements(nb);
2283 }
2284
2285 void copy(
2286 const MeshCellFacetsStore& rhs, bool copy_attributes=true
2287 ) {
2288 MeshSubElementsStore::copy(rhs, copy_attributes);
2289 adjacent_cell_ = rhs.adjacent_cell_;
2290 }
2291
2292 protected:
2293 MeshVertices& vertices_;
2294 MeshCellsStore& cells_;
2295 vector<index_t> adjacent_cell_;
2296
2297 friend class MeshCells;
2298 friend class Mesh;
2299 friend class GeogramIOHandler;
2300 };
2301
2302 /*************************************************************************/
2303
2308 class GEOGRAM_API MeshCells : public MeshCellsStore, public MeshElements {
2309 public:
2315
2322 return nb_corners(c);
2323 }
2324
2332 return cell_corners_.vertex(corner(c,lv));
2333 }
2334
2342 cell_corners_.set_vertex(corner(c,lv),v);
2343 }
2344
2353 template <index_t DIM=3> const vecng<DIM,double>& point(
2354 index_t c, index_t lv
2355 ) const {
2356 return vertices_.point<DIM>(vertex(c,lv));
2357 }
2358
2367 template <index_t DIM=3> vecng<DIM,double>& point(
2368 index_t c, index_t lv
2369 ) {
2370 return vertices_.point<DIM>(vertex(c,lv));
2371 }
2372
2381 return cell_facets_.adjacent_cell(facet(c,lf));
2382 }
2383
2392 cell_facets_.set_adjacent_cell(facet(c,lf),c2);
2393 }
2394
2402 geo_debug_assert(lf < nb_facets(c));
2403 return descriptor(c).nb_vertices_in_facet[lf];
2404 }
2405
2415 geo_debug_assert(lv < facet_nb_vertices(c, lf));
2416 return cell_corners_.vertex(
2417 corner(c, descriptor(c).facet_vertex[lf][lv])
2418 );
2419 }
2429 geo_debug_assert(lc < facet_nb_vertices(c, lf));
2430 return corner(c, descriptor(c).facet_vertex[lf][lc]);
2431 }
2432
2442 geo_debug_assert(le < nb_edges(c));
2443 geo_debug_assert(lv < 2);
2444 return cell_corners_.vertex(
2445 corner(c,descriptor(c).edge_vertex[le][lv])
2446 );
2447 }
2448
2460 geo_debug_assert(le < nb_edges(c));
2461 geo_debug_assert(lf < 2);
2462 return descriptor(c).edge_adjacent_facet[le][lf];
2463 }
2464
2471 geo_debug_assert(c < nb());
2472 return index_range(
2473 index_as_iterator(corners_begin(c)),
2474 index_as_iterator(corners_end(c))
2475 );
2476 }
2477
2484 geo_debug_assert(c < nb());
2485 return index_range(
2486 index_as_iterator(facets_begin(c)),
2487 index_as_iterator(facets_end(c))
2488 );
2489 }
2490
2491#ifndef MESH_NO_SYNTAXIC_SUGAR
2492
2499 template <index_t DIM=3> auto points(index_t cell) const {
2500 geo_debug_assert(cell < nb());
2501 typedef vecng<DIM,double> vecn;
2502 return transform_range_ref(
2503 corners(cell), [this](index_t c)->const vecn& {
2504 index_t v = cell_corners_.vertex(c);
2505 return vertices_.point<DIM>(v);
2506 }
2507 );
2508 }
2509
2516 template <index_t DIM=3> auto points(index_t cell) {
2517 geo_debug_assert(cell < nb());
2518 typedef vecng<DIM,double> vecn;
2519 return transform_range_ref(
2520 corners(cell), [this](index_t c)->vecn& {
2521 index_t v = cell_corners_.vertex(c);
2522 return vertices_.point<DIM>(v);
2523 }
2524 );
2525 }
2526
2534 auto adjacent(index_t c) const {
2535 geo_debug_assert(c < nb());
2536 return transform_range(
2537 facets(c), [this](index_t f)->index_t {
2538 return cell_facets_.adjacent_cell(f);
2539 }
2540 );
2541 }
2542
2543#endif
2544
2545 void clear(
2546 bool keep_attributes=true, bool keep_memory=false
2547 ) override;
2548
2550 vector<index_t>& to_delete,
2551 bool remove_isolated_vertices=true
2552 ) override;
2553
2554 void permute_elements(vector<index_t>& permutation) override;
2555
2564 index_t create_cells(index_t nb_cells, MeshCellType type) {
2565
2566 if(nb_cells == 0) {
2567 return NO_CELL;
2568 }
2569
2570
2571 if(type != MESH_TET) {
2572 is_not_simplicial();
2573 }
2574
2575 const CellDescriptor& desc = cell_type_to_cell_descriptor(type);
2576
2577 // Note: there is padding, the same number of corners and
2578 // faces is created for each cell, so that a single cell
2579 // pointer is used for both.
2580
2581 index_t cell_size = std::max(desc.nb_vertices, desc.nb_facets);
2582 index_t first_cell = nb();
2583 index_t co = cell_corners_.nb();
2584
2585 cell_corners_.create_sub_elements(
2586 nb_cells*cell_size
2587 );
2588
2589 cell_facets_.create_sub_elements(
2590 nb_cells*cell_size
2591 );
2592
2593 index_t result = create_sub_elements(nb_cells, type);
2594
2595 if(!is_simplicial_) {
2596 for(index_t c=first_cell; c<=first_cell+nb_cells; ++c) {
2597 cell_ptr_[c] = co;
2598 co += cell_size;
2599 }
2600
2601 geo_debug_assert(cell_ptr_.size() == nb()+1);
2602 geo_debug_assert(cell_ptr_[nb()] == cell_corners_.nb());
2603 geo_debug_assert(cell_ptr_[nb()] == cell_facets_.nb());
2604 }
2605
2606 return result;
2607 }
2608
2615 return create_cells(nb_tets, MESH_TET);
2616 }
2617
2624 return create_cells(nb_hexes, MESH_HEX);
2625 }
2626
2633 return create_cells(nb_prisms, MESH_PRISM);
2634 }
2635
2642 return create_cells(nb_pyramids, MESH_PYRAMID);
2643 }
2644
2654 index_t v1, index_t v2, index_t v3, index_t v4,
2655 index_t adj1 = NO_CELL,
2656 index_t adj2 = NO_CELL,
2657 index_t adj3 = NO_CELL,
2658 index_t adj4 = NO_CELL
2659 ) {
2660 cell_corners_.create_sub_element(v1);
2661 cell_corners_.create_sub_element(v2);
2662 cell_corners_.create_sub_element(v3);
2663 cell_corners_.create_sub_element(v4);
2664 cell_facets_.create_sub_element(adj1);
2665 cell_facets_.create_sub_element(adj2);
2666 cell_facets_.create_sub_element(adj3);
2667 cell_facets_.create_sub_element(adj4);
2668 index_t result = create_sub_element(MESH_TET);
2669 if(!is_simplicial_) {
2670 cell_ptr_[nb()] = cell_corners_.nb();
2671 }
2672 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2673 return result;
2674 }
2675
2686 index_t v1, index_t v2, index_t v3, index_t v4,
2687 index_t v5, index_t v6, index_t v7, index_t v8,
2688 index_t adj1 = NO_CELL,
2689 index_t adj2 = NO_CELL,
2690 index_t adj3 = NO_CELL,
2691 index_t adj4 = NO_CELL,
2692 index_t adj5 = NO_CELL,
2693 index_t adj6 = NO_CELL
2694 ) {
2695 is_not_simplicial();
2696 cell_corners_.create_sub_element(v1);
2697 cell_corners_.create_sub_element(v2);
2698 cell_corners_.create_sub_element(v3);
2699 cell_corners_.create_sub_element(v4);
2700 cell_corners_.create_sub_element(v5);
2701 cell_corners_.create_sub_element(v6);
2702 cell_corners_.create_sub_element(v7);
2703 cell_corners_.create_sub_element(v8);
2704 cell_facets_.create_sub_element(adj1);
2705 cell_facets_.create_sub_element(adj2);
2706 cell_facets_.create_sub_element(adj3);
2707 cell_facets_.create_sub_element(adj4);
2708 cell_facets_.create_sub_element(adj5);
2709 cell_facets_.create_sub_element(adj6);
2710 cell_facets_.create_sub_element(NO_CELL); // padding
2711 cell_facets_.create_sub_element(NO_CELL); // padding
2712 index_t result = create_sub_element(MESH_HEX);
2713 cell_ptr_[nb()] = cell_corners_.nb();
2714 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2715 return result;
2716 }
2717
2728 index_t v1, index_t v2,
2729 index_t v3, index_t v4,
2730 index_t v5, index_t v6,
2731 index_t adj1 = NO_CELL,
2732 index_t adj2 = NO_CELL,
2733 index_t adj3 = NO_CELL,
2734 index_t adj4 = NO_CELL,
2735 index_t adj5 = NO_CELL
2736 ) {
2737 is_not_simplicial();
2738 cell_corners_.create_sub_element(v1);
2739 cell_corners_.create_sub_element(v2);
2740 cell_corners_.create_sub_element(v3);
2741 cell_corners_.create_sub_element(v4);
2742 cell_corners_.create_sub_element(v5);
2743 cell_corners_.create_sub_element(v6);
2744 cell_facets_.create_sub_element(adj1);
2745 cell_facets_.create_sub_element(adj2);
2746 cell_facets_.create_sub_element(adj3);
2747 cell_facets_.create_sub_element(adj4);
2748 cell_facets_.create_sub_element(adj5);
2749 cell_facets_.create_sub_element(NO_CELL); // padding
2750 index_t result = create_sub_element(MESH_PRISM);
2751 cell_ptr_[nb()] = cell_corners_.nb();
2752 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2753 return result;
2754 }
2755
2766 index_t v1, index_t v2, index_t v3, index_t v4, index_t v5,
2767 index_t adj1 = NO_CELL,
2768 index_t adj2 = NO_CELL,
2769 index_t adj3 = NO_CELL,
2770 index_t adj4 = NO_CELL,
2771 index_t adj5 = NO_CELL
2772 ) {
2773 is_not_simplicial();
2774 cell_corners_.create_sub_element(v1);
2775 cell_corners_.create_sub_element(v2);
2776 cell_corners_.create_sub_element(v3);
2777 cell_corners_.create_sub_element(v4);
2778 cell_corners_.create_sub_element(v5);
2779 cell_facets_.create_sub_element(adj1);
2780 cell_facets_.create_sub_element(adj2);
2781 cell_facets_.create_sub_element(adj3);
2782 cell_facets_.create_sub_element(adj4);
2783 cell_facets_.create_sub_element(adj5);
2784 index_t result = create_sub_element(MESH_PYRAMID);
2785 cell_ptr_[nb()] = cell_corners_.nb();
2786 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2787 return result;
2788 }
2789
2803 index_t v1, index_t v2, index_t v3, index_t v4,
2804 index_t adj1 = NO_CELL,
2805 index_t adj2 = NO_CELL,
2806 index_t adj3 = NO_CELL
2807 ) {
2808 is_not_simplicial();
2809 cell_corners_.create_sub_element(v1);
2810 cell_corners_.create_sub_element(v2);
2811 cell_corners_.create_sub_element(v3);
2812 cell_corners_.create_sub_element(v4);
2813 cell_facets_.create_sub_element(adj1);
2814 cell_facets_.create_sub_element(adj2);
2815 cell_facets_.create_sub_element(adj3);
2816 cell_facets_.create_sub_element(NO_CELL); // padding
2817 index_t result = create_sub_element(MESH_CONNECTOR);
2818 cell_ptr_[nb()] = cell_corners_.nb();
2819 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2820 return result;
2821 }
2822
2834 bool remove_trivial_slivers = true, bool verbose_if_OK=false
2835 );
2836
2842
2851
2863 coord_index_t dim,
2864 vector<double>& vertices,
2865 vector<index_t>& tets,
2866 bool steal_args
2867 );
2868
2878 vector<index_t>& tets,
2879 bool steal_args
2880 );
2881
2882 void pop() override;
2883
2884 index_t tet_adjacent(index_t t, index_t lf) const {
2885 geo_debug_assert(is_simplicial_);
2886 geo_debug_assert(t < nb());
2887 geo_debug_assert(lf < 4);
2888 return cell_facets_.adjacent_cell_[4*t+lf];
2889 }
2890
2891 index_t find_tet_adjacent(index_t t, index_t t2) const {
2892 geo_debug_assert(is_simplicial_);
2893 geo_debug_assert(t < nb());
2894 geo_debug_assert(t2 < nb());
2895 for(index_t lf=0; lf<4; ++lf) {
2896 if(cell_facets_.adjacent_cell_[4*t+lf] == t2) {
2897 return lf;
2898 }
2899 }
2900 return NO_FACET;
2901 }
2902
2903 index_t tet_vertex(index_t t, index_t lv) const {
2904 geo_debug_assert(is_simplicial_);
2905 geo_debug_assert(t < nb());
2906 geo_debug_assert(lv < 4);
2907 return cell_corners_.corner_vertex_[4*t+lv];
2908 }
2909
2910 index_t find_tet_vertex(index_t t, index_t v) const {
2911 geo_debug_assert(is_simplicial_);
2912 geo_debug_assert(t < nb());
2913 geo_debug_assert(v < vertices_.nb());
2914 for(index_t lv=0; lv<4; ++lv) {
2915 if(cell_corners_.corner_vertex_[4*t+lv] == v) {
2916 return lv;
2917 }
2918 }
2919 return NO_VERTEX;
2920 }
2921
2933 index_t t, index_t lf, index_t lv
2934 ) const {
2935 geo_debug_assert(is_simplicial_);
2936 geo_debug_assert(t < nb());
2937 geo_debug_assert(lf < 4);
2938 geo_debug_assert(lv < 3);
2939 return cell_corners_.vertex(
2940 4 * t + local_tet_facet_vertex_index(lf,lv)
2941 );
2942 }
2943
2958 index_t t, index_t v1, index_t v2, index_t v3
2959 ) const {
2960 geo_debug_assert(is_simplicial_);
2961 for(index_t lf = 0; lf < 4; ++lf) {
2962 index_t w1 = tet_facet_vertex(t, lf, 0);
2963 index_t w2 = tet_facet_vertex(t, lf, 1);
2964 index_t w3 = tet_facet_vertex(t, lf, 2);
2965 if(
2966 (v1 == w1 && v2 == w2 && v3 == w3) ||
2967 (v1 == w2 && v2 == w3 && v3 == w1) ||
2968 (v1 == w3 && v2 == w1 && v3 == w2)
2969 ) {
2970 return lf;
2971 }
2972 }
2973 return NO_FACET;
2974 }
2975
2985 geo_debug_assert(lf < 4);
2986 geo_debug_assert(lv < 3);
2987 return MeshCellDescriptors::tet_descriptor.facet_vertex[lf][lv];
2988 }
2989
2990 protected:
2991
2999 if(is_simplicial_) {
3000 is_simplicial_ = false;
3001 cell_ptr_.resize(nb()+1);
3002 cell_type_.assign(nb(), MESH_TET);
3003 for(index_t c=0; c<cell_ptr_.size(); ++c) {
3004 cell_ptr_[c] = 4*c;
3005 }
3006 }
3007 }
3008
3021 index_t c1, index_t f1, index_t c2, index_t f2
3022 ) const;
3023
3033 geo_debug_assert(c < nb());
3034 geo_debug_assert(v < vertices_.nb());
3035 for(index_t lv=0; lv<nb_vertices(c); ++lv) {
3036 if(vertex(c,lv) == v) {
3037 return lv;
3038 }
3039 }
3040 return NO_VERTEX;
3041 }
3042
3055 index_t c1, index_t c2, index_t f2
3056 ) const {
3057 for(index_t f1=0; f1<nb_facets(c1); ++f1) {
3058 if(facets_match(c1,f1,c2,f2)) {
3059 return f1;
3060 }
3061 }
3062 return NO_FACET;
3063 }
3064
3078 index_t c1, index_t lf1,
3079 index_t c2, index_t lf2
3080 ) const;
3081
3082
3097 index_t c1, index_t f1,
3098 index_t c2, index_t f2,
3099 index_t& e1, index_t& e2
3100 ) const;
3101
3121 index_t c1, index_t lf1,
3122 const std::vector< std::pair<index_t, index_t> >& matches
3123 );
3124
3130
3131 protected:
3132 MeshVertices& vertices_;
3133 MeshCellCornersStore& cell_corners_;
3134 MeshCellFacetsStore& cell_facets_;
3135 friend class Mesh;
3136 friend class GeogramIOHandler;
3137 };
3138
3139 /*************************************************************************/
3140
3149 MESH_NONE = 0,
3150 MESH_VERTICES = 1,
3151 MESH_FACETS = 2,
3152 MESH_EDGES = 4,
3153 MESH_CELLS = 8,
3154 MESH_ALL_ELEMENTS = 15,
3155 MESH_FACET_CORNERS = 16,
3156 MESH_CELL_CORNERS = 32,
3157 MESH_CELL_FACETS = 64,
3158 MESH_ALL_SUBELEMENTS = 65
3159 };
3160
3161 /*************************************************************************/
3162
3169 class GEOGRAM_API Mesh {
3170 public:
3171 MeshVertices vertices;
3172 MeshEdges edges;
3173 MeshFacets facets;
3174 MeshFacetCornersStore facet_corners;
3175 MeshCells cells;
3176 MeshCellCornersStore cell_corners;
3177 MeshCellFacetsStore cell_facets;
3178
3186 Mesh(index_t dimension=3, bool single_precision=false);
3187
3191 virtual ~Mesh();
3192
3203 void clear(bool keep_attributes=true, bool keep_memory=false);
3204
3208 void show_stats(const std::string& tag = "Mesh") const;
3209
3210
3219
3220
3233 void copy(
3234 const Mesh& rhs,
3235 bool copy_attributes=true,
3236 MeshElementsFlags what=MESH_ALL_ELEMENTS
3237 );
3238
3249 bool load(const std::string& filename);
3250
3258 bool save(const std::string& filename) const;
3259
3264 std::string get_attributes() const;
3265
3272 std::string get_scalar_attributes() const;
3273
3280 std::string get_vector_attributes(index_t max_dim = 0) const;
3281
3287
3295
3303
3304
3312
3321 ) const;
3322
3330
3339 const std::string& name
3340 );
3341
3357 const std::string& full_attribute_name,
3358 MeshElementsFlags& where,
3359 std::string& attribute_name,
3360 index_t& component
3361 );
3362
3363 protected:
3372 const std::string& tag, const std::string& subelement_name,
3373 const MeshSubElementsStore& subelements
3374 ) const;
3375
3383 Mesh(const Mesh& rhs) = delete;
3384
3392 const Mesh& operator=(const Mesh& rhs) = delete;
3393 };
3394
3395 /*************************************************************************/
3396}
3397
3398#endif
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
Generic mechanism for attributes.
Manages an attribute attached to a set of object.
Manages a set of attributes attached to an object.
Definition attributes.h:947
index_t size() const
Gets the size.
Definition attributes.h:982
Stores the cell corners of a mesh (low-level store)
Definition mesh.h:2097
void set_vertex(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition mesh.h:2116
index_t vertex(index_t c) const
Gets the vertex that a corner is incident to.
Definition mesh.h:2106
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
index_t * vertex_index_ptr(index_t c)
Gets a pointer to the vertex that a corner is incident to.
Definition mesh.h:2129
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
vecng< DIM, double > & point(index_t c)
Gets the point associated with a corner.
Definition mesh.h:2152
const index_t * vertex_index_ptr(index_t c) const
Gets a pointer to the vertex that a corner is incident to.
Definition mesh.h:2141
const vecng< DIM, double > & point(index_t c) const
Gets the point associated with a corner.
Definition mesh.h:2164
Stores the cell facets of a mesh (low-level store)
Definition mesh.h:2212
index_t adjacent_cell(index_t f) const
Gets a cell adjacent to a facet.
Definition mesh.h:2226
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
index_t * adjacent_cell_ptr(index_t f)
Gets a pointer to a cell adjacent to a facet.
Definition mesh.h:2261
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
const index_t * adjacent_cell_ptr(index_t f) const
Gets a const pointer to a cell adjacent to a facet.
Definition mesh.h:2250
MeshCellFacetsStore(Mesh &mesh)
MeshCellFacetsStore constructor.
void set_adjacent_cell(index_t f, index_t c)
Sets a cell adjacent to a facet.
Definition mesh.h:2238
Stores the cells of a mesh (low-level store)
Definition mesh.h:1852
index_t facet(index_t c, index_t lf) const
Gets a facet of a cell by local facet index.
Definition mesh.h:1987
bool are_simplices() const
Tests whether all the cells are tetrahedra.
Definition mesh.h:1863
static const CellDescriptor & cell_type_to_cell_descriptor(MeshCellType t)
Gets a descriptor by cell type.
const CellDescriptor & descriptor(index_t c) const
Gets the descriptor of a cell.
index_t corner(index_t c, index_t lv) const
Gets a corner of a cell by local vertex index.
Definition mesh.h:1939
index_t nb_facets(index_t c) const
Gets the number of facets of a cell.
Definition mesh.h:1954
Numeric::uint8 * cell_type_ptr(index_t c)
Gets a pointer to a cell type by cell index.
Definition mesh.h:2030
index_t corners_end(index_t c) const
Gets the upper limit for iterating over the corners of a cell.
Definition mesh.h:1928
MeshCellType type(index_t c) const
Gets the type of a cell.
Definition mesh.h:1873
index_t facets_end(index_t c) const
Gets the upper limit for iterating over the facets of a cell.
Definition mesh.h:1976
const index_t * cell_ptr_ptr(index_t c) const
Gets a pointer to a cell pointer index by cell index.
Definition mesh.h:2019
const Numeric::uint8 * cell_type_ptr(index_t c) const
Gets a pointer to a cell type by cell index.
Definition mesh.h:2041
index_t nb_corners(index_t c) const
Gets the number of corners of a cell.
Definition mesh.h:1906
index_t corners_begin(index_t c) const
Gets the first element for iterating over the corners of a cell.
Definition mesh.h:1917
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
index_t * cell_ptr_ptr(index_t c)
Gets a pointer to a cell pointer index by cell index.
Definition mesh.h:2008
index_t nb_edges(index_t c) const
Gets the number of edges in a cell.
Definition mesh.h:1998
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
index_t facets_begin(index_t c) const
Gets the first element for iterating over the facets of a cell.
Definition mesh.h:1965
The cells of a mesh.
Definition mesh.h:2308
index_t create_cells(index_t nb_cells, MeshCellType type)
Creates a contiguous chunk of cells of the same type.
Definition mesh.h:2564
void pop() override
Removes the last element.
void compute_borders()
Replaces the surfacic part of this mesh with the borders of the volumetric part.
void set_vertex(index_t c, index_t lv, index_t v)
Sets a vertex of a cell by local vertex index.
Definition mesh.h:2341
index_t create_pyramids(index_t nb_pyramids)
Creates a contiguous chunk of pyramids.
Definition mesh.h:2641
void assign_tet_mesh(vector< index_t > &tets, bool steal_args)
Copies a tetrahedron mesh into this Mesh.
index_t adjacent(index_t c, index_t lf) const
Gets a cell adjacent to another one by local facet index.
Definition mesh.h:2380
void assign_tet_mesh(coord_index_t dim, vector< double > &vertices, vector< index_t > &tets, bool steal_args)
Copies a tetrahedron mesh into this Mesh.
vecng< DIM, double > & point(index_t c, index_t lv)
Gets a point by cell and local vertex index.
Definition mesh.h:2367
bool triangular_facets_have_common_edge(index_t c1, index_t f1, index_t c2, index_t f2, index_t &e1, index_t &e2) const
Tests whether two triangular cell facets have a common edge.
bool facets_match(index_t c1, index_t f1, index_t c2, index_t f2) const
Tests whether two cell facets can be connected.
index_t create_connector(index_t v1, index_t v2, index_t v3, index_t v4, index_t adj1=NO_CELL, index_t adj2=NO_CELL, index_t adj3=NO_CELL)
Creates a connector.
Definition mesh.h:2802
index_t tet_facet_vertex(index_t t, index_t lf, index_t lv) const
Gets a vertex of a tetrahedron by local facet index and local vertex index in facet.
Definition mesh.h:2932
index_range corners(index_t c) const
Gets the corners of a cell.
Definition mesh.h:2470
auto points(index_t cell)
Gets the points associated with the vertices of a cell.
Definition mesh.h:2516
MeshCells(Mesh &mesh)
MeshCells constructor.
index_t edge_vertex(index_t c, index_t le, index_t lv) const
Gets a cell vertex by local edge index and local vertex index in the edge.
Definition mesh.h:2441
void connect(bool remove_trivial_slivers=true, bool verbose_if_OK=false)
Connects the cells.
static index_t local_tet_facet_vertex_index(index_t lf, index_t lv)
Gives the local index of a vertex in a tetrahedron from its facet and vertex local indices.
Definition mesh.h:2984
index_t create_prism(index_t v1, index_t v2, index_t v3, index_t v4, index_t v5, index_t v6, index_t adj1=NO_CELL, index_t adj2=NO_CELL, index_t adj3=NO_CELL, index_t adj4=NO_CELL, index_t adj5=NO_CELL)
Creates a prism.
Definition mesh.h:2727
index_t nb_vertices(index_t c) const
Gets the number of vertices of a cell.
Definition mesh.h:2321
index_t facet_vertex(index_t c, index_t lf, index_t lv) const
Gets a vertex of a cell by local facet index and local vertex index in the facet.
Definition mesh.h:2414
void delete_elements(vector< index_t > &to_delete, bool remove_isolated_vertices=true) override
Deletes a set of elements.
index_t create_pyramid(index_t v1, index_t v2, index_t v3, index_t v4, index_t v5, index_t adj1=NO_CELL, index_t adj2=NO_CELL, index_t adj3=NO_CELL, index_t adj4=NO_CELL, index_t adj5=NO_CELL)
Creates a pyramid.
Definition mesh.h:2765
index_t find_tet_facet(index_t t, index_t v1, index_t v2, index_t v3) const
Finds the local index of a facet in a tetrahedron by the global indices of its vertices.
Definition mesh.h:2957
void permute_elements(vector< index_t > &permutation) override
Applies a permutation to the elements and their attributes.
void is_not_simplicial()
Indicates that the stored elements are no longer only tetrahedra.
Definition mesh.h:2998
index_t facet_corner(index_t c, index_t lf, index_t lc) const
Gets a corner of a cell by local facet index and local corner index in the facet.
Definition mesh.h:2428
index_t find_cell_vertex(index_t c, index_t v) const
Finds the local index of a vertex in a cell.
Definition mesh.h:3032
index_t create_hexes(index_t nb_hexes)
Creates a contiguous chunk of hexahedra.
Definition mesh.h:2623
index_t create_tets(index_t nb_tets)
Creates a contiguous chunk of tetrahedra.
Definition mesh.h:2614
index_t edge_adjacent_facet(index_t c, index_t le, index_t lf) const
Gets a cell local facet index by local edge index and local facet index in the edge.
Definition mesh.h:2459
auto adjacent(index_t c) const
Gets the cells adjacent to a given cell.
Definition mesh.h:2534
void compute_borders(Attribute< index_t > &facet_cell)
Replaces the surfacic part of this mesh with the borders of the volumetric part.
bool create_connector(index_t c1, index_t lf1, const std::vector< std::pair< index_t, index_t > > &matches)
Creates a connector between a quadrandular facet and two triangular facets.
void set_adjacent(index_t c, index_t lf, index_t c2)
Sets a cell adjacent to another one by local facet index.
Definition mesh.h:2391
void clear(bool keep_attributes=true, bool keep_memory=false) override
Removes all the elements and attributes.
index_t create_prisms(index_t nb_prisms)
Creates a contiguous chunk of prisms.
Definition mesh.h:2632
index_t create_tet(index_t v1, index_t v2, index_t v3, index_t v4, index_t adj1=NO_CELL, index_t adj2=NO_CELL, index_t adj3=NO_CELL, index_t adj4=NO_CELL)
Creates a tetrahedron.
Definition mesh.h:2653
index_t create_hex(index_t v1, index_t v2, index_t v3, index_t v4, index_t v5, index_t v6, index_t v7, index_t v8, index_t adj1=NO_CELL, index_t adj2=NO_CELL, index_t adj3=NO_CELL, index_t adj4=NO_CELL, index_t adj5=NO_CELL, index_t adj6=NO_CELL)
Creates an hexahedron.
Definition mesh.h:2685
void connect_tets()
Optimized implementation of connect() used when the mesh is simplicial.
index_t facet_nb_vertices(index_t c, index_t lf) const
Gets the number of vertices in a cell facet.
Definition mesh.h:2401
bool triangular_facet_matches_quad_facet(index_t c1, index_t lf1, index_t c2, index_t lf2) const
Tests whether a triangular facet matches a quad facet.
index_range facets(index_t c) const
Gets the facets of a cell.
Definition mesh.h:2483
auto points(index_t cell) const
Gets the points associated with the vertices of a cell.
Definition mesh.h:2499
index_t find_cell_facet(index_t c1, index_t c2, index_t f2) const
Finds the local index of a facet in a cell that can be connected to a facet of another cell.
Definition mesh.h:3054
const vecng< DIM, double > & point(index_t c, index_t lv) const
Gets a point by cell and local vertex index.
Definition mesh.h:2353
index_t vertex(index_t c, index_t lv) const
Gets a vertex of a cell by local vertex index.
Definition mesh.h:2331
The edges of a mesh.
Definition mesh.h:716
index_t vertex(index_t e, index_t lv) const
Gets the index of an edge vertex.
Definition mesh.h:727
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
void flip(index_t e)
Swaps both extremities of an edge.
void pop() override
Removes the last element.
const index_t * vertex_index_ptr(index_t c) const
Gets a pointer to a vertex index by corner index.
Definition mesh.h:763
void clear(bool keep_attributes=true, bool keep_memory=false) override
Removes all the elements and attributes.
index_t create_edge(index_t v1, index_t v2)
Creates a new edge.
Definition mesh.h:790
index_t create_edge()
Creates a new edge.
Definition mesh.h:772
void permute_elements(vector< index_t > &permutation) override
Applies a permutation to the elements and their attributes.
index_t create_edges(index_t nb)
Creates a batch of edges.
Definition mesh.h:781
index_t * vertex_index_ptr(index_t c)
Gets a pointer to a vertex index by corner index.
Definition mesh.h:752
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
void delete_elements(vector< index_t > &to_delete, bool remove_isolated_vertices=true) override
Deletes a set of elements.
void set_vertex(index_t e, index_t lv, index_t v)
Sets a vertex of an edge.
Definition mesh.h:739
Base class for mesh elements.
Definition mesh.h:252
virtual void delete_elements(vector< index_t > &to_delete, bool remove_isolated_vertices=true)=0
Deletes a set of elements.
static bool has_non_zero(const GEO::vector< index_t > &I)
Tests whether a vector contains a non-zero value.
Definition mesh.h:311
virtual void clear(bool keep_attributes=true, bool keep_memory=false)=0
Removes all the elements and attributes.
virtual void pop()=0
Removes the last element.
virtual void permute_elements(vector< index_t > &permutation)=0
Applies a permutation to the elements and their attributes.
Stores the facet corners of a mesh (low-level store)
Definition mesh.h:976
index_t * vertex_index_ptr(index_t c)
Gets a pointer to the vertex that a corner is incident to.
Definition mesh.h:1072
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
const index_t * adjacent_facet_ptr(index_t c) const
Gets a pointer to the the facet index that a corner is adjacent to.
Definition mesh.h:1008
vecng< DIM, double > & point(index_t c)
Gets the point associated with a corner.
Definition mesh.h:1106
index_t * adjacent_facet_ptr(index_t c)
Gets a pointer to the the facet index that a corner is adjacent to.
Definition mesh.h:1021
index_t adjacent_facet(index_t c) const
Gets the facet that a corner is adjacent to.
Definition mesh.h:996
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
const index_t * vertex_index_ptr(index_t c) const
Gets a pointer to the vertex that a corner is incident to.
Definition mesh.h:1084
void set_vertex_no_check(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition mesh.h:1048
index_t vertex(index_t c) const
Gets the vertex that a corner is incident to.
Definition mesh.h:985
const vecng< DIM, double > & point(index_t c) const
Gets the point associated with a corner.
Definition mesh.h:1118
void set_adjacent_facet(index_t c, index_t f)
Sets the facet that a corner is adjacent to.
Definition mesh.h:1059
const vector< index_t > & vertex_indices() const
Gets the vertex indices of all corners as a single vector.
Definition mesh.h:1096
void set_vertex(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition mesh.h:1032
Stores the facets of a mesh (low-level store)
Definition mesh.h:849
index_t corner(index_t f, index_t lv) const
Gets a corner by facet and local vertex index.
Definition mesh.h:892
index_t corners_end(index_t f) const
Gets the upper limit for iterating over the corners of a facet.
Definition mesh.h:870
index_t nb_corners(index_t f) const
Gets the number of corners in a facet.
Definition mesh.h:880
const index_t * corners_begin_ptr(index_t f) const
Gets a pointer to the first element for iterating over the corners of a facet.
Definition mesh.h:927
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
index_t * corners_begin_ptr(index_t f)
Gets a pointer to the first element for iterating over the corners of a facet.
Definition mesh.h:915
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
bool are_simplices() const
Tests whether all the facets are triangles.
Definition mesh.h:905
index_t corners_begin(index_t f) const
Gets the first element for iterating over the corners of a facet.
Definition mesh.h:859
The facets of a mesh.
Definition mesh.h:1173
index_t create_triangle(index_t v1, index_t v2, index_t v3)
Creates a triangle.
Definition mesh.h:1435
auto triangle_points(index_t f)
Decomposes a facet into triangles.
Definition mesh.h:1724
void compute_borders()
Replaces the edges of this mesh with the borders of the surfacic part.
void clear(bool keep_attributes=true, bool keep_memory=false) override
Removes all the elements and attributes.
index_t create_quad(index_t v1, index_t v2, index_t v3, index_t v4)
Creates a quad.
Definition mesh.h:1456
auto triangles(index_t f) const
Decomposes a facet into triangles.
Definition mesh.h:1674
index_t create_polygon(const vector< index_t > &vertices)
Creates a polygonal facet.
Definition mesh.h:1518
void is_not_simplicial()
Indicates that the stored elements are no longer only triangles.
Definition mesh.h:1761
void triangulate()
Triangulates the facets.
MeshFacets(Mesh &mesh)
MeshFacets constructor.
friend void tessellate_facets(Mesh &M, index_t max_nb_vertices)
Subdivides the facets with more than nb_vertices.
index_t vertex(index_t f, index_t lv) const
Gets a vertex by facet and local vertex index.
Definition mesh.h:1199
void connect(index_t facets_begin, index_t facets_end)
Connects a contiguous sequence of facets.
void reserve(index_t nb_to_reserve)
Reserves space for new facets.
Definition mesh.h:1407
void permute_elements(vector< index_t > &permutation) override
Applies a permutation to the elements and their attributes.
index_t nb_vertices(index_t f) const
Gets the number of vertices of a facet.
Definition mesh.h:1188
void is_simplicial()
Indicates that the stored elements are only triangles.
Definition mesh.h:1747
void delete_elements(vector< index_t > &to_delete, bool remove_isolated_vertices=true) override
Deletes a set of elements.
void connect()
Connects the facets.
void flip(index_t f)
Flips a facet.
index_t create_polygon(index_t nb_vertices)
Creates a polygonal facet.
Definition mesh.h:1474
index_t create_polygon(index_t nb_vertices, const index_t *vertices)
Creates a polygonal facet.
Definition mesh.h:1496
void set_vertex(index_t f, index_t lv, index_t v)
Sets a vertex by facet and local vertex index.
Definition mesh.h:1239
auto vertices(index_t f) const
Gets the vertices of a facet.
Definition mesh.h:1609
index_t find_common_vertex(index_t f1, index_t f2) const
finds a common vertex shared by two facets
Definition mesh.h:1265
index_range corners(index_t f) const
Gets the corners of a facet.
Definition mesh.h:1594
void pop() override
Removes the last element.
index_t find_edge(index_t f, index_t v1, index_t v2) const
Finds an edge by vertex indices.
Definition mesh.h:1346
auto adjacent(index_t f) const
Gets the facets adjacent to a given facet.
Definition mesh.h:1625
index_t find_vertex(index_t f, index_t v) const
Gets the local index of a vertex in a facet.
Definition mesh.h:1250
vecng< DIM, double > & point(index_t f, index_t lv)
Gets a point by facet and local vertex index.
Definition mesh.h:1226
index_t find_adjacent(index_t f, index_t f2) const
Gets the local index of a facet adjacent to another one.
Definition mesh.h:1293
index_t prev_corner_around_facet(index_t f, index_t c) const
Gets the predecessor of a corner around a facet.
Definition mesh.h:1333
auto points(index_t f)
Gets the points associated with the vertices of a facet.
Definition mesh.h:1657
void assign_triangle_mesh(coord_index_t dim, vector< double > &vertices, vector< index_t > &triangles, bool steal_args)
Copies a triangle mesh into this Mesh.
index_t create_quads(index_t nb_quads)
Creates a contiguous chunk of quads.
Definition mesh.h:1426
index_t create_facets(index_t nb_facets, index_t nb_vertices_per_polygon)
Creates a contiguous chunk of facets.
Definition mesh.h:1377
const vecng< DIM, double > & point(index_t f, index_t lv) const
Gets a point by facet and local vertex index.
Definition mesh.h:1212
index_t adjacent(index_t f, index_t le) const
Gets an adjacent facet by facet and local edge index.
Definition mesh.h:1282
auto points(index_t f) const
Gets the points associated with the vertices of a facet.
Definition mesh.h:1640
void set_adjacent(index_t f, index_t le, index_t f2)
Sets an adjacent facet by facet and local edge index.
Definition mesh.h:1309
index_t create_triangles(index_t nb_triangles)
Creates a contiguous chunk of triangles.
Definition mesh.h:1417
index_t next_corner_around_facet(index_t f, index_t c) const
Gets the successor of a corner around a facet.
Definition mesh.h:1320
auto triangle_points(index_t f) const
Decomposes a facet into triangles.
Definition mesh.h:1700
Base class for mesh sub-element storage.
Definition mesh.h:79
index_as_iterator begin() const
Used by range-based for.
Definition mesh.h:117
virtual ~MeshSubElementsStore()
MeshElementStore destructor.
AttributesManager & attributes() const
Gets the attributes manager.
Definition mesh.h:109
MeshSubElementsStore(Mesh &mesh)
Constructs a new MeshSubElementStore.
index_t create_sub_element()
Creates attributes for a sub-element.
Definition mesh.h:189
virtual void clear_store(bool keep_attributes, bool keep_memory=false)
Removes all the elements and attributes.
index_t create_sub_elements(index_t nb)
Creates a contiguous chunk of attributes for sub-elements.
Definition mesh.h:168
index_t nb() const
Gets the number of (sub-)elements.
Definition mesh.h:98
void reserve_store(index_t nb_to_reserve)
Reserves space for new elements.
Definition mesh.h:157
index_as_iterator end() const
Used by range-based for.
Definition mesh.h:125
void copy(const MeshSubElementsStore &rhs, bool copy_attributes=true)
Copies a MeshSubElementsStore into this one.
Definition mesh.h:223
void adjust_store()
Makes the size of the store tightly match the number of the elements.
Definition mesh.h:210
virtual void resize_store(index_t new_size)
Resizes this MeshSubElementsStore.
The vertices of a mesh.
Definition mesh.h:332
void pop() override
Removes the last element.
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
void clear(bool keep_attributes=true, bool keep_memory=false) override
Removes all the elements and attributes.
auto points() const
Gets the 3D points of the mesh as an iterable sequence.
Definition mesh.h:616
index_t create_vertex(const double *coords)
Creates a new vertex.
Definition mesh.h:362
index_t create_vertex(const vecng< DIM, double > &p)
Creates a vertex from a 3d point.
Definition mesh.h:385
void assign_points(const double *points, index_t dim, index_t nb_pts)
Assigns all the points.
const float * single_precision_point_ptr(index_t v) const
Gets a (single-precision) point.
Definition mesh.h:538
const double * point_ptr(index_t v) const
Gets a point.
Definition mesh.h:477
const vecng< DIM, double > & point(index_t v) const
Gets a point.
Definition mesh.h:520
float * single_precision_point_ptr(index_t v)
Gets a (single-precision) point.
Definition mesh.h:551
auto points()
Gets the 3D points of the mesh as an iterable sequence.
Definition mesh.h:632
void remove_isolated()
Removes the vertices that have no mesh element incident to them.
void set_dimension(index_t dim)
Sets the dimension of the vertices.
Definition mesh.h:462
void set_double_precision()
Sets double precision mode.
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
void permute_elements(vector< index_t > &permutation) override
Applies a permutation to the elements and their attributes.
vector< double > & point_coordinates()
Gets the coordinates of all the points as a single vector.
Definition mesh.h:577
void assign_points(vector< double > &points, index_t dim, bool steal_arg)
Assigns all the points.
bool double_precision() const
Tests whether vertices are stored in double-precision mode.
Definition mesh.h:441
bool single_precision() const
Tests whether vertices are stored in single-precision mode.
Definition mesh.h:430
const vector< double > & point_coordinates() const
Gets the coordinates of all the points as a single vector.
Definition mesh.h:566
vecng< DIM, double > & point(index_t v)
Gets a point.
Definition mesh.h:504
index_t dimension() const
Gets the dimension of the vertices.
Definition mesh.h:449
index_t create_vertices(index_t nb)
Creates a contiguous chunk of vertices.
Definition mesh.h:397
void set_single_precision()
Sets single precision mode.
double * point_ptr(index_t v)
Gets a point.
Definition mesh.h:490
index_t create_vertex()
Creates a new vertex.
Definition mesh.h:353
void delete_elements(vector< index_t > &to_delete, bool remove_isolated_vertices=true) override
Deletes a set of elements.
Represents a mesh.
Definition mesh.h:3169
Mesh(index_t dimension=3, bool single_precision=false)
Mesh constructor.
void copy(const Mesh &rhs, bool copy_attributes=true, MeshElementsFlags what=MESH_ALL_ELEMENTS)
Copies a mesh onto this one.
MeshElementsFlags
Indicates the mesh elements (vertices, facets or cells) present in a mesh.
Definition mesh.h:3148
bool load(const std::string &filename)
Loads this mesh from a file.
MeshSubElementsStore & get_subelements_by_index(index_t i)
Gets a MeshSubElementsStore by index.
index_t nb_subelements_types() const
Gets the number of subelements types.
void assert_is_valid()
Does some validity checks.
static std::string subelements_type_to_name(MeshElementsFlags what)
Gets a subelement name by subelement type.
void clear(bool keep_attributes=true, bool keep_memory=false)
Removes all the elements and attributes of this mesh.
const MeshSubElementsStore & get_subelements_by_index(index_t i) const
Gets a MeshSubElementsStore by index.
bool save(const std::string &filename) const
Saves this mesh to a file.
virtual ~Mesh()
Mesh destructor.
std::string get_attributes() const
Gets the list of all attributes.
Mesh(const Mesh &rhs)=delete
Forbids copy.
static bool parse_attribute_name(const std::string &full_attribute_name, MeshElementsFlags &where, std::string &attribute_name, index_t &component)
Extracts localisation, name and optional component from an attribute name.
void display_attributes(const std::string &tag, const std::string &subelement_name, const MeshSubElementsStore &subelements) const
Displays the list of attributes to the Logger.
const MeshSubElementsStore & get_subelements_by_type(MeshElementsFlags what) const
Gets a MeshSubElementsStore by subelements type.
MeshSubElementsStore & get_subelements_by_type(MeshElementsFlags what)
Gets a MeshSubElementsStore by subelements type.
std::string get_vector_attributes(index_t max_dim=0) const
Gets the list of all vector attributes.
const Mesh & operator=(const Mesh &rhs)=delete
Forbids copy.
std::string get_scalar_attributes() const
Gets the list of all scalar attributes.
static MeshElementsFlags name_to_subelements_type(const std::string &name)
Gets a subelement type by subelement name.
void show_stats(const std::string &tag="Mesh") const
Displays number of vertices, facets and borders.
Wraps an integer to be used with the range-based for construct.
Definition range.h:66
A generic index_range bounded by two "non-iterators".
Definition range.h:106
Generic maths vector.
Definition vecg.h:74
T * data()
Gets modifiable vector data.
Definition vecg.h:165
Vector with aligned memory allocation.
Definition memory.h:703
T * data()
Gets a pointer to the array of elements.
Definition memory.h:849
index_t size() const
Gets the number of elements.
Definition memory.h:749
Common include file, providing basic definitions. Should be included before anything else by all head...
Geometric functions in 2d and 3d.
void copy(void *to, const void *from, size_t size)
Copies a memory block.
Definition memory.h:133
CellDescriptor * cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES]
Maps a cell type to the associated cell descriptor.
uint8_t uint8
Definition numeric.h:139
Global Vorpaline namespace.
auto transform_range_ref(const RANGE &range, XFORM xform)
Creates a range that applies a user-defined function to each element when accessed.
Definition range.h:569
auto transform_range(const RANGE &range, XFORM xform)
Creates a range that applies a user-defined function to each element when accessed.
Definition range.h:552
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:340
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition numeric.h:374
C++-20 like helpers for manipulating ranges of integers.
Lookup tables that describe the combinatorics of each cell type.
Definition mesh.h:1797
index_t nb_vertices_in_facet[6]
Definition mesh.h:1805
index_t facet_vertex[6][4]
Definition mesh.h:1810
index_t nb_vertices
Definition mesh.h:1799
index_t nb_facets
Definition mesh.h:1802
index_t edge_adjacent_facet[12][2]
Definition mesh.h:1824
index_t nb_edges
Definition mesh.h:1814
index_t edge_vertex[12][2]
Definition mesh.h:1819