14#define BOOST_TEST_MODULE Test O2Tessellated class
15#define BOOST_TEST_MAIN
16#define BOOST_TEST_DYN_LINK
17#include <boost/test/unit_test.hpp>
30using Vertex_t = O2Tessellated::Vertex_t;
36 explicit Rng(
unsigned long long seed) : mState(seed) {}
37 double uniform(
double low,
double high)
39 mState = mState * 6364136223846793005ULL + 1442695040888963407ULL;
40 const double unit =
static_cast<double>((mState >> 11) & ((1ULL << 53) - 1)) /
static_cast<double>(1ULL << 53);
41 return low + unit * (high - low);
45 unsigned long long mState;
49void addBox(O2Tessellated& shape,
double cx,
double cy,
double cz,
double hx,
double hy,
double hz)
51 const double x0 = cx - hx,
x1 = cx + hx;
52 const double y0 = cy - hy,
y1 = cy + hy;
53 const double z0 = cz - hz, z1 = cz + hz;
54 const Vertex_t corner[8] = {{
x0,
y0, z0}, {
x1,
y0, z0}, {
x1,
y1, z0}, {
x0,
y1, z0}, {
x0,
y0, z1}, {
x1,
y0, z1}, {
x1,
y1, z1}, {
x0,
y1, z1}};
56 const int quad[6][4] = {{0, 3, 2, 1}, {4, 5, 6, 7}, {0, 1, 5, 4}, {2, 3, 7, 6}, {1, 2, 6, 5}, {0, 4, 7, 3}};
57 for (
const auto&
face : quad) {
58 shape.AddFacet(corner[
face[0]], corner[
face[1]], corner[
face[2]]);
59 shape.AddFacet(corner[
face[0]], corner[
face[2]], corner[
face[3]]);
67 constexpr double EPS = 1.e-8;
68 const double infinity = std::numeric_limits<double>::infinity();
69 const double e1[3] = {
v1[0] -
v0[0],
v1[1] -
v0[1],
v1[2] -
v0[2]};
70 const double e2[3] = {
v2[0] -
v0[0],
v2[1] -
v0[1],
v2[2] -
v0[2]};
71 const double p[3] = {dir[1] * e2[2] - dir[2] * e2[1], dir[2] * e2[0] - dir[0] * e2[2],
72 dir[0] * e2[1] - dir[1] * e2[0]};
73 const double det = e1[0] * p[0] + e1[1] * p[1] + e1[2] * p[2];
74 if (std::abs(det) <= EPS) {
78 const double invDet = 1.0 / det;
79 const double u = (tvec[0] * p[0] + tvec[1] * p[1] + tvec[2] * p[2]) * invDet;
80 if (u < 0.0 || u > 1.0) {
83 const double q[3] = {tvec[1] * e1[2] - tvec[2] * e1[1], tvec[2] * e1[0] - tvec[0] * e1[2],
84 tvec[0] * e1[1] - tvec[1] * e1[0]};
85 const double v = (dir[0] * q[0] + dir[1] * q[1] + dir[2] * q[2]) * invDet;
86 if (v < 0.0 || u + v > 1.0) {
89 const double t = e2[0] * q[0] + e2[1] * q[1] + e2[2] * q[2];
90 return (t * invDet > 0.) ? t * invDet : infinity;
94double bruteForce(
const O2Tessellated& shape,
const double*
origin,
const double* dir,
bool entering)
96 double best = TGeoShape::Big();
97 for (
int facet = 0; facet < shape.GetNfacets(); ++facet) {
102 const double e1[3] = {
v1[0] -
v0[0],
v1[1] -
v0[1],
v1[2] -
v0[2]};
103 const double e2[3] = {
v2[0] -
v0[0],
v2[1] -
v0[1],
v2[2] -
v0[2]};
104 const double normal[3] = {e1[1] * e2[2] - e1[2] * e2[1], e1[2] * e2[0] - e1[0] * e2[2],
105 e1[0] * e2[1] - e1[1] * e2[0]};
106 const double along = normal[0] * dir[0] + normal[1] * dir[1] + normal[2] * dir[2];
108 if (entering ? (along > 0.) : (along <= 0.)) {
111 best = std::min(best, rayTriangleReference(
origin, dir,
v0,
v1,
v2));
117void buildRow(O2Tessellated& shape)
120 addBox(shape, -21. + 6. *
index, 0., 0., 2., 3., 4.);
122 shape.CloseShape(
true,
false,
false);
128 O2Tessellated shape(
"row");
135 for (
int trial = 0; trial < 4000; ++trial) {
137 const double origin[3] = {rng.uniform(-40., 40.), rng.uniform(-12., 12.), rng.uniform(-12., 12.)};
138 double dir[3] = {rng.uniform(-1., 1.), rng.uniform(-1., 1.), rng.uniform(-1., 1.)};
139 const double norm = std::sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
147 const double outside = shape.DistFromOutside(
origin, dir, 1, TGeoShape::Big(),
nullptr);
148 const double inside = shape.DistFromInside(
origin, dir, 1, TGeoShape::Big(),
nullptr);
149 const double outsideReference = bruteForce(shape,
origin, dir,
true);
150 const double insideReference = bruteForce(shape,
origin, dir,
false);
154 outsideHits += outsideReference < TGeoShape::Big() ? 1 : 0;
155 insideHits += insideReference < TGeoShape::Big() ? 1 : 0;
159 BOOST_CHECK_GT(outsideHits, 200);
160 BOOST_CHECK_GT(insideHits, 200);
165 O2Tessellated shape(
"row");
169 const double origin[3] = {-40., 0., 0.};
170 const double dir[3] = {1., 0., 0.};
173 bruteForce(shape,
origin, dir,
true));
176 const double inner[3] = {-21., 0., 0.};
177 BOOST_CHECK_EQUAL(shape.DistFromInside(inner, dir, 1, TGeoShape::Big(),
nullptr), 2.);
178 BOOST_CHECK_EQUAL(shape.DistFromInside(inner, dir, 1, TGeoShape::Big(),
nullptr),
179 bruteForce(shape, inner, dir,
false));
header::DataOrigin origin
header::DataDescription description
Tessellated::Vertex_t Vertex_t
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLenum GLuint GLint GLenum face
GLfloat GLfloat GLfloat v2
GLuint GLfloat GLfloat y0
BOOST_AUTO_TEST_CASE(PrunedRayQueriesEqualTheBruteForceMinimum)
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())