]>
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> | |
29 | #include <cassert> | |
30 | ||
31 | ClassImp(AliMpSlatZonePadIterator) | |
32 | ||
33 | // This iterator only works within a region of constant density. | |
34 | ||
35 | namespace | |
36 | { | |
9447b076 | 37 | const Double_t epsilon = 1E-4; // cm |
dee1d5f1 | 38 | Double_t DMAX(std::numeric_limits<Double_t>::max()); |
39 | } | |
40 | ||
41 | //_____________________________________________________________________________ | |
42 | AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat, | |
43 | const AliMpArea& area) | |
44 | : AliMpVPadIterator(), | |
45 | fkSlat(slat), | |
46 | fSlatSegmentation(new AliMpSlatSegmentation(slat)), | |
47 | fArea(area), | |
48 | fOffset(0.0,0.0), | |
49 | fStep(0.0,0.0), | |
50 | fIsDone(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 | //______________________________________________________________________________ |
66 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ |
75 | AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator() | |
76 | { | |
77 | // | |
78 | // Dtor. | |
79 | // | |
80 | delete fSlatSegmentation; | |
81 | } | |
82 | ||
884a73f1 | 83 | //______________________________________________________________________________ |
84 | AliMpSlatZonePadIterator& | |
85 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ |
98 | Bool_t | |
99 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
196 | AliMpPad | |
197 | AliMpSlatZonePadIterator::CurrentItem() const | |
198 | { | |
199 | // | |
200 | // Returns the current iteration position (i.e. a pad) | |
201 | // | |
202 | return fCurrentPad; | |
203 | } | |
204 | ||
205 | //_____________________________________________________________________________ | |
206 | Bool_t | |
207 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
236 | void | |
237 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
274 | void | |
275 | AliMpSlatZonePadIterator::Invalidate() | |
276 | { | |
277 | // | |
278 | // Invalidate the iterator. | |
279 | // | |
280 | ||
281 | fOffset = TVector2(DMAX,DMAX); | |
282 | fCurrentPad = AliMpPad::Invalid(); | |
283 | fIsDone = kTRUE; | |
284 | } | |
285 | ||
286 | //_____________________________________________________________________________ | |
287 | Bool_t | |
288 | AliMpSlatZonePadIterator::IsDone() const | |
289 | { | |
290 | // | |
291 | // Whether the iteration is finished or not. | |
292 | // | |
293 | return fIsDone; | |
294 | } | |
295 | ||
296 | //_____________________________________________________________________________ | |
297 | void | |
298 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
336 | void | |
337 | AliMpSlatZonePadIterator::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 | } |