Geogram  Version 1.9.1
A programming library of geometric algorithms
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 
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/range.h>
46 #include <geogram/basic/geometry.h>
47 
53 namespace GEO {
54 
55  class Mesh;
56 
57  static constexpr index_t NO_VERTEX = NO_INDEX;
58  static constexpr index_t NO_EDGE = NO_INDEX;
59  static constexpr index_t NO_FACET = NO_INDEX;
60  static constexpr index_t NO_CELL = NO_INDEX;
61  static constexpr index_t NO_CORNER = NO_INDEX;
62 
70  class GEOGRAM_API MeshSubElementsStore {
71  public:
72 
79 
84 
89  index_t nb() const {
90  return nb_;
91  }
92 
101  return const_cast<AttributesManager&>(attributes_);
102  }
103 
109  return index_as_iterator(0);
110  }
111 
117  return index_as_iterator(nb());
118  }
119 
120  protected:
121 
131  virtual void clear_store(
132  bool keep_attributes, bool keep_memory = false
133  );
134 
141  virtual void resize_store(index_t new_size);
142 
143 
148  void reserve_store(index_t nb_to_reserve) {
149  index_t nb = this->nb();
150  resize_store(nb + nb_to_reserve);
151  resize_store(nb);
152  }
153 
160  index_t result = nb_;
161  if(nb_ + nb > attributes_.size()) {
162  index_t new_capacity=nb_ + nb;
163  if(nb < 128) {
164  new_capacity = std::max(index_t(16),attributes_.size());
165  while(new_capacity < nb_ + nb) {
166  new_capacity *= 2;
167  }
168  }
169  attributes_.reserve(new_capacity);
170  }
171  nb_ += nb;
172  attributes_.resize(nb_);
173  return result;
174  }
175 
181  index_t result = nb_;
182  ++nb_;
183  if(attributes_.capacity() < nb_) {
184  index_t new_capacity =
185  std::max(index_t(16),attributes_.capacity()*2);
186  attributes_.reserve(new_capacity);
187  }
188  attributes_.resize(nb_);
189  return result;
190  }
191 
201  void adjust_store() {
202  attributes_.resize(nb_);
203  }
204 
214  void copy(
215  const MeshSubElementsStore& rhs,
216  bool copy_attributes = true
217  ) {
218  nb_ = rhs.nb();
219  if(copy_attributes) {
220  attributes_.copy(rhs.attributes_);
221  } else {
222  attributes_.clear(false,false);
223  attributes_.resize(rhs.attributes_.size());
224  }
225  }
226 
227  protected:
228  Mesh& mesh_;
229  AttributesManager attributes_;
230  index_t nb_;
231  };
232 
233 
234  /**************************************************************************/
235 
243  class GEOGRAM_API MeshElements {
244  public:
245  MeshElements();
246  virtual ~MeshElements();
247 
257  virtual void delete_elements(
258  vector<index_t>& to_delete,
259  bool remove_isolated_vertices=true
260  ) = 0;
261 
274  virtual void permute_elements(vector<index_t>& permutation) = 0;
275 
285  virtual void clear(
286  bool keep_attributes=true, bool keep_memory=false
287  ) = 0;
288 
292  virtual void pop() = 0;
293 
294  protected:
302  static bool has_non_zero(const GEO::vector<index_t>& I) {
303  for(index_t i = 0; i < I.size(); i++) {
304  if(I[i] != 0) {
305  return true;
306  }
307  }
308  return false;
309  }
310  };
311 
312  /**************************************************************************/
313 
314  class MeshEdges;
315  class MeshFacetCornersStore;
316  class MeshCellCornersStore;
317 
322  class GEOGRAM_API MeshVertices :
323  public MeshSubElementsStore, public MeshElements {
324  public:
325  MeshVertices(Mesh& mesh);
326  ~MeshVertices() override;
327 
333 
335  vector<index_t>& to_delete, bool remove_isolated_vertices=true
336  ) override;
337 
338  void permute_elements(vector<index_t>& permutation) override;
339 
346  }
347 
353  index_t create_vertex(const double* coords) {
354  // Sanity check:
355  // It is not correct to call create_vertex(point_ptr(v)) since
356  // create_vertex may realloc the points coordinates vector, thus
357  // invalidate point_ptr(v).
359  nb() == 0 ||
360  coords < point_ptr(0) ||
361  coords >= point_ptr(0) + nb() * dimension()
362  );
363  index_t result = create_vertex();
364  for(index_t c=0; c<dimension(); ++c) {
365  point_ptr(result)[c] = coords[c];
366  }
367  return result;
368  }
369 
377  }
378 
379  void clear(
380  bool keep_attributes=true, bool keep_memory=false
381  ) override;
382 
391 
401 
408  bool single_precision() const {
409  return point_fp32_.is_bound();
410  }
411 
419  bool double_precision() const {
420  return point_.is_bound();
421  }
422 
427  index_t dimension() const {
428  return
429  single_precision() ?
430  point_fp32_.dimension() :
431  point_.dimension() ;
432  }
433 
440  void set_dimension(index_t dim) {
441  if(single_precision()) {
442  point_fp32_.redim(dim);
443  } else {
444  point_.redim(dim);
445  }
446  }
447 
455  const double* point_ptr(index_t v) const {
456  geo_debug_assert(v < nb());
457  geo_debug_assert(!single_precision());
458  return &point_[v*point_.dimension()];
459  }
460 
468  double* point_ptr(index_t v) {
469  geo_debug_assert(v < nb());
470  geo_debug_assert(!single_precision());
471  return &point_[v*point_.dimension()];
472  }
473 
474 
483  geo_debug_assert(v < nb());
484  geo_debug_assert(!single_precision());
485  geo_debug_assert(dimension() >= 3);
486  return *(vec3*)(&point_[v*point_.dimension()]);
487  }
488 
496  const vec3& point(index_t v) const {
497  geo_debug_assert(v < nb());
498  geo_debug_assert(!single_precision());
499  geo_debug_assert(dimension() >= 3);
500  return *(const vec3*)(&point_[v*point_.dimension()]);
501  }
502 
510  const float* single_precision_point_ptr(index_t v) const {
511  geo_debug_assert(v < nb());
512  geo_debug_assert(single_precision());
513  return &point_fp32_[v*point_fp32_.dimension()];
514  }
515 
524  geo_debug_assert(v < nb());
525  geo_debug_assert(single_precision());
526  return &point_fp32_[v*point_fp32_.dimension()];
527  }
528 
539  vector<double>& points, index_t dim, bool steal_arg
540  );
541 
551  const double* points, index_t dim, index_t nb_pts
552  );
553 
554  void pop() override;
555 
556  protected:
557 
559  bool keep_attributes, bool keep_memory = false
560  ) override;
561 
562  void resize_store(index_t new_size) override;
563 
564  void bind_point_attribute(index_t dim, bool single_precision=false);
565 
566  void copy(const MeshVertices& rhs, bool copy_attributes=true) {
567  index_t dim = rhs.dimension();
568  if(point_fp32_.is_bound()) {
569  point_fp32_.destroy();
570  }
571  if(point_.is_bound()) {
572  point_.destroy();
573  }
574  MeshSubElementsStore::copy(rhs, copy_attributes);
575  if(rhs.single_precision()) {
576  point_fp32_.bind_if_is_defined(attributes(),"point_fp32");
577  if(!point_fp32_.is_bound()) {
578  point_fp32_.create_vector_attribute(
579  attributes(), "point_fp32", dim
580  );
581  }
582  } else {
583  point_.bind_if_is_defined(attributes(),"point");
584  if(!point_.is_bound()) {
585  point_.create_vector_attribute(
586  attributes(), "point", dim
587  );
588  }
589  }
590  // Even if we do not copy the attributes, we need at least
591  // to copy the coordinates of the points !!
592  if(!copy_attributes) {
593  if(rhs.single_precision()) {
594  Memory::copy(
595  single_precision_point_ptr(0),
597  rhs.dimension()*rhs.nb()*sizeof(float)
598  );
599  } else {
600  Memory::copy(
601  point_ptr(0),
602  rhs.point_ptr(0),
603  rhs.dimension()*rhs.nb()*sizeof(double)
604  );
605  }
606  }
607  }
608 
609  MeshEdges& edges_;
610  MeshFacetCornersStore& facet_corners_;
611  MeshCellCornersStore& cell_corners_;
612  Attribute<double> point_;
613  Attribute<float> point_fp32_;
614 
615  friend class Mesh;
616  friend class GeogramIOHandler;
617  };
618 
619  /*************************************************************************/
620 
625  class GEOGRAM_API MeshEdges :
626  public MeshSubElementsStore, public MeshElements {
627  public:
628  MeshEdges(Mesh& mesh);
629  ~MeshEdges() override;
630 
637  index_t vertex(index_t e, index_t lv) const {
638  geo_debug_assert(e < nb());
639  geo_debug_assert(lv < 2);
640  return edge_vertex_[2*e+lv];
641  }
642 
650  geo_debug_assert(e < nb());
651  geo_debug_assert(lv < 2);
652  edge_vertex_[2*e+lv] = v;
653  }
654 
655 
663  geo_debug_assert(c < 2*nb());
664  return &(edge_vertex_[c]);
665  }
666 
673  const index_t* vertex_index_ptr(index_t c) const {
674  geo_debug_assert(c < 2*nb());
675  return &(edge_vertex_[c]);
676  }
677 
683  return create_sub_element();
684  }
685 
692  return create_sub_elements(nb);
693  }
694 
701  index_t result = create_edge();
702  set_vertex(result,0,v1);
703  set_vertex(result,1,v2);
704  return result;
705  }
706 
708  vector<index_t>& to_delete, bool remove_isolated_vertices=true
709  ) override;
710 
711  void permute_elements(vector<index_t>& permutation) override;
712 
713  void clear(
714  bool keep_attributes=true, bool keep_memory=false
715  ) override;
716 
717  void pop() override;
718 
719  protected:
721  bool keep_attributes, bool keep_memory = false
722  ) override;
723 
724  void resize_store(index_t new_size) override;
725 
726  index_t create_sub_element() {
727  edge_vertex_.push_back(NO_VERTEX);
728  edge_vertex_.push_back(NO_VERTEX);
730  }
731 
732  index_t create_sub_elements(index_t nb_in) {
733  edge_vertex_.resize(2*(nb()+nb_in),NO_VERTEX);
735  }
736 
737  void copy(const MeshEdges& rhs, bool copy_attributes=true) {
738  MeshSubElementsStore::copy(rhs, copy_attributes);
739  edge_vertex_ = rhs.edge_vertex_;
740  }
741 
742  vector<index_t> edge_vertex_;
743  friend class Mesh;
744  friend class GeogramIOHandler;
745  };
746 
747  /**************************************************************************/
748 
753  class GEOGRAM_API MeshFacetsStore : public MeshSubElementsStore {
754  public:
755  MeshFacetsStore(Mesh& mesh);
756 
764  geo_debug_assert(f < nb());
765  return (is_simplicial_ ? 3*f : facet_ptr_[f]);
766  }
767 
775  geo_debug_assert(f < nb());
776  return (is_simplicial_ ? 3*(f+1): facet_ptr_[f+1]);
777  }
778 
785  geo_debug_assert(f < nb());
786  return (is_simplicial_ ? 3 : facet_ptr_[f+1] - facet_ptr_[f]);
787  }
788 
796  index_t corner(index_t f, index_t lv) const {
797  geo_debug_assert(f < nb());
798  geo_debug_assert(lv < nb_corners(f));
799  return corners_begin(f)+lv;
800  }
801 
809  bool are_simplices() const {
810  return is_simplicial_;
811  }
812 
820  geo_debug_assert(!is_simplicial_);
821  geo_debug_assert(f < nb());
822  return &facet_ptr_[f];
823  }
824 
825  protected:
827  bool keep_attributes, bool keep_memory = false
828  ) override;
829 
830  void resize_store(index_t new_size) override;
831 
832  index_t create_sub_element() {
833  if(!is_simplicial_) {
834  facet_ptr_.push_back(NO_CORNER);
835  }
837  }
838 
839  index_t create_sub_elements(index_t nb) {
840  if(!is_simplicial_) {
841  for(index_t i=0; i<nb; ++i) {
842  facet_ptr_.push_back(NO_CORNER);
843  }
844  }
846  }
847 
848  void copy(const MeshFacetsStore& rhs, bool copy_attributes=true) {
849  MeshSubElementsStore::copy(rhs,copy_attributes);
850  is_simplicial_ = rhs.is_simplicial_;
851  facet_ptr_ = rhs.facet_ptr_;
852  }
853 
854  protected:
855  bool is_simplicial_;
856  vector<index_t> facet_ptr_;
857  friend class Mesh;
858  friend class GeogramIOHandler;
859  };
860 
861  /*************************************************************************/
862 
867  class GEOGRAM_API MeshFacetCornersStore : public MeshSubElementsStore {
868  public:
870 
876  index_t vertex(index_t c) const {
877  geo_assert(c < nb());
878  return corner_vertex_[c];
879  }
880 
888  geo_assert(c < nb());
889  return corner_adjacent_facet_[c];
890  }
891 
900  geo_assert(c < nb());
901  return &corner_adjacent_facet_[c];
902  }
903 
904 
913  geo_assert(c < nb());
914  return &corner_adjacent_facet_[c];
915  }
916 
924  geo_debug_assert(c < nb());
925  geo_debug_assert(v < vertices_.nb());
926  corner_vertex_[c] = v;
927  }
928 
940  geo_debug_assert(c < nb());
941  corner_vertex_[c] = v;
942  }
943 
951  geo_debug_assert(c < nb());
952  geo_debug_assert(f == NO_FACET || f < facets_.nb());
953  corner_adjacent_facet_[c] = f;
954  }
955 
964  geo_debug_assert(c < nb());
965  return &(corner_vertex_[c]);
966  }
967 
975  const index_t* vertex_index_ptr(index_t c) const {
976  geo_debug_assert(c < nb());
977  return &(corner_vertex_[c]);
978  }
979 
980  protected:
982  bool keep_attributes, bool keep_memory = false
983  ) override;
984 
985  void resize_store(index_t new_size) override;
986 
987  index_t create_sub_element(index_t v, index_t f = NO_FACET) {
988  corner_vertex_.push_back(v);
989  corner_adjacent_facet_.push_back(f);
991  }
992 
993  index_t create_sub_elements(index_t nb) {
994  for(index_t i=0; i<nb; ++i) {
995  corner_vertex_.push_back(NO_VERTEX);
996  }
997  for(index_t i=0; i<nb; ++i) {
998  corner_adjacent_facet_.push_back(NO_FACET);
999  }
1001  }
1002 
1003  void copy(
1004  const MeshFacetCornersStore& rhs, bool copy_attributes=true
1005  ) {
1006  MeshSubElementsStore::copy(rhs, copy_attributes);
1007  corner_vertex_ = rhs.corner_vertex_;
1008  corner_adjacent_facet_ = rhs.corner_adjacent_facet_;
1009  }
1010 
1011  protected:
1012  MeshVertices& vertices_;
1013  MeshFacetsStore& facets_;
1014  vector<index_t> corner_vertex_;
1015  vector<index_t> corner_adjacent_facet_;
1016 
1017  friend class MeshFacets;
1018  friend class Mesh;
1019  friend class GeogramIOHandler;
1020  };
1021 
1022  /*************************************************************************/
1023 
1028  class GEOGRAM_API MeshFacets : public MeshFacetsStore, public MeshElements {
1029  public:
1030 
1037 
1044  return nb_corners(f);
1045  }
1046 
1055  return facet_corners_.vertex(corner(f,lv));
1056  }
1057 
1066  facet_corners_.set_vertex(corner(f,lv),v);
1067  }
1068 
1077  for(index_t lv=0; lv<nb_vertices(f); ++lv) {
1078  if(vertex(f,lv) == v) {
1079  return lv;
1080  }
1081  }
1082  return NO_VERTEX;
1083  }
1084 
1092  for(index_t lv=0; lv<nb_vertices(f1); ++lv) {
1093  index_t v = vertex(f1,lv);
1094  if(find_vertex(f2,v) != NO_VERTEX) {
1095  return lv;
1096  }
1097  }
1098  return NO_VERTEX;
1099  }
1100 
1109  return facet_corners_.adjacent_facet(corner(f,le));
1110  }
1111 
1120  for(index_t le=0; le<nb_vertices(f); ++le) {
1121  if(adjacent(f,le) == f2) {
1122  return le;
1123  }
1124  }
1125  return NO_INDEX;
1126  }
1127 
1136  facet_corners_.set_adjacent_facet(corner(f,le),f2);
1137  }
1138 
1147  geo_debug_assert(f < nb());
1148  geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1149  return c + 1 == corners_end(f) ? corners_begin(f) : c + 1;
1150  }
1151 
1160  geo_debug_assert(f < nb());
1161  geo_debug_assert(c >= corners_begin(f) && c < corners_end(f));
1162  return c == corners_begin(f) ? corners_end(f) - 1 : c - 1;
1163  }
1164 
1173  for(index_t c1 = corners_begin(f); c1 != corners_end(f); ++c1) {
1174  index_t c2 = next_corner_around_facet(f,c1);
1175  if(
1176  facet_corners_.vertex(c1) == v1 &&
1177  facet_corners_.vertex(c2) == v2
1178  ) {
1179  return c1 - corners_begin(f);
1180  }
1181  }
1182  return NO_INDEX;
1183  }
1184 
1186  vector<index_t>& to_delete,
1187  bool remove_isolated_vertices=true
1188  ) override;
1189 
1190  void permute_elements(vector<index_t>& permutation) override;
1191 
1192  void clear(
1193  bool keep_attributes=true, bool keep_memory=false
1194  ) override;
1195 
1204  index_t nb_facets, index_t nb_vertices_per_polygon
1205  ) {
1206  if(nb_vertices_per_polygon != 3) {
1207  is_not_simplicial();
1208  }
1209 
1210  index_t first_facet = nb();
1211  index_t co = facet_corners_.nb();
1212  facet_corners_.create_sub_elements(
1213  nb_facets*nb_vertices_per_polygon
1214  );
1215  index_t result = create_sub_elements(nb_facets);
1216 
1217  if(!is_simplicial_) {
1218  for(index_t f=first_facet; f<=first_facet+nb_facets; ++f) {
1219  facet_ptr_[f] = co;
1220  co += nb_vertices_per_polygon;
1221  }
1222  geo_debug_assert(facet_ptr_.size() == nb()+1);
1223  geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1224  }
1225  return result;
1226  }
1227 
1233  void reserve(index_t nb_to_reserve) {
1234  facet_corners_.reserve_store(nb_to_reserve*3);
1235  this->reserve_store(nb_to_reserve);
1236  }
1237 
1244  return create_facets(nb_triangles, 3);
1245  }
1246 
1253  return create_facets(nb_quads, 4);
1254  }
1255 
1262  geo_debug_assert(v1 != v2);
1263  geo_debug_assert(v2 != v3);
1264  geo_debug_assert(v3 != v1);
1265  facet_corners_.create_sub_element(v1);
1266  facet_corners_.create_sub_element(v2);
1267  facet_corners_.create_sub_element(v3);
1268  index_t result = create_sub_element();
1269  if(!is_simplicial_) {
1270  facet_ptr_[result+1] = facet_corners_.nb();
1271  geo_debug_assert(facet_ptr_.size() == nb()+1);
1272  geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1273  }
1274  return result;
1275  }
1276 
1283  is_not_simplicial();
1284  facet_corners_.create_sub_element(v1);
1285  facet_corners_.create_sub_element(v2);
1286  facet_corners_.create_sub_element(v3);
1287  facet_corners_.create_sub_element(v4);
1288  index_t result = create_sub_element();
1289  facet_ptr_[result+1] = facet_corners_.nb();
1290  geo_debug_assert(facet_ptr_.size() == nb()+1);
1291  geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1292  return result;
1293  }
1294 
1301  if(nb_vertices != 3) {
1302  is_not_simplicial();
1303  }
1304  for(index_t i=0; i<nb_vertices; ++i) {
1305  facet_corners_.create_sub_element(NO_VERTEX);
1306  }
1307  index_t result = create_sub_element();
1308  if(!is_simplicial_) {
1309  facet_ptr_[result+1] = facet_corners_.nb();
1310  geo_debug_assert(facet_ptr_.size() == nb()+1);
1311  geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1312  }
1313  return result;
1314  }
1315 
1322  index_t create_polygon(index_t nb_vertices, const index_t* vertices) {
1323  if(nb_vertices != 3) {
1324  is_not_simplicial();
1325  }
1326  for(index_t i=0; i<nb_vertices; ++i) {
1327  facet_corners_.create_sub_element(vertices[i]);
1328  }
1329  index_t result = create_sub_element();
1330  if(!is_simplicial_) {
1331  facet_ptr_[result+1] = facet_corners_.nb();
1332  geo_debug_assert(facet_ptr_.size() == nb()+1);
1333  geo_debug_assert(facet_ptr_[nb()] == facet_corners_.nb());
1334  }
1335  return result;
1336  }
1337 
1345  return create_polygon(vertices.size(), vertices.data());
1346  }
1347 
1352  void connect();
1353 
1360  void connect(index_t facets_begin, index_t facets_end);
1361 
1366  void triangulate();
1367 
1373  void flip(index_t f);
1374 
1380 
1393  coord_index_t dim,
1394  vector<double>& vertices,
1395  vector<index_t>& triangles,
1396  bool steal_args
1397  );
1398 
1399  /*
1400  * \brief Copies a triangle mesh into this Mesh.
1401  * \details Facet adjacence are not computed.
1402  * Facet and corner attributes are zeroed.
1403  * \param[in] triangles facet to vertex links
1404  * \param[in] steal_args if set, vertices and triangles
1405  * are 'stolen' from the arguments
1406  * (using vector::swap).
1407  */
1408  void assign_triangle_mesh(
1409  vector<index_t>& triangles,
1410  bool steal_args
1411  );
1412 
1413  void pop() override;
1414 
1421  geo_debug_assert(f < nb());
1422  return index_range(
1423  index_as_iterator(corners_begin(f)),
1424  index_as_iterator(corners_end(f))
1425  );
1426  }
1427 
1428  protected:
1429 
1433  void is_simplicial() {
1434  if(!is_simplicial_) {
1435  is_simplicial_ = true;
1436  facet_ptr_.resize(1);
1437  facet_ptr_[0] = 0;
1438  }
1439  }
1440 
1448  if(is_simplicial_) {
1449  is_simplicial_ = false;
1450  facet_ptr_.resize(nb()+1);
1451  for(index_t f=0; f<facet_ptr_.size(); ++f) {
1452  facet_ptr_[f] = 3*f;
1453  }
1454  }
1455  }
1456 
1457  protected:
1458  MeshVertices& vertices_;
1459  MeshFacetCornersStore& facet_corners_;
1460  friend class Mesh;
1461  friend class GeogramIOHandler;
1462  friend void GEOGRAM_API tessellate_facets(
1463  Mesh& M, index_t max_nb_vertices
1464  );
1465  };
1466 
1467  /*************************************************************************/
1468 
1469  enum MeshCellType {
1470  MESH_TET = 0,
1471  MESH_HEX = 1,
1472  MESH_PRISM = 2,
1473  MESH_PYRAMID = 3,
1474  MESH_CONNECTOR = 4,
1475  MESH_NB_CELL_TYPES = 5
1476  };
1477 
1486 
1489 
1492 
1497 
1501 
1506 
1511  };
1512 
1513 
1520  namespace MeshCellDescriptors {
1524  GEOGRAM_API extern CellDescriptor*
1525  cell_type_to_cell_descriptor[GEO::MESH_NB_CELL_TYPES];
1526 
1527  GEOGRAM_API extern CellDescriptor tet_descriptor;
1528  GEOGRAM_API extern CellDescriptor hex_descriptor;
1529  GEOGRAM_API extern CellDescriptor prism_descriptor;
1530  GEOGRAM_API extern CellDescriptor pyramid_descriptor;
1531  GEOGRAM_API extern CellDescriptor connector_descriptor;
1532  }
1533 
1538  class GEOGRAM_API MeshCellsStore : public MeshSubElementsStore {
1539  public:
1540  MeshCellsStore(Mesh& mesh);
1541 
1549  bool are_simplices() const {
1550  return is_simplicial_;
1551  }
1552 
1559  MeshCellType type(index_t c) const {
1560  geo_debug_assert(c < nb());
1561  return is_simplicial_ ? MESH_TET : MeshCellType(cell_type_[c]);
1562  }
1563 
1573  geo_debug_assert(c < nb());
1574  return is_simplicial_ ? MeshCellDescriptors::tet_descriptor :
1575  *(
1577  cell_type_[c]
1578  ]
1579  );
1580  }
1581 
1592  MeshCellType t
1593  ) {
1594  geo_debug_assert(t < GEO::MESH_NB_CELL_TYPES);
1596  }
1597 
1604  geo_debug_assert(c < nb());
1605  return descriptor(c).nb_vertices;
1606  }
1607 
1615  geo_debug_assert(c < nb());
1616  return is_simplicial_ ? 4*c : cell_ptr_[c];
1617  }
1618 
1626  geo_debug_assert(c < nb());
1627  return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_corners(c);
1628  }
1629 
1637  geo_debug_assert(c < nb());
1638  // There seems to be a linkage problem under MSVC for the
1639  // following assertion check...
1640 #ifndef GEO_OS_WINDOWS
1641  geo_debug_assert(lv < nb_corners(c));
1642 #endif
1643  return corners_begin(c) + lv;
1644  }
1645 
1652  geo_debug_assert(c < nb());
1653  return descriptor(c).nb_facets;
1654  }
1655 
1663  geo_debug_assert(c < nb());
1664  return is_simplicial_ ? 4*c : cell_ptr_[c];
1665  }
1666 
1674  geo_debug_assert(c < nb());
1675  return is_simplicial_ ? 4*(c+1) : cell_ptr_[c] + nb_facets(c);
1676  }
1677 
1684  index_t facet(index_t c, index_t lf) const {
1685  geo_debug_assert(c < nb());
1686  geo_debug_assert(lf < nb_facets(c));
1687  return facets_begin(c) + lf;
1688  }
1689 
1696  return descriptor(c).nb_edges;
1697  }
1698 
1699  protected:
1701  bool keep_attributes, bool keep_memory = false
1702  ) override;
1703 
1704  void resize_store(index_t new_size) override;
1705 
1706  index_t create_sub_element(MeshCellType type) {
1707  if(!is_simplicial_) {
1708  cell_ptr_.push_back(NO_CORNER);
1709  cell_type_.push_back(Numeric::uint8(type));
1710  }
1712  }
1713 
1714  index_t create_sub_elements(index_t nb, MeshCellType type) {
1715  if(!is_simplicial_) {
1716  for(index_t i=0; i<nb; ++i) {
1717  cell_ptr_.push_back(NO_CORNER);
1718  cell_type_.push_back(Numeric::uint8(type));
1719  }
1720  }
1722  }
1723 
1724  void copy(
1725  const MeshCellsStore& rhs, bool copy_attributes=true
1726  ) {
1727  MeshSubElementsStore::copy(rhs, copy_attributes);
1728  is_simplicial_ = rhs.is_simplicial_;
1729  cell_type_ = rhs.cell_type_;
1730  cell_ptr_ = rhs.cell_ptr_;
1731  }
1732 
1733  protected:
1734  bool is_simplicial_;
1735  vector<Numeric::uint8> cell_type_;
1736  vector<index_t> cell_ptr_;
1737 
1738  protected:
1739  friend class Mesh;
1740  friend class GeogramIOHandler;
1741  };
1742 
1743  /*************************************************************************/
1744 
1749  class GEOGRAM_API MeshCellCornersStore : public MeshSubElementsStore {
1750  public:
1751  MeshCellCornersStore(Mesh& mesh);
1752 
1759  geo_assert(c < nb());
1760  return corner_vertex_[c];
1761  }
1762 
1769  geo_debug_assert(c < nb());
1770  geo_debug_assert(v < vertices_.nb());
1771  corner_vertex_[c] = v;
1772  }
1773 
1782  geo_debug_assert(c < nb());
1783  return &(corner_vertex_[c]);
1784  }
1785 
1794  geo_debug_assert(c < nb());
1795  return &(corner_vertex_[c]);
1796  }
1797 
1798  protected:
1800  bool keep_attributes, bool keep_memory = false
1801  ) override;
1802 
1803  void resize_store(index_t new_size) override;
1804 
1805  index_t create_sub_element(index_t v) {
1806  corner_vertex_.push_back(v);
1808  }
1809 
1810  index_t create_sub_elements(index_t nb) {
1811  for(index_t i=0; i<nb; ++i) {
1812  corner_vertex_.push_back(NO_VERTEX);
1813  }
1815  }
1816 
1817  void copy(
1818  const MeshCellCornersStore& rhs, bool copy_attributes=true
1819  ) {
1820  MeshSubElementsStore::copy(rhs, copy_attributes);
1821  corner_vertex_ = rhs.corner_vertex_;
1822  }
1823 
1824  protected:
1825  MeshVertices& vertices_;
1826  vector<index_t> corner_vertex_;
1827 
1828  friend class MeshCells;
1829  friend class Mesh;
1830  friend class GeogramIOHandler;
1831  };
1832 
1833  /*************************************************************************/
1834 
1839  class GEOGRAM_API MeshCellFacetsStore : public MeshSubElementsStore {
1840  public:
1846 
1854  geo_assert(f < nb());
1855  return adjacent_cell_[f];
1856  }
1857 
1866  geo_debug_assert(f < nb());
1867  geo_debug_assert(c == NO_CELL || c < cells_.nb());
1868  adjacent_cell_[f] = c;
1869  }
1870 
1878  geo_assert(f < nb());
1879  return &adjacent_cell_[f];
1880  }
1881 
1889  geo_assert(f < nb());
1890  return &adjacent_cell_[f];
1891  }
1892 
1893  protected:
1895  bool keep_attributes, bool keep_memory = false
1896  ) override;
1897 
1898  void resize_store(index_t new_size) override;
1899 
1900  index_t create_sub_element(index_t c = NO_CELL) {
1901  adjacent_cell_.push_back(c);
1903  }
1904 
1905  index_t create_sub_elements(index_t nb) {
1906  for(index_t i=0; i<nb; ++i) {
1907  adjacent_cell_.push_back(NO_CELL);
1908  }
1910  }
1911 
1912  void copy(
1913  const MeshCellFacetsStore& rhs, bool copy_attributes=true
1914  ) {
1915  MeshSubElementsStore::copy(rhs, copy_attributes);
1916  adjacent_cell_ = rhs.adjacent_cell_;
1917  }
1918 
1919  protected:
1920  MeshVertices& vertices_;
1921  MeshCellsStore& cells_;
1922  vector<index_t> adjacent_cell_;
1923 
1924  friend class MeshCells;
1925  friend class Mesh;
1926  friend class GeogramIOHandler;
1927  };
1928 
1929  /*************************************************************************/
1930 
1935  class GEOGRAM_API MeshCells : public MeshCellsStore, public MeshElements {
1936  public:
1941  MeshCells(Mesh& mesh);
1942 
1949  return nb_corners(c);
1950  }
1951 
1959  return cell_corners_.vertex(corner(c,lv));
1960  }
1961 
1969  cell_corners_.set_vertex(corner(c,lv),v);
1970  }
1971 
1980  return cell_facets_.adjacent_cell(facet(c,lf));
1981  }
1982 
1991  cell_facets_.set_adjacent_cell(facet(c,lf),c2);
1992  }
1993 
2001  geo_debug_assert(lf < nb_facets(c));
2002  return descriptor(c).nb_vertices_in_facet[lf];
2003  }
2004 
2014  geo_debug_assert(lv < facet_nb_vertices(c, lf));
2015  return cell_corners_.vertex(
2016  corner(c, descriptor(c).facet_vertex[lf][lv])
2017  );
2018  }
2028  geo_debug_assert(lc < facet_nb_vertices(c, lf));
2029  return corner(c, descriptor(c).facet_vertex[lf][lc]);
2030  }
2031 
2041  geo_debug_assert(le < nb_edges(c));
2042  geo_debug_assert(lv < 2);
2043  return cell_corners_.vertex(
2044  corner(c,descriptor(c).edge_vertex[le][lv])
2045  );
2046  }
2047 
2059  geo_debug_assert(le < nb_edges(c));
2060  geo_debug_assert(lf < 2);
2061  return descriptor(c).edge_adjacent_facet[le][lf];
2062  }
2063 
2070  geo_debug_assert(c < nb());
2071  return index_range(
2072  index_as_iterator(corners_begin(c)),
2073  index_as_iterator(corners_end(c))
2074  );
2075  }
2076 
2077  void clear(
2078  bool keep_attributes=true, bool keep_memory=false
2079  ) override;
2080 
2082  vector<index_t>& to_delete,
2083  bool remove_isolated_vertices=true
2084  ) override;
2085 
2086  void permute_elements(vector<index_t>& permutation) override;
2087 
2096  index_t create_cells(index_t nb_cells, MeshCellType type) {
2097 
2098  if(nb_cells == 0) {
2099  return NO_CELL;
2100  }
2101 
2102 
2103  if(type != MESH_TET) {
2104  is_not_simplicial();
2105  }
2106 
2107  const CellDescriptor& desc = cell_type_to_cell_descriptor(type);
2108 
2109  // Note: there is padding, the same number of corners and
2110  // faces is created for each cell, so that a single cell
2111  // pointer is used for both.
2112 
2113  index_t cell_size = std::max(desc.nb_vertices, desc.nb_facets);
2114  index_t first_cell = nb();
2115  index_t co = cell_corners_.nb();
2116 
2117  cell_corners_.create_sub_elements(
2118  nb_cells*cell_size
2119  );
2120 
2121  cell_facets_.create_sub_elements(
2122  nb_cells*cell_size
2123  );
2124 
2125  index_t result = create_sub_elements(nb_cells, type);
2126 
2127  if(!is_simplicial_) {
2128  for(index_t c=first_cell; c<=first_cell+nb_cells; ++c) {
2129  cell_ptr_[c] = co;
2130  co += cell_size;
2131  }
2132 
2133  geo_debug_assert(cell_ptr_.size() == nb()+1);
2134  geo_debug_assert(cell_ptr_[nb()] == cell_corners_.nb());
2135  geo_debug_assert(cell_ptr_[nb()] == cell_facets_.nb());
2136  }
2137 
2138  return result;
2139  }
2140 
2147  return create_cells(nb_tets, MESH_TET);
2148  }
2149 
2156  return create_cells(nb_hexes, MESH_HEX);
2157  }
2158 
2165  return create_cells(nb_prisms, MESH_PRISM);
2166  }
2167 
2174  return create_cells(nb_pyramids, MESH_PYRAMID);
2175  }
2176 
2186  index_t v1, index_t v2, index_t v3, index_t v4,
2187  index_t adj1 = NO_CELL,
2188  index_t adj2 = NO_CELL,
2189  index_t adj3 = NO_CELL,
2190  index_t adj4 = NO_CELL
2191  ) {
2192  cell_corners_.create_sub_element(v1);
2193  cell_corners_.create_sub_element(v2);
2194  cell_corners_.create_sub_element(v3);
2195  cell_corners_.create_sub_element(v4);
2196  cell_facets_.create_sub_element(adj1);
2197  cell_facets_.create_sub_element(adj2);
2198  cell_facets_.create_sub_element(adj3);
2199  cell_facets_.create_sub_element(adj4);
2200  index_t result = create_sub_element(MESH_TET);
2201  if(!is_simplicial_) {
2202  cell_ptr_[nb()] = cell_corners_.nb();
2203  }
2204  geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2205  return result;
2206  }
2207 
2218  index_t v1, index_t v2, index_t v3, index_t v4,
2219  index_t v5, index_t v6, index_t v7, index_t v8,
2220  index_t adj1 = NO_CELL,
2221  index_t adj2 = NO_CELL,
2222  index_t adj3 = NO_CELL,
2223  index_t adj4 = NO_CELL,
2224  index_t adj5 = NO_CELL,
2225  index_t adj6 = NO_CELL
2226  ) {
2227  is_not_simplicial();
2228  cell_corners_.create_sub_element(v1);
2229  cell_corners_.create_sub_element(v2);
2230  cell_corners_.create_sub_element(v3);
2231  cell_corners_.create_sub_element(v4);
2232  cell_corners_.create_sub_element(v5);
2233  cell_corners_.create_sub_element(v6);
2234  cell_corners_.create_sub_element(v7);
2235  cell_corners_.create_sub_element(v8);
2236  cell_facets_.create_sub_element(adj1);
2237  cell_facets_.create_sub_element(adj2);
2238  cell_facets_.create_sub_element(adj3);
2239  cell_facets_.create_sub_element(adj4);
2240  cell_facets_.create_sub_element(adj5);
2241  cell_facets_.create_sub_element(adj6);
2242  cell_facets_.create_sub_element(NO_CELL); // padding
2243  cell_facets_.create_sub_element(NO_CELL); // padding
2244  index_t result = create_sub_element(MESH_HEX);
2245  cell_ptr_[nb()] = cell_corners_.nb();
2246  geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2247  return result;
2248  }
2249 
2260  index_t v1, index_t v2,
2261  index_t v3, index_t v4,
2262  index_t v5, index_t v6,
2263  index_t adj1 = NO_CELL,
2264  index_t adj2 = NO_CELL,
2265  index_t adj3 = NO_CELL,
2266  index_t adj4 = NO_CELL,
2267  index_t adj5 = NO_CELL
2268  ) {
2269  is_not_simplicial();
2270  cell_corners_.create_sub_element(v1);
2271  cell_corners_.create_sub_element(v2);
2272  cell_corners_.create_sub_element(v3);
2273  cell_corners_.create_sub_element(v4);
2274  cell_corners_.create_sub_element(v5);
2275  cell_corners_.create_sub_element(v6);
2276  cell_facets_.create_sub_element(adj1);
2277  cell_facets_.create_sub_element(adj2);
2278  cell_facets_.create_sub_element(adj3);
2279  cell_facets_.create_sub_element(adj4);
2280  cell_facets_.create_sub_element(adj5);
2281  cell_facets_.create_sub_element(NO_CELL); // padding
2282  index_t result = create_sub_element(MESH_PRISM);
2283  cell_ptr_[nb()] = cell_corners_.nb();
2284  geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2285  return result;
2286  }
2287 
2298  index_t v1, index_t v2, index_t v3, index_t v4, index_t v5,
2299  index_t adj1 = NO_CELL,
2300  index_t adj2 = NO_CELL,
2301  index_t adj3 = NO_CELL,
2302  index_t adj4 = NO_CELL,
2303  index_t adj5 = NO_CELL
2304  ) {
2305  is_not_simplicial();
2306  cell_corners_.create_sub_element(v1);
2307  cell_corners_.create_sub_element(v2);
2308  cell_corners_.create_sub_element(v3);
2309  cell_corners_.create_sub_element(v4);
2310  cell_corners_.create_sub_element(v5);
2311  cell_facets_.create_sub_element(adj1);
2312  cell_facets_.create_sub_element(adj2);
2313  cell_facets_.create_sub_element(adj3);
2314  cell_facets_.create_sub_element(adj4);
2315  cell_facets_.create_sub_element(adj5);
2316  index_t result = create_sub_element(MESH_PYRAMID);
2317  cell_ptr_[nb()] = cell_corners_.nb();
2318  geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2319  return result;
2320  }
2321 
2335  index_t v1, index_t v2, index_t v3, index_t v4,
2336  index_t adj1 = NO_CELL,
2337  index_t adj2 = NO_CELL,
2338  index_t adj3 = NO_CELL
2339  ) {
2340  is_not_simplicial();
2341  cell_corners_.create_sub_element(v1);
2342  cell_corners_.create_sub_element(v2);
2343  cell_corners_.create_sub_element(v3);
2344  cell_corners_.create_sub_element(v4);
2345  cell_facets_.create_sub_element(adj1);
2346  cell_facets_.create_sub_element(adj2);
2347  cell_facets_.create_sub_element(adj3);
2348  cell_facets_.create_sub_element(NO_CELL); // padding
2349  index_t result = create_sub_element(MESH_CONNECTOR);
2350  cell_ptr_[nb()] = cell_corners_.nb();
2351  geo_debug_assert(cell_facets_.nb() == cell_corners_.nb());
2352  return result;
2353  }
2354 
2365  void connect(
2366  bool remove_trivial_slivers = true, bool verbose_if_OK=false
2367  );
2368 
2374 
2383 
2395  coord_index_t dim,
2396  vector<double>& vertices,
2397  vector<index_t>& tets,
2398  bool steal_args
2399  );
2400 
2410  vector<index_t>& tets,
2411  bool steal_args
2412  );
2413 
2414  void pop() override;
2415 
2416  index_t tet_adjacent(index_t t, index_t lf) const {
2417  geo_debug_assert(is_simplicial_);
2418  geo_debug_assert(t < nb());
2419  geo_debug_assert(lf < 4);
2420  return cell_facets_.adjacent_cell_[4*t+lf];
2421  }
2422 
2423  index_t find_tet_adjacent(index_t t, index_t t2) const {
2424  geo_debug_assert(is_simplicial_);
2425  geo_debug_assert(t < nb());
2426  geo_debug_assert(t2 < nb());
2427  for(index_t lf=0; lf<4; ++lf) {
2428  if(cell_facets_.adjacent_cell_[4*t+lf] == t2) {
2429  return lf;
2430  }
2431  }
2432  return NO_FACET;
2433  }
2434 
2435  index_t tet_vertex(index_t t, index_t lv) const {
2436  geo_debug_assert(is_simplicial_);
2437  geo_debug_assert(t < nb());
2438  geo_debug_assert(lv < 4);
2439  return cell_corners_.corner_vertex_[4*t+lv];
2440  }
2441 
2442  index_t find_tet_vertex(index_t t, index_t v) const {
2443  geo_debug_assert(is_simplicial_);
2444  geo_debug_assert(t < nb());
2445  geo_debug_assert(v < vertices_.nb());
2446  for(index_t lv=0; lv<4; ++lv) {
2447  if(cell_corners_.corner_vertex_[4*t+lv] == v) {
2448  return lv;
2449  }
2450  }
2451  return NO_VERTEX;
2452  }
2453 
2465  index_t t, index_t lf, index_t lv
2466  ) const {
2467  geo_debug_assert(is_simplicial_);
2468  geo_debug_assert(t < nb());
2469  geo_debug_assert(lf < 4);
2470  geo_debug_assert(lv < 3);
2471  return cell_corners_.vertex(
2472  4 * t + local_tet_facet_vertex_index(lf,lv)
2473  );
2474  }
2475 
2490  index_t t, index_t v1, index_t v2, index_t v3
2491  ) const {
2492  geo_debug_assert(is_simplicial_);
2493  for(index_t lf = 0; lf < 4; ++lf) {
2494  index_t w1 = tet_facet_vertex(t, lf, 0);
2495  index_t w2 = tet_facet_vertex(t, lf, 1);
2496  index_t w3 = tet_facet_vertex(t, lf, 2);
2497  if(
2498  (v1 == w1 && v2 == w2 && v3 == w3) ||
2499  (v1 == w2 && v2 == w3 && v3 == w1) ||
2500  (v1 == w3 && v2 == w1 && v3 == w2)
2501  ) {
2502  return lf;
2503  }
2504  }
2505  return NO_FACET;
2506  }
2507 
2517  geo_debug_assert(lf < 4);
2518  geo_debug_assert(lv < 3);
2519  return MeshCellDescriptors::tet_descriptor.facet_vertex[lf][lv];
2520  }
2521 
2522  protected:
2523 
2531  if(is_simplicial_) {
2532  is_simplicial_ = false;
2533  cell_ptr_.resize(nb()+1);
2534  cell_type_.assign(nb(), MESH_TET);
2535  for(index_t c=0; c<cell_ptr_.size(); ++c) {
2536  cell_ptr_[c] = 4*c;
2537  }
2538  }
2539  }
2540 
2553  index_t c1, index_t f1, index_t c2, index_t f2
2554  ) const;
2555 
2565  geo_debug_assert(c < nb());
2566  geo_debug_assert(v < vertices_.nb());
2567  for(index_t lv=0; lv<nb_vertices(c); ++lv) {
2568  if(vertex(c,lv) == v) {
2569  return lv;
2570  }
2571  }
2572  return NO_VERTEX;
2573  }
2574 
2587  index_t c1, index_t c2, index_t f2
2588  ) const {
2589  for(index_t f1=0; f1<nb_facets(c1); ++f1) {
2590  if(facets_match(c1,f1,c2,f2)) {
2591  return f1;
2592  }
2593  }
2594  return NO_FACET;
2595  }
2596 
2610  index_t c1, index_t lf1,
2611  index_t c2, index_t lf2
2612  ) const;
2613 
2614 
2629  index_t c1, index_t f1,
2630  index_t c2, index_t f2,
2631  index_t& e1, index_t& e2
2632  ) const;
2633 
2653  index_t c1, index_t lf1,
2654  const std::vector< std::pair<index_t, index_t> >& matches
2655  );
2656 
2662 
2663  protected:
2664  MeshVertices& vertices_;
2665  MeshCellCornersStore& cell_corners_;
2666  MeshCellFacetsStore& cell_facets_;
2667  friend class Mesh;
2668  friend class GeogramIOHandler;
2669  };
2670 
2671  /*************************************************************************/
2672 
2681  MESH_NONE = 0,
2682  MESH_VERTICES = 1,
2683  MESH_FACETS = 2,
2684  MESH_EDGES = 4,
2685  MESH_CELLS = 8,
2686  MESH_ALL_ELEMENTS = 15,
2687  MESH_FACET_CORNERS = 16,
2688  MESH_CELL_CORNERS = 32,
2689  MESH_CELL_FACETS = 64,
2690  MESH_ALL_SUBELEMENTS = 65
2691  };
2692 
2693  /*************************************************************************/
2694 
2701  class GEOGRAM_API Mesh {
2702  public:
2703  MeshVertices vertices;
2704  MeshEdges edges;
2705  MeshFacets facets;
2706  MeshFacetCornersStore facet_corners;
2707  MeshCells cells;
2708  MeshCellCornersStore cell_corners;
2709  MeshCellFacetsStore cell_facets;
2710 
2718  Mesh(index_t dimension=3, bool single_precision=false);
2719 
2723  virtual ~Mesh();
2724 
2735  void clear(bool keep_attributes=true, bool keep_memory=false);
2736 
2740  void show_stats(const std::string& tag = "Mesh") const;
2741 
2742 
2751 
2752 
2763  void copy(
2764  const Mesh& rhs,
2765  bool copy_attributes=true,
2766  MeshElementsFlags what=MESH_ALL_ELEMENTS
2767  );
2768 
2769 
2774  std::string get_attributes() const;
2775 
2782  std::string get_scalar_attributes() const;
2783 
2790  std::string get_vector_attributes(index_t max_dim = 0) const;
2791 
2797 
2805 
2813 
2814 
2822 
2830  MeshElementsFlags what
2831  ) const;
2832 
2840 
2849  const std::string& name
2850  );
2851 
2867  const std::string& full_attribute_name,
2868  MeshElementsFlags& where,
2869  std::string& attribute_name,
2870  index_t& component
2871  );
2872 
2873  protected:
2882  const std::string& tag, const std::string& subelement_name,
2883  const MeshSubElementsStore& subelements
2884  ) const;
2885 
2886  private:
2894  Mesh(const Mesh& rhs);
2895 
2903  const Mesh& operator=(const Mesh& rhs);
2904  };
2905 
2906  /*************************************************************************/
2907 }
2908 
2909 #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.
Managers a set of attributes attached to an object.
Definition: attributes.h:834
index_t size() const
Gets the size.
Definition: attributes.h:869
Stores the cell corners of a mesh (low-level store)
Definition: mesh.h:1749
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:1793
void set_vertex(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition: mesh.h:1768
index_t vertex(index_t c) const
Gets the vertex that a corner is incident to.
Definition: mesh.h:1758
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
index_t * vertex_index_ptr(index_t c)
Gets a pointer to the vertex that a corner is incident to.
Definition: mesh.h:1781
Stores the cell facets of a mesh (low-level store)
Definition: mesh.h:1839
index_t adjacent_cell(index_t f) const
Gets a cell adjacent to a facet.
Definition: mesh.h:1853
const index_t * adjacent_cell_ptr(index_t f) const
Gets a const pointer to a cell adjacent to a facet.
Definition: mesh.h:1877
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:1888
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
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:1865
Stores the cells of a mesh (low-level store)
Definition: mesh.h:1538
index_t facet(index_t c, index_t lf) const
Gets a facet of a cell by local facet index.
Definition: mesh.h:1684
bool are_simplices() const
Tests whether all the cells are tetrahedra.
Definition: mesh.h:1549
index_t corner(index_t c, index_t lv) const
Gets a corner of a cell by local vertex index.
Definition: mesh.h:1636
index_t nb_facets(index_t c) const
Gets the number of facets of a cell.
Definition: mesh.h:1651
index_t corners_end(index_t c) const
Gets the upper limit for iterating over the corners of a cell.
Definition: mesh.h:1625
MeshCellType type(index_t c) const
Gets the type of a cell.
Definition: mesh.h:1559
index_t facets_end(index_t c) const
Gets the upper limit for iterating over the facets of a cell.
Definition: mesh.h:1673
const CellDescriptor & descriptor(index_t c) const
Gets the descriptor of a cell.
Definition: mesh.h:1572
index_t nb_corners(index_t c) const
Gets the number of corners of a cell.
Definition: mesh.h:1603
index_t corners_begin(index_t c) const
Gets the first element for iterating over the corners of a cell.
Definition: mesh.h:1614
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.
Definition: mesh.h:1695
static const CellDescriptor & cell_type_to_cell_descriptor(MeshCellType t)
Gets a descriptor by cell type.
Definition: mesh.h:1591
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:1662
The cells of a mesh.
Definition: mesh.h:1935
index_t create_cells(index_t nb_cells, MeshCellType type)
Creates a contiguous chunk of cells of the same type.
Definition: mesh.h:2096
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:1968
index_t create_pyramids(index_t nb_pyramids)
Creates a contiguous chunk of pyramids.
Definition: mesh.h:2173
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:1979
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.
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:2334
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:2464
index_range corners(index_t c) const
Gets the corners of a cell.
Definition: mesh.h:2069
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:2040
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:2516
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:2259
index_t nb_vertices(index_t c) const
Gets the number of vertices of a cell.
Definition: mesh.h:1948
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:2013
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:2297
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:2489
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:2530
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:2027
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:2564
index_t create_hexes(index_t nb_hexes)
Creates a contiguous chunk of hexahedra.
Definition: mesh.h:2155
index_t create_tets(index_t nb_tets)
Creates a contiguous chunk of tetrahedra.
Definition: mesh.h:2146
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:2058
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:1990
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:2164
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:2185
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:2217
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:2000
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_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:2586
index_t vertex(index_t c, index_t lv) const
Gets a vertex of a cell by local vertex index.
Definition: mesh.h:1958
The edges of a mesh.
Definition: mesh.h:626
index_t vertex(index_t e, index_t lv) const
Gets the index of an edge vertex.
Definition: mesh.h:637
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
void pop() override
Removes the last element.
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:700
index_t create_edge()
Creates a new edge.
Definition: mesh.h:682
void permute_elements(vector< index_t > &permutation) override
Applies a permutation to the elements and their attributes.
index_t * vertex_index_ptr(index_t c)
Gets a pointer to a vertex index by corner index.
Definition: mesh.h:662
const index_t * vertex_index_ptr(index_t c) const
Gets a pointer to a vertex index by corner index.
Definition: mesh.h:673
index_t create_edges(index_t nb)
Creates a batch of edges.
Definition: mesh.h:691
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:649
Base class for mesh elements.
Definition: mesh.h:243
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:302
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:867
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
index_t adjacent_facet(index_t c) const
Gets the facet that a corner is adjacent to.
Definition: mesh.h:887
void clear_store(bool keep_attributes, bool keep_memory=false) override
Removes all the elements and attributes.
void set_vertex_no_check(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition: mesh.h:939
index_t vertex(index_t c) const
Gets the vertex that a corner is incident to.
Definition: mesh.h:876
void set_adjacent_facet(index_t c, index_t f)
Sets the facet that a corner is adjacent to.
Definition: mesh.h:950
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:899
index_t * vertex_index_ptr(index_t c)
Gets a pointer to the vertex that a corner is incident to.
Definition: mesh.h:963
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:912
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:975
void set_vertex(index_t c, index_t v)
Sets the vertex that a corner is incident to.
Definition: mesh.h:923
Stores the facets of a mesh (low-level store)
Definition: mesh.h:753
index_t corner(index_t f, index_t lv) const
Gets a corner by facet and local vertex index.
Definition: mesh.h:796
index_t corners_end(index_t f) const
Gets the upper limit for iterating over the corners of a facet.
Definition: mesh.h:774
index_t nb_corners(index_t f) const
Gets the number of corners in a facet.
Definition: mesh.h:784
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.
Definition: mesh.h:809
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:819
index_t corners_begin(index_t f) const
Gets the first element for iterating over the corners of a facet.
Definition: mesh.h:763
The facets of a mesh.
Definition: mesh.h:1028
index_t create_triangle(index_t v1, index_t v2, index_t v3)
Creates a triangle.
Definition: mesh.h:1261
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:1282
index_t create_polygon(const vector< index_t > &vertices)
Creates a polygonal facet.
Definition: mesh.h:1344
void is_not_simplicial()
Indicates that the stored elements are no longer only triangles.
Definition: mesh.h:1447
void triangulate()
Triangulates the facets.
MeshFacets(Mesh &mesh)
MeshFacets constructor.
index_t vertex(index_t f, index_t lv) const
Gets a vertex by facet and local vertex index.
Definition: mesh.h:1054
index_t find_edge(index_t f, index_t v1, index_t v2)
Finds an edge by vertex indices.
Definition: mesh.h:1172
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:1233
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:1043
void is_simplicial()
Indicates that the stored elements are only triangles.
Definition: mesh.h:1433
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:1300
index_t create_polygon(index_t nb_vertices, const index_t *vertices)
Creates a polygonal facet.
Definition: mesh.h:1322
void set_vertex(index_t f, index_t lv, index_t v)
Sets a vertex by facet and local vertex index.
Definition: mesh.h:1065
index_t find_common_vertex(index_t f1, index_t f2) const
finds a common vertex shared by two facets
Definition: mesh.h:1091
index_range corners(index_t f) const
Gets the corners of a facet.
Definition: mesh.h:1420
void pop() override
Removes the last element.
index_t find_vertex(index_t f, index_t v) const
Gets the local index of a vertex in a facet.
Definition: mesh.h:1076
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:1119
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:1159
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:1252
index_t create_facets(index_t nb_facets, index_t nb_vertices_per_polygon)
Creates a contiguous chunk of facets.
Definition: mesh.h:1203
index_t adjacent(index_t f, index_t le) const
Gets an adjacent facet by facet and local edge index.
Definition: mesh.h:1108
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:1135
index_t create_triangles(index_t nb_triangles)
Creates a contiguous chunk of triangles.
Definition: mesh.h:1243
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:1146
Base class for mesh sub-element storage.
Definition: mesh.h:70
index_as_iterator begin() const
Used by range-based for.
Definition: mesh.h:108
virtual ~MeshSubElementsStore()
MeshElementStore destructor.
MeshSubElementsStore(Mesh &mesh)
Constructs a new MeshSubElementStore.
index_t create_sub_element()
Creates attributes for a sub-element.
Definition: mesh.h:180
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:159
index_t nb() const
Gets the number of (sub-)elements.
Definition: mesh.h:89
void reserve_store(index_t nb_to_reserve)
Reserves space for new elements.
Definition: mesh.h:148
index_as_iterator end() const
Used by range-based for.
Definition: mesh.h:116
void copy(const MeshSubElementsStore &rhs, bool copy_attributes=true)
Copies a MeshSubElementsStore into this one.
Definition: mesh.h:214
void adjust_store()
Makes the size of the store tightly match the number of the elements.
Definition: mesh.h:201
AttributesManager & attributes() const
Gets the attributes manager.
Definition: mesh.h:100
virtual void resize_store(index_t new_size)
Resizes this MeshSubElementsStore.
The vertices of a mesh.
Definition: mesh.h:323
void pop() override
Removes the last element.
void resize_store(index_t new_size) override
Resizes this MeshSubElementsStore.
const double * point_ptr(index_t v) const
Gets a point.
Definition: mesh.h:455
void clear(bool keep_attributes=true, bool keep_memory=false) override
Removes all the elements and attributes.
float * single_precision_point_ptr(index_t v)
Gets a (single-precision) point.
Definition: mesh.h:523
index_t create_vertex(const double *coords)
Creates a new vertex.
Definition: mesh.h:353
void assign_points(const double *points, index_t dim, index_t nb_pts)
Assigns all the points.
const vec3 & point(index_t v) const
Gets a point.
Definition: mesh.h:496
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:440
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.
const float * single_precision_point_ptr(index_t v) const
Gets a (single-precision) point.
Definition: mesh.h:510
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:419
bool single_precision() const
Tests whether vertices are stored in single-precision mode.
Definition: mesh.h:408
index_t dimension() const
Gets the dimension of the vertices.
Definition: mesh.h:427
index_t create_vertices(index_t nb)
Creates a contiguous chunk of vertices.
Definition: mesh.h:375
double * point_ptr(index_t v)
Gets a point.
Definition: mesh.h:468
void set_single_precision()
Sets single precision mode.
vec3 & point(index_t v)
Gets a point.
Definition: mesh.h:482
index_t create_vertex()
Creates a new vertex.
Definition: mesh.h:344
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:2701
const MeshSubElementsStore & get_subelements_by_index(index_t i) const
Gets a MeshSubElementsStore by index.
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:2680
index_t nb_subelements_types() const
Gets the number of subelements types.
void assert_is_valid()
Does some validity checks.
MeshSubElementsStore & get_subelements_by_type(MeshElementsFlags what)
Gets a MeshSubElementsStore by subelements type.
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.
virtual ~Mesh()
Mesh destructor.
std::string get_attributes() const
Gets the list of all attributes.
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.
MeshSubElementsStore & get_subelements_by_index(index_t i)
Gets a MeshSubElementsStore by index.
const MeshSubElementsStore & get_subelements_by_type(MeshElementsFlags what) const
Gets a MeshSubElementsStore by subelements type.
std::string get_vector_attributes(index_t max_dim=0) const
Gets the list of all vector attributes.
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
T * data()
Gets a pointer to the array of elements.
Definition: memory.h:774
index_t size() const
Gets the number of elements.
Definition: memory.h:674
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
geo_index_t index_t
The type for storing and manipulating indices.
Definition: numeric.h:329
void tessellate_facets(Mesh &M, index_t max_nb_vertices)
Subdivides the facets with more than nb_vertices.
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:1483
index_t nb_vertices_in_facet[6]
Definition: mesh.h:1491
index_t facet_vertex[6][4]
Definition: mesh.h:1496
index_t nb_vertices
Definition: mesh.h:1485
index_t nb_facets
Definition: mesh.h:1488
index_t edge_adjacent_facet[12][2]
Definition: mesh.h:1510
index_t nb_edges
Definition: mesh.h:1500
index_t edge_vertex[12][2]
Definition: mesh.h:1505