GEAR  1.9.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends Pages
FixedPadSizeDiskLayout.cc
1 #include "gearimpl/FixedPadSizeDiskLayout.h"
2 
3 #include <cmath>
4 #include <math.h>
5 #include <iostream>
6 #include <sstream>
7 #include <stdexcept>
8 
9 namespace gear {
10 
12  {
13  cleanup();
14  }
15 
17  {
18  return new FixedPadSizeDiskLayout(*this);
19  }
20 
22  {
23  for( unsigned i=0; i<_padIndices.size(); ++i ){
24  delete _padIndices[i] ;
25  }
26  }
27 
29  double padHeight, double padWidth,
30  int nRow ,
31  double padGap,
32  double phiMax) :
33  _rMin( rMin ),
34  _rMax( rMax ),
35  _phiMax( phiMax ),
36  _padWidth( padWidth ) ,
37  _padHeight(padHeight) ,
38  _padGap( padGap )
39  {
40 
41  // minimal sanity check:
42  if ( _padHeight <= 0.0 || _padWidth <= 0.0 ) {
43 
44  std::stringstream s ;
45  s << " FixedPadSizeDiskLayout: missing or inconsistent parameters"
46  << " - padHeight: " << _padHeight
47  << " - padWidth : " << _padWidth ;
48 
49  throw ParseException( s.str() ) ;
50  }
51 
52  // wrap phi to +- 2*pi, which is the max range for phiMin and phiMax
53 
54  while( _phiMax < -2.*M_PI ) { _phiMax += 2. * M_PI ; }
55  while( _phiMax > 2.*M_PI ) { _phiMax -= 2. * M_PI ; }
56 
57 
58  _extent.resize(4) ;
59  _extent[0] = _rMin ;
60  _extent[1] = _rMax ;
61  _extent[2] = 0.0 ;
62  _extent[3] = _phiMax ;
63 
64  // compute the row properties
65 
66  //int nr = (int) std::floor ( ( rMax - rMin ) / _padHeight ) ;
67  //int nr = (int) ( ( rMax - rMin ) / _padHeight ) ;
68  int nr = ( ( rMax + 0.01 - rMin ) / _padHeight ) ;
69 
70  _nRow = ( nRow > 0 ) ? nRow : nr ;
71 
72  if( nRow > nr ) {
73 
74  std::cout << " WARNING: FixedPadSizeDiskLayout() : cannot place " << nRow
75  << " rows of height " << _padHeight
76  << " mm between rMin = " << rMin << " mm and rMax = " << rMax
77  << " mm - will use nRow = " << nr << " !! "
78  << std::endl ;
79 
80  _nRow = nr ;
81 
82 
83  }
84 
85  _padIndices.resize( _nRow ) ;
86  // initialise all pointers to 0
87  // this thing is only filled when accessed by getPadsInRow() the first time
88  // to allocate the memory only when needed
89  for (std::vector< std::vector<int>* >::iterator rowIter = _padIndices.begin() ;
90  rowIter < _padIndices.end(); rowIter++)
91  {
92  *rowIter=0;
93  }
94 
95  _rowHeight = ( rMax - rMin ) / _nRow ;
96 
97  _nPad = 0 ;
98 
99  for( int i = 0 ; i < _nRow ; i++ ) {
100 
101  Row row ;
102 
103  row.RCenter = rMin + ( i * _rowHeight ) + .5 * _rowHeight ;
104 
105  double u = row.RCenter * _phiMax ;
106 
107  row.NPad = static_cast<int>( std::floor( u / (_padWidth + padGap ) ) );
108 
109  row.PhiPad = _phiMax / row.NPad ;
110 
111 // std::cout << " row, row.NPad , row.PhiPad : " << i << " , " << row.NPad << " , " << row.PhiPad
112 // << std::endl;
113 
114  _nPad += row.NPad ;
115 
116  _rows.push_back( row ) ;
117  }
118 
119  }
120 
122  {
123  copy_and_assign(right);
124  }
125 
127  {
128  cleanup();
129  copy_and_assign(right);
130  return *this;
131  }
132 
134  {
135  _rMin = right._rMin;
136  _rMax = right._rMax;
137  _phiMax = right._phiMax;
138  _rowHeight = right._rowHeight;
139  _padWidth = right._padWidth;
140  _padHeight = right._padHeight;
141  _padGap = right._padGap;
142  _nRow = right._nRow;
143  _nPad = right._nPad;
144  _rows = right._rows;
145  _extent = right._extent;
146 
147  // just set the _padIndices to an vector of empty entries.
148  // In every instance, also the copied ones, it is filled only at first
149  // usage to save memory
150  // just like in the constructor
151  _padIndices.resize( _nRow ) ;
152  for (std::vector< std::vector<int>* >::iterator rowIter = _padIndices.begin() ;
153  rowIter < _padIndices.end(); rowIter++)
154  {
155  *rowIter=0;
156  }
157 
158 
159  }
160 
162  return _rows.size() ;
163  }
164 
165 
166  double FixedPadSizeDiskLayout::getPadWidth(int padIndex) const {
167 
168  // phi of pad in row :
169  int rowNum = getRowNumber( padIndex ) ;
170  try {
171 
172  // need to return padWidth in radians !!
173  return _padWidth / _rows.at( rowNum ).RCenter ;
174 
175  }
176  catch(std::out_of_range){
177  return 0. ;
178  }
179  }
180 
181  double FixedPadSizeDiskLayout::getPadPitch(int padIndex) const {
182 
183  // phi of pad in row :
184  int rowNum = getRowNumber( padIndex ) ;
185  try {
186 
187  // need to return padPitch in radians !!
188  return _rows.at( rowNum ).PhiPad;
189 
190  }
191  catch(std::out_of_range){
192  return 0. ;
193  }
194  }
195 
196 
197 
199 
200  int rowNum = getRowNumber( padIndex ) ;
201  int padNum = getPadNumber( padIndex ) ;
202 
203  double r = _rows[ rowNum ].RCenter ;
204 
205  double phi = ( padNum + 0.5 ) * _rows[ rowNum ].PhiPad ;
206 
207  return Vector2D( r , phi ) ;
208 // return std::make_pair( r , phi ) ;
209  }
210 
211  const std::vector<int>& FixedPadSizeDiskLayout::getPadsInRow(int rowNumber) const {
212 
213  static std::vector<int> empty ;
214  try {
215  if( _padIndices.at(rowNumber ) == 0 ) {
216 
217  int nPad = _rows.at(rowNumber).NPad ;
218 
219  _padIndices[ rowNumber ] = new std::vector<int>( nPad ) ;
220 
221  for(int i = 0 ; i < nPad ; i++){
222 
223  _padIndices[rowNumber]->operator[](i) = getPadIndex( rowNumber , i ) ;
224  }
225 
226  }
227  } catch( std::out_of_range& r) {
228 
229  // std::cout << " FixedPadSizeDiskLayout::getPadsInRow : no row " << rowNumber << std::endl ;
230  return empty ;
231 
232  }
233 
234  return *_padIndices[ rowNumber ] ;
235 
236  }
237 
238  int FixedPadSizeDiskLayout::getPadIndex(int rowNum, int padNum) const {
239 
240  if( (unsigned) rowNum > _rows.size() - 1 ) {
241 
242  throw std::out_of_range(" FixedPadSizeDiskLayout::getPadIndex row number too large !");
243  }
244 
245  if( padNum > _rows[rowNum].NPad - 1 ) {
246 
247  std::stringstream sstr ;
248 
249  sstr << "FixedPadSizeDiskLayout::getPadIndex: pad number too large: "
250  << padNum << " only " << _rows[rowNum].NPad << " pads in row " << rowNum ;
251 
252  throw std::out_of_range( sstr.str() );
253  }
254 
255  return (rowNum << 16 ) | ( 0x0000ffff & padNum ) ;
256 
257 
258  }
259 
260  int FixedPadSizeDiskLayout::getNearestPad(double r, double phi) const {
261 
262  if (fabs(r) < 1e-6)
263  throw Exception("FixedPadSizeDiskLayout::getNearestPad: r can't be zero !");
264 
265  // Initialise with the radius itself. In case of a full circle there is no
266  // phiMin or phiMax, just to avoid compiler warnings
267  double rProjectedOnPhiMax = r;
268  double rProjectedOnPhiMin = r;
269 
270  if (fabs(_phiMax - 2*M_PI) < 1e-6) {
271 
272  // wrap phi to 0 < phi < 2*M_PI
273  while( phi < 0 ) { phi += 2. * M_PI ; }
274  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
275 
276  } else {
277 
278  while( phi < -2*M_PI ) { phi += 2. * M_PI ; }
279  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
280 
281  rProjectedOnPhiMax = r * cos(phi - _phiMax);
282  rProjectedOnPhiMin = r * cos(phi - 0.);
283 
284  }
285 
286  //
287 
288  int rowNum = 0;
289  int padNum = 0;
290 
291  // We make two distinct cases:
292  // Area 1: The point (r, phi) is inside (r > 0, phiMin <= phi <= phiMax),
293  // Area 2: Points outside Area 1.
294 
295  // Area 1
296  // This was the original code for the whole circle. (Modified a bit)
297 
298  if ( r > 0. && phi >= 0. && phi <= _phiMax) {
299  rowNum = r < _rMin ? 0 : (int) std::floor( ( r - _rMin ) / _rowHeight ) ;
300 
301  if( rowNum >= _nRow )
302  rowNum = _nRow -1 ;
303 
304  padNum = (int) std::floor( phi / _rows[ rowNum ].PhiPad ) ;
305 
306  if( padNum >= _rows[ rowNum ].NPad )
307  padNum = _rows[ rowNum ].NPad - 1 ;
308 
309  // std::cout << " FixedPadSizeDiskLayout::getNearestPad( " << r << " , " << phi << " ) "
310  // << " _rows[ rowNum ].PhiPad : " << _rows[ rowNum ].PhiPad
311  // << std::endl ;
312 
313  return getPadIndex( rowNum , padNum ) ;
314  }
315 
316  // Area 2 can be optimized by dividing it into more areas.
317  // Then we don't need to calculate distances at all!
318  // For best understanding you need to draw all the areas on paper by hand.
319  //
320  // Expensive condition checkings are moved towards the end.
321 
322  else if ( rProjectedOnPhiMin < _rMin && phi < 0 ) {
323  //std::cout << "r < _rMin && phi < 0" << std::endl;
324 
325  rowNum = 0;
326  padNum = 0;
327  }
328 
329  else if ( rProjectedOnPhiMin > _rMax && phi < 0 ) {
330  //std::cout << "r > _rMax && phi < 0" << std::endl;
331 
332  rowNum = _nRow - 1;
333  padNum = 0;
334  }
335 
336  else if ( rProjectedOnPhiMax < _rMin && phi > _phiMax ) {
337  //std::cout << "r < _rMin * cos(phi - _phiMax) && phi > _phiMax" << std::endl;
338 
339  rowNum = 0;
340  padNum = _rows[ rowNum ].NPad - 1 ;
341  }
342 
343  else if ( rProjectedOnPhiMax > _rMax && phi > _phiMax ) {
344  //std::cout << "r > _rMax * cos(phi - _phiMax) && phi > _phiMax" << std::endl;
345 
346  rowNum = _nRow - 1;
347  padNum = _rows[ rowNum ].NPad - 1 ;
348  }
349 
350  else if ( rProjectedOnPhiMin >= _rMin && rProjectedOnPhiMin <= _rMax && phi < 0 ) {
351  //std::cout << "r >= _rMin && r <= _rMax && phi < 0" << std::endl;
352 
353  r = rProjectedOnPhiMin;
354 
355  rowNum = (int) std::floor( ( r - _rMin ) / _rowHeight ) ;
356 
357  rowNum = rowNum < 0 ? 0 : rowNum;
358  rowNum = rowNum >= _nRow ? _nRow -1 : rowNum;
359 
360  padNum = 0;
361  }
362 
363  else if ( rProjectedOnPhiMax >= _rMin && rProjectedOnPhiMax <= _rMax && phi > _phiMax ) {
364  //std::cout << "r >= _rMin * cos(phi - _phiMax) && r <= _rMax * cos(phi - _phiMax) && phi > _phiMax" << std::endl;
365 
366  r = rProjectedOnPhiMax;
367 
368  rowNum = (int) std::floor( ( r - _rMin ) / _rowHeight ) ;
369 
370  rowNum = rowNum < 0 ? 0 : rowNum;
371  rowNum = rowNum >= _nRow ? _nRow -1 : rowNum;
372 
373  padNum = _rows[ rowNum ].NPad - 1 ;
374  }
375 
376  else {
377  std::cout
378  << "I have no idea where the nearest pad is for the point ("
379  << r << ", "
380  << phi << ")"
381  << std::endl;
382 
383  rowNum = 0;
384  padNum = 0;
385  }
386 
387  return getPadIndex( rowNum , padNum ) ;
388 
389  // Another implementation that was implemented before the upper
390  // implementation.
391 
392  // Area 2
393  // Check each pad that is on the border, except for the pads on the most
394  // outer circle, since that one is in Area 1.
395 
396  //float r_pad, p_pad;
397  //float x_pad, y_pad;
398  //
399  //float minDistance = 0;
400  //float curDistance = 0.;
401  //
402  //float minR = 0.;
403  //float minPhi = 0.;
404  //
405  //for (
406  // std::vector<Row>::const_iterator it = _rows.begin();
407  // it != _rows.end();
408  // ++it
409  //) {
410  //
411  // for (
412  // float checkPhi = 0.5 * it->PhiPad;
413  // checkPhi < it->PhiPad * it->NPad;
414  // checkPhi += it->PhiPad
415  // ) {
416  //
417  // r_pad = it->RCenter;
418  // p_pad = checkPhi;
419  //
420  // x_pad = r_pad * cos(p_pad);
421  // y_pad = r_pad * sin(p_pad);
422  //
423  // curDistance = pow(x_pad - r*cos(phi), 2) + pow(y_pad - r*sin(phi), 2);
424  //
425  // if (
426  // (curDistance < minDistance)
427  // || (it == _rows.begin() && checkPhi - 0.5 * it->PhiPad < 1e-6)
428  // ) {
429  // minDistance = curDistance;
430  //
431  // minR = r_pad;
432  // minPhi = p_pad;
433  // }
434  //
435  // // When it is not the row closest to the origin,
436  // // jump to the second last pad in the row
437  // // (the foreach loop will then jump to the last pad)
438  //
439  // if (it != _rows.begin()) {
440  // checkPhi += it->PhiPad * (it->NPad - 2);
441  // }
442  //
443  // }
444  //
445  //}
446  //
447  //rowNum = (int) std::floor( ( minR - _rMin ) / _rowHeight ) ;
448  //
449  //padNum = (int) std::floor( minPhi / _rows[ rowNum ].PhiPad ) ;
450 
451  //return getPadIndex( rowNum , padNum ) ;
452  }
453 
455 
456  int pn = getPadNumber( padIndex ) + 1 ;
457  int rn = getRowNumber( padIndex) ;
458 
459  int nPad = _rows.at(rn).NPad ;
460 
461  if( pn > nPad-1 ) {
462 
463  // If it is a full circle, go back to the first one.
464  if (fabs(_phiMax - 2*M_PI) < 1e-6)
465  pn = 0;
466 
467  else
468  throw Exception("FixedPadSizeDiskLayout::getLeftNeighbour: no left neighbour pad !");
469 
470  }
471 
472 
473  return getPadIndex( rn , pn ) ;
474  }
475 
477 
478  int pn = getPadNumber( padIndex ) - 1 ;
479  int rn = getRowNumber( padIndex) ;
480 
481  int nPad = _rows.at(rn).NPad ;
482 
483  if( pn < 0 ){
484 
485  // If it is a full circle, go back to the last one.
486  if (fabs(_phiMax - 2*M_PI) < 1e-6)
487  pn = nPad - 1;
488 
489  else
490  throw Exception("FixedPadSizeDiskLayout::getRightNeighbour: no right neighbour pad !");
491 
492  }
493 
494  return getPadIndex( rn , pn ) ;
495  }
496 
497 
498  bool FixedPadSizeDiskLayout::isInsidePad(double r, double phi, int padIndex) const {
499 
500 // double rCenter = 0. ;
501 // int rowNumber = getRowNumber( padIndex ) ;
502 // try { rCenter = _rows.at( rowNumber ).RCenter ;
503 // }
504 // catch(std::out_of_range){
505 // return false ;
506 // }
507 
508  if( r < _rMin || r > _rMax )
509  return false ;
510 
511  // wrap phi to 0 < phi < 2*M_PI
512 
513  while( phi < 0 ) { phi += 2. * M_PI ; }
514  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
515 
516  Vector2D p = getPadCenter( padIndex ) ;
517 
518 // double phiPadHalf = 0.5 * _padWidth / rCenter ;
519 
520  double phiPadHalf = 0.5 * getPadWidth( padIndex ) ;
521 
522 
523 // std::cout << " isInsidePad( " << rowNumber << ", " << phiPadHalf << ", " << 0.5 * _padHeight
524 // << " - ( " << p.first << ", " << p.second << " ) "
525 // << (std::abs( r - p.first ) <= 0.5 * _padHeight) << "&&"
526 // << (std::abs( phi - p.second ) <= phiPadHalf)
527 // << std::endl ;
528 
529 // return ( std::abs( r - p.first ) <= 0.5 * _padHeight &&
530 // std::abs( phi - p.second ) <= phiPadHalf ) ;
531 
532  return ( std::abs( r - p[0] ) <= 0.5 * _padHeight &&
533  std::abs( phi - p[1] ) <= phiPadHalf ) ;
534 
535  }
536 
537  bool FixedPadSizeDiskLayout::isInsidePad(double r, double phi) const {
538 
539  if( r < _rMin || r > _rMax )
540  return false ;
541 
542  // wrap phi to 0 < phi < 2*M_PI
543 
544  while( phi < 0 ) { phi += 2. * M_PI ; }
545  while( phi > 2.*M_PI ) { phi -= 2. * M_PI ; }
546 
547  return isInsidePad( r , phi , getNearestPad( r, phi ) ) ;
548 
549  }
550 
551 } // namespace
FixedPadSizeDiskLayout(double rMin, double rMax, double padHeight, double PadWidth, int nRow=0, double padGap=0., double phiMax=2 *M_PI)
Construct the FixedPadSizeDiskLayout from the given parameters rMin, rMax, padHeight and PadWidth whe...
FixedPadSizeDiskLayout & operator=(const FixedPadSizeDiskLayout &)
The assignment operator.
virtual int getNRows() const
The number of rows.
Abstract description of a planar subdetector with pads (cells) that are positioned in rows (circular ...
virtual double getPadPitch(int padIndex) const
The pitch of the pad in radians (metal + gap)
void copy_and_assign(const FixedPadSizeDiskLayout &)
function to copy all internal variables, incl.
virtual int getPadNumber(int padIndex) const
The pad number (column) within the row - numbering starts at phi/x =.
Base exception class for GEAR - all other exceptions extend this.
Definition: GEAR.h:41
void cleanup()
function to delete all the objects pointed to and owned by the FixedPadSizeDiskLayout.
Implementation of PadRowLayout2D for a disk with fixed sized keystone pads.
virtual int getNearestPad(double c0, double c1) const
The index of the pad nearest to the given point in 2d coordinates (x,y,) or (r,phi).
virtual int getRightNeighbour(int padIndex) const
The index of the right neighbour pad.
virtual bool isInsidePad(double c0, double c1, int padIndex) const
True if coordinate (c0,c1) is within the given pad.
ParseException used for parse errors, e.g.
Definition: GEAR.h:65
Internal helper class for FixedPadSizeDiskLayout.
virtual int getLeftNeighbour(int padIndex) const
The index of the left neighbour pad.
virtual int getPadIndex(int rowNum, int padNum) const
Create a padIndex for the given row and pad ( column ) number.
virtual const std::vector< int > & getPadsInRow(int rowNumber) const
Indices of all pads in row rowNumber (row indices start from 0 at the bottom (CARTESIAN) or at the ce...
virtual int getRowNumber(int padIndex) const
The number of the row that contains the pad at padIndex - numbering starts at r/y==0.
virtual Vector2D getPadCenter(int padIndex) const
The center of the pad in 2d coordinates, (x,y) or (r,phi).
PadRowLayout2D * clone() const
Returns a copy (clone) of this class.
virtual ~FixedPadSizeDiskLayout()
Destructor.
virtual double getPadWidth(int padIndex) const
The width of the pad in radians (only the metal)