GEAR  1.9.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends Pages
FTDParametersImpl.cc
1 #include "gearimpl/FTDParametersImpl.h"
2 #include <math.h>
3 #include <iostream>
4 
5 #define _EPSILON 0.0001
6 
7 namespace gear
8 {
9 
10 // FTDParametersImpl::FTDParametersImpl
11 // ( double shellInnerRadiusMin, double shellInnerRadiusMax,
12 // double shellOuterRadius, double shellHalfLength,
13 // double shellRadLength ) :
14 // _shellInnerRadiusMin( shellInnerRadiusMin ) ,
15 // _shellInnerRadiusMax( shellInnerRadiusMax ) ,
16 // _shellOuterRadius( shellOuterRadius ) ,
17 // _shellHalfLength( shellHalfLength ) ,
18 // _shellRadLength( shellRadLength )
19 // {
20 // }
21 
22  int FTDParametersImpl::getLayerIndex( const Vector3D & /*p*/ ) const
23 {
24  //fg: this needs revisiting - if needed at all (changed definition of z position)
25 
26  // // // very first check for quick calculation
27  // // if( fabs( p[2] ) > _shellHalfLength )
28  // // {
29  // // // Outside shell
30  // // return -1;
31  // // }
32 
33  // // get radius of point in XY-plane
34  // double pRadius = sqrt( p[0]*p[0] + p[1]*p[1] ) ;
35 
36  // //get absolute z
37  // double zabs = fabs(p[2]);
38 
39  // for( int possibleLayer = 0 ; possibleLayer < _layer.getNLayers() ; possibleLayer++ )
40  // {
41  // // // first some quick checks to reduce cpu time
42  // // // check if is ouside shell the radius
43  // // if( pRadius > getShellOuterRadius() )
44  // // {
45  // // continue;
46  // // }
47  // // else if( pRadius < getShellInnerRadiusMin() )
48  // // {
49  // // continue;
50  // // }
51  // // check if is inside this disk (z), including sensitive parts
52  // double zmax = fabs(_layer.getZposition(possibleLayer))+_layer.getSupportThickness(possibleLayer)/2.0
53  // +_layer.getSensitiveThickness(possibleLayer);
54  // double zmin = fabs(_layer.getZposition(possibleLayer))-_layer.getSupportThickness(possibleLayer)/2.0
55  // -_layer.getSensitiveThickness(possibleLayer);
56 
57  // if( zabs > zmax || zabs < zmin )
58  // {
59  // continue;
60  // }
61  // // If we are here, the point correspond to this layer...
62  // return possibleLayer;
63  // }
64  return -1;
65 }
66 
67 // returns the index of the sensitive layers 1 facing the IP, 2 back the IP
69 {
70  //fg: this needs revisiting - if needed at all (changed definition of z position)
71  return -1 ;
72 
73  // int layer = getLayerIndex( p );
74  // if( layer == -1)
75  // {
76  // return -1;
77  // }
78  // int petal = getPetalIndex(p,true);
79  // if(petal == -1)
80  // {
81  // return -1;
82  // }
83  // // if are here, means that the point is inside the volume of the petal+sensor
84  // // but still don't know if is inside the sensor
85  // double zmax = fabs(_layer.getZposition(layer))+_layer.getSupportThickness(layer)/2.0
86  // +_layer.getSensitiveThickness(layer);
87  // double zmin = fabs(_layer.getZposition(layer))-_layer.getSupportThickness(layer)/2.0
88  // -_layer.getSensitiveThickness(layer);
89 
90  // //double zmaxbackIP = zmax;
91  // double zminbackIP = zmax-_layer.getSensitiveThickness(layer);
92  // double zmaxfaceIP = zmin+_layer.getSensitiveThickness(layer);
93  // //double zminfaceIP = zmin;
94  // // Already known the point is between zmaxfaceIP and zminbackIP,
95  // // checking the others
96  // float zabs = fabs(p[2]);
97 
98  // if( zabs < zminbackIP && zabs > zmaxfaceIP )
99  // {
100  // // Is between the sensitives (inside the petal)
101  // return -1;
102  // }
103 
104  // if( zabs <= zmaxfaceIP )
105  // {
106  // return FACE;
107  // }
108  // else if( zabs >= zminbackIP )
109  // {
110  // return BACK;
111  // }
112  // else
113  // {
114  // std::cout << "********************************************************" << std::endl;
115  // std::cout << "*********** WARNING WARNING *******************" << std::endl;
116  // std::cout << "********************************************************" << std::endl;
117  // std::cout << "Unexpected ERROR! Contact with the maintainer of this code. " << std::endl;
118  // std::cout <<" This would not have to be happened" << std::endl;
119  // std::cout << "********************************************************" << std::endl;
120  // return -1;
121  // }
122 
123 }
124 
125 // Returns the petal number. If sensitive=true, the calculus are done using the dimensions
126 // of the sensitive: this is a case only to be called by the getSensitiveIndex method
127 int FTDParametersImpl::getPetalIndex( const Vector3D & p, const bool & sensitive ) const
128 {
129  int layer = getLayerIndex( p );
130  // Checking if found something
131  if( layer == -1 )
132  {
133  return -1;
134  }
135  // get radius of point in XY-plane
136  double pRadius = sqrt( p[0]*p[0] + p[1]*p[1] ) ;
137 
138  //get phi of point in XY-Plane
139  double pPhi = atan2( p[1], p[0] );
140 
141  // Localize the petal:
142  int foundpetal = -1;
143  for(int petal=0; petal < _layer.getNPetals(layer); petal++)
144  {
145  const double lowpetalphi = _layer.getStartPhi(layer, petal, sensitive);
146  const double highpetalphi = _layer.getEndPhi(layer, petal, sensitive);
147  if( pPhi <= highpetalphi && pPhi >= lowpetalphi )
148  {
149  foundpetal = petal;
150  break;
151  }
152  }
153  if( foundpetal == -1)
154  {
155  // FIXME: Why I am here?? se supone que deberia haber encontrado algo
156  return -1;
157  }
158  // Last check: is inside the R of the petal(sensitive)
159  double rMin = 0.0;
160  double rMax = _layer.getMaxRadius(layer,sensitive);
161  if( ! sensitive )
162  {
163  rMin = _layer.getSupportRinner(layer);
164  }
165  else
166  {
167  rMin = _layer.getSensitiveRinner(layer);
168  }
169 
170  if( pRadius < rMin || pRadius > rMax )
171  {
172  return -1;
173  }
174 
175  return foundpetal;
176 }
177 
178 
179 
180 // returns if a point is in a petal (support or sensitive)
181 bool FTDParametersImpl::isPointInFTD(const Vector3D & p, const bool & sensitive) const
182 {
183 
184  int index = -1;
185  if( sensitive )
186  {
187  index = getSensitiveIndex(p);
188  }
189  else
190  {
191  index = getPetalIndex(p);
192  }
193 
194  bool isIn = false;
195  if( index != -1 )
196  {
197  isIn = true;
198  }
199 
200  return isIn;
201 }
202 
203 
204 // First try...
205 /*bool FTDParametersImpl::isPointInFTD(const Vector3D & p, const bool & sensitive) const
206 {
207  // very first check for quick calculation
208  if( fabs( p[2] ) > _shellHalfLength )
209  {
210  // Outside shell
211  return false ;
212  }
213 
214  // get radius of point in XY-plane
215  double pRadius = sqrt( p[0]*p[0] + p[1]*p[1] ) ;
216 
217  //get phi of point in XY-Plane
218  double pPhi = getPhiPoint( p ) ;
219 
220  //get absolute z
221  double zabs = fabs(p[2]);
222 
223  for( int possibleLayer = 0 ; possibleLayer < _layer.getNLayers() ; possibleLayer++ )
224  {
225  // first some quick checks to reduce cpu time
226  // check if is ouside shell the radius
227  if( pRadius > getShellOuterRadius() )
228  {
229  continue;
230  }
231  else if( pRadius < getShellInnerRadiusMin() )
232  {
233  continue;
234  }
235  // check if is inside this disk (z)
236  double zmax = fabs(_layer.getLadderZposition(possibleLayer))+_layer.getLadderThickness(possibleLayer)/2.0;
237  double zmin = fabs(_layer.getLadderZposition(possibleLayer))-_layer.getLadderThickness(possibleLayer)/2.0;
238  if( sensitive )
239  {
240  zmax +=_layer.getSensitiveThickness(possibleLayer);
241  zmin -=_layer.getSensitiveThickness(possibleLayer);
242  }
243 
244  if( zabs > zmax || zabs < zmin )
245  {
246  continue;
247  }
248  // If we are here, the point correspond to this layer...
249  // * Refining the z wide if sensitive: two faces
250  if( sensitive )
251  {
252  double zmaxfaceIP = zmax;
253  double zminfaceIP = zmax-_layer.getSensitiveThickness(possibleLayer);
254  double zmaxbackIP = zmin+_layer.getSensitiveThickness(possbileLayer);
255  double zminbackIP = zmin;
256  // Already known the point is between zmaxfaceIP and zminbackIP,
257  // checking the others
258  if( zabs < zminfaceIP && zabs > zmaxbackIP )
259  {
260  // Is between the sensitives (in the petal)
261  continue;
262  }
263  }
264  // * XY-Plane stuff:
265  // ** Localize the petal:
266  int foundpetal = -1;
267  for(unsigned int petal=0, petal < _layer.getNLadders(possibleLayer); petal++)
268  {
269  const double lowpetalphi = getStartPhi(possibleLayer, petal, sensitive);
270  const double highpetalphi = getEndPhi(possibleLayer, petal, sensitive);
271  if( pPhi <= highpetalphi && pPhi >= lowpetalphi )
272  {
273  foundpetal = petal;
274  break;
275  }
276  }
277  if( foundpetal == -1)
278  {
279  // FIXME: Why I am here?? se supone que deberia haber encontrado algo
280  continue;
281  }
282  // Last check: is inside the R of the petal(sensitive)
283  double rMin = 0.0;
284  double rMax = getMaxRadius(possibleLayer,sensitive);
285  if( ! sensitive )
286  {
287  rMin = getLadderRinner(possibleLayer);
288  }
289  else
290  {
291  rMin = getSensitiveRinner(possibleLayer);
292  }
293 
294  if( pRadius >= rMin && pRadius <= rMax )
295  {
296  return true;
297  }
298  }
299 
300  // debug
301 // std::cout << "**n[0] :" << nBase[0] << " n[1] " <<nBase[1] <<" n[2] " <<nBase[2] << std::endl ;
302 // std::cout << "**nv[0]:" << thisVector[0] << " nv[1]:" << thisVector[1] << "nv[2]:" << thisVector[2] << std::endl ;
303 // std::cout << "**c :" << c << " thick: " << thick << std::endl ; // debug
304 // std::cout << "**sPhi : " << sPhi*180/M_PI <<" pPhi " << pPhi*180/M_PI << " ePhi: " << ePhi*180/M_PI << std::endl ;
305 // std::cout << "**Phi : " << phi*180/M_PI << " atan() : " << atan( p[0]/p[1] ) << std::endl ;
306 // std::cout << "**isEqual[0] " << isEqual( thisVector[0] , -c*nBase[0] )
307 // << " , " << isEqual( thisVector[1] , -c*nBase[1] )
308 // << " , " << isEqual( thisVector[2] , -c*nBase[2] )
309 // << std::endl ;
310  return false ;
311 } // function isPointInFTD
312 */
313 
314 /*Vector3D FTDParametersImpl::distanceToNearestFTD(const Vector3D & p,const bool & sensitive ) const
315 {
316  Vector3D origin( 0,0,0 ) ;
317 
318  // check if point is in already
319  if( isPointInFTD( p , sensitive ) )
320  {
321  return origin ;
322  }
323 
324  // Simulate the disks as 3D-cylinders of Radius max = rMax
325  // and Radius inner = rMin, and length zLength
326  // Let's assume the point is not in the plane of any disk
327 
328  // Let's assume the point is in the plane of a disk
329 
330 
331 
332  // check if point is origin
333  if( origin.x() == p.x() && origin.y() == p.y() && origin.z() == p.z() )
334  {
335  if( _layer.getNLayers() > 0 ){
336 
337  // simply use first ladder - distance d , phi0 , gap/2 :
338  //fg: fixme: review definition of phi...
339  return Vector3D( _layer.getLadderDistance(0) , -_layer.getInternalPhi0(0) , _shellGap/2 , Vector3D::cylindrical ) ;
340  }
341 
342  return origin ;
343  }
344 
345  //fg: FIXME: this code needs to be cleaned up and checked
346  // it can also probably be made a bit faster ...
347 
348 
349  double pPhi = getPhiPoint( p ) ;
350 
351  // this Point is solution
352  Vector3D vPointPlane ;
353  double minDistance = 99999.99 ;
354 
355  // go through all layers
356  for ( int nearestLayer=0 ; nearestLayer < _layer.getNLayers() ; nearestLayer++ ) {
357 
358  // get deltaPhi between ladders
359  double deltaPhi = ( 2 * M_PI ) / _layer.getNLadders( nearestLayer ) ;
360 
361  // get extensions for layer
362  double dist, zStart, zEnd, left, right, thick ;
363  if( !sensitive ) {
364  zEnd = _layer.getLadderLength( nearestLayer ) + _shellGap/2 ;
365  left = -_layer.getLadderWidth( nearestLayer ) / 2 - _layer.getLadderOffset( nearestLayer ) ;
366  right = _layer.getLadderWidth( nearestLayer ) / 2 - _layer.getLadderOffset( nearestLayer ) ;
367  thick = _layer.getLadderThickness( nearestLayer ) ;
368  dist = _layer.getLadderDistance( nearestLayer ) ;
369  }
370  if (sensitive ) {
371  zEnd = _layer.getSensitiveLength( nearestLayer ) + _shellGap/2 ;
372  left = -_layer.getSensitiveWidth( nearestLayer ) / 2 - _layer.getSensitiveOffset( nearestLayer ) ;
373  right = _layer.getSensitiveWidth( nearestLayer ) / 2 - _layer.getSensitiveOffset( nearestLayer ) ;
374  thick = _layer.getSensitiveThickness( nearestLayer ) ;
375  dist = _layer.getSensitiveDistance( nearestLayer ) ;
376  }
377 
378  zStart = _shellGap/2 ;
379 
380  // go through all ladders/sensitive
381  for( int i = 0 ; i < _layer.getNLadders( nearestLayer ) ; i++ ) {
382 
383  double phi = _layer.getInternalPhi0( nearestLayer ) + i*deltaPhi ;
384  phi = correctPhiRange( phi ) ;
385 
386  // check start and end phi for this layer
387  double sPhi = correctPhiRange( phi - deltaPhi ) ;
388  double ePhi = correctPhiRange( phi + deltaPhi ) ;
389 
390  // check if point is in range of ladder
391  bool isInRange =
392  ( ( sPhi <= pPhi ) && ( pPhi <= ePhi ) )
393  ||( ( sPhi > ePhi ) && ( pPhi <= ePhi ) )
394  ||( ( sPhi > ePhi ) && ( pPhi >= sPhi ) ) ;
395 
396  if ( !isInRange ) {
397 
398  continue ;
399  }
400 
401  // take normal vector of planes, Base, Side, Z and spacePoint
402 //fg: ------- test vector3d ---------------------------
403 // Vector3D nBase, nSide, nZ ;
404 
405 // nBase[0] = sin( phi ) ;
406 // nBase[1] = cos( phi ) ;
407 // nBase[2] = 0;
408 
409 // nSide[0] = cos( phi ) ;
410 // nSide[1] = -sin( phi ) ;
411 // nSide[2] = 0 ;
412 
413 // nZ[0] = 0 ;
414 // nZ[1] = 0 ;
415 // nZ[2] = 1 ;
416 
417 // if( p[2] < 0 ) {
418 // nZ[2] = - nZ[2] ;
419 // }
420 
421 // Vector3D spacePoint ;
422 // spacePoint[0] = dist * nBase[0] ;
423 // spacePoint[1] = dist * nBase[1] ;
424 // spacePoint[2] = dist * nBase[2] ;
425 
426 
427  Vector3D nBase( sin( phi ), cos( phi ), 0.0 ) ;
428  Vector3D nSide( cos( phi ), -sin( phi ), 0.0 ) ;
429 
430  Vector3D nZ( 0. , 0. , 1. ) ;
431  if( p[2] < 0 ) {
432  nZ[2] = -nZ[2] ;
433  }
434  Vector3D spacePoint = dist * nBase ;
435 
436 //fg: ------- end test vector3d ---------------------------
437 
438 
439 
440  // upper and lower base
441  // inner (1) and outer (2) boundary
442  for ( int j = 1 ; j<=2 ; j ++ ) {
443 
444  double d = 0 ;
445  if( j == 2 ) {
446  d = thick ;
447  }
448 
449 //fg: ------- test vector3d ---------------------------
450 // Vector3D r ;
451 // r[0] = spacePoint[0] + d * nBase[0] ;
452 // r[1] = spacePoint[1] + d * nBase[1] ;
453 // r[2] = spacePoint[2] + d * nBase[2] ;
454  Vector3D r = spacePoint + d * nBase ;
455 //fg: ------- end test vector3d ---------------------------
456 
457 
458  Vector3D myVec = distanceToPlane( p, r, nBase, nSide, nZ, left, right, zStart, zEnd ) ;
459 
460  // debug
461 // Vector3D iP ( p[0]+myVec[0] , p[1]+myVec[1] , p[2]+myVec[2] ) ;
462 // bool isCorrect = isPointInFTD( iP ) ;
463 
464 // if ( !isCorrect ) {
465 // std::cout << "distanceToPlane returns sth wrong. j =" <<j << std::endl ;
466 // }
467 
468  double thisDistance = sqrt( myVec[0] * myVec[0] + myVec[1] * myVec[1] + myVec[2] * myVec[2] ) ;
469  if ( thisDistance <= minDistance ) {
470  minDistance = thisDistance ;
471  vPointPlane = myVec ;
472 
473 // // debug
474 // std::cout << "\nmyVec set " <<"base " << myVec[0] << " , " << myVec[1] << " , " << myVec[2] << std::endl ; //debug
475 // std::cout << " lay " << nearestLayer << " d " << d << " phi " << phi * 180/M_PI << " j " << j <<std::endl ;
476 // std::cout << " r " << r[0] << " , " << r[1] << " , " << r[2]
477 // << " nSide " << nSide[0] << " , " << nSide[1] << " , " << nSide[2]
478 // << " <--> " <
479 // << left << " - " << right << std::endl;
480  }
481 
482  } // for j -- lower & upper boundary
483 
484 
485  // left and right side
486  // 1 left, 2 right
487 
488  for ( int j = 1 ; j<=2 ; j ++ ) {
489 
490  double d = 0;
491  if ( (!sensitive) and ( j == 1 ) ) {
492  d = - _layer.getLadderWidth( nearestLayer ) / 2 - _layer.getLadderOffset( nearestLayer ) ;
493  }
494  if( (!sensitive) and ( j == 2 ) ) {
495  d = _layer.getLadderWidth( nearestLayer ) / 2 - _layer.getLadderOffset( nearestLayer ) ;
496  }
497  if( (sensitive) and ( j == 1 ) ) {
498  d = - _layer.getSensitiveWidth( nearestLayer ) / 2 - _layer.getSensitiveOffset( nearestLayer ) ;
499  }
500  if( (sensitive) and ( j == 2 ) ) {
501  d = _layer.getSensitiveWidth( nearestLayer ) / 2 - _layer.getSensitiveOffset( nearestLayer ) ;
502  }
503 
504  // lower left corner as r
505  Vector3D r ;
506  r[0] = spacePoint[0] + d * nSide[0] ;
507  r[1] = spacePoint[1] + d * nSide[1] ;
508  r[2] = spacePoint[2] + d * nSide[2] ;
509 
510  Vector3D myVec = distanceToPlane( p, r, nSide, nBase, nZ, 0, thick, zStart, zEnd ) ;
511 
512  double thisDistance = sqrt( myVec[0] * myVec[0] + myVec[1] * myVec[1] + myVec[2] * myVec[2] ) ;
513  if ( thisDistance < minDistance ) {
514  minDistance = thisDistance ;
515  vPointPlane = myVec ;
516 // std::cout << "myVec set " <<"left/right " << myVec[0] << " , " << myVec[1] << " , " << myVec[2] << std::endl ; //debug
517  }
518 
519  } // for j -- left and right corner
520 
521 
522 
523  // z Front and Back
524  for( int j = 1 ; j <= 2 ; j++ ) {
525 
526  double d = 0 ;
527 
528  if( j == 1 ) {
529  d = zEnd ;
530  }
531  else {
532  d = zStart ;
533  }
534 
535  // lower middle corner as r
536  Vector3D r;
537  r[0] = spacePoint[0] + d * nZ[0] ;
538  r[1] = spacePoint[1] + d * nZ[1] ;
539  r[2] = spacePoint[2] + d * nZ[2] ;
540 
541  Vector3D myVec = distanceToPlane( p, r, nZ, nBase, nSide, 0, thick, left, right ) ;
542 
543  double thisDistance = sqrt( myVec[0] * myVec[0] + myVec[1] * myVec[1] + myVec[2] * myVec[2] ) ;
544 
545  if ( thisDistance < minDistance ) {
546  minDistance = thisDistance ;
547  vPointPlane = myVec ;
548 // std::cout << "myVec set " <<" front/back " << myVec[0] << " , " << myVec[1] << " , " << myVec[2] << std::endl ; //debug
549 // std::cout << " thick " << thick << " left " << left << " right " << right << std::endl ;
550 // std::cout << " r " << r[0] << " , " << r[1] << " , " << r[2] << std::endl ;
551  }
552 
553  } // for j -- front and back
554 
555  } // for i -- all ladders in layer
556 
557  } // for nearestLayer -- all layers in vxd
558 
559 
560  return vPointPlane ;
561 
562  } // function distanceToFTD
563 
564 
565 
566 
567 
568  Vector3D FTDParametersImpl::intersectionFTD( Vector3D p , Vector3D v , bool sensitive ) const {
569 
570  // return values
571  double currentLength = 99999 ;
572  Vector3D currentPoint (0. , 0. , 0. ) ;
573 
574  for ( int takeLayer=0 ; takeLayer < _layer.getNLayers() ; takeLayer++ ) {
575 
576  // get deltaPhi between ladders
577  double deltaPhi = ( 2 * M_PI ) / _layer.getNLadders( takeLayer ) ;
578 
579  // get extensions for layer
580  double zStart, zEnd, left, right, thick ;
581  if( !sensitive ) {
582  zEnd = _layer.getLadderLength( takeLayer ) + _shellGap/2 ;
583  left = -_layer.getLadderWidth( takeLayer ) / 2 - _layer.getLadderOffset( takeLayer ) ;
584  right = _layer.getLadderWidth( takeLayer ) / 2 - _layer.getLadderOffset( takeLayer ) ;
585  thick = _layer.getLadderThickness( takeLayer ) ;
586  }
587  if (sensitive ) {
588  zEnd = _layer.getSensitiveLength( takeLayer ) + _shellGap/2 ;
589  left = -_layer.getSensitiveWidth( takeLayer ) / 2 - _layer.getSensitiveOffset( takeLayer ) ;
590  right = _layer.getSensitiveWidth( takeLayer ) / 2 - _layer.getSensitiveOffset( takeLayer ) ;
591  thick = _layer.getSensitiveThickness( takeLayer ) ;
592  }
593 
594  // go through both sides
595  for( int side = 0 ; side <2 ; side++ ) {
596  if( side == 0 ) {
597  zStart = _shellGap /2 ;
598  }
599  else {
600  zEnd = - zEnd ;
601  zStart = - _shellGap/2 ;
602  }
603 
604  // go through all ladders/sensitive
605  for( int i = 0 ; i < _layer.getNLadders( takeLayer ) ; i++ ) {
606 
607  double phi = _layer.getInternalPhi0( takeLayer ) + i*deltaPhi ;
608  phi = correctPhiRange( phi ) ;
609 
610  // take normal vector of planes, Base, Side, Z and spacePoint
611  Vector3D nBase, nSide, nZ, spacePoint;
612 
613  nBase[0] = sin( phi ) ;
614  nBase[1] = cos( phi ) ;
615  nBase[2] = 0;
616 
617  nSide[0] = cos( phi ) ;
618  nSide[1] = -sin( phi ) ;
619  nSide[2] = 0 ;
620 
621  nZ[0] = 0 ;
622  nZ[1] = 0 ;
623  nZ[2] = 1 ;
624 
625  // upper and lower base
626  // inner (1) and outer (2) boundary
627  for ( int j = 1 ; j<=2 ; j ++ ) {
628 
629  double d = 0 ;
630  if ( (!sensitive) and ( j == 1 ) ) {
631  d = _layer.getLadderDistance( takeLayer ) ;
632  }
633  if( (!sensitive) and ( j == 2 ) ) {
634  d = _layer.getLadderDistance( takeLayer ) + thick ;
635  }
636  if( (sensitive) and ( j == 1 ) ) {
637  d = _layer.getSensitiveDistance( takeLayer ) ;
638  }
639  if( (sensitive) and ( j == 2 ) ) {
640  d = _layer.getSensitiveDistance( takeLayer ) + thick ;
641  }
642  Vector3D r( d * nBase[0] , d * nBase[1] , d * nBase[2] ) ;
643 
644  // this vector is equivalent to spacepoint -- needed later on
645  if ( j == 1 ) spacePoint = r ;
646 
647  // get intersection point plane/line
648  Vector3D interSection = planeLineIntersection( r, nBase, p, v ) ;
649 
650  // get vector from point to intersection point
651  Vector3D vip ;
652  vip[0] = interSection[0] - p[0] ;
653  vip[1] = interSection[1] - p[1] ;
654  vip[2] = interSection[2] - p[2] ;
655 
656  // get vector from spacepoint to intersection point
657  Vector3D vn ;
658  vn[0] = interSection[0] - spacePoint[0] ;
659  vn[1] = interSection[1] - spacePoint[1] ;
660  vn[2] = interSection[2] - spacePoint[2] ;
661 
662  // correct in Plane
663  Vector3D inBorder = correctToBorderPoint( vn, nSide, nZ, left, right, zStart, zEnd ) ;
664 
665  // check if point has not changed -> intersects with vxd
666  if ( isEqual( inBorder , vn ) ) {
667 
668  // check if this is closest intersection
669  double thisLength = sqrt( vip[0]*vip[0] + vip[1]*vip[1] +vip[2]*vip[2] ) ;
670  if( thisLength < currentLength ) {
671  currentPoint = interSection ;
672  currentLength = thisLength ;
673  }
674  }
675 
676  } // for j -- lower & upper boundary
677 
678 
679  // left and right side
680  // 1 left, 2 right
681 
682  for ( int j = 1 ; j<=2 ; j ++ ) {
683 
684  double d = 0;
685  if ( (!sensitive) and ( j == 1 ) ) {
686  d = -( _layer.getLadderWidth( takeLayer ) / 2 + _layer.getLadderOffset( takeLayer ) );
687  }
688  if( (!sensitive) and ( j == 2 ) ) {
689  d = _layer.getLadderWidth( takeLayer ) / 2 - _layer.getLadderOffset( takeLayer ) ;
690  }
691  if( (sensitive) and ( j == 1 ) ) {
692  d = -( _layer.getSensitiveWidth( takeLayer ) / 2 + _layer.getSensitiveOffset( takeLayer ) ) ;
693  }
694  if( (sensitive) and ( j == 2 ) ) {
695  d = _layer.getSensitiveWidth( takeLayer ) / 2 - _layer.getSensitiveOffset( takeLayer ) ;
696  }
697 
698  // lower left corner as r
699  Vector3D r ;
700  r[0] = spacePoint[0] + d * nSide[0] ;
701  r[1] = spacePoint[1] + d * nSide[1] ;
702  r[2] = spacePoint[2] + d * nSide[2] ;
703 
704  // get intersection point plane/line
705  Vector3D interSection = planeLineIntersection( r, nSide, p, v ) ;
706 
707  // get vector from point to intersection point
708  Vector3D vip ;
709  vip[0] = interSection[0] - p[0] ;
710  vip[1] = interSection[1] - p[1] ;
711  vip[2] = interSection[2] - p[2] ;
712 
713  // get vector from spacepoint to intersection point
714  Vector3D vn ;
715  vn[0] = interSection[0] - spacePoint[0] ;
716  vn[1] = interSection[1] - spacePoint[1] ;
717  vn[2] = interSection[2] - spacePoint[2] ;
718 
719  // correct in Plane
720  Vector3D inBorder = correctToBorderPoint( vn, nBase, nZ, 0, thick, zStart, zEnd ) ;
721 
722  if ( isEqual( inBorder , vn )) {
723  // check if this is closest intersection
724  double thisLength = sqrt( vip[0]*vip[0] + vip[1]*vip[1] + vip[2]*vip[2] ) ;
725  if( thisLength < currentLength ) {
726  currentPoint = interSection ;
727  currentLength = thisLength ;
728  }
729 
730  }
731 
732 
733  } // for j -- left and right corner
734 
735 
736  // front and back side in z
737 
738  for( int j = 1 ; j <= 2 ; j++ ) {
739 
740  double d = 0 ;
741 
742  if( j == 1 ) {
743  d = zEnd ;
744  }
745  else {
746  d = zStart ;
747  }
748 
749  // lower left corner as r
750  Vector3D r;
751  r[0] = spacePoint[0] + d * nZ[0] ;
752  r[1] = spacePoint[1] + d * nZ[1] ;
753  r[2] = spacePoint[2] + d * nZ[2] ;
754 
755  // get intersection point plane/line
756  Vector3D interSection = planeLineIntersection( r, nZ, p, v ) ;
757 
758  // get vector from point to intersection point
759  Vector3D vip ;
760  vip[0] = interSection[0] - p[0] ;
761  vip[1] = interSection[1] - p[1] ;
762  vip[2] = interSection[2] - p[2] ;
763 
764  // get vector from spacepoint to intersection point
765  Vector3D vn ;
766  vn[0] = interSection[0] - spacePoint[0] ;
767  vn[1] = interSection[1] - spacePoint[1] ;
768  vn[2] = interSection[2] - spacePoint[2] ;
769 
770  // correct in Plane
771  Vector3D inBorder = correctToBorderPoint( vn, nBase, nSide, 0, thick, left, right ) ;
772 
773  if ( isEqual( inBorder , vn ) ) {
774  // check if this is closest intersection
775  double thisLength = sqrt( vip[0]*vip[0] + vip[1]*vip[1] + vip[2]*vip[2] ) ;
776  if( thisLength < currentLength ) {
777  currentPoint = interSection ;
778  currentLength = thisLength ;
779  }
780  }
781 
782  } // for j -- front and back
783 
784 
785  } // for i -- all ladders in layer
786 
787  } // for all zSides
788 
789  } // for nearestLayer -- all layers in vxd
790 
791  return currentPoint ;
792 
793  } // function isIntersectionFTD
794 
795 
796 
797  Vector3D FTDParametersImpl::distanceToPlane( Vector3D p, Vector3D r, Vector3D n, Vector3D u, Vector3D v, float minU, float maxU, float minV, float maxV ) const {
798 
799  // check zeros
800 
801  if ( n[0]==0 && n[1]==0 && n[2]==0 ) {
802 
803  std::cout << "\ndistanceToPlane - Fatal error!" << std::endl ;
804  std::cout << "normal vector (0,0,0)" << std::endl ;
805  return Vector3D (0,0,0) ;
806  }
807 
808  // check u and v
809  if ( !isEqual( n[0]*( u[0]+v[0] ) + n[1]*( u[1]+v[1] ) + n[2]*( u[2]+v[2] ) , 0 ) ){
810  std::cout << "\ndistanceToPlan - Fatal error! "
811  << "n not normal to u and v " << std::endl ;
812  return Vector3D (0,0,0) ;
813  }
814 
815  // The normal n to the plane is n(n0,n1,n2).
816  // The nearest point in the plane is pn(pn0, pn1, pn2)
817  //
818  // The line defined by (pn0-p0)/n0 = (pn1-p1)/n1 = (pn2-p2)/n2 = t
819  // goes through p(p0,p1,p2) and is parallel to n.
820  //
821  // Solving for the point pn we get
822  //
823  // pn0 = n0*t+p0
824  // pn1 = n1*t+p1
825  // pn2 = n2*t+p2
826  //
827  // Now place these values in the equation for the plane:
828  //
829  // n0 * (n0*t+p0) + n1*(n1*t+p1) + n2*(n2*t+p2) + r = 0
830  //
831  // and solve for t:
832  //
833  // t = (-n0*p0-n1*p1-n2*p2-d) / ( n0 * n0 + n1 * n1 + n2 * n2 )
834 
835 
836  // the distance to plane is Vector to spacepoint scalar with n
837 
838  double d = ( r[0] * n[0] + r[1] * n[1] + r[2] * n[2] ) ;
839 
840  double t = - ( n[0] * p[0] + n[1] * p[1] + n[2] * p[2] - d ) ;
841 
842  // nearest point in plane
843  Vector3D pn ;
844  pn[0] = p[0] + n[0] * t;
845  pn[1] = p[1] + n[1] * t;
846  pn[2] = p[2] + n[2] * t;
847 
848  // vector from spacespoint to nearest point in plane
849  Vector3D vn ;
850  vn[0] = pn[0] - r[0] ;
851  vn[1] = pn[1] - r[1] ;
852  vn[2] = pn[2] - r[2] ;
853 
854  // correct to borderPoint
855  Vector3D vCor = correctToBorderPoint( vn , u, v, minU, maxU, minV, maxV ) ;
856 
857  // final vector from point to plane
858  Vector3D final ;
859  final[0] = r[0] + vCor[0] - p[0] ;
860  final[1] = r[1] + vCor[1] - p[1] ;
861  final[2] = r[2] + vCor[2] - p[2] ;
862 
863  return final ;
864 
865  } // function distanceToPlane
866 
867 
868 
869  Vector3D FTDParametersImpl::planeLineIntersection( Vector3D r, Vector3D n, Vector3D linePoint, Vector3D lineDir) const {
870 
871  // calculate distance of plane
872  double distance = ( r[0]*n[0] + r[1]*n[1] + r[2]*n[2] ) / ( sqrt( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] ) ) ;
873 
874  // equations for a point defined by the line with distance to plane = 0
875  // n * ( linePoint + t * lineDir ) - distance = 0
876  // solve for t
877 
878  double numerator = distance - n[0]*linePoint[0] - n[1]*linePoint[1] - n[2]*linePoint[2] ;
879  double denominator = n[0]*lineDir[0] + n[1]*lineDir[1] + n[2]*lineDir[2] ;
880 
881  if ( denominator == 0 ) {
882  // line paralell to plane -> no intersection
883  return Vector3D ( 0. , 0. , 0. ) ;
884  }
885 
886  double t = numerator/denominator ;
887 
888  if( t < 0 ) {
889  // intersection not in direction of line
890  return Vector3D ( 0. , 0. , 0. ) ;
891  }
892 
893  Vector3D final ;
894  final[0] = linePoint[0] + t * lineDir[0] ;
895  final[1] = linePoint[1] + t * lineDir[1] ;
896  final[2] = linePoint[2] + t * lineDir[2] ;
897 
898  return final ;
899 
900  }// function planLineIntersectin
901 
902 
903 
904  Vector3D FTDParametersImpl::correctToBorderPoint( Vector3D vPlane , Vector3D u, Vector3D v, float minU, float maxU, float minV, float maxV ) const {
905 
906  // check if the given vector is within the boundaries
907  double neededUs = vPlane[0] * u[0] + vPlane[1] * u[1] + vPlane[2] * u[2] ;
908  double neededVs = vPlane[0] * v[0] + vPlane[1] * v[1] + vPlane[2] * v[2] ;
909 
910 
911  double goUs = neededUs, goVs = neededVs ;
912  bool changed = false ;
913 
914  if( neededUs < minU ) {
915  goUs = minU ;
916  changed = true ;
917  }
918  if( neededUs > maxU ) {
919  goUs = maxU ;
920  changed = true ;
921  }
922  if( neededVs < minV ) {
923  goVs = minV ;
924  changed = true ;
925  }
926  if( neededVs > maxV ) {
927  goVs = maxV ;
928  changed = true ;
929  }
930 
931  if( !changed ) return vPlane ;
932 
933  Vector3D final ;
934  final[0] = goUs * u[0] + goVs * v[0] ;
935  final[1] = goUs * u[1] + goVs * v[1] ;
936  final[2] = goUs * u[2] + goVs * v[2] ;
937 
938  return final ;
939 
940  } // correctToBorderPoint
941 
942 
943  double FTDParametersImpl::correctPhiRange( double Phi ) const {
944 
945  if( Phi > M_PI ) {
946  return ( Phi - 2 * M_PI ) ;
947  }
948  if( Phi <= -M_PI ) {
949  return ( Phi + 2 * M_PI ) ;
950  }
951 
952  return Phi ;
953 
954  } // function correctPhiRange
955 
956 
957  double FTDParametersImpl::getPhiPoint( Vector3D p ) const {
958 
959  //FG: this is the the angle with the negative y-axis
960  // see comment at the top !
961 
962  // get phi of point in projection 2D
963  double pPhi = 0. ;
964  if( ( p[0] >= 0 ) && ( p[1] == 0 ) )
965  pPhi = -M_PI/2 ;
966 
967  if( ( p[0] < 0 ) && ( p[1] == 0 ) )
968  pPhi = M_PI/2 ;
969 
970  if( ( p[0] == 0 ) && ( p[1] < 0 ) )
971  pPhi = 0 ;
972 
973  if( ( p[0] != 0 ) && ( p[1] < 0 ) )
974  pPhi = atan( p[0] / p[1] ) + M_PI ;
975 
976  else
977  pPhi = atan( p[0] / p[1] ) ;
978 
979  pPhi = correctPhiRange( pPhi ) ;
980 
981  return pPhi ;
982 
983  } // function getPhiPoint
984 
985 
986 
987  bool FTDParametersImpl::isEqual( double valueOne, double valueTwo ) const
988  {
989 
990  // save calculating time if equal
991  if ( valueOne == valueTwo ) return true ;
992 
993 
994  // if one value is 0.0 we use the absolute distance
995  if( valueOne * valueTwo == 0.0 )
996 
997  return fabs( valueOne - valueTwo ) < _EPSILON ;
998 
999 
1000  // if both values are smaller than epsilon they are equal for our purpose
1001  if ( fabs(valueOne) < _EPSILON && fabs(valueTwo) < _EPSILON )
1002 
1003  return true ;
1004 
1005 
1006  // otherwise we require the relative distance of the two values to be smaller than epsilon
1007  return fabs( 2 * (valueOne - valueTwo) ) / (fabs(valueOne) + fabs(valueTwo) ) < _EPSILON ;
1008 
1009  }
1010 
1011 
1012  bool FTDParametersImpl::isEqual( Vector3D p1 , Vector3D p2 ) const
1013  {
1014  for( int i=0 ; i<3 ; i++ ) {
1015  if( !( p1[i] == p2[i] ) ) {
1016  return false ;
1017  }
1018  }
1019  return true ;
1020  } // function isEqual
1021 
1022 
1023  bool FTDParametersImpl::differsLess( double valueOne, double valueTwo ) const
1024  {
1025 
1026  return ( ( fabs( valueOne ) + fabs( valueTwo ) ) < _EPSILON ) ;
1027 
1028  } // function differsLess
1029  */
1030 
1031 } // namespace
1032 
1033 
1034 
virtual int getSensitiveIndex(const Vector3D &p) const
returns the petal Index which correspond to the layer where the point is.
virtual double getSupportRinner(int layerIndex) const
The R-min of the petals in the XY-plane in mm for supports.
int getPetalIndex(const Vector3D &p, const bool &sensitive=false) const
returns the petal number corresponding to a given point.
virtual double getSensitiveRinner(int layerIndex) const
The R-min of the support in the XY-plane in mm for sensors.
bool isPointInFTD(const Vector3D &p, const bool &sensitive=false) const
returns if a point is in support (sensitive == false) or in sensitive (sensitive == true) ...
Simple three dimensional vector providing the components for cartesian, cylindrical and spherical coo...
Definition: Vector3D.h:18
virtual double getMaxRadius(const int &layerIndex, const bool &sensitive=false) const
returns maximum radius for a given layer
virtual int getLayerIndex(const Vector3D &p) const
returns the layerIndex which correspond to the layer where the point is.
virtual double getEndPhi(const int &layerIndex, const int &petalInd, const bool &sensitive=false) const
returns ending phi for first petal in layer layerIndex (on side facing IP)
virtual int getNPetals(int layerIndex) const
The number of petals in the layer layerIndex - layer indexing starts at 0 for the layer closest to IP...
virtual double getStartPhi(const int &layerIndex, const int &petalInd, const bool &sensitive=false) const
returns starting phi for first petal in layer layerIndex (on side facing IP)