81 int line1[2], line2[2];
83 for (
int i = 0; i <
fNvert; ++i) {
86 for (
int j = 0;
j <
other.GetNvert(); ++
j) {
92 bool order1 = line1[1] == line1[0] + 1;
93 bool order2 = line2[1] == (line2[0] + 1) %
other.GetNvert();
135 return seed ^ (std::hash<long>{}(
value) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
137 for (
int i = 0; i < 3; i++) {
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)
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());
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)
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());
275 for (
int i = 0; i <
nvert - 1; ++i) {
279 for (
int j = i + 1;
j <
nvert; ++
j) {
308 std::cout <<
"Facet: " <<
ifacet <<
" is degenerated\n";
314 for (
int i = 1; i <
nvert - 1; ++i) {
320 std::cout <<
"Facet: " <<
ifacet <<
" has zero surface area\n";
333 if (initialized && !
check) {
374 for (
int i = 0; i <
fNfacets; ++i) {
401 Error(
"Check",
"Tessellated solid %s has following not fully connected facets:",
GetName());
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());
415 std::cout <<
icrt <<
"\n";
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};
442 for (
int i = 0; i <
facet.GetNvert(); ++i) {
443 for (
int j = 0;
j < 3; ++
j) {
452 for (
int i = 0; i < 3; ++i)
488 std::cout <<
"=== Tessellated shape " <<
GetName() <<
" having " <<
GetNvertices() <<
" vertices and "
554 Error(
"ResizeCenter",
"Not all faces are defined");
560 constexpr double kTol = 1
e-12;
563 for (
size_t i = 0; i <
fVertices.size(); ++i) {
612 using std::vector, std::string, std::ifstream, std::stringstream, std::endl;
664 if (!file.is_open()) {
665 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unable to open %s",
objfile);
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) {
689 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Detected face having unsupported %zu vertices",
702 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unsupported relative vertex index definition in %s",
717 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Not enough faces detected in %s",
objfile);
727 for (
int i = 0; i <
nfacets; ++i) {
729 if (
facet.nvert == 3)
734 tsl->CloseShape(
check,
true, verbose);
752 constexpr double EPS = 1
e-8;
753 const double INF = std::numeric_limits<double>::infinity();
758 if (std::abs(
det) <=
EPS) {
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]];
785 if (
facet.GetNvert() == 3)
787 const auto &
v3 = vertices[
facet[3]];
789 return std::min(t,
t2);
793 const std::vector<Vertex_t> &vertices,
double rayEPS = 1
e-8)
799template <
typename T =
float>
802 Vec3f(T x_, T
y_, T
z_) :
x(x_),
y(
y_), z(
z_){};
808 return {
a.x -
b.x,
a.y -
b.y,
a.z -
b.z};
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};
820 return a.x *
b.x +
a.y *
b.y +
a.z *
b.z;
829template <
typename T =
float>
839 if (
d1 <= T(0.0) &&
d2 <= T(0.0)) {
846 if (
d3 >= T(0.0) &&
d4 <=
d3) {
861 if (
d6 >= T(0.0f) &&
d5 <=
d6) {
874 if (
va <= 0.0f && (
d4 -
d3) >= 0.0f && (
d5 -
d6) >= 0.0f) {
892template <
typename T =
float>
896 const auto &
v0 = vertices[
facet[0]];
897 const auto &
v1 = vertices[
facet[1]];
898 const auto &
v2 = vertices[
facet[2]];
901 if (
facet.GetNvert() == 3)
903 const auto &
v3 = vertices[
facet[3]];
906 return std::min(
d,
d2);
920 using Scalar = float;
934 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(
orig);
936 return static_cast<float>(
orig + epsilon);
961 Ray
ray(
Vec3(point[0], point[1], point[2]),
962 Vec3(dir[0], dir[1], dir[2]),
1003 using Scalar = float;
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]),
1040 if (
n.Dot(
dir_v) <= 0.) {
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;
1091 Fatal(
"BuildBVH",
"only facets with 3 or 4 vertices supported");
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());
1145 using Scalar = float;
1159 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(
orig);
1161 return static_cast<float>(
orig + epsilon);
1176 Ray
ray(
Vec3(point[0], point[1], point[2]),
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>,
1223 void clear() { this->c.clear(); }
1229template <
bool returnFace>
1236 using Scalar = float;
1260 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
1261 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
1306 queue.push(BVHPrioElement{
childid, -1.});
1317 if (queue.size() > 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) {
float Float_t
Float 4 bytes (float)
const char Option_t
Option string (const char)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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.
This builder is only a wrapper around all the other builders, which selects the best builder dependin...
static BVH_ALWAYS_INLINE Bvh< Node > build(ThreadPool &thread_pool, std::span< const BBox > bboxes, std::span< const Vec > centers, const Config &config={})
Build a BVH in parallel using the given thread pool.
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
BVH_ALWAYS_INLINE Vec< T, 3 > cross(const Vec< T, 3 > &a, const Vec< T, 3 > &b)
BVH_ALWAYS_INLINE T dot(const Vec< T, N > &a, const Vec< T, N > &b)
static Vertex_t Cross(Vertex_t const &left, Vertex_t const &right)
The cross (vector) product of two Vector3D<T> objects.
static double Dot(Vertex_t const &left, Vertex_t const &right)
The dot product of two vector objects.
Quality quality
The quality of the BVH produced by the builder.
Growing stack that can be used for BVH traversal.
Binary BVH node, containing its bounds and an index into its children or the primitives it contains.