70 #ifdef BUILD_EGS_MESH_DLL
71 #define EGS_MESH_EXPORT __declspec(dllexport)
73 #define EGS_MESH_EXPORT __declspec(dllimport)
75 #define EGS_MESH_LOCAL
79 #ifdef HAVE_VISIBILITY
80 #define EGS_MESH_EXPORT __attribute__ ((visibility ("default")))
81 #define EGS_MESH_LOCAL __attribute__ ((visibility ("hidden")))
83 #define EGS_MESH_EXPORT
84 #define EGS_MESH_LOCAL
91 class EGS_Mesh_Octree;
100 Tetrahedron(
int tag,
int medium_tag,
int a,
int b,
int c,
int d) :
101 tag(tag), medium_tag(medium_tag), a(a), b(b), c(c), d(d) {}
113 Node(
int tag,
double x,
double y,
double z) :
114 tag(tag), x(x), y(y), z(z) {}
123 Medium(
int tag, std::string medium_name) :
124 tag(tag), medium_name(medium_name) {}
126 std::string medium_name;
130 EGS_MeshSpec(std::vector<Tetrahedron> elements, std::vector<Node> nodes,
131 std::vector<Medium> media) : elements(std::move(elements)),
132 nodes(std::move(nodes)), media(std::move(media)) {}
142 void checkValid()
const;
146 for (
auto &node: nodes) {
158 std::vector<EGS_MeshSpec::Node>
nodes;
160 std::vector<EGS_MeshSpec::Medium>
media;
262 return elt_tags_.size();
267 return nodes_.size();
273 return neighbours_.at(i);
278 const auto &n = element_nodes(i);
279 return std::abs((n.A - n.D) * ((n.B - n.D) % (n.C - n.D))) / 6.0;
284 return EGS_BaseGeometry::getMediumRho(medium_indices_.at(i));
290 return elt_tags_.at(i);
297 return boundary_faces_[4*reg] || boundary_faces_[4*reg + 1] ||
298 boundary_faces_[4*reg + 2] || boundary_faces_[4*reg + 3];
303 const auto &n = element_nodes(i);
304 elt_info <<
" Tetrahedron " << i <<
":\n"
305 <<
" \tNode coordinates (cm):\n"
306 <<
" \t0: " << n.A.x <<
" " << n.A.y <<
" " << n.A.z <<
"\n"
307 <<
" \t1: " << n.B.x <<
" " << n.B.y <<
" " << n.B.z <<
"\n"
308 <<
" \t2: " << n.C.x <<
" " << n.C.y <<
" " << n.C.z <<
"\n"
309 <<
" \t3: " << n.D.x <<
" " << n.C.y <<
" " << n.C.z <<
"\n"
310 <<
" \tNeighbour elements:\n"
311 <<
" \t\tOn face 0: " << neighbours_[i][0] <<
"\n"
312 <<
" \t\tOn face 1: " << neighbours_[i][1] <<
"\n"
313 <<
" \t\tOn face 2: " << neighbours_[i][2] <<
"\n"
314 <<
" \t\tOn face 3: " << neighbours_[i][3] <<
"\n"
316 <<
" \tBoundary element: " << is_boundary(i) <<
"\n"
317 <<
" \tMedia index: "<< medium_indices_[i] <<
"\n";
321 const std::string &getType()
const override {
326 int medium(
int ireg)
const override;
329 EGS_Float &t,
int *newmed=0,
EGS_Vector *normal=0)
override;
330 EGS_Float hownear(
int ireg,
const EGS_Vector &x)
override;
331 void printInfo()
const override;
334 bool insideElement(
int i,
const EGS_Vector &x);
338 struct Intersection {
339 Intersection(EGS_Float dist,
int face_index)
340 : dist(dist), face_index(face_index) {}
366 const auto &node_indices = elt_node_indices_.at(element);
368 nodes_.at(node_indices[0]),
369 nodes_.at(node_indices[1]),
370 nodes_.at(node_indices[2]),
371 nodes_.at(node_indices[3])
378 return nodes_.at(node_offset);
383 return elt_node_indices_.at(element);
388 return EGS_Mesh::min_step_size;
394 EGS_Float min_interior_face_dist(
int ireg,
const EGS_Vector &x);
398 EGS_Float min_exterior_face_dist(
const EGS_Vector &x);
402 EGS_Float &t,
int *newmed,
EGS_Vector *normal);
406 struct PointLocation {
407 PointLocation() =
default;
408 PointLocation(EGS_Float direction_dot_normal, EGS_Float signed_distance)
409 : direction_dot_normal(direction_dot_normal), signed_distance(
412 EGS_Float direction_dot_normal = 0.0;
413 EGS_Float signed_distance = 0.0;
416 PointLocation find_point_location(
const EGS_Vector &x,
const
420 Intersection find_interior_intersection(
421 const std::array<PointLocation, 4> &ixs);
423 int howfar_interior_thick_plane(
424 const std::array<PointLocation, 4> &intersect_tests,
int ireg,
430 int howfar_interior_recover_lost_particle(
int ireg,
const EGS_Vector &x,
431 const EGS_Vector &u, EGS_Float &t,
int *newmed);
437 inline void update_medium(
int newreg,
int *newmed)
const {
446 *newmed = medium(newreg);
450 inline void update_normal(
const EGS_Vector &face_normal,
456 if (face_normal * u_norm > 0.0) {
457 *normal = -1.0 * face_normal;
460 *normal = face_normal;
466 if (num_elements() < 50000) {
489 void initializeElements(std::vector<EGS_MeshSpec::Tetrahedron> elements,
490 std::vector<EGS_MeshSpec::Node> nodes,
491 std::vector<EGS_MeshSpec::Medium> materials);
496 void initializeMedia(std::vector<EGS_MeshSpec::Tetrahedron> elements,
497 std::vector<EGS_MeshSpec::Medium> materials);
503 void initializeNeighbours();
510 void initializeOctrees();
514 void initializeNormals();
516 std::vector<EGS_Vector> nodes_;
517 std::vector<int> elt_tags_;
518 std::vector<std::array<int, 4>> elt_node_indices_;
521 std::vector<bool> boundary_faces_;
524 std::vector<std::array<EGS_Vector, 4>> face_normals_;
525 std::vector<int> medium_indices_;
527 std::unique_ptr<EGS_Mesh_Octree> volume_tree_;
528 std::unique_ptr<EGS_Mesh_Octree> surface_tree_;
530 std::vector<std::array<int, 4>> neighbours_;
531 static const std::string type;
533 static constexpr EGS_Float min_step_size = 1e-10;
546 class EGS_MESH_EXPORT PercentCounter {
555 void start(EGS_Float goal);
559 void step(EGS_Float delta);
562 void finish(
const std::string &end_msg);
572 double progress_ = 0.0;
575 int old_percent_ = 0;
577 std::chrono::time_point<std::chrono::system_clock> t_start_;
580 bool interactive_ =
false;
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
A container for raw unstructured tetrahedral mesh data.
std::vector< EGS_MeshSpec::Tetrahedron > elements
Unique mesh elements.
void scale(EGS_Float factor)
Multiply all node coordinates by a constant factor.
std::vector< EGS_MeshSpec::Node > nodes
Unique nodes.
std::vector< EGS_MeshSpec::Medium > media
Unique medium information.
A tetrahedral mesh geometry.
EGS_Float element_density(int i) const
Returns the density in g/cm3 of element i.
const std::array< int, 4 > & element_neighbours(int i) const
void printElement(int i, std::ostream &elt_info=std::cout) const
Print information about element i to the stream elt_info.
static EGS_Float get_min_step_size()
Returns the minimum step size (i.e. the fuzzy plane tolerance).
int num_elements() const
Returns the number of mesh elements.
Nodes element_nodes(int element) const
Given an element offset, return the element's node coordinates.
int num_nodes() const
Returns the number of unique mesh nodes.
EGS_Float element_volume(int i) const
Returns the volume in cm3 of element i.
bool is_boundary(int reg) const
const EGS_Vector & node_coordinates(int node_offset) const
int element_tag(int i) const
const std::array< int, 4 > & element_node_offsets(int element) const
Given an element offset, return its four node offsets.
A class representing 3D vectors.
EGS_BaseGeometry class header file.
void(* EGS_InfoFunction)(const char *,...)
Defines a function printf-like prototype for functions to be used to report info, warnings,...
EGS_Vector methods for the manipulation of 3D vectors in cartesian co-ordinates.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
A medium. The medium name must match an EGSnrc medium name.
A 3D point. Units are cm.
A tetrahedral mesh element.