ATLAS Offline Software
Loading...
Searching...
No Matches
CombinedVolumeBounds.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// CombinedVolumeBounds.cxx, (c) ATLAS Detector software
8
9// Trk
11
16// TrkSurfaces
25#include "TrkSurfaces/Surface.h"
26// Gaudi
27#include "GaudiKernel/MsgStream.h"
28// STD
29#include <cmath>
30#include <iostream>
31#include <stdexcept>
32#include <utility>
33
35
37 std::unique_ptr<Volume> vol1,
38 std::unique_ptr<Volume> vol2,
39 bool intersection)
40 : VolumeBounds()
41 , m_first(std::move(vol1))
42 , m_second(std::move(vol2))
46{}
47
57
59
62{
63 if (this != &bobo) {
64 m_first.reset(bobo.m_first->clone());
65 m_second.reset(bobo.m_second->clone());
69 }
70 return *this;
71}
72
73std::vector<std::unique_ptr<Trk::Surface>>
75
76 auto retsf = std::vector<std::unique_ptr<Trk::Surface>>();
77
78 const Trk::CylinderVolumeBounds* cylVol = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(m_first->volumeBounds()));
79 const Trk::SimplePolygonBrepVolumeBounds* spbVol = dynamic_cast<const Trk::SimplePolygonBrepVolumeBounds*>(&(m_first->volumeBounds()));
80 const Trk::CombinedVolumeBounds* comVol = dynamic_cast<const Trk::CombinedVolumeBounds*>(&(m_first->volumeBounds()));
81 const Trk::SubtractedVolumeBounds* subVol = dynamic_cast<const Trk::SubtractedVolumeBounds*>(&(m_first->volumeBounds()));
82
83 // get surfaces for first boundaries
84 std::vector<std::unique_ptr<Trk::Surface>> firstSurfaces =
85 m_first->volumeBounds().decomposeToSurfaces(transf * m_first->transform());
86 // get surfaces for second boundaries
87 std::vector<std::unique_ptr<Trk::Surface>> secondSurfaces =
88 m_second->volumeBounds().decomposeToSurfaces(transf * m_second->transform());
89 unsigned int nSurf = firstSurfaces.size() + secondSurfaces.size();
90 m_boundsOrientation.resize(nSurf);
91
92 std::vector<unsigned int> subtrSecond;
93
94 // loop over surfaces; convert disc surface to a plane surface using elliptic
95 // bounds
96 for (unsigned int out = 0; out < firstSurfaces.size(); out++) {
97 //
98 const SubtractedPlaneSurface* splo = dynamic_cast<const SubtractedPlaneSurface*>(firstSurfaces[out].get());
99 const PlaneSurface* plo = dynamic_cast<const PlaneSurface*>(firstSurfaces[out].get());
100 const SubtractedCylinderSurface* sclo = dynamic_cast<const SubtractedCylinderSurface*>(firstSurfaces[out].get());
101 const CylinderSurface* clo = dynamic_cast<const CylinderSurface*>(firstSurfaces[out].get());
102 const DiscSurface* dlo = dynamic_cast<const DiscSurface*>(firstSurfaces[out].get());
103
104 // resolve bounds orientation : copy from combined/subtracted, swap inner
105 // cyl, swap bottom spb
106 if (comVol){
107 m_boundsOrientation[out] = comVol->boundsOrientation()[out];
108 }
109 else if (subVol){
110 m_boundsOrientation[out] = subVol->boundsOrientation()[out];
111 }
112 else if (cylVol && clo && out == 3){
113 m_boundsOrientation[out] = false;
114 }
115 else if (spbVol && out == 0){
116 m_boundsOrientation[out] = false;
117 }
118 else{
119 m_boundsOrientation[out] = true;
120 }
121
122 std::unique_ptr<Trk::Volume> secondSub(createSubtractedVolume(
123 firstSurfaces[out]->transform().inverse() * transf, m_second.get()));
124
125 if (sclo || splo) {
126 bool shared = false;
127 const Trk::AreaExcluder* vEx;
128 if (splo) {
129 vEx = splo->subtractedVolume();
130 shared = splo->shared();
131 }
132 if (sclo) {
133 vEx = sclo->subtractedVolume();
134 shared = sclo->shared();
135 }
136 const Trk::VolumeExcluder* volExcl = dynamic_cast<const Trk::VolumeExcluder*>(vEx);
137 if (!volExcl){
138 throw std::logic_error("Not a VolumeExcluder");
139 }
140
141 auto firstSub = std::make_unique<Trk::Volume>(*volExcl->volume());
142
143 std::unique_ptr<Trk::Volume> comb_sub{};
144 if (!shared && !m_intersection){
145 comb_sub = std::make_unique<Trk::Volume>(
146 nullptr,
147 std::make_shared<Trk::CombinedVolumeBounds>(std::move(secondSub), std::move(firstSub), m_intersection));
148 }
149 if (!shared && m_intersection){
150 comb_sub = std::make_unique<Trk::Volume>(
151 nullptr,
152 std::make_shared<Trk::SubtractedVolumeBounds>(std::move(secondSub), std::move(firstSub)));
153 }
154 if (shared && m_intersection){
155 comb_sub = std::make_unique<Trk::Volume>(
156 nullptr,
157 std::make_shared<Trk::CombinedVolumeBounds>(std::move(secondSub), std::move(firstSub), m_intersection));
158 }
159 if (shared && !m_intersection){
160 comb_sub = std::make_unique<Trk::Volume>(
161 nullptr,
162 std::make_shared<Trk::SubtractedVolumeBounds>(std::move(firstSub), std::move(secondSub)));
163 }
164 auto volEx = std::make_shared<const Trk::VolumeExcluder>(std::move(comb_sub));
165 bool new_shared = shared;
166 if (m_intersection){
167 new_shared = true;
168 }
169 if (splo){
170 retsf.push_back(std::make_unique<Trk::SubtractedPlaneSurface>(*splo, std::move(volEx), new_shared));
171 }
172 else if (sclo){
173 retsf.push_back(std::make_unique<Trk::SubtractedCylinderSurface>(*sclo, std::move(volEx), new_shared));
174 }
175 } else if (plo || clo || dlo) {
176 auto volEx = std::make_shared<const Trk::VolumeExcluder>(std::move(secondSub));
177 if (plo){
178 retsf.push_back(std::make_unique<Trk::SubtractedPlaneSurface>(*plo, std::move(volEx), m_intersection));
179 }
180 else if (clo){
181 retsf.push_back(std::make_unique<Trk::SubtractedCylinderSurface>(*clo, std::move(volEx), m_intersection));
182 }
183 else if (dlo) {
184 const DiscBounds* db = dynamic_cast<const DiscBounds*>(&(dlo->bounds()));
185 if (!db){
186 throw std::logic_error("Not DiscBounds");
187 }
188 auto eb = std::make_shared<EllipseBounds>(db->rMin(), db->rMin(), db->rMax(), db->rMax(), db->halfPhiSector());
189 retsf.push_back( std::make_unique<Trk::SubtractedPlaneSurface>(
191 std::move(volEx),
193 }
194 } else {
195 throw std::runtime_error(
196 "Unhandled surface in CombinedVolumeBounds::decomposeToSurfaces.");
197 }
198 }
199
200 cylVol =
201 dynamic_cast<const Trk::CylinderVolumeBounds*>(&(m_second->volumeBounds()));
202 spbVol = dynamic_cast<const Trk::SimplePolygonBrepVolumeBounds*>(
203 &(m_second->volumeBounds()));
204 comVol =
205 dynamic_cast<const Trk::CombinedVolumeBounds*>(&(m_second->volumeBounds()));
206 subVol = dynamic_cast<const Trk::SubtractedVolumeBounds*>(
207 &(m_second->volumeBounds()));
208 unsigned int nOut = firstSurfaces.size();
209
210 for (unsigned int in = 0; in < secondSurfaces.size(); in++) {
211 //
212 const SubtractedPlaneSurface* spli = dynamic_cast<const SubtractedPlaneSurface*>(secondSurfaces[in].get());
213 const PlaneSurface* pli = dynamic_cast<const PlaneSurface*>(secondSurfaces[in].get());
214 const SubtractedCylinderSurface* scli = dynamic_cast<const SubtractedCylinderSurface*>(secondSurfaces[in].get());
215 const CylinderSurface* cli = dynamic_cast<const CylinderSurface*>(secondSurfaces[in].get());
216 const DiscSurface* dli = dynamic_cast<const DiscSurface*>(secondSurfaces[in].get());
217
218 // resolve bounds orientation : copy from combined/subtracted, swap inner
219 // cyl, swap bottom spb
220 if (comVol){
221 m_boundsOrientation[nOut + in] = comVol->boundsOrientation()[in];
222 }
223 else if (subVol){
224 m_boundsOrientation[nOut + in] = subVol->boundsOrientation()[in];
225 }
226 else if (cylVol && cli && in == 3){
227 m_boundsOrientation[nOut + in] = false;
228 }
229 else if (spbVol && in == 0){
230 m_boundsOrientation[nOut + in] = false;
231 }
232 else{
233 m_boundsOrientation[nOut + in] = true;
234 }
235
236 std::unique_ptr<Trk::Volume> firstSub(createSubtractedVolume(
237 secondSurfaces[in]->transform().inverse() * transf, m_first.get()));
238 if (scli || spli) {
239 bool shared = false;
240 const Trk::AreaExcluder* vEx;
241 if (spli) {
242 vEx = spli->subtractedVolume();
243 shared = spli->shared();
244 }
245 if (scli) {
246 vEx = scli->subtractedVolume();
247 shared = scli->shared();
248 }
249 const Trk::VolumeExcluder* volExcl = dynamic_cast<const Trk::VolumeExcluder*>(vEx);
250 if (!volExcl){
251 throw std::logic_error("Not a VolumeExcluder");
252 }
253 auto secondSub = std::make_unique<Trk::Volume>(*volExcl->volume());
254
255 std::unique_ptr<Trk::Volume> comb_sub{};
256 if (!shared && !m_intersection){
257 comb_sub = std::make_unique<Trk::Volume>(
258 nullptr,
259 std::make_shared<Trk::CombinedVolumeBounds>(std::move(firstSub), std::move(secondSub), m_intersection));
260 }
261 if (!shared && m_intersection){
262 comb_sub = std::make_unique<Trk::Volume>(
263 nullptr,
264 std::make_shared<Trk::SubtractedVolumeBounds>(std::move(firstSub), std::move(secondSub)));
265 }
266 if (shared && m_intersection){
267 comb_sub = std::make_unique<Trk::Volume>(
268 nullptr,
269 std::make_shared<Trk::CombinedVolumeBounds>(std::move(firstSub), std::move(secondSub), m_intersection));
270 }
271 if (shared && !m_intersection){
272 comb_sub = std::make_unique<Trk::Volume>(
273 nullptr,
274 std::make_shared<Trk::SubtractedVolumeBounds>(std::move(secondSub), std::move(firstSub)));
275 }
276 auto volEx = std::make_shared<const Trk::VolumeExcluder>(std::move(comb_sub));
277 bool new_shared = shared;
278 if (m_intersection){
279 new_shared = true;
280 }
281 if (spli){
282 retsf.push_back(std::make_unique<Trk::SubtractedPlaneSurface>(*spli, std::move(volEx), new_shared));
283 }
284 else if (scli)
285 retsf.push_back( std::make_unique<Trk::SubtractedCylinderSurface>(*scli, std::move(volEx), new_shared));
286
287 } else if (pli || cli || dli) {
288 auto volEx = std::make_shared<const Trk::VolumeExcluder>(std::move(firstSub));
289 if (pli){
290 retsf.push_back(std::make_unique<Trk::SubtractedPlaneSurface>(*pli, std::move(volEx), m_intersection));
291 }
292 else if (cli){
293 retsf.push_back(std::make_unique<Trk::SubtractedCylinderSurface>(*cli, std::move(volEx), m_intersection));
294 }
295 else if (dli) {
296 const DiscBounds* db = dynamic_cast<const DiscBounds*>(&(dli->bounds()));
297 if (!db){
298 throw std::logic_error("Not DiscBounds");
299 }
300 auto eb = std::make_shared<EllipseBounds>(db->rMin(), db->rMin(), db->rMax(), db->rMax(), db->halfPhiSector());
301 auto pliN = PlaneSurface(Amg::Transform3D(dli->transform()), eb);
302 retsf.push_back(std::make_unique<Trk::SubtractedPlaneSurface>(pliN, std::move(volEx), m_intersection));
303 }
304 } else {
305 throw std::runtime_error(
306 "Unhandled surface in CombinedVolumeBounds::decomposeToSurfaces.");
307 }
308 }
309 return retsf;
310}
311
312// ostream operator overload
313
314MsgStream&
316{
317 std::stringstream temp_sl;
318 temp_sl << std::setiosflags(std::ios::fixed);
319 temp_sl << std::setprecision(7);
320 temp_sl << "Trk::CombinedVolumeBounds: first,second ";
321 sl << temp_sl.str();
322 std::as_const(*m_first).volumeBounds().dump(sl);
323 std::as_const(*m_second).volumeBounds().dump(sl);
324 return sl;
325}
326
327std::ostream&
328Trk::CombinedVolumeBounds::dump(std::ostream& sl) const
329{
330 std::stringstream temp_sl;
331 temp_sl << std::setiosflags(std::ios::fixed);
332 temp_sl << std::setprecision(7);
333 temp_sl << "Trk::CombinedVolumeBounds: first,second ";
334 sl << temp_sl.str();
335 std::as_const(*m_first).volumeBounds().dump(sl);
336 std::as_const(*m_second).volumeBounds().dump(sl);
337 return sl;
338}
339
342 const Amg::Transform3D& transf,
343 const Trk::Volume* subtrVol)
344{
345 if (!subtrVol){
346 return nullptr;
347 }
348 return new Trk::Volume(*subtrVol, transf);
349}
350
Pure abstract base class.
Bounds for a generic combined volume, the decomposeToSurfaces method creates a vector of n surfaces (...
std::unique_ptr< Volume > m_second
virtual MsgStream & dump(MsgStream &sl) const override final
Output Method for MsgStream.
CombinedVolumeBounds()
Default Constructor.
virtual std::vector< std::unique_ptr< Trk::Surface > > decomposeToSurfaces(const Amg::Transform3D &transform) override final
Method to decompose the Bounds into boundarySurfaces.
CombinedVolumeBounds & operator=(const CombinedVolumeBounds &bobo)
Assignment operator.
std::unique_ptr< Volume > m_first
const std::vector< bool > & boundsOrientation() const
This method returns bounds orientation.
EightObjectsAccessor m_objectAccessor
virtual ~CombinedVolumeBounds()
Destructor.
bool intersection() const
This method distinguishes between Union(0) and Intersection(1)
virtual CombinedVolumeBounds * clone() const override final
Virtual constructor.
static Trk::Volume * createSubtractedVolume(const Amg::Transform3D &transf, const Trk::Volume *subtrVol)
std::vector< bool > m_boundsOrientation
Class for a CylinderSurface in the ATLAS detector.
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
Class to describe the bounds for a planar DiscSurface.
Definition DiscBounds.h:44
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
const SurfaceBounds & bounds() const override final
This method returns the bounds by reference.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
Bounds for the exact transcript of the GeoSimplePolygonBrep; volume defined by combination of symm....
Class for a cylinder subtracted/shared surface in the ATLAS detector.
const AreaExcluder * subtractedVolume() const
This method allows access to the subtracted part.
bool shared() const
This method indicates the subtraction mode.
Class for a planar subtracted/shared surface in the ATLAS detector.
bool shared() const
This method indicates the subtraction mode.
const AreaExcluder * subtractedVolume() const
This method allows access to the subtracted part.
Bounds for a generic subtracted volume, the decomposeToSurfaces method creates a vector of n surfaces...
const std::vector< bool > & boundsOrientation() const
This method returns bounds orientation.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
VolumeBounds()
Default Constructor.
removes explicit dependence of Subtracted*Surface on TrkVolumes
const Volume * volume() const
Acces the subtracted volume.
Base class for all volumes inside the tracking realm, it defines the interface for inherited Volume c...
Definition Volume.h:36
Eigen::Affine3d Transform3D
STL namespace.