ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
IntersectionTest.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "IntersectionTest.h"
9 
10 #include <tomasakeninemoeller/opttritri.h>
11 #include <tomasakeninemoeller/tribox3.h>
12 
13 namespace cloudViewer {
14 namespace utility {
15 
16 bool IntersectionTest::AABBAABB(const Eigen::Vector3d& min0,
17  const Eigen::Vector3d& max0,
18  const Eigen::Vector3d& min1,
19  const Eigen::Vector3d& max1) {
20  if (max0(0) < min1(0) || min0(0) > max1(0)) {
21  return false;
22  }
23  if (max0(1) < min1(1) || min0(1) > max1(1)) {
24  return false;
25  }
26  if (max0(2) < min1(2) || min0(2) > max1(2)) {
27  return false;
28  }
29  return true;
30 }
31 
32 bool IntersectionTest::TriangleTriangle3d(const Eigen::Vector3d& p0,
33  const Eigen::Vector3d& p1,
34  const Eigen::Vector3d& p2,
35  const Eigen::Vector3d& q0,
36  const Eigen::Vector3d& q1,
37  const Eigen::Vector3d& q2) {
38  const Eigen::Vector3d mu = (p0 + p1 + p2 + q0 + q1 + q2) / 6;
39  const Eigen::Vector3d sigma =
40  (((p0 - mu).array().square() + (p1 - mu).array().square() +
41  (p2 - mu).array().square() + (q0 - mu).array().square() +
42  (q1 - mu).array().square() + (q2 - mu).array().square()) /
43  5)
44  .sqrt() +
45  1e-12;
46  Eigen::Vector3d p0m = (p0 - mu).array() / sigma.array();
47  Eigen::Vector3d p1m = (p1 - mu).array() / sigma.array();
48  Eigen::Vector3d p2m = (p2 - mu).array() / sigma.array();
49  Eigen::Vector3d q0m = (q0 - mu).array() / sigma.array();
50  Eigen::Vector3d q1m = (q1 - mu).array() / sigma.array();
51  Eigen::Vector3d q2m = (q2 - mu).array() / sigma.array();
52  return NoDivTriTriIsect(p0m.data(), p1m.data(), p2m.data(), q0m.data(),
53  q1m.data(), q2m.data()) != 0;
54 }
55 
56 bool IntersectionTest::TriangleAABB(const Eigen::Vector3d& box_center,
57  const Eigen::Vector3d& box_half_size,
58  const Eigen::Vector3d& vert0,
59  const Eigen::Vector3d& vert1,
60  const Eigen::Vector3d& vert2) {
61  double* tri_verts[3] = {const_cast<double*>(vert0.data()),
62  const_cast<double*>(vert1.data()),
63  const_cast<double*>(vert2.data())};
64  return triBoxOverlap(const_cast<double*>(box_center.data()),
65  const_cast<double*>(box_half_size.data()),
66  tri_verts) != 0;
67 }
68 
69 bool IntersectionTest::PointsCoplanar(const Eigen::Vector3d& p0,
70  const Eigen::Vector3d& p1,
71  const Eigen::Vector3d& p2,
72  const Eigen::Vector3d& p3) {
73  return (p1 - p0).dot((p2 - p0).cross(p3 - p0)) < 1e-12;
74 }
75 
76 double IntersectionTest::LinesMinimumDistance(const Eigen::Vector3d& p1,
77  const Eigen::Vector3d& p2,
78  const Eigen::Vector3d& p3,
79  const Eigen::Vector3d& p4) {
80  constexpr double EPS = 1e-12;
81  Eigen::Vector3d p13 = p1 - p3;
82  Eigen::Vector3d p21 = p2 - p1;
83  // not a line, but a single point
84  if (std::abs(p21(0)) < EPS && std::abs(p21(1)) < EPS &&
85  std::abs(p21(2)) < EPS) {
86  return -1;
87  }
88  Eigen::Vector3d p43 = p4 - p3;
89  // not a line, but a single point
90  if (std::abs(p43(0)) < EPS && std::abs(p43(1)) < EPS &&
91  std::abs(p43(2)) < EPS) {
92  return -2;
93  }
94 
95  double d1343 = p13.dot(p43);
96  double d4321 = p43.dot(p21);
97  double d1321 = p13.dot(p21);
98  double d4343 = p43.dot(p43);
99  double d2121 = p21.dot(p21);
100 
101  double denominator = d2121 * d4343 - d4321 * d4321;
102  // lines are parallel
103  if (std::abs(denominator) < EPS) {
104  return -3;
105  }
106  double numerator = d1343 * d4321 - d1321 * d4343;
107 
108  double mua = numerator / denominator;
109  double mub = (d1343 + d4321 * mua) / d4343;
110 
111  Eigen::Vector3d pa = p1 + mua * p21;
112  Eigen::Vector3d pb = p3 + mub * p43;
113  double dist = (pa - pb).norm();
114  return dist;
115 }
116 
118  const Eigen::Vector3d& p0,
119  const Eigen::Vector3d& p1,
120  const Eigen::Vector3d& q0,
121  const Eigen::Vector3d& q1) {
122  const Eigen::Vector3d p10 = p1 - p0;
123  const Eigen::Vector3d q10 = q1 - q0;
124  const Eigen::Vector3d p0q0 = p0 - q0;
125  double a = p10.dot(p10);
126  double b = p10.dot(q10);
127  double c = q10.dot(q10);
128  double d = p10.dot(p0q0);
129  double e = q10.dot(p0q0);
130  // double f = p0q0.dot(p0q0);
131  double det = a * c - b * b;
132  double s, t;
133  if (det > 0) // non parallel segments
134  {
135  double bte = b * e;
136  double ctd = c * d;
137  if (bte <= ctd) {
138  if (e <= 0) {
139  s = (-d >= a ? 1 : (-d > 0 ? -d / a : 0));
140  t = 0;
141  } else if (e < c) {
142  s = 0;
143  t = e / c;
144  } else {
145  s = (b - d >= a ? 1 : (b - d > 0 ? (b - d) / a : 0));
146  t = 1;
147  }
148  } else {
149  s = bte - ctd;
150  if (s >= det) {
151  if (b + e <= 0) {
152  s = (-d <= 0 ? 0 : (-d < a ? -d / a : 1));
153  t = 0;
154  } else if (b + e < c) {
155  s = 1;
156  t = (b + e) / c;
157  } else {
158  s = (b - d <= 0 ? 0 : (b - d < a ? (b - d) / a : 1));
159  t = 1;
160  }
161  } else {
162  double ate = a * e;
163  double btd = b * d;
164  if (ate <= btd) {
165  s = (-d <= 0 ? 0 : (-d >= a ? 1 : -d / a));
166  t = 0;
167  } else {
168  t = ate - btd;
169  if (t >= det) {
170  s = (b - d <= 0 ? 0 : (b - d >= a ? 1 : (b - d) / a));
171  t = 1;
172  } else {
173  s /= det;
174  t /= det;
175  }
176  }
177  }
178  }
179  } else // parallel segments
180  {
181  if (e <= 0) {
182  s = (-d <= 0 ? 0 : (-d >= a ? 1 : -d / a));
183  t = 0;
184  } else if (e >= c) {
185  s = (b - d <= 0 ? 0 : (b - d >= a ? 1 : (b - d) / a));
186  t = 1;
187  } else {
188  s = 0;
189  t = e / c;
190  }
191  }
192 
193  Eigen::Vector3d p = (1 - s) * p0 + s * p1;
194  Eigen::Vector3d q = (1 - t) * q0 + t * q1;
195  double dist = (p - q).norm();
196  return dist;
197 }
198 
199 } // namespace utility
200 } // namespace cloudViewer
static double LinesMinimumDistance(const Eigen::Vector3d &p0, const Eigen::Vector3d &p1, const Eigen::Vector3d &q0, const Eigen::Vector3d &q1)
static double LineSegmentsMinimumDistance(const Eigen::Vector3d &p0, const Eigen::Vector3d &p1, const Eigen::Vector3d &q0, const Eigen::Vector3d &q1)
static bool TriangleTriangle3d(const Eigen::Vector3d &p0, const Eigen::Vector3d &p1, const Eigen::Vector3d &p2, const Eigen::Vector3d &q0, const Eigen::Vector3d &q1, const Eigen::Vector3d &q2)
static bool TriangleAABB(const Eigen::Vector3d &box_center, const Eigen::Vector3d &box_half_size, const Eigen::Vector3d &vert0, const Eigen::Vector3d &vert1, const Eigen::Vector3d &vert2)
static bool AABBAABB(const Eigen::Vector3d &min0, const Eigen::Vector3d &max0, const Eigen::Vector3d &min1, const Eigen::Vector3d &max1)
static bool PointsCoplanar(const Eigen::Vector3d &p0, const Eigen::Vector3d &p1, const Eigen::Vector3d &p2, const Eigen::Vector3d &p3)
Tests if the given four points all lie on the same plane.
__host__ __device__ float3 cross(float3 a, float3 b)
Definition: cutil_math.h:1295
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
static double dist(double x1, double y1, double x2, double y2)
Definition: lsd.c:207
constexpr float EPS
Definition: IoUImpl.h:20
Generic file read and write utility for python interface.