GEAR  1.9.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends Pages
FixedPadAngleDiskLayout.cc
1 #include "gearimpl/FixedPadAngleDiskLayout.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 FixedPadAngleDiskLayout(*this);
19  }
20 
22  {
23  for( unsigned i=0; i<_padIndices.size(); ++i ){
24  delete _padIndices[i] ;
25  }
26  }
27 
28  FixedPadAngleDiskLayout::FixedPadAngleDiskLayout( double rMin, double rMax, int nRow,
29  double phiMin, double phiMax, int nPadsInRow )
30  : _rMin( rMin ),
31  _rMax( rMax ),
32  _nRow( nRow ) ,
33  _phiMin( phiMin ),
34  _phiMax( phiMax ),
35  _nPadsInRow( nPadsInRow )
36  {
37 
38  _rowHeight = ( rMax - rMin ) / _nRow ;
39  _padAngle = (phiMax - phiMin) / nPadsInRow;
40 
41 // // minimal sanity check:
42 // if ( _padHeight <= 0.0 || _padWidth <= 0.0 ) {
43 //
44 // std::stringstream s ;
45 // s << " FixedPadAngleDiskLayout: missing or inconsistent parameters"
46 // << " - padHeight: " << _padHeight
47 // << " - padWidth : " << _padWidth ;
48 //
49 // throw ParseException( s.str() ) ;
50 // }
51 
52  _extent.resize(4) ;
53  _extent[0] = rMin ;
54  _extent[1] = rMax ;
55  _extent[2] = phiMin ;
56  _extent[3] = phiMax ;
57 
58 // // compute the row properties
59 //
60 // int nr = (int) std::floor ( ( rMax - rMin ) / _padHeight ) ;
61 //
62 // _nRow = ( nRow > 0 ) ? nRow : nr ;
63 //
64 // if( nRow > nr ) {
65 //
66 // std::cout << " WARNING: FixedPadAngleDiskLayout() : cannot place " << nRow
67 // << " rows of height " << _padHeight
68 // << " mm between rMin = " << rMin << " mm and rMax = " << rMax
69 // << " mm - will use nRow = " << nr << " !! "
70 // << std::endl ;
71 //
72 // _nRow = nr ;
73 //
74 // }
75 
76  _padIndices.resize( nRow ) ;
77  // initialise all pointers to 0
78  // this thing is only filled when accessed by getPadsInRow() the first time
79  // to allocate the memory only when needed
80  for (std::vector< std::vector<int>* >::iterator rowIter = _padIndices.begin() ;
81  rowIter < _padIndices.end(); rowIter++)
82  {
83  *rowIter=0;
84  }
85 
86 
87  _nPad = nRow * nPadsInRow ;
88 
89 // for( int i = 0 ; i < _nRow ; i++ ) {
90 //
91 // Row row ;
92 //
93 // row.RCenter = rMin + ( i * _rowHeight ) + .5 * _rowHeight ;
94 //
95 // double u = 2. * row.RCenter * M_PI ;
96 //
97 // row.NPad = (int) std::floor( u / (_padWidth + padGap ) ) ;
98 //
99 // row.PhiPad = 2. * M_PI / row.NPad ;
100 //
103 //
104 // _nPad += row.NPad ;
105 //
106 // _rows.push_back( row ) ;
107 // }
108  }
109 
111  {
112  copy_and_assign(right);
113  }
114 
116  {
117  cleanup();
118  copy_and_assign(right);
119  return *this;
120  }
121 
123  {
124  _padAngle = right._padAngle;
125  _rMin = right._rMin;
126  _rMax = right._rMax;
127  _nRow = right._nRow;
128  _rowHeight = right._rowHeight;
129  _phiMin = right._phiMin;
130  _phiMax = right._phiMax;
131 
132  _nPad = right._nPad;
133  _nPadsInRow = right._nPadsInRow;
134 
135  _extent = right._extent;
136 
137  // just set the _padIndices to an vector of empty entries.
138  // In every instance, also the copied ones, it is filled only at first
139  // usage to save memory
140  // just like in the constructor
141  _padIndices.resize( _nRow ) ;
142  for (std::vector< std::vector<int>* >::iterator rowIter = _padIndices.begin() ;
143  rowIter < _padIndices.end(); rowIter++)
144  {
145  *rowIter=0;
146  }
147 
148 
149  }
150 
152 
153  int rowNum = getRowNumber( padIndex ) ;
154  int padNum = getPadNumber( padIndex ) ;
155 
156  double r = (static_cast<double>(rowNum)+0.5) * _rowHeight + _rMin;
157 
158  double phi = ( static_cast<double>(padNum) + 0.5 ) * _padAngle + _phiMin ;
159 
160  return Vector2D( r , phi ) ;
161  }
162 
163  const std::vector<int>& FixedPadAngleDiskLayout::getPadsInRow(int rowNumber) const {
164 
165  static std::vector<int> empty ;
166  try
167  {
168  if( _padIndices.at(rowNumber ) == 0 )
169  {
170  _padIndices[ rowNumber ] = new std::vector<int>( _nPadsInRow ) ;
171 
172  for(int i = 0 ; i < _nPadsInRow ; i++)
173  {
174  _padIndices[rowNumber]->operator[](i) = getPadIndex( rowNumber , i ) ;
175  }
176 
177  }
178  } catch( std::out_of_range& r) {
179 
180  // std::cout << " FixedPadAngleDiskLayout::getPadsInRow : no row " << rowNumber << std::endl ;
181  return empty ;
182 
183  }
184 
185  return *_padIndices[ rowNumber ] ;
186 
187  }
188 
189  int FixedPadAngleDiskLayout::getPadIndex(int rowNum, int padNum) const {
190 
191  if( rowNum > _nRow - 1 )
192  {
193  throw std::out_of_range(" FixedPadAngleDiskLayout::getPadIndex row number too large !");
194  }
195 
196  if( padNum > _nPadsInRow - 1 ) {
197 
198  std::stringstream sstr ;
199 
200  sstr << "FixedPadAngleDiskLayout::getPadIndex: pad number too large: "
201  << padNum << ", only " << _nPadsInRow << " pads in row " << rowNum ;
202 
203  throw std::out_of_range( sstr.str() );
204  }
205 
206  return (rowNum << 16 ) | ( 0x0000ffff & padNum ) ;
207 
208 
209  }
210 
211  int FixedPadAngleDiskLayout::getNearestPad(double r, double phi) const
212  {
213 
214  if( r < 0.0 )
215  throw std::out_of_range("FixedPadAngleDiskLayout::getNearestPad: radius must not be negative in polar coordinates!" );
216 
217  double phiMean = (_phiMax+_phiMin)/2.;
218 
219  // wrap phi to a symmetric range of 2*pi around the mean angle of the module
220  while( phi < phiMean-M_PI ) { phi += 2. * M_PI ; }
221  while( phi > phiMean+M_PI ) { phi -= 2. * M_PI ; }
222 
223  if ( (phi <= _phiMax) && (phi >= _phiMin) )
224  {
225  // This is easy, the pad number in the row is the one corresponding to the angle
226  int padNumber = static_cast<int>( (phi - _phiMin) / _padAngle );
227 
228  int rowNum = r < _rMin ? 0 : (int) std::floor( ( r - _rMin ) / _rowHeight ) ;
229 
230  if( rowNum >= _nRow )
231  rowNum = _nRow -1 ;
232 
233  return getPadIndex( rowNum , padNumber ) ;
234  }
235 
236  int rowNum_right;
237  if (fabs(phi - _phiMin) > M_PI_2)
238  {
239  // Note: It is also possible that fabs(phi - _phiMin) > M_PI_2 is larger than 3/2 pi, in which case
240  // the statement 'rowNum_right =0' is not necessarily correct and the calculation below
241  // might be used. However, the nearest pad will not be on this edge (has to be within +- pi).
242  // Hence the calculation of the distance will pick the other, correct pad, so it does not matter
243  // if the calculated distance is done to the nearest pad on this edge or the pad in row 0.
244  rowNum_right = 0;
245  }
246  else
247  {
248  // calculate pca to straight line along radius with _phiMin
249 
250  // determine r_intersect for x = r_intersect * cos(_phiMin) = r* cos(phi) - m * sin(_phiMin)
251  // y = r_intersect * sin(_phiMin) = r*sin(phi) + m * cos(_phiMin)
252  // solve this to r_intersect and m
253  double r_intersect_min = r * (cos(phi)*cos(_phiMin) + sin(phi)*sin(_phiMin));
254  // double m_min = r * (cos(phi)*sin(_phiMin) - sin(phi)*cos(_phiMin));
255 
256  // determine the nearest pad on the rightmost edge
257  rowNum_right = r_intersect_min < _rMin ? 0 : (int) std::floor( ( r - _rMin ) / _rowHeight ) ;
258  if( rowNum_right >= _nRow )
259  rowNum_right = _nRow -1 ;
260  }
261 
262  // now the same for _phiMax
263  int rowNum_left;
264  if (fabs(phi - _phiMax) > M_PI_2)
265  {
266  rowNum_left = 0;
267  }
268  else
269  {
270  double r_intersect_max = r * (cos(phi)*cos(_phiMax) + sin(phi)*sin(_phiMax));
271  // double m_max = r * (cos(phi)*sin(_phiMax) - sin(phi)*cos(_phiMax));
272 
273  // determine the nearest pad on the leftmost edge
274  rowNum_left = r_intersect_max < _rMin ? 0 : (int) std::floor( ( r - _rMin ) / _rowHeight ) ;
275  if( rowNum_left >= _nRow )
276  rowNum_left = _nRow -1 ;
277  }
278 
279  double distance_right = getDistanceToPad( r, phi, getPadIndex( rowNum_right , 0 ) );
280  double distance_left = getDistanceToPad( r, phi, getPadIndex( rowNum_left , _nPadsInRow - 1 ) );
281 
282  return (distance_right < distance_left ? getPadIndex( rowNum_right , 0 ) : getPadIndex( rowNum_left , _nPadsInRow - 1 ) );
283 
284  }
285 
287 
288  int pn = getPadNumber( padIndex ) - 1 ;
289  int rn = getRowNumber( padIndex) ;
290 
291  // anything larger than _nPadsInRow would have caused an out_of_range exception in
292  // getPadNumber
293  if(pn == -1)
294  {
295  // take into account wrap arround in case of full circle (incl. rounding errors)
296  if (fabs(_phiMax - _phiMin - 2*M_PI) < 1e-6 )
297  pn = _nPadsInRow - 1;
298  else
299  throw Exception("FixedPadAngleDiskLayout::getRightNeighbour: no right neighbour pad !");
300  }
301 
302  return getPadIndex( rn , pn ) ;
303  }
304 
306 
307  int pn = getPadNumber( padIndex ) + 1 ;
308  int rn = getRowNumber( padIndex) ;
309 
310  // anything larger than _nPadsInRow would have caused an out_of_range exception in
311  // getPadNumber
312  if (pn == _nPadsInRow)
313  {
314  // take into account wrap arround in case of full circle (incl. rounding errors)
315  if (fabs(_phiMax - _phiMin - 2*M_PI) < 1e-6 )
316  pn = 0 ;
317  else
318  throw Exception("FixedPadAngleDiskLayout::getLeftNeighbour: no left neighbour pad !");
319  }
320 
321  return getPadIndex( rn , pn ) ;
322  }
323 
324 
325  bool FixedPadAngleDiskLayout::isInsidePad(double r, double phi, int padIndex) const {
326 
327 // double rCenter = 0. ;
328 // int rowNumber = getRowNumber( padIndex ) ;
329 // try { rCenter = _rows.at( rowNumber ).RCenter ;
330 // }
331 // catch(std::out_of_range){
332 // return false ;
333 // }
334  Vector2D padCenter = getPadCenter( padIndex);
335 
336  if( (r < padCenter[0] - _rowHeight/2.) || (r > padCenter[0] + _rowHeight/2.) ||
337  (phi < padCenter[1]- _padAngle/2.) || (phi > padCenter[1]+_padAngle/2. ) )
338  return false ;
339  else
340  return true;
341  }
342 
343  bool FixedPadAngleDiskLayout::isInsidePad(double r, double phi) const {
344 
345  if( (r < _rMin) || (r > _rMax) || (phi < _phiMin) || (phi > _phiMax) )
346  return false ;
347  else
348  return true ;
349  }
350 
351 } // namespace
352 
virtual int getNearestPad(double c0, double c1) const
The index of the pad nearest to the given point in 2d coordinates (r, phi).
virtual Vector2D getPadCenter(int padIndex) const
The center of the pad in 2d coordinates (r,phi).
virtual ~FixedPadAngleDiskLayout()
Destructor.
Abstract description of a planar subdetector with pads (cells) that are positioned in rows (circular ...
Base exception class for GEAR - all other exceptions extend this.
Definition: GEAR.h:41
virtual int getRightNeighbour(int padIndex) const
The index of the right neighbour pad.
virtual double getDistanceToPad(double c0, double c1, int padIndex) const
Returns the closest distance to the edge (outer border) of the pad.
Implementation of PadRowLayout2D for a disk with fixed angled keystone pads.
FixedPadAngleDiskLayout & operator=(const FixedPadAngleDiskLayout &)
The assignment operator.
virtual int getLeftNeighbour(int padIndex) const
The index of the left neighbour pad.
virtual bool isInsidePad(double c0, double c1, int padIndex) const
True if coordinate (c0,c1) is within the given pad.
void copy_and_assign(const FixedPadAngleDiskLayout &)
Function to copy all internal variables, incl. the objects pointed to and owned by the FixedPadAngleD...
FixedPadAngleDiskLayout(double rMin, double rMax, int nRow, double phiMin, double phiMax, int nPadsInRow)
Construct the FixedPadAngleDiskLayout from the given parameters rMin, rMax, nRow, phiMin...
virtual int getPadIndex(int rowNum, int padNum) const
Create a padIndex for the given row and pad ( column ) number.
virtual int getRowNumber(int padIndex) const
The number of the row that contains the pad at padIndex.
PadRowLayout2D * clone() const
Returns a copy (clone) of this class.
virtual const std::vector< int > & getPadsInRow(int rowNumber) const
Indices of all pads in row rowNumber (row indices start at rMin).
virtual int getPadNumber(int padIndex) const
The pad number (column) within the row.
void cleanup()
Function to delete all the objects pointed to and owned by the FixedPadAngleDiskLayout.