]>
Commit | Line | Data |
---|---|---|
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 | |
30 | ClassImp(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 | 39 | const Double_t AliMpSlatZonePadIterator::fgkEpsilon = 1E-4; // cm |
40 | const Double_t AliMpSlatZonePadIterator::fgkDmax = std::numeric_limits<Double_t>::max(); | |
dee1d5f1 | 41 | |
42 | //_____________________________________________________________________________ | |
43 | AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat, | |
44 | const AliMpArea& area) | |
45 | : AliMpVPadIterator(), | |
46 | fkSlat(slat), | |
47 | fSlatSegmentation(new AliMpSlatSegmentation(slat)), | |
48 | fArea(area), | |
49 | fOffset(0.0,0.0), | |
50 | fStep(0.0,0.0), | |
51 | fIsDone(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 | //______________________________________________________________________________ |
67 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ |
76 | AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator() | |
77 | { | |
78 | // | |
79 | // Dtor. | |
80 | // | |
81 | delete fSlatSegmentation; | |
82 | } | |
83 | ||
884a73f1 | 84 | //______________________________________________________________________________ |
85 | AliMpSlatZonePadIterator& | |
86 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ |
99 | Bool_t | |
100 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
197 | AliMpPad | |
198 | AliMpSlatZonePadIterator::CurrentItem() const | |
199 | { | |
200 | // | |
201 | // Returns the current iteration position (i.e. a pad) | |
202 | // | |
203 | return fCurrentPad; | |
204 | } | |
205 | ||
206 | //_____________________________________________________________________________ | |
207 | Bool_t | |
208 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
237 | void | |
238 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
275 | void | |
276 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
288 | Bool_t | |
289 | AliMpSlatZonePadIterator::IsDone() const | |
290 | { | |
291 | // | |
292 | // Whether the iteration is finished or not. | |
293 | // | |
294 | return fIsDone; | |
295 | } | |
296 | ||
297 | //_____________________________________________________________________________ | |
298 | void | |
299 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
337 | void | |
338 | AliMpSlatZonePadIterator::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 | } |