PolyFEM
Loading...
Searching...
No Matches
PolygonQuadrature.cpp
Go to the documentation of this file.
2#include "TriQuadrature.hpp"
3
4#include <igl/predicates/ear_clipping.h>
5#include <igl/write_triangle_mesh.h>
6
7#ifdef POLYFEM_WITH_TRIANGLE
8#include <igl/triangle/triangulate.h>
9#endif
10
11#include <vector>
12#include <cassert>
13#include <iostream>
14
15namespace polyfem
16{
17 namespace quadrature
18 {
19 namespace
20 {
21 template <class TriMat>
22 double transform_pts(const TriMat &tri, const Eigen::MatrixXd &pts, Eigen::MatrixXd &trafoed)
23 {
24 Eigen::Matrix2d trafo;
25 trafo.row(0) = tri.row(1) - tri.row(0);
26 trafo.row(1) = tri.row(2) - tri.row(0);
27
28 trafoed = pts * trafo;
29
30 trafoed.col(0).array() += tri(0, 0);
31 trafoed.col(1).array() += tri(0, 1);
32
33 return trafo.determinant();
34 }
35
36 void assign_quadrature(const Quadrature &tri_quadr_pts, const Eigen::MatrixXi &tris, const Eigen::MatrixXd pts, Quadrature &quadr)
37 {
38 Eigen::MatrixXd trafod_pts;
39 Eigen::Matrix<double, 3, 2> triangle;
40
41 const long offset = tri_quadr_pts.weights.rows();
42 quadr.points.resize(tris.rows() * offset, 2);
43 quadr.weights.resize(tris.rows() * offset, 1);
44
45 for (long i = 0; i < tris.rows(); ++i)
46 {
47 const auto &indices = tris.row(i);
48
49 triangle.row(0) = pts.row(indices(0));
50 triangle.row(1) = pts.row(indices(1));
51 triangle.row(2) = pts.row(indices(2));
52
53 const double det = transform_pts(triangle, tri_quadr_pts.points, trafod_pts);
54 quadr.points.block(i * offset, 0, trafod_pts.rows(), trafod_pts.cols()) = trafod_pts;
55 quadr.weights.block(i * offset, 0, tri_quadr_pts.weights.rows(), tri_quadr_pts.weights.cols()) = tri_quadr_pts.weights * det;
56 }
57 }
58 } // namespace
59
63
64 void PolygonQuadrature::get_quadrature(const Eigen::MatrixXd &poly, const int order, Quadrature &quadr)
65 {
66 Quadrature tri_quadr_pts;
67 TriQuadrature tri_quadr;
68 tri_quadr.get_quadrature(order, tri_quadr_pts);
69
70#ifdef POLYFEM_WITH_TRIANGLE
71 Eigen::MatrixXi E(poly.rows(), 2);
72 const Eigen::MatrixXd H(0, 2);
73 const std::string flags = "Qzqa0.01";
74
75 for (int i = 0; i < poly.rows(); ++i)
76 E.row(i) << i, (i + 1) % poly.rows();
77
78 Eigen::MatrixXi tris;
79 Eigen::MatrixXd pts;
80
81 igl::triangle::triangulate(poly, E, H, flags, pts, tris);
82 assign_quadrature(tri_quadr_pts, tris, pts, quadr);
83
84 Eigen::MatrixXd asd(pts.rows(), 3);
85 asd.col(0) = pts.col(0);
86 asd.col(1) = pts.col(1);
87 asd.col(2).setZero();
88 igl::write_triangle_mesh("quad.obj", asd, tris);
89
90#else
91 const int n_vertices = poly.rows();
92 double area = 0;
93 Eigen::Matrix2d tmp;
94
95 Eigen::MatrixXi tris(n_vertices, 3);
96 Eigen::MatrixXd pts(n_vertices + 1, 2);
97 pts.row(n_vertices) = poly.colwise().mean();
98
99 for (int e = 0; e < n_vertices; ++e)
100 {
101 const int ep = (e + 1) % n_vertices;
102 tris.row(e) << e, ep, n_vertices;
103 pts.row(e) = poly.row(e);
104
105 tmp.row(0) = poly.row(e);
106 tmp.row(1) = poly.row(ep);
107
108 area += tmp.determinant();
109 }
110
111 area = fabs(area);
112
113 assign_quadrature(tri_quadr_pts, tris, pts, quadr);
114
115 // polygon is concave
116 if (quadr.weights.minCoeff() < 0)
117 {
118 const Eigen::MatrixXi rt = Eigen::MatrixXi::Zero(poly.rows(), 1);
119 tris.resize(0, 0);
120 Eigen::VectorXi I;
121 igl::predicates::ear_clipping(poly, rt, tris, I);
122
123 assign_quadrature(tri_quadr_pts, tris, poly, quadr);
124 }
125#endif
126
127 assert(quadr.weights.minCoeff() >= 0);
128 }
129 } // namespace quadrature
130} // namespace polyfem
Quadrature quadrature
void get_quadrature(const Eigen::MatrixXd &poly, const int order, Quadrature &quadr)
Gets the quadrature points & weights for a polygon.
void get_quadrature(const int order, Quadrature &quad)
list indices
Definition p_bases.py:232