16 const Eigen::Matrix<T, 3, 1>& p1,
17 const Eigen::Matrix<T, 3, 1>& p2,
18 const Eigen::Matrix<T, 3, 1>& p3,
19 const Eigen::Matrix<T, 3, 1>& p4)
21 const auto v = ((p2 - p1).cross(p3 - p1)).dot(p4 - p1);
22 return v == 0 ? 0 : (v < 0 ? -1 : 1);
27 const Eigen::Matrix<double, 3, 1>& p1,
28 const Eigen::Matrix<double, 3, 1>& p2,
29 const Eigen::Matrix<double, 3, 1>& p3,
30 const Eigen::Matrix<double, 3, 1>& p4);
34T cross_2d(
const Eigen::Matrix<T, 2, 1>& p1,
const Eigen::Matrix<T, 2, 1>& p2)
36 return p1.homogeneous().cross(p2.homogeneous()).z();
42 const Eigen::Matrix<T, 2, 1>& p1,
43 const Eigen::Matrix<T, 2, 1>& p2,
44 const Eigen::Matrix<T, 2, 1>& p3)
46 const auto det = cross_2d<T>(p2 - p1, p3 - p1);
47 return det == 0 ? 0 : (det < 0 ? -1 : 1);
52 const Eigen::Matrix<double, 2, 1>& p1,
53 const Eigen::Matrix<double, 2, 1>& p2,
54 const Eigen::Matrix<double, 2, 1>& p3);
56template <
typename T,
bool EarlyOut = false>
57std::optional<std::tuple<Eigen::Matrix<T, 3, 1>,
bool>> open_segment_triangle_intersection_3d(
58 const std::array<Eigen::Matrix<T, 3, 1>, 2>& seg,
59 const std::array<Eigen::Matrix<T, 3, 1>, 3>& tri)
61 std::optional<std::tuple<Eigen::Matrix<T, 3, 1>,
bool>> ret_value = std::nullopt;
62 const auto& [e0, e1] = seg;
63 const auto& [t0, t1, t2] = tri;
67 auto det = [](
const auto& u,
const auto& v,
const auto& w) -> T {
return u.cross(v).dot(w); };
68 auto detsum = [det](
const auto& E,
const auto& a,
const auto& b,
const auto& c) -> T {
69 return det(E, a, b) + det(E, c, a) + det(E, b, c);
72 const T d_0 = detsum(e0, t0, t1, t2);
73 const T d_1 = detsum(e1, t0, t1, t2);
74 const T d = d_0 - d_1;
75 const T D = det(t0, t1, t2);
79 if (d == 0)
return ret_value;
82 const T t = (d_0 - D) / d;
84 const bool t_outside = t <= 0 || t >= 1;
85 if (t_outside)
return ret_value;
87 const T u = (detsum(e0, e1, t0, t2) + det(e1, t0, t2)) / d;
89 const bool u_outside = u < 0 || u > 1;
90 if constexpr (EarlyOut)
91 if (u_outside)
return ret_value;
93 const T v = (detsum(e0, e1, t0, t1) - det(e1, t0, t1)) / d;
94 const bool v_outside = v < 0 || v > 1;
95 if constexpr (EarlyOut)
96 if (v_outside)
return ret_value;
97 const bool uv_outside = u + v > 1;
98 if constexpr (EarlyOut)
99 if (uv_outside)
return ret_value;
102 auto& [p, is_inside] = ret_value.emplace();
103 p = (1 - t) * e0 + t * e1;
104 is_inside = u_outside || v_outside || uv_outside;
110bool open_segment_triangle_intersection_3d(
111 const std::array<Eigen::Matrix<T, 3, 1>, 2>& seg,
112 const std::array<Eigen::Matrix<T, 3, 1>, 3>& tri,
113 Eigen::Matrix<T, 3, 1>& p)
115 auto ret_opt = open_segment_triangle_intersection_3d<T, true>(seg, tri);
116 if (!ret_opt.has_value()) {
119 p = std::get<0>(ret_opt.value());
124bool open_segment_plane_intersection_3d(
125 const std::array<Eigen::Matrix<T, 3, 1>, 2>& seg,
126 const std::array<Eigen::Matrix<T, 3, 1>, 3>& tri,
127 Eigen::Matrix<T, 3, 1>& p,
130 auto ret_opt = open_segment_triangle_intersection_3d<T, false>(seg, tri);
131 if (!ret_opt.has_value()) {
134 std::tie(p, is_inside) = ret_opt.value();
139bool segment_triangle_coplanar_3d(
140 const std::array<Eigen::Matrix<T, 3, 1>, 2>& seg,
141 const std::array<Eigen::Matrix<T, 3, 1>, 3>& tri)
143 const auto o1 = orient3d_t(seg[0], tri[0], tri[1], tri[2]);
144 const auto o2 = orient3d_t(seg[1], tri[0], tri[1], tri[2]);
146 return o1 == 0 && o2 == 0;
151bool open_segment_open_segment_intersection_2d(
152 const std::array<Eigen::Matrix<T, 2, 1>, 2>& seg_1,
153 const std::array<Eigen::Matrix<T, 2, 1>, 2>& seg_2,
156 const auto o1 = orient2d_t(seg_1[0], seg_2[0], seg_2[1]);
157 const auto o2 = orient2d_t(seg_1[1], seg_2[0], seg_2[1]);
160 if (o1 == 0 && o2 == 0)
169 const auto o3 = orient2d_t(seg_2[0], seg_1[0], seg_1[1]);
170 const auto o4 = orient2d_t(seg_2[1], seg_1[0], seg_1[1]);
175 const Eigen::Matrix<T, 2, 1> e1 = seg_1[1] - seg_1[0];
176 const Eigen::Matrix<T, 2, 1> e2 = seg_2[1] - seg_2[0];
177 t1 = cross_2d<T>(seg_2[0] - seg_1[0], e2) / cross_2d(e1, e2);
185int project_to_2d_by_normal(
const Eigen::Matrix<T, 3, 1>& n)
189 for (
int j = 0; j < 3; j++) {
190 if (abs(n[j]) > max) {
200int project_triangle_to_2d(
201 const std::array<Eigen::Matrix<T, 3, 1>, 3>& points3,
202 std::array<Eigen::Matrix<T, 2, 1>, 3>& points2)
204 const auto& p1 = points3[0];
205 const auto& p2 = points3[1];
206 const auto& p3 = points3[2];
208 Eigen::Matrix<T, 3, 1> n = (p2 - p1).cross(p3 - p1);
210 int J = project_to_2d_by_normal(n);
212 for (
int i = 0; i < points3.size(); i++) {
214 points2[i] = Eigen::Matrix<T, 2, 1>(points3[i][1], points3[i][2]);
216 points2[i] = Eigen::Matrix<T, 2, 1>(points3[i][0], points3[i][2]);
218 points2[i] = Eigen::Matrix<T, 2, 1>(points3[i][0], points3[i][1]);
226Eigen::Matrix<T, 2, 1> project_point_to_2d(
const Eigen::Matrix<T, 3, 1>& p,
int t)
229 return Eigen::Matrix<T, 2, 1>(p[1], p[2]);
231 return Eigen::Matrix<T, 2, 1>(p[0], p[2]);
233 return Eigen::Matrix<T, 2, 1>(p[0], p[1]);
237bool is_point_inside_triangle(
238 const Eigen::Matrix<T, 2, 1>& p,
239 const std::array<Eigen::Matrix<T, 2, 1>, 3>& tri)
250 auto res1 = orient2d_t(p, tri[0], tri[1]);
251 auto res2 = orient2d_t(p, tri[1], tri[2]);
252 auto res3 = orient2d_t(p, tri[2], tri[0]);
254 if (res1 == 0 && res2 == 0)
return true;
255 if (res1 == 0 && res3 == 0)
return true;
256 if (res2 == 0 && res3 == 0)
return true;
258 if ((res1 == res2 && res2 == res3) || (res1 == 0 && res2 == res3) ||
259 (res2 == 0 && res3 == res1) || (res3 == 0 && res2 == res1))