]>
Commit | Line | Data |
---|---|---|
618ea77a | 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$ | |
18 | ||
19 | #include "AliMpPCBPadIterator.h" | |
20 | ||
21 | #include "AliMpArea.h" | |
22 | #include "AliMpConstants.h" | |
23 | #include "AliLog.h" | |
24 | #include "AliMpPCB.h" | |
25 | #include "AliMpSlat.h" | |
26 | #include "AliMpSlatSegmentation.h" | |
27 | ||
28 | #include "Riostream.h" | |
29 | #include "TMath.h" | |
30 | ||
31 | /// | |
32 | /// \class AliMpPCBPadIterator | |
33 | /// | |
34 | /// Iterates over slat pads within a region of constant pad size. | |
35 | /// | |
36 | /// \author Laurent Aphecetche | |
37 | ||
38 | /// \cond CLASSIMP | |
39 | ClassImp(AliMpPCBPadIterator) | |
40 | /// \endcond | |
41 | ||
42 | //_____________________________________________________________________________ | |
43 | AliMpPCBPadIterator::AliMpPCBPadIterator(const AliMpSlat* slat, | |
44 | const AliMpArea& area) | |
45 | : AliMpVPadIterator(), | |
46 | fkSlat(slat), | |
47 | fSlatSegmentation(new AliMpSlatSegmentation(slat)), | |
48 | fMinIndices(), | |
49 | fMaxIndices(), | |
50 | fOffset(0,0), | |
51 | fCurrentPad(), | |
52 | fIsDone(kTRUE) | |
53 | { | |
54 | // | |
55 | // Normal ctor. | |
56 | // Iteration will be done on the slat, over the crop of (area,slat_area) | |
57 | // | |
58 | if (!CropArea(area)) | |
59 | { | |
60 | AliError(Form("Could not crop area : (x,y)min=(%e,%e) ; max=(%e,%e) for slat %s", | |
61 | area.LeftBorder(),area.DownBorder(), | |
62 | area.RightBorder(),area.UpBorder(),fkSlat->GetID())); | |
63 | } | |
64 | Invalidate(); | |
65 | } | |
66 | ||
67 | //_____________________________________________________________________________ | |
68 | AliMpPCBPadIterator::~AliMpPCBPadIterator() | |
69 | { | |
70 | // | |
71 | // Dtor. | |
72 | // | |
73 | delete fSlatSegmentation; | |
74 | } | |
75 | ||
76 | //_____________________________________________________________________________ | |
77 | Bool_t | |
78 | AliMpPCBPadIterator::CropArea(const AliMpArea& area) | |
79 | { | |
80 | // | |
81 | // Checks the area is correct, and truncate it | |
82 | // if it goes outside the slat. | |
83 | ||
84 | AliDebug(3,Form("Input area (%7.2f,%7.2f)->(%7.2f,%7.2f)", | |
85 | area.LeftBorder(),area.DownBorder(), | |
86 | area.RightBorder(),area.UpBorder())); | |
87 | ||
88 | const Double_t kEpsilon = AliMpConstants::LengthTolerance(); | |
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(area.LeftBorder(),area.DownBorder()); | |
93 | AliMpPCB* last = fkSlat->FindPCB(area.RightBorder()-kEpsilon, | |
94 | area.DownBorder()); | |
95 | ||
96 | // Check we're indeed dealing with only one pcb | |
97 | if ( first != last ) | |
98 | { | |
99 | AliError("This iterator supposed to work on a single PCB. Please check"); | |
100 | return kFALSE; | |
101 | } | |
102 | ||
103 | AliDebug(3,Form("PCB %s Ixmin %2d Ixmax %2d", | |
104 | first->GetID(),first->Ixmin(),first->Ixmax())); | |
105 | ||
106 | Double_t xleft = first->ActiveXmin(); | |
107 | Double_t xright = first->ActiveXmax() - kEpsilon; | |
108 | ||
109 | AliDebug(3,Form("xleft,xright=%e,%e",xleft,xright)); | |
110 | ||
111 | Double_t xmin = std::max(area.LeftBorder(),xleft); | |
112 | Double_t xmax = std::min(area.RightBorder(),xright); | |
113 | Double_t ymin = std::max(area.DownBorder(),0.0); | |
114 | Double_t ymax = std::min(area.UpBorder(),first->DY()*2.0-kEpsilon); | |
115 | ||
116 | AliDebug(3,Form("Cropped area (%e,%e)->(%e,%e)", | |
117 | xmin,ymin,xmax,ymax)); | |
118 | ||
119 | // At this point (xmin,ymin)->(xmax,ymax) should be a zone completely included | |
120 | // inside the slat. | |
121 | // We now try to convert this into a couple of indices pair indicating the | |
122 | // region to iterate over, using integer values, not floating point ones. | |
123 | // For this, we must find out the 4 pads that intersect the (xmin,ymin;xmax,ymax) | |
124 | // area. | |
125 | ||
126 | Int_t ixmin = first->Ixmin() + TMath::FloorNint((xmin-first->ActiveXmin())/first->PadSizeX()); | |
127 | Int_t ixmax = first->Ixmin() + TMath::CeilNint((xmax-first->ActiveXmin())/first->PadSizeX()) - 1; | |
128 | Int_t iymin = first->Iymin() + TMath::FloorNint((ymin-first->Ymin())/first->PadSizeY()); | |
129 | Int_t iymax = first->Iymin() + TMath::CeilNint((ymax-first->Ymin())/first->PadSizeY()) - 1; | |
130 | ||
131 | ||
132 | fMinIndices.Set(ixmin,iymin); | |
133 | fMaxIndices.Set(ixmax,iymax); | |
134 | ||
135 | AliDebug(3,Form("Paddified cropped area (%d,%d)->(%d,%d) %d,%d ; %d,%d", | |
136 | ixmin,iymin,ixmax,iymax, | |
137 | fMinIndices.GetFirst(),fMinIndices.GetSecond(), | |
138 | fMaxIndices.GetFirst(),fMaxIndices.GetSecond())); | |
139 | ||
140 | return fMinIndices.IsValid() && fMaxIndices.IsValid(); | |
141 | } | |
142 | ||
143 | //_____________________________________________________________________________ | |
144 | AliMpPad | |
145 | AliMpPCBPadIterator::CurrentItem() const | |
146 | { | |
147 | // | |
148 | // Returns the current iteration position (i.e. a pad) | |
149 | // | |
150 | return fCurrentPad; | |
151 | } | |
152 | ||
153 | //_____________________________________________________________________________ | |
154 | void | |
155 | AliMpPCBPadIterator::First() | |
156 | { | |
157 | // | |
158 | // (re)Starts the iteration. | |
159 | // | |
160 | ||
161 | AliDebug(3,Form("area = (%d,%d)->(%d,%d)", | |
162 | fMinIndices.GetFirst(),fMinIndices.GetSecond(), | |
163 | fMaxIndices.GetFirst(),fMaxIndices.GetSecond())); | |
164 | fOffset = fMinIndices; | |
165 | fIsDone = kFALSE; | |
166 | SetPad(fCurrentPad,fOffset); | |
167 | if (!fCurrentPad.IsValid()) Next(); | |
168 | if ( !fCurrentPad.IsValid() ) | |
169 | { | |
170 | // did not find any valid pad in there, bailing out. | |
171 | fIsDone = kTRUE; | |
172 | AliError(Form("Could not initiate iterator for slat %s. " | |
173 | " Please check the area you gave : %d,%d to %d,%d", | |
174 | fkSlat->GetName(), | |
175 | fMinIndices.GetFirst(), | |
176 | fMinIndices.GetSecond(), | |
177 | fMaxIndices.GetFirst(), | |
178 | fMaxIndices.GetSecond())); | |
179 | return; | |
180 | } | |
181 | } | |
182 | ||
183 | //_____________________________________________________________________________ | |
184 | Bool_t | |
185 | AliMpPCBPadIterator::GetNextPosition(Int_t& ix, Int_t& iy) | |
186 | { | |
187 | // Get the next iteration position. | |
188 | // On input, fOffset must be a valid position (i.e. within iteration | |
189 | // area already). | |
190 | ||
191 | ++ix; | |
192 | ||
193 | if ( ix > fMaxIndices.GetFirst() ) | |
194 | { | |
195 | AliDebug(3,"Going back left and one step upper"); | |
196 | // Go back leftmost position... | |
197 | ix = fMinIndices.GetFirst(); | |
198 | // ... and up | |
199 | ++iy; | |
200 | if ( iy > fMaxIndices.GetSecond() ) | |
201 | { | |
202 | return false; | |
203 | } | |
204 | } | |
205 | return true; | |
206 | } | |
207 | ||
208 | ||
209 | //_____________________________________________________________________________ | |
210 | void | |
211 | AliMpPCBPadIterator::Invalidate() | |
212 | { | |
213 | // | |
214 | // Invalidate the iterator. | |
215 | // | |
216 | fOffset = AliMpIntPair::Invalid(); | |
217 | fCurrentPad = AliMpPad::Invalid(); | |
218 | fIsDone = kTRUE; | |
219 | } | |
220 | ||
221 | //_____________________________________________________________________________ | |
222 | Bool_t | |
223 | AliMpPCBPadIterator::IsDone() const | |
224 | { | |
225 | // | |
226 | // Whether the iteration is finished or not. | |
227 | // | |
228 | return fIsDone; | |
229 | } | |
230 | ||
231 | //_____________________________________________________________________________ | |
232 | void | |
233 | AliMpPCBPadIterator::Next() | |
234 | { | |
235 | // This one is the meat of the class. | |
236 | // We're iterating in x-direction mainly, starting from | |
237 | // lower-left of the iteration area, and proceeding right, | |
238 | // until we reach right border, in which case we increment y | |
239 | // and go back to leftmost position. | |
240 | // End of iteration occurs when both x and y are outside the iteration | |
241 | // window. | |
242 | ||
243 | if (IsDone()) return; | |
244 | ||
245 | AliMpPad pad(fCurrentPad); | |
246 | int n = 0; | |
247 | Int_t ix(fOffset.GetFirst()); | |
248 | Int_t iy(fOffset.GetSecond()); | |
249 | ||
250 | while ( ( pad == fCurrentPad || !pad.IsValid() ) && n<100 ) | |
251 | { | |
252 | ++n; | |
253 | if (GetNextPosition(ix,iy)==kFALSE) | |
254 | { | |
255 | Invalidate(); | |
256 | return; | |
257 | } | |
258 | SetPad(pad,AliMpIntPair(ix,iy)); | |
259 | } | |
260 | if ( n>=100 ) | |
261 | { | |
262 | AliFatal("This should not happen!"); | |
263 | } | |
264 | fCurrentPad = pad; | |
265 | } | |
266 | ||
267 | //_____________________________________________________________________________ | |
268 | void | |
269 | AliMpPCBPadIterator::Print(Option_t*) const | |
270 | { | |
271 | /// printout | |
272 | cout << Form("fkSlat=%p fSlatSegmentation=%p (%s)",fkSlat,fSlatSegmentation, | |
273 | fkSlat->GetName()) << endl | |
274 | << Form("minIndices=(%d,%d) maxIndices=(%d,%d)", | |
275 | fMinIndices.GetFirst(),fMinIndices.GetSecond(), | |
276 | fMaxIndices.GetFirst(),fMaxIndices.GetSecond()) << endl | |
277 | << Form("currentOffset=(%d,%d) isdone=%d currentpad=", | |
278 | fOffset.GetFirst(),fOffset.GetSecond(),IsDone()) << endl; | |
279 | fCurrentPad.Print(); | |
280 | } | |
281 | ||
282 | //_____________________________________________________________________________ | |
283 | void | |
284 | AliMpPCBPadIterator::SetPad(AliMpPad& pad, const AliMpIntPair& indices) | |
285 | { | |
286 | // | |
287 | // Sets the current pad. | |
288 | // | |
289 | pad = fSlatSegmentation->PadByIndices(indices,kFALSE); | |
290 | if (pad.IsValid()) | |
291 | { | |
292 | fOffset = indices; | |
293 | } | |
294 | } |