Project
Loading...
Searching...
No Matches
O2BVHSurfaceSolid.h
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
13
14#ifndef ALICEO2_CADSUPPORT_O2BVHSURFACESOLID_
15#define ALICEO2_CADSUPPORT_O2BVHSURFACESOLID_
16
17#include "TGeoBBox.h"
18
19#include <array>
20#include <iosfwd>
21#include <vector>
22
23class TBuffer3D;
24
25namespace o2
26{
27namespace cad
28{
29
32 int kind = 0;
33 double lineStart[2] = {0., 0.};
34 double lineEnd[2] = {0., 0.};
35 double center[2] = {0., 0.};
36 double radius = 0.;
37 double startAngle = 0.;
38 double endAngle = 0.;
39 int degree = 0;
40 std::vector<double> poles;
41 std::vector<double> weights;
42 std::vector<double> knots;
43};
44
53
55 double origin[3] = {0., 0., 0.};
56 double axisA[3] = {0., 0., 0.};
57 double axisB[3] = {0., 0., 0.};
58
61 std::vector<double> scalars;
62
63 bool innerWall = false;
64 bool trimmed = false;
65
67 std::vector<double> polygonPoints;
68 std::vector<BVHSurfaceCurveRecord> curves;
69 std::vector<int> wireSizes;
70
72 std::vector<unsigned int> boundaryEdgeIds;
73 std::vector<unsigned char> boundaryEdgeFlags;
74
76 static int expectedScalarCount(int recordKind);
77};
78
80{
81 public:
82 using Point2D = std::array<double, 2>;
83 using Point3D = std::array<double, 3>;
84
86 explicit O2BVHSurfaceSolid(const char* name);
87 ~O2BVHSurfaceSolid() override;
88
91
92 bool AddPlanarSurface(const Point3D& origin, const Point3D& axisU, const Point3D& axisV,
93 const std::vector<Point2D>& outerWire,
94 const std::vector<std::vector<Point2D>>& innerWires = {});
95
105 double radius = 0.;
106 double startAngle = 0.;
107 double endAngle = 0.;
108 int degree = 0;
109 std::vector<Point2D> poles;
110 std::vector<double> weights;
111 std::vector<double> knots;
112
114 {
116 curve.kind = Line;
117 curve.lineStart = start;
118 curve.lineEnd = end;
119 return curve;
120 }
121 static PlanarBoundaryCurve makeArc(const Point2D& c, double r, double start, double end)
122 {
124 curve.kind = Arc;
125 curve.center = c;
126 curve.radius = r;
127 curve.startAngle = start;
128 curve.endAngle = end;
129 return curve;
130 }
131 static PlanarBoundaryCurve makeBSpline(int splineDegree, std::vector<Point2D> splinePoles,
132 std::vector<double> splineWeights, std::vector<double> splineKnots)
133 {
135 curve.kind = BSpline;
136 curve.degree = splineDegree;
137 curve.poles = std::move(splinePoles);
138 curve.weights = std::move(splineWeights);
139 curve.knots = std::move(splineKnots);
140 return curve;
141 }
142 };
143
145 bool AddCurvedPlanarSurface(const Point3D& origin, const Point3D& axisU, const Point3D& axisV,
146 const std::vector<PlanarBoundaryCurve>& outerWire,
147 const std::vector<std::vector<PlanarBoundaryCurve>>& innerWires = {});
148
150 bool AddCylindricalSurface(const Point3D& centerPoint, const Point3D& axis, const Point3D& referenceAxisU,
151 double radius, double heightMin, double heightMax, double phiStart = 0.,
152 double phiSweep = 6.283185307179586, bool innerWall = false);
153
155 bool AddCylindricalSurface(const Point3D& centerPoint, const Point3D& axis, const Point3D& referenceAxisU,
156 double radius, double heightMin, double heightMax, double phiStart, double phiSweep,
157 bool innerWall, const std::vector<PlanarBoundaryCurve>& outerTrim,
158 const std::vector<std::vector<PlanarBoundaryCurve>>& innerTrims = {});
159
161 bool AddSphericalSurface(const Point3D& center, const Point3D& polarAxis, const Point3D& referenceAxisU,
162 double radius, double thetaMin = 0., double thetaMax = 3.141592653589793,
163 double phiStart = 0., double phiSweep = 6.283185307179586, bool innerWall = false);
164
166 bool AddSphericalSurface(const Point3D& center, const Point3D& polarAxis, const Point3D& referenceAxisU,
167 double radius, double thetaMin, double thetaMax, double phiStart, double phiSweep,
168 bool innerWall, const std::vector<PlanarBoundaryCurve>& outerTrim,
169 const std::vector<std::vector<PlanarBoundaryCurve>>& innerTrims = {});
170
172 bool AddConicalSurface(const Point3D& centerPoint, const Point3D& axis, const Point3D& referenceAxisU,
173 double radiusAtMin, double radiusAtMax, double heightMin, double heightMax,
174 double phiStart = 0., double phiSweep = 6.283185307179586, bool innerWall = false);
175
177 bool AddConicalSurface(const Point3D& centerPoint, const Point3D& axis, const Point3D& referenceAxisU,
178 double radiusAtMin, double radiusAtMax, double heightMin, double heightMax, double phiStart,
179 double phiSweep, bool innerWall, const std::vector<PlanarBoundaryCurve>& outerTrim,
180 const std::vector<std::vector<PlanarBoundaryCurve>>& innerTrims = {});
181
183 bool AddToroidalSurface(const Point3D& centerPoint, const Point3D& axis, const Point3D& referenceAxisU,
184 double majorRadius, double minorRadius, double phiStart = 0.,
185 double phiSweep = 6.283185307179586, double tubeStart = 0.,
186 double tubeSweep = 6.283185307179586, bool innerWall = false);
187
189 bool AddToroidalSurface(const Point3D& centerPoint, const Point3D& axis, const Point3D& referenceAxisU,
190 double majorRadius, double minorRadius, double phiStart, double phiSweep, double tubeStart,
191 double tubeSweep, bool innerWall, const std::vector<PlanarBoundaryCurve>& outerTrim,
192 const std::vector<std::vector<PlanarBoundaryCurve>>& innerTrims = {});
193
196 enum BoundaryEdgeFlag : unsigned char {
197 kEdgeReversed = 1u << 0,
198 kEdgeDegenerate = 1u << 1,
199 kEdgeAnchored = 1u << 2
200 };
201
203 bool SetSurfaceBoundaryEdges(int surfaceIndex, const std::vector<unsigned int>& edgeIds,
204 const std::vector<unsigned char>& edgeFlags);
206
208 void CloseShape(bool check = true);
209
210 int GetNsurfaces() const;
211 bool IsDefined() const;
212
215 void SetModelTolerance(double toleranceCm);
216 double GetModelTolerance() const { return fModelTolerance; }
218
220 bool HasBVH() const;
224 int CountBVHRayCandidates(const Point3D& point, const Point3D& direction) const;
225
227 static void SetRayTMaxPruning(bool enable);
228 static bool GetRayTMaxPruning();
229
231 static void ResetRayCandidateCounter();
232 static long long GetRayCandidateCount();
233
235 static void ResetSafetyCandidateCounter();
236 static long long GetSafetyCandidateCount();
237
239 static void SetSafetyBoundUnsoundForTest(bool enable);
240 static bool GetSafetyBoundUnsoundForTest();
241
244 double distance = 0.;
245 double normalAlignment = 0.;
247 bool onTrimBoundary = false;
248 };
249
251 void DescribeContainsCrossings(const Point3D& point, std::vector<ContainsCrossing>& bvhCrossings,
252 std::vector<ContainsCrossing>& loopCrossings) const;
253
255 void DescribeContainsCrossings(const Point3D& point, const Point3D& direction,
256 std::vector<ContainsCrossing>& bvhCrossings,
257 std::vector<ContainsCrossing>& loopCrossings) const;
258
261 bool IsClosed() const;
264 bool IsOrientationConsistent() const;
265
280
285 bool IsNavigable() const;
288 static const char* GetNavigationReliabilityName(NavigationReliability reliability);
289
291 int GetBoundaryEdgeCount() const;
292 int GetNonManifoldEdgeCount() const;
293 int GetReversedEdgeCount() const;
294
298 double GetMaxRimIsolation() const;
302 bool HasEdgeIdentity() const;
304 int GetSourceEdgeCount() const;
305 int GetSharedSourceEdgeCount() const;
306 int GetBoundarySourceEdgeCount() const;
308 int GetReversedSourceEdgeCount() const;
311 double GetMaxSharedEdgeDeviation() const;
314 int GetMeasuredSharedEdgeCount() const;
318 double GetRimChordResolution() const;
320 double GetRimMatchTolerance() const;
322 double GetTotalRimLength() const;
323 double GetUnmatchedRimLength() const;
325 int GetRimCount() const;
326 int GetMatchedRimCount() const;
327 int GetBoundaryRimCount() const;
328 int GetNonManifoldRimCount() const;
329 int GetReversedRimCount() const;
330
332 struct RimReport {
333 int surface = -1;
334 int rimOnSurface = -1;
335 bool closed = false;
336 int chords = 0;
338 double length = 0.;
339 double unmatchedLength = 0.;
341 double maxIsolation = 0.;
342 std::array<double, 3> maxIsolationPoint{{0., 0., 0.}};
347 };
350 const std::vector<RimReport>& GetRimReports() const;
351
353 void GetSurfaceCapacityContributions(std::vector<double>& contributions) const;
355
356 void ComputeBBox() override;
357
358 int DistancetoPrimitive(int, int) override { return 99999; }
359 const TBuffer3D& GetBuffer3D(int reqSections, Bool_t localFrame) const override;
360 void GetMeshNumbers(int& nvert, int& nsegs, int& npols) const override;
361 int GetNmeshVertices() const override;
362
364 Bool_t GetPointsOnSegments(Int_t npoints, Double_t* array) const override;
365
368 static constexpr double kSurfacePointTolerance = 1.e-11;
369
370 void InspectShape() const override {}
371 TBuffer3D* MakeBuffer3D() const override;
372 void Print(Option_t* option = "") const override;
373 void SavePrimitive(std::ostream&, Option_t*) override {}
374 void SetPoints(double* points) const override;
375 void SetPoints(Float_t* points) const override;
376 void SetSegsAndPols(TBuffer3D& buff) const override;
377 void Sizeof3D() const override {}
378
379 Double_t DistFromOutside(const Double_t* point, const Double_t* dir, Int_t iact = 1,
380 Double_t step = TGeoShape::Big(), Double_t* safe = nullptr) const override;
381 Double_t DistFromInside(const Double_t* point, const Double_t* dir, Int_t iact = 1,
382 Double_t step = TGeoShape::Big(), Double_t* safe = nullptr) const override;
383 bool Contains(const Double_t* point) const override;
386 bool Contains_Loop(const Double_t* point) const;
388 bool ContainsAlongDirection(const Double_t* point, const Double_t* direction) const;
390 Double_t DistFromOutside_Loop(const Double_t* point, const Double_t* dir,
391 Double_t stepmax = TGeoShape::Big()) const;
392 Double_t DistFromInside_Loop(const Double_t* point, const Double_t* dir,
393 Double_t stepmax = TGeoShape::Big()) const;
394 Double_t Safety(const Double_t* point, Bool_t in = kTRUE) const override;
395 void ComputeNormal(const Double_t* point, const Double_t* dir, Double_t* norm) const override;
397 Double_t Safety_Loop(const Double_t* point, Bool_t in = kTRUE) const;
398 void ComputeNormal_Loop(const Double_t* point, const Double_t* dir, Double_t* norm) const;
399 Double_t Capacity() const override;
400
402 const std::vector<BVHSurfaceRecord>& GetSurfaceRecords() const { return fRecords; }
403
404 private:
406 bool containsByParity(const Double_t* point, bool useBVH) const;
407
409 void computeNormalFrom(const Double_t* point, const Double_t* dir, Double_t* norm, bool useLoop) const;
410
412 bool RebuildFromRecords();
413
415 bool ProjectOntoPatch(int surfaceIndex, double* point) const;
416
417 struct Impl;
418 Impl* fImpl = nullptr;
419
421 std::vector<BVHSurfaceRecord> fRecords;
422
424 double fModelTolerance = 0.;
425
426 ClassDefOverride(O2BVHSurfaceSolid, 3) // BVH surface-bounded shape class
427};
428
429} // namespace cad
430} // namespace o2
431
432#endif
header::DataOrigin origin
float center
double lower[3]
double upper[3]
uint32_t c
Definition RawData.h:2
O2BVHSurfaceSolid & operator=(const O2BVHSurfaceSolid &)=delete
Double_t DistFromOutside_Loop(const Double_t *point, const Double_t *dir, Double_t stepmax=TGeoShape::Big()) const
Non-BVH DistFrom* over all surfaces: the oracles the BVH paths must match exactly.
@ Reliable
closed, consistently oriented 2-manifold: parity is well defined
@ Undetermined
CloseShape() has not run yet: no diagnostics exist.
bool AddCylindricalSurface(const Point3D &centerPoint, const Point3D &axis, const Point3D &referenceAxisU, double radius, double heightMin, double heightMax, double phiStart=0., double phiSweep=6.283185307179586, bool innerWall=false)
Add a cylindrical wall of radius around axis over a height range and a phi sweep; innerWall points th...
double GetRimMatchTolerance() const
The declared rim match tolerance in cm, the model's own or a fallback: the floor of each chord's matc...
void Print(Option_t *option="") const override
static void ResetSafetyCandidateCounter()
Per-thread count of surfaces handed to distanceSqToPatch by Safety and ComputeNormal since the last r...
TBuffer3D * MakeBuffer3D() const override
bool ContainsAlongDirection(const Double_t *point, const Double_t *direction) const
Diagnostic: the parity answer for one explicit direction, bypassing Contains()'s re-shoot policy.
void GetMeshNumbers(int &nvert, int &nsegs, int &npols) const override
void InspectShape() const override
bool Contains_Loop(const Double_t *point) const
Double_t DistFromInside_Loop(const Double_t *point, const Double_t *dir, Double_t stepmax=TGeoShape::Big()) const
int GetRimCount() const
Rim counts: total, and split by the same four states as the edge counters above.
const TBuffer3D & GetBuffer3D(int reqSections, Bool_t localFrame) const override
void SavePrimitive(std::ostream &, Option_t *) override
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
static void SetSafetyBoundUnsoundForTest(bool enable)
Test-only sabotage: prune on the distance to the box centre, which bounds nothing,...
void CloseShape(bool check=true)
Finalize the shape: bounding box, display mesh, BVH and closure diagnostics, reported when check is s...
void ComputeNormal_Loop(const Double_t *point, const Double_t *dir, Double_t *norm) const
int CountBVHRayCandidates(const Point3D &point, const Point3D &direction) const
Test hook: distinct surfaces whose cover boxes the ray traverses; -1 without a BVH.
static long long GetSafetyCandidateCount()
void SetPoints(double *points) const override
Double_t Safety_Loop(const Double_t *point, Bool_t in=kTRUE) const
Non-BVH Safety/ComputeNormal over all surfaces: the oracles the BVH traversal must match bit for bit.
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
void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) const override
Bool_t GetPointsOnSegments(Int_t npoints, Double_t *array) const override
Fill array with npoints points on the solid's exact boundary; kFALSE below GetNmeshVertices() so ROOT...
bool Contains(const Double_t *point) const override
void SetSegsAndPols(TBuffer3D &buff) const override
void GetSurfaceCapacityContributions(std::vector< double > &contributions) const
Each face's divergence-theorem contribution to Capacity(), in record order.
Double_t Capacity() const override
O2BVHSurfaceSolid(const O2BVHSurfaceSolid &)=delete
std::array< double, 3 > Point3D
bool GetBVHRootBounds(Point3D &lower, Point3D &upper) const
Fill the BVH root-node bounding box; returns false when no BVH has been built.
int DistancetoPrimitive(int, int) override
NavigationReliability GetNavigationReliability() const
The reliability state derived from the last CloseShape(); Undetermined before it has run.
std::array< double, 2 > Point2D
static void SetRayTMaxPruning(bool enable)
Ray tmax tightening in the distance queries, on by default; it never changes an answer....
int GetSourceEdgeCount() const
Distinct source edges and their incidence: shared, boundary, non-manifold, reversed and degenerate.
bool AddCurvedPlanarSurface(const Point3D &origin, const Point3D &axisU, const Point3D &axisV, const std::vector< PlanarBoundaryCurve > &outerWire, const std::vector< std::vector< PlanarBoundaryCurve > > &innerWires={})
Add an exact planar surface bounded by line/arc wires; axisU and axisV are orthonormal and axisU x ax...
static long long GetRayCandidateCount()
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const override
The distance to the nearest patch, rounded down by one ulp so that Safety is never too large.
int GetNmeshVertices() const override
double GetMaxSharedEdgeDeviation() const
Largest Hausdorff distance between the two faces' realisations of one shared edge,...
static const char * GetNavigationReliabilityName(NavigationReliability reliability)
const std::vector< RimReport > & GetRimReports() const
bool AddConicalSurface(const Point3D &centerPoint, const Point3D &axis, const Point3D &referenceAxisU, double radiusAtMin, double radiusAtMax, double heightMin, double heightMax, double phiStart=0., double phiSweep=6.283185307179586, bool innerWall=false)
Add a conical wall whose radius runs linearly from radiusAtMin to radiusAtMax; one radius may be zero...
static constexpr double kSurfacePointTolerance
void SetModelTolerance(double toleranceCm)
bool SetSurfaceBoundaryEdges(int surfaceIndex, const std::vector< unsigned int > &edgeIds, const std::vector< unsigned char > &edgeFlags)
Attach surface surfaceIndex's edge identities in trim-curve order; false on a bad index or mismatched...
const std::vector< BVHSurfaceRecord > & GetSurfaceRecords() const
The Add*Surface calls this solid was built from, in order.
bool AddSphericalSurface(const Point3D &center, const Point3D &polarAxis, const Point3D &referenceAxisU, double radius, double thetaMin=0., double thetaMax=3.141592653589793, double phiStart=0., double phiSweep=6.283185307179586, bool innerWall=false)
Add a spherical surface of radius trimmed to a theta range and a phi sweep; the defaults give a full ...
bool AddToroidalSurface(const Point3D &centerPoint, const Point3D &axis, const Point3D &referenceAxisU, double majorRadius, double minorRadius, double phiStart=0., double phiSweep=6.283185307179586, double tubeStart=0., double tubeSweep=6.283185307179586, bool innerWall=false)
Add a toroidal surface trimmed to a phiRing x phiTube rectangle; the defaults give a full torus,...
void Sizeof3D() const override
double GetTotalRimLength() const
Summed trim-boundary length, and the part with no other face within the match band,...
void DescribeContainsCrossings(const Point3D &point, std::vector< ContainsCrossing > &bvhCrossings, std::vector< ContainsCrossing > &loopCrossings) const
Diagnostic: the parity ray's crossings at point from the BVH and from the loop, sorted by distance.
bool AddPlanarSurface(const Point3D &origin, const Point3D &axisU, const Point3D &axisV, const std::vector< Point2D > &outerWire, const std::vector< std::vector< Point2D > > &innerWires={})
static void ResetRayCandidateCounter()
Per-thread count of surfaces handed to the BVH leaf callback by DistFrom* since the last reset.
@ kEdgeAnchored
entry i is trim curve i of this face, so it can be measured
@ kEdgeReversed
the face runs against the edge's own direction
@ kEdgeDegenerate
cone apex / sphere pole: a point, so it has no second face
bool HasBVH() const
Whether the BVH acceleration structure has been built (after CloseShape).
int GetBoundaryEdgeCount() const
Per-chord closure counts: diagnostics only; GetNavigationReliability() reads the rim counts below.
GLuint GLuint end
Definition glcorearb.h:469
GLenum array
Definition glcorearb.h:4274
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei GLsizei GLfloat distance
Definition glcorearb.h:5506
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLboolean enable
Definition glcorearb.h:3991
GLboolean r
Definition glcorearb.h:1233
GLuint start
Definition glcorearb.h:469
void check(const std::vector< std::string > &arguments, const std::vector< ConfigParamSpec > &workflowOptions, const std::vector< DeviceSpec > &deviceSpecs, CheckMatrix &matrix)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
One boundary curve of a BVHSurfaceRecord in the flat form ROOT streams: a segment,...
std::vector< double > poles
B-spline control points, flattened (u, v) pairs.
std::vector< double > knots
B-spline clamped flat knot vector.
std::vector< double > weights
B-spline weights (empty => non-rational)
int kind
PlanarBoundaryCurve::Kind: 0 = Line, 1 = Arc, 2 = BSpline.
The persistent record of one successful Add*Surface call; reading a solid back replays the records.
std::vector< int > wireSizes
std::vector< BVHSurfaceCurveRecord > curves
std::vector< double > scalars
std::vector< double > polygonPoints
The wires, outer first: PlanarPolygon stores (u, v) pairs in polygonPoints, the others curves; wireSi...
bool trimmed
the wire-trim overload was used (quadrics only)
double axisA[3]
axisU / axis / polarAxis
double axisB[3]
axisV / referenceAxisU
std::vector< unsigned char > boundaryEdgeFlags
static int expectedScalarCount(int recordKind)
How many entries scalars must hold for kind, or -1 for an unknown kind.
std::vector< unsigned int > boundaryEdgeIds
Sidecar v3 boundary edge identities in curve order: an edge-table index and a BoundaryEdgeFlag byte; ...
double origin[3]
origin / centerPoint / center
One crossing of the containment parity ray, as seen by Contains().
bool onTrimBoundary
The hit lay in its patch's on-boundary band, so a tie-break kept it; Contains() re-shoots on these.
One boundary curve in the surface's local (u, v) frame: a line segment, a circular arc or a clamped (...
std::vector< double > weights
B-spline weights (empty ⇒ non-rational)
static PlanarBoundaryCurve makeLine(const Point2D &start, const Point2D &end)
static PlanarBoundaryCurve makeBSpline(int splineDegree, std::vector< Point2D > splinePoles, std::vector< double > splineWeights, std::vector< double > splineKnots)
std::vector< double > knots
B-spline clamped flat knot vector.
std::vector< Point2D > poles
B-spline control points.
static PlanarBoundaryCurve makeArc(const Point2D &c, double r, double start, double end)
One trim loop of one face as the closure measurement saw it, naming the rim and its worst chord.
double maxIsolation
Largest distance from a chord midpoint of this rim to another face's chord, where,...
int unmatchedChords
of them, how many found no other face within the tolerance
int surface
index into GetSurfaceRecords() of the face owning this rim
int rimOnSurface
which trim loop of that face, in the order the face emits them
bool closed
the rim polyline returns to its own first point