]>
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 | ||
26 | #include <algorithm> | |
27 | #include <limits> | |
28 | #include <cassert> | |
29 | ||
30 | ClassImp(AliMpSlatZonePadIterator) | |
31 | ||
32 | // This iterator only works within a region of constant density. | |
33 | ||
34 | namespace | |
35 | { | |
36 | const Double_t epsilon = 1E-9; // mm | |
37 | Double_t DMAX(std::numeric_limits<Double_t>::max()); | |
38 | } | |
39 | ||
40 | //_____________________________________________________________________________ | |
41 | AliMpSlatZonePadIterator::AliMpSlatZonePadIterator(const AliMpSlat* slat, | |
42 | const AliMpArea& area) | |
43 | : AliMpVPadIterator(), | |
44 | fkSlat(slat), | |
45 | fSlatSegmentation(new AliMpSlatSegmentation(slat)), | |
46 | fArea(area), | |
47 | fOffset(0.0,0.0), | |
48 | fStep(0.0,0.0), | |
49 | fIsDone(kTRUE) | |
50 | { | |
51 | // | |
52 | // Normal ctor. | |
53 | // Iteration will be done on the slat, over the crop of (area,slat_area) | |
54 | // | |
55 | if (!CropArea()) | |
56 | { | |
57 | AliFatal(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s", | |
58 | area.LeftBorder(),area.DownBorder(), | |
59 | area.RightBorder(),area.UpBorder(),fkSlat->GetID())); | |
60 | } | |
61 | Invalidate(); | |
62 | } | |
63 | ||
64 | //_____________________________________________________________________________ | |
65 | AliMpSlatZonePadIterator::~AliMpSlatZonePadIterator() | |
66 | { | |
67 | // | |
68 | // Dtor. | |
69 | // | |
70 | delete fSlatSegmentation; | |
71 | } | |
72 | ||
73 | //_____________________________________________________________________________ | |
74 | Bool_t | |
75 | AliMpSlatZonePadIterator::CropArea() | |
76 | { | |
77 | // | |
78 | // Checks the area is correct, and truncate it | |
79 | // if it goes outside the slat. | |
80 | ||
81 | AliDebug(3,Form("Input area (%7.2f,%7.2f)->(%7.2f,%7.2f)", | |
82 | fArea.LeftBorder(),fArea.DownBorder(), | |
83 | fArea.RightBorder(),fArea.UpBorder())); | |
84 | ||
85 | // Left and right x-limits have to come from first and last pcbs | |
86 | // to deal with short and rounded pcbs cases. | |
87 | AliMpPCB* first = fkSlat->FindPCB(fArea.LeftBorder(),fArea.DownBorder()); | |
88 | AliMpPCB* last = fkSlat->FindPCB(fArea.RightBorder()-epsilon, | |
89 | fArea.DownBorder()); | |
90 | ||
91 | AliDebug(3,Form("First PCB %s Ixmin %2d Last PCB %s Ixmax %2d", | |
92 | first->GetID(),first->Ixmin(), | |
93 | last->GetID(),last->Ixmax())); | |
94 | ||
95 | Double_t xleft = first->ActiveXmin(); | |
96 | Double_t xright = last->ActiveXmax() - epsilon; | |
97 | ||
98 | AliDebug(3,Form("xleft,xright=%7.2f,%7.2f",xleft,xright)); | |
99 | ||
100 | Double_t xmin = std::max(fArea.LeftBorder(),xleft); | |
101 | Double_t xmax = std::min(fArea.RightBorder(),xright); | |
102 | Double_t ymin = std::max(fArea.DownBorder(),0.0); | |
103 | Double_t ymax = std::min(fArea.UpBorder(),fkSlat->DY()*2.0-epsilon); | |
104 | ||
105 | AliDebug(3,Form("Cropped area (%7.2f,%7.2f)->(%7.2f,%7.2f)", | |
106 | xmin,ymin,xmax,ymax)); | |
107 | ||
108 | // At this point (xmin,ymin)->(xmax,ymax) should be a zone completely included | |
109 | // inside the slat. | |
110 | // But there's so far no guarantee that it is "filling" an integer number | |
111 | // of pads. The following lines solve this, by expanding the area up to | |
112 | // the bottomLeft and topRight limits of the pads sitting at (xmin,ymin) | |
113 | // and (xmax,ymax). | |
114 | ||
115 | AliMpPad bottomLeft | |
116 | = fSlatSegmentation->PadByPosition(TVector2(xmin,ymin),kFALSE); | |
117 | if ( bottomLeft.IsValid() ) | |
118 | { | |
119 | xmin = std::min(xmin,fkSlat->DX() + | |
120 | bottomLeft.Position().X() - bottomLeft.Dimensions().X()); | |
121 | ymin = std::min(ymin,fkSlat->DY() + | |
122 | bottomLeft.Position().Y() - bottomLeft.Dimensions().Y()); | |
123 | } | |
124 | ||
125 | AliMpPad topRight | |
126 | = fSlatSegmentation->PadByPosition(TVector2(xmax,ymax),kFALSE); | |
127 | if ( topRight.IsValid() ) | |
128 | { | |
129 | xmax = std::max(xmax,fkSlat->DX() + | |
130 | topRight.Position().X() + topRight.Dimensions().X()); | |
131 | ymax = std::max(ymax,fkSlat->DY() + | |
132 | topRight.Position().Y() + topRight.Dimensions().Y()); | |
133 | } | |
134 | ||
135 | fArea = AliMpArea(TVector2((xmin+xmax)/2.0,(ymin+ymax)/2.0), | |
136 | TVector2((xmax-xmin)/2.0,(ymax-ymin)/2.0)); | |
137 | ||
138 | AliDebug(3,Form("Paddified cropped area (%7.2f,%7.2f)->(%7.2f,%7.2f)", | |
139 | fArea.LeftBorder(),fArea.DownBorder(), | |
140 | fArea.RightBorder(),fArea.UpBorder())); | |
141 | ||
142 | // Finally set the step sizes equal to the smallest pad sizes (which is | |
143 | // hereby assumed to be that of the first pcb). | |
144 | fStep.Set(first->PadSizeX(),first->PadSizeY()); | |
145 | ||
146 | AliDebug(3,Form("Step Sizes (%7.2f,%7.2f)",fStep.X(),fStep.Y())); | |
147 | ||
148 | return fArea.IsValid(); | |
149 | } | |
150 | ||
151 | //_____________________________________________________________________________ | |
152 | AliMpPad | |
153 | AliMpSlatZonePadIterator::CurrentItem() const | |
154 | { | |
155 | // | |
156 | // Returns the current iteration position (i.e. a pad) | |
157 | // | |
158 | return fCurrentPad; | |
159 | } | |
160 | ||
161 | //_____________________________________________________________________________ | |
162 | Bool_t | |
163 | AliMpSlatZonePadIterator::GetNextPosition(Double_t& x, Double_t& y) | |
164 | { | |
165 | // Get the next iteration position. | |
166 | // On input, fOffset must be a valid position (i.e. within iteration | |
167 | // area already). | |
168 | ||
169 | AliDebug(3,Form("input (x,y)=(%7.2f,%7.2f)",x,y)); | |
170 | ||
171 | x += fStep.X(); | |
172 | ||
173 | if ( x > fArea.Dimensions().X() ) | |
174 | { | |
175 | AliDebug(3,"Going back left"); | |
176 | // Go back leftmost position... | |
177 | x = -1.0*fArea.Dimensions().X(); | |
178 | // ... and up | |
179 | y += fStep.Y(); | |
180 | // Update y offset | |
181 | fOffset.Set(fOffset.X(),y); | |
182 | if ( y > fArea.Dimensions().Y() ) | |
183 | { | |
184 | return false; | |
185 | } | |
186 | } | |
187 | AliDebug(3,Form("output (x,y)=(%7.2f,%7.2f",x,y)); | |
188 | return true; | |
189 | } | |
190 | ||
191 | //_____________________________________________________________________________ | |
192 | void | |
193 | AliMpSlatZonePadIterator::First() | |
194 | { | |
195 | // | |
196 | // (re)Starts the iteration. | |
197 | // | |
198 | ||
199 | fOffset = fArea.Dimensions()*(-1.0); | |
200 | fIsDone = kFALSE; | |
201 | SetPad(fCurrentPad,fArea.Position()+fOffset); | |
202 | if (!fCurrentPad.IsValid()) Next(); | |
203 | AliDebug(3,Form("fOffset after Next=%7.2f,%7.2f",fOffset.X(),fOffset.Y())); | |
204 | if ( !fCurrentPad.IsValid() ) | |
205 | { | |
206 | // did not find any valid pad in there, bailing out. | |
207 | fIsDone = kTRUE; | |
208 | AliError("Could not initiate iterator. Please check the area you gave."); | |
209 | return; | |
210 | } | |
211 | else | |
212 | { | |
213 | // Reposition to pad center (both in x and y). | |
214 | // Please note that repositionning y is valid here, and only here | |
215 | // (i.e. do *not* do this in Next() for instance). | |
216 | fOffset.Set(fCurrentPad.Position().X()+fkSlat->DX()-fArea.Position().X(), | |
217 | fCurrentPad.Position().Y()+fkSlat->DY()-fArea.Position().Y()); | |
218 | fIsDone = kFALSE; | |
219 | } | |
220 | AliDebug(3,Form("fOffset repositionned=%7.2f,%7.2f",fOffset.X(),fOffset.Y())); | |
221 | } | |
222 | ||
223 | //_____________________________________________________________________________ | |
224 | void | |
225 | AliMpSlatZonePadIterator::Invalidate() | |
226 | { | |
227 | // | |
228 | // Invalidate the iterator. | |
229 | // | |
230 | ||
231 | fOffset = TVector2(DMAX,DMAX); | |
232 | fCurrentPad = AliMpPad::Invalid(); | |
233 | fIsDone = kTRUE; | |
234 | } | |
235 | ||
236 | //_____________________________________________________________________________ | |
237 | Bool_t | |
238 | AliMpSlatZonePadIterator::IsDone() const | |
239 | { | |
240 | // | |
241 | // Whether the iteration is finished or not. | |
242 | // | |
243 | return fIsDone; | |
244 | } | |
245 | ||
246 | //_____________________________________________________________________________ | |
247 | void | |
248 | AliMpSlatZonePadIterator::Next() | |
249 | { | |
250 | // This one is the meat of the class. | |
251 | // We're iterating in x-direction mainly, starting from | |
252 | // lower-left of the iteration area, and proceeding right, | |
253 | // until we reach right border, in which case we increment y | |
254 | // and go back to leftmost position. | |
255 | // Put otherwise, here's basically how it should work: | |
256 | // try to do x+=xstep. If outside the area, get back to xmin | |
257 | // and try y+=ystep. If outside of the window end-of-game. | |
258 | // When new x,y known, get the corresponding pad. | |
259 | // If same pad as before (should not happen if step sizes are | |
260 | // well chosen) or not valid pad (might happen for e.g. rounded pcbs), | |
261 | // restart. | |
262 | // End of iteration occurs when both x and y are outside the iteration | |
263 | // window. | |
264 | ||
265 | if (IsDone()) return; | |
266 | ||
267 | AliMpPad pad(fCurrentPad); | |
268 | int n = 0; | |
269 | Double_t x(fOffset.X()); | |
270 | Double_t y(fOffset.Y()); | |
271 | ||
272 | while ( ( pad == fCurrentPad || !pad.IsValid() ) && n<100 ) | |
273 | { | |
274 | ++n; | |
275 | if (GetNextPosition(x,y)==kFALSE) | |
276 | { | |
277 | Invalidate(); | |
278 | return; | |
279 | } | |
280 | SetPad(pad,fArea.Position()+TVector2(x,y)); | |
281 | } | |
282 | fCurrentPad = pad; | |
283 | } | |
284 | ||
285 | //_____________________________________________________________________________ | |
286 | void | |
287 | AliMpSlatZonePadIterator::SetPad(AliMpPad& pad, const TVector2& pos) | |
288 | { | |
289 | // | |
290 | // Sets the current pad. | |
291 | // | |
292 | pad = fSlatSegmentation->PadByPosition(pos,kFALSE); | |
293 | if ( pad.IsValid() ) | |
294 | { | |
295 | // Reposition fOffset to pad center (only in x-direction). | |
296 | fOffset.Set(pad.Position().X()+fkSlat->DX()-fArea.Position().X(), | |
297 | fOffset.Y()); | |
298 | } | |
299 | } |