OGS
GeometricBasics.cpp
Go to the documentation of this file.
1 
10 #include "GeometricBasics.h"
11 
12 #include <Eigen/Dense>
13 
14 #include "BaseLib/Logging.h"
15 #include "Point3d.h"
16 
17 namespace MathLib
18 {
20  MathLib::Point3d const& a,
21  MathLib::Point3d const& b,
22  MathLib::Point3d const& c)
23 {
24  auto const pp = Eigen::Map<Eigen::Vector3d const>(p.getCoords());
25  auto const pa = Eigen::Map<Eigen::Vector3d const>(a.getCoords());
26  auto const pb = Eigen::Map<Eigen::Vector3d const>(b.getCoords());
27  auto const pc = Eigen::Map<Eigen::Vector3d const>(c.getCoords());
28 
29  Eigen::Vector3d const u = pp - pa;
30  Eigen::Vector3d const v = pp - pb;
31  Eigen::Vector3d const w = pp - pc;
32  return u.cross(v).dot(w);
33 }
34 
36  MathLib::Point3d const& b,
37  MathLib::Point3d const& c,
38  MathLib::Point3d const& d)
39 {
40  auto const va = Eigen::Map<Eigen::Vector3d const>(a.getCoords());
41  auto const vb = Eigen::Map<Eigen::Vector3d const>(b.getCoords());
42  auto const vc = Eigen::Map<Eigen::Vector3d const>(c.getCoords());
43  auto const vd = Eigen::Map<Eigen::Vector3d const>(d.getCoords());
44  Eigen::Vector3d const w = vb - va;
45  Eigen::Vector3d const u = vc - va;
46  Eigen::Vector3d const v = vd - va;
47  return std::abs(u.cross(v).dot(w)) / 6.0;
48 }
49 
51  MathLib::Point3d const& c)
52 {
53  auto const va = Eigen::Map<Eigen::Vector3d const>(a.getCoords());
54  auto const vb = Eigen::Map<Eigen::Vector3d const>(b.getCoords());
55  auto const vc = Eigen::Map<Eigen::Vector3d const>(c.getCoords());
56  Eigen::Vector3d const u = vc - va;
57  Eigen::Vector3d const v = vb - va;
58  Eigen::Vector3d const w = u.cross(v);
59  return 0.5 * w.norm();
60 }
61 
63  MathLib::Point3d const& b, MathLib::Point3d const& c,
64  MathLib::Point3d const& d, double eps)
65 {
66  double const d0(MathLib::orientation3d(d, a, b, c));
67  // if tetrahedron is not coplanar
68  if (std::abs(d0) > std::numeric_limits<double>::epsilon())
69  {
70  bool const d0_sign(d0 > 0);
71  // if p is on the same side of bcd as a
72  double const d1(MathLib::orientation3d(d, p, b, c));
73  if (!(d0_sign == (d1 >= 0) || std::abs(d1) < eps))
74  {
75  return false;
76  }
77  // if p is on the same side of acd as b
78  double const d2(MathLib::orientation3d(d, a, p, c));
79  if (!(d0_sign == (d2 >= 0) || std::abs(d2) < eps))
80  {
81  return false;
82  }
83  // if p is on the same side of abd as c
84  double const d3(MathLib::orientation3d(d, a, b, p));
85  if (!(d0_sign == (d3 >= 0) || std::abs(d3) < eps))
86  {
87  return false;
88  }
89  // if p is on the same side of abc as d
90  double const d4(MathLib::orientation3d(p, a, b, c));
91  return d0_sign == (d4 >= 0) || std::abs(d4) < eps;
92  }
93  return false;
94 }
95 
97  MathLib::Point3d const& a,
98  MathLib::Point3d const& b,
99  MathLib::Point3d const& c,
100  double eps_pnt_out_of_plane,
101  double eps_pnt_out_of_tri,
102  MathLib::TriangleTest algorithm)
103 {
104  switch (algorithm)
105  {
106  case MathLib::GAUSS:
107  return gaussPointInTriangle(p, a, b, c, eps_pnt_out_of_plane,
108  eps_pnt_out_of_tri);
110  return barycentricPointInTriangle(p, a, b, c, eps_pnt_out_of_plane,
111  eps_pnt_out_of_tri);
112  default:
113  ERR("Selected algorithm for point in triangle testing not found, "
114  "falling back on default.");
115  }
116  return gaussPointInTriangle(p, a, b, c, eps_pnt_out_of_plane,
117  eps_pnt_out_of_tri);
118 }
119 
121  MathLib::Point3d const& a,
122  MathLib::Point3d const& b,
123  MathLib::Point3d const& c,
124  double eps_pnt_out_of_plane,
125  double eps_pnt_out_of_tri)
126 {
127  auto const pa = Eigen::Map<Eigen::Vector3d const>(a.getCoords());
128  auto const pb = Eigen::Map<Eigen::Vector3d const>(b.getCoords());
129  auto const pc = Eigen::Map<Eigen::Vector3d const>(c.getCoords());
130  Eigen::Vector3d const v = pb - pa;
131  Eigen::Vector3d const w = pc - pa;
132 
133  Eigen::Matrix2d mat;
134  mat(0, 0) = v.squaredNorm();
135  mat(0, 1) = v[0] * w[0] + v[1] * w[1] + v[2] * w[2];
136  mat(1, 0) = mat(0, 1);
137  mat(1, 1) = w.squaredNorm();
138  Eigen::Vector2d y(
139  v[0] * (q[0] - a[0]) + v[1] * (q[1] - a[1]) + v[2] * (q[2] - a[2]),
140  w[0] * (q[0] - a[0]) + w[1] * (q[1] - a[1]) + w[2] * (q[2] - a[2]));
141 
142  y = mat.partialPivLu().solve(y);
143 
144  const double lower(eps_pnt_out_of_tri);
145  const double upper(1 + lower);
146 
147  if (-lower <= y[0] && y[0] <= upper && -lower <= y[1] && y[1] <= upper &&
148  y[0] + y[1] <= upper)
149  {
150  MathLib::Point3d const q_projected(std::array<double, 3>{
151  {a[0] + y[0] * v[0] + y[1] * w[0], a[1] + y[0] * v[1] + y[1] * w[1],
152  a[2] + y[0] * v[2] + y[1] * w[2]}});
153  if (MathLib::sqrDist(q, q_projected) <= eps_pnt_out_of_plane)
154  {
155  return true;
156  }
157  }
158 
159  return false;
160 }
161 
163  MathLib::Point3d const& a,
164  MathLib::Point3d const& b,
165  MathLib::Point3d const& c,
166  double eps_pnt_out_of_plane,
167  double eps_pnt_out_of_tri)
168 {
169  if (std::abs(MathLib::orientation3d(p, a, b, c)) > eps_pnt_out_of_plane)
170  {
171  return false;
172  }
173 
174  auto const vp = Eigen::Map<Eigen::Vector3d const>(p.getCoords());
175  auto const va = Eigen::Map<Eigen::Vector3d const>(a.getCoords());
176  auto const vb = Eigen::Map<Eigen::Vector3d const>(b.getCoords());
177  auto const vc = Eigen::Map<Eigen::Vector3d const>(c.getCoords());
178  Eigen::Vector3d const pa = va - vp;
179  Eigen::Vector3d const pb = vb - vp;
180  Eigen::Vector3d const pc = vc - vp;
181  double const area_x_2(calcTriangleArea(a, b, c) * 2);
182 
183  double const alpha((pb.cross(pc).norm()) / area_x_2);
184  if (alpha < -eps_pnt_out_of_tri || alpha > 1 + eps_pnt_out_of_tri)
185  {
186  return false;
187  }
188  double const beta((pc.cross(pa).norm()) / area_x_2);
189  if (beta < -eps_pnt_out_of_tri || beta > 1 + eps_pnt_out_of_tri)
190  {
191  return false;
192  }
193  double const gamma(1 - alpha - beta);
194  return !(gamma < -eps_pnt_out_of_tri || gamma > 1 + eps_pnt_out_of_tri);
195 }
196 
198  MathLib::Point3d const& a,
199  MathLib::Point3d const& b,
200  MathLib::Point3d const& c)
201 {
202  // criterion: p-a = u0 * (b-a) + u1 * (c-a); 0 <= u0, u1 <= 1, u0+u1 <= 1
203  Eigen::Matrix2d mat;
204  mat(0, 0) = b[0] - a[0];
205  mat(0, 1) = c[0] - a[0];
206  mat(1, 0) = b[1] - a[1];
207  mat(1, 1) = c[1] - a[1];
208  Eigen::Vector2d y;
209  y << p[0] - a[0], p[1] - a[1];
210 
211  y = mat.partialPivLu().solve(y);
212 
213  // check if u0 and u1 fulfills the condition
214  return 0 <= y[0] && y[0] <= 1 && 0 <= y[1] && y[1] <= 1 && y[0] + y[1] <= 1;
215 }
216 
218  const MathLib::Point3d& c, const MathLib::Point3d& d)
219 {
220  for (unsigned x = 0; x < 3; ++x)
221  {
222  const unsigned y = (x + 1) % 3;
223  const double abc =
224  (b[x] - a[x]) * (c[y] - a[y]) - (b[y] - a[y]) * (c[x] - a[x]);
225  const double abd =
226  (b[x] - a[x]) * (d[y] - a[y]) - (b[y] - a[y]) * (d[x] - a[x]);
227 
228  if ((abc > 0 && abd < 0) || (abc < 0 && abd > 0))
229  {
230  return true;
231  }
232  }
233  return false;
234 }
235 
237  const MathLib::Point3d& c, const MathLib::Point3d& d)
238 {
239  auto const pa = Eigen::Map<Eigen::Vector3d const>(a.getCoords());
240  auto const pb = Eigen::Map<Eigen::Vector3d const>(b.getCoords());
241  auto const pc = Eigen::Map<Eigen::Vector3d const>(c.getCoords());
242  auto const pd = Eigen::Map<Eigen::Vector3d const>(d.getCoords());
243 
244  Eigen::Vector3d const ab = pb - pa;
245  Eigen::Vector3d const ac = pc - pa;
246  Eigen::Vector3d const ad = pd - pa;
247 
248  auto const eps_squared =
249  std::pow(std::numeric_limits<double>::epsilon(), 2);
250  if (ab.squaredNorm() < eps_squared || ac.squaredNorm() < eps_squared ||
251  ad.squaredNorm() < eps_squared)
252  {
253  return true;
254  }
255 
256  // In exact arithmetic <ac*ad^T, ab> should be zero
257  // if all four points are coplanar.
258  const double sqr_scalar_triple(std::pow(ac.cross(ad).dot(ab), 2));
259  // Due to evaluating the above numerically some cancellation or rounding
260  // can occur. For this reason a normalisation factor is introduced.
261  const double normalisation_factor =
262  (ab.squaredNorm() * ac.squaredNorm() * ad.squaredNorm());
263 
264  // tolerance 1e-11 is chosen such that
265  // a = (0,0,0), b=(1,0,0), c=(0,1,0) and d=(1,1,1e-6) are considered as
266  // coplanar
267  // a = (0,0,0), b=(1,0,0), c=(0,1,0) and d=(1,1,1e-5) are considered as not
268  // coplanar
269  return (sqr_scalar_triple / normalisation_factor < 1e-11);
270 }
271 
272 } // end namespace MathLib
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
Definition of the Point3d class.
const T * getCoords() const
Definition: TemplatePoint.h:75
static const double q
double orientation3d(MathLib::Point3d const &p, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c)
bool gaussPointInTriangle(MathLib::Point3d const &q, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c, double eps_pnt_out_of_plane, double eps_pnt_out_of_tri)
double calcTriangleArea(MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c)
bool isCoplanar(const MathLib::Point3d &a, const MathLib::Point3d &b, const MathLib::Point3d &c, const MathLib::Point3d &d)
Checks if the four given points are located on a plane.
static const double p
bool dividedByPlane(const MathLib::Point3d &a, const MathLib::Point3d &b, const MathLib::Point3d &c, const MathLib::Point3d &d)
bool isPointInTriangle(MathLib::Point3d const &p, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c, double eps_pnt_out_of_plane, double eps_pnt_out_of_tri, MathLib::TriangleTest algorithm)
bool barycentricPointInTriangle(MathLib::Point3d const &p, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c, double eps_pnt_out_of_plane, double eps_pnt_out_of_tri)
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition: Point3d.h:48
double calcTetrahedronVolume(MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c, MathLib::Point3d const &d)
bool isPointInTetrahedron(MathLib::Point3d const &p, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c, MathLib::Point3d const &d, double eps)
bool isPointInTriangleXY(MathLib::Point3d const &p, MathLib::Point3d const &a, MathLib::Point3d const &b, MathLib::Point3d const &c)