80 int line1[2], line2[2];
82 for (
int i = 0; i <
fNvert; ++i) {
85 for (
int j = 0;
j <
other.GetNvert(); ++
j) {
91 bool order1 = line1[1] == line1[0] + 1;
92 bool order2 = line2[1] == (line2[0] + 1) %
other.GetNvert();
134 return seed ^ (std::hash<long>{}(
value) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
136 for (
int i = 0; i < 3; i++) {
148 for (
auto it =
range.first; it !=
range.second; ++it) {
169 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
179 Error(
"AddFacet",
"Triangular facet at index %d degenerated. Not adding.",
GetNfacets());
183 for (
auto i = 0; i < 3; ++i)
197 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
201 Error(
"AddFacet",
"Shape %s Cannot add facets by indices without vertices. Not adding",
GetName());
216 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
226 Error(
"AddFacet",
"Quadrilateral facet at index %d degenerated. Not adding.",
GetNfacets());
231 for (
auto i = 0; i <
nvert; ++i)
250 Error(
"AddFacet",
"Shape %s already fully defined. Not adding",
GetName());
254 Error(
"AddFacet",
"Shape %s Cannot add facets by indices without vertices. Not adding",
GetName());
274 for (
int i = 0; i <
nvert - 1; ++i) {
278 for (
int j = i + 1;
j <
nvert; ++
j) {
307 std::cout <<
"Facet: " <<
ifacet <<
" is degenerated\n";
313 for (
int i = 1; i <
nvert - 1; ++i) {
319 std::cout <<
"Facet: " <<
ifacet <<
" has zero surface area\n";
346 std::cerr <<
"Inconsistency in normal container";
375 for (
int i = 0; i <
fNfacets; ++i) {
402 Error(
"Check",
"Tessellated solid %s has following not fully connected facets:",
GetName());
412 Warning(
"Check",
"Tessellated solid %s has following facets with flipped normals:",
GetName());
416 std::cout <<
icrt <<
"\n";
424 Info(
"Check",
"Automatically flipped %d facets to match first defined facet",
nfixed);
438 double vmin[3] = {kBig, kBig, kBig};
439 double vmax[3] = {-kBig, -kBig, -kBig};
441 for (
int i = 0; i <
facet.GetNvert(); ++i) {
442 for (
int j = 0;
j < 3; ++
j) {
451 for (
int i = 0; i < 3; ++i)
487 std::cout <<
"=== Tessellated shape " <<
GetName() <<
" having " <<
GetNvertices() <<
" vertices and "
553 Error(
"ResizeCenter",
"Not all faces are defined");
559 constexpr double kTol = 1
e-12;
562 for (
size_t i = 0; i <
fVertices.size(); ++i) {
611 using std::vector, std::string, std::ifstream, std::stringstream, std::endl;
663 if (!file.is_open()) {
664 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unable to open %s",
objfile);
673 if (
line.rfind(
'v', 0) == 0 &&
line.rfind(
"vt", 0) != 0 &&
line.rfind(
"vn", 0) != 0 &&
line.rfind(
"vn", 0) != 0) {
675 double pos[4] = {0, 0, 0, 1};
676 ss >> tag >> pos[0] >> pos[1] >> pos[2] >> pos[3];
677 vertices.emplace_back(pos[0] * pos[3], pos[1] * pos[3], pos[2] * pos[3]);
680 else if (
line.rfind(
'f', 0) == 0) {
688 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Detected face having unsupported %zu vertices",
701 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Unsupported relative vertex index definition in %s",
716 ::Error(
"TGeoTessellated::ImportFromObjFormat",
"Not enough faces detected in %s",
objfile);
726 for (
int i = 0; i <
nfacets; ++i) {
728 if (
facet.nvert == 3)
733 tsl->CloseShape(
check,
true, verbose);
751 constexpr double EPS = 1
e-8;
752 const double INF = std::numeric_limits<double>::infinity();
757 if (std::abs(
det) <=
EPS) {
776template <
typename T =
float>
779 Vec3f(T x_, T
y_, T
z_) :
x(x_),
y(
y_), z(
z_){};
785 return {
a.x -
b.x,
a.y -
b.y,
a.z -
b.z};
791 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};
797 return a.x *
b.x +
a.y *
b.y +
a.z *
b.z;
806template <
typename T =
float>
816 if (
d1 <= T(0.0) &&
d2 <= T(0.0)) {
823 if (
d3 >= T(0.0) &&
d4 <=
d3) {
838 if (
d6 >= T(0.0f) &&
d5 <=
d6) {
851 if (
va <= 0.0f && (
d4 -
d3) >= 0.0f && (
d5 -
d6) >= 0.0f) {
873 if (
len2 == T(0.0f)) {
874 std::cerr <<
"Degnerate triangle. Cannot determine normal";
900 using Scalar = float;
914 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(
orig);
916 return static_cast<float>(
orig + epsilon);
941 Ray
ray(
Vec3(point[0], point[1], point[2]),
942 Vec3(dir[0], dir[1], dir[2]),
984 using Scalar = float;
998 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(
orig);
1000 return static_cast<float>(
orig + epsilon);
1004 Ray
ray(
Vec3(point[0], point[1], point[2]),
1005 Vec3(dir[0], dir[1], dir[2]),
1021 if (
n.Dot(
dir_v) <= 0.) {
1050 for (
size_t i = 0; i <
fFacets.size(); ++i) {
1056 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]);
1066 using Scalar = float;
1082 bbox.min[0] = std::min(std::min(
v1[0],
v2[0]),
v3[0]) - 0.001f;
1083 bbox.min[1] = std::min(std::min(
v1[1],
v2[1]),
v3[1]) - 0.001f;
1084 bbox.min[2] = std::min(std::min(
v1[2],
v2[2]),
v3[2]) - 0.001f;
1085 bbox.max[0] = std::max(std::max(
v1[0],
v2[0]),
v3[0]) + 0.001f;
1086 bbox.max[1] = std::max(std::max(
v1[1],
v2[1]),
v3[1]) + 0.001f;
1087 bbox.max[2] = std::max(std::max(
v1[2],
v2[2]),
v3[2]) + 0.001f;
1093 std::vector<BBox> bboxes;
1094 std::vector<Vec3> centers;
1098 centers.reserve(nd);
1100 for (
int i = 0; i < nd; ++i) {
1104 (bboxes).push_back(GetBoundingBox(
facet));
1105 centers.emplace_back((bboxes).back().get_center());
1129 using Scalar = float;
1143 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(
orig);
1145 return static_cast<float>(
orig + epsilon);
1160 Ray
ray(
Vec3(point[0], point[1], point[2]),
1182 if (t != std::numeric_limits<double>::infinity()) {
1196struct BVHPrioElement {
1206template <
typename Comparator>
1207class BVHPrioQueue :
public std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>, Comparator> {
1209 using std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>,
1213 void clear() { this->c.clear(); }
1219template <
bool returnFace>
1226 using Scalar = float;
1250 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
1251 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
1302 queue.push(BVHPrioElement{
childid, -1.});
1313 if (queue.size() > 0) {
1365 if (
norm[0] * dir[0] +
norm[1] * dir[1] +
norm[2] * dir[2] < 0) {
1379 if (
b.IsReading()) {
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 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, N > normalize(const Vec< T, N > &v)
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.