Adding classes forgotten in previous commit
authorlaphecet <laphecet@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 6 Apr 2009 20:33:28 +0000 (20:33 +0000)
committerlaphecet <laphecet@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 6 Apr 2009 20:33:28 +0000 (20:33 +0000)
28 files changed:
MUON/AliMUONContour.cxx [new file with mode: 0644]
MUON/AliMUONContour.h [new file with mode: 0644]
MUON/AliMUONContourMaker.cxx [new file with mode: 0644]
MUON/AliMUONContourMaker.h [new file with mode: 0644]
MUON/AliMUONContourMakerTest.cxx [new file with mode: 0644]
MUON/AliMUONContourMakerTest.h [new file with mode: 0644]
MUON/AliMUONContourPainter.cxx [new file with mode: 0644]
MUON/AliMUONContourPainter.h [new file with mode: 0644]
MUON/AliMUONManuContourMaker.cxx [new file with mode: 0644]
MUON/AliMUONManuContourMaker.h [new file with mode: 0644]
MUON/AliMUONNode.cxx [new file with mode: 0644]
MUON/AliMUONNode.h [new file with mode: 0644]
MUON/AliMUONPainterContour.cxx [deleted file]
MUON/AliMUONPainterContour.h [deleted file]
MUON/AliMUONPainterContourMaker.cxx [deleted file]
MUON/AliMUONPainterContourMaker.h [deleted file]
MUON/AliMUONPainterDataRegistry.cxx [new file with mode: 0644]
MUON/AliMUONPainterDataRegistry.h [new file with mode: 0644]
MUON/AliMUONPointWithRef.cxx [new file with mode: 0644]
MUON/AliMUONPointWithRef.h [new file with mode: 0644]
MUON/AliMUONPolygon.cxx [new file with mode: 0644]
MUON/AliMUONPolygon.h [new file with mode: 0644]
MUON/AliMUONSegment.cxx [new file with mode: 0644]
MUON/AliMUONSegment.h [new file with mode: 0644]
MUON/AliMUONSegmentTree.cxx [new file with mode: 0644]
MUON/AliMUONSegmentTree.h [new file with mode: 0644]
MUON/mapping/AliMpUID.cxx [new file with mode: 0644]
MUON/mapping/AliMpUID.h [new file with mode: 0644]

diff --git a/MUON/AliMUONContour.cxx b/MUON/AliMUONContour.cxx
new file mode 100644 (file)
index 0000000..a5c4493
--- /dev/null
@@ -0,0 +1,304 @@
+/**************************************************************************
+* 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();
+}
diff --git a/MUON/AliMUONContour.h b/MUON/AliMUONContour.h
new file mode 100644 (file)
index 0000000..6092251
--- /dev/null
@@ -0,0 +1,76 @@
+#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
diff --git a/MUON/AliMUONContourMaker.cxx b/MUON/AliMUONContourMaker.cxx
new file mode 100644 (file)
index 0000000..73435cc
--- /dev/null
@@ -0,0 +1,462 @@
+/**************************************************************************
+* 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()));
+    }
+  }
+}
+
diff --git a/MUON/AliMUONContourMaker.h b/MUON/AliMUONContourMaker.h
new file mode 100644 (file)
index 0000000..43869c9
--- /dev/null
@@ -0,0 +1,54 @@
+#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
diff --git a/MUON/AliMUONContourMakerTest.cxx b/MUON/AliMUONContourMakerTest.cxx
new file mode 100644 (file)
index 0000000..298e7b7
--- /dev/null
@@ -0,0 +1,530 @@
+/**************************************************************************
+* 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;
+}
+
diff --git a/MUON/AliMUONContourMakerTest.h b/MUON/AliMUONContourMakerTest.h
new file mode 100644 (file)
index 0000000..1483de3
--- /dev/null
@@ -0,0 +1,64 @@
+#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
diff --git a/MUON/AliMUONContourPainter.cxx b/MUON/AliMUONContourPainter.cxx
new file mode 100644 (file)
index 0000000..56797ce
--- /dev/null
@@ -0,0 +1,101 @@
+/**************************************************************************
+* 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);
+  
+}
diff --git a/MUON/AliMUONContourPainter.h b/MUON/AliMUONContourPainter.h
new file mode 100644 (file)
index 0000000..c7ae413
--- /dev/null
@@ -0,0 +1,36 @@
+#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
diff --git a/MUON/AliMUONManuContourMaker.cxx b/MUON/AliMUONManuContourMaker.cxx
new file mode 100644 (file)
index 0000000..538172a
--- /dev/null
@@ -0,0 +1,288 @@
+/**************************************************************************
+* 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;
+}
+
+
+
+
diff --git a/MUON/AliMUONManuContourMaker.h b/MUON/AliMUONManuContourMaker.h
new file mode 100644 (file)
index 0000000..0dbea02
--- /dev/null
@@ -0,0 +1,56 @@
+#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
diff --git a/MUON/AliMUONNode.cxx b/MUON/AliMUONNode.cxx
new file mode 100644 (file)
index 0000000..ac98327
--- /dev/null
@@ -0,0 +1,224 @@
+/**************************************************************************
+* 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;
+}
+
diff --git a/MUON/AliMUONNode.h b/MUON/AliMUONNode.h
new file mode 100644 (file)
index 0000000..eac51b4
--- /dev/null
@@ -0,0 +1,77 @@
+#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
diff --git a/MUON/AliMUONPainterContour.cxx b/MUON/AliMUONPainterContour.cxx
deleted file mode 100644 (file)
index c0010d9..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/**************************************************************************
-* 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];
-}
diff --git a/MUON/AliMUONPainterContour.h b/MUON/AliMUONPainterContour.h
deleted file mode 100644 (file)
index 6caec5d..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#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
diff --git a/MUON/AliMUONPainterContourMaker.cxx b/MUON/AliMUONPainterContourMaker.cxx
deleted file mode 100644 (file)
index f70f507..0000000
+++ /dev/null
@@ -1,1572 +0,0 @@
-/**************************************************************************
-* 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();
-}
-                                         
diff --git a/MUON/AliMUONPainterContourMaker.h b/MUON/AliMUONPainterContourMaker.h
deleted file mode 100644 (file)
index 7c0582d..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-#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
-
diff --git a/MUON/AliMUONPainterDataRegistry.cxx b/MUON/AliMUONPainterDataRegistry.cxx
new file mode 100644 (file)
index 0000000..b3294fc
--- /dev/null
@@ -0,0 +1,279 @@
+/**************************************************************************
+* 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 );
+}
diff --git a/MUON/AliMUONPainterDataRegistry.h b/MUON/AliMUONPainterDataRegistry.h
new file mode 100644 (file)
index 0000000..ae0a8c7
--- /dev/null
@@ -0,0 +1,81 @@
+#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
diff --git a/MUON/AliMUONPointWithRef.cxx b/MUON/AliMUONPointWithRef.cxx
new file mode 100644 (file)
index 0000000..2c38730
--- /dev/null
@@ -0,0 +1,89 @@
+/**************************************************************************
+* 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;
+}
diff --git a/MUON/AliMUONPointWithRef.h b/MUON/AliMUONPointWithRef.h
new file mode 100644 (file)
index 0000000..33fe464
--- /dev/null
@@ -0,0 +1,47 @@
+#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
diff --git a/MUON/AliMUONPolygon.cxx b/MUON/AliMUONPolygon.cxx
new file mode 100644 (file)
index 0000000..5aa62b7
--- /dev/null
@@ -0,0 +1,208 @@
+/**************************************************************************
+* 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;
+}
+
diff --git a/MUON/AliMUONPolygon.h b/MUON/AliMUONPolygon.h
new file mode 100644 (file)
index 0000000..c49badd
--- /dev/null
@@ -0,0 +1,61 @@
+#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
diff --git a/MUON/AliMUONSegment.cxx b/MUON/AliMUONSegment.cxx
new file mode 100644 (file)
index 0000000..4a463b2
--- /dev/null
@@ -0,0 +1,148 @@
+/**************************************************************************
+* 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 );
+}
+
diff --git a/MUON/AliMUONSegment.h b/MUON/AliMUONSegment.h
new file mode 100644 (file)
index 0000000..4e987f9
--- /dev/null
@@ -0,0 +1,91 @@
+#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
diff --git a/MUON/AliMUONSegmentTree.cxx b/MUON/AliMUONSegmentTree.cxx
new file mode 100644 (file)
index 0000000..e987ba5
--- /dev/null
@@ -0,0 +1,118 @@
+/**************************************************************************
+* 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; 
+}
diff --git a/MUON/AliMUONSegmentTree.h b/MUON/AliMUONSegmentTree.h
new file mode 100644 (file)
index 0000000..b1d75c8
--- /dev/null
@@ -0,0 +1,60 @@
+#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
diff --git a/MUON/mapping/AliMpUID.cxx b/MUON/mapping/AliMpUID.cxx
new file mode 100644 (file)
index 0000000..5861b9c
--- /dev/null
@@ -0,0 +1,363 @@
+/**************************************************************************
+* 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;
+}
+
diff --git a/MUON/mapping/AliMpUID.h b/MUON/mapping/AliMpUID.h
new file mode 100644 (file)
index 0000000..999f714
--- /dev/null
@@ -0,0 +1,80 @@
+#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