1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 // $MpId: AliMpSlatZonePadIterator.cxx,v 1.9 2006/05/24 13:58:50 ivana Exp $
19 #include "AliMpSlatZonePadIterator.h"
23 #include "AliMpSlat.h"
24 #include "AliMpSlatSegmentation.h"
26 #include "Riostream.h"
31 /// \class AliMpSlatZonePadIterator
33 /// Iterates over slat pads within a region of constant pad size.
35 /// \author Laurent Aphecetche
38 ClassImp(AliMpSlatZonePadIterator)
41 const Double_t AliMpSlatZonePadIterator::fgkEpsilon = 1E-4; // cm
42 const Double_t AliMpSlatZonePadIterator::fgkDmax = std::numeric_limits<Double_t>::max();
44 //_____________________________________________________________________________
45 AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat,
46 const AliMpArea& area)
47 : AliMpVPadIterator(),
49 fSlatSegmentation(new AliMpSlatSegmentation(slat)),
58 // Iteration will be done on the slat, over the crop of (area,slat_area)
62 AliError(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s",
63 area.LeftBorder(),area.DownBorder(),
64 area.RightBorder(),area.UpBorder(),fkSlat->GetID()));
69 //_____________________________________________________________________________
70 AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator()
75 delete fSlatSegmentation;
78 //_____________________________________________________________________________
80 AliMpSlatZonePadIterator::CropArea()
83 // Checks the area is correct, and truncate it
84 // if it goes outside the slat.
86 AliDebug(3,Form("Input area (%7.2f,%7.2f)->(%7.2f,%7.2f)",
87 fArea.LeftBorder(),fArea.DownBorder(),
88 fArea.RightBorder(),fArea.UpBorder()));
90 // Left and right x-limits have to come from first and last pcbs
91 // to deal with short and rounded pcbs cases.
92 AliMpPCB* first = fkSlat->FindPCB(fArea.LeftBorder(),fArea.DownBorder());
93 AliMpPCB* last = fkSlat->FindPCB(fArea.RightBorder()-fgkEpsilon,
96 AliDebug(3,Form("First PCB %s Ixmin %2d Last PCB %s Ixmax %2d",
97 first->GetID(),first->Ixmin(),
98 last->GetID(),last->Ixmax()));
100 Double_t xleft = first->ActiveXmin();
101 Double_t xright = last->ActiveXmax() - fgkEpsilon;
103 AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright));
105 Double_t xmin = std::max(fArea.LeftBorder(),xleft);
106 Double_t xmax = std::min(fArea.RightBorder(),xright);
107 Double_t ymin = std::max(fArea.DownBorder(),0.0);
108 Double_t ymax = std::min(fArea.UpBorder(),fkSlat->DY()*2.0-fgkEpsilon);
110 AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)",
111 xmin,ymin,xmax,ymax));
113 // At this point (xmin,ymin)->(xmax,ymax) should be a zone completely included
115 // But there's so far no guarantee that it is "filling" an integer number
116 // of pads. The following lines solve this, by expanding the area up to
117 // the bottomLeft and topRight limits of the pads sitting at (xmin,ymin)
121 = fSlatSegmentation->PadByPosition(TVector2(xmin,ymin)-fkSlat->Position(),
125 cout << "bottomLeft=" << endl;
127 cout << bottomLeft.Position().X()+fkSlat->Position().X()
128 << "," << bottomLeft.Position().Y()+fkSlat->Position().Y()
132 if ( bottomLeft.IsValid() )
134 xmin = std::min(xmin,fkSlat->DX() +
135 bottomLeft.Position().X() - bottomLeft.Dimensions().X());
136 ymin = std::min(ymin,fkSlat->DY() +
137 bottomLeft.Position().Y() - bottomLeft.Dimensions().Y());
141 = fSlatSegmentation->PadByPosition(TVector2(xmax,ymax)-fkSlat->Position(),
144 cout << "topRight=" << endl;
146 cout << topRight.Position().X()+fkSlat->Position().X()
147 << "," << topRight.Position().Y()+fkSlat->Position().Y()
152 if ( topRight.IsValid() )
154 xmax = std::max(xmax,fkSlat->DX() +
155 topRight.Position().X() + topRight.Dimensions().X());
156 ymax = std::max(ymax,fkSlat->DY() +
157 topRight.Position().Y() + topRight.Dimensions().Y());
160 fArea = AliMpArea(TVector2((xmin+xmax)/2.0,(ymin+ymax)/2.0),
161 TVector2((xmax-xmin)/2.0,(ymax-ymin)/2.0));
163 AliDebug(3,Form("Paddified cropped area (%7.2f,%7.2f)->(%7.2f,%7.2f)",
164 fArea.LeftBorder(),fArea.DownBorder(),
165 fArea.RightBorder(),fArea.UpBorder()));
167 // Finally set the step sizes equal to the smallest pad sizes (which is
168 // hereby assumed to be that of the first pcb).
169 fStep.Set(first->PadSizeX(),first->PadSizeY());
171 AliDebug(3,Form("Step Sizes (%7.2f,%7.2f)",fStep.X(),fStep.Y()));
173 return fArea.IsValid();
176 //_____________________________________________________________________________
178 AliMpSlatZonePadIterator::CurrentItem() const
181 // Returns the current iteration position (i.e. a pad)
186 //_____________________________________________________________________________
188 AliMpSlatZonePadIterator::GetNextPosition(Double_t& x, Double_t& y)
190 // Get the next iteration position.
191 // On input, fOffset must be a valid position (i.e. within iteration
194 AliDebug(3,Form("input (x,y)=(%7.2f,%7.2f)",x,y));
198 if ( x > fArea.Dimensions().X() )
200 AliDebug(3,"Going back left and one step upper");
201 // Go back leftmost position...
202 x = -1.0*fArea.Dimensions().X();
206 fOffset.Set(fOffset.X(),y);
207 if ( y > fArea.Dimensions().Y() )
212 AliDebug(3,Form("output (x,y)=(%7.2f,%7.2f",x,y));
216 //_____________________________________________________________________________
218 AliMpSlatZonePadIterator::First()
221 // (re)Starts the iteration.
224 fOffset = fArea.Dimensions()*(-1.0);
226 SetPad(fCurrentPad,fArea.Position()+fOffset);
227 if (!fCurrentPad.IsValid()) Next();
228 AliDebug(3,Form("fOffset after Next=%7.2f,%7.2f",fOffset.X(),fOffset.Y()));
229 if ( !fCurrentPad.IsValid() )
231 // did not find any valid pad in there, bailing out.
233 AliError(Form("Could not initiate iterator for slat %s. "
234 " Please check the area you gave : %e,%e +- %e,%e",
236 fArea.Position().X(),
237 fArea.Position().Y(),
238 fArea.Dimensions().X(),
239 fArea.Dimensions().Y()));
244 // Reposition to pad center (both in x and y).
245 // Please note that repositionning y is valid here, and only here
246 // (i.e. do *not* do this in Next() for instance).
247 fOffset.Set(fCurrentPad.Position().X()+fkSlat->DX()-fArea.Position().X(),
248 fCurrentPad.Position().Y()+fkSlat->DY()-fArea.Position().Y());
251 AliDebug(3,Form("fOffset repositionned=%7.2f,%7.2f",fOffset.X(),fOffset.Y()));
254 //_____________________________________________________________________________
256 AliMpSlatZonePadIterator::Invalidate()
259 // Invalidate the iterator.
262 fOffset = TVector2(fgkDmax,fgkDmax);
263 fCurrentPad = AliMpPad::Invalid();
267 //_____________________________________________________________________________
269 AliMpSlatZonePadIterator::IsDone() const
272 // Whether the iteration is finished or not.
277 //_____________________________________________________________________________
279 AliMpSlatZonePadIterator::Next()
281 // This one is the meat of the class.
282 // We're iterating in x-direction mainly, starting from
283 // lower-left of the iteration area, and proceeding right,
284 // until we reach right border, in which case we increment y
285 // and go back to leftmost position.
286 // Put otherwise, here's basically how it should work:
287 // try to do x+=xstep. If outside the area, get back to xmin
288 // and try y+=ystep. If outside of the window end-of-game.
289 // When new x,y known, get the corresponding pad.
290 // If same pad as before (should not happen if step sizes are
291 // well chosen) or not valid pad (might happen for e.g. rounded pcbs),
293 // End of iteration occurs when both x and y are outside the iteration
296 if (IsDone()) return;
298 AliMpPad pad(fCurrentPad);
300 Double_t x(fOffset.X());
301 Double_t y(fOffset.Y());
303 while ( ( pad == fCurrentPad || !pad.IsValid() ) && n<100 )
306 if (GetNextPosition(x,y)==kFALSE)
311 SetPad(pad,fArea.Position()+TVector2(x,y));
316 //_____________________________________________________________________________
318 AliMpSlatZonePadIterator::SetPad(AliMpPad& pad, const TVector2& pos)
321 // Sets the current pad.
323 pad = fSlatSegmentation->PadByPosition(pos-fkSlat->Position(),kFALSE);
326 // Reposition fOffset to pad center (only in x-direction).
327 fOffset.Set(pad.Position().X()+fkSlat->DX()-fArea.Position().X(),
332 AliDebug(3,Form("No pad at pos=%e,%e",pos.X(),pos.Y()));