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