]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/mapping/AliMpSlatZonePadIterator.cxx
Work around for CINT bug in root 5.10/00, with gcc4.0.2
[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>
29#include <cassert>
30
31ClassImp(AliMpSlatZonePadIterator)
32
33// This iterator only works within a region of constant density.
34
35namespace
36{
9447b076 37 const Double_t epsilon = 1E-4; // cm
dee1d5f1 38 Double_t DMAX(std::numeric_limits<Double_t>::max());
39}
40
41//_____________________________________________________________________________
42AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat,
43 const AliMpArea& area)
44: AliMpVPadIterator(),
45fkSlat(slat),
46fSlatSegmentation(new AliMpSlatSegmentation(slat)),
47fArea(area),
48fOffset(0.0,0.0),
49fStep(0.0,0.0),
50fIsDone(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 {
b4c2e272 58 AliError(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s",
dee1d5f1 59 area.LeftBorder(),area.DownBorder(),
60 area.RightBorder(),area.UpBorder(),fkSlat->GetID()));
61 }
62 Invalidate();
63}
64
884a73f1 65//______________________________________________________________________________
66AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlatZonePadIterator& right)
67 : AliMpVPadIterator(right)
68{
69/// Protected copy constructor (not implemented)
70
71 AliFatal("Copy constructor not provided.");
72}
73
dee1d5f1 74//_____________________________________________________________________________
75AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator()
76{
77 //
78 // Dtor.
79 //
80 delete fSlatSegmentation;
81}
82
884a73f1 83//______________________________________________________________________________
84AliMpSlatZonePadIterator&
85AliMpSlatZonePadIterator::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
dee1d5f1 97//_____________________________________________________________________________
98Bool_t
99AliMpSlatZonePadIterator::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
9447b076 122 AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright));
dee1d5f1 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
9447b076 129 AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)",
dee1d5f1 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
1964cd2e 140 = fSlatSegmentation->PadByPosition(TVector2(xmin,ymin)-fkSlat->Position(),
141 kFALSE);
9447b076 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
dee1d5f1 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
1964cd2e 160 = fSlatSegmentation->PadByPosition(TVector2(xmax,ymax)-fkSlat->Position(),
161 kFALSE);
9447b076 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
dee1d5f1 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//_____________________________________________________________________________
196AliMpPad
197AliMpSlatZonePadIterator::CurrentItem() const
198{
199 //
200 // Returns the current iteration position (i.e. a pad)
201 //
202 return fCurrentPad;
203}
204
205//_____________________________________________________________________________
206Bool_t
207AliMpSlatZonePadIterator::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 {
1964cd2e 219 AliDebug(3,"Going back left and one step upper");
dee1d5f1 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() )
1964cd2e 227 {
228 return false;
229 }
dee1d5f1 230 }
231 AliDebug(3,Form("output (x,y)=(%7.2f,%7.2f",x,y));
232 return true;
233}
234
235//_____________________________________________________________________________
236void
237AliMpSlatZonePadIterator::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;
1964cd2e 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()));
dee1d5f1 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//_____________________________________________________________________________
274void
275AliMpSlatZonePadIterator::Invalidate()
276{
277 //
278 // Invalidate the iterator.
279 //
280
281 fOffset = TVector2(DMAX,DMAX);
282 fCurrentPad = AliMpPad::Invalid();
283 fIsDone = kTRUE;
284}
285
286//_____________________________________________________________________________
287Bool_t
288AliMpSlatZonePadIterator::IsDone() const
289{
290 //
291 // Whether the iteration is finished or not.
292 //
293 return fIsDone;
294}
295
296//_____________________________________________________________________________
297void
298AliMpSlatZonePadIterator::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 )
1964cd2e 323 {
324 ++n;
325 if (GetNextPosition(x,y)==kFALSE)
dee1d5f1 326 {
1964cd2e 327 Invalidate();
328 return;
329 }
330 SetPad(pad,fArea.Position()+TVector2(x,y));
331 }
dee1d5f1 332 fCurrentPad = pad;
333}
334
335//_____________________________________________________________________________
336void
337AliMpSlatZonePadIterator::SetPad(AliMpPad& pad, const TVector2& pos)
338{
339 //
340 // Sets the current pad.
341 //
1964cd2e 342 pad = fSlatSegmentation->PadByPosition(pos-fkSlat->Position(),kFALSE);
dee1d5f1 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(),
1964cd2e 347 fOffset.Y());
dee1d5f1 348 }
1964cd2e 349 else
350 {
351 AliDebug(3,Form("No pad at pos=%e,%e",pos.X(),pos.Y()));
352 }
dee1d5f1 353}