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