ECCE @ 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-2018 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 // CylinderVolumeBounds.cpp, Acts project
12 
22 
23 #include <cmath>
24 #include <iostream>
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  buildSurfaceBounds();
40 }
41 
43  const RadialBounds& rBounds, double thickness) noexcept(false)
44  : VolumeBounds() {
45  if (thickness <= 0.) {
46  throw(std::invalid_argument(
47  "CylinderVolumeBounds: invalid extrusion thickness."));
48  }
49  m_values[eMinR] = rBounds.get(RadialBounds::eMinR);
50  m_values[eMaxR] = rBounds.get(RadialBounds::eMaxR);
51  m_values[eHalfLengthZ] = 0.5 * thickness;
52  m_values[eHalfPhiSector] = rBounds.get(RadialBounds::eHalfPhiSector);
53  m_values[eAveragePhi] = rBounds.get(RadialBounds::eAveragePhi);
54  buildSurfaceBounds();
55 }
56 
57 std::vector<std::shared_ptr<const Acts::Surface>>
59  const Transform3D* transformPtr) const {
60  std::vector<std::shared_ptr<const Surface>> rSurfaces;
61  rSurfaces.reserve(6);
62 
63  // set the transform
65  (transformPtr == nullptr) ? Transform3D::Identity() : (*transformPtr);
66  auto trfShared = std::make_shared<Transform3D>(transform);
67 
68  const Transform3D* tTransform = nullptr;
69  Vector3D cylCenter(transform.translation());
70 
71  // bottom Disc (negative z)
72  tTransform =
73  new Transform3D(transform * AngleAxis3D(M_PI, Vector3D(1., 0., 0.)) *
74  Translation3D(Vector3D(0., 0., get(eHalfLengthZ))));
75  rSurfaces.push_back(Surface::makeShared<DiscSurface>(
76  std::shared_ptr<const Transform3D>(tTransform), m_discBounds));
77  // top Disc (positive z)
78  tTransform = new Transform3D(
79  transform * Translation3D(Vector3D(0., 0., get(eHalfLengthZ))));
80  rSurfaces.push_back(Surface::makeShared<DiscSurface>(
81  std::shared_ptr<const Transform3D>(tTransform), m_discBounds));
82 
83  // outer Cylinder - shares the transform
84  rSurfaces.push_back(
85  Surface::makeShared<CylinderSurface>(trfShared, m_outerCylinderBounds));
86 
87  // innermost Cylinder
88  if (m_innerCylinderBounds != nullptr) {
89  rSurfaces.push_back(
90  Surface::makeShared<CylinderSurface>(trfShared, m_innerCylinderBounds));
91  }
92 
93  // the cylinder is sectoral
94  if (m_sectorPlaneBounds != nullptr) {
95  // sectorPlane 1 (negative phi)
96  const Transform3D* sp1Transform = new Transform3D(
97  transform * AngleAxis3D(-get(eHalfPhiSector), Vector3D(0., 0., 1.)) *
98  Translation3D(Vector3D(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.)) *
99  AngleAxis3D(M_PI / 2, Vector3D(1., 0., 0.)));
100  rSurfaces.push_back(Surface::makeShared<PlaneSurface>(
101  std::shared_ptr<const Transform3D>(sp1Transform), m_sectorPlaneBounds));
102  // sectorPlane 2 (positive phi)
103  const Transform3D* sp2Transform = new Transform3D(
104  transform * AngleAxis3D(get(eHalfPhiSector), Vector3D(0., 0., 1.)) *
105  Translation3D(Vector3D(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.)) *
106  AngleAxis3D(-M_PI / 2, Vector3D(1., 0., 0.)));
107  rSurfaces.push_back(Surface::makeShared<PlaneSurface>(
108  std::shared_ptr<const Transform3D>(sp2Transform), m_sectorPlaneBounds));
109  }
110  return rSurfaces;
111 }
112 
114  if (get(eMinR) > s_epsilon) {
115  m_innerCylinderBounds = std::make_shared<const CylinderBounds>(
116  get(eMinR), get(eHalfLengthZ), get(eHalfPhiSector), get(eAveragePhi));
117  }
118  m_outerCylinderBounds = std::make_shared<const CylinderBounds>(
119  get(eMaxR), get(eHalfLengthZ), get(eHalfPhiSector), get(eAveragePhi));
120  m_discBounds = std::make_shared<const RadialBounds>(
121  get(eMinR), get(eMaxR), get(eHalfPhiSector), get(eAveragePhi));
122 
123  if (std::abs(get(eHalfPhiSector) - M_PI) > s_epsilon) {
124  m_sectorPlaneBounds = std::make_shared<const RectangleBounds>(
125  0.5 * (get(eMaxR) - get(eMinR)), get(eHalfLengthZ));
126  }
127 }
128 
129 std::ostream& Acts::CylinderVolumeBounds::toStream(std::ostream& sl) const {
130  return dumpT<std::ostream>(sl);
131 }
132 
134  const Transform3D* trf, const Vector3D& envelope,
135  const Volume* entity) const {
136  double xmax, xmin, ymax, ymin;
137  xmax = get(eMaxR);
138 
139  if (get(eHalfPhiSector) > M_PI / 2.) {
140  // more than half
141  ymax = xmax;
142  ymin = -xmax;
143  xmin = xmax * std::cos(get(eHalfPhiSector));
144  } else {
145  // less than half
146  ymax = get(eMaxR) * std::sin(get(eHalfPhiSector));
147  ymin = -ymax;
148  // in this case, xmin is given by the inner radius
149  xmin = get(eMinR) * std::cos(get(eHalfPhiSector));
150  }
151 
152  Vector3D vmin(xmin, ymin, -get(eHalfLengthZ));
153  Vector3D vmax(xmax, ymax, get(eHalfLengthZ));
154 
155  // this is probably not perfect, but at least conservative
156  Volume::BoundingBox box{entity, vmin - envelope, vmax + envelope};
157  return trf == nullptr ? box : box.transformed(*trf);
158 }