]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/mapping/AliMpSlatZonePadIterator.cxx
New class - the factory for building mapping segmentations
[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$
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
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 {
58 AliFatal(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//_____________________________________________________________________________
66AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator()
67{
68 //
69 // Dtor.
70 //
71 delete fSlatSegmentation;
72}
73
74//_____________________________________________________________________________
75Bool_t
76AliMpSlatZonePadIterator::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
9447b076 99 AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright));
dee1d5f1 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
9447b076 106 AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)",
dee1d5f1 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
1964cd2e 117 = fSlatSegmentation->PadByPosition(TVector2(xmin,ymin)-fkSlat->Position(),
118 kFALSE);
9447b076 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
dee1d5f1 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
1964cd2e 137 = fSlatSegmentation->PadByPosition(TVector2(xmax,ymax)-fkSlat->Position(),
138 kFALSE);
9447b076 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
dee1d5f1 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//_____________________________________________________________________________
173AliMpPad
174AliMpSlatZonePadIterator::CurrentItem() const
175{
176 //
177 // Returns the current iteration position (i.e. a pad)
178 //
179 return fCurrentPad;
180}
181
182//_____________________________________________________________________________
183Bool_t
184AliMpSlatZonePadIterator::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 {
1964cd2e 196 AliDebug(3,"Going back left and one step upper");
dee1d5f1 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() )
1964cd2e 204 {
205 return false;
206 }
dee1d5f1 207 }
208 AliDebug(3,Form("output (x,y)=(%7.2f,%7.2f",x,y));
209 return true;
210}
211
212//_____________________________________________________________________________
213void
214AliMpSlatZonePadIterator::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;
1964cd2e 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()));
dee1d5f1 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//_____________________________________________________________________________
251void
252AliMpSlatZonePadIterator::Invalidate()
253{
254 //
255 // Invalidate the iterator.
256 //
257
258 fOffset = TVector2(DMAX,DMAX);
259 fCurrentPad = AliMpPad::Invalid();
260 fIsDone = kTRUE;
261}
262
263//_____________________________________________________________________________
264Bool_t
265AliMpSlatZonePadIterator::IsDone() const
266{
267 //
268 // Whether the iteration is finished or not.
269 //
270 return fIsDone;
271}
272
273//_____________________________________________________________________________
274void
275AliMpSlatZonePadIterator::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 )
1964cd2e 300 {
301 ++n;
302 if (GetNextPosition(x,y)==kFALSE)
dee1d5f1 303 {
1964cd2e 304 Invalidate();
305 return;
306 }
307 SetPad(pad,fArea.Position()+TVector2(x,y));
308 }
dee1d5f1 309 fCurrentPad = pad;
310}
311
312//_____________________________________________________________________________
313void
314AliMpSlatZonePadIterator::SetPad(AliMpPad& pad, const TVector2& pos)
315{
316 //
317 // Sets the current pad.
318 //
1964cd2e 319 pad = fSlatSegmentation->PadByPosition(pos-fkSlat->Position(),kFALSE);
dee1d5f1 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(),
1964cd2e 324 fOffset.Y());
dee1d5f1 325 }
1964cd2e 326 else
327 {
328 AliDebug(3,Form("No pad at pos=%e,%e",pos.X(),pos.Y()));
329 }
dee1d5f1 330}