--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+///\class AliMUONContour
+///
+/// A contour is a set of (closed and counter-clockwise-oriented) polygons
+///
+/// \author Laurent Aphecetche, Subatech
+
+#include "AliMUONContour.h"
+
+#include "AliLog.h"
+#include "AliMUONPolygon.h"
+#include "AliMpArea.h"
+#include <Riostream.h>
+#include <TGeoMatrix.h>
+#include <TMath.h>
+#include <TObjArray.h>
+#include <TPolyLine.h>
+#include <TString.h>
+#include <TVector2.h>
+#include <float.h>
+
+///\cond CLASSIMP
+ClassImp(AliMUONContour)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONContour::AliMUONContour(const char* name) : TNamed(name,""),
+fPolygons(new TObjArray),
+fXmin(FLT_MAX),
+fXmax(-FLT_MAX),
+fYmin(FLT_MAX),
+fYmax(-FLT_MAX),
+fNofVertices(0)
+{
+ /// ctor
+ fPolygons->SetOwner(kTRUE);
+}
+
+//_____________________________________________________________________________
+AliMUONContour::AliMUONContour(const char* name, const AliMpArea& area)
+: TNamed(name,""),
+fPolygons(new TObjArray),
+fXmin(area.LeftBorder()),
+fXmax(area.RightBorder()),
+fYmin(area.DownBorder()),
+fYmax(area.UpBorder()),
+fNofVertices(0)
+{
+ /// ctor
+ fPolygons->SetOwner(kTRUE);
+
+ AliMUONPolygon* pol = new AliMUONPolygon(area.GetPositionX(),
+ area.GetPositionY(),
+ area.GetDimensionX(),
+ area.GetDimensionY());
+
+ fPolygons->AddLast(pol);
+
+ fNofVertices = pol->NumberOfVertices();
+}
+
+//______________________________________________________________________________
+AliMUONContour::AliMUONContour(const AliMUONContour& rhs)
+: TNamed(rhs),
+fPolygons(0x0),
+fXmin(FLT_MAX),
+fXmax(-FLT_MAX),
+fYmin(FLT_MAX),
+fYmax(-FLT_MAX),
+fNofVertices(0)
+{
+ /// Copy constructor.
+
+ ((AliMUONContour&)rhs).Copy(*this);
+}
+
+//______________________________________________________________________________
+AliMUONContour&
+AliMUONContour::operator=(const AliMUONContour& rhs)
+{
+ /// Assignment operator
+ if ( this != &rhs )
+ {
+ delete fPolygons;
+ fPolygons = 0;
+ rhs.Copy(*this);
+ }
+ return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONContour::~AliMUONContour()
+{
+ /// dtor
+ delete fPolygons;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContour::Add(const AliMUONPolygon& polygon)
+{
+ /// Add points from the polygon
+
+ for ( Int_t i = 0; i < polygon.NumberOfVertices(); ++i )
+ {
+ Double_t x = polygon.X(i);
+ Double_t y = polygon.Y(i);
+ fXmin = TMath::Min(fXmin,x);
+ fXmax = TMath::Max(fXmax,x);
+ fYmin = TMath::Min(fYmin,y);
+ fYmax = TMath::Max(fYmax,y);
+ }
+
+ fPolygons->AddLast(new AliMUONPolygon(polygon));
+
+ fNofVertices += polygon.NumberOfVertices();
+}
+
+//_____________________________________________________________________________
+AliMpArea
+AliMUONContour::Area() const
+{
+ /// Return the area covered by this contour (i.e. the area that
+ /// contains all the poylines)
+
+ return AliMpArea( (fXmax+fXmin)/2.0, (fYmax+fYmin)/2.0 ,
+ TMath::Abs(fXmax-fXmin)/2.0, TMath::Abs(fYmax-fYmin)/2.0 );
+}
+
+//______________________________________________________________________________
+void
+AliMUONContour::AssertOrientation(Bool_t autoCorrect)
+{
+ /// Insure that all our polygons are counter-clockwise oriented
+ /// If autoCorrect==kTRUE, we change the orientation if it is not
+ /// already correct.
+ /// If autoCorrect==kFALSE and the orientation is not correct, we
+ /// just issue an error message.
+
+ for ( Int_t i = 0; i <= fPolygons->GetLast(); ++i )
+ {
+ AliMUONPolygon* pol = static_cast<AliMUONPolygon*>(fPolygons->UncheckedAt(i));
+ if ( !pol->IsCounterClockwiseOriented() )
+ {
+ if ( autoCorrect )
+ {
+ pol->ReverseOrientation();
+ }
+ else
+ {
+ AliError("Got a polygon oriented the wrong way");
+ StdoutToAliError(Print(););
+ return;
+ }
+ }
+ }
+}
+
+//______________________________________________________________________________
+void AliMUONContour::Copy(TObject& obj) const
+{
+ /// Copy this to obj
+
+ AliMUONContour& rhs = static_cast<AliMUONContour&>(obj);
+ TNamed::Copy(rhs);
+ delete rhs.fPolygons;
+ rhs.fPolygons = new TObjArray(fPolygons->GetLast()+1);
+ rhs.fPolygons->SetOwner(kTRUE);
+ TIter next(fPolygons);
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ rhs.fPolygons->AddLast(pol->Clone());
+ }
+ rhs.fXmin = fXmin;
+ rhs.fXmax = fXmax;
+ rhs.fYmin = fYmin;
+ rhs.fYmax = fYmax;
+ rhs.fNofVertices = fNofVertices;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONContour::IsInside(Double_t x, Double_t y) const
+{
+ /// Whether the point (x,y) is inside one of ours polylines
+
+ if ( x >= fXmin && x <= fXmax && y >= fYmin && y <= fYmax )
+ {
+ TIter next(fPolygons);
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ if ( pol->Contains(x,y) )
+ {
+ return kTRUE;
+ }
+ }
+ }
+
+ return kFALSE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContour::Offset(Double_t x, Double_t y)
+{
+ /// Offset all lines by a given offset
+
+ TIter next(fPolygons);
+ AliMUONPolygon* pol;
+
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ for ( Int_t i = 0; i < pol->NumberOfVertices(); ++i )
+ {
+ pol->SetVertex(i,pol->X(i)+x,pol->Y(i)+y);
+ }
+ }
+
+ fXmin += x;
+ fXmax += x;
+ fYmin += y;
+ fYmax += y;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContour::Print(Option_t* opt) const
+{
+ /// Printout
+
+ cout << GetName() << " NofVertices=" << NumberOfVertices() << " Ngroups=" << fPolygons->GetLast()+1 << endl;
+ TString sopt(opt);
+ sopt.ToUpper();
+ if (sopt.Contains("B"))
+ {
+ Area().Print("B");
+ }
+
+ TIter next(fPolygons);
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ pol->Print(opt);
+ }
+
+
+ cout << endl;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContour::Transform(const TGeoHMatrix& matrix)
+{
+ /// Transform the polygons using the given transformation
+
+ TIter next(fPolygons);
+ AliMUONPolygon* pol;
+
+ fXmin = fYmin = FLT_MAX;
+ fXmax = fYmax = -FLT_MAX;
+
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ for ( Int_t i = 0; i < pol->NumberOfVertices(); ++i )
+ {
+ Double_t pl[3] = { pol->X(i), pol->Y(i), 0 };
+ Double_t pg[3] = { 0., 0., 0. };
+ matrix.LocalToMaster(pl, pg);
+ pol->SetVertex(i,pg[0],pg[1]);
+ fXmin = TMath::Min(fXmin,pg[0]);
+ fYmin = TMath::Min(fYmin,pg[1]);
+ fXmax = TMath::Max(fXmax,pg[0]);
+ fYmax = TMath::Max(fYmax,pg[1]);
+ }
+ }
+
+ AssertOrientation(kTRUE);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONContour::IsValid() const
+{
+ /// A valid contour is one with a valid area and at least 3 vertices.
+ return fNofVertices >= 3 && Area().IsValid();
+}
--- /dev/null
+#ifndef ALIMUONCONTOUR_H
+#define ALIMUONCONTOUR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONContour
+/// \brief 2D contour
+///
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TNamed
+# include "TNamed.h"
+#endif
+
+#ifndef ALI_MP_AREA_H
+# include "AliMpArea.h"
+#endif
+
+class AliMUONPolygon;
+class TGeoHMatrix;
+class TObjArray;
+
+class AliMUONContour : public TNamed
+{
+public:
+ AliMUONContour(const char* name="");
+ AliMUONContour(const char* name, const AliMpArea& area);
+ AliMUONContour(const AliMUONContour& rhs);
+ AliMUONContour& operator=(const AliMUONContour& rhs);
+ virtual ~AliMUONContour();
+
+ AliMpArea Area() const;
+
+ /// Get a full copy of this object.
+ virtual TObject* Clone(const char* /*newname*/="") const { return new AliMUONContour(*this); }
+
+ /// Add an offset to all points
+ void Offset(Double_t x, Double_t y);
+
+ /// Apply a global transformation to all points
+ void Transform(const TGeoHMatrix& matrix);
+
+ void Add(const AliMUONPolygon& polygon);
+
+ virtual void Copy(TObject& obj) const;
+
+ Bool_t IsInside(Double_t x, Double_t y) const;
+
+ virtual void Print(Option_t* opt="") const;
+
+ /// Get the number of vertices of this contour
+ Int_t NumberOfVertices() const { return fNofVertices; }
+
+ Bool_t IsValid() const;
+
+ /// Get the list of polygons we have
+ const TObjArray* Polygons() const { return fPolygons; }
+
+ void AssertOrientation(Bool_t autoCorrect=kFALSE);
+
+private:
+ TObjArray* fPolygons; ///< the polygons that this contour is made of
+ Double_t fXmin; ///< min x-value
+ Double_t fXmax; ///< max x-value
+ Double_t fYmin; ///< min y-value
+ Double_t fYmax; ///< max y-value
+ Int_t fNofVertices; ///< total number of vertices
+
+ ClassDef(AliMUONContour,1) // 2D-contour of an object
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+///
+/// Maker/merger of contours. Can create contour from a set polygons or
+/// merger a set of contours into a single one.
+///
+/// This is based on (one of the) algorithm found in
+/// Diane L. Souvaine and Iliana Bjorling-Sachs,
+/// Proceedings of the IEEE, Vol. 80, No. 9, September 1992, p. 1449
+///
+/// Note that besides the AliMUON prefix, nothing is really MUON specific
+/// in this class...
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+#include "AliMUONContourMaker.h"
+
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include "AliMUONContour.h"
+#include "AliMUONPointWithRef.h"
+#include "AliMUONPolygon.h"
+#include "AliMUONSegment.h"
+#include "AliMUONSegmentTree.h"
+#include "Riostream.h"
+#include "TArrayD.h"
+#include "TMath.h"
+#include <cassert>
+
+/// \cond CLASSIMP
+ClassImp(AliMUONContourMaker)
+/// \endcond
+
+namespace
+{
+ void PrintSegments(const TObjArray& array)
+ {
+ TIter next(&array);
+ AliMUONSegment* s;
+ Int_t i(0);
+ while ( ( s = static_cast<AliMUONSegment*>(next()) ) )
+ {
+ cout << Form("i=%d %s",i,s->AsString()) << endl;
+ ++i;
+ }
+ }
+}
+
+//_____________________________________________________________________________
+AliMUONContourMaker::AliMUONContourMaker()
+{
+}
+
+//_____________________________________________________________________________
+AliMUONContourMaker::~AliMUONContourMaker()
+{
+}
+
+//_____________________________________________________________________________
+AliMUONContour*
+AliMUONContourMaker::CreateContour(const TObjArray& polygons, const char* name) const
+{
+ /// Create the contour of the polygon array
+ /// and get back the intermediate verticals and horizontal segments
+ /// both arrays are arrays of AliMUONSegment objects.
+
+ AliCodeTimerAuto("");
+
+ if ( polygons.IsEmpty() ) return 0x0; // protection against user error...
+
+ // Sanity check : insure that all polygons are oriented counter-clockwise
+ TIter next(&polygons);
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ if ( !pol->IsCounterClockwiseOriented() )
+ {
+ AliError(Form("Got a clockwise oriented polygon in CreateContour(%s). That's not OK !",name));
+ StdoutToAliError(polygons.Print());
+ return 0x0;
+ }
+ }
+
+ AliMUONContour* contour(0x0);
+
+ if ( polygons.GetLast() == 0 )
+ {
+ AliCodeTimerAuto("Trivial case");
+ contour = new AliMUONContour(name);
+ pol = static_cast<const AliMUONPolygon*>(polygons.First());
+ contour->Add(*pol);
+ contour->AssertOrientation();
+ return contour;
+ }
+
+ TObjArray polygonVerticalEdges; // arrray of AliMUONSegment objects
+ polygonVerticalEdges.SetOwner(kTRUE);
+ // get vertical edges of input polygons
+ GetVerticalEdges(polygons,polygonVerticalEdges);
+
+ // sort them in ascending x order
+ // if same x, insure that left edges are before right edges
+ // within same x, order by increasing bottommost y (see AliMUONSegment::Compare method)
+ polygonVerticalEdges.Sort();
+
+ if ( polygonVerticalEdges.GetLast()+1 < 2 )
+ {
+ AliError(Form("Got too few edges here for createContour %s",name));
+ polygons.Print();
+ TObject* o(0x0);
+ o->Print();
+ }
+
+ // Find the vertical edges of the merged contour. This is the meat of the algorithm...
+ TObjArray contourVerticalEdges;
+ contourVerticalEdges.SetOwner(kTRUE);
+ Sweep(polygonVerticalEdges,contourVerticalEdges);
+
+ TObjArray horizontals;
+ horizontals.SetOwner(kTRUE);
+ VerticalToHorizontal(contourVerticalEdges,horizontals);
+
+ contour = FinalizeContour(contourVerticalEdges,horizontals);
+
+ if ( contour && name ) contour->SetName(name);
+
+ return contour;
+}
+
+//_____________________________________________________________________________
+AliMUONContour*
+AliMUONContourMaker::FinalizeContour(const TObjArray& verticals,
+ const TObjArray& horizontals) const
+{
+ /// For a list of vertical and horizontal edges, we build the final
+ /// contour object.
+
+ AliCodeTimerAuto("");
+
+ TObjArray all; // array of AliMUONSegment
+ TObjArray inorder; // array of AliMUONSegment
+
+ all.SetOwner(kFALSE);
+ inorder.SetOwner(kFALSE);
+
+ for ( Int_t i = 0; i <= verticals.GetLast(); ++i )
+ {
+ all.Add(verticals.UncheckedAt(i));
+ all.Add(horizontals.UncheckedAt(i));
+ }
+
+ Int_t i(0);
+
+ AliMUONContour* contour = new AliMUONContour;
+
+ int total(0);
+
+ while ( !all.IsEmpty() )
+ {
+ total++;
+
+ if ( total > 1000 )
+ {
+ AliError("Total 1000 reached !!!!");
+ return 0x0;
+ }
+
+ AliMUONSegment* si = static_cast<AliMUONSegment*>(all.UncheckedAt(i));
+ inorder.Add(si);
+ const AliMUONSegment* all0 = static_cast<const AliMUONSegment*>(all.First());
+ if ( i != 0 && AliMUONSegment::AreEqual(si->EndX(),all0->StartX()) && AliMUONSegment::AreEqual(si->EndY(),all0->StartY()) )
+ {
+ Int_t n(-1);
+
+ AliMUONPolygon polygon(inorder.GetLast()+2);
+
+ // we got a cycle. Add it to the contour
+ for ( Int_t j = 0; j <= inorder.GetLast(); ++j )
+ {
+ AliMUONSegment* s = static_cast<AliMUONSegment*>(inorder.UncheckedAt(j));
+ polygon.SetVertex(++n,s->StartX(),s->StartY());
+ all.Remove(s);
+ }
+
+ all.Compress();
+
+ polygon.Close();
+
+ contour->Add(polygon);
+
+ if ( ! all.IsEmpty() )
+ {
+ i = 0;
+ inorder.Clear();
+ }
+ continue;
+ }
+
+ for ( Int_t j = 0; j <= all.GetLast(); ++j)
+ {
+ if ( j != i )
+ {
+ const AliMUONSegment* sj = static_cast<const AliMUONSegment*>(all.UncheckedAt(j));
+ if ( AliMUONSegment::AreEqual(si->EndX(),sj->StartX()) && AliMUONSegment::AreEqual(si->EndY(),sj->StartY()))
+ {
+ i = j;
+ break;
+ }
+ }
+ }
+ }
+
+ contour->AssertOrientation(kTRUE);
+ return contour;
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONContourMaker::GetVerticalEdges(const TObjArray& polygons, TObjArray& polygonVerticalEdges) const
+{
+ /// From an array of polygons, extract the list of vertical edges.
+ /// Output array polygonVerticalEdges should be empty before calling.
+
+ AliCodeTimerAuto("");
+
+ for ( Int_t i = 0; i <= polygons.GetLast(); ++i )
+ {
+ const AliMUONPolygon* g = static_cast<const AliMUONPolygon*>(polygons.UncheckedAt(i));
+ for ( Int_t j = 0; j < g->NumberOfVertices()-1; ++j )
+ {
+ if ( AliMUONSegment::AreEqual(g->X(j),g->X(j+1)) ) // segment is vertical
+ {
+ polygonVerticalEdges.Add(new AliMUONSegment(g->X(j),g->Y(j),g->X(j+1),g->Y(j+1)));
+ }
+ }
+ }
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONContourMaker::GetYPositions(const TObjArray& polygonVerticalEdges,
+ TArrayD& yPositions) const
+{
+ /// Fill the array yPositions with the different y positions found in
+ /// polygonVerticalEdges
+
+ AliCodeTimerAuto("");
+
+ Double_t* y = new Double_t[polygonVerticalEdges.GetSize()*2];
+ Int_t n(0);
+
+ for ( Int_t i = 0; i < polygonVerticalEdges.GetLast(); ++i )
+ {
+ AliMUONSegment* s = static_cast<AliMUONSegment*>(polygonVerticalEdges.UncheckedAt(i));
+ y[n] = s->StartY();
+ y[n+1] = s->EndY();
+ n += 2;
+ }
+ Int_t* ix = new Int_t[n+1];
+
+ TMath::Sort(n,y,ix,kFALSE);
+
+ yPositions.Set(n+1);
+
+ Int_t u(0);
+ Double_t x(FLT_MAX);
+
+ for ( Int_t i = 0; i < n; ++i )
+ {
+ if ( y[ix[i]] != x )
+ {
+ yPositions[u] = y[ix[i]];
+ x = y[ix[i]];
+ ++u;
+ }
+ }
+
+ yPositions.Set(u);
+
+ delete[] ix;
+ delete[] y;
+
+}
+
+//_____________________________________________________________________________
+AliMUONContour*
+AliMUONContourMaker::MergeContour(const TObjArray& contours, const char* name) const
+{
+ /// Merge all the polygons of all contours into a single contour
+
+ AliCodeTimerAuto("");
+
+ TObjArray polygons;
+ polygons.SetOwner(kTRUE);
+
+ TIter next(&contours);
+ AliMUONContour* contour;
+ while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
+ {
+ const TObjArray* contourPolygons = contour->Polygons();
+ TIter nextPol(contourPolygons);
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(nextPol()) ) )
+ {
+ polygons.Add(new AliMUONPolygon(*pol));
+ }
+ }
+
+ if ( polygons.IsEmpty() ) return 0x0;
+
+ contour = CreateContour(polygons,name);
+
+ return contour;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMaker::SortPoints(const TObjArray& polygonVerticalEdges,
+ TObjArray& sortedPoints) const
+{
+ /// Sort the point of the vertical edges in ascending order, first on ordinate,
+ /// then on abcissa, and put them in output vector sortedPoints.
+ /// Output array sortedPoints should be empty before calling this method.
+
+ AliCodeTimerAuto("");
+
+ for ( Int_t i = 0; i <= polygonVerticalEdges.GetLast(); ++i )
+ {
+ const AliMUONSegment* e = static_cast<const AliMUONSegment*>(polygonVerticalEdges.UncheckedAt(i));
+ sortedPoints.Add(new AliMUONPointWithRef(e->StartX(),e->StartY(),i));
+ sortedPoints.Add(new AliMUONPointWithRef(e->EndX(),e->EndY(),i));
+ // note that we keep track of the original edge, which is used
+ // later on to deduce orientation of horizontal edges.
+ }
+
+ sortedPoints.Sort();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMaker::Sweep(const TObjArray& polygonVerticalEdges,
+ TObjArray& contourVerticalEdges) const
+{
+ /// This is the meat of the algorithm of the contour merging...
+
+ AliCodeTimerAuto("");
+
+ TArrayD yPositions;
+ GetYPositions(polygonVerticalEdges,yPositions);
+
+ AliMUONSegmentTree segmentTree(yPositions);
+
+ for ( Int_t i = 0; i <= polygonVerticalEdges.GetLast(); ++i )
+ {
+ const AliMUONSegment* edge = static_cast<const AliMUONSegment*>(polygonVerticalEdges.UncheckedAt(i));
+
+ assert(edge!=0x0);
+
+ if ( edge->IsLeftEdge() )
+ {
+ segmentTree.Contribution(edge->Bottom(),edge->Top());
+ segmentTree.InsertInterval(edge->Bottom(),edge->Top());
+ }
+ else
+ {
+ segmentTree.DeleteInterval(edge->Bottom(),edge->Top());
+ segmentTree.Contribution(edge->Bottom(),edge->Top());
+ }
+
+ AliMUONSegment e1(*edge);
+
+ if ( i < polygonVerticalEdges.GetLast() )
+ {
+ const AliMUONSegment* next = static_cast<const AliMUONSegment*>(polygonVerticalEdges.UncheckedAt(i+1));
+ e1 = *next;
+ }
+
+ if ( ( edge->IsLeftEdge() != e1.IsLeftEdge() ) ||
+ ( !AliMUONSegment::AreEqual(edge->StartX(),e1.StartX() ) ) ||
+ ( i == polygonVerticalEdges.GetLast() ) )
+ {
+ const TObjArray& stack = segmentTree.Stack();
+
+ double x = edge->StartX();
+
+ for ( Int_t j = 0; j <= stack.GetLast(); ++j )
+ {
+ AliMUONSegment* sj = static_cast<AliMUONSegment*>(stack.UncheckedAt(j));
+ AliMUONSegment* s = new AliMUONSegment(x,sj->StartY(),x,sj->EndY());
+
+ if (s->IsAPoint())
+ {
+ delete s;
+ continue;
+ }
+
+ if ( edge->IsLeftEdge() != s->IsLeftEdge() )
+ {
+ s->Set(x,sj->EndY(),x,sj->StartY());
+ }
+ contourVerticalEdges.Add(s);
+ }
+ segmentTree.ResetStack();
+ }
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMaker::VerticalToHorizontal(const TObjArray& polygonVerticalEdges,
+ TObjArray& horizontalEdges) const
+{
+ /// Deduce the set of horizontal edges from the vertical edges
+ /// Output array horizontalEdges should be empty before calling this method
+
+ AliCodeTimerAuto("");
+
+ TObjArray points; // array of AliMUONPointWithRef
+ points.SetOwner(kTRUE);
+
+ SortPoints(polygonVerticalEdges,points);
+
+ for ( Int_t k = 0; k < (points.GetLast()+1)/2; ++k )
+ {
+ const AliMUONPointWithRef* p1 = static_cast<AliMUONPointWithRef*>(points.UncheckedAt(k*2));
+ const AliMUONPointWithRef* p2 = static_cast<AliMUONPointWithRef*>(points.UncheckedAt(k*2+1));
+
+ const AliMUONSegment* refEdge = static_cast<const AliMUONSegment*>(polygonVerticalEdges.UncheckedAt(p1->Ref()));
+
+ // (p1,p2) is the horizontal edge.
+ // refEdge is used to deduce the orientation of (p1,p2)
+
+ if ( AliMUONSegment::AreEqual(p1->X(),refEdge->EndX()) && AliMUONSegment::AreEqual(p1->Y(),refEdge->EndY()) )
+// if ( AreEqual(p1,refEdge->End()) )
+ {
+ horizontalEdges.Add(new AliMUONSegment(p1->X(),p1->Y(),p2->X(),p2->Y()));
+ }
+ else
+ {
+ horizontalEdges.Add(new AliMUONSegment(p2->X(),p2->Y(),p1->X(),p1->Y()));
+ }
+ }
+}
+
--- /dev/null
+#ifndef ALIMUONCONTOURMAKER_H
+#define ALIMUONCONTOURMAKER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONContourMaker
+/// \brief Creator/merger of AliMUONContour objects
+///
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+#ifndef ROOT_TMap
+#include "TMap.h"
+#endif
+
+class AliMUONContour;
+class TObjArray;
+class TArrayD;
+
+class AliMUONContourMaker : public TObject
+{
+public:
+ AliMUONContourMaker();
+ virtual ~AliMUONContourMaker();
+
+ AliMUONContour* CreateContour(const TObjArray& polygons, const char* name=0x0) const;
+
+ AliMUONContour* MergeContour(const TObjArray& contours, const char* name=0x0) const;
+
+private:
+
+ AliMUONContour* FinalizeContour(const TObjArray& verticals, const TObjArray& horizontals) const;
+
+ void GetYPositions(const TObjArray& polygonVerticalEdges, TArrayD& yPositions) const;
+
+ void GetVerticalEdges(const TObjArray& polygons, TObjArray& polygonVerticalEdges) const;
+
+ void SortPoints(const TObjArray& polygonVerticalEdges, TObjArray& sortedPoints) const;
+
+ void Sweep(const TObjArray& polygonVerticalEdges, TObjArray& contourVerticalEdges) const;
+
+ void VerticalToHorizontal(const TObjArray& verticalEdges, TObjArray& horizontalEdges) const;
+
+ ClassDef(AliMUONContourMaker,1) // Maker/merger of AliMUONContour objects
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+///
+/// \class AliMUONContourMakerTest
+///
+/// Class used to test (and in particular time) the contour creation
+/// algorithms.
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+#include "AliMUONContourMakerTest.h"
+
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include "AliMUONContour.h"
+#include "AliMUONContourMaker.h"
+#include "AliMUONGeometryDetElement.h"
+#include "AliMUONGeometryTransformer.h"
+#include "AliMUONManuContourMaker.h"
+#include "AliMUONPolygon.h"
+#include "AliMUONSegment.h"
+#include "AliMpArea.h"
+#include "AliMpCDB.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEManager.h"
+#include "AliMpExMap.h"
+#include <float.h>
+#include "Riostream.h"
+#include "TArrow.h"
+#include "TCanvas.h"
+#include "TFile.h"
+#include "TGeoMatrix.h"
+#include "TLine.h"
+#include "TObjArray.h"
+#include "TPolyLine.h"
+#include "TSystem.h"
+
+///\cond CLASSIMP
+ClassImp(AliMUONContourMakerTest)
+///\endcond
+
+namespace
+{
+ //_____________________________________________________________________________
+ void Plot(TPolyLine& line, Bool_t orientation)
+ {
+ if ( !orientation )
+ {
+ line.Draw();
+ }
+ else
+ {
+ Double_t* x = line.GetX();
+ Double_t* y = line.GetY();
+
+ for ( Int_t i = 0; i < line.GetLastPoint(); ++i )
+ {
+ Double_t x1 = x[i];
+ Double_t y1 = y[i];
+ Double_t x2 = x[i+1];
+ Double_t y2 = y[i+1];
+
+ Bool_t horizontal = AliMUONSegment::AreEqual(y1,y2);
+
+ TLine* a = new TArrow(x1,y1,x2,y2,0.03,"->-");
+ if (horizontal)
+ {
+ a->SetLineStyle(3);
+ }
+ a->Draw();
+ }
+ }
+ }
+}
+
+//_____________________________________________________________________________
+AliMUONContourMakerTest::AliMUONContourMakerTest()
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONContourMakerTest::~AliMUONContourMakerTest()
+{
+ /// dtor
+}
+
+
+//______________________________________________________________________________
+TObjArray*
+AliMUONContourMakerTest::CreateContourList(const TObjArray& manuContours)
+{
+ /// Create an array of maps of contour names
+ ///
+ /// Assyming that key is something like station#/chamber#/de#/buspatch#/manu#
+ /// the idea here is to put one TMap for each level in mapArray :
+ ///
+ /// mapArray[0].key = station0
+ /// mapArray[0].value = map of strings { station0/chamber0, station0/chamber1 }
+ ///
+ /// Then each entry in mapArray will be converted into a contour by
+ /// merging its children (e.g. station0 contour will be made from the merging
+ /// of station0/chamber0 and station0/chamber1 in the example above).
+ ///
+
+ AliCodeTimerAuto("");
+
+ TIter next(&manuContours);
+ AliMUONContour* contour;
+ TObjArray* mapArray = new TObjArray;
+
+ while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
+ {
+ // Key is something like station#/chamber#/de#/buspatch#/manu#
+
+ TString key(contour->GetName());
+ TObjArray* s = key.Tokenize("/");
+ for ( Int_t i = 0; i < s->GetLast(); ++i )
+ {
+ TMap* m = static_cast<TMap*>(mapArray->At(i));
+ if (!m)
+ {
+ m = new TMap;
+ if ( i > mapArray->GetSize() ) mapArray->Expand(i);
+ mapArray->AddAt(m,i);
+ }
+ TString parent;
+ for ( Int_t k = 0; k <= i; ++k )
+ {
+ TObjString* str = static_cast<TObjString*>(s->At(k));
+ parent += str->String();
+ if ( k < i ) parent += "/";
+ }
+ TString child(parent);
+ child += "/";
+ child += static_cast<TObjString*>(s->At(i+1))->String();
+
+ TObjArray* ma = static_cast<TObjArray*>(m->GetValue(parent.Data()));
+ if (!ma)
+ {
+ ma = new TObjArray;
+ m->Add(new TObjString(parent.Data()),ma);
+ }
+ TPair* p = static_cast<TPair*>(ma->FindObject(child.Data()));
+ if ( !p )
+ {
+ ma->Add(new TObjString(child.Data()));
+ }
+ }
+ delete s;
+ }
+
+ return mapArray;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::Exec(const Option_t* opt)
+{
+ /// Main method
+ /// Generate the geometry transformations, then
+ /// contours for all manus, and then for all the elements
+ /// (bus patches, detection elements, etc...)
+
+ AliInfo("Resetting all timers before I start...");
+
+ AliCodeTimer::Instance()->Reset();
+
+ AliMpCDB::LoadDDLStore2();
+
+ AliCodeTimer::Instance()->Print();
+
+ AliInfo("Resetting all timers after loading the mapping...");
+
+ AliCodeTimer::Instance()->Reset();
+
+ AliCodeTimerAuto("");
+
+ AliMpExMap* real(0x0);
+ AliMpExMap* exploded(0x0);
+
+ GenerateTransformations(real,exploded);
+
+ TObjArray* manus(0x0);
+ TObjArray* all(0x0);
+
+ TString sopt(opt);
+
+ if ( sopt.Contains("MANU") || sopt.Contains("ALL") )
+ {
+ AliMUONManuContourMaker manuMaker(exploded);
+ manus = manuMaker.GenerateManuContours(kTRUE);
+ }
+
+ if ( sopt.Contains("ALL") && manus )
+ {
+ manus->SetOwner(kFALSE);
+ all = GenerateAllContours(*manus);
+ if ( sopt.Contains("SAVE") && all )
+ {
+ TFile f("AliMUONContourMakerTest.all.root","RECREATE");
+ all->Write("ALL",TObject::kSingleKey);
+ f.Close();
+ }
+
+ }
+
+ AliCodeTimer::Instance()->Print();
+
+ delete manus;
+ delete all;
+}
+
+//______________________________________________________________________________
+TObjArray*
+AliMUONContourMakerTest::GenerateAllContours(const TObjArray& manuContours)
+{
+ /// From a map of manu contours, generate the compound contours (bp, de, etc...)
+ /// by merging them.
+ /// Note that manuContours should NOT be the owner of its contours,
+ /// as they are adopted by the array returned by this method.
+
+ AliCodeTimerAuto("");
+
+ // Get the list of contours to create
+ TObjArray* mapArray = CreateContourList(manuContours);
+
+ // Now loop over the mapArray to actually create the contours
+ TIter next2(mapArray,kIterBackward);
+
+ TMap allContourMap;
+ allContourMap.SetOwnerKeyValue(kTRUE,kFALSE); // not owner of contours, as the returned array will be the owner
+ TObjArray* allContourArray = new TObjArray;
+ allContourArray->SetOwner(kTRUE);
+
+ TIter nextContour(&manuContours);
+ AliMUONContour* contour(0x0);
+
+ while ( ( contour = static_cast<AliMUONContour*>(nextContour()) ) )
+ {
+ allContourMap.Add(new TObjString(contour->GetName()),contour);
+ allContourArray->Add(contour);
+ }
+
+ AliMUONContourMaker maker;
+
+ for ( Int_t i = mapArray->GetLast(); i >= 1; --i )
+ // end at 1 to avoid merging different cathodes together, which
+ // would not work...
+ {
+ TMap* a = static_cast<TMap*>(mapArray->At(i));
+ TIter next3(a);
+ TObjString* str;
+ while ( ( str = static_cast<TObjString*>(next3()) ) )
+ {
+ TObjArray* m = static_cast<TObjArray*>(a->GetValue(str->String().Data()));
+ TIter next4(m);
+ TObjString* k;
+ TObjArray subcontours;
+ subcontours.SetOwner(kFALSE);
+ while ( ( k = static_cast<TObjString*>(next4()) ) )
+ {
+ contour = static_cast<AliMUONContour*>(allContourMap.GetValue(k->String().Data()));
+ if ( contour )
+ {
+ subcontours.Add(contour);
+ }
+ else
+ {
+ AliError(Form("Did not find contour %s",k->String().Data()))
+ return allContourArray;
+ }
+ }
+
+ contour = maker.MergeContour(subcontours,str->String().Data());
+
+ bool error(kFALSE);
+
+ if (!contour)
+ {
+ error=kTRUE;
+ AliError(Form("ERROR : could not merge into %s",str->String().Data()));
+ }
+ else
+ {
+ if ( contour->Area().IsValid() == kFALSE )
+ {
+ error=kTRUE;
+ AliError(Form("ERROR : area of contour %s is invalid",str->String().Data()));
+ }
+ }
+
+ if ( error )
+ {
+ // do it again, but get intermediate results to plot them
+ PrintAsPNG(str->String().Data(),subcontours);
+ if (contour )
+ {
+ StdoutToAliError(contour->Area().Print("B"););
+ }
+ AliError(Form("%d subcontours",subcontours.GetLast()+1));
+ StdoutToAliError(subcontours.Print(););
+ // check whether one of the subcontour itself is already invalid ?
+ TIter next(&subcontours);
+ AliMUONContour* cont;
+ while ( ( cont = static_cast<AliMUONContour*>(next()) ) )
+ {
+ if (!cont->IsValid())
+ {
+ AliError(Form("subcontour %s is invalid",cont->GetName()));
+ }
+ }
+ TFile f("subcontour.root","recreate");
+ subcontours.Write("fault",TObject::kSingleKey);
+ f.Close();
+
+ return allContourArray;
+ }
+
+ allContourArray->Add(contour);
+ allContourMap.Add(new TObjString(str->String().Data()),contour);
+ }
+ }
+
+ return allContourArray;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::GenerateTransformations(AliMpExMap*& real, AliMpExMap*& exploded)
+{
+ /// Generate geometric transformations to be used to compute the contours
+ /// (real are, as the name implies, real ones, while the other ones are
+ /// a bit tweaked to look fine on screen).
+
+ AliCodeTimerAuto("");
+
+ AliMUONGeometryTransformer transformer;
+ Bool_t ok = transformer.LoadGeometryData("transform.dat");
+ // transformer.LoadGeometryData("geometry.root"); //FIXME: add a protection if geometry.root file does not exist
+ if (!ok)
+ {
+ cout << "ERROR : cannot get geometry !" << endl;
+ return;
+ }
+ real = new AliMpExMap;
+ exploded = new AliMpExMap;
+ AliMpDEIterator deIt;
+ deIt.First();
+ while ( !deIt.IsDone() )
+ {
+ Int_t detElemId = deIt.CurrentDEId();
+ const AliMUONGeometryDetElement* de = transformer.GetDetElement(detElemId);
+
+ real->Add(detElemId,de->GetGlobalTransformation()->Clone());
+
+ TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(de->GetGlobalTransformation()->Clone());
+ Double_t* translation = matrix->GetTranslation();
+
+ if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 )
+ {
+ translation[0] *= 1.0;
+ translation[1] *= 1.5;
+ }
+ else
+ {
+ Double_t shift = 5; // cm
+ Double_t xshift[] = { shift, -shift, -shift, shift };
+ Double_t yshift[] = { shift, shift, -shift, -shift };
+ Int_t ishift = detElemId % 100;
+
+ translation[0] += xshift[ishift];
+ translation[1] += yshift[ishift];
+ }
+ matrix->SetTranslation(translation);
+ exploded->Add(detElemId,matrix);
+ deIt.Next();
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::GetBoundingBox(const TObjArray& array,
+ Double_t& xmin, Double_t& ymin,
+ Double_t& xmax, Double_t& ymax,
+ Bool_t enlarge) const
+{
+ /// Get the bounding box of all the contours in array.
+ /// If enlarge = kTRUE, the bounding box is "enlarged" a bit
+ /// (e.g. to leave some blank around a plot in a canvas)
+ ///
+
+ xmin=ymin=FLT_MAX;
+ xmax=ymax=-FLT_MAX;
+ TIter next(&array);
+ AliMUONContour* contour;
+ while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
+ {
+ AliMpArea area(contour->Area());
+ xmin = TMath::Min(xmin,area.LeftBorder());
+ xmax = TMath::Max(xmax,area.RightBorder());
+ ymin = TMath::Min(ymin,area.DownBorder());
+ ymax = TMath::Max(ymax,area.UpBorder());
+ }
+
+ if (enlarge)
+ {
+ Double_t xsize = (xmax-xmin);
+ Double_t ysize = (ymax-ymin);
+ Double_t xshift = xsize*0.1;
+ Double_t yshift = ysize*0.1;
+ xmin -= xshift;
+ ymin -= yshift;
+ xmax = xmin + xsize + xshift*2;
+ ymax = ymin + ysize + yshift*2;
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::PlotSegments(const TObjArray& segments, Int_t lineColor, Int_t lineWidth, Bool_t orientation) const
+{
+ /// Plot an array of segments
+
+ TIter next(&segments);
+ AliMUONSegment* s;
+ while ( ( s = static_cast<AliMUONSegment*>(next()) ) )
+ {
+ TPolyLine* line = new TPolyLine(2);
+ line->SetPoint(0,s->StartX(),s->StartY());
+ line->SetPoint(1,s->EndX(),s->EndY());
+ line->SetLineColor(lineColor);
+ line->SetLineWidth(lineWidth);
+ ::Plot(*line,orientation);
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::Plot(const AliMUONPolygon& polygon,
+ Int_t lineColor, Int_t lineWidth,
+ Bool_t orientation) const
+{
+ /// Plot a polygon
+ TPolyLine* line = new TPolyLine(polygon.NumberOfVertices());
+ for ( Int_t i = 0; i < polygon.NumberOfVertices(); ++i )
+ {
+ line->SetPoint(i,polygon.X(i),polygon.Y(i));
+ }
+
+ line->SetLineColor(lineColor);
+ line->SetLineWidth(lineWidth);
+ ::Plot(*line,kFALSE);
+ if ( orientation ) ::Plot(*line,kTRUE);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::Plot(const AliMUONContour& contour, Int_t lineColor, Int_t lineWidth,
+ Bool_t orientation) const
+{
+ /// Plot a contour (i.e. a set of polygons)
+ const TObjArray* polygons = contour.Polygons();
+ TIter next(polygons);
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ Plot(*pol,lineColor,lineWidth,orientation);
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourMakerTest::PlotContours(const TObjArray& array, Bool_t orientations) const
+{
+ /// Plot an array of contours
+ TIter next(&array);
+ AliMUONContour* contour;
+ while ( ( contour = static_cast<AliMUONContour*>(next()) ) )
+ {
+ Plot(*contour,5,4,orientations);
+ }
+}
+
+//______________________________________________________________________________
+void
+AliMUONContourMakerTest::PrintAsPNG(const char* basename, const TObjArray& contourArray,
+ const TObjArray* verticals, const TObjArray* horizontals) const
+{
+ /// Output contours and segments into a PNG file.
+ TCanvas* c = new TCanvas(basename,basename,0,0,600,600);
+ double xmin,ymin,xmax,ymax;
+ GetBoundingBox(contourArray,xmin,ymin,xmax,ymax,kTRUE);
+ c->Range(xmin,ymin,xmax,ymax);
+ PlotContours(contourArray,kTRUE);
+ c->Modified();
+ c->Update();
+ TString name(Form("%s",basename));
+ name.ReplaceAll("/","_");
+ c->Print(Form("%s.png",name.Data()));
+ if ( verticals || horizontals )
+ {
+ c->Clear();
+ if ( verticals ) PlotSegments(*verticals,1);
+ if ( horizontals) PlotSegments(*horizontals,2);
+ c->Modified();
+ c->Update();
+ name = Form("%s",basename);
+ name.ReplaceAll("/","_");
+ c->Print(Form("%s-segments.png",name.Data()));
+ }
+ delete c;
+}
+
--- /dev/null
+#ifndef ALIMUONCONTOURMAKERTEST_H
+#define ALIMUONCONTOURMAKERTEST_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup evaluation
+/// \class AliMUONContourMakerTest
+/// \brief Test of ContourMaker classes
+///
+// author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMpExMap;
+class TObjArray;
+class TString;
+class AliMpMotifPosition;
+class AliMUONContour;
+class AliMUONPolygon;
+
+class AliMUONContourMakerTest : public TObject
+{
+public:
+ AliMUONContourMakerTest();
+ virtual ~AliMUONContourMakerTest();
+
+ void Exec(const Option_t* opt="ALL");
+
+ void GetBoundingBox(const TObjArray& array,
+ Double_t& xmin, Double_t& ymin,
+ Double_t& xmax, Double_t& ymax,
+ Bool_t enlarge=kFALSE) const;
+
+ void Plot(const AliMUONContour& contour, Int_t lineColor=5, Int_t lineWidth=4, Bool_t orientation=kFALSE) const;
+
+ void Plot(const AliMUONPolygon& polygon, Int_t lineColor=5, Int_t lineWidth=4, Bool_t orientation=kFALSE) const;
+
+ void PlotContours(const TObjArray& array, Bool_t orientations=kFALSE) const;
+
+ void PlotSegments(const TObjArray& segments, Int_t lineColor=1, Int_t lineWidth=2, Bool_t orientations=kFALSE) const;
+
+ void PrintAsPNG(const char* basename, const TObjArray& contourArray,
+ const TObjArray* contourVerticalEdges=0x0,
+ const TObjArray* horizontals=0x0) const;
+
+private:
+
+ TObjArray* CreateContourList(const TObjArray& manuContours);
+
+ TObjArray* GenerateAllContours(const TObjArray& manuContours);
+
+ void GenerateTransformations(AliMpExMap*& real, AliMpExMap*& exploded);
+
+ TString NameIt(const AliMpMotifPosition& motifPosition) const;
+
+ ClassDef(AliMUONContourMakerTest,1) // Test of AliMUONContourMaker
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONContourPainter
+///
+/// Class to draw AliMUONContour objects (2D)
+///
+/// \author Laurent Aphecetche, Subatech
+
+#include "AliMUONContourPainter.h"
+
+#include "TVirtualX.h"
+#include "AliMUONPolygon.h"
+#include "AliMUONContour.h"
+#include "TObjArray.h"
+#include "TVirtualPad.h"
+
+///\cond CLASSIMP
+ClassImp(AliMUONContourPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONContourPainter::AliMUONContourPainter()
+{
+ /// Ctor
+}
+
+//_____________________________________________________________________________
+AliMUONContourPainter::~AliMUONContourPainter()
+{
+ /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONContourPainter::Paint(const AliMUONContour& contour,
+ Int_t lineColor, Int_t lineWidth,
+ Int_t fillColor, Int_t fillStyle)
+{
+ /// Paint the given contour.
+ /// If lineColor > 0 the outline is drawn
+ /// If fillColor > 0 the contour is filled.
+
+ Bool_t outline(lineColor>0);
+ Bool_t fill(fillColor>0);
+
+ Int_t fc = gVirtualX->GetFillColor();
+ Int_t fs = gVirtualX->GetFillStyle();
+ Int_t lc = gVirtualX->GetLineColor();
+ Int_t lw = gVirtualX->GetLineWidth();
+
+ if ( lineColor > 0 ) gVirtualX->SetLineColor(lineColor);
+ if ( lineWidth > 0 ) gVirtualX->SetLineWidth(lineWidth);
+ if ( fillColor > 0 ) gVirtualX->SetFillColor(fillColor);
+ if ( fillStyle > 0 ) gVirtualX->SetFillStyle(fillStyle);
+
+ TIter next(contour.Polygons());
+ AliMUONPolygon* pol;
+ while ( ( pol = static_cast<AliMUONPolygon*>(next()) ) )
+ {
+ Int_t n = pol->NumberOfVertices();
+ Double_t* x = new Double_t[n];
+ Double_t* y = new Double_t[n];
+ for ( Int_t i = 0; i < n; ++i )
+ {
+ x[i] = gPad->GetLogx() ? gPad->XtoPad(pol->X(i)) : pol->X(i);
+ y[i] = gPad->GetLogy() ? gPad->YtoPad(pol->Y(i)) : pol->Y(i);
+ }
+ if ( fill )
+ {
+ gPad->PaintFillArea(n,x,y);
+ }
+ if (outline)
+ {
+ gPad->PaintPolyLine(n,x,y);
+ }
+
+ delete[] x;
+ delete[] y;
+ }
+
+ gVirtualX->SetFillColor(fc);
+ gVirtualX->SetFillStyle(fs);
+ gVirtualX->SetLineColor(lc);
+ gVirtualX->SetLineWidth(lw);
+
+}
--- /dev/null
+#ifndef ALIMUONCONTOURPAINTER_H
+#define ALIMUONCONTOURPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONContourPainter
+/// \brief Class to draw AliMUONContour objects
+///
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONContour;
+
+class AliMUONContourPainter : public TObject
+{
+public:
+ AliMUONContourPainter();
+ virtual ~AliMUONContourPainter();
+
+ using TObject::Paint;
+
+ static void Paint(const AliMUONContour& contour,
+ Int_t lineColor=1, Int_t lineStyle=1,
+ Int_t fillColor=-1, Int_t fillStyle=1001);
+
+ ClassDef(AliMUONContourPainter,1) //
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONManuContourMaker
+///
+/// Maker of manu contours.
+///
+/// Make use of the AliMUONContourMaker class, but this one contains
+/// specific things for MUON (as the mapping, for instance), hence its
+/// separation from AliMUONContourMaker.
+///
+/// This class requires that the mapping is loaded before anything can be done.
+///
+/// \author Laurent Aphecetche, Subatech
+
+#include "AliMUONManuContourMaker.h"
+
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include "AliMUONContour.h"
+#include "AliMUONContourMaker.h"
+#include "AliMUONPolygon.h"
+#include "AliMpCathodType.h"
+#include "AliMpConnection.h"
+#include "AliMpConstants.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEManager.h"
+#include "AliMpIntPair.h"
+#include "AliMpMotifPosition.h"
+#include "AliMpMotifType.h"
+#include "AliMpManuIterator.h"
+#include "AliMpPlaneType.h"
+#include "AliMpSegmentation.h"
+#include "AliMpUID.h"
+#include "AliMpVMotif.h"
+#include "AliMpVSegmentation.h"
+#include "TGeoMatrix.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TString.h"
+#include "TVector2.h"
+
+///\cond CLASSIMP
+ClassImp(AliMUONManuContourMaker)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONManuContourMaker::AliMUONManuContourMaker(AliMpExMap* deTransformations)
+: TObject(), fDETransformations(deTransformations), fLocalManuContours(222,1)
+{
+ fLocalManuContours.SetOwnerKeyValue(kTRUE,kTRUE);
+}
+
+//_____________________________________________________________________________
+AliMUONManuContourMaker::~AliMUONManuContourMaker()
+{
+}
+
+//_____________________________________________________________________________
+AliMUONContour*
+AliMUONManuContourMaker::CreateManuContour(Int_t detElemId, Int_t manuId, const char* name) const
+{
+ /// Create the contour of a given manu (global coordinates)
+
+ AliCodeTimerAuto("");
+
+ TString sname(name);
+
+ if ( sname.Length()==0 )
+ {
+ sname = ManuPathName(detElemId,manuId);
+ }
+
+ const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
+ const AliMpMotifPosition* motifPos = seg->MotifPosition(manuId);
+
+ AliMUONContour* contour = CreateMotifContour(*motifPos);
+
+ if (!contour)
+ {
+ AliError(Form("Could not build contour %s",sname.Data()));
+ return 0x0;
+ }
+
+ contour->SetName(sname.Data());
+
+ contour->Offset(motifPos->GetPositionX()-seg->GetPositionX(),
+ motifPos->GetPositionY()-seg->GetPositionY());
+
+ TGeoHMatrix* matrix = 0x0;
+
+ if ( fDETransformations )
+ {
+ matrix = static_cast<TGeoHMatrix*>(fDETransformations->GetValue(detElemId));
+ if ( matrix ) contour->Transform(*matrix);
+ }
+
+ return contour;
+}
+
+
+//_____________________________________________________________________________
+AliMUONContour*
+AliMUONManuContourMaker::CreateMotifContour(const AliMpMotifPosition& motifPosition) const
+{
+ /// Create the contour of a given MOTIF (i.e. local coordinates only).
+
+ AliCodeTimerAuto("");
+
+ TString mpName(NameIt(motifPosition));
+
+ AliMUONContour* contour = static_cast<AliMUONContour*>(fLocalManuContours.GetValue(mpName.Data()));
+
+ if ( contour )
+ {
+ // if we have already done the job, just have to clone it and we are done
+ return static_cast<AliMUONContour*>(contour->Clone());
+ }
+
+ TObjArray polygons(AliMpConstants::ManuNofChannels()); // array of AliMUONPolygon objects
+ polygons.SetOwner(kTRUE);
+
+ AliMpVMotif* motif = motifPosition.GetMotif();
+
+ AliMpMotifType* motifType = motif->GetMotifType();
+
+ if ( motifType->IsFull() )
+ {
+ // motif is a simple rectangle. No need to loop over pads, we can
+ // compute the contour right here and now.
+ polygons.Add(new AliMUONPolygon(0.0,0.0,motif->DimensionX(),motif->DimensionY()));
+ }
+ else
+ {
+ for ( Int_t i = 0; i <= AliMpConstants::ManuNofChannels(); ++i )
+ {
+ AliMpConnection* connection = motifType->FindConnectionByGassiNum(i);
+
+ if ( connection )
+ {
+ Int_t ix = connection->GetLocalIx();
+ Int_t iy = connection->GetLocalIy();
+
+ Double_t x,y,dx,dy;
+
+ motif->GetPadDimensionsByIndices(ix,iy,dx,dy);
+ motif->PadPositionLocal(ix,iy,x,y);
+
+ AliMUONPolygon* pol = new AliMUONPolygon(x,y,dx,dy);
+ polygons.Add(pol);
+ }
+ }
+ }
+
+ AliMUONContourMaker maker;
+
+ contour = maker.CreateContour(polygons);
+
+ if (!contour || !contour->IsValid() )
+ {
+ AliError(Form("Failed to properly create contour %s contour = %p",mpName.Data(),contour));
+ if ( contour )
+ {
+ AliError(Form("nofVertices=%d area.isvalid=%d",contour->NumberOfVertices(),contour->Area().IsValid()));
+ StdoutToAliError(contour->Area().Print(););
+ }
+ delete contour;
+ return 0x0;
+ }
+
+ {
+ AliCodeTimerAuto("localmanucontour.add");
+ fLocalManuContours.Add(new TObjString(mpName),contour);
+ }
+
+ return static_cast<AliMUONContour*>(contour->Clone());
+}
+
+//_____________________________________________________________________________
+TObjArray*
+AliMUONManuContourMaker::GenerateManuContours(Bool_t stopAtError)
+{
+ /// Generate the contours for all the manus, taking into account the given transformation
+ /// (to go from local to global). That transformation need not be the real one (i.e.
+ /// it can be an "exploded" one to ease visualization).
+
+ AliCodeTimerAuto("");
+
+ TObjArray* manuContours = new TObjArray;
+
+ manuContours->SetOwner(kTRUE);
+
+ AliMpManuIterator it;
+ Int_t detElemId, manuId;
+ Int_t nmanus(0);
+ Int_t nok(0);
+
+ while ( it.Next(detElemId,manuId) )
+ {
+ ++nmanus;
+ AliMUONContour* contour = CreateManuContour(detElemId,manuId);
+ if (contour)
+ {
+ manuContours->Add(contour);
+ }
+ else
+ {
+ if ( stopAtError )
+ {
+ break;
+ }
+ }
+ ++nok;
+ }
+
+ AliInfo(Form("%d manus. %d contours successfully created",nmanus,nok));
+
+ return manuContours;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONManuContourMaker::NameIt(const AliMpMotifPosition& motifPosition) const
+{
+ /// Get the name of an AliMpMotifPosition
+
+ AliMpVMotif* motif = motifPosition.GetMotif();
+ TString name(Form("%s",motif->GetID().Data()));
+
+ for ( Int_t i = 0; i < motif->GetNofPadDimensions(); ++i )
+ {
+ name += Form("/%7.3f-%7.3f:",motif->GetPadDimensionX(i),motif->GetPadDimensionY(i));
+ }
+
+ return name;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONManuContourMaker::ManuPathName(Int_t detElemId, Int_t manuId, Bool_t withCathodeName)
+{
+ /// Get the name of a manu
+
+ AliMp::PlaneType planeType;
+ if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
+ {
+ planeType = AliMp::kNonBendingPlane;
+ }
+ else
+ {
+ planeType = AliMp::kBendingPlane;
+ }
+ AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,planeType);
+
+ Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
+ Int_t stationId = chamberId/2;
+
+ Int_t busPatchId = AliMpDDLStore::Instance()->GetBusPatchId(detElemId, manuId);
+
+ AliMpUID id(cathodeType,stationId,chamberId,detElemId,busPatchId,manuId);
+
+ if ( withCathodeName ) return id.PathName();
+
+ TString name(id.PathName());
+
+ name.ReplaceAll("Cathode0/","");
+ name.ReplaceAll("Cathode1/","");
+
+ return name;
+}
+
+
+
+
--- /dev/null
+#ifndef ALIMUONMANUCONTOURMAKER_H
+#define ALIMUONMANUCONTOURMAKER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONManuContourMaker
+/// \brief Maker of AliMUONContour objects for all the tracker manus
+///
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+#ifndef ROOT_TMap
+# include "TMap.h"
+#endif
+
+class AliMpExMap;
+class AliMpMotifPosition;
+class AliMUONContour;
+
+class AliMUONManuContourMaker : public TObject
+{
+public:
+ AliMUONManuContourMaker(AliMpExMap* deTransformations);
+ virtual ~AliMUONManuContourMaker();
+
+ AliMUONContour* CreateManuContour(Int_t detElemId, Int_t manuId, const char* name="") const;
+
+ AliMUONContour* CreateMotifContour(const AliMpMotifPosition& motifPosition) const;
+
+ TObjArray* GenerateManuContours(Bool_t stopAtError=kFALSE);
+
+ static TString ManuPathName(Int_t detElemId, Int_t manu, Bool_t withCathodeName=kTRUE);
+
+private:
+ /// not implemented
+ AliMUONManuContourMaker(const AliMUONManuContourMaker& rhs);
+ /// not implemented
+ AliMUONManuContourMaker& operator=(const AliMUONManuContourMaker& rhs);
+
+ TString NameIt(const AliMpMotifPosition& motifPosition) const;
+
+private:
+ AliMpExMap* fDETransformations; //< map<int,TGeoHMatrix> of detElemId to matrix
+ mutable TMap fLocalManuContours; //< map of local manu contours
+
+ ClassDef(AliMUONManuContourMaker,1) //
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONNode
+///
+/// A node of a segment tree
+///
+/// For the details of the meaning of cardinality and potent data
+/// members, please see Diane L. Souvaine and Iliana Bjorling-Sachs,
+/// Proceedings of the IEEE, Vol. 80, No. 9, September 1992, p. 1449
+///
+///
+/// \Author Laurent Aphecetche, Subatech
+
+#include "AliMUONNode.h"
+
+#include "AliLog.h"
+#include "AliMUONSegment.h"
+#include "Riostream.h"
+#include "TMath.h"
+#include "TObjArray.h"
+#include "TString.h"
+
+///\cond CLASSIMP
+ClassImp(AliMUONNode)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONNode::AliMUONNode(Double_t a, Double_t b, Double_t midpoint)
+: fLeftNode(0x0), fRightNode(0x0), fMin(a), fMax(b), fMidPoint(midpoint), fC(0), fP(0)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONNode::~AliMUONNode()
+{
+ /// dtor
+ delete fLeftNode;
+ delete fRightNode;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::Print(const char* opt) const
+{
+ /// Printout
+ cout << opt << Form("[%7.2f,%7.2f]",fMin,fMax);
+ if ( !TMath::IsNaN(fMidPoint) ) cout << Form(" (%7.2f)",fMidPoint);
+ cout << endl;
+
+ TString sopt(opt);
+ sopt += " ";
+
+ if ( fLeftNode )
+ {
+ fLeftNode->Print(sopt.Data());
+ }
+ if ( fRightNode )
+ {
+ fRightNode->Print(sopt.Data());
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::Contribution(Double_t b, Double_t e, TObjArray& stack)
+{
+ /// Contribution of an edge (b,e) to the final contour
+ if ( fMax < fMin )
+ {
+ AliError(Form("fMax(%10.5f) < fMin(%10.5f",fMax,fMin));
+ }
+
+ if ( fC == 0 )
+ {
+ if ( IsFullyContained(b,e) && fP == 0 )
+ {
+ AliMUONSegment* back = static_cast<AliMUONSegment*>(stack.Last());
+
+ if ( back && AliMUONSegment::AreEqual(back->EndY(),fMin) )
+ {
+ // merge to existing segment
+ Double_t y(back->StartY());
+ back->Set(0.0,y,0.0,fMax);
+ }
+ else
+ {
+ // add a new segment
+ stack.Add(new AliMUONSegment(0.0,fMin,0.0,fMax));
+ }
+ }
+ else
+ {
+ if ( b < fMidPoint )
+ {
+ fLeftNode->Contribution(b,e,stack);
+ }
+ if ( fMidPoint < e )
+ {
+ fRightNode->Contribution(b,e,stack);
+ }
+ }
+ }
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONNode::IsFullyContained(Double_t b, Double_t e) const
+{
+ /// Whether this node's interval is fully contained into [b,e]
+
+ return ( ( b < fMin || AliMUONSegment::AreEqual(b,fMin) ) && ( fMax < e || AliMUONSegment::AreEqual(e,fMax)) );
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::InsertInterval(Double_t b, Double_t e, TObjArray& stack)
+{
+ /// Insert an interval
+ if ( IsFullyContained(b,e) )
+ {
+ C(1);
+ }
+ else
+ {
+ if ( b < fMidPoint )
+ {
+ fLeftNode->InsertInterval(b,e,stack);
+ }
+ if ( fMidPoint < e )
+ {
+ fRightNode->InsertInterval(b,e,stack);
+ }
+ }
+ Update();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::DeleteInterval(Double_t b, Double_t e, TObjArray& stack)
+{
+ /// Delete an interval
+ if ( IsFullyContained(b,e) )
+ {
+ C(-1);
+ }
+ else
+ {
+ if ( fC > 0 ) Demote();
+ if ( b < fMidPoint )
+ {
+ fLeftNode->DeleteInterval(b,e,stack);
+ }
+
+ if ( fMidPoint < e )
+ {
+ fRightNode->DeleteInterval(b,e,stack);
+ }
+ }
+ Update();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::Update()
+{
+ /// Update internal values
+ if ( !fLeftNode )
+ {
+ fP = 0;
+ }
+ else
+ {
+ if (fLeftNode->C() > 0 && fRightNode->C() > 0 )
+ {
+ Promote();
+ }
+ if (fLeftNode->C()==0 && fRightNode->C()==0 && fLeftNode->P()==0 && fRightNode->P()==0 )
+ {
+ fP = 0;
+ }
+ else
+ {
+ fP = 1;
+ }
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::Promote()
+{
+ /// Promote node
+ fLeftNode->C(-1);
+ fRightNode->C(-1);
+ C(+1);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONNode::Demote()
+{
+ /// Demote node
+ fLeftNode->C(+1);
+ fRightNode->C(+1);
+ C(-1);
+ fP = 1;
+}
+
--- /dev/null
+#ifndef ALIMUONNODE_H
+#define ALIMUONNODE_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONNode
+/// \brief A node of a segment tree
+///
+// author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class TObjArray;
+
+class AliMUONNode : public TObject
+{
+public:
+ AliMUONNode(Double_t a, Double_t b, Double_t midpoInt_t);
+ virtual ~AliMUONNode();
+
+ void Print(const char* opt="") const;
+
+ void Contribution(Double_t b, Double_t e, TObjArray& stack);
+
+ void InsertInterval(Double_t b, Double_t e, TObjArray& stack);
+
+ void DeleteInterval(Double_t b, Double_t e, TObjArray& stack);
+
+ Bool_t IsFullyContained(Double_t b, Double_t e) const;
+
+ void Update();
+
+ void Demote();
+
+ void Promote();
+
+ /// Get cardinality
+ Int_t C() const { return fC; }
+
+ /// Increase cardinality
+ void C(Int_t v) { fC += v; }
+
+ /// Get potent state
+ Int_t P() const { return fP; }
+
+ /// Set left node
+ void LeftNode(AliMUONNode* n) { fLeftNode = n; }
+
+ /// Set right node
+ void RightNode(AliMUONNode* n) { fRightNode = n; }
+
+private:
+
+ /// not implemented
+ AliMUONNode(const AliMUONNode& node);
+ /// not implemented
+ AliMUONNode& operator=(const AliMUONNode& node);
+ AliMUONNode* fLeftNode; //< left node
+ AliMUONNode* fRightNode; //< right node
+
+ Double_t fMin; //< Min
+ Double_t fMax; //< Max
+ Double_t fMidPoint; //< (Min+Max)/2
+
+ Int_t fC; //< cardinality
+ Int_t fP; //< potent state
+
+ ClassDef(AliMUONNode,0); // A node of a segment tree
+};
+
+#endif
+++ /dev/null
-/**************************************************************************
-* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
-* *
-* Author: The ALICE Off-line Project. *
-* Contributors are mentioned in the code where appropriate. *
-* *
-* Permission to use, copy, modify and distribute this software and its *
-* documentation strictly for non-commercial purposes is hereby granted *
-* without fee, provided that the above copyright notice appears in all *
-* copies and that both the copyright notice and this permission notice *
-* appear in the supporting documentation. The authors make no claims *
-* about the suitability of this software for any purpose. It is *
-* provided "as is" without express or implied warranty. *
-**************************************************************************/
-
-// $Id$
-
-#include "AliMUONPainterContour.h"
-
-#include "AliMpArea.h"
-#include "AliLog.h"
-#include <Riostream.h>
-#include <TGeoMatrix.h>
-#include <TMath.h>
-#include <TObjArray.h>
-#include <TPolyLine.h>
-#include <TString.h>
-#include <TVector2.h>
-#include <TVirtualX.h>
-#include <float.h>
-
-///\class AliMUONPainterContour
-///
-/// Contour for one painter. A contour is a set of TPolyLine (one polyline
-/// per closed shape).
-///
-///\author Laurent Aphecetche, Subatech
-
-///\cond CLASSIMP
-ClassImp(AliMUONPainterContour)
-///\endcond
-
-//_____________________________________________________________________________
-AliMUONPainterContour::AliMUONPainterContour(const char* name) : TNamed(name,""),
-fPolyLines(new TObjArray),
-fXmin(FLT_MAX),
-fXmax(-FLT_MAX),
-fYmin(FLT_MAX),
-fYmax(-FLT_MAX)
-{
- /// ctor
- fPolyLines->SetOwner(kTRUE);
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour::AliMUONPainterContour(const char* name, const AliMpArea& area)
-: TNamed(name,""),
-fPolyLines(new TObjArray),
-fXmin(area.LeftBorder()),
-fXmax(area.RightBorder()),
-fYmin(area.DownBorder()),
-fYmax(area.UpBorder())
-{
- /// ctor
- fPolyLines->SetOwner(kTRUE);
- TPolyLine* line = new TPolyLine(5);
- Double_t x, y, dx, dy;
- area.GetParameters(x, y, dx, dy);
- line->SetPoint(0,x-dx,y-dy);
- line->SetPoint(1,x-dx,y+dy);
- line->SetPoint(2,x+dx,y+dy);
- line->SetPoint(3,x+dx,y-dy);
- line->SetPoint(4,x-dx,y-dy);
-
- fPolyLines->AddLast(line);
-}
-
-//______________________________________________________________________________
-AliMUONPainterContour::AliMUONPainterContour(const AliMUONPainterContour& rhs)
-: TNamed(rhs),
-fPolyLines(0x0),
-fXmin(FLT_MAX),
-fXmax(-FLT_MAX),
-fYmin(FLT_MAX),
-fYmax(-FLT_MAX)
-{
- /// Copy constructor.
-
- ((AliMUONPainterContour&)rhs).Copy(*this);
-}
-
-//______________________________________________________________________________
-AliMUONPainterContour&
-AliMUONPainterContour::operator=(const AliMUONPainterContour& rhs)
-{
- /// Assignment operator
- if ( this != &rhs )
- {
- delete fPolyLines;
- fPolyLines = 0;
- rhs.Copy(*this);
- }
- return *this;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour::~AliMUONPainterContour()
-{
- /// dtor
- delete fPolyLines;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContour::AdoptPolyLine(TPolyLine* line)
-{
- /// Adopt one polyline into our array of polylines
- fPolyLines->AddLast(line);
- for ( Int_t i = 0; i <= line->GetLastPoint(); ++i )
- {
- Double_t x = line->GetX()[i];
- Double_t y = line->GetY()[i];
- fXmin = TMath::Min(fXmin,x);
- fXmax = TMath::Max(fXmax,x);
- fYmin = TMath::Min(fYmin,y);
- fYmax = TMath::Max(fYmax,y);
- }
-}
-
-//_____________________________________________________________________________
-AliMpArea
-AliMUONPainterContour::Area() const
-{
- /// Return the area covered by this contour (i.e. the area that
- /// contains all the poylines)
-
- return AliMpArea( ( fXmax+fXmin)/2.0, (fYmax+fYmin)/2.0 ,
- TMath::Abs(fXmax-fXmin)/2.0, TMath::Abs(fYmax-fYmin)/2.0 );
-}
-
-//______________________________________________________________________________
-void AliMUONPainterContour::Copy(TObject& obj) const
-{
- /// Copy this to obj
-
- AliMUONPainterContour& rhs = static_cast<AliMUONPainterContour&>(obj);
- TNamed::Copy(rhs);
- rhs.fPolyLines = new TObjArray;
- rhs.fPolyLines->SetOwner(kTRUE);
- TIter next(fPolyLines);
- TPolyLine* line;
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- rhs.fPolyLines->AddLast(line->Clone());
- }
- rhs.fXmin = fXmin;
- rhs.fXmax = fXmax;
- rhs.fYmin = fYmin;
- rhs.fYmax = fYmax;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContour::IsInside(Double_t x, Double_t y) const
-{
- /// Whether the point (x,y) is inside one of ours polylines
-// if ( x >= fXmin && x <= fXmax && y >= fYmin && y <= fYmax )
- {
- TIter next(fPolyLines);
- TPolyLine* line;
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- if ( TMath::IsInside(x,y,line->Size(),line->GetX(),line->GetY() ) )
- {
- return kTRUE;
- }
- }
- }
- return kFALSE;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContour::Offset(const TVector2& offset)
-{
- /// Offset all lines by a given offset
-
- TIter next(fPolyLines);
- TPolyLine* line;
-
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- for ( Int_t i = 0; i <= line->GetLastPoint(); ++i )
- {
- Double_t x = line->GetX()[i];
- Double_t y = line->GetY()[i];
- x += offset.X();
- y += offset.Y();
- line->SetPoint(i,x,y);
- }
- }
-
- fXmin += offset.X();
- fXmax += offset.X();
- fYmin += offset.Y();
- fYmax += offset.Y();
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContour::PaintArea(Int_t fillColor, Int_t fillStyle)
-{
- /// Paint a filled contour
-
- Int_t fc = gVirtualX->GetFillColor();
- Int_t fs = gVirtualX->GetFillStyle();
-
- TIter next(fPolyLines);
- TPolyLine* line;
-
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- line->SetFillColor(fillColor);
- line->SetFillStyle(fillStyle);
- line->Paint("F");
- }
-
- gVirtualX->SetFillColor(fc);
- gVirtualX->SetFillStyle(fs);
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContour::PaintOutline(Int_t lineColor, Int_t lineWidth)
-{
- /// Paint the outline of this contour
-
- Int_t lc = gVirtualX->GetLineColor();
- Int_t lw = gVirtualX->GetLineWidth();
-
- TIter next(fPolyLines);
- TPolyLine* line;
-
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- line->SetLineColor(lineColor);
- line->SetLineWidth(lineWidth);
- line->Paint();
- }
-
- gVirtualX->SetLineColor(lc);
- gVirtualX->SetLineWidth(lw);
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContour::Print(Option_t* opt) const
-{
- /// Printout
-
- cout << GetName() << " Ngroups=" << fPolyLines->GetLast()+1;
- TString sopt(opt);
- sopt.ToUpper();
-
- TIter next(fPolyLines);
- TPolyLine* line;
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- cout << " (" << line->Size() << ")";
- if ( sopt.Contains("FULL") )
- {
- cout << endl;
- for ( Int_t i = 0; i < line->Size(); ++i )
- {
- Double_t x = line->GetX()[i];
- Double_t y = line->GetY()[i];
- cout << Form("Point %3d = %7.3f %7.3f",i,x,y) << endl;
- }
- }
- }
- cout << endl;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContour::Transform(const TGeoHMatrix& matrix)
-{
- /// Transform the polylines using the given transformation
-
- TIter next(fPolyLines);
- TPolyLine* line;
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- for ( Int_t i = 0; i < line->Size(); ++i )
- {
- Double_t pl[3] = { line->GetX()[i], line->GetY()[i], 0 };
- Double_t pg[3] = { 0., 0., 0. };
- matrix.LocalToMaster(pl, pg);
- line->SetPoint(i,pg[0],pg[1]);
- }
- }
-
-
- Double_t pl[3] = { fXmin,fYmin, 0 };
- Double_t pg[3] = { 0., 0., 0. };
- matrix.LocalToMaster(pl, pg);
-
- fXmin = pg[0];
- fYmin = pg[1];
-
- pl[0] = fXmax;
- pl[1] = fYmax;
-
- matrix.LocalToMaster(pl, pg);
- fXmax = pg[0];
- fYmax= pg[1];
-}
+++ /dev/null
-#ifndef ALIMUONPAINTERCONTOUR_H
-#define ALIMUONPAINTERCONTOUR_H
-
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
-* See cxx source for full Copyright notice */
-
-// $Id$
-
-/// \ingroup graphics
-/// \class AliMUONPainterContour
-/// \brief Contour(s) of a painter
-///
-// Author Laurent Aphecetche, Subatech
-
-#ifndef ROOT_TNamed
-# include "TNamed.h"
-#endif
-
-class AliMpArea;
-class TObjArray;
-class TPolyLine;
-class TGeoHMatrix;
-class TVector2;
-
-class AliMUONPainterContour : public TNamed
-{
-public:
- AliMUONPainterContour(const char* name="");
- AliMUONPainterContour(const char* name, const AliMpArea& area);
- AliMUONPainterContour(const AliMUONPainterContour& rhs);
- AliMUONPainterContour& operator=(const AliMUONPainterContour& rhs);
- virtual ~AliMUONPainterContour();
-
- AliMpArea Area() const;
-
- /// Add an offset to all points
- void Offset(const TVector2& offset);
-
- /// Apply a global transformation to all points
- void Transform(const TGeoHMatrix& matrix);
-
- void AdoptPolyLine(TPolyLine* line);
-
- virtual void Copy(TObject& obj) const;
-
- Bool_t IsInside(Double_t x, Double_t y) const;
-
- /// Paint the outline
- void Paint(Option_t* ="") { PaintOutline(1,1); }
-
- void PaintOutline(Int_t lineColor, Int_t lineWidth);
-
- void PaintArea(Int_t fillColor, Int_t fillStyle=1001);
-
- virtual void Print(Option_t* opt="") const;
-
- /// Return as an array of polylines
- const TObjArray* AsPolyLines() const { return fPolyLines; }
-
-private:
- TObjArray* fPolyLines; ///< the polylines used to represent to contour
- Double_t fXmin; ///< min x-value
- Double_t fXmax; ///< max x-value
- Double_t fYmin; ///< min y-value
- Double_t fYmax; ///< max y-value
-
- ClassDef(AliMUONPainterContour,1) // Contour for one painter
-};
-
-#endif
+++ /dev/null
-/**************************************************************************
-* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
-* *
-* Author: The ALICE Off-line Project. *
-* Contributors are mentioned in the code where appropriate. *
-* *
-* Permission to use, copy, modify and distribute this software and its *
-* documentation strictly for non-commercial purposes is hereby granted *
-* without fee, provided that the above copyright notice appears in all *
-* copies and that both the copyright notice and this permission notice *
-* appear in the supporting documentation. The authors make no claims *
-* about the suitability of this software for any purpose. It is *
-* provided "as is" without express or implied warranty. *
-**************************************************************************/
-
-// $Id$
-
-#include "AliMUONPainterContourMaker.h"
-
-#include "AliMUONPainterContour.h"
-#include "AliMUONPainterHelper.h"
-#include "AliMUONVCalibParam.h"
-#include "AliMUONVDigit.h"
-#include "AliMpConnection.h"
-#include "AliMpConstants.h"
-#include "AliMpDEManager.h"
-#include "AliMpExMap.h"
-#include "AliMpMotifMap.h"
-#include "AliMpMotifPosition.h"
-#include "AliMpMotifType.h"
-#include "AliMpSector.h"
-#include "AliMpSegmentation.h"
-#include "AliMpSlat.h"
-#include "AliMpStationType.h"
-#include "AliMpVMotif.h"
-#include "AliCodeTimer.h"
-#include "AliLog.h"
-#include <Riostream.h>
-#include <TArrayI.h>
-#include <TGeoMatrix.h>
-#include <TLine.h>
-#include <TMap.h>
-#include <TMath.h>
-#include <TMathBase.h>
-#include <TObjArray.h>
-#include <TPolyLine.h>
-#include <cassert>
-#include <float.h>
-
-/// \class AliMUONPainterContourMaker
-///
-/// A class to build painter contours.
-///
-/// The basics are to build one manu contour, and then to merge contours
-/// to build higher order objects, like PCBS, DEs, etc...
-///
-/// \author Laurent Aphecetche, Subatech
-
-///\cond CLASSIMP
-ClassImp(AliMUONPainterContourMaker)
-ClassImp(AliMUONPainterContourMaker::AliMUONNeighbour)
-///\endcond
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::AliMUONNeighbour::Compare(const TObject* obj) const
-{
- /// Compare two neighbours objects
-
- const AliMUONNeighbour* n = static_cast<const AliMUONNeighbour*>(obj);
-
- if ( Position().X() < n->Position().X() )
- {
- return -1;
- }
- else if ( Position().X() > n->Position().X() )
- {
- return 1;
- }
- else
- {
- // same X
- if ( Position().Y() < n->Position().Y() )
- {
- return -1;
- }
- else if ( Position().Y() > n->Position().Y() )
- {
- return 1;
- }
- }
- return 0;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::AliMUONNeighbour::Print(Option_t*) const
-{
- /// Printout
- cout << Form("ID %10d DE %4d Manu %4d Channel %2d "
- "(X,Y)=(%7.3f,%7.3f) L,R,T,B=%1d,%1d,%1d,%1d",
- ID(),
- AliMUONVDigit::DetElemId(ID()),
- AliMUONVDigit::ManuId(ID()),
- AliMUONVDigit::ManuChannel(ID()),
- Position().X(),Position().Y(),
- HasLeftNeighbour(),HasRightNeighbour(),
- HasTopNeighbour(),HasBottomNeighbour())
- << endl;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContourMaker::AliMUONPainterContourMaker(AliMpExMap* globalTransformations)
-: TObject(),
- fGlobalTransformations(globalTransformations),
- fLocalManuContours(new TMap),
- fContours(new TMap)
-{
- /// ctor
- fContours->SetOwner(kTRUE);
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContourMaker::~AliMUONPainterContourMaker()
-{
- /// dtor
- fLocalManuContours->DeleteAll();
- delete fLocalManuContours;
- fContours->DeleteAll();
- delete fContours;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::Add(AliMUONPainterContour* contour)
-{
- /// Add a contour to our store of contours
- fContours->Add(new TObjString(contour->GetName()),contour);
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
- Double_t x2, Double_t y2, Int_t id) const
-{
- /// Add one segment defined by (x1,y1,x2,y2) to the array of segments
- AliCodeTimerAuto("")
- AliDebug(1,Form("AddSegment %7.3f,%7.3f -> %7.3f,%7.3f",x1,y1,x2,y2));
- TLine* line = new TLine(x1,y1,x2,y2);
- line->SetUniqueID(id);
- segments.Add(line);
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::HasLine(const TObjArray& segments,
- const TLine& line) const
-{
- /// Check whether line is already part of segments array
-
- TIter next(&segments);
- TLine* l;
-
- while ( ( l = static_cast<TLine*>(next()) ) )
- {
- if ( IsEqual(line,*l) ) return kTRUE;
- }
-
- return kFALSE;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::AddSegments(TObjArray& segments,
- const AliMUONPainterContour& contour) const
-
-{
- /// Add all the segments (that are not already there)
- /// of contour to the segments array
-
- AliCodeTimerAuto("")
-
- const TObjArray* pl = contour.AsPolyLines();
-
- TIter next(pl);
-
- Int_t n(0);
-
- TPolyLine* line;
-
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- n += line->GetLastPoint();
- }
-
- AliDebug(1,Form("Adding %d groups (%d lines) from contour %s ",pl->GetLast()+1,n,contour.GetName()));
-
- next.Reset();
-
- while ( ( line = static_cast<TPolyLine*>(next()) ) )
- {
- AliDebug(1,"line=");
-// StdoutToAliDebug(1,line->Print(););
- for ( Int_t i = 0; i < line->GetLastPoint(); ++i )
- {
- Double_t x1 = line->GetX()[i];
- Double_t y1 = line->GetY()[i];
- Double_t x2 = line->GetX()[i+1];
- Double_t y2 = line->GetY()[i+1];
-
- TLine* l = new TLine(x1,y1,x2,y2);
-
- if ( !HasLine(segments,*l) )
- {
- segments.Add(l);
- AliDebug(1,Form("Adding line %s",LineAsString(*l).Data()));
- }
- else
- {
- AliDebug(1,Form("Line %s is already there",LineAsString(*l).Data()));
- }
- }
- }
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour*
-AliMUONPainterContourMaker::ConvertEdgePadsToContour(TObjArray& ePads,
- const char* name) const
-{
- /// Convert an array of edge pads into a contour of a given name
-
- AliCodeTimerAuto("")
-
- ePads.Sort();
-
- AliDebug(1,Form("%d pads to convert:",ePads.GetEntries()));
-// StdoutToAliDebug(1,ePads.Print();)
-
- TObjArray segments;
- segments.SetOwner(kTRUE);
-
- TIter nextPad(&ePads);
- AliMUONNeighbour* ne;
-
- while ( ( ne = static_cast<AliMUONNeighbour*>(nextPad()) ) )
- {
- Int_t id = ne->ID();
-
- if ( ! ne->HasLeftNeighbour() )
- {
- AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
- ne->LowerLeft().X(),ne->UpperRight().Y(),id);
- }
- if ( ! ne->HasRightNeighbour() )
- {
- AddSegment(segments,ne->UpperRight().X(),ne->LowerLeft().Y(),
- ne->UpperRight().X(),ne->UpperRight().Y(),id);
- }
- if ( ! ne->HasTopNeighbour() )
- {
- AddSegment(segments,ne->LowerLeft().X(),ne->UpperRight().Y(),
- ne->UpperRight().X(),ne->UpperRight().Y(),id);
- }
- if ( ! ne->HasBottomNeighbour() )
- {
- AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
- ne->UpperRight().X(),ne->LowerLeft().Y(),id);
- }
- }
-
- return ConvertSegmentsToContour(segments,name);
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::PrintLine(const TLine& line, const char* msg) const
-{
- /// Printout of a line
- cout << Form("%10s %s",
- msg,LineAsString(line).Data()) << endl;
-}
-
-//_____________________________________________________________________________
-TString
-AliMUONPainterContourMaker::LineAsString(const TLine& line, Bool_t slope) const
-{
- /// Return a string representation of the line
-
- TString rv(Form("%7.3f,%7.3f -> %7.3f,%7.3f",
- line.GetX1(),line.GetY1(),
- line.GetX2(),line.GetY2()));
-
- if ( slope )
- {
- if ( IsHorizontal(line) ) rv += " H";
- else if ( IsVertical(line) ) rv += " V";
- else rv += Form(" (slope %e)",Slope(line));
- }
-
- return rv;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::PrintSegments(const TObjArray& segments) const
-{
- /// Printout of segment arrays (debug)
-
- for ( Int_t i = 0; i <= segments.GetLast(); ++i )
- {
- TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
-
- cout << Form("***--- i %4d",i);
- if ( l )
- {
- PrintLine(*l);
- }
- else
- {
- cout << " line is null ?" << endl;
- }
- }
-}
-
-//_____________________________________________________________________________
-TLine*
-AliMUONPainterContourMaker::AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const
-{
- /// Add one segment (taken from position i in array) into polyline
-
- AliDebug(1,Form("i=%d",i));
- TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
- if (l)
- {
- line.SetNextPoint(l->GetX1(),l->GetY1());
- line.SetNextPoint(l->GetX2(),l->GetY2());
- }
- else
- {
- AliError(Form("Did not find the line at i=%d",i));
- PrintSegments(segments);
- }
- return l;
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::FindPoint(Double_t x, Double_t y,
- TObjArray& segments) const
-{
- /// Find if point (x,y) is in segments array, and return
- /// its index (=position within array)
-
- TIter next(&segments);
- TLine* l;
-
- while ( ( l = static_cast<TLine*>(next()) ) )
- {
- if ( IsEqual(l->GetX1(),x) && IsEqual(l->GetY1(),y) )
- {
- return segments.IndexOf(l);
- }
- }
- AliError(Form("Did not find point %7.3f %7.3f in those segments:",x,y));
-// StdoutToAliDebug(1,PrintSegments(segments););
- return -1;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour*
-AliMUONPainterContourMaker::ConvertSegmentsToContour(TObjArray& segments,
- const char* name) const
-{
- /// Convert an array of segments into a contour
-
- AliDebug(1,"");
- AliCodeTimerAuto("");
-
- AliMUONPainterContour* contour = new AliMUONPainterContour(name);
-
- Int_t n(0); // this is a protection against infinite loop (used for debug only)
-
- while ( segments.GetLast() >= 0 && n < 100 )
- {
- TPolyLine lines;
- TIter next(&segments);
- TLine* l;
-
- while ( ( l = static_cast<TLine*>(next() ) ) )
- {
- TLine* inserted = InsertSegment(lines,*l);
- if ( inserted )
- {
- segments.Remove(inserted);
- next.Reset();
- }
-
- // check for closure
- if ( IsLineClosed(lines) )
- {
- AliDebug(1,"Line closed. Starting a new one");
- break;
- }
- }
-
- TPolyLine* sl = Simplify(lines);
-
- contour->AdoptPolyLine(sl);
- ++n;
- }
-
- if ( segments.GetLast() >= 0 )
- {
- AliError("segment should be empty by now");
-// StdoutToAliError(PrintSegments(segments););
- }
-
- return contour;
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const
-{
- /// Return position of (x,y) within the polyline
-
- AliCodeTimerAuto("")
-
- for ( Int_t i = 0; i < lines.Size(); ++i )
- {
- if ( IsEqual(lines.GetX()[i],x) && IsEqual(lines.GetY()[i],y) )
- {
- return i;
- }
- }
- return -1;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::CleanSegments(TObjArray& segments,
- const TArrayI& toBeRemoved) const
-{
- /// Remove segments at indices stored in toBeRemoved array
- for ( Int_t i = 0; i < toBeRemoved.GetSize(); ++i )
- {
- if ( toBeRemoved[i] )
- {
- segments.RemoveAt(i);
- }
- }
- segments.Compress();
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::SplitSegments(TObjArray& segments) const
-{
- /// Split segments that have partial overlap
-
- AliCodeTimerAuto("")
-
- TArrayI toBeRemoved(segments.GetLast()+1);
- toBeRemoved.Reset(0);
- Bool_t added(kFALSE);
-
- for ( Int_t i = 0; i <= segments.GetLast() && !added; ++i )
- {
- if ( toBeRemoved[i] ) continue;
-
- TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
-
- for ( Int_t j = i+1; j <= segments.GetLast() && !added; ++j )
- {
- if ( toBeRemoved[j] ) continue;
-
- TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
-
- Int_t o = Overlap(*li,*lj);
-
- if ( o )
- {
- toBeRemoved[i] = toBeRemoved[j] = 1;
-
- Double_t x[] = { li->GetX1(), lj->GetX1(), li->GetX2(), lj->GetX2() };
- Double_t y[] = { li->GetY1(), lj->GetY1(), li->GetY2(), lj->GetY2() };
-
- Double_t xmin(FLT_MAX), ymin(FLT_MAX);
- Double_t xmax(-FLT_MAX), ymax(-FLT_MAX);
-
- for ( Int_t k = 0; k < 4; ++k )
- {
- xmin = TMath::Min(x[k],xmin);
- ymin = TMath::Min(y[k],ymin);
- xmax = TMath::Max(x[k],xmax);
- ymax = TMath::Max(y[k],ymax);
- }
-
- TLine fullLine(xmin,ymin,xmax,ymax);
-
- for ( Int_t i1 = 0; i1 < 4; ++i1 )
- {
- for ( Int_t j1 = i1+1; j1 < 4; ++j1 )
- {
- if ( TMath::Abs(i1-j1) != 2 )
- {
- TLine test(x[i1],y[i1],x[j1],y[j1]);
-
- Bool_t isFullLine = IsEqual(test,fullLine);
-
- if ( !IsPoint(test) && !isFullLine )
- {
- segments.Add(new TLine(test));
- added = kTRUE;
- }
- }
- }
- }
- }
- }
- }
-
- CleanSegments(segments,toBeRemoved);
-
- return added;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::ShouldBeRemoved(const TObjArray& contours,
- Double_t x, Double_t y) const
-{
- /// Tells whether or not a point can be removed, because it lies
- /// inside the global contour
-
- const Double_t kPrecision(AliMpConstants::LengthTolerance());
- const Double_t kShiftX[] = { kPrecision,kPrecision,-kPrecision,-kPrecision };
- const Double_t kShiftY[] = { kPrecision,-kPrecision,kPrecision,-kPrecision };
-
- TIter next(&contours);
- AliMUONPainterContour* contour;
-
- Int_t n(0);
-
- while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
- {
- for ( Int_t i = 0; i < 4; ++i )
- {
- if ( contour->IsInside( x + kShiftX[i], y + kShiftY[i]) )
- {
- ++n;
- }
- }
- }
-
- return (n>=4);
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::RemoveInsideSegments(const TObjArray& contours,
- TObjArray& segments) const
-{
- /// Remove segments that have 2 triple points
-
- AliCodeTimerAuto("")
-
- TArrayI toBeRemoved(segments.GetLast()+1);
- toBeRemoved.Reset(0);
-
- for ( Int_t i = 0; i <= segments.GetLast(); ++i )
- {
- TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
-
- Double_t x = (line->GetX1() + line->GetX2())/2.0;
- Double_t y = (line->GetY1() + line->GetY2())/2.0;
-
- if ( ShouldBeRemoved(contours,x,y) )
- {
- toBeRemoved[i] = 1;
- }
- }
-
- Int_t before = segments.GetLast()+1;
-
- CleanSegments(segments,toBeRemoved);
-
- Int_t after = segments.GetLast()+1;
-
- AliDebug(1,Form("# of segments before = %d after = %d",before,after));
-
- return after-before;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour*
-AliMUONPainterContourMaker::MergeContours(const TObjArray& contours,
- const char* contourName) const
-{
- /// Merge an array of contours into a single contour, with a given name
-
- AliCodeTimerAuto("");
-
- AliDebug(1,Form("Merging %d contours into %s",contours.GetLast()+1,contourName));
-
- if ( contours.GetSize() == 0 ) return 0x0;
-
- TIter next(&contours);
- AliMUONPainterContour* contour;
-
- TObjArray segments;
- segments.SetOwner(kTRUE);
-
- while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
- {
- AddSegments(segments,*contour);
- }
-
-// AliDebug(1,"After AddSegments");
-// StdoutToAliDebug(1,PrintSegments(segments));
-
- while (SplitSegments(segments)) {}
-
-// AliDebug(1,"After SplitSegments");
-// StdoutToAliDebug(1,PrintSegments(segments));
-
-// if (!SanityCheck(contours,segments))
-// {
-// return 0x0;
-// }
-
- RemoveInsideSegments(contours,segments);
-
-// if (!SanityCheck(contours,segments))
-// {
-// return 0x0;
-// }
-
-// AliDebug(1,"After RemoveInsideSegments");
-// StdoutToAliDebug(1,PrintSegments(segments););
-
-// if (!SanityCheck(contours,segments))
-// {
-// return 0x0;
-// }
-
- return ConvertSegmentsToContour(segments,contourName);
-}
-
-//_____________________________________________________________________________
-TString
-AliMUONPainterContourMaker::NameIt(const AliMpMotifPosition& motifPosition) const
-{
- /// Get the name of an AliMpMotifPosition
-
- AliMpVMotif* motif = motifPosition.GetMotif();
- TString name(Form("%s",motif->GetID().Data()));
-
- for ( Int_t i = 0; i < motif->GetNofPadDimensions(); ++i )
- {
- name += Form("/%7.3f-%7.3f:",motif->GetPadDimensionX(i),motif->GetPadDimensionY(i));
- }
- return name;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour*
-AliMUONPainterContourMaker::FindLocalManuContour(Int_t detElemId, Int_t manuId) const
-{
- /// Get a pre-computed manu contour (in local coordinates)
- AliCodeTimerAuto("")
-
- AliMpMotifPosition* motifPos = FindMotifPosition(detElemId,manuId);
-
- TObject* o = fLocalManuContours->GetValue(NameIt(*motifPos));
-
- if (o) return static_cast<AliMUONPainterContour*>(o);
- return 0x0;
-}
-
-//_____________________________________________________________________________
-AliMpMotifPosition*
-AliMUONPainterContourMaker::FindMotifPosition(Int_t detElemId, Int_t manuId) const
-{
- /// Find a given motifPosition object
-
- AliCodeTimerAuto("")
-
- AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
-
- if ( stationType == AliMp::kStation345 )
- {
- const AliMpSlat* kSlat
- = AliMpSegmentation::Instance()->GetSlatByElectronics(detElemId,manuId);
- if ( ! kSlat ) {
- AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
- }
- return kSlat->FindMotifPosition(manuId);
- }
- else
- {
- const AliMpSector* kSector
- = AliMpSegmentation::Instance()->GetSectorByElectronics(detElemId,manuId);
- if ( ! kSector ) {
- AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
- }
- return kSector->GetMotifMap()->FindMotifPosition(manuId);
- }
- return 0x0;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour*
-AliMUONPainterContourMaker::GenerateManuContour(const char* name,
- Int_t detElemId, Int_t manuId,
- AliMUONAttPainter viewType) const
-{
- /// Generate the contour for a given manu
-
- AliDebug(3,Form("DE %04d ManuID %04d Name %s",detElemId,manuId,name));
-
- AliCodeTimerAuto("")
-
- AliMpMotifPosition* motifPosition = FindMotifPosition(detElemId,manuId);
- AliMpVMotif* motif = motifPosition->GetMotif();
-
- AliMUONPainterContour* contour = FindLocalManuContour(detElemId,manuId);
- // do we already have the local contour for that manu ?
-
- // no : build it
- if (!contour)
- {
- AliCodeTimerAuto("Generation of local contour");
- TObjArray ePads;
- ePads.SetOwner(kTRUE);
- AliMpMotifType* motifType = motif->GetMotifType();
- AliDebug(3,Form("motifType %s",motifType->GetID().Data()));
-
-// for ( Int_t i = 0; i <= motifType->GetNofPads(); ++i )
- for ( Int_t i = 0; i <= AliMpConstants::ManuNofChannels(); ++i )
- {
-// AliMpConnection* connection = motifType->FindConnectionByPadNum(i);
- AliMpConnection* connection = motifType->FindConnectionByGassiNum(i);
-
- AliDebug(3,Form("connection i =%d",i));
-
- if ( connection )
- {
- Int_t ix = connection->GetLocalIx();
- Int_t iy = connection->GetLocalIy();
- Bool_t left(kTRUE);
- Bool_t right(kTRUE);
- Bool_t top(kTRUE);
- Bool_t bottom(kTRUE);
-
- if ( ! motifType->FindConnectionByLocalIndices(ix+1, iy) )
- {
- right = kFALSE;
- }
- if ( ! motifType->FindConnectionByLocalIndices(ix-1, iy) )
- {
- left = kFALSE;
- }
- if ( ! motifType->FindConnectionByLocalIndices(ix, iy+1) )
- {
- top = kFALSE;
- }
- if ( ! motifType->FindConnectionByLocalIndices(ix, iy-1) )
- {
- bottom = kFALSE;
- }
-
- AliDebug(3,Form("indices=(%3d,%3d) L %d R %d T %d B %d",
- ix,iy, left,right,top,bottom));
-
- Double_t posx, posy;
- motif->PadPositionLocal(ix, iy, posx, posy);
-
- Double_t dx, dy;
- motif->GetPadDimensionsByIndices(ix, iy, dx, dy);
-
- if ( !left || !right || !top || !bottom )
- {
- // the pad is on the edge
- Int_t id = AliMUONVDigit::BuildUniqueID(detElemId,manuId,
- connection->GetManuChannel(),0);
- ePads.AddLast(new AliMUONNeighbour(id,TVector2(posx, posy),TVector2(dx, dy),left,right,top,bottom));
- }
- }
- }
-
- contour = ConvertEdgePadsToContour(ePads,NameIt(*motifPosition));
-
- AliDebug(1,Form("localContour:"));
-// StdoutToAliDebug(1,contour->Print("full"));
- // register the local contour
- fLocalManuContours->Add(new TObjString(contour->GetName()),contour);
- }
-
- AliMUONPainterContour* globalContour = static_cast<AliMUONPainterContour*>(contour->Clone(name));
-
- // once we have the local contour, convert it to global
-
- TVector2 pos(motifPosition->GetPositionX(), motifPosition->GetPositionY());
-
- if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 )
- {
- const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(detElemId,manuId);
- pos -= TVector2(slat->GetPositionX(),slat->GetPositionY()) ;
- }
- globalContour->Offset(pos);
- TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
- globalContour->Transform(*matrix);
-
- if ( viewType.IsBackView() )
- {
- AliWarning("Got a back view : will rotate ! This has not been really tested. Please do so now !");
- TGeoRotation rot;
- rot.RotateZ(180);
- globalContour->Transform(rot);
- }
-
- return globalContour;
-}
-
-//_____________________________________________________________________________
-AliMUONPainterContour*
-AliMUONPainterContourMaker::GetContour(const char* name) const
-{
- /// Get contour by name
-
- TObject* o = fContours->GetValue(name);
- return static_cast<AliMUONPainterContour*>(o);
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::HasContour(const char* name) const
-{
- /// Whether contour named "name" exists
- TObject* o = fContours->GetValue(name);
- if (o) return kTRUE;
- return kFALSE;
-}
-
-//_____________________________________________________________________________
-TLine*
-AliMUONPainterContourMaker::InsertSegment(TPolyLine& lines, TLine& l) const
-{
- /// Insert line into polyline, at the correct position
-
- AliCodeTimerAuto("")
-// AliDebug(2,Form("Trying to insert %7.3f,%7.3f -> %7.3f,%7.3f from "
-// "(DE,manu,ch)=(%d,%d,%d) into",
-// l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2(),
-// AliMUONVDigit::DetElemId(l.GetUniqueID()),
-// AliMUONVDigit::ManuId(l.GetUniqueID()),
-// AliMUONVDigit::ManuChannel(l.GetUniqueID())));
-
- if ( lines.Size()==0 )
- {
-// AliDebug(2,"Starting line");
-//
- lines.SetNextPoint(l.GetX1(),l.GetY1());
- lines.SetNextPoint(l.GetX2(),l.GetY2());
- return &l;
- }
-
- Int_t i1 = FindPoint(lines,l.GetX1(),l.GetY1());
- Int_t i2 = FindPoint(lines,l.GetX2(),l.GetY2());
-
- if ( i1 < 0 && i2 < 0 )
- {
-// AliDebug(2,"Not yet");
- return 0x0;
- }
-
- if ( i1 >= 0 && i2 >= 0 )
- {
- if ( i1==0 )
- {
- lines.SetNextPoint(l.GetX1(),l.GetY1());
- }
- else if ( i2==0 )
- {
- lines.SetNextPoint(l.GetX2(),l.GetY2());
- }
- else
- {
- AliError("Segment already there but does not correspond to ending the polyline !");
- AliError(Form("Segment is %7.3f,%7.3f -> %7.3f,%7.3f and existing points are : ",
- l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2()));
-
- for ( Int_t i = 0; i < lines.Size(); ++i )
- {
- AliError(Form("Point %2d X %7.3f Y %7.3f",i,lines.GetX()[i],lines.GetY()[i]));
- }
-// TObject* o(0x0);
-// o->Print(); // to crash and throw gdb...
- }
- return &l;
- }
-
- Double_t x = (i1>=0) ? l.GetX2() : l.GetX1();
- Double_t y = (i1>=0) ? l.GetY2() : l.GetY1();
-
- Int_t iref = ( i1 >= 0 ? i1 : i2 ) ;
-
- Bool_t firstPoint = ( iref == 0 );
-
- if ( firstPoint )
- {
- // must insert segment before
- lines.SetPolyLine(lines.Size()+1);
-// AliDebug(2,Form("Inserting %7.3f,%7.3f",x,y));
- for ( Int_t i = lines.Size()-1; i > 0; --i )
- {
- lines.SetPoint(i,lines.GetX()[i-1],lines.GetY()[i-1]);
- }
- lines.SetPoint(0,x,y);
- }
- else
- {
-// AliDebug(2,Form("Appending %7.3f,%7.3f",x,y));
- lines.SetNextPoint(x,y);
- }
-
- return &l;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsEqual(Double_t x, Double_t y) const
-{
- /// Whether x==y
-
- if ( TMath::Abs(x-y) < AliMpConstants::LengthTolerance() ) return kTRUE;
- else return kFALSE;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsEqual(const TLine& line1,
- const TLine& line2) const
-{
- /// Whether line1 == line2
-
- Bool_t check1 =
- IsEqual(line1.GetX1(),line2.GetX1()) &&
- IsEqual(line1.GetY1(),line2.GetY1()) &&
- IsEqual(line1.GetX2(),line2.GetX2()) &&
- IsEqual(line1.GetY2(),line2.GetY2());
-
- Bool_t check2 =
- IsEqual(line1.GetX1(),line2.GetX2()) &&
- IsEqual(line1.GetY1(),line2.GetY2()) &&
- IsEqual(line1.GetX2(),line2.GetX1()) &&
- IsEqual(line1.GetY2(),line2.GetY1());
-
- return (check1 || check2);
-}
-
-//_____________________________________________________________________________
-Double_t
-AliMUONPainterContourMaker::Slope(const TLine& line) const
-{
- /// Get the slope of line
-
- Double_t x = TMath::Abs(line.GetX2() - line.GetX1());
-
- if ( x < AliMpConstants::LengthTolerance() ) return FLT_MAX;
-
- return TMath::Abs(line.GetY2() - line.GetY1())/x;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsPoint(const TLine& line) const
-{
- /// Whether the line is a point (sic ;-) )
- return
- IsEqual(line.GetX1(),line.GetX2()) &&
- IsEqual(line.GetY1(),line.GetY2());
-}
-
-//_____________________________________________________________________________
-TLine
-AliMUONPainterContourMaker::Shift(const TLine& line, Double_t x, Double_t y) const
-{
- /// Shift the line by a given offset
-
- return TLine(line.GetX1()-x,line.GetY1()-y,line.GetX2()-x,line.GetY2()-y);
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::SameDirection(const TLine& line1, const TLine& line2) const
-{
- /// Whether both lines have the same direction.
-
- TLine l1 = Shift(line1,line1.GetX1(),line1.GetY1());
- TLine l2 = Shift(line2,line2.GetX1(),line2.GetY1());
-
- Double_t v = l1.GetX2()*l2.GetX2() + l1.GetY2()*l2.GetY2();
-
- return v > 0 ;
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::Swap(TLine& line) const
-{
- /// Swap both points of the line
-
- Double_t x = line.GetX1();
- Double_t y = line.GetY1();
-
- line.SetX1(line.GetX2());
- line.SetY1(line.GetY2());
- line.SetX2(x);
- line.SetY2(y);
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::IsInRange(Double_t x, Double_t a, Double_t b,
- Bool_t strict) const
-{
- /// Whether w is in [a,b] (if strict=kFALSE) or in ]a,b[ (if strict=kTRUE)
-
- if ( a > b )
- {
- Double_t tmp(b);
- b = a;
- a = tmp;
- }
-
- Bool_t rv(kFALSE);
-
- if ( strict )
- {
- rv = ( x > a && x < b );
- }
- else
- {
- rv = ( x >= a && x <= b);
- }
-
- AliDebug(4,Form("x = %7.3f a = %7.3f b = %7.3f strict = %d IsInRange = %d",x,a,b,strict,rv));
-
- return rv;
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::IsInLine(const TLine& line,
- Double_t x,
- Double_t y,
- Bool_t strict) const
-{
- /// Check whether point (x,y) is belonging to the line segment
- /// by computing the distance point to line
- /// line1 must not be a single point.
- /// Returns the number of *coordinates* that matches, for a point
- /// that lies on line (if point is not on the line, returns 0 always).
- /// For instance, if (x,y) is on the line (and strict=kFALSE),
- /// it will return 1 if x *or* y corresponds to line.GetX1() or X2 or Y1 or Y2,
- /// and 2 if the pair (x,y) corresponds to one of the line points.
-
- Double_t x1 = line.GetX1();
- Double_t x2 = line.GetX2();
- Double_t y1 = line.GetY1();
- Double_t y2 = line.GetY2();
-
- Double_t distance = TMath::Abs( (x2-x1)*(y1-y) - (x1-x)*(y2-y1) );
-
- distance /= TMath::Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
-
- Bool_t online = ( distance < AliMpConstants::LengthTolerance() ) ;
-
- Int_t rv(0);
-
- if (online)
- {
- // point is on the line,
- // check in addition that it's within the segment
-
- rv = IsInRange(x,x1,x2,strict) + IsInRange(y,y1,y2,strict);
- }
- else
- {
- rv = 0;
- }
-
- AliDebug(4,Form("Point (%7.3f,%7.3f) isinline=%d in line %s",
- x,y,rv,LineAsString(line).Data()));
-
- return rv;
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::IsInside(const TLine& line1,
- const TLine& line2,
- Bool_t useEndPoints) const
-{
- /// Check whether one or both points of line2 are within line1.
- /// Both line1 and line2 must have the same slope
- /// and the same direction
-
- if (!IsEqual(Slope(line1),Slope(line2))) return 0;
-
- TLine l2(line2);
-
- if (!SameDirection(line1,line2))
- {
- Swap(l2);
- }
-
- Int_t rv =
- IsInLine(line1,l2.GetX1(),l2.GetY1(),!useEndPoints) +
- IsInLine(line1,l2.GetX2(),l2.GetY2(),!useEndPoints);
-
- assert(rv<=4);
-
- return rv;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsInside(const TObjArray& segments,
- const TLine& line) const
-{
- /// Whether the segment (line) is contained inside the contour defined
- /// by all the segments (i.e. is it on the boundary or not)
- /// Basic (and dirty) implementation only working with horizontal and vertical lines.
- /// I know there must be a better way to do it, but it took me way too long
- /// to get this stuff working, so I'm giving up on the optimisation/cleaning,
- /// at least for now...
- /// If you'd like to clean this (while keeping it working in all cases), be
- /// my guest and do it ;-) )
-
- Int_t p1 = CountPoint(segments,line.GetX1(),line.GetY1());
- Int_t p2 = CountPoint(segments,line.GetX2(),line.GetY2());
-
- Bool_t triplet = ( p1 >= 3 || p2 >= 3 );
-
- AliDebug(4,Form("IsInside(segments,%s) triplet=%d",
- LineAsString(line).Data(),triplet));
-
- if (!triplet) return kFALSE;
-
- Bool_t top(kFALSE), bottom(kFALSE), left(kFALSE), right(kFALSE);
-
- Bool_t vertical(IsVertical(line));
- Bool_t horizontal(IsHorizontal(line));
-
- if (!vertical && !horizontal )
- {
- AliFatal("Only working with horizontal and vertical lines");
- }
-
- for ( Int_t i = 0; i <= segments.GetLast(); ++i )
- {
- TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
-
- if ( IsEqual(*l,line) ) continue;
-
- if ( vertical && IsVertical(*l) )
- {
- TLine tmpLine(l->GetX1(),line.GetY1(),
- l->GetX1(),line.GetY2());
-
- AliDebug(4,Form("i=%2d VV\nIsInside(l=%s,%s)=%d\nIsInside(%s,l=%s)=%d",
- i,
- LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
- IsInside(*l,tmpLine,kTRUE),
- LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
- IsInside(tmpLine,*l,kTRUE)));
-
- if ( IsInside(*l,tmpLine,kTRUE) == 4 || IsInside(tmpLine,*l,kTRUE) == 4 )
- {
- if ( l->GetX1() > line.GetX1() )
- {
- right = kTRUE;
- }
- else
- {
- left = kTRUE;
- }
- }
- }
-
- if ( vertical && IsHorizontal(*l) )
- {
- if ( !IsEqual(l->GetY1(),line.GetX1()) &&
- !IsEqual(l->GetY1(),line.GetY2()) &&
- IsInLine(*l,line.GetX1(),l->GetY1(),kFALSE)==2 )
- {
- if ( line.GetY2() < l->GetY1() )
- {
- top = kTRUE;
- }
- else if ( line.GetY2() > l->GetY1() )
- {
- bottom = kTRUE;
- }
- }
- }
-
- if ( horizontal && IsHorizontal(*l) )
- {
- TLine tmpLine(line.GetX1(),l->GetY1(),
- line.GetX2(),l->GetY1());
-
- AliDebug(4,Form("i=%2d HH\nIsInside(%s,%s)=%d\nIsInside(%s,%s)=%d",
- i,
- LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
- IsInside(*l,tmpLine),
- LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
- IsInside(tmpLine,*l)));
-
- if ( IsInside(*l,tmpLine) == 4 || IsInside(tmpLine,*l) == 4 )
- {
- if ( l->GetY1() > line.GetY1() )
- {
- top = kTRUE;
- }
- else
- {
- bottom = kTRUE;
- }
- }
- }
-
- if ( horizontal && IsVertical(*l) )
- {
- if ( !IsEqual(l->GetX1(),line.GetX1()) &&
- !IsEqual(l->GetX1(),line.GetX2()) &&
- IsInLine(*l,l->GetX1(),line.GetY1(),kFALSE)==2 )
- {
- if ( line.GetX2() < l->GetX1() )
- {
- right = kTRUE;
- }
- else if ( line.GetX2() > l->GetX1() )
- {
- left = kTRUE;
- }
- }
- }
-
- }
-
- Bool_t rv(kFALSE);
-
- AliDebug(3,Form("%s %s R %d L %d T %d B% d IsInside %d",
- IsVertical(line) ?
- "Vertical " :
- "Horizontal",
- LineAsString(line,kFALSE).Data(),right,left,top,bottom,rv));
-
- if ( vertical )
- {
- rv = (right && left) && ( top || bottom );
- }
-
- if ( horizontal )
- {
- rv = (top && bottom) && ( right || left );
- }
-
- return rv;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsHorizontal(const TLine& line) const
-{
- /// whether line is horizontal
-
- static Double_t l2 = AliMpConstants::LengthTolerance()*AliMpConstants::LengthTolerance();
-
- return ( Slope(line) < l2 );
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsVertical(const TLine& line) const
-{
- /// whether line is vertical
-
- return ( TMath::Abs(Slope(line)) == FLT_MAX );
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::Overlap(const TLine& line1,
- const TLine& line2) const
-{
- /// Whether line1 and line2 overlap
-
- Int_t rv(0);
-
- if ( IsEqual(line1,line2) )
- {
- // First things first. If both lines are the same one,
- // they for sure overlap ;-)
- rv = 4;
- }
- else
- {
- rv = IsInside(line1,line2) + IsInside(line2,line1);
- }
-
- AliDebug(3,Form("%s and %s : overlap=%d",
- LineAsString(line1).Data(),
- LineAsString(line2).Data(),
- rv));
-
- return rv;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::IsLineClosed(const TPolyLine& line) const
-{
- /// check if polyline is already closed (i.e. last point = first point)
-
- Double_t* x = line.GetX();
- Double_t* y = line.GetY();
-
- if ( IsEqual(x[line.GetLastPoint()],x[0]) &&
- IsEqual(y[line.GetLastPoint()],y[0]) )
- {
- return kTRUE;
- }
- else
- {
- return kFALSE;
- }
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::Local2Global(Int_t detElemId,
- Double_t xl, Double_t yl, Double_t zl,
- Double_t& xg, Double_t& yg, Double_t& zg) const
-{
- /// Convert local coordinates to global ones
- TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
- Double_t pl[3] = { xl, yl, zl };
- Double_t pg[3] = { 0., 0., 0. };
- matrix->LocalToMaster(pl, pg);
- xg = pg[0];
- yg = pg[1];
- zg = pg[2];
-}
-
-//_____________________________________________________________________________
-void
-AliMUONPainterContourMaker::Print(Option_t* opt) const
-{
- /// Printout
-
- cout << "Local Contours" << endl;
-
- TIter next(fLocalManuContours);
- TObjString* key;
-
- while ( ( key = static_cast<TObjString*>(next()) ) )
- {
- cout << key->String().Data() << endl;
- AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fLocalManuContours->GetValue(key));
- contour->Print(opt);
- }
-
- cout << "Global Contours" << endl;
-
- TIter nextC(fContours);
-
- while ( ( key = static_cast<TObjString*>(nextC()) ) )
- {
- AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fContours->GetValue(key));
- contour->Print(opt);
- }
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::CountPoint(const TObjArray& segments,
- Double_t x, Double_t y) const
-{
- /// Count the number of times the point (x,y) appears in the segment array
-
- Int_t n(0);
-
- for ( Int_t i = 0; i <= segments.GetLast(); ++i )
- {
- TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
-
- if ( IsEqual(x,line->GetX1()) &&
- IsEqual(y,line->GetY1()) )
- {
- ++n;
- }
-
- if ( IsEqual(x,line->GetX2()) &&
- IsEqual(y,line->GetY2()) )
- {
- ++n;
- }
- }
-
- return n;
-}
-
-//_____________________________________________________________________________
-Bool_t
-AliMUONPainterContourMaker::SanityCheck(const TObjArray& contours,
- const TObjArray& segments, Bool_t check) const
-{
- /// (debug) check
-
- Bool_t ok(kTRUE);
-
- // cross-check that we have no more complete duplicates
- // and that we have no orphan point
-
- Double_t xmin(FLT_MAX), xmax(-FLT_MAX);
- Double_t ymin(FLT_MAX), ymax(-FLT_MAX);
-
- for ( Int_t i = 0; i <= segments.GetLast(); ++i )
- {
- TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
-
- if (!IsHorizontal(*li) && !IsVertical(*li))
- {
- AliError("Got an oblique line !");
- return kFALSE;
- }
-
- xmin = TMath::Min(xmin,li->GetX1());
- xmin = TMath::Min(xmin,li->GetX2());
-
- xmax = TMath::Max(xmax,li->GetX1());
- xmax = TMath::Max(xmax,li->GetX2());
-
- ymin = TMath::Min(ymin,li->GetY1());
- ymin = TMath::Min(ymin,li->GetY2());
-
- ymax = TMath::Max(ymax,li->GetY1());
- ymax = TMath::Max(ymax,li->GetY2());
-
- }
-
- AliDebug(1,Form("xmin=%7.3f ymin=%7.3f xmax=%7.3f ymax=%7.3f",
- xmin,ymin,xmax,ymax));
-
- for ( Int_t i = 0; i <= segments.GetLast(); ++i )
- {
- TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
-
- if (!check)
- {
- for ( Int_t j = 0; j <= segments.GetLast(); ++j )
- {
- TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
-
- if ( i != j && IsEqual(*li,*lj) )
- {
- ok = kFALSE;
- PrintLine(*li);
- PrintLine(*lj);
- AliFatal("");
- }
- }
- }
-
-
- Int_t rv(0);
-
- Double_t x = (li->GetX1()+li->GetX2())/2.0;
- Double_t y = (li->GetY1()+li->GetY2())/2.0;
-
- if ( ShouldBeRemoved(contours,x,y) ) rv = 1;
-
- AliDebug(1,Form("Line %4d %7.3f,%7.3f -> %7.3f,%7.3f [ %d ]",
- i,
- li->GetX1(),li->GetY1(),
- li->GetX2(),li->GetY2(),
- rv));
- }
-
- return kTRUE;
-}
-
-//_____________________________________________________________________________
-TPolyLine*
-AliMUONPainterContourMaker::Simplify(const TPolyLine& lines) const
-{
- /// try to simplify the polyline, by minimizing the number of points
-
- if ( lines.Size() < 3 )
- {
- AliError("Cannot simplify lines with less that 3 points !");
- return 0x0;
- }
-
- AliCodeTimerAuto("")
-
-// cout << "Before simplify" << endl;
-//
-// for ( Int_t i = 0; i < lines.Size(); ++i )
-// {
-// cout << Form("Point %3d %7.3f %7.3f",i,lines.GetX()[i],lines.GetY()[i]) << endl;
-// }
-
- TPolyLine* l = new TPolyLine;
-
- Double_t* x = lines.GetX();
- Double_t* y = lines.GetY();
-
- l->SetNextPoint(x[0],y[0]);
-
- Bool_t verticalCurrent = IsEqual(x[1],x[0]);
- Bool_t horizontalCurrent = IsEqual(y[1],y[0]);
-
- Int_t i(2);
-
- while ( i < lines.Size() )
- {
- Bool_t vertical = IsEqual(x[i],x[i-1]);
- Bool_t horizontal = IsEqual(y[i],y[i-1]);
-
-// cout << Form("i %3d %7.3f %7.3f vert %d horiz %d (current vert %d horiz %d)",
-// i,x[i],y[i],vertical,horizontal,verticalCurrent,horizontalCurrent)
-// << endl;
-
- if ( ( vertical != verticalCurrent ) ||
- ( horizontal != horizontalCurrent ) )
- {
-// cout << Form("Changing direction : adding point %7.3f %7.3f",x[i-1],y[i-1]) << endl;
- l->SetNextPoint(x[i-1],y[i-1]);
- verticalCurrent = vertical;
- horizontalCurrent = horizontal;
- }
- ++i;
- }
-
- l->SetNextPoint(l->GetX()[0],l->GetY()[0]);
-
-// cout << "After simplify" << endl;
-//
-// for ( Int_t i = 0; i < l->Size(); ++i )
-// {
-// cout << Form("Point %3d %7.3f %7.3f",i,l->GetX()[i],l->GetY()[i]) << endl;
-// }
-
- return l;
-}
-
-//_____________________________________________________________________________
-Int_t
-AliMUONPainterContourMaker::Size() const
-{
- /// Number of contours we have already
-
- return fContours->GetSize();
-}
-
+++ /dev/null
-#ifndef ALIMUONPAINTERCONTOURMAKER_H
-#define ALIMUONPAINTERCONTOURMAKER_H
-
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
-* See cxx source for full Copyright notice */
-
-// $Id$
-
-/// \ingroup graphics
-/// \class AliMUONPainterContourMaker
-/// \brief Utility class to build painter contours
-///
-// Author Laurent Aphecetche, Subatech
-
-#ifndef ROOT_TVector2
-# include "TVector2.h"
-#endif
-
-#ifndef ROOT_TObject
-# include "TObject.h"
-#endif
-
-#ifndef ALIMUONVPAINTER_H
-# include "AliMUONVPainter.h"
-#endif
-
-class AliMpExMap;
-class AliMpMotifPosition;
-class AliMUONAttPainter;
-class AliMUONPainterContour;
-class AliMUONPainterPadStore;
-class TArrayI;
-class TMap;
-#include <TLine.h>
-class TPolyLine;
-class TObjArray;
-
-class AliMUONPainterContourMaker : public TObject
-{
-public:
- AliMUONPainterContourMaker(AliMpExMap* globalTransformations=0x0);
- virtual ~AliMUONPainterContourMaker();
-
- void Add(AliMUONPainterContour* contour);
-
- AliMUONPainterContour* FindLocalManuContour(Int_t detElemId, Int_t manuId) const;
-
- AliMUONPainterContour* GetContour(const char* name) const;
-
- AliMUONPainterContour* GenerateManuContour(const char* name,
- Int_t detElemId,
- Int_t manuId,
- AliMUONAttPainter viewType) const;
-
- Bool_t HasContour(const char* name) const;
-
- AliMUONPainterContour* MergeContours(const TObjArray& contours,
- const char* contourName) const;
-
- Int_t Size() const;
-
- void Print(Option_t* opt="") const;
-
-public:
-
- /// \ingroup graphics
- /// \brief Store information about one pad's neighbours.
- /// \author Laurent Aphecetche, Subatech
- class AliMUONNeighbour : public TObject
- {
-public:
- /// default ctor
- AliMUONNeighbour()
- : fID(-1), fPosition(), fDimensions(),
- fLeft(kFALSE), fRight(kFALSE),
- fTop(kFALSE), fBottom(kFALSE) {}
-
- /// normal ctor
- AliMUONNeighbour(Int_t absID,
- const TVector2& position,
- const TVector2& dimensions,
- Bool_t hasLeftNeighbour, Bool_t hasRightNeighbour,
- Bool_t hasTopNeighbour, Bool_t hasBottomNeighbour)
- : fID(absID), fPosition(position), fDimensions(dimensions),
- fLeft(hasLeftNeighbour), fRight(hasRightNeighbour),
- fTop(hasTopNeighbour), fBottom(hasBottomNeighbour) {}
-
- /// dtor
- virtual ~AliMUONNeighbour() {}
-
- /// we are sortable
- virtual Bool_t IsSortable() const { return kTRUE; }
-
- virtual Int_t Compare(const TObject* object) const;
-
- /// our id
- Int_t ID() const { return fID; }
-
- /// Whether we have a neighbour on our left
- Bool_t HasLeftNeighbour() const { return fLeft; }
- /// Whether we have a neighbour on our right
- Bool_t HasRightNeighbour() const { return fRight; }
- /// Whether we have a neighbour above
- Bool_t HasTopNeighbour() const { return fTop; }
- /// Whether we have a neighbour below
- Bool_t HasBottomNeighbour() const { return fBottom; }
-
- /// Our position
- TVector2 Position() const { return fPosition; }
- /// Our (half-)dimensions
- TVector2 Dimensions() const { return fDimensions; }
-
- /// Lower left corner
- TVector2 LowerLeft() const { return fPosition - fDimensions; }
- /// Upper right corner
- TVector2 UpperRight() const { return fPosition + fDimensions; }
-
- void Print(Option_t* opt="") const;
-
- /// Set our position
- void SetPosition(Double_t x, Double_t y) { fPosition.Set(x,y); }
-
-private:
- Int_t fID; ///< id of the pad
- TVector2 fPosition; ///< position
- TVector2 fDimensions; ///< (half)dimension
- Bool_t fLeft; ///< do we have a neighbour on our left ?
- Bool_t fRight; ///< do we have a neighbour on our right ?
- Bool_t fTop; ///< do we have a neighbour on top of us ?
- Bool_t fBottom; ///< do we have a neighbour below us ?
-
- ClassDef(AliMUONNeighbour,1) // Neighbour internal class
- };
-
-
-public:
-
-
- void AddSegments(TObjArray& segments, const AliMUONPainterContour& contour) const;
-
- void AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
- Double_t x2, Double_t y2, Int_t padID) const;
-
- TLine* AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const;
-
- AliMpMotifPosition* FindMotifPosition(Int_t detElemId, Int_t manuId) const;
-
- Int_t FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const;
-
- Int_t FindPoint(Double_t x, Double_t y, TObjArray& segments) const;
-
- TLine* InsertSegment(TPolyLine& lines, TLine& l) const;
-
- using TObject::IsEqual;
-
- Bool_t IsEqual(Double_t x, Double_t y) const;
-
- Int_t Overlap(const TLine& line1, const TLine& line2) const;
-
- Bool_t IsLineClosed(const TPolyLine& line) const;
-
- AliMUONPainterContour* ConvertEdgePadsToContour(TObjArray& edgePads, const char* name) const;
-
- AliMUONPainterContour* ConvertSegmentsToContour(TObjArray& segments, const char* name) const;
-
- void Local2Global(Int_t detElemId, Double_t xl, Double_t yl, Double_t zl,
- Double_t& xg, Double_t& yg, Double_t& zg) const;
-
- TString NameIt(const AliMpMotifPosition& motifPosition) const;
-
- TPolyLine* Simplify(const TPolyLine& lines) const;
-
- Double_t Slope(const TLine& line) const;
-
- Bool_t IsPoint(const TLine& line) const;
-
- void PrintLine(const TLine& line, const char* msg="") const;
-
- void PrintSegments(const TObjArray& segments) const;
-
- Bool_t SameDirection(const TLine& line1, const TLine& line2) const;
-
- void Swap(TLine& line) const;
-
- TLine Shift(const TLine& line, Double_t x, Double_t y) const;
-
- Int_t IsInside(const TLine& line1, const TLine& line2,
- Bool_t useEndPoints=kFALSE) const;
-
- Bool_t IsInside(const TObjArray& segments, const TLine& line) const;
-
- Int_t IsInLine(const TLine& line, Double_t x, Double_t y,
- Bool_t strict=kTRUE) const;
-
- Bool_t IsEqual(const TLine& line1, const TLine& line2) const;
-
- Bool_t SanityCheck(const TObjArray& contours, const TObjArray& segments, Bool_t check=kTRUE) const;
-
- TString LineAsString(const TLine& line, Bool_t slope=kTRUE) const;
-
- Int_t IsInRange(Double_t x, Double_t a, Double_t b,
- Bool_t strict=kTRUE) const;
-
- Bool_t HasLine(const TObjArray& segments, const TLine& line) const;
-
- void CleanSegments(TObjArray& segments, const TArrayI& toBeRemoved) const;
-
- Int_t SplitSegments(TObjArray& segments) const;
-
- Int_t RemoveInsideSegments(const TObjArray& contours, TObjArray& segments) const;
-
- Bool_t IsHorizontal(const TLine& line) const;
-
- Bool_t IsVertical(const TLine& line) const;
-
- Int_t CountPoint(const TObjArray& segments, Double_t x, Double_t y) const;
-
- Bool_t ShouldBeRemoved(const TObjArray& contours, Double_t x, Double_t y) const;
-
-private:
- /// not implemented
- AliMUONPainterContourMaker(const AliMUONPainterContourMaker& rhs);
- /// not implemented
- AliMUONPainterContourMaker& operator=(const AliMUONPainterContourMaker& rhs);
-
- AliMpExMap* fGlobalTransformations; ///< store of global transformations for DEs
- TMap* fLocalManuContours; ///< store for local contours of all manus
- TMap* fContours; ///< store for all our contours
-
- ClassDef(AliMUONPainterContourMaker,1) // Painter contour builder
-};
-
-#endif
-
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id: AliMUONPainterDataRegistry.cxx 26812 2008-06-20 15:22:59Z laphecet $
+
+#include "AliMUONPainterDataRegistry.h"
+
+#include "AliMpManuIterator.h"
+#include "AliMUON2DMap.h"
+#include "AliMUONCalibParamND.h"
+#include "AliMUONTrackerData.h"
+#include "AliMUONVTrackerDataMaker.h"
+#include "AliLog.h"
+#include <THashList.h>
+#include <TObjArray.h>
+#include <TString.h>
+#include <Riostream.h>
+
+///\class AliMUONPainterDataRegistry
+///
+/// Registry for AliMUONVPainter related stuff : painter data sources
+/// and painter matrices
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterDataRegistry)
+///\endcond
+
+AliMUONPainterDataRegistry* AliMUONPainterDataRegistry::fgInstance(0x0);
+
+//_____________________________________________________________________________
+AliMUONPainterDataRegistry::AliMUONPainterDataRegistry() : TObject(), TQObject(),
+fDataMakers(new TObjArray),
+fZombies(new TObjArray),
+fInteractiveReadOutConfig(0x0)
+{
+ /// ctor
+ fDataMakers->SetOwner(kTRUE);
+ fZombies->SetOwner(kTRUE);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterDataRegistry::~AliMUONPainterDataRegistry()
+{
+ /// dtor
+ delete fDataMakers;
+ delete fInteractiveReadOutConfig;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::CreateInteractiveReadOutConfig() const
+{
+ /// Create a base config
+
+ fInteractiveReadOutConfig = new AliMUONTrackerData("IROC","IROC",1);
+ fInteractiveReadOutConfig->SetDimensionName(0,"Switch");
+ fInteractiveReadOutConfig->DisableChannelLevel();
+ AliMpManuIterator it;
+ Int_t detElemId;
+ Int_t manuId;
+ AliMUON2DMap store(true);
+
+ while ( it.Next(detElemId,manuId) )
+ {
+ AliMUONVCalibParam* param = new AliMUONCalibParamND(1,64,detElemId,manuId,1);
+ store.Add(param);
+ }
+ fInteractiveReadOutConfig->Add(store);
+}
+
+//_____________________________________________________________________________
+AliMUONVTrackerDataMaker*
+AliMUONPainterDataRegistry::DataMaker(Int_t i) const
+{
+ /// Get one data source
+ if ( i >= 0 && i <= fDataMakers->GetLast() )
+ {
+ return static_cast<AliMUONVTrackerDataMaker*>(fDataMakers->At(i));
+ }
+ else
+ {
+ AliError(Form("Index out of bounds : %d / %d",i,fDataMakers->GetLast()+1));
+ return 0x0;
+ }
+}
+
+//_____________________________________________________________________________
+AliMUONVTrackerData*
+AliMUONPainterDataRegistry::DataSource(Int_t i) const
+{
+ /// Get one data source
+
+ AliMUONVTrackerDataMaker* maker = DataMaker(i);
+ if ( maker ) return maker->Data();
+ return 0x0;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::DataMakerWasRegistered(AliMUONVTrackerDataMaker* data)
+{
+ /// A new reader source was registered
+ Long_t param[] = { (Long_t)data };
+
+ Emit("DataMakerWasRegistered(AliMUONVTrackerDataMaker*)",param);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::DataMakerWasUnregistered(AliMUONVTrackerDataMaker* data)
+{
+ /// A data reader was unregistered
+ Long_t param[] = { (Long_t)data };
+
+ Emit("DataMakerWasUnregistered(AliMUONVTrackerDataMaker*)",param);
+
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::DataSourceWasRegistered(AliMUONVTrackerData* data)
+{
+ /// A new data source was registered
+ Long_t param[] = { (Long_t)data };
+
+ Emit("DataSourceWasRegistered(AliMUONVTrackerData*)",param);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::DataSourceWasUnregistered(AliMUONVTrackerData* data)
+{
+ /// A data source was unregistered
+ Long_t param[] = { (Long_t)data };
+
+ Emit("DataSourceWasUnregistered(AliMUONVTrackerData*)",param);
+
+}
+
+//_____________________________________________________________________________
+AliMUONVTrackerData*
+AliMUONPainterDataRegistry::DataSource(const char* name) const
+{
+ /// Find a data source by name
+ for ( Int_t i = 0; i < NumberOfDataMakers(); ++i )
+ {
+ AliMUONVTrackerData* data = DataMaker(i)->Data();
+ if ( data )
+ {
+ TString dname(data->GetName());
+ if ( dname == name ) return data;
+ }
+ }
+ return 0x0;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterDataRegistry*
+AliMUONPainterDataRegistry::Instance()
+{
+ /// Get unique instance of this class
+ if ( !fgInstance ) fgInstance = new AliMUONPainterDataRegistry;
+ return fgInstance;
+}
+
+//_____________________________________________________________________________
+AliMUONVTrackerData*
+AliMUONPainterDataRegistry::InteractiveReadOutConfig() const
+{
+ /// Return an object that contains the parts of the detector selected
+ /// (using the mouse) to be part of the readout.
+
+ if (!fInteractiveReadOutConfig) CreateInteractiveReadOutConfig();
+ return fInteractiveReadOutConfig;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::Print(Option_t* opt) const
+{
+ /// Printout
+ TString sopt(opt);
+ sopt.ToUpper();
+
+ cout << "Number of data readers = " << NumberOfDataMakers() << endl;
+
+ if ( sopt.Contains("FULL") || sopt.Contains("READER") || sopt.Contains("DATA") )
+ {
+ TIter next(fDataMakers);
+ AliMUONVTrackerDataMaker* reader;
+
+ while ( ( reader = static_cast<AliMUONVTrackerDataMaker*>(next()) ) )
+ {
+ if ( sopt.Contains("DATA") )
+ {
+ AliMUONVTrackerData* data = reader->Data();
+ if ( data ) data->Print();
+ }
+ else
+ {
+ reader->Print();
+ }
+ }
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::Register(AliMUONVTrackerDataMaker* reader)
+{
+ /// reader is adopted, i.e. the registry becomes the owner of it.
+ fDataMakers->AddLast(reader);
+ DataMakerWasRegistered(reader);
+ if ( reader->Data() ) DataSourceWasRegistered(reader->Data());
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterDataRegistry::NumberOfDataMakers() const
+{
+ /// The number of data readers we handle
+ return fDataMakers->GetLast()+1;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataRegistry::DeleteZombies()
+{
+ /// Delete zombies
+ fZombies->Delete();
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterDataRegistry::Unregister(AliMUONVTrackerDataMaker* reader)
+{
+ /// Unregister some reader
+
+ if (!reader) return kFALSE;
+
+ if ( reader->Data() )
+ {
+ DataSourceWasUnregistered(reader->Data());
+ reader->Data()->Destroyed(); // we pretend it's deleted now, even
+ // if it will be only later on when zombie are killed, so that
+ // for instance painters depending on it will no longer try to access it
+ }
+
+ DataMakerWasUnregistered(reader);
+
+ TObject* o = fDataMakers->Remove(reader);
+
+ fZombies->Add(o); // for later deletion
+
+// if ( o )
+// {
+// delete o;
+// }
+// else
+// {
+// AliError(Form("Could not unregister data named %s title %s",reader->GetName(),
+// reader->GetTitle()));
+// }
+ return ( o != 0x0 );
+}
--- /dev/null
+#ifndef ALIMUONPAINTERDATAREGISTRY_H
+#define ALIMUONPAINTERDATAREGISTRY_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id: AliMUONPainterDataRegistry.h 26812 2008-06-20 15:22:59Z laphecet $
+
+/// \ingroup graphics
+/// \class AliMUONPainterDataRegistry
+/// \brief Registry for painter data sources
+///
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+#ifndef ROOT_TQObject
+# include <TQObject.h>
+#endif
+
+class TObjArray;
+class AliMUONVTrackerData;
+class AliMUONVTrackerDataMaker;
+
+class AliMUONPainterDataRegistry : public TObject, public TQObject
+{
+public:
+ virtual ~AliMUONPainterDataRegistry();
+
+ AliMUONVTrackerDataMaker* DataMaker(Int_t i) const;
+
+ AliMUONVTrackerData* DataSource(Int_t i) const;
+
+ AliMUONVTrackerData* DataSource(const char* name) const;
+
+ AliMUONVTrackerData* InteractiveReadOutConfig() const;
+
+ void DataSourceWasRegistered(AliMUONVTrackerData* data); // *SIGNAL*
+
+ void DataSourceWasUnregistered(AliMUONVTrackerData* data); // *SIGNAL*
+
+ void DataMakerWasRegistered(AliMUONVTrackerDataMaker* reader); // *SIGNAL*
+
+ void DataMakerWasUnregistered(AliMUONVTrackerDataMaker* reader); // *SIGNAL*
+
+ static AliMUONPainterDataRegistry* Instance();
+
+ Int_t NumberOfDataMakers() const;
+
+ /// Number of data sources = data makers
+ Int_t NumberOfDataSources() const { return NumberOfDataMakers(); }
+
+ void Print(Option_t* opt) const;
+
+ void Register(AliMUONVTrackerDataMaker* reader);
+
+ Bool_t Unregister(AliMUONVTrackerDataMaker* reader);
+
+ void DeleteZombies();
+
+private:
+ /// Not implemented
+ AliMUONPainterDataRegistry();
+ /// Not implemented
+ AliMUONPainterDataRegistry(const AliMUONPainterDataRegistry&);
+ /// Not implemented
+ AliMUONPainterDataRegistry& operator=(const AliMUONPainterDataRegistry&);
+
+ void CreateInteractiveReadOutConfig() const;
+
+private:
+ static AliMUONPainterDataRegistry* fgInstance; ///< unique instance
+ TObjArray* fDataMakers; ///< data makers
+ TObjArray* fZombies; ///< data readers to be deleted
+ mutable AliMUONVTrackerData* fInteractiveReadOutConfig; ///< clickable readout configuration
+
+ ClassDef(AliMUONPainterDataRegistry,1) // Registry for AliMUONVTrackerDataMaker objects
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+///\class AliMUONPointWithRef
+///
+/// A class used to represent a point with an external integer reference
+/// and with a specific sorting method (see AliMUONContourMaker)
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+#include "AliMUONPointWithRef.h"
+
+#include "AliMUONSegment.h"
+#include "Riostream.h"
+#include "TString.h"
+
+//\cond CLASSIMP
+ClassImp(AliMUONPointWithRef)
+//\endcond
+
+//_____________________________________________________________________________
+AliMUONPointWithRef::AliMUONPointWithRef() : fX(), fY(), fRef(-1)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPointWithRef::AliMUONPointWithRef(Double_t x, Double_t y, Int_t ref)
+: fX(x), fY(y), fRef(ref)
+{
+ /// dtor
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPointWithRef::Compare(const TObject* obj) const
+{
+ // Should serve to sort the vertical edges in ascending order, first on absissa,
+ // then on ordinate
+
+ if ( this == obj ) return 0;
+
+ const AliMUONPointWithRef* rhs = static_cast<const AliMUONPointWithRef*>(obj);
+
+ if ( AliMUONSegment::AreEqual(Y(),rhs->Y()) )
+ {
+ if ( AliMUONSegment::AreEqual(X(),rhs->X()) )
+ {
+ return 0;
+ }
+ else if ( X() > rhs->X() )
+ {
+ return 1;
+ }
+ else
+ return -1;
+ }
+ else if ( Y() < rhs->Y() )
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPointWithRef::Print(Option_t*) const
+{
+ /// Printout
+ cout << Form("(%10.5f,%10.5f) [%4d]",X(),Y(),Ref()) << endl;
+}
--- /dev/null
+#ifndef ALIMUONPOINTWITHREF_H
+#define ALIMUONPOINTWITHREF_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONPointWithRef
+/// \brief A TVector2 with an integer ref, and a specific Compare
+///
+// author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONPointWithRef : public TObject
+{
+public:
+ AliMUONPointWithRef(Double_t x, Double_t y, Int_t ref);
+ AliMUONPointWithRef();
+ virtual ~AliMUONPointWithRef() {}
+
+ /// We are sortable
+ virtual Bool_t IsSortable() const { return kTRUE; }
+
+ virtual Int_t Compare(const TObject* obj) const;
+
+ Double_t X() const { return fX; }
+
+ Double_t Y() const { return fY; }
+
+ Int_t Ref() const { return fRef; }
+
+ void Print(Option_t* opt="") const;
+
+private:
+ Double_t fX; //< x value
+ Double_t fY; //< y value
+ Int_t fRef; //< index of the original point in some array
+
+ ClassDef(AliMUONPointWithRef,1) // A point with an external integer reference
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONPolygon
+///
+/// A simple planar polygon, with a given orientation
+///
+/// \author Laurent Aphecetche, Subatech
+
+#include "AliMUONPolygon.h"
+
+#include "AliLog.h"
+#include "Riostream.h"
+#include "TMath.h"
+
+///\cond CLASSIMP
+ClassImp(AliMUONPolygon)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPolygon::AliMUONPolygon(Int_t nvertices)
+: TObject(),
+fN(nvertices),
+fX(new Double_t[fN]),
+fY(new Double_t[fN])
+{
+ /// Ctor with a predefined number of vertices.
+}
+
+//_____________________________________________________________________________
+AliMUONPolygon::AliMUONPolygon(Double_t xpos, Double_t ypos, Double_t halfsizex, Double_t halfsizey)
+: TObject(),
+fN(5),
+fX(new Double_t[fN]),
+fY(new Double_t[fN])
+{
+ /// Ctor. Polygon will be a rectangle.
+
+
+ double xmin(xpos-halfsizex);
+ double xmax(xpos+halfsizex);
+ double ymin(ypos-halfsizey);
+ double ymax(ypos+halfsizey);
+
+ SetVertex(0,xmin,ymin);
+ SetVertex(1,xmax,ymin);
+ SetVertex(2,xmax,ymax);
+ SetVertex(3,xmin,ymax);
+
+ Close();
+}
+
+
+//_____________________________________________________________________________
+AliMUONPolygon::~AliMUONPolygon()
+{
+ /// dtor
+ delete[] fX;
+ delete[] fY;
+}
+
+//______________________________________________________________________________
+AliMUONPolygon::AliMUONPolygon(const AliMUONPolygon& rhs)
+: TObject(rhs),
+fN(0),
+fX(0x0),
+fY(0x0)
+{
+ /// Copy constructor.
+
+ ((AliMUONPolygon&)rhs).Copy(*this);
+}
+
+//______________________________________________________________________________
+AliMUONPolygon&
+AliMUONPolygon::operator=(const AliMUONPolygon& rhs)
+{
+ /// Assignment operator
+ if ( this != &rhs )
+ {
+ rhs.Copy(*this);
+ }
+ return *this;
+}
+
+//______________________________________________________________________________
+Bool_t
+AliMUONPolygon::Contains(Double_t x, Double_t y) const
+{
+ /// Whether the polygon contains point (x,y)
+
+ // Note that the polygon must be a closed polygon (1st and last point
+ // must be identical), which should be the case here.
+
+ return TMath::IsInside(x,y,fN,fX,fY);
+}
+
+//______________________________________________________________________________
+void AliMUONPolygon::Copy(TObject& obj) const
+{
+ /// Copy this to obj
+
+ AliMUONPolygon& rhs = static_cast<AliMUONPolygon&>(obj);
+
+ Double_t* x = new Double_t[fN];
+ Double_t* y = new Double_t[fN];
+
+ for ( Int_t i = 0; i < fN; ++i )
+ {
+ x[i] = fX[i];
+ y[i] = fY[i];
+ }
+
+ delete rhs.fX;
+ delete rhs.fY;
+
+ rhs.fX = x;
+ rhs.fY = y;
+ rhs.fN = fN;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPolygon::Close()
+{
+ /// Make that last point = first point
+
+ SetVertex(fN-1,X(0),Y(0));
+}
+
+//_____________________________________________________________________________
+void AliMUONPolygon::Print(Option_t*) const
+{
+ /// Printout
+ cout << Form("AliMUONPolygon : %3d vertices. Signed Area=%e",NumberOfVertices(),SignedArea()) << endl;
+ for ( Int_t i = 0; i < NumberOfVertices(); ++i )
+ {
+ cout << Form("%10.5f,%10.5f",X(i),Y(i)) << endl;
+ }
+}
+
+//_____________________________________________________________________________
+Double_t
+AliMUONPolygon::SignedArea() const
+{
+ /// Compute the signed area of this polygon
+ /// Algorithm from F. Feito, J.C. Torres and A. Urena,
+ /// Comput. & Graphics, Vol. 19, pp. 595-600, 1995
+
+ Double_t area(0.0);
+
+ for ( Int_t i = 0; i < NumberOfVertices()-1; ++i )
+ {
+ area += X(i)*Y(i+1) - X(i+1)*Y(i);
+ }
+
+ return area;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPolygon::ReverseOrientation()
+{
+ /// Reverse the orientation of this polygon
+ Double_t* x = new Double_t[fN];
+ Double_t* y = new Double_t[fN];
+
+ for ( Int_t i = fN-1; i >= 0; --i )
+ {
+ x[i] = X(fN-i-1);
+ y[i] = Y(fN-i-1);
+ }
+
+ delete[] fX;
+ delete[] fY;
+
+ fX = x;
+ fY = y;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPolygon::SetVertex(Int_t i, Double_t x, Double_t y)
+{
+ /// Set one vertex
+ if ( i >= fN )
+ {
+ TObject* o(0x0);
+ o->Print(); // to crash
+ }
+ fX[i] = x;
+ fY[i] = y;
+}
+
--- /dev/null
+#ifndef ALIMUONPOLYGON_H
+#define ALIMUONPOLYGON_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONPolygon
+/// \brief A planar polygon
+///
+// author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONPolygon : public TObject
+{
+public:
+ AliMUONPolygon(Int_t nvertices=5);
+ AliMUONPolygon(Double_t xpos, Double_t ypos, Double_t halfsizex, Double_t halfsizey);
+ AliMUONPolygon(const AliMUONPolygon& rhs);
+ AliMUONPolygon& operator=(const AliMUONPolygon& rhs);
+ virtual ~AliMUONPolygon();
+
+ virtual TObject* Clone(const char* /*newname*/="") const { return new AliMUONPolygon(*this); }
+
+ Bool_t Contains(Double_t x, Double_t y) const;
+
+ Double_t SignedArea() const;
+
+ /// Whether this polygon is oriented counter clockwise
+ Bool_t IsCounterClockwiseOriented() const { return SignedArea() > 0.0; }
+
+ void ReverseOrientation();
+
+ void SetVertex(Int_t i, Double_t x, Double_t y);
+
+ Double_t X(Int_t i) const { return fX[i]; }
+
+ Double_t Y(Int_t i) const { return fY[i]; }
+
+ Int_t NumberOfVertices() const { return fN; }
+
+ void Print(Option_t* opt="") const;
+
+ void Copy(TObject& obj) const;
+
+ void Close();
+
+private:
+ Int_t fN; /// Number of vertices
+ Double_t* fX; //[fN]
+ Double_t* fY; //[fN]
+
+ ClassDef(AliMUONPolygon,1) // A simple polygon
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONSegment
+///
+/// A basic line segment, to be used in contour making algorithms.
+///
+/// In particular, this class defines what a left or right edge is.
+///
+/// Also, please note that, due to the way Root collections are sorted (relying
+/// on TObject::Compare method), the way the AliMUONSegment::Compare method
+/// is implemented below is really important when it comes to understand
+/// contour making algorithm. Keep that in mind.
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+#include "AliMUONSegment.h"
+
+#include "TMath.h"
+#include "Riostream.h"
+#include "AliMpConstants.h"
+
+/// \cond CLASSIMP
+ClassImp(AliMUONSegment)
+/// \endcond
+
+const Double_t AliMUONSegment::fgkPrecision(AliMpConstants::LengthTolerance());
+
+//_____________________________________________________________________________
+AliMUONSegment::AliMUONSegment() :
+TObject(),
+fStartX(), fStartY(), fEndX(), fEndY(), fSmallerY(), fIsHorizontal(), fIsVertical(),
+fIsLeftEdge(), fIsRightEdge(), fIsAPoint(kTRUE)
+{
+ /// Ctor
+ Set(fStartX,fStartY,fEndX,fEndY);
+}
+
+//_____________________________________________________________________________
+AliMUONSegment::AliMUONSegment(Double_t xstart, Double_t ystart, Double_t xend, Double_t yend)
+: TObject(),
+fStartX(xstart), fStartY(ystart), fEndX(xend), fEndY(yend), fSmallerY(), fIsHorizontal(), fIsVertical(),
+fIsLeftEdge(), fIsRightEdge(), fIsAPoint(kTRUE)
+{
+ /// Ctor
+ Set(xstart,ystart,xend,yend);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONSegment::AreEqual(double a, double b)
+{
+ /// Whether the two floats are equal within the given precision
+ return (TMath::Abs(b-a) < fgkPrecision);
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONSegment::Compare(const TObject* obj) const
+{
+ /// Compare method, which sort segments in ascending x order
+ /// if same x, insure that left edges are before right edges
+ /// within same x, order by increasing bottommost y
+ /// Mind your steps ! This method is critical to the contour merging algorithm !
+
+ const AliMUONSegment* rhs = static_cast<const AliMUONSegment*>(obj);
+
+ if ( AreEqual(StartX(),rhs->StartX()) )
+ {
+ if ( IsLeftEdge() && rhs->IsRightEdge() ) return -1;
+ if ( IsRightEdge() && rhs->IsLeftEdge() ) return 1;
+ if ( SmallerY() < rhs->SmallerY() ) return -1;
+ if ( SmallerY() > rhs->SmallerY() ) return 1;
+ return 0;
+ }
+ else if ( StartX() < rhs->StartX() )
+ {
+ return -1;
+ }
+ else //if ( StartX() > rhs->StartX() )
+ {
+ return 1;
+ }
+}
+
+//_____________________________________________________________________________
+double AliMUONSegment::Top() const
+{
+ /// Max Y of the segment
+ return TMath::Max(fStartY,fEndY);
+}
+
+//_____________________________________________________________________________
+double AliMUONSegment::Distance() const
+{
+ /// Length of the segment
+ return TMath::Sqrt((fStartX-fEndX)*(fStartX-fEndX) +
+ (fStartY-fEndY)*(fStartY-fEndY));
+}
+
+//_____________________________________________________________________________
+void AliMUONSegment::Print(Option_t*) const
+{
+ /// Printout
+ cout << AsString() << endl;
+}
+
+//_____________________________________________________________________________
+const char* AliMUONSegment::AsString() const
+{
+ /// Return a string representation of this object
+ return Form("[ (%10.5f,%10.5f) -> (%10.5f,%10.5f) %s ] (d=%e)",fStartX,fStartY,fEndX,fEndY,
+ IsLeftEdge() ? "L" : ( IsRightEdge() ? "R" : ( IsHorizontal() ? "H" : "" )),
+ Distance() );
+}
+
+//_____________________________________________________________________________
+void
+AliMUONSegment::Set(Double_t xstart, Double_t ystart, Double_t xend, Double_t yend)
+{
+ /// Set start and end point, and (re)compute internal values
+ fStartX = xstart;
+ fEndX = xend;
+ fStartY = ystart;
+ fEndY = yend;
+ fSmallerY = TMath::Min(fStartY,fEndY);
+ fIsHorizontal = AreEqual(fStartY,fEndY);
+ fIsVertical = AreEqual(fStartX,fEndX);
+ fIsLeftEdge = fIsVertical && ( fStartY > fEndY );
+ fIsRightEdge = fIsVertical && ( fStartY < fEndY );
+ fIsAPoint = ( Distance() < fgkPrecision );
+}
+
--- /dev/null
+#ifndef ALIMUONSEGMENT_H
+#define ALIMUONSEGMENT_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONSegment
+/// \brief A basic line segment, used for contour making algorithm(s)
+///
+// author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONSegment : public TObject
+{
+public:
+ AliMUONSegment();
+ AliMUONSegment(Double_t xstart, Double_t ystart, Double_t xend, Double_t yend);
+ virtual ~AliMUONSegment() {}
+
+ virtual Int_t Compare(const TObject* obj) const;
+
+ /// We are sortable
+ virtual Bool_t IsSortable() const { return kTRUE; }
+
+ /// Return the x-coordinate of our starting point
+ Double_t StartX() const { return fStartX; }
+ /// Return the y-coordinate of our starting point
+ Double_t StartY() const { return fStartY; }
+ /// Return the x-coordinate of our ending point
+ Double_t EndX() const { return fEndX; }
+ /// Return the y-coordinate of our ending point
+ Double_t EndY() const { return fEndY; }
+
+ /// Return our smallest y (of starting or ending point)
+ double SmallerY() const { return fSmallerY; }
+
+ /// Whether we are a horizontal segment
+ Bool_t IsHorizontal() const { return fIsHorizontal; }
+
+ /// Whethere we are a vertical segment
+ Bool_t IsVertical() const { return fIsVertical; }
+
+ /// Whether we are a left edge
+ Bool_t IsLeftEdge() const { return fIsLeftEdge; }
+
+ /// Whether we are a right edge
+ Bool_t IsRightEdge() const { return fIsRightEdge; }
+
+ /// Return our bottom y
+ double Bottom() const { return SmallerY(); }
+
+ double Top() const;
+
+ double Distance() const;
+
+ /// Whether we're just a point
+ Bool_t IsAPoint() const { return fIsAPoint; }
+
+ const char* AsString() const;
+
+ static Bool_t AreEqual(double a, double b);
+
+ void Print(Option_t* opt="") const;
+
+ void Set(Double_t xstart, Double_t ystart, Double_t xend, Double_t yend);
+
+private:
+ Double_t fStartX; /// x of start point
+ Double_t fStartY; /// y of start point
+ Double_t fEndX; /// x of end point
+ Double_t fEndY; /// y of end point
+ Double_t fSmallerY; /// Either StartY or EndY
+ Bool_t fIsHorizontal; /// Whether the segment is horizontal
+ Bool_t fIsVertical; /// Whether the segment is vertical
+ Bool_t fIsLeftEdge; /// Whether the segment is a left edge
+ Bool_t fIsRightEdge; /// Whether the segment is a right edge
+ Bool_t fIsAPoint; /// Whether start==end
+
+ static const Double_t fgkPrecision; /// Floating point precision used in comparisons
+
+ ClassDef(AliMUONSegment,1) // A basic line segment
+};
+
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+///
+/// \class AliMUONSegmentTree
+///
+/// Implementation of a segment tree, which is used to make contour
+/// merging (see AliMUONContourMaker)
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+#include "AliMUONSegmentTree.h"
+
+#include "AliLog.h"
+#include "AliMUONNode.h"
+#include "Riostream.h"
+#include "TArrayD.h"
+#include "TMath.h"
+
+/// \cond CLASSIMP
+ClassImp(AliMUONSegmentTree)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONSegmentTree::AliMUONSegmentTree(const TArrayD& values)
+: fRoot(0x0), fStack()
+{
+ /// Values should be sorted and have at least 2 elements.
+
+ fStack.SetOwner(kTRUE);
+
+ if ( values.GetSize() < 2 )
+ {
+ AliError("cannot build a segmenttree with less than 2 values !");
+ TObject* forceACrash(0x0);
+ forceACrash->Print();
+ }
+
+ fRoot = Build(values,0,values.GetSize()-1);
+}
+
+//_____________________________________________________________________________
+AliMUONSegmentTree::~AliMUONSegmentTree()
+{
+ /// dtor
+ delete fRoot;
+}
+
+//_____________________________________________________________________________
+AliMUONNode*
+AliMUONSegmentTree::Build(const TArrayD& values, Int_t i, Int_t j)
+{
+ /// Build the segment tree from a list of values
+
+ double midpoint(TMath::Sqrt(-1.0));
+ Int_t mid((i+j)/2);
+
+ if ( mid != i && mid != j ) midpoint = values[mid];
+
+ AliMUONNode* node = new AliMUONNode(values[i],values[j],midpoint);
+
+ if ( j - i == 1 ) return node;
+
+ node->LeftNode(Build(values,i,(i+j)/2));
+ node->RightNode(Build(values,(i+j)/2,j));
+
+ return node;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONSegmentTree::Contribution(double b, double e)
+{
+ /// Compute the contribution of edge (b,e)
+ fRoot->Contribution(b,e,fStack);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONSegmentTree::InsertInterval(double b, double e)
+{
+ /// Insert interval (b,e)
+ fRoot->InsertInterval(b,e,fStack);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONSegmentTree::DeleteInterval(double b, double e)
+{
+ /// Delete interval (b,e)
+ fRoot->DeleteInterval(b,e,fStack);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONSegmentTree::Print(Option_t*) const
+{
+ /// Printout
+ if (fRoot)
+ fRoot->Print();
+ else
+ cout << "Empty binary tree" << endl;
+}
--- /dev/null
+#ifndef ALIMUONSEGMENTTREE_H
+#define ALIMUONSEGMENTTREE_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup geometry
+/// \class AliMUONSegmentTree
+/// \brief Implementation of a segment tree
+///
+// author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+#ifndef ROOT_TObjArray
+# include "TObjArray.h"
+#endif
+
+class TArrayD;
+class AliMUONNode;
+
+class AliMUONSegmentTree : public TObject
+{
+public:
+ AliMUONSegmentTree(const TArrayD& values);
+ virtual ~AliMUONSegmentTree();
+
+ AliMUONNode* Build(const TArrayD& values, Int_t i, Int_t j);
+
+ void Print(Option_t* opt="") const;
+
+ /// Get the stack
+ const TObjArray& Stack() const { return fStack; }
+
+ /// Reset the stack
+ void ResetStack() { fStack.Clear(); }
+
+ void Contribution(double b, double e);
+
+ void InsertInterval(double b, double e);
+
+ void DeleteInterval(double d, double e);
+
+private:
+ /// not implemented
+ AliMUONSegmentTree(const AliMUONSegmentTree& rhs);
+ /// not implemented
+ AliMUONSegmentTree& operator=(const AliMUONSegmentTree& rhs);
+
+ AliMUONNode* fRoot; /// root of the tree
+ TObjArray fStack; /// array of AliMUONSegment objects
+
+ ClassDef(AliMUONSegmentTree,1) // Implementation of a segment tree
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMpUID.h"
+
+#include "AliLog.h"
+#include "Riostream.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TSystem.h"
+
+///
+/// station/chamber/de/bp/manu
+///
+/// station/chamber/pcb/manu
+
+ClassImp(AliMpUID)
+
+namespace
+{
+ const char* nameTemplateMANU = "MANU %d";
+ const char* nameTemplateDE = "DE %d";
+ const char* nameTemplateBP = "BusPatch %d";
+ const char* nameTemplateCHAMBER = "Chamber %d";
+ const char* nameTemplateSTATION = "Station %d";
+ const char* nameTemplatePCB = "PCB %d";
+
+ const char* pathTemplateMANU = "Cathode%d/Station%d/Chamber%d/DE%04d/BUSPATCH%04d/MANU%04d";
+ const char* pathTemplateBP = "Cathode%d/Station%d/Chamber%d/DE%04d/BUSPATCH%04d";
+ const char* pathTemplateDE = "Cathode%d/Station%d/Chamber%d/DE%04d";
+ const char* pathTemplateCHAMBER = "Cathode%d/Station%d/Chamber%d";
+ const char* pathTemplateSTATION = "Cathode%d/Station%d";
+
+ const char* pathTemplateMANUPCB = "Cathode%d/Station%d/Chamber%d/DE%04d/PCB%d/MANU%04d";
+ const char* pathTemplatePCB = "Cathode%d/Station%d/Chamber%d/DE%04d/PCB%d";
+}
+
+//_____________________________________________________________________________
+AliMpUID::AliMpUID()
+:
+fCathodeId(-1),
+fStationId(-1),
+fChamberId(-1),
+fDetElemId(-1),
+fBusPatchId(-1),
+fManuId(-1),
+fPCBId(-1)
+{
+ /// empty ctor
+}
+
+//_____________________________________________________________________________
+AliMpUID::AliMpUID(AliMp::CathodType cathodeType, Int_t station, Int_t chamber, Int_t de, Int_t bp, Int_t manu, Int_t pcb)
+:
+fCathodeId(cathodeType),
+fStationId(station),
+fChamberId(chamber),
+fDetElemId(de),
+fBusPatchId(bp),
+fManuId(manu),
+fPCBId(pcb)
+{
+ /// default ctor
+}
+
+//_____________________________________________________________________________
+AliMpUID::AliMpUID(AliMp::CathodType cathodeType, const AliMpUID& b)
+:
+fCathodeId(cathodeType),
+fStationId(b.StationId()),
+fChamberId(b.ChamberId()),
+fDetElemId(b.DetElemId()),
+fBusPatchId(b.BusPatchId()),
+fManuId(b.ManuId()),
+fPCBId(b.PCBId())
+{
+ /// build the id from b, but using the given cathodeType
+}
+
+//_____________________________________________________________________________
+AliMpUID::AliMpUID(AliMp::CathodType cathodeType, const char* pathname)
+:
+fCathodeId(cathodeType),
+fStationId(-1),
+fChamberId(-1),
+fDetElemId(-1),
+fBusPatchId(-1),
+fManuId(-1),
+fPCBId(-1)
+{
+ /// build id from path, but using the given cathodeType
+
+ if ( CheckTemplate(pathname,pathTemplateMANUPCB,fPCBId) && fPCBId >= 0 ) return;
+ if ( CheckTemplate(pathname,pathTemplatePCB,fPCBId) && fPCBId >= 0 ) return;
+
+ if ( CheckTemplate(pathname,pathTemplateMANU,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateBP,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateDE,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateCHAMBER,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateSTATION,fBusPatchId) ) return;
+}
+
+
+//_____________________________________________________________________________
+AliMpUID::AliMpUID(const char* pathname)
+:
+fCathodeId(2),
+fStationId(-1),
+fChamberId(-1),
+fDetElemId(-1),
+fBusPatchId(-1),
+fManuId(-1),
+fPCBId(-1)
+{
+ /// Build id from path
+
+ if ( CheckTemplate(pathname,pathTemplateMANUPCB,fPCBId) && fPCBId >= 0 ) return;
+ if ( CheckTemplate(pathname,pathTemplatePCB,fPCBId) && fPCBId >= 0 ) return;
+
+ if ( CheckTemplate(pathname,pathTemplateMANU,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateBP,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateDE,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateCHAMBER,fBusPatchId) ) return;
+ if ( CheckTemplate(pathname,pathTemplateSTATION,fBusPatchId) ) return;
+}
+
+//_____________________________________________________________________________
+TString
+AliMpUID::BaseName() const
+{
+ /// Get the basename
+ return gSystem->BaseName(PathName().Data());
+}
+
+//_____________________________________________________________________________
+AliMp::CathodType
+AliMpUID::CathodeId() const
+{
+ /// return cathode id (not always valid)
+ return AliMp::GetCathodType(fCathodeId);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMpUID::CheckTemplate(const char* name, const char* pathTemplateName, Int_t& value)
+{
+ /// Check a name against a template
+
+ if ( TString(name).Contains("Cathode") )
+ {
+ sscanf(name,pathTemplateName,&fCathodeId,&fStationId,&fChamberId,&fDetElemId,&value,&fManuId);
+ }
+ else
+ {
+ TString templ(pathTemplateName);
+ Int_t i = templ.Index("/");
+ templ = templ(i+1,templ.Length()-i-1);
+ sscanf(name,templ.Data(),&fStationId,&fChamberId,&fDetElemId,&value,&fManuId);
+ }
+ return IsValid();
+}
+
+//_____________________________________________________________________________
+TString
+AliMpUID::DirName() const
+{
+ /// Get dirname
+ return gSystem->DirName(PathName().Data());
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMpUID::IsStation() const
+{
+ /// Whether we identify a station
+ return fCathodeId >= 0 && fStationId >= 0 && fChamberId == -1 ;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMpUID::IsChamber() const
+{
+ /// Whether we identify a chamber
+
+ return fCathodeId >= 0 && fStationId >= 0 && fChamberId >= 0 && fDetElemId == -1;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMpUID::IsDetectionElement() const
+{
+ /// whether we identify a detection element
+ return fCathodeId >= 0 && fStationId >= 0 && fChamberId >= 0 && fDetElemId >= 0 && fBusPatchId==-1 && fPCBId == -1;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMpUID::IsBusPatch() const
+{
+ /// whether we identify a bus patch
+ return fCathodeId >= 0 && fStationId >= 0 && fChamberId >= 0 && fDetElemId >= 0 && fBusPatchId>=0 && fManuId ==-1;
+}
+
+//_____________________________________________________________________________
+Bool_t AliMpUID::IsManu() const
+{
+ /// whether we identify a manu
+ return
+ fCathodeId >= 0 &&
+ fStationId >= 0 &&
+ fChamberId >= 0 &&
+ fDetElemId >= 0 &&
+ ( fBusPatchId>=0 || fPCBId >=0 ) &&
+ fManuId >=0;
+}
+
+//_____________________________________________________________________________
+Bool_t AliMpUID::IsPCB() const
+{
+ /// Whether we identify a PCB
+ return fCathodeId >= 0 && fPCBId >= 0 && fManuId == -1;
+}
+
+//_____________________________________________________________________________
+Bool_t AliMpUID::IsValid() const
+{
+ /// Whether we're a valid UID...
+ return IsStation() || IsChamber() || IsDetectionElement() || IsBusPatch() || IsManu() || IsPCB();
+}
+
+//_____________________________________________________________________________
+TString
+AliMpUID::Name() const
+{
+ /// Get our name
+ if ( IsManu() )
+ {
+ return Form(nameTemplateMANU,ManuId());
+ }
+
+ if ( IsPCB() )
+ {
+ return Form(nameTemplatePCB,PCBId());
+ }
+
+ if ( IsBusPatch() )
+ {
+ return Form(nameTemplateBP,BusPatchId());
+ }
+
+ if ( IsDetectionElement() )
+ {
+ return Form(nameTemplateDE,DetElemId());
+ }
+
+ if ( IsChamber() )
+ {
+ return Form(nameTemplateCHAMBER,ChamberId());
+ }
+
+ if ( IsStation() )
+ {
+ return Form(nameTemplateSTATION,StationId());
+ }
+
+ return "INVALID NAME";
+}
+
+//_____________________________________________________________________________
+TString
+AliMpUID::PathName() const
+{
+ /// Get our pathname
+ if ( IsManu() )
+ {
+ if ( fPCBId >= 0 )
+ {
+ return StripCathode(Form(pathTemplateMANUPCB,CathodeId(),StationId(),ChamberId(),DetElemId(),PCBId(),ManuId()));
+ }
+ else
+ {
+ return StripCathode(Form(pathTemplateMANU,CathodeId(),StationId(),ChamberId(),DetElemId(),BusPatchId(),ManuId()));
+ }
+ }
+
+ if ( IsPCB() )
+ {
+ return StripCathode(Form(pathTemplatePCB,CathodeId(),StationId(),ChamberId(),DetElemId(),PCBId()));
+ }
+
+ if ( IsBusPatch() )
+ {
+ return StripCathode(Form(pathTemplateBP,CathodeId(),StationId(),ChamberId(),DetElemId(),BusPatchId()));
+ }
+
+ if ( IsDetectionElement() )
+ {
+ return StripCathode(Form(pathTemplateDE,CathodeId(),StationId(),ChamberId(),DetElemId()));
+ }
+
+ if ( IsChamber() )
+ {
+ return StripCathode(Form(pathTemplateCHAMBER,CathodeId(),StationId(),ChamberId()));
+ }
+
+ if ( IsStation() )
+ {
+ return StripCathode(Form(pathTemplateSTATION,CathodeId(),StationId()));
+ }
+
+ return "INVALID PATHNAME";
+}
+
+//_____________________________________________________________________________
+void
+AliMpUID::Print(Option_t*) const
+{
+ /// Printout
+ cout << Name().Data() << " (" << PathName().Data() << ")" << endl;
+}
+
+//_____________________________________________________________________________
+TString
+AliMpUID::StripCathode(const char* name) const
+{
+ /// Remove cathode information if both cathodes are present
+
+ TString rv(name);
+
+ if ( fCathodeId == 2 )
+ {
+ rv.ReplaceAll("Cathode2/","");
+ }
+
+ return rv;
+}
+
+//_____________________________________________________________________________
+TString
+AliMpUID::Type() const
+{
+ /// Remove cathode information if both cathodes are present
+ TString n(Name());
+ TObjArray* s = n.Tokenize(" ");
+ TString rv(static_cast<TObjString*>(s->At(0))->String());
+ delete s;
+ return rv;
+}
+
--- /dev/null
+#ifndef ALIMPUID_H
+#define ALIMPUID_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup management
+/// \class AliMpUID
+/// \brief Global (string-eable) ID of a tracker channel
+///
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+#ifndef ROOT_TString
+# include "TString.h"
+#endif
+#ifndef ALI_MP_CATHOD_TYPE_H
+# include "AliMpCathodType.h"
+#endif
+
+class AliMpUID : public TObject
+{
+public:
+ AliMpUID();
+ AliMpUID(AliMp::CathodType cathodeType, Int_t station, Int_t chamber=-1, Int_t de=-1,
+ Int_t bp=-1, Int_t manu=-1, Int_t pcb=-1);
+ AliMpUID(AliMp::CathodType cathodeType, const AliMpUID& b);
+ AliMpUID(AliMp::CathodType cathodeType, const char* pathname);
+ AliMpUID(const char* pathname);
+
+ virtual ~AliMpUID() {}
+
+ TString Name() const;
+ TString PathName() const;
+ TString BaseName() const;
+ TString DirName() const;
+
+ Bool_t IsStation() const;
+ Bool_t IsChamber() const;
+ Bool_t IsDetectionElement() const;
+ Bool_t IsBusPatch() const;
+ Bool_t IsManu() const;
+ Bool_t IsPCB() const;
+ Bool_t IsValid() const;
+
+ AliMp::CathodType CathodeId() const;
+ Int_t StationId() const { return fStationId; }
+ Int_t ChamberId() const { return fChamberId; }
+ Int_t DetElemId() const { return fDetElemId; }
+ Int_t BusPatchId() const { return fBusPatchId; }
+ Int_t ManuId() const { return fManuId; }
+ Int_t PCBId() const { return fPCBId; }
+
+ virtual void Print(Option_t* opt="") const;
+
+ /// Return our type (e.g. PCB, Chamber, DE, MANU, etc...)
+ TString Type() const;
+
+private:
+
+ Bool_t CheckTemplate(const char* name, const char* templateName, Int_t& value);
+ TString StripCathode(const char* name) const;
+
+private:
+ Int_t fCathodeId; // Cathode number
+ Int_t fStationId; // Station id
+ Int_t fChamberId; // Chamber id
+ Int_t fDetElemId; // Detection element id
+ Int_t fBusPatchId; // Bus patch id
+ Int_t fManuId; // Manu id
+ Int_t fPCBId; // PCB id
+
+ ClassDef(AliMpUID,1) // UID of a tracker channel
+};
+
+#endif