40#ifndef GEOGRAM_MESH_MESH
41#define GEOGRAM_MESH_MESH
46#include <geogram/basic/vector_attribute.h>
54#define MESH_NO_SYNTAXIC_SUGAR
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;
141 bool keep_attributes,
bool keep_memory =
false
159 resize_store(nb + nb_to_reserve);
170 if(nb_ + nb > attributes_.size()) {
173 new_capacity = std::max(
index_t(16),attributes_.size());
174 while(new_capacity < nb_ + nb) {
178 attributes_.reserve(new_capacity);
181 attributes_.resize(nb_);
192 if(attributes_.capacity() < nb_) {
194 std::max(
index_t(16),attributes_.capacity()*2);
195 attributes_.reserve(new_capacity);
197 attributes_.resize(nb_);
211 attributes_.resize(nb_);
225 bool copy_attributes =
true
228 if(copy_attributes) {
229 attributes_.copy(rhs.attributes_);
231 attributes_.clear(
false,
false);
232 attributes_.resize(rhs.attributes_.
size());
268 bool remove_isolated_vertices=
true
295 bool keep_attributes=
true,
bool keep_memory=
false
324 class MeshFacetCornersStore;
325 class MeshCellCornersStore;
354 return MeshSubElementsStore::create_sub_element();
369 coords < point_ptr(0) ||
370 coords >= point_ptr(0) + nb() * dimension()
372 index_t result = create_vertex();
373 for(
index_t c=0; c<dimension(); ++c) {
374 point_ptr(result)[c] = coords[c];
389 return create_vertex(p.
data());
398 return MeshSubElementsStore::create_sub_elements(nb);
402 bool keep_attributes=
true,
bool keep_memory=
false
431 return point_fp32_.is_bound();
442 return point_.is_bound();
452 point_fp32_.dimension() :
463 if(single_precision()) {
464 point_fp32_.redim(dim);
480 return &point_[v*point_.dimension()];
493 return &point_[v*point_.dimension()];
509 &point_[v*point_.dimension()]
527 &point_[v*point_.dimension()]
541 return &point_fp32_[v*point_fp32_.dimension()];
554 return &point_fp32_[v*point_fp32_.dimension()];
584#ifndef MESH_NO_SYNTAXIC_SUGAR
590 template <index_t DIM = 3>
auto points()
const {
594 [
this](
index_t v)->
const vecn& {
596 return *
reinterpret_cast<const vecn*
>(point_ptr(v));
606 template <index_t DIM = 3>
auto points() {
612 return *
reinterpret_cast<vecn*
>(point_ptr(v));
623 bool keep_attributes,
bool keep_memory =
false
628 void bind_point_attribute(
index_t dim,
bool single_precision=
false);
630 void copy(
const MeshVertices& rhs,
bool copy_attributes=
true) {
632 if(point_fp32_.is_bound()) {
633 point_fp32_.destroy();
635 if(point_.is_bound()) {
638 MeshSubElementsStore::copy(rhs, copy_attributes);
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
647 point_.bind_if_is_defined(attributes(),
"point");
648 if(!point_.is_bound()) {
649 point_.create_vector_attribute(
650 attributes(),
"point", dim
656 if(!copy_attributes) {
659 single_precision_point_ptr(0),
674 MeshFacetCornersStore& facet_corners_;
675 MeshCellCornersStore& cell_corners_;
676 Attribute<double> point_;
677 Attribute<float> point_fp32_;
680 friend class GeogramIOHandler;
704 return edge_vertex_[2*e+lv];
716 edge_vertex_[2*e+lv] = v;
728 return &(edge_vertex_[c]);
739 return &(edge_vertex_[c]);
747 return create_sub_element();
756 return create_sub_elements(nb);
765 index_t result = create_edge();
766 set_vertex(result,0,v1);
767 set_vertex(result,1,v2);
778 bool keep_attributes=
true,
bool keep_memory=
false
785 bool keep_attributes,
bool keep_memory =
false
791 edge_vertex_.push_back(NO_VERTEX);
792 edge_vertex_.push_back(NO_VERTEX);
793 return MeshSubElementsStore::create_sub_element();
797 edge_vertex_.resize(2*(nb()+nb_in),NO_VERTEX);
798 return MeshSubElementsStore::create_sub_elements(nb_in);
801 void copy(
const MeshEdges& rhs,
bool copy_attributes=
true) {
802 MeshSubElementsStore::copy(rhs, copy_attributes);
803 edge_vertex_ = rhs.edge_vertex_;
806 vector<index_t> edge_vertex_;
808 friend class GeogramIOHandler;
829 return (is_simplicial_ ? 3*f : facet_ptr_[f]);
840 return (is_simplicial_ ? 3*(f+1): facet_ptr_[f+1]);
850 return (is_simplicial_ ? 3 : facet_ptr_[f+1] - facet_ptr_[f]);
863 return corners_begin(f)+lv;
874 return is_simplicial_;
886 return &facet_ptr_[f];
891 bool keep_attributes,
bool keep_memory =
false
897 if(!is_simplicial_) {
898 facet_ptr_.push_back(NO_CORNER);
900 return MeshSubElementsStore::create_sub_element();
903 index_t create_sub_elements(index_t nb) {
904 if(!is_simplicial_) {
905 for(index_t i=0; i<nb; ++i) {
906 facet_ptr_.push_back(NO_CORNER);
909 return MeshSubElementsStore::create_sub_elements(nb);
912 void copy(
const MeshFacetsStore& rhs,
bool copy_attributes=
true) {
913 MeshSubElementsStore::copy(rhs,copy_attributes);
914 is_simplicial_ = rhs.is_simplicial_;
915 facet_ptr_ = rhs.facet_ptr_;
920 vector<index_t> facet_ptr_;
922 friend class GeogramIOHandler;
942 return corner_vertex_[c];
953 return corner_adjacent_facet_[c];
965 return &corner_adjacent_facet_[c];
978 return &corner_adjacent_facet_[c];
990 corner_vertex_[c] = v;
1005 corner_vertex_[c] = v;
1017 corner_adjacent_facet_[c] = f;
1029 return &(corner_vertex_[c]);
1041 return &(corner_vertex_[c]);
1052 return vertices_.point<DIM>(vertex(c));
1066 return vertices_.point(vertex(c));
1071 bool keep_attributes,
bool keep_memory =
false
1077 corner_vertex_.push_back(v);
1078 corner_adjacent_facet_.push_back(f);
1079 return MeshSubElementsStore::create_sub_element();
1084 corner_vertex_.push_back(NO_VERTEX);
1086 for(index_t i=0; i<nb; ++i) {
1087 corner_adjacent_facet_.push_back(NO_FACET);
1089 return MeshSubElementsStore::create_sub_elements(nb);
1093 const MeshFacetCornersStore& rhs,
bool copy_attributes=
true
1095 MeshSubElementsStore::copy(rhs, copy_attributes);
1096 corner_vertex_ = rhs.corner_vertex_;
1097 corner_adjacent_facet_ = rhs.corner_adjacent_facet_;
1101 MeshVertices& vertices_;
1102 MeshFacetsStore& facets_;
1103 vector<index_t> corner_vertex_;
1104 vector<index_t> corner_adjacent_facet_;
1106 friend class MeshFacets;
1108 friend class GeogramIOHandler;
1133 return nb_corners(f);
1144 return facet_corners_.vertex(corner(f,lv));
1159 return vertices_.point<DIM>(vertex(f,lv));
1173 return vertices_.point<DIM>(vertex(f,lv));
1184 facet_corners_.set_vertex(corner(f,lv),v);
1195 for(
index_t lv=0; lv<nb_vertices(f); ++lv) {
1196 if(vertex(f,lv) == v) {
1210 for(
index_t lv=0; lv<nb_vertices(f1); ++lv) {
1212 if(find_vertex(f2,v) != NO_VERTEX) {
1227 return facet_corners_.adjacent_facet(corner(f,le));
1238 for(
index_t le=0; le<nb_vertices(f); ++le) {
1239 if(adjacent(f,le) == f2) {
1254 facet_corners_.set_adjacent_facet(corner(f,le),f2);
1267 return c + 1 == corners_end(f) ? corners_begin(f) : c + 1;
1280 return c == corners_begin(f) ? corners_end(f) - 1 : c - 1;
1291 for(
index_t c1 = corners_begin(f); c1 != corners_end(f); ++c1) {
1292 index_t c2 = next_corner_around_facet(f,c1);
1294 facet_corners_.vertex(c1) == v1 &&
1295 facet_corners_.vertex(c2) == v2
1297 return c1 - corners_begin(f);
1305 bool remove_isolated_vertices=
true
1311 bool keep_attributes=
true,
bool keep_memory=
false
1324 if(nb_vertices_per_polygon != 3) {
1325 is_not_simplicial();
1329 index_t co = facet_corners_.nb();
1330 facet_corners_.create_sub_elements(
1331 nb_facets*nb_vertices_per_polygon
1333 index_t result = create_sub_elements(nb_facets);
1335 if(!is_simplicial_) {
1336 for(
index_t f=first_facet; f<=first_facet+nb_facets; ++f) {
1338 co += nb_vertices_per_polygon;
1352 facet_corners_.reserve_store(nb_to_reserve*3);
1353 this->reserve_store(nb_to_reserve);
1362 return create_facets(nb_triangles, 3);
1371 return create_facets(nb_quads, 4);
1383 facet_corners_.create_sub_element(v1);
1384 facet_corners_.create_sub_element(v2);
1385 facet_corners_.create_sub_element(v3);
1386 index_t result = create_sub_element();
1387 if(!is_simplicial_) {
1388 facet_ptr_[result+1] = facet_corners_.nb();
1401 is_not_simplicial();
1402 facet_corners_.create_sub_element(v1);
1403 facet_corners_.create_sub_element(v2);
1404 facet_corners_.create_sub_element(v3);
1405 facet_corners_.create_sub_element(v4);
1406 index_t result = create_sub_element();
1407 facet_ptr_[result+1] = facet_corners_.nb();
1419 if(nb_vertices != 3) {
1420 is_not_simplicial();
1422 for(
index_t i=0; i<nb_vertices; ++i) {
1423 facet_corners_.create_sub_element(NO_VERTEX);
1425 index_t result = create_sub_element();
1426 if(!is_simplicial_) {
1427 facet_ptr_[result+1] = facet_corners_.nb();
1441 if(nb_vertices != 3) {
1442 is_not_simplicial();
1444 for(
index_t i=0; i<nb_vertices; ++i) {
1445 facet_corners_.create_sub_element(vertices[i]);
1447 index_t result = create_sub_element();
1448 if(!is_simplicial_) {
1449 facet_ptr_[result+1] = facet_corners_.nb();
1463 return create_polygon(vertices.
size(), vertices.
data());
1526 void assign_triangle_mesh(
1546#ifndef MESH_NO_SYNTAXIC_SUGAR
1557 return facet_corners_.vertex(c);
1573 return facet_corners_.adjacent_facet(c);
1588 corners(f), [
this](
index_t c)->
const vecn& {
1589 index_t v = facet_corners_.vertex(c);
1590 return vertices_.point<DIM>(v);
1605 corners(f), [
this](
index_t c)->vecn& {
1606 index_t v = facet_corners_.vertex(c);
1607 return vertices_.point<DIM>(v);
1620 index_t v0 = facet_corners_.vertex(corners_begin(f));
1626 [
this,v0](
index_t c)->std::tuple<index_t, index_t, index_t> {
1627 return std::make_tuple(
1629 facet_corners_.vertex(c),
1630 facet_corners_.vertex(c+1)
1649 [
this](std::tuple<index_t, index_t, index_t> T)
1650 ->std::tuple<const vecn&, const vecn&, const vecn&> {
1651 return std::tuple<const vecn&, const vecn&, const vecn&>(
1652 vertices_.point<DIM>(std::get<0>(T)),
1653 vertices_.point<DIM>(std::get<1>(T)),
1654 vertices_.point<DIM>(std::get<2>(T))
1673 [
this](std::tuple<index_t, index_t, index_t> T)
1674 ->std::tuple<vecn&, vecn&, vecn&> {
1675 return std::tuple<vecn&, vecn&, vecn&>(
1676 vertices_.point(std::get<0>(T)),
1677 vertices_.point(std::get<1>(T)),
1678 vertices_.point(std::get<2>(T))
1692 if(!is_simplicial_) {
1693 is_simplicial_ =
true;
1694 facet_ptr_.resize(1);
1706 if(is_simplicial_) {
1707 is_simplicial_ =
false;
1708 facet_ptr_.resize(nb()+1);
1709 for(
index_t f=0; f<facet_ptr_.size(); ++f) {
1710 facet_ptr_[f] = 3*f;
1719 friend class GeogramIOHandler;
1733 MESH_NB_CELL_TYPES = 5
1778 namespace MeshCellDescriptors {
1808 return is_simplicial_;
1819 return is_simplicial_ ? MESH_TET : MeshCellType(cell_type_[c]);
1852 return descriptor(c).nb_vertices;
1863 return is_simplicial_ ? 4*c : cell_ptr_[c];
1874 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_corners(c);
1887#ifndef GEO_OS_WINDOWS
1890 return corners_begin(c) + lv;
1900 return descriptor(c).nb_facets;
1911 return is_simplicial_ ? 4*c : cell_ptr_[c];
1922 return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_facets(c);
1934 return facets_begin(c) + lf;
1943 return descriptor(c).nb_edges;
1948 bool keep_attributes,
bool keep_memory =
false
1953 index_t create_sub_element(MeshCellType type) {
1954 if(!is_simplicial_) {
1955 cell_ptr_.push_back(NO_CORNER);
1958 return MeshSubElementsStore::create_sub_element();
1961 index_t create_sub_elements(index_t nb, MeshCellType type) {
1962 if(!is_simplicial_) {
1963 for(index_t i=0; i<nb; ++i) {
1964 cell_ptr_.push_back(NO_CORNER);
1965 cell_type_.push_back(Numeric::uint8(type));
1968 return MeshSubElementsStore::create_sub_elements(nb);
1972 const MeshCellsStore& rhs,
bool copy_attributes=
true
1974 MeshSubElementsStore::copy(rhs, copy_attributes);
1975 is_simplicial_ = rhs.is_simplicial_;
1976 cell_type_ = rhs.cell_type_;
1977 cell_ptr_ = rhs.cell_ptr_;
1981 bool is_simplicial_;
1982 vector<Numeric::uint8> cell_type_;
1983 vector<index_t> cell_ptr_;
1987 friend class GeogramIOHandler;
2007 return corner_vertex_[c];
2018 corner_vertex_[c] = v;
2030 return &(corner_vertex_[c]);
2042 return &(corner_vertex_[c]);
2053 return vertices_.point<DIM>(vertex(c));
2067 return vertices_.point(vertex(c));
2072 bool keep_attributes,
bool keep_memory =
false
2078 corner_vertex_.push_back(v);
2079 return MeshSubElementsStore::create_sub_element();
2084 corner_vertex_.push_back(NO_VERTEX);
2086 return MeshSubElementsStore::create_sub_elements(nb);
2090 const MeshCellCornersStore& rhs,
bool copy_attributes=
true
2092 MeshSubElementsStore::copy(rhs, copy_attributes);
2093 corner_vertex_ = rhs.corner_vertex_;
2097 MeshVertices& vertices_;
2098 vector<index_t> corner_vertex_;
2100 friend class MeshCells;
2102 friend class GeogramIOHandler;
2127 return adjacent_cell_[f];
2140 adjacent_cell_[f] = c;
2151 return &adjacent_cell_[f];
2162 return &adjacent_cell_[f];
2167 bool keep_attributes,
bool keep_memory =
false
2173 adjacent_cell_.push_back(c);
2174 return MeshSubElementsStore::create_sub_element();
2179 adjacent_cell_.push_back(NO_CELL);
2181 return MeshSubElementsStore::create_sub_elements(nb);
2185 const MeshCellFacetsStore& rhs,
bool copy_attributes=
true
2187 MeshSubElementsStore::copy(rhs, copy_attributes);
2188 adjacent_cell_ = rhs.adjacent_cell_;
2192 MeshVertices& vertices_;
2193 MeshCellsStore& cells_;
2194 vector<index_t> adjacent_cell_;
2196 friend class MeshCells;
2198 friend class GeogramIOHandler;
2221 return nb_corners(c);
2231 return cell_corners_.vertex(corner(c,lv));
2241 cell_corners_.set_vertex(corner(c,lv),v);
2255 return vertices_.point<DIM>(vertex(c,lv));
2269 return vertices_.point<DIM>(vertex(c,lv));
2280 return cell_facets_.adjacent_cell(facet(c,lf));
2291 cell_facets_.set_adjacent_cell(facet(c,lf),c2);
2302 return descriptor(c).nb_vertices_in_facet[lf];
2315 return cell_corners_.vertex(
2316 corner(c, descriptor(c).facet_vertex[lf][lv])
2329 return corner(c, descriptor(c).facet_vertex[lf][lc]);
2343 return cell_corners_.vertex(
2344 corner(c,descriptor(c).edge_vertex[le][lv])
2361 return descriptor(c).edge_adjacent_facet[le][lf];
2390#ifndef MESH_NO_SYNTAXIC_SUGAR
2402 corners(cell), [
this](
index_t c)->
const vecn& {
2403 index_t v = cell_corners_.vertex(c);
2404 return vertices_.point<DIM>(v);
2419 corners(cell), [
this](
index_t c)->vecn& {
2420 index_t v = cell_corners_.vertex(c);
2421 return vertices_.point<DIM>(v);
2437 return cell_facets_.adjacent_cell(f);
2445 bool keep_attributes=
true,
bool keep_memory=
false
2450 bool remove_isolated_vertices=
true
2470 if(type != MESH_TET) {
2471 is_not_simplicial();
2482 index_t co = cell_corners_.nb();
2484 cell_corners_.create_sub_elements(
2488 cell_facets_.create_sub_elements(
2492 index_t result = create_sub_elements(nb_cells, type);
2494 if(!is_simplicial_) {
2495 for(
index_t c=first_cell; c<=first_cell+nb_cells; ++c) {
2514 return create_cells(nb_tets, MESH_TET);
2523 return create_cells(nb_hexes, MESH_HEX);
2532 return create_cells(nb_prisms, MESH_PRISM);
2541 return create_cells(nb_pyramids, MESH_PYRAMID);
2559 cell_corners_.create_sub_element(v1);
2560 cell_corners_.create_sub_element(v2);
2561 cell_corners_.create_sub_element(v3);
2562 cell_corners_.create_sub_element(v4);
2563 cell_facets_.create_sub_element(adj1);
2564 cell_facets_.create_sub_element(adj2);
2565 cell_facets_.create_sub_element(adj3);
2566 cell_facets_.create_sub_element(adj4);
2567 index_t result = create_sub_element(MESH_TET);
2568 if(!is_simplicial_) {
2569 cell_ptr_[nb()] = cell_corners_.nb();
2594 is_not_simplicial();
2595 cell_corners_.create_sub_element(v1);
2596 cell_corners_.create_sub_element(v2);
2597 cell_corners_.create_sub_element(v3);
2598 cell_corners_.create_sub_element(v4);
2599 cell_corners_.create_sub_element(v5);
2600 cell_corners_.create_sub_element(v6);
2601 cell_corners_.create_sub_element(v7);
2602 cell_corners_.create_sub_element(v8);
2603 cell_facets_.create_sub_element(adj1);
2604 cell_facets_.create_sub_element(adj2);
2605 cell_facets_.create_sub_element(adj3);
2606 cell_facets_.create_sub_element(adj4);
2607 cell_facets_.create_sub_element(adj5);
2608 cell_facets_.create_sub_element(adj6);
2609 cell_facets_.create_sub_element(NO_CELL);
2610 cell_facets_.create_sub_element(NO_CELL);
2611 index_t result = create_sub_element(MESH_HEX);
2612 cell_ptr_[nb()] = cell_corners_.nb();
2636 is_not_simplicial();
2637 cell_corners_.create_sub_element(v1);
2638 cell_corners_.create_sub_element(v2);
2639 cell_corners_.create_sub_element(v3);
2640 cell_corners_.create_sub_element(v4);
2641 cell_corners_.create_sub_element(v5);
2642 cell_corners_.create_sub_element(v6);
2643 cell_facets_.create_sub_element(adj1);
2644 cell_facets_.create_sub_element(adj2);
2645 cell_facets_.create_sub_element(adj3);
2646 cell_facets_.create_sub_element(adj4);
2647 cell_facets_.create_sub_element(adj5);
2648 cell_facets_.create_sub_element(NO_CELL);
2649 index_t result = create_sub_element(MESH_PRISM);
2650 cell_ptr_[nb()] = cell_corners_.nb();
2672 is_not_simplicial();
2673 cell_corners_.create_sub_element(v1);
2674 cell_corners_.create_sub_element(v2);
2675 cell_corners_.create_sub_element(v3);
2676 cell_corners_.create_sub_element(v4);
2677 cell_corners_.create_sub_element(v5);
2678 cell_facets_.create_sub_element(adj1);
2679 cell_facets_.create_sub_element(adj2);
2680 cell_facets_.create_sub_element(adj3);
2681 cell_facets_.create_sub_element(adj4);
2682 cell_facets_.create_sub_element(adj5);
2683 index_t result = create_sub_element(MESH_PYRAMID);
2684 cell_ptr_[nb()] = cell_corners_.nb();
2707 is_not_simplicial();
2708 cell_corners_.create_sub_element(v1);
2709 cell_corners_.create_sub_element(v2);
2710 cell_corners_.create_sub_element(v3);
2711 cell_corners_.create_sub_element(v4);
2712 cell_facets_.create_sub_element(adj1);
2713 cell_facets_.create_sub_element(adj2);
2714 cell_facets_.create_sub_element(adj3);
2715 cell_facets_.create_sub_element(NO_CELL);
2716 index_t result = create_sub_element(MESH_CONNECTOR);
2717 cell_ptr_[nb()] = cell_corners_.nb();
2733 bool remove_trivial_slivers =
true,
bool verbose_if_OK=
false
2787 return cell_facets_.adjacent_cell_[4*t+lf];
2794 for(
index_t lf=0; lf<4; ++lf) {
2795 if(cell_facets_.adjacent_cell_[4*t+lf] == t2) {
2802 index_t tet_vertex(index_t t, index_t lv)
const {
2806 return cell_corners_.corner_vertex_[4*t+lv];
2809 index_t find_tet_vertex(index_t t, index_t v)
const {
2813 for(index_t lv=0; lv<4; ++lv) {
2814 if(cell_corners_.corner_vertex_[4*t+lv] == v) {
2838 return cell_corners_.vertex(
2839 4 * t + local_tet_facet_vertex_index(lf,lv)
2860 for(
index_t lf = 0; lf < 4; ++lf) {
2861 index_t w1 = tet_facet_vertex(t, lf, 0);
2862 index_t w2 = tet_facet_vertex(t, lf, 1);
2863 index_t w3 = tet_facet_vertex(t, lf, 2);
2865 (v1 == w1 && v2 == w2 && v3 == w3) ||
2866 (v1 == w2 && v2 == w3 && v3 == w1) ||
2867 (v1 == w3 && v2 == w1 && v3 == w2)
2886 return MeshCellDescriptors::tet_descriptor.facet_vertex[lf][lv];
2898 if(is_simplicial_) {
2899 is_simplicial_ =
false;
2900 cell_ptr_.resize(nb()+1);
2901 cell_type_.assign(nb(), MESH_TET);
2902 for(
index_t c=0; c<cell_ptr_.size(); ++c) {
2934 for(
index_t lv=0; lv<nb_vertices(c); ++lv) {
2935 if(vertex(c,lv) == v) {
2956 for(
index_t f1=0; f1<nb_facets(c1); ++f1) {
2957 if(facets_match(c1,f1,c2,f2)) {
3021 const std::vector< std::pair<index_t, index_t> >& matches
3035 friend class GeogramIOHandler;
3053 MESH_ALL_ELEMENTS = 15,
3054 MESH_FACET_CORNERS = 16,
3055 MESH_CELL_CORNERS = 32,
3056 MESH_CELL_FACETS = 64,
3057 MESH_ALL_SUBELEMENTS = 65
3102 void clear(
bool keep_attributes=
true,
bool keep_memory=
false);
3134 bool copy_attributes=
true,
3218 const std::string& name
3236 const std::string& full_attribute_name,
3238 std::string& attribute_name,
3251 const std::string& tag,
const std::string& subelement_name,
#define geo_assert(x)
Verifies that a condition is met.
#define geo_debug_assert(x)
Verifies that a condition is met.
Generic mechanism for attributes.
Common include file, providing basic definitions. Should be included before anything else by all head...
Manages an attribute attached to a set of object.
Managers a set of attributes attached to an object.
index_t size() const
Gets the size.
Stores the cell facets of a mesh (low-level store)
index_t adjacent_cell(index_t f) const
Gets a cell adjacent to a facet.
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.
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.
MeshCellFacetsStore(Mesh &mesh)
MeshCellFacetsStore constructor.
void set_adjacent_cell(index_t f, index_t c)
Sets a cell adjacent to a facet.
Stores the cells of a mesh (low-level store)
index_t facet(index_t c, index_t lf) const
Gets a facet of a cell by local facet index.
bool are_simplices() const
Tests whether all the cells are tetrahedra.
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.
index_t nb_facets(index_t c) const
Gets the number of facets of a cell.
index_t corners_end(index_t c) const
Gets the upper limit for iterating over the corners of a cell.
MeshCellType type(index_t c) const
Gets the type of a cell.
index_t facets_end(index_t c) const
Gets the upper limit for iterating over the facets of a cell.
index_t nb_corners(index_t c) const
Gets the number of corners of a cell.
index_t corners_begin(index_t c) const
Gets the first element for iterating over the corners of a cell.
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
index_t nb_edges(index_t c) const
Gets the number of edges in a cell.
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.
index_t create_cells(index_t nb_cells, MeshCellType type)
Creates a contiguous chunk of cells of the same type.
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.
index_t create_pyramids(index_t nb_pyramids)
Creates a contiguous chunk of pyramids.
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.
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.
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.
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.
index_range corners(index_t c) const
Gets the corners of a cell.
auto points(index_t cell)
Gets the points associated with the vertices of a cell.
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.
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.
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.
index_t nb_vertices(index_t c) const
Gets the number of vertices of a cell.
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.
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.
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.
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.
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.
index_t find_cell_vertex(index_t c, index_t v) const
Finds the local index of a vertex in a cell.
index_t create_hexes(index_t nb_hexes)
Creates a contiguous chunk of hexahedra.
index_t create_tets(index_t nb_tets)
Creates a contiguous chunk of tetrahedra.
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.
auto adjacent(index_t c) const
Gets the cells adjacent to a given cell.
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.
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.
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.
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.
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.
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.
auto points(index_t cell) const
Gets the points associated with the vertices of a cell.
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.
const vecng< DIM, double > & point(index_t c, index_t lv) const
Gets a point by cell and local vertex index.
index_t vertex(index_t c, index_t lv) const
Gets a vertex of a cell by local vertex index.
index_t vertex(index_t e, index_t lv) const
Gets the index of an edge vertex.
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
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.
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.
index_t create_edge()
Creates a new edge.
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.
index_t * vertex_index_ptr(index_t c)
Gets a pointer to a vertex index by corner index.
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.
Base class for mesh elements.
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.
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 facets of a mesh (low-level store)
index_t corner(index_t f, index_t lv) const
Gets a corner by facet and local vertex index.
index_t corners_end(index_t f) const
Gets the upper limit for iterating over the corners of a facet.
index_t nb_corners(index_t f) const
Gets the number of corners in a facet.
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.
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
bool are_simplices() const
Tests whether all the facets are triangles.
index_t corners_begin(index_t f) const
Gets the first element for iterating over the corners of a facet.
index_t create_triangle(index_t v1, index_t v2, index_t v3)
Creates a triangle.
auto triangle_points(index_t f)
Decomposes a facet into triangles.
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.
auto triangles(index_t f) const
Decomposes a facet into triangles.
index_t create_polygon(const vector< index_t > &vertices)
Creates a polygonal facet.
void is_not_simplicial()
Indicates that the stored elements are no longer only triangles.
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.
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.
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.
void is_simplicial()
Indicates that the stored elements are only triangles.
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.
index_t create_polygon(index_t nb_vertices, const index_t *vertices)
Creates a polygonal facet.
void set_vertex(index_t f, index_t lv, index_t v)
Sets a vertex by facet and local vertex index.
auto vertices(index_t f) const
Gets the vertices of a facet.
index_t find_common_vertex(index_t f1, index_t f2) const
finds a common vertex shared by two facets
index_range corners(index_t f) const
Gets the corners of a facet.
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.
auto adjacent(index_t f) const
Gets the facets adjacent to a given facet.
index_t find_vertex(index_t f, index_t v) const
Gets the local index of a vertex in a facet.
vecng< DIM, double > & point(index_t f, index_t lv)
Gets a point by facet and local vertex index.
index_t find_adjacent(index_t f, index_t f2) const
Gets the local index of a facet adjacent to another one.
index_t prev_corner_around_facet(index_t f, index_t c) const
Gets the predecessor of a corner around a facet.
auto points(index_t f)
Gets the points associated with the vertices of a facet.
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.
index_t create_facets(index_t nb_facets, index_t nb_vertices_per_polygon)
Creates a contiguous chunk of facets.
const vecng< DIM, double > & point(index_t f, index_t lv) const
Gets a point by facet and local vertex index.
index_t adjacent(index_t f, index_t le) const
Gets an adjacent facet by facet and local edge index.
auto points(index_t f) const
Gets the points associated with the vertices of a facet.
void set_adjacent(index_t f, index_t le, index_t f2)
Sets an adjacent facet by facet and local edge index.
index_t create_triangles(index_t nb_triangles)
Creates a contiguous chunk of triangles.
index_t next_corner_around_facet(index_t f, index_t c) const
Gets the successor of a corner around a facet.
auto triangle_points(index_t f) const
Decomposes a facet into triangles.
Base class for mesh sub-element storage.
index_as_iterator begin() const
Used by range-based for.
virtual ~MeshSubElementsStore()
MeshElementStore destructor.
AttributesManager & attributes() const
Gets the attributes manager.
MeshSubElementsStore(Mesh &mesh)
Constructs a new MeshSubElementStore.
index_t create_sub_element()
Creates attributes for a sub-element.
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.
index_t nb() const
Gets the number of (sub-)elements.
void reserve_store(index_t nb_to_reserve)
Reserves space for new elements.
index_as_iterator end() const
Used by range-based for.
void copy(const MeshSubElementsStore &rhs, bool copy_attributes=true)
Copies a MeshSubElementsStore into this one.
void adjust_store()
Makes the size of the store tightly match the number of the elements.
virtual void resize_store(index_t new_size)
Resizes this MeshSubElementsStore.
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.
index_t create_vertex(const double *coords)
Creates a new vertex.
index_t create_vertex(const vecng< DIM, double > &p)
Creates a vertex from a 3d point.
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.
const double * point_ptr(index_t v) const
Gets a point.
const vecng< DIM, double > & point(index_t v) const
Gets a point.
float * single_precision_point_ptr(index_t v)
Gets a (single-precision) point.
auto points()
Gets the 3D points of the mesh as an iterable sequence.
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.
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.
bool single_precision() const
Tests whether vertices are stored in single-precision mode.
vecng< DIM, double > & point(index_t v)
Gets a point.
index_t dimension() const
Gets the dimension of the vertices.
index_t create_vertices(index_t nb)
Creates a contiguous chunk of vertices.
void set_single_precision()
Sets single precision mode.
double * point_ptr(index_t v)
Gets a point.
index_t create_vertex()
Creates a new vertex.
void delete_elements(vector< index_t > &to_delete, bool remove_isolated_vertices=true) override
Deletes a set of elements.
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.
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.
A generic index_range bounded by two "non-iterators".
T * data()
Gets modifiable vector data.
Vector with aligned memory allocation.
T * data()
Gets a pointer to the array of elements.
index_t size() const
Gets the number of elements.
Geometric functions in 2d and 3d.
void copy(void *to, const void *from, size_t size)
Copies a memory block.
CellDescriptor * cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES]
Maps a cell type to the associated cell descriptor.
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.
auto transform_range(const RANGE &range, XFORM xform)
Creates a range that applies a user-defined function to each element when accessed.
geo_index_t index_t
The type for storing and manipulating indices.
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
C++-20 like helpers for manipulating ranges of integers.
Lookup tables that describe the combinatorics of each cell type.
index_t nb_vertices_in_facet[6]
index_t facet_vertex[6][4]
index_t edge_adjacent_facet[12][2]
index_t edge_vertex[12][2]