ATLAS Offline Software
Loading...
Searching...
No Matches
VolumeSplitterUtils.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4
5
7#include "GeoModelKernel/GeoTube.h"
8#include "GeoModelKernel/GeoPcon.h"
9#include <iostream>
10
11namespace InDetDD {
12 const SegmentList&
13 SegmentSplitter::split(const Zone* zone, const Ray& ray) {
14 addChildSegment(zone, ray);
15 return m_segments;
16 }
17
18 Ray
19 SegmentSplitter::addChildSegment(const Zone* zone, const Ray& ray) {
20 //std::cout << "addChildSegment: " << zone->label() << " " << ray << std::endl;
21 // Point startPoint = ray.start();
22 // If start point is not yet know to be in current zone. We need to search children.
23 // If not in children searchPoint will return a copy of ray. Otherwise it will
24 // add segments of the child and return a ray that starts from the exit of the child.
25 Ray nextRay = ray;
26
27 if (!ray.foundStart()) {
28 nextRay = searchPoint(zone, ray);
29 }
30 bool exit = false;
31 while (nextRay.valid() && !exit) {
32 Point nextPoint = getNextBoundary(zone, nextRay);
33 addSegment(zone, nextRay.start(), nextPoint);
34
35 //std::cout << "Next boundary: " << nextPoint;
36 //if (nextPoint.last()) std::cout << " Last ";
37 //if (nextPoint.exit()) std::cout << " Exit ";
38 //if (nextPoint.child()) std::cout << " Child: " << nextPoint.child()->label();
39 //std::cout << std::endl;
40
41 if (nextPoint.last()) { // last indicates end of ray. ie ray ended before exit or child entry.
42 nextRay.setInvalid();
43 } else {
44 nextRay.set(nextPoint, nextRay.end());
45 }
46 exit = nextPoint.exit();
47 if (nextPoint.child()) {
48 nextRay = addChildSegment(nextPoint.child(), nextRay);
49 }
50 }
51 return nextRay;
52 }
53
54 void
55 SegmentSplitter::addSegment(const Zone* zone, const Point& start, const Point& end) {
56 m_segments.add(zone->label(), start, end, zone->rotated());
57 }
58
59 Point
60 SegmentSplitter::getNextBoundary(const Zone* zone, const Ray& ray) {
61 Point nextPoint; //invalid
62
63 // Search children
64 for (Zone::ChildIterator iter = zone->begin(); iter != zone->end(); ++iter) {
65 const Zone* child = *iter;
66 // return invalid if not crossed.
67 Point newPoint = child->findEntry(ray);
68 nextPoint = nearestPoint(newPoint, nextPoint);
69 }
70 //search exit
71 nextPoint = nearestPoint(zone->findExit(ray), nextPoint);
72 if (!nextPoint.valid()) {
73 // Return endpoint
74 return ray.end();
75 }
76 return nextPoint;
77 }
78
79 Point
80 SegmentSplitter::nearestPoint(const Point& point1, const Point& point2) {
81 if (!point2.valid()) return point1;
82
83 if (!point1.valid()) return point2;
84
85 if ((point2.r() == point1.r() && point2.z() < point1.z()) ||
86 (point2.z() == point1.z() && point2.r() < point1.r())) {
87 return point2;
88 }
89 return point1;
90 //return first point. If either invalid return the other.
91 // If both invalid return invalid
92 }
93
94 Ray
95 SegmentSplitter::searchPoint(const Zone* zone, const Ray& ray) {
96 // If not found in children return original ray.
97 //std::cout << "Searching for point " << ray.start() << std::endl;
98 Ray nextRay = ray;
99
100 for (Zone::ChildIterator iter = zone->begin(); iter != zone->end(); ++iter) {
101 const Zone* child = *iter;
102 if (child->inSide(ray.start())) {
103 //std::cout << "Point " << ray.start() << " found in zone " << child->label() << std::endl;
104 nextRay = addChildSegment(child, ray);
105 break;
106 }
107 }
108 nextRay.setFound();
109 return nextRay;
110 }
111
112 Zone::Zone(const std::string& label, bool rotated)
113 : m_label(label),
115 {}
116
118 for (ChildIterator iter = begin(); iter != end(); ++iter) {
119 delete *iter;
120 }
121 }
122
123 void
124 Zone::add(const Zone* zone) {
125 m_children.push_back(zone);
126 }
127
129 : Zone(label)
130 {}
131
132 bool
134 return true;
135 }
136
137 Point
139 // Will never be called.
140 return {};
141 }
142
143 Point
145 // Invalid means no exit point.
146 return {};
147 }
148
149 TubeZone::TubeZone(const std::string& label, double zmin, double zmax, double rmin, double rmax, bool rotated)
150 : Zone(label, rotated),
151 m_zmin(zmin),
152 m_zmax(zmax),
153 m_rmin(rmin),
154 m_rmax(rmax)
155 {}
156
157 TubeZone::TubeZone(const std::string& label, const GeoTube* shape, double zOffset, bool rotated)
158 : Zone(label, rotated),
159 m_zmin(zOffset - shape->getZHalfLength()),
160 m_zmax(zOffset + shape->getZHalfLength()),
161 m_rmin(shape->getRMin()),
162 m_rmax(shape->getRMax())
163 {}
164
165
166 bool
167 TubeZone::inSide(const Point& point) const {
168 return(inZ(point.z()) && inR(point.r()));
169 }
170
171 bool
172 TubeZone::inZ(double z) const {
173 return(z >= m_zmin && z < m_zmax);
174 }
175
176 bool
177 TubeZone::inR(double r) const {
178 return(r >= m_rmin && r < m_rmax);
179 }
180
181// Assume either vertical or horizontal.
182 Point
183 TubeZone::findEntry(const Ray& ray) const {
184 if (ray.horizontal()) {
185 if (inR(ray.start().r()) && ray.start().z() < m_zmin && ray.end().z() > m_zmin) {
186 Point p(m_zmin, ray.start().r());
187 p.setChild(this);
188 return p;
189 }
190 } else if (ray.vertical()) {
191 if (inZ(ray.start().z()) && ray.start().r() < m_rmin && ray.end().r() > m_rmin) {
192 Point p(ray.start().z(), m_rmin);
193 p.setChild(this);
194 return p;
195 }
196 } else {
197 std::cout << "Unexpected case" << std::endl;
198 }
199 // Return invalid point since doesn't intersect.
200 return {}; // invalid point
201 }
202
203// Assume already inside.
204 Point
205 TubeZone::findExit(const Ray& ray) const {
206 if (ray.horizontal()) {
207 if (ray.end().z() > m_zmax) {
208 Point p(m_zmax, ray.start().r());
209 p.setExit();
210 return p;
211 }
212 } else if (ray.vertical()) {
213 if (ray.end().r() > m_rmax) {
214 Point p(ray.start().z(), m_rmax);
215 p.setExit();
216 return p;
217 }
218 } else {
219 std::cout << "Unexpected case" << std::endl;
220 }
221 // ends with. Return invalid point.
222 return {};
223 }
224
225 PconZone::PconZone(const std::string& label, bool rotated)
226 : Zone(label, rotated)
227 {}
228
229 PconZone::PconZone(const std::string& label, const GeoPcon* shape, bool rotated)
230 : Zone(label, rotated) {
231 for (unsigned int i = 0; i < shape->getNPlanes(); ++i) {
232 addPlane(shape->getZPlane(i), shape->getRMinPlane(i), shape->getRMaxPlane(i));
233 }
234 }
235
236 void
237 PconZone::addPlane(double z, double rmin, double rmax) {
238 m_z.push_back(z);
239 m_rmin.push_back(rmin);
240 m_rmax.push_back(rmax);
241 }
242
243 bool
244 PconZone::inSide(const Point& point) const {
245 // Assume comes in pairs with same CLHEP::radii.
246 for (unsigned int i = 0; i + 1 < m_z.size(); i += 2) {
247 if (inZ(i, point.z()) && inR(i, point.r())) return true;
248 }
249 return false;
250 }
251
252 bool
253 PconZone::inZ(unsigned int i, double z) const {
254 return(z >= m_z[i] && z < m_z[i + 1]);
255 }
256
257 bool
258 PconZone::inR(unsigned int i, double r) const {
259 if (i >= m_z.size()) return false;
260
261 return(r >= m_rmin[i] && r < m_rmax[i]);
262 }
263
264// Assume either vertical or horizontal.
265 Point
266 PconZone::findEntry(const Ray& ray) const {
267 if (ray.horizontal()) {
268 for (unsigned int i = 0; i + 1 < m_z.size(); i += 2) {
269 if (inR(i, ray.start().r()) && ray.start().z() < m_z[i] && ray.end().z() > m_z[i]) {
270 Point p(m_z[i], ray.start().r());
271 p.setChild(this);
272 return p;
273 }
274 }
275 } else if (ray.vertical()) {
276 for (unsigned int i = 0; i + 1 < m_z.size(); i += 2) {
277 if (inZ(i, ray.start().z()) && ray.start().r() < m_rmin[i] && ray.end().r() > m_rmin[i]) {
278 Point p(ray.start().z(), m_rmin[i]);
279 p.setChild(this);
280 return p;
281 }
282 }
283 } else {
284 std::cout << "Unexpected case" << std::endl;
285 }
286 // Return invalid point since doesn't intersect.
287 return {}; // invalid point
288 }
289
290// Assume already inside.
291 Point
292 PconZone::findExit(const Ray& ray) const {
293 if (ray.horizontal()) {
294 for (unsigned int i = 0; i + 1 < m_z.size(); i += 2) {
295 if (inZ(i, ray.start().z()) && ray.end().z() > m_z[i + 1] && !inR(i + 2, ray.start().r())) {
296 Point p(m_z[i + 1], ray.start().r());
297 p.setExit();
298 return p;
299 }
300 }
301 } else if (ray.vertical()) {
302 for (unsigned int i = 0; i + 1 < m_z.size(); i += 2) {
303 if (inZ(i, ray.start().z()) && ray.end().r() > m_rmax[i]) {
304 Point p(ray.start().z(), m_rmax[i]);
305 p.setExit();
306 return p;
307 }
308 }
309 } else {
310 std::cout << "Unexpected case" << std::endl;
311 }
312 // ends with. Return invalid point.
313 return {};
314 }
315
317 : m_valid(false),
318 m_found(false),
319 m_horizontal(false),
320 m_vertical(false)
321 {}
322
323 Ray::Ray(const Point& start, const Point& end)
324 : m_valid(true),
325 m_found(false),
326 m_start(start),
327 m_end(end) {
328 m_end.setLast();
329 setDirection();
330 }
331
332 void
333 Ray::set(const Point& start, const Point& end) {
334 m_start = start;
335 m_end = end;
336 setDirection();
337 }
338
339 void
341 m_vertical = (m_start.z() == m_end.z());
342 m_horizontal = (m_start.r() == m_end.r());
343 if (m_vertical && m_horizontal) {
344 m_vertical = false;
345 m_horizontal = false;
346 }
347 }
348
350 : m_valid(false),
351 m_exit(false),
352 m_last(false),
353 m_z(0),
354 m_r(0),
355 m_child(nullptr)
356 {}
357
358 Point::Point(double z, double r)
359 : m_valid(true),
360 m_exit(false),
361 m_last(false),
362 m_z(z),
363 m_r(r),
364 m_child(nullptr)
365 {}
366
367 Segment::Segment(const std::string& label, const Point& start, const Point& end, bool rotated)
368 : m_label(label),
370 m_zmin(start.z()),
371 m_zmax(end.z()),
372 m_rmin(start.r()),
373 m_rmax(end.r())
374 {}
375
376 void
377 SegmentList::add(const std::string& label, const Point& start, const Point& end, bool rotated) {
378 m_segments.emplace_back(label, start, end, rotated);
379 }
380
381 void
382 SegmentList::add(const Segment& segment) {
383 m_segments.push_back(segment);
384 }
385
386 bool
388 if (size() > 0) {
389 const Segment& seg = m_segments[0];
390 return(seg.rmin() == seg.rmax());
391 }
392 // Not relevant if array empty.
393 return true;
394 }
395
396 void
398 for (std::vector<Segment>::const_iterator iter = m_segments.begin(); iter != m_segments.end(); ++iter) {
399 iter->print();
400 }
401 }
402
403 void
405 std::cout << m_label << " "
406 << m_zmin << " "
407 << m_zmax << " "
408 << m_rmin << " "
409 << m_rmax
410 << std::endl;
411 }
412
413 std::ostream&
414 operator << (std::ostream& os, const InDetDD::Ray& ray) {
415 if (!ray.valid()) {
416 os << "INVALID";
417 } else {
418 os << ray.start() << " --> " << ray.end();
419 }
420 return os;
421 }
422
423 std::ostream&
424 operator << (std::ostream& os, const InDetDD::Point& point) {
425 if (!point.valid()) {
426 os << "INVALID";
427 } else {
428 os << "(" << point.z() << ", " << point.r() << ")";
429 }
430 return os;
431 }
432}
#define z
PconZone(const std::string &label, bool rotated=false)
virtual Point findExit(const Ray &ray) const
std::vector< double > m_z
std::vector< double > m_rmax
virtual bool inSide(const Point &point) const
std::vector< double > m_rmin
bool inZ(unsigned int i, double z) const
virtual Point findEntry(const Ray &ray) const
void addPlane(double z, double rmin, double rmax)
bool inR(unsigned int i, double r) const
const Zone * child() const
bool valid() const
bool vertical() const
void set(const Point &start, const Point &end)
const Point & end() const
const Point & start() const
bool horizontal() const
bool foundStart() const
void add(const std::string &label, const Point &start, const Point &end, bool rotated=false)
unsigned int size() const
std::vector< Segment > m_segments
void addSegment(const Zone *, const Point &start, const Point &end)
const SegmentList & split(const Zone *, const Ray &)
Ray searchPoint(const Zone *zone, const Ray &ray)
Point getNextBoundary(const Zone *, const Ray &)
Point nearestPoint(const Point &point1, const Point &point2)
Ray addChildSegment(const Zone *, const Ray &)
const std::string & label() const
Segment(const std::string &label, const Point &start, const Point &end, bool rotated=false)
TubeZone(const std::string &label, double zmin, double zmax, double rmin, double rmax, bool rotated=false)
virtual bool inSide(const Point &point) const
virtual Point findExit(const Ray &ray) const
bool inR(double r) const
bool inZ(double z) const
virtual Point findEntry(const Ray &ray) const
UnboundedZone(const std::string &label)
virtual Point findExit(const Ray &ray) const
virtual Point findEntry(const Ray &ray) const
virtual bool inSide(const Point &point) const
ChildIterator begin() const
void add(const Zone *)
bool rotated() const
std::vector< constZone * >::const_iterator ChildIterator
const std::string & label() const
virtual bool inSide(const Point &point) const =0
virtual Point findEntry(const Ray &ray) const =0
std::vector< const Zone * > m_children
ChildIterator end() const
Zone(const std::string &label, bool rotated=false)
int r
Definition globals.cxx:22
std::string label(const std::string &format, int i)
Definition label.h:19
Message Stream Member.
std::ostream & operator<<(std::ostream &os, const SiCellId &cellId)
Definition SiCellId.cxx:8
Point(double x_, double y_, double slope_)
Single point and slope to next point.