File indexing completed on 2025-10-13 08:19:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Surfaces/CylinderSurface.hpp"
0014 #include "Acts/Surfaces/PlanarBounds.hpp"
0015 #include "Acts/Surfaces/PlaneSurface.hpp"
0016 #include "Acts/Surfaces/RectangleBounds.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Surfaces/SurfaceArray.hpp"
0019 #include "Acts/Utilities/Axis.hpp"
0020 #include "Acts/Utilities/AxisDefinitions.hpp"
0021 #include "Acts/Utilities/Helpers.hpp"
0022
0023 #include <cmath>
0024 #include <cstddef>
0025 #include <fstream>
0026 #include <iomanip>
0027 #include <iostream>
0028 #include <memory>
0029 #include <numbers>
0030 #include <string>
0031 #include <tuple>
0032 #include <utility>
0033 #include <vector>
0034
0035 #include <boost/format.hpp>
0036
0037 using Acts::VectorHelpers::phi;
0038
0039 using namespace Acts;
0040
0041 namespace ActsTests {
0042
0043
0044 GeometryContext tgContext = GeometryContext();
0045
0046 using SrfVec = std::vector<std::shared_ptr<const Surface>>;
0047 struct SurfaceArrayFixture {
0048 std::vector<std::shared_ptr<const Surface>> m_surfaces;
0049
0050 SurfaceArrayFixture() { BOOST_TEST_MESSAGE("setup fixture"); }
0051 ~SurfaceArrayFixture() { BOOST_TEST_MESSAGE("teardown fixture"); }
0052
0053 SrfVec fullPhiTestSurfacesEC(std::size_t n = 10, double shift = 0,
0054 double zbase = 0, double r = 10) {
0055 SrfVec res;
0056
0057 double phiStep = 2 * std::numbers::pi / n;
0058 for (std::size_t i = 0; i < n; ++i) {
0059 double z = zbase + ((i % 2 == 0) ? 1 : -1) * 0.2;
0060
0061 Transform3 trans;
0062 trans.setIdentity();
0063 trans.rotate(Eigen::AngleAxisd(i * phiStep + shift, Vector3(0, 0, 1)));
0064 trans.translate(Vector3(r, 0, z));
0065
0066 auto bounds = std::make_shared<const RectangleBounds>(2, 1);
0067 std::shared_ptr<const Surface> srf =
0068 Surface::makeShared<PlaneSurface>(trans, bounds);
0069
0070 res.push_back(srf);
0071 m_surfaces.push_back(
0072 std::move(srf));
0073 }
0074
0075 return res;
0076 }
0077
0078 SrfVec fullPhiTestSurfacesBRL(int n = 10, double shift = 0, double zbase = 0,
0079 double incl = std::numbers::pi / 9.,
0080 double w = 2, double h = 1.5) {
0081 SrfVec res;
0082
0083 double phiStep = 2 * std::numbers::pi / n;
0084 for (int i = 0; i < n; ++i) {
0085 double z = zbase;
0086
0087 Transform3 trans;
0088 trans.setIdentity();
0089 trans.rotate(Eigen::AngleAxisd(i * phiStep + shift, Vector3(0, 0, 1)));
0090 trans.translate(Vector3(10, 0, z));
0091 trans.rotate(Eigen::AngleAxisd(incl, Vector3(0, 0, 1)));
0092 trans.rotate(Eigen::AngleAxisd(std::numbers::pi / 2., Vector3(0, 1, 0)));
0093
0094 auto bounds = std::make_shared<const RectangleBounds>(w, h);
0095 std::shared_ptr<const Surface> srf =
0096 Surface::makeShared<PlaneSurface>(trans, bounds);
0097
0098 res.push_back(srf);
0099 m_surfaces.push_back(
0100 std::move(srf));
0101 }
0102
0103 return res;
0104 }
0105
0106 SrfVec straightLineSurfaces(
0107 std::size_t n = 10., double step = 3, const Vector3& origin = {0, 0, 1.5},
0108 const Transform3& pretrans = Transform3::Identity(),
0109 const Vector3& dir = {0, 0, 1}) {
0110 SrfVec res;
0111 for (std::size_t i = 0; i < n; ++i) {
0112 Transform3 trans;
0113 trans.setIdentity();
0114 trans.translate(origin + dir * step * i);
0115
0116 trans.rotate(AngleAxis3(std::numbers::pi / 2., Vector3(1, 0, 0)));
0117 trans = trans * pretrans;
0118
0119 auto bounds = std::make_shared<const RectangleBounds>(2, 1.5);
0120
0121 std::shared_ptr<const Surface> srf =
0122 Surface::makeShared<PlaneSurface>(trans, bounds);
0123
0124 res.push_back(srf);
0125 m_surfaces.push_back(
0126 std::move(srf));
0127 }
0128
0129 return res;
0130 }
0131
0132 SrfVec makeBarrel(int nPhi, int nZ, double w, double h) {
0133 double z0 = -(nZ - 1) * w;
0134 SrfVec res;
0135
0136 for (int i = 0; i < nZ; i++) {
0137 double z = i * w * 2 + z0;
0138 SrfVec ring =
0139 fullPhiTestSurfacesBRL(nPhi, 0, z, std::numbers::pi / 9., w, h);
0140 res.insert(res.end(), ring.begin(), ring.end());
0141 }
0142
0143 return res;
0144 }
0145
0146 void draw_surfaces(const SrfVec& surfaces, const std::string& fname) {
0147 std::ofstream os;
0148 os.open(fname);
0149
0150 os << std::fixed << std::setprecision(4);
0151
0152 std::size_t nVtx = 0;
0153 for (const auto& srfx : surfaces) {
0154 std::shared_ptr<const PlaneSurface> srf =
0155 std::dynamic_pointer_cast<const PlaneSurface>(srfx);
0156 const PlanarBounds* bounds =
0157 dynamic_cast<const PlanarBounds*>(&srf->bounds());
0158
0159 for (const auto& vtxloc : bounds->vertices()) {
0160 Vector3 vtx =
0161 srf->transform(tgContext) * Vector3(vtxloc.x(), vtxloc.y(), 0);
0162 os << "v " << vtx.x() << " " << vtx.y() << " " << vtx.z() << "\n";
0163 }
0164
0165
0166 os << "f";
0167 for (std::size_t i = 1; i <= bounds->vertices().size(); ++i) {
0168 os << " " << nVtx + i;
0169 }
0170 os << "\n";
0171
0172 nVtx += bounds->vertices().size();
0173 }
0174
0175 os.close();
0176 }
0177 };
0178
0179 BOOST_AUTO_TEST_SUITE(SurfacesSuite)
0180
0181 BOOST_FIXTURE_TEST_CASE(SurfaceArray_create, SurfaceArrayFixture) {
0182 GeometryContext tgContext = GeometryContext();
0183
0184 SrfVec brl = makeBarrel(30, 7, 2, 1);
0185 std::vector<const Surface*> brlRaw = unpackSmartPointers(brl);
0186 draw_surfaces(brl, "SurfaceArray_create_BRL_1.obj");
0187
0188 Axis<AxisType::Equidistant, AxisBoundaryType::Closed> phiAxis(
0189 -std::numbers::pi, std::numbers::pi, 30u);
0190 Axis<AxisType::Equidistant, AxisBoundaryType::Bound> zAxis(-14, 14, 7u);
0191
0192 double R = 10;
0193 auto itransform = [R](const Vector2& loc) {
0194 return Vector3(R * std::cos(loc[0]), R * std::sin(loc[0]), loc[1]);
0195 };
0196
0197 auto cylinder =
0198 Surface::makeShared<CylinderSurface>(Transform3::Identity(), R, 10);
0199 auto sl = std::make_unique<
0200 SurfaceArray::SurfaceGridLookup<decltype(phiAxis), decltype(zAxis)>>(
0201 cylinder, 1, std::make_tuple(std::move(phiAxis), std::move(zAxis)));
0202 sl->fill(tgContext, brlRaw);
0203 SurfaceArray sa(std::move(sl), brl);
0204
0205
0206 sa.toStream(tgContext, std::cout);
0207
0208 for (const auto& srf : brl) {
0209 Vector3 ctr = srf->referencePosition(tgContext, AxisDirection::AxisR);
0210 Vector3 normal = srf->normal(tgContext, ctr, Vector3::UnitZ());
0211 std::vector<const Surface*> binContent = sa.at(ctr, normal);
0212
0213 BOOST_CHECK(binContent.size() <= 2u);
0214 }
0215
0216 std::vector<const Surface*> neighbors = sa.neighbors(
0217 itransform(Vector2(0, 0)), itransform(Vector2(0, 0)).normalized());
0218 BOOST_CHECK_EQUAL(neighbors.size(), 6u);
0219 }
0220
0221 BOOST_AUTO_TEST_CASE(SurfaceArray_singleElement) {
0222 const double w = 3;
0223 const double h = 4;
0224 auto bounds = std::make_shared<const RectangleBounds>(w, h);
0225 auto srf = Surface::makeShared<PlaneSurface>(Transform3::Identity(), bounds);
0226
0227 SurfaceArray sa(srf);
0228
0229 auto binContent = sa.at(Vector3(42, 42, 42), Vector3::UnitX());
0230 BOOST_CHECK_EQUAL(binContent.size(), 1u);
0231 BOOST_CHECK_EQUAL(binContent.at(0), srf.get());
0232 BOOST_CHECK_EQUAL(sa.surfaces().size(), 1u);
0233 BOOST_CHECK_EQUAL(sa.surfaces().at(0), srf.get());
0234 }
0235
0236 BOOST_AUTO_TEST_CASE(SurfaceArray_manyElementsSingleLookup) {
0237 const double w = 3;
0238 const double h = 4;
0239 auto bounds = std::make_shared<const RectangleBounds>(w, h);
0240 auto srf0 = Surface::makeShared<PlaneSurface>(Transform3::Identity(), bounds);
0241 auto srf1 = Surface::makeShared<PlaneSurface>(Transform3::Identity(), bounds);
0242
0243 std::vector<const Surface*> sfPointers = {srf0.get(), srf1.get()};
0244 std::vector<std::shared_ptr<const Surface>> surfaces = {srf0, srf1};
0245
0246 auto singleLookUp =
0247 std::make_unique<Acts::SurfaceArray::SingleElementLookup>(sfPointers);
0248
0249 SurfaceArray sa(std::move(singleLookUp), surfaces);
0250
0251 auto binContent = sa.at(Vector3(42, 42, 42), Vector3::UnitX());
0252 BOOST_CHECK_EQUAL(binContent.size(), 2u);
0253 BOOST_CHECK_EQUAL(sa.surfaces().size(), 2u);
0254 }
0255
0256 BOOST_AUTO_TEST_SUITE_END()
0257
0258 }