build_mesh_from_cell_complex.h
1 /* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2  * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3  * Author(s): Siargey Kachanovich
4  *
5  * Copyright (C) 2019 Inria
6  *
7  * Modification(s):
8  * - YYYY/MM Author: Description of the modification
9  */
10 
11 #ifndef IO_BUILD_MESH_FROM_CELL_COMPLEX_H_
12 #define IO_BUILD_MESH_FROM_CELL_COMPLEX_H_
13 
14 #include <gudhi/IO/output_debug_traces_to_html.h> // for DEBUG_TRACES
15 #include <gudhi/IO/Mesh_medit.h>
16 
17 #include <Eigen/Dense>
18 
19 #include <cstdlib> // for std::size_t
20 #include <map>
21 #include <set>
22 #include <string>
23 #include <utility> // for std::make_pair
24 #include <algorithm> // for std::min
25 
26 namespace Gudhi {
27 
28 namespace coxeter_triangulation {
29 
30 struct Configuration {
31  Configuration(bool t_edges, bool t_triangles, bool t_tetrahedra, std::size_t r_edges, std::size_t r_triangles,
32  std::size_t r_tetrahedra)
33  : toggle_edges(t_edges),
34  toggle_triangles(t_triangles),
35  toggle_tetrahedra(t_tetrahedra),
36  ref_edges(r_edges),
37  ref_triangles(r_triangles),
38  ref_tetrahedra(r_tetrahedra) {}
39 
40  Configuration() {}
41 
42  bool toggle_edges = true, toggle_triangles = true, toggle_tetrahedra = true;
43  std::size_t ref_edges = 1, ref_triangles = 1, ref_tetrahedra = 1;
44 };
45 
46 template <class Hasse_cell, class Simplex_cell_map>
47 void populate_mesh(Mesh_medit& output, Simplex_cell_map& sc_map, Configuration configuration, std::size_t amb_d,
48  std::map<Hasse_cell*, std::size_t> vi_map) {
49  using Mesh_element_vertices = Mesh_medit::Mesh_elements::value_type::first_type;
50  std::map<Hasse_cell*, std::size_t> ci_map;
51  std::size_t index = vi_map.size() + 1; // current size of output.vertex_points
52  if (sc_map.size() >= 3)
53  for (const auto& sc_pair : sc_map[2]) {
54  Eigen::VectorXd barycenter = Eigen::VectorXd::Zero(amb_d);
55  std::set<std::size_t> vertex_indices;
56  Hasse_cell* cell = sc_pair.second;
57  for (const auto& ei_pair : cell->get_boundary())
58  for (const auto& vi_pair : ei_pair.first->get_boundary()) vertex_indices.emplace(vi_map[vi_pair.first]);
59  for (const std::size_t& v : vertex_indices) barycenter += output.vertex_points[v - 1];
60  ci_map.emplace(cell, index++);
61  output.vertex_points.emplace_back((1. / vertex_indices.size()) * barycenter);
62 #ifdef DEBUG_TRACES
63  std::string vlist = " (" + std::to_string(index - 1) + ")";
64  for (const std::size_t& v : vertex_indices) vlist += " " + std::to_string(v);
65  cell_vlist_map.emplace(to_string(cell), vlist);
66 #endif
67  }
68 
69  if (configuration.toggle_edges && sc_map.size() >= 2)
70  for (const auto& sc_pair : sc_map[1]) {
71  Hasse_cell* edge_cell = sc_pair.second;
72  Mesh_element_vertices edge;
73  for (const auto& vi_pair : edge_cell->get_boundary()) edge.push_back(vi_map[vi_pair.first]);
74  output.edges.emplace_back(edge, configuration.ref_edges);
75 #ifdef DEBUG_TRACES
76  std::string vlist;
77  for (const std::size_t& v : edge) vlist += " " + std::to_string(v);
78  cell_vlist_map.emplace(to_string(edge_cell), vlist);
79 #endif
80  }
81 
82  if (configuration.toggle_triangles && sc_map.size() >= 3)
83  for (const auto& sc_pair : sc_map[2]) {
84  for (const auto& ei_pair : sc_pair.second->get_boundary()) {
85  Mesh_element_vertices triangle(1, ci_map[sc_pair.second]);
86  for (const auto& vi_pair : ei_pair.first->get_boundary()) triangle.push_back(vi_map[vi_pair.first]);
87  output.triangles.emplace_back(triangle, configuration.ref_triangles);
88  }
89  }
90 
91  if (configuration.toggle_tetrahedra && sc_map.size() >= 4)
92  for (const auto& sc_pair : sc_map[3]) {
93  Eigen::VectorXd barycenter = Eigen::VectorXd::Zero(amb_d);
94  std::set<std::size_t> vertex_indices;
95  Hasse_cell* cell = sc_pair.second;
96  for (const auto& ci_pair : cell->get_boundary())
97  for (const auto& ei_pair : ci_pair.first->get_boundary())
98  for (const auto& vi_pair : ei_pair.first->get_boundary()) vertex_indices.emplace(vi_map[vi_pair.first]);
99  for (const std::size_t& v : vertex_indices) barycenter += output.vertex_points[v - 1];
100  output.vertex_points.emplace_back((1. / vertex_indices.size()) * barycenter);
101 #ifdef DEBUG_TRACES
102  std::string vlist = " (" + std::to_string(index) + ")";
103  for (const std::size_t& v : vertex_indices) vlist += " " + std::to_string(v);
104  cell_vlist_map.emplace(to_string(cell), vlist);
105 #endif
106 
107  for (const auto& ci_pair : cell->get_boundary())
108  for (const auto& ei_pair : ci_pair.first->get_boundary()) {
109  Mesh_element_vertices tetrahedron = {index, ci_map[sc_pair.second]};
110  for (const auto& vi_pair : ei_pair.first->get_boundary()) tetrahedron.push_back(vi_map[vi_pair.first]);
111  output.tetrahedra.emplace_back(tetrahedron, configuration.ref_tetrahedra);
112  }
113  index++;
114  }
115 }
116 
121 template <class Cell_complex>
123  Configuration i_configuration = Configuration(),
124  Configuration b_configuration = Configuration()) {
125  using Hasse_cell = typename Cell_complex::Hasse_cell;
126  Mesh_medit output;
127  std::map<Hasse_cell*, std::size_t> vi_map; // one for vertices, other for 2d-cells
128  std::size_t index = 1; // current size of output.vertex_points
129 
130  if (cell_complex.cell_point_map().empty()) return output;
131  std::size_t amb_d = std::min((int)cell_complex.cell_point_map().begin()->second.size(), 3);
132 
133  for (const auto& cp_pair : cell_complex.cell_point_map()) {
134 #ifdef DEBUG_TRACES
135  std::string vlist;
136  vlist += " " + std::to_string(index);
137  cell_vlist_map.emplace(to_string(cp_pair.first), vlist);
138 #endif
139  vi_map.emplace(cp_pair.first, index++);
140  output.vertex_points.push_back(cp_pair.second);
141  output.vertex_points.back().conservativeResize(amb_d);
142  }
143 
144  populate_mesh(output, cell_complex.interior_simplex_cell_maps(), i_configuration, amb_d, vi_map);
145 #ifdef DEBUG_TRACES
146  for (const auto& sc_map : cell_complex.interior_simplex_cell_maps())
147  for (const auto& sc_pair : sc_map) {
148  std::string simplex = "I" + to_string(sc_pair.first);
149  std::string cell = to_string(sc_pair.second);
150  std::string vlist = cell_vlist_map.at(cell).substr(1);
151  simplex_vlist_map.emplace(simplex, vlist);
152  }
153 #endif
154  populate_mesh(output, cell_complex.boundary_simplex_cell_maps(), b_configuration, amb_d, vi_map);
155 #ifdef DEBUG_TRACES
156  for (const auto& sc_map : cell_complex.boundary_simplex_cell_maps())
157  for (const auto& sc_pair : sc_map) {
158  std::string simplex = "B" + to_string(sc_pair.first);
159  std::string cell = to_string(sc_pair.second);
160  std::string vlist = cell_vlist_map.at(cell).substr(1);
161  simplex_vlist_map.emplace(simplex, vlist);
162  }
163 #endif
164  return output;
165 }
166 
167 } // namespace coxeter_triangulation
168 
169 } // namespace Gudhi
170 
171 #endif
A class that constructs the cell complex from the output provided by the class Gudhi::coxeter_triangu...
Definition: Cell_complex.h:38
const Cell_point_map & cell_point_map() const
Returns a map from the vertex cells in the cell complex of type Gudhi::Hasse_cell to their Cartesian ...
Definition: Cell_complex.h:315
const Simplex_cell_maps & boundary_simplex_cell_maps() const
Returns a vector of maps from the cells of various dimensions on the boundary of the cell complex of ...
Definition: Cell_complex.h:280
Gudhi::Hasse_diagram::Hasse_diagram_cell< int, double, bool > Hasse_cell
Type of a cell in the cell complex. Always is Gudhi::Hasse_cell from the Hasse diagram module....
Definition: Cell_complex.h:49
const Simplex_cell_maps & interior_simplex_cell_maps() const
Returns a vector of maps from the cells of various dimensions in the interior of the cell complex of ...
Definition: Cell_complex.h:273
Mesh_medit build_mesh_from_cell_complex(const Cell_complex &cell_complex, Configuration i_configuration=Configuration(), Configuration b_configuration=Configuration())
Builds a Gudhi::coxeter_triangulation::Mesh_medit from a Gudhi::coxeter_triangulation::Cell_complex.
Definition: build_mesh_from_cell_complex.h:122
Structure to store a mesh that can be output in Medit .mesh file format using the output_meshes_to_me...
Definition: Mesh_medit.h:29
Vertex_points vertex_points
Range of vertices of type Eigen::VectorXd to output.
Definition: Mesh_medit.h:43