ATLAS Offline Software
ObjSurfaceWriter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // This file was largely imported from the Acts testing framework
6 
7 #include "ObjSurfaceWriter.h"
8 
9 #include <ios>
10 #include <iostream>
11 #include <stdexcept>
12 
13 #include "Acts/Geometry/Layer.hpp"
14 #include "Acts/Surfaces/CylinderBounds.hpp"
15 #include "Acts/Surfaces/PlanarBounds.hpp"
16 #include "Acts/Surfaces/RadialBounds.hpp"
17 #include "Acts/Surfaces/SurfaceBounds.hpp"
18 #include "Acts/Geometry/GeometryIdentifier.hpp"
19 
20 #include "Acts/Geometry/Polyhedron.hpp"
21 #include "Acts/Surfaces/CylinderSurface.hpp"
22 #include "Acts/Surfaces/StrawSurface.hpp"
23 
24 namespace {
25  // this method went away in acts 0.19.0. Porting over this code to use IVisualization seems
26  // to be not worth, so porting this (relatively simple) method here.
27  std::string objString(const Acts::Polyhedron& polyhedron, size_t vtxOffset) {
28  std::stringstream sstr;
29 
30  for (const auto& vtx : polyhedron.vertices) {
31  sstr << "v " << vtx.x() << " " << vtx.y() << " " << vtx.z() << std::endl;
32 
33  }
34  for (const auto& face : polyhedron.faces) {
35  sstr << "f";
36  for (const auto& idx : face) {
37  sstr << " " << (vtxOffset + idx + 1);
38 
39  }
40  sstr << std::endl;
41 
42  }
43  return sstr.str();
44 
45  }
46 }
47 
48 
49 
50 
53  : m_cfg(cfg)
54 {
55  // Validate the configuration
56  if (!m_cfg.logger) {
57  throw std::invalid_argument("Missing logger");
58  } else if (m_cfg.name.empty()) {
59  throw std::invalid_argument("Missing algorithm name");
60  } else if (!m_cfg.outputStream) {
61  throw std::invalid_argument("Missing output stream");
62  }
63 
64  // Write down the file prefix
65  (*(m_cfg.outputStream)) << m_cfg.filePrefix << '\n';
66 }
67 
68 const std::string &
70 {
71  return m_cfg.name;
72 }
73 void
74 Acts::ObjSurfaceWriter::write(const std::string& sinfo)
75 {
76  // lock the mutex for writing
77  std::lock_guard<std::mutex> lock(m_write_mutex);
78  // and write
79  (*m_cfg.outputStream) << sinfo;
80 }
81 
82 void
83 Acts::ObjSurfaceWriter::write(const Acts::GeometryContext &gctx,
84  const Acts::Surface &surface)
85 {
86  std::lock_guard<std::mutex> lock(m_write_mutex);
87 
88  // check
89  ACTS_DEBUG(">>Obj: Writer for Surface object called.");
90 
91  auto scalor = m_cfg.outputScalor;
92  // let's get the bounds & the transform
93  const Acts::SurfaceBounds& surfaceBounds = surface.bounds();
94  auto sTransform = surface.transform(gctx);
95 
96  // dynamic_cast to PlanarBounds
97  const Acts::PlanarBounds* planarBounds
98  = dynamic_cast<const Acts::PlanarBounds*>(&surfaceBounds);
99 
100  const Acts::CylinderBounds* cylinderBounds
101  = dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds);
102 
103  const Acts::StrawSurface* strawSurface
104  = dynamic_cast<const Acts::StrawSurface*>(&surface);
105 
106  // only continue if the cast worked
107  if (m_cfg.outputSensitive) {
108  if (planarBounds) {
109  ACTS_VERBOSE(">>Obj: Writing out a PlaneSurface");
110  // set the precision - just to be sure
111  (*(m_cfg.outputStream)) << '\n';
112  (*(m_cfg.outputStream)) << std::setprecision(m_cfg.outputPrecision);
113  // get the vertices
114  auto planarVertices = planarBounds->vertices();
115  // loop over the vertices
116  std::vector<Acts::Vector3> vertices;
117  vertices.reserve(planarVertices.size());
118  for (auto pv : planarVertices) {
119  // get the point in 3D
120  Acts::Vector3 v3D(sTransform * Acts::Vector3(pv.x(), pv.y(), 0.));
121  vertices.push_back(v3D);
122  }
123  // get the thickness and vertical faces
124  double thickness = 0.;
125  std::vector<unsigned int> vfaces;
126  if (surface.associatedDetectorElement()) {
127  // get the thickness form the detector element
128  thickness = surface.associatedDetectorElement()->thickness();
129  vfaces = {1, 1, 1, 1};
130  }
131  // output to file
132  ObjHelper::writePlanarFace(*(m_cfg.outputStream),
133  m_vtnCounter,
134  scalor,
135  vertices,
136  thickness,
137  vfaces);
138  (*(m_cfg.outputStream)) << '\n';
139  }
140  else if(cylinderBounds) {
141 
142  auto cylinderSurface = dynamic_cast<const Acts::CylinderSurface*>(&surface);
143  if (cylinderSurface == nullptr) { // protection against nullptr
144  ACTS_ERROR("Unable to dynamic cast surface to Acts::CylinderSurface");
145  return;
146  }
147 
148  Acts::Polyhedron ph =
149  cylinderSurface->polyhedronRepresentation(gctx, 10);
150  (*(m_cfg.outputStream)) << objString(ph, m_vtnCounter.vcounter);
151  m_vtnCounter.vcounter += ph.vertices.size();
152 
153  }
154  else if(strawSurface) {
155 
156  Acts::Polyhedron ph =
157  strawSurface->polyhedronRepresentation(gctx, 10);
158  (*(m_cfg.outputStream)) << objString(ph, m_vtnCounter.vcounter);
159  m_vtnCounter.vcounter += ph.vertices.size();
160 
161  }
162  else {
163  ACTS_ERROR("Unable to print this bounds type: " << surfaceBounds.type());
164  }
165  }
166 
167  // check if you have layer and check what your have
168  // dynamic cast to CylinderBounds work the same
169  if (cylinderBounds && m_cfg.outputLayerSurface) {
170  ACTS_VERBOSE(">>Obj: Writing out a CylinderSurface with r = "
171  << cylinderBounds->get(Acts::CylinderBounds::eR));
172  // name the object
173  auto layerID = surface.geometryId().layer();
174  (*(m_cfg.outputStream))
175  << " o Cylinder_" << std::to_string(layerID) << '\n';
176  // output to the file
177  ObjHelper::writeTube(*(m_cfg.outputStream),
178  m_vtnCounter,
179  scalor,
180  m_cfg.outputPhiSegments,
181  sTransform,
182  cylinderBounds->get(Acts::CylinderBounds::eR),
183  cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ),
184  m_cfg.outputThickness);
185  (*(m_cfg.outputStream)) << '\n';
186  }
187 
189  const Acts::RadialBounds* radialBounds
190  = dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds);
191  if (radialBounds && m_cfg.outputLayerSurface) {
192  ACTS_VERBOSE(">>Obj: Writing out a DiskSurface at z = "
193  << sTransform.translation().z());
194  // name the object
195  auto layerID = surface.geometryId().layer();
196  (*(m_cfg.outputStream)) << "o Disk_" << std::to_string(layerID) << '\n';
197  // we use the tube writer in the other direction
198  double rMin = radialBounds->rMin();
199  double rMax = radialBounds->rMax();
200  double thickness = rMax - rMin;
201  // output to the file
202  ObjHelper::writeTube(*(m_cfg.outputStream),
203  m_vtnCounter,
204  scalor,
205  m_cfg.outputPhiSegments,
206  sTransform,
207  0.5 * (rMin + rMax),
208  m_cfg.outputThickness,
209  thickness);
210  (*(m_cfg.outputStream)) << '\n';
211  }
212 
213 }
Acts::ObjSurfaceWriter::Config::filePrefix
std::string filePrefix
file prefix to be written out
Definition: ObjSurfaceWriter.h:49
Acts::ObjSurfaceWriter::Config::logger
std::shared_ptr< const Acts::Logger > logger
the default logger
Definition: ObjSurfaceWriter.h:33
ObjHelper::writePlanarFace
void writePlanarFace(std::ofstream &stream, VtnCounter &vtnCounter, double scalor, const std::vector< Acts::Vector3 > &vertices, double thickness=0., const std::vector< unsigned int > &vsides={})
This will write a planar face.
Definition: ObjHelper.cxx:69
Acts::ObjSurfaceWriter::ObjSurfaceWriter
ObjSurfaceWriter(const Config &cfg)
Constructor.
Definition: ObjSurfaceWriter.cxx:51
Acts::ObjSurfaceWriter::write
void write(const Acts::GeometryContext &gctx, const Acts::Surface &surface)
The write interface.
Definition: ObjSurfaceWriter.cxx:83
ObjHelper::writeTube
void writeTube(std::ofstream &stream, VtnCounter &vtnCounter, double scalor, unsigned int nSegments, const Acts::Transform3 &transform, double r, double hZ, double thickness=0.)
This will write a cylindrical object.
Definition: ObjHelper.cxx:114
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
WriteCaloSwCorrections.cfg
cfg
Definition: WriteCaloSwCorrections.py:23
Acts::ObjSurfaceWriter::Config::outputStream
std::shared_ptr< std::ofstream > outputStream
the output stream
Definition: ObjSurfaceWriter.h:56
Acts::ObjSurfaceWriter::m_cfg
Config m_cfg
the config class
Definition: ObjSurfaceWriter.h:85
python.changerun.pv
pv
Definition: changerun.py:81
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
Acts::ObjSurfaceWriter::Config
Definition: ObjSurfaceWriter.h:30
Acts::ObjSurfaceWriter::Config::name
std::string name
the name of the algorithm
Definition: ObjSurfaceWriter.h:35
Acts::ObjSurfaceWriter::name
const std::string & name() const
Framework name() method.
Definition: ObjSurfaceWriter.cxx:69
ObjSurfaceWriter.h