www.mooseframework.org
LineSegment.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "LineSegment.h"
11 
12 #include "JsonIO.h"
13 
14 #include "libmesh/plane.h"
15 #include "libmesh/vector_value.h"
16 
17 LineSegment::LineSegment(const Point & p0, const Point & p1) : _p0(p0), _p1(p1) {}
18 
19 bool
20 LineSegment::closest_point(const Point & p, bool clamp_to_segment, Point & closest_p) const
21 {
22  Point p0_p = p - _p0;
23  Point p0_p1 = _p1 - _p0;
24  Real p0_p1_2 = p0_p1.norm_sq();
25  Real perp = p0_p(0) * p0_p1(0) + p0_p(1) * p0_p1(1) + p0_p(2) * p0_p1(2);
26  Real t = perp / p0_p1_2;
27  bool on_segment = true;
28 
29  if (t < 0.0 || t > 1.0)
30  on_segment = false;
31 
32  if (clamp_to_segment)
33  {
34  if (t < 0.0)
35  t = 0.0;
36  else if (t > 1.0)
37  t = 1.0;
38  }
39 
40  closest_p = _p0 + p0_p1 * t;
41  return on_segment;
42 }
43 
44 Point
45 LineSegment::closest_point(const Point & p) const
46 {
47  Point closest_p;
48  closest_point(p, true, closest_p);
49  return closest_p;
50 }
51 
52 bool
53 LineSegment::closest_normal_point(const Point & p, Point & closest_p) const
54 {
55  return closest_point(p, false, closest_p);
56 }
57 
58 bool
59 LineSegment::contains_point(const Point & p) const
60 {
61  Point closest_p;
62  return closest_point(p, false, closest_p) && closest_p.absolute_fuzzy_equals(p);
63 }
64 
65 bool
66 LineSegment::intersect(const Plane & pl, Point & intersect_p) const
67 {
82  Point pl0 = pl.get_planar_point();
83  RealVectorValue N = pl.unit_normal(_p0);
84  RealVectorValue I = (_p1 - _p0).unit();
85 
86  Real numerator = (pl0 - _p0) * N;
87  Real denominator = I * N;
88 
89  // The Line is parallel to the plane
90  if (std::abs(denominator) < 1.e-10)
91  {
92  // The Line is on the plane
93  if (std::abs(numerator) < 1.e-10)
94  {
95  // The solution is not unique so we'll just pick an end point for now
96  intersect_p = _p0;
97  return true;
98  }
99  return false;
100  }
101 
102  Real d = numerator / denominator;
103 
104  // Make sure we haven't moved off the line segment!
105  if (d + libMesh::TOLERANCE < 0 || d - libMesh::TOLERANCE > (_p1 - _p0).norm())
106  return false;
107 
108  intersect_p = d * I + _p0;
109 
110  return true;
111 }
112 
113 bool
114 LineSegment::intersect(const LineSegment & l, Point & intersect_p) const
115 {
137  RealVectorValue a = _p1 - _p0;
138  RealVectorValue b = l._p1 - l._p0;
139  RealVectorValue c = l._p0 - _p0;
140 
141  RealVectorValue v = a.cross(b);
142 
143  // Check for parallel lines
144  if (std::abs(v.norm()) < 1.e-10 && std::abs(c.cross(a).norm()) < 1.e-10)
145  {
146  // TODO: The lines are co-linear but more work is needed to determine and intersection point
147  // it could be the case that the line segments don't lie on the same line or overlap only
148  // a bit
149  return true;
150  }
151 
152  // Check that the lines are coplanar
153  Real concur = c * (a.cross(b));
154  if (std::abs(concur) > 1.e-10)
155  return false;
156 
157  Real s = (c.cross(b) * v) / (v * v);
158  Real t = (c.cross(a) * v) / (v * v);
159 
160  // if s and t are between 0 and 1 then the Line Segments intersect
161  // TODO: We could handle other case of clamping to the end of Line
162  // Segements if we want to here
163 
164  if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
165  {
166  intersect_p = _p0 + s * a;
167  return true;
168  }
169  return false;
170 
226 }
227 
228 void
229 LineSegment::set(const Point & p0, const Point & p1)
230 {
231  setStart(p0);
232  setEnd(p1);
233 }
234 
235 void
236 dataStore(std::ostream & stream, LineSegment & l, void * context)
237 {
238  dataStore(stream, l.start(), context);
239  dataStore(stream, l.end(), context);
240 }
241 
242 void
243 dataLoad(std::istream & stream, LineSegment & l, void * context)
244 {
245  Point p0;
246  dataLoad(stream, p0, context);
247  Point p1;
248  dataLoad(stream, p1, context);
249  l.set(p0, p1);
250 }
251 
252 void
253 to_json(nlohmann::json & json, const LineSegment & l)
254 {
255  to_json(json["start"], l.start());
256  to_json(json["end"], l.end());
257 }
void setEnd(const Point &p1)
Sets the end of the line segment.
Definition: LineSegment.h:78
const Point & end() const
Ending of the line segment.
Definition: LineSegment.h:68
auto norm() const -> decltype(std::norm(Real()))
void to_json(nlohmann::json &json, const LineSegment &l)
Definition: LineSegment.C:253
The LineSegment class is used by the LineMaterialSamplerBase class and for some ray tracing stuff...
Definition: LineSegment.h:29
Point closest_point(const Point &p) const
Returns the closest point on the LineSegment to the passed in point.
Definition: LineSegment.C:45
LineSegment()=default
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
void dataStore(std::ostream &stream, LineSegment &l, void *context)
Definition: LineSegment.C:236
bool intersect(const Plane &pl, Point &intersect_p) const
Definition: LineSegment.C:66
void setStart(const Point &p0)
Sets the beginning of the line segment.
Definition: LineSegment.h:73
void set(const Point &p0, const Point &p1)
Sets the points on the line segment.
Definition: LineSegment.C:229
bool closest_normal_point(const Point &p, Point &closest_p) const
Finds the closest point on the Line determined by the Line Segments.
Definition: LineSegment.C:53
const Point & start() const
Beginning of the line segment.
Definition: LineSegment.h:63
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
bool contains_point(const Point &p) const
Determines whether a point is in a line segment or not.
Definition: LineSegment.C:59
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void dataLoad(std::istream &stream, LineSegment &l, void *context)
Definition: LineSegment.C:243