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