106 {
107 std::unique_ptr<Volume> vol{};
108 double tol = 0.1;
109
111
112 if (
sh->type() ==
"Trap") {
113 const GeoTrap* trap =
dynamic_cast<const GeoTrap*
>(
sh);
114 std::shared_ptr<TrapezoidVolumeBounds> volBounds{};
115 if (trap->getDxdyndzp() < trap->getDxdyndzn()) {
116 volBounds = std::make_shared<TrapezoidVolumeBounds>(trap->getDxdyndzp(),
117 trap->getDxdyndzn(),
118 trap->getDydzn(),
119 trap->getZHalfLength());
120 } else {
121 volBounds = std::make_shared<TrapezoidVolumeBounds>(trap->getDxdyndzn(),
122 trap->getDxdyndzp(),
123 trap->getDydzn(),
124 trap->getZHalfLength());
125 }
126 return std::make_unique<Volume>(
makeTransform(transf), std::move(volBounds));
127 }
else if (
sh->type() ==
"Pgon") {
128 const GeoPgon* pgon =
dynamic_cast<const GeoPgon*
>(
sh);
129 double hlz = 0.5 * std::abs(pgon->getZPlane(1) - pgon->getZPlane(0));
130 double phiH = pgon->getDPhi() / (2. * pgon->getNSides());
131 double hly = 0.5 * std::cos(phiH) * (pgon->getRMaxPlane(0) - pgon->getRMinPlane(0));
132 double dly = 0.5 * std::cos(phiH) * (pgon->getRMaxPlane(0) + pgon->getRMinPlane(0));
133 double hlxmin = pgon->getRMinPlane(0) * std::sin(phiH);
134 double hlxmax = pgon->getRMaxPlane(0) * std::sin(phiH);
135 if (pgon->getDPhi() == 2 *
M_PI) {
136
137 auto volBounds = std::make_shared<CylinderVolumeBounds>(pgon->getRMaxPlane(0), hlz);
138 auto subBounds = std::make_shared<CuboidVolumeBounds>(hlxmax + tol, hlxmax + tol,
139 hlz + tol);
140 auto volume = std::make_unique<Volume>(
makeTransform(transf), std::move(volBounds));
141 auto bVol = std::make_unique<Volume>(nullptr, std::move(subBounds));
142 const unsigned int nsides(pgon->getNSides());
143 const double twicePhiH(2.0 * phiH);
144 const double xTranslationDistance = hlxmax + std::cos(phiH) * (pgon->getRMaxPlane(0));
145
147 for (
unsigned int i = 0;
i < nsides;
i++) {
148 const double angle =
i * twicePhiH;
150 auto volS = std::make_unique<Volume>(*bVol, totalTransform);
151 auto combBounds =std::make_shared<SubtractedVolumeBounds>(std::move(volume),
152 std::move(volS));
153 volume = std::make_unique<Volume>(nullptr, std::move(combBounds));
154 }
155 return volume;
156 }
157
158 if (pgon->getNSides() == 1) {
159 auto volBounds = std::make_shared<TrapezoidVolumeBounds>(hlxmin, hlxmax, hly, hlz);
163 return std::make_unique<Volume>(
makeTransform(totalTransform),
164 std::move(volBounds));
165 }
166
167 if (pgon->getNSides() == 2) {
168 auto cylBounds = std::make_shared<CylinderVolumeBounds>(0, dly + hly, hlz);
170 std::move(cylBounds));
171 }
172 return vol;
173 }
else if (
sh->type() ==
"Trd") {
174 const GeoTrd* trd =
dynamic_cast<const GeoTrd*
>(
sh);
175
176 double x1 = trd->getXHalfLength1();
177 double x2 = trd->getXHalfLength2();
178 double y1 = trd->getYHalfLength1();
179 double y2 = trd->getYHalfLength2();
180 double z = trd->getZHalfLength();
181
182 ATH_MSG_DEBUG(
" Trd x1 " << x1 <<
" x2 " << x2 <<
" y1 " << y1 <<
" y2 "
183 << y2 <<
" z " <<
z);
184
185
186 if (y1 == y2) {
187 if (x1 <= x2) {
188 auto volBounds = std::make_shared<TrapezoidVolumeBounds>(x1, x2,
z, y1);
190 ATH_MSG_DEBUG(
" Trd new volume case 1 Trapezoid minHalflengthX "
191 << volBounds->minHalflengthX()
192 << " maxHalflengthX() "
193 << volBounds->maxHalflengthX());
194 vol = std::make_unique<Volume>(
makeTransform(totalTransform),
195 std::move(volBounds));
196
197
198 } else {
199
200 auto volBounds = std::make_shared<TrapezoidVolumeBounds>(x2, x1,
z, y1);
204
210 ATH_MSG_DEBUG(
" Trd new volume case 2 Trapezoid minHalflengthX "
211 << volBounds->minHalflengthX() << " maxHalflengthX() "
212 << volBounds->maxHalflengthX());
219 topG = transf * top2;
220 bottomG = transf * bottom2;
227 topG = totalTransform * topR;
228 bottomG = totalTransform * bottomR;
231 topG = totalTransform * top2R;
232 bottomG = totalTransform * bottom2R;
235
250 }
251 vol = std::make_unique<Volume>(
makeTransform(totalTransform),
252 std::move(volBounds));
253 }
254 return vol;
255 } else if (x1 == x2) {
256 if (y1 < y2) {
257 auto volBounds =
258 std::make_shared<TrapezoidVolumeBounds>(y1, y2,
z, x1);
259 ATH_MSG_DEBUG(
" Trd new volume case 3 Trapezoid minHalflengthX "
260 << volBounds->minHalflengthX()<< " maxHalflengthX() "
261 << volBounds->maxHalflengthX());
265 vol = std::make_unique<Volume>(
makeTransform(totalTransform),
266 std::move(volBounds));
267
268 } else {
269 auto volBounds = std::make_shared<TrapezoidVolumeBounds>(y2, y1,
z, x1);
270 ATH_MSG_DEBUG(
" Trd new volume case 4 Trapezoid minHalflengthX "
271 << volBounds->minHalflengthX()
272 << " maxHalflengthX() "<< volBounds->maxHalflengthX());
273
278 vol = std::make_unique<Volume>(
makeTransform(totalTransform),
279 std::move(volBounds));
280 }
281 return vol;
282 } else {
284 << x1 <<
"," << x2 <<
"," << y1 <<
"," << y2 <<
","<<
z);
285 }
286 }
else if (
sh->type() ==
"Box") {
287 const GeoBox* box =
dynamic_cast<const GeoBox*
>(
sh);
288
289 double x = box->getXHalfLength();
290 double y = box->getYHalfLength();
291 double z = box->getZHalfLength();
292 auto volBounds = std::make_shared<CuboidVolumeBounds>(
x,
y,
z);
293 return std::make_unique<Volume>(
makeTransform(transf), std::move(volBounds));
294 }
else if (
sh->type() ==
"Para") {
295 const GeoPara* para =
dynamic_cast<const GeoPara*
>(
sh);
296
297 double x = para->getXHalfLength();
298 double y = para->getYHalfLength();
299 double z = para->getZHalfLength();
300 auto volBounds = std::make_shared<CuboidVolumeBounds>(
x,
y,
z);
301 return std::make_unique<Volume>(
makeTransform(transf), std::move(volBounds));
302
303 }
else if (
sh->type() ==
"Tube") {
304 const GeoTube*
tube =
dynamic_cast<const GeoTube*
>(
sh);
306 }
else if (
sh->type() ==
"Tubs") {
307 const GeoTubs* tubs =
dynamic_cast<const GeoTubs*
>(
sh);
308 double rMin = tubs->getRMin();
309 double rMax = tubs->getRMax();
310 double z = tubs->getZHalfLength();
311 double aPhi = tubs->getSPhi();
312 double dPhi = tubs->getDPhi();
313 auto volBounds = std::make_shared<CylinderVolumeBounds>(rMin, rMax, 0.5 * dPhi,
z);
315 return std::make_unique<Volume>(
makeTransform(totalTransform), std::move(volBounds));
316 }
else if (
sh->type() ==
"Cons") {
317 const GeoCons* cons =
dynamic_cast<const GeoCons*
>(
sh);
318 double rMin1 = cons->getRMin1();
319 double rMin2 = cons->getRMin2();
320 double rMax1 = cons->getRMax1();
321 double rMax2 = cons->getRMax2();
322 double z = cons->getDZ();
323 double aPhi = cons->getSPhi();
324 double dPhi = cons->getDPhi();
325
326 if (dPhi == 2 *
M_PI) {
327 auto volBounds =std::make_shared<CylinderVolumeBounds>(0.5 * (rMin1 + rMin2),
328 0.5 * (rMax1 + rMax2),
z);
330 std::move(volBounds));
331 } else {
332 auto volBounds =std::make_shared<CylinderVolumeBounds>(0.5 * (rMin1 + rMin2),
333 0.5 * (rMax1 + rMax2),
336 return std::make_unique<Volume>(
makeTransform(totalTransform),
337 std::move(volBounds));
338 }
339 }
else if (
sh->type() ==
"Pcon") {
340 const GeoPcon* con =
dynamic_cast<const GeoPcon*
>(
sh);
341 std::shared_ptr<CylinderVolumeBounds> volBounds{};
342 double aPhi = con->getSPhi();
343 double dPhi = con->getDPhi();
344 double z1 = con->getZPlane(0);
345 double r1 = con->getRMinPlane(0);
346 double R1 = con->getRMaxPlane(0);
347 std::vector<std::unique_ptr<Volume>> cyls;
348 const unsigned int nPlanes = con->getNPlanes();
349 ATH_MSG_DEBUG(
" convert pcon aPhi " << aPhi <<
" dPhi " << dPhi <<
" z1 " << z1 <<
" r1 "
350 << r1 << " R1 " << R1 << " nPlanes " << nPlanes);
351 for (unsigned int iv = 1; iv < nPlanes; iv++) {
352 double z2 = con->getZPlane(iv);
353 double r2 = con->getRMinPlane(iv);
354 double R2 = con->getRMaxPlane(iv);
355 double zshift = 0.5 * (z1 + z2);
356 double hz = 0.5 * std::abs(z1 - z2);
357 double rmin = std::max(r1, r2);
358 double rmax = std::sqrt((R1 * R1 + R1 * R2 + R2 * R2 - r1 * r1 - r1 * r2 - r2 * r2) / 3 + rmin * rmin);
359 ATH_MSG_DEBUG(
" iPlane " << iv <<
" z2 " << z2 <<
" r2 " << r2 <<
" R2 " << R2 <<
" zshift " << zshift
360 << " hz " << hz << " rmin " << rmin << " rmax " << rmax);
361 double dz = con->getZPlane(iv) - con->getZPlane(iv - 1);
362 double drMin = con->getRMinPlane(iv) - con->getRMinPlane(iv - 1);
363 double drMax = con->getRMaxPlane(iv) - con->getRMaxPlane(iv - 1);
365 if (std::abs(dz) > 1 && (std::abs(drMin) > 0.1 * std::abs(dz) ||
366 std::abs(drMax) > 0.1 * std::abs(dz))) {
367 double dMax = std::abs(dz);
368 dMax = std::max(std::abs(drMin), dMax);
369 dMax = std::max(std::abs(drMax), dMax);
370 nSteps = std::clamp(dMax / 50., 2., 20.);
372 << nSteps << " cylinders should be created " << dz
373 << " drMin " << drMin << " drMax " << drMax
374 << " splopeMin " << drMin / dz << " slopeMax "
375 << drMax / dz);
376 }
377 for (
int j = 0; j <
nSteps; j++) {
379 double zStep = (0.5 + j) * dz / nSteps;
380 if (nSteps > 1) {
381 hz = 0.5 * std::abs(z1 - z2) /
nSteps;
382 zshift = z1 + zStep;
383 rmin =
r1 + drMin * zStep / dz;
384 rmax = R1 + drMax * zStep / dz;
385 }
387 << " rmin " << rmin << " rmax "
388 << rmax << " hz " << hz);
389
390 if (dPhi == 2 *
M_PI) {
391 volBounds = std::make_shared<CylinderVolumeBounds>(rmin, rmax, hz);
393 cyls.emplace_back(std::make_unique<Volume>(
makeTransform(totalTransform),
394 volBounds));
395 } else {
396 volBounds = std::make_shared<CylinderVolumeBounds>(rmin, rmax, 0.5 * dPhi, hz);
399 cyls.emplace_back(std::make_unique<Volume>(
makeTransform(totalTransform),
400 volBounds));
401 }
402 }
403 z1 = z2;
405 R1 = R2;
406 }
407
408 if (cyls.size() < 2) {
409 return std::move(cyls[0]);
410 } else {
411 auto comb =std::make_shared<CombinedVolumeBounds>(std::move(cyls[0]), std::move(cyls[1]), false);
412 std::unique_ptr<Volume> combVol = std::make_unique<Volume>(nullptr, std::move(comb));
413 for (
unsigned int ic = 2;
ic < cyls.size(); ++
ic) {
414 comb = std::make_shared<CombinedVolumeBounds>(std::move(combVol), std::move(cyls[ic]), false);
415 combVol = std::make_unique<Volume>(nullptr, std::move(comb));
416 }
417 return combVol;
418 }
419 }
else if (
sh->type() ==
"SimplePolygonBrep") {
420 const GeoSimplePolygonBrep* spb =
dynamic_cast<const GeoSimplePolygonBrep*
>(
sh);
421 unsigned int nv = spb->getNVertices();
422 std::vector<std::pair<double, double>> ivtx(nv);
423 for (unsigned int iv = 0; iv < nv; iv++) {
424 ivtx[iv] = std::make_pair(spb->getXVertex(iv), spb->getYVertex(iv));
425 ATH_MSG_DEBUG(
" SimplePolygonBrep x "<< spb->getXVertex(iv) <<
" y " << spb->getYVertex(iv)
426 << " z " << spb->getDZ());
427 }
428
429 if (nv == 4 || nv == 6) {
430 std::vector<double> xstep;
431 std::vector<std::pair<double, double>> ystep;
432 bool trdlike = true;
433 for (unsigned int iv = 0; iv < nv; ++iv) {
434 if (ystep.empty() || spb->getYVertex(iv) > ystep.back().first)
435 ystep.emplace_back(spb->getYVertex(iv),
436 std::abs(spb->getXVertex(iv)));
437 else {
438 std::vector<std::pair<double, double>>::iterator iy = ystep.begin();
439 while (iy + 1 < ystep.end() &&
440 spb->getYVertex(iv) > (*iy).first + 1.e-3) {
441 ++iy;
442 }
443 if (spb->getYVertex(iv) < (*iy).first - 1.e-3) {
444 ystep.insert(iy, std::make_pair(spb->getYVertex(iv), std::abs(spb->getXVertex(iv))));
445 } else if (spb->getYVertex(iv) == (*iy).first &&
446 std::abs(spb->getXVertex(iv)) != (*iy).second) {
447 trdlike = false;
448 }
449 }
450 }
451
452 if (trdlike) {
453 std::shared_ptr<VolumeBounds> volBounds{};
454 if (nv == 4) {
455 if (ystep[1].second >= ystep[0].second) {
456 volBounds = std::make_shared<TrapezoidVolumeBounds>(ystep[0].second,
457 ystep[1].second,
458 0.5 * (ystep[1].first - ystep[0].first),
459 spb->getDZ());
461 std::move(volBounds));
462 }
463 }
464
465 if (nv == 6) {
466 if (ystep[1].second >= ystep[0].second &&
467 ystep[2].second >= ystep[1].second) {
468 volBounds = std::make_shared<DoubleTrapezoidVolumeBounds>(ystep[0].second,
469 ystep[1].second,
470 ystep[2].second,
471 0.5 * (ystep[1].first - ystep[0].first),
472 0.5 * (ystep[2].first - ystep[1].first),
473 spb->getDZ());
475 std::move(volBounds));
476 }
477 }
478 }
479 }
480 auto newBounds = std::make_shared<SimplePolygonBrepVolumeBounds>(ivtx, spb->getDZ());
482 std::move(newBounds));
483 }
484
485 else if (
sh->type() ==
"Subtraction") {
486 const GeoShapeSubtraction* sub =
dynamic_cast<const GeoShapeSubtraction*
>(
sh);
487
488 const GeoShape* shA = sub->getOpA();
489 const GeoShape* shB = sub->getOpB();
492 auto volBounds = std::make_shared<SubtractedVolumeBounds>(std::move(volA),
493 std::move(volB));
494 return std::make_unique<Volume>(nullptr, std::move(volBounds));
495 }
else if (
sh->type() ==
"Union") {
496 const GeoShapeUnion* uni =
dynamic_cast<const GeoShapeUnion*
>(
sh);
497 const GeoShape* shA = uni->getOpA();
498 const GeoShape* shB = uni->getOpB();
501 auto volBounds = std::make_shared<CombinedVolumeBounds>(std::move(volA),
502 std::move(volB), false);
503 return std::make_unique<Volume>(nullptr, std::move(volBounds));
504 }
else if (
sh->type() ==
"Intersection") {
505 const GeoShapeIntersection*
intersect =
dynamic_cast<const GeoShapeIntersection*
>(
sh);
506
507 const GeoShape* shA =
intersect->getOpA();
508 const GeoShape* shB =
intersect->getOpB();
511 auto volBounds = std::make_shared<CombinedVolumeBounds>(std::move(volA),
512 std::move(volB), true);
513 return std::make_unique<Volume>(nullptr, std::move(volBounds));
514 }
515
516 if (
sh->type() ==
"Shift") {
517 const GeoShapeShift* shift =
dynamic_cast<const GeoShapeShift*
>(
sh);
519 }
521 return nullptr;
522}
#define ATH_MSG_WARNING(x)
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
bool msgLvl(const MSG::Level lvl) const
Test the output level.
static std::shared_ptr< CylinderVolumeBounds > convert(const GeoTubs *gtub)
Convert a tubs.
std::unique_ptr< Volume > translateGeoShape(const GeoShape *shape, const Amg::Transform3D &trf) const
Convert an arbitrary GeoShape into Trk::Volume.
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
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)
bool dPhi(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
@ z
global position (cartesian)