https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
17using libMesh::Point;
18using libMesh::Real;
20
21LineSegment::LineSegment(const Point & p0, const Point & p1) : _p0(p0), _p1(p1) {}
22
23bool
24LineSegment::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
50{
51 Point closest_p;
52 closest_point(p, true, closest_p);
53 return closest_p;
54}
55
56bool
57LineSegment::closest_normal_point(const Point & p, Point & closest_p) const
58{
59 return closest_point(p, false, closest_p);
60}
61
62bool
64{
65 Point closest_p;
66 return closest_point(p, false, closest_p) && closest_p.absolute_fuzzy_equals(p);
67}
68
69bool
70LineSegment::intersect(const libMesh::Plane & pl, Point & intersect_p) const
71{
86 Point pl0 = pl.get_planar_point();
87 RealVectorValue N = pl.unit_normal(_p0);
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
117bool
118LineSegment::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
252bool
253LineSegment::intersect(const LineSegment & line_segment) const
254{
255 Point p;
256 return intersect(line_segment, p);
257}
258
259void
260LineSegment::set(const Point & p0, const Point & p1)
261{
262 setStart(p0);
263 setEnd(p1);
264}
265
266void
267dataStore(std::ostream & stream, LineSegment & l, void * context)
268{
269 dataStore(stream, l.start(), context);
270 dataStore(stream, l.end(), context);
271}
272
273void
274dataLoad(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
283void
284to_json(nlohmann::json & json, const LineSegment & l)
285{
286 to_json(json["start"], l.start());
287 to_json(json["end"], l.end());
288}
289
290Point
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
302Ball
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 dataLoad(std::istream &stream, LineSegment &l, void *context)
void to_json(nlohmann::json &json, const LineSegment &l)
void dataStore(std::ostream &stream, LineSegment &l, void *context)
Point center
Definition MortarUtils.C:58
Ball primitive: a circle in 2D or a sphere in 3D.
Definition Ball.h:35
The LineSegment class is used by the LineMaterialSamplerBase class and for some ray tracing stuff.
Definition LineSegment.h:31
LineSegment()=default
Ball computeBoundingBall() const override
Compute a bounding ball for this line segment.
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.
Definition LineSegment.C:70
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
bool contains_point(const Point &p) const
Determines whether a point is in a line segment or not.
Definition LineSegment.C:63
const Point & end() const
Ending of the line segment.
Definition LineSegment.h:90
void set(const Point &p0, const Point &p1)
Sets the points on the line segment.
void setStart(const Point &p0)
Sets the beginning of the line segment.
Definition LineSegment.h:95
Point normal() const
normal vector of the line segment
void setEnd(const Point &p1)
Sets the end of the line segment.
const Point & start() const
Beginning of the line segment.
Definition LineSegment.h:85
Point closest_point(const Point &p) const
Returns the closest point on the LineSegment to the passed in point.
Definition LineSegment.C:49
const Point & get_planar_point() const
virtual Point unit_normal(const Point &p) const override
bool absolute_fuzzy_equals(const TypeVector< Real > &rhs, Real tol=TOLERANCE) const
auto norm_sq() const
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
auto norm() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Real radius