]>
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$ | |
13985652 | 17 | // $MpId: AliMpSlatZonePadIterator.cxx,v 1.9 2006/05/24 13:58:50 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 | |
85fec35d | 30 | /// |
31 | /// \class AliMpSlatZonePadIterator | |
32 | /// | |
33 | /// Iterates over slat pads within a region of constant pad size. | |
34 | /// | |
35 | /// \author Laurent Aphecetche | |
dee1d5f1 | 36 | |
13985652 | 37 | /// \cond CLASSIMP |
38 | ClassImp(AliMpSlatZonePadIterator) | |
39 | /// \endcond | |
40 | ||
85fec35d | 41 | const Double_t AliMpSlatZonePadIterator::fgkEpsilon = 1E-4; // cm |
42 | const Double_t AliMpSlatZonePadIterator::fgkDmax = std::numeric_limits<Double_t>::max(); | |
dee1d5f1 | 43 | |
44 | //_____________________________________________________________________________ | |
45 | AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat, | |
46 | const AliMpArea& area) | |
47 | : AliMpVPadIterator(), | |
48 | fkSlat(slat), | |
49 | fSlatSegmentation(new AliMpSlatSegmentation(slat)), | |
50 | fArea(area), | |
51 | fOffset(0.0,0.0), | |
52 | fStep(0.0,0.0), | |
ab31db03 | 53 | fCurrentPad(), |
dee1d5f1 | 54 | fIsDone(kTRUE) |
55 | { | |
56 | // | |
57 | // Normal ctor. | |
58 | // Iteration will be done on the slat, over the crop of (area,slat_area) | |
59 | // | |
60 | if (!CropArea()) | |
61 | { | |
b4c2e272 | 62 | AliError(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s", |
dee1d5f1 | 63 | area.LeftBorder(),area.DownBorder(), |
64 | area.RightBorder(),area.UpBorder(),fkSlat->GetID())); | |
65 | } | |
66 | Invalidate(); | |
67 | } | |
68 | ||
69 | //_____________________________________________________________________________ | |
70 | AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator() | |
71 | { | |
72 | // | |
73 | // Dtor. | |
74 | // | |
75 | delete fSlatSegmentation; | |
76 | } | |
77 | ||
78 | //_____________________________________________________________________________ | |
79 | Bool_t | |
80 | AliMpSlatZonePadIterator::CropArea() | |
81 | { | |
82 | // | |
83 | // Checks the area is correct, and truncate it | |
84 | // if it goes outside the slat. | |
85 | ||
86 | AliDebug(3,Form("Input area (%7.2f,%7.2f)->(%7.2f,%7.2f)", | |
87 | fArea.LeftBorder(),fArea.DownBorder(), | |
88 | fArea.RightBorder(),fArea.UpBorder())); | |
89 | ||
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()); | |
85fec35d | 93 | AliMpPCB* last = fkSlat->FindPCB(fArea.RightBorder()-fgkEpsilon, |
dee1d5f1 | 94 | fArea.DownBorder()); |
95 | ||
96 | AliDebug(3,Form("First PCB %s Ixmin %2d Last PCB %s Ixmax %2d", | |
97 | first->GetID(),first->Ixmin(), | |
98 | last->GetID(),last->Ixmax())); | |
99 | ||
100 | Double_t xleft = first->ActiveXmin(); | |
85fec35d | 101 | Double_t xright = last->ActiveXmax() - fgkEpsilon; |
dee1d5f1 | 102 | |
9447b076 | 103 | AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright)); |
dee1d5f1 | 104 | |
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); | |
85fec35d | 108 | Double_t ymax = std::min(fArea.UpBorder(),fkSlat->DY()*2.0-fgkEpsilon); |
dee1d5f1 | 109 | |
9447b076 | 110 | AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)", |
dee1d5f1 | 111 | xmin,ymin,xmax,ymax)); |
112 | ||
113 | // At this point (xmin,ymin)->(xmax,ymax) should be a zone completely included | |
114 | // inside the slat. | |
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) | |
118 | // and (xmax,ymax). | |
119 | ||
120 | AliMpPad bottomLeft | |
1964cd2e | 121 | = fSlatSegmentation->PadByPosition(TVector2(xmin,ymin)-fkSlat->Position(), |
122 | kFALSE); | |
9447b076 | 123 | |
124 | StdoutToAliDebug(3, | |
125 | cout << "bottomLeft=" << endl; | |
126 | bottomLeft.Print(); | |
127 | cout << bottomLeft.Position().X()+fkSlat->Position().X() | |
128 | << "," << bottomLeft.Position().Y()+fkSlat->Position().Y() | |
129 | << endl; | |
130 | ); | |
131 | ||
dee1d5f1 | 132 | if ( bottomLeft.IsValid() ) |
133 | { | |
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()); | |
138 | } | |
139 | ||
140 | AliMpPad topRight | |
1964cd2e | 141 | = fSlatSegmentation->PadByPosition(TVector2(xmax,ymax)-fkSlat->Position(), |
142 | kFALSE); | |
9447b076 | 143 | StdoutToAliDebug(3, |
144 | cout << "topRight=" << endl; | |
145 | topRight.Print(); | |
146 | cout << topRight.Position().X()+fkSlat->Position().X() | |
147 | << "," << topRight.Position().Y()+fkSlat->Position().Y() | |
148 | << endl; | |
149 | ||
150 | ); | |
151 | ||
dee1d5f1 | 152 | if ( topRight.IsValid() ) |
153 | { | |
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()); | |
158 | } | |
159 | ||
160 | fArea = AliMpArea(TVector2((xmin+xmax)/2.0,(ymin+ymax)/2.0), | |
161 | TVector2((xmax-xmin)/2.0,(ymax-ymin)/2.0)); | |
162 | ||
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())); | |
166 | ||
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()); | |
170 | ||
171 | AliDebug(3,Form("Step Sizes (%7.2f,%7.2f)",fStep.X(),fStep.Y())); | |
172 | ||
173 | return fArea.IsValid(); | |
174 | } | |
175 | ||
176 | //_____________________________________________________________________________ | |
177 | AliMpPad | |
178 | AliMpSlatZonePadIterator::CurrentItem() const | |
179 | { | |
180 | // | |
181 | // Returns the current iteration position (i.e. a pad) | |
182 | // | |
183 | return fCurrentPad; | |
184 | } | |
185 | ||
186 | //_____________________________________________________________________________ | |
187 | Bool_t | |
188 | AliMpSlatZonePadIterator::GetNextPosition(Double_t& x, Double_t& y) | |
189 | { | |
190 | // Get the next iteration position. | |
191 | // On input, fOffset must be a valid position (i.e. within iteration | |
192 | // area already). | |
193 | ||
194 | AliDebug(3,Form("input (x,y)=(%7.2f,%7.2f)",x,y)); | |
195 | ||
196 | x += fStep.X(); | |
197 | ||
198 | if ( x > fArea.Dimensions().X() ) | |
199 | { | |
1964cd2e | 200 | AliDebug(3,"Going back left and one step upper"); |
dee1d5f1 | 201 | // Go back leftmost position... |
202 | x = -1.0*fArea.Dimensions().X(); | |
203 | // ... and up | |
204 | y += fStep.Y(); | |
205 | // Update y offset | |
206 | fOffset.Set(fOffset.X(),y); | |
207 | if ( y > fArea.Dimensions().Y() ) | |
1964cd2e | 208 | { |
209 | return false; | |
210 | } | |
dee1d5f1 | 211 | } |
212 | AliDebug(3,Form("output (x,y)=(%7.2f,%7.2f",x,y)); | |
213 | return true; | |
214 | } | |
215 | ||
216 | //_____________________________________________________________________________ | |
217 | void | |
218 | AliMpSlatZonePadIterator::First() | |
219 | { | |
220 | // | |
221 | // (re)Starts the iteration. | |
222 | // | |
223 | ||
224 | fOffset = fArea.Dimensions()*(-1.0); | |
225 | fIsDone = kFALSE; | |
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() ) | |
230 | { | |
231 | // did not find any valid pad in there, bailing out. | |
232 | fIsDone = kTRUE; | |
1964cd2e | 233 | AliError(Form("Could not initiate iterator for slat %s. " |
234 | " Please check the area you gave : %e,%e +- %e,%e", | |
235 | fkSlat->GetName(), | |
236 | fArea.Position().X(), | |
237 | fArea.Position().Y(), | |
238 | fArea.Dimensions().X(), | |
239 | fArea.Dimensions().Y())); | |
dee1d5f1 | 240 | return; |
241 | } | |
242 | else | |
243 | { | |
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()); | |
249 | fIsDone = kFALSE; | |
250 | } | |
251 | AliDebug(3,Form("fOffset repositionned=%7.2f,%7.2f",fOffset.X(),fOffset.Y())); | |
252 | } | |
253 | ||
254 | //_____________________________________________________________________________ | |
255 | void | |
256 | AliMpSlatZonePadIterator::Invalidate() | |
257 | { | |
258 | // | |
259 | // Invalidate the iterator. | |
260 | // | |
261 | ||
85fec35d | 262 | fOffset = TVector2(fgkDmax,fgkDmax); |
dee1d5f1 | 263 | fCurrentPad = AliMpPad::Invalid(); |
264 | fIsDone = kTRUE; | |
265 | } | |
266 | ||
267 | //_____________________________________________________________________________ | |
268 | Bool_t | |
269 | AliMpSlatZonePadIterator::IsDone() const | |
270 | { | |
271 | // | |
272 | // Whether the iteration is finished or not. | |
273 | // | |
274 | return fIsDone; | |
275 | } | |
276 | ||
277 | //_____________________________________________________________________________ | |
278 | void | |
279 | AliMpSlatZonePadIterator::Next() | |
280 | { | |
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), | |
292 | // restart. | |
293 | // End of iteration occurs when both x and y are outside the iteration | |
294 | // window. | |
295 | ||
296 | if (IsDone()) return; | |
297 | ||
298 | AliMpPad pad(fCurrentPad); | |
299 | int n = 0; | |
300 | Double_t x(fOffset.X()); | |
301 | Double_t y(fOffset.Y()); | |
302 | ||
303 | while ( ( pad == fCurrentPad || !pad.IsValid() ) && n<100 ) | |
1964cd2e | 304 | { |
305 | ++n; | |
306 | if (GetNextPosition(x,y)==kFALSE) | |
dee1d5f1 | 307 | { |
1964cd2e | 308 | Invalidate(); |
309 | return; | |
310 | } | |
311 | SetPad(pad,fArea.Position()+TVector2(x,y)); | |
312 | } | |
dee1d5f1 | 313 | fCurrentPad = pad; |
314 | } | |
315 | ||
316 | //_____________________________________________________________________________ | |
317 | void | |
318 | AliMpSlatZonePadIterator::SetPad(AliMpPad& pad, const TVector2& pos) | |
319 | { | |
320 | // | |
321 | // Sets the current pad. | |
322 | // | |
1964cd2e | 323 | pad = fSlatSegmentation->PadByPosition(pos-fkSlat->Position(),kFALSE); |
dee1d5f1 | 324 | if ( pad.IsValid() ) |
325 | { | |
326 | // Reposition fOffset to pad center (only in x-direction). | |
327 | fOffset.Set(pad.Position().X()+fkSlat->DX()-fArea.Position().X(), | |
1964cd2e | 328 | fOffset.Y()); |
dee1d5f1 | 329 | } |
1964cd2e | 330 | else |
331 | { | |
332 | AliDebug(3,Form("No pad at pos=%e,%e",pos.X(),pos.Y())); | |
333 | } | |
dee1d5f1 | 334 | } |