EIC 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 
19 
20 #include <cmath>
21 #include <iostream>
22 
24  const CylinderBounds& cBounds, double thickness) noexcept(false)
25  : VolumeBounds() {
26  double cR = cBounds.get(CylinderBounds::eR);
27  if (thickness <= 0. or (cR - 0.5 * thickness) < 0.) {
28  throw(std::invalid_argument(
29  "CylinderVolumeBounds: invalid extrusion thickness."));
30  }
31  m_values[eMinR] = cR - 0.5 * thickness;
32  m_values[eMaxR] = cR + 0.5 * thickness;
33  m_values[eHalfLengthZ] = cBounds.get(CylinderBounds::eHalfLengthZ);
34  m_values[eHalfPhiSector] = cBounds.get(CylinderBounds::eHalfPhiSector);
35  m_values[eAveragePhi] = cBounds.get(CylinderBounds::eAveragePhi);
37 }
38 
40  const RadialBounds& rBounds, double thickness) noexcept(false)
41  : VolumeBounds() {
42  if (thickness <= 0.) {
43  throw(std::invalid_argument(
44  "CylinderVolumeBounds: invalid extrusion thickness."));
45  }
46  m_values[eMinR] = rBounds.get(RadialBounds::eMinR);
47  m_values[eMaxR] = rBounds.get(RadialBounds::eMaxR);
48  m_values[eHalfLengthZ] = 0.5 * thickness;
49  m_values[eHalfPhiSector] = rBounds.get(RadialBounds::eHalfPhiSector);
50  m_values[eAveragePhi] = rBounds.get(RadialBounds::eAveragePhi);
52 }
53 
55  const Transform3D& transform) const {
56  OrientedSurfaces oSurfaces;
57  oSurfaces.reserve(6);
58 
59  // [0] Bottom Disc (negative z)
60  auto dSurface = Surface::makeShared<DiscSurface>(
61  transform * Translation3D(0., 0., -get(eHalfLengthZ)), m_discBounds);
62  oSurfaces.push_back(OrientedSurface(std::move(dSurface), forward));
63  // [1] Top Disc (positive z)
64  dSurface = Surface::makeShared<DiscSurface>(
65  transform * Translation3D(0., 0., get(eHalfLengthZ)), m_discBounds);
66  oSurfaces.push_back(OrientedSurface(std::move(dSurface), backward));
67 
68  // [2] Outer Cylinder
69  auto cSurface =
70  Surface::makeShared<CylinderSurface>(transform, m_outerCylinderBounds);
71  oSurfaces.push_back(OrientedSurface(std::move(cSurface), backward));
72 
73  // [3] Inner Cylinder (optional)
74  if (m_innerCylinderBounds != nullptr) {
75  cSurface =
76  Surface::makeShared<CylinderSurface>(transform, m_innerCylinderBounds);
77  oSurfaces.push_back(OrientedSurface(std::move(cSurface), forward));
78  }
79 
80  // [4] & [5] - Sectoral planes (optional)
81  if (m_sectorPlaneBounds != nullptr) {
82  // sectorPlane 1 (negative phi)
83  const Transform3D sp1Transform = Transform3D(
84  transform * AngleAxis3D(-get(eHalfPhiSector), Vector3D(0., 0., 1.)) *
85  Translation3D(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.) *
86  AngleAxis3D(M_PI / 2, Vector3D(1., 0., 0.)));
87  auto pSurface =
88  Surface::makeShared<PlaneSurface>(sp1Transform, m_sectorPlaneBounds);
89  oSurfaces.push_back(OrientedSurface(std::move(pSurface), forward));
90  // sectorPlane 2 (positive phi)
91  const Transform3D sp2Transform = Transform3D(
92  transform * AngleAxis3D(get(eHalfPhiSector), Vector3D(0., 0., 1.)) *
93  Translation3D(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.) *
94  AngleAxis3D(-M_PI / 2, Vector3D(1., 0., 0.)));
95  pSurface =
96  Surface::makeShared<PlaneSurface>(sp2Transform, m_sectorPlaneBounds);
97  oSurfaces.push_back(OrientedSurface(std::move(pSurface), backward));
98  }
99  return oSurfaces;
100 }
101 
103  if (get(eMinR) > s_epsilon) {
104  m_innerCylinderBounds = std::make_shared<const CylinderBounds>(
105  get(eMinR), get(eHalfLengthZ), get(eHalfPhiSector), get(eAveragePhi));
106  }
107  m_outerCylinderBounds = std::make_shared<const CylinderBounds>(
108  get(eMaxR), get(eHalfLengthZ), get(eHalfPhiSector), get(eAveragePhi));
109  m_discBounds = std::make_shared<const RadialBounds>(
110  get(eMinR), get(eMaxR), get(eHalfPhiSector), get(eAveragePhi));
111 
112  if (std::abs(get(eHalfPhiSector) - M_PI) > s_epsilon) {
113  m_sectorPlaneBounds = std::make_shared<const RectangleBounds>(
114  0.5 * (get(eMaxR) - get(eMinR)), get(eHalfLengthZ));
115  }
116 }
117 
118 std::ostream& Acts::CylinderVolumeBounds::toStream(std::ostream& sl) const {
119  return dumpT<std::ostream>(sl);
120 }
121 
123  const Transform3D* trf, const Vector3D& envelope,
124  const Volume* entity) const {
125  double xmax, xmin, ymax, ymin;
126  xmax = get(eMaxR);
127 
128  if (get(eHalfPhiSector) > M_PI / 2.) {
129  // more than half
130  ymax = xmax;
131  ymin = -xmax;
132  xmin = xmax * std::cos(get(eHalfPhiSector));
133  } else {
134  // less than half
135  ymax = get(eMaxR) * std::sin(get(eHalfPhiSector));
136  ymin = -ymax;
137  // in this case, xmin is given by the inner radius
138  xmin = get(eMinR) * std::cos(get(eHalfPhiSector));
139  }
140 
141  Vector3D vmin(xmin, ymin, -get(eHalfLengthZ));
142  Vector3D vmax(xmax, ymax, get(eHalfLengthZ));
143 
144  // this is probably not perfect, but at least conservative
145  Volume::BoundingBox box{entity, vmin - envelope, vmax + envelope};
146  return trf == nullptr ? box : box.transformed(*trf);
147 }