16#define BOOST_TEST_MODULE Test HalfSpaceBox
17#define BOOST_TEST_MAIN
18#define BOOST_TEST_DYN_LINK
19#include <boost/test/unit_test.hpp>
22#include "TGeoManager.h"
25#include "TGeoMatrix.h"
26#include "TGeoHalfSpace.h"
27#include "TGeoCompositeShape.h"
44std::vector<Plane> tpcPlanes()
46 const double slope = TMath::Tan(22. * TMath::DegToRad());
47 const double intp = 1.245;
49 const double p1[3] = {intp *
slope /
b, -intp /
b, 0.};
50 const double p2[3] = {-intp *
slope /
b, -intp /
b, 0.};
52 {
"sp1", {
p1[0],
p1[1], 0.}, {-
p1[0], -
p1[1], 0.}},
53 {
"sp2", {
p2[0],
p2[1], 0.}, {-
p2[0], -
p2[1], 0.}},
54 {
"cutil1", {0., 0.105, 0.}, {0., 1., 0.}},
55 {
"cutomh1", {0., -1.05, -3.4}, {0., -TMath::Tan(30. * TMath::DegToRad()), 1.}},
56 {
"cutomh2", {0., -1.05, 3.4}, {0., -TMath::Tan(30. * TMath::DegToRad()), -1.}},
57 {
"cutomh3", {-1.65, 0., -0.9}, {TMath::Tan(75. * TMath::DegToRad()), 0., 1.}},
58 {
"cutomh4", {-1.65, 0., 0.9}, {TMath::Tan(75. * TMath::DegToRad()), 0., -1.}},
59 {
"cutomh5", {1.65, -1.05, 0.}, {-1., -TMath::Tan(20. * TMath::DegToRad()), 0.}},
60 {
"cutohs1", {0., -0.186, 0.}, {0., -1., 0.}},
61 {
"cutmmh1", {-1.65, 0., -0.9}, {8., 0., 8. * TMath::Tan(13. * TMath::DegToRad())}},
62 {
"cutmmh2", {-1.65, 0., 0.9}, {8., 0., -8. * TMath::Tan(13. * TMath::DegToRad())}},
63 {
"cutmmh3", {0., 1.85, -2.8}, {0., -6.1, 6.1 * TMath::Tan(20. * TMath::DegToRad())}},
64 {
"cutmmh4", {0., 1.85, 2.8}, {0., -6.1, -6.1 * TMath::Tan(20. * TMath::DegToRad())}},
65 {
"cutmmh5", {0.75, 0., -8.9}, {2.4 * TMath::Tan(30. * TMath::DegToRad()), 0., 2.4}},
66 {
"cutmmh6", {0.75, 0., 8.9}, {2.4 * TMath::Tan(30. * TMath::DegToRad()), 0., -2.4}}};
72void compare(
const TString& tag,
const double p[3],
const double n[3],
double parentHalfSize,
double reach,
73 TRandom3& rnd,
int nPoints,
int nRays,
double& maxDistDiff)
75 const double nl = std::sqrt(
n[0] *
n[0] +
n[1] *
n[1] +
n[2] *
n[2]);
76 BOOST_REQUIRE(nl > 1e-6);
77 constexpr double kSurfaceBand = 1e-9;
79 new TGeoBBox(TString::Format(
"parent_%s", tag.Data()).Data(), parentHalfSize, parentHalfSize, parentHalfSize);
80 new TGeoHalfSpace(TString::Format(
"hs_%s", tag.Data()).Data(),
const_cast<double*
>(p),
const_cast<double*
>(
n));
83 auto*
ref =
new TGeoCompositeShape(TString::Format(
"ref_%s", tag.Data()),
84 TString::Format(
"parent_%s-hs_%s", tag.Data(), tag.Data()));
85 auto*
box =
new TGeoCompositeShape(TString::Format(
"new_%s", tag.Data()),
86 TString::Format(
"parent_%s-(bx_%s:bx_%s_tr)", tag.Data(), tag.Data(), tag.Data()));
88 const double range = 1.2 * parentHalfSize;
89 for (
int k = 0; k < nPoints; ++k) {
91 for (
int i = 0;
i < 3; ++
i) {
94 const double d = ((
x[0] - p[0]) *
n[0] + (
x[1] - p[1]) *
n[1] + (
x[2] - p[2]) *
n[2]) / nl;
95 if (std::abs(d) < kSurfaceBand) {
98 if (
ref->Contains(
x) !=
box->Contains(
x)) {
99 BOOST_REQUIRE_MESSAGE(
false,
"containment differs for " << tag.Data() <<
" at (" <<
x[0] <<
"," <<
x[1] <<
","
100 <<
x[2] <<
"), distance to plane " << d);
104 for (
int k = 0; k < nRays; ++k) {
106 for (
int i = 0;
i < 3; ++
i) {
108 dir[
i] = rnd.Uniform(-1., 1.);
110 const double dn = std::sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
114 for (
int i = 0;
i < 3; ++
i) {
117 const bool inside =
ref->Contains(
x);
118 if (inside !=
box->Contains(
x)) {
121 const double d1 = inside ?
ref->DistFromInside(
x, dir, 3) :
ref->DistFromOutside(
x, dir, 3);
122 const double d2 = inside ?
box->DistFromInside(
x, dir, 3) :
box->DistFromOutside(
x, dir, 3);
123 if (d1 > 1e15 && d2 > 1e15) {
126 maxDistDiff = std::max(maxDistDiff, std::abs(d1 - d2));
133 auto* geom =
new TGeoManager(
"halfspacetest",
"half-space replacement test");
134 TRandom3 rnd(20240101);
135 double maxDistDiff = 0.;
138 for (
const auto& pl : tpcPlanes()) {
139 compare(pl.label, pl.p, pl.n, 10., 100., rnd, 200000, 20000, maxDistDiff);
143 for (
int i = 0;
i < 200; ++
i) {
145 for (
int k = 0; k < 3; ++k) {
146 p[k] = rnd.Uniform(-5., 5.);
147 n[k] = rnd.Uniform(-1., 1.);
149 if (std::sqrt(
n[0] *
n[0] +
n[1] *
n[1] +
n[2] *
n[2]) < 1e-3) {
152 compare(TString::Format(
"rnd%d",
i), p,
n, 10., 100., rnd, 20000, 2000, maxDistDiff);
156 BOOST_CHECK_SMALL(maxDistDiff, 1e-9);
157 BOOST_TEST_MESSAGE(
"maximum ray-distance difference: " << maxDistDiff);
167 auto* geom =
new TGeoManager(
"halfspacetest2",
"half-space replacement, compound expression");
168 const double shift[3] = {0., -0.175, 0.};
169 const double p[3] = {0., 0.105, 0.};
170 const double n[3] = {0., 1., 0.};
172 new TGeoBBox(
"tpcihs1", 4.7, 0.66, 2.35);
173 new TGeoBBox(
"tpcihs2", 4.7, 0.485, 1.0,
const_cast<double*
>(shift));
174 new TGeoBBox(
"tpcihs3", 1.5, 0.485, 2.35,
const_cast<double*
>(shift));
175 new TGeoTube(
"tpcihs4", 0.0, 2.38, 0.1);
176 auto* trans2 =
new TGeoTranslation(
"trans2", 0.0, 2.84, 2.25);
177 trans2->RegisterYourself();
178 auto* trans3 =
new TGeoTranslation(
"trans3", 0.0, 2.84, -2.25);
179 trans3->RegisterYourself();
180 new TGeoHalfSpace(
"cutil1",
const_cast<double*
>(p),
const_cast<double*
>(
n));
183 auto*
ref =
new TGeoCompositeShape(
184 "ref_tpcihs6",
"tpcihs1-(tpcihs2+tpcihs3)-(tpcihs4:trans2)-(tpcihs4:trans3)-cutil1");
185 auto*
box =
new TGeoCompositeShape(
186 "new_tpcihs6",
"tpcihs1-(tpcihs2+tpcihs3)-(tpcihs4:trans2)-(tpcihs4:trans3)-(bcutil1:bcutil1_tr)");
188 TRandom3 rnd(20240102);
189 long inRef = 0, inBox = 0;
190 for (
int k = 0; k < 2000000; ++k) {
192 for (
int i = 0;
i < 3; ++
i) {
193 x[
i] = rnd.Uniform(-6., 6.);
195 if (std::abs(
x[1] - p[1]) < 1e-9) {
198 const bool a =
ref->Contains(
x);
199 const bool b =
box->Contains(
x);
203 BOOST_REQUIRE_MESSAGE(
false,
"containment differs at (" <<
x[0] <<
"," <<
x[1] <<
"," <<
x[2] <<
")");
207 BOOST_CHECK_GT(inRef, 0);
constexpr int p1()
constexpr to accelerate the coordinates changing
Collection of utility functions for TGeo.
static void makeHalfSpaceBox(const char *name, const double p[3], const double n[3], double reach)
GLboolean GLboolean GLboolean b
GLuint GLsizei const GLchar * label
GLboolean GLboolean GLboolean GLboolean a
GLsizei const GLint * box
void compare(std::string_view s1, std::string_view s2)
BOOST_AUTO_TEST_CASE(HalfSpaceBox_reproduces_TGeoHalfSpace)
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())