Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "Triangle.h" 11 : #include "LineSegment.h" 12 : 13 : #include <cmath> 14 : 15 : using libMesh::Point; 16 : using libMesh::Real; 17 : 18 0 : Triangle::Triangle(const Point & p0, const Point & p1, const Point & p2) : _p0(p0), _p1(p1), _p2(p2) 19 : { 20 0 : } 21 : 22 : Point 23 0 : Triangle::normal() const 24 : { 25 0 : const auto v1 = _p1 - _p0; 26 0 : const auto v2 = _p2 - _p0; 27 : 28 0 : auto n = v1.cross(v2); 29 0 : n /= n.norm(); 30 : 31 0 : return n; 32 : } 33 : 34 : bool 35 0 : Triangle::intersect(const LineSegment & line_segment, Point & intersect_p) const 36 : { 37 0 : const auto & a = line_segment.start(); 38 0 : const auto & b = line_segment.end(); 39 : 40 : // (a) Build basic vectors and choose a robust tolerance 41 0 : const Point dir = b - a; 42 : 43 0 : const Point edge1 = _p1 - _p0; 44 0 : const Point edge2 = _p2 - _p0; 45 0 : constexpr Real eps = libMesh::TOLERANCE; 46 : 47 : // (b) Test for parallel or degenerate configuration 48 0 : const Point pvec = dir.cross(edge2); 49 0 : const Real det = edge1 * pvec; 50 0 : if (std::abs(det) < eps) 51 0 : return false; // ray nearly parallel to triangle 52 : 53 0 : const Real inv_det = 1.0 / det; 54 : 55 : // (c) Compute barycentric coordinate u and check 0 <= u <= 1 56 0 : const Point tvec = a - _p0; 57 0 : const Real u = (tvec * pvec) * inv_det; 58 0 : if (!MooseUtils::absoluteFuzzyGreaterEqual(u, 0.0, eps) || 59 0 : !MooseUtils::absoluteFuzzyLessEqual(u, 1.0, eps)) 60 0 : return false; 61 : 62 : // (d) Compute barycentric coordinate v and check 0 <= v and u + v <= 1 63 0 : const Point qvec = tvec.cross(edge1); 64 0 : const Real v = (dir * qvec) * inv_det; 65 0 : if (!MooseUtils::absoluteFuzzyGreaterEqual(v, 0.0, eps) || 66 0 : !MooseUtils::absoluteFuzzyLessEqual(u + v, 1.0, eps)) 67 0 : return false; 68 : 69 : // (e) Locate intersection along line segment (0 <= t <= 1 constrains to a--b) 70 0 : const Real t = (edge2 * qvec) * inv_det; 71 0 : if (!MooseUtils::absoluteFuzzyGreaterEqual(t, 0.0, eps) || 72 0 : !MooseUtils::absoluteFuzzyLessEqual(t, 1.0, eps)) 73 0 : return false; 74 : 75 : // (f) Intersection lies inside both the triangle and the segment 76 0 : intersect_p = a + dir * t; 77 0 : return true; 78 : } 79 : 80 : bool 81 0 : Triangle::intersect(const LineSegment & line_segment) const 82 : { 83 0 : libMesh::Point p; 84 0 : return intersect(line_segment, p); 85 : } 86 : 87 : Ball 88 0 : Triangle::computeBoundingBall() const 89 : { 90 0 : const Point centroid = (_p0 + _p1 + _p2) / 3.0; 91 : 92 0 : Real max_sq_dist = 0.0; 93 0 : for (const auto * p : {&_p0, &_p1, &_p2}) 94 : { 95 0 : const Real dist_sq = (*p - centroid).norm_sq(); 96 0 : if (dist_sq > max_sq_dist) 97 0 : max_sq_dist = dist_sq; 98 : } 99 : 100 0 : const Real radius = std::sqrt(max_sq_dist); 101 0 : return Ball(centroid, radius); 102 : }