https://mooseframework.inl.gov
Loading...
Searching...
No Matches
RayTracing.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// Moose includes
11#include "RayTracing.h"
12#include "LineSegment.h"
13#include "MooseError.h"
14
15#include "libmesh/plane.h"
16#include "libmesh/point.h"
17#include "libmesh/mesh.h"
18#include "libmesh/elem.h"
19
20namespace Moose
21{
22
33int
34sideIntersectedByLine(const Elem * elem,
35 std::vector<int> & not_side,
36 const LineSegment & line_segment,
37 Point & intersection_point)
38{
39 unsigned int n_sides = elem->n_sides();
40
41 // Whether or not they intersect
42 bool intersect = false;
43
44 unsigned int dim = elem->dim();
45
46 for (unsigned int i = 0; i < n_sides; i++)
47 {
48 // Don't search the "not_side"
49 // Note: A linear search is fine here because this vector is going to be < n_sides
50 if (std::find(not_side.begin(), not_side.end(), static_cast<int>(i)) != not_side.end())
51 continue;
52
53 // Get a simplified side element
54 std::unique_ptr<const Elem> side_elem = elem->side_ptr(i);
55
56 if (dim == 3)
57 {
58 // Make a plane out of the first three nodes on the side
59 libMesh::Plane plane(side_elem->point(0), side_elem->point(1), side_elem->point(2));
60
61 // See if they intersect
62 intersect = line_segment.intersect(plane, intersection_point);
63 }
64 else if (dim == 2)
65 {
66 // Make a Line Segment out of the first two nodes on the side
67 LineSegment side_segment(side_elem->point(0), side_elem->point(1));
68
69 // See if they intersect
70 intersect = line_segment.intersect(side_segment, intersection_point);
71 }
72 else // 1D
73 {
74 // See if the line segment contains the point
75 intersect = line_segment.contains_point(side_elem->point(0));
76
77 // If it does then save off that one point as the intersection point
78 if (intersect)
79 intersection_point = side_elem->point(0);
80 }
81
82 if (intersect)
83 {
84 if (side_elem->contains_point(intersection_point))
85 {
86 const Elem * neighbor = elem->neighbor_ptr(i);
87
88 // If this side is on a boundary, let's do another search and see if we can find a better
89 // candidate
90 if (!neighbor)
91 {
92 not_side.push_back(i); // Make sure we don't find this side again
93
94 int better_side = sideIntersectedByLine(elem, not_side, line_segment, intersection_point);
95
96 if (better_side != -1)
97 return better_side;
98 }
99
100 return i;
101 }
102 }
103 }
104
105 // Didn't find one
106 return -1;
107}
108
114int
115sideNeighborIsOn(const Elem * elem, const Elem * neighbor)
116{
117 unsigned int n_sides = elem->n_sides();
118
119 for (unsigned int i = 0; i < n_sides; i++)
120 {
121 if (elem->neighbor_ptr(i) == neighbor)
122 return i;
123 }
124
125 return -1;
126}
127
143void
145 const Elem * current_elem,
146 int incoming_side,
147 const Point & incoming_point,
148 std::vector<Elem *> & intersected_elems,
149 std::vector<LineSegment> & segments)
150{
151 Point intersection_point;
152
153 std::vector<int> not_side(1, incoming_side);
154
155 // Find the side of this element that the LineSegment intersects... while ignoring the incoming
156 // side (we don't want to move backward!)
157 int intersected_side =
158 sideIntersectedByLine(current_elem, not_side, line_segment, intersection_point);
159
160 if (intersected_side != -1) // -1 means that we didn't find any side
161 {
162 // Get the neighbor on that side
163 const Elem * neighbor = current_elem->neighbor_ptr(intersected_side);
164
165 if (neighbor)
166 {
167 // Add it to the list
168 intersected_elems.push_back(const_cast<Elem *>(neighbor));
169
170 // Add the line segment across the element to the segments list
171 segments.push_back(LineSegment(incoming_point, intersection_point));
172
173 // Note: This is finding the side the current_elem is on for the neighbor. That's the
174 // "incoming_side" for the neighbor
175 int incoming_side = sideNeighborIsOn(neighbor, current_elem);
176
177 // Recurse
179 line_segment, neighbor, incoming_side, intersection_point, intersected_elems, segments);
180 }
181 else // Add the final segment
182 segments.push_back(LineSegment(incoming_point, line_segment.end()));
183 }
184 else // Add the final segment
185 segments.push_back(LineSegment(incoming_point, line_segment.end()));
186
187 // Finished... return out!
188 return;
189}
190
191void
193 const Point & p1,
194 const MeshBase & /*mesh*/,
195 const PointLocatorBase & point_locator,
196 std::vector<Elem *> & intersected_elems,
197 std::vector<LineSegment> & segments)
198{
199 // Make sure our list is clear
200 intersected_elems.clear();
201
202 // Find the starting element
203 const Elem * first_elem = point_locator(p0);
204
205 // Quick return if can't even locate the first element.
206 if (!first_elem)
207 return;
208
209 intersected_elems.push_back(const_cast<Elem *>(first_elem));
210
211 // Make a LineSegment object out of our two points for ease:
212 LineSegment line_segment = LineSegment(p0, p1);
213
214 // Find 'em!
216 line_segment, first_elem, -1, p0, intersected_elems, segments);
217}
218}
The LineSegment class is used by the LineMaterialSamplerBase class and for some ray tracing stuff.
Definition LineSegment.h:31
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 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
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
int sideIntersectedByLine(const Elem *elem, std::vector< int > &not_side, const LineSegment &line_segment, Point &intersection_point)
Figure out which (if any) side of an Elem is intersected by a line.
Definition RayTracing.C:34
void elementsIntersectedByLine(const Point &p0, const Point &p1, const MeshBase &mesh, const libMesh::PointLocatorBase &point_locator, std::vector< Elem * > &intersected_elems, std::vector< LineSegment > &segments)
Find all of the elements intersected by a line.
int sideNeighborIsOn(const Elem *elem, const Elem *neighbor)
Returns the side number for elem that neighbor is on.
Definition RayTracing.C:115
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:175
void recursivelyFindElementsIntersectedByLine(const LineSegment &line_segment, const Elem *current_elem, int incoming_side, const Point &incoming_point, std::vector< Elem * > &intersected_elems, std::vector< LineSegment > &segments)
Recursively find all elements intersected by a line segment.
Definition RayTracing.C:144