File indexing completed on 2025-07-11 07:50:10
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Direction.hpp"
0013 #include "Acts/Geometry/Volume.hpp"
0014 #include "Acts/Surfaces/ConvexPolygonBounds.hpp"
0015 #include "Acts/Surfaces/PlaneSurface.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "Acts/Utilities/BoundingBox.hpp"
0018 #include "Acts/Visualization/IVisualization3D.hpp"
0019
0020 #include <array>
0021 #include <cmath>
0022 #include <cstddef>
0023 #include <memory>
0024 #include <ostream>
0025 #include <stdexcept>
0026 #include <utility>
0027
0028 namespace Acts {
0029
0030 GenericCuboidVolumeBounds::GenericCuboidVolumeBounds(
0031 const std::array<Vector3, 8>& vertices) noexcept(false)
0032 : m_vertices(vertices) {
0033 construct();
0034 }
0035
0036 GenericCuboidVolumeBounds::GenericCuboidVolumeBounds(
0037 const std::array<double, GenericCuboidVolumeBounds::BoundValues::eSize>&
0038 values) noexcept(false)
0039 : m_vertices() {
0040 for (std::size_t iv = 0; iv < 8; ++iv) {
0041 m_vertices[iv] =
0042 Vector3(values[iv * 3], values[iv * 3 + 1], values[iv * 3 + 2]);
0043 }
0044 construct();
0045 }
0046
0047 bool GenericCuboidVolumeBounds::inside(const Vector3& gpos, double tol) const {
0048 constexpr std::array<std::size_t, 6> vtxs = {0, 4, 0, 1, 2, 1};
0049
0050 bool ref = std::signbit((gpos - m_vertices[vtxs[0]]).dot(m_normals[0]));
0051 for (std::size_t i = 1; i < 6; i++) {
0052 double dot = (gpos - m_vertices[vtxs[i]]).dot(m_normals[i]);
0053 if (std::signbit(dot) != ref) {
0054
0055 if (std::abs(dot) > tol) {
0056
0057 return false;
0058 }
0059
0060 }
0061 }
0062 return true;
0063 }
0064
0065 std::vector<OrientedSurface> GenericCuboidVolumeBounds::orientedSurfaces(
0066 const Transform3& transform) const {
0067 std::vector<OrientedSurface> oSurfaces;
0068
0069
0070 Vector3 cog(0, 0, 0);
0071
0072 for (std::size_t i = 0; i < 8; i++) {
0073 cog += m_vertices[i];
0074 }
0075
0076 cog *= 0.125;
0077
0078 auto make_surface = [&](const auto& a, const auto& b, const auto& c,
0079 const auto& d) -> void {
0080
0081 Vector3 ctrd = (a + b + c + d) / 4.;
0082
0083 const Vector3 ab = b - a, ac = c - a;
0084 Vector3 normal = ab.cross(ac).normalized();
0085
0086 Direction dir = Direction::fromScalar((cog - d).dot(normal));
0087
0088
0089
0090
0091 Transform3 vol2srf;
0092
0093
0094
0095
0096 vol2srf = (Eigen::Quaternion<Transform3::Scalar>().setFromTwoVectors(
0097 normal, Vector3::UnitZ()));
0098
0099 vol2srf = vol2srf * Translation3(-ctrd);
0100
0101
0102 Vector3 a_l, b_l, c_l, d_l;
0103 a_l = vol2srf * a;
0104 b_l = vol2srf * b;
0105 c_l = vol2srf * c;
0106 d_l = vol2srf * d;
0107
0108 std::vector<Vector2> vertices({{a_l.x(), a_l.y()},
0109 {b_l.x(), b_l.y()},
0110 {c_l.x(), c_l.y()},
0111 {d_l.x(), d_l.y()}});
0112
0113 auto polyBounds = std::make_shared<const ConvexPolygonBounds<4>>(vertices);
0114 auto srfTrf = transform * vol2srf.inverse();
0115 auto srf = Surface::makeShared<PlaneSurface>(srfTrf, polyBounds);
0116
0117 oSurfaces.push_back(OrientedSurface{std::move(srf), dir});
0118 };
0119
0120 make_surface(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
0121 make_surface(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
0122 make_surface(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
0123 make_surface(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
0124 make_surface(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
0125 make_surface(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
0126
0127 return oSurfaces;
0128 }
0129
0130 std::ostream& GenericCuboidVolumeBounds::toStream(std::ostream& sl) const {
0131 sl << "GenericCuboidVolumeBounds: vertices (x, y, z) =\n";
0132 for (std::size_t i = 0; i < 8; i++) {
0133 if (i > 0) {
0134 sl << ",\n";
0135 }
0136 sl << "[" << m_vertices[i].transpose() << "]";
0137 }
0138 return sl;
0139 }
0140
0141 void GenericCuboidVolumeBounds::construct() noexcept(false) {
0142
0143
0144 Vector3 cog(0, 0, 0);
0145
0146 for (std::size_t i = 0; i < 8; i++) {
0147 cog += m_vertices[i];
0148 }
0149
0150 cog *= 0.125;
0151
0152 std::size_t idx = 0;
0153
0154 auto handle_face = [&](const auto& a, const auto& b, const auto& c,
0155 const auto& d) {
0156
0157 const Vector3 ab = b - a, ac = c - a;
0158 Vector3 normal = ab.cross(ac).normalized();
0159
0160 if ((cog - a).dot(normal) < 0) {
0161
0162 normal *= -1.;
0163 }
0164
0165
0166 normal += Vector3::Zero();
0167
0168
0169 if (std::abs((a - d).dot(normal)) > 1e-6) {
0170 throw(std::invalid_argument(
0171 "GenericCuboidBounds: Four points do not lie on the same plane!"));
0172 }
0173
0174 m_normals[idx] = normal;
0175 idx++;
0176 };
0177
0178
0179 handle_face(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
0180 handle_face(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
0181 handle_face(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
0182 handle_face(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
0183 handle_face(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
0184 handle_face(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
0185 }
0186
0187 std::vector<double> GenericCuboidVolumeBounds::values() const {
0188 std::vector<double> rvalues;
0189 rvalues.reserve(BoundValues::eSize);
0190 for (std::size_t iv = 0; iv < 8; ++iv) {
0191 for (std::size_t ic = 0; ic < 3; ++ic) {
0192 rvalues.push_back(m_vertices[iv][ic]);
0193 }
0194 }
0195 return rvalues;
0196 }
0197
0198 Volume::BoundingBox GenericCuboidVolumeBounds::boundingBox(
0199 const Transform3* trf, const Vector3& envelope,
0200 const Volume* entity) const {
0201 Vector3 vmin, vmax;
0202
0203 Transform3 transform = Transform3::Identity();
0204 if (trf != nullptr) {
0205 transform = *trf;
0206 }
0207
0208 vmin = transform * m_vertices[0];
0209 vmax = transform * m_vertices[0];
0210
0211 for (std::size_t i = 1; i < 8; i++) {
0212 Vector3 vtx = transform * m_vertices[i];
0213 vmin = vmin.cwiseMin(vtx);
0214 vmax = vmax.cwiseMax(vtx);
0215 }
0216
0217 return {entity, vmin - envelope, vmax + envelope};
0218 }
0219
0220 void GenericCuboidVolumeBounds::draw(IVisualization3D& helper,
0221 const Transform3& transform) const {
0222 auto draw_face = [&](const auto& a, const auto& b, const auto& c,
0223 const auto& d) {
0224 helper.face(std::vector<Vector3>(
0225 {transform * a, transform * b, transform * c, transform * d}));
0226 };
0227
0228 draw_face(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
0229 draw_face(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
0230 draw_face(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
0231 draw_face(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
0232 draw_face(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
0233 draw_face(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
0234 }
0235
0236 }