Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:21

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // Project include(s)
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 // Detray test include(s)
0017 #include "detray/test/framework/types.hpp"
0018 #include "detray/test/utils/ratio_test.hpp"
0019 
0020 // GTest include
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 /// This tests the basic functionality of a 2D cylinder
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   // Move outside point inside using a tolerance
0053   ASSERT_TRUE(c.is_inside(p2_out, 0.6f));
0054 
0055   // Check area
0056   const scalar a{c.area()};
0057   EXPECT_NEAR(a, 150.796447f * unit<scalar>::mm2, tol);
0058   ASSERT_EQ(a, c.measure());
0059 
0060   // Check bounding box
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 /// This tests the inside/outside method of the mask
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   // Make sure the test point is on the cylinder before calling the
0093   // mask(this is normally ensured by the intersector)
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 /// This tests the basic functionality of a 3D cylinder
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   // Move outside point inside using a tolerance
0131   ASSERT_TRUE(c.is_inside(p3_out, 0.6f));
0132 
0133   // Check volume
0134   const scalar v{c.volume()};
0135   EXPECT_NEAR(v, 226.194671058f * unit<scalar>::mm3, tol);
0136   ASSERT_EQ(v, c.measure());
0137 
0138   // Check bounding box
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 /// This tests the inside/outside method of the mask
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 }