Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylinderVolumeBounds.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylinderVolumeBounds.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2020 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 
21 
22 #include <cmath>
23 #include <type_traits>
24 #include <utility>
25 
27  const CylinderBounds& cBounds, double thickness) noexcept(false)
28  : VolumeBounds() {
29  double cR = cBounds.get(CylinderBounds::eR);
30  if (thickness <= 0. or (cR - 0.5 * thickness) < 0.) {
31  throw(std::invalid_argument(
32  "CylinderVolumeBounds: invalid extrusion thickness."));
33  }
34  m_values[eMinR] = cR - 0.5 * thickness;
35  m_values[eMaxR] = cR + 0.5 * thickness;
36  m_values[eHalfLengthZ] = cBounds.get(CylinderBounds::eHalfLengthZ);
37  m_values[eHalfPhiSector] = cBounds.get(CylinderBounds::eHalfPhiSector);
38  m_values[eAveragePhi] = cBounds.get(CylinderBounds::eAveragePhi);
39  m_values[eBevelMinZ] = cBounds.get(CylinderBounds::eBevelMinZ);
40  m_values[eBevelMaxZ] = cBounds.get(CylinderBounds::eBevelMaxZ);
42 }
43 
45  const RadialBounds& rBounds, double thickness) noexcept(false)
46  : VolumeBounds() {
47  if (thickness <= 0.) {
48  throw(std::invalid_argument(
49  "CylinderVolumeBounds: invalid extrusion thickness."));
50  }
51  m_values[eMinR] = rBounds.get(RadialBounds::eMinR);
52  m_values[eMaxR] = rBounds.get(RadialBounds::eMaxR);
53  m_values[eHalfLengthZ] = 0.5 * thickness;
54  m_values[eHalfPhiSector] = rBounds.get(RadialBounds::eHalfPhiSector);
55  m_values[eAveragePhi] = rBounds.get(RadialBounds::eAveragePhi);
56  m_values[eBevelMinZ] = (double)0.;
57  m_values[eBevelMaxZ] = (double)0.;
59 }
60 
62  const Transform3& transform) const {
63  OrientedSurfaces oSurfaces;
64  oSurfaces.reserve(6);
65 
66  Translation3 vMinZ(0., 0., -get(eHalfLengthZ));
67  Translation3 vMaxZ(0., 0., get(eHalfLengthZ));
68  // Set up transform for beveled edges if they are defined
69  double bevelMinZ = get(eBevelMinZ);
70  double bevelMaxZ = get(eBevelMaxZ);
71  Transform3 transMinZ, transMaxZ;
72  if (bevelMinZ != 0.) {
73  double sy = 1 - 1 / std::cos(bevelMinZ);
74  transMinZ = transform * vMinZ *
75  Eigen::AngleAxisd(-bevelMinZ, Eigen::Vector3d(1., 0., 0.)) *
76  Eigen::Scaling(1., 1. + sy, 1.);
77  } else {
78  transMinZ = transform * vMinZ;
79  }
80  if (bevelMaxZ != 0.) {
81  double sy = 1 - 1 / std::cos(bevelMaxZ);
82  transMaxZ = transform * vMaxZ *
83  Eigen::AngleAxisd(bevelMaxZ, Eigen::Vector3d(1., 0., 0.)) *
84  Eigen::Scaling(1., 1. + sy, 1.);
85  } else {
86  transMaxZ = transform * vMaxZ;
87  }
88  // [0] Bottom Disc (negative z)
89  auto dSurface = Surface::makeShared<DiscSurface>(transMinZ, m_discBounds);
90  oSurfaces.push_back(
92  // [1] Top Disc (positive z)
93  dSurface = Surface::makeShared<DiscSurface>(transMaxZ, m_discBounds);
94  oSurfaces.push_back(
96 
97  // [2] Outer Cylinder
98  auto cSurface =
99  Surface::makeShared<CylinderSurface>(transform, m_outerCylinderBounds);
100  oSurfaces.push_back(
102 
103  // [3] Inner Cylinder (optional)
104  if (m_innerCylinderBounds != nullptr) {
105  cSurface =
106  Surface::makeShared<CylinderSurface>(transform, m_innerCylinderBounds);
107  oSurfaces.push_back(
109  }
110 
111  // [4] & [5] - Sectoral planes (optional)
112  if (m_sectorPlaneBounds != nullptr) {
113  // sectorPlane 1 (negative phi)
114  const Transform3 sp1Transform =
115  Transform3(transform *
117  Vector3(0., 0., 1.)) *
118  Translation3(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.) *
119  AngleAxis3(M_PI / 2, Vector3(1., 0., 0.)));
120  auto pSurface =
121  Surface::makeShared<PlaneSurface>(sp1Transform, m_sectorPlaneBounds);
122  oSurfaces.push_back(
124  // sectorPlane 2 (positive phi)
125  const Transform3 sp2Transform =
126  Transform3(transform *
128  Vector3(0., 0., 1.)) *
129  Translation3(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.) *
130  AngleAxis3(-M_PI / 2, Vector3(1., 0., 0.)));
131  pSurface =
132  Surface::makeShared<PlaneSurface>(sp2Transform, m_sectorPlaneBounds);
133  oSurfaces.push_back(
135  }
136  return oSurfaces;
137 }
138 
140  if (get(eMinR) > s_epsilon) {
141  m_innerCylinderBounds = std::make_shared<const CylinderBounds>(
142  get(eMinR), get(eHalfLengthZ), get(eHalfPhiSector), get(eAveragePhi),
143  get(eBevelMinZ), get(eBevelMaxZ));
144  }
145  m_outerCylinderBounds = std::make_shared<const CylinderBounds>(
146  get(eMaxR), get(eHalfLengthZ), get(eHalfPhiSector), get(eAveragePhi),
147  get(eBevelMinZ), get(eBevelMaxZ));
148  m_discBounds = std::make_shared<const RadialBounds>(
149  get(eMinR), get(eMaxR), get(eHalfPhiSector), get(eAveragePhi));
150 
151  if (std::abs(get(eHalfPhiSector) - M_PI) > s_epsilon) {
152  m_sectorPlaneBounds = std::make_shared<const RectangleBounds>(
153  0.5 * (get(eMaxR) - get(eMinR)), get(eHalfLengthZ));
154  }
155 }
156 
157 std::ostream& Acts::CylinderVolumeBounds::toStream(std::ostream& sl) const {
158  return dumpT<std::ostream>(sl);
159 }
160 
162  const Transform3* trf, const Vector3& envelope,
163  const Volume* entity) const {
164  double xmax = 0, xmin = 0, ymax = 0, ymin = 0;
165  xmax = get(eMaxR);
166 
167  if (get(eHalfPhiSector) > M_PI / 2.) {
168  // more than half
169  ymax = xmax;
170  ymin = -xmax;
171  xmin = xmax * std::cos(get(eHalfPhiSector));
172  } else {
173  // less than half
174  ymax = get(eMaxR) * std::sin(get(eHalfPhiSector));
175  ymin = -ymax;
176  // in this case, xmin is given by the inner radius
177  xmin = get(eMinR) * std::cos(get(eHalfPhiSector));
178  }
179 
180  Vector3 vmin(xmin, ymin, -get(eHalfLengthZ));
181  Vector3 vmax(xmax, ymax, get(eHalfLengthZ));
182 
183  // this is probably not perfect, but at least conservative
184  Volume::BoundingBox box{entity, vmin - envelope, vmax + envelope};
185  return trf == nullptr ? box : box.transformed(*trf);
186 }