]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/mapping/AliMpSlatZonePadIterator.cxx
- Reordering includes and/or
[u/mrichter/AliRoot.git] / MUON / mapping / AliMpSlatZonePadIterator.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: AliMpSlatZonePadIterator.cxx,v 1.6 2006/03/02 16:38:11 ivana Exp $
18
19 #include "AliMpSlatZonePadIterator.h"
20
21 #include "AliLog.h"
22 #include "AliMpPCB.h"
23 #include "AliMpSlat.h"
24 #include "AliMpSlatSegmentation.h"
25
26 #include "Riostream.h"
27 #include <algorithm>
28 #include <limits>
29 #include <cassert>
30
31 ClassImp(AliMpSlatZonePadIterator)
32
33 // This iterator only works within a region of constant density.
34
35 namespace 
36 {
37   const Double_t epsilon = 1E-4; // cm
38   Double_t DMAX(std::numeric_limits<Double_t>::max());
39 }
40
41 //_____________________________________________________________________________
42 AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat,
43                                                    const AliMpArea& area)
44 : AliMpVPadIterator(),
45 fkSlat(slat),
46 fSlatSegmentation(new AliMpSlatSegmentation(slat)),
47 fArea(area),
48 fOffset(0.0,0.0),
49 fStep(0.0,0.0),
50 fIsDone(kTRUE)
51 {
52   //
53   // Normal ctor.
54   // Iteration will be done on the slat, over the crop of (area,slat_area)
55   //
56   if (!CropArea()) 
57     {
58       AliError(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s",
59                     area.LeftBorder(),area.DownBorder(),
60                     area.RightBorder(),area.UpBorder(),fkSlat->GetID()));
61     }
62   Invalidate();
63 }
64
65 //_____________________________________________________________________________
66 AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator()
67 {
68   //
69   // Dtor.
70   //
71   delete fSlatSegmentation;
72 }
73
74 //_____________________________________________________________________________
75 Bool_t
76 AliMpSlatZonePadIterator::CropArea()
77 {
78   //
79   // Checks the area is correct, and truncate it
80   // if it goes outside the slat.
81
82   AliDebug(3,Form("Input area (%7.2f,%7.2f)->(%7.2f,%7.2f)",
83                   fArea.LeftBorder(),fArea.DownBorder(),
84                   fArea.RightBorder(),fArea.UpBorder()));
85
86   // Left and right x-limits have to come from first and last pcbs
87   // to deal with short and rounded pcbs cases.
88   AliMpPCB* first = fkSlat->FindPCB(fArea.LeftBorder(),fArea.DownBorder());
89   AliMpPCB* last = fkSlat->FindPCB(fArea.RightBorder()-epsilon,
90                                  fArea.DownBorder());
91
92   AliDebug(3,Form("First PCB %s Ixmin %2d Last PCB %s Ixmax %2d",
93                   first->GetID(),first->Ixmin(),
94                   last->GetID(),last->Ixmax()));
95
96   Double_t xleft = first->ActiveXmin();
97   Double_t xright = last->ActiveXmax() - epsilon;
98
99   AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright));
100
101   Double_t xmin = std::max(fArea.LeftBorder(),xleft);
102   Double_t xmax = std::min(fArea.RightBorder(),xright);
103   Double_t ymin = std::max(fArea.DownBorder(),0.0);
104   Double_t ymax = std::min(fArea.UpBorder(),fkSlat->DY()*2.0-epsilon);
105
106   AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)",
107                   xmin,ymin,xmax,ymax));
108   
109   // At this point (xmin,ymin)->(xmax,ymax) should be a zone completely included
110   // inside the slat.
111   // But there's so far no guarantee that it is "filling" an integer number
112   // of pads. The following lines solve this, by expanding the area up to 
113   // the bottomLeft and topRight limits of the pads sitting at (xmin,ymin)
114   // and (xmax,ymax).
115
116   AliMpPad bottomLeft 
117     = fSlatSegmentation->PadByPosition(TVector2(xmin,ymin)-fkSlat->Position(),
118                                        kFALSE);
119
120   StdoutToAliDebug(3,
121                    cout << "bottomLeft=" << endl;
122                    bottomLeft.Print();
123                    cout << bottomLeft.Position().X()+fkSlat->Position().X()
124                    << "," << bottomLeft.Position().Y()+fkSlat->Position().Y()
125                    << endl;
126                    );
127   
128   if ( bottomLeft.IsValid() )
129     {
130       xmin = std::min(xmin,fkSlat->DX() + 
131                       bottomLeft.Position().X() - bottomLeft.Dimensions().X());
132       ymin = std::min(ymin,fkSlat->DY() + 
133                       bottomLeft.Position().Y() - bottomLeft.Dimensions().Y());
134     }
135
136   AliMpPad topRight 
137     = fSlatSegmentation->PadByPosition(TVector2(xmax,ymax)-fkSlat->Position(),
138                                        kFALSE);
139   StdoutToAliDebug(3,
140                    cout << "topRight=" << endl;
141                    topRight.Print();
142                    cout << topRight.Position().X()+fkSlat->Position().X()
143                    << "," << topRight.Position().Y()+fkSlat->Position().Y()
144                    << endl;
145                    
146                    );
147
148   if ( topRight.IsValid() )
149     {
150       xmax = std::max(xmax,fkSlat->DX() + 
151                       topRight.Position().X() + topRight.Dimensions().X());
152       ymax = std::max(ymax,fkSlat->DY() + 
153                       topRight.Position().Y() + topRight.Dimensions().Y());
154     }
155
156   fArea = AliMpArea(TVector2((xmin+xmax)/2.0,(ymin+ymax)/2.0),
157                     TVector2((xmax-xmin)/2.0,(ymax-ymin)/2.0));
158  
159   AliDebug(3,Form("Paddified cropped area (%7.2f,%7.2f)->(%7.2f,%7.2f)",
160                   fArea.LeftBorder(),fArea.DownBorder(),
161                   fArea.RightBorder(),fArea.UpBorder())); 
162
163   // Finally set the step sizes equal to the smallest pad sizes (which is
164   // hereby assumed to be that of the first pcb).
165   fStep.Set(first->PadSizeX(),first->PadSizeY());
166
167   AliDebug(3,Form("Step Sizes (%7.2f,%7.2f)",fStep.X(),fStep.Y()));
168
169   return fArea.IsValid();
170 }
171
172 //_____________________________________________________________________________
173 AliMpPad
174 AliMpSlatZonePadIterator::CurrentItem() const
175 {
176   //
177   // Returns the current iteration position (i.e. a pad)
178   //
179   return fCurrentPad;
180 }
181
182 //_____________________________________________________________________________
183 Bool_t
184 AliMpSlatZonePadIterator::GetNextPosition(Double_t& x, Double_t& y)
185 {
186   // Get the next iteration position. 
187   // On input, fOffset must be a valid position (i.e. within iteration
188   // area already).
189
190   AliDebug(3,Form("input (x,y)=(%7.2f,%7.2f)",x,y));
191
192   x += fStep.X();
193
194   if ( x > fArea.Dimensions().X() ) 
195     {
196       AliDebug(3,"Going back left and one step upper");
197       // Go back leftmost position...
198       x = -1.0*fArea.Dimensions().X();
199       // ... and up
200       y += fStep.Y();
201       // Update y offset
202       fOffset.Set(fOffset.X(),y);
203       if ( y > fArea.Dimensions().Y() )
204       {
205         return false;
206       }
207     }
208   AliDebug(3,Form("output (x,y)=(%7.2f,%7.2f",x,y));
209   return true;
210 }
211
212 //_____________________________________________________________________________
213 void
214 AliMpSlatZonePadIterator::First()
215 {
216   //
217   // (re)Starts the iteration.
218   //
219   
220   fOffset = fArea.Dimensions()*(-1.0);
221   fIsDone = kFALSE;
222   SetPad(fCurrentPad,fArea.Position()+fOffset);
223   if (!fCurrentPad.IsValid()) Next();
224   AliDebug(3,Form("fOffset after Next=%7.2f,%7.2f",fOffset.X(),fOffset.Y()));
225   if ( !fCurrentPad.IsValid() ) 
226     {
227       // did not find any valid pad in there, bailing out.
228       fIsDone = kTRUE;
229       AliError(Form("Could not initiate iterator for slat %s. "
230                     " Please check the area you gave : %e,%e +- %e,%e",
231                     fkSlat->GetName(),
232                     fArea.Position().X(),
233                     fArea.Position().Y(),
234                     fArea.Dimensions().X(),
235                     fArea.Dimensions().Y()));
236       return;
237     }
238   else
239     {
240       // Reposition to pad center (both in x and y).
241       // Please note that repositionning y is valid here, and only here
242       // (i.e. do *not* do this in Next() for instance).
243       fOffset.Set(fCurrentPad.Position().X()+fkSlat->DX()-fArea.Position().X(),
244                   fCurrentPad.Position().Y()+fkSlat->DY()-fArea.Position().Y());
245       fIsDone = kFALSE;
246     }
247   AliDebug(3,Form("fOffset repositionned=%7.2f,%7.2f",fOffset.X(),fOffset.Y()));
248 }
249
250 //_____________________________________________________________________________
251 void
252 AliMpSlatZonePadIterator::Invalidate()
253 {
254   //
255   // Invalidate the iterator.
256   //
257   
258   fOffset = TVector2(DMAX,DMAX);
259   fCurrentPad = AliMpPad::Invalid();
260   fIsDone = kTRUE;
261 }
262
263 //_____________________________________________________________________________
264 Bool_t
265 AliMpSlatZonePadIterator::IsDone() const
266 {
267   //
268   // Whether the iteration is finished or not.
269   //
270   return fIsDone;
271 }
272
273 //_____________________________________________________________________________
274 void
275 AliMpSlatZonePadIterator::Next()
276 {
277   // This one is the meat of the class.
278   // We're iterating in x-direction mainly, starting from 
279   // lower-left of the iteration area, and proceeding right,
280   // until we reach right border, in which case we increment y
281   // and go back to leftmost position.
282   // Put otherwise, here's basically how it should work:
283   // try to do x+=xstep. If outside the area, get back to xmin
284   // and try y+=ystep. If outside of the window end-of-game.
285   // When new x,y known, get the corresponding pad.
286   // If same pad as before (should not happen if step sizes are
287   // well chosen) or not valid pad (might happen for e.g. rounded pcbs), 
288   // restart.
289   // End of iteration occurs when both x and y are outside the iteration
290   // window.
291   
292   if (IsDone()) return;
293
294   AliMpPad pad(fCurrentPad);
295   int n = 0;
296   Double_t x(fOffset.X());
297   Double_t y(fOffset.Y());
298
299   while ( ( pad == fCurrentPad || !pad.IsValid() ) && n<100 )
300   {
301     ++n;
302     if (GetNextPosition(x,y)==kFALSE) 
303     {
304       Invalidate();
305       return;
306     } 
307     SetPad(pad,fArea.Position()+TVector2(x,y));
308   }
309   fCurrentPad = pad;
310 }
311
312 //_____________________________________________________________________________
313 void
314 AliMpSlatZonePadIterator::SetPad(AliMpPad& pad, const TVector2& pos)
315 {
316   //
317   // Sets the current pad.
318   //
319   pad = fSlatSegmentation->PadByPosition(pos-fkSlat->Position(),kFALSE);
320   if ( pad.IsValid() )
321     {
322       // Reposition fOffset to pad center (only in x-direction).
323       fOffset.Set(pad.Position().X()+fkSlat->DX()-fArea.Position().X(),
324                   fOffset.Y());
325     }
326   else
327   {
328     AliDebug(3,Form("No pad at pos=%e,%e",pos.X(),pos.Y()));
329   }
330 }