ATLAS Offline Software
Loading...
Searching...
No Matches
InDetProjHelper.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class InDetProjHelper //
9// //
10// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11// Initial version: February 2008 //
12// //
14
17#include "VP1Base/VP1Msg.h"
18
20
21#ifdef BUILDVP1LIGHT
22 #include "CLHEP/Units/SystemOfUnits.h"
23 #define SYSTEM_OF_UNITS CLHEP
24#else
25 #include "GaudiKernel/SystemOfUnits.h"
26 #define SYSTEM_OF_UNITS Gaudi::Units
27#endif
28
29//Fixme: Epsilon in projections! (at least take surface thickness into account!)
30
31//____________________________________________________________________
48
49//____________________________________________________________________
66
67//____________________________________________________________________
84
85//____________________________________________________________________
87public:
89
90 //Applicable projections:
91 InDetProjFlags::InDetProjPartsFlags parts;
92
93 //The parameters:
94 double surfacethickness = 0.0;
96 double barrel_inner_radius = 0.0;
97 double barrel_outer_radius = 0.0;
98 double barrel_posneg_z = 0.0;
99 double endcap_surface_z = 0.0;
106
107 //Parameters of maximal cylinder covering all enabled parts of
108 //detector:
109 double covercyl_zmin = 0.0;
110 double covercyl_zmax = 0.0;
111 double covercyl_rmin = 0.0;
112 double covercyl_rmax = 0.0;
113
114// //Helper methods:
115 void lineCircleIntersection( const Amg::Vector3D&a, const Amg::Vector3D&b,const double& r,
116 double & u1, double& u2 ) const;
117
118 //Clip segments to cylinders and planes:
119 void movePoint1ToZPlaneAndPoint2( Amg::Vector3D& p1, const Amg::Vector3D& p2, const double& z ) const;
120 bool clipSegmentToZInterval( Amg::Vector3D&a, Amg::Vector3D&b, const double& zmin, const double& zmax ) const;
121 void movePoint1ToInfiniteCylinderAndPoint2( Amg::Vector3D&p1, const Amg::Vector3D&p2, const double& r ) const;
123 const double& rmin, const double& rmax,
124 Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const;
125
127 const double& rmin, const double& rmax,
128 const double& zmin, const double& zmax,
129 Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const;
130
131 void clipPathToHollowCylinder( const std::vector<Amg::Vector3D >& in,
132// Amg::SetVectorVector3D& out,//<- where clipped pieces of the paths will be appended.
133 Amg::SetVectorVector3D& out,//<- where clipped pieces of the paths will be appended.
134 const double& rmin, const double& rmax,
135 const double& zmin, const double& zmax ) const;
136
137 bool touchesHollowCylinder( const std::vector<Amg::Vector3D >& path,
138 const double& rmin, const double& rmax,
139 const double& zmin, const double& zmax ) const;
140 //Project points to cylinders and planes:
141 void projectPathToInfiniteCylinder( const std::vector<Amg::Vector3D >& in,
142 Amg::SetVectorVector3D& outset, const double& r ) const;
143 void projectPathToZPlane( const std::vector<Amg::Vector3D >& in,
144 Amg::SetVectorVector3D& outset, const double& z ) const;
145 void projectPathToZPlane_specialZtoR( const std::vector<Amg::Vector3D >& in,
146 Amg::SetVectorVector3D& outset, const double& z ) const;
147
148};
149
150//____________________________________________________________________
151InDetProjHelper::InDetProjHelper( double surfacethickness,
152 double data_disttosurface_epsilon,
153 double barrel_inner_radius,
154 double barrel_outer_radius,
155 double barrel_posneg_z,
156 double endcap_surface_z,
157 double endcap_surface_length,
158 double endcap_inner_radius,
159 double endcap_outer_radius,
160 double endcap_zasr_innerradius,
161 double endcap_zasr_endcapz_begin,
162 double endcap_zasr_squeezefact,
163 IVP1System* sys )
164 : VP1HelperClassBase(sys,"InDetProjHelper"), m_d(new Imp)
165{
166 m_d->theclass = this;
167
168 m_d->surfacethickness = surfacethickness;
169 m_d->data_disttosurface_epsilon = data_disttosurface_epsilon;
170 m_d->barrel_inner_radius = barrel_inner_radius;
171 m_d->barrel_outer_radius = barrel_outer_radius;
172 m_d->barrel_posneg_z = barrel_posneg_z;
173 m_d->endcap_surface_z = endcap_surface_z;
174 m_d->endcap_surface_length = endcap_surface_length;
175 m_d->endcap_inner_radius = endcap_inner_radius;
176 m_d->endcap_outer_radius = endcap_outer_radius;
177 m_d->endcap_zasr_innerradius = endcap_zasr_innerradius;
178 m_d->endcap_zasr_endcapz_begin = endcap_zasr_endcapz_begin;
179 m_d->endcap_zasr_squeezefact = endcap_zasr_squeezefact;
180
182 m_d->covercyl_zmin = 0.0;
183 m_d->covercyl_zmax = 0.0;
184 m_d->covercyl_rmin = 0.0;
185 m_d->covercyl_rmax = 0.0;
186
187}
188
189//____________________________________________________________________
194
195//____________________________________________________________________
196InDetProjFlags::InDetProjPartsFlags InDetProjHelper::setParts( InDetProjFlags::InDetProjPartsFlags newparts )
197{
198 if ( m_d->parts==newparts )
199 return m_d->parts;
200 InDetProjFlags::InDetProjPartsFlags oldparts = m_d->parts;
201 m_d->parts = newparts;
202
203 //Update parameters of smallest cylinder covering all enabled clip volumes.
204 if (m_d->parts == InDetProjFlags::NoProjections) {
205 m_d->covercyl_zmin = 0.0;
206 m_d->covercyl_zmax = 0.0;
207 m_d->covercyl_rmin = 0.0;
208 m_d->covercyl_rmax = 0.0;
209 return oldparts;
210 }
211
212 bool no_ec_neg = !( m_d->parts & InDetProjFlags::EndCap_AllNeg );
213 bool no_ec_pos = !( m_d->parts & InDetProjFlags::EndCap_AllPos );
214 bool no_brl_neg = !( m_d->parts & InDetProjFlags::Barrel_AllNeg );
215 bool no_brl_pos = !( m_d->parts & InDetProjFlags::Barrel_AllPos );
216 bool barrel = m_d->parts & InDetProjFlags::Barrel_All;
217 bool endcap = m_d->parts & InDetProjFlags::EndCap_All;
218
219 m_d->covercyl_zmin = - m_d->endcap_surface_z - 0.5*m_d->endcap_surface_length;
220 if ( no_ec_neg ) {
221 m_d->covercyl_zmin = - m_d->barrel_posneg_z;
222 if ( no_brl_neg ) {
223 m_d->covercyl_zmin = 0.0;
224 if ( no_brl_pos ) {
225 m_d->covercyl_zmin = m_d->barrel_posneg_z;
226 if ( no_ec_pos )
227 m_d->covercyl_zmin = m_d->endcap_surface_z + 0.5*m_d->endcap_surface_length + 1.0e99;
228 }
229 }
230 }
231 m_d->covercyl_zmax = m_d->endcap_surface_z + 0.5*m_d->endcap_surface_length;
232 if ( no_ec_pos ) {
233 m_d->covercyl_zmax = m_d->barrel_posneg_z;
234 if ( no_brl_pos ) {
235 m_d->covercyl_zmax = 0.0;
236 if ( no_brl_neg ) {
237 m_d->covercyl_zmax = - m_d->barrel_posneg_z;
238 if ( no_ec_neg )
239 m_d->covercyl_zmax = - m_d->endcap_surface_z - 0.5*m_d->endcap_surface_length - 1.0e99;
240 }
241 }
242 }
243 if ( m_d->covercyl_zmin >= m_d->covercyl_zmax )
244 m_d->covercyl_zmin = m_d->covercyl_zmax = 0;
245
246 if ( barrel && endcap ) {
247 m_d->covercyl_rmin = std::min(m_d->barrel_inner_radius,m_d->endcap_inner_radius);
248 m_d->covercyl_rmax = std::max(m_d->barrel_outer_radius,m_d->endcap_outer_radius);
249 } else {
250 if (barrel) {
251 m_d->covercyl_rmin = m_d->barrel_inner_radius;
252 m_d->covercyl_rmax = m_d->barrel_outer_radius;
253 } else if (endcap) {
254 m_d->covercyl_rmin = m_d->endcap_inner_radius;
255 m_d->covercyl_rmax = m_d->endcap_outer_radius;
256 } else {
257 message("Unforeseen execution path encountered.");
258 m_d->covercyl_rmin = 0;
259 m_d->covercyl_rmax = 0;
260 }
261 }
262 if ( m_d->covercyl_rmin >= m_d->covercyl_rmax )
263 m_d->covercyl_rmin = m_d->covercyl_rmax = 0;
264 return oldparts;
265}
266
267//____________________________________________________________________
268InDetProjFlags::InDetProjPartsFlags InDetProjHelper::parts() const
269{
270 return m_d->parts;
271}
272
273//____________________________________________________________________
274void InDetProjHelper::clipPath( const std::vector<Amg::Vector3D >& path,
275 Amg::SetVectorVector3D& resulting_subpaths ) const
276{
277 clipPath(path,resulting_subpaths,resulting_subpaths,resulting_subpaths,resulting_subpaths);
278}
279
280//____________________________________________________________________
281void InDetProjHelper::clipPath( const std::vector<Amg::Vector3D >& path,
282 Amg::SetVectorVector3D& resulting_subpaths_barrelA,
283 Amg::SetVectorVector3D& resulting_subpaths_barrelC,
284 Amg::SetVectorVector3D& resulting_subpaths_endcapA,
285 Amg::SetVectorVector3D& resulting_subpaths_endcapC ) const
286{
287 if (VP1Msg::verbose())
288 messageVerbose("clipPath(..) called. Input path has "+QString::number(path.size())+" points.");
289
290 resulting_subpaths_barrelA.clear();
291 resulting_subpaths_barrelC.clear();
292 resulting_subpaths_endcapA.clear();
293 resulting_subpaths_endcapC.clear();
294
295 //Fixme: If verbose - perform sanity check of input data (check for NAN's).
296 if (m_d->parts == InDetProjFlags::NoProjections ) {
297 if (VP1Msg::verbose())
298 messageVerbose("All projections currently off.");
299 return;
300 }
301 if ( path.size()<2 ) {
302 if (VP1Msg::verbose())
303 messageVerbose("Input path too short.");
304 return;
305 }
306
307 // Find the clipped path's in all of the enabled detector parts.
308
309 //For efficiency, we first clip the path to the smallest
310 //axis-aligned cylinder containing all of the projective volumes
311 Amg::SetVectorVector3D paths_clipped;
312 m_d->clipPathToHollowCylinder( path, paths_clipped,
313 m_d->covercyl_rmin, m_d->covercyl_rmax,
314 m_d->covercyl_zmin, m_d->covercyl_zmax );
315
316 if (paths_clipped.empty()) {
317 if (VP1Msg::verbose())
318 messageVerbose("Path entirely outside clip volumes.");
319 return;
320 }
321
322 const bool enabled_brlA = m_d->parts & InDetProjFlags::Barrel_AllPos;
323 const bool enabled_brlC = m_d->parts & InDetProjFlags::Barrel_AllNeg;
324 const bool enabled_ecA = m_d->parts & InDetProjFlags::EndCap_AllPos;
325 const bool enabled_ecC = m_d->parts & InDetProjFlags::EndCap_AllNeg;
326
327 //Special case: If exactly one of the four parts is enabled, we already have our result:
328 if ( ( (enabled_brlA?1:0) + (enabled_brlC?1:0) + (enabled_ecA?1:0) + (enabled_ecC?1:0) ) == 1 ) {
329 if (enabled_brlA) {
330 resulting_subpaths_barrelA = paths_clipped;
331 if (VP1Msg::verbose())
332 messageVerbose("clipPath(..) only brlA enabled. Returning.");
333 return;
334 }
335 if (enabled_brlC) {
336 resulting_subpaths_barrelC = paths_clipped;
337 if (VP1Msg::verbose())
338 messageVerbose("clipPath(..) only brlC enabled. Returning.");
339 return;
340 }
341 if (enabled_ecA) {
342 resulting_subpaths_endcapA = paths_clipped;
343 if (VP1Msg::verbose())
344 messageVerbose("clipPath(..) only ecA enabled. Returning.");
345 return;
346 }
347 if (enabled_ecC) {
348 resulting_subpaths_endcapC = paths_clipped;
349 if (VP1Msg::verbose())
350 messageVerbose("clipPath(..) only ecC enabled. Returning.");
351 return;
352 }
353 }
354
355
356 //For each of the segments, we then find its clipped parts inside
357 //the four detector volumes: BarrelA, BarrelC, EndCapA, EndCapC.
358 // Amg::SetVectorVector3D paths_brlA, paths_brlC, paths_ecA,paths_ecC;
359 Amg::SetVectorVector3D::const_iterator it, itE(paths_clipped.end());
360 for (it = paths_clipped.begin();it!=itE;++it) {
361 if ( enabled_brlA )
362 m_d->clipPathToHollowCylinder( *it, resulting_subpaths_barrelA, m_d->barrel_inner_radius, m_d->barrel_outer_radius, 0, m_d->barrel_posneg_z );
363 if ( enabled_brlC )
364 m_d->clipPathToHollowCylinder( *it, resulting_subpaths_barrelC, m_d->barrel_inner_radius, m_d->barrel_outer_radius, - m_d->barrel_posneg_z, 0 );
365 if ( enabled_ecA )
366 m_d->clipPathToHollowCylinder( *it, resulting_subpaths_endcapA, m_d->endcap_inner_radius, m_d->endcap_outer_radius,
367 m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 );
368 if ( enabled_ecC )
369 m_d->clipPathToHollowCylinder( *it, resulting_subpaths_endcapC, m_d->endcap_inner_radius, m_d->endcap_outer_radius,
370 - m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, - m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 );
371 }
372
373 messageVerbose("clipPath(..) end.");
374 //Fixme: If verbose: sanity check on output!
375}
376
377//____________________________________________________________________
379{
380 double dx(p2.x()-p1.x()), dy(p2.y()-p1.y()), dz(p2.z()-p1.z());
381 if (dz==0.0) {
382 theclass->message("movePoint1ToZPlaneAndPoint2 Error: Points have same z!!");
383 return;
384 }
385 double s( (z-p1.z())/dz );
386 p1 = Amg::Vector3D{p1.x()+dx*s, p1.y()+dy*s, z};
387}
388
389//____________________________________________________________________
391 const double& zmin, const double& zmax ) const
392{
393 if (a.z()<zmin) {
394 if (b.z()<zmin)//both <zmin
395 return false;
396 //a<zmin, b>=zmin:
398 if (b.z()>zmax)
400 return true;
401 } else {
402 if (b.z()<zmin) {
403 //a>=zmin, b<zmin
405 if (a.z()>zmax)
407 return true;
408 } else {
409 //Both are > zmin
410 if (a.z()>zmax) {
411 if (b.z()>zmax)
412 return false;
414 return true;
415 } else {
416 //zmin<=a<=zmax, b>=zmin
417 if (b.z()>zmax)
419 return true;
420 }
421 }
422 }
423}
424
425//____________________________________________________________________
427{
428 //Fixme: what happens here if we don't cross? And how can we be sure
429 //that we don't move FURTHER than the other point? (i.e. if the
430 //infinite line with p1 and p2 crosses, but the segment p1p2 does
431 //not!?
432
433// double p1r(p1.r());
434// double dr(p2.r()-p1r);
435 double p1r( p1.mag() );
436 double dr( p2.mag() -p1r );
437
438 if (dr==0.0) {
439 theclass->message("movePoint1ToInfiniteCylinderAndPoint2 Error: Points have same r!!");
440 return;
441 }
442 double s((r-p1r)/dr);
443 double t(1.0-s);
444 p1 = Amg::Vector3D{p1.x()*t + p2.x()*s, p1.y()*t + p2.y()*s, p1.z()*t + p2.z()*s };
445
446}
447
448//____________________________________________________________________
450 double & u1, double& u2 ) const
451{
452 const double dx = b.x()-a.x();
453 const double dy = b.y()-a.y();
454 double A = dx*dx+dy*dy;
455 if (A==0.0) {
456 //That's not a line => no intersections unless points are exactly on circumference!
457 u1 = u2 = ( a.x()*a.x()+a.y()*a.y() == r*r ? 0.0 : 1.0e99 );
458 return;
459 }
460 double B = 2.0*( a.x()*dx + a.y()*dy );
461 double C = a.x()*a.x()+a.y()*a.y() - r*r;
462 double D = B*B-4*A*C;
463
464 if (D>0.0) {
465 //Intersections
466 double sqrtD = sqrt(D);
467 u1 = 0.5 * ( -B - sqrtD) / A;
468 u2 = 0.5 * ( -B + sqrtD) / A;
469 } else if (D<0.0) {
470 //No intersections:
471 u1 = u2 = -1.0e99;
472 } else {
473 //intersection in one point
474 u1 = u2 = -0.5*B/A;
475 }
476
477}
478
479//____________________________________________________________________
481 const double& rmin, const double& rmax,
482 Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const
483{
484 //* if returns false: segment does not intersect hollow cylinder - do
485 // NOT use returned points for anything.
486 //* if returns true and seg2_a==seg2_b: Use "a" and "b" for the clipped segment.
487 //* if returns true and seg2_a!=seg2_b: The clip resulting in TWO new segments
488 // (it was cut in two by the inner wall).
489
490 //Fixme: Stuff like the following!:
491 // if (VP1SanityCheck::enabled()) {
492 // VP1SanityCheck::beginGroup("InDetProjHelper::Imp::clipSegmentToInfiniteHollowCylinder");
493 // VP1SanityCheck::positiveParameter("rmin",rmin);
494 // VP1SanityCheck::positiveParameter("rmax",rmax);
495 // VP1SanityCheck::parameter("point a",a);
496 // VP1SanityCheck::parameter("point b",b);
497 // VP1SanityCheck::endGroup();
498 // }
499 const double ar2 = a.x()*a.x()+a.y()*a.y();
500 const double br2 = b.x()*b.x()+b.y()*b.y();
501 const double rmin2 = rmin*rmin;
502 //We might be inside inner wall:
503 if (ar2 <= rmin2 && br2 <= rmin2 ) {
504 // seg2_a=seg2_b;
505// if (VP1Msg::verbose())
506// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Segment entirely inside rmin.");
507 return false;
508 }
509 //Some fast checks for being outside:
510 if ( (a.x()<=-rmax&&b.x()<=-rmax) || (a.x()>=rmax&&b.x()>=rmax) || (a.y()<=-rmax&&b.y()<=-rmax)|| (a.y()>=rmax&&b.y()>=rmax) ) {
511// if (VP1Msg::verbose())
512// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Segment clearly entirely outside outside rmax.");
513// seg2_a=seg2_b;
514 return false;
515 }
516
517 //If a==b (apart from perhaps z coord), the check is simple:
518 const double dx = b.x()-a.x();
519 const double dy = b.y()-a.y();
520 const double rmax2 = rmax*rmax;
521 if (dx==0.0&&dy==0.0) {
522 //Apparently a==b (apart from perhaps z coord).
523// if (VP1Msg::verbose())
524// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder a==b.");
525 return ar2<=rmax2;
526 }
527 //Find point which is closest to the z-axis and on the segment:
528 const double u = - (a.y()*dy+a.x()*dx)/(dx*dx+dy*dy);
529 const double px = ( u <= 0 ? a.x() : ( u >= 1 ? b.x() : a.x()+u*dx ) );
530 const double py = ( u <= 0 ? a.y() : ( u >= 1 ? b.y() : a.y()+u*dy ) );
531 const double pr2 = px*px+py*py;
532 if (pr2>=rmax2) {
533// if (VP1Msg::verbose())
534// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder segment entirely outside rmax.");
535// seg2_a=seg2_b;
536 return false;
537
538
539 }
540 //We now know that the segment does indeed intersect the clip volume.
541 seg2_a=seg2_b;//signature of just one segment:
542
543 if (pr2>=rmin2&&ar2<=rmax2&&br2<=rmax2) {
544 //We are actually already entirely inside the clip volume.
545// if (VP1Msg::verbose())
546// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder segment entirely inside clip volume."
547// " (pr="+QString::number(sqrt(pr2))+", ar="+QString::number(sqrt(ar2))
548// +", br="+QString::number(sqrt(br2))+")");
549 return true;
550 }
551
552 //First we simply clip to the outer cylinder:
553 if (ar2>rmax2||br2>rmax2) {
554 //We need to clip a-b to be inside the outer cylinder.
555 //Find intersections:
556 double u1, u2;
557 lineCircleIntersection(a,b,rmax,u1,u2);//u1<=u2 !
558 if (u1==u2) {
559 //We are just touching - but we already tested against this!
560 theclass->message("This should never happen(1).");
561 // seg2_a=seg2_b;
562 return false;
563 }
564 Amg::Vector3D asave(a);
565 if (u1>0&&u1<1) {
566 //move a to a+u1*(b-a)
567 a = a+u1*(b-a);
568// if (VP1Msg::verbose())
569// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder sliding a towards b, at the rmax circle.");
570 }
571 if (u2>0&&u2<1) {
572 //move b to a+u2*(b-a)
573 b = asave+u2*(b-asave);
574// if (VP1Msg::verbose())
575// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder sliding b towards a, at the rmax circle.");
576 }
577 }
578
579 if (pr2>=rmin2) {
580// if (VP1Msg::verbose())
581// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder remaining segment is now entirely inside.");
582 return true;
583 }
584 //Ok, we know that we intersect the inner cylinder
585 double u1, u2;
586 lineCircleIntersection(a,b,rmin,u1,u2);//u1<=u2 !
587
588 if (u1>0&&u1<1) {
589 if (u2>0&&u2<1) {
590 //We intersect twice. Thus, two line segments:
591 //a to "a+u1*(b-a)" and "a+u2*(b-a)" to b
592 //a=a;
593 seg2_b = b;
594 b = a+u1*(seg2_b-a);
595 seg2_a=a+u2*(seg2_b-a);
596// if (VP1Msg::verbose())
597// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Two resulting segments!.");
598 return true;
599 }
600 b = a+u1*(b-a);
601// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder One resulting segment (b->a)!.");
602 return true;
603 }
604 if (u2>0&&u2<1)
605 a = a+u2*(b-a);
606// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder One resulting segment (a->b)!.");
607 return true;
608}
609
610
611
612//____________________________________________________________________
614 const double& rmin, const double& rmax,
615 const double& zmin, const double& zmax,
616 Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const
617{
618 // seg2_a = seg2_b;//test
619// if (VP1Msg::verbose()) {
620// theclass->messageVerbose("clipSegmentToHollowCylinder called with:");
621// theclass->messageVerbose(" rmin = "+QString::number(rmin));
622// theclass->messageVerbose(" rmax = "+QString::number(rmax));
623// theclass->messageVerbose(" zmin = "+QString::number(zmin));
624// theclass->messageVerbose(" zmax = "+QString::number(zmax));
625// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")");
626// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")");
627// }
628 if (!clipSegmentToZInterval(a,b,zmin,zmax)) {
629 // seg2_a = seg2_b;
630// if (VP1Msg::verbose())
631// theclass->messageVerbose("clipSegmentToHollowCylinder segment outside z-interval.");
632 return false;
633 }
634// if (VP1Msg::verbose()) {
635// theclass->messageVerbose("clipSegmentToHollowCylinder parameters after clipSegmentToZInterval:");
636// if (a.z()<zmin||a.z()>zmax)
637// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToZInterval call (a_z wrong).");
638// if (b.z()<zmin||b.z()>zmax)
639// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToZInterval call (b_z wrong).");
640// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")");
641// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")");
642// }
643 if (!clipSegmentToInfiniteHollowCylinder(a,b,rmin,rmax,seg2_a,seg2_b)) {
644 // seg2_a = seg2_b;
645// if (VP1Msg::verbose())
646// theclass->messageVerbose("clipSegmentToHollowCylinder segment outside infinite hollow cylinder.");
647 return false;
648 }
649// if (VP1Msg::verbose()) {
650// theclass->messageVerbose("clipSegmentToHollowCylinder parameters after clipSegmentToInfiniteHollowCylinder:");
651// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")");
652// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")");
653// const double ar2 = a.x()*a.x()+a.y()*a.y();
654// const double br2 = b.x()*b.x()+b.y()*b.y();
655// if (ar2<rmin*rmin||ar2>rmax*rmax)
656// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToInfiniteHollowCylinder call (a wrong).");
657// if (br2<rmin*rmin||br2>rmax*rmax)
658// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToInfiniteHollowCylinder call (b wrong).");
659// theclass->messageVerbose("clipSegmentToHollowCylinder returning.");
660// }
661
662 return true;
663}
664
665//____________________________________________________________________
666void InDetProjHelper::Imp::clipPathToHollowCylinder( const std::vector<Amg::Vector3D >& in,
667// Amg::SetVectorVector3D& out,
669 const double& rmin, const double& rmax,
670 const double& zmin, const double& zmax ) const
671{
672// if (VP1Msg::verbose()) {
673// theclass->messageVerbose("clipPathToHollowCylinder called");
674// theclass->messageVerbose(" ===> rmin = "+QString::number(rmin));
675// theclass->messageVerbose(" ===> rmax = "+QString::number(rmax));
676// theclass->messageVerbose(" ===> zmin = "+QString::number(zmin));
677// theclass->messageVerbose(" ===> zmax = "+QString::number(zmax));
678// }
679
680 out.clear();
681 if (rmin>=rmax||rmin<0||zmin>=zmax) {
682 theclass->message("clipPathToHollowCylinder Error: Non-sensical cylinder parameters!");
683 return;
684 }
685 const unsigned n=in.size();
686 if (n<2)
687 return;
688
690 Amg::Vector3D seg2_a,seg2_b;
691 std::vector<Amg::Vector3D > v;
692 for (unsigned i = 1; i<n; ++i) {
693 // theclass->messageVerbose("clipPathToHollowCylinder -> dealing with segment "+QString::number(i-1)+"->"+QString::number(i));
694
695 a = in.at(i-1);//fixme: .at()->[]
696 b = in.at(i);
697 if ( clipSegmentToHollowCylinder( a,b,rmin,rmax,zmin,zmax,seg2_a,seg2_b ) ) {
698 if (v.empty()) {
699 v.push_back(a);
700 v.push_back(b);
701 if (seg2_a!=seg2_b) {
702 out.insert(v);
703 v.clear();
704 v.push_back(seg2_a);
705 v.push_back(seg2_b);
706 }
707 } else {
708 //We know that previous segment was also touching. Therefore
709 //it must necessarily be true that v.back()==a.
710 if ( v.back() != a ) {
711 theclass->messageDebug("ERROR: Inconsistency found while building clip part");//Fixme: downgrade to messageDebug for now, but need to understand this!
712 out.insert(v);
713 v.clear();
714 v.push_back(a);
715 }
716 v.push_back(b);
717 if (seg2_a!=seg2_b) {
718 out.insert(v);
719 v.clear();
720 v.push_back(seg2_a);
721 v.push_back(seg2_b);
722 }
723 }
724 } else {
725// theclass->messageVerbose("Segment does not touch");
726 //Segment doesn't touch cylinder volume - flush part currently building if any.
727 if (!v.empty()) {
728 out.insert(v);
729 v.clear();
730 }
731 }
732 }
733 if (!v.empty()) {
734// theclass->messageDebug("v not empty");
735 out.insert(v);
736 }
737}
738
739//____________________________________________________________________
740void InDetProjHelper::Imp::projectPathToInfiniteCylinder( const std::vector<Amg::Vector3D >& in,
741 Amg::SetVectorVector3D& outset, const double& r ) const
742{
743 std::vector<Amg::Vector3D > out(in);
744 std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end());
745 double s;
746 for (;it!=itE;++it) {
747 if ( it->x()==0.0 && it->y()==0.0 ) {
748 theclass->message("ERROR: Point has x==0 and y==0. Ambiguous projection of point.");
749
750// it->setX(1.0);
751 it->x() = 1.0;
752 }
753 s = r / sqrt( it->x()*it->x()+it->y()*it->y() );
754
755// it->setX(it->x()*s);
756// it->setY(it->y()*s);
757 it->x() = it->x()*s;
758 it->y() = it->y()*s;
759
760 }
761 outset.insert(out);
762}
763
764//____________________________________________________________________
765void InDetProjHelper::Imp::projectPathToZPlane( const std::vector<Amg::Vector3D >& in,
766 Amg::SetVectorVector3D& outset, const double& z ) const
767{
768 std::vector<Amg::Vector3D > out(in);
769 std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end());
770 for (;it!=itE;++it) {
771// it->setZ(z);
772 it->z() = z;
773 }
774 outset.insert(out);
775}
776
777
778//____________________________________________________________________
780 const double& planeZ,
781 const double& planeRBegin,
782 const double& endcapZBegin,
783 const double& squeezeFactor )
784{
785 if ( p.x()==0.0 && p.y()==0.0 ) {
786 VP1Msg::message("InDetProjHelper::transformECPointToZPlane_specialZtoR ERROR: "
787 "Point has x==0 and y==0. Ambiguous projection of point.");
788// p.setX(1.0);
789 p.x() = 1.0;
790 }
791 const double r = planeRBegin + (fabs(p.z())-endcapZBegin)/squeezeFactor;
792 const double s = r / sqrt( p.x()*p.x()+p.y()*p.y() );
793// p.setX(p.x()*s);
794// p.setY(p.y()*s);
795// p.setZ(planeZ);
796 p.x() = p.x()*s;
797 p.y() = p.y()*s;
798 p.z() = planeZ;
799}
800
801//____________________________________________________________________
802void InDetProjHelper::Imp::projectPathToZPlane_specialZtoR( const std::vector<Amg::Vector3D >& in,
804 const double& z ) const
805{
806 std::vector<Amg::Vector3D > out(in);
807 std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end());
808 for (;it!=itE;++it)
810 z,
814 outset.insert(out);
815}
816
817//____________________________________________________________________
818void InDetProjHelper::projectPath( const std::vector<Amg::Vector3D >& path,
819 Amg::SetVectorVector3D& resulting_projs ) const
820{
821 projectPath(path,resulting_projs,resulting_projs,resulting_projs,resulting_projs);
822}
823
824//____________________________________________________________________
825void InDetProjHelper::projectPath( const std::vector<Amg::Vector3D >& path,
826 Amg::SetVectorVector3D& resulting_projections_barrelA,
827 Amg::SetVectorVector3D& resulting_projections_barrelC,
828 Amg::SetVectorVector3D& resulting_projections_endcapA,
829 Amg::SetVectorVector3D& resulting_projections_endcapC ) const
830{
831 if (VP1Msg::verbose())
832 messageVerbose("projectPath(..) called. Input path has "+QString::number(path.size())+" points.");
833
834 resulting_projections_barrelA.clear();
835 resulting_projections_barrelC.clear();
836 resulting_projections_endcapA.clear();
837 resulting_projections_endcapC.clear();
838
839 //Fixme: If verbose - perform sanity check of input data (check for NAN's).
840 if (m_d->parts == InDetProjFlags::NoProjections ) {
841 if (VP1Msg::verbose())
842 messageVerbose("All projections currently off.");
843 return;
844 }
845 if ( path.size()<2 ) {
846 if (VP1Msg::verbose())
847 messageVerbose("Input path too short.");
848 return;
849 }
850
851 // ===> First we must find the clipped path's in all of the enabled detector parts.
852
853 Amg::SetVectorVector3D paths_brlA, paths_brlC, paths_ecA,paths_ecC;
854 clipPath( path,paths_brlA, paths_brlC, paths_ecA,paths_ecC);
855
856 // ===> Then we project those.
857
858 //Fixme: The dependence on surface thickness and epsilon below is very preliminary.
859
860 const double eps = m_d->data_disttosurface_epsilon;
861 const double endcapeps(-5*SYSTEM_OF_UNITS::mm);//fixme hardcoding..
862
863 Amg::SetVectorVector3D::const_iterator it,itE;
864
865 if (m_d->parts & InDetProjFlags::Barrel_AllPos) {
866 itE = paths_brlA.end();
867 if ( m_d->parts & InDetProjFlags::BarrelCentral )
868 for ( it = paths_brlA.begin(); it!=itE; ++it )
869 m_d->projectPathToZPlane( *it, resulting_projections_barrelA, 0.5*m_d->surfacethickness+eps );
870 if ( m_d->parts & InDetProjFlags::BarrelPositive )
871 for ( it = paths_brlA.begin(); it!=itE; ++it )
872 m_d->projectPathToZPlane( *it, resulting_projections_barrelA, m_d->barrel_posneg_z - eps );
873 }
874 if ( m_d->parts & InDetProjFlags::Barrel_AllNeg ) {
875 itE = paths_brlC.end();
876 if ( m_d->parts & InDetProjFlags::BarrelCentral )
877 for ( it = paths_brlC.begin(); it!=itE; ++it )
878 m_d->projectPathToZPlane( *it, resulting_projections_barrelC, - 0.5*m_d->surfacethickness - eps);
879 if ( m_d->parts & InDetProjFlags::BarrelNegative )
880 for ( it = paths_brlC.begin(); it!=itE; ++it )
881 m_d->projectPathToZPlane( *it, resulting_projections_barrelC, - m_d->barrel_posneg_z );
882 }
883 if ( m_d->parts & InDetProjFlags::EndCap_AllPos ) {
884 itE = paths_ecA.end();
886 for ( it = paths_ecA.begin(); it!=itE; ++it )
887 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapA, m_d->endcap_inner_radius + eps+endcapeps );
889 for ( it = paths_ecA.begin(); it!=itE; ++it )
890 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapA, m_d->endcap_outer_radius + eps+endcapeps );
891 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
893 for ( it = paths_ecA.begin(); it!=itE; ++it )
894 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapA,
895 0.5*m_d->surfacethickness + eps );
896 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
898 for ( it = paths_ecA.begin(); it!=itE; ++it )
899 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapA,
900 m_d->barrel_posneg_z - 0.5*m_d->surfacethickness - eps /*fixme: +- epsilon??*/ );
901 }
902 if ( m_d->parts & InDetProjFlags::EndCap_AllNeg ) {
903 itE = paths_ecC.end();
905 for ( it = paths_ecC.begin(); it!=itE; ++it )
906 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapC, m_d->endcap_inner_radius + eps+endcapeps );
908 for ( it = paths_ecC.begin(); it!=itE; ++it )
909 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapC, m_d->endcap_outer_radius + eps+endcapeps );
910 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
912 for ( it = paths_ecC.begin(); it!=itE; ++it )
913 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapC,
914 - 0.5*m_d->surfacethickness - eps );
915 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
917 for ( it = paths_ecC.begin(); it!=itE; ++it )
918 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapC,
919 - m_d->barrel_posneg_z + 0.5*m_d->surfacethickness + eps/*fixme: +- epsilon??*/ );
920 }
921
922}
923
924//____________________________________________________________________
925InDetProjHelper::PartsFlags InDetProjHelper::touchedParts( const std::vector<Amg::Vector3D >& path ) const
926{
927 if (VP1Msg::verbose())
928 messageVerbose("touchedParts(..) called. Input path has "+QString::number(path.size())+" points.");
929 PartsFlags touchedparts = NoParts;
930 if ( m_d->touchesHollowCylinder(path,m_d->barrel_inner_radius, m_d->barrel_outer_radius, 0, m_d->barrel_posneg_z) )
931 touchedparts |= BarrelA;
932 if ( m_d->touchesHollowCylinder(path,m_d->barrel_inner_radius, m_d->barrel_outer_radius, - m_d->barrel_posneg_z, 0) )
933 touchedparts |= BarrelC;
934 if ( m_d->touchesHollowCylinder(path,m_d->endcap_inner_radius, m_d->endcap_outer_radius,
935 m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 ) )
936 touchedparts |= EndCapA;
937 if ( m_d->touchesHollowCylinder(path, m_d->endcap_inner_radius, m_d->endcap_outer_radius,
938 - m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, - m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5) )
939 touchedparts |= EndCapC;
940 return touchedparts;
941}
942
943//____________________________________________________________________
944bool InDetProjHelper::Imp::touchesHollowCylinder( const std::vector<Amg::Vector3D >& path,
945 const double& rmin, const double& rmax,
946 const double& zmin, const double& zmax ) const
947{
948 const double rmin2(rmin*rmin), rmax2(rmax*rmax);
949 double r2;
950 std::vector<Amg::Vector3D >::const_iterator it(path.begin()), itE(path.end());
951 for (;it!=itE;++it) {
952 if (it->z()<zmin)
953 continue;
954 if (it->z()>zmax)
955 continue;
956 r2 = it->x()*it->x()+it->y()*it->y();
957 if (r2<rmin2)
958 continue;
959 if (r2<=rmax2)
960 return true;
961 }
962 return false;
963}
static Double_t a
#define z
void clipPathToHollowCylinder(const std::vector< Amg::Vector3D > &in, Amg::SetVectorVector3D &out, const double &rmin, const double &rmax, const double &zmin, const double &zmax) const
bool clipSegmentToInfiniteHollowCylinder(Amg::Vector3D &a, Amg::Vector3D &b, const double &rmin, const double &rmax, Amg::Vector3D &seg2_a, Amg::Vector3D &seg2_b) const
bool clipSegmentToZInterval(Amg::Vector3D &a, Amg::Vector3D &b, const double &zmin, const double &zmax) const
InDetProjFlags::InDetProjPartsFlags parts
void movePoint1ToZPlaneAndPoint2(Amg::Vector3D &p1, const Amg::Vector3D &p2, const double &z) const
bool clipSegmentToHollowCylinder(Amg::Vector3D &a, Amg::Vector3D &b, const double &rmin, const double &rmax, const double &zmin, const double &zmax, Amg::Vector3D &seg2_a, Amg::Vector3D &seg2_b) const
void projectPathToInfiniteCylinder(const std::vector< Amg::Vector3D > &in, Amg::SetVectorVector3D &outset, const double &r) const
bool touchesHollowCylinder(const std::vector< Amg::Vector3D > &path, const double &rmin, const double &rmax, const double &zmin, const double &zmax) const
void projectPathToZPlane_specialZtoR(const std::vector< Amg::Vector3D > &in, Amg::SetVectorVector3D &outset, const double &z) const
void movePoint1ToInfiniteCylinderAndPoint2(Amg::Vector3D &p1, const Amg::Vector3D &p2, const double &r) const
void lineCircleIntersection(const Amg::Vector3D &a, const Amg::Vector3D &b, const double &r, double &u1, double &u2) const
InDetProjHelper * theclass
void projectPathToZPlane(const std::vector< Amg::Vector3D > &in, Amg::SetVectorVector3D &outset, const double &z) const
static InDetProjHelper * createTRTHelper(IVP1System *sys=0)
static InDetProjHelper * createPixelHelper(IVP1System *sys=0)
static void transformECPointToZPlane_specialZtoR(Amg::Vector3D &p, const double &planeZ, const double &planeRBegin, const double &endcapZBegin, const double &squeezeFactor)
InDetProjFlags::InDetProjPartsFlags setParts(InDetProjFlags::InDetProjPartsFlags)
InDetProjFlags::InDetProjPartsFlags parts() const
static InDetProjHelper * createSCTHelper(IVP1System *sys=0)
PartsFlags touchedParts(const std::vector< Amg::Vector3D > &path) const
InDetProjHelper(double surfacethickness, double data_disttosurface_epsilon, double barrel_inner_radius, double barrel_outer_radius, double barrel_posneg_z, double endcap_surface_z, double endcap_surface_length, double endcap_inner_radius, double endcap_outer_radius, double endcap_zasr_innerradius, double endcap_zasr_endcapz_begin, double endcap_zasr_squeezefact, IVP1System *sys)
void clipPath(const std::vector< Amg::Vector3D > &path, Amg::SetVectorVector3D &resulting_subpaths) const
void projectPath(const std::vector< Amg::Vector3D > &path, Amg::SetVectorVector3D &resulting_projections) const
static double sct_barrel_inner_radius()
static double trt_endcap_surface_z()
static double sct_endcap_zasr_squeezefact()
static double trt_barrel_posneg_z()
static double sct_endcap_surface_z()
static double sct_endcap_zasr_innerradius()
static double pixel_endcap_outer_radius()
static double trt_endcap_inner_radius()
static double trt_endcap_surface_length()
static double sct_endcap_surface_length()
static double sct_endcap_outer_radius()
static double trt_endcap_zasr_squeezefact()
static double pixel_barrel_outer_radius()
static double sct_barrel_posneg_z()
static double surfacethickness()
static double pixel_data_disttosurface_epsilon()
static double pixel_barrel_posneg_z()
static double pixel_endcap_inner_radius()
static double trt_barrel_outer_radius()
static double pixel_endcap_zasr_endcapz_begin()
static double trt_endcap_zasr_endcapz_begin()
static double trt_data_disttosurface_epsilon()
static double trt_endcap_outer_radius()
static double pixel_endcap_zasr_squeezefact()
static double pixel_barrel_inner_radius()
static double pixel_endcap_surface_length()
static double pixel_endcap_surface_z()
static double sct_data_disttosurface_epsilon()
static double sct_endcap_zasr_endcapz_begin()
static double sct_endcap_inner_radius()
static double pixel_endcap_zasr_innerradius()
static double sct_barrel_outer_radius()
static double trt_endcap_zasr_innerradius()
static double trt_barrel_inner_radius()
VP1HelperClassBase(IVP1System *sys=0, QString helpername="")
void messageVerbose(const QString &) const
void message(const QString &) const
static bool verbose()
Definition VP1Msg.h:31
static void message(const QString &, IVP1System *sys=0)
Definition VP1Msg.cxx:30
int r
Definition globals.cxx:22
struct color C
std::set< std::vector< Amg::Vector3D >, VectorVector3DComparer > SetVectorVector3D
Eigen::Matrix< double, 3, 1 > Vector3D
hold the test vectors and ease the comparison