]>
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$ | |
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 | ||
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 | { | |
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 | //_____________________________________________________________________________ | |
66 | AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator() | |
67 | { | |
68 | // | |
69 | // Dtor. | |
70 | // | |
71 | delete fSlatSegmentation; | |
72 | } | |
73 | ||
74 | //_____________________________________________________________________________ | |
75 | Bool_t | |
76 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
173 | AliMpPad | |
174 | AliMpSlatZonePadIterator::CurrentItem() const | |
175 | { | |
176 | // | |
177 | // Returns the current iteration position (i.e. a pad) | |
178 | // | |
179 | return fCurrentPad; | |
180 | } | |
181 | ||
182 | //_____________________________________________________________________________ | |
183 | Bool_t | |
184 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
213 | void | |
214 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
251 | void | |
252 | AliMpSlatZonePadIterator::Invalidate() | |
253 | { | |
254 | // | |
255 | // Invalidate the iterator. | |
256 | // | |
257 | ||
258 | fOffset = TVector2(DMAX,DMAX); | |
259 | fCurrentPad = AliMpPad::Invalid(); | |
260 | fIsDone = kTRUE; | |
261 | } | |
262 | ||
263 | //_____________________________________________________________________________ | |
264 | Bool_t | |
265 | AliMpSlatZonePadIterator::IsDone() const | |
266 | { | |
267 | // | |
268 | // Whether the iteration is finished or not. | |
269 | // | |
270 | return fIsDone; | |
271 | } | |
272 | ||
273 | //_____________________________________________________________________________ | |
274 | void | |
275 | AliMpSlatZonePadIterator::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 | //_____________________________________________________________________________ | |
313 | void | |
314 | AliMpSlatZonePadIterator::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 | } |