69 #ifdef BUILD_EGS_MESH_DLL
70 #define EGS_MESH_EXPORT __declspec(dllexport)
72 #define EGS_MESH_EXPORT __declspec(dllimport)
74 #define EGS_MESH_LOCAL
78 #ifdef HAVE_VISIBILITY
79 #define EGS_MESH_EXPORT __attribute__ ((visibility ("default")))
80 #define EGS_MESH_LOCAL __attribute__ ((visibility ("hidden")))
82 #define EGS_MESH_EXPORT
83 #define EGS_MESH_LOCAL
90 class EGS_Mesh_Octree;
99 Tetrahedron(
int tag,
int medium_tag,
int a,
int b,
int c,
int d) :
100 tag(tag), medium_tag(medium_tag), a(a), b(b), c(c), d(d) {}
112 Node(
int tag,
double x,
double y,
double z) :
113 tag(tag), x(x), y(y), z(z) {}
122 Medium(
int tag, std::string medium_name) :
123 tag(tag), medium_name(medium_name) {}
125 std::string medium_name;
129 EGS_MeshSpec(std::vector<Tetrahedron> elements, std::vector<Node> nodes,
130 std::vector<Medium> media) : elements(std::move(elements)),
131 nodes(std::move(nodes)), media(std::move(media)) {}
141 void checkValid()
const;
145 for (
auto &node: nodes) {
157 std::vector<EGS_MeshSpec::Node>
nodes;
159 std::vector<EGS_MeshSpec::Medium>
media;
261 return elt_tags_.size();
266 return nodes_.size();
272 return neighbours_.at(i);
277 const auto &n = element_nodes(i);
278 return std::abs((n.A - n.D) * ((n.B - n.D) % (n.C - n.D))) / 6.0;
283 return EGS_BaseGeometry::getMediumRho(medium_indices_.at(i));
289 return elt_tags_.at(i);
296 return boundary_faces_[4*reg] || boundary_faces_[4*reg + 1] ||
297 boundary_faces_[4*reg + 2] || boundary_faces_[4*reg + 3];
302 const auto &n = element_nodes(i);
303 elt_info <<
" Tetrahedron " << i <<
":\n"
304 <<
" \tNode coordinates (cm):\n"
305 <<
" \t0: " << n.A.x <<
" " << n.A.y <<
" " << n.A.z <<
"\n"
306 <<
" \t1: " << n.B.x <<
" " << n.B.y <<
" " << n.B.z <<
"\n"
307 <<
" \t2: " << n.C.x <<
" " << n.C.y <<
" " << n.C.z <<
"\n"
308 <<
" \t3: " << n.D.x <<
" " << n.C.y <<
" " << n.C.z <<
"\n"
309 <<
" \tNeighbour elements:\n"
310 <<
" \t\tOn face 0: " << neighbours_[i][0] <<
"\n"
311 <<
" \t\tOn face 1: " << neighbours_[i][1] <<
"\n"
312 <<
" \t\tOn face 2: " << neighbours_[i][2] <<
"\n"
313 <<
" \t\tOn face 3: " << neighbours_[i][3] <<
"\n"
315 <<
" \tBoundary element: " << is_boundary(i) <<
"\n"
316 <<
" \tMedia index: "<< medium_indices_[i] <<
"\n";
320 const std::string &
getType()
const override {
325 int medium(
int ireg)
const override;
328 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0)
override;
333 bool insideElement(
int i,
const EGS_Vector &x);
337 struct Intersection {
338 Intersection(EGS_Float dist,
int face_index)
339 : dist(dist), face_index(face_index) {}
365 const auto &node_indices = elt_node_indices_.at(element);
367 nodes_.at(node_indices[0]),
368 nodes_.at(node_indices[1]),
369 nodes_.at(node_indices[2]),
370 nodes_.at(node_indices[3])
377 return nodes_.at(node_offset);
382 return elt_node_indices_.at(element);
387 return EGS_Mesh::min_step_size;
393 EGS_Float min_interior_face_dist(
int ireg,
const EGS_Vector &x);
397 EGS_Float min_exterior_face_dist(
const EGS_Vector &x);
401 EGS_Float &t,
int *newmed,
EGS_Vector *normal);
405 struct PointLocation {
406 PointLocation() =
default;
407 PointLocation(EGS_Float direction_dot_normal, EGS_Float signed_distance)
408 : direction_dot_normal(direction_dot_normal), signed_distance(
411 EGS_Float direction_dot_normal = 0.0;
412 EGS_Float signed_distance = 0.0;
415 PointLocation find_point_location(
const EGS_Vector &x,
const
419 Intersection find_interior_intersection(
420 const std::array<PointLocation, 4> &ixs);
422 int howfar_interior_thick_plane(
423 const std::array<PointLocation, 4> &intersect_tests,
int ireg,
429 int howfar_interior_recover_lost_particle(
int ireg,
const EGS_Vector &x,
430 const EGS_Vector &u, EGS_Float &t,
int *newmed);
436 inline void update_medium(
int newreg,
int *newmed)
const {
449 inline void update_normal(
const EGS_Vector &face_normal,
455 if (face_normal * u_norm > 0.0) {
456 *normal = -1.0 * face_normal;
459 *normal = face_normal;
465 if (num_elements() < 50000) {
488 void initializeElements(std::vector<EGS_MeshSpec::Tetrahedron> elements,
489 std::vector<EGS_MeshSpec::Node> nodes,
490 std::vector<EGS_MeshSpec::Medium> materials);
495 void initializeMedia(std::vector<EGS_MeshSpec::Tetrahedron> elements,
496 std::vector<EGS_MeshSpec::Medium> materials);
502 void initializeNeighbours();
509 void initializeOctrees();
513 void initializeNormals();
515 std::vector<EGS_Vector> nodes_;
516 std::vector<int> elt_tags_;
517 std::vector<std::array<int, 4>> elt_node_indices_;
520 std::vector<bool> boundary_faces_;
523 std::vector<std::array<EGS_Vector, 4>> face_normals_;
524 std::vector<int> medium_indices_;
526 std::unique_ptr<EGS_Mesh_Octree> volume_tree_;
527 std::unique_ptr<EGS_Mesh_Octree> surface_tree_;
529 std::vector<std::array<int, 4>> neighbours_;
530 static const std::string type;
532 static constexpr EGS_Float min_step_size = 1e-10;
545 class EGS_MESH_EXPORT PercentCounter {
554 void start(EGS_Float goal);
558 void step(EGS_Float delta);
561 void finish(
const std::string &end_msg);
571 double progress_ = 0.0;
574 int old_percent_ = 0;
576 std::chrono::time_point<std::chrono::system_clock> t_start_;
579 bool interactive_ =
false;
A 3D point. Units are cm.
virtual const string & getType() const =0
Get the geometry type.
virtual bool isInside(const EGS_Vector &x)=0
Is the position x inside the geometry?
A tetrahedral mesh element.
const std::array< int, 4 > & element_neighbours(int i) const
A medium. The medium name must match an EGSnrc medium name.
virtual int medium(int ireg) const
Returns the medium index in region ireg.
const EGS_Vector & node_coordinates(int node_offset) const
virtual void printInfo() const
Print information about this geometry.
A container for raw unstructured tetrahedral mesh data.
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
void scale(EGS_Float factor)
Multiply all node coordinates by a constant factor.
A class representing 3D vectors.
virtual int isWhere(const EGS_Vector &x)=0
In which region is poisition x?
void printElement(int i, std::ostream &elt_info=std::cout) const
Print information about element i to the stream elt_info.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
int num_nodes() const
Returns the number of unique mesh nodes.
const std::array< int, 4 > & element_node_offsets(int element) const
Given an element offset, return its four node offsets.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
static EGS_Float get_min_step_size()
Returns the minimum step size (i.e. the fuzzy plane tolerance).
A tetrahedral mesh geometry.
virtual int inside(const EGS_Vector &x)=0
Returns the region index, if inside, or -1 if outside (obsolete)
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
Nodes element_nodes(int element) const
Given an element offset, return the element's node coordinates.
std::vector< EGS_MeshSpec::Tetrahedron > elements
Unique mesh elements.
std::vector< EGS_MeshSpec::Node > nodes
Unique nodes.
virtual EGS_Float hownear(int ireg, const EGS_Vector &x)=0
Calculate the distance to a boundary for position x in any direction.
bool is_boundary(int reg) const
EGS_Float element_volume(int i) const
Returns the volume in cm3 of element i.
int element_tag(int i) const
void(* EGS_InfoFunction)(const char *,...)
Defines a function printf-like prototype for functions to be used to report info, warnings...
EGS_BaseGeometry class header file.
int num_elements() const
Returns the number of mesh elements.
EGS_Float element_density(int i) const
Returns the density in g/cm3 of element i.
std::vector< EGS_MeshSpec::Medium > media
Unique medium information.