5#include <Eigen/Geometry>
7#include <igl/barycentric_coordinates.h>
9#include <ipc/distance/point_edge.hpp>
10#include <ipc/distance/point_triangle.hpp>
15 const Eigen::Vector2d &a,
16 const Eigen::Vector2d &b,
17 const Eigen::Vector2d &c)
19 return ((b.x() - a.x()) * (c.y() - a.y()) - (c.x() - a.x()) * (b.y() - a.y())) / 2.0;
23 const Eigen::Vector3d &a,
24 const Eigen::Vector3d &b,
25 const Eigen::Vector3d &c)
27 return (b - a).cross(c - a).norm() / 2.0;
32 assert(
V.rows() == 3);
44 const Eigen::Vector3d &a,
45 const Eigen::Vector3d &b,
46 const Eigen::Vector3d &c,
47 const Eigen::Vector3d &d)
49 return (b - a).cross(c - a).dot(d - a) / 6.0;
54 assert(
V.rows() == 4 &&
V.cols() == 3);
66 Eigen::Matrix<double, 3, 2> triangle_clockwise;
67 triangle_clockwise.row(0) =
triangle.row(2);
68 triangle_clockwise.row(1) =
triangle.row(1);
69 triangle_clockwise.row(2) =
triangle.row(0);
71 return triangle_clockwise;
74 std::vector<Eigen::MatrixXd>
triangle_fan(
const Eigen::MatrixXd &convex_polygon)
76 assert(convex_polygon.rows() >= 3);
77 std::vector<Eigen::MatrixXd> triangles;
78 for (
int i = 1; i < convex_polygon.rows() - 1; ++i)
80 triangles.emplace_back(3, convex_polygon.cols());
81 triangles.back().row(0) = convex_polygon.row(0);
82 triangles.back().row(1) = convex_polygon.row(i);
83 triangles.back().row(2) = convex_polygon.row(i + 1);
89 const Eigen::VectorXd &p,
90 const Eigen::MatrixXd &
V)
92 Eigen::MatrixXd A(p.size() + 1, p.size() + 1);
93 A.topRows(p.size()) =
V.transpose();
94 A.bottomRows(1).setOnes();
96 Eigen::VectorXd rhs(p.size() + 1);
97 rhs.topRows(p.size()) = p;
98 rhs.bottomRows(1).setOnes();
101 const Eigen::VectorXd bc = A.partialPivLu().solve(rhs);
102 assert((A * bc - rhs).norm() / rhs.norm() < 1e-12);
108 const Eigen::Vector2d &t0,
109 const Eigen::Vector2d &t1,
110 const Eigen::Vector2d &t2,
111 const Eigen::Vector2d ¢er,
114 Eigen::RowVector3d bc;
115 igl::barycentric_coordinates(
116 center.transpose(), t0.transpose(), t1.transpose(), t2.transpose(),
119 if (bc.minCoeff() >= 0)
121 assert(bc.maxCoeff() <= 1 + 1e-12);
125 const double radius_sqr = radius * radius;
127 if (ipc::point_edge_distance(center, t0, t1) <= radius_sqr
128 || ipc::point_edge_distance(center, t1, t2) <= radius_sqr
129 || ipc::point_edge_distance(center, t2, t0) <= radius_sqr)
138 const Eigen::Vector3d &t0,
139 const Eigen::Vector3d &t1,
140 const Eigen::Vector3d &t2,
141 const Eigen::Vector3d &t3,
142 const Eigen::Vector3d ¢er,
145 Eigen::RowVector4d bc;
146 igl::barycentric_coordinates(
147 center.transpose(), t0.transpose(), t1.transpose(),
148 t2.transpose(), t3.transpose(), bc);
150 if (bc.minCoeff() >= 0)
152 assert(bc.maxCoeff() <= 1 + 1e-12);
156 const double radius_sqr = radius * radius;
158 if (ipc::point_triangle_distance(center, t0, t1, t2) <= radius_sqr
159 || ipc::point_triangle_distance(center, t0, t1, t3) <= radius_sqr
160 || ipc::point_triangle_distance(center, t0, t2, t3) <= radius_sqr
161 || ipc::point_triangle_distance(center, t1, t2, t3) <= radius_sqr)
176 assert((ea0 - ea1).norm() != 0 && (eb1 - eb0).norm() != 0);
177 const VectorNd ea = (ea1 - ea0).normalized();
178 const VectorNd eb = (eb1 - eb0).normalized();
179 return abs(ea.dot(eb)) > 1 - tol;
183 const Eigen::Vector3d &t00,
184 const Eigen::Vector3d &t01,
185 const Eigen::Vector3d &t02,
186 const Eigen::Vector3d &t10,
187 const Eigen::Vector3d &t11,
188 const Eigen::Vector3d &t12,
191 const Eigen::Vector3d n0 = (t01 - t00).
cross(t02 - t00).normalized();
192 const Eigen::Vector3d n1 = (t11 - t10).
cross(t12 - t10).normalized();
193 return abs(n0.dot(n1)) > 1 - tol;
202 return (aabb0_min.array() <= aabb1_max.array()).all() && (aabb1_min.array() <= aabb0_max.array()).all();
213 g[0] = (1.0 / 2.0) * by + (1.0 / 2.0) * t0;
214 g[1] = -1.0 / 2.0 * bx - 1.0 / 2.0 * t1;
215 g[2] = -1.0 / 2.0 * ay - 1.0 / 2.0 * t0;
216 g[3] = (1.0 / 2.0) * ax + (1.0 / 2.0) * t1;
217 g[4] = (1.0 / 2.0) * (ay - by);
218 g[5] = (1.0 / 2.0) * (-ax + bx);
261 void tetrahedron_volume_gradient(
double ax,
double ay,
double az,
double bx,
double by,
double bz,
double cx,
double cy,
double cz,
double dx,
double dy,
double dz,
double g[12])
263 const auto t0 = az - dz;
265 const auto t2 = by + t1;
266 const auto t3 = ay - dy;
268 const auto t5 = bz + t4;
269 const auto t6 = ay - by;
270 const auto t7 = az + t4;
271 const auto t8 = ay + t1;
272 const auto t9 = az - bz;
273 const auto t10 = t6 * t7 - t8 * t9;
274 const auto t11 = -cx;
275 const auto t12 = bx + t11;
276 const auto t13 = ax - dx;
277 const auto t14 = ax - bx;
278 const auto t15 = ax + t11;
279 const auto t16 = t14 * t7 - t15 * t9;
280 const auto t17 = t14 * t8 - t15 * t6;
281 g[0] = -1.0 / 6.0 * t0 * t2 - 1.0 / 6.0 * t10 + (1.0 / 6.0) * t3 * t5;
282 g[1] = (1.0 / 6.0) * t0 * t12 - 1.0 / 6.0 * t13 * t5 + (1.0 / 6.0) * t16;
283 g[2] = -1.0 / 6.0 * t12 * t3 + (1.0 / 6.0) * t13 * t2 - 1.0 / 6.0 * t17;
284 g[3] = (1.0 / 6.0) * t0 * t8 - 1.0 / 6.0 * t3 * t7;
285 g[4] = -1.0 / 6.0 * t0 * t15 + (1.0 / 6.0) * t13 * t7;
286 g[5] = -1.0 / 6.0 * t13 * t8 + (1.0 / 6.0) * t15 * t3;
287 g[6] = -1.0 / 6.0 * t0 * t6 + (1.0 / 6.0) * t3 * t9;
288 g[7] = (1.0 / 6.0) * t0 * t14 - 1.0 / 6.0 * t13 * t9;
289 g[8] = (1.0 / 6.0) * t13 * t6 - 1.0 / 6.0 * t14 * t3;
290 g[9] = (1.0 / 6.0) * t10;
291 g[10] = -1.0 / 6.0 * t16;
292 g[11] = (1.0 / 6.0) * t17;
295 void tetrahedron_volume_hessian(
double ax,
double ay,
double az,
double bx,
double by,
double bz,
double cx,
double cy,
double cz,
double dx,
double dy,
double dz,
double H[144])
298 const auto t1 = cz + t0;
299 const auto t2 = -1.0 / 6.0 * t1;
301 const auto t4 = cy + t3;
302 const auto t5 = (1.0 / 6.0) * t4;
303 const auto t6 = bz + t0;
304 const auto t7 = (1.0 / 6.0) * t6;
305 const auto t8 = by + t3;
306 const auto t9 = -1.0 / 6.0 * t8;
307 const auto t10 = -cz;
308 const auto t11 = bz + t10;
309 const auto t12 = -1.0 / 6.0 * t11;
310 const auto t13 = -cy;
311 const auto t14 = by + t13;
312 const auto t15 = (1.0 / 6.0) * t14;
313 const auto t16 = (1.0 / 6.0) * t1;
314 const auto t17 = -dx;
315 const auto t18 = cx + t17;
316 const auto t19 = -1.0 / 6.0 * t18;
317 const auto t20 = -1.0 / 6.0 * t6;
318 const auto t21 = bx + t17;
319 const auto t22 = (1.0 / 6.0) * t21;
320 const auto t23 = (1.0 / 6.0) * t11;
321 const auto t24 = -cx;
322 const auto t25 = bx + t24;
323 const auto t26 = -1.0 / 6.0 * t25;
324 const auto t27 = -1.0 / 6.0 * t4;
325 const auto t28 = (1.0 / 6.0) * t18;
326 const auto t29 = (1.0 / 6.0) * t8;
327 const auto t30 = -1.0 / 6.0 * t21;
328 const auto t31 = -1.0 / 6.0 * t14;
329 const auto t32 = (1.0 / 6.0) * t25;
330 const auto t33 = az + t0;
331 const auto t34 = -1.0 / 6.0 * t33;
332 const auto t35 = ay + t3;
333 const auto t36 = (1.0 / 6.0) * t35;
334 const auto t37 = az + t10;
335 const auto t38 = (1.0 / 6.0) * t37;
336 const auto t39 = ay + t13;
337 const auto t40 = -1.0 / 6.0 * t39;
338 const auto t41 = (1.0 / 6.0) * t33;
339 const auto t42 = ax + t17;
340 const auto t43 = -1.0 / 6.0 * t42;
341 const auto t44 = -1.0 / 6.0 * t37;
342 const auto t45 = ax + t24;
343 const auto t46 = (1.0 / 6.0) * t45;
344 const auto t47 = -1.0 / 6.0 * t35;
345 const auto t48 = (1.0 / 6.0) * t42;
346 const auto t49 = (1.0 / 6.0) * t39;
347 const auto t50 = -1.0 / 6.0 * t45;
348 const auto t51 = az - bz;
349 const auto t52 = -1.0 / 6.0 * t51;
350 const auto t53 = ay - by;
351 const auto t54 = (1.0 / 6.0) * t53;
352 const auto t55 = (1.0 / 6.0) * t51;
353 const auto t56 = ax - bx;
354 const auto t57 = -1.0 / 6.0 * t56;
355 const auto t58 = -1.0 / 6.0 * t53;
356 const auto t59 = (1.0 / 6.0) * t56;
Eigen::Matrix< double, dim, 1 > cross(const Eigen::Matrix< double, dim, 1 > &x, const Eigen::Matrix< double, dim, 1 > &y)
bool tetrahedron_intersects_ball(const Eigen::Vector3d &t0, const Eigen::Vector3d &t1, const Eigen::Vector3d &t2, const Eigen::Vector3d &t3, const Eigen::Vector3d ¢er, const double radius)
Determine if a 3D tetrahedron intersects a 3D ball.
bool are_aabbs_intersecting(const VectorNd &aabb0_min, const VectorNd &aabb0_max, const VectorNd &aabb1_min, const VectorNd &aabb1_max)
Determine if two axis-aligned bounding boxes intersect.
void triangle_area_2D_hessian(double ax, double ay, double bx, double by, double cx, double cy, double H[36])
Compute the Hessian of the signed area of a 2D triangle defined by three points.
void tetrahedron_volume_gradient(double ax, double ay, double az, double bx, double by, double bz, double cx, double cy, double cz, double dx, double dy, double dz, double g[12])
Compute the gradient of the signed volume of a tetrahedron defined by four points.
void tetrahedron_volume_hessian(double ax, double ay, double az, double bx, double by, double bz, double cx, double cy, double cz, double dx, double dy, double dz, double H[144])
Compute the gradient of the signed area of a 2D triangle defined by three points.
double tetrahedron_volume(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c, const Eigen::Vector3d &d)
Compute the signed volume of a tetrahedron defined by four points.
void triangle_area_2D_gradient(double ax, double ay, double bx, double by, double cx, double cy, double g[6])
Compute the gradient of the signed area of a 2D triangle defined by three points.
bool are_edges_collinear(const VectorNd &ea0, const VectorNd &ea1, const VectorNd &eb0, const VectorNd &eb1, const double tol)
Determine if two edges are collinear.
double triangle_area_3D(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c)
Compute the area of a 3D triangle defined by three points.
Eigen::MatrixXd triangle_to_clockwise_order(const Eigen::MatrixXd &triangle)
Reorder the vertices of a triangle so they are in clockwise order.
std::vector< Eigen::MatrixXd > triangle_fan(const Eigen::MatrixXd &convex_polygon)
Convert a convex polygon to a list of triangles fanned around the first vertex.
bool are_triangles_coplanar(const Eigen::Vector3d &t00, const Eigen::Vector3d &t01, const Eigen::Vector3d &t02, const Eigen::Vector3d &t10, const Eigen::Vector3d &t11, const Eigen::Vector3d &t12, const double tol)
Determine if two triangles are coplanar.
Eigen::VectorXd barycentric_coordinates(const Eigen::VectorXd &p, const Eigen::MatrixXd &V)
Compute barycentric coordinates for point p with respect to a simplex.
double triangle_area(const Eigen::MatrixXd V)
Compute the signed area of a triangle defined by three points.
double triangle_area_2D(const Eigen::Vector2d &a, const Eigen::Vector2d &b, const Eigen::Vector2d &c)
Compute the signed area of a 2D triangle defined by three points.
bool triangle_intersects_disk(const Eigen::Vector2d &t0, const Eigen::Vector2d &t1, const Eigen::Vector2d &t2, const Eigen::Vector2d ¢er, const double radius)
Determine if a 2D triangle intersects a 2D disk.
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd