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