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