4#include <igl/writeMESH.h>
6#include <boost/filesystem.hpp>
18 const Eigen::RowVector3d &kernel, Eigen::MatrixXd &OV, Eigen::MatrixXi &OF, Eigen::MatrixXi &OT)
20 assert(
V.cols() == 3);
21 OV.resize(
V.rows() + 1,
V.cols());
22 OV.topRows(
V.rows()) =
V;
23 OV.bottomRows(1) = kernel;
25 OT.resize(OF.rows(), 4);
26 OT.col(0).setConstant(
V.rows());
35#ifdef POLYFEM_WITH_MMG
38 const int max_num_quadrature_points = 2048;
40 bool mmg_remesh_volume(
const Eigen::MatrixXd &
V,
const Eigen::MatrixXi &
F,
const Eigen::MatrixXi &T,
41 Eigen::MatrixXd &TV, Eigen::MatrixXi &TF, Eigen::MatrixXi &TT)
43 using namespace boost;
45 double scaling = (
V.colwise().maxCoeff() -
V.colwise().minCoeff()).maxCoeff();
46 Eigen::RowVector3d translation =
V.colwise().minCoeff();
48 auto tmp_dir = filesystem::temp_directory_path();
49 auto base_path = tmp_dir / filesystem::unique_path(
"polyfem_%%%%-%%%%-%%%%-%%%%");
50 auto f_input = base_path;
51 f_input +=
"_in.mesh";
52 auto f_output = base_path;
53 f_output +=
"_out.mesh";
54 auto f_sol = base_path;
57 TV = (
V.rowwise() - translation) / scaling;
58 igl::writeMESH(f_input.string(), TV, T,
F);
60 std::string app(POLYFEM_MMG_PATH);
61 std::string cmd = app +
" -ar 20 -hausd 0.01 -v 0 -in " + f_input.string() +
" -out " + f_output.string();
63 cmd +=
" &> /dev/null";
65 logger().trace(
"Running command:\n {}", cmd);
66 if (::system(cmd.c_str()) == 0)
69 GEO::mesh_load(f_output.string(), M);
71 TV = (scaling * TV).rowwise() + translation;
73 filesystem::remove(f_input);
74 filesystem::remove(f_output);
75 filesystem::remove(f_sol);
80 filesystem::remove(f_input);
87 template <
class TriMat>
88 double transform_pts(
const TriMat &tri,
const Eigen::MatrixXd &pts, Eigen::MatrixXd &transformed)
90 Eigen::Matrix3d matrix;
91 matrix.row(0) = tri.row(1) - tri.row(0);
92 matrix.row(1) = tri.row(2) - tri.row(0);
93 matrix.row(2) = tri.row(3) - tri.row(0);
95 transformed = pts * matrix;
97 transformed.col(0).array() += tri(0, 0);
98 transformed.col(1).array() += tri(0, 1);
99 transformed.col(2).array() += tri(0, 2);
101 return matrix.determinant();
109 const Eigen::RowVector3d &kernel,
const int order,
Quadrature &quadr)
111 std::string flags =
"Qpq2.0";
113 Eigen::MatrixXd VV, OV, TV;
114 Eigen::MatrixXi OF, TF, tets;
121 double scaling = (
V.colwise().maxCoeff() -
V.colwise().minCoeff()).maxCoeff();
122 Eigen::RowVector3d translation =
V.colwise().minCoeff();
126#ifdef POLYFEM_WITH_MMG
127 if (tet_quadr_pts.
weights.size() * tets.rows() > max_num_quadrature_points)
130 Eigen::MatrixXi F0, T0;
131 bool res = mmg_remesh_volume(TV, TF, tets,
V0, F0, T0);
133 if (res && T0.rows() < tets.rows())
142 const long offset = tet_quadr_pts.
weights.rows();
143 quadr.
points.resize(tets.rows() * offset, 3);
144 quadr.
weights.resize(tets.rows() * offset, 1);
146 Eigen::MatrixXd transformed_points;
148 for (
long i = 0; i < tets.rows(); ++i)
150 Eigen::Matrix<double, 4, 3> tetra;
151 const auto &indices = tets.row(i);
152 tetra.row(0) = TV.row(indices(0));
153 tetra.row(1) = TV.row(indices(1));
154 tetra.row(2) = TV.row(indices(2));
155 tetra.row(3) = TV.row(indices(3));
161 const double det = transform_pts(tetra, tet_quadr_pts.
points, transformed_points);
164 quadr.
points.block(i * offset, 0, transformed_points.rows(), transformed_points.cols()) = transformed_points;
static void get_quadrature(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::RowVector3d &kernel, const int order, Quadrature &quadr)
Gets the quadrature points & weights for a polyhedron.
void get_quadrature(const int order, Quadrature &quad)
void from_geogram_mesh(const GEO::Mesh &M, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &T)
Extract simplices from a Geogram mesh.
spdlog::logger & logger()
Retrieves the current logger.
void tertrahedralize_star_shaped_surface(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::RowVector3d &kernel, Eigen::MatrixXd &OV, Eigen::MatrixXi &OF, Eigen::MatrixXi &OT)
Tetrahedralize a star-shaped mesh, with a given point in its kernel.