ECCE @ EIC 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 
16 
17 #include <array>
18 #include <ostream>
19 
20 #include "Acts/Geometry/Volume.hpp"
22 
24  const std::array<Acts::Vector3D, 8>& vertices) noexcept(false)
25  : m_vertices(vertices) {
26  construct();
27 }
28 
30  const std::array<double, GenericCuboidVolumeBounds::eSize>&
31  values) noexcept(false)
32  : m_vertices() {
33  for (size_t iv = 0; iv < 8; ++iv) {
34  m_vertices[iv] =
35  Vector3D(values[iv * 3], values[iv * 3 + 1], values[iv * 3 + 2]);
36  }
37  construct();
38 }
39 
41  double tol) const {
42  constexpr std::array<size_t, 6> vtxs = {0, 4, 0, 1, 2, 1};
43  // needs to be on same side, get ref
44  bool ref = std::signbit((gpos - m_vertices[vtxs[0]]).dot(m_normals[0]));
45  for (size_t i = 1; i < 6; i++) {
46  double dot = (gpos - m_vertices[vtxs[i]]).dot(m_normals[i]);
47  if (std::signbit(dot) != ref) {
48  // technically outside, but how far?
49  if (std::abs(dot) > tol) {
50  // distance greater than tol
51  return false;
52  }
53  // distance smaller than tol, ignore
54  }
55  }
56  return true;
57 }
58 
59 std::vector<std::shared_ptr<const Acts::Surface>>
61  const Acts::Transform3D* transform) const {
62  std::vector<std::shared_ptr<const Acts::Surface>> surfaces;
63 
64  // approximate cog of the volume
65  Vector3D cog(0, 0, 0);
66 
67  for (size_t i = 0; i < 8; i++) {
68  cog += m_vertices[i];
69  }
70 
71  cog *= 0.125; // 1/8.
72 
73  auto make_surface = [&](const auto& a, const auto& b, const auto& c,
74  const auto& d) {
75  // calculate centroid of these points
76  Vector3D ctrd = (a + b + c + d) / 4.;
77  // create normal
78  const Vector3D ab = b - a, ac = c - a;
79  Vector3D normal = ab.cross(ac).normalized();
80 
81  if ((cog - d).dot(normal) > 0) {
82  // normal points inwards, flip normal
83  normal *= -1.;
84  }
85  // get rid of -0 values if present
86  normal += Vector3D::Zero();
87 
88  // normal should point away from volume center now
89 
90  // build transform from z unit to normal
91  // z is normal in local coordinates
92  // Volume local to surface local
93  Transform3D vol2srf;
94  vol2srf = (Eigen::Quaternion<double>().setFromTwoVectors(
95  normal, Vector3D::UnitZ()));
96 
97  vol2srf = vol2srf * Translation3D(-ctrd);
98 
99  // now calculate position of vertices in surface local frame
100  Vector3D a_l, b_l, c_l, d_l;
101  a_l = vol2srf * a;
102  b_l = vol2srf * b;
103  c_l = vol2srf * c;
104  d_l = vol2srf * d;
105 
106  std::vector<Vector2D> vertices({{a_l.x(), a_l.y()},
107  {b_l.x(), b_l.y()},
108  {c_l.x(), c_l.y()},
109  {d_l.x(), d_l.y()}});
110 
111  auto polyBounds = std::make_shared<const ConvexPolygonBounds<4>>(vertices);
112 
113  auto srfTrf = std::make_shared<Transform3D>(vol2srf.inverse());
114  if (transform != nullptr) {
115  *srfTrf = (*transform) * (*srfTrf);
116  }
117 
118  auto srf = Surface::makeShared<PlaneSurface>(std::move(srfTrf), polyBounds);
119 
120  surfaces.push_back(std::move(srf));
121  };
122 
123  make_surface(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
124  make_surface(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
125  make_surface(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
126  make_surface(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
127  make_surface(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
128  make_surface(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
129 
130  return surfaces;
131 }
132 
134  std::ostream& sl) const {
135  sl << "Acts::GenericCuboidVolumeBounds: vertices (x, y, z) =\n";
136  for (size_t i = 0; i < 8; i++) {
137  if (i > 0) {
138  sl << ",\n";
139  }
140  sl << "[" << m_vertices[i].transpose() << "]";
141  }
142  return sl;
143 }
144 
146  // calculate approximate center of gravity first, so we can make sure
147  // the normals point inwards
148  Vector3D cog(0, 0, 0);
149 
150  for (size_t i = 0; i < 8; i++) {
151  cog += m_vertices[i];
152  }
153 
154  cog *= 0.125; // 1/8.
155 
156  size_t idx = 0;
157 
158  auto handle_face = [&](const auto& a, const auto& b, const auto& c,
159  const auto& d) {
160  // we assume a b c d to be counter clockwise
161  const Vector3D ab = b - a, ac = c - a;
162  Vector3D normal = ab.cross(ac).normalized();
163 
164  if ((cog - a).dot(normal) < 0) {
165  // normal points outwards, flip normal
166  normal *= -1.;
167  }
168 
169  // get rid of -0 values if present
170  normal += Vector3D::Zero();
171 
172  // check if d is on the surface
173  if (std::abs((a - d).dot(normal)) > 1e-6) {
174  throw(std::invalid_argument(
175  "GenericCuboidBounds: Four points do not lie on the same plane!"));
176  }
177 
178  m_normals[idx] = normal;
179  idx++;
180  };
181 
182  // handle faces
183  handle_face(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
184  handle_face(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
185  handle_face(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
186  handle_face(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
187  handle_face(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
188  handle_face(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
189 }
190 
191 std::vector<double> Acts::GenericCuboidVolumeBounds::values() const {
192  std::vector<double> rvalues;
193  rvalues.reserve(eSize);
194  for (size_t iv = 0; iv < 8; ++iv) {
195  for (size_t ic = 0; ic < 3; ++ic) {
196  rvalues.push_back(m_vertices[iv][ic]);
197  }
198  }
199  return rvalues;
200 }
201 
203  const Acts::Transform3D* trf, const Vector3D& envelope,
204  const Volume* entity) const {
205  Vector3D vmin, vmax;
206 
207  Transform3D transform = Transform3D::Identity();
208  if (trf != nullptr) {
209  transform = *trf;
210  }
211 
212  vmin = transform * m_vertices[0];
213  vmax = transform * m_vertices[0];
214 
215  for (size_t i = 1; i < 8; i++) {
216  Vector3D vtx = transform * m_vertices[i];
217  vmin = vmin.cwiseMin(vtx);
218  vmax = vmax.cwiseMax(vtx);
219  }
220 
221  return {entity, vmin - envelope, vmax + envelope};
222 }
223 
225  const Transform3D& transform) const {
226  auto draw_face = [&](const auto& a, const auto& b, const auto& c,
227  const auto& d) {
228  helper.face(std::vector<Vector3D>(
229  {transform * a, transform * b, transform * c, transform * d}));
230  };
231 
232  draw_face(m_vertices[0], m_vertices[1], m_vertices[2], m_vertices[3]);
233  draw_face(m_vertices[4], m_vertices[5], m_vertices[6], m_vertices[7]);
234  draw_face(m_vertices[0], m_vertices[3], m_vertices[7], m_vertices[4]);
235  draw_face(m_vertices[1], m_vertices[2], m_vertices[6], m_vertices[5]);
236  draw_face(m_vertices[2], m_vertices[3], m_vertices[7], m_vertices[6]);
237  draw_face(m_vertices[1], m_vertices[0], m_vertices[4], m_vertices[5]);
238 }