ATLAS Offline Software
Loading...
Searching...
No Matches
Trk::VolumeIntersection Class Reference

A Simple Helper Class that collects methods for calculation of overlap of two geometrical objects. More...

#include <VolumeIntersection.h>

Collaboration diagram for Trk::VolumeIntersection:

Static Public Member Functions

static std::pair< bool, std::unique_ptr< Trk::Volume > > intersect (const Volume &volA, const Volume &volB)
static std::pair< bool, std::unique_ptr< Trk::Volume > > intersectApproximative (const Volume &volA, const Volume &volB)

Static Private Member Functions

static PolygonCache polygonXY (const Volume &inVol, int swap=0)
static Trk::PolygonCache intersectPgon (Trk::PolygonCache &, Trk::PolygonCache &)
static bool inside (const std::pair< double, double > &vtx, const std::vector< std::pair< double, double > > &pgon)
static double det (const std::pair< double, double > &a, const std::pair< double, double > &b, bool)

Detailed Description

A Simple Helper Class that collects methods for calculation of overlap of two geometrical objects.

Author
sarka.nosp@m..tod.nosp@m.orova.nosp@m.@cer.nosp@m.n.ch

Definition at line 55 of file VolumeIntersection.h.

Member Function Documentation

◆ det()

double Trk::VolumeIntersection::det ( const std::pair< double, double > & a,
const std::pair< double, double > & b,
bool dot )
staticprivate

Definition at line 405 of file VolumeIntersection.cxx.

407 {
408
409 if (dot)
410 return (a.first * b.first + a.second * b.second);
411
412 return (a.first * b.second - a.second * b.first);
413}
static Double_t a

◆ inside()

bool Trk::VolumeIntersection::inside ( const std::pair< double, double > & vtx,
const std::vector< std::pair< double, double > > & pgon )
staticprivate

Definition at line 387 of file VolumeIntersection.cxx.

389 {
390
391 // GM code
392 bool in = false;
393 size_t nv = pgon.size();
394 for (size_t i = 0, k = nv - 1; i < nv; k = i++) {
395 if ((pgon[i].second > vtx.second) != (pgon[k].second > vtx.second)) {
396 double ctg = (pgon[k].first - pgon[i].first) /
397 (pgon[k].second - pgon[i].second);
398 in ^= (vtx.first <
399 (vtx.second - pgon[i].second) * ctg + pgon[i].first);
400 }
401 }
402 return in;
403}

◆ intersect()

std::pair< bool, std::unique_ptr< Trk::Volume > > Trk::VolumeIntersection::intersect ( const Volume & volA,
const Volume & volB )
static

Definition at line 38 of file VolumeIntersection.cxx.

39 {
40
41 // if combination of shifted polygons, calculable
42 Trk::PolygonCache pgA = polygonXY(volA);
43 Trk::PolygonCache pgB = polygonXY(volB);
44
45 if (pgA.nVtx > 0 && pgB.nVtx > 0) {
46 // check orientation of xy face
47 Amg::Vector3D a0 = pgA.vertices[1] - pgA.vertices[0];
48 Amg::Vector3D a1 = pgA.vertices[2] - pgA.vertices[1];
49 Amg::Vector3D b0 = pgB.vertices[1] - pgB.vertices[0];
50 Amg::Vector3D b1 = pgB.vertices[2] - pgB.vertices[1];
51
52 if (std::abs((a0.cross(a1).unit()).dot(b0.cross(b1).unit())) < 1.e-3) {
53 if (std::abs((a0.cross(a1).unit()).dot(b1)) < 1.e-3)
54 pgB = polygonXY(volB, 1); // xy -> yz, only if cuboid-like
55 else if (std::abs((a0.cross(a1).unit()).dot(b0)) < 1.e-3)
56 pgB = polygonXY(volB, 2); // xy -> zx, only if cuboid-like
57 // new check orientation of xy face
58 b0 = pgB.vertices[1] - pgB.vertices[0];
59 b1 = pgB.vertices[2] - pgB.vertices[1];
60 }
61 if (std::abs(std::abs((a0.cross(a1).unit()).dot(b0.cross(b1).unit())) -
62 1.) > 1.e-3) {
63 return std::make_pair(false, nullptr);
64 }
65
66 Amg::Transform3D trf{Amg::Transform3D::Identity()};
67 const Amg::Vector3D norm = a0.cross(a1).unit();
68 if (norm.z() != 1.) { // rotate to align with z axis
69 trf = Amg::getRotateY3D(-norm.theta()) *
70 Amg::getRotateZ3D(-norm.phi());
71 for (Amg::Vector3D& vertex : pgA.vertices) {
72 vertex = trf * vertex;
73 }
74 for (Amg::Vector3D& vertex : pgB.vertices) {
75 vertex = trf * vertex;
76 }
77 pgA.center = trf * pgA.center;
78 pgB.center = trf * pgB.center;
79 }
80 // overlap in z
81 pgA.minZ = std::min(pgA.vertices[0].z(),
82 2 * pgA.center.z() - pgA.vertices[0].z());
83 pgA.maxZ = std::max(pgA.vertices[0].z(),
84 2 * pgA.center.z() - pgA.vertices[0].z());
85 pgB.minZ = std::min(pgB.vertices[0].z(),
86 2 * pgB.center.z() - pgB.vertices[0].z());
87 pgB.maxZ = std::max(pgB.vertices[0].z(),
88 2 * pgB.center.z() - pgB.vertices[0].z());
89
90 if (pgA.minZ > pgB.maxZ || pgB.minZ > pgA.maxZ) {
91 return std::make_pair(true, nullptr);
92 } // no overlap in z
93
94 Trk::PolygonCache result = intersectPgon(pgA, pgB);
95 std::unique_ptr<Trk::Volume> overlap;
96 if (result.nVtx > 0) {
97 auto spb = std::make_shared<Trk::SimplePolygonBrepVolumeBounds>(result.xyVertices, 0.5 * (result.maxZ - result.minZ));
98 Amg::Transform3D transf = trf.inverse() *
99 Amg::Translation3D(0., 0., 0.5 * (result.maxZ + result.minZ));
100 overlap = std::make_unique<Trk::Volume>(makeTransform(transf), spb);
101 }
102 return std::make_pair(true, std::move(overlap));
103 } // end shifted polygons
104
105 return std::make_pair(false, nullptr);
106}
static Trk::PolygonCache intersectPgon(Trk::PolygonCache &, Trk::PolygonCache &)
static PolygonCache polygonXY(const Volume &inVol, int swap=0)
double a0
Definition globals.cxx:27
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
Eigen::Translation< double, 3 > Translation3D
std::unique_ptr< Amg::Transform3D > makeTransform(const Amg::Transform3D &trf)
std::vector< Amg::Vector3D > vertices

◆ intersectApproximative()

std::pair< bool, std::unique_ptr< Trk::Volume > > Trk::VolumeIntersection::intersectApproximative ( const Volume & volA,
const Volume & volB )
static

Definition at line 416 of file VolumeIntersection.cxx.

417 {
418
419 // if combination of shifted polygons, calculable
420 Trk::PolygonCache pgA = polygonXY(volA);
421 Trk::PolygonCache pgB = polygonXY(volB);
422
423 const Trk::CylinderVolumeBounds *cylA{nullptr};
424 const Trk::CylinderVolumeBounds *cylB{nullptr};
425 if (pgA.nVtx == 0)
426 cylA = dynamic_cast<const Trk::CylinderVolumeBounds*>(
427 &(volA.volumeBounds()));
428 if (pgB.nVtx == 0)
429 cylB = dynamic_cast<const Trk::CylinderVolumeBounds*>(
430 &(volB.volumeBounds()));
431
432 if (cylA && cylB) {
433 double distance_center = (volA.center() - volB.center()).norm();
434 if (distance_center >
435 std::hypot(cylA->outerRadius(), cylA->halflengthZ()) +
436 std::hypot(cylB->outerRadius(), cylB->halflengthZ())) {
437 return std::make_pair(true, nullptr);
438 }
439 }
440
441 if (pgA.nVtx > 0 && pgB.nVtx > 0) {
442 // check orientation of xy face
443 Amg::Vector3D a0{pgA.vertices[1] - pgA.vertices[0]};
444 Amg::Vector3D a1{pgA.vertices[2] - pgA.vertices[1]};
445 Amg::Vector3D b0{pgB.vertices[1] - pgB.vertices[0]};
446 Amg::Vector3D b1{pgB.vertices[2] - pgB.vertices[1]};
447 if (std::abs((b0.cross(b1).unit()).dot(a0.cross(a1).unit())) < 1.e-3) {
448 if (std::abs((b0.cross(b1).unit()).dot(a1)) < 1.e-3)
449 pgA = polygonXY(volA, 1); // xy -> yz, only if cuboid-like
450 else if (std::abs((b0.cross(b1).unit()).dot(a0)) < 1.e-3)
451 pgA = polygonXY(volA, 2); // xy -> zx, only if cuboid-like
452 // new check orientation of xy face
453 a0 = pgA.vertices[1] - pgA.vertices[0];
454 a1 = pgA.vertices[2] - pgA.vertices[1];
455 }
456 if (std::abs(std::abs((b0.cross(b1).unit()).dot(a0.cross(a1).unit())) -
457 1.) > 1.e-3) {
458 return std::make_pair(false, nullptr);
459 }
460
461 Amg::Transform3D trf{Amg::Transform3D::Identity()};
462 Amg::Vector3D norm = a0.cross(a1).unit();
463 if (norm.z() != 1.) { // rotate to align with z axis
464 trf = Amg::AngleAxis3D(-norm.theta(), Amg::Vector3D::UnitY()) *
465 Amg::AngleAxis3D(-norm.phi(), Amg::Vector3D::UnitZ());
466
467 for (Amg::Vector3D& vtx : pgA.vertices) {
468 vtx = trf * vtx;
469 }
470 for (Amg::Vector3D& vtx : pgB.vertices) {
471 vtx = trf * vtx;
472 }
473 pgA.center = trf * pgA.center;
474 pgB.center = trf * pgB.center;
475 }
476 // overlap in z
477 pgA.minZ = std::min(pgA.vertices[0].z(),
478 2 * pgA.center.z() - pgA.vertices[0].z());
479 pgA.maxZ = std::max(pgA.vertices[0].z(),
480 2 * pgA.center.z() - pgA.vertices[0].z());
481 pgB.minZ = std::min(pgB.vertices[0].z(),
482 2 * pgB.center.z() - pgB.vertices[0].z());
483 pgB.maxZ = std::max(pgB.vertices[0].z(),
484 2 * pgB.center.z() - pgB.vertices[0].z());
485
486 if (pgA.minZ > pgB.maxZ || pgB.minZ > pgA.maxZ) {
487 return std::make_pair(true, nullptr);
488 } // no overlap in z
489
490 Trk::PolygonCache result = intersectPgon(pgA, pgB);
491 std::unique_ptr<Trk::Volume> overlap{};
492 if (result.nVtx > 0) {
493 auto spb = std::make_shared<Trk::SimplePolygonBrepVolumeBounds>(result.xyVertices,
494 0.5 * (result.maxZ - result.minZ));
495 Amg::Transform3D transf = trf.inverse() *
496 Amg::Translation3D(0., 0., 0.5 * (result.maxZ + result.minZ));
497 overlap = std::make_unique<Trk::Volume>(makeTransform(transf), spb);
498 }
499 return std::make_pair(true, std::move(overlap));
500 } // end shifted polygons
501
502 return std::make_pair(false, nullptr);
503}
double halflengthZ() const
This method returns the halflengthZ.
double outerRadius() const
This method returns the outer radius.
Eigen::AngleAxisd AngleAxis3D

◆ intersectPgon()

Trk::PolygonCache Trk::VolumeIntersection::intersectPgon ( Trk::PolygonCache & pgA,
Trk::PolygonCache & pgB )
staticprivate

Definition at line 108 of file VolumeIntersection.cxx.

109 {
110
111 // retrieve xy vertices (size+1)
112 for (const Amg::Vector3D& vtx : pgA.vertices)
113 pgA.xyVertices.emplace_back(vtx.x(), vtx.y());
114 pgA.xyVertices.emplace_back(pgA.vertices.front().x(), pgA.vertices.front().y());
115 for (const Amg::Vector3D& vtx : pgB.vertices)
116 pgB.xyVertices.emplace_back(vtx.x(), vtx.y());
117 pgB.xyVertices.emplace_back(pgB.vertices.front().x(), pgB.vertices.front().y());
118 // find common
119 for (const std::pair<double, double>& vtx : pgA.xyVertices) {
120 pgA.commonVertices.push_back(inside(vtx, pgB.xyVertices));
121 }
122 for (const std::pair<double, double>& vtx : pgB.xyVertices) {
123 pgB.commonVertices.push_back(inside(vtx, pgA.xyVertices));
124 }
125 // edges
126 for (int ia = 0; ia < pgA.nVtx; ia++) {
127 pgA.edges.emplace_back(
128 pgA.xyVertices[ia + 1].first - pgA.xyVertices[ia].first,
129 pgA.xyVertices[ia + 1].second - pgA.xyVertices[ia].second);
130 }
131 for (int ib = 0; ib < pgB.nVtx; ib++) {
132 pgB.edges.emplace_back(
133 pgB.xyVertices[ib + 1].first - pgB.xyVertices[ib].first,
134 pgB.xyVertices[ib + 1].second - pgB.xyVertices[ib].second);
135 }
136 // edge intersections
137 std::vector<Trk::EdgeCross> edge_cross;
138 for (int ia = 0; ia < pgA.nVtx; ia++) {
139 for (int ib = 0; ib < pgB.nVtx; ib++) {
140 double rs = det(pgA.edges[ia], pgB.edges[ib], false);
141 double qps = det(pgB.xyVertices[ib], pgB.edges[ib], false) -
142 det(pgA.xyVertices[ia], pgB.edges[ib], false);
143 double rpq = det(pgA.edges[ia], pgA.xyVertices[ia], false) -
144 det(pgA.edges[ia], pgB.xyVertices[ib], false);
145 if (rs == 0 && rpq == 0) {
146 double t0 =
147 det(pgA.edges[ia], pgA.edges[ia], true) > 0
148 ? (det(pgB.xyVertices[ib], pgA.edges[ia], true) -
149 det(pgA.xyVertices[ia], pgA.edges[ia], true)) /
150 det(pgA.edges[ia], pgA.edges[ia], true)
151 : 0;
152 double t1 =
153 det(pgA.edges[ia], pgA.edges[ia], true) > 0
154 ? t0 + det(pgB.edges[ib], pgA.edges[ia], true) /
155 det(pgA.edges[ia], pgA.edges[ia], true)
156 : 0;
157 if (t0 > 0 && t0 < 1.)
158 edge_cross.emplace_back(
159 std::make_pair(ia, ib), std::make_pair(t0, -1));
160 if (t1 > 0 && t1 < 1.)
161 edge_cross.emplace_back(
162 std::make_pair(ia, ib), std::make_pair(t1, -1));
163 } else if (rs != 0 && qps / rs > 0 && qps / rs < 1 &&
164 rpq / rs > 0 && rpq / rs < 1) {
165 edge_cross.emplace_back(std::make_pair(ia, ib),
166 std::make_pair(qps / rs, rpq / rs));
167 }
168 }
169 }
170 // collect new vertices : first in edge-crossing format
171 std::vector<Trk::EdgeCross> setVtx;
172 for (int ia = 0; ia < pgA.nVtx; ia++) {
173 if (pgA.commonVertices[ia])
174 setVtx.emplace_back(std::make_pair(ia, -1),
175 std::make_pair(0., -1.));
176 for (const Trk::EdgeCross& ie : edge_cross) {
177 if (ie.edge_id.first == ia) {
178 if (!setVtx.empty() && setVtx.back().edge_id.first == ia &&
179 setVtx.back().edge_pos.first > ie.edge_pos.first)
180 setVtx.insert(setVtx.end() - 1, ie);
181 else
182 setVtx.push_back(ie);
183 }
184 } // loop over edge crossings
185 }
186 // insert common vertices from polygonB
187 for (int ib = 0; ib < pgB.nVtx; ib++) {
188 if (pgB.commonVertices[ib]) {
189 int nlow = ib == 0 ? pgB.nVtx : ib - 1;
190 // find entry with nearest intersection along edge
191 std::vector<Trk::EdgeCross>::iterator it = setVtx.begin();
192 std::vector<Trk::EdgeCross>::iterator itb = setVtx.end();
193 while (it != setVtx.end()) {
194 if ((*it).edge_id.second == nlow) {
195 if (itb == setVtx.end() ||
196 (*it).edge_pos.second > (*itb).edge_pos.second)
197 itb = it;
198 }
199 ++it;
200 }
201 setVtx.insert(
202 itb, Trk::EdgeCross(
203 std::make_pair(ib, -2),
204 std::make_pair(
205 0., -1.))); // -2 indicates vertex coming from B
206 }
207 }
208
209 // TODO verify the ordering
210
211 // calculate position of vertices and fill the cache
212 Trk::PolygonCache pgon;
213 pgon.minZ = std::max(pgA.minZ, pgB.minZ);
214 pgon.maxZ = std::min(pgA.maxZ, pgB.maxZ);
215 pgon.nVtx = setVtx.size() < 3 ? 0 : setVtx.size();
216
217 if (pgon.nVtx < 3)
218 return pgon;
219
220 for (auto vtx : setVtx) {
221 if (vtx.edge_id.second == -1)
222 pgon.xyVertices.push_back(pgA.xyVertices[vtx.edge_id.first]);
223 else if (vtx.edge_id.second == -2)
224 pgon.xyVertices.push_back(pgB.xyVertices[vtx.edge_id.first]);
225 else { // calculate intersection
226 Amg::Vector2D vpos{pgA.xyVertices[vtx.edge_id.first].first,
227 pgA.xyVertices[vtx.edge_id.first].second};
228 Amg::Vector2D vdir{pgA.edges[vtx.edge_id.first].first,
229 pgA.edges[vtx.edge_id.first].second};
230 Amg::Vector2D vint = vpos + vtx.edge_pos.first * vdir;
231 pgon.xyVertices.emplace_back(vint.x(), vint.y());
232 }
233 }
234
235 return pgon;
236}
static Double_t rs
static Double_t t0
static double det(const std::pair< double, double > &a, const std::pair< double, double > &b, bool)
std::vector< ALFA_RawDataCollection_p1 > t1
Eigen::Matrix< double, 2, 1 > Vector2D
std::vector< std::pair< double, double > > xyVertices
std::vector< std::pair< double, double > > edges
std::vector< bool > commonVertices

◆ polygonXY()

Trk::PolygonCache Trk::VolumeIntersection::polygonXY ( const Volume & inVol,
int swap = 0 )
staticprivate

Definition at line 238 of file VolumeIntersection.cxx.

239 {
240
241 const CuboidVolumeBounds* box =
242 dynamic_cast<const Trk::CuboidVolumeBounds*>(&(vol.volumeBounds()));
243 const TrapezoidVolumeBounds* trd =
244 dynamic_cast<const Trk::TrapezoidVolumeBounds*>(&(vol.volumeBounds()));
245 const DoubleTrapezoidVolumeBounds* trdd =
246 dynamic_cast<const Trk::DoubleTrapezoidVolumeBounds*>(
247 &(vol.volumeBounds()));
248 const PrismVolumeBounds* prism =
249 dynamic_cast<const Trk::PrismVolumeBounds*>(&(vol.volumeBounds()));
250 const SimplePolygonBrepVolumeBounds* spb =
251 dynamic_cast<const Trk::SimplePolygonBrepVolumeBounds*>(
252 &(vol.volumeBounds()));
253
254 bool isPolygon = (box || trd || prism || spb || trdd);
255
256 if (!isPolygon)
257 return Trk::PolygonCache{};
258
259 Trk::PolygonCache cache;
260
261 double hz = 0.;
262 std::vector<Amg::Vector3D> vtxLocal;
263
264 if (swap > 0 &&
265 (box || (trd && trd->minHalflengthX() ==
266 trd->maxHalflengthX()))) { // swapping faces
267
268 if (swap == 1) {
269 if (box) {
270 hz = box->halflengthX();
271 cache.nVtx = 4;
272 vtxLocal.emplace_back(box->halflengthX(), box->halflengthY(),
273 box->halflengthZ());
274 vtxLocal.emplace_back(box->halflengthX(), -box->halflengthY(),
275 box->halflengthZ());
276 vtxLocal.emplace_back(box->halflengthX(), -box->halflengthY(),
277 -box->halflengthZ());
278 vtxLocal.emplace_back(box->halflengthX(), box->halflengthY(),
279 -box->halflengthZ());
280 } else if (trd) {
281 hz = trd->minHalflengthX();
282 cache.nVtx = 4;
283 vtxLocal.emplace_back(trd->minHalflengthX(), trd->halflengthY(),
284 trd->halflengthZ());
285 vtxLocal.emplace_back(trd->minHalflengthX(),
286 -trd->halflengthY(), trd->halflengthZ());
287 vtxLocal.emplace_back(trd->maxHalflengthX(),
288 -trd->halflengthY(), -trd->halflengthZ());
289 vtxLocal.emplace_back(trd->maxHalflengthX(), trd->halflengthY(),
290 -trd->halflengthZ());
291 }
292 } else if (swap == 2) {
293 if (box) {
294 hz = box->halflengthY();
295 cache.nVtx = 4;
296 vtxLocal.emplace_back(box->halflengthX(), box->halflengthY(),
297 box->halflengthZ());
298 vtxLocal.emplace_back(-box->halflengthX(), box->halflengthY(),
299 box->halflengthZ());
300 vtxLocal.emplace_back(-box->halflengthX(), box->halflengthY(),
301 -box->halflengthZ());
302 vtxLocal.emplace_back(box->halflengthX(), box->halflengthY(),
303 -box->halflengthZ());
304 } else if (trd) {
305 hz = trd->halflengthY();
306 cache.nVtx = 4;
307 vtxLocal.emplace_back(trd->minHalflengthX(), trd->halflengthY(),
308 trd->halflengthZ());
309 vtxLocal.emplace_back(-trd->minHalflengthX(),
310 trd->halflengthY(), trd->halflengthZ());
311 vtxLocal.emplace_back(-trd->minHalflengthX(),
312 trd->halflengthY(), -trd->halflengthZ());
313 vtxLocal.emplace_back(trd->minHalflengthX(), trd->halflengthY(),
314 -trd->halflengthZ());
315 }
316 }
317 cache.hZ = hz;
318 cache.center = vol.transform().translation();
319
320 for (const Amg::Vector3D& vtxloc : vtxLocal) {
321 Amg::Vector3D vtx = vol.transform() * vtxloc;
322 cache.vertices.push_back(std::move(vtx));
323 }
324 return cache;
325 } // end swap
326
327 if (box) {
328 hz = box->halflengthZ();
329 cache.nVtx = 4;
330 vtxLocal.emplace_back(box->halflengthX(), box->halflengthY(),
331 box->halflengthZ());
332 vtxLocal.emplace_back(-box->halflengthX(), box->halflengthY(),
333 box->halflengthZ());
334 vtxLocal.emplace_back(-box->halflengthX(), -box->halflengthY(),
335 box->halflengthZ());
336 vtxLocal.emplace_back(box->halflengthX(), -box->halflengthY(),
337 box->halflengthZ());
338 } else if (trd) {
339 hz = trd->halflengthZ();
340 cache.nVtx = 4;
341 vtxLocal.emplace_back(trd->minHalflengthX(), -trd->halflengthY(),
342 trd->halflengthZ());
343 vtxLocal.emplace_back(-trd->minHalflengthX(), -trd->halflengthY(),
344 trd->halflengthZ());
345 vtxLocal.emplace_back(-trd->maxHalflengthX(), trd->halflengthY(),
346 trd->halflengthZ());
347 vtxLocal.emplace_back(trd->maxHalflengthX(), trd->halflengthY(),
348 trd->halflengthZ());
349 } else if (trdd) {
350 hz = trdd->halflengthZ();
351 cache.nVtx = 6;
352 vtxLocal.emplace_back(trdd->maxHalflengthX(), 2 * trdd->halflengthY2(),
353 trdd->halflengthZ());
354 vtxLocal.emplace_back(-trdd->maxHalflengthX(), 2 * trdd->halflengthY2(),
355 trdd->halflengthZ());
356 vtxLocal.emplace_back(-trdd->medHalflengthX(), 0., trdd->halflengthZ());
357 vtxLocal.emplace_back(-trdd->minHalflengthX(),
358 -2 * trdd->halflengthY1(), trdd->halflengthZ());
359 vtxLocal.emplace_back(trdd->minHalflengthX(), -2 * trdd->halflengthY1(),
360 trdd->halflengthZ());
361 vtxLocal.emplace_back(trdd->medHalflengthX(), 0., trdd->halflengthZ());
362 } else if (prism) {
363 hz = prism->halflengthZ();
364 const std::vector<std::pair<double, double>> vtcs = prism->xyVertices();
365 for (const auto& vtc : vtcs)
366 vtxLocal.emplace_back(vtc.first, vtc.second, prism->halflengthZ());
367 cache.nVtx = vtcs.size();
368 } else if (spb) {
369 hz = spb->halflengthZ();
370 const std::vector<std::pair<double, double>> vtcs = spb->xyVertices();
371 for (const auto& vtc : vtcs)
372 vtxLocal.emplace_back(vtc.first, vtc.second, spb->halflengthZ());
373 cache.nVtx = vtcs.size();
374 }
375
376 cache.hZ = hz;
377 cache.center = vol.transform().translation();
378
379 for (const Amg::Vector3D& vtxloc : vtxLocal) {
380 Amg::Vector3D vtx = vol.transform() * vtxloc;
381 cache.vertices.push_back(std::move(vtx));
382 }
383
384 return cache;
385}
void swap(DataVector< T > &a, DataVector< T > &b)
See DataVector<T, BASE>::swap().

The documentation for this class was generated from the following files: