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.set( p1.x()+dx*s, p1.y()+dy*s, z );
387 Amg::setVector3DCartesian( p1, p1.x()+dx*s, p1.y()+dy*s, z );
388}
389
390//____________________________________________________________________
392 const double& zmin, const double& zmax ) const
393{
394 if (a.z()<zmin) {
395 if (b.z()<zmin)//both <zmin
396 return false;
397 //a<zmin, b>=zmin:
399 if (b.z()>zmax)
401 return true;
402 } else {
403 if (b.z()<zmin) {
404 //a>=zmin, b<zmin
406 if (a.z()>zmax)
408 return true;
409 } else {
410 //Both are > zmin
411 if (a.z()>zmax) {
412 if (b.z()>zmax)
413 return false;
415 return true;
416 } else {
417 //zmin<=a<=zmax, b>=zmin
418 if (b.z()>zmax)
420 return true;
421 }
422 }
423 }
424}
425
426//____________________________________________________________________
428{
429 //Fixme: what happens here if we don't cross? And how can we be sure
430 //that we don't move FURTHER than the other point? (i.e. if the
431 //infinite line with p1 and p2 crosses, but the segment p1p2 does
432 //not!?
433
434// double p1r(p1.r());
435// double dr(p2.r()-p1r);
436 double p1r( Amg::rVector3D(p1) );
437 double dr( Amg::rVector3D(p2)-p1r );
438
439 if (dr==0.0) {
440 theclass->message("movePoint1ToInfiniteCylinderAndPoint2 Error: Points have same r!!");
441 return;
442 }
443 double s((r-p1r)/dr);
444 double t(1.0-s);
445 Amg::setVector3DCartesian( p1, p1.x()*t + p2.x()*s, p1.y()*t + p2.y()*s, p1.z()*t + p2.z()*s );
446
447}
448
449//____________________________________________________________________
451 double & u1, double& u2 ) const
452{
453 const double dx = b.x()-a.x();
454 const double dy = b.y()-a.y();
455 double A = dx*dx+dy*dy;
456 if (A==0.0) {
457 //That's not a line => no intersections unless points are exactly on circumference!
458 u1 = u2 = ( a.x()*a.x()+a.y()*a.y() == r*r ? 0.0 : 1.0e99 );
459 return;
460 }
461 double B = 2.0*( a.x()*dx + a.y()*dy );
462 double C = a.x()*a.x()+a.y()*a.y() - r*r;
463 double D = B*B-4*A*C;
464
465 if (D>0.0) {
466 //Intersections
467 double sqrtD = sqrt(D);
468 u1 = 0.5 * ( -B - sqrtD) / A;
469 u2 = 0.5 * ( -B + sqrtD) / A;
470 } else if (D<0.0) {
471 //No intersections:
472 u1 = u2 = -1.0e99;
473 } else {
474 //intersection in one point
475 u1 = u2 = -0.5*B/A;
476 }
477
478}
479
480//____________________________________________________________________
482 const double& rmin, const double& rmax,
483 Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const
484{
485 //* if returns false: segment does not intersect hollow cylinder - do
486 // NOT use returned points for anything.
487 //* if returns true and seg2_a==seg2_b: Use "a" and "b" for the clipped segment.
488 //* if returns true and seg2_a!=seg2_b: The clip resulting in TWO new segments
489 // (it was cut in two by the inner wall).
490
491 //Fixme: Stuff like the following!:
492 // if (VP1SanityCheck::enabled()) {
493 // VP1SanityCheck::beginGroup("InDetProjHelper::Imp::clipSegmentToInfiniteHollowCylinder");
494 // VP1SanityCheck::positiveParameter("rmin",rmin);
495 // VP1SanityCheck::positiveParameter("rmax",rmax);
496 // VP1SanityCheck::parameter("point a",a);
497 // VP1SanityCheck::parameter("point b",b);
498 // VP1SanityCheck::endGroup();
499 // }
500 const double ar2 = a.x()*a.x()+a.y()*a.y();
501 const double br2 = b.x()*b.x()+b.y()*b.y();
502 const double rmin2 = rmin*rmin;
503 //We might be inside inner wall:
504 if (ar2 <= rmin2 && br2 <= rmin2 ) {
505 // seg2_a=seg2_b;
506// if (VP1Msg::verbose())
507// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Segment entirely inside rmin.");
508 return false;
509 }
510 //Some fast checks for being outside:
511 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) ) {
512// if (VP1Msg::verbose())
513// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Segment clearly entirely outside outside rmax.");
514// seg2_a=seg2_b;
515 return false;
516 }
517
518 //If a==b (apart from perhaps z coord), the check is simple:
519 const double dx = b.x()-a.x();
520 const double dy = b.y()-a.y();
521 const double rmax2 = rmax*rmax;
522 if (dx==0.0&&dy==0.0) {
523 //Apparently a==b (apart from perhaps z coord).
524// if (VP1Msg::verbose())
525// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder a==b.");
526 return ar2<=rmax2;
527 }
528 //Find point which is closest to the z-axis and on the segment:
529 const double u = - (a.y()*dy+a.x()*dx)/(dx*dx+dy*dy);
530 const double px = ( u <= 0 ? a.x() : ( u >= 1 ? b.x() : a.x()+u*dx ) );
531 const double py = ( u <= 0 ? a.y() : ( u >= 1 ? b.y() : a.y()+u*dy ) );
532 const double pr2 = px*px+py*py;
533 if (pr2>=rmax2) {
534// if (VP1Msg::verbose())
535// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder segment entirely outside rmax.");
536// seg2_a=seg2_b;
537 return false;
538
539
540 }
541 //We now know that the segment does indeed intersect the clip volume.
542 seg2_a=seg2_b;//signature of just one segment:
543
544 if (pr2>=rmin2&&ar2<=rmax2&&br2<=rmax2) {
545 //We are actually already entirely inside the clip volume.
546// if (VP1Msg::verbose())
547// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder segment entirely inside clip volume."
548// " (pr="+QString::number(sqrt(pr2))+", ar="+QString::number(sqrt(ar2))
549// +", br="+QString::number(sqrt(br2))+")");
550 return true;
551 }
552
553 //First we simply clip to the outer cylinder:
554 if (ar2>rmax2||br2>rmax2) {
555 //We need to clip a-b to be inside the outer cylinder.
556 //Find intersections:
557 double u1, u2;
558 lineCircleIntersection(a,b,rmax,u1,u2);//u1<=u2 !
559 if (u1==u2) {
560 //We are just touching - but we already tested against this!
561 theclass->message("This should never happen(1).");
562 // seg2_a=seg2_b;
563 return false;
564 }
565 Amg::Vector3D asave(a);
566 if (u1>0&&u1<1) {
567 //move a to a+u1*(b-a)
568 a = a+u1*(b-a);
569// if (VP1Msg::verbose())
570// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder sliding a towards b, at the rmax circle.");
571 }
572 if (u2>0&&u2<1) {
573 //move b to a+u2*(b-a)
574 b = asave+u2*(b-asave);
575// if (VP1Msg::verbose())
576// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder sliding b towards a, at the rmax circle.");
577 }
578 }
579
580 if (pr2>=rmin2) {
581// if (VP1Msg::verbose())
582// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder remaining segment is now entirely inside.");
583 return true;
584 }
585 //Ok, we know that we intersect the inner cylinder
586 double u1, u2;
587 lineCircleIntersection(a,b,rmin,u1,u2);//u1<=u2 !
588
589 if (u1>0&&u1<1) {
590 if (u2>0&&u2<1) {
591 //We intersect twice. Thus, two line segments:
592 //a to "a+u1*(b-a)" and "a+u2*(b-a)" to b
593 //a=a;
594 seg2_b = b;
595 b = a+u1*(seg2_b-a);
596 seg2_a=a+u2*(seg2_b-a);
597// if (VP1Msg::verbose())
598// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Two resulting segments!.");
599 return true;
600 }
601 b = a+u1*(b-a);
602// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder One resulting segment (b->a)!.");
603 return true;
604 }
605 if (u2>0&&u2<1)
606 a = a+u2*(b-a);
607// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder One resulting segment (a->b)!.");
608 return true;
609}
610
611
612
613//____________________________________________________________________
615 const double& rmin, const double& rmax,
616 const double& zmin, const double& zmax,
617 Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const
618{
619 // seg2_a = seg2_b;//test
620// if (VP1Msg::verbose()) {
621// theclass->messageVerbose("clipSegmentToHollowCylinder called with:");
622// theclass->messageVerbose(" rmin = "+QString::number(rmin));
623// theclass->messageVerbose(" rmax = "+QString::number(rmax));
624// theclass->messageVerbose(" zmin = "+QString::number(zmin));
625// theclass->messageVerbose(" zmax = "+QString::number(zmax));
626// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")");
627// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")");
628// }
629 if (!clipSegmentToZInterval(a,b,zmin,zmax)) {
630 // seg2_a = seg2_b;
631// if (VP1Msg::verbose())
632// theclass->messageVerbose("clipSegmentToHollowCylinder segment outside z-interval.");
633 return false;
634 }
635// if (VP1Msg::verbose()) {
636// theclass->messageVerbose("clipSegmentToHollowCylinder parameters after clipSegmentToZInterval:");
637// if (a.z()<zmin||a.z()>zmax)
638// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToZInterval call (a_z wrong).");
639// if (b.z()<zmin||b.z()>zmax)
640// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToZInterval call (b_z wrong).");
641// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")");
642// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")");
643// }
644 if (!clipSegmentToInfiniteHollowCylinder(a,b,rmin,rmax,seg2_a,seg2_b)) {
645 // seg2_a = seg2_b;
646// if (VP1Msg::verbose())
647// theclass->messageVerbose("clipSegmentToHollowCylinder segment outside infinite hollow cylinder.");
648 return false;
649 }
650// if (VP1Msg::verbose()) {
651// theclass->messageVerbose("clipSegmentToHollowCylinder parameters after clipSegmentToInfiniteHollowCylinder:");
652// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")");
653// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")");
654// const double ar2 = a.x()*a.x()+a.y()*a.y();
655// const double br2 = b.x()*b.x()+b.y()*b.y();
656// if (ar2<rmin*rmin||ar2>rmax*rmax)
657// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToInfiniteHollowCylinder call (a wrong).");
658// if (br2<rmin*rmin||br2>rmax*rmax)
659// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToInfiniteHollowCylinder call (b wrong).");
660// theclass->messageVerbose("clipSegmentToHollowCylinder returning.");
661// }
662
663 return true;
664}
665
666//____________________________________________________________________
667void InDetProjHelper::Imp::clipPathToHollowCylinder( const std::vector<Amg::Vector3D >& in,
668// Amg::SetVectorVector3D& out,
670 const double& rmin, const double& rmax,
671 const double& zmin, const double& zmax ) const
672{
673// if (VP1Msg::verbose()) {
674// theclass->messageVerbose("clipPathToHollowCylinder called");
675// theclass->messageVerbose(" ===> rmin = "+QString::number(rmin));
676// theclass->messageVerbose(" ===> rmax = "+QString::number(rmax));
677// theclass->messageVerbose(" ===> zmin = "+QString::number(zmin));
678// theclass->messageVerbose(" ===> zmax = "+QString::number(zmax));
679// }
680
681 out.clear();
682 if (rmin>=rmax||rmin<0||zmin>=zmax) {
683 theclass->message("clipPathToHollowCylinder Error: Non-sensical cylinder parameters!");
684 return;
685 }
686 const unsigned n=in.size();
687 if (n<2)
688 return;
689
691 Amg::Vector3D seg2_a,seg2_b;
692 std::vector<Amg::Vector3D > v;
693 for (unsigned i = 1; i<n; ++i) {
694 // theclass->messageVerbose("clipPathToHollowCylinder -> dealing with segment "+QString::number(i-1)+"->"+QString::number(i));
695
696 a = in.at(i-1);//fixme: .at()->[]
697 b = in.at(i);
698 if ( clipSegmentToHollowCylinder( a,b,rmin,rmax,zmin,zmax,seg2_a,seg2_b ) ) {
699 if (v.empty()) {
700 v.push_back(a);
701 v.push_back(b);
702 if (seg2_a!=seg2_b) {
703 out.insert(v);
704 v.clear();
705 v.push_back(seg2_a);
706 v.push_back(seg2_b);
707 }
708 } else {
709 //We know that previous segment was also touching. Therefore
710 //it must necessarily be true that v.back()==a.
711 if ( v.back() != a ) {
712 theclass->messageDebug("ERROR: Inconsistency found while building clip part");//Fixme: downgrade to messageDebug for now, but need to understand this!
713 out.insert(v);
714 v.clear();
715 v.push_back(a);
716 }
717 v.push_back(b);
718 if (seg2_a!=seg2_b) {
719 out.insert(v);
720 v.clear();
721 v.push_back(seg2_a);
722 v.push_back(seg2_b);
723 }
724 }
725 } else {
726// theclass->messageVerbose("Segment does not touch");
727 //Segment doesn't touch cylinder volume - flush part currently building if any.
728 if (!v.empty()) {
729 out.insert(v);
730 v.clear();
731 }
732 }
733 }
734 if (!v.empty()) {
735// theclass->messageDebug("v not empty");
736 out.insert(v);
737 }
738}
739
740//____________________________________________________________________
741void InDetProjHelper::Imp::projectPathToInfiniteCylinder( const std::vector<Amg::Vector3D >& in,
742 Amg::SetVectorVector3D& outset, const double& r ) const
743{
744 std::vector<Amg::Vector3D > out(in);
745 std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end());
746 double s;
747 for (;it!=itE;++it) {
748 if ( it->x()==0.0 && it->y()==0.0 ) {
749 theclass->message("ERROR: Point has x==0 and y==0. Ambiguous projection of point.");
750
751// it->setX(1.0);
752 it->x() = 1.0;
753 }
754 s = r / sqrt( it->x()*it->x()+it->y()*it->y() );
755
756// it->setX(it->x()*s);
757// it->setY(it->y()*s);
758 it->x() = it->x()*s;
759 it->y() = it->y()*s;
760
761 }
762 outset.insert(out);
763}
764
765//____________________________________________________________________
766void InDetProjHelper::Imp::projectPathToZPlane( const std::vector<Amg::Vector3D >& in,
767 Amg::SetVectorVector3D& outset, const double& z ) const
768{
769 std::vector<Amg::Vector3D > out(in);
770 std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end());
771 for (;it!=itE;++it) {
772// it->setZ(z);
773 it->z() = z;
774 }
775 outset.insert(out);
776}
777
778
779//____________________________________________________________________
781 const double& planeZ,
782 const double& planeRBegin,
783 const double& endcapZBegin,
784 const double& squeezeFactor )
785{
786 if ( p.x()==0.0 && p.y()==0.0 ) {
787 VP1Msg::message("InDetProjHelper::transformECPointToZPlane_specialZtoR ERROR: "
788 "Point has x==0 and y==0. Ambiguous projection of point.");
789// p.setX(1.0);
790 p.x() = 1.0;
791 }
792 const double r = planeRBegin + (fabs(p.z())-endcapZBegin)/squeezeFactor;
793 const double s = r / sqrt( p.x()*p.x()+p.y()*p.y() );
794// p.setX(p.x()*s);
795// p.setY(p.y()*s);
796// p.setZ(planeZ);
797 p.x() = p.x()*s;
798 p.y() = p.y()*s;
799 p.z() = planeZ;
800}
801
802//____________________________________________________________________
803void InDetProjHelper::Imp::projectPathToZPlane_specialZtoR( const std::vector<Amg::Vector3D >& in,
805 const double& z ) const
806{
807 std::vector<Amg::Vector3D > out(in);
808 std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end());
809 for (;it!=itE;++it)
811 z,
815 outset.insert(out);
816}
817
818//____________________________________________________________________
819void InDetProjHelper::projectPath( const std::vector<Amg::Vector3D >& path,
820 Amg::SetVectorVector3D& resulting_projs ) const
821{
822 projectPath(path,resulting_projs,resulting_projs,resulting_projs,resulting_projs);
823}
824
825//____________________________________________________________________
826void InDetProjHelper::projectPath( const std::vector<Amg::Vector3D >& path,
827 Amg::SetVectorVector3D& resulting_projections_barrelA,
828 Amg::SetVectorVector3D& resulting_projections_barrelC,
829 Amg::SetVectorVector3D& resulting_projections_endcapA,
830 Amg::SetVectorVector3D& resulting_projections_endcapC ) const
831{
832 if (VP1Msg::verbose())
833 messageVerbose("projectPath(..) called. Input path has "+QString::number(path.size())+" points.");
834
835 resulting_projections_barrelA.clear();
836 resulting_projections_barrelC.clear();
837 resulting_projections_endcapA.clear();
838 resulting_projections_endcapC.clear();
839
840 //Fixme: If verbose - perform sanity check of input data (check for NAN's).
841 if (m_d->parts == InDetProjFlags::NoProjections ) {
842 if (VP1Msg::verbose())
843 messageVerbose("All projections currently off.");
844 return;
845 }
846 if ( path.size()<2 ) {
847 if (VP1Msg::verbose())
848 messageVerbose("Input path too short.");
849 return;
850 }
851
852 // ===> First we must find the clipped path's in all of the enabled detector parts.
853
854 Amg::SetVectorVector3D paths_brlA, paths_brlC, paths_ecA,paths_ecC;
855 clipPath( path,paths_brlA, paths_brlC, paths_ecA,paths_ecC);
856
857 // ===> Then we project those.
858
859 //Fixme: The dependence on surface thickness and epsilon below is very preliminary.
860
861 const double eps = m_d->data_disttosurface_epsilon;
862 const double endcapeps(-5*SYSTEM_OF_UNITS::mm);//fixme hardcoding..
863
864 Amg::SetVectorVector3D::const_iterator it,itE;
865
866 if (m_d->parts & InDetProjFlags::Barrel_AllPos) {
867 itE = paths_brlA.end();
868 if ( m_d->parts & InDetProjFlags::BarrelCentral )
869 for ( it = paths_brlA.begin(); it!=itE; ++it )
870 m_d->projectPathToZPlane( *it, resulting_projections_barrelA, 0.5*m_d->surfacethickness+eps );
871 if ( m_d->parts & InDetProjFlags::BarrelPositive )
872 for ( it = paths_brlA.begin(); it!=itE; ++it )
873 m_d->projectPathToZPlane( *it, resulting_projections_barrelA, m_d->barrel_posneg_z - eps );
874 }
875 if ( m_d->parts & InDetProjFlags::Barrel_AllNeg ) {
876 itE = paths_brlC.end();
877 if ( m_d->parts & InDetProjFlags::BarrelCentral )
878 for ( it = paths_brlC.begin(); it!=itE; ++it )
879 m_d->projectPathToZPlane( *it, resulting_projections_barrelC, - 0.5*m_d->surfacethickness - eps);
880 if ( m_d->parts & InDetProjFlags::BarrelNegative )
881 for ( it = paths_brlC.begin(); it!=itE; ++it )
882 m_d->projectPathToZPlane( *it, resulting_projections_barrelC, - m_d->barrel_posneg_z );
883 }
884 if ( m_d->parts & InDetProjFlags::EndCap_AllPos ) {
885 itE = paths_ecA.end();
887 for ( it = paths_ecA.begin(); it!=itE; ++it )
888 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapA, m_d->endcap_inner_radius + eps+endcapeps );
890 for ( it = paths_ecA.begin(); it!=itE; ++it )
891 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapA, m_d->endcap_outer_radius + eps+endcapeps );
892 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
894 for ( it = paths_ecA.begin(); it!=itE; ++it )
895 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapA,
896 0.5*m_d->surfacethickness + eps );
897 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
899 for ( it = paths_ecA.begin(); it!=itE; ++it )
900 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapA,
901 m_d->barrel_posneg_z - 0.5*m_d->surfacethickness - eps /*fixme: +- epsilon??*/ );
902 }
903 if ( m_d->parts & InDetProjFlags::EndCap_AllNeg ) {
904 itE = paths_ecC.end();
906 for ( it = paths_ecC.begin(); it!=itE; ++it )
907 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapC, m_d->endcap_inner_radius + eps+endcapeps );
909 for ( it = paths_ecC.begin(); it!=itE; ++it )
910 m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapC, m_d->endcap_outer_radius + eps+endcapeps );
911 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
913 for ( it = paths_ecC.begin(); it!=itE; ++it )
914 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapC,
915 - 0.5*m_d->surfacethickness - eps );
916 //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx:
918 for ( it = paths_ecC.begin(); it!=itE; ++it )
919 m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapC,
920 - m_d->barrel_posneg_z + 0.5*m_d->surfacethickness + eps/*fixme: +- epsilon??*/ );
921 }
922
923}
924
925//____________________________________________________________________
926InDetProjHelper::PartsFlags InDetProjHelper::touchedParts( const std::vector<Amg::Vector3D >& path ) const
927{
928 if (VP1Msg::verbose())
929 messageVerbose("touchedParts(..) called. Input path has "+QString::number(path.size())+" points.");
930 PartsFlags touchedparts = NoParts;
931 if ( m_d->touchesHollowCylinder(path,m_d->barrel_inner_radius, m_d->barrel_outer_radius, 0, m_d->barrel_posneg_z) )
932 touchedparts |= BarrelA;
933 if ( m_d->touchesHollowCylinder(path,m_d->barrel_inner_radius, m_d->barrel_outer_radius, - m_d->barrel_posneg_z, 0) )
934 touchedparts |= BarrelC;
935 if ( m_d->touchesHollowCylinder(path,m_d->endcap_inner_radius, m_d->endcap_outer_radius,
936 m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 ) )
937 touchedparts |= EndCapA;
938 if ( m_d->touchesHollowCylinder(path, m_d->endcap_inner_radius, m_d->endcap_outer_radius,
939 - m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, - m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5) )
940 touchedparts |= EndCapC;
941 return touchedparts;
942}
943
944//____________________________________________________________________
945bool InDetProjHelper::Imp::touchesHollowCylinder( const std::vector<Amg::Vector3D >& path,
946 const double& rmin, const double& rmax,
947 const double& zmin, const double& zmax ) const
948{
949 const double rmin2(rmin*rmin), rmax2(rmax*rmax);
950 double r2;
951 std::vector<Amg::Vector3D >::const_iterator it(path.begin()), itE(path.end());
952 for (;it!=itE;++it) {
953 if (it->z()<zmin)
954 continue;
955 if (it->z()>zmax)
956 continue;
957 r2 = it->x()*it->x()+it->y()*it->y();
958 if (r2<rmin2)
959 continue;
960 if (r2<=rmax2)
961 return true;
962 }
963 return false;
964}
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
void setVector3DCartesian(Amg::Vector3D &v1, double x1, double y1, double z1)
Sets components in cartesian coordinate system.
double rVector3D(const Amg::Vector3D &v1)
Gets r-component in spherical coordinate system.
std::set< std::vector< Amg::Vector3D >, VectorVector3DComparer > SetVectorVector3D
Eigen::Matrix< double, 3, 1 > Vector3D
hold the test vectors and ease the comparison