41 #include <gsl/gsl_sys.h>
43 #include <boost/filesystem.hpp>
47 #define SQR(x) ((x)*(x))
48 #define PointID(triangle_id, vertex_id) Triangles_m[triangle_id][vertex_id]
49 #define Point(triangle_id, vertex_id) Points_m[Triangles_m[triangle_id][vertex_id]]
63 #define FUNC_EQ(x, y) inline bool eq(double x, double y) { \
64 return almost_eq(x, y); \
67 #define FUNC_EQ_ZERO(x) inline bool eq_zero(double x) { \
68 return almost_eq_zero(x); \
71 #define FUNC_LE(x, y) inline bool le(double x, double y) { \
72 if (almost_eq(x, y)) { \
78 #define FUNC_LE_ZERO(x) inline bool le_zero(double x) { \
79 if (almost_eq_zero(x)) { \
85 #define FUNC_LT(x, y) inline bool lt(double x, double y) { \
86 if (almost_eq(x, y)) { \
92 #define FUNC_LT_ZERO(x) inline bool lt_zero(double x) { \
93 if (almost_eq_zero(x)) { \
99 #define FUNC_GE(x, y) inline bool ge(double x, double y) { \
100 if (almost_eq(x, y)) { \
106 #define FUNC_GE_ZERO(x) inline bool ge_zero(double x) { \
107 if (almost_eq_zero(x)) { \
113 #define FUNC_GT(x, y) inline bool gt(double x, double y) { \
114 if (almost_eq(x, y)) { \
120 #define FUNC_GT_ZERO(x) inline bool gt_zero(double x) { \
121 if (almost_eq_zero(x)) { \
133 inline bool almost_eq(
double A,
double B,
double maxDiff = 1
e-15,
double maxRelDiff = DBL_EPSILON) {
136 const double diff =
std::abs(A - B);
142 const double largest = (B > A) ? B : A;
144 if (diff <= largest * maxRelDiff)
151 return (diff <= maxDiff);
166 namespace cmp_ulp_obsolete {
171 inline bool almost_eq(
double A,
double B,
double maxDiff = 1
e-20,
int maxUlps = 1000) {
186 #pragma GCC diagnostic push
187 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
188 auto aInt = *(int64_t*)&A;
189 #pragma GCC diagnostic pop
192 aInt = 0x8000000000000000 - aInt;
195 #pragma GCC diagnostic push
196 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
197 auto bInt = *(int64_t*)&B;
198 #pragma GCC diagnostic pop
201 bInt = 0x8000000000000000 - bInt;
204 if (
std::abs (aInt - bInt) <= maxUlps) {
233 inline bool almost_eq (
double A,
double B,
double maxDiff = 1
e-20,
int maxUlps = 1000) {
244 #pragma GCC diagnostic push
245 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
246 auto aInt = *(int64_t*)&A;
247 auto bInt = *(int64_t*)&B;
248 #pragma GCC diagnostic pop
252 if (std::signbit (aInt) != std::signbit (bInt))
256 return (
std::abs (aInt - bInt) <= maxUlps);
274 namespace cmp = cmp_ulp;
309 Vector_t get_max_extent (std::vector<Vector_t>& coords) {
311 coords.begin (), coords.end (), VectorLessX ());
313 coords.begin (), coords.end (), VectorLessY ());
315 coords.begin (), coords.end (), VectorLessZ ());
323 Vector_t get_min_extent (std::vector<Vector_t>& coords) {
325 coords.begin (), coords.end (), VectorLessX ());
327 coords.begin (), coords.end (), VectorLessY ());
329 coords.begin (), coords.end (), VectorLessZ ());
336 static void write_voxel_mesh (
338 const std::unordered_map<
int, std::unordered_set<int> >& ids,
344 const size_t numpoints = 8 * ids.size ();
347 *gmsg <<
level2 <<
"* Writing VTK file of voxel mesh '" << fname <<
"'" <<
endl;
352 of <<
"# vtk DataFile Version 2.0" <<
std::endl;
353 of <<
"generated using BoundaryGeometry::computeMeshVoxelization"
356 of <<
"DATASET UNSTRUCTURED_GRID" <<
std::endl;
357 of <<
"POINTS " << numpoints <<
" float" <<
std::endl;
359 const auto nr0_times_nr1 = nr[0] * nr[1];
360 for (
auto& elem: ids) {
361 auto id = elem.first;
362 int k = (
id - 1) / nr0_times_nr1;
363 int rest = (
id - 1) % nr0_times_nr1;
364 int j = rest / nr[0];
365 int i = rest % nr[0];
368 P[0] = i * hr_m[0] + origin[0];
369 P[1] = j * hr_m[1] + origin[1];
370 P[2] = k * hr_m[2] + origin[2];
372 of << P[0] <<
" " << P[1] <<
" " << P[2] <<
std::endl;
373 of << P[0] + hr_m[0] <<
" " << P[1] <<
" " << P[2] <<
std::endl;
374 of << P[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] <<
std::endl;
375 of << P[0] + hr_m[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] <<
std::endl;
376 of << P[0] <<
" " << P[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
377 of << P[0] + hr_m[0] <<
" " << P[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
378 of << P[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
379 of << P[0] + hr_m[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
382 const auto num_cells = ids.size ();
383 of <<
"CELLS " << num_cells <<
" " << 9 * num_cells <<
std::endl;
384 for (
size_t i = 0; i < num_cells; i++)
386 << 8 * i <<
" " << 8 * i + 1 <<
" " << 8 * i + 2 <<
" " << 8 * i + 3 <<
" "
387 << 8 * i + 4 <<
" " << 8 * i + 5 <<
" " << 8 * i + 6 <<
" " << 8 * i + 7 << std::endl;
388 of <<
"CELL_TYPES " << num_cells <<
std::endl;
389 for (
size_t i = 0; i < num_cells; i++)
390 of <<
"11" << std::endl;
391 of <<
"CELL_DATA " << num_cells <<
std::endl;
392 of <<
"SCALARS " <<
"cell_attribute_data" <<
" float " <<
"1" <<
std::endl;
393 of <<
"LOOKUP_TABLE " <<
"default" <<
std::endl;
394 for (
size_t i = 0; i < num_cells; i++)
395 of << (
float)(i) << std::endl;
397 of <<
"COLOR_SCALARS " <<
"BBoxColor " << 4 <<
std::endl;
398 for (
size_t i = 0; i < num_cells; i++) {
399 of <<
"1.0" <<
" 1.0 " <<
"0.0 " <<
"1.0" <<
std::endl;
430 inline double v1(
int i)
const {
436 inline double v2(
int i)
const {
442 inline double v3(
int i)
const {
451 pts[0][0] *= scaleby[0];
452 pts[0][1] *= scaleby[1];
453 pts[0][2] *= scaleby[2];
454 pts[1][0] *= scaleby[0];
455 pts[1][1] *= scaleby[1];
456 pts[1][2] *= scaleby[2];
457 pts[2][0] *= scaleby[0];
458 pts[2][1] *= scaleby[1];
459 pts[2][2] *= scaleby[2];
477 int outcode_fcmp = 0;
479 if (
cmp::gt(p[0], 0.5)) outcode_fcmp |= 0x01;
480 if (
cmp::lt(p[0], -0.5)) outcode_fcmp |= 0x02;
481 if (
cmp::gt(p[1], 0.5)) outcode_fcmp |= 0x04;
482 if (
cmp::lt(p[1], -0.5)) outcode_fcmp |= 0x08;
483 if (
cmp::gt(p[2], 0.5)) outcode_fcmp |= 0x10;
484 if (
cmp::lt(p[2], -0.5)) outcode_fcmp |= 0x20;
486 return(outcode_fcmp);
497 int outcode_fcmp = 0;
499 if (
cmp::gt( p[0] + p[1], 1.0)) outcode_fcmp |= 0x001;
500 if (
cmp::gt( p[0] - p[1], 1.0)) outcode_fcmp |= 0x002;
501 if (
cmp::gt(-p[0] + p[1], 1.0)) outcode_fcmp |= 0x004;
502 if (
cmp::gt(-p[0] - p[1], 1.0)) outcode_fcmp |= 0x008;
503 if (
cmp::gt( p[0] + p[2], 1.0)) outcode_fcmp |= 0x010;
504 if (
cmp::gt( p[0] - p[2], 1.0)) outcode_fcmp |= 0x020;
505 if (
cmp::gt(-p[0] + p[2], 1.0)) outcode_fcmp |= 0x040;
506 if (
cmp::gt(-p[0] - p[2], 1.0)) outcode_fcmp |= 0x080;
507 if (
cmp::gt( p[1] + p[2], 1.0)) outcode_fcmp |= 0x100;
508 if (
cmp::gt( p[1] - p[2], 1.0)) outcode_fcmp |= 0x200;
509 if (
cmp::gt(-p[1] + p[2], 1.0)) outcode_fcmp |= 0x400;
510 if (
cmp::gt(-p[1] - p[2], 1.0)) outcode_fcmp |= 0x800;
512 return(outcode_fcmp);
523 int outcode_fcmp = 0;
525 if (
cmp::gt( p[0] + p[1] + p[2], 1.5)) outcode_fcmp |= 0x01;
526 if (
cmp::gt( p[0] + p[1] - p[2], 1.5)) outcode_fcmp |= 0x02;
527 if (
cmp::gt( p[0] - p[1] + p[2], 1.5)) outcode_fcmp |= 0x04;
528 if (
cmp::gt( p[0] - p[1] - p[2], 1.5)) outcode_fcmp |= 0x08;
529 if (
cmp::gt(-p[0] + p[1] + p[2], 1.5)) outcode_fcmp |= 0x10;
530 if (
cmp::gt(-p[0] + p[1] - p[2], 1.5)) outcode_fcmp |= 0x20;
531 if (
cmp::gt(-p[0] - p[1] + p[2], 1.5)) outcode_fcmp |= 0x40;
532 if (
cmp::gt(-p[0] - p[1] - p[2], 1.5)) outcode_fcmp |= 0x80;
534 return(outcode_fcmp);
553 #define LERP(a, b, t) (a + t * (b - a))
555 plane_point[0] =
LERP(p1[0], p2[0], alpha);
556 plane_point[1] =
LERP(p1[1], p2[1], alpha);
557 plane_point[2] =
LERP(p1[2], p2[2], alpha);
559 return(face_plane(plane_point) & mask);
573 const int outcode_diff
575 if ((0x01 & outcode_diff) != 0)
576 if (check_point(p1,p2,( .5-p1[0])/(p2[0]-p1[0]),0x3e) ==
INSIDE)
return(
INSIDE);
577 if ((0x02 & outcode_diff) != 0)
578 if (check_point(p1,p2,(-.5-p1[0])/(p2[0]-p1[0]),0x3d) ==
INSIDE)
return(
INSIDE);
579 if ((0x04 & outcode_diff) != 0)
580 if (check_point(p1,p2,( .5-p1[1])/(p2[1]-p1[1]),0x3b) ==
INSIDE)
return(
INSIDE);
581 if ((0x08 & outcode_diff) != 0)
582 if (check_point(p1,p2,(-.5-p1[1])/(p2[1]-p1[1]),0x37) ==
INSIDE)
return(
INSIDE);
583 if ((0x10 & outcode_diff) != 0)
584 if (check_point(p1,p2,( .5-p1[2])/(p2[2]-p1[2]),0x2f) ==
INSIDE)
return(
INSIDE);
585 if ((0x20 & outcode_diff) != 0)
586 if (check_point(p1,p2,(-.5-p1[2])/(p2[2]-p1[2]),0x1f) ==
INSIDE)
return(
INSIDE);
599 return (((A[0] < EPS) ? 4 : 0) | ((A[0] > -EPS) ? 32 : 0) |
600 ((A[1] < EPS) ? 2 : 0) | ((A[1] > -EPS) ? 16 : 0) |
601 ((A[2] < EPS) ? 1 : 0) | ((A[2] > -EPS) ? 8 : 0));
605 point_triangle_intersection (
630 const int sign12 = SIGN3(cross12_1p);
635 const int sign23 = SIGN3(cross23_2p);
640 const int sign31 = SIGN3(cross31_3p);
660 triangle_intersects_cube (
679 if ((v1_test & v2_test & v3_test) != 0)
return(
OUTSIDE);
684 v1_test |= bevel_2d(t.
v1()) << 8;
685 v2_test |= bevel_2d(t.
v2()) << 8;
686 v3_test |= bevel_2d(t.
v3()) << 8;
687 if ((v1_test & v2_test & v3_test) != 0)
return(
OUTSIDE);
692 v1_test |= bevel_3d(t.
v1()) << 24;
693 v2_test |= bevel_3d(t.
v2()) << 24;
694 v3_test |= bevel_3d(t.
v3()) << 24;
695 if ((v1_test & v2_test & v3_test) != 0)
return(
OUTSIDE);
705 if ((v1_test & v2_test) == 0)
707 if ((v1_test & v3_test) == 0)
709 if ((v2_test & v3_test) == 0)
739 double d = norm[0] * t.
v1(0) + norm[1] * t.
v1(1) + norm[2] * t.
v1(2);
745 double denom = norm[0] + norm[1] + norm[2];
750 if (point_triangle_intersection(hitpp,t) ==
INSIDE)
753 denom = norm[0] + norm[1] - norm[2];
756 hitpn[2] = -(hitpn[0] = hitpn[1] = d / denom);
758 if (point_triangle_intersection(hitpn,t) ==
INSIDE)
761 denom = norm[0] - norm[1] + norm[2];
764 hitnp[1] = -(hitnp[0] = hitnp[2] = d / denom);
766 if (point_triangle_intersection(hitnp,t) ==
INSIDE)
769 denom = norm[0] - norm[1] - norm[2];
772 hitnn[1] = hitnn[2] = -(hitnn[0] = d / denom);
774 if (point_triangle_intersection(hitnn,t) ==
INSIDE)
841 pts[0][0] *= scale[0];
842 pts[0][1] *= scale[1];
843 pts[0][2] *= scale[2];
844 pts[1][0] *= scale[0];
845 pts[1][1] *= scale[1];
846 pts[1][2] *= scale[2];
893 t_.
scale (scaleby , v_.
pts[0] + 0.5);
894 return triangle_intersects_cube (t_);
916 static inline Vector_t normalVector (
924 return N / magnitude;
928 static inline double computeArea (
950 SIZE,
"GEOMETRY",
"The \"GEOMETRY\" statement defines the beam pipe geometry.") {
954 "Specifies the geometry file [H5hut]",
959 "If FGEOM is selected topo is over-written. ",
960 {
"RECTANGULAR",
"BOXCORNER",
"ELLIPTIC"},
965 "Specifies the length of a tube shaped elliptic beam pipe [m]",
970 "Specifies the start of a tube shaped elliptic beam pipe [m]",
975 "Specifies the major semi-axis of a tube shaped elliptic beam pipe [m]",
980 "Specifies the major semi-axis of a tube shaped elliptic beam pipe [m]",
985 "In case of BOXCORNER Specifies first part with height == B [m]",
990 "In case of BOXCORNER Specifies first second with height == B-C [m]",
995 "In case of BOXCORNER Specifies height of corner C [m]",
1000 "Multiplicative scaling factor for coordinates ",
1005 "Multiplicative scaling factor for X coordinates ",
1010 "Multiplicative scaling factor for Y coordinates ",
1015 "Multiplicative scaling factor for Z coordinates ",
1020 "Shift in z direction",
1024 (
"INSIDEPOINT",
"A point inside the geometry");
1045 gsl_rng_env_setup();
1046 randGen_m = gsl_rng_alloc(gsl_rng_default);
1053 const std::string&
name,
1056 gsl_rng_env_setup();
1057 randGen_m = gsl_rng_alloc(gsl_rng_default);
1102 throw OpalException (
"BoundaryGeometry::find()",
"Geometry \""
1103 + name +
"\" not found.");
1112 const int triangle_id,
1178 const int triangle_id,
1194 const double a = -
dot(n,w0);
1195 const double b =
dot(n,dir);
1205 const double r = a / b;
1223 const double uu =
dot(u,u);
1224 const double uv =
dot(u,v);
1225 const double vv =
dot(v,v);
1227 const double wu =
dot(w,u);
1228 const double wv =
dot(w,v);
1229 const double D = uv * uv - uu * vv;
1232 const double s = (uv * wv - vv * wu) / D;
1236 const double t = (uv * wu - uu * wv) / D;
1250 static inline double magnitude (
1266 double distance = P[0] - x;
1271 if (
cmp::lt(x - P[0], distance)) {
1272 distance = x - P[0];
1273 ref_pt = {x, P[1], P[2]};
1278 if (
cmp::lt(P[1] - y, distance)) {
1280 ref_pt = {P[0], y, P[1]};
1285 if (
cmp::lt(y - P[1], distance)) {
1286 distance = y - P[1];
1287 ref_pt = {P[0], y, P[2]};
1291 if (
cmp::lt(P[2] - z, distance)) {
1292 distance = P[2] - z;
1293 ref_pt = {P[0], P[1], z};
1297 if (
cmp::lt(z - P[2], distance)) {
1298 ref_pt = {P[0], P[1], z};
1307 return (k % 2) == 1;
1366 *gmsg <<
level2 <<
"* Searching for a point inside the geometry..." <<
endl;
1371 std::vector<Vector_t> P_outs {
1381 for (
const auto& P: P_outs) {
1406 }
else if (n == n_i) {
1437 *gmsg <<
"* " << __func__ <<
": "
1438 <<
"reference_pt=" << reference_pt
1439 <<
", P=" << P <<
endl;
1443 const Vector_t v = reference_pt - P;
1451 int triangle_id = -1;
1453 for (
int i = 0; i < N; i++) {
1460 *gmsg <<
"* " << __func__ <<
": "
1461 <<
"result: " << result <<
endl;
1487 *gmsg <<
"* " << __func__ <<
": "
1505 int triangle_id = -1;
1508 I, triangle_id) > 0) ? 1 : 0;
1511 *gmsg <<
"* " << __func__ <<
": "
1512 <<
" result=" << result
1543 #define mapPoint2VoxelIndices(pt, i, j, k) { \
1544 i = floor ((pt[0] - voxelMesh_m.minExtent [0]) / voxelMesh_m.sizeOfVoxel[0]); \
1545 j = floor ((pt[1] - voxelMesh_m.minExtent [1]) / voxelMesh_m.sizeOfVoxel[1]); \
1546 k = floor ((pt[2] - voxelMesh_m.minExtent [2]) / voxelMesh_m.sizeOfVoxel[2]); \
1547 if (!(0 <= i && i < voxelMesh_m.nr_m[0] && \
1548 0 <= j && j < voxelMesh_m.nr_m[1] && \
1549 0 <= k && k < voxelMesh_m.nr_m[2])) { \
1551 << "* " << __func__ << ":" \
1552 << " WARNING: pt=" << pt \
1553 << " is outside the bbox" \
1588 for (
unsigned int triangle_id = 0; triangle_id <
Triangles_m.size(); triangle_id++) {
1600 int i_min, j_min, k_min;
1601 int i_max, j_max, k_max;
1605 for (
int i = i_min; i <= i_max; i++) {
1606 for (
int j = j_min; j <= j_max; j++) {
1607 for (
int k = k_min; k <= k_max; k++) {
1617 *gmsg <<
level2 <<
"* Mesh voxelization done" <<
endl;
1625 bool writeVTK =
false;
1627 if (!std::filesystem::exists(vtkFileName)) {
1632 auto t_geom = boost::filesystem::last_write_time(
h5FileName_m);
1633 auto t_vtk = boost::filesystem::last_write_time(vtkFileName);
1634 if (std::difftime(t_geom, t_vtk) > 0) {
1640 write_voxel_mesh (vtkFileName,
1664 double longest_edge_max_m = 0.0;
1665 for (
unsigned int i = 0; i < bg->
Triangles_m.size(); i++) {
1671 SQR (x1[0] - x2[0]) +
SQR (x1[1] - x2[1]) +
SQR (x1[2] - x2[2]));
1673 SQR (x3[0] - x2[0]) +
SQR (x3[1] - x2[1]) +
SQR (x3[2] - x2[2]));
1675 SQR (x3[0] - x1[0]) +
SQR (x3[1] - x1[1]) +
SQR (x3[2] - x1[2]));
1677 double max = length_edge1;
1678 if (length_edge2 > max) max = length_edge2;
1679 if (length_edge3 > max) max = length_edge3;
1682 if (longest_edge_max_m < max) longest_edge_max_m =
max;
1839 static void computeTriangleNeighbors (
1841 std::vector<std::set<unsigned int>>& neighbors
1843 std::vector<std::set<unsigned int>> adjacencies_to_pt (bg->
Points_m.size());
1846 for (
unsigned int triangle_id = 0; triangle_id < bg->
Triangles_m.size(); triangle_id++) {
1847 for (
unsigned int j = 1; j <= 3; j++) {
1848 auto pt_id = bg->PointID (triangle_id, j);
1850 adjacencies_to_pt [pt_id].insert (triangle_id);
1854 for (
unsigned int triangle_id = 0; triangle_id < bg->
Triangles_m.size(); triangle_id++) {
1855 std::set<unsigned int> to_A = adjacencies_to_pt [bg->PointID (triangle_id, 1)];
1856 std::set<unsigned int> to_B = adjacencies_to_pt [bg->PointID (triangle_id, 2)];
1857 std::set<unsigned int> to_C = adjacencies_to_pt [bg->PointID (triangle_id, 3)];
1859 std::set<unsigned int> intersect;
1860 std::set_intersection (
1861 to_A.begin(), to_A.end(),
1862 to_B.begin(), to_B.end(),
1863 std::inserter(intersect,intersect.begin()));
1864 std::set_intersection(
1865 to_B.begin(), to_B.end(),
1866 to_C.begin(), to_C.end(),
1867 std::inserter(intersect,intersect.begin()));
1868 std::set_intersection(
1869 to_C.begin(), to_C.end(),
1870 to_A.begin(), to_A.end(),
1871 std::inserter(intersect, intersect.begin()));
1872 intersect.erase (triangle_id);
1874 neighbors [triangle_id] = intersect;
1876 *gmsg <<
level2 <<
"* " << __func__ <<
": Computing neighbors done" <<
endl;
1906 std::vector<Vector_t> intersection_points;
1909 for (
unsigned int triangle_id = 0; triangle_id < bg->
Triangles_m.size(); triangle_id++) {
1912 intersection_points.push_back (result);
1917 return ((intersection_points.size () % 2) == 1);
1921 static bool hasInwardPointingNormal (
1923 const int triangle_id
1928 const Vector_t triNormal = normalVector (A, B, C);
1937 const Vector_t P = (A+B+
C)/3 + triNormal * minvoxelmesh;
1947 const bool is_inside =
isInside (bg, P);
1948 const double dotPA_N =
dot (P - A, triNormal);
1949 return (is_inside && dotPA_N >= 0) || (!is_inside && dotPA_N < 0);
1953 static void orientTriangle (
BoundaryGeometry* bg,
int ref_id,
int triangle_id) {
1958 for (
int i = 1; i <= 3; i++) {
1959 for (
int j = 1; j <= 3; j++) {
1960 if (bg->PointID (triangle_id, j) == bg->PointID (ref_id, i)) {
1964 if (n == 2)
goto edge_found;
1970 int diff =
id[1] -
id[0];
1971 if ((((ic[1] - ic[0]) == 1) && ((diff == 1) || (diff == -2))) ||
1972 (((ic[1] - ic[0]) == 2) && ((diff == -1) || (diff == 2)))) {
1973 std::swap (bg->PointID (triangle_id,
id[0]), bg->PointID (triangle_id,
id[1]));
1978 std::vector<std::set<unsigned int>> neighbors (bg->
Triangles_m.size());
1980 computeTriangleNeighbors (bg, neighbors);
1983 int triangle_id = 0;
1985 std::vector<unsigned int> triangles (bg->
Triangles_m.size());
1986 std::vector<unsigned int>::size_type queue_cursor = 0;
1987 std::vector<unsigned int>::size_type queue_end = 0;
1988 std::vector <bool> isOriented (bg->
Triangles_m.size(),
false);
1995 while (isOriented[triangle_id])
1999 if (!hasInwardPointingNormal (bg, triangle_id)) {
2000 std::swap (bg->PointID (triangle_id, 2), bg->PointID (triangle_id, 3));
2002 isOriented[triangle_id] =
true;
2005 triangles[queue_end++] = triangle_id;
2007 for (
auto neighbor_id: neighbors[triangle_id]) {
2008 if (isOriented[neighbor_id])
continue;
2009 orientTriangle (bg, triangle_id, neighbor_id);
2010 isOriented[neighbor_id] =
true;
2011 triangles[queue_end++] = neighbor_id;
2014 }
while (queue_cursor < queue_end && (triangle_id = triangles[queue_cursor],
true));
2018 *gmsg <<
level2 <<
"* " << __func__ <<
": mesh is contiguous" <<
endl;
2020 *gmsg <<
level2 <<
"* " << __func__ <<
": mesh is discontiguous (" << parts <<
") parts" <<
endl;
2022 *gmsg <<
level2 <<
"* Triangle Normal built done" <<
endl;
2028 *gmsg <<
level2 <<
"* Initializing Boundary Geometry..." <<
endl;
2034 "', please check if it exists");
2044 #if defined (NDEBUG)
2047 rc = H5SetErrorHandler (H5AbortErrorhandler);
2049 H5SetVerbosityLevel (1);
2051 h5_prop_t props = H5CreateFileProp ();
2053 H5SetPropFileMPIOCollective (props, &comm);
2054 h5_file_t f = H5OpenFile (
h5FileName_m.c_str(), H5_O_RDONLY, props);
2055 H5CloseProp (props);
2057 h5t_mesh_t* m =
nullptr;
2058 H5FedOpenTriangleMesh (f,
"0", &m);
2059 H5FedSetLevel (m, 0);
2061 auto numTriangles = H5FedGetNumElementsTotal (m);
2065 h5_loc_id_t local_id;
2067 h5t_iterator_t* iter = H5FedBeginTraverseEntities (m, 0);
2068 while ((local_id = H5FedTraverseEntities (iter)) >= 0) {
2069 h5_loc_id_t local_vids[4];
2070 H5FedGetVertexIndicesOfEntity (m, local_id, local_vids);
2072 PointID (i, 1) = local_vids[0];
2073 PointID (i, 2) = local_vids[1];
2074 PointID (i, 3) = local_vids[2];
2077 H5FedEndTraverseEntities (iter);
2080 int num_points = H5FedGetNumVerticesTotal (m);
2082 for (i = 0; i < num_points; i++) {
2084 H5FedGetVertexCoordsByIndex (m, i, P);
2086 P[0] * xyzscale * xscale,
2087 P[1] * xyzscale * yscale,
2088 P[2] * xyzscale * zscale + zshift));
2092 *gmsg <<
level2 <<
"* Reading mesh done" <<
endl;
2094 Local::computeGeometryInterval (
this);
2099 if (pt.size () != 3) {
2101 "BoundaryGeometry::initialize()",
2102 "Dimension of INSIDEPOINT must be 3");
2107 if (is_inside ==
false) {
2109 "BoundaryGeometry::initialize()",
2110 "INSIDEPOINT is not inside the geometry");
2117 *gmsg <<
level2 <<
"* using as point inside the geometry: ("
2122 *gmsg <<
level2 <<
"* no point inside the geometry found!" <<
endl;
2125 Local::makeTriangleNormalInwardPointing (
this);
2139 *gmsg <<
level2 <<
"* Triangle barycent built done" <<
endl;
2141 *gmsg << *
this <<
endl;
2168 *gmsg <<
"* " << __func__ <<
": "
2175 const Ray r =
Ray (P, v_);
2206 std::unordered_set<int> triangle_ids;
2207 for (
int i = i_min; i <= i_max; i++) {
2208 for (
int j = j_min; j <= j_max; j++) {
2209 for (
int k = k_min; k <= k_max; k++) {
2213 if (
debugFlags_m & debug_intersectTinyLineSegmentBoundary) {
2214 *gmsg <<
"* " << __func__ <<
": "
2215 <<
" Test voxel: (" << i <<
", " << j <<
", " << k <<
"), "
2232 const auto triangles_intersecting_voxel =
2234 if (triangles_intersecting_voxel !=
voxelMesh_m.ids.end()) {
2235 triangle_ids.insert (
2236 triangles_intersecting_voxel->second.begin(),
2237 triangles_intersecting_voxel->second.end());
2246 int num_intersections = 0;
2247 int tmp_intersect_result = 0;
2249 for (
auto it = triangle_ids.begin ();
2250 it != triangle_ids.end ();
2259 if (
debugFlags_m & debug_intersectTinyLineSegmentBoundary) {
2260 *gmsg <<
"* " << __func__ <<
": "
2261 <<
" Test triangle: " << *
it
2262 <<
" intersect: " << tmp_intersect_result
2269 switch (tmp_intersect_result) {
2278 t = (tmp_intersect_pt[0] - P[0]) / (Q[0] - P[0]);
2280 t = (tmp_intersect_pt[1] - P[1]) / (Q[1] - P[1]);
2282 t = (tmp_intersect_pt[2] - P[2]) / (Q[2] - P[2]);
2284 num_intersections++;
2287 if (
debugFlags_m & debug_intersectTinyLineSegmentBoundary) {
2288 *gmsg <<
"* " << __func__ <<
": "
2294 intersect_pt = tmp_intersect_pt;
2295 triangle_id = (*it);
2299 PAssert (tmp_intersect_result != -1);
2303 return num_intersections;
2321 *gmsg <<
"* " << __func__ <<
": "
2331 int intersect_result = 0;
2333 int i_min, j_min, k_min;
2334 int i_max, j_max, k_max;
2348 }
while (( (i_max-i_min+1) * (j_max-j_min+1) * (k_max-k_min+1)) > 27);
2353 for (
int l = 1; l <=
n; l++, P = Q) {
2356 P, Q, intersect_pt, triangle_id);
2357 if (triangle_id != -1) {
2362 if (
debugFlags_m & debug_intersectLineSegmentBoundary) {
2363 *gmsg <<
"* " << __func__ <<
": "
2364 <<
" result=" << intersect_result
2365 <<
" intersection pt: " << intersect_pt
2370 return intersect_result;
2392 *gmsg <<
"* " << __func__ <<
": "
2413 int tmp_triangle_id = -1;
2415 if (tmp_triangle_id >= 0) {
2416 intersect_pt = tmp_intersect_pt;
2417 triangle_id = tmp_triangle_id;
2422 *gmsg <<
"* " << __func__ <<
":"
2423 <<
" result=" << ret;
2425 *gmsg <<
" intersetion=" << intersect_pt;
2438 of.open (fn.c_str ());
2441 of <<
"# vtk DataFile Version 2.0" <<
std::endl;
2442 of <<
"generated using DataSink::writeGeoToVtk" <<
std::endl;
2443 of <<
"ASCII" << std::endl <<
std::endl;
2444 of <<
"DATASET UNSTRUCTURED_GRID" <<
std::endl;
2446 for (
unsigned int i = 0; i <
Points_m.size (); i++)
2462 of <<
"5" << std::endl;
2464 of <<
"SCALARS " <<
"cell_attribute_data" <<
" float " <<
"1" <<
std::endl;
2465 of <<
"LOOKUP_TABLE " <<
"default" <<
std::endl;
2467 of << (
float)(i) << std::endl;
2474 os <<
"* ************* B O U N D A R Y G E O M E T R Y *********************************** " <<
endl;
2491 os <<
"* Total triangle num " <<
Triangles_m.size() <<
'\n'
2492 <<
"* Total points num " <<
Points_m.size () <<
'\n'
2493 <<
"* Geometry bounds(m) Max = " <<
maxExtent_m <<
'\n'
2496 <<
"* Resolution of voxel mesh " <<
voxelMesh_m.nr_m <<
'\n'
2497 <<
"* Size of voxel " <<
voxelMesh_m.sizeOfVoxel <<
'\n'
2499 os <<
"* ********************************************************************************** " <<
endl;
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
static OpalData * getInstance()
bool builtin
Built-in flag.
Tps< T > sqrt(const Tps< T > &x)
Square root.
constexpr double c
The velocity of light in m/s.
bool almost_eq_zero(double A, double maxDiff=1e-15)
const Vector_t & v3() const
virtual BoundaryGeometry * clone(const std::string &name)
Return a clone.
Vector_t mapPoint2Voxel(const Vector_t &)
#define PointID(triangle_id, vertex_id)
void setOpalName(const std::string &name)
Set object name.
The base class for all OPAL objects.
bool almost_eq_zero(double A, double maxDiff=1e-15)
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
bool intersect(const Ray &r, double &tmin, double &tmax) const
std::string getString(const Attribute &attr)
Get string value.
int mapVoxelIndices2ID(const int i, const int j, const int k)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
int intersectTriangleVoxel(const int triangle_id, const int i, const int j, const int k)
void define(Object *newObject)
Define a new object.
static MPI_Comm getComm()
bool intersect(const Ray &r) const
const Vector_t & v1() const
Vektor< double, 3 > Vector_t
virtual void update()
Update this object.
void scale(const Vector_t &scale)
std::vector< std::array< unsigned int, 4 > > Triangles_m
int intersectLineTriangle(const enum INTERSECTION_TESTS kind, const Vector_t &P0, const Vector_t &P1, const int triangle_id, Vector_t &I)
Abstract base class for accelerator geometry classes.
IpplTimings::TimerRef TRayTrace_m
int partInside(const Vector_t &r, const Vector_t &v, const double dt, Vector_t &intecoords, int &triId)
virtual void execute()
Execute the command.
static BoundaryGeometry * find(const std::string &name)
int intersectLineSegmentBoundary(const Vector_t &P0, const Vector_t &P1, Vector_t &intersection_pt, int &triangle_id)
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
bool isInside(const Vector_t &P)
bool enableVTK
If true VTK files are written.
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
Inform & endl(Inform &inf)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
static void startTimer(TimerRef t)
bool lt(double x, double y)
std::vector< double > TriAreas_m
bool almost_eq(double A, double B, double maxDiff=1e-20, int maxUlps=1000)
bool isInside(const Vector_t &P) const
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
static Communicate * Comm
The base class for all OPAL exceptions.
bool gt(double x, double y)
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Ray(Vector_t o, Vector_t d)
const Vector_t & v2() const
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
int fastIsInside(const Vector_t &reference_pt, const Vector_t &P)
std::vector< Vector_t > TriNormals_m
IpplTimings::TimerRef TfastIsInside_m
void scale(const Vector_t &scaleby, const Vector_t &shiftby)
Inform & printInfo(Inform &os) const
bool ge(double x, double y)
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
bool almost_eq(double A, double B, double maxDiff=1e-20, int maxUlps=1000)
bool findInsidePoint(void)
IpplTimings::TimerRef Tinitialize_m
const std::string & getOpalName() const
Return object name.
std::vector< Attribute > itsAttr
The object attributes.
virtual bool canReplaceBy(Object *object)
Test if replacement is allowed.
constexpr double alpha
The fine structure constant, no dimension.
Topology getTopology() const
Voxel(const Vector_t &min, const Vector_t &max)
int intersectTinyLineSegmentBoundary(const Vector_t &, const Vector_t &, Vector_t &, int &)
std::string combineFilePath(std::initializer_list< std::string > ilist)
double getReal(const Attribute &attr)
Return real value.
bool almost_eq(double A, double B, double maxDiff=1e-15, double maxRelDiff=DBL_EPSILON)
void computeMeshVoxelization(void)
The base class for all OPAL definitions.
static TimerRef getTimer(const char *nm)
T isnan(T x)
isnan function with adjusted return type
Object * find(const std::string &name)
Find entry.
constexpr double e
The value of .
Inform & level2(Inform &inf)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
int intersect(const Triangle &t) const
void updateElement(ElementBase *element)
bool le(double x, double y)
IpplTimings::TimerRef TisInside_m
struct BoundaryGeometry::@71 voxelMesh_m
IpplTimings::TimerRef TPartInside_m
Vector_t mapIndices2Voxel(const int, const int, const int)
#define mapPoint2VoxelIndices(pt, i, j, k)
static void stopTimer(TimerRef t)
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
bool almost_eq_zero(double A, double maxDiff=1e-15)
const Ray & operator=(const Ray &a)=delete
void writeGeomToVtk(std::string fn)
const Vector_t & getPoint(const int triangle_id, const int vertex_id)
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
int intersectRayBoundary(const Vector_t &P, const Vector_t &v, Vector_t &I)
virtual ~BoundaryGeometry()
Triangle(const Vector_t &v1, const Vector_t &v2, const Vector_t &v3)
std::vector< Vector_t > Points_m