https://mooseframework.inl.gov
LineSegment.C
Go to the documentation of this file.
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 "LineSegment.h"
11 
12 #include "JsonIO.h"
13 
14 #include "libmesh/plane.h"
15 #include "libmesh/vector_value.h"
16 
17 using libMesh::Point;
18 using libMesh::Real;
20 
21 LineSegment::LineSegment(const Point & p0, const Point & p1) : _p0(p0), _p1(p1) {}
22 
23 bool
24 LineSegment::closest_point(const Point & p, bool clamp_to_segment, Point & closest_p) const
25 {
26  Point p0_p = p - _p0;
27  Point p0_p1 = _p1 - _p0;
28  Real p0_p1_2 = p0_p1.norm_sq();
29  Real perp = p0_p(0) * p0_p1(0) + p0_p(1) * p0_p1(1) + p0_p(2) * p0_p1(2);
30  Real t = perp / p0_p1_2;
31  bool on_segment = true;
32 
33  if (t < 0.0 || t > 1.0)
34  on_segment = false;
35 
36  if (clamp_to_segment)
37  {
38  if (t < 0.0)
39  t = 0.0;
40  else if (t > 1.0)
41  t = 1.0;
42  }
43 
44  closest_p = _p0 + p0_p1 * t;
45  return on_segment;
46 }
47 
48 Point
49 LineSegment::closest_point(const Point & p) const
50 {
51  Point closest_p;
52  closest_point(p, true, closest_p);
53  return closest_p;
54 }
55 
56 bool
57 LineSegment::closest_normal_point(const Point & p, Point & closest_p) const
58 {
59  return closest_point(p, false, closest_p);
60 }
61 
62 bool
64 {
65  Point closest_p;
66  return closest_point(p, false, closest_p) && closest_p.absolute_fuzzy_equals(p);
67 }
68 
69 bool
70 LineSegment::intersect(const libMesh::Plane & pl, Point & intersect_p) const
71 {
86  Point pl0 = pl.get_planar_point();
88  RealVectorValue I = (_p1 - _p0).unit();
89 
90  Real numerator = (pl0 - _p0) * N;
91  Real denominator = I * N;
92 
93  // The Line is parallel to the plane
94  if (std::abs(denominator) < 1.e-10)
95  {
96  // The Line is on the plane
97  if (std::abs(numerator) < 1.e-10)
98  {
99  // The solution is not unique so we'll just pick an end point for now
100  intersect_p = _p0;
101  return true;
102  }
103  return false;
104  }
105 
106  Real d = numerator / denominator;
107 
108  // Make sure we haven't moved off the line segment!
109  if (d + libMesh::TOLERANCE < 0 || d - libMesh::TOLERANCE > (_p1 - _p0).norm())
110  return false;
111 
112  intersect_p = d * I + _p0;
113 
114  return true;
115 }
116 
117 bool
118 LineSegment::intersect(const LineSegment & l, Point & intersect_p) const
119 {
141  RealVectorValue a = _p1 - _p0;
142  RealVectorValue b = l._p1 - l._p0;
143  RealVectorValue c = l._p0 - _p0;
144 
145  RealVectorValue v = a.cross(b);
146 
147  const auto tol = 1.e-10;
148 
149  // Parallel lines check
150  if (v.norm() < tol)
151  {
152  // Parallel but not collinear: no intersection
153  if (c.cross(a).norm() >= tol)
154  return false;
155 
156  // Collinear: segments overlap if any endpoint lies on the other segment
157  const bool overlap = this->contains_point(l._p0) || this->contains_point(l._p1) ||
159 
160  if (!overlap)
161  return false;
162 
163  // Pick a deterministic intersection point on the overlap
164  if (this->contains_point(l._p0))
165  intersect_p = l._p0;
166  else if (this->contains_point(l._p1))
167  intersect_p = l._p1;
168  else if (l.contains_point(_p0))
169  intersect_p = _p0;
170  else
171  intersect_p = _p1;
172 
173  return true;
174  }
175 
176  // Check that the lines are coplanar
177  Real concur = c * (a.cross(b));
178  if (std::abs(concur) > 1.e-10)
179  return false;
180 
181  Real s = (c.cross(b) * v) / (v * v);
182  Real t = (c.cross(a) * v) / (v * v);
183 
184  // if s and t are between 0 and 1 then the Line Segments intersect
185  // TODO: We could handle other case of clamping to the end of Line
186  // Segements if we want to here
187 
188  if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
189  {
190  intersect_p = _p0 + s * a;
191  return true;
192  }
193  return false;
194 
250 }
251 
252 bool
253 LineSegment::intersect(const LineSegment & line_segment) const
254 {
255  Point p;
256  return intersect(line_segment, p);
257 }
258 
259 void
260 LineSegment::set(const Point & p0, const Point & p1)
261 {
262  setStart(p0);
263  setEnd(p1);
264 }
265 
266 void
267 dataStore(std::ostream & stream, LineSegment & l, void * context)
268 {
269  dataStore(stream, l.start(), context);
270  dataStore(stream, l.end(), context);
271 }
272 
273 void
274 dataLoad(std::istream & stream, LineSegment & l, void * context)
275 {
276  Point p0;
277  dataLoad(stream, p0, context);
278  Point p1;
279  dataLoad(stream, p1, context);
280  l.set(p0, p1);
281 }
282 
283 void
284 to_json(nlohmann::json & json, const LineSegment & l)
285 {
286  to_json(json["start"], l.start());
287  to_json(json["end"], l.end());
288 }
289 
290 Point
292 {
293  const auto tangent = _p1 - _p0;
294 
295  // Rotate 90 degrees counter-clockwise (2D)
296  Point n(-tangent(1), tangent(0), 0.0);
297  n /= n.norm();
298 
299  return n;
300 }
301 
302 Ball
304 {
305  const Point center = 0.5 * (_p0 + _p1);
306  const Real radius = 0.5 * (_p1 - _p0).norm();
307  return Ball(center, radius);
308 }
void setEnd(const Point &p1)
Sets the end of the line segment.
Definition: LineSegment.h:100
const Point & end() const
Ending of the line segment.
Definition: LineSegment.h:90
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Definition: EigenADReal.h:50
Ball primitive: a circle in 2D or a sphere in 3D.
Definition: Ball.h:34
const Real radius
auto norm() const
void to_json(nlohmann::json &json, const LineSegment &l)
Definition: LineSegment.C:284
VectorValue< Real > RealVectorValue
Definition: SubProblem.h:33
The LineSegment class is used by the LineMaterialSamplerBase class and for some ray tracing stuff...
Definition: LineSegment.h:30
Point closest_point(const Point &p) const
Returns the closest point on the LineSegment to the passed in point.
const Point & get_planar_point() const
LineSegment()=default
void dataStore(std::ostream &stream, LineSegment &l, void *context)
Definition: LineSegment.C:267
Point normal() const
normal vector of the line segment
Definition: LineSegment.C:291
void setStart(const Point &p0)
Sets the beginning of the line segment.
Definition: LineSegment.h:95
auto norm_sq() const
void set(const Point &p0, const Point &p1)
Sets the points on the line segment.
Definition: LineSegment.C:260
bool intersect(const libMesh::Plane &pl, Point &intersect_p) const
Check if a line segment intersects a plane, and if so, return the intersection point.
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:57
Ball computeBoundingBall() const override
Compute a bounding ball for this line segment.
Definition: LineSegment.C:303
const Point & start() const
Beginning of the line segment.
Definition: LineSegment.h:85
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:63
bool absolute_fuzzy_equals(const TypeVector< Real > &rhs, Real tol=TOLERANCE) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto norm(const T &a)
virtual Point unit_normal(const Point &p) const override
void dataLoad(std::istream &stream, LineSegment &l, void *context)
Definition: LineSegment.C:274