59 int nvert = nvertices;
62 if (vert[(i + 1) % nvert] == vert[i]) {
64 for (
int j = i + 2; j < nvert; ++j)
65 vert[j - 1] = vert[j];
80 bool neighbour =
false;
81 int line1[2], line2[2];
83 for (
int i = 0; i <
fNvert; ++i) {
86 for (
int j = 0; j < other.
GetNvert(); ++j) {
87 if (ivert == other[j]) {
92 bool order1 = line1[1] == line1[0] + 1;
93 bool order2 = line2[1] == (line2[0] + 1) % other.
GetNvert();
94 flip = (order1 == order2);
129 constexpr double tolerance = 1.e-10;
130 auto vertexHash = [&](
Vertex_t const &vertex) {
134 auto hash_combine = [](
long seed,
const long value) {
135 return seed ^ (std::hash<long>{}(
value) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
137 for (
int i = 0; i < 3; i++) {
139 hash = hash_combine(hash, std::roundl(vertex[i] / tolerance));
144 auto hash = vertexHash(vert);
145 bool isAdded =
false;
149 for (
auto it = range.first; it != range.second; ++it) {
170 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
180 Error(
"AddFacet",
"Triangular facet at index %d degenerated. Not adding.",
GetNfacets());
184 for (
auto i = 0; i < 3; ++i)
187 fFacets.emplace_back(ind[0], ind[1], ind[2]);
198 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
202 Error(
"AddFacet",
"Shape %s Cannot add facets by indices without vertices. Not adding",
GetName());
207 fFacets.emplace_back(i0, i1, i2);
217 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
227 Error(
"AddFacet",
"Quadrilateral facet at index %d degenerated. Not adding.",
GetNfacets());
232 for (
auto i = 0; i < nvert; ++i)
236 fFacets.emplace_back(ind[0], ind[1], ind[2]);
238 fFacets.emplace_back(ind[0], ind[1], ind[2], ind[3]);
251 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
255 Error(
"AddFacet",
"Shape %s Cannot add facets by indices without vertices. Not adding",
GetName());
260 fFacets.emplace_back(i0, i1, i2, i3);
270 constexpr double kTolerance = 1.e-20;
271 auto const &facet =
fFacets[ifacet];
272 int nvert = facet.GetNvert();
275 for (
int i = 0; i < nvert - 1; ++i) {
277 if (e1.
Mag2() < kTolerance)
279 for (
int j = i + 1; j < nvert; ++j) {
281 if (e2.
Mag2() < kTolerance)
285 if (normal.
Mag2() < kTolerance)
302 constexpr double kTolerance = 1.e-10;
303 auto const &facet =
fFacets[ifacet];
304 int nvert = facet.GetNvert();
305 bool degenerated =
true;
308 std::cout <<
"Facet: " << ifacet <<
" is degenerated\n";
313 double surfaceArea = 0.;
314 for (
int i = 1; i < nvert - 1; ++i) {
319 if (surfaceArea < kTolerance) {
320 std::cout <<
"Facet: " << ifacet <<
" has zero surface area\n";
333 if (initialized && !check) {
372 bool hasorphans =
false;
373 bool hasflipped =
false;
374 for (
int i = 0; i <
fNfacets; ++i) {
379 for (
int icrt = 0; icrt <
fNfacets; ++icrt) {
381 if (nn[icrt] >=
fFacets[icrt].GetNvert())
383 for (
int i = icrt + 1; i <
fNfacets; ++i) {
384 bool isneighbour =
fFacets[icrt].IsNeighbour(
fFacets[i], flipped[i]);
387 flipped[i] = !flipped[i];
392 if (nn[icrt] ==
fFacets[icrt].GetNvert())
396 if (nn[icrt] <
fFacets[icrt].GetNvert())
400 if (hasorphans && verbose) {
401 Error(
"Check",
"Tessellated solid %s has following not fully connected facets:",
GetName());
402 for (
int icrt = 0; icrt <
fNfacets; ++icrt) {
403 if (nn[icrt] <
fFacets[icrt].GetNvert())
404 std::cout << icrt <<
" (" <<
fFacets[icrt].GetNvert() <<
" edges, " << nn[icrt] <<
" neighbours)\n";
411 Warning(
"Check",
"Tessellated solid %s has following facets with flipped normals:",
GetName());
412 for (
int icrt = 0; icrt <
fNfacets; ++icrt) {
415 std::cout << icrt <<
"\n";
422 if (nfixed && verbose)
423 Info(
"Check",
"Automatically flipped %d facets to match first defined facet", nfixed);
439 double vmin[3] = {kBig, kBig, kBig};
440 double vmax[3] = {-kBig, -kBig, -kBig};
441 for (
const auto &facet :
fFacets) {
442 for (
int i = 0; i < facet.GetNvert(); ++i) {
443 for (
int j = 0; j < 3; ++j) {
449 fDX = 0.5 * (vmax[0] - vmin[0]);
450 fDY = 0.5 * (vmax[1] - vmin[1]);
451 fDZ = 0.5 * (vmax[2] - vmin[2]);
452 for (
int i = 0; i < 3; ++i)
453 fOrigin[i] = 0.5 * (vmax[i] + vmin[i]);
473 const int nsegs =
fNseg;
488 std::cout <<
"=== Tessellated shape " <<
GetName() <<
" having " <<
GetNvertices() <<
" vertices and "
498 int *segs = buff.
fSegs;
499 int *pols = buff.
fPols;
504 for (
const auto &facet :
fFacets) {
505 auto nvert = facet.GetNvert();
507 pols[indpol++] = nvert;
508 for (
auto j = 0; j < nvert; ++j) {
509 int k = (j + 1) % nvert;
512 segs[indseg++] = facet[j];
513 segs[indseg++] = facet[k];
515 pols[indpol + nvert - j - 1] = sind++;
528 vertex.CopyTo(&
points[ind]);
540 points[ind++] = vertex.x();
541 points[ind++] = vertex.y();
542 points[ind++] = vertex.z();
554 Error(
"ResizeCenter",
"Not all faces are defined");
559 double scale = maxsize / maxedge;
560 constexpr double kTol = 1
e-12;
561 const bool modified = (std::abs(scale - 1.0) > kTol) || (std::abs(origin[0]) > kTol) ||
562 (std::abs(origin[1]) > kTol) || (std::abs(origin[2]) > kTol);
563 for (
size_t i = 0; i <
fVertices.size(); ++i) {
586 const int nsegs =
fNseg;
590 if (buffer.
SetRawSizes(nvert, 3 * nvert, nsegs, 3 * nsegs, npols, 6 * npols)) {
612 using std::vector, std::string, std::ifstream, std::stringstream, std::endl;
614 vector<Vertex_t> vertices;
615 vector<string> sfacets;
623 FacetInd_t(
int a,
int b,
int c)
630 FacetInd_t(
int a,
int b,
int c,
int d)
640 vector<FacetInd_t> facets;
663 ifstream file(objfile);
664 if (!file.is_open()) {
665 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unable to open %s", objfile);
669 while (getline(file,
line)) {
670 stringstream ss(
line);
674 if (
line.rfind(
'v', 0) == 0 &&
line.rfind(
"vt", 0) != 0 &&
line.rfind(
"vn", 0) != 0 &&
line.rfind(
"vn", 0) != 0) {
676 double pos[4] = {0, 0, 0, 1};
677 ss >> tag >> pos[0] >> pos[1] >> pos[2] >> pos[3];
678 vertices.emplace_back(pos[0] * pos[3], pos[1] * pos[3], pos[2] * pos[3]);
681 else if (
line.rfind(
'f', 0) == 0) {
687 sfacets.push_back(word);
688 if (sfacets.size() > 4 || sfacets.size() < 3) {
689 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Detected face having unsupported %zu vertices",
694 for (
auto &sword : sfacets) {
695 stringstream ssword(sword);
697 getline(ssword, token,
'/');
700 ind[nvert++] = stoi(token) - 1;
701 if (ind[nvert - 1] < 0) {
702 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unsupported relative vertex index definition in %s",
708 facets.emplace_back(ind[0], ind[1], ind[2]);
710 facets.emplace_back(ind[0], ind[1], ind[2], ind[3]);
714 int nvertices = (
int)vertices.size();
715 int nfacets = (
int)facets.size();
717 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Not enough faces detected in %s", objfile);
721 string sobjfile(objfile);
723 std::cout <<
"Read " << nvertices <<
" vertices and " << nfacets <<
" facets from " << sobjfile << endl;
725 auto tsl =
new TGeoTessellated(sobjfile.erase(sobjfile.find_last_of(
'.')).c_str(), vertices);
727 for (
int i = 0; i < nfacets; ++i) {
728 auto facet = facets[i];
729 if (facet.nvert == 3)
730 tsl->AddFacet(facet.i0, facet.i1, facet.i2);
732 tsl->AddFacet(facet.i0, facet.i1, facet.i2, facet.i3);
734 tsl->CloseShape(check,
true, verbose);
752 constexpr double EPS = 1
e-8;
753 const double INF = std::numeric_limits<double>::infinity();
757 auto det = e1.Dot(
p);
758 if (std::abs(det) <= EPS) {
763 auto invDet = 1.0 / det;
764 auto u = tvec.
Dot(
p) * invDet;
765 if (u < 0.0 || u > 1.0) {
769 auto v = dir.
Dot(
q) * invDet;
770 if (v < 0.0 || u + v > 1.0) {
773 auto t = e2.Dot(
q) * invDet;
774 return (t > rayEPS) ? t : INF;
778 const std::vector<Vertex_t> &vertices,
double rayEPS = 1
e-8)
781 const auto &
v0 = vertices[facet[0]];
782 const auto &
v1 = vertices[facet[1]];
783 const auto &
v2 = vertices[facet[2]];
784 auto t = rayTriangle(orig, dir,
v0,
v1,
v2, rayEPS);
787 const auto &
v3 = vertices[facet[3]];
788 auto t2 = rayTriangle(orig, dir,
v0,
v2,
v3, rayEPS);
789 return std::min(t, t2);
793 const std::vector<Vertex_t> &vertices,
double rayEPS = 1
e-8)
796 return rayFacet(orig, dir, facet, vertices, rayEPS) != std::numeric_limits<double>::infinity();
799template <
typename T =
float>
802 Vec3f(T x_, T y_, T z_) :
x(x_),
y(y_), z(z_){};
806inline Vec3f<T>
operator-(
const Vec3f<T> &
a,
const Vec3f<T> &
b)
808 return {
a.x -
b.x,
a.y -
b.y,
a.z -
b.z};
812inline Vec3f<T> cross(
const Vec3f<T> &
a,
const Vec3f<T> &
b)
814 return {
a.y *
b.z -
a.z *
b.y,
a.z *
b.x -
a.x *
b.z,
a.x *
b.y -
a.y *
b.x};
818inline T dot(
const Vec3f<T> &
a,
const Vec3f<T> &
b)
820 return a.x *
b.x +
a.y *
b.y +
a.z *
b.z;
829template <
typename T =
float>
830T pointTriangleDistSq(
const Vec3f<T> &
p,
const Vec3f<T> &
a,
const Vec3f<T> &
b,
const Vec3f<T> &
c)
837 auto d1 = dot(ab, ap);
838 auto d2 = dot(ac, ap);
839 if (d1 <= T(0.0) && d2 <= T(0.0)) {
844 auto d3 = dot(ab, bp);
845 auto d4 = dot(ac, bp);
846 if (d3 >= T(0.0) && d4 <= d3) {
850 T vc = d1 * d4 - d3 * d2;
851 if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
852 T
v = d1 / (d1 - d3);
853 Vec3f<T> proj = {
a.x +
v * ab.x,
a.y +
v * ab.y,
a.z +
v * ab.z};
854 Vec3f<T>
d =
p - proj;
861 if (d6 >= T(0.0f) && d5 <= d6) {
865 T vb = d5 * d2 - d1 * d6;
866 if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
867 T
w = d2 / (d2 - d6);
868 Vec3f<T> proj = {
a.x +
w * ac.x,
a.y +
w * ac.y,
a.z +
w * ac.z};
869 Vec3f<T>
d =
p - proj;
873 T va = d3 * d6 - d5 * d4;
874 if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
875 T
w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
876 Vec3f<T> proj = {
b.x +
w * (
c.x -
b.x),
b.y +
w * (
c.y -
b.y),
b.z +
w * (
c.z -
b.z)};
877 Vec3f<T>
d =
p - proj;
882 T denom = T(1.0f) / (va + vb + vc);
886 Vec3f<T> proj = {
a.x + ab.x *
v + ac.x *
w,
a.y + ab.y *
v + ac.y *
w,
a.z + ab.z *
v + ac.z *
w};
888 Vec3f<T>
d =
p - proj;
892template <
typename T =
float>
893T pointFacetDistSq(
const Vec3f<T> &
p,
const TGeoFacet &facet,
const std::vector<Vertex_t> &vertices)
896 const auto &
v0 = vertices[facet[0]];
897 const auto &
v1 = vertices[facet[1]];
898 const auto &
v2 = vertices[facet[2]];
899 auto d = pointTriangleDistSq(
p, Vec3f<T>(
v0[0],
v0[1],
v0[2]), Vec3f<T>(
v1[0],
v1[1],
v1[2]),
900 Vec3f<T>(
v2[0],
v2[1],
v2[2]));
903 const auto &
v3 = vertices[facet[3]];
904 auto d2 = pointTriangleDistSq(
p, Vec3f<T>(
v0[0],
v0[1],
v0[2]), Vec3f<T>(
v2[0],
v2[1],
v2[2]),
905 Vec3f<T>(
v3[0],
v3[1],
v3[2]));
906 return std::min(
d, d2);
918 double local_step =
Big();
920 using Scalar = float;
921 using Vec3 = bvh::v2::Vec<Scalar, 3>;
922 using Node = bvh::v2::Node<Scalar, 3>;
923 using Bvh = bvh::v2::Bvh<Node>;
924 using Ray = bvh::v2::Ray<Scalar, 3>;
927 auto mybvh = (Bvh *)
fBVH;
933 auto truncate_roundup = [](
double orig) {
934 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(orig);
936 return static_cast<float>(orig + epsilon);
940 const auto topnode_bbox = mybvh->get_root().get_bbox();
941 if ((-point[0] + topnode_bbox.min[0]) > stepmax) {
944 if ((-point[1] + topnode_bbox.min[1]) > stepmax) {
947 if ((-point[2] + topnode_bbox.min[2]) > stepmax) {
950 if ((point[0] - topnode_bbox.max[0]) > stepmax) {
953 if ((point[1] - topnode_bbox.max[1]) > stepmax) {
956 if ((point[2] - topnode_bbox.max[2]) > stepmax) {
961 Ray ray(Vec3(point[0], point[1], point[2]),
962 Vec3(dir[0], dir[1], dir[2]),
964 truncate_roundup(local_step));
966 static constexpr bool use_robust_traversal =
true;
968 Vertex_t dir_v{dir[0], dir[1], dir[2]};
970 bvh::v2::GrowingStack<Bvh::Index> stack;
971 mybvh->intersect<
false, use_robust_traversal>(ray, mybvh->get_root().index, stack, [&](
size_t begin,
size_t end) {
972 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
973 auto objectid = mybvh->prim_ids[prim_id];
974 const auto &facet =
fFacets[objectid];
978 if (
n.Dot(dir_v) > 0.) {
982 auto thisdist = rayFacet(
Vertex_t(point[0], point[1], point[2]), dir_v, facet,
fVertices, 0.);
984 if (thisdist < local_step) {
985 local_step = thisdist;
1001 double local_step =
Big();
1003 using Scalar = float;
1004 using Vec3 = bvh::v2::Vec<Scalar, 3>;
1005 using Node = bvh::v2::Node<Scalar, 3>;
1006 using Bvh = bvh::v2::Bvh<Node>;
1007 using Ray = bvh::v2::Ray<Scalar, 3>;
1010 auto mybvh = (Bvh *)
fBVH;
1016 auto truncate_roundup = [](
double orig) {
1017 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(orig);
1019 return static_cast<float>(orig + epsilon);
1023 Ray ray(Vec3(point[0], point[1], point[2]),
1024 Vec3(dir[0], dir[1], dir[2]),
1026 truncate_roundup(local_step));
1028 static constexpr bool use_robust_traversal =
true;
1030 Vertex_t dir_v{dir[0], dir[1], dir[2]};
1032 bvh::v2::GrowingStack<Bvh::Index> stack;
1033 mybvh->intersect<
false, use_robust_traversal>(ray, mybvh->get_root().index, stack, [&](
size_t begin,
size_t end) {
1034 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
1035 auto objectid = mybvh->prim_ids[prim_id];
1036 auto facet =
fFacets[objectid];
1040 if (
n.Dot(dir_v) <= 0.) {
1044 const double t = rayFacet(
Vertex_t{point[0], point[1], point[2]}, dir_v, facet,
fVertices, 0.);
1045 if (t < local_step) {
1065 for (
size_t i = 0; i <
fFacets.size(); ++i) {
1071 a[0] * (
b[1] *
c[2] -
b[2] *
c[1]) +
b[0] * (
c[1] *
a[2] -
c[2] *
a[1]) +
c[0] * (
a[1] *
b[2] -
a[2] *
b[1]);
1081 using Scalar = float;
1082 using BBox = bvh::v2::BBox<Scalar, 3>;
1083 using Vec3 = bvh::v2::Vec<Scalar, 3>;
1084 using Node = bvh::v2::Node<Scalar, 3>;
1085 using Bvh = bvh::v2::Bvh<Node>;
1088 auto GetBoundingBox = [
this](
TGeoFacet const &facet) {
1089 const auto nvertices = facet.GetNvert();
1090 if (nvertices != 3 && nvertices != 4)
1091 Fatal(
"BuildBVH",
"only facets with 3 or 4 vertices supported");
1095 const auto &
v4 = (nvertices == 4) ?
fVertices[facet[3]] :
v3;
1098 bbox.min[0] = std::min(std::min(std::min(
v1[0],
v2[0]),
v3[0]),
v4[0]) - 0.001f;
1099 bbox.min[1] = std::min(std::min(std::min(
v1[1],
v2[1]),
v3[1]),
v4[1]) - 0.001f;
1100 bbox.min[2] = std::min(std::min(std::min(
v1[2],
v2[2]),
v3[2]),
v4[2]) - 0.001f;
1101 bbox.max[0] = std::max(std::max(std::max(
v1[0],
v2[0]),
v3[0]),
v4[0]) + 0.001f;
1102 bbox.max[1] = std::max(std::max(std::max(
v1[1],
v2[1]),
v3[1]),
v4[1]) + 0.001f;
1103 bbox.max[2] = std::max(std::max(std::max(
v1[2],
v2[2]),
v3[2]),
v4[2]) + 0.001f;
1109 std::vector<BBox> bboxes;
1110 std::vector<Vec3> centers;
1114 centers.reserve(nd);
1116 for (
int i = 0; i < nd; ++i) {
1120 (bboxes).push_back(GetBoundingBox(facet));
1121 centers.emplace_back((bboxes).back().get_center());
1131 typename bvh::v2::DefaultBuilder<Node>::Config config;
1132 config.quality = bvh::v2::DefaultBuilder<Node>::Quality::High;
1133 auto bvh = bvh::v2::DefaultBuilder<Node>::build(bboxes, centers, config);
1134 auto bvhptr =
new Bvh;
1135 *bvhptr = std::move(
bvh);
1136 fBVH = (
void *)(bvhptr);
1145 using Scalar = float;
1146 using Vec3 = bvh::v2::Vec<Scalar, 3>;
1147 using Node = bvh::v2::Node<Scalar, 3>;
1148 using Bvh = bvh::v2::Bvh<Node>;
1149 using Ray = bvh::v2::Ray<Scalar, 3>;
1152 auto mybvh = (Bvh *)
fBVH;
1158 auto truncate_roundup = [](
double orig) {
1159 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(orig);
1161 return static_cast<float>(orig + epsilon);
1172 Vertex_t test_dir{1.0, 1.41421356237, 1.73205080757};
1174 double local_step =
Big();
1176 Ray ray(Vec3(point[0], point[1], point[2]),
1177 Vec3(test_dir[0], test_dir[1], test_dir[2]),
1179 truncate_roundup(local_step));
1181 static constexpr bool use_robust_traversal =
true;
1184 bvh::v2::GrowingStack<Bvh::Index> stack;
1185 size_t crossings = 0;
1186 mybvh->intersect<
false, use_robust_traversal>(ray, mybvh->get_root().index, stack, [&](
size_t begin,
size_t end) {
1187 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
1188 auto objectid = mybvh->prim_ids[prim_id];
1189 auto &facet =
fFacets[objectid];
1192 if (rayFacetHit(
Vertex_t(point[0], point[1], point[2]), test_dir, facet,
fVertices, 0.)) {
1199 return crossings & 1;
1206struct BVHPrioElement {
1216template <
typename Comparator>
1217class BVHPrioQueue :
public std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>, Comparator> {
1219 using std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>,
1220 Comparator>::priority_queue;
1223 void clear() { this->c.clear(); }
1229template <
bool returnFace>
1236 using Scalar = float;
1237 using Vec3 = bvh::v2::Vec<Scalar, 3>;
1238 using Node = bvh::v2::Node<Scalar, 3>;
1239 using Bvh = bvh::v2::Bvh<Node>;
1242 auto mybvh = (Bvh *)
fBVH;
1245 Vec3 testpoint(point[0], point[1], point[2]);
1247 auto currnode = mybvh->nodes[0];
1249 bool outside_top =
false;
1255 return std::sqrt(safety_sq_to_top);
1260 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
1261 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
1265 float current_safety_to_node_sq = 0.f;
1268 *closest_facet_id = -1;
1272 if (currnode.is_leaf()) {
1274 const auto begin_prim_id = currnode.index.first_id();
1275 const auto end_prim_id = begin_prim_id + currnode.index.prim_count();
1277 for (
auto p_id = begin_prim_id; p_id < end_prim_id; p_id++) {
1278 const auto object_id = mybvh->prim_ids[p_id];
1280 const auto &facet =
fFacets[object_id];
1281 auto thissafetySQ = pointFacetDistSq(Vec3f<float>(point[0], point[1], point[2]), facet,
fVertices);
1283 if (thissafetySQ < smallest_safety_sq) {
1284 smallest_safety_sq = thissafetySQ;
1286 *closest_facet_id = object_id;
1293 const auto leftchild_id = currnode.index.first_id();
1294 const auto rightchild_id = leftchild_id + 1;
1296 for (
size_t childid : {leftchild_id, rightchild_id}) {
1297 if (childid >= mybvh->nodes.size()) {
1301 const auto &node = mybvh->nodes[childid];
1306 queue.push(BVHPrioElement{childid, -1.});
1309 if (safety_to_node_square <= smallest_safety_sq) {
1311 queue.push(BVHPrioElement{childid, safety_to_node_square});
1317 if (queue.size() > 0) {
1318 auto currElement = queue.top();
1319 currnode = mybvh->nodes[currElement.bvh_node_id];
1320 current_safety_to_node_sq = currElement.value;
1325 }
while (current_safety_to_node_sq <= smallest_safety_sq);
1327 return std::nextafter(std::sqrt(smallest_safety_sq), 0.0f);
1339 return SafetyKernel<false>(point, in);
1353 int closest_face_id = -1;
1354 SafetyKernel<true>(point,
true, &closest_face_id);
1356 if (closest_face_id < 0) {
1369 if (norm[0] * dir[0] + norm[1] * dir[1] + norm[2] * dir[2] < 0) {
1383 if (
b.IsReading()) {
1398 for (
size_t i = 0; i <
fFacets.size(); ++i) {
1400 bool degenerated =
false;
float Float_t
Float 4 bytes (float)
const char Option_t
Option string (const char)
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
TTime operator-(const TTime &t1, const TTime &t2)
Generic 3D primitive description class.
Bool_t SectionsValid(UInt_t mask) const
void SetSectionsValid(UInt_t mask)
Bool_t SetRawSizes(UInt_t reqPnts, UInt_t reqPntsCapacity, UInt_t reqSegs, UInt_t reqSegsCapacity, UInt_t reqPols, UInt_t reqPolsCapacity)
Set kRaw tessellation section of buffer with supplied sizes.
Buffer base class used for serializing objects.
void FillBuffer3D(TBuffer3D &buffer, Int_t reqSections, Bool_t localFrame) const override
Fills the supplied buffer, with sections in desired frame See TBuffer3D.h for explanation of sections...
Bool_t Contains(const Double_t *point) const override
Test if point is inside this shape.
bool IsNeighbour(const TGeoFacet &other, bool &flip) const
Check if a connected neighbour facet has compatible normal.
static int CompactFacet(Vertex_t *vert, int nvertices)
Compact consecutive equal vertices.
Int_t GetBasicColor() const
Get the basic color (0-7).
void TransformPoints(Double_t *points, UInt_t NbPoints) const
Tranform a set of points (LocalToMaster)
const char * GetName() const override
Get the shape name.
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const override
Safety.
void ResizeCenter(double maxsize)
Resize and center the shape in a box of size maxsize.
int AddVertex(const Vertex_t &vert)
Add a vertex checking for duplicates, returning the vertex index.
bool Contains(const Double_t *point) const override
Contains.
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
ComputeNormal interface.
bool FacetCheck(int ifacet) const
Check validity of facet.
void Streamer(TBuffer &) override
Custom streamer which performs Closing on read.
Double_t SafetyKernel(const Double_t *point, bool in, int *closest_facet_id=nullptr) const
a reusable safety kernel, which optionally returns the closest face
void Print(Option_t *option="") const override
Prints basic info.
Double_t Capacity() const override
Capacity.
Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
DistFromOutside.
void * fBVH
to know if shape still needs closure/initialization
Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const override
DistFromOutside.
void SetSegsAndPols(TBuffer3D &buff) const override
Fills TBuffer3D structure for segments and polygons.
const TBuffer3D & GetBuffer3D(int reqSections, Bool_t localFrame) const override
Fills a static 3D buffer and returns a reference.
void SetPoints(double *points) const override
Fill tessellated points to an array.
bool CheckClosure(bool fixFlipped=true, bool verbose=true)
Check closure of the solid and check/fix flipped normals.
bool fDefined
! Shape fully defined
Vertex_t FacetComputeNormal(int ifacet, bool °enerated) const
Compute normal for a given facet.
void CloseShape(bool check=true, bool fixFlipped=true, bool verbose=true)
Close the shape: calculate bounding box and compact vertices.
Tessellated::Vertex_t Vertex_t
void GetMeshNumbers(int &nvert, int &nsegs, int &npols) const override
Returns numbers of vertices, segments and polygons composing the shape mesh.
std::vector< TGeoFacet > fFacets
static TGeoTessellated * ImportFromObjFormat(const char *objfile, bool check=false, bool verbose=false)
Reader from .obj format.
TBuffer3D * MakeBuffer3D() const override
Creates a TBuffer3D describing this shape.
void ComputeBBox() override
Compute bounding box.
std::multimap< long, int > fVerticesMap
! Temporary map used to deduplicate vertices
std::vector< Vertex_t > fOutwardNormals
bool AddFacet(const Vertex_t &pt0, const Vertex_t &pt1, const Vertex_t &pt2)
Adding a triangular facet from vertex positions in absolute coordinates.
void CalculateNormals()
Calculate the normals.
std::vector< Vertex_t > fVertices
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
ROOT::Geom::Vertex_t Vertex_t
static Vertex_t Cross(Vertex_t const &left, Vertex_t const &right)
The cross (vector) product of two Vector3D<T> objects.
void Normalize()
Normalizes the vector by dividing each entry by the length.
static double Dot(Vertex_t const &left, Vertex_t const &right)
The dot product of two vector objects.