]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/MUONmapping/AliMpPCBPadIterator.cxx
Correct use of ROOT_INCLUDE_DIR
[u/mrichter/AliRoot.git] / MUON / MUONmapping / AliMpPCBPadIterator.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17 // $MpId$
18
19 #include "AliMpPCBPadIterator.h"
20
21 #include "AliMpArea.h"
22 #include "AliMpConstants.h"
23 #include "AliLog.h"
24 #include "AliMpPCB.h"
25 #include "AliMpSlat.h"
26 #include "AliMpSlatSegmentation.h"
27 #include "AliMpEncodePair.h"
28
29 #include "Riostream.h"
30 #include "TMath.h"
31
32
33 //-----------------------------------------------------------------------------
34 /// \class AliMpPCBPadIterator
35 /// 
36 /// Iterates over slat pads within a region of constant pad size.
37 /// 
38 /// \author Laurent Aphecetche
39 //-----------------------------------------------------------------------------
40
41 using std::cout;
42 using std::endl;
43 /// \cond CLASSIMP
44 ClassImp(AliMpPCBPadIterator)
45 /// \endcond
46
47 //_____________________________________________________________________________
48 AliMpPCBPadIterator::AliMpPCBPadIterator(const AliMpSlat* slat,
49                                          const AliMpArea& area)
50 : AliMpVPadIterator(),
51 fkSlat(slat),
52 fSlatSegmentation(new AliMpSlatSegmentation(slat)),
53 fMinIndices(0),
54 fMaxIndices(0),
55 fOffset(0),
56 fCurrentPad(),
57 fIsDone(kTRUE)
58 {
59   ///
60   /// Normal ctor.
61   /// Iteration will be done on the slat, over the crop of (area,slat_area)
62   ///
63   if (!CropArea(area)) 
64   {
65     AliError(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s",
66                   area.LeftBorder(),area.DownBorder(),
67                   area.RightBorder(),area.UpBorder(),fkSlat->GetID()));
68   }
69   Invalidate();
70 }
71
72 //_____________________________________________________________________________
73 AliMpPCBPadIterator::~AliMpPCBPadIterator()
74 {
75   ///
76   /// Dtor.
77   ///
78   delete fSlatSegmentation;
79 }
80
81 //_____________________________________________________________________________
82 Bool_t
83 AliMpPCBPadIterator::CropArea(const AliMpArea& area)
84 {
85   ///
86   /// Checks the area is correct, and truncate it
87   /// if it goes outside the slat.
88   
89   AliDebug(3,Form("Input area (%7.2f,%7.2f)->(%7.2f,%7.2f)",
90                   area.LeftBorder(),area.DownBorder(),
91                   area.RightBorder(),area.UpBorder()));
92   
93   const Double_t kEpsilon = AliMpConstants::LengthTolerance();
94   
95   // Left and right x-limits have to come from first and last pcbs
96   // to deal with short and rounded pcbs cases.
97   AliMpPCB* first = fkSlat->FindPCB(area.LeftBorder(),area.DownBorder());
98   AliMpPCB* last = fkSlat->FindPCB(area.RightBorder()-kEpsilon,
99                                    area.DownBorder());
100   
101   // Check we're indeed dealing with only one pcb
102   if ( first != last )
103   {
104     AliError("This iterator supposed to work on a single PCB. Please check");
105     return kFALSE;
106   }
107   
108   AliDebug(3,Form("PCB %s Ixmin %2d Ixmax %2d",
109                   first->GetID(),first->Ixmin(),first->Ixmax()));
110   
111   Double_t xleft = first->ActiveXmin();
112   Double_t xright = first->ActiveXmax() - kEpsilon;
113   
114   AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright));
115   
116   Double_t xmin = TMath::Max(area.LeftBorder(),xleft);
117   Double_t xmax = TMath::Min(area.RightBorder(),xright);
118   Double_t ymin = TMath::Max(area.DownBorder(),0.0);
119   Double_t ymax = TMath::Min(area.UpBorder(),first->DY()*2.0-kEpsilon);
120   
121   AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)",
122                   xmin,ymin,xmax,ymax));
123   
124   // At this point (xmin,ymin)->(xmax,ymax) should be a zone completely included
125   // inside the slat.
126   // We now try to convert this into a couple of indices pair indicating the
127   // region to iterate over, using integer values, not floating point ones.
128   // For this, we must find out the 4 pads that intersect the (xmin,ymin;xmax,ymax)
129   // area.
130   
131   Int_t ixmin = first->Ixmin() + TMath::FloorNint((xmin-first->ActiveXmin())/first->PadSizeX());
132   Int_t ixmax = first->Ixmin() + TMath::CeilNint((xmax-first->ActiveXmin())/first->PadSizeX()) - 1;
133   Int_t iymin = first->Iymin() + TMath::FloorNint((ymin-first->Ymin())/first->PadSizeY());
134   Int_t iymax = first->Iymin() + TMath::CeilNint((ymax-first->Ymin())/first->PadSizeY()) - 1;
135   
136   
137   fMinIndices = AliMp::Pair(ixmin,iymin);
138   fMaxIndices = AliMp::Pair(ixmax,iymax);
139   
140   AliDebug(3,Form("Paddified cropped area (%d,%d)->(%d,%d) %d,%d ; %d,%d",
141                   ixmin,iymin,ixmax,iymax,
142                   AliMp::PairFirst(fMinIndices),AliMp::PairSecond(fMinIndices),
143                   AliMp::PairFirst(fMaxIndices),AliMp::PairSecond(fMaxIndices)));
144   
145   return fMinIndices >= 0 && fMaxIndices >= 0;
146 }
147
148 //_____________________________________________________________________________
149 AliMpPad
150 AliMpPCBPadIterator::CurrentItem() const
151 {
152   ///
153   /// Returns the current iteration position (i.e. a pad)
154   ///
155   return fCurrentPad;
156 }
157
158 //_____________________________________________________________________________
159 void
160 AliMpPCBPadIterator::First()
161 {
162   ///
163   /// (re)Starts the iteration.
164   ///
165   
166   AliDebug(3,Form("area = (%d,%d)->(%d,%d)",
167                   AliMp::PairFirst(fMinIndices),AliMp::PairSecond(fMinIndices),
168                   AliMp::PairFirst(fMaxIndices),AliMp::PairSecond(fMaxIndices)));
169   fOffset = fMinIndices;
170   fIsDone = kFALSE;
171   SetPad(fCurrentPad,AliMp::PairFirst(fOffset),AliMp::PairSecond(fOffset));
172   if ( ! fCurrentPad.IsValid() ) Next();
173   if ( ! fCurrentPad.IsValid() ) 
174   {
175     // did not find any valid pad in there, bailing out.
176     fIsDone = kTRUE;
177     AliError(Form("Could not initiate iterator for slat %s. "
178                   " Please check the area you gave : %d,%d to %d,%d",
179                   fkSlat->GetName(),
180                   AliMp::PairFirst(fMinIndices),AliMp::PairSecond(fMinIndices),
181                   AliMp::PairFirst(fMaxIndices),AliMp::PairSecond(fMaxIndices)));
182     return;
183   }
184 }
185
186 //_____________________________________________________________________________
187 Bool_t
188 AliMpPCBPadIterator::GetNextPosition(Int_t& ix, Int_t& iy) const
189 {
190   /// Get the next iteration position. 
191   /// On input, fOffset must be a valid position (i.e. within iteration
192   /// area already).
193   
194   ++ix;
195   
196   if ( ix > AliMp::PairFirst(fMaxIndices) )
197   {
198     // Go back leftmost position...
199     ix = AliMp::PairFirst(fMinIndices);
200     // ... and up
201     ++iy;
202     if ( iy > AliMp::PairSecond(fMaxIndices) )
203     {
204       return false;
205     }
206   }
207   return true;
208 }
209
210
211 //_____________________________________________________________________________
212 void
213 AliMpPCBPadIterator::Invalidate()
214 {
215   ///
216   /// Invalidate the iterator.
217   ///
218   fOffset = 0;
219   fCurrentPad = AliMpPad::Invalid();
220   fIsDone = kTRUE;
221 }
222
223 //_____________________________________________________________________________
224 Bool_t
225 AliMpPCBPadIterator::IsDone() const
226 {
227   ///
228   /// Whether the iteration is finished or not.
229   ///
230   return fIsDone;
231 }
232
233 //_____________________________________________________________________________
234 void
235 AliMpPCBPadIterator::Next()
236 {
237   /// This one is the meat of the class.
238   /// We're iterating in x-direction mainly, starting from 
239   /// lower-left of the iteration area, and proceeding right,
240   /// until we reach right border, in which case we increment y
241   /// and go back to leftmost position.
242   /// End of iteration occurs when both x and y are outside the iteration
243   /// window.
244   
245   if (IsDone()) return;
246   
247   AliMpPad pad(fCurrentPad);
248   int n = 0;
249   Int_t ix(AliMp::PairFirst(fOffset));
250   Int_t iy(AliMp::PairSecond(fOffset));
251   
252   while ( ( pad == fCurrentPad || ! pad.IsValid() ) && n<100 )
253   {
254     ++n;
255     if (GetNextPosition(ix,iy)==kFALSE) 
256     {
257       Invalidate();
258       return;
259     } 
260     SetPad(pad,ix,iy);
261   }
262   if ( n>=100 )
263   {
264     AliFatal("This should not happen!");
265   }
266   fCurrentPad = pad;
267 }
268
269 //_____________________________________________________________________________
270 void 
271 AliMpPCBPadIterator::Print(Option_t*) const
272 {
273   /// printout
274   cout << Form("fkSlat=%p fSlatSegmentation=%p (%s)",fkSlat,fSlatSegmentation,
275                fkSlat->GetName()) << endl
276   << Form("minIndices=(%d,%d) maxIndices=(%d,%d)",
277           AliMp::PairFirst(fMinIndices),AliMp::PairSecond(fMinIndices),
278           AliMp::PairFirst(fMaxIndices),AliMp::PairSecond(fMaxIndices)) << endl
279   << Form("currentOffset=(%d,%d) isdone=%d currentpad=",
280           AliMp::PairFirst(fOffset),AliMp::PairSecond(fOffset),fIsDone) << endl;
281   fCurrentPad.Print();
282 }
283
284 //_____________________________________________________________________________
285 void
286 AliMpPCBPadIterator::SetPad(AliMpPad& pad, Int_t ix, Int_t iy)
287 {
288   ///
289   /// Sets the current pad.
290   ///
291   pad = fSlatSegmentation->PadByIndices(ix, iy,kFALSE);
292   if (pad.IsValid())
293   {
294     fOffset = AliMp::Pair(ix,iy);
295   }
296 }