EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CuboidVolumeBuilder.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CuboidVolumeBuilder.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018-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 
12 #include "Acts/Geometry/Layer.hpp"
27 
28 std::shared_ptr<const Acts::PlaneSurface>
30  const GeometryContext& /*gctx*/,
31  const CuboidVolumeBuilder::SurfaceConfig& cfg) const {
32  std::shared_ptr<PlaneSurface> surface;
33 
34  // Build transformation
35  Transform3D trafo(Transform3D::Identity() * cfg.rotation);
36  trafo.translation() = cfg.position;
37 
38  // Create and store surface
39  if (cfg.detElementConstructor) {
40  surface = Surface::makeShared<PlaneSurface>(
41  cfg.rBounds,
42  *(cfg.detElementConstructor(trafo, cfg.rBounds, cfg.thickness)));
43  } else {
44  surface = Surface::makeShared<PlaneSurface>(trafo, cfg.rBounds);
45  }
46  surface->assignSurfaceMaterial(cfg.surMat);
47  return surface;
48 }
49 
50 std::shared_ptr<const Acts::Layer> Acts::CuboidVolumeBuilder::buildLayer(
51  const GeometryContext& gctx,
53  // Build the surface
54  if (cfg.surface == nullptr) {
55  cfg.surface = buildSurface(gctx, cfg.surfaceCfg);
56  }
57  // Build transformation centered at the surface position
58  Transform3D trafo(Transform3D::Identity() * cfg.surfaceCfg.rotation);
59  trafo.translation() = cfg.surfaceCfg.position;
60 
62  lCfg.surfaceArrayCreator = std::make_shared<const SurfaceArrayCreator>();
63  LayerCreator layerCreator(lCfg);
64  return layerCreator.planeLayer(gctx, {cfg.surface}, cfg.binsY, cfg.binsZ,
65  BinningValue::binX, std::nullopt, trafo);
66 }
67 
68 std::pair<double, double> Acts::CuboidVolumeBuilder::binningRange(
69  const GeometryContext& /*gctx*/,
70  const Acts::CuboidVolumeBuilder::VolumeConfig& cfg) const {
71  using namespace UnitLiterals;
72  // Construct return value
73  std::pair<double, double> minMax = std::make_pair(
75  for (const auto& layercfg : cfg.layerCfg) {
76  auto surfacePosMin =
77  layercfg.surfaceCfg.position.x() - layercfg.surfaceCfg.thickness / 2.;
78  auto surfacePosMax =
79  layercfg.surfaceCfg.position.x() + layercfg.surfaceCfg.thickness / 2.;
80  // Test if new extreme is found and set it
81  if (surfacePosMin < minMax.first) {
82  minMax.first = surfacePosMin;
83  }
84  if (surfacePosMax > minMax.second) {
85  minMax.second = surfacePosMax;
86  }
87  }
88  return minMax;
89 }
90 
91 std::shared_ptr<Acts::TrackingVolume> Acts::CuboidVolumeBuilder::buildVolume(
92  const GeometryContext& gctx,
94  // Build transformation
95  Transform3D trafo(Transform3D::Identity());
96  trafo.translation() = cfg.position;
97  // Set bounds
98  auto bounds = std::make_shared<const CuboidVolumeBounds>(
99  cfg.length.x() * 0.5, cfg.length.y() * 0.5, cfg.length.z() * 0.5);
100 
101  if (cfg.layerCfg.empty()) {
102  // Build dummy layer if no layer is given (tmp solution)
103  SurfaceConfig sCfg;
104  sCfg.position = cfg.position;
105  // Rotation of the surfaces: +pi/2 around axis y
106  Vector3D xPos(0., 0., 1.);
107  Vector3D yPos(0., 1., 0.);
108  Vector3D zPos(-1., 0., 0.);
109  sCfg.rotation.col(0) = xPos;
110  sCfg.rotation.col(1) = yPos;
111  sCfg.rotation.col(2) = zPos;
112  // Bounds
113  sCfg.rBounds = std::make_shared<const RectangleBounds>(
114  RectangleBounds(cfg.length.y() * 0.5, cfg.length.z() * 0.5));
115 
116  LayerConfig lCfg;
117  lCfg.surfaceCfg = sCfg;
118 
119  cfg.layerCfg.push_back(lCfg);
120  }
121 
122  // Gather the layers
123  LayerVector layVec;
124  if (cfg.layers.empty()) {
125  cfg.layers.reserve(cfg.layerCfg.size());
126 
127  for (auto& layerCfg : cfg.layerCfg) {
128  cfg.layers.push_back(buildLayer(gctx, layerCfg));
129  layVec.push_back(cfg.layers.back());
130  }
131  } else {
132  for (auto& lay : cfg.layers) {
133  layVec.push_back(lay);
134  }
135  }
136 
137  // Build layer array
138  std::pair<double, double> minMax = binningRange(gctx, cfg);
140  LayerArrayCreator layArrCreator(
141  lacCnf, getDefaultLogger("LayerArrayCreator", Logging::INFO));
142  std::unique_ptr<const LayerArray> layArr(
143  layArrCreator.layerArray(gctx, layVec, minMax.first, minMax.second,
145 
146  // Build confined volumes
147  if (cfg.trackingVolumes.empty())
148  for (VolumeConfig vc : cfg.volumeCfg)
149  cfg.trackingVolumes.push_back(buildVolume(gctx, vc));
150 
151  std::shared_ptr<TrackingVolume> trackVolume;
152  if (layVec.empty()) {
153  // Build TrackingVolume
154  trackVolume =
155  TrackingVolume::create(trafo, bounds, cfg.volumeMaterial, nullptr,
156  nullptr, cfg.trackingVolumes, cfg.name);
157  } else {
158  // Build TrackingVolume
159  trackVolume = TrackingVolume::create(trafo, bounds, cfg.volumeMaterial,
160  std::move(layArr), nullptr,
161  cfg.trackingVolumes, cfg.name);
162  }
163  return trackVolume;
164 }
165 
167  const GeometryContext& gctx, Acts::TrackingVolumePtr /*unused*/,
168  Acts::VolumeBoundsPtr /*unused*/) const {
169  // Build volumes
170  std::vector<std::shared_ptr<TrackingVolume>> volumes;
171  volumes.reserve(m_cfg.volumeCfg.size());
172  for (VolumeConfig volCfg : m_cfg.volumeCfg) {
173  volumes.push_back(buildVolume(gctx, volCfg));
174  }
175 
176  // Glue volumes
177  for (unsigned int i = 0; i < volumes.size() - 1; i++) {
178  volumes[i + 1]->glueTrackingVolume(
179  gctx, BoundarySurfaceFace::negativeFaceYZ, volumes[i].get(),
181  volumes[i]->glueTrackingVolume(gctx, BoundarySurfaceFace::positiveFaceYZ,
182  volumes[i + 1].get(),
184  }
185 
186  // Translation
187  Transform3D trafo(Transform3D::Identity());
188  trafo.translation() = m_cfg.position;
189 
190  // Size of the volume
191  auto volume = std::make_shared<const CuboidVolumeBounds>(
192  m_cfg.length.x() * 0.5, m_cfg.length.y() * 0.5, m_cfg.length.z() * 0.5);
193 
194  // Build vector of confined volumes
195  std::vector<std::pair<TrackingVolumePtr, Vector3D>> tapVec;
196  tapVec.reserve(m_cfg.volumeCfg.size());
197  for (auto& tVol : volumes) {
198  tapVec.push_back(std::make_pair(tVol, tVol->center()));
199  }
200 
201  // Set bin boundaries along binning
202  std::vector<float> binBoundaries;
203  binBoundaries.push_back(volumes[0]->center().x() -
204  m_cfg.volumeCfg[0].length.x() * 0.5);
205  for (size_t i = 0; i < volumes.size(); i++) {
206  binBoundaries.push_back(volumes[i]->center().x() +
207  m_cfg.volumeCfg[i].length.x() * 0.5);
208  }
209 
210  // Build binning
211  BinningData binData(BinningOption::open, BinningValue::binX, binBoundaries);
212  auto bu = std::make_unique<const BinUtility>(binData);
213 
214  // Build TrackingVolume array
215  std::shared_ptr<const TrackingVolumeArray> trVolArr(
216  new BinnedArrayXD<TrackingVolumePtr>(tapVec, std::move(bu)));
217 
218  // Create world volume
220  TrackingVolume::create(trafo, volume, trVolArr, "World"));
221 
222  return mtvp;
223 }