PolyFEM
Loading...
Searching...
No Matches
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 std::cout << "Running command:\n" + cmd << std::endl;
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 // std::cout << "points per tet: "<< tet_quadr_pts.weights.size()<< std::endl;
121 // std::cout << "#T before: " << tets.rows() << std::endl;
122 // std::cout << "#T after: " << T0.rows() << std::endl;
123 // std::cout << "res: "<< res << std::endl;
124
125 if (res && T0.rows() < tets.rows())
126 {
127 TV = V0;
128 TF = F0;
129 tets = T0;
130 }
131 }
132#endif
133
134 // igl::write_triangle_mesh("poly_current.obj", VV, F);
135 // igl::simplify_polyhedron(VV, F, OV, OF, J);
136 // igl::write_triangle_mesh("poly_out.obj", OV, OF);
137
138 // OV = (OV * scaling).rowwise() + translation;
139 // int res = igl::copyleft::tetgen::tetrahedralize(V, F, flags, TV, tets, TF);
140 // std::cout << "tetgen out" << std::endl;
141 // assert(res == 0);
142
143 // static int counter = 0;
144 // std::stringstream ss;
145 // ss << std::setw(6) << std::setfill('0') << counter++;
146 // std::string s = ss.str();
147
148 // if (res != 0) {
149 // std::cerr << "Tetgen did not succeed. Returned code: " << res << std::endl;
150 // igl::write_triangle_mesh("poly_" + s + ".obj", V, F);
151 // } else {
152 // igl::writeMESH("tet_" ".mesh", TV, tets, TF);
153 // }
154
155 // GEO::Mesh M;
156 // GEO::mesh_load("tet_.o.mesh", M);
157 // from_geogram_mesh(M, TV, TF, tets);
158 // std::cout << tets.rows() << std::endl;
159
160 // std::cout << "volume: " << volume(M) << std::endl;
161
162 const long offset = tet_quadr_pts.weights.rows();
163 quadr.points.resize(tets.rows() * offset, 3);
164 quadr.weights.resize(tets.rows() * offset, 1);
165
166 Eigen::MatrixXd transformed_points;
167
168 for (long i = 0; i < tets.rows(); ++i)
169 {
170 Eigen::Matrix<double, 4, 3> tetra;
171 const auto &indices = tets.row(i);
172 tetra.row(0) = TV.row(indices(0));
173 tetra.row(1) = TV.row(indices(1));
174 tetra.row(2) = TV.row(indices(2));
175 tetra.row(3) = TV.row(indices(3));
176
177 // viewer.data.add_edges(triangle.row(0), triangle.row(1), Eigen::Vector3d(1,0,0).transpose());
178 // viewer.data.add_edges(triangle.row(0), triangle.row(2), Eigen::Vector3d(1,0,0).transpose());
179 // viewer.data.add_edges(triangle.row(2), triangle.row(1), Eigen::Vector3d(1,0,0).transpose());
180
181 const double det = transform_pts(tetra, tet_quadr_pts.points, transformed_points);
182 assert(det > 0);
183
184 quadr.points.block(i * offset, 0, transformed_points.rows(), transformed_points.cols()) = transformed_points;
185 quadr.weights.block(i * offset, 0, tet_quadr_pts.weights.rows(), tet_quadr_pts.weights.cols()) = tet_quadr_pts.weights * det;
186 }
187
188 // assert(quadr.weights.minCoeff() >= 0);
189 // std::cout<<"#quadrature points: " << quadr.weights.size()<<" "<<quadr.weights.sum()<<std::endl;
190 }
191 } // namespace quadrature
192} // 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.