File indexing completed on 2026-01-06 09:23:52
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/Definitions/Direction.hpp"
0013 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Surfaces/PlanarBounds.hpp"
0016 #include "Acts/Surfaces/PlaneSurface.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Surfaces/SurfaceBounds.hpp"
0019 #include "Acts/Utilities/BoundingBox.hpp"
0020 #include "Acts/Utilities/Helpers.hpp"
0021 #include "Acts/Visualization/IVisualization3D.hpp"
0022 #include "Acts/Visualization/PlyVisualization3D.hpp"
0023 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0024
0025 #include <array>
0026 #include <cmath>
0027 #include <fstream>
0028 #include <memory>
0029 #include <numbers>
0030 #include <utility>
0031 #include <vector>
0032
0033 using namespace Acts;
0034
0035 namespace ActsTests {
0036
0037 GeometryContext gctx = GeometryContext();
0038
0039 BOOST_AUTO_TEST_SUITE(GeometrySuite)
0040
0041 BOOST_AUTO_TEST_CASE(construction_test) {
0042 std::array<Vector3, 8> vertices{};
0043 vertices = {{{0, 0, 0},
0044 {2, 0, 0},
0045 {2, 1, 0},
0046 {0, 1, 0},
0047 {0, 0, 1},
0048 {2, 0, 1},
0049 {2, 1, 1},
0050 {0, 1, 1}}};
0051 GenericCuboidVolumeBounds cubo(vertices);
0052
0053 BOOST_CHECK(cubo.inside({0.5, 0.5, 0.5}));
0054 BOOST_CHECK(cubo.inside({1.5, 0.5, 0.5}));
0055 BOOST_CHECK(!cubo.inside({2.5, 0.5, 0.5}));
0056 BOOST_CHECK(!cubo.inside({0.5, 1.5, 0.5}));
0057 BOOST_CHECK(!cubo.inside({0.5, 0.5, 1.5}));
0058 BOOST_CHECK(!cubo.inside({-0.5, 0.5, 0.5}));
0059
0060 BOOST_CHECK(!cubo.inside({2.2, 1, 1}, 0.1));
0061 BOOST_CHECK(cubo.inside({2.2, 1, 1}, 0.21));
0062 BOOST_CHECK(cubo.inside({2.2, 1, 1}, 0.3));
0063 }
0064
0065 BOOST_AUTO_TEST_CASE(GenericCuboidBoundsOrientedSurfaces) {
0066 std::array<Vector3, 8> vertices{};
0067 vertices = {{{0, 0, 0},
0068 {2, 0, 0},
0069 {2, 1, 0},
0070 {0, 1, 0},
0071 {0, 0, 1},
0072 {2, 0, 1},
0073 {2, 1, 1},
0074 {0, 1, 1}}};
0075 GenericCuboidVolumeBounds cubo(vertices);
0076
0077 auto is_in = [](const auto& tvtx, const auto& vertices_) {
0078 for (const auto& vtx : vertices_) {
0079 if (checkCloseAbs(vtx, tvtx, 1e-9)) {
0080 return true;
0081 }
0082 }
0083 return false;
0084 };
0085
0086 auto surfaces = cubo.orientedSurfaces(Transform3::Identity());
0087 for (const auto& srf : surfaces) {
0088 auto pbounds = dynamic_cast<const PlanarBounds*>(&srf.surface->bounds());
0089 for (const auto& vtx : pbounds->vertices()) {
0090 Vector3 glob = srf.surface->localToGlobal(gctx, vtx, {});
0091
0092 BOOST_CHECK(is_in(glob, vertices));
0093 }
0094 }
0095
0096 vertices = {{{0, 0, 0},
0097 {2, 0, 0.4},
0098 {2, 1, 0.4},
0099 {0, 1, 0},
0100 {0, 0, 1},
0101 {1.8, 0, 1},
0102 {1.8, 1, 1},
0103 {0, 1, 1}}};
0104 cubo = GenericCuboidVolumeBounds(vertices);
0105
0106 surfaces = cubo.orientedSurfaces(Transform3::Identity());
0107 for (const auto& srf : surfaces) {
0108 auto pbounds = dynamic_cast<const PlanarBounds*>(&srf.surface->bounds());
0109 for (const auto& vtx : pbounds->vertices()) {
0110 Vector3 glob = srf.surface->localToGlobal(gctx, vtx, {});
0111
0112 BOOST_CHECK(is_in(glob, vertices));
0113 }
0114 }
0115
0116 Transform3 trf;
0117 trf = Translation3(Vector3(0, 8, -5)) *
0118 AngleAxis3(std::numbers::pi / 3., Vector3(1, -3, 9).normalized());
0119
0120 surfaces = cubo.orientedSurfaces(trf);
0121 for (const auto& srf : surfaces) {
0122 auto pbounds = dynamic_cast<const PlanarBounds*>(&srf.surface->bounds());
0123 for (const auto& vtx : pbounds->vertices()) {
0124 Vector3 glob = srf.surface->localToGlobal(gctx, vtx, {});
0125
0126 BOOST_CHECK(is_in(trf.inverse() * glob, vertices));
0127 }
0128 }
0129 }
0130
0131 BOOST_AUTO_TEST_CASE(ply_test) {
0132 std::array<Vector3, 8> vertices{};
0133 vertices = {{{0, 0, 0},
0134 {2, 0, 0},
0135 {2, 1, 0},
0136 {0, 1, 0},
0137 {0, 0, 1},
0138 {2, 0, 1},
0139 {2, 1, 1},
0140 {0, 1, 1}}};
0141 GenericCuboidVolumeBounds cubo(vertices);
0142 PlyVisualization3D<double> ply;
0143 cubo.draw(ply);
0144
0145 std::ofstream os("cuboid.ply");
0146 os << ply << std::flush;
0147 os.close();
0148 }
0149
0150 BOOST_AUTO_TEST_CASE(bounding_box_creation) {
0151 float tol = 1e-4;
0152 std::array<Vector3, 8> vertices{};
0153 vertices = {{{0, 0, 0},
0154 {2, 0, 0.4},
0155 {2, 1, 0.4},
0156 {0, 1, 0},
0157 {0, 0, 1},
0158 {1.8, 0, 1},
0159 {1.8, 1, 1},
0160 {0, 1, 1}}};
0161
0162 GenericCuboidVolumeBounds gcvb(vertices);
0163 auto bb = gcvb.boundingBox();
0164
0165 Transform3 rot;
0166 rot = AngleAxis3(std::numbers::pi / 2., Vector3::UnitX());
0167
0168 BOOST_CHECK_EQUAL(bb.entity(), nullptr);
0169 BOOST_CHECK_EQUAL(bb.max(), Vector3(2, 1, 1));
0170 BOOST_CHECK_EQUAL(bb.min(), Vector3(0., 0., 0.));
0171
0172 bb = gcvb.boundingBox(&rot);
0173
0174 BOOST_CHECK_EQUAL(bb.entity(), nullptr);
0175 CHECK_CLOSE_ABS(bb.max(), Vector3(2, 0, 1), tol);
0176 BOOST_CHECK_EQUAL(bb.min(), Vector3(0, -1, 0));
0177
0178 rot = AngleAxis3(std::numbers::pi / 2., Vector3::UnitZ());
0179 bb = gcvb.boundingBox(&rot);
0180 BOOST_CHECK_EQUAL(bb.entity(), nullptr);
0181 CHECK_CLOSE_ABS(bb.max(), Vector3(0, 2, 1), tol);
0182 CHECK_CLOSE_ABS(bb.min(), Vector3(-1, 0., 0.), tol);
0183
0184 rot = AngleAxis3(0.542, Vector3::UnitZ()) *
0185 AngleAxis3(std::numbers::pi / 5., Vector3(1, 3, 6).normalized());
0186
0187 bb = gcvb.boundingBox(&rot);
0188 BOOST_CHECK_EQUAL(bb.entity(), nullptr);
0189 CHECK_CLOSE_ABS(bb.max(), Vector3(1.00976, 2.26918, 1.11988), tol);
0190 CHECK_CLOSE_ABS(bb.min(), Vector3(-0.871397, 0, -0.0867708), tol);
0191
0192
0193 const auto boundValues = gcvb.values();
0194 BOOST_CHECK_EQUAL(boundValues.size(), 24u);
0195
0196 auto bValueArrray =
0197 toArray<GenericCuboidVolumeBounds::BoundValues::eSize, double>(
0198 boundValues);
0199 GenericCuboidVolumeBounds gcvbCopy(bValueArrray);
0200 BOOST_CHECK_EQUAL(gcvbCopy.values().size(), 24u);
0201
0202
0203 rot = AngleAxis3(0.542, Vector3::UnitZ()) *
0204 AngleAxis3(std::numbers::pi / 5., Vector3(1, 3, 6).normalized());
0205
0206 bb = gcvbCopy.boundingBox(&rot);
0207 BOOST_CHECK_EQUAL(bb.entity(), nullptr);
0208 CHECK_CLOSE_ABS(bb.max(), Vector3(1.00976, 2.26918, 1.11988), tol);
0209 CHECK_CLOSE_ABS(bb.min(), Vector3(-0.871397, 0, -0.0867708), tol);
0210 }
0211
0212 BOOST_AUTO_TEST_CASE(GenericCuboidVolumeBoundarySurfaces) {
0213 std::array<Vector3, 8> vertices{};
0214 vertices = {{{0, 0, 0},
0215 {4, 0, 0},
0216 {4, 2, 0},
0217 {0, 2, 0},
0218 {0, 0, 2},
0219 {4, 0, 2},
0220 {4, 2, 2},
0221 {0, 2, 2}}};
0222
0223 GenericCuboidVolumeBounds cubo(vertices);
0224
0225 auto gcvbOrientedSurfaces = cubo.orientedSurfaces(Transform3::Identity());
0226 BOOST_CHECK_EQUAL(gcvbOrientedSurfaces.size(), 6);
0227
0228 for (auto& os : gcvbOrientedSurfaces) {
0229 auto geoCtx = GeometryContext();
0230 auto osCenter = os.surface->center(geoCtx);
0231 const auto* pSurface = dynamic_cast<const PlaneSurface*>(os.surface.get());
0232 BOOST_REQUIRE_MESSAGE(pSurface != nullptr,
0233 "The surface is not a plane surface");
0234 auto osNormal = pSurface->normal(geoCtx);
0235
0236 Vector3 insideGcvb = osCenter + os.direction * osNormal;
0237 Vector3 outsideGcvb = osCenter - os.direction * osNormal;
0238 BOOST_CHECK(cubo.inside(insideGcvb));
0239 BOOST_CHECK(!cubo.inside(outsideGcvb));
0240 }
0241 }
0242
0243 BOOST_AUTO_TEST_SUITE_END()
0244 }