107 std::unique_ptr<Volume> vol{};
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(),
119 trap->getZHalfLength());
121 volBounds = std::make_shared<TrapezoidVolumeBounds>(trap->getDxdyndzn(),
124 trap->getZHalfLength());
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) {
137 auto volBounds = std::make_shared<CylinderVolumeBounds>(pgon->getRMaxPlane(0), hlz);
138 auto subBounds = std::make_shared<CuboidVolumeBounds>(hlxmax + tol, hlxmax + 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));
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),
153 volume = std::make_unique<Volume>(
nullptr, std::move(combBounds));
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));
167 if (pgon->getNSides() == 2) {
168 auto cylBounds = std::make_shared<CylinderVolumeBounds>(0, dly + hly, hlz);
170 std::move(cylBounds));
173 }
else if (
sh->type() ==
"Trd") {
174 const GeoTrd* trd =
dynamic_cast<const GeoTrd*
>(
sh);
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();
183 <<
y2 <<
" z " <<
z);
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));
200 auto volBounds = std::make_shared<TrapezoidVolumeBounds>(
x2,
x1,
z,
y1);
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;
251 vol = std::make_unique<Volume>(
makeTransform(totalTransform),
252 std::move(volBounds));
255 }
else if (
x1 ==
x2) {
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));
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());
278 vol = std::make_unique<Volume>(
makeTransform(totalTransform),
279 std::move(volBounds));
284 <<
x1 <<
"," <<
x2 <<
"," <<
y1 <<
"," <<
y2 <<
","<<
z);
286 }
else if (
sh->type() ==
"Box") {
287 const GeoBox* box =
dynamic_cast<const GeoBox*
>(
sh);
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);
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));
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();
327 auto volBounds =std::make_shared<CylinderVolumeBounds>(0.5 * (rMin1 + rMin2),
328 0.5 * (rMax1 + rMax2),
z);
330 std::move(volBounds));
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));
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);
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 "
377 for (
int j = 0; j <
nSteps; j++) {
379 double zStep = (0.5 + j) * dz /
nSteps;
381 hz = 0.5 * std::abs(z1 - z2) /
nSteps;
383 rmin =
r1 + drMin * zStep / dz;
384 rmax = R1 + drMax * zStep / dz;
387 <<
" rmin " << rmin <<
" rmax "
388 << rmax <<
" hz " <<
hz);
391 volBounds = std::make_shared<CylinderVolumeBounds>(rmin, rmax,
hz);
393 cyls.emplace_back(std::make_unique<Volume>(
makeTransform(totalTransform),
396 volBounds = std::make_shared<CylinderVolumeBounds>(rmin, rmax, 0.5 *
dPhi,
hz);
399 cyls.emplace_back(std::make_unique<Volume>(
makeTransform(totalTransform),
408 if (cyls.size() < 2) {
409 return std::move(cyls[0]);
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));
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());
429 if (nv == 4 || nv == 6) {
430 std::vector<double> xstep;
431 std::vector<std::pair<double, double>> ystep;
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)));
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) {
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) {
453 std::shared_ptr<VolumeBounds> volBounds{};
456 volBounds = std::make_shared<TrapezoidVolumeBounds>(ystep[0].
second,
461 std::move(volBounds));
468 volBounds = std::make_shared<DoubleTrapezoidVolumeBounds>(ystep[0].
second,
475 std::move(volBounds));
480 auto newBounds = std::make_shared<SimplePolygonBrepVolumeBounds>(ivtx, spb->getDZ());
482 std::move(newBounds));
485 else if (
sh->type() ==
"Subtraction") {
486 const GeoShapeSubtraction* sub =
dynamic_cast<const GeoShapeSubtraction*
>(
sh);
488 const GeoShape* shA = sub->getOpA();
489 const GeoShape* shB = sub->getOpB();
492 auto volBounds = std::make_shared<SubtractedVolumeBounds>(std::move(volA),
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);
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));
516 if (
sh->type() ==
"Shift") {
517 const GeoShapeShift* shift =
dynamic_cast<const GeoShapeShift*
>(
sh);