47 bool simplify,
bool blend,
48 double blendMassLimit)
const {
50 const std::string name = gv->getLogVol()->getName();
54 gv->getLogVol()->getShape(), ident)};
68 double volumeFromGeoShape =
76 double volume = volumeFromGeoShape >= 0 ? volumeFromGeoShape : -1.;
77 if ((simplify || blend) && volumeFromGeoShape < 0) {
92 if (constituents.size() == 1 && !constituents[0].second) {
93 return std::make_unique<TrackingVolume>(*volGeo, mat,
nullptr,
nullptr,
97 std::unique_ptr<Volume> envelope{};
98 std::string envName = name;
100 std::unique_ptr<TrackingVolume> trEnv{};
102 bool blended =
false;
104 if (constituents.size() == 1) {
106 envelope = std::make_unique<Volume>(*(constituents.front().first),
107 volGeo->transform());
110 if (blend && volume > 0 && volEnv > 0 &&
111 volume * mat.rho < blendMassLimit)
114 if ((simplify || blended) && volume > 0 && volEnv > 0) {
116 double fraction = volume / volEnv;
117 Material matScaled(mat.X0 / fraction, mat.L0 / fraction, mat.A,
118 mat.Z, fraction * mat.rho);
119 if (blend && !blended)
120 envName = envName +
"_PERM";
121 trEnv = std::make_unique<TrackingVolume>(*envelope, matScaled,
122 nullptr,
nullptr, envName);
124 auto confinedVols =std::make_unique<std::vector<TrackingVolume*>>();
125 confinedVols->push_back(std::make_unique<TrackingVolume>(*volGeo, mat,
nullptr,
nullptr, name).
release());
126 envName = name +
"_envelope";
127 trEnv = std::make_unique<TrackingVolume>(*envelope, dummyMaterial, std::move(confinedVols), envName);
135 std::unique_ptr<VolumeSpan> span =
139 for (
const auto& fv : constituents) {
142 &(fv.first->volumeBounds()));
150 <<
"envelope estimate: object contains cylinder:"
151 << name <<
":" << isCyl);
153 <<
"complex volume span for envelope:" << name
154 <<
":x range:" << (*span).xMin <<
","
157 <<
"complex volume span for envelope:" << name
158 <<
":y range:" << (*span).yMin <<
","
161 <<
"complex volume span for envelope:" << name
162 <<
":z range:" << (*span).zMin <<
","
165 <<
"complex volume span for envelope:" << name
166 <<
":R range:" << (*span).rMin <<
","
169 <<
"complex volume span for envelope:" << name
170 <<
":phi range:" << (*span).phiMin <<
","
176 0.5 * ((*span).yMin + (*span).yMax),
177 0.5 * ((*span).zMin + (*span).zMax)}};
179 std::shared_ptr<VolumeBounds> bounds =
180 std::make_shared<CuboidVolumeBounds>(
181 0.5 * ((*span).xMax - (*span).xMin),
182 0.5 * ((*span).yMax - (*span).yMin),
183 0.5 * ((*span).zMax - (*span).zMin));
184 envelope = std::make_unique<Volume>(
185 makeTransform(cylTrf), std::move(bounds));
187 double dPhi = (*span).phiMin > (*span).phiMax
188 ? (*span).phiMax - (*span).phiMin + 2 *
M_PI
189 : (*span).phiMax - (*span).phiMin;
190 std::shared_ptr<VolumeBounds> cylBounds{};
192 if (dPhi < 2 *
M_PI) {
193 double aPhi = 0.5 * ((*span).phiMax + (*span).phiMin);
194 cylBounds = std::make_shared<CylinderVolumeBounds>(
195 (*span).rMin, (*span).rMax, 0.5 * dPhi,
196 0.5 * ((*span).zMax - (*span).zMin));
199 cylBounds = std::make_shared<CylinderVolumeBounds>(
200 (*span).rMin, (*span).rMax,
201 0.5 * ((*span).zMax - (*span).zMin));
203 envelope = std::make_unique<Volume>(
204 makeTransform(cylTrf), std::move(cylBounds));
209 if (blend && volume > 0 && volEnv > 0 && volume * mat.rho < blendMassLimit)
212 if ((simplify || blended) && volume > 0 && volEnv > 0) {
213 double fraction = volume / volEnv;
214 Material matScaled(mat.X0 / fraction, mat.L0 / fraction, mat.A, mat.Z,
216 if (blend && !blended)
217 envName = envName +
"_PERM";
218 trEnv = std::make_unique<TrackingVolume>(*envelope, mat,
nullptr,
221 auto confinedVols = std::make_unique<std::vector<TrackingVolume*>>();
222 confinedVols->push_back( std::make_unique<TrackingVolume>(*volGeo, mat,
nullptr,
nullptr, name).
release());
223 envName = envName +
"_envelope";
224 trEnv = std::make_unique<TrackingVolume>(*envelope, dummyMaterial, std::move(confinedVols), envName);
235 inputVol.
parts.push_back(std::make_unique<Volume>(trVol));
236 constituents.push_back(std::move(inputVol));
237 VolumePartVec::iterator sIter = constituents.begin();
241 while (sIter != constituents.end()) {
243 for (
unsigned int ii = 0; ii < (*sIter).parts.size(); ++ii) {
244 const VolumeBounds& bounds{((*sIter).parts[ii]->volumeBounds())};
250 (*sIter).parts[ii].reset(comb->
first()->
clone());
252 constituents.push_back(vp);
253 constituents.back().parts[ii].reset(comb->
second()->
clone());
254 constituents.push_back(std::move(vp));
255 constituents.back().parts.emplace_back(comb->
second()->
clone());
256 constituents.back().sign = -1. * constituents.back().sign;
260 (*sIter).parts[ii].reset(sub->
outer()->
clone());
264 volume += -1. * (*sIter).sign * volSub;
266 constituents.emplace_back(*sIter);
267 constituents.back().parts.emplace_back(
269 constituents.back().sign = -1. * constituents.back().sign;
277 sIter=constituents.erase(sIter);
284 sIter = constituents.begin();
285 else if ((*sIter).parts.size() == 1) {
287 volume += (*sIter).sign * volSingle;
288 sIter=constituents.erase(sIter);
290 std::vector<std::shared_ptr<Volume>>
::iterator tit =
291 (*sIter).parts.begin();
292 bool noovrlp =
false;
293 while (tit + 1 != (*sIter).parts.end()) {
294 std::pair<bool, std::unique_ptr<Volume>> overlap =
296 if (overlap.first && !overlap.second) {
297 sIter=constituents.erase(sIter);
301 else if (overlap.first && overlap.second) {
302 (*sIter).parts.erase(tit, tit + 2);
303 (*sIter).parts.push_back(std::move(overlap.second));
304 tit = (*sIter).parts.begin();
307 sIter=constituents.erase(sIter);
312 sIter=constituents.erase(sIter);
316 std::pair<bool, std::unique_ptr<Volume>> overlap =
320 if (overlap.second) {
321 (*sIter).parts.erase(tit, tit + 2);
322 (*sIter).parts.push_back(std::move(overlap.second));
323 tit = (*sIter).parts.begin();
325 sIter=constituents.erase(sIter);
334 }
else if ((*sIter).parts.size() == 1) {
336 volume += (*sIter).sign * volSingle;
337 sIter=constituents.erase(sIter);
344 if (!constituents.empty()) {
346 << constituents.size() <<
" items "
347 <<
":volume estimate:" << volume);
356 constituents.emplace_back(std::make_unique<Volume>(trVol),
nullptr);
357 VolumePairVec::iterator sIter = constituents.begin();
358 std::shared_ptr<VolumeBounds> newBounds{};
359 while (sIter != constituents.end()) {
363 &((*sIter).first->volumeBounds()));
366 &((*sIter).first->volumeBounds()));
369 std::shared_ptr<Volume> subVol = (*sIter).second;
370 sIter = constituents.erase(sIter);
371 std::shared_ptr<Volume> combFirst{comb->
first()->
clone()};
372 std::shared_ptr<Volume> combSecond{comb->
second()->
clone()};
374 newBounds = std::make_shared<Trk::SubtractedVolumeBounds>(
375 std::unique_ptr<Trk::Volume>(combFirst->clone()), std::unique_ptr<Trk::Volume>(combSecond->clone()));
376 std::unique_ptr<Trk::Volume> newSubVol =
377 std::make_unique<Volume>(
nullptr, std::move(newBounds));
379 newBounds = std::make_shared<CombinedVolumeBounds>(
380 std::unique_ptr<Trk::Volume>(subVol->clone()), std::move(newSubVol),
false);
381 std::shared_ptr<Volume> newCSubVol =
382 std::make_unique<Volume>(
nullptr, std::move(newBounds));
384 constituents.insert(sIter,
385 std::make_pair(combFirst, newCSubVol));
389 sIter, std::make_pair(combFirst, std::move(newSubVol)));
393 constituents.insert(sIter, std::make_pair(combFirst, subVol));
395 newBounds = std::make_shared<CombinedVolumeBounds>(
396 std::unique_ptr<Trk::Volume>(subVol->clone()),
397 std::unique_ptr<Trk::Volume>(combFirst->clone()),
false);
398 std::unique_ptr<Trk::Volume> newSubVol =
399 std::make_unique<Volume>(
nullptr, std::move(newBounds));
402 std::make_pair(combSecond, std::move(newSubVol)));
405 constituents.insert(sIter,
406 std::make_pair(combSecond, combFirst));
409 sIter = constituents.begin();
411 std::shared_ptr<Volume> subVol = (*sIter).second;
412 sIter = constituents.erase(sIter);
413 std::shared_ptr<Volume> innerVol{sub->
inner()->
clone()};
414 std::shared_ptr<Volume> outerVol{sub->
outer()->
clone()};
416 newBounds = std::make_shared<CombinedVolumeBounds>(
417 std::unique_ptr<Trk::Volume>(subVol->clone()),
418 std::unique_ptr<Trk::Volume>(innerVol->clone()),
false);
419 std::unique_ptr<Volume> newSubVol =
420 std::make_unique<Trk::Volume>(
nullptr, newBounds);
423 sIter, std::make_pair(outerVol, std::move(newSubVol)));
426 constituents.insert(sIter, std::make_pair(outerVol, innerVol));
428 sIter = constituents.begin();
438 double zTol,
double phiTol)
const {
476 scomb.
rMin = std::min((*s1).rMin, (*s2).rMin);
477 scomb.
rMax = std::max((*s1).rMax, (*s2).rMax);
478 scomb.
xMin = std::min((*s1).xMin, (*s2).xMin);
479 scomb.
xMax = std::max((*s1).xMax, (*s2).xMax);
480 scomb.
yMin = std::min((*s1).yMin, (*s2).yMin);
481 scomb.
yMax = std::max((*s1).yMax, (*s2).yMax);
482 scomb.
zMin = std::min((*s1).zMin, (*s2).zMin);
483 scomb.
zMax = std::max((*s1).zMax, (*s2).zMax);
484 if ((*s1).phiMin < (*s1).phiMax && (*s2).phiMin < (*s2).phiMax) {
485 scomb.
phiMin = std::min((*s1).phiMin, (*s2).phiMin);
486 scomb.
phiMax = std::max((*s1).phiMax, (*s2).phiMax);
487 }
else if ((*s1).phiMin < (*s1).phiMax && (*s2).phiMin > (*s2).phiMax) {
488 if ((*s1).phiMin > (*s2).phiMax) {
489 scomb.
phiMin = std::min((*s1).phiMin, (*s2).phiMin);
490 scomb.
phiMax = (*s2).phiMax;
491 }
else if ((*s1).phiMax < (*s2).phiMin) {
492 scomb.
phiMin = (*s2).phiMin;
493 scomb.
phiMax = std::max((*s1).phiMax, (*s2).phiMax);
498 }
else if ((*s1).phiMin > (*s1).phiMax && (*s2).phiMin < (*s2).phiMax) {
499 if ((*s2).phiMin > (*s1).phiMax) {
500 scomb.
phiMin = std::min((*s1).phiMin, (*s2).phiMin);
501 scomb.
phiMax = (*s1).phiMax;
502 }
else if ((*s2).phiMax < (*s1).phiMin) {
503 scomb.
phiMin = (*s1).phiMin;
504 scomb.
phiMax = std::max((*s1).phiMax, (*s2).phiMax);
510 scomb.
phiMin = std::min((*s1).phiMin, (*s2).phiMin);
511 scomb.
phiMax = std::max((*s1).phiMax, (*s2).phiMax);
513 return std::make_unique<VolumeSpan>(scomb);
519 double minPhi{2 *
M_PI};
529 std::vector<Amg::Vector3D> vtx;
530 std::vector<std::pair<int, int>> edges;
550 edges.emplace_back(0, 1);
551 edges.emplace_back(0, 2);
552 edges.emplace_back(1, 3);
553 edges.emplace_back(2, 3);
554 edges.emplace_back(4, 5);
555 edges.emplace_back(4, 6);
556 edges.emplace_back(5, 7);
557 edges.emplace_back(6, 7);
558 edges.emplace_back(0, 4);
559 edges.emplace_back(1, 5);
560 edges.emplace_back(2, 6);
561 edges.emplace_back(3, 7);
580 edges.emplace_back(0, 1);
581 edges.emplace_back(0, 2);
582 edges.emplace_back(1, 3);
583 edges.emplace_back(2, 3);
584 edges.emplace_back(4, 5);
585 edges.emplace_back(4, 6);
586 edges.emplace_back(5, 7);
587 edges.emplace_back(6, 7);
588 edges.emplace_back(0, 4);
589 edges.emplace_back(1, 5);
590 edges.emplace_back(2, 6);
591 edges.emplace_back(3, 7);
614 edges.emplace_back(0, 1);
615 edges.emplace_back(0, 2);
616 edges.emplace_back(1, 3);
617 edges.emplace_back(2, 4);
618 edges.emplace_back(3, 5);
619 edges.emplace_back(4, 5);
620 edges.emplace_back(6, 7);
621 edges.emplace_back(6, 8);
622 edges.emplace_back(7, 9);
623 edges.emplace_back(8, 10);
624 edges.emplace_back(9, 11);
625 edges.emplace_back(10, 11);
626 edges.emplace_back(0, 6);
627 edges.emplace_back(1, 7);
628 edges.emplace_back(2, 8);
629 edges.emplace_back(3, 9);
630 edges.emplace_back(4, 10);
631 edges.emplace_back(5, 11);
637 edges.emplace_back(0, 1);
639 const double cosDphi = std::cos(dPhi);
640 const double sinDphi = std::sin(dPhi);
668 edges.emplace_back(2, 3);
669 edges.emplace_back(4, 5);
670 edges.emplace_back(6, 7);
671 edges.emplace_back(8, 9);
672 if (bcyl->
type() == 1 || bcyl->
type() == 3) {
673 edges.emplace_back(3, 5);
674 edges.emplace_back(7, 9);
676 if (bcyl->
type() == 2 || bcyl->
type() == 3) {
677 edges.emplace_back(2, 4);
678 edges.emplace_back(6, 8);
686 edges.emplace_back(0, 1);
688 const double cosDphi = std::cos(dPhi);
689 const double sinDphi = std::sin(dPhi);
711 edges.emplace_back(2, 3);
712 edges.emplace_back(4, 5);
713 edges.emplace_back(6, 7);
714 edges.emplace_back(8, 9);
719 const std::vector<std::pair<double, double>> vtcs = spb->
xyVertices();
720 for (
const auto& vtc : vtcs) {
721 vtx.emplace_back(vtc.first, vtc.second, spb->
halflengthZ());
722 vtx.emplace_back(vtc.first, vtc.second, -spb->
halflengthZ());
723 edges.emplace_back(vtx.size() - 2, vtx.size() - 1);
724 if (vtx.size() > 2) {
726 vtx.size() - 4, vtx.size() - 2);
728 vtx.size() - 3, vtx.size() - 1);
730 if (vtx.size() > 4) {
731 edges.emplace_back(vtx.size() - 2, 1);
732 edges.emplace_back(vtx.size() - 1, 0);
735 edges.emplace_back(0, vtx.size() - 2);
736 edges.emplace_back(1, vtx.size() - 1);
740 const std::vector<std::pair<double, double>> vtcs = prism->
xyVertices();
741 for (
const auto& vtc : vtcs) {
742 vtx.emplace_back(vtc.first, vtc.second, prism->
halflengthZ());
743 vtx.emplace_back(vtc.first, vtc.second, -prism->
halflengthZ());
744 edges.emplace_back(vtx.size() - 2, vtx.size() - 1);
745 if (vtx.size() > 2) {
747 vtx.size() - 4, vtx.size() - 2);
749 vtx.size() - 3, vtx.size() - 1);
752 edges.emplace_back(0, vtx.size() - 2);
753 edges.emplace_back(1, vtx.size() - 1);
756 std::vector<Amg::Vector3D> vtxt;
758 for (
unsigned int ie = 0; ie < vtx.size(); ie++) {
763 double rad = gp.perp();
766 minX = std::min(minX, gp[0]);
767 maxX = std::max(maxX, gp[0]);
768 minY = std::min(minY, gp[1]);
769 maxY = std::max(maxY, gp[1]);
770 minZ = std::min(minZ, gp[2]);
771 maxZ = std::max(maxZ, gp[2]);
772 minR = std::min(minR, rad);
773 maxR = std::max(maxR, rad);
774 maxPhi = std::max(maxPhi,
phi);
775 minPhi = std::min(minPhi,
phi);
784 (vtxt[edges[0].first] - vtxt[edges[0].second]).
unit();
785 maxZ += ro * sin(dir.theta());
786 minZ += -ro * sin(dir.theta());
792 double le = (vtxt[0] - vtxt[1]).norm();
793 if ((closest.
position - vtxt[0]).norm() < le &&
794 (closest.
position - vtxt[1]).norm() < le) {
795 if (minR > closest.
position.perp() - ro)
796 minR = std::max(0., closest.
position.perp() - ro);
799 if (phiClosest < minPhi || phiClosest > maxPhi) {
800 double phiTmp = minPhi;
805 minR = std::max(0., minR - ro * std::abs(dir.z()));
807 const double aTan = std::atan2(ro, minR);
812 if (maxPhi > 2 *
M_PI)
815 maxR += ro * std::abs(cos(dir.theta()));
818 double rAx = std::max(vtxt[0].
perp(), vtxt[1].
perp());
822 minR = std::max(0., minR - ro * std::abs(cos(dir.theta())));
826 for (
unsigned int ie = 0; ie < edges.size(); ie++) {
828 (vtxt[edges[ie].first] - vtxt[edges[ie].second]).
unit();
832 (vtxt[edges[ie].first] - vtxt[edges[ie].second]).norm();
833 if ((closest.
position - vtxt[edges[ie].first]).norm() < le &&
834 (closest.
position - vtxt[edges[ie].second]).norm() < le)
839 if (vtxt.size() > 10) {
842 double phiSecLmin = std::min(
845 double phiSecLmax = std::max(
850 double phiSecUmin = std::min(
853 double phiSecUmax = std::max(
856 minPhi = std::min(std::min(phiSecLmin, phiSecLmax),
857 std::min(phiSecUmin, phiSecUmax));
858 maxPhi = std::max(std::max(phiSecLmin, phiSecLmax),
859 std::max(phiSecUmin, phiSecUmax));
860 if (vtxt[10].
phi() +
M_PI < minPhi ||
861 vtxt[10].
phi() +
M_PI > maxPhi) {
865 for (
unsigned int iv = 2; iv < vtxt.size(); iv++) {
866 phiTmp = vtxt[iv].phi() +
M_PI;
869 minPhi = phiTmp < minPhi ? phiTmp : minPhi;
870 maxPhi = phiTmp > maxPhi ? phiTmp : maxPhi;
872 if (minPhi > 2 *
M_PI)
874 if (maxPhi > 2 *
M_PI)
880 maxR += ro * std::abs(std::cos(dir.theta()));
882 if (minPhi >= maxPhi && (minPhi - maxPhi) <
M_PI) {
892 for (
unsigned int ie = 0; ie < edges.size(); ie++) {
894 (vtxt[edges[ie].first] - vtxt[edges[ie].second]).
unit();
897 double le = (vtxt[edges[ie].first] - vtxt[edges[ie].second]).norm();
898 if ((closest.
position - vtxt[edges[ie].first]).norm() < le &&
899 (closest.
position - vtxt[edges[ie].second]).norm() < le)
904 if (std::abs(maxPhi - minPhi) >
M_PI) {
905 double phiTmp = minPhi;
908 for (
unsigned int iv = 0; iv < vtxt.size(); iv++) {
909 phiTmp = vtxt[iv].phi() +
M_PI;
912 minPhi = phiTmp < minPhi ? phiTmp : minPhi;
913 maxPhi = phiTmp > maxPhi ? phiTmp : maxPhi;
915 if (minPhi > 2 *
M_PI)
917 if (maxPhi > 2 *
M_PI)
919 if (minPhi >= maxPhi && (minPhi - maxPhi) <
M_PI) {
926 if (cyl || bcyl || box || trd || dtrd || spb || prism) {
927 span.zMin = minZ - zTol;
928 span.zMax = maxZ - +zTol;
929 minPhi = (minPhi - phiTol) < 0 ? minPhi - phiTol + 2 *
M_PI
931 span.phiMin = minPhi;
932 maxPhi = (maxPhi + phiTol) > 2 *
M_PI ? maxPhi + phiTol - 2 *
M_PI
934 span.phiMax = maxPhi;
935 span.rMin = std::max(70.001, minR - zTol);
936 span.rMax = maxR + zTol;
937 span.xMin = minX - zTol;
938 span.xMax = maxX - +zTol;
939 span.yMin = minY - zTol;
940 span.yMax = maxY - +zTol;
944 return std::make_unique<VolumeSpan>(span);