KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
intersection_utilities.h
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Ruben Zorrilla
11 // Vicente Mataix Ferrandiz
12 //
13 
14 #pragma once
15 
16 // System includes
17 
18 // External includes
19 
20 // Project includes
21 #include "includes/define.h"
22 #include "geometries/point.h"
24 #include "utilities/math_utils.h"
26 
27 namespace Kratos
28 {
29 
32 
36 
40 
44 
48 
59 class KRATOS_API(KRATOS_CORE) IntersectionUtilities
60 {
61 public:
64 
67 
71 
75 
80 
83 
87 
100  template <class TGeometryType>
102  const TGeometryType& rTriangleGeometry,
103  const array_1d<double,3>& rLinePoint1,
104  const array_1d<double,3>& rLinePoint2,
105  array_1d<double,3>& rIntersectionPoint,
106  const double epsilon = 1e-12) {
107 
108  // This is the adaption of the implementation provided in:
109  // http://www.softsurfer.com/Archive/algorithm_0105/algorithm_0105.htm#intersect_RayTriangle()
110  // Based on Tomas Möller & Ben Trumbore (1997) Fast, Minimum Storage Ray-Triangle Intersection, Journal of Graphics Tools, 2:1, 21-28, DOI: 10.1080/10867651.1997.10487468
111 
112  // Get triangle edge vectors and plane normal
113  const array_1d<double,3> u = rTriangleGeometry[1] - rTriangleGeometry[0];
114  const array_1d<double,3> v = rTriangleGeometry[2] - rTriangleGeometry[0];
117 
118  // Check if the triangle is degenerate (do not deal with this case)
119  if (MathUtils<double>::Norm3(n) < epsilon){
120  return -1;
121  }
122 
123  const array_1d<double,3> dir = rLinePoint2 - rLinePoint1; // Edge direction vector
124  const array_1d<double,3> w_0 = rLinePoint1 - rTriangleGeometry[0];
125  const double a = -inner_prod(n,w_0);
126  const double b = inner_prod(n,dir);
127 
128  // Check if the ray is parallel to the triangle plane
129  if (std::abs(b) < epsilon){
130  if (a == 0.0){
131  return 2; // Edge lies in the triangle plane
132  } else {
133  return 0; // Edge does not lie in the triangle plane
134  }
135  }
136 
137  // If the edge is not parallel, compute the intersection point
138  const double r = a / b;
139  if (r < 0.0){
140  return 0; // Edge goes away from triangle
141  } else if (r > 1.0) {
142  return 0; // Edge goes away from triangle
143  }
144 
145  rIntersectionPoint = rLinePoint1 + r*dir;
146 
147  // Check if the intersection point is inside the triangle
148  if (PointInTriangle(rTriangleGeometry[0], rTriangleGeometry[1], rTriangleGeometry[2], rIntersectionPoint)) {
149  return 1;
150  }
151  return 0;
152  }
153 
161  template <class TGeometryType>
163  const TGeometryType& rTriangle,
164  const array_1d<double,3>& rPoint0,
165  const array_1d<double,3>& rPoint1)
166  {
167  return TriangleLineIntersection2D(rTriangle[0], rTriangle[1], rTriangle[2], rPoint0, rPoint1);
168  }
169 
180  const array_1d<double,3>& rVert0,
181  const array_1d<double,3>& rVert1,
182  const array_1d<double,3>& rVert2,
183  const array_1d<double,3>& rPoint0,
184  const array_1d<double,3>& rPoint1)
185  {
186  // Check the intersection of each edge against the intersecting object
187  array_1d<double,3> int_point;
188  if (ComputeLineLineIntersection(rVert0, rVert1, rPoint0, rPoint1, int_point)) return true;
189  if (ComputeLineLineIntersection(rVert1, rVert2, rPoint0, rPoint1, int_point)) return true;
190  if (ComputeLineLineIntersection(rVert2, rVert0, rPoint0, rPoint1, int_point)) return true;
191 
192  // Let check second geometry is inside the first one.
193  if (PointInTriangle(rVert0, rVert1, rVert2, rPoint0)) return true;
194 
195  return false;
196  }
197 
211  static bool PointInTriangle(
212  const array_1d<double,3>& rVert0,
213  const array_1d<double,3>& rVert1,
214  const array_1d<double,3>& rVert2,
215  const array_1d<double,3>& rPoint,
216  const double Tolerance = std::numeric_limits<double>::epsilon())
217  {
218  const array_1d<double,3> u = rVert1 - rVert0;
219  const array_1d<double,3> v = rVert2 - rVert0;
220  const array_1d<double,3> w = rPoint - rVert0;
221 
222  const double uu = inner_prod(u, u);
223  const double uv = inner_prod(u, v);
224  const double vv = inner_prod(v, v);
225  const double wu = inner_prod(w, u);
226  const double wv = inner_prod(w, v);
227  const double denom = uv * uv - uu * vv;
228 
229  const double xi = (uv * wv - vv * wu) / denom;
230  const double eta = (uv * wu - uu * wv) / denom;
231 
232  if (xi < -Tolerance) return false;
233  if (eta < -Tolerance) return false;
234  if (xi + eta > 1.0 + Tolerance) return false;
235  return true;
236  }
237 
254  template <class TGeometryType, class TCoordinatesType>
255  static int ComputeTriangleLineIntersectionInTheSamePlane( //static IntersectionUtilitiesTetrahedraLineIntersectionStatus ComputeTriangleLineIntersectionInTheSamePlane(
256  const TGeometryType& rTriangleGeometry,
257  const TCoordinatesType& rLinePoint1,
258  const TCoordinatesType& rLinePoint2,
259  TCoordinatesType& rIntersectionPoint1,
260  TCoordinatesType& rIntersectionPoint2,
261  int& rSolution,//IntersectionUtilitiesTetrahedraLineIntersectionStatus& rSolution,
262  const double Epsilon = 1e-12
263  )
264  {
265  // Lambda function to check the inside of a line corrected
266  auto is_inside_projected = [&Epsilon] (auto& rGeometry, const TCoordinatesType& rPoint) -> bool {
267  // We compute the distance, if it is not in the plane we project
268  const Point point_to_project(rPoint);
269  Point point_projected;
270  const double distance = GeometricalProjectionUtilities::FastProjectOnLine(rGeometry, point_to_project, point_projected);
271 
272  // We check if we are on the plane
273  if (std::abs(distance) > Epsilon * rGeometry.Length()) {
274  return false;
275  }
276  array_1d<double, 3> local_coordinates;
277  return rGeometry.IsInside(point_projected, local_coordinates);
278  };
279 
280  // Compute intersection with the edges
281  for (auto& r_edge : rTriangleGeometry.GenerateEdges()) {
282  const auto& r_edge_point_1 = r_edge[0].Coordinates();
283  const auto& r_edge_point_2 = r_edge[1].Coordinates();
284  array_1d<double, 3> intersection_point_1, intersection_point_2;
285  const auto check_1 = ComputeLineLineIntersection(rLinePoint1, rLinePoint2, r_edge_point_1, r_edge_point_2, intersection_point_1, Epsilon);
286  const auto check_2 = ComputeLineLineIntersection(r_edge_point_1, r_edge_point_2, rLinePoint1, rLinePoint2, intersection_point_2, Epsilon);
287  if (check_1 == 0 && check_2 == 0) continue; // No intersection
288  array_1d<double, 3> intersection_point = check_1 != 0 ? intersection_point_1 : intersection_point_2;
289  if (check_1 == 2 || check_2 == 2) { // Aligned
290  // Check actually are aligned
291  array_1d<double, 3> vector_line = r_edge_point_2 - r_edge_point_1;
292  vector_line /= norm_2(vector_line);
293  array_1d<double, 3> diff_coor_1 = rLinePoint1 - r_edge_point_1;
294  const double diff_coor_1_norm = norm_2(diff_coor_1);
295  if (diff_coor_1_norm > std::numeric_limits<double>::epsilon()) {
296  diff_coor_1 /= diff_coor_1_norm;
297  } else {
298  diff_coor_1 = rLinePoint1 - r_edge_point_2;
299  diff_coor_1 /= norm_2(diff_coor_1);
300  }
301  array_1d<double, 3> diff_coor_2 = rLinePoint2 - r_edge_point_1;
302  const double diff_coor_2_norm = norm_2(diff_coor_2);
303  if (diff_coor_2_norm > std::numeric_limits<double>::epsilon()) {
304  diff_coor_2 /= diff_coor_2_norm;
305  } else {
306  diff_coor_2 = rLinePoint2 - r_edge_point_2;
307  diff_coor_2 /= norm_2(diff_coor_2);
308  }
309  const double diff1m = norm_2(diff_coor_1 - vector_line);
310  const double diff1p = norm_2(diff_coor_1 + vector_line);
311  const double diff2m = norm_2(diff_coor_2 - vector_line);
312  const double diff2p = norm_2(diff_coor_2 + vector_line);
313 
314  // Now we compute the intersection
315  if ((diff1m < Epsilon || diff1p < Epsilon) && (diff2m < Epsilon || diff2p < Epsilon)) {
316  // First point
317  if (is_inside_projected(r_edge, rLinePoint1)) { // Is inside the line
318  if (rSolution == 0) {//if (rSolution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION) {
319  noalias(rIntersectionPoint1) = rLinePoint1;
320  rSolution = 2;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION;
321  } else {
322  if (norm_2(rIntersectionPoint1 - rLinePoint1) > Epsilon) { // Must be different from the first one
323  noalias(rIntersectionPoint2) = rLinePoint1;
324  rSolution = 1;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION;
325  break;
326  }
327  }
328  } else { // Is in the border of the line
329  if (rSolution == 0) {//if (rSolution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION) {
330  noalias(rIntersectionPoint1) = norm_2(r_edge_point_1 - rLinePoint1) < norm_2(r_edge_point_2 - rLinePoint1) ? r_edge_point_1 : r_edge_point_2;
331  rSolution = 2;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION;
332  } else {
333  noalias(intersection_point) = norm_2(r_edge_point_1 - rLinePoint1) < norm_2(r_edge_point_2 - rLinePoint1) ? r_edge_point_1 : r_edge_point_2;
334  if (norm_2(rIntersectionPoint1 - intersection_point) > Epsilon) { // Must be different from the first one
335  noalias(rIntersectionPoint2) = intersection_point;
336  rSolution = 1;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION;
337  break;
338  }
339  }
340  }
341  // Second point
342  if (rSolution == 2) {//if (rSolution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION) {
343  if (is_inside_projected(r_edge, rLinePoint2)) { // Is inside the line
344  if (norm_2(rIntersectionPoint1 - rLinePoint2) > Epsilon) { // Must be different from the first one
345  noalias(rIntersectionPoint2) = rLinePoint2;
346  rSolution = 1;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION;
347  break;
348  }
349  } else { // Is in the border of the line
350  noalias(intersection_point) = norm_2(r_edge_point_1 - rLinePoint2) < norm_2(r_edge_point_2 - rLinePoint2) ? r_edge_point_1 : r_edge_point_2;
351  if (norm_2(rIntersectionPoint1 - intersection_point) > Epsilon) { // Must be different from the first one
352  noalias(rIntersectionPoint2) = intersection_point;
353  rSolution = 1;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION;
354  break;
355  }
356  }
357  } else { // We are done
358  break;
359  }
360  }
361  } else { // Direct intersection
362  if (rSolution == 0) {//if (rSolution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION) {
363  noalias(rIntersectionPoint1) = intersection_point;
364  rSolution = 2;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION;
365  } else {
366  if (norm_2(rIntersectionPoint1 - intersection_point) > Epsilon) { // Must be different from the first one
367  noalias(rIntersectionPoint2) = intersection_point;
368  rSolution = 1;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION;
369  break;
370  }
371  }
372  }
373  }
374 
375  return rSolution;
376  }
377 
413  template <class TGeometryType, class TCoordinatesType, bool TConsiderInsidePoints = true>
414  static int ComputeTetrahedraLineIntersection(//static IntersectionUtilitiesTetrahedraLineIntersectionStatus ComputeTetrahedraLineIntersection(
415  const TGeometryType& rTetrahedraGeometry,
416  const TCoordinatesType& rLinePoint1,
417  const TCoordinatesType& rLinePoint2,
418  TCoordinatesType& rIntersectionPoint1,
419  TCoordinatesType& rIntersectionPoint2,
420  const double Epsilon = 1e-12
421  )
422  {
423  int solution = 0;// IntersectionUtilitiesTetrahedraLineIntersectionStatus solution = IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION;
424  for (auto& r_face : rTetrahedraGeometry.GenerateFaces()) {
425  array_1d<double,3> intersection_point;
426  const int face_solution = ComputeTriangleLineIntersection(r_face, rLinePoint1, rLinePoint2, intersection_point, Epsilon);
427  if (face_solution == 1) { // The line intersects the face
428  if (solution == 0) {// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION) {
429  noalias(rIntersectionPoint1) = intersection_point;
430  solution = 2;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION;
431  } else {
432  if (norm_2(rIntersectionPoint1 - intersection_point) > Epsilon) { // Must be different from the first one
433  noalias(rIntersectionPoint2) = intersection_point;
434  solution = 1;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION;
435  break;
436  }
437  }
438  } else if (face_solution == 2) { // The line is coincident with the face
439  ComputeTriangleLineIntersectionInTheSamePlane(r_face, rLinePoint1, rLinePoint2, rIntersectionPoint1, rIntersectionPoint2, solution, Epsilon);
440  if (solution == 1) break;// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION) break;
441  }
442  }
443 
444  // Check if points are inside
445  if constexpr (TConsiderInsidePoints) {
446  if (solution == 0) {// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION) {
447  array_1d<double,3> local_coordinates;
448  if (rTetrahedraGeometry.IsInside(rLinePoint1, local_coordinates)) {
449  noalias(rIntersectionPoint1) = rLinePoint1;
450  solution = 4;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION_ONE_INSIDE;
451  }
452  if (rTetrahedraGeometry.IsInside(rLinePoint2, local_coordinates)) {
453  if (solution == 0) {// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::NO_INTERSECTION) {
454  noalias(rIntersectionPoint1) = rLinePoint2;
455  solution = 4;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION_ONE_INSIDE;
456  } else {
457  noalias(rIntersectionPoint2) = rLinePoint2;
458  solution = 3;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION_BOTH_INSIDE;
459  }
460  }
461  } else if (solution == 2) {// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION) {
462  array_1d<double,3> local_coordinates;
463  if (rTetrahedraGeometry.IsInside(rLinePoint1, local_coordinates)) {
464  if (norm_2(rIntersectionPoint1 - rLinePoint1) > Epsilon) { // Must be different from the first one
465  noalias(rIntersectionPoint2) = rLinePoint1;
466  solution = 4;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION_ONE_INSIDE;
467  }
468  }
469  if (solution == 2) {// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION) {
470  if (rTetrahedraGeometry.IsInside(rLinePoint2, local_coordinates)) {
471  if (norm_2(rIntersectionPoint1 - rLinePoint2) > Epsilon) { // Must be different from the first one
472  noalias(rIntersectionPoint2) = rLinePoint2;
473  solution = 4;// IntersectionUtilitiesTetrahedraLineIntersectionStatus::TWO_POINTS_INTERSECTION_ONE_INSIDE;
474  }
475  }
476  }
477  }
478  }
479 
480  // Checking if any node of the tetrahedra
481  if (solution == 2) {// if (solution == IntersectionUtilitiesTetrahedraLineIntersectionStatus::ONE_POINT_INTERSECTION) {
482  // Detect the node of the tetrahedra and directly assign
483  int index_node = -1;
484  for (int i_node = 0; i_node < 4; ++i_node) {
485  if (norm_2(rTetrahedraGeometry[i_node].Coordinates() - rIntersectionPoint1) < Epsilon) {
486  index_node = i_node;
487  break;
488  }
489  }
490  // Return index
491  if (index_node > -1) {
492  return index_node + 5;
493  //return static_cast<IntersectionUtilitiesTetrahedraLineIntersectionStatus>(index_node + 5);
494  }
495  }
496 
497  return solution;
498  }
499 
511  template<class TGeometryType>
513  const TGeometryType& rSegment1,
514  const TGeometryType& rSegment2
515  )
516  {
517  // Zero tolerance
518  const double zero_tolerance = std::numeric_limits<double>::epsilon();
519 
520  // Check geometry type
521  KRATOS_ERROR_IF_NOT((rSegment1.GetGeometryFamily() == GeometryData::KratosGeometryFamily::Kratos_Linear && rSegment1.PointsNumber() == 2)) << "The first geometry type is not correct, it is suppossed to be a linear line" << std::endl;
522  KRATOS_ERROR_IF_NOT((rSegment2.GetGeometryFamily() == GeometryData::KratosGeometryFamily::Kratos_Linear && rSegment2.PointsNumber() == 2)) << "The second geometry type is not correct, it is suppossed to be a linear line" << std::endl;
523 
524  // Resulting line segment
525  auto resulting_line = PointerVector<Point>();
526 
527  // Variable definitions
528  array_1d<double, 3> p13,p43,p21;
529  double d1343,d4321,d1321,d4343,d2121;
530  double mua, mub;
531  double numer,denom;
532 
533  // Points segments
534  const Point& p1 = rSegment1[0];
535  const Point& p2 = rSegment1[1];
536  const Point& p3 = rSegment2[0];
537  const Point& p4 = rSegment2[1];
538 
539  p13[0] = p1.X() - p3.X();
540  p13[1] = p1.Y() - p3.Y();
541  p13[2] = p1.Z() - p3.Z();
542 
543  p43[0] = p4.X() - p3.X();
544  p43[1] = p4.Y() - p3.Y();
545  p43[2] = p4.Z() - p3.Z();
546  if (std::abs(p43[0]) < zero_tolerance && std::abs(p43[1]) < zero_tolerance && std::abs(p43[2]) < zero_tolerance)
547  return resulting_line;
548 
549  p21[0] = p2.X() - p1.X();
550  p21[1] = p2.Y() - p1.Y();
551  p21[2] = p2.Z() - p1.Z();
552  if (std::abs(p21[0]) < zero_tolerance && std::abs(p21[1]) < zero_tolerance && std::abs(p21[2]) < zero_tolerance)
553  return resulting_line;
554 
555  d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
556  d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
557  d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
558  d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
559  d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
560 
561  denom = d2121 * d4343 - d4321 * d4321;
562  auto pa = Kratos::make_shared<Point>(0.0, 0.0, 0.0);
563  auto pb = Kratos::make_shared<Point>(0.0, 0.0, 0.0);
564  if (std::abs(denom) < zero_tolerance) { // Parallel lines, infinite solutions. Projecting points and getting one perpendicular line
565  // Projection auxiliary variables
566  Point projected_point;
567  array_1d<double,3> local_coords;
568  // Projecting first segment
569  GeometricalProjectionUtilities::FastProjectOnLine(rSegment2, rSegment1[0], projected_point);
570  if (rSegment2.IsInside(projected_point, local_coords)) {
571  pa->Coordinates() = rSegment1[0].Coordinates();
572  pb->Coordinates() = projected_point;
573  } else {
574  GeometricalProjectionUtilities::FastProjectOnLine(rSegment2, rSegment1[1], projected_point);
575  if (rSegment2.IsInside(projected_point, local_coords)) {
576  pa->Coordinates() = rSegment1[1].Coordinates();
577  pb->Coordinates() = projected_point;
578  } else { // Trying to project second segment
579  GeometricalProjectionUtilities::FastProjectOnLine(rSegment1, rSegment2[0], projected_point);
580  if (rSegment1.IsInside(projected_point, local_coords)) {
581  pa->Coordinates() = rSegment2[0].Coordinates();
582  pb->Coordinates() = projected_point;
583  } else {
584  GeometricalProjectionUtilities::FastProjectOnLine(rSegment1, rSegment2[1], projected_point);
585  if (rSegment1.IsInside(projected_point, local_coords)) {
586  pa->Coordinates() = rSegment2[1].Coordinates();
587  pb->Coordinates() = projected_point;
588  } else { // Parallel and not projection possible
589  return resulting_line;
590  }
591  }
592  }
593  }
594  } else {
595  numer = d1343 * d4321 - d1321 * d4343;
596 
597  mua = numer / denom;
598  mub = (d1343 + d4321 * mua) / d4343;
599 
600  pa->X() = p1.X() + mua * p21[0];
601  pa->Y() = p1.Y() + mua * p21[1];
602  pa->Z() = p1.Z() + mua * p21[2];
603  pb->X() = p3.X() + mub * p43[0];
604  pb->Y() = p3.Y() + mub * p43[1];
605  pb->Z() = p3.Z() + mub * p43[2];
606  }
607 
608  resulting_line.push_back(pa);
609  resulting_line.push_back(pb);
610  return resulting_line;
611  }
612 
625  template <class TGeometryType>
627  const TGeometryType& rLineGeometry,
628  const array_1d<double,3>& rLinePoint0,
629  const array_1d<double,3>& rLinePoint1,
630  array_1d<double,3>& rIntersectionPoint,
631  const double epsilon = 1e-12)
632  {
633  return ComputeLineLineIntersection(
634  rLineGeometry[0], rLineGeometry[1], rLinePoint0, rLinePoint1, rIntersectionPoint, epsilon);
635  }
636 
651  const array_1d<double,3>& rLine1Point0,
652  const array_1d<double,3>& rLine1Point1,
653  const array_1d<double,3>& rLine2Point0,
654  const array_1d<double,3>& rLine2Point1,
655  array_1d<double,3>& rIntersectionPoint,
656  const double epsilon = 1e-12)
657  {
658  const array_1d<double,3> r = rLine1Point1 - rLine1Point0;
659  const array_1d<double,3> s = rLine2Point1 - rLine2Point0;
660  const array_1d<double,3> q_p = rLine2Point0 - rLine1Point0; // q - p
661 
662  const double aux_1 = CrossProd2D(r,s);
663  const double aux_2 = CrossProd2D(q_p,r);
664  const double aux_3 = CrossProd2D(q_p,s);
665 
666  // Check intersection cases
667  // Check that the lines are not collinear
668  if (std::abs(aux_1) < epsilon && std::abs(aux_2) < epsilon){
669  const double aux_4 = inner_prod(r,r);
670  const double aux_5 = inner_prod(s,r);
671  const double t_0 = inner_prod(q_p,r)/aux_4;
672  const double t_1 = t_0 + aux_5/aux_4;
673  if (aux_5 < 0.0){
674  if (t_1 >= 0.0 && t_0 <= 1.0){
675  return 2; // The lines are collinear and overlapping
676  }
677  } else {
678  if (t_0 >= 0.0 && t_1 <= 1.0){
679  return 2; // The lines are collinear and overlapping
680  }
681  }
682  // Check that the lines are parallel and non-intersecting
683  } else if (std::abs(aux_1) < epsilon && std::abs(aux_2) > epsilon){
684  return 0;
685  // Check that the lines intersect
686  } else if (std::abs(aux_1) > epsilon){
687  const double u = aux_2/aux_1;
688  const double t = aux_3/aux_1;
689  if (((u >= 0.0) && (u <= 1.0)) && ((t >= 0.0) && (t <= 1.0))){
690  rIntersectionPoint = rLine2Point0 + u*s;
691  // Check if the intersection occurs in one of the end points
692  if (u < epsilon || (1.0 - u) < epsilon) {
693  return 3;
694  } else {
695  return 1;
696  }
697  }
698  }
699  // Otherwise, the lines are non-parallel but do not intersect
700  return 0;
701  }
702 
716  const array_1d<double,3>& rPlaneBasePoint,
717  const array_1d<double,3>& rPlaneNormal,
718  const array_1d<double,3>& rLinePoint1,
719  const array_1d<double,3>& rLinePoint2,
720  array_1d<double,3>& rIntersectionPoint,
721  const double epsilon = 1e-12)
722  {
723  // This is the adaption of the implementation provided in:
724  // http://www.softsurfer.com/Archive/algorithm_0105/algorithm_0105.htm#intersect_RayTriangle()
725  // (Intersection of a Segment with a Plane)
726 
727  // Get direction vector of edge
728  const array_1d<double,3> line_dir = rLinePoint2 - rLinePoint1;
729 
730  // Check if the segment is parallel to the plane or even coincides with it
731  const double a = inner_prod(rPlaneNormal,( rPlaneBasePoint - rLinePoint1 ));
732  const double b = inner_prod(rPlaneNormal,line_dir);
733  if (std::abs(b) < epsilon){
734  if (std::abs(a) < epsilon){
735  return 2; // Segment lies in the plane
736  } else {
737  return 0; // Segment does not lie in the plane, but is parallel to it
738  }
739  }
740 
741  // Compute the intersection point and check if it is inside the bounds of the segment
742  const double r = a / b;
743  if (r < 0.0){
744  return 0; // Intersection point lies outside the bounds of the segment
745  } else if (r > 1.0) {
746  return 0; // Intersection point lies outside the bounds of the segment
747  }
748  rIntersectionPoint = rLinePoint1 + r * line_dir;
749 
750  return 1;
751  }
752 
766  const array_1d<double,3> &rBoxPoint0,
767  const array_1d<double,3> &rBoxPoint1,
768  const array_1d<double,3> &rLinePoint0,
769  const array_1d<double,3> &rLinePoint1)
770  {
771  array_1d<double,3> intersection_point = ZeroVector(3);
772 
773  if (rLinePoint1[0] < rBoxPoint0[0] && rLinePoint0[0] < rBoxPoint0[0]) return false;
774  if (rLinePoint1[0] > rBoxPoint1[0] && rLinePoint0[0] > rBoxPoint1[0]) return false;
775  if (rLinePoint1[1] < rBoxPoint0[1] && rLinePoint0[1] < rBoxPoint0[1]) return false;
776  if (rLinePoint1[1] > rBoxPoint1[1] && rLinePoint0[1] > rBoxPoint1[1]) return false;
777  if (rLinePoint1[2] < rBoxPoint0[2] && rLinePoint0[2] < rBoxPoint0[2]) return false;
778  if (rLinePoint1[2] > rBoxPoint1[2] && rLinePoint0[2] > rBoxPoint1[2]) return false;
779  if (rLinePoint0[0] > rBoxPoint0[0] && rLinePoint0[0] < rBoxPoint1[0] &&
780  rLinePoint0[1] > rBoxPoint0[1] && rLinePoint0[1] < rBoxPoint1[1] &&
781  rLinePoint0[2] > rBoxPoint0[2] && rLinePoint0[2] < rBoxPoint1[2]) {
782  return true;
783  }
784  if ((GetLineBoxIntersection(rLinePoint0[0]-rBoxPoint0[0], rLinePoint1[0]-rBoxPoint0[0], rLinePoint0, rLinePoint1, intersection_point) && InBox(intersection_point, rBoxPoint0, rBoxPoint1, 1 )) ||
785  (GetLineBoxIntersection(rLinePoint0[1]-rBoxPoint0[1], rLinePoint1[1]-rBoxPoint0[1], rLinePoint0, rLinePoint1, intersection_point) && InBox(intersection_point, rBoxPoint0, rBoxPoint1, 2 )) ||
786  (GetLineBoxIntersection(rLinePoint0[2]-rBoxPoint0[2], rLinePoint1[2]-rBoxPoint0[2], rLinePoint0, rLinePoint1, intersection_point) && InBox(intersection_point, rBoxPoint0, rBoxPoint1, 3 )) ||
787  (GetLineBoxIntersection(rLinePoint0[0]-rBoxPoint1[0], rLinePoint1[0]-rBoxPoint1[0], rLinePoint0, rLinePoint1, intersection_point) && InBox(intersection_point, rBoxPoint0, rBoxPoint1, 1 )) ||
788  (GetLineBoxIntersection(rLinePoint0[1]-rBoxPoint1[1], rLinePoint1[1]-rBoxPoint1[1], rLinePoint0, rLinePoint1, intersection_point) && InBox(intersection_point, rBoxPoint0, rBoxPoint1, 2 )) ||
789  (GetLineBoxIntersection(rLinePoint0[2]-rBoxPoint1[2], rLinePoint1[2]-rBoxPoint1[2], rLinePoint0, rLinePoint1, intersection_point) && InBox(intersection_point, rBoxPoint0, rBoxPoint1, 3 ))){
790  return true;
791  }
792 
793  return false;
794  }
795 
799 
803 
807 
811 private:
812 
815 
819 
823 
827 
835  static inline double CrossProd2D(const array_1d<double,3> &a, const array_1d<double,3> &b){
836  return (a(0)*b(1) - a(1)*b(0));
837  }
838 
839  static inline int GetLineBoxIntersection(
840  const double Dist1,
841  const double Dist2,
842  const array_1d<double,3> &rPoint1,
843  const array_1d<double,3> &rPoint2,
844  array_1d<double,3> &rIntersectionPoint)
845  {
846  if ((Dist1 * Dist2) >= 0.0){
847  return 0;
848  }
849  // if ( Dist1 == Dist2) return 0;
850  if (std::abs(Dist1-Dist2) < 1e-12){
851  return 0;
852  }
853  rIntersectionPoint = rPoint1 + (rPoint2-rPoint1)*(-Dist1/(Dist2-Dist1));
854  return 1;
855  }
856 
857  static inline int InBox(
858  const array_1d<double,3> &rIntersectionPoint,
859  const array_1d<double,3> &rBoxPoint0,
860  const array_1d<double,3> &rBoxPoint1,
861  const unsigned int Axis)
862  {
863  if ( Axis==1 && rIntersectionPoint[2] > rBoxPoint0[2] && rIntersectionPoint[2] < rBoxPoint1[2] && rIntersectionPoint[1] > rBoxPoint0[1] && rIntersectionPoint[1] < rBoxPoint1[1]) return 1;
864  if ( Axis==2 && rIntersectionPoint[2] > rBoxPoint0[2] && rIntersectionPoint[2] < rBoxPoint1[2] && rIntersectionPoint[0] > rBoxPoint0[0] && rIntersectionPoint[0] < rBoxPoint1[0]) return 1;
865  if ( Axis==3 && rIntersectionPoint[0] > rBoxPoint0[0] && rIntersectionPoint[0] < rBoxPoint1[0] && rIntersectionPoint[1] > rBoxPoint0[1] && rIntersectionPoint[1] < rBoxPoint1[1]) return 1;
866  return 0;
867  }
868 
872 
876 
880 
884 
885 }; /* Class IntersectionUtilities */
886 
889 
893 
894 } /* namespace Kratos.*/
static double FastProjectOnLine(const TGeometryType &rGeometry, const PointType &rPointToProject, PointType &rPointProjected)
Project a point over a line (2D or 3D)
Definition: geometrical_projection_utilities.h:192
Utilities to compute intersections between different geometries.
Definition: intersection_utilities.h:60
IntersectionUtilities()
Default constructor.
Definition: intersection_utilities.h:79
static bool TriangleLineIntersection2D(const array_1d< double, 3 > &rVert0, const array_1d< double, 3 > &rVert1, const array_1d< double, 3 > &rVert2, const array_1d< double, 3 > &rPoint0, const array_1d< double, 3 > &rPoint1)
Definition: intersection_utilities.h:179
static int ComputeTriangleLineIntersectionInTheSamePlane(const TGeometryType &rTriangleGeometry, const TCoordinatesType &rLinePoint1, const TCoordinatesType &rLinePoint2, TCoordinatesType &rIntersectionPoint1, TCoordinatesType &rIntersectionPoint2, int &rSolution, const double Epsilon=1e-12)
Find the 3D intersection of a line (bounded) with a triangle (bounded) in the same plane.
Definition: intersection_utilities.h:255
static int ComputeLineBoxIntersection(const array_1d< double, 3 > &rBoxPoint0, const array_1d< double, 3 > &rBoxPoint1, const array_1d< double, 3 > &rLinePoint0, const array_1d< double, 3 > &rLinePoint1)
Compute a segment box intersection Provided the minimum and maximum points of a box cell,...
Definition: intersection_utilities.h:765
KRATOS_CLASS_POINTER_DEFINITION(IntersectionUtilities)
Pointer definition of IntersectionUtilities.
static int ComputeTetrahedraLineIntersection(const TGeometryType &rTetrahedraGeometry, const TCoordinatesType &rLinePoint1, const TCoordinatesType &rLinePoint2, TCoordinatesType &rIntersectionPoint1, TCoordinatesType &rIntersectionPoint2, const double Epsilon=1e-12)
Find the 3D intersection of a line (bounded) with a tetrahedra (bounded)
Definition: intersection_utilities.h:414
static bool PointInTriangle(const array_1d< double, 3 > &rVert0, const array_1d< double, 3 > &rVert1, const array_1d< double, 3 > &rVert2, const array_1d< double, 3 > &rPoint, const double Tolerance=std::numeric_limits< double >::epsilon())
This uses the Cramer's rule for solving a linear system and obtain the barycentric coordinates.
Definition: intersection_utilities.h:211
static int ComputeLineLineIntersection(const array_1d< double, 3 > &rLine1Point0, const array_1d< double, 3 > &rLine1Point1, const array_1d< double, 3 > &rLine2Point0, const array_1d< double, 3 > &rLine2Point1, array_1d< double, 3 > &rIntersectionPoint, const double epsilon=1e-12)
Definition: intersection_utilities.h:650
static bool TriangleLineIntersection2D(const TGeometryType &rTriangle, const array_1d< double, 3 > &rPoint0, const array_1d< double, 3 > &rPoint1)
Definition: intersection_utilities.h:162
static int ComputeTriangleLineIntersection(const TGeometryType &rTriangleGeometry, const array_1d< double, 3 > &rLinePoint1, const array_1d< double, 3 > &rLinePoint2, array_1d< double, 3 > &rIntersectionPoint, const double epsilon=1e-12)
Definition: intersection_utilities.h:101
static int ComputePlaneLineIntersection(const array_1d< double, 3 > &rPlaneBasePoint, const array_1d< double, 3 > &rPlaneNormal, const array_1d< double, 3 > &rLinePoint1, const array_1d< double, 3 > &rLinePoint2, array_1d< double, 3 > &rIntersectionPoint, const double epsilon=1e-12)
Find the 3D intersection of a plane (infinite) with a segment (bounded)
Definition: intersection_utilities.h:715
static PointerVector< Point > ComputeShortestLineBetweenTwoLines(const TGeometryType &rSegment1, const TGeometryType &rSegment2)
Calculates the line to line intersection (shortest line). If line is length 0, it is considered a poi...
Definition: intersection_utilities.h:512
static int ComputeLineLineIntersection(const TGeometryType &rLineGeometry, const array_1d< double, 3 > &rLinePoint0, const array_1d< double, 3 > &rLinePoint1, array_1d< double, 3 > &rIntersectionPoint, const double epsilon=1e-12)
Definition: intersection_utilities.h:626
virtual ~IntersectionUtilities()
Destructor.
Definition: intersection_utilities.h:82
Various mathematical utilitiy functions.
Definition: math_utils.h:62
Point class.
Definition: point.h:59
double Y() const
Definition: point.h:187
double Z() const
Definition: point.h:193
double X() const
Definition: point.h:181
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
solution
Definition: KratosDEM.py:9
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
v
Definition: generate_convection_diffusion_explicit_element.py:114
w
Definition: generate_convection_diffusion_explicit_element.py:108
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
int t
Definition: ode_solve.py:392
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
dir
Definition: radii_error_plotter.py:10
e
Definition: run_cpp_mpi_tests.py:31