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