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