ATLAS Offline Software
Loading...
Searching...
No Matches
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
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
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
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
70{
71 m_xyVtx.resize(trabo.m_xyVtx.size());
72 m_xyVtx.assign(trabo.m_xyVtx.begin(), trabo.m_xyVtx.end());
74}
75
80
83{
84 if (this != &trabo) {
85 m_halfZ = trabo.m_halfZ;
87 m_xyVtx.resize(trabo.m_xyVtx.size());
88 m_xyVtx.assign(trabo.m_xyVtx.begin(), trabo.m_xyVtx.end());
89 delete m_baseBounds;
92 trabo.m_ordering; // ordering cache will be valid if trabo cache is valid
93 }
94 return *this;
95}
96
97std::vector<std::unique_ptr<Trk::Surface>>
99 (const Amg::Transform3D& transform)
100{
101 auto retsf = std::vector<std::unique_ptr<Trk::Surface>>();
102
103 // face surfaces xy
104 // (1) - at positive local z
105 auto xyPlane = std::make_unique<Trk::PlaneSurface>(
107 transform * Amg::Translation3D(Amg::Vector3D(0., 0., m_halfZ))),
108 std::make_shared<Trk::TriangleBounds>(m_xyVtx));
109 retsf.push_back(std::move(xyPlane));
110 // (2) - at negative local z
111 auto xymPlane = std::make_unique<Trk::PlaneSurface>(
113 transform * Amg::Translation3D(Amg::Vector3D(0., 0., -m_halfZ)) *
114 Amg::AngleAxis3D(180 * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.))),
115 std::make_shared<Trk::TriangleBounds>(mirror_xyVtx()));
116 retsf.push_back(std::move(xymPlane));
117 // loop over xy vertices
118 // (3)
119 for (unsigned int iv = 0; iv < m_xyVtx.size(); iv++) {
120 if (iv != m_xyVtx.size() - 1)
121 retsf.push_back(sideSurf(transform, iv, iv + 1));
122 else
123 retsf.push_back(sideSurf(transform, iv, 0));
124 }
125
126 return retsf;
127}
128
129// faces in xy
130std::unique_ptr<Trk::PlaneSurface>
132 const Amg::Transform3D& transform,
133 unsigned int iv1,
134 unsigned int iv2) const
135{
136 std::unique_ptr<Trk::PlaneSurface> plane = nullptr;
137
138 double xdif = m_xyVtx[iv2].first - m_xyVtx[iv1].first;
139 double ydif = m_xyVtx[iv2].second - m_xyVtx[iv1].second;
140 double xsize = sqrt(xdif * xdif + ydif * ydif);
141
142 double ori = ordering() > 0 ? 1. : -1.;
143
144 Amg::Vector3D pos(
145 0.5 * (m_xyVtx[iv1].first + m_xyVtx[iv2].first),
146 0.5 * (m_xyVtx[iv1].second + m_xyVtx[iv2].second),
147 0.);
148 double phi = ori * ydif < 0 ? M_PI / 2 : -M_PI / 2;
149 if (ori > 0 && ydif > 0)
150 phi = M_PI / 2;
151 if (std::abs(xdif) > 1e-6) {
152 phi = atan(ydif / xdif);
153 if (xdif < 0)
154 phi += M_PI;
155 }
156
158 transform * Amg::Translation3D(pos) *
159 Amg::AngleAxis3D(phi, Amg::Vector3D(0., 0., 1.)) *
160 Amg::AngleAxis3D(-ori * 90 * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.)));
161 plane = std::make_unique<Trk::PlaneSurface>(tr, std::make_shared<Trk::RectangleBounds>(0.5 * xsize, m_halfZ));
162
163 // verify position of vertices - uncomment for debugging
164 // if
165 // (!plane->isOnSurface(Trk::GlobalPosition(m_xyVtx[iv1].first,m_xyVtx[iv1].second,m_halfZ),true,0.001,0.001)
166 // ||
167 // !plane->isOnSurface(Trk::GlobalPosition(m_xyVtx[iv2].first,m_xyVtx[iv2].second,-m_halfZ),true,0.001,0.001)
168 // )
169 // std::cout << "ERROR in PRISM side boundary:vertices out of plane"<<
170 // std::endl;
171
172 // orientation
173 int ivr = (iv1 == 0 || iv2 == 0) ? 1 : 0;
174 if (ivr == 1 && (iv1 == 1 || iv2 == 1))
175 ivr = 2;
176
177 double ox = m_xyVtx[ivr].first - pos[0];
178 double oy = m_xyVtx[ivr].second - pos[1];
179 Amg::Vector3D d(ox, oy, 0.);
180
181 // protect against wrong orientation
182 if (d.dot(plane->normal()) > 0.) {
183 tr = Amg::Transform3D(
184 transform * Amg::Translation3D(pos) *
185 Amg::AngleAxis3D(phi + M_PI, Amg::Vector3D(0., 0., 1.)) *
187 -ori * 90 * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.)));
188 plane =
189 std::make_unique<Trk::PlaneSurface>(tr, std::make_shared<Trk::RectangleBounds>(0.5 * xsize, m_halfZ));
190 }
191
192 return plane;
193}
194
195bool
197{
198 if (std::abs(pos.z()) > m_halfZ + tol)
199 return false;
200 // xy plane
201 Amg::Vector2D locp(pos.x(), pos.y());
202 return (m_baseBounds->inside(locp, tol, tol));
203}
204
205std::vector<std::pair<double, double>>
207{
208 std::vector<std::pair<double, double>> mirrored;
209 mirrored.resize(m_xyVtx.size());
210
211 for (unsigned int i = 0; i < m_xyVtx.size(); i++)
212 mirrored[i] =
213 std::pair<double, double>(m_xyVtx[i].first, -m_xyVtx[i].second);
214
215 return mirrored;
216}
217
218int
220{
221 if (m_ordering.isValid()) {
222 return *(m_ordering.ptr());
223 }
224
225 int tmp_ordering = 1;
226
227 double yd2 = m_xyVtx[2].second - m_xyVtx[1].second;
228 double yd0 = m_xyVtx[0].second - m_xyVtx[1].second;
229 double xd2 = m_xyVtx[2].first - m_xyVtx[1].first;
230 double xd0 = m_xyVtx[0].first - m_xyVtx[1].first;
231 double ph2 = yd2 < 0 ? -M_PI / 2 : M_PI / 2;
232 if (std::abs(xd2) > 1e-6) {
233 ph2 = atan(yd2 / xd2);
234 if (xd2 < 0)
235 ph2 += M_PI;
236 }
237 double ph0 = yd0 < 0 ? -M_PI / 2 : M_PI / 2;
238 if (std::abs(xd0) > 1e-6) {
239 ph0 = atan(yd0 / xd0);
240 if (xd0 < 0)
241 ph0 += M_PI;
242 }
243 if (ph0 < 0)
244 ph0 += 2 * M_PI;
245 if (ph2 < 0)
246 ph2 += 2 * M_PI;
247
248 if ((ph0 > ph2 && ph0 - ph2 < M_PI) || (ph2 - ph0) > M_PI)
249 tmp_ordering = 0;
250
251 m_ordering.set(tmp_ordering);
252 return *(m_ordering.ptr());
253}
254
255// ostream operator overload
256MsgStream&
258{
259 std::stringstream temp_sl;
260 temp_sl << std::setiosflags(std::ios::fixed);
261 temp_sl << std::setprecision(7);
262 temp_sl << "Trk::PrismVolumeBounds: (halfZ, generating vtx) = ";
263 temp_sl << "( " << m_halfZ << ")";
264 for (const auto & myVtx : m_xyVtx)
265 temp_sl << "(" << myVtx.first << "," << myVtx.second << ")";
266 sl << temp_sl.str();
267
268 return sl;
269}
270
271std::ostream&
272Trk::PrismVolumeBounds::dump(std::ostream& sl) const
273{
274 std::stringstream temp_sl;
275 temp_sl << std::setiosflags(std::ios::fixed);
276 temp_sl << std::setprecision(7);
277 temp_sl << "Trk::PrismVolumeBounds: (halfZ, generating vtx) = ";
278 temp_sl << "( " << m_halfZ << ")";
279 for (const auto & myVtx : m_xyVtx)
280 temp_sl << "(" << myVtx.first << "," << myVtx.second << ")";
281 sl << temp_sl.str();
282
283 return sl;
284}
#define M_PI
Bounds for the transcript of triangular prism.
PrismVolumeBounds & operator=(const PrismVolumeBounds &bobo)
Assignment operator.
std::vector< std::pair< double, double > > mirror_xyVtx() const
mirror the input vertices for down-side boundary
double m_halfZ
halflength in z
virtual ~PrismVolumeBounds()
Destructor.
Trk::EightObjectsAccessor m_objectAccessor
There's only one single object Acessor for the moment has to be implemented if Cuboids are used more ...
PrismVolumeBounds()
Default Constructor.
CxxUtils::CachedValue< int > m_ordering
cache vertex ordering
std::vector< std::pair< double, double > > m_xyVtx
generating xy vertices
Trk::TriangleBounds * m_baseBounds
base xy bounds
int ordering() const
assess ordering of vertices
MsgStream & dump(MsgStream &sl) const override final
Output Method for MsgStream.
virtual std::vector< std::unique_ptr< Trk::Surface > > decomposeToSurfaces(const Amg::Transform3D &transform) override final
Method to decompose the Bounds into Surfaces.
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.
std::unique_ptr< Trk::PlaneSurface > sideSurf(const Amg::Transform3D &, unsigned int, unsigned int) const
method to construct side boundary planes
Bounds for a triangular, planar surface.
VolumeBounds()
Default Constructor.
Eigen::AngleAxisd AngleAxis3D
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
@ phi
Definition ParamDefs.h:75