Loading [MathJax]/extensions/tex2jax.js
PolyFEM
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PolyhedronQuadrature.cpp
Go to the documentation of this file.
1
3#include "TetQuadrature.hpp"
5#include <geogram/mesh/mesh_io.h>
6#include <igl/writeMESH.h>
7#ifdef POLYFEM_WITH_MMG
8#include <boost/filesystem.hpp>
9#endif
10#include <vector>
11#include <cassert>
12#include <iostream>
14
15namespace polyfem
16{
17 namespace quadrature
18 {
19 namespace
20 {
21
22#ifdef POLYFEM_WITH_MMG
23
24 // try to remesh volume if polyhedron creates more than this # of quadrature points
25 const int max_num_quadrature_points = 2048;
26
27 bool mmg_remesh_volume(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, const Eigen::MatrixXi &T,
28 Eigen::MatrixXd &TV, Eigen::MatrixXi &TF, Eigen::MatrixXi &TT)
29 {
30 using namespace boost;
31
32 double scaling = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
33 Eigen::RowVector3d translation = V.colwise().minCoeff();
34
35 auto tmp_dir = filesystem::temp_directory_path();
36 auto base_path = tmp_dir / filesystem::unique_path("polyfem_%%%%-%%%%-%%%%-%%%%");
37 auto f_input = base_path;
38 f_input += "_in.mesh";
39 auto f_output = base_path;
40 f_output += "_out.mesh";
41 auto f_sol = base_path;
42 f_sol += "_out.sol";
43
44 TV = (V.rowwise() - translation) / scaling;
45 igl::writeMESH(f_input.string(), TV, T, F);
46
47 std::string app(POLYFEM_MMG_PATH);
48 std::string cmd = app + " -ar 20 -hausd 0.01 -v 0 -in " + f_input.string() + " -out " + f_output.string();
49#ifndef WIN32
50 cmd += " &> /dev/null";
51#endif
52 logger().trace("Running command:\n {}", cmd);
53 if (::system(cmd.c_str()) == 0)
54 {
55 GEO::Mesh M;
56 GEO::mesh_load(f_output.string(), M);
57 from_geogram_mesh(M, TV, TF, TT);
58 TV = (scaling * TV).rowwise() + translation;
59
60 filesystem::remove(f_input);
61 filesystem::remove(f_output);
62 filesystem::remove(f_sol);
63 return true;
64 }
65 else
66 {
67 filesystem::remove(f_input);
68 return false;
69 }
70 }
71
72#endif
73
74 template <class TriMat>
75 double transform_pts(const TriMat &tri, const Eigen::MatrixXd &pts, Eigen::MatrixXd &transformed)
76 {
77 Eigen::Matrix3d matrix;
78 matrix.row(0) = tri.row(1) - tri.row(0);
79 matrix.row(1) = tri.row(2) - tri.row(0);
80 matrix.row(2) = tri.row(3) - tri.row(0);
81
82 transformed = pts * matrix;
83
84 transformed.col(0).array() += tri(0, 0);
85 transformed.col(1).array() += tri(0, 1);
86 transformed.col(2).array() += tri(0, 2);
87
88 return matrix.determinant();
89 }
90
91 } // anonymous namespace
92
94
95 void PolyhedronQuadrature::get_quadrature(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F,
96 const Eigen::RowVector3d &kernel, const int order, Quadrature &quadr)
97 {
98 std::string flags = "Qpq2.0";
99 Eigen::VectorXi J;
100 Eigen::MatrixXd VV, OV, TV;
101 Eigen::MatrixXi OF, TF, tets;
102
103 Quadrature tet_quadr_pts;
104 TetQuadrature tet_quadr;
105 tet_quadr.get_quadrature(4, tet_quadr_pts);
106 // assert(tet_quadr_pts.weights.minCoeff() >= 0);
107
108 double scaling = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
109 Eigen::RowVector3d translation = V.colwise().minCoeff();
110
112
113#ifdef POLYFEM_WITH_MMG
114 if (tet_quadr_pts.weights.size() * tets.rows() > max_num_quadrature_points)
115 {
116 Eigen::MatrixXd V0;
117 Eigen::MatrixXi F0, T0;
118 bool res = mmg_remesh_volume(TV, TF, tets, V0, F0, T0);
119
120 if (res && T0.rows() < tets.rows())
121 {
122 TV = V0;
123 TF = F0;
124 tets = T0;
125 }
126 }
127#endif
128
129 const long offset = tet_quadr_pts.weights.rows();
130 quadr.points.resize(tets.rows() * offset, 3);
131 quadr.weights.resize(tets.rows() * offset, 1);
132
133 Eigen::MatrixXd transformed_points;
134
135 for (long i = 0; i < tets.rows(); ++i)
136 {
137 Eigen::Matrix<double, 4, 3> tetra;
138 const auto &indices = tets.row(i);
139 tetra.row(0) = TV.row(indices(0));
140 tetra.row(1) = TV.row(indices(1));
141 tetra.row(2) = TV.row(indices(2));
142 tetra.row(3) = TV.row(indices(3));
143
144 // viewer.data.add_edges(triangle.row(0), triangle.row(1), Eigen::Vector3d(1,0,0).transpose());
145 // viewer.data.add_edges(triangle.row(0), triangle.row(2), Eigen::Vector3d(1,0,0).transpose());
146 // viewer.data.add_edges(triangle.row(2), triangle.row(1), Eigen::Vector3d(1,0,0).transpose());
147
148 const double det = transform_pts(tetra, tet_quadr_pts.points, transformed_points);
149 assert(det > 0);
150
151 quadr.points.block(i * offset, 0, transformed_points.rows(), transformed_points.cols()) = transformed_points;
152 quadr.weights.block(i * offset, 0, tet_quadr_pts.weights.rows(), tet_quadr_pts.weights.cols()) = tet_quadr_pts.weights * det;
153 }
154
155 // assert(quadr.weights.minCoeff() >= 0);
156 }
157 } // namespace quadrature
158} // namespace polyfem
int V
Quadrature quadrature
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)
M
Definition eigs.py:94
void from_geogram_mesh(const GEO::Mesh &M, Eigen::MatrixXd &V, Eigen::MatrixXi &F, Eigen::MatrixXi &T)
Extract simplices from a Geogram mesh.
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.
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:44