File indexing completed on 2026-05-27 07:24:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "detray/definitions/units.hpp"
0011 #include "detray/geometry/concepts.hpp"
0012 #include "detray/geometry/mask.hpp"
0013 #include "detray/geometry/shapes/cylinder2D.hpp"
0014 #include "detray/geometry/shapes/cylinder3D.hpp"
0015
0016
0017 #include "detray/test/framework/types.hpp"
0018 #include "detray/test/utils/ratio_test.hpp"
0019
0020
0021 #include <gtest/gtest.h>
0022
0023 using namespace detray;
0024
0025 using test_algebra = test::algebra;
0026 using scalar = test::scalar;
0027 using point3 = test::point3;
0028
0029 constexpr scalar tol{1e-4f};
0030
0031 constexpr scalar r{3.f * unit<scalar>::mm};
0032 constexpr scalar hz{4.f * unit<scalar>::mm};
0033
0034
0035 GTEST_TEST(detray_masks, cylinder2D) {
0036 static_assert(concepts::shape<cylinder2D, test_algebra>);
0037 static_assert(concepts::cylindrical_shape<cylinder2D, test_algebra>);
0038
0039 point3 p2_in = {r, static_cast<scalar>(-1.f), r};
0040 point3 p2_edge = {r, hz, r};
0041 point3 p2_out = {3.5f, 4.5f, 3.5f};
0042
0043 mask<cylinder2D, test_algebra> c{0u, r, -hz, hz};
0044
0045 ASSERT_NEAR(c[cylinder2D::e_r], r, tol);
0046 ASSERT_NEAR(c[cylinder2D::e_lower_z], -hz, tol);
0047 ASSERT_NEAR(c[cylinder2D::e_upper_z], hz, tol);
0048
0049 ASSERT_TRUE(c.is_inside(p2_in));
0050 ASSERT_TRUE(c.is_inside(p2_edge));
0051 ASSERT_FALSE(c.is_inside(p2_out));
0052
0053 ASSERT_TRUE(c.is_inside(p2_out, 0.6f));
0054
0055
0056 const scalar a{c.area()};
0057 EXPECT_NEAR(a, 150.796447f * unit<scalar>::mm2, tol);
0058 ASSERT_EQ(a, c.measure());
0059
0060
0061 constexpr scalar envelope{0.01f};
0062 const auto loc_bounds = c.local_min_bounds(envelope);
0063 ASSERT_NEAR(loc_bounds[cuboid3D::e_min_x], -(r + envelope), tol);
0064 ASSERT_NEAR(loc_bounds[cuboid3D::e_min_y], -(r + envelope), tol);
0065 ASSERT_NEAR(loc_bounds[cuboid3D::e_min_z], -(hz + envelope), tol);
0066 ASSERT_NEAR(loc_bounds[cuboid3D::e_max_x], (r + envelope), tol);
0067 ASSERT_NEAR(loc_bounds[cuboid3D::e_max_y], (r + envelope), tol);
0068 ASSERT_NEAR(loc_bounds[cuboid3D::e_max_z], (hz + envelope), tol);
0069
0070 const auto centroid = c.centroid();
0071 ASSERT_NEAR(centroid[0], 0.f, tol);
0072 ASSERT_NEAR(centroid[1], 0.f, tol);
0073 ASSERT_NEAR(centroid[2], 0.f, tol);
0074 }
0075
0076
0077 GTEST_TEST(detray_masks, cylinder2D_ratio_test) {
0078 struct mask_check {
0079 bool operator()(const point3 &p, const mask<cylinder2D, test_algebra> &cyl,
0080 const test::transform3 &trf, const scalar t) {
0081 return cyl.is_inside(trf, p, t);
0082 }
0083 };
0084
0085 constexpr mask<cylinder2D, test_algebra> cyl{0u, r, 0.f, 5.f};
0086
0087 constexpr scalar t{0.f};
0088 const test::transform3 trf{};
0089 constexpr scalar size{10.f * unit<scalar>::mm};
0090 const auto n_points{static_cast<std::size_t>(std::pow(10000, 2))};
0091
0092
0093
0094 std::vector<point3> points = test::generate_regular_points<cylinder2D>(
0095 n_points, {cyl[cylinder2D::e_r], size});
0096
0097 scalar ratio = test::ratio_test<mask_check>(points, cyl, trf, t);
0098
0099 const scalar area{cyl.measure()};
0100 const scalar world{2.f * constant<scalar>::pi * r * size};
0101
0102 ASSERT_NEAR(ratio, area / world, 0.02f);
0103 }
0104
0105
0106 GTEST_TEST(detray_masks, cylinder3D) {
0107 static_assert(concepts::shape<cylinder3D, test_algebra>);
0108 static_assert(concepts::cylindrical_shape<cylinder3D, test_algebra>);
0109
0110 point3 p3_in = {r, static_cast<scalar>(0.f), static_cast<scalar>(-1.f)};
0111 point3 p3_edge = {static_cast<scalar>(0.f), r, hz};
0112 point3 p3_out = {r * constant<scalar>::inv_sqrt2,
0113 r * constant<scalar>::inv_sqrt2, static_cast<scalar>(4.5f)};
0114 point3 p3_off = {1.f, 1.f, -9.f};
0115
0116 mask<cylinder3D, test_algebra> c{
0117 0u, 0.f, -constant<scalar>::pi, -hz, r, constant<scalar>::pi, hz};
0118
0119 ASSERT_NEAR(c[cylinder3D::e_min_r], 0.f, tol);
0120 ASSERT_NEAR(c[cylinder3D::e_max_r], r, tol);
0121 ASSERT_NEAR(c[cylinder3D::e_min_phi], -constant<scalar>::pi, tol);
0122 ASSERT_NEAR(c[cylinder3D::e_max_phi], constant<scalar>::pi, tol);
0123 ASSERT_NEAR(c[cylinder3D::e_min_z], -hz, tol);
0124 ASSERT_NEAR(c[cylinder3D::e_max_z], hz, tol);
0125
0126 ASSERT_TRUE(c.is_inside(p3_in));
0127 ASSERT_TRUE(c.is_inside(p3_edge));
0128 ASSERT_FALSE(c.is_inside(p3_out));
0129 ASSERT_FALSE(c.is_inside(p3_off));
0130
0131 ASSERT_TRUE(c.is_inside(p3_out, 0.6f));
0132
0133
0134 const scalar v{c.volume()};
0135 EXPECT_NEAR(v, 226.194671058f * unit<scalar>::mm3, tol);
0136 ASSERT_EQ(v, c.measure());
0137
0138
0139 constexpr scalar envelope{0.01f};
0140 const auto loc_bounds = c.local_min_bounds(envelope);
0141 ASSERT_NEAR(loc_bounds[cuboid3D::e_min_x], -(r + envelope), tol);
0142 ASSERT_NEAR(loc_bounds[cuboid3D::e_min_y], -(r + envelope), tol);
0143 ASSERT_NEAR(loc_bounds[cuboid3D::e_min_z], -(hz + envelope), tol);
0144 ASSERT_NEAR(loc_bounds[cuboid3D::e_max_x], (r + envelope), tol);
0145 ASSERT_NEAR(loc_bounds[cuboid3D::e_max_y], (r + envelope), tol);
0146 ASSERT_NEAR(loc_bounds[cuboid3D::e_max_z], (hz + envelope), tol);
0147
0148 const auto centroid = c.centroid();
0149 ASSERT_NEAR(centroid[0], 0.f, tol);
0150 ASSERT_NEAR(centroid[1], 0.f, tol);
0151 ASSERT_NEAR(centroid[2], 0.f, tol);
0152 }
0153
0154
0155 GTEST_TEST(detray_masks, cylinder3D_ratio_test) {
0156 struct mask_check {
0157 bool operator()(const point3 &p, const mask<cylinder3D, test_algebra> &cyl,
0158 const test::transform3 &trf, const scalar t) {
0159 return cyl.is_inside(trf, p, t);
0160 }
0161 };
0162
0163 constexpr mask<cylinder3D, test_algebra> cyl{
0164 0u, 1.f, -constant<scalar>::pi, 0.f, 3.f, constant<scalar>::pi, 5.f};
0165
0166 constexpr scalar t{0.f};
0167 const test::transform3 trf{};
0168 constexpr scalar size{10.f * unit<scalar>::mm};
0169 const auto n_points{static_cast<std::size_t>(std::pow(500, 3))};
0170
0171 std::vector<point3> points =
0172 test::generate_regular_points<cuboid3D>(n_points, {size});
0173
0174 scalar ratio = test::ratio_test<mask_check>(points, cyl, trf, t);
0175
0176 const scalar volume{cyl.measure()};
0177 const scalar world{size * size * size};
0178
0179 ASSERT_NEAR(ratio, volume / world, 0.001f);
0180 }