Added copy constructor and assignement operator (I. Hrivnacova)
[u/mrichter/AliRoot.git] / MUON / mapping / AliMpSectorSegmentation.cxx
1 // $Id$
2 // Category: sector
3 //
4 // Class AliMpSectorSegmentation
5 // -----------------------------
6 // Class describing the segmentation of the sector.        
7 // Provides methods related to pads:
8 // conversion between pad indices, pad location, pad position;
9 // finding pad neighbour.
10 //
11 // Authors: David Guez, Ivana Hrivnacova; IPN Orsay
12
13 #include <Riostream.h>
14 #include <TMath.h>
15 #include <TError.h>
16
17 #include "AliMpSectorSegmentation.h"
18 #include "AliMpSector.h"
19 #include "AliMpZone.h"
20 #include "AliMpSubZone.h"
21 #include "AliMpRow.h"
22 #include "AliMpVRowSegment.h"
23 #include "AliMpMotifMap.h"
24 #include "AliMpVMotif.h"
25 #include "AliMpMotifPosition.h"
26 #include "AliMpConnection.h"
27 #include "AliMpNeighboursPadIterator.h"
28 #include "AliMpSectorAreaHPadIterator.h"
29 #include "AliMpSectorAreaVPadIterator.h"
30 #include "AliMpIntPair.h"
31 #include "AliMpArea.h"
32 #include "AliMpConstants.h"
33
34 ClassImp(AliMpSectorSegmentation)
35
36 #ifdef WITH_ROOT
37 const Double_t AliMpSectorSegmentation::fgkSeparator = 10000.;
38 #endif
39
40 //______________________________________________________________________________
41 AliMpSectorSegmentation::AliMpSectorSegmentation(const AliMpSector* sector) 
42   : AliMpVSegmentation(),
43     fkSector(sector)
44 {
45 //
46   fPadBuffer = new AliMpPad(AliMpPad::Invalid());
47   
48   FillPadDimensionsMap();
49 }
50
51 //______________________________________________________________________________
52 AliMpSectorSegmentation::AliMpSectorSegmentation() 
53   : AliMpVSegmentation(),
54     fkSector(0),
55     fPadBuffer(0),
56     fPadDimensionsMap()      
57 {
58 //
59 }
60
61 //_____________________________________________________________________________
62 AliMpSectorSegmentation::AliMpSectorSegmentation(
63                                     const AliMpSectorSegmentation& right) 
64   : AliMpVSegmentation(right) {
65 // 
66   Fatal("AliMpSectorSegmentation", "Copy constructor not provided.");
67 }
68
69 //______________________________________________________________________________
70 AliMpSectorSegmentation::~AliMpSectorSegmentation() {
71 // 
72   delete fPadBuffer;
73 }
74
75 //
76 // operators
77 //
78
79 //_____________________________________________________________________________
80 AliMpSectorSegmentation& 
81 AliMpSectorSegmentation::operator=(const AliMpSectorSegmentation& right)
82 {
83   // check assignement to self
84   if (this == &right) return *this;
85
86   Fatal("operator =", "Assignement operator not provided.");
87     
88   return *this;  
89 }    
90
91 //
92 // private methods
93 //
94
95 #ifdef WITH_ROOT
96 //______________________________________________________________________________
97 Long_t AliMpSectorSegmentation::GetIndex(const TVector2& vector2) const
98 {
99 // Converts the twovector to long.
100 // ---
101
102   if (vector2.X() >= fgkSeparator || vector2.Y() >= fgkSeparator)
103     Fatal("GetIndex", "Index out of limit.");
104       
105   return Long_t(vector2.X()*fgkSeparator + vector2.Y() + 1.);
106 }  
107
108 //______________________________________________________________________________
109 TVector2  AliMpSectorSegmentation::GetVector(Long_t index) const
110 {
111 // Converts the long index to twovector.
112 // ---
113
114   return TVector2(TMath::Floor((index-1.)/fgkSeparator), 
115                   (index-1.) - TMath::Floor((index-1.)/fgkSeparator)*fgkSeparator);
116 }  
117 #endif
118
119 //______________________________________________________________________________
120 void AliMpSectorSegmentation::FillPadDimensionsMap()
121 {
122 // Fills the maps between zone ids and pad dimensions.
123 // ---
124
125   for (Int_t i=0; i<fkSector->GetNofZones(); i++) {
126     AliMpZone* zone   = fkSector->GetZone(i+1);
127     Int_t  zoneID = zone->GetID();
128     
129     if (!AliMpConstants::IsEqual(zone->GetPadDimensions(), TVector2())) {
130
131       // regular zone
132 #ifdef WITH_STL
133       fPadDimensionsMap[zoneID*10] = zone->GetPadDimensions();
134 #endif
135 #ifdef WITH_ROOT
136       fPadDimensionsMap.Add((Long_t)(zoneID*10), 
137                             GetIndex(zone->GetPadDimensions()));
138 #endif
139     }
140     else {
141       // special zone
142       Int_t subIndex = 0;
143       for (Int_t j=0; j<zone->GetNofSubZones(); j++) {
144         AliMpSubZone* subZone = zone->GetSubZone(j);
145         AliMpVMotif*  motif = subZone->GetMotif();
146         
147         for (Int_t k=0; k<motif->GetNofPadDimensions(); k++) {
148           Int_t index = zoneID*10 +  subIndex++;
149 #ifdef WITH_STL
150           fPadDimensionsMap[index] = motif->GetPadDimensions(k);
151 #endif
152 #ifdef WITH_ROOT
153           fPadDimensionsMap.Add((Long_t)(index), 
154                             GetIndex(motif->GetPadDimensions(k)));
155 #endif
156         }
157       }   
158     }     
159   }      
160 }
161
162 //______________________________________________________________________________
163 AliMpMotifPosition* 
164 AliMpSectorSegmentation::FindMotifPosition(const AliMpIntPair& indices) const
165 {
166 // Find the motif position which contains the given pad indices
167 // return 0 if not found
168 // ---
169
170   switch (fkSector->GetDirection()) {
171     case kX : {
172     // Case where all the pads have the same size along X direction
173
174       for (Int_t irow=0; irow<fkSector->GetNofRows(); ++irow) {
175         AliMpRow* row = fkSector->GetRow(irow);
176         if (row->GetLowIndicesLimit().GetFirst()<=indices.GetFirst() &&
177             row->GetHighIndicesLimit().GetFirst()>=indices.GetFirst()) {
178             
179            for (Int_t iseg=0;iseg<row->GetNofRowSegments();++iseg){
180             AliMpVRowSegment* seg = row->GetRowSegment(iseg);
181             if (seg->GetLowIndicesLimit().GetFirst()<=indices.GetFirst() &&
182                 seg->GetHighIndicesLimit().GetFirst()>=indices.GetFirst()) {
183
184               AliMpMotifPosition* motifPos;
185               for (Int_t imot=0;imot<seg->GetNofMotifs();++imot) {
186                 motifPos 
187                   = fkSector->GetMotifMap()
188                     ->FindMotifPosition(seg->GetMotifPositionId(imot));
189                 if (motifPos && motifPos->HasPad(indices)) return motifPos;
190               }
191             }
192           }
193         }
194       }
195       return 0;
196     }
197     break;
198     ////////////////////////////////////////////////////////////////////////////////
199     case kY : {
200       // Case where all the pads have the same size along Y direction   
201       // look for the row which contains the indices
202       AliMpRow* row=0;
203       Int_t irow;
204       for (irow=0; irow<fkSector->GetNofRows(); ++irow) {
205         row = fkSector->GetRow(irow);
206         AliMpVRowSegment* lastSeg = row->GetRowSegment(row->GetNofRowSegments()-1);
207         if (lastSeg->GetLowIndicesLimit().GetSecond()<=indices.GetSecond() &&
208             lastSeg->GetHighIndicesLimit().GetSecond()>=indices.GetSecond()) break;
209         // NOTE : We use the last row segment in order to ensure that
210         // we are not on a special motif
211       }
212       if (irow==fkSector->GetNofRows()) return 0;
213       // look for the row segment, in the found row, which contains the indices
214       AliMpVRowSegment* seg=0;
215       Int_t iseg;
216       for (iseg=0;iseg<row->GetNofRowSegments();++iseg){
217         seg = row->GetRowSegment(iseg);
218         if (seg->HasIndices(indices)) break;
219       }
220       if (iseg==row->GetNofRowSegments()) return 0;
221   
222       // look for the motif position which contains the indices
223       AliMpMotifPosition* motifPos=0;
224       Int_t imot=0;
225       for (imot=0;imot<seg->GetNofMotifs();++imot) {
226         motifPos 
227           = fkSector->GetMotifMap()
228             ->FindMotifPosition(seg->GetMotifPositionId(imot));
229         if (motifPos && motifPos->HasPad(indices)) break;
230       }      
231       if (imot==seg->GetNofMotifs()) return 0;
232    
233       return motifPos;      
234     }
235     default: return 0;
236   }
237 }
238
239 //______________________________________________________________________________
240 AliMpPad 
241 AliMpSectorSegmentation::PadByXDirection(const TVector2& startPosition, 
242                                          Double_t maxX) const
243 {
244 // Find the first valid pad from starting position in the
245 // direction of pad lines up to distance dx.
246 // ---
247
248   // Define step limits
249   Double_t  stepX = fkSector->GetMinPadDimensions().X();
250  
251   // Search in X direction
252   AliMpPad pad;
253   TVector2 position(startPosition);    
254   do {
255     pad = PadByPosition(position, false);
256     position += TVector2(stepX, 0.);
257   }   
258   while ( !pad.IsValid() && position.X() < maxX ); 
259   
260   // Invalidate pad if it is outside limits
261   if ((pad.Position().X() - pad.Dimensions().X()) > maxX) 
262     pad = AliMpPad::Invalid();
263
264   return pad;
265 }
266
267 //______________________________________________________________________________
268 AliMpPad 
269 AliMpSectorSegmentation::PadByYDirection(const TVector2& startPosition, 
270                                          Double_t maxY) const
271 {
272 // Find the first valid pad from starting position in the
273 // direction of pad columns up to distance dx.
274 // ---
275   
276   // Define step limits
277   Double_t stepY = fkSector->GetMinPadDimensions().Y();
278  
279   // Search in Y direction
280   AliMpPad pad;
281   TVector2 position(startPosition);    
282   do {
283     pad = PadByPosition(position, false);
284     position += TVector2(0., stepY);
285   }   
286   while ( !pad.IsValid() && position.Y() < maxY ); 
287   
288   // Invalidate pad if it is outside limits
289   if ((pad.Position().Y() - pad.Dimensions().Y()) > maxY) 
290     pad = AliMpPad::Invalid();
291
292   return pad;
293 }
294
295 //______________________________________________________________________________
296 AliMpVPadIterator* AliMpSectorSegmentation::CreateIterator() const
297 {
298 // The inherited method cannot be used
299
300   Fatal("CreateIterator", "Center pad has to be specified.");
301   return 0;
302 }
303   
304
305 //
306 // public methods
307 //
308
309 //______________________________________________________________________________
310 AliMpVPadIterator* 
311 AliMpSectorSegmentation::CreateIterator(const AliMpArea& area) const
312 {
313 // Creates the are iterator. 
314 // (The inherited method cannot be used)
315 // ---
316
317   switch (fkSector->GetDirection()) {
318   
319     case kX: return new AliMpSectorAreaVPadIterator(this, area);
320              ;;
321     case kY: return new AliMpSectorAreaHPadIterator(this, area);
322              ;;
323   }
324   
325   Fatal("CreateIterator", "Incomplete switch on Sector direction");
326   return 0;  
327 }   
328   
329 //______________________________________________________________________________
330 AliMpVPadIterator* 
331 AliMpSectorSegmentation::CreateIterator(const AliMpPad& centerPad,
332                                         Bool_t includeCenter) const
333 {
334 // Creates the neighbours pad iterator.
335 // (The inherited method cannot be used)
336
337   return new AliMpNeighboursPadIterator(this, centerPad, includeCenter);
338 }   
339   
340 //______________________________________________________________________________
341 AliMpPad 
342 AliMpSectorSegmentation::PadByLocation(const AliMpIntPair& location, 
343                                        Bool_t warning) const
344 {
345 // Find the pad which corresponds to the given location
346   
347   if ((*fPadBuffer).GetLocation()==location) return (*fPadBuffer);
348   
349   AliMpMotifPosition* motifPos = 
350     fkSector->GetMotifMap()->FindMotifPosition(location.GetFirst());
351   if (!motifPos){
352     if (warning) Warning("PadByLocation","The pad motif position ID doesn't exists");
353     return AliMpPad::Invalid();
354   }
355   
356   AliMpVMotif* motif = motifPos->GetMotif();
357   AliMpIntPair localIndices = 
358     motif->GetMotifType()->FindLocalIndicesByGassiNum(location.GetSecond());
359   if (! localIndices.IsValid()) {
360     if (warning) Warning("PadByLocation","The pad number doesn't exists");
361     return AliMpPad::Invalid();
362   }
363   TVector2 delta = motif->PadPositionLocal(localIndices);
364   return (*fPadBuffer) = AliMpPad(location,
365               motifPos->GlobalIndices(localIndices),
366               motifPos->Position()+delta,
367               motif->GetPadDimensions(localIndices));
368
369 }
370 //______________________________________________________________________________
371 AliMpPad 
372 AliMpSectorSegmentation::PadByIndices(const AliMpIntPair& indices,
373                                       Bool_t warning ) const
374 {
375 // Find the pad which corresponds to the given indices  
376
377   if ((*fPadBuffer).GetIndices()==indices) return (*fPadBuffer);    
378    
379   AliMpMotifPosition* motifPos = FindMotifPosition(indices);
380   if (!motifPos) {    
381     if (warning) Warning("PadByIndices","Pad indices not contained in any motif!");
382     return AliMpPad::Invalid();
383   }
384   
385   // retrieve the local indices in the found motif
386   AliMpVMotif* motif = motifPos->GetMotif();
387   AliMpIntPair localIndices = indices - motifPos->GetLowIndicesLimit();
388   
389   AliMpConnection* connection=
390     motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);
391     
392   if (!connection){
393     if (warning) Warning("PadByIndices","No connection with the given indices!");
394     return AliMpPad::Invalid();
395   }
396
397   TVector2 localPos = motif->PadPositionLocal(localIndices);
398
399   return (*fPadBuffer) 
400     = AliMpPad(AliMpIntPair(motifPos->GetID(),connection->GetGassiNum()),
401                indices,
402                motifPos->Position()+localPos,
403                motif->GetPadDimensions(localIndices)); 
404
405 }
406 //______________________________________________________________________________
407 AliMpPad 
408 AliMpSectorSegmentation::PadByPosition(const TVector2& position,
409                                        Bool_t warning) const
410 {
411 // Find the pad which corresponds to the given position
412
413   if ((*fPadBuffer).Position().X()==position.X() && 
414       (*fPadBuffer).Position().Y()==position.Y()) return (*fPadBuffer);  
415
416   Int_t motifPosID = fkSector->FindMotifPositionId(position);
417   AliMpMotifPosition* motifPos 
418     = fkSector->GetMotifMap()
419         ->FindMotifPosition(motifPosID);
420     
421   if (!motifPos){
422     if (warning) Warning("PadByPosition","Position outside limits");
423     return AliMpPad::Invalid();
424   }
425
426   AliMpVMotif* motif =  motifPos->GetMotif();  
427   AliMpIntPair localIndices 
428     = motif->PadIndicesLocal(position-motifPos->Position());
429     
430   AliMpConnection* connect = 
431     motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);
432
433    if (!connect){
434     if (warning) Warning("PadByPosition","Position outside motif limits");
435     return AliMpPad::Invalid();
436   }
437   
438   return (*fPadBuffer)
439     = AliMpPad(AliMpIntPair(motifPosID,connect->GetGassiNum()),
440                motifPos->GlobalIndices(localIndices),
441                motifPos->Position()+motif->PadPositionLocal(localIndices),
442                motif->GetPadDimensions(localIndices));
443
444 }
445
446 //______________________________________________________________________________
447 AliMpPad 
448 AliMpSectorSegmentation::PadByDirection(const TVector2& startPosition, 
449                                         Double_t distance) const
450 {
451 // Find the first valid pad from starting position in the
452 // direction of pad lines/columns up to the specified distance.
453 // Pad lines are the lines of pads in the sector with constant pad y size,
454 // pad columns are the columns of pads in the sector with constant pad x size. 
455 // ---
456
457   switch (fkSector->GetDirection()) {
458   
459     case kX: return PadByYDirection(startPosition, distance);
460              ;;
461     case kY: return PadByXDirection(startPosition, distance);
462              ;;
463   }
464   
465   Fatal("PadByDirection", "Incomplete switch on Sector direction");
466   return AliMpPad::Invalid();  
467 }
468
469 //______________________________________________________________________________
470 Bool_t AliMpSectorSegmentation::HasPad(const AliMpIntPair& indices) const
471 {
472 // Does the pad specified by <indices> exist ?
473 // ---
474
475   return PadByIndices(indices,kFALSE) != AliMpPad::Invalid();
476 }
477
478 //______________________________________________________________________________
479 Bool_t AliMpSectorSegmentation::HasMotifPosition(Int_t motifPositionID) const
480 {
481 // Does the motif position specified by motifPositionID exist ?
482 // ---
483
484   return (fkSector->GetMotifMap()->FindMotifPosition(motifPositionID) != 0);
485 }
486
487 //______________________________________________________________________________
488 TVector2  AliMpSectorSegmentation::GetMinPadDimensions() const
489 {
490 // Returnes the dimensions of the smallest pad.
491 // ---
492
493   return fkSector->GetMinPadDimensions();
494 }  
495
496 //______________________________________________________________________________
497 Int_t AliMpSectorSegmentation::Zone(const AliMpPad& pad, Bool_t warning) const
498 {
499 // Returns the zone index of the zone containing the specified pad.
500 // This zone index is different from the zone ID,
501 // as it is unique for each pad dimensions.
502 // It is composed in this way:
503 //   zoneID*10 + specific index 
504 // Specific index is present only for zones containing special motifs.
505 // ---
506
507   if (!pad.IsValid()) {
508     if (warning) Warning("Zone(AliMpPad)", "Invalid pad");
509     return 0;
510   }  
511
512 #ifdef WITH_STL
513   PadDimensionsMapCIterator it;
514   for (it = fPadDimensionsMap.begin(); it != fPadDimensionsMap.end(); ++it) {
515     if (AliMpConstants::IsEqual(it->second, pad.Dimensions()))
516       return it->first;
517   }
518 #endif
519
520 #ifdef WITH_ROOT
521   PadDimensionsMapCIterator it(&fPadDimensionsMap);
522   Long_t key, value;
523   while ( it.Next(key, value) ) {
524     TVector2 dimensions =  GetVector(value);
525     if (AliMpConstants::IsEqual(dimensions, pad.Dimensions()))
526       return (Int_t)key;
527   }  
528  return 0;
529
530 #endif
531
532   // Should never happen
533   Fatal("Zone(AliMpPad)", "not found");
534   return 0;
535 }  
536
537 //______________________________________________________________________________
538 TVector2 
539 AliMpSectorSegmentation::PadDimensions(Int_t zone, Bool_t warning) const
540 {
541 // Returns the pad dimensions for the zone with the specified zone index.
542 // ---
543
544 #ifdef WITH_STL
545   PadDimensionsMapCIterator it = fPadDimensionsMap.find(zone);
546   if (it != fPadDimensionsMap.end()) return it->second;
547 #endif
548
549 #ifdef WITH_ROOT
550   Long_t value = fPadDimensionsMap.GetValue(zone);
551   if (value) return GetVector(value);
552 #endif
553
554   if (warning) Warning("PadDimensions(zone)", "not found");
555   return TVector2();
556 }  
557
558 //______________________________________________________________________________
559 Bool_t AliMpSectorSegmentation::CircleTest(const AliMpIntPair& indices) const
560 {
561 // Verifies that all methods for retrieving pads are consistents between them.
562 // Returns true if the pad with specified indices was found and verified,
563 // false otherwise.
564 // ---
565
566   if (!HasPad(indices)) return false;
567
568   // Verify the indice->location->position->indice way
569   AliMpIntPair location = PadByIndices(indices).GetLocation();
570   TVector2 position = PadByLocation(location).Position();
571   AliMpIntPair retIndices = PadByPosition(position).GetIndices();
572     
573   if (retIndices != indices) {
574     cout << "Pad " << indices << " lead to inconsistency" << endl;
575     cout << "in indice->location->position->indice way..." << endl;
576     cout << "starting from " << indices << "-->" << location << "-->" 
577          << '(' << position.X() << ',' << position.Y() << ')'
578          << " and retIndices: " << retIndices << endl;
579   }
580     
581     
582   // Verify the indice->position->location->indice way    
583   position = PadByIndices(indices).Position();
584   location = PadByPosition(position).GetLocation();
585   retIndices = PadByLocation(location).GetIndices();
586
587   if (retIndices != indices) {
588     cout << "Pad " << indices << " lead to inconsistency" << endl;
589     cout << "in indice->position->location->indice way..." <<endl;
590     cout << "starting from " << indices 
591          << " and retIndices: " << retIndices << endl;
592   }
593   
594   return true;
595 }