Geogram Version 1.9.7
A programming library of geometric algorithms
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 const_cast<AttributesManager&>(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_.size());
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 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 *reinterpret_cast<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 *reinterpret_cast<const 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 vector<double>& points, index_t dim, bool steal_arg
568 );
569
579 const double* points, index_t dim, index_t nb_pts
580 );
581
582 void pop() override;
583
584#ifndef MESH_NO_SYNTAXIC_SUGAR
585
590 template <index_t DIM = 3> auto points() const {
591 typedef vecng<DIM,double> vecn;
592 return transform_range_ref(
593 index_range(0, nb()),
594 [this](index_t v)->const vecn& {
595 // for MSVC that cannot chose among const/non-const versions
596 return *reinterpret_cast<const vecn*>(point_ptr(v));
597 // return point<DIM>(v); // MSVC does not understand this one
598 }
599 );
600 }
601
606 template <index_t DIM = 3> auto points() {
607 typedef vecng<DIM,double> vecn;
608 return transform_range_ref(
609 index_range(0, nb()),
610 [this](index_t v)->vecn& {
611 // for MSVC that cannot chose among const/non-const versions
612 return *reinterpret_cast<vecn*>(point_ptr(v));
613 // return point<DIM>(v); // MSVC does not understand this one
614 }
615 );
616 }
617
618#endif
619
620 protected:
621
623 bool keep_attributes, bool keep_memory = false
624 ) override;
625
626 void resize_store(index_t new_size) override;
627
628 void bind_point_attribute(index_t dim, bool single_precision=false);
629
630 void copy(const MeshVertices& rhs, bool copy_attributes=true) {
631 index_t dim = rhs.dimension();
632 if(point_fp32_.is_bound()) {
633 point_fp32_.destroy();
634 }
635 if(point_.is_bound()) {
636 point_.destroy();
637 }
638 MeshSubElementsStore::copy(rhs, copy_attributes);
639 if(rhs.single_precision()) {
640 point_fp32_.bind_if_is_defined(attributes(),"point_fp32");
641 if(!point_fp32_.is_bound()) {
642 point_fp32_.create_vector_attribute(
643 attributes(), "point_fp32", dim
644 );
645 }
646 } else {
647 point_.bind_if_is_defined(attributes(),"point");
648 if(!point_.is_bound()) {
649 point_.create_vector_attribute(
650 attributes(), "point", dim
651 );
652 }
653 }
654 // Even if we do not copy the attributes, we need at least
655 // to copy the coordinates of the points !!
656 if(!copy_attributes) {
657 if(rhs.single_precision()) {
658 Memory::copy(
659 single_precision_point_ptr(0),
661 rhs.dimension()*rhs.nb()*sizeof(float)
662 );
663 } else {
664 Memory::copy(
665 point_ptr(0),
666 rhs.point_ptr(0),
667 rhs.dimension()*rhs.nb()*sizeof(double)
668 );
669 }
670 }
671 }
672
673 MeshEdges& edges_;
674 MeshFacetCornersStore& facet_corners_;
675 MeshCellCornersStore& cell_corners_;
676 Attribute<double> point_;
677 Attribute<float> point_fp32_;
678
679 friend class Mesh;
680 friend class GeogramIOHandler;
681 };
682
683 /*************************************************************************/
684
689 class GEOGRAM_API MeshEdges :
690 public MeshSubElementsStore, public MeshElements {
691 public:
692 MeshEdges(Mesh& mesh);
693 ~MeshEdges() override;
694
702 geo_debug_assert(e < nb());
703 geo_debug_assert(lv < 2);
704 return edge_vertex_[2*e+lv];
705 }
706
714 geo_debug_assert(e < nb());
715 geo_debug_assert(lv < 2);
716 edge_vertex_[2*e+lv] = v;
717 }
718
719
727 geo_debug_assert(c < 2*nb());
728 return &(edge_vertex_[c]);
729 }
730
738 geo_debug_assert(c < 2*nb());
739 return &(edge_vertex_[c]);
740 }
741
747 return create_sub_element();
748 }
749
756 return create_sub_elements(nb);
757 }
758
765 index_t result = create_edge();
766 set_vertex(result,0,v1);
767 set_vertex(result,1,v2);
768 return result;
769 }
770
772 vector<index_t>& to_delete, bool remove_isolated_vertices=true
773 ) override;
774
775 void permute_elements(vector<index_t>& permutation) override;
776
777 void clear(
778 bool keep_attributes=true, bool keep_memory=false
779 ) override;
780
781 void pop() override;
782
787 void flip(index_t e);
788
789 protected:
791 bool keep_attributes, bool keep_memory = false
792 ) override;
793
794 void resize_store(index_t new_size) override;
795
796 index_t create_sub_element() {
797 edge_vertex_.push_back(NO_VERTEX);
798 edge_vertex_.push_back(NO_VERTEX);
799 return MeshSubElementsStore::create_sub_element();
800 }
801
802 index_t create_sub_elements(index_t nb_in) {
803 edge_vertex_.resize(2*(nb()+nb_in),NO_VERTEX);
804 return MeshSubElementsStore::create_sub_elements(nb_in);
805 }
806
807 void copy(const MeshEdges& rhs, bool copy_attributes=true) {
808 MeshSubElementsStore::copy(rhs, copy_attributes);
809 edge_vertex_ = rhs.edge_vertex_;
810 }
811
812 vector<index_t> edge_vertex_;
813 friend class Mesh;
814 friend class GeogramIOHandler;
815 };
816
817 /**************************************************************************/
818
823 class GEOGRAM_API MeshFacetsStore : public MeshSubElementsStore {
824 public:
825 MeshFacetsStore(Mesh& mesh);
826
834 geo_debug_assert(f < nb());
835 return (is_simplicial_ ? 3*f : facet_ptr_[f]);
836 }
837
845 geo_debug_assert(f < nb());
846 return (is_simplicial_ ? 3*(f+1): facet_ptr_[f+1]);
847 }
848
855 geo_debug_assert(f < nb());
856 return (is_simplicial_ ? 3 : facet_ptr_[f+1] - facet_ptr_[f]);
857 }
858
867 geo_debug_assert(f < nb());
868 geo_debug_assert(lv < nb_corners(f));
869 return corners_begin(f)+lv;
870 }
871
879 bool are_simplices() const {
880 return is_simplicial_;
881 }
882
890 geo_debug_assert(!is_simplicial_);
891 geo_debug_assert(f < nb());
892 return &facet_ptr_[f];
893 }
894
902 geo_debug_assert(!is_simplicial_);
903 geo_debug_assert(f < nb());
904 return &facet_ptr_[f];
905 }
906
907
908 protected:
910 bool keep_attributes, bool keep_memory = false
911 ) override;
912
913 void resize_store(index_t new_size) override;
914
915 index_t create_sub_element() {
916 if(!is_simplicial_) {
917 facet_ptr_.push_back(NO_CORNER);
918 }
919 return MeshSubElementsStore::create_sub_element();
920 }
921
922 index_t create_sub_elements(index_t nb) {
923 if(!is_simplicial_) {
924 for(index_t i=0; i<nb; ++i) {
925 facet_ptr_.push_back(NO_CORNER);
926 }
927 }
928 return MeshSubElementsStore::create_sub_elements(nb);
929 }
930
931 void copy(const MeshFacetsStore& rhs, bool copy_attributes=true) {
932 MeshSubElementsStore::copy(rhs,copy_attributes);
933 is_simplicial_ = rhs.is_simplicial_;
934 facet_ptr_ = rhs.facet_ptr_;
935 }
936
937 protected:
938 bool is_simplicial_;
939 vector<index_t> facet_ptr_;
940 friend class Mesh;
941 friend class GeogramIOHandler;
942 };
943
944 /*************************************************************************/
945
950 class GEOGRAM_API MeshFacetCornersStore : public MeshSubElementsStore {
951 public:
953
960 geo_assert(c < nb());
961 return corner_vertex_[c];
962 }
963
971 geo_assert(c < nb());
972 return corner_adjacent_facet_[c];
973 }
974
983 geo_assert(c < nb());
984 return &corner_adjacent_facet_[c];
985 }
986
987
996 geo_assert(c < nb());
997 return &corner_adjacent_facet_[c];
998 }
999
1007 geo_debug_assert(c < nb());
1008 geo_debug_assert(v < vertices_.nb());
1009 corner_vertex_[c] = v;
1010 }
1011
1023 geo_debug_assert(c < nb());
1024 corner_vertex_[c] = v;
1025 }
1026
1034 geo_debug_assert(c < nb());
1035 geo_debug_assert(f == NO_FACET || f < facets_.nb());
1036 corner_adjacent_facet_[c] = f;
1037 }
1038
1047 geo_debug_assert(c < nb());
1048 return &(corner_vertex_[c]);
1049 }
1050
1059 geo_debug_assert(c < nb());
1060 return &(corner_vertex_[c]);
1061 }
1062
1069 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
1070 geo_debug_assert(c < nb());
1071 return vertices_.point<DIM>(vertex(c));
1072 }
1073
1081 template <index_t DIM=3> const vecng<DIM,double>& point(
1082 index_t c
1083 ) const {
1084 geo_debug_assert(c < nb());
1085 return vertices_.point(vertex(c));
1086 }
1087
1088 protected:
1090 bool keep_attributes, bool keep_memory = false
1091 ) override;
1092
1093 void resize_store(index_t new_size) override;
1094
1095 index_t create_sub_element(index_t v, index_t f = NO_FACET) {
1096 corner_vertex_.push_back(v);
1097 corner_adjacent_facet_.push_back(f);
1098 return MeshSubElementsStore::create_sub_element();
1099 }
1100
1101 index_t create_sub_elements(index_t nb) {
1102 for(index_t i=0; i<nb; ++i) {
1103 corner_vertex_.push_back(NO_VERTEX);
1104 }
1105 for(index_t i=0; i<nb; ++i) {
1106 corner_adjacent_facet_.push_back(NO_FACET);
1107 }
1108 return MeshSubElementsStore::create_sub_elements(nb);
1109 }
1110
1111 void copy(
1112 const MeshFacetCornersStore& rhs, bool copy_attributes=true
1113 ) {
1114 MeshSubElementsStore::copy(rhs, copy_attributes);
1115 corner_vertex_ = rhs.corner_vertex_;
1116 corner_adjacent_facet_ = rhs.corner_adjacent_facet_;
1117 }
1118
1119 protected:
1120 MeshVertices& vertices_;
1121 MeshFacetsStore& facets_;
1122 vector<index_t> corner_vertex_;
1123 vector<index_t> corner_adjacent_facet_;
1124
1125 friend class MeshFacets;
1126 friend class Mesh;
1127 friend class GeogramIOHandler;
1128 };
1129
1130 /*************************************************************************/
1131
1136 class GEOGRAM_API MeshFacets : public MeshFacetsStore, public MeshElements {
1137 public:
1138
1145
1152 return nb_corners(f);
1153 }
1154
1163 return facet_corners_.vertex(corner(f,lv));
1164 }
1165
1166
1175 template <index_t DIM=3> const vecng<DIM,double>& point(
1176 index_t f, index_t lv
1177 ) const {
1178 return vertices_.point<DIM>(vertex(f,lv));
1179 }
1180
1189 template <index_t DIM=3> vecng<DIM,double>& point(
1190 index_t f, index_t lv
1191 ) {
1192 return vertices_.point<DIM>(vertex(f,lv));
1193 }
1194
1203 facet_corners_.set_vertex(corner(f,lv),v);
1204 }
1205
1214 for(index_t lv=0; lv<nb_vertices(f); ++lv) {
1215 if(vertex(f,lv) == v) {
1216 return lv;
1217 }
1218 }
1219 return NO_VERTEX;
1220 }
1221
1229 for(index_t lv=0; lv<nb_vertices(f1); ++lv) {
1230 index_t v = vertex(f1,lv);
1231 if(find_vertex(f2,v) != NO_VERTEX) {
1232 return lv;
1233 }
1234 }
1235 return NO_VERTEX;
1236 }
1237
1246 return facet_corners_.adjacent_facet(corner(f,le));
1247 }
1248
1257 for(index_t le=0; le<nb_vertices(f); ++le) {
1258 if(adjacent(f,le) == f2) {
1259 return le;
1260 }
1261 }
1262 return NO_INDEX;
1263 }
1264
1273 facet_corners_.set_adjacent_facet(corner(f,le),f2);
1274 }
1275
1284 geo_debug_assert(f < nb());
1285 geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1286 return c + 1 == corners_end(f) ? corners_begin(f) : c + 1;
1287 }
1288
1297 geo_debug_assert(f < nb());
1298 geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1299 return c == corners_begin(f) ? corners_end(f) - 1 : c - 1;
1300 }
1301
1310 for(index_t c1 = corners_begin(f); c1 != corners_end(f); ++c1) {
1311 index_t c2 = next_corner_around_facet(f,c1);
1312 if(
1313 facet_corners_.vertex(c1) == v1 &&
1314 facet_corners_.vertex(c2) == v2
1315 ) {
1316 return c1 - corners_begin(f);
1317 }
1318 }
1319 return NO_INDEX;
1320 }
1321
1323 vector<index_t>& to_delete,
1324 bool remove_isolated_vertices=true
1325 ) override;
1326
1327 void permute_elements(vector<index_t>& permutation) override;
1328
1329 void clear(
1330 bool keep_attributes=true, bool keep_memory=false
1331 ) override;
1332
1341 index_t nb_facets, index_t nb_vertices_per_polygon
1342 ) {
1343 if(nb_vertices_per_polygon != 3) {
1344 is_not_simplicial();
1345 }
1346
1347 index_t first_facet = nb();
1348 index_t co = facet_corners_.nb();
1349 facet_corners_.create_sub_elements(
1350 nb_facets*nb_vertices_per_polygon
1351 );
1352 index_t result = create_sub_elements(nb_facets);
1353
1354 if(!is_simplicial_) {
1355 for(index_t f=first_facet; f<=first_facet+nb_facets; ++f) {
1356 facet_ptr_[f] = co;
1357 co += nb_vertices_per_polygon;
1358 }
1359 geo_debug_assert(facet_ptr_.size() == nb()+1);
1360 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1361 }
1362 return result;
1363 }
1364
1370 void reserve(index_t nb_to_reserve) {
1371 facet_corners_.reserve_store(nb_to_reserve*3);
1372 this->reserve_store(nb_to_reserve);
1373 }
1374
1381 return create_facets(nb_triangles, 3);
1382 }
1383
1390 return create_facets(nb_quads, 4);
1391 }
1392
1399 geo_debug_assert(v1 != v2);
1400 geo_debug_assert(v2 != v3);
1401 geo_debug_assert(v3 != v1);
1402 facet_corners_.create_sub_element(v1);
1403 facet_corners_.create_sub_element(v2);
1404 facet_corners_.create_sub_element(v3);
1405 index_t result = create_sub_element();
1406 if(!is_simplicial_) {
1407 facet_ptr_[result+1] = facet_corners_.nb();
1408 geo_debug_assert(facet_ptr_.size() == nb()+1);
1409 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1410 }
1411 return result;
1412 }
1413
1420 is_not_simplicial();
1421 facet_corners_.create_sub_element(v1);
1422 facet_corners_.create_sub_element(v2);
1423 facet_corners_.create_sub_element(v3);
1424 facet_corners_.create_sub_element(v4);
1425 index_t result = create_sub_element();
1426 facet_ptr_[result+1] = facet_corners_.nb();
1427 geo_debug_assert(facet_ptr_.size() == nb()+1);
1428 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1429 return result;
1430 }
1431
1438 if(nb_vertices != 3) {
1439 is_not_simplicial();
1440 }
1441 for(index_t i=0; i<nb_vertices; ++i) {
1442 facet_corners_.create_sub_element(NO_VERTEX);
1443 }
1444 index_t result = create_sub_element();
1445 if(!is_simplicial_) {
1446 facet_ptr_[result+1] = facet_corners_.nb();
1447 geo_debug_assert(facet_ptr_.size() == nb()+1);
1448 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1449 }
1450 return result;
1451 }
1452
1459 index_t create_polygon(index_t nb_vertices, const index_t* vertices) {
1460 if(nb_vertices != 3) {
1461 is_not_simplicial();
1462 }
1463 for(index_t i=0; i<nb_vertices; ++i) {
1464 facet_corners_.create_sub_element(vertices[i]);
1465 }
1466 index_t result = create_sub_element();
1467 if(!is_simplicial_) {
1468 facet_ptr_[result+1] = facet_corners_.nb();
1469 geo_debug_assert(facet_ptr_.size() == nb()+1);
1470 geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1471 }
1472 return result;
1473 }
1474
1482 return create_polygon(vertices.size(), vertices.data());
1483 }
1484
1489 void connect();
1490
1497 void connect(index_t facets_begin, index_t facets_end);
1498
1504
1510 void flip(index_t f);
1511
1517
1530 coord_index_t dim,
1531 vector<double>& vertices,
1532 vector<index_t>& triangles,
1533 bool steal_args
1534 );
1535
1536 /*
1537 * \brief Copies a triangle mesh into this Mesh.
1538 * \details Facet adjacence are not computed.
1539 * Facet and corner attributes are zeroed.
1540 * \param[in] triangles facet to vertex links
1541 * \param[in] steal_args if set, vertices and triangles
1542 * are 'stolen' from the arguments
1543 * (using vector::swap).
1544 */
1545 void assign_triangle_mesh(
1546 vector<index_t>& triangles,
1547 bool steal_args
1548 );
1549
1550 void pop() override;
1551
1558 geo_debug_assert(f < nb());
1559 return index_range(
1560 index_as_iterator(corners_begin(f)),
1561 index_as_iterator(corners_end(f))
1562 );
1563 }
1564
1565#ifndef MESH_NO_SYNTAXIC_SUGAR
1566
1572 auto vertices(index_t f) const {
1573 geo_debug_assert(f < nb());
1574 return transform_range(
1575 corners(f), [this](index_t c)->index_t {
1576 return facet_corners_.vertex(c);
1577 }
1578 );
1579 }
1580
1588 auto adjacent(index_t f) const {
1589 geo_debug_assert(f < nb());
1590 return transform_range(
1591 corners(f), [this](index_t c)->index_t {
1592 return facet_corners_.adjacent_facet(c);
1593 }
1594 );
1595 }
1596
1603 template <index_t DIM=3> auto points(index_t f) const {
1604 geo_debug_assert(f < nb());
1605 typedef vecng<DIM,double> vecn;
1606 return transform_range_ref(
1607 corners(f), [this](index_t c)->const vecn& {
1608 index_t v = facet_corners_.vertex(c);
1609 return vertices_.point<DIM>(v);
1610 }
1611 );
1612 }
1613
1620 template <index_t DIM=3> auto points(index_t f) {
1621 geo_debug_assert(f < nb());
1622 typedef vecng<DIM,double> vecn;
1623 return transform_range_ref(
1624 corners(f), [this](index_t c)->vecn& {
1625 index_t v = facet_corners_.vertex(c);
1626 return vertices_.point<DIM>(v);
1627 }
1628 );
1629 }
1630
1637 auto triangles(index_t f) const {
1638 geo_debug_assert(f < nb());
1639 index_t v0 = facet_corners_.vertex(corners_begin(f));
1640 return transform_range(
1642 index_as_iterator(corners_begin(f)+1),
1643 index_as_iterator(corners_end(f)-1)
1644 ),
1645 [this,v0](index_t c)->std::tuple<index_t, index_t, index_t> {
1646 return std::make_tuple(
1647 v0,
1648 facet_corners_.vertex(c),
1649 facet_corners_.vertex(c+1)
1650 );
1651 }
1652 );
1653 }
1654
1663 template <index_t DIM=3> auto triangle_points(index_t f) const {
1664 geo_debug_assert(f < nb());
1665 typedef vecng<DIM,double> vecn;
1666 return transform_range(
1667 triangles(f),
1668 [this](std::tuple<index_t, index_t, index_t> T)
1669 ->std::tuple<const vecn&, const vecn&, const vecn&> {
1670 return std::tuple<const vecn&, const vecn&, const vecn&>(
1671 vertices_.point<DIM>(std::get<0>(T)),
1672 vertices_.point<DIM>(std::get<1>(T)),
1673 vertices_.point<DIM>(std::get<2>(T))
1674 );
1675 }
1676 );
1677 }
1678
1687 template <index_t DIM=3> auto triangle_points(index_t f) {
1688 geo_debug_assert(f < nb());
1689 typedef vecng<DIM,double> vecn;
1690 return transform_range(
1691 triangles(f),
1692 [this](std::tuple<index_t, index_t, index_t> T)
1693 ->std::tuple<vecn&, vecn&, vecn&> {
1694 return std::tuple<vecn&, vecn&, vecn&>(
1695 vertices_.point(std::get<0>(T)),
1696 vertices_.point(std::get<1>(T)),
1697 vertices_.point(std::get<2>(T))
1698 );
1699 }
1700 );
1701 }
1702
1703#endif
1704
1705 protected:
1706
1711 if(!is_simplicial_) {
1712 is_simplicial_ = true;
1713 facet_ptr_.resize(1);
1714 facet_ptr_[0] = 0;
1715 }
1716 }
1717
1725 if(is_simplicial_) {
1726 is_simplicial_ = false;
1727 facet_ptr_.resize(nb()+1);
1728 for(index_t f=0; f<facet_ptr_.size(); ++f) {
1729 facet_ptr_[f] = 3*f;
1730 }
1731 }
1732 }
1733
1734 protected:
1735 MeshVertices& vertices_;
1736 MeshFacetCornersStore& facet_corners_;
1737 friend class Mesh;
1738 friend class GeogramIOHandler;
1739 friend void GEOGRAM_API tessellate_facets(
1740 Mesh& M, index_t max_nb_vertices
1741 );
1742 };
1743
1744 /*************************************************************************/
1745
1746 enum MeshCellType {
1747 MESH_TET = 0,
1748 MESH_HEX = 1,
1749 MESH_PRISM = 2,
1750 MESH_PYRAMID = 3,
1751 MESH_CONNECTOR = 4,
1752 MESH_NB_CELL_TYPES = 5
1753 };
1754
1789
1790
1797 namespace MeshCellDescriptors {
1801 GEOGRAM_API extern CellDescriptor*
1802 cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES];
1803
1804 GEOGRAM_API extern CellDescriptor tet_descriptor;
1805 GEOGRAM_API extern CellDescriptor hex_descriptor;
1806 GEOGRAM_API extern CellDescriptor prism_descriptor;
1807 GEOGRAM_API extern CellDescriptor pyramid_descriptor;
1808 GEOGRAM_API extern CellDescriptor connector_descriptor;
1809 }
1810
1815 class GEOGRAM_API MeshCellsStore : public MeshSubElementsStore {
1816 public:
1817 MeshCellsStore(Mesh& mesh);
1818
1826 bool are_simplices() const {
1827 return is_simplicial_;
1828 }
1829
1836 MeshCellType type(index_t c) const {
1837 geo_debug_assert(c < nb());
1838 return is_simplicial_ ? MESH_TET : MeshCellType(cell_type_[c]);
1839 }
1840
1850
1861 MeshCellType t
1862 );
1863
1870 geo_debug_assert(c < nb());
1871 return descriptor(c).nb_vertices;
1872 }
1873
1881 geo_debug_assert(c < nb());
1882 return is_simplicial_ ? 4*c : cell_ptr_[c];
1883 }
1884
1892 geo_debug_assert(c < nb());
1893 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_corners(c);
1894 }
1895
1903 geo_debug_assert(c < nb());
1904 // There seems to be a linkage problem under MSVC for the
1905 // following assertion check...
1906#ifndef GEO_OS_WINDOWS
1907 geo_debug_assert(lv < nb_corners(c));
1908#endif
1909 return corners_begin(c) + lv;
1910 }
1911
1918 geo_debug_assert(c < nb());
1919 return descriptor(c).nb_facets;
1920 }
1921
1929 geo_debug_assert(c < nb());
1930 return is_simplicial_ ? 4*c : cell_ptr_[c];
1931 }
1932
1940 geo_debug_assert(c < nb());
1941 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_facets(c);
1942 }
1943
1951 geo_debug_assert(c < nb());
1952 geo_debug_assert(lf < nb_facets(c));
1953 return facets_begin(c) + lf;
1954 }
1955
1962 return descriptor(c).nb_edges;
1963 }
1964
1972 geo_debug_assert(!is_simplicial_);
1973 return &cell_ptr_[c];
1974 }
1975
1982 const index_t* cell_ptr_ptr(index_t c) const {
1983 geo_debug_assert(!is_simplicial_);
1984 return &cell_ptr_[c];
1985 }
1986
1994 geo_debug_assert(!is_simplicial_);
1995 return &cell_type_[c];
1996 }
1997
2005 geo_debug_assert(!is_simplicial_);
2006 return &cell_type_[c];
2007 }
2008
2009
2010 protected:
2012 bool keep_attributes, bool keep_memory = false
2013 ) override;
2014
2015 void resize_store(index_t new_size) override;
2016
2017 index_t create_sub_element(MeshCellType type) {
2018 if(!is_simplicial_) {
2019 cell_ptr_.push_back(NO_CORNER);
2020 cell_type_.push_back(Numeric::uint8(type));
2021 }
2022 return MeshSubElementsStore::create_sub_element();
2023 }
2024
2025 index_t create_sub_elements(index_t nb, MeshCellType type) {
2026 if(!is_simplicial_) {
2027 for(index_t i=0; i<nb; ++i) {
2028 cell_ptr_.push_back(NO_CORNER);
2029 cell_type_.push_back(Numeric::uint8(type));
2030 }
2031 }
2032 return MeshSubElementsStore::create_sub_elements(nb);
2033 }
2034
2035 void copy(
2036 const MeshCellsStore& rhs, bool copy_attributes=true
2037 ) {
2038 MeshSubElementsStore::copy(rhs, copy_attributes);
2039 is_simplicial_ = rhs.is_simplicial_;
2040 cell_type_ = rhs.cell_type_;
2041 cell_ptr_ = rhs.cell_ptr_;
2042 }
2043
2044 protected:
2045 bool is_simplicial_;
2046 vector<Numeric::uint8> cell_type_;
2047 vector<index_t> cell_ptr_;
2048
2049 protected:
2050 friend class Mesh;
2051 friend class GeogramIOHandler;
2052 };
2053
2054 /*************************************************************************/
2055
2060 class GEOGRAM_API MeshCellCornersStore : public MeshSubElementsStore {
2061 public:
2063
2070 geo_assert(c < nb());
2071 return corner_vertex_[c];
2072 }
2073
2080 geo_debug_assert(c < nb());
2081 geo_debug_assert(v < vertices_.nb());
2082 corner_vertex_[c] = v;
2083 }
2084
2093 geo_debug_assert(c < nb());
2094 return &(corner_vertex_[c]);
2095 }
2096
2105 geo_debug_assert(c < nb());
2106 return &(corner_vertex_[c]);
2107 }
2108
2115 template <index_t DIM=3> vecng<DIM,double>& point(index_t c) {
2116 geo_debug_assert(c < nb());
2117 return vertices_.point<DIM>(vertex(c));
2118 }
2119
2127 template <index_t DIM=3> const vecng<DIM,double>& point(
2128 index_t c
2129 ) const {
2130 geo_debug_assert(c < nb());
2131 return vertices_.point(vertex(c));
2132 }
2133
2134 protected:
2136 bool keep_attributes, bool keep_memory = false
2137 ) override;
2138
2139 void resize_store(index_t new_size) override;
2140
2141 index_t create_sub_element(index_t v) {
2142 corner_vertex_.push_back(v);
2143 return MeshSubElementsStore::create_sub_element();
2144 }
2145
2146 index_t create_sub_elements(index_t nb) {
2147 for(index_t i=0; i<nb; ++i) {
2148 corner_vertex_.push_back(NO_VERTEX);
2149 }
2150 return MeshSubElementsStore::create_sub_elements(nb);
2151 }
2152
2153 void copy(
2154 const MeshCellCornersStore& rhs, bool copy_attributes=true
2155 ) {
2156 MeshSubElementsStore::copy(rhs, copy_attributes);
2157 corner_vertex_ = rhs.corner_vertex_;
2158 }
2159
2160 protected:
2161 MeshVertices& vertices_;
2162 vector<index_t> corner_vertex_;
2163
2164 friend class MeshCells;
2165 friend class Mesh;
2166 friend class GeogramIOHandler;
2167 };
2168
2169 /*************************************************************************/
2170
2175 class GEOGRAM_API MeshCellFacetsStore : public MeshSubElementsStore {
2176 public:
2182
2190 geo_assert(f < nb());
2191 return adjacent_cell_[f];
2192 }
2193
2202 geo_debug_assert(f < nb());
2203 geo_debug_assert(c == NO_CELL || c < cells_.nb());
2204 adjacent_cell_[f] = c;
2205 }
2206
2214 geo_assert(f < nb());
2215 return &adjacent_cell_[f];
2216 }
2217
2225 geo_assert(f < nb());
2226 return &adjacent_cell_[f];
2227 }
2228
2229 protected:
2231 bool keep_attributes, bool keep_memory = false
2232 ) override;
2233
2234 void resize_store(index_t new_size) override;
2235
2236 index_t create_sub_element(index_t c = NO_CELL) {
2237 adjacent_cell_.push_back(c);
2238 return MeshSubElementsStore::create_sub_element();
2239 }
2240
2241 index_t create_sub_elements(index_t nb) {
2242 for(index_t i=0; i<nb; ++i) {
2243 adjacent_cell_.push_back(NO_CELL);
2244 }
2245 return MeshSubElementsStore::create_sub_elements(nb);
2246 }
2247
2248 void copy(
2249 const MeshCellFacetsStore& rhs, bool copy_attributes=true
2250 ) {
2251 MeshSubElementsStore::copy(rhs, copy_attributes);
2252 adjacent_cell_ = rhs.adjacent_cell_;
2253 }
2254
2255 protected:
2256 MeshVertices& vertices_;
2257 MeshCellsStore& cells_;
2258 vector<index_t> adjacent_cell_;
2259
2260 friend class MeshCells;
2261 friend class Mesh;
2262 friend class GeogramIOHandler;
2263 };
2264
2265 /*************************************************************************/
2266
2271 class GEOGRAM_API MeshCells : public MeshCellsStore, public MeshElements {
2272 public:
2278
2285 return nb_corners(c);
2286 }
2287
2295 return cell_corners_.vertex(corner(c,lv));
2296 }
2297
2305 cell_corners_.set_vertex(corner(c,lv),v);
2306 }
2307
2316 template <index_t DIM=3> const vecng<DIM,double>& point(
2317 index_t c, index_t lv
2318 ) const {
2319 return vertices_.point<DIM>(vertex(c,lv));
2320 }
2321
2330 template <index_t DIM=3> vecng<DIM,double>& point(
2331 index_t c, index_t lv
2332 ) {
2333 return vertices_.point<DIM>(vertex(c,lv));
2334 }
2335
2344 return cell_facets_.adjacent_cell(facet(c,lf));
2345 }
2346
2355 cell_facets_.set_adjacent_cell(facet(c,lf),c2);
2356 }
2357
2365 geo_debug_assert(lf < nb_facets(c));
2366 return descriptor(c).nb_vertices_in_facet[lf];
2367 }
2368
2378 geo_debug_assert(lv < facet_nb_vertices(c, lf));
2379 return cell_corners_.vertex(
2380 corner(c, descriptor(c).facet_vertex[lf][lv])
2381 );
2382 }
2392 geo_debug_assert(lc < facet_nb_vertices(c, lf));
2393 return corner(c, descriptor(c).facet_vertex[lf][lc]);
2394 }
2395
2405 geo_debug_assert(le < nb_edges(c));
2406 geo_debug_assert(lv < 2);
2407 return cell_corners_.vertex(
2408 corner(c,descriptor(c).edge_vertex[le][lv])
2409 );
2410 }
2411
2423 geo_debug_assert(le < nb_edges(c));
2424 geo_debug_assert(lf < 2);
2425 return descriptor(c).edge_adjacent_facet[le][lf];
2426 }
2427
2434 geo_debug_assert(c < nb());
2435 return index_range(
2436 index_as_iterator(corners_begin(c)),
2437 index_as_iterator(corners_end(c))
2438 );
2439 }
2440
2447 geo_debug_assert(c < nb());
2448 return index_range(
2449 index_as_iterator(facets_begin(c)),
2450 index_as_iterator(facets_end(c))
2451 );
2452 }
2453
2454#ifndef MESH_NO_SYNTAXIC_SUGAR
2455
2462 template <index_t DIM=3> auto points(index_t cell) const {
2463 geo_debug_assert(cell < nb());
2464 typedef vecng<DIM,double> vecn;
2465 return transform_range_ref(
2466 corners(cell), [this](index_t c)->const vecn& {
2467 index_t v = cell_corners_.vertex(c);
2468 return vertices_.point<DIM>(v);
2469 }
2470 );
2471 }
2472
2479 template <index_t DIM=3> auto points(index_t cell) {
2480 geo_debug_assert(cell < nb());
2481 typedef vecng<DIM,double> vecn;
2482 return transform_range_ref(
2483 corners(cell), [this](index_t c)->vecn& {
2484 index_t v = cell_corners_.vertex(c);
2485 return vertices_.point<DIM>(v);
2486 }
2487 );
2488 }
2489
2497 auto adjacent(index_t c) const {
2498 geo_debug_assert(c < nb());
2499 return transform_range(
2500 facets(c), [this](index_t f)->index_t {
2501 return cell_facets_.adjacent_cell(f);
2502 }
2503 );
2504 }
2505
2506#endif
2507
2508 void clear(
2509 bool keep_attributes=true, bool keep_memory=false
2510 ) override;
2511
2513 vector<index_t>& to_delete,
2514 bool remove_isolated_vertices=true
2515 ) override;
2516
2517 void permute_elements(vector<index_t>& permutation) override;
2518
2527 index_t create_cells(index_t nb_cells, MeshCellType type) {
2528
2529 if(nb_cells == 0) {
2530 return NO_CELL;
2531 }
2532
2533
2534 if(type != MESH_TET) {
2535 is_not_simplicial();
2536 }
2537
2538 const CellDescriptor& desc = cell_type_to_cell_descriptor(type);
2539
2540 // Note: there is padding, the same number of corners and
2541 // faces is created for each cell, so that a single cell
2542 // pointer is used for both.
2543
2544 index_t cell_size = std::max(desc.nb_vertices, desc.nb_facets);
2545 index_t first_cell = nb();
2546 index_t co = cell_corners_.nb();
2547
2548 cell_corners_.create_sub_elements(
2549 nb_cells*cell_size
2550 );
2551
2552 cell_facets_.create_sub_elements(
2553 nb_cells*cell_size
2554 );
2555
2556 index_t result = create_sub_elements(nb_cells, type);
2557
2558 if(!is_simplicial_) {
2559 for(index_t c=first_cell; c<=first_cell+nb_cells; ++c) {
2560 cell_ptr_[c] = co;
2561 co += cell_size;
2562 }
2563
2564 geo_debug_assert(cell_ptr_.size() == nb()+1);
2565 geo_debug_assert(cell_ptr_[nb()] == cell_corners_.nb());
2566 geo_debug_assert(cell_ptr_[nb()] == cell_facets_.nb());
2567 }
2568
2569 return result;
2570 }
2571
2578 return create_cells(nb_tets, MESH_TET);
2579 }
2580
2587 return create_cells(nb_hexes, MESH_HEX);
2588 }
2589
2596 return create_cells(nb_prisms, MESH_PRISM);
2597 }
2598
2605 return create_cells(nb_pyramids, MESH_PYRAMID);
2606 }
2607
2617 index_t v1, index_t v2, index_t v3, index_t v4,
2618 index_t adj1 = NO_CELL,
2619 index_t adj2 = NO_CELL,
2620 index_t adj3 = NO_CELL,
2621 index_t adj4 = NO_CELL
2622 ) {
2623 cell_corners_.create_sub_element(v1);
2624 cell_corners_.create_sub_element(v2);
2625 cell_corners_.create_sub_element(v3);
2626 cell_corners_.create_sub_element(v4);
2627 cell_facets_.create_sub_element(adj1);
2628 cell_facets_.create_sub_element(adj2);
2629 cell_facets_.create_sub_element(adj3);
2630 cell_facets_.create_sub_element(adj4);
2631 index_t result = create_sub_element(MESH_TET);
2632 if(!is_simplicial_) {
2633 cell_ptr_[nb()] = cell_corners_.nb();
2634 }
2635 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2636 return result;
2637 }
2638
2649 index_t v1, index_t v2, index_t v3, index_t v4,
2650 index_t v5, index_t v6, index_t v7, index_t v8,
2651 index_t adj1 = NO_CELL,
2652 index_t adj2 = NO_CELL,
2653 index_t adj3 = NO_CELL,
2654 index_t adj4 = NO_CELL,
2655 index_t adj5 = NO_CELL,
2656 index_t adj6 = NO_CELL
2657 ) {
2658 is_not_simplicial();
2659 cell_corners_.create_sub_element(v1);
2660 cell_corners_.create_sub_element(v2);
2661 cell_corners_.create_sub_element(v3);
2662 cell_corners_.create_sub_element(v4);
2663 cell_corners_.create_sub_element(v5);
2664 cell_corners_.create_sub_element(v6);
2665 cell_corners_.create_sub_element(v7);
2666 cell_corners_.create_sub_element(v8);
2667 cell_facets_.create_sub_element(adj1);
2668 cell_facets_.create_sub_element(adj2);
2669 cell_facets_.create_sub_element(adj3);
2670 cell_facets_.create_sub_element(adj4);
2671 cell_facets_.create_sub_element(adj5);
2672 cell_facets_.create_sub_element(adj6);
2673 cell_facets_.create_sub_element(NO_CELL); // padding
2674 cell_facets_.create_sub_element(NO_CELL); // padding
2675 index_t result = create_sub_element(MESH_HEX);
2676 cell_ptr_[nb()] = cell_corners_.nb();
2677 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2678 return result;
2679 }
2680
2691 index_t v1, index_t v2,
2692 index_t v3, index_t v4,
2693 index_t v5, index_t v6,
2694 index_t adj1 = NO_CELL,
2695 index_t adj2 = NO_CELL,
2696 index_t adj3 = NO_CELL,
2697 index_t adj4 = NO_CELL,
2698 index_t adj5 = NO_CELL
2699 ) {
2700 is_not_simplicial();
2701 cell_corners_.create_sub_element(v1);
2702 cell_corners_.create_sub_element(v2);
2703 cell_corners_.create_sub_element(v3);
2704 cell_corners_.create_sub_element(v4);
2705 cell_corners_.create_sub_element(v5);
2706 cell_corners_.create_sub_element(v6);
2707 cell_facets_.create_sub_element(adj1);
2708 cell_facets_.create_sub_element(adj2);
2709 cell_facets_.create_sub_element(adj3);
2710 cell_facets_.create_sub_element(adj4);
2711 cell_facets_.create_sub_element(adj5);
2712 cell_facets_.create_sub_element(NO_CELL); // padding
2713 index_t result = create_sub_element(MESH_PRISM);
2714 cell_ptr_[nb()] = cell_corners_.nb();
2715 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2716 return result;
2717 }
2718
2729 index_t v1, index_t v2, index_t v3, index_t v4, index_t v5,
2730 index_t adj1 = NO_CELL,
2731 index_t adj2 = NO_CELL,
2732 index_t adj3 = NO_CELL,
2733 index_t adj4 = NO_CELL,
2734 index_t adj5 = NO_CELL
2735 ) {
2736 is_not_simplicial();
2737 cell_corners_.create_sub_element(v1);
2738 cell_corners_.create_sub_element(v2);
2739 cell_corners_.create_sub_element(v3);
2740 cell_corners_.create_sub_element(v4);
2741 cell_corners_.create_sub_element(v5);
2742 cell_facets_.create_sub_element(adj1);
2743 cell_facets_.create_sub_element(adj2);
2744 cell_facets_.create_sub_element(adj3);
2745 cell_facets_.create_sub_element(adj4);
2746 cell_facets_.create_sub_element(adj5);
2747 index_t result = create_sub_element(MESH_PYRAMID);
2748 cell_ptr_[nb()] = cell_corners_.nb();
2749 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2750 return result;
2751 }
2752
2766 index_t v1, index_t v2, index_t v3, index_t v4,
2767 index_t adj1 = NO_CELL,
2768 index_t adj2 = NO_CELL,
2769 index_t adj3 = NO_CELL
2770 ) {
2771 is_not_simplicial();
2772 cell_corners_.create_sub_element(v1);
2773 cell_corners_.create_sub_element(v2);
2774 cell_corners_.create_sub_element(v3);
2775 cell_corners_.create_sub_element(v4);
2776 cell_facets_.create_sub_element(adj1);
2777 cell_facets_.create_sub_element(adj2);
2778 cell_facets_.create_sub_element(adj3);
2779 cell_facets_.create_sub_element(NO_CELL); // padding
2780 index_t result = create_sub_element(MESH_CONNECTOR);
2781 cell_ptr_[nb()] = cell_corners_.nb();
2782 geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2783 return result;
2784 }
2785
2797 bool remove_trivial_slivers = true, bool verbose_if_OK=false
2798 );
2799
2805
2814
2826 coord_index_t dim,
2827 vector<double>& vertices,
2828 vector<index_t>& tets,
2829 bool steal_args
2830 );
2831
2841 vector<index_t>& tets,
2842 bool steal_args
2843 );
2844
2845 void pop() override;
2846
2847 index_t tet_adjacent(index_t t, index_t lf) const {
2848 geo_debug_assert(is_simplicial_);
2849 geo_debug_assert(t < nb());
2850 geo_debug_assert(lf < 4);
2851 return cell_facets_.adjacent_cell_[4*t+lf];
2852 }
2853
2854 index_t find_tet_adjacent(index_t t, index_t t2) const {
2855 geo_debug_assert(is_simplicial_);
2856 geo_debug_assert(t < nb());
2857 geo_debug_assert(t2 < nb());
2858 for(index_t lf=0; lf<4; ++lf) {
2859 if(cell_facets_.adjacent_cell_[4*t+lf] == t2) {
2860 return lf;
2861 }
2862 }
2863 return NO_FACET;
2864 }
2865
2866 index_t tet_vertex(index_t t, index_t lv) const {
2867 geo_debug_assert(is_simplicial_);
2868 geo_debug_assert(t < nb());
2869 geo_debug_assert(lv < 4);
2870 return cell_corners_.corner_vertex_[4*t+lv];
2871 }
2872
2873 index_t find_tet_vertex(index_t t, index_t v) const {
2874 geo_debug_assert(is_simplicial_);
2875 geo_debug_assert(t < nb());
2876 geo_debug_assert(v < vertices_.nb());
2877 for(index_t lv=0; lv<4; ++lv) {
2878 if(cell_corners_.corner_vertex_[4*t+lv] == v) {
2879 return lv;
2880 }
2881 }
2882 return NO_VERTEX;
2883 }
2884
2896 index_t t, index_t lf, index_t lv
2897 ) const {
2898 geo_debug_assert(is_simplicial_);
2899 geo_debug_assert(t < nb());
2900 geo_debug_assert(lf < 4);
2901 geo_debug_assert(lv < 3);
2902 return cell_corners_.vertex(
2903 4 * t + local_tet_facet_vertex_index(lf,lv)
2904 );
2905 }
2906
2921 index_t t, index_t v1, index_t v2, index_t v3
2922 ) const {
2923 geo_debug_assert(is_simplicial_);
2924 for(index_t lf = 0; lf < 4; ++lf) {
2925 index_t w1 = tet_facet_vertex(t, lf, 0);
2926 index_t w2 = tet_facet_vertex(t, lf, 1);
2927 index_t w3 = tet_facet_vertex(t, lf, 2);
2928 if(
2929 (v1 == w1 && v2 == w2 && v3 == w3) ||
2930 (v1 == w2 && v2 == w3 && v3 == w1) ||
2931 (v1 == w3 && v2 == w1 && v3 == w2)
2932 ) {
2933 return lf;
2934 }
2935 }
2936 return NO_FACET;
2937 }
2938
2948 geo_debug_assert(lf < 4);
2949 geo_debug_assert(lv < 3);
2950 return MeshCellDescriptors::tet_descriptor.facet_vertex[lf][lv];
2951 }
2952
2953 protected:
2954
2962 if(is_simplicial_) {
2963 is_simplicial_ = false;
2964 cell_ptr_.resize(nb()+1);
2965 cell_type_.assign(nb(), MESH_TET);
2966 for(index_t c=0; c<cell_ptr_.size(); ++c) {
2967 cell_ptr_[c] = 4*c;
2968 }
2969 }
2970 }
2971
2984 index_t c1, index_t f1, index_t c2, index_t f2
2985 ) const;
2986
2996 geo_debug_assert(c < nb());
2997 geo_debug_assert(v < vertices_.nb());
2998 for(index_t lv=0; lv<nb_vertices(c); ++lv) {
2999 if(vertex(c,lv) == v) {
3000 return lv;
3001 }
3002 }
3003 return NO_VERTEX;
3004 }
3005
3018 index_t c1, index_t c2, index_t f2
3019 ) const {
3020 for(index_t f1=0; f1<nb_facets(c1); ++f1) {
3021 if(facets_match(c1,f1,c2,f2)) {
3022 return f1;
3023 }
3024 }
3025 return NO_FACET;
3026 }
3027
3041 index_t c1, index_t lf1,
3042 index_t c2, index_t lf2
3043 ) const;
3044
3045
3060 index_t c1, index_t f1,
3061 index_t c2, index_t f2,
3062 index_t& e1, index_t& e2
3063 ) const;
3064
3084 index_t c1, index_t lf1,
3085 const std::vector< std::pair<index_t, index_t> >& matches
3086 );
3087
3093
3094 protected:
3095 MeshVertices& vertices_;
3096 MeshCellCornersStore& cell_corners_;
3097 MeshCellFacetsStore& cell_facets_;
3098 friend class Mesh;
3099 friend class GeogramIOHandler;
3100 };
3101
3102 /*************************************************************************/
3103
3112 MESH_NONE = 0,
3113 MESH_VERTICES = 1,
3114 MESH_FACETS = 2,
3115 MESH_EDGES = 4,
3116 MESH_CELLS = 8,
3117 MESH_ALL_ELEMENTS = 15,
3118 MESH_FACET_CORNERS = 16,
3119 MESH_CELL_CORNERS = 32,
3120 MESH_CELL_FACETS = 64,
3121 MESH_ALL_SUBELEMENTS = 65
3122 };
3123
3124 /*************************************************************************/
3125
3132 class GEOGRAM_API Mesh {
3133 public:
3134 MeshVertices vertices;
3135 MeshEdges edges;
3136 MeshFacets facets;
3137 MeshFacetCornersStore facet_corners;
3138 MeshCells cells;
3139 MeshCellCornersStore cell_corners;
3140 MeshCellFacetsStore cell_facets;
3141
3149 Mesh(index_t dimension=3, bool single_precision=false);
3150
3154 virtual ~Mesh();
3155
3166 void clear(bool keep_attributes=true, bool keep_memory=false);
3167
3171 void show_stats(const std::string& tag = "Mesh") const;
3172
3173
3182
3183
3196 void copy(
3197 const Mesh& rhs,
3198 bool copy_attributes=true,
3199 MeshElementsFlags what=MESH_ALL_ELEMENTS
3200 );
3201
3202
3207 std::string get_attributes() const;
3208
3215 std::string get_scalar_attributes() const;
3216
3223 std::string get_vector_attributes(index_t max_dim = 0) const;
3224
3230
3238
3246
3247
3255
3264 ) const;
3265
3273
3282 const std::string& name
3283 );
3284
3300 const std::string& full_attribute_name,
3301 MeshElementsFlags& where,
3302 std::string& attribute_name,
3303 index_t& component
3304 );
3305
3306 protected:
3315 const std::string& tag, const std::string& subelement_name,
3316 const MeshSubElementsStore& subelements
3317 ) const;
3318
3326 Mesh(const Mesh& rhs) = delete;
3327
3335 const Mesh& operator=(const Mesh& rhs) = delete;
3336 };
3337
3338 /*************************************************************************/
3339}
3340
3341#endif
#define geo_assert(x)
Verifies that a condition is met.
Definition assert.h:149
#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.
Managers a set of attributes attached to an object.
Definition attributes.h:917
index_t size() const
Gets the size.
Definition attributes.h:952
Stores the cell corners of a mesh (low-level store)
Definition mesh.h:2060
void set_vertex(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition mesh.h:2079
index_t vertex(index_t c) const
Gets the vertex that a corner is incident to.
Definition mesh.h:2069
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:2092
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:2115
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:2104
const vecng< DIM, double > & point(index_t c) const
Gets the point associated with a corner.
Definition mesh.h:2127
Stores the cell facets of a mesh (low-level store)
Definition mesh.h:2175
index_t adjacent_cell(index_t f) const
Gets a cell adjacent to a facet.
Definition mesh.h:2189
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:2224
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:2213
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:2201
Stores the cells of a mesh (low-level store)
Definition mesh.h:1815
index_t facet(index_t c, index_t lf) const
Gets a facet of a cell by local facet index.
Definition mesh.h:1950
bool are_simplices() const
Tests whether all the cells are tetrahedra.
Definition mesh.h:1826
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:1902
index_t nb_facets(index_t c) const
Gets the number of facets of a cell.
Definition mesh.h:1917
Numeric::uint8 * cell_type_ptr(index_t c)
Gets a pointer to a cell type by cell index.
Definition mesh.h:1993
index_t corners_end(index_t c) const
Gets the upper limit for iterating over the corners of a cell.
Definition mesh.h:1891
MeshCellType type(index_t c) const
Gets the type of a cell.
Definition mesh.h:1836
index_t facets_end(index_t c) const
Gets the upper limit for iterating over the facets of a cell.
Definition mesh.h:1939
const index_t * cell_ptr_ptr(index_t c) const
Gets a pointer to a cell pointer index by cell index.
Definition mesh.h:1982
const Numeric::uint8 * cell_type_ptr(index_t c) const
Gets a pointer to a cell type by cell index.
Definition mesh.h:2004
index_t nb_corners(index_t c) const
Gets the number of corners of a cell.
Definition mesh.h:1869
index_t corners_begin(index_t c) const
Gets the first element for iterating over the corners of a cell.
Definition mesh.h:1880
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:1971
index_t nb_edges(index_t c) const
Gets the number of edges in a cell.
Definition mesh.h:1961
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:1928
The cells of a mesh.
Definition mesh.h:2271
index_t create_cells(index_t nb_cells, MeshCellType type)
Creates a contiguous chunk of cells of the same type.
Definition mesh.h:2527
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:2304
index_t create_pyramids(index_t nb_pyramids)
Creates a contiguous chunk of pyramids.
Definition mesh.h:2604
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:2343
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:2330
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:2765
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:2895
index_range corners(index_t c) const
Gets the corners of a cell.
Definition mesh.h:2433
auto points(index_t cell)
Gets the points associated with the vertices of a cell.
Definition mesh.h:2479
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:2404
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:2947
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:2690
index_t nb_vertices(index_t c) const
Gets the number of vertices of a cell.
Definition mesh.h:2284
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:2377
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:2728
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:2920
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:2961
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:2391
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:2995
index_t create_hexes(index_t nb_hexes)
Creates a contiguous chunk of hexahedra.
Definition mesh.h:2586
index_t create_tets(index_t nb_tets)
Creates a contiguous chunk of tetrahedra.
Definition mesh.h:2577
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:2422
auto adjacent(index_t c) const
Gets the cells adjacent to a given cell.
Definition mesh.h:2497
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:2354
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:2595
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:2616
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:2648
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:2364
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:2446
auto points(index_t cell) const
Gets the points associated with the vertices of a cell.
Definition mesh.h:2462
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:3017
const vecng< DIM, double > & point(index_t c, index_t lv) const
Gets a point by cell and local vertex index.
Definition mesh.h:2316
index_t vertex(index_t c, index_t lv) const
Gets a vertex of a cell by local vertex index.
Definition mesh.h:2294
The edges of a mesh.
Definition mesh.h:690
index_t vertex(index_t e, index_t lv) const
Gets the index of an edge vertex.
Definition mesh.h:701
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:737
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:764
index_t create_edge()
Creates a new edge.
Definition mesh.h:746
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:755
index_t * vertex_index_ptr(index_t c)
Gets a pointer to a vertex index by corner index.
Definition mesh.h:726
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:713
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:950
index_t * vertex_index_ptr(index_t c)
Gets a pointer to the vertex that a corner is incident to.
Definition mesh.h:1046
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:982
vecng< DIM, double > & point(index_t c)
Gets the point associated with a corner.
Definition mesh.h:1069
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:995
index_t adjacent_facet(index_t c) const
Gets the facet that a corner is adjacent to.
Definition mesh.h:970
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:1058
void set_vertex_no_check(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition mesh.h:1022
index_t vertex(index_t c) const
Gets the vertex that a corner is incident to.
Definition mesh.h:959
const vecng< DIM, double > & point(index_t c) const
Gets the point associated with a corner.
Definition mesh.h:1081
void set_adjacent_facet(index_t c, index_t f)
Sets the facet that a corner is adjacent to.
Definition mesh.h:1033
void set_vertex(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition mesh.h:1006
Stores the facets of a mesh (low-level store)
Definition mesh.h:823
index_t corner(index_t f, index_t lv) const
Gets a corner by facet and local vertex index.
Definition mesh.h:866
index_t corners_end(index_t f) const
Gets the upper limit for iterating over the corners of a facet.
Definition mesh.h:844
index_t nb_corners(index_t f) const
Gets the number of corners in a facet.
Definition mesh.h:854
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:901
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:889
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:879
index_t corners_begin(index_t f) const
Gets the first element for iterating over the corners of a facet.
Definition mesh.h:833
The facets of a mesh.
Definition mesh.h:1136
index_t create_triangle(index_t v1, index_t v2, index_t v3)
Creates a triangle.
Definition mesh.h:1398
auto triangle_points(index_t f)
Decomposes a facet into triangles.
Definition mesh.h:1687
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:1419
auto triangles(index_t f) const
Decomposes a facet into triangles.
Definition mesh.h:1637
index_t create_polygon(const vector< index_t > &vertices)
Creates a polygonal facet.
Definition mesh.h:1481
void is_not_simplicial()
Indicates that the stored elements are no longer only triangles.
Definition mesh.h:1724
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:1162
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:1370
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:1151
void is_simplicial()
Indicates that the stored elements are only triangles.
Definition mesh.h:1710
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:1437
index_t create_polygon(index_t nb_vertices, const index_t *vertices)
Creates a polygonal facet.
Definition mesh.h:1459
void set_vertex(index_t f, index_t lv, index_t v)
Sets a vertex by facet and local vertex index.
Definition mesh.h:1202
auto vertices(index_t f) const
Gets the vertices of a facet.
Definition mesh.h:1572
index_t find_common_vertex(index_t f1, index_t f2) const
finds a common vertex shared by two facets
Definition mesh.h:1228
index_range corners(index_t f) const
Gets the corners of a facet.
Definition mesh.h:1557
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:1309
auto adjacent(index_t f) const
Gets the facets adjacent to a given facet.
Definition mesh.h:1588
index_t find_vertex(index_t f, index_t v) const
Gets the local index of a vertex in a facet.
Definition mesh.h:1213
vecng< DIM, double > & point(index_t f, index_t lv)
Gets a point by facet and local vertex index.
Definition mesh.h:1189
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:1256
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:1296
auto points(index_t f)
Gets the points associated with the vertices of a facet.
Definition mesh.h:1620
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:1389
index_t create_facets(index_t nb_facets, index_t nb_vertices_per_polygon)
Creates a contiguous chunk of facets.
Definition mesh.h:1340
const vecng< DIM, double > & point(index_t f, index_t lv) const
Gets a point by facet and local vertex index.
Definition mesh.h:1175
index_t adjacent(index_t f, index_t le) const
Gets an adjacent facet by facet and local edge index.
Definition mesh.h:1245
auto points(index_t f) const
Gets the points associated with the vertices of a facet.
Definition mesh.h:1603
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:1272
index_t create_triangles(index_t nb_triangles)
Creates a contiguous chunk of triangles.
Definition mesh.h:1380
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:1283
auto triangle_points(index_t f) const
Decomposes a facet into triangles.
Definition mesh.h:1663
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:590
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:606
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.
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
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:3132
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:3111
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.
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:70
T * data()
Gets modifiable vector data.
Definition vecg.h:161
Vector with aligned memory allocation.
Definition memory.h:660
T * data()
Gets a pointer to the array of elements.
Definition memory.h:806
index_t size() const
Gets the number of elements.
Definition memory.h:706
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:129
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:135
Global Vorpaline namespace.
Definition basic.h:55
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:329
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition numeric.h:363
C++-20 like helpers for manipulating ranges of integers.
Lookup tables that describe the combinatorics of each cell type.
Definition mesh.h:1760
index_t nb_vertices_in_facet[6]
Definition mesh.h:1768
index_t facet_vertex[6][4]
Definition mesh.h:1773
index_t nb_vertices
Definition mesh.h:1762
index_t nb_facets
Definition mesh.h:1765
index_t edge_adjacent_facet[12][2]
Definition mesh.h:1787
index_t nb_edges
Definition mesh.h:1777
index_t edge_vertex[12][2]
Definition mesh.h:1782