ATLAS Offline Software
Loading...
Searching...
No Matches
VolumeSplitter.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3 */
4
8#include "GaudiKernel/SystemOfUnits.h"
9
10#include <sstream>
11#include <algorithm>
12
13namespace InDetDD {
15 : m_ownVolumes(true),
16 m_epsilon(0.0001 * Gaudi::Units::mm)
17 {}
18
20 if (m_ownVolumes) {
21 for (std::vector<const ServiceVolume*>::iterator iter = m_volumes.begin(); iter != m_volumes.end(); ++iter) {
22 delete *iter;
23 }
24 }
25 }
26
27 const std::vector<const ServiceVolume*>&
28 VolumeSplitter::splitAll(const Zone& zone, const std::vector<const ServiceVolume*>& origVolumeList) {
29 for (unsigned int i = 0; i < origVolumeList.size(); ++i) {
30 split(zone, *(origVolumeList[i]));
31 }
32 return m_volumes;
33 }
34
35 void
36 VolumeSplitter::split(const Zone& zone, const ServiceVolume& origVolume) {
37 makeVolumes(&zone, origVolume);
38 }
39
40 Ray
42 double zmin = origVolume.zmin();
43 double zmax = origVolume.zmax();
44 double rmin = origVolume.rmin();
45 double rmax = origVolume.rmax();
46
47 if (zmax < zmin) std::swap(zmin, zmax);
48 if (rmax < rmin) std::swap(rmin, rmax);
49
50 bool horizontal = (std::abs(zmax - zmin) > std::abs(rmax - rmin));
51 if (horizontal) {
52 double rmid = 0.5 * (rmin + rmax);
53 return Ray(Point(zmin, rmid), Point(zmax, rmid));
54 } else {
55 double zmid = 0.5 * (zmin + zmax);
56 return Ray(Point(zmid, rmin), Point(zmid, rmax));
57 }
58 }
59
60 void
61 VolumeSplitter::makeVolumes(const Zone* zone, const ServiceVolume& origVolume) {
62 // See if its a symmetric volume
63 if (origVolume.zsymm()) {
64 ServiceVolume param1(origVolume);
65 ServiceVolume param2(origVolume);
66 param1.addLabel("A");
67 param1.setNeedsRotation(false);
68 param2.addLabel("C");
69 param2.setZmin(-origVolume.zmax());
70 param2.setZmax(-origVolume.zmin());
71 param2.setNeedsRotation(origVolume.needsRotation());
72 splitVolume(zone, param1);
73 splitVolume(zone, param2);
74 } else {
75 ServiceVolume param1(origVolume);
76 param1.setNeedsRotation(false);
77 splitVolume(zone, param1);
78 }
79 }
80
81 void
82 VolumeSplitter::splitVolume(const Zone* zone, const ServiceVolume& param) {
83 Ray ray = makeRay(param);
84 SegmentSplitter splitter;
85 const SegmentList& segments = splitter.split(zone, ray);
86
87 //std::cout << "Segments: " << std::endl;
88 //segments.print();
89
90 double volumeTotal = 0;
91
92 std::vector<ServiceVolume* > tmpServiceVec;
93 tmpServiceVec.reserve(segments.size());
94 for (unsigned int i = 0; i < segments.size(); ++i) {
95 const Segment& seg = segments.getSegment(i);
96 ServiceVolume* paramNew = new ServiceVolume(param);
97
98 if (segments.horizontal()) {
99 if (param.splittableInZ()) {
100 paramNew->setZmin(seg.zmin());
101 paramNew->setZmax(seg.zmax());
102 // If z changed adjust r in cone like volumes
103 adjustR(param, paramNew);
104 } else if (i == 1) {
105 std::cout << "Volume " << param.fullLabel() << " cannot be split in Z" << std::endl;
106 }
107 } else {
108 // vertical
109 if (param.splittableInR()) {
110 paramNew->setRmin(seg.rmin());
111 paramNew->setRmax(seg.rmax());
112 } else if (i == 1) {
113 std::cout << "Volume " << param.fullLabel() << " cannot be split in R" << std::endl;
114 }
115 }
116
117 if (seg.rotated()) {
118 // Often the -ve endcap region is created as the +ve endcap and then rotated. Therefore we have to reflect the z
119 // coords.
120 // Also have to turn off the needsRotation flag in case it was set.
121 //std::cout << "Segment " << i << " rotated " << paramNew->zmin() << " " << paramNew->zmax() <<std::endl;
122 double zminTmp = paramNew->zmin();
123 paramNew->setZmin(-paramNew->zmax());
124 paramNew->setZmax(-zminTmp);
125 paramNew->setNeedsRotation(false);
126 //std::cout << "After adjusted " << paramNew->zmin() << " " << paramNew->zmax() <<std::endl;
127 }
128
129 if (param.splittableInZ()) {
130 paramNew->reduceSize(m_epsilon); // safety gap between volumes
131 }
132
133 paramNew->setRegion(seg.label());
134 tmpServiceVec.push_back(paramNew);
135
136 paramNew->getShape();
137 volumeTotal += paramNew->volume();
138 //std::cout << i << ": volume: " << paramNew->volume() << std::endl;
139 }
140 //std::cout << "Total volume: " << volumeTotal << std::endl;
141 for (unsigned int i = 0; i < segments.size(); ++i) {
142 ServiceVolume* paramNew = tmpServiceVec[i];
143 if (segments.size() > 1) {
144 std::ostringstream ostr;
145 ostr << "_" << i + 1;
146 paramNew->addLabel(ostr.str());
147 }
148 paramNew->setOrigVolume(volumeTotal);
149 m_volumes.push_back(paramNew);
150 }
151 }
152
153// This takes care of cone like volumes and adjust the radius according to the adjusted z.
154 void
156 double z1 = param.zmin();
157 double z2 = param.zmax();
158 double z1New = paramNew->zmin();
159 double z2New = paramNew->zmax();
160 double rmin1 = param.rmin();
161 double rmin2 = param.rmin2();
162 double rmax1 = param.rmax();
163 double rmax2 = param.rmax2();
164
165 // Make sure z1 < z2
166 // as r1, r2 order assumes this
167 if (z1 > z2) std::swap(z1, z2);
168 if (z1New > z2New) std::swap(z1New, z2New);
169
170 // Avoid divide by zero.
171 if (z1 == z2) return;
172
173 if (z1 != z1New || z2 != z2New) {
174 if (rmin2 > 0 && rmax2 > 0 && (rmin1 != rmin2 || rmax1 != rmax2)) {
175 double slopeMin = (rmin2 - rmin1) / (z2 - z1);
176 double slopeMax = (rmax2 - rmax1) / (z2 - z1);
177
178 double rmin1New = (z1New - z1) * slopeMin + rmin1;
179 double rmin2New = (z2New - z1) * slopeMin + rmin1;
180
181 double rmax1New = (z1New - z1) * slopeMax + rmax1;
182 double rmax2New = (z2New - z1) * slopeMax + rmax1;
183
184 paramNew->setRmin(rmin1New);
185 paramNew->setRmax(rmax1New);
186 paramNew->setRmin2(rmin2New);
187 paramNew->setRmax2(rmax2New);
188 }
189 }
190 }
191} // end namespace
ChargedTracksWeightFilter::Spline::Point Point
unsigned int size() const
const Segment & getSegment(unsigned int i) const
const SegmentList & split(const Zone *, const Ray &)
const std::string & label() const
void adjustR(const ServiceVolume &param, ServiceVolume *paramNew)
void split(const Zone &zone, const ServiceVolume &origVolume)
Ray makeRay(const ServiceVolume &origVolume)
const std::vector< const ServiceVolume * > & splitAll(const Zone &zone, const std::vector< const ServiceVolume * > &)
void makeVolumes(const Zone *zone, const ServiceVolume &origVolume)
std::vector< const ServiceVolume * > m_volumes
void splitVolume(const Zone *zone, const ServiceVolume &vol)
=============================================================================
Message Stream Member.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)