1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 #include "AliMUONPainterContourMaker.h"
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"
40 #include <Riostream.h>
42 #include <TGeoMatrix.h>
46 #include <TMathBase.h>
47 #include <TObjArray.h>
48 #include <TPolyLine.h>
52 ///\class AliMUONPainterContourMaker
54 /// A class to build painter contours.
56 /// The basics are to build one manu contour, and then to merge contours
57 /// to build higher order objects, like PCBS, DEs, etc...
59 ///\author Laurent Aphecetche, Subatech
62 ClassImp(AliMUONPainterContourMaker)
63 ClassImp(AliMUONPainterContourMaker::AliMUONNeighbour)
66 //_____________________________________________________________________________
68 AliMUONPainterContourMaker::AliMUONNeighbour::Compare(const TObject* obj) const
70 /// Compare two neighbours objects
72 const AliMUONNeighbour* n = static_cast<const AliMUONNeighbour*>(obj);
74 if ( Position().X() < n->Position().X() )
78 else if ( Position().X() > n->Position().X() )
85 if ( Position().Y() < n->Position().Y() )
89 else if ( Position().Y() > n->Position().Y() )
97 //_____________________________________________________________________________
99 AliMUONPainterContourMaker::AliMUONNeighbour::Print(Option_t*) const
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",
105 AliMUONVDigit::DetElemId(ID()),
106 AliMUONVDigit::ManuId(ID()),
107 AliMUONVDigit::ManuChannel(ID()),
108 Position().X(),Position().Y(),
109 HasLeftNeighbour(),HasRightNeighbour(),
110 HasTopNeighbour(),HasBottomNeighbour())
114 //_____________________________________________________________________________
115 AliMUONPainterContourMaker::AliMUONPainterContourMaker(AliMpExMap* globalTransformations)
117 fGlobalTransformations(globalTransformations),
118 fLocalManuContours(new TMap),
122 fContours->SetOwner(kTRUE);
125 //_____________________________________________________________________________
126 AliMUONPainterContourMaker::~AliMUONPainterContourMaker()
129 fLocalManuContours->DeleteAll();
130 delete fLocalManuContours;
131 fContours->DeleteAll();
135 //_____________________________________________________________________________
137 AliMUONPainterContourMaker::Add(AliMUONPainterContour* contour)
139 /// Add a contour to our store of contours
140 fContours->Add(new TObjString(contour->GetName()),contour);
143 //_____________________________________________________________________________
145 AliMUONPainterContourMaker::AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
146 Double_t x2, Double_t y2, Int_t id) const
148 /// Add one segment defined by (x1,y1,x2,y2) to the array of segments
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);
156 //_____________________________________________________________________________
158 AliMUONPainterContourMaker::HasLine(const TObjArray& segments,
159 const TLine& line) const
161 /// Check whether line is already part of segments array
163 TIter next(&segments);
166 while ( ( l = static_cast<TLine*>(next()) ) )
168 if ( IsEqual(line,*l) ) return kTRUE;
174 //_____________________________________________________________________________
176 AliMUONPainterContourMaker::AddSegments(TObjArray& segments,
177 const AliMUONPainterContour& contour) const
180 /// Add all the segments (that are not already there)
181 /// of contour to the segments array
185 const TObjArray* pl = contour.AsPolyLines();
193 while ( ( line = static_cast<TPolyLine*>(next()) ) )
195 n += line->GetLastPoint();
198 AliDebug(1,Form("Adding %d groups (%d lines) from contour %s ",pl->GetLast()+1,n,contour.GetName()));
202 while ( ( line = static_cast<TPolyLine*>(next()) ) )
205 // StdoutToAliDebug(1,line->Print(););
206 for ( Int_t i = 0; i < line->GetLastPoint(); ++i )
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];
213 TLine* line = new TLine(x1,y1,x2,y2);
215 if ( !HasLine(segments,*line) )
218 AliDebug(1,Form("Adding line %s",LineAsString(*line).Data()));
222 AliDebug(1,Form("Line %s is already there",LineAsString(*line).Data()));
228 //_____________________________________________________________________________
229 AliMUONPainterContour*
230 AliMUONPainterContourMaker::ConvertEdgePadsToContour(TObjArray& ePads,
231 const char* name) const
233 /// Convert an array of edge pads into a contour of a given name
239 AliDebug(1,Form("%d pads to convert:",ePads.GetEntries()));
240 // StdoutToAliDebug(1,ePads.Print();)
243 segments.SetOwner(kTRUE);
245 TIter nextPad(&ePads);
246 AliMUONNeighbour* ne;
248 while ( ( ne = static_cast<AliMUONNeighbour*>(nextPad()) ) )
252 if ( ! ne->HasLeftNeighbour() )
254 AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
255 ne->LowerLeft().X(),ne->UpperRight().Y(),id);
257 if ( ! ne->HasRightNeighbour() )
259 AddSegment(segments,ne->UpperRight().X(),ne->LowerLeft().Y(),
260 ne->UpperRight().X(),ne->UpperRight().Y(),id);
262 if ( ! ne->HasTopNeighbour() )
264 AddSegment(segments,ne->LowerLeft().X(),ne->UpperRight().Y(),
265 ne->UpperRight().X(),ne->UpperRight().Y(),id);
267 if ( ! ne->HasBottomNeighbour() )
269 AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
270 ne->UpperRight().X(),ne->LowerLeft().Y(),id);
274 return ConvertSegmentsToContour(segments,name);
277 //_____________________________________________________________________________
279 AliMUONPainterContourMaker::PrintLine(const TLine& line, const char* msg) const
281 /// Printout of a line
282 cout << Form("%10s %s",
283 msg,LineAsString(line).Data()) << endl;
286 //_____________________________________________________________________________
288 AliMUONPainterContourMaker::LineAsString(const TLine& line, Bool_t slope) const
290 /// Return a string representation of the line
292 TString rv(Form("%7.3f,%7.3f -> %7.3f,%7.3f",
293 line.GetX1(),line.GetY1(),
294 line.GetX2(),line.GetY2()));
298 if ( IsHorizontal(line) ) rv += " H";
299 else if ( IsVertical(line) ) rv += " V";
300 else rv += Form(" (slope %e)",Slope(line));
306 //_____________________________________________________________________________
308 AliMUONPainterContourMaker::PrintSegments(const TObjArray& segments) const
310 /// Printout of segment arrays (debug)
312 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
314 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
316 cout << Form("***--- i %4d",i);
323 cout << " line is null ?" << endl;
328 //_____________________________________________________________________________
330 AliMUONPainterContourMaker::AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const
332 /// Add one segment (taken from position i in array) into polyline
334 AliDebug(1,Form("i=%d",i));
335 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
338 line.SetNextPoint(l->GetX1(),l->GetY1());
339 line.SetNextPoint(l->GetX2(),l->GetY2());
343 AliError(Form("Did not find the line at i=%d",i));
344 PrintSegments(segments);
349 //_____________________________________________________________________________
351 AliMUONPainterContourMaker::FindPoint(Double_t x, Double_t y,
352 TObjArray& segments) const
354 /// Find if point (x,y) is in segments array, and return
355 /// its index (=position within array)
357 TIter next(&segments);
360 while ( ( l = static_cast<TLine*>(next()) ) )
362 if ( IsEqual(l->GetX1(),x) && IsEqual(l->GetY1(),y) )
364 return segments.IndexOf(l);
367 AliError(Form("Did not find point %7.3f %7.3f in those segments:",x,y));
368 // StdoutToAliDebug(1,PrintSegments(segments););
372 //_____________________________________________________________________________
373 AliMUONPainterContour*
374 AliMUONPainterContourMaker::ConvertSegmentsToContour(TObjArray& segments,
375 const char* name) const
377 /// Convert an array of segments into a contour
380 AliCodeTimerAuto("");
382 AliMUONPainterContour* contour = new AliMUONPainterContour(name);
384 Int_t n(0); // this is a protection against infinite loop (used for debug only)
386 while ( segments.GetLast() >= 0 && n < 100 )
389 TIter next(&segments);
392 while ( ( l = static_cast<TLine*>(next() ) ) )
394 TLine* inserted = InsertSegment(lines,*l);
397 segments.Remove(inserted);
402 if ( IsLineClosed(lines) )
404 AliDebug(1,"Line closed. Starting a new one");
409 TPolyLine* sl = Simplify(lines);
411 contour->AdoptPolyLine(sl);
415 if ( segments.GetLast() >= 0 )
417 AliError("segment should be empty by now");
418 // StdoutToAliError(PrintSegments(segments););
424 //_____________________________________________________________________________
426 AliMUONPainterContourMaker::FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const
428 /// Return position of (x,y) within the polyline
432 for ( Int_t i = 0; i < lines.Size(); ++i )
434 if ( IsEqual(lines.GetX()[i],x) && IsEqual(lines.GetY()[i],y) )
442 //_____________________________________________________________________________
444 AliMUONPainterContourMaker::CleanSegments(TObjArray& segments,
445 const TArrayI& toBeRemoved) const
447 /// Remove segments at indices stored in toBeRemoved array
448 for ( Int_t i = 0; i < toBeRemoved.GetSize(); ++i )
450 if ( toBeRemoved[i] )
452 segments.RemoveAt(i);
458 //_____________________________________________________________________________
460 AliMUONPainterContourMaker::SplitSegments(TObjArray& segments) const
462 /// Split segments that have partial overlap
466 TArrayI toBeRemoved(segments.GetLast()+1);
467 toBeRemoved.Reset(0);
468 Bool_t added(kFALSE);
470 for ( Int_t i = 0; i <= segments.GetLast() && !added; ++i )
472 if ( toBeRemoved[i] ) continue;
474 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
476 for ( Int_t j = i+1; j <= segments.GetLast() && !added; ++j )
478 if ( toBeRemoved[j] ) continue;
480 TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
482 Int_t o = Overlap(*li,*lj);
486 toBeRemoved[i] = toBeRemoved[j] = 1;
488 Double_t x[] = { li->GetX1(), lj->GetX1(), li->GetX2(), lj->GetX2() };
489 Double_t y[] = { li->GetY1(), lj->GetY1(), li->GetY2(), lj->GetY2() };
491 Double_t xmin(FLT_MAX), ymin(FLT_MAX);
492 Double_t xmax(-FLT_MAX), ymax(-FLT_MAX);
494 for ( Int_t i = 0; i < 4; ++i )
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);
502 TLine fullLine(xmin,ymin,xmax,ymax);
504 for ( Int_t i = 0; i < 4; ++i )
506 for ( Int_t j = i+1; j < 4; ++j )
508 if ( TMath::Abs(i-j) != 2 )
510 TLine test(x[i],y[i],x[j],y[j]);
512 Bool_t isFullLine = IsEqual(test,fullLine);
514 if ( !IsPoint(test) && !isFullLine )
516 segments.Add(new TLine(test));
526 CleanSegments(segments,toBeRemoved);
531 //_____________________________________________________________________________
533 AliMUONPainterContourMaker::ShouldBeRemoved(const TObjArray& contours,
534 Double_t x, Double_t y) const
536 /// Tells whether or not a point can be removed, because it lies
537 /// inside the global contour
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 };
543 TIter next(&contours);
544 AliMUONPainterContour* contour;
548 while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
550 for ( Int_t i = 0; i < 4; ++i )
552 if ( contour->IsInside( x + kShiftX[i], y + kShiftY[i]) )
562 //_____________________________________________________________________________
564 AliMUONPainterContourMaker::RemoveInsideSegments(const TObjArray& contours,
565 TObjArray& segments) const
567 /// Remove segments that have 2 triple points
571 TArrayI toBeRemoved(segments.GetLast()+1);
572 toBeRemoved.Reset(0);
574 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
576 TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
578 Double_t x = (line->GetX1() + line->GetX2())/2.0;
579 Double_t y = (line->GetY1() + line->GetY2())/2.0;
581 if ( ShouldBeRemoved(contours,x,y) )
587 Int_t before = segments.GetLast()+1;
589 CleanSegments(segments,toBeRemoved);
591 Int_t after = segments.GetLast()+1;
593 AliDebug(1,Form("# of segments before = %d after = %d",before,after));
598 //_____________________________________________________________________________
599 AliMUONPainterContour*
600 AliMUONPainterContourMaker::MergeContours(const TObjArray& contours,
601 const char* contourName) const
603 /// Merge an array of contours into a single contour, with a given name
605 AliCodeTimerAuto("");
607 AliDebug(1,Form("Merging %d contours into %s",contours.GetLast()+1,contourName));
609 if ( contours.GetSize() == 0 ) return 0x0;
611 TIter next(&contours);
612 AliMUONPainterContour* contour;
615 segments.SetOwner(kTRUE);
617 while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
619 AddSegments(segments,*contour);
622 // AliDebug(1,"After AddSegments");
623 // StdoutToAliDebug(1,PrintSegments(segments));
625 while (SplitSegments(segments));
627 // AliDebug(1,"After SplitSegments");
628 // StdoutToAliDebug(1,PrintSegments(segments));
630 // if (!SanityCheck(contours,segments))
635 RemoveInsideSegments(contours,segments);
637 // if (!SanityCheck(contours,segments))
642 // AliDebug(1,"After RemoveInsideSegments");
643 // StdoutToAliDebug(1,PrintSegments(segments););
645 // if (!SanityCheck(contours,segments))
650 return ConvertSegmentsToContour(segments,contourName);
653 //_____________________________________________________________________________
655 AliMUONPainterContourMaker::NameIt(const AliMpMotifPosition& motifPosition) const
657 /// Get the name of an AliMpMotifPosition
659 AliMpVMotif* motif = motifPosition.GetMotif();
660 TString name(Form("%s",motif->GetID().Data()));
662 for ( Int_t i = 0; i < motif->GetNofPadDimensions(); ++i )
664 TVector2 padDim = motif->GetPadDimensions(i);
665 name += Form("/%7.3f-%7.3f:",padDim.X(),padDim.Y());
670 //_____________________________________________________________________________
671 AliMUONPainterContour*
672 AliMUONPainterContourMaker::FindLocalManuContour(Int_t detElemId, Int_t manuId) const
674 /// Get a pre-computed manu contour (in local coordinates)
677 AliMpMotifPosition* motifPos = FindMotifPosition(detElemId,manuId);
679 TObject* o = fLocalManuContours->GetValue(NameIt(*motifPos));
681 if (o) return static_cast<AliMUONPainterContour*>(o);
685 //_____________________________________________________________________________
687 AliMUONPainterContourMaker::FindMotifPosition(Int_t detElemId, Int_t manuId) const
689 /// Find a given motifPosition object
693 const AliMpVSegmentation* vseg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
696 AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
699 AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
701 if ( stationType == AliMp::kStation345 )
703 const AliMpSlatSegmentation* seg = static_cast<const AliMpSlatSegmentation*>(vseg);
704 const AliMpSlat* slat = seg->Slat();
705 return slat->FindMotifPosition(manuId);
709 const AliMpSectorSegmentation* seg = static_cast<const AliMpSectorSegmentation*>(vseg);
710 const AliMpSector* sector = seg->GetSector();
711 return sector->GetMotifMap()->FindMotifPosition(manuId);
716 //_____________________________________________________________________________
717 AliMUONPainterContour*
718 AliMUONPainterContourMaker::GenerateManuContour(const char* name,
719 Int_t detElemId, Int_t manuId,
720 AliMUONAttPainter viewType) const
722 /// Generate the contour for a given manu
724 AliDebug(3,Form("DE %04d ManuID %04d Name %s",detElemId,manuId,name));
728 AliMpMotifPosition* motifPosition = FindMotifPosition(detElemId,manuId);
729 AliMpVMotif* motif = motifPosition->GetMotif();
731 AliMUONPainterContour* contour = FindLocalManuContour(detElemId,manuId);
732 // do we already have the local contour for that manu ?
737 AliCodeTimerAuto("Generation of local contour");
739 ePads.SetOwner(kTRUE);
740 AliMpMotifType* motifType = motif->GetMotifType();
741 AliDebug(3,Form("motifType %s",motifType->GetID().Data()));
743 // for ( Int_t i = 0; i <= motifType->GetNofPads(); ++i )
744 for ( Int_t i = 0; i <= AliMpConstants::ManuNofChannels(); ++i )
746 // AliMpConnection* connection = motifType->FindConnectionByPadNum(i);
747 AliMpConnection* connection = motifType->FindConnectionByGassiNum(i);
749 AliDebug(3,Form("connection i =%d",i));
753 AliMpIntPair indices = connection->LocalIndices();
757 Bool_t bottom(kTRUE);
759 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(1,0)) )
763 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(-1,0)) )
767 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,1)) )
771 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,-1)) )
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));
780 TVector2 position = motif->PadPositionLocal(indices);
781 TVector2 dimensions = motif->GetPadDimensions(indices);
783 if ( !left || !right || !top || !bottom )
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));
793 contour = ConvertEdgePadsToContour(ePads,NameIt(*motifPosition));
795 AliDebug(1,Form("localContour:"));
796 // StdoutToAliDebug(1,contour->Print("full"));
797 // register the local contour
798 fLocalManuContours->Add(new TObjString(contour->GetName()),contour);
801 AliMUONPainterContour* globalContour = static_cast<AliMUONPainterContour*>(contour->Clone(name));
803 // once we have the local contour, convert it to global
805 TVector2 pos(motifPosition->Position());
807 if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 )
809 const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(detElemId,manuId);
810 pos -= slat->Position();
812 globalContour->Offset(pos);
813 TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
814 globalContour->Transform(*matrix);
816 if ( viewType.IsBackView() )
818 AliWarning("Got a back view : will rotate ! This has not been really tested. Please do so now !");
821 globalContour->Transform(rot);
824 return globalContour;
827 //_____________________________________________________________________________
828 AliMUONPainterContour*
829 AliMUONPainterContourMaker::GetContour(const char* name) const
831 /// Get contour by name
833 TObject* o = fContours->GetValue(name);
834 return static_cast<AliMUONPainterContour*>(o);
837 //_____________________________________________________________________________
839 AliMUONPainterContourMaker::HasContour(const char* name) const
841 /// Whether contour named "name" exists
842 TObject* o = fContours->GetValue(name);
847 //_____________________________________________________________________________
849 AliMUONPainterContourMaker::InsertSegment(TPolyLine& lines, TLine& l) const
851 /// Insert line into polyline, at the correct position
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())));
861 if ( lines.Size()==0 )
863 // AliDebug(2,"Starting line");
865 lines.SetNextPoint(l.GetX1(),l.GetY1());
866 lines.SetNextPoint(l.GetX2(),l.GetY2());
870 Int_t i1 = FindPoint(lines,l.GetX1(),l.GetY1());
871 Int_t i2 = FindPoint(lines,l.GetX2(),l.GetY2());
873 if ( i1 < 0 && i2 < 0 )
875 // AliDebug(2,"Not yet");
879 if ( i1 >= 0 && i2 >= 0 )
883 lines.SetNextPoint(l.GetX1(),l.GetY1());
887 lines.SetNextPoint(l.GetX2(),l.GetY2());
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()));
895 for ( Int_t i = 0; i < lines.Size(); ++i )
897 AliError(Form("Point %2d X %7.3f Y %7.3f",i,lines.GetX()[i],lines.GetY()[i]));
900 // o->Print(); // to crash and throw gdb...
905 Double_t x = (i1>=0) ? l.GetX2() : l.GetX1();
906 Double_t y = (i1>=0) ? l.GetY2() : l.GetY1();
908 Int_t iref = ( i1 >= 0 ? i1 : i2 ) ;
910 Bool_t firstPoint = ( iref == 0 );
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 )
919 lines.SetPoint(i,lines.GetX()[i-1],lines.GetY()[i-1]);
921 lines.SetPoint(0,x,y);
925 // AliDebug(2,Form("Appending %7.3f,%7.3f",x,y));
926 lines.SetNextPoint(x,y);
932 //_____________________________________________________________________________
934 AliMUONPainterContourMaker::IsEqual(Double_t x, Double_t y) const
938 if ( TMath::Abs(x-y) < AliMpConstants::LengthTolerance() ) return kTRUE;
942 //_____________________________________________________________________________
944 AliMUONPainterContourMaker::IsEqual(const TLine& line1,
945 const TLine& line2) const
947 /// Whether line1 == line2
950 IsEqual(line1.GetX1(),line2.GetX1()) &&
951 IsEqual(line1.GetY1(),line2.GetY1()) &&
952 IsEqual(line1.GetX2(),line2.GetX2()) &&
953 IsEqual(line1.GetY2(),line2.GetY2());
956 IsEqual(line1.GetX1(),line2.GetX2()) &&
957 IsEqual(line1.GetY1(),line2.GetY2()) &&
958 IsEqual(line1.GetX2(),line2.GetX1()) &&
959 IsEqual(line1.GetY2(),line2.GetY1());
961 return (check1 || check2);
964 //_____________________________________________________________________________
966 AliMUONPainterContourMaker::Slope(const TLine& line) const
968 /// Get the slope of line
970 Double_t x = TMath::Abs(line.GetX2() - line.GetX1());
972 if ( x < AliMpConstants::LengthTolerance() ) return FLT_MAX;
974 return TMath::Abs(line.GetY2() - line.GetY1())/x;
977 //_____________________________________________________________________________
979 AliMUONPainterContourMaker::IsPoint(const TLine& line) const
981 /// Whether the line is a point (sic ;-) )
983 IsEqual(line.GetX1(),line.GetX2()) &&
984 IsEqual(line.GetY1(),line.GetY2());
987 //_____________________________________________________________________________
989 AliMUONPainterContourMaker::Shift(const TLine& line, Double_t x, Double_t y) const
991 /// Shift the line by a given offset
993 return TLine(line.GetX1()-x,line.GetY1()-y,line.GetX2()-x,line.GetY2()-y);
996 //_____________________________________________________________________________
998 AliMUONPainterContourMaker::SameDirection(const TLine& line1, const TLine& line2) const
1000 /// Whether both lines have the same direction.
1002 TLine l1 = Shift(line1,line1.GetX1(),line1.GetY1());
1003 TLine l2 = Shift(line2,line2.GetX1(),line2.GetY1());
1005 Double_t v = l1.GetX2()*l2.GetX2() + l1.GetY2()*l2.GetY2();
1010 //_____________________________________________________________________________
1012 AliMUONPainterContourMaker::Swap(TLine& line) const
1014 /// Swap both points of the line
1016 Double_t x = line.GetX1();
1017 Double_t y = line.GetY1();
1019 line.SetX1(line.GetX2());
1020 line.SetY1(line.GetY2());
1025 //_____________________________________________________________________________
1027 AliMUONPainterContourMaker::IsInRange(Double_t x, Double_t a, Double_t b,
1028 Bool_t strict) const
1030 /// Whether w is in [a,b] (if strict=kFALSE) or in ]a,b[ (if strict=kTRUE)
1043 rv = ( x > a && x < b );
1047 rv = ( x >= a && x <= b);
1050 AliDebug(4,Form("x = %7.3f a = %7.3f b = %7.3f strict = %d IsInRange = %d",x,a,b,strict,rv));
1055 //_____________________________________________________________________________
1057 AliMUONPainterContourMaker::IsInLine(const TLine& line,
1060 Bool_t strict) const
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.
1071 Double_t x1 = line.GetX1();
1072 Double_t x2 = line.GetX2();
1073 Double_t y1 = line.GetY1();
1074 Double_t y2 = line.GetY2();
1076 Double_t distance = TMath::Abs( (x2-x1)*(y1-y) - (x1-x)*(y2-y1) );
1078 distance /= TMath::Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
1080 Bool_t online = ( distance < AliMpConstants::LengthTolerance() ) ;
1086 // point is on the line,
1087 // check in addition that it's within the segment
1089 rv = IsInRange(x,x1,x2,strict) + IsInRange(y,y1,y2,strict);
1096 AliDebug(4,Form("Point (%7.3f,%7.3f) isinline=%d in line %s",
1097 x,y,rv,LineAsString(line).Data()));
1102 //_____________________________________________________________________________
1104 AliMUONPainterContourMaker::IsInside(const TLine& line1,
1106 Bool_t useEndPoints) const
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
1112 if (!IsEqual(Slope(line1),Slope(line2))) return 0;
1116 if (!SameDirection(line1,line2))
1122 IsInLine(line1,l2.GetX1(),l2.GetY1(),!useEndPoints) +
1123 IsInLine(line1,l2.GetX2(),l2.GetY2(),!useEndPoints);
1130 //_____________________________________________________________________________
1132 AliMUONPainterContourMaker::IsInside(const TObjArray& segments,
1133 const TLine& line) const
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 ;-) )
1144 Int_t p1 = CountPoint(segments,line.GetX1(),line.GetY1());
1145 Int_t p2 = CountPoint(segments,line.GetX2(),line.GetY2());
1147 Bool_t triplet = ( p1 >= 3 || p2 >= 3 );
1149 AliDebug(4,Form("IsInside(segments,%s) triplet=%d",
1150 LineAsString(line).Data(),triplet));
1152 if (!triplet) return kFALSE;
1154 Bool_t top(kFALSE), bottom(kFALSE), left(kFALSE), right(kFALSE);
1156 Bool_t vertical(IsVertical(line));
1157 Bool_t horizontal(IsHorizontal(line));
1159 if (!vertical && !horizontal )
1161 AliFatal("Only working with horizontal and vertical lines");
1164 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1166 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
1168 if ( IsEqual(*l,line) ) continue;
1170 if ( vertical && IsVertical(*l) )
1172 TLine tmpLine(l->GetX1(),line.GetY1(),
1173 l->GetX1(),line.GetY2());
1175 AliDebug(4,Form("i=%2d VV\nIsInside(l=%s,%s)=%d\nIsInside(%s,l=%s)=%d",
1177 LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
1178 IsInside(*l,tmpLine,kTRUE),
1179 LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
1180 IsInside(tmpLine,*l,kTRUE)));
1182 if ( IsInside(*l,tmpLine,kTRUE) == 4 || IsInside(tmpLine,*l,kTRUE) == 4 )
1184 if ( l->GetX1() > line.GetX1() )
1195 if ( vertical && IsHorizontal(*l) )
1197 if ( !IsEqual(l->GetY1(),line.GetX1()) &&
1198 !IsEqual(l->GetY1(),line.GetY2()) &&
1199 IsInLine(*l,line.GetX1(),l->GetY1(),kFALSE)==2 )
1201 if ( line.GetY2() < l->GetY1() )
1205 else if ( line.GetY2() > l->GetY1() )
1212 if ( horizontal && IsHorizontal(*l) )
1214 TLine tmpLine(line.GetX1(),l->GetY1(),
1215 line.GetX2(),l->GetY1());
1217 AliDebug(4,Form("i=%2d HH\nIsInside(%s,%s)=%d\nIsInside(%s,%s)=%d",
1219 LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
1220 IsInside(*l,tmpLine),
1221 LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
1222 IsInside(tmpLine,*l)));
1224 if ( IsInside(*l,tmpLine) == 4 || IsInside(tmpLine,*l) == 4 )
1226 if ( l->GetY1() > line.GetY1() )
1237 if ( horizontal && IsVertical(*l) )
1239 if ( !IsEqual(l->GetX1(),line.GetX1()) &&
1240 !IsEqual(l->GetX1(),line.GetX2()) &&
1241 IsInLine(*l,l->GetX1(),line.GetY1(),kFALSE)==2 )
1243 if ( line.GetX2() < l->GetX1() )
1247 else if ( line.GetX2() > l->GetX1() )
1258 AliDebug(3,Form("%s %s R %d L %d T %d B% d IsInside %d",
1262 LineAsString(line,kFALSE).Data(),right,left,top,bottom,rv));
1266 rv = (right && left) && ( top || bottom );
1271 rv = (top && bottom) && ( right || left );
1277 //_____________________________________________________________________________
1279 AliMUONPainterContourMaker::IsHorizontal(const TLine& line) const
1281 /// whether line is horizontal
1283 static Double_t l2 = AliMpConstants::LengthTolerance()*AliMpConstants::LengthTolerance();
1285 return ( Slope(line) < l2 );
1288 //_____________________________________________________________________________
1290 AliMUONPainterContourMaker::IsVertical(const TLine& line) const
1292 /// whether line is vertical
1294 return ( TMath::Abs(Slope(line)) == FLT_MAX );
1297 //_____________________________________________________________________________
1299 AliMUONPainterContourMaker::Overlap(const TLine& line1,
1300 const TLine& line2) const
1302 /// Whether line1 and line2 overlap
1306 if ( IsEqual(line1,line2) )
1308 // First things first. If both lines are the same one,
1309 // they for sure overlap ;-)
1314 rv = IsInside(line1,line2) + IsInside(line2,line1);
1317 AliDebug(3,Form("%s and %s : overlap=%d",
1318 LineAsString(line1).Data(),
1319 LineAsString(line2).Data(),
1325 //_____________________________________________________________________________
1327 AliMUONPainterContourMaker::IsLineClosed(const TPolyLine& line) const
1329 /// check if polyline is already closed (i.e. last point = first point)
1331 Double_t* x = line.GetX();
1332 Double_t* y = line.GetY();
1334 if ( IsEqual(x[line.GetLastPoint()],x[0]) &&
1335 IsEqual(y[line.GetLastPoint()],y[0]) )
1345 //_____________________________________________________________________________
1347 AliMUONPainterContourMaker::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
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);
1361 //_____________________________________________________________________________
1363 AliMUONPainterContourMaker::Print(Option_t* opt) const
1367 cout << "Local Contours" << endl;
1369 TIter next(fLocalManuContours);
1372 while ( ( key = static_cast<TObjString*>(next()) ) )
1374 cout << key->String().Data() << endl;
1375 AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fLocalManuContours->GetValue(key));
1376 contour->Print(opt);
1379 cout << "Global Contours" << endl;
1381 TIter nextC(fContours);
1383 while ( ( key = static_cast<TObjString*>(nextC()) ) )
1385 AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fContours->GetValue(key));
1386 contour->Print(opt);
1390 //_____________________________________________________________________________
1392 AliMUONPainterContourMaker::CountPoint(const TObjArray& segments,
1393 Double_t x, Double_t y) const
1395 /// Count the number of times the point (x,y) appears in the segment array
1399 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1401 TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
1403 if ( IsEqual(x,line->GetX1()) &&
1404 IsEqual(y,line->GetY1()) )
1409 if ( IsEqual(x,line->GetX2()) &&
1410 IsEqual(y,line->GetY2()) )
1419 //_____________________________________________________________________________
1421 AliMUONPainterContourMaker::SanityCheck(const TObjArray& contours,
1422 const TObjArray& segments, Bool_t check) const
1428 // cross-check that we have no more complete duplicates
1429 // and that we have no orphan point
1431 Double_t xmin(FLT_MAX), xmax(-FLT_MAX);
1432 Double_t ymin(FLT_MAX), ymax(-FLT_MAX);
1434 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1436 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
1438 if (!IsHorizontal(*li) && !IsVertical(*li))
1440 AliError("Got an oblique line !");
1444 xmin = TMath::Min(xmin,li->GetX1());
1445 xmin = TMath::Min(xmin,li->GetX2());
1447 xmax = TMath::Max(xmax,li->GetX1());
1448 xmax = TMath::Max(xmax,li->GetX2());
1450 ymin = TMath::Min(ymin,li->GetY1());
1451 ymin = TMath::Min(ymin,li->GetY2());
1453 ymax = TMath::Max(ymax,li->GetY1());
1454 ymax = TMath::Max(ymax,li->GetY2());
1458 AliDebug(1,Form("xmin=%7.3f ymin=%7.3f xmax=%7.3f ymax=%7.3f",
1459 xmin,ymin,xmax,ymax));
1461 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1463 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
1467 for ( Int_t j = 0; j <= segments.GetLast(); ++j )
1469 TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
1471 if ( i != j && IsEqual(*li,*lj) )
1484 Double_t x = (li->GetX1()+li->GetX2())/2.0;
1485 Double_t y = (li->GetY1()+li->GetY2())/2.0;
1487 if ( ShouldBeRemoved(contours,x,y) ) rv = 1;
1489 AliDebug(1,Form("Line %4d %7.3f,%7.3f -> %7.3f,%7.3f [ %d ]",
1491 li->GetX1(),li->GetY1(),
1492 li->GetX2(),li->GetY2(),
1499 //_____________________________________________________________________________
1501 AliMUONPainterContourMaker::Simplify(const TPolyLine& lines) const
1503 /// try to simplify the polyline, by minimizing the number of points
1505 if ( lines.Size() < 3 )
1507 AliError("Cannot simplify lines with less that 3 points !");
1511 AliCodeTimerAuto("")
1513 // cout << "Before simplify" << endl;
1515 // for ( Int_t i = 0; i < lines.Size(); ++i )
1517 // cout << Form("Point %3d %7.3f %7.3f",i,lines.GetX()[i],lines.GetY()[i]) << endl;
1520 TPolyLine* l = new TPolyLine;
1522 Double_t* x = lines.GetX();
1523 Double_t* y = lines.GetY();
1525 l->SetNextPoint(x[0],y[0]);
1527 Bool_t verticalCurrent = IsEqual(x[1],x[0]);
1528 Bool_t horizontalCurrent = IsEqual(y[1],y[0]);
1532 while ( i < lines.Size() )
1534 Bool_t vertical = IsEqual(x[i],x[i-1]);
1535 Bool_t horizontal = IsEqual(y[i],y[i-1]);
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)
1541 if ( ( vertical != verticalCurrent ) ||
1542 ( horizontal != horizontalCurrent ) )
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;
1552 l->SetNextPoint(l->GetX()[0],l->GetY()[0]);
1554 // cout << "After simplify" << endl;
1556 // for ( Int_t i = 0; i < l->Size(); ++i )
1558 // cout << Form("Point %3d %7.3f %7.3f",i,l->GetX()[i],l->GetY()[i]) << endl;
1564 //_____________________________________________________________________________
1566 AliMUONPainterContourMaker::Size() const
1568 /// Number of contours we have already
1570 return fContours->GetSize();