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 "AliMpSegmentation.h"
33 #include "AliMpSlat.h"
34 #include "AliMpStationType.h"
35 #include "AliMpVMotif.h"
36 #include "AliCodeTimer.h"
38 #include <Riostream.h>
40 #include <TGeoMatrix.h>
44 #include <TMathBase.h>
45 #include <TObjArray.h>
46 #include <TPolyLine.h>
50 /// \class AliMUONPainterContourMaker
52 /// A class to build painter contours.
54 /// The basics are to build one manu contour, and then to merge contours
55 /// to build higher order objects, like PCBS, DEs, etc...
57 /// \author Laurent Aphecetche, Subatech
60 ClassImp(AliMUONPainterContourMaker)
61 ClassImp(AliMUONPainterContourMaker::AliMUONNeighbour)
64 //_____________________________________________________________________________
66 AliMUONPainterContourMaker::AliMUONNeighbour::Compare(const TObject* obj) const
68 /// Compare two neighbours objects
70 const AliMUONNeighbour* n = static_cast<const AliMUONNeighbour*>(obj);
72 if ( Position().X() < n->Position().X() )
76 else if ( Position().X() > n->Position().X() )
83 if ( Position().Y() < n->Position().Y() )
87 else if ( Position().Y() > n->Position().Y() )
95 //_____________________________________________________________________________
97 AliMUONPainterContourMaker::AliMUONNeighbour::Print(Option_t*) const
100 cout << Form("ID %10d DE %4d Manu %4d Channel %2d "
101 "(X,Y)=(%7.3f,%7.3f) L,R,T,B=%1d,%1d,%1d,%1d",
103 AliMUONVDigit::DetElemId(ID()),
104 AliMUONVDigit::ManuId(ID()),
105 AliMUONVDigit::ManuChannel(ID()),
106 Position().X(),Position().Y(),
107 HasLeftNeighbour(),HasRightNeighbour(),
108 HasTopNeighbour(),HasBottomNeighbour())
112 //_____________________________________________________________________________
113 AliMUONPainterContourMaker::AliMUONPainterContourMaker(AliMpExMap* globalTransformations)
115 fGlobalTransformations(globalTransformations),
116 fLocalManuContours(new TMap),
120 fContours->SetOwner(kTRUE);
123 //_____________________________________________________________________________
124 AliMUONPainterContourMaker::~AliMUONPainterContourMaker()
127 fLocalManuContours->DeleteAll();
128 delete fLocalManuContours;
129 fContours->DeleteAll();
133 //_____________________________________________________________________________
135 AliMUONPainterContourMaker::Add(AliMUONPainterContour* contour)
137 /// Add a contour to our store of contours
138 fContours->Add(new TObjString(contour->GetName()),contour);
141 //_____________________________________________________________________________
143 AliMUONPainterContourMaker::AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
144 Double_t x2, Double_t y2, Int_t id) const
146 /// Add one segment defined by (x1,y1,x2,y2) to the array of segments
148 AliDebug(1,Form("AddSegment %7.3f,%7.3f -> %7.3f,%7.3f",x1,y1,x2,y2));
149 TLine* line = new TLine(x1,y1,x2,y2);
150 line->SetUniqueID(id);
154 //_____________________________________________________________________________
156 AliMUONPainterContourMaker::HasLine(const TObjArray& segments,
157 const TLine& line) const
159 /// Check whether line is already part of segments array
161 TIter next(&segments);
164 while ( ( l = static_cast<TLine*>(next()) ) )
166 if ( IsEqual(line,*l) ) return kTRUE;
172 //_____________________________________________________________________________
174 AliMUONPainterContourMaker::AddSegments(TObjArray& segments,
175 const AliMUONPainterContour& contour) const
178 /// Add all the segments (that are not already there)
179 /// of contour to the segments array
183 const TObjArray* pl = contour.AsPolyLines();
191 while ( ( line = static_cast<TPolyLine*>(next()) ) )
193 n += line->GetLastPoint();
196 AliDebug(1,Form("Adding %d groups (%d lines) from contour %s ",pl->GetLast()+1,n,contour.GetName()));
200 while ( ( line = static_cast<TPolyLine*>(next()) ) )
203 // StdoutToAliDebug(1,line->Print(););
204 for ( Int_t i = 0; i < line->GetLastPoint(); ++i )
206 Double_t x1 = line->GetX()[i];
207 Double_t y1 = line->GetY()[i];
208 Double_t x2 = line->GetX()[i+1];
209 Double_t y2 = line->GetY()[i+1];
211 TLine* l = new TLine(x1,y1,x2,y2);
213 if ( !HasLine(segments,*l) )
216 AliDebug(1,Form("Adding line %s",LineAsString(*l).Data()));
220 AliDebug(1,Form("Line %s is already there",LineAsString(*l).Data()));
226 //_____________________________________________________________________________
227 AliMUONPainterContour*
228 AliMUONPainterContourMaker::ConvertEdgePadsToContour(TObjArray& ePads,
229 const char* name) const
231 /// Convert an array of edge pads into a contour of a given name
237 AliDebug(1,Form("%d pads to convert:",ePads.GetEntries()));
238 // StdoutToAliDebug(1,ePads.Print();)
241 segments.SetOwner(kTRUE);
243 TIter nextPad(&ePads);
244 AliMUONNeighbour* ne;
246 while ( ( ne = static_cast<AliMUONNeighbour*>(nextPad()) ) )
250 if ( ! ne->HasLeftNeighbour() )
252 AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
253 ne->LowerLeft().X(),ne->UpperRight().Y(),id);
255 if ( ! ne->HasRightNeighbour() )
257 AddSegment(segments,ne->UpperRight().X(),ne->LowerLeft().Y(),
258 ne->UpperRight().X(),ne->UpperRight().Y(),id);
260 if ( ! ne->HasTopNeighbour() )
262 AddSegment(segments,ne->LowerLeft().X(),ne->UpperRight().Y(),
263 ne->UpperRight().X(),ne->UpperRight().Y(),id);
265 if ( ! ne->HasBottomNeighbour() )
267 AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
268 ne->UpperRight().X(),ne->LowerLeft().Y(),id);
272 return ConvertSegmentsToContour(segments,name);
275 //_____________________________________________________________________________
277 AliMUONPainterContourMaker::PrintLine(const TLine& line, const char* msg) const
279 /// Printout of a line
280 cout << Form("%10s %s",
281 msg,LineAsString(line).Data()) << endl;
284 //_____________________________________________________________________________
286 AliMUONPainterContourMaker::LineAsString(const TLine& line, Bool_t slope) const
288 /// Return a string representation of the line
290 TString rv(Form("%7.3f,%7.3f -> %7.3f,%7.3f",
291 line.GetX1(),line.GetY1(),
292 line.GetX2(),line.GetY2()));
296 if ( IsHorizontal(line) ) rv += " H";
297 else if ( IsVertical(line) ) rv += " V";
298 else rv += Form(" (slope %e)",Slope(line));
304 //_____________________________________________________________________________
306 AliMUONPainterContourMaker::PrintSegments(const TObjArray& segments) const
308 /// Printout of segment arrays (debug)
310 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
312 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
314 cout << Form("***--- i %4d",i);
321 cout << " line is null ?" << endl;
326 //_____________________________________________________________________________
328 AliMUONPainterContourMaker::AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const
330 /// Add one segment (taken from position i in array) into polyline
332 AliDebug(1,Form("i=%d",i));
333 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
336 line.SetNextPoint(l->GetX1(),l->GetY1());
337 line.SetNextPoint(l->GetX2(),l->GetY2());
341 AliError(Form("Did not find the line at i=%d",i));
342 PrintSegments(segments);
347 //_____________________________________________________________________________
349 AliMUONPainterContourMaker::FindPoint(Double_t x, Double_t y,
350 TObjArray& segments) const
352 /// Find if point (x,y) is in segments array, and return
353 /// its index (=position within array)
355 TIter next(&segments);
358 while ( ( l = static_cast<TLine*>(next()) ) )
360 if ( IsEqual(l->GetX1(),x) && IsEqual(l->GetY1(),y) )
362 return segments.IndexOf(l);
365 AliError(Form("Did not find point %7.3f %7.3f in those segments:",x,y));
366 // StdoutToAliDebug(1,PrintSegments(segments););
370 //_____________________________________________________________________________
371 AliMUONPainterContour*
372 AliMUONPainterContourMaker::ConvertSegmentsToContour(TObjArray& segments,
373 const char* name) const
375 /// Convert an array of segments into a contour
378 AliCodeTimerAuto("");
380 AliMUONPainterContour* contour = new AliMUONPainterContour(name);
382 Int_t n(0); // this is a protection against infinite loop (used for debug only)
384 while ( segments.GetLast() >= 0 && n < 100 )
387 TIter next(&segments);
390 while ( ( l = static_cast<TLine*>(next() ) ) )
392 TLine* inserted = InsertSegment(lines,*l);
395 segments.Remove(inserted);
400 if ( IsLineClosed(lines) )
402 AliDebug(1,"Line closed. Starting a new one");
407 TPolyLine* sl = Simplify(lines);
409 contour->AdoptPolyLine(sl);
413 if ( segments.GetLast() >= 0 )
415 AliError("segment should be empty by now");
416 // StdoutToAliError(PrintSegments(segments););
422 //_____________________________________________________________________________
424 AliMUONPainterContourMaker::FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const
426 /// Return position of (x,y) within the polyline
430 for ( Int_t i = 0; i < lines.Size(); ++i )
432 if ( IsEqual(lines.GetX()[i],x) && IsEqual(lines.GetY()[i],y) )
440 //_____________________________________________________________________________
442 AliMUONPainterContourMaker::CleanSegments(TObjArray& segments,
443 const TArrayI& toBeRemoved) const
445 /// Remove segments at indices stored in toBeRemoved array
446 for ( Int_t i = 0; i < toBeRemoved.GetSize(); ++i )
448 if ( toBeRemoved[i] )
450 segments.RemoveAt(i);
456 //_____________________________________________________________________________
458 AliMUONPainterContourMaker::SplitSegments(TObjArray& segments) const
460 /// Split segments that have partial overlap
464 TArrayI toBeRemoved(segments.GetLast()+1);
465 toBeRemoved.Reset(0);
466 Bool_t added(kFALSE);
468 for ( Int_t i = 0; i <= segments.GetLast() && !added; ++i )
470 if ( toBeRemoved[i] ) continue;
472 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
474 for ( Int_t j = i+1; j <= segments.GetLast() && !added; ++j )
476 if ( toBeRemoved[j] ) continue;
478 TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
480 Int_t o = Overlap(*li,*lj);
484 toBeRemoved[i] = toBeRemoved[j] = 1;
486 Double_t x[] = { li->GetX1(), lj->GetX1(), li->GetX2(), lj->GetX2() };
487 Double_t y[] = { li->GetY1(), lj->GetY1(), li->GetY2(), lj->GetY2() };
489 Double_t xmin(FLT_MAX), ymin(FLT_MAX);
490 Double_t xmax(-FLT_MAX), ymax(-FLT_MAX);
492 for ( Int_t k = 0; k < 4; ++k )
494 xmin = TMath::Min(x[k],xmin);
495 ymin = TMath::Min(y[k],ymin);
496 xmax = TMath::Max(x[k],xmax);
497 ymax = TMath::Max(y[k],ymax);
500 TLine fullLine(xmin,ymin,xmax,ymax);
502 for ( Int_t i1 = 0; i1 < 4; ++i1 )
504 for ( Int_t j1 = i1+1; j1 < 4; ++j1 )
506 if ( TMath::Abs(i1-j1) != 2 )
508 TLine test(x[i1],y[i1],x[j1],y[j1]);
510 Bool_t isFullLine = IsEqual(test,fullLine);
512 if ( !IsPoint(test) && !isFullLine )
514 segments.Add(new TLine(test));
524 CleanSegments(segments,toBeRemoved);
529 //_____________________________________________________________________________
531 AliMUONPainterContourMaker::ShouldBeRemoved(const TObjArray& contours,
532 Double_t x, Double_t y) const
534 /// Tells whether or not a point can be removed, because it lies
535 /// inside the global contour
537 const Double_t kPrecision(AliMpConstants::LengthTolerance());
538 const Double_t kShiftX[] = { kPrecision,kPrecision,-kPrecision,-kPrecision };
539 const Double_t kShiftY[] = { kPrecision,-kPrecision,kPrecision,-kPrecision };
541 TIter next(&contours);
542 AliMUONPainterContour* contour;
546 while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
548 for ( Int_t i = 0; i < 4; ++i )
550 if ( contour->IsInside( x + kShiftX[i], y + kShiftY[i]) )
560 //_____________________________________________________________________________
562 AliMUONPainterContourMaker::RemoveInsideSegments(const TObjArray& contours,
563 TObjArray& segments) const
565 /// Remove segments that have 2 triple points
569 TArrayI toBeRemoved(segments.GetLast()+1);
570 toBeRemoved.Reset(0);
572 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
574 TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
576 Double_t x = (line->GetX1() + line->GetX2())/2.0;
577 Double_t y = (line->GetY1() + line->GetY2())/2.0;
579 if ( ShouldBeRemoved(contours,x,y) )
585 Int_t before = segments.GetLast()+1;
587 CleanSegments(segments,toBeRemoved);
589 Int_t after = segments.GetLast()+1;
591 AliDebug(1,Form("# of segments before = %d after = %d",before,after));
596 //_____________________________________________________________________________
597 AliMUONPainterContour*
598 AliMUONPainterContourMaker::MergeContours(const TObjArray& contours,
599 const char* contourName) const
601 /// Merge an array of contours into a single contour, with a given name
603 AliCodeTimerAuto("");
605 AliDebug(1,Form("Merging %d contours into %s",contours.GetLast()+1,contourName));
607 if ( contours.GetSize() == 0 ) return 0x0;
609 TIter next(&contours);
610 AliMUONPainterContour* contour;
613 segments.SetOwner(kTRUE);
615 while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
617 AddSegments(segments,*contour);
620 // AliDebug(1,"After AddSegments");
621 // StdoutToAliDebug(1,PrintSegments(segments));
623 while (SplitSegments(segments)) {}
625 // AliDebug(1,"After SplitSegments");
626 // StdoutToAliDebug(1,PrintSegments(segments));
628 // if (!SanityCheck(contours,segments))
633 RemoveInsideSegments(contours,segments);
635 // if (!SanityCheck(contours,segments))
640 // AliDebug(1,"After RemoveInsideSegments");
641 // StdoutToAliDebug(1,PrintSegments(segments););
643 // if (!SanityCheck(contours,segments))
648 return ConvertSegmentsToContour(segments,contourName);
651 //_____________________________________________________________________________
653 AliMUONPainterContourMaker::NameIt(const AliMpMotifPosition& motifPosition) const
655 /// Get the name of an AliMpMotifPosition
657 AliMpVMotif* motif = motifPosition.GetMotif();
658 TString name(Form("%s",motif->GetID().Data()));
660 for ( Int_t i = 0; i < motif->GetNofPadDimensions(); ++i )
662 TVector2 padDim = motif->GetPadDimensions(i);
663 name += Form("/%7.3f-%7.3f:",padDim.X(),padDim.Y());
668 //_____________________________________________________________________________
669 AliMUONPainterContour*
670 AliMUONPainterContourMaker::FindLocalManuContour(Int_t detElemId, Int_t manuId) const
672 /// Get a pre-computed manu contour (in local coordinates)
675 AliMpMotifPosition* motifPos = FindMotifPosition(detElemId,manuId);
677 TObject* o = fLocalManuContours->GetValue(NameIt(*motifPos));
679 if (o) return static_cast<AliMUONPainterContour*>(o);
683 //_____________________________________________________________________________
685 AliMUONPainterContourMaker::FindMotifPosition(Int_t detElemId, Int_t manuId) const
687 /// Find a given motifPosition object
691 AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
693 if ( stationType == AliMp::kStation345 )
695 const AliMpSlat* kSlat
696 = AliMpSegmentation::Instance()->GetSlatByElectronics(detElemId,manuId);
698 AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
700 return kSlat->FindMotifPosition(manuId);
704 const AliMpSector* kSector
705 = AliMpSegmentation::Instance()->GetSectorByElectronics(detElemId,manuId);
707 AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
709 return kSector->GetMotifMap()->FindMotifPosition(manuId);
714 //_____________________________________________________________________________
715 AliMUONPainterContour*
716 AliMUONPainterContourMaker::GenerateManuContour(const char* name,
717 Int_t detElemId, Int_t manuId,
718 AliMUONAttPainter viewType) const
720 /// Generate the contour for a given manu
722 AliDebug(3,Form("DE %04d ManuID %04d Name %s",detElemId,manuId,name));
726 AliMpMotifPosition* motifPosition = FindMotifPosition(detElemId,manuId);
727 AliMpVMotif* motif = motifPosition->GetMotif();
729 AliMUONPainterContour* contour = FindLocalManuContour(detElemId,manuId);
730 // do we already have the local contour for that manu ?
735 AliCodeTimerAuto("Generation of local contour");
737 ePads.SetOwner(kTRUE);
738 AliMpMotifType* motifType = motif->GetMotifType();
739 AliDebug(3,Form("motifType %s",motifType->GetID().Data()));
741 // for ( Int_t i = 0; i <= motifType->GetNofPads(); ++i )
742 for ( Int_t i = 0; i <= AliMpConstants::ManuNofChannels(); ++i )
744 // AliMpConnection* connection = motifType->FindConnectionByPadNum(i);
745 AliMpConnection* connection = motifType->FindConnectionByGassiNum(i);
747 AliDebug(3,Form("connection i =%d",i));
751 AliMpIntPair indices = connection->LocalIndices();
755 Bool_t bottom(kTRUE);
757 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(1,0)) )
761 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(-1,0)) )
765 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,1)) )
769 if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,-1)) )
774 AliDebug(3,Form("indices=(%3d,%3d) L %d R %d T %d B %d",
775 indices.GetFirst(),indices.GetSecond(),
776 left,right,top,bottom));
778 TVector2 position = motif->PadPositionLocal(indices);
779 TVector2 dimensions = motif->GetPadDimensions(indices);
781 if ( !left || !right || !top || !bottom )
783 // the pad is on the edge
784 Int_t id = AliMUONVDigit::BuildUniqueID(detElemId,manuId,
785 connection->GetManuChannel(),0);
786 ePads.AddLast(new AliMUONNeighbour(id,position,dimensions,left,right,top,bottom));
791 contour = ConvertEdgePadsToContour(ePads,NameIt(*motifPosition));
793 AliDebug(1,Form("localContour:"));
794 // StdoutToAliDebug(1,contour->Print("full"));
795 // register the local contour
796 fLocalManuContours->Add(new TObjString(contour->GetName()),contour);
799 AliMUONPainterContour* globalContour = static_cast<AliMUONPainterContour*>(contour->Clone(name));
801 // once we have the local contour, convert it to global
803 TVector2 pos(motifPosition->Position());
805 if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 )
807 const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(detElemId,manuId);
808 pos -= slat->Position();
810 globalContour->Offset(pos);
811 TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
812 globalContour->Transform(*matrix);
814 if ( viewType.IsBackView() )
816 AliWarning("Got a back view : will rotate ! This has not been really tested. Please do so now !");
819 globalContour->Transform(rot);
822 return globalContour;
825 //_____________________________________________________________________________
826 AliMUONPainterContour*
827 AliMUONPainterContourMaker::GetContour(const char* name) const
829 /// Get contour by name
831 TObject* o = fContours->GetValue(name);
832 return static_cast<AliMUONPainterContour*>(o);
835 //_____________________________________________________________________________
837 AliMUONPainterContourMaker::HasContour(const char* name) const
839 /// Whether contour named "name" exists
840 TObject* o = fContours->GetValue(name);
845 //_____________________________________________________________________________
847 AliMUONPainterContourMaker::InsertSegment(TPolyLine& lines, TLine& l) const
849 /// Insert line into polyline, at the correct position
852 // AliDebug(2,Form("Trying to insert %7.3f,%7.3f -> %7.3f,%7.3f from "
853 // "(DE,manu,ch)=(%d,%d,%d) into",
854 // l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2(),
855 // AliMUONVDigit::DetElemId(l.GetUniqueID()),
856 // AliMUONVDigit::ManuId(l.GetUniqueID()),
857 // AliMUONVDigit::ManuChannel(l.GetUniqueID())));
859 if ( lines.Size()==0 )
861 // AliDebug(2,"Starting line");
863 lines.SetNextPoint(l.GetX1(),l.GetY1());
864 lines.SetNextPoint(l.GetX2(),l.GetY2());
868 Int_t i1 = FindPoint(lines,l.GetX1(),l.GetY1());
869 Int_t i2 = FindPoint(lines,l.GetX2(),l.GetY2());
871 if ( i1 < 0 && i2 < 0 )
873 // AliDebug(2,"Not yet");
877 if ( i1 >= 0 && i2 >= 0 )
881 lines.SetNextPoint(l.GetX1(),l.GetY1());
885 lines.SetNextPoint(l.GetX2(),l.GetY2());
889 AliError("Segment already there but does not correspond to ending the polyline !");
890 AliError(Form("Segment is %7.3f,%7.3f -> %7.3f,%7.3f and existing points are : ",
891 l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2()));
893 for ( Int_t i = 0; i < lines.Size(); ++i )
895 AliError(Form("Point %2d X %7.3f Y %7.3f",i,lines.GetX()[i],lines.GetY()[i]));
898 // o->Print(); // to crash and throw gdb...
903 Double_t x = (i1>=0) ? l.GetX2() : l.GetX1();
904 Double_t y = (i1>=0) ? l.GetY2() : l.GetY1();
906 Int_t iref = ( i1 >= 0 ? i1 : i2 ) ;
908 Bool_t firstPoint = ( iref == 0 );
912 // must insert segment before
913 lines.SetPolyLine(lines.Size()+1);
914 // AliDebug(2,Form("Inserting %7.3f,%7.3f",x,y));
915 for ( Int_t i = lines.Size()-1; i > 0; --i )
917 lines.SetPoint(i,lines.GetX()[i-1],lines.GetY()[i-1]);
919 lines.SetPoint(0,x,y);
923 // AliDebug(2,Form("Appending %7.3f,%7.3f",x,y));
924 lines.SetNextPoint(x,y);
930 //_____________________________________________________________________________
932 AliMUONPainterContourMaker::IsEqual(Double_t x, Double_t y) const
936 if ( TMath::Abs(x-y) < AliMpConstants::LengthTolerance() ) return kTRUE;
940 //_____________________________________________________________________________
942 AliMUONPainterContourMaker::IsEqual(const TLine& line1,
943 const TLine& line2) const
945 /// Whether line1 == line2
948 IsEqual(line1.GetX1(),line2.GetX1()) &&
949 IsEqual(line1.GetY1(),line2.GetY1()) &&
950 IsEqual(line1.GetX2(),line2.GetX2()) &&
951 IsEqual(line1.GetY2(),line2.GetY2());
954 IsEqual(line1.GetX1(),line2.GetX2()) &&
955 IsEqual(line1.GetY1(),line2.GetY2()) &&
956 IsEqual(line1.GetX2(),line2.GetX1()) &&
957 IsEqual(line1.GetY2(),line2.GetY1());
959 return (check1 || check2);
962 //_____________________________________________________________________________
964 AliMUONPainterContourMaker::Slope(const TLine& line) const
966 /// Get the slope of line
968 Double_t x = TMath::Abs(line.GetX2() - line.GetX1());
970 if ( x < AliMpConstants::LengthTolerance() ) return FLT_MAX;
972 return TMath::Abs(line.GetY2() - line.GetY1())/x;
975 //_____________________________________________________________________________
977 AliMUONPainterContourMaker::IsPoint(const TLine& line) const
979 /// Whether the line is a point (sic ;-) )
981 IsEqual(line.GetX1(),line.GetX2()) &&
982 IsEqual(line.GetY1(),line.GetY2());
985 //_____________________________________________________________________________
987 AliMUONPainterContourMaker::Shift(const TLine& line, Double_t x, Double_t y) const
989 /// Shift the line by a given offset
991 return TLine(line.GetX1()-x,line.GetY1()-y,line.GetX2()-x,line.GetY2()-y);
994 //_____________________________________________________________________________
996 AliMUONPainterContourMaker::SameDirection(const TLine& line1, const TLine& line2) const
998 /// Whether both lines have the same direction.
1000 TLine l1 = Shift(line1,line1.GetX1(),line1.GetY1());
1001 TLine l2 = Shift(line2,line2.GetX1(),line2.GetY1());
1003 Double_t v = l1.GetX2()*l2.GetX2() + l1.GetY2()*l2.GetY2();
1008 //_____________________________________________________________________________
1010 AliMUONPainterContourMaker::Swap(TLine& line) const
1012 /// Swap both points of the line
1014 Double_t x = line.GetX1();
1015 Double_t y = line.GetY1();
1017 line.SetX1(line.GetX2());
1018 line.SetY1(line.GetY2());
1023 //_____________________________________________________________________________
1025 AliMUONPainterContourMaker::IsInRange(Double_t x, Double_t a, Double_t b,
1026 Bool_t strict) const
1028 /// Whether w is in [a,b] (if strict=kFALSE) or in ]a,b[ (if strict=kTRUE)
1041 rv = ( x > a && x < b );
1045 rv = ( x >= a && x <= b);
1048 AliDebug(4,Form("x = %7.3f a = %7.3f b = %7.3f strict = %d IsInRange = %d",x,a,b,strict,rv));
1053 //_____________________________________________________________________________
1055 AliMUONPainterContourMaker::IsInLine(const TLine& line,
1058 Bool_t strict) const
1060 /// Check whether point (x,y) is belonging to the line segment
1061 /// by computing the distance point to line
1062 /// line1 must not be a single point.
1063 /// Returns the number of *coordinates* that matches, for a point
1064 /// that lies on line (if point is not on the line, returns 0 always).
1065 /// For instance, if (x,y) is on the line (and strict=kFALSE),
1066 /// it will return 1 if x *or* y corresponds to line.GetX1() or X2 or Y1 or Y2,
1067 /// and 2 if the pair (x,y) corresponds to one of the line points.
1069 Double_t x1 = line.GetX1();
1070 Double_t x2 = line.GetX2();
1071 Double_t y1 = line.GetY1();
1072 Double_t y2 = line.GetY2();
1074 Double_t distance = TMath::Abs( (x2-x1)*(y1-y) - (x1-x)*(y2-y1) );
1076 distance /= TMath::Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
1078 Bool_t online = ( distance < AliMpConstants::LengthTolerance() ) ;
1084 // point is on the line,
1085 // check in addition that it's within the segment
1087 rv = IsInRange(x,x1,x2,strict) + IsInRange(y,y1,y2,strict);
1094 AliDebug(4,Form("Point (%7.3f,%7.3f) isinline=%d in line %s",
1095 x,y,rv,LineAsString(line).Data()));
1100 //_____________________________________________________________________________
1102 AliMUONPainterContourMaker::IsInside(const TLine& line1,
1104 Bool_t useEndPoints) const
1106 /// Check whether one or both points of line2 are within line1.
1107 /// Both line1 and line2 must have the same slope
1108 /// and the same direction
1110 if (!IsEqual(Slope(line1),Slope(line2))) return 0;
1114 if (!SameDirection(line1,line2))
1120 IsInLine(line1,l2.GetX1(),l2.GetY1(),!useEndPoints) +
1121 IsInLine(line1,l2.GetX2(),l2.GetY2(),!useEndPoints);
1128 //_____________________________________________________________________________
1130 AliMUONPainterContourMaker::IsInside(const TObjArray& segments,
1131 const TLine& line) const
1133 /// Whether the segment (line) is contained inside the contour defined
1134 /// by all the segments (i.e. is it on the boundary or not)
1135 /// Basic (and dirty) implementation only working with horizontal and vertical lines.
1136 /// I know there must be a better way to do it, but it took me way too long
1137 /// to get this stuff working, so I'm giving up on the optimisation/cleaning,
1138 /// at least for now...
1139 /// If you'd like to clean this (while keeping it working in all cases), be
1140 /// my guest and do it ;-) )
1142 Int_t p1 = CountPoint(segments,line.GetX1(),line.GetY1());
1143 Int_t p2 = CountPoint(segments,line.GetX2(),line.GetY2());
1145 Bool_t triplet = ( p1 >= 3 || p2 >= 3 );
1147 AliDebug(4,Form("IsInside(segments,%s) triplet=%d",
1148 LineAsString(line).Data(),triplet));
1150 if (!triplet) return kFALSE;
1152 Bool_t top(kFALSE), bottom(kFALSE), left(kFALSE), right(kFALSE);
1154 Bool_t vertical(IsVertical(line));
1155 Bool_t horizontal(IsHorizontal(line));
1157 if (!vertical && !horizontal )
1159 AliFatal("Only working with horizontal and vertical lines");
1162 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1164 TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
1166 if ( IsEqual(*l,line) ) continue;
1168 if ( vertical && IsVertical(*l) )
1170 TLine tmpLine(l->GetX1(),line.GetY1(),
1171 l->GetX1(),line.GetY2());
1173 AliDebug(4,Form("i=%2d VV\nIsInside(l=%s,%s)=%d\nIsInside(%s,l=%s)=%d",
1175 LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
1176 IsInside(*l,tmpLine,kTRUE),
1177 LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
1178 IsInside(tmpLine,*l,kTRUE)));
1180 if ( IsInside(*l,tmpLine,kTRUE) == 4 || IsInside(tmpLine,*l,kTRUE) == 4 )
1182 if ( l->GetX1() > line.GetX1() )
1193 if ( vertical && IsHorizontal(*l) )
1195 if ( !IsEqual(l->GetY1(),line.GetX1()) &&
1196 !IsEqual(l->GetY1(),line.GetY2()) &&
1197 IsInLine(*l,line.GetX1(),l->GetY1(),kFALSE)==2 )
1199 if ( line.GetY2() < l->GetY1() )
1203 else if ( line.GetY2() > l->GetY1() )
1210 if ( horizontal && IsHorizontal(*l) )
1212 TLine tmpLine(line.GetX1(),l->GetY1(),
1213 line.GetX2(),l->GetY1());
1215 AliDebug(4,Form("i=%2d HH\nIsInside(%s,%s)=%d\nIsInside(%s,%s)=%d",
1217 LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
1218 IsInside(*l,tmpLine),
1219 LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
1220 IsInside(tmpLine,*l)));
1222 if ( IsInside(*l,tmpLine) == 4 || IsInside(tmpLine,*l) == 4 )
1224 if ( l->GetY1() > line.GetY1() )
1235 if ( horizontal && IsVertical(*l) )
1237 if ( !IsEqual(l->GetX1(),line.GetX1()) &&
1238 !IsEqual(l->GetX1(),line.GetX2()) &&
1239 IsInLine(*l,l->GetX1(),line.GetY1(),kFALSE)==2 )
1241 if ( line.GetX2() < l->GetX1() )
1245 else if ( line.GetX2() > l->GetX1() )
1256 AliDebug(3,Form("%s %s R %d L %d T %d B% d IsInside %d",
1260 LineAsString(line,kFALSE).Data(),right,left,top,bottom,rv));
1264 rv = (right && left) && ( top || bottom );
1269 rv = (top && bottom) && ( right || left );
1275 //_____________________________________________________________________________
1277 AliMUONPainterContourMaker::IsHorizontal(const TLine& line) const
1279 /// whether line is horizontal
1281 static Double_t l2 = AliMpConstants::LengthTolerance()*AliMpConstants::LengthTolerance();
1283 return ( Slope(line) < l2 );
1286 //_____________________________________________________________________________
1288 AliMUONPainterContourMaker::IsVertical(const TLine& line) const
1290 /// whether line is vertical
1292 return ( TMath::Abs(Slope(line)) == FLT_MAX );
1295 //_____________________________________________________________________________
1297 AliMUONPainterContourMaker::Overlap(const TLine& line1,
1298 const TLine& line2) const
1300 /// Whether line1 and line2 overlap
1304 if ( IsEqual(line1,line2) )
1306 // First things first. If both lines are the same one,
1307 // they for sure overlap ;-)
1312 rv = IsInside(line1,line2) + IsInside(line2,line1);
1315 AliDebug(3,Form("%s and %s : overlap=%d",
1316 LineAsString(line1).Data(),
1317 LineAsString(line2).Data(),
1323 //_____________________________________________________________________________
1325 AliMUONPainterContourMaker::IsLineClosed(const TPolyLine& line) const
1327 /// check if polyline is already closed (i.e. last point = first point)
1329 Double_t* x = line.GetX();
1330 Double_t* y = line.GetY();
1332 if ( IsEqual(x[line.GetLastPoint()],x[0]) &&
1333 IsEqual(y[line.GetLastPoint()],y[0]) )
1343 //_____________________________________________________________________________
1345 AliMUONPainterContourMaker::Local2Global(Int_t detElemId,
1346 Double_t xl, Double_t yl, Double_t zl,
1347 Double_t& xg, Double_t& yg, Double_t& zg) const
1349 /// Convert local coordinates to global ones
1350 TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
1351 Double_t pl[3] = { xl, yl, zl };
1352 Double_t pg[3] = { 0., 0., 0. };
1353 matrix->LocalToMaster(pl, pg);
1359 //_____________________________________________________________________________
1361 AliMUONPainterContourMaker::Print(Option_t* opt) const
1365 cout << "Local Contours" << endl;
1367 TIter next(fLocalManuContours);
1370 while ( ( key = static_cast<TObjString*>(next()) ) )
1372 cout << key->String().Data() << endl;
1373 AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fLocalManuContours->GetValue(key));
1374 contour->Print(opt);
1377 cout << "Global Contours" << endl;
1379 TIter nextC(fContours);
1381 while ( ( key = static_cast<TObjString*>(nextC()) ) )
1383 AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fContours->GetValue(key));
1384 contour->Print(opt);
1388 //_____________________________________________________________________________
1390 AliMUONPainterContourMaker::CountPoint(const TObjArray& segments,
1391 Double_t x, Double_t y) const
1393 /// Count the number of times the point (x,y) appears in the segment array
1397 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1399 TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
1401 if ( IsEqual(x,line->GetX1()) &&
1402 IsEqual(y,line->GetY1()) )
1407 if ( IsEqual(x,line->GetX2()) &&
1408 IsEqual(y,line->GetY2()) )
1417 //_____________________________________________________________________________
1419 AliMUONPainterContourMaker::SanityCheck(const TObjArray& contours,
1420 const TObjArray& segments, Bool_t check) const
1426 // cross-check that we have no more complete duplicates
1427 // and that we have no orphan point
1429 Double_t xmin(FLT_MAX), xmax(-FLT_MAX);
1430 Double_t ymin(FLT_MAX), ymax(-FLT_MAX);
1432 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1434 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
1436 if (!IsHorizontal(*li) && !IsVertical(*li))
1438 AliError("Got an oblique line !");
1442 xmin = TMath::Min(xmin,li->GetX1());
1443 xmin = TMath::Min(xmin,li->GetX2());
1445 xmax = TMath::Max(xmax,li->GetX1());
1446 xmax = TMath::Max(xmax,li->GetX2());
1448 ymin = TMath::Min(ymin,li->GetY1());
1449 ymin = TMath::Min(ymin,li->GetY2());
1451 ymax = TMath::Max(ymax,li->GetY1());
1452 ymax = TMath::Max(ymax,li->GetY2());
1456 AliDebug(1,Form("xmin=%7.3f ymin=%7.3f xmax=%7.3f ymax=%7.3f",
1457 xmin,ymin,xmax,ymax));
1459 for ( Int_t i = 0; i <= segments.GetLast(); ++i )
1461 TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
1465 for ( Int_t j = 0; j <= segments.GetLast(); ++j )
1467 TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
1469 if ( i != j && IsEqual(*li,*lj) )
1482 Double_t x = (li->GetX1()+li->GetX2())/2.0;
1483 Double_t y = (li->GetY1()+li->GetY2())/2.0;
1485 if ( ShouldBeRemoved(contours,x,y) ) rv = 1;
1487 AliDebug(1,Form("Line %4d %7.3f,%7.3f -> %7.3f,%7.3f [ %d ]",
1489 li->GetX1(),li->GetY1(),
1490 li->GetX2(),li->GetY2(),
1497 //_____________________________________________________________________________
1499 AliMUONPainterContourMaker::Simplify(const TPolyLine& lines) const
1501 /// try to simplify the polyline, by minimizing the number of points
1503 if ( lines.Size() < 3 )
1505 AliError("Cannot simplify lines with less that 3 points !");
1509 AliCodeTimerAuto("")
1511 // cout << "Before simplify" << endl;
1513 // for ( Int_t i = 0; i < lines.Size(); ++i )
1515 // cout << Form("Point %3d %7.3f %7.3f",i,lines.GetX()[i],lines.GetY()[i]) << endl;
1518 TPolyLine* l = new TPolyLine;
1520 Double_t* x = lines.GetX();
1521 Double_t* y = lines.GetY();
1523 l->SetNextPoint(x[0],y[0]);
1525 Bool_t verticalCurrent = IsEqual(x[1],x[0]);
1526 Bool_t horizontalCurrent = IsEqual(y[1],y[0]);
1530 while ( i < lines.Size() )
1532 Bool_t vertical = IsEqual(x[i],x[i-1]);
1533 Bool_t horizontal = IsEqual(y[i],y[i-1]);
1535 // cout << Form("i %3d %7.3f %7.3f vert %d horiz %d (current vert %d horiz %d)",
1536 // i,x[i],y[i],vertical,horizontal,verticalCurrent,horizontalCurrent)
1539 if ( ( vertical != verticalCurrent ) ||
1540 ( horizontal != horizontalCurrent ) )
1542 // cout << Form("Changing direction : adding point %7.3f %7.3f",x[i-1],y[i-1]) << endl;
1543 l->SetNextPoint(x[i-1],y[i-1]);
1544 verticalCurrent = vertical;
1545 horizontalCurrent = horizontal;
1550 l->SetNextPoint(l->GetX()[0],l->GetY()[0]);
1552 // cout << "After simplify" << endl;
1554 // for ( Int_t i = 0; i < l->Size(); ++i )
1556 // cout << Form("Point %3d %7.3f %7.3f",i,l->GetX()[i],l->GetY()[i]) << endl;
1562 //_____________________________________________________________________________
1564 AliMUONPainterContourMaker::Size() const
1566 /// Number of contours we have already
1568 return fContours->GetSize();