ATLAS Offline Software
PrismVolumeBounds.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // PrismVolumeBounds.cxx, (c) ATLAS Detector software
8 
9 // Trk
11 #include "TrkVolumes/Volume.h"
12 // TrkSurfaces
16 // Gaudi
17 #include "GaudiKernel/MsgStream.h"
18 #include "GaudiKernel/SystemOfUnits.h"
19 // STD
20 #include <cmath>
21 #include <iomanip>
22 #include <iostream>
23 
25  : VolumeBounds()
26  , m_halfZ()
27  , m_baseBounds(nullptr)
28  , m_ordering()
29  , // invalid cache
30  m_objectAccessor()
31 {}
32 
34  std::vector<std::pair<float, float>> xyVtx,
35  float halez)
36  : VolumeBounds()
37  , m_halfZ(halez)
38  , m_baseBounds(nullptr)
39  , m_ordering()
40  , // invalid cache
41  m_objectAccessor()
42 {
43  m_xyVtx.resize(xyVtx.size());
44  m_xyVtx.assign(xyVtx.begin(), xyVtx.end());
46 }
47 
49  std::vector<std::pair<double, double>> xyVtx,
50  double halez)
51  : VolumeBounds()
52  , m_halfZ(halez)
53  , m_baseBounds(nullptr)
54  , m_ordering()
55  , // invalid cache
56  m_objectAccessor()
57 {
58  m_xyVtx.resize(xyVtx.size());
59  m_xyVtx.assign(xyVtx.begin(), xyVtx.end());
61 }
62 
64  : VolumeBounds()
65  , m_halfZ(trabo.m_halfZ)
66  , m_baseBounds(nullptr)
67  , m_ordering(trabo.m_ordering)
68  , // ordering cache will be valid if trabo/other cache is valid
69  m_objectAccessor(trabo.m_objectAccessor)
70 {
71  m_xyVtx.resize(trabo.m_xyVtx.size());
72  m_xyVtx.assign(trabo.m_xyVtx.begin(), trabo.m_xyVtx.end());
74 }
75 
77 {
78  delete m_baseBounds;
79 }
80 
83 {
84  if (this != &trabo) {
85  m_halfZ = trabo.m_halfZ;
86  m_objectAccessor = trabo.m_objectAccessor;
87  m_xyVtx.resize(trabo.m_xyVtx.size());
88  m_xyVtx.assign(trabo.m_xyVtx.begin(), trabo.m_xyVtx.end());
89  delete m_baseBounds;
90  m_baseBounds = new Trk::TriangleBounds(m_xyVtx);
91  m_ordering =
92  trabo.m_ordering; // ordering cache will be valid if trabo cache is valid
93  }
94  return *this;
95 }
96 
97 const std::vector<const Trk::Surface*>*
99  (const Amg::Transform3D& transform)
100 {
101  std::vector<const Trk::Surface*>* retsf =
102  new std::vector<const Trk::Surface*>;
103 
104  // face surfaces xy
105  // (1) - at positive local z
106  Trk::PlaneSurface* xyPlane = new Trk::PlaneSurface(
108  transform * Amg::Translation3D(Amg::Vector3D(0., 0., m_halfZ))),
109  new Trk::TriangleBounds(m_xyVtx));
110  retsf->push_back(xyPlane);
111  // (2) - at negative local z
112  Trk::PlaneSurface* xymPlane = new Trk::PlaneSurface(
114  transform * Amg::Translation3D(Amg::Vector3D(0., 0., -m_halfZ)) *
115  Amg::AngleAxis3D(180 * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.))),
116  new Trk::TriangleBounds(mirror_xyVtx()));
117  retsf->push_back(xymPlane);
118  // loop over xy vertices
119  // (3)
120  for (unsigned int iv = 0; iv < m_xyVtx.size(); iv++) {
121  if (iv != m_xyVtx.size() - 1)
122  retsf->push_back(sideSurf(transform, iv, iv + 1));
123  else
124  retsf->push_back(sideSurf(transform, iv, 0));
125  }
126 
127  return retsf;
128 }
129 
130 // faces in xy
134  unsigned int iv1,
135  unsigned int iv2) const
136 {
137  Trk::PlaneSurface* plane = nullptr;
138 
139  double xdif = m_xyVtx[iv2].first - m_xyVtx[iv1].first;
140  double ydif = m_xyVtx[iv2].second - m_xyVtx[iv1].second;
141  double xsize = sqrt(xdif * xdif + ydif * ydif);
142 
143  double ori = ordering() > 0 ? 1. : -1.;
144 
146  0.5 * (m_xyVtx[iv1].first + m_xyVtx[iv2].first),
147  0.5 * (m_xyVtx[iv1].second + m_xyVtx[iv2].second),
148  0.);
149  double phi = ori * ydif < 0 ? M_PI / 2 : -M_PI / 2;
150  if (ori > 0 && ydif > 0)
151  phi = M_PI / 2;
152  if (std::abs(xdif) > 1e-6) {
153  phi = atan(ydif / xdif);
154  if (xdif < 0)
155  phi += M_PI;
156  }
157 
158  Amg::Transform3D tr(
160  Amg::AngleAxis3D(phi, Amg::Vector3D(0., 0., 1.)) *
161  Amg::AngleAxis3D(-ori * 90 * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.)));
162  plane =
163  new Trk::PlaneSurface(tr, new Trk::RectangleBounds(0.5 * xsize, m_halfZ));
164 
165  // verify position of vertices - uncomment for debugging
166  // if
167  // (!plane->isOnSurface(Trk::GlobalPosition(m_xyVtx[iv1].first,m_xyVtx[iv1].second,m_halfZ),true,0.001,0.001)
168  // ||
169  // !plane->isOnSurface(Trk::GlobalPosition(m_xyVtx[iv2].first,m_xyVtx[iv2].second,-m_halfZ),true,0.001,0.001)
170  // )
171  // std::cout << "ERROR in PRISM side boundary:vertices out of plane"<<
172  // std::endl;
173 
174  // orientation
175  int ivr = (iv1 == 0 || iv2 == 0) ? 1 : 0;
176  if (ivr == 1 && (iv1 == 1 || iv2 == 1))
177  ivr = 2;
178 
179  double ox = m_xyVtx[ivr].first - pos[0];
180  double oy = m_xyVtx[ivr].second - pos[1];
181  Amg::Vector3D d(ox, oy, 0.);
182 
183  // protect against wrong orientation
184  if (d.dot(plane->normal()) > 0.) {
185  delete plane;
186  tr = Amg::Transform3D(
188  Amg::AngleAxis3D(phi + M_PI, Amg::Vector3D(0., 0., 1.)) *
190  -ori * 90 * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.)));
191  plane =
192  new Trk::PlaneSurface(tr, new Trk::RectangleBounds(0.5 * xsize, m_halfZ));
193  }
194 
195  return plane;
196 }
197 
198 bool
200 {
201  if (std::abs(pos.z()) > m_halfZ + tol)
202  return false;
203  // xy plane
204  Amg::Vector2D locp(pos.x(), pos.y());
205  return (m_baseBounds->inside(locp, tol, tol));
206 }
207 
208 std::vector<std::pair<double, double>>
210 {
211  std::vector<std::pair<double, double>> mirrored;
212  mirrored.resize(m_xyVtx.size());
213 
214  for (unsigned int i = 0; i < m_xyVtx.size(); i++)
215  mirrored[i] =
216  std::pair<double, double>(m_xyVtx[i].first, -m_xyVtx[i].second);
217 
218  return mirrored;
219 }
220 
221 int
223 {
224  if (m_ordering.isValid()) {
225  return *(m_ordering.ptr());
226  }
227 
228  int tmp_ordering = 1;
229 
230  double yd2 = m_xyVtx[2].second - m_xyVtx[1].second;
231  double yd0 = m_xyVtx[0].second - m_xyVtx[1].second;
232  double xd2 = m_xyVtx[2].first - m_xyVtx[1].first;
233  double xd0 = m_xyVtx[0].first - m_xyVtx[1].first;
234  double ph2 = yd2 < 0 ? -M_PI / 2 : M_PI / 2;
235  if (std::abs(xd2) > 1e-6) {
236  ph2 = atan(yd2 / xd2);
237  if (xd2 < 0)
238  ph2 += M_PI;
239  }
240  double ph0 = yd0 < 0 ? -M_PI / 2 : M_PI / 2;
241  if (std::abs(xd0) > 1e-6) {
242  ph0 = atan(yd0 / xd0);
243  if (xd0 < 0)
244  ph0 += M_PI;
245  }
246  if (ph0 < 0)
247  ph0 += 2 * M_PI;
248  if (ph2 < 0)
249  ph2 += 2 * M_PI;
250 
251  if ((ph0 > ph2 && ph0 - ph2 < M_PI) || (ph2 - ph0) > M_PI)
252  tmp_ordering = 0;
253 
254  m_ordering.set(tmp_ordering);
255  return *(m_ordering.ptr());
256 }
257 
258 // ostream operator overload
259 MsgStream&
260 Trk::PrismVolumeBounds::dump(MsgStream& sl) const
261 {
262  std::stringstream temp_sl;
263  temp_sl << std::setiosflags(std::ios::fixed);
264  temp_sl << std::setprecision(7);
265  temp_sl << "Trk::PrismVolumeBounds: (halfZ, generating vtx) = ";
266  temp_sl << "( " << m_halfZ << ")";
267  for (const auto & myVtx : m_xyVtx)
268  temp_sl << "(" << myVtx.first << "," << myVtx.second << ")";
269  sl << temp_sl.str();
270 
271  return sl;
272 }
273 
274 std::ostream&
275 Trk::PrismVolumeBounds::dump(std::ostream& sl) const
276 {
277  std::stringstream temp_sl;
278  temp_sl << std::setiosflags(std::ios::fixed);
279  temp_sl << std::setprecision(7);
280  temp_sl << "Trk::PrismVolumeBounds: (halfZ, generating vtx) = ";
281  temp_sl << "( " << m_halfZ << ")";
282  for (const auto & myVtx : m_xyVtx)
283  temp_sl << "(" << myVtx.first << "," << myVtx.second << ")";
284  sl << temp_sl.str();
285 
286  return sl;
287 }
Trk::RectangleBounds
Definition: RectangleBounds.h:38
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
Trk::PrismVolumeBounds::m_ordering
CxxUtils::CachedValue< int > m_ordering
cache vertex ordering
Definition: PrismVolumeBounds.h:108
RectangleBounds.h
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
hist_file_dump.d
d
Definition: hist_file_dump.py:137
Trk::PrismVolumeBounds::m_objectAccessor
Trk::EightObjectsAccessor m_objectAccessor
There's only one single object Acessor for the moment has to be implemented if Cuboids are used more ...
Definition: PrismVolumeBounds.h:113
M_PI
#define M_PI
Definition: ActiveFraction.h:11
deg
#define deg
Definition: SbPolyhedron.cxx:17
Trk::PrismVolumeBounds::m_halfZ
double m_halfZ
halflength in z
Definition: PrismVolumeBounds.h:106
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
PrismVolumeBounds.h
Trk::VolumeBounds
Definition: VolumeBounds.h:45
Volume.h
Trk::TriangleBounds
Definition: TriangleBounds.h:39
lumiFormat.i
int i
Definition: lumiFormat.py:92
Trk::PrismVolumeBounds::PrismVolumeBounds
PrismVolumeBounds()
Default Constructor.
Definition: PrismVolumeBounds.cxx:24
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
Trk::Surface::normal
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
Trk::PrismVolumeBounds
Definition: PrismVolumeBounds.h:44
Trk::PrismVolumeBounds::sideSurf
Trk::PlaneSurface * sideSurf(const Amg::Transform3D &, unsigned int, unsigned int) const
method to construct side boundary planes
Definition: PrismVolumeBounds.cxx:132
Trk::PrismVolumeBounds::inside
bool inside(const Amg::Vector3D &, double tol=0.) const override final
This method checks if position in the 3D volume frame is inside the volume.
Definition: PrismVolumeBounds.cxx:199
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::PrismVolumeBounds::dump
MsgStream & dump(MsgStream &sl) const override final
Output Method for MsgStream.
Definition: PrismVolumeBounds.cxx:260
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Trk::PrismVolumeBounds::operator=
PrismVolumeBounds & operator=(const PrismVolumeBounds &bobo)
Assignment operator.
Definition: PrismVolumeBounds.cxx:82
Trk::PrismVolumeBounds::~PrismVolumeBounds
virtual ~PrismVolumeBounds()
Destructor.
Definition: PrismVolumeBounds.cxx:76
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
TriangleBounds.h
Trk::PrismVolumeBounds::m_xyVtx
std::vector< std::pair< double, double > > m_xyVtx
generating xy vertices
Definition: PrismVolumeBounds.h:105
Trk::PlaneSurface
Definition: PlaneSurface.h:64
PlaneSurface.h
Trk::PrismVolumeBounds::mirror_xyVtx
std::vector< std::pair< double, double > > mirror_xyVtx() const
mirror the input vertices for down-side boundary
Definition: PrismVolumeBounds.cxx:209
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Amg::Translation3D
Eigen::Translation< double, 3 > Translation3D
Definition: GeoPrimitives.h:44
Amg::AngleAxis3D
Eigen::AngleAxisd AngleAxis3D
Definition: GeoPrimitives.h:45
Trk::PrismVolumeBounds::ordering
int ordering() const
assess ordering of vertices
Definition: PrismVolumeBounds.cxx:222
Trk::PrismVolumeBounds::decomposeToSurfaces
const std::vector< const Trk::Surface * > * decomposeToSurfaces(const Amg::Transform3D &transform) override final
Method to decompose the Bounds into Surfaces.
Definition: PrismVolumeBounds.cxx:99
Trk::phi
@ phi
Definition: ParamDefs.h:81
Trk::PrismVolumeBounds::m_baseBounds
Trk::TriangleBounds * m_baseBounds
base xy bounds
Definition: PrismVolumeBounds.h:107
hist_file_dump.ordering
ordering
Definition: hist_file_dump.py:80