Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GenericCuboidVolumeBounds.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GenericCuboidVolumeBounds.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
13 #include "Acts/Geometry/Volume.hpp"
19 
20 #include <algorithm>
21 #include <array>
22 #include <cmath>
23 #include <cstddef>
24 #include <memory>
25 #include <ostream>
26 #include <stdexcept>
27 #include <type_traits>
28 #include <utility>
29 
31  const std::array<Acts::Vector3, 8>& vertices) noexcept(false)
32  : m_vertices(vertices) {
33  construct();
34 }
35 
37  const std::array<double, GenericCuboidVolumeBounds::BoundValues::eSize>&
38  values) noexcept(false)
39  : m_vertices() {
40  for (size_t iv = 0; iv < 8; ++iv) {
41  m_vertices[iv] =
42  Vector3(values[iv * 3], values[iv * 3 + 1], values[iv * 3 + 2]);
43  }
44  construct();
45 }
46 
48  double tol) const {
49  constexpr std::array<size_t, 6> vtxs = {0, 4, 0, 1, 2, 1};
50  // needs to be on same side, get ref
51  bool ref = std::signbit((gpos - m_vertices[vtxs[0]]).dot(m_normals[0]));
52  for (size_t i = 1; i < 6; i++) {
53  double dot = (gpos - m_vertices[vtxs[i]]).dot(m_normals[i]);
54  if (std::signbit(dot) != ref) {
55  // technically outside, but how far?
56  if (std::abs(dot) > tol) {
57  // distance greater than tol
58  return false;
59  }
60  // distance smaller than tol, ignore
61  }
62  }
63  return true;
64 }
65 
67  const Transform3& transform) const {
68  OrientedSurfaces oSurfaces;
69 
70  // approximate cog of the volume
71  Vector3 cog(0, 0, 0);
72 
73  for (size_t i = 0; i < 8; i++) {
74  cog += m_vertices[i];
75  }
76 
77  cog *= 0.125; // 1/8.
78 
79  auto make_surface = [&](const auto& a, const auto& b, const auto& c,
80  const auto& d) -> void {
81  // calculate centroid of these points
82  Vector3 ctrd = (a + b + c + d) / 4.;
83  // create normal
84  const Vector3 ab = b - a, ac = c - a;
85  Vector3 normal = ab.cross(ac).normalized();
86 
87  Direction dir = Direction::fromScalar((cog - d).dot(normal));
88 
89  // build transform from z unit to normal
90  // z is normal in local coordinates
91  // Volume local to surface local
92  Transform3 vol2srf;
93 
94  // GCC13+ Complains about maybe uninitialized memory inside Eigen's SVD code
95  // This warning is ignored in this compilation unit by using the pragma at
96  // the top of this file.
97  vol2srf = (Eigen::Quaternion<Transform3::Scalar>().setFromTwoVectors(
98  normal, Vector3::UnitZ()));
99 
100  vol2srf = vol2srf * Translation3(-ctrd);
101 
102  // now calculate position of vertices in surface local frame
103  Vector3 a_l, b_l, c_l, d_l;
104  a_l = vol2srf * a;
105  b_l = vol2srf * b;
106  c_l = vol2srf * c;
107  d_l = vol2srf * d;
108 
109  std::vector<Vector2> vertices({{a_l.x(), a_l.y()},
110  {b_l.x(), b_l.y()},
111  {c_l.x(), c_l.y()},
112  {d_l.x(), d_l.y()}});
113 
114  auto polyBounds = std::make_shared<const ConvexPolygonBounds<4>>(vertices);
115  auto srfTrf = transform * vol2srf.inverse();
116  auto srf = Surface::makeShared<PlaneSurface>(srfTrf, polyBounds);
117 
118  oSurfaces.push_back(OrientedSurface(std::move(srf), dir));
119  };
120 
121  make_surface(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
122  make_surface(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
123  make_surface(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
124  make_surface(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
125  make_surface(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
126  make_surface(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
127 
128  return oSurfaces;
129 }
130 
132  std::ostream& sl) const {
133  sl << "Acts::GenericCuboidVolumeBounds: vertices (x, y, z) =\n";
134  for (size_t i = 0; i < 8; i++) {
135  if (i > 0) {
136  sl << ",\n";
137  }
138  sl << "[" << m_vertices[i].transpose() << "]";
139  }
140  return sl;
141 }
142 
144  // calculate approximate center of gravity first, so we can make sure
145  // the normals point inwards
146  Vector3 cog(0, 0, 0);
147 
148  for (size_t i = 0; i < 8; i++) {
149  cog += m_vertices[i];
150  }
151 
152  cog *= 0.125; // 1/8.
153 
154  size_t idx = 0;
155 
156  auto handle_face = [&](const auto& a, const auto& b, const auto& c,
157  const auto& d) {
158  // we assume a b c d to be counter clockwise
159  const Vector3 ab = b - a, ac = c - a;
160  Vector3 normal = ab.cross(ac).normalized();
161 
162  if ((cog - a).dot(normal) < 0) {
163  // normal points outwards, flip normal
164  normal *= -1.;
165  }
166 
167  // get rid of -0 values if present
168  normal += Vector3::Zero();
169 
170  // check if d is on the surface
171  if (std::abs((a - d).dot(normal)) > 1e-6) {
172  throw(std::invalid_argument(
173  "GenericCuboidBounds: Four points do not lie on the same plane!"));
174  }
175 
176  m_normals[idx] = normal;
177  idx++;
178  };
179 
180  // handle faces
181  handle_face(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
182  handle_face(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
183  handle_face(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
184  handle_face(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
185  handle_face(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
186  handle_face(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
187 }
188 
189 std::vector<double> Acts::GenericCuboidVolumeBounds::values() const {
190  std::vector<double> rvalues;
191  rvalues.reserve(BoundValues::eSize);
192  for (size_t iv = 0; iv < 8; ++iv) {
193  for (size_t ic = 0; ic < 3; ++ic) {
194  rvalues.push_back(m_vertices[iv][ic]);
195  }
196  }
197  return rvalues;
198 }
199 
201  const Acts::Transform3* trf, const Vector3& envelope,
202  const Volume* entity) const {
203  Vector3 vmin, vmax;
204 
205  Transform3 transform = Transform3::Identity();
206  if (trf != nullptr) {
207  transform = *trf;
208  }
209 
210  vmin = transform * m_vertices[0];
211  vmax = transform * m_vertices[0];
212 
213  for (size_t i = 1; i < 8; i++) {
214  Vector3 vtx = transform * m_vertices[i];
215  vmin = vmin.cwiseMin(vtx);
216  vmax = vmax.cwiseMax(vtx);
217  }
218 
219  return {entity, vmin - envelope, vmax + envelope};
220 }
221 
223  const Transform3& transform) const {
224  auto draw_face = [&](const auto& a, const auto& b, const auto& c,
225  const auto& d) {
226  helper.face(std::vector<Vector3>(
227  {transform * a, transform * b, transform * c, transform * d}));
228  };
229 
230  draw_face(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
231  draw_face(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
232  draw_face(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
233  draw_face(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
234  draw_face(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
235  draw_face(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
236 }