8#include <geogram/mesh/mesh.h>
9#include <geogram/mesh/mesh_io.h>
11#include <igl/read_triangle_mesh.h>
21 Eigen::MatrixXi padded_elements(
const std::vector<std::vector<int>> &elements)
24 for (
const auto &element : elements)
25 width = std::max(width, int(element.size()));
26 Eigen::MatrixXi result;
27 result.setConstant(elements.size(), width, -1);
28 for (
int i = 0; i < elements.size(); ++i)
29 for (
int j = 0; j < elements[i].size(); ++j)
30 result(i, j) = elements[i][j];
34 Eigen::MatrixXd geogram_vertices(
const GEO::Mesh &mesh,
const int dimension)
36 Eigen::MatrixXd
vertices(mesh.vertices.nb(), dimension);
37 for (
int i = 0; i <
vertices.rows(); ++i)
38 for (
int d = 0; d < dimension; ++d)
39 vertices(i, d) = mesh.vertices.point(i)[d];
43 void finalize_surface(SurfaceMeshData &surface)
45 std::vector<bool> used(surface.vertices.rows(),
false);
46 for (
int i = 0; i < surface.edges.rows(); ++i)
47 for (
int j = 0; j < surface.edges.cols(); ++j)
48 used[surface.edges(i, j)] =
true;
49 for (
int i = 0; i < surface.faces.rows(); ++i)
50 for (
int j = 0; j < surface.faces.cols(); ++j)
51 used[surface.faces(i, j)] =
true;
52 const int count = std::count(used.begin(), used.end(),
false);
53 surface.points.resize(count);
54 for (
int i = 0,
point = 0; i < used.size(); ++i)
56 surface.points[
point++] = i;
62 Eigen::MatrixXd vertices;
63 Eigen::MatrixXi cells;
64 std::vector<std::vector<int>> higher_order_connectivity;
65 std::vector<std::vector<double>>
weights;
66 std::vector<int> body_ids;
67 std::vector<std::vector<int>> boundary_elements;
68 std::vector<int> boundary_ids;
70 path.string(), vertices, cells, higher_order_connectivity,
weights,
71 body_ids, boundary_elements, boundary_ids))
74 MeshData data(std::move(vertices), std::move(cells));
92 int encoded_cell_count = 0;
93 if (!(input >> vertex_count >> face_count >> encoded_cell_count)
94 || vertex_count <= 0 || face_count <= 0 || encoded_cell_count <= 0 || encoded_cell_count % 3 != 0)
96 const int cell_count = encoded_cell_count / 3;
98 Eigen::MatrixXd vertices(vertex_count, 3);
99 for (
int i = 0; i < vertex_count; ++i)
100 if (!(input >> vertices(i, 0) >> vertices(i, 1) >> vertices(i, 2)))
103 std::vector<std::vector<int>>
faces(face_count);
104 for (
auto &face :
faces)
107 if (!(input >> size) || size < 3)
110 for (
int &vertex : face)
112 if (!(input >> vertex))
114 if (vertex < 0 || vertex >= vertex_count)
115 log_and_throw_error(
"Invalid HYBRID face vertex {} in {}: expected an index in [0, {}).", vertex, description, vertex_count);
119 std::vector<std::vector<int>> cell_faces(cell_count);
120 std::vector<std::vector<int>> orientations(cell_count);
121 std::vector<std::vector<int>> elements(cell_count);
122 for (
int i = 0; i < cell_count; ++i)
125 if (!(input >> face_size) || face_size <= 0)
127 cell_faces[i].resize(face_size);
128 for (
int &face : cell_faces[i])
129 if (!(input >> face) || face < 0 || face >= face_count)
132 int orientation_size = 0;
133 if (!(input >> orientation_size) || orientation_size != face_size)
135 orientations[i].resize(orientation_size);
136 for (
int &orientation : orientations[i])
137 if (!(input >> orientation))
140 std::set<int> vertices_in_cell;
141 for (
const int face : cell_faces[i])
142 vertices_in_cell.insert(
faces[face].begin(),
faces[face].end());
143 elements[i].assign(vertices_in_cell.begin(), vertices_in_cell.end());
146 std::vector<bool> cell_is_hex(cell_count);
147 for (
int i = 0; i < cell_count; ++i)
150 if (!(input >> value))
152 cell_is_hex[i] = value != 0;
155 Eigen::MatrixXd kernels(cell_count, 3);
161 if (marker !=
"KERNEL" || !(input >> count) || count != cell_count)
163 for (
int i = 0; i < cell_count; ++i)
164 if (!(input >> kernels(i, 0) >> kernels(i, 1) >> kernels(i, 2)))
172 for (
int i = 0; i < cell_count; ++i)
174 for (
const int vertex : elements[i])
175 kernels.row(i) += vertices.row(vertex);
176 kernels.row(i) /= elements[i].size();
179 MeshData data(std::move(vertices), padded_elements(elements));
192 if (!GEO::mesh_load(path.string(), mesh))
201 std::vector<std::vector<int>> elements(mesh.facets.nb());
202 for (
int i = 0; i < elements.size(); ++i)
204 elements[i].resize(mesh.facets.nb_vertices(i));
205 for (
int j = 0; j < elements[i].size(); ++j)
206 elements[i][j] = mesh.facets.vertex(i, j);
208 return MeshData(geogram_vertices(mesh, 2), padded_elements(elements));
211 if (mesh.cells.nb() != 0)
213 std::vector<std::vector<int>> elements(mesh.cells.nb());
214 for (
int i = 0; i < elements.size(); ++i)
216 elements[i].resize(mesh.cells.nb_vertices(i));
217 for (
int j = 0; j < elements[i].size(); ++j)
218 elements[i][j] = mesh.cells.vertex(i, j);
219 if (mesh.cells.type(i) == GEO::MESH_HEX)
223 std::swap(elements[i][0], elements[i][1]);
224 std::swap(elements[i][4], elements[i][5]);
227 return MeshData(geogram_vertices(mesh, 3), padded_elements(elements));
230 if (mesh.facets.nb() == 0)
232 std::vector<std::vector<int>>
faces(mesh.facets.nb());
233 std::set<int> used_vertices;
234 for (
int i = 0; i <
faces.size(); ++i)
236 faces[i].resize(mesh.facets.nb_vertices(i));
237 for (
int j = 0; j <
faces[i].size(); ++j)
239 faces[i][j] = mesh.facets.vertex(i, j);
240 used_vertices.insert(
faces[i][j]);
243 std::vector<std::vector<int>> elements(1);
244 elements[0].assign(used_vertices.begin(), used_vertices.end());
245 MeshData data(geogram_vertices(mesh, 3), padded_elements(elements));
253 const int last = mesh.vertices.nb() - 1;
254 if (used_vertices.find(last) == used_vertices.end())
259 for (
const int vertex : elements[0])
269 Eigen::MatrixXi cells;
270 std::vector<std::vector<int>> elements;
271 std::vector<std::vector<double>>
weights;
272 std::vector<int> body_ids;
276 if (cells.cols() == 1)
278 else if (cells.cols() == 2)
279 result.
edges = cells;
280 else if (cells.cols() == 3)
281 result.
faces = cells;
282 else if (cells.cols() == 4 && result.
vertices.cols() == 3)
284 Eigen::MatrixXd surface_vertices;
287 result.
vertices = std::move(surface_vertices);
292 finalize_surface(result);
301 finalize_surface(result);
306 const std::filesystem::path &path,
310 if (!igl::read_triangle_mesh(path.string(), result.
vertices, result.
faces))
312 finalize_surface(result);
319 if (!GEO::mesh_load(path.string(), mesh))
321 if (mesh.facets.nb() == 0)
326 const int width = mesh.facets.nb_vertices(0);
327 result.
faces.resize(mesh.facets.nb(), width);
328 for (
int i = 0; i < result.
faces.rows(); ++i)
330 if (mesh.facets.nb_vertices(i) != width)
332 for (
int j = 0; j < width; ++j)
333 result.
faces(i, j) = mesh.facets.vertex(i, j);
335 finalize_surface(result);
std::vector< Eigen::VectorXi > faces
static bool load(const std::string &path, Eigen::MatrixXd &vertices, Eigen::MatrixXi &cells, std::vector< std::vector< int > > &elements, std::vector< std::vector< double > > &weights, std::vector< int > &body_ids)
static bool read(const std::string obj_file_name, std::vector< std::vector< double > > &V, std::vector< std::vector< double > > &TC, std::vector< std::vector< double > > &N, std::vector< std::vector< int > > &F, std::vector< std::vector< int > > &FTC, std::vector< std::vector< int > > &FN, std::vector< std::vector< int > > &L)
Read a mesh from an ascii obj file.
Format-independent input used to construct a runtime Mesh.
Eigen::MatrixXd higher_order_nodes
std::vector< std::vector< int > > higher_order_connectivity
std::vector< std::vector< int > > boundary_elements
std::vector< std::vector< int > > faces
Optional topology for arbitrary polyhedral cells.
std::vector< int > body_ids
bool elements_are_ordered
Whether each element row carries a format-defined local vertex order.
std::vector< int > boundary_ids
Eigen::MatrixXd cell_kernel_points
std::vector< std::vector< int > > cell_faces
std::vector< std::vector< int > > cell_face_orientations
std::vector< std::vector< double > > higher_order_weights
std::vector< bool > cell_is_hex
static MeshData read_hybrid(std::istream &input, const std::string &description)
static MeshData read_msh(const std::filesystem::path &path)
static bool read_triangle_surface(const std::filesystem::path &path, SurfaceMeshData &result)
static SurfaceMeshData read_geogram_surface(const std::filesystem::path &path)
static SurfaceMeshData read_obj_surface(const std::filesystem::path &path)
static SurfaceMeshData read_msh_surface(const std::filesystem::path &path)
static MeshData read_geogram(const std::filesystem::path &path)
static MeshData from_geogram(GEO::Mesh &mesh)
bool is_planar(const GEO::Mesh &M, const double tol=1e-5)
Determine if the given mesh is planar (2D or tiny z-range).
void extract_triangle_surface_from_tets(const Eigen::MatrixXd &vertices, const Eigen::MatrixXi &tets, Eigen::MatrixXd &surface_vertices, Eigen::MatrixXi &tris)
Extract triangular surface from a tetmesh.
void log_and_throw_error(const std::string &msg)