]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONPainterContourMaker.cxx
Introduction of AliTRDLeastSquare
[u/mrichter/AliRoot.git] / MUON / AliMUONPainterContourMaker.cxx
CommitLineData
0145e89a 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
18#include "AliMUONPainterContourMaker.h"
19
20#include "AliMUONPainterContour.h"
21#include "AliMUONPainterHelper.h"
22#include "AliMUONVCalibParam.h"
23#include "AliMUONVDigit.h"
24#include "AliMpConnection.h"
25#include "AliMpConstants.h"
26#include "AliMpDEManager.h"
27#include "AliMpExMap.h"
28#include "AliMpMotifMap.h"
29#include "AliMpMotifPosition.h"
30#include "AliMpMotifType.h"
31#include "AliMpSector.h"
32#include "AliMpSectorSegmentation.h"
33#include "AliMpSegmentation.h"
34#include "AliMpSlat.h"
35#include "AliMpSlatSegmentation.h"
36#include "AliMpStationType.h"
37#include "AliMpVMotif.h"
38#include "AliCodeTimer.h"
39#include "AliLog.h"
40#include <Riostream.h>
41#include <TArrayI.h>
42#include <TGeoMatrix.h>
43#include <TLine.h>
44#include <TMap.h>
45#include <TMath.h>
46#include <TMathBase.h>
47#include <TObjArray.h>
48#include <TPolyLine.h>
49#include <cassert>
50#include <float.h>
51
cec5da80 52/// \class AliMUONPainterContourMaker
0145e89a 53///
54/// A class to build painter contours.
55///
56/// The basics are to build one manu contour, and then to merge contours
57/// to build higher order objects, like PCBS, DEs, etc...
58///
cec5da80 59/// \author Laurent Aphecetche, Subatech
0145e89a 60
61///\cond CLASSIMP
62ClassImp(AliMUONPainterContourMaker)
63ClassImp(AliMUONPainterContourMaker::AliMUONNeighbour)
64///\endcond
65
66//_____________________________________________________________________________
67Int_t
68AliMUONPainterContourMaker::AliMUONNeighbour::Compare(const TObject* obj) const
69{
70 /// Compare two neighbours objects
71
72 const AliMUONNeighbour* n = static_cast<const AliMUONNeighbour*>(obj);
73
74 if ( Position().X() < n->Position().X() )
75 {
76 return -1;
77 }
78 else if ( Position().X() > n->Position().X() )
79 {
80 return 1;
81 }
82 else
83 {
84 // same X
85 if ( Position().Y() < n->Position().Y() )
86 {
87 return -1;
88 }
89 else if ( Position().Y() > n->Position().Y() )
90 {
91 return 1;
92 }
93 }
94 return 0;
95}
96
97//_____________________________________________________________________________
98void
99AliMUONPainterContourMaker::AliMUONNeighbour::Print(Option_t*) const
100{
101 /// Printout
102 cout << Form("ID %10d DE %4d Manu %4d Channel %2d "
103 "(X,Y)=(%7.3f,%7.3f) L,R,T,B=%1d,%1d,%1d,%1d",
104 ID(),
105 AliMUONVDigit::DetElemId(ID()),
106 AliMUONVDigit::ManuId(ID()),
107 AliMUONVDigit::ManuChannel(ID()),
108 Position().X(),Position().Y(),
109 HasLeftNeighbour(),HasRightNeighbour(),
110 HasTopNeighbour(),HasBottomNeighbour())
111 << endl;
112}
113
114//_____________________________________________________________________________
115AliMUONPainterContourMaker::AliMUONPainterContourMaker(AliMpExMap* globalTransformations)
116: TObject(),
117 fGlobalTransformations(globalTransformations),
118 fLocalManuContours(new TMap),
119 fContours(new TMap)
120{
121 /// ctor
122 fContours->SetOwner(kTRUE);
123}
124
125//_____________________________________________________________________________
126AliMUONPainterContourMaker::~AliMUONPainterContourMaker()
127{
128 /// dtor
129 fLocalManuContours->DeleteAll();
130 delete fLocalManuContours;
131 fContours->DeleteAll();
132 delete fContours;
133}
134
135//_____________________________________________________________________________
136void
137AliMUONPainterContourMaker::Add(AliMUONPainterContour* contour)
138{
139 /// Add a contour to our store of contours
140 fContours->Add(new TObjString(contour->GetName()),contour);
141}
142
143//_____________________________________________________________________________
144void
145AliMUONPainterContourMaker::AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
146 Double_t x2, Double_t y2, Int_t id) const
147{
148 /// Add one segment defined by (x1,y1,x2,y2) to the array of segments
149 AliCodeTimerAuto("")
150 AliDebug(1,Form("AddSegment %7.3f,%7.3f -> %7.3f,%7.3f",x1,y1,x2,y2));
151 TLine* line = new TLine(x1,y1,x2,y2);
152 line->SetUniqueID(id);
153 segments.Add(line);
154}
155
156//_____________________________________________________________________________
157Bool_t
158AliMUONPainterContourMaker::HasLine(const TObjArray& segments,
159 const TLine& line) const
160{
161 /// Check whether line is already part of segments array
162
163 TIter next(&segments);
164 TLine* l;
165
166 while ( ( l = static_cast<TLine*>(next()) ) )
167 {
168 if ( IsEqual(line,*l) ) return kTRUE;
169 }
170
171 return kFALSE;
172}
173
174//_____________________________________________________________________________
175void
176AliMUONPainterContourMaker::AddSegments(TObjArray& segments,
177 const AliMUONPainterContour& contour) const
178
179{
180 /// Add all the segments (that are not already there)
181 /// of contour to the segments array
182
183 AliCodeTimerAuto("")
184
185 const TObjArray* pl = contour.AsPolyLines();
186
187 TIter next(pl);
188
189 Int_t n(0);
190
191 TPolyLine* line;
192
193 while ( ( line = static_cast<TPolyLine*>(next()) ) )
194 {
195 n += line->GetLastPoint();
196 }
197
198 AliDebug(1,Form("Adding %d groups (%d lines) from contour %s ",pl->GetLast()+1,n,contour.GetName()));
199
200 next.Reset();
201
202 while ( ( line = static_cast<TPolyLine*>(next()) ) )
203 {
204 AliDebug(1,"line=");
205// StdoutToAliDebug(1,line->Print(););
206 for ( Int_t i = 0; i < line->GetLastPoint(); ++i )
207 {
208 Double_t x1 = line->GetX()[i];
209 Double_t y1 = line->GetY()[i];
210 Double_t x2 = line->GetX()[i+1];
211 Double_t y2 = line->GetY()[i+1];
212
213 TLine* line = new TLine(x1,y1,x2,y2);
214
215 if ( !HasLine(segments,*line) )
216 {
217 segments.Add(line);
218 AliDebug(1,Form("Adding line %s",LineAsString(*line).Data()));
219 }
220 else
221 {
222 AliDebug(1,Form("Line %s is already there",LineAsString(*line).Data()));
223 }
224 }
225 }
226}
227
228//_____________________________________________________________________________
229AliMUONPainterContour*
230AliMUONPainterContourMaker::ConvertEdgePadsToContour(TObjArray& ePads,
231 const char* name) const
232{
233 /// Convert an array of edge pads into a contour of a given name
234
235 AliCodeTimerAuto("")
236
237 ePads.Sort();
238
239 AliDebug(1,Form("%d pads to convert:",ePads.GetEntries()));
240// StdoutToAliDebug(1,ePads.Print();)
241
242 TObjArray segments;
243 segments.SetOwner(kTRUE);
244
245 TIter nextPad(&ePads);
246 AliMUONNeighbour* ne;
247
248 while ( ( ne = static_cast<AliMUONNeighbour*>(nextPad()) ) )
249 {
250 Int_t id = ne->ID();
251
252 if ( ! ne->HasLeftNeighbour() )
253 {
254 AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
255 ne->LowerLeft().X(),ne->UpperRight().Y(),id);
256 }
257 if ( ! ne->HasRightNeighbour() )
258 {
259 AddSegment(segments,ne->UpperRight().X(),ne->LowerLeft().Y(),
260 ne->UpperRight().X(),ne->UpperRight().Y(),id);
261 }
262 if ( ! ne->HasTopNeighbour() )
263 {
264 AddSegment(segments,ne->LowerLeft().X(),ne->UpperRight().Y(),
265 ne->UpperRight().X(),ne->UpperRight().Y(),id);
266 }
267 if ( ! ne->HasBottomNeighbour() )
268 {
269 AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
270 ne->UpperRight().X(),ne->LowerLeft().Y(),id);
271 }
272 }
273
274 return ConvertSegmentsToContour(segments,name);
275}
276
277//_____________________________________________________________________________
278void
279AliMUONPainterContourMaker::PrintLine(const TLine& line, const char* msg) const
280{
281 /// Printout of a line
282 cout << Form("%10s %s",
283 msg,LineAsString(line).Data()) << endl;
284}
285
286//_____________________________________________________________________________
287TString
288AliMUONPainterContourMaker::LineAsString(const TLine& line, Bool_t slope) const
289{
290 /// Return a string representation of the line
291
292 TString rv(Form("%7.3f,%7.3f -> %7.3f,%7.3f",
293 line.GetX1(),line.GetY1(),
294 line.GetX2(),line.GetY2()));
295
296 if ( slope )
297 {
298 if ( IsHorizontal(line) ) rv += " H";
299 else if ( IsVertical(line) ) rv += " V";
300 else rv += Form(" (slope %e)",Slope(line));
301 }
302
303 return rv;
304}
305
306//_____________________________________________________________________________
307void
308AliMUONPainterContourMaker::PrintSegments(const TObjArray& segments) const
309{
310 /// Printout of segment arrays (debug)
311
312 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
313 {
314 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
315
316 cout << Form("***--- i %4d",i);
317 if ( l )
318 {
319 PrintLine(*l);
320 }
321 else
322 {
323 cout << " line is null ?" << endl;
324 }
325 }
326}
327
328//_____________________________________________________________________________
329TLine*
330AliMUONPainterContourMaker::AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const
331{
332 /// Add one segment (taken from position i in array) into polyline
333
334 AliDebug(1,Form("i=%d",i));
335 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
336 if (l)
337 {
338 line.SetNextPoint(l->GetX1(),l->GetY1());
339 line.SetNextPoint(l->GetX2(),l->GetY2());
340 }
341 else
342 {
343 AliError(Form("Did not find the line at i=%d",i));
344 PrintSegments(segments);
345 }
346 return l;
347}
348
349//_____________________________________________________________________________
350Int_t
351AliMUONPainterContourMaker::FindPoint(Double_t x, Double_t y,
352 TObjArray& segments) const
353{
354 /// Find if point (x,y) is in segments array, and return
355 /// its index (=position within array)
356
357 TIter next(&segments);
358 TLine* l;
359
360 while ( ( l = static_cast<TLine*>(next()) ) )
361 {
362 if ( IsEqual(l->GetX1(),x) && IsEqual(l->GetY1(),y) )
363 {
364 return segments.IndexOf(l);
365 }
366 }
367 AliError(Form("Did not find point %7.3f %7.3f in those segments:",x,y));
368// StdoutToAliDebug(1,PrintSegments(segments););
369 return -1;
370}
371
372//_____________________________________________________________________________
373AliMUONPainterContour*
374AliMUONPainterContourMaker::ConvertSegmentsToContour(TObjArray& segments,
375 const char* name) const
376{
377 /// Convert an array of segments into a contour
378
379 AliDebug(1,"");
380 AliCodeTimerAuto("");
381
382 AliMUONPainterContour* contour = new AliMUONPainterContour(name);
383
384 Int_t n(0); // this is a protection against infinite loop (used for debug only)
385
386 while ( segments.GetLast() >= 0 && n < 100 )
387 {
388 TPolyLine lines;
389 TIter next(&segments);
390 TLine* l;
391
392 while ( ( l = static_cast<TLine*>(next() ) ) )
393 {
394 TLine* inserted = InsertSegment(lines,*l);
395 if ( inserted )
396 {
397 segments.Remove(inserted);
398 next.Reset();
399 }
400
401 // check for closure
402 if ( IsLineClosed(lines) )
403 {
404 AliDebug(1,"Line closed. Starting a new one");
405 break;
406 }
407 }
408
409 TPolyLine* sl = Simplify(lines);
410
411 contour->AdoptPolyLine(sl);
412 ++n;
413 }
414
415 if ( segments.GetLast() >= 0 )
416 {
417 AliError("segment should be empty by now");
418// StdoutToAliError(PrintSegments(segments););
419 }
420
421 return contour;
422}
423
424//_____________________________________________________________________________
425Int_t
426AliMUONPainterContourMaker::FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const
427{
428 /// Return position of (x,y) within the polyline
429
430 AliCodeTimerAuto("")
431
432 for ( Int_t i = 0; i < lines.Size(); ++i )
433 {
434 if ( IsEqual(lines.GetX()[i],x) && IsEqual(lines.GetY()[i],y) )
435 {
436 return i;
437 }
438 }
439 return -1;
440}
441
442//_____________________________________________________________________________
443void
444AliMUONPainterContourMaker::CleanSegments(TObjArray& segments,
445 const TArrayI& toBeRemoved) const
446{
447 /// Remove segments at indices stored in toBeRemoved array
448 for ( Int_t i = 0; i < toBeRemoved.GetSize(); ++i )
449 {
450 if ( toBeRemoved[i] )
451 {
452 segments.RemoveAt(i);
453 }
454 }
455 segments.Compress();
456}
457
458//_____________________________________________________________________________
459Int_t
460AliMUONPainterContourMaker::SplitSegments(TObjArray& segments) const
461{
462 /// Split segments that have partial overlap
463
464 AliCodeTimerAuto("")
465
466 TArrayI toBeRemoved(segments.GetLast()+1);
467 toBeRemoved.Reset(0);
468 Bool_t added(kFALSE);
469
470 for ( Int_t i = 0; i <= segments.GetLast() && !added; ++i )
471 {
472 if ( toBeRemoved[i] ) continue;
473
474 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
475
476 for ( Int_t j = i+1; j <= segments.GetLast() && !added; ++j )
477 {
478 if ( toBeRemoved[j] ) continue;
479
480 TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
481
482 Int_t o = Overlap(*li,*lj);
483
484 if ( o )
485 {
486 toBeRemoved[i] = toBeRemoved[j] = 1;
487
488 Double_t x[] = { li->GetX1(), lj->GetX1(), li->GetX2(), lj->GetX2() };
489 Double_t y[] = { li->GetY1(), lj->GetY1(), li->GetY2(), lj->GetY2() };
490
491 Double_t xmin(FLT_MAX), ymin(FLT_MAX);
492 Double_t xmax(-FLT_MAX), ymax(-FLT_MAX);
493
494 for ( Int_t i = 0; i < 4; ++i )
495 {
496 xmin = TMath::Min(x[i],xmin);
497 ymin = TMath::Min(y[i],ymin);
498 xmax = TMath::Max(x[i],xmax);
499 ymax = TMath::Max(y[i],ymax);
500 }
501
502 TLine fullLine(xmin,ymin,xmax,ymax);
503
504 for ( Int_t i = 0; i < 4; ++i )
505 {
506 for ( Int_t j = i+1; j < 4; ++j )
507 {
508 if ( TMath::Abs(i-j) != 2 )
509 {
510 TLine test(x[i],y[i],x[j],y[j]);
511
512 Bool_t isFullLine = IsEqual(test,fullLine);
513
514 if ( !IsPoint(test) && !isFullLine )
515 {
516 segments.Add(new TLine(test));
517 added = kTRUE;
518 }
519 }
520 }
521 }
522 }
523 }
524 }
525
526 CleanSegments(segments,toBeRemoved);
527
528 return added;
529}
530
531//_____________________________________________________________________________
532Bool_t
533AliMUONPainterContourMaker::ShouldBeRemoved(const TObjArray& contours,
534 Double_t x, Double_t y) const
535{
536 /// Tells whether or not a point can be removed, because it lies
537 /// inside the global contour
538
539 const Double_t kPrecision(AliMpConstants::LengthTolerance());
540 const Double_t kShiftX[] = { kPrecision,kPrecision,-kPrecision,-kPrecision };
541 const Double_t kShiftY[] = { kPrecision,-kPrecision,kPrecision,-kPrecision };
542
543 TIter next(&contours);
544 AliMUONPainterContour* contour;
545
546 Int_t n(0);
547
548 while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
549 {
550 for ( Int_t i = 0; i < 4; ++i )
551 {
552 if ( contour->IsInside( x + kShiftX[i], y + kShiftY[i]) )
553 {
554 ++n;
555 }
556 }
557 }
558
559 return (n>=4);
560}
561
562//_____________________________________________________________________________
563Int_t
564AliMUONPainterContourMaker::RemoveInsideSegments(const TObjArray& contours,
565 TObjArray& segments) const
566{
567 /// Remove segments that have 2 triple points
568
569 AliCodeTimerAuto("")
570
571 TArrayI toBeRemoved(segments.GetLast()+1);
572 toBeRemoved.Reset(0);
573
574 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
575 {
576 TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
577
578 Double_t x = (line->GetX1() + line->GetX2())/2.0;
579 Double_t y = (line->GetY1() + line->GetY2())/2.0;
580
581 if ( ShouldBeRemoved(contours,x,y) )
582 {
583 toBeRemoved[i] = 1;
584 }
585 }
586
587 Int_t before = segments.GetLast()+1;
588
589 CleanSegments(segments,toBeRemoved);
590
591 Int_t after = segments.GetLast()+1;
592
593 AliDebug(1,Form("# of segments before = %d after = %d",before,after));
594
595 return after-before;
596}
597
598//_____________________________________________________________________________
599AliMUONPainterContour*
600AliMUONPainterContourMaker::MergeContours(const TObjArray& contours,
601 const char* contourName) const
602{
603 /// Merge an array of contours into a single contour, with a given name
604
605 AliCodeTimerAuto("");
606
607 AliDebug(1,Form("Merging %d contours into %s",contours.GetLast()+1,contourName));
608
609 if ( contours.GetSize() == 0 ) return 0x0;
610
611 TIter next(&contours);
612 AliMUONPainterContour* contour;
613
614 TObjArray segments;
615 segments.SetOwner(kTRUE);
616
617 while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
618 {
619 AddSegments(segments,*contour);
620 }
621
622// AliDebug(1,"After AddSegments");
623// StdoutToAliDebug(1,PrintSegments(segments));
624
625 while (SplitSegments(segments));
626
627// AliDebug(1,"After SplitSegments");
628// StdoutToAliDebug(1,PrintSegments(segments));
629
630// if (!SanityCheck(contours,segments))
631// {
632// return 0x0;
633// }
634
635 RemoveInsideSegments(contours,segments);
636
637// if (!SanityCheck(contours,segments))
638// {
639// return 0x0;
640// }
641
642// AliDebug(1,"After RemoveInsideSegments");
643// StdoutToAliDebug(1,PrintSegments(segments););
644
645// if (!SanityCheck(contours,segments))
646// {
647// return 0x0;
648// }
649
650 return ConvertSegmentsToContour(segments,contourName);
651}
652
653//_____________________________________________________________________________
654TString
655AliMUONPainterContourMaker::NameIt(const AliMpMotifPosition& motifPosition) const
656{
657 /// Get the name of an AliMpMotifPosition
658
659 AliMpVMotif* motif = motifPosition.GetMotif();
660 TString name(Form("%s",motif->GetID().Data()));
661
662 for ( Int_t i = 0; i < motif->GetNofPadDimensions(); ++i )
663 {
664 TVector2 padDim = motif->GetPadDimensions(i);
665 name += Form("/%7.3f-%7.3f:",padDim.X(),padDim.Y());
666 }
667 return name;
668}
669
670//_____________________________________________________________________________
671AliMUONPainterContour*
672AliMUONPainterContourMaker::FindLocalManuContour(Int_t detElemId, Int_t manuId) const
673{
674 /// Get a pre-computed manu contour (in local coordinates)
675 AliCodeTimerAuto("")
676
677 AliMpMotifPosition* motifPos = FindMotifPosition(detElemId,manuId);
678
679 TObject* o = fLocalManuContours->GetValue(NameIt(*motifPos));
680
681 if (o) return static_cast<AliMUONPainterContour*>(o);
682 return 0x0;
683}
684
685//_____________________________________________________________________________
686AliMpMotifPosition*
687AliMUONPainterContourMaker::FindMotifPosition(Int_t detElemId, Int_t manuId) const
688{
689 /// Find a given motifPosition object
690
691 AliCodeTimerAuto("")
692
693 const AliMpVSegmentation* vseg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
694 if (!vseg)
695 {
696 AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
697 }
698
699 AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
700
701 if ( stationType == AliMp::kStation345 )
702 {
703 const AliMpSlatSegmentation* seg = static_cast<const AliMpSlatSegmentation*>(vseg);
704 const AliMpSlat* slat = seg->Slat();
705 return slat->FindMotifPosition(manuId);
706 }
707 else
708 {
709 const AliMpSectorSegmentation* seg = static_cast<const AliMpSectorSegmentation*>(vseg);
710 const AliMpSector* sector = seg->GetSector();
711 return sector->GetMotifMap()->FindMotifPosition(manuId);
712 }
713 return 0x0;
714}
715
716//_____________________________________________________________________________
717AliMUONPainterContour*
718AliMUONPainterContourMaker::GenerateManuContour(const char* name,
719 Int_t detElemId, Int_t manuId,
720 AliMUONAttPainter viewType) const
721{
722 /// Generate the contour for a given manu
723
724 AliDebug(3,Form("DE %04d ManuID %04d Name %s",detElemId,manuId,name));
725
726 AliCodeTimerAuto("")
727
728 AliMpMotifPosition* motifPosition = FindMotifPosition(detElemId,manuId);
729 AliMpVMotif* motif = motifPosition->GetMotif();
730
731 AliMUONPainterContour* contour = FindLocalManuContour(detElemId,manuId);
732 // do we already have the local contour for that manu ?
733
734 // no : build it
735 if (!contour)
736 {
737 AliCodeTimerAuto("Generation of local contour");
738 TObjArray ePads;
739 ePads.SetOwner(kTRUE);
740 AliMpMotifType* motifType = motif->GetMotifType();
741 AliDebug(3,Form("motifType %s",motifType->GetID().Data()));
742
743// for ( Int_t i = 0; i <= motifType->GetNofPads(); ++i )
744 for ( Int_t i = 0; i <= AliMpConstants::ManuNofChannels(); ++i )
745 {
746// AliMpConnection* connection = motifType->FindConnectionByPadNum(i);
747 AliMpConnection* connection = motifType->FindConnectionByGassiNum(i);
748
749 AliDebug(3,Form("connection i =%d",i));
750
751 if ( connection )
752 {
753 AliMpIntPair indices = connection->LocalIndices();
754 Bool_t left(kTRUE);
755 Bool_t right(kTRUE);
756 Bool_t top(kTRUE);
757 Bool_t bottom(kTRUE);
758
759 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(1,0)) )
760 {
761 right = kFALSE;
762 }
763 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(-1,0)) )
764 {
765 left = kFALSE;
766 }
767 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,1)) )
768 {
769 top = kFALSE;
770 }
771 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,-1)) )
772 {
773 bottom = kFALSE;
774 }
775
776 AliDebug(3,Form("indices=(%3d,%3d) L %d R %d T %d B %d",
777 indices.GetFirst(),indices.GetSecond(),
778 left,right,top,bottom));
779
780 TVector2 position = motif->PadPositionLocal(indices);
781 TVector2 dimensions = motif->GetPadDimensions(indices);
782
783 if ( !left || !right || !top || !bottom )
784 {
785 // the pad is on the edge
786 Int_t id = AliMUONVDigit::BuildUniqueID(detElemId,manuId,
787 connection->GetGassiNum(),0);
788 ePads.AddLast(new AliMUONNeighbour(id,position,dimensions,left,right,top,bottom));
789 }
790 }
791 }
792
793 contour = ConvertEdgePadsToContour(ePads,NameIt(*motifPosition));
794
795 AliDebug(1,Form("localContour:"));
796// StdoutToAliDebug(1,contour->Print("full"));
797 // register the local contour
798 fLocalManuContours->Add(new TObjString(contour->GetName()),contour);
799 }
800
801 AliMUONPainterContour* globalContour = static_cast<AliMUONPainterContour*>(contour->Clone(name));
802
803 // once we have the local contour, convert it to global
804
805 TVector2 pos(motifPosition->Position());
806
807 if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 )
808 {
809 const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(detElemId,manuId);
810 pos -= slat->Position();
811 }
812 globalContour->Offset(pos);
813 TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
814 globalContour->Transform(*matrix);
815
816 if ( viewType.IsBackView() )
817 {
818 AliWarning("Got a back view : will rotate ! This has not been really tested. Please do so now !");
819 TGeoRotation rot;
820 rot.RotateZ(180);
821 globalContour->Transform(rot);
822 }
823
824 return globalContour;
825}
826
827//_____________________________________________________________________________
828AliMUONPainterContour*
829AliMUONPainterContourMaker::GetContour(const char* name) const
830{
831 /// Get contour by name
832
833 TObject* o = fContours->GetValue(name);
834 return static_cast<AliMUONPainterContour*>(o);
835}
836
837//_____________________________________________________________________________
838Bool_t
839AliMUONPainterContourMaker::HasContour(const char* name) const
840{
841 /// Whether contour named "name" exists
842 TObject* o = fContours->GetValue(name);
843 if (o) return kTRUE;
844 return kFALSE;
845}
846
847//_____________________________________________________________________________
848TLine*
849AliMUONPainterContourMaker::InsertSegment(TPolyLine& lines, TLine& l) const
850{
851 /// Insert line into polyline, at the correct position
852
853 AliCodeTimerAuto("")
854// AliDebug(2,Form("Trying to insert %7.3f,%7.3f -> %7.3f,%7.3f from "
855// "(DE,manu,ch)=(%d,%d,%d) into",
856// l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2(),
857// AliMUONVDigit::DetElemId(l.GetUniqueID()),
858// AliMUONVDigit::ManuId(l.GetUniqueID()),
859// AliMUONVDigit::ManuChannel(l.GetUniqueID())));
860
861 if ( lines.Size()==0 )
862 {
863// AliDebug(2,"Starting line");
864//
865 lines.SetNextPoint(l.GetX1(),l.GetY1());
866 lines.SetNextPoint(l.GetX2(),l.GetY2());
867 return &l;
868 }
869
870 Int_t i1 = FindPoint(lines,l.GetX1(),l.GetY1());
871 Int_t i2 = FindPoint(lines,l.GetX2(),l.GetY2());
872
873 if ( i1 < 0 && i2 < 0 )
874 {
875// AliDebug(2,"Not yet");
876 return 0x0;
877 }
878
879 if ( i1 >= 0 && i2 >= 0 )
880 {
881 if ( i1==0 )
882 {
883 lines.SetNextPoint(l.GetX1(),l.GetY1());
884 }
885 else if ( i2==0 )
886 {
887 lines.SetNextPoint(l.GetX2(),l.GetY2());
888 }
889 else
890 {
891 AliError("Segment already there but does not correspond to ending the polyline !");
892 AliError(Form("Segment is %7.3f,%7.3f -> %7.3f,%7.3f and existing points are : ",
893 l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2()));
894
895 for ( Int_t i = 0; i < lines.Size(); ++i )
896 {
897 AliError(Form("Point %2d X %7.3f Y %7.3f",i,lines.GetX()[i],lines.GetY()[i]));
898 }
899// TObject* o(0x0);
900// o->Print(); // to crash and throw gdb...
901 }
902 return &l;
903 }
904
905 Double_t x = (i1>=0) ? l.GetX2() : l.GetX1();
906 Double_t y = (i1>=0) ? l.GetY2() : l.GetY1();
907
908 Int_t iref = ( i1 >= 0 ? i1 : i2 ) ;
909
910 Bool_t firstPoint = ( iref == 0 );
911
912 if ( firstPoint )
913 {
914 // must insert segment before
915 lines.SetPolyLine(lines.Size()+1);
916// AliDebug(2,Form("Inserting %7.3f,%7.3f",x,y));
917 for ( Int_t i = lines.Size()-1; i > 0; --i )
918 {
919 lines.SetPoint(i,lines.GetX()[i-1],lines.GetY()[i-1]);
920 }
921 lines.SetPoint(0,x,y);
922 }
923 else
924 {
925// AliDebug(2,Form("Appending %7.3f,%7.3f",x,y));
926 lines.SetNextPoint(x,y);
927 }
928
929 return &l;
930}
931
932//_____________________________________________________________________________
933Bool_t
934AliMUONPainterContourMaker::IsEqual(Double_t x, Double_t y) const
935{
936 /// Whether x==y
937
938 if ( TMath::Abs(x-y) < AliMpConstants::LengthTolerance() ) return kTRUE;
939 else return kFALSE;
940}
941
942//_____________________________________________________________________________
943Bool_t
944AliMUONPainterContourMaker::IsEqual(const TLine& line1,
945 const TLine& line2) const
946{
947 /// Whether line1 == line2
948
949 Bool_t check1 =
950 IsEqual(line1.GetX1(),line2.GetX1()) &&
951 IsEqual(line1.GetY1(),line2.GetY1()) &&
952 IsEqual(line1.GetX2(),line2.GetX2()) &&
953 IsEqual(line1.GetY2(),line2.GetY2());
954
955 Bool_t check2 =
956 IsEqual(line1.GetX1(),line2.GetX2()) &&
957 IsEqual(line1.GetY1(),line2.GetY2()) &&
958 IsEqual(line1.GetX2(),line2.GetX1()) &&
959 IsEqual(line1.GetY2(),line2.GetY1());
960
961 return (check1 || check2);
962}
963
964//_____________________________________________________________________________
965Double_t
966AliMUONPainterContourMaker::Slope(const TLine& line) const
967{
968 /// Get the slope of line
969
970 Double_t x = TMath::Abs(line.GetX2() - line.GetX1());
971
972 if ( x < AliMpConstants::LengthTolerance() ) return FLT_MAX;
973
974 return TMath::Abs(line.GetY2() - line.GetY1())/x;
975}
976
977//_____________________________________________________________________________
978Bool_t
979AliMUONPainterContourMaker::IsPoint(const TLine& line) const
980{
981 /// Whether the line is a point (sic ;-) )
982 return
983 IsEqual(line.GetX1(),line.GetX2()) &&
984 IsEqual(line.GetY1(),line.GetY2());
985}
986
987//_____________________________________________________________________________
988TLine
989AliMUONPainterContourMaker::Shift(const TLine& line, Double_t x, Double_t y) const
990{
991 /// Shift the line by a given offset
992
993 return TLine(line.GetX1()-x,line.GetY1()-y,line.GetX2()-x,line.GetY2()-y);
994}
995
996//_____________________________________________________________________________
997Bool_t
998AliMUONPainterContourMaker::SameDirection(const TLine& line1, const TLine& line2) const
999{
1000 /// Whether both lines have the same direction.
1001
1002 TLine l1 = Shift(line1,line1.GetX1(),line1.GetY1());
1003 TLine l2 = Shift(line2,line2.GetX1(),line2.GetY1());
1004
1005 Double_t v = l1.GetX2()*l2.GetX2() + l1.GetY2()*l2.GetY2();
1006
1007 return v > 0 ;
1008}
1009
1010//_____________________________________________________________________________
1011void
1012AliMUONPainterContourMaker::Swap(TLine& line) const
1013{
1014 /// Swap both points of the line
1015
1016 Double_t x = line.GetX1();
1017 Double_t y = line.GetY1();
1018
1019 line.SetX1(line.GetX2());
1020 line.SetY1(line.GetY2());
1021 line.SetX2(x);
1022 line.SetY2(y);
1023}
1024
1025//_____________________________________________________________________________
1026Int_t
1027AliMUONPainterContourMaker::IsInRange(Double_t x, Double_t a, Double_t b,
1028 Bool_t strict) const
1029{
1030 /// Whether w is in [a,b] (if strict=kFALSE) or in ]a,b[ (if strict=kTRUE)
1031
1032 if ( a > b )
1033 {
1034 Double_t tmp(b);
1035 b = a;
1036 a = tmp;
1037 }
1038
1039 Bool_t rv(kFALSE);
1040
1041 if ( strict )
1042 {
1043 rv = ( x > a && x < b );
1044 }
1045 else
1046 {
1047 rv = ( x >= a && x <= b);
1048 }
1049
1050 AliDebug(4,Form("x = %7.3f a = %7.3f b = %7.3f strict = %d IsInRange = %d",x,a,b,strict,rv));
1051
1052 return rv;
1053}
1054
1055//_____________________________________________________________________________
1056Int_t
1057AliMUONPainterContourMaker::IsInLine(const TLine& line,
1058 Double_t x,
1059 Double_t y,
1060 Bool_t strict) const
1061{
1062 /// Check whether point (x,y) is belonging to the line segment
1063 /// by computing the distance point to line
1064 /// line1 must not be a single point.
1065 /// Returns the number of *coordinates* that matches, for a point
1066 /// that lies on line (if point is not on the line, returns 0 always).
1067 /// For instance, if (x,y) is on the line (and strict=kFALSE),
1068 /// it will return 1 if x *or* y corresponds to line.GetX1() or X2 or Y1 or Y2,
1069 /// and 2 if the pair (x,y) corresponds to one of the line points.
1070
1071 Double_t x1 = line.GetX1();
1072 Double_t x2 = line.GetX2();
1073 Double_t y1 = line.GetY1();
1074 Double_t y2 = line.GetY2();
1075
1076 Double_t distance = TMath::Abs( (x2-x1)*(y1-y) - (x1-x)*(y2-y1) );
1077
1078 distance /= TMath::Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
1079
1080 Bool_t online = ( distance < AliMpConstants::LengthTolerance() ) ;
1081
1082 Int_t rv(0);
1083
1084 if (online)
1085 {
1086 // point is on the line,
1087 // check in addition that it's within the segment
1088
1089 rv = IsInRange(x,x1,x2,strict) + IsInRange(y,y1,y2,strict);
1090 }
1091 else
1092 {
1093 rv = 0;
1094 }
1095
1096 AliDebug(4,Form("Point (%7.3f,%7.3f) isinline=%d in line %s",
1097 x,y,rv,LineAsString(line).Data()));
1098
1099 return rv;
1100}
1101
1102//_____________________________________________________________________________
1103Int_t
1104AliMUONPainterContourMaker::IsInside(const TLine& line1,
1105 const TLine& line2,
1106 Bool_t useEndPoints) const
1107{
1108 /// Check whether one or both points of line2 are within line1.
1109 /// Both line1 and line2 must have the same slope
1110 /// and the same direction
1111
1112 if (!IsEqual(Slope(line1),Slope(line2))) return 0;
1113
1114 TLine l2(line2);
1115
1116 if (!SameDirection(line1,line2))
1117 {
1118 Swap(l2);
1119 }
1120
1121 Int_t rv =
1122 IsInLine(line1,l2.GetX1(),l2.GetY1(),!useEndPoints) +
1123 IsInLine(line1,l2.GetX2(),l2.GetY2(),!useEndPoints);
1124
1125 assert(rv<=4);
1126
1127 return rv;
1128}
1129
1130//_____________________________________________________________________________
1131Bool_t
1132AliMUONPainterContourMaker::IsInside(const TObjArray& segments,
1133 const TLine& line) const
1134{
1135 /// Whether the segment (line) is contained inside the contour defined
1136 /// by all the segments (i.e. is it on the boundary or not)
1137 /// Basic (and dirty) implementation only working with horizontal and vertical lines.
1138 /// I know there must be a better way to do it, but it took me way too long
1139 /// to get this stuff working, so I'm giving up on the optimisation/cleaning,
1140 /// at least for now...
1141 /// If you'd like to clean this (while keeping it working in all cases), be
1142 /// my guest and do it ;-) )
1143
1144 Int_t p1 = CountPoint(segments,line.GetX1(),line.GetY1());
1145 Int_t p2 = CountPoint(segments,line.GetX2(),line.GetY2());
1146
1147 Bool_t triplet = ( p1 >= 3 || p2 >= 3 );
1148
1149 AliDebug(4,Form("IsInside(segments,%s) triplet=%d",
1150 LineAsString(line).Data(),triplet));
1151
1152 if (!triplet) return kFALSE;
1153
1154 Bool_t top(kFALSE), bottom(kFALSE), left(kFALSE), right(kFALSE);
1155
1156 Bool_t vertical(IsVertical(line));
1157 Bool_t horizontal(IsHorizontal(line));
1158
1159 if (!vertical && !horizontal )
1160 {
1161 AliFatal("Only working with horizontal and vertical lines");
1162 }
1163
1164 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1165 {
1166 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
1167
1168 if ( IsEqual(*l,line) ) continue;
1169
1170 if ( vertical && IsVertical(*l) )
1171 {
1172 TLine tmpLine(l->GetX1(),line.GetY1(),
1173 l->GetX1(),line.GetY2());
1174
1175 AliDebug(4,Form("i=%2d VV\nIsInside(l=%s,%s)=%d\nIsInside(%s,l=%s)=%d",
1176 i,
1177 LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
1178 IsInside(*l,tmpLine,kTRUE),
1179 LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
1180 IsInside(tmpLine,*l,kTRUE)));
1181
1182 if ( IsInside(*l,tmpLine,kTRUE) == 4 || IsInside(tmpLine,*l,kTRUE) == 4 )
1183 {
1184 if ( l->GetX1() > line.GetX1() )
1185 {
1186 right = kTRUE;
1187 }
1188 else
1189 {
1190 left = kTRUE;
1191 }
1192 }
1193 }
1194
1195 if ( vertical && IsHorizontal(*l) )
1196 {
1197 if ( !IsEqual(l->GetY1(),line.GetX1()) &&
1198 !IsEqual(l->GetY1(),line.GetY2()) &&
1199 IsInLine(*l,line.GetX1(),l->GetY1(),kFALSE)==2 )
1200 {
1201 if ( line.GetY2() < l->GetY1() )
1202 {
1203 top = kTRUE;
1204 }
1205 else if ( line.GetY2() > l->GetY1() )
1206 {
1207 bottom = kTRUE;
1208 }
1209 }
1210 }
1211
1212 if ( horizontal && IsHorizontal(*l) )
1213 {
1214 TLine tmpLine(line.GetX1(),l->GetY1(),
1215 line.GetX2(),l->GetY1());
1216
1217 AliDebug(4,Form("i=%2d HH\nIsInside(%s,%s)=%d\nIsInside(%s,%s)=%d",
1218 i,
1219 LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
1220 IsInside(*l,tmpLine),
1221 LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
1222 IsInside(tmpLine,*l)));
1223
1224 if ( IsInside(*l,tmpLine) == 4 || IsInside(tmpLine,*l) == 4 )
1225 {
1226 if ( l->GetY1() > line.GetY1() )
1227 {
1228 top = kTRUE;
1229 }
1230 else
1231 {
1232 bottom = kTRUE;
1233 }
1234 }
1235 }
1236
1237 if ( horizontal && IsVertical(*l) )
1238 {
1239 if ( !IsEqual(l->GetX1(),line.GetX1()) &&
1240 !IsEqual(l->GetX1(),line.GetX2()) &&
1241 IsInLine(*l,l->GetX1(),line.GetY1(),kFALSE)==2 )
1242 {
1243 if ( line.GetX2() < l->GetX1() )
1244 {
1245 right = kTRUE;
1246 }
1247 else if ( line.GetX2() > l->GetX1() )
1248 {
1249 left = kTRUE;
1250 }
1251 }
1252 }
1253
1254 }
1255
1256 Bool_t rv(kFALSE);
1257
1258 AliDebug(3,Form("%s %s R %d L %d T %d B% d IsInside %d",
1259 IsVertical(line) ?
1260 "Vertical " :
1261 "Horizontal",
1262 LineAsString(line,kFALSE).Data(),right,left,top,bottom,rv));
1263
1264 if ( vertical )
1265 {
1266 rv = (right && left) && ( top || bottom );
1267 }
1268
1269 if ( horizontal )
1270 {
1271 rv = (top && bottom) && ( right || left );
1272 }
1273
1274 return rv;
1275}
1276
1277//_____________________________________________________________________________
1278Bool_t
1279AliMUONPainterContourMaker::IsHorizontal(const TLine& line) const
1280{
1281 /// whether line is horizontal
1282
1283 static Double_t l2 = AliMpConstants::LengthTolerance()*AliMpConstants::LengthTolerance();
1284
1285 return ( Slope(line) < l2 );
1286}
1287
1288//_____________________________________________________________________________
1289Bool_t
1290AliMUONPainterContourMaker::IsVertical(const TLine& line) const
1291{
1292 /// whether line is vertical
1293
1294 return ( TMath::Abs(Slope(line)) == FLT_MAX );
1295}
1296
1297//_____________________________________________________________________________
1298Int_t
1299AliMUONPainterContourMaker::Overlap(const TLine& line1,
1300 const TLine& line2) const
1301{
1302 /// Whether line1 and line2 overlap
1303
1304 Int_t rv(0);
1305
1306 if ( IsEqual(line1,line2) )
1307 {
1308 // First things first. If both lines are the same one,
1309 // they for sure overlap ;-)
1310 rv = 4;
1311 }
1312 else
1313 {
1314 rv = IsInside(line1,line2) + IsInside(line2,line1);
1315 }
1316
1317 AliDebug(3,Form("%s and %s : overlap=%d",
1318 LineAsString(line1).Data(),
1319 LineAsString(line2).Data(),
1320 rv));
1321
1322 return rv;
1323}
1324
1325//_____________________________________________________________________________
1326Bool_t
1327AliMUONPainterContourMaker::IsLineClosed(const TPolyLine& line) const
1328{
1329 /// check if polyline is already closed (i.e. last point = first point)
1330
1331 Double_t* x = line.GetX();
1332 Double_t* y = line.GetY();
1333
1334 if ( IsEqual(x[line.GetLastPoint()],x[0]) &&
1335 IsEqual(y[line.GetLastPoint()],y[0]) )
1336 {
1337 return kTRUE;
1338 }
1339 else
1340 {
1341 return kFALSE;
1342 }
1343}
1344
1345//_____________________________________________________________________________
1346void
1347AliMUONPainterContourMaker::Local2Global(Int_t detElemId,
1348 Double_t xl, Double_t yl, Double_t zl,
1349 Double_t& xg, Double_t& yg, Double_t& zg) const
1350{
1351 /// Convert local coordinates to global ones
1352 TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
1353 Double_t pl[3] = { xl, yl, zl };
1354 Double_t pg[3] = { 0., 0., 0. };
1355 matrix->LocalToMaster(pl, pg);
1356 xg = pg[0];
1357 yg = pg[1];
1358 zg = pg[2];
1359}
1360
1361//_____________________________________________________________________________
1362void
1363AliMUONPainterContourMaker::Print(Option_t* opt) const
1364{
1365 /// Printout
1366
1367 cout << "Local Contours" << endl;
1368
1369 TIter next(fLocalManuContours);
1370 TObjString* key;
1371
1372 while ( ( key = static_cast<TObjString*>(next()) ) )
1373 {
1374 cout << key->String().Data() << endl;
1375 AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fLocalManuContours->GetValue(key));
1376 contour->Print(opt);
1377 }
1378
1379 cout << "Global Contours" << endl;
1380
1381 TIter nextC(fContours);
1382
1383 while ( ( key = static_cast<TObjString*>(nextC()) ) )
1384 {
1385 AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fContours->GetValue(key));
1386 contour->Print(opt);
1387 }
1388}
1389
1390//_____________________________________________________________________________
1391Int_t
1392AliMUONPainterContourMaker::CountPoint(const TObjArray& segments,
1393 Double_t x, Double_t y) const
1394{
1395 /// Count the number of times the point (x,y) appears in the segment array
1396
1397 Int_t n(0);
1398
1399 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1400 {
1401 TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
1402
1403 if ( IsEqual(x,line->GetX1()) &&
1404 IsEqual(y,line->GetY1()) )
1405 {
1406 ++n;
1407 }
1408
1409 if ( IsEqual(x,line->GetX2()) &&
1410 IsEqual(y,line->GetY2()) )
1411 {
1412 ++n;
1413 }
1414 }
1415
1416 return n;
1417}
1418
1419//_____________________________________________________________________________
1420Bool_t
1421AliMUONPainterContourMaker::SanityCheck(const TObjArray& contours,
1422 const TObjArray& segments, Bool_t check) const
1423{
1424 /// (debug) check
1425
1426 Bool_t ok(kTRUE);
1427
1428 // cross-check that we have no more complete duplicates
1429 // and that we have no orphan point
1430
1431 Double_t xmin(FLT_MAX), xmax(-FLT_MAX);
1432 Double_t ymin(FLT_MAX), ymax(-FLT_MAX);
1433
1434 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1435 {
1436 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
1437
1438 if (!IsHorizontal(*li) && !IsVertical(*li))
1439 {
1440 AliError("Got an oblique line !");
1441 return kFALSE;
1442 }
1443
1444 xmin = TMath::Min(xmin,li->GetX1());
1445 xmin = TMath::Min(xmin,li->GetX2());
1446
1447 xmax = TMath::Max(xmax,li->GetX1());
1448 xmax = TMath::Max(xmax,li->GetX2());
1449
1450 ymin = TMath::Min(ymin,li->GetY1());
1451 ymin = TMath::Min(ymin,li->GetY2());
1452
1453 ymax = TMath::Max(ymax,li->GetY1());
1454 ymax = TMath::Max(ymax,li->GetY2());
1455
1456 }
1457
1458 AliDebug(1,Form("xmin=%7.3f ymin=%7.3f xmax=%7.3f ymax=%7.3f",
1459 xmin,ymin,xmax,ymax));
1460
1461 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1462 {
1463 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
1464
1465 if (!check)
1466 {
1467 for ( Int_t j = 0; j <= segments.GetLast(); ++j )
1468 {
1469 TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
1470
1471 if ( i != j && IsEqual(*li,*lj) )
1472 {
1473 ok = kFALSE;
1474 PrintLine(*li);
1475 PrintLine(*lj);
1476 AliFatal("");
1477 }
1478 }
1479 }
1480
1481
1482 Int_t rv(0);
1483
1484 Double_t x = (li->GetX1()+li->GetX2())/2.0;
1485 Double_t y = (li->GetY1()+li->GetY2())/2.0;
1486
1487 if ( ShouldBeRemoved(contours,x,y) ) rv = 1;
1488
1489 AliDebug(1,Form("Line %4d %7.3f,%7.3f -> %7.3f,%7.3f [ %d ]",
1490 i,
1491 li->GetX1(),li->GetY1(),
1492 li->GetX2(),li->GetY2(),
1493 rv));
1494 }
1495
1496 return kTRUE;
1497}
1498
1499//_____________________________________________________________________________
1500TPolyLine*
1501AliMUONPainterContourMaker::Simplify(const TPolyLine& lines) const
1502{
1503 /// try to simplify the polyline, by minimizing the number of points
1504
1505 if ( lines.Size() < 3 )
1506 {
1507 AliError("Cannot simplify lines with less that 3 points !");
1508 return 0x0;
1509 }
1510
1511 AliCodeTimerAuto("")
1512
1513// cout << "Before simplify" << endl;
1514//
1515// for ( Int_t i = 0; i < lines.Size(); ++i )
1516// {
1517// cout << Form("Point %3d %7.3f %7.3f",i,lines.GetX()[i],lines.GetY()[i]) << endl;
1518// }
1519
1520 TPolyLine* l = new TPolyLine;
1521
1522 Double_t* x = lines.GetX();
1523 Double_t* y = lines.GetY();
1524
1525 l->SetNextPoint(x[0],y[0]);
1526
1527 Bool_t verticalCurrent = IsEqual(x[1],x[0]);
1528 Bool_t horizontalCurrent = IsEqual(y[1],y[0]);
1529
1530 Int_t i(2);
1531
1532 while ( i < lines.Size() )
1533 {
1534 Bool_t vertical = IsEqual(x[i],x[i-1]);
1535 Bool_t horizontal = IsEqual(y[i],y[i-1]);
1536
1537// cout << Form("i %3d %7.3f %7.3f vert %d horiz %d (current vert %d horiz %d)",
1538// i,x[i],y[i],vertical,horizontal,verticalCurrent,horizontalCurrent)
1539// << endl;
1540
1541 if ( ( vertical != verticalCurrent ) ||
1542 ( horizontal != horizontalCurrent ) )
1543 {
1544// cout << Form("Changing direction : adding point %7.3f %7.3f",x[i-1],y[i-1]) << endl;
1545 l->SetNextPoint(x[i-1],y[i-1]);
1546 verticalCurrent = vertical;
1547 horizontalCurrent = horizontal;
1548 }
1549 ++i;
1550 }
1551
1552 l->SetNextPoint(l->GetX()[0],l->GetY()[0]);
1553
1554// cout << "After simplify" << endl;
1555//
1556// for ( Int_t i = 0; i < l->Size(); ++i )
1557// {
1558// cout << Form("Point %3d %7.3f %7.3f",i,l->GetX()[i],l->GetY()[i]) << endl;
1559// }
1560
1561 return l;
1562}
1563
1564//_____________________________________________________________________________
1565Int_t
1566AliMUONPainterContourMaker::Size() const
1567{
1568 /// Number of contours we have already
1569
1570 return fContours->GetSize();
1571}
1572