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#include "MooseError.h"
14
15#include "libmesh/plane.h"
16#include "libmesh/vector_value.h"
17
18LineSegment::LineSegment(const Point & p0, const Point & p1) : _p0(p0), _p1(p1) {}
19
20bool
21LineSegment::closest_point(const Point & p, bool clamp_to_segment, Point & closest_p) const
22{
23 Point p0_p = p - _p0;
24 Point p0_p1 = _p1 - _p0;
25 Real p0_p1_2 = p0_p1.norm_sq();
26 Real perp = p0_p(0) * p0_p1(0) + p0_p(1) * p0_p1(1) + p0_p(2) * p0_p1(2);
27 Real t = perp / p0_p1_2;
28 bool on_segment = true;
29
30 if (t < 0.0 || t > 1.0)
31 on_segment = false;
32
33 if (clamp_to_segment)
34 {
35 if (t < 0.0)
36 t = 0.0;
37 else if (t > 1.0)
38 t = 1.0;
39 }
40
41 closest_p = _p0 + p0_p1 * t;
42 return on_segment;
43}
44
45Point
46LineSegment::closest_point(const Point & p) const
47{
48 Point closest_p;
49 closest_point(p, true, closest_p);
50 return closest_p;
51}
52
53bool
54LineSegment::closest_normal_point(const Point & p, Point & closest_p) const
55{
56 return closest_point(p, false, closest_p);
57}
58
59bool
60LineSegment::contains_point(const Point & p) const
61{
62 Point closest_p;
63 return closest_point(p, false, closest_p) && closest_p.absolute_fuzzy_equals(p);
64}
65
66bool
67LineSegment::intersect(const libMesh::Plane & pl, Point & intersect_p) const
68{
83 Point pl0 = pl.get_planar_point();
84 RealVectorValue N = pl.unit_normal(_p0);
85 RealVectorValue I = (_p1 - _p0).unit();
86
87 Real numerator = (pl0 - _p0) * N;
88 Real denominator = I * N;
89
90 // The Line is parallel to the plane
91 if (std::abs(denominator) < 1.e-10)
92 {
93 // The Line is on the plane
94 if (std::abs(numerator) < 1.e-10)
95 {
96 // The solution is not unique so we'll just pick an end point for now
97 intersect_p = _p0;
98 return true;
99 }
100 return false;
101 }
102
103 Real d = numerator / denominator;
104
105 // Make sure we haven't moved off the line segment!
106 if (d + libMesh::TOLERANCE < 0 || d - libMesh::TOLERANCE > (_p1 - _p0).norm())
107 return false;
108
109 intersect_p = d * I + _p0;
110
111 return true;
112}
113
114bool
115LineSegment::intersect(const LineSegment & l, Point & intersect_p) const
116{
138 RealVectorValue a = _p1 - _p0;
139 RealVectorValue b = l._p1 - l._p0;
140 RealVectorValue c = l._p0 - _p0;
141
142 RealVectorValue v = a.cross(b);
143
144 const auto tol = 1.e-10;
145
146 // Parallel lines check
147 if (v.norm() < tol)
148 {
149 // Parallel but not collinear: no intersection
150 if (c.cross(a).norm() >= tol)
151 return false;
152
153 // Collinear: segments overlap if any endpoint lies on the other segment
154 const bool overlap = this->contains_point(l._p0) || this->contains_point(l._p1) ||
156
157 if (!overlap)
158 return false;
159
160 // Pick a deterministic intersection point on the overlap
161 if (this->contains_point(l._p0))
162 intersect_p = l._p0;
163 else if (this->contains_point(l._p1))
164 intersect_p = l._p1;
165 else if (l.contains_point(_p0))
166 intersect_p = _p0;
167 else
168 intersect_p = _p1;
169
170 return true;
171 }
172
173 // Check that the lines are coplanar
174 Real concur = c * (a.cross(b));
175 if (std::abs(concur) > 1.e-10)
176 return false;
177
178 Real s = (c.cross(b) * v) / (v * v);
179 Real t = (c.cross(a) * v) / (v * v);
180
181 // if s and t are between 0 and 1 then the Line Segments intersect
182 // TODO: We could handle other case of clamping to the end of Line
183 // Segements if we want to here
184
185 if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
186 {
187 intersect_p = _p0 + s * a;
188 return true;
189 }
190 return false;
191
247}
248
249bool
250LineSegment::intersect(const LineSegment & line_segment) const
251{
252 Point p;
253 return intersect(line_segment, p);
254}
255
256void
257LineSegment::set(const Point & p0, const Point & p1)
258{
259 setStart(p0);
260 setEnd(p1);
261}
262
263void
264dataStore(std::ostream & stream, LineSegment & l, void * context)
265{
266 dataStore(stream, l.start(), context);
267 dataStore(stream, l.end(), context);
268}
269
270void
271dataLoad(std::istream & stream, LineSegment & l, void * context)
272{
273 Point p0;
274 dataLoad(stream, p0, context);
275 Point p1;
276 dataLoad(stream, p1, context);
277 l.set(p0, p1);
278}
279
280void
281to_json(nlohmann::json & json, const LineSegment & l)
282{
283 to_json(json["start"], l.start());
284 to_json(json["end"], l.end());
285}
286
287Point
289{
290 const auto tangent = _p1 - _p0;
291
292 // Rotate 90 degrees counter-clockwise (2D)
293 Point n(-tangent(1), tangent(0), 0.0);
294 const Real norm = n.norm();
295 if (norm == 0.0)
296 mooseError("LineSegment: cannot compute the normal of a zero-length line segment.");
297
298 return n / norm;
299}
300
301Ball
303{
304 const Point center = 0.5 * (_p0 + _p1);
305 const Real radius = 0.5 * (_p1 - _p0).norm();
306 return Ball(center, radius);
307}
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)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
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:67
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:54
bool contains_point(const Point &p) const
Determines whether a point is in a line segment or not.
Definition LineSegment.C:60
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:46
const Point & get_planar_point() const
virtual Point unit_normal(const Point &p) const override
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
const Real radius