From 0dfcc00e14b508f7e5a8a2f0b458bb1447fc28c1 Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Mon, 9 Feb 2004 14:03:34 +0000
Subject: [PATCH] From Andrei Gheata: I have attached the new files and all
 modifications done by Mihaela to include the new shape TGeoXtru representing
 the old TXTRU shape. Currently she implemented the Contains() method. The
 shape can be also visualized in the pad or x3d (see atached macro). The only
 limitation in x3d is that the end-polygons are not decomposed into convex
 polygons, so in case the section of the TGeoXtru is concave the drawing is
 not well handled.   I also included a minor modification in TGeoManager.h
 needed by FLUKA (that now can perform tracking and completers gAlice->Run()
 with TGeo!!!)

git-svn-id: http://root.cern.ch/svn/root/trunk@8163 27541ba8-7e3a-0410-8455-c3a389f83636
---
 geom/Module.mk                  |   2 +-
 geom/inc/LinkDef1.h             |   3 +-
 geom/inc/TGeoManager.h          |   4 +-
 geom/inc/TGeoShape.h            |   5 +-
 geom/inc/TGeoXtru.h             |  87 ++++++
 geom/inc/TVirtualGeoPainter.h   |   4 +-
 geom/src/TGeoManager.cxx        |  11 +
 geom/src/TGeoXtru.cxx           | 462 ++++++++++++++++++++++++++++++++
 geompainter/inc/TGeoPainter.h   |   2 +
 geompainter/src/TGeoPainter.cxx | 144 +++++++++-
 minuit/src/TMinuit.cxx          |  18 +-
 11 files changed, 729 insertions(+), 13 deletions(-)
 create mode 100644 geom/inc/TGeoXtru.h
 create mode 100644 geom/src/TGeoXtru.cxx

diff --git a/geom/Module.mk b/geom/Module.mk
index e7c47348ae5..2e5d1b2e987 100644
--- a/geom/Module.mk
+++ b/geom/Module.mk
@@ -31,7 +31,7 @@ GEOMH1       := TGeoAtt.h TGeoBoolNode.h \
                 TGeoPgon.h TGeoArb8.h TGeoTrd1.h TGeoTrd2.h \
                 TGeoManager.h TGeoCompositeShape.h \
                 TVirtualGeoPainter.h TVirtualGeoTrack.h \
-		TGeoPolygon.h
+		TGeoPolygon.h TGeoXtru.h
 GEOMH2       := TGeoPatternFinder.h TGeoCache.h
 GEOMH1       := $(patsubst %,$(MODDIRI)/%,$(GEOMH1))
 GEOMH2       := $(patsubst %,$(MODDIRI)/%,$(GEOMH2))
diff --git a/geom/inc/LinkDef1.h b/geom/inc/LinkDef1.h
index e866a1cfe85..4b96745c740 100644
--- a/geom/inc/LinkDef1.h
+++ b/geom/inc/LinkDef1.h
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: LinkDef1.h,v 1.2 2003/10/20 08:46:33 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: LinkDef1.h,v 1.3 2004/01/20 15:44:32 brun Exp $
 // Author : Andrei Gheata 10/06/02
 /*************************************************************************
  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
@@ -56,6 +56,7 @@
 #pragma link C++ class TGeoTrd2+;
 #pragma link C++ class TGeoCompositeShape+;
 #pragma link C++ class TGeoPolygon+;
+#pragma link C++ class TGeoXtru+;
 #pragma link C++ class TGeoVolume-;
 #pragma link C++ class TGeoVolumeAssembly+;
 #pragma link C++ class TGeoVolumeMulti+;
diff --git a/geom/inc/TGeoManager.h b/geom/inc/TGeoManager.h
index b584d27c544..3cec6457600 100644
--- a/geom/inc/TGeoManager.h
+++ b/geom/inc/TGeoManager.h
@@ -285,6 +285,8 @@ public:
    TGeoVolume            *MakeTubs(const char *name, const TGeoMedium *medium,
                                       Double_t rmin, Double_t rmax, Double_t dz,
                                       Double_t phi1, Double_t phi2);
+   TGeoVolume            *MakeXtru(const char *name, const TGeoMedium *medium,
+                                   Int_t nz);
    TGeoVolumeAssembly    *MakeVolumeAssembly(const char *name);
    TGeoVolumeMulti       *MakeVolumeMulti(const char *name, const TGeoMedium *medium);
    void                   SetTopVolume(TGeoVolume *vol);
@@ -331,7 +333,7 @@ public:
    Bool_t                 IsOutside() const            {return fIsOutside;} 
    Bool_t                 IsOnBoundary() const         {return fIsOnBoundary;}
    Bool_t                 IsNullStep() const           {return fIsNullStep;}
-   void                   SetOutside()                 {fIsOutside = kTRUE;}
+   void                   SetOutside(Bool_t flag=kTRUE) {fIsOutside = flag;}
    void                   UpdateCurrentPosition(Double_t *nextpoint);
    
 
diff --git a/geom/inc/TGeoShape.h b/geom/inc/TGeoShape.h
index d684ef010dc..cf087709545 100644
--- a/geom/inc/TGeoShape.h
+++ b/geom/inc/TGeoShape.h
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TGeoShape.h,v 1.19 2003/12/10 17:09:07 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TGeoShape.h,v 1.20 2003/12/11 10:34:33 brun Exp $
 // Author: Andrei Gheata   31/01/02
 
 /*************************************************************************
@@ -62,7 +62,8 @@ enum EShapeType {
    kGeoTrd1    = BIT(23),
    kGeoTrd2    = BIT(24),
    kGeoComb    = BIT(25),
-   kGeoClosedShape = BIT(26)
+   kGeoClosedShape = BIT(26),
+   kGeoXtru    = BIT(27)
 };
 
 protected :
diff --git a/geom/inc/TGeoXtru.h b/geom/inc/TGeoXtru.h
new file mode 100644
index 00000000000..1adfa0a675a
--- /dev/null
+++ b/geom/inc/TGeoXtru.h
@@ -0,0 +1,87 @@
+// @(#)root/geom:$Name:  $:$Id: $
+// Author: Mihaela Gheata   24/01/04
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TGeoXtru
+#define ROOT_TGeoXtru
+
+#ifndef ROOT_TGeoBBox
+#include "TGeoBBox.h"
+#endif
+
+  
+/*************************************************************************
+ * TGeoXtru - An extrusion with fixed outline shape in x-y and a sequence
+ * of z extents (segments).  The overall scale of the outline scales
+ * linearly between z points and the center can have an x-y offset.
+ *
+ * Based on the initial implementation of R. Hatcher
+ *************************************************************************/
+
+class TGeoPolygon;
+
+class TGeoXtru : public TGeoBBox
+{
+protected:
+   // data members
+   Int_t                 fNvert; // number of vertices of the 2D polygon (at least 3)
+   Int_t                 fNz;    // number of z planes (at least two)
+   Double_t              fZcurrent; // current Z position
+   TGeoPolygon          *fPoly;  // polygon defining section shape
+   Double_t             *fX;     //[fNvert] X positions for polygon vertices
+   Double_t             *fY;     //[fNvert] Y positions for polygon vertices
+   Double_t             *fXc;    //[fNvert] current X positions for polygon vertices
+   Double_t             *fYc;    //[fNvert] current Y positions for polygon vertices
+   Double_t             *fZ;     //[fNz] array of Z planes positions 
+   Double_t             *fScale; //[fNz] array of scale factors (for each Z)
+   Double_t             *fX0;    //[fNz] array of X offsets (for each Z)
+   Double_t             *fY0;    //[fNz] array of Y offsets (for each Z)
+public:
+   // constructors
+   TGeoXtru();
+   TGeoXtru(Int_t nz);
+   TGeoXtru(const char *name, Int_t nz);
+   TGeoXtru(Double_t *param);
+   // destructor
+   virtual ~TGeoXtru();
+   // methods
+   virtual void          ComputeBBox();
+   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
+   virtual Bool_t        Contains(Double_t *point) const;
+   Bool_t                DefinePolygon(Int_t nvert, const Double_t *xv, const Double_t *yv);
+   virtual void          DefineSection(Int_t snum, Double_t z, Double_t x0=0., Double_t y0=0., Double_t scale=1.);
+   virtual Double_t      DistToOut(Double_t *point, Double_t *dir, Int_t iact=1, 
+                                   Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual Double_t      DistToIn(Double_t *point, Double_t *dir, Int_t iact=1, 
+                                   Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
+//   virtual Int_t         GetByteCount() const {return 60+12*fNz;}
+   Int_t                 GetNz() const    {return fNz;}
+   Int_t                 GetNvert() const {return fNvert;}
+   Double_t             *GetZ() const     {return fZ;}
+   Double_t              GetZ(Int_t ipl) const;
+   virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape * /*mother*/, TGeoMatrix * /*mat*/) const {return 0;}
+   virtual void          InspectShape() const;
+   virtual void         *Make3DBuffer(const TGeoVolume *vol) const;
+   virtual void          Paint(Option_t *option);
+   virtual void          PaintNext(TGeoHMatrix *glmat, Option_t *option);
+   Double_t             &Z(Int_t ipl) {return fZ[ipl];}
+   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   void                  SetCurrentZ(Double_t z, Int_t iz);
+   void                  SetCurrentVertices(Double_t x0, Double_t y0, Double_t scale);
+   virtual void          SetDimensions(Double_t *param);
+   virtual void          SetPoints(Double_t *buff) const;
+   virtual void          SetPoints(Float_t *buff) const;
+   virtual void          Sizeof3D() const;
+
+  ClassDef(TGeoXtru, 1)         // extruded polygon class 
+};
+
+#endif
diff --git a/geom/inc/TVirtualGeoPainter.h b/geom/inc/TVirtualGeoPainter.h
index 5d72cdb3735..48a137f0ce6 100644
--- a/geom/inc/TVirtualGeoPainter.h
+++ b/geom/inc/TVirtualGeoPainter.h
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TVirtualGeoPainter.h,v 1.22 2003/08/29 09:55:29 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TVirtualGeoPainter.h,v 1.23 2003/11/11 15:44:28 brun Exp $
 // Author: Andrei Gheata   11/01/02
 
 /*************************************************************************
@@ -102,6 +102,7 @@ public:
    virtual void      *MakeTubs3DBuffer(const TGeoVolume *vol) = 0;
    virtual void      *MakePcon3DBuffer(const TGeoVolume *vol) = 0;
    virtual void      *MakeSphere3DBuffer(const TGeoVolume *vol) = 0;
+   virtual void      *MakeXtru3DBuffer(const TGeoVolume *vol) = 0;
    virtual void       ModifiedPad() const = 0;
    virtual void       Paint(Option_t *option="") = 0;
    virtual void       PaintBox(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0) = 0;
@@ -111,6 +112,7 @@ public:
    virtual void       PaintTubs(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0) = 0;
    virtual void       PaintSphere(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0) = 0;
    virtual void       PaintPcon(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0) = 0;
+   virtual void       PaintXtru(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0) = 0;
    virtual void       PaintNode(TGeoNode *node, Option_t *option="") = 0;
    virtual void       PaintOverlap(void *ovlp, Option_t *option="")  = 0;
    virtual void       PrintOverlaps() const = 0;
diff --git a/geom/src/TGeoManager.cxx b/geom/src/TGeoManager.cxx
index 808ee2bbb6e..50e9b091f7a 100644
--- a/geom/src/TGeoManager.cxx
+++ b/geom/src/TGeoManager.cxx
@@ -428,6 +428,7 @@
 #include "TGeoTrd1.h"
 #include "TGeoTrd2.h"
 #include "TGeoTorus.h"
+#include "TGeoXtru.h"
 #include "TGeoCompositeShape.h"
 #include "TVirtualGeoPainter.h"
 #include "TVirtualGeoTrack.h"
@@ -3481,6 +3482,16 @@ TGeoVolume *TGeoManager::MakeGtra(const char *name, const TGeoMedium *medium,
    TGeoVolume *vol = new TGeoVolume(name, gtra, medium);
    return vol;
 }
+//_____________________________________________________________________________
+TGeoVolume *TGeoManager::MakeXtru(const char *name, const TGeoMedium *medium, Int_t nz)
+{
+// Make a TGeoXtru-shaped volume with nz planes
+   TGeoXtru *xtru = new TGeoXtru(nz);
+
+   TGeoVolume *vol = new TGeoVolume(name, xtru, medium);
+   return vol;
+}   
+
 //_____________________________________________________________________________
 TGeoVolumeAssembly *TGeoManager::MakeVolumeAssembly(const char *name)
 {
diff --git a/geom/src/TGeoXtru.cxx b/geom/src/TGeoXtru.cxx
new file mode 100644
index 00000000000..c9d72b6d4d1
--- /dev/null
+++ b/geom/src/TGeoXtru.cxx
@@ -0,0 +1,462 @@
+// @(#)root/geom:$Name:  $:$Id:$
+// Author: Mihaela Gheata   24/01/04
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+/*************************************************************************
+ * TGeoXtru - An extrusion with fixed outline shape in x-y and a sequence
+ * of z extents (segments).  The overall scale of the outline scales
+ * linearly between z points and the center can have an x-y offset.
+ *
+ * Based on the initial implementation of R. Hatcher
+ *************************************************************************/
+
+// Creation of TGeoXtru shape
+//=============================
+//   A TGeoXtru represents a polygonal extrusion. It is defined by the:
+// a. 'Blueprint' of the arbitrary polygon representing any Z section. This
+//    is an arbytrary polygon (convex or not) defined by the X/Y positions of
+//    its vertices.
+// b. A sequence of Z sections ordered on the Z axis. Each section defines the
+//   'actual' parameters of the polygon at a given Z. The sections may be 
+//    translated with respect to the blueprint and/or scaled. The TGeoXtru
+//   segment in between 2 Z sections is a solid represented by the linear 
+//   extrusion between the 2 polygons. Two consecutive sections may be defined
+//   at same Z position.
+//
+// 1. TGeoXtru *xtru = TGeoXtru(Int_t nz);
+//   where nz=number of Z planes
+// 2. Double_t x[nvertices]; // array of X positions of blueprint polygon vertices
+//    Double_t y[nvertices]; // array of Y positions of blueprint polygon vertices
+// 3. xtru->DefinePolygon(nvertices,x,y);
+// 4. DefineSection(0, z0, x0, y0, scale0); // Z position, offset and scale for first section
+//    DefineSection(1, z1, x1, y1, scale1); // -''- secons section
+//    ....
+//    DefineSection(nz-1, zn, xn, yn, scalen); // parameters for last section
+//
+// *NOTES*
+// Currently navigation functionality not fully implemented (only Contains()).
+// Decomposition in concave polygons not implemented - drawing in solid mode
+// within x3d produces incorrect end-faces
+
+#include "TROOT.h"
+
+#include "TGeoManager.h"
+#include "TGeoVolume.h"
+#include "TGeoPolygon.h"
+#include "TVirtualGeoPainter.h"
+#include "TGeoXtru.h"
+
+ClassImp(TGeoXtru)
+
+//_____________________________________________________________________________
+TGeoXtru::TGeoXtru()
+{
+// dummy ctor
+   SetShapeBit(TGeoShape::kGeoXtru);
+   fNvert = 0;
+   fNz = 0;
+   fZcurrent = 0.;
+   fPoly = 0;
+   fX = 0;
+   fY = 0;
+   fXc = 0;
+   fYc = 0;
+   fZ = 0;
+   fScale = 0;
+   fX0 = 0;
+   fY0 = 0;
+}   
+
+//_____________________________________________________________________________
+TGeoXtru::TGeoXtru(Int_t nz)
+         :TGeoBBox(0, 0, 0)
+{
+// Default constructor
+   SetShapeBit(TGeoShape::kGeoXtru);
+   if (nz<2) {
+      Error("ctor", "Cannot create TGeoXtru with less than 2 Z planes");
+      return;
+   }
+   fNvert = 0;
+   fNz = nz;   
+   fZcurrent = 0.;
+   fPoly = 0;
+   fX = 0;
+   fY = 0;
+   fXc = 0;
+   fYc = 0;
+   fZ = new Double_t[nz];
+   fScale = new Double_t[nz];
+   fX0 = new Double_t[nz];
+   fY0 = new Double_t[nz];
+}
+
+//_____________________________________________________________________________
+TGeoXtru::TGeoXtru(Double_t *param)
+         :TGeoBBox(0, 0, 0)
+{
+// Default constructor in GEANT3 style
+// param[0] = nz  // number of z planes
+//
+// param[1] = z1  // Z position of first plane
+// param[2] = x1  // X position of first plane
+// param[3] = y1  // Y position of first plane
+// param[4] = scale1  // scale factor for first plane
+// ...
+// param[4*(nz-1]+1] = zn
+// param[4*(nz-1)+2] = xn
+// param[4*(nz-1)+3] = yn
+// param[4*(nz-1)+4] = scalen
+   SetShapeBit(TGeoShape::kGeoXtru);
+   fNvert = 0;
+   fNz = 0;
+   fZcurrent = 0.;
+   fPoly = 0;
+   fX = 0;
+   fY = 0;
+   fXc = 0;
+   fYc = 0;
+   fZ = 0;
+   fScale = 0;
+   fX0 = 0;
+   fY0 = 0;
+   SetDimensions(param);
+}
+
+//_____________________________________________________________________________
+TGeoXtru::~TGeoXtru()
+{
+// destructor
+   if (fX)  {delete[] fX; fX = 0;}
+   if (fY)  {delete[] fY; fY = 0;}
+   if (fXc) {delete[] fXc; fXc = 0;}
+   if (fYc) {delete[] fYc; fYc = 0;}
+   if (fZ)  {delete[] fZ; fZ = 0;}
+   if (fScale) {delete[] fScale; fScale = 0;}
+   if (fX0)  {delete[] fX0; fX0 = 0;}
+   if (fY0)  {delete[] fY0; fY0 = 0;}
+}
+
+//_____________________________________________________________________________   
+void TGeoXtru::ComputeBBox()
+{
+// compute bounding box of the pcon
+   if (!fX || !fZ || !fNvert) {
+      Error("ComputeBBox", "polygon not defined");
+      return;
+   }   
+   Double_t zmin = fZ[0];
+   Double_t zmax = fZ[fNz-1];
+   Double_t xmin = TGeoShape::Big();
+   Double_t xmax = -TGeoShape::Big();
+   Double_t ymin = TGeoShape::Big();
+   Double_t ymax = -TGeoShape::Big();
+   for (Int_t i=0; i<fNz; i++) {
+      SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
+      for (Int_t j=0; j<fNvert; j++) {
+         if (fXc[j]<xmin) xmin=fXc[j];
+         if (fXc[j]>xmax) xmax=fXc[j];
+         if (fYc[j]<ymin) ymin=fYc[j];
+         if (fYc[j]>ymax) ymax=fYc[j];
+      }
+   }
+   fOrigin[0] = 0.5*(xmin+xmax);      
+   fOrigin[1] = 0.5*(ymin+ymax);      
+   fOrigin[2] = 0.5*(zmin+zmax);      
+   fDX = 0.5*(xmax-xmin);
+   fDY = 0.5*(ymax-ymin);
+   fDZ = 0.5*(zmax-zmin);
+}   
+
+//_____________________________________________________________________________   
+void TGeoXtru::ComputeNormal(Double_t * /*point*/, Double_t * /*dir*/, Double_t *norm)
+{
+// Compute normal to closest surface from POINT. 
+   memset(norm,0,3*sizeof(Double_t));
+   norm[2] = 1.;
+   Warning("ComputeNormal", "not implemented");
+}
+
+//_____________________________________________________________________________
+Bool_t TGeoXtru::Contains(Double_t *point) const
+{
+// test if point is inside this shape
+   // Check Z range
+   TGeoXtru *xtru = (TGeoXtru*)this;
+   if (point[2]<fZ[0]) return kFALSE;   
+   if (point[2]>fZ[fNz-1]) return kFALSE; 
+   Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
+   if (point[2]==fZ[iz]) {
+      xtru->SetCurrentVertices(fX0[iz],fY0[iz], fScale[iz]);
+      if (fPoly->Contains(point)) return kTRUE;
+      if (iz>1 && fZ[iz]==fZ[iz-1]) {
+         xtru->SetCurrentVertices(fX0[iz-1],fY0[iz-1], fScale[iz-1]);
+         return fPoly->Contains(point);
+      } else if (iz<fNz-2 && fZ[iz]==fZ[iz+1]) {
+         xtru->SetCurrentVertices(fX0[iz+1],fY0[iz+1], fScale[iz+1]);
+         return fPoly->Contains(point);
+      }      
+   }      
+   xtru->SetCurrentZ(point[2], iz);
+   // Now fXc,fYc represent the vertices of the section at point[2]
+   return fPoly->Contains(point);
+}
+
+//_____________________________________________________________________________
+Int_t TGeoXtru::DistancetoPrimitive(Int_t px, Int_t py)
+{
+// compute closest distance from point px,py to each corner
+   const Int_t numPoints = fNvert*fNz;
+   return ShapeDistancetoPrimitive(numPoints, px, py);
+}
+
+//_____________________________________________________________________________
+Double_t TGeoXtru::DistToOut(Double_t * /*point*/, Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
+{
+// compute distance from inside point to surface of the polycone
+   Warning("DistToOut", "not implemented");
+   return TGeoShape::Big();  
+}
+
+//_____________________________________________________________________________
+Double_t TGeoXtru::DistToIn(Double_t * /*point*/, Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
+{
+// compute distance from outside point to surface of the tube
+   Warning("DistToIn", "not implemented");
+   return TGeoShape::Big();  
+}
+
+//_____________________________________________________________________________
+Bool_t TGeoXtru::DefinePolygon(Int_t nvert, const Double_t *xv, const Double_t *yv)
+{
+// Creates the polygon representing the blueprint of any Xtru section.
+//   nvert     = number of vertices >2
+//   xv[nvert] = array of X vertex positions 
+//   yv[nvert] = array of Y vertex positions 
+// *NOTE* should be called before DefineSection or ctor with 'param'
+   if (nvert<3) {
+      Error("DefinePolygon","cannot create polygon with less than 3 vertices");
+      return kFALSE;
+   }
+   fNvert = nvert;
+   if (fX) delete [] fX;
+   fX = new Double_t[nvert];
+   if (fY) delete [] fY;
+   fY = new Double_t[nvert];
+   if (fXc) delete [] fXc;
+   fXc = new Double_t[nvert];
+   if (fYc) delete [] fYc;
+   fYc = new Double_t[nvert];
+   memcpy(fX,xv,nvert*sizeof(Double_t));
+   memcpy(fXc,xv,nvert*sizeof(Double_t));
+   memcpy(fY,yv,nvert*sizeof(Double_t));
+   memcpy(fYc,yv,nvert*sizeof(Double_t));
+   
+   if (fPoly) delete fPoly;
+   fPoly = new TGeoPolygon(nvert);
+   fPoly->SetXY(fXc,fYc); // initialize with current coordinates
+   fPoly->FinishPolygon();
+   return kTRUE;
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::DefineSection(Int_t snum, Double_t z, Double_t x0, Double_t y0, Double_t scale)
+{
+// defines z position of a section plane, rmin and rmax at this z.
+   if ((snum<0) || (snum>=fNz)) return;
+   fZ[snum]  = z;
+   fX0[snum] = x0;
+   fY0[snum] = y0;
+   fScale[snum] = scale;
+   if (snum) {
+      if (fZ[snum]<fZ[snum-1]) {
+         Warning("DefineSection", "Z position of section %i not in increasing order",snum);
+         return;
+      }   
+   }
+   if (snum==(fNz-1)) ComputeBBox();
+}
+            
+//_____________________________________________________________________________
+Double_t TGeoXtru::GetZ(Int_t ipl) const
+{
+   if (ipl<0 || ipl>(fNz-1)) {
+      Error("GetZ","ipl=%i out of range (0,%i)",ipl,0,fNz-1);
+      return 0.;
+   }
+   return fZ[ipl];
+}      
+
+//_____________________________________________________________________________
+void TGeoXtru::InspectShape() const
+{
+// print shape parameters
+   printf("*** TGeoXtru parameters ***\n");
+   printf("    Nz    = %i\n", fNz);
+   printf("    List of (x,y) of polygon vertices:\n");
+   for (Int_t ivert = 0; ivert<fNvert; ivert++)
+      printf("    x = %11.5f  y = %11.5f\n", fX[ivert],fY[ivert]);
+   for (Int_t ipl=0; ipl<fNz; ipl++)
+      printf("     plane %i: z=%11.5f x0=%11.5f y0=%11.5f scale=%11.5f\n", ipl, fZ[ipl], fX0[ipl], fY0[ipl], fScale[ipl]);
+   TGeoBBox::InspectShape();
+}
+
+//_____________________________________________________________________________
+void *TGeoXtru::Make3DBuffer(const TGeoVolume *vol) const
+{
+   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
+   if (!painter) return 0;
+   return painter->MakeXtru3DBuffer(vol);
+}   
+
+//_____________________________________________________________________________
+void TGeoXtru::Paint(Option_t *option)
+{
+// paint this shape according to option
+   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
+   if (!painter) return;
+   TGeoVolume *vol = gGeoManager->GetCurrentVolume();
+   if (vol->GetShape() != (TGeoShape*)this) return;
+   painter->PaintXtru(this, option);
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::PaintNext(TGeoHMatrix *glmat, Option_t *option)
+{
+// paint this shape according to option
+   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
+   if (!painter) return;
+   painter->PaintXtru(this, option, glmat);
+}
+
+//_____________________________________________________________________________
+Double_t TGeoXtru::Safety(Double_t * /*point*/, Bool_t /*in*/) const
+{
+// computes the closest distance from given point to this shape, according
+// to option. The matching point on the shape is stored in spoint.
+   //---> localize the Z segment
+   Warning("Safety", "not implemented");
+   return TGeoShape::Big();  
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::SetCurrentZ(Double_t z, Int_t iz)
+{
+// Recompute current section vertices for a given Z position within range of section iz.
+   Double_t x0, y0, scale, a, b;
+   Int_t ind1, ind2;
+   ind1 = iz;
+   ind2 = iz+1;   
+   Double_t invdz = 1./(fZ[ind2]-fZ[ind1]);
+   a = (fX0[ind1]*fZ[ind2]-fX0[ind2]*fZ[ind1])*invdz;
+   b = (fX0[ind2]-fX0[ind1])*invdz;
+   x0 = a+b*z;
+   a = (fY0[ind1]*fZ[ind2]-fY0[ind2]*fZ[ind1])*invdz;
+   b = (fY0[ind2]-fY0[ind1])*invdz;
+   y0 = a+b*z;
+   a = (fScale[ind1]*fZ[ind2]-fScale[ind2]*fZ[ind1])*invdz;
+   b = (fScale[ind2]-fScale[ind1])*invdz;
+   scale = a+b*z;
+   SetCurrentVertices(x0,y0,scale);
+}
+      
+//_____________________________________________________________________________
+void TGeoXtru::SetCurrentVertices(Double_t x0, Double_t y0, Double_t scale)      
+{
+// Set current vertex coordinates according X0, Y0 and SCALE.
+   for (Int_t i=0; i<fNvert; i++) {
+      fXc[i] = scale*fX[i] + x0;
+      fYc[i] = scale*fY[i] + y0;
+   }   
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::SetDimensions(Double_t *param)
+{
+// param[0] = nz  // number of z planes
+//
+// param[1] = z1  // Z position of first plane
+// param[2] = x1  // X position of first plane
+// param[3] = y1  // Y position of first plane
+// param[4] = scale1  // scale factor for first plane
+// ...
+// param[4*(nz-1]+1] = zn
+// param[4*(nz-1)+2] = xn
+// param[4*(nz-1)+3] = yn
+// param[4*(nz-1)+4] = scalen
+   fNz = (Int_t)param[0];   
+   if (fNz<2) {
+      Error("SetDimensions","Cannot create TGeoXtru with less than 2 Z planes");
+      return;
+   }
+   if (fZ) delete [] fZ;
+   if (fScale) delete [] fScale;
+   if (fX0) delete [] fX0;
+   if (fY0) delete [] fY0;
+   fZ = new Double_t[fNz];
+   fScale = new Double_t[fNz];
+   fX0 = new Double_t[fNz];
+   fY0 = new Double_t[fNz];
+   
+   for (Int_t i=0; i<fNz; i++) 
+      DefineSection(i, param[1+4*i], param[2+4*i], param[3+4*i], param[4+4*i]);
+}   
+
+//_____________________________________________________________________________
+void TGeoXtru::SetPoints(Double_t *buff) const
+{
+// create polycone mesh points
+   Int_t i, j;
+   Int_t indx = 0;
+   TGeoXtru *xtru = (TGeoXtru*)this;
+   if (buff) {
+      for (i = 0; i < fNz; i++) {
+         xtru->SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
+         for (j = 0; j < fNvert; j++) {
+            buff[indx++] = fXc[j];
+            buff[indx++] = fYc[j];
+            buff[indx++] = fZ[i];
+         }
+      }
+   }
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::SetPoints(Float_t *buff) const
+{
+// create polycone mesh points
+   Int_t i, j;
+   Int_t indx = 0;
+   TGeoXtru *xtru = (TGeoXtru*)this;
+   if (buff) {
+      for (i = 0; i < fNz; i++) {
+         xtru->SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
+         for (j = 0; j < fNvert; j++) {
+            buff[indx++] = fXc[j];
+            buff[indx++] = fYc[j];
+            buff[indx++] = fZ[i];
+         }
+      }
+   }
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::Sizeof3D() const
+{
+// fill size of this 3-D object
+   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
+   if (!painter) return;
+
+   Int_t numPoints = fNz*fNvert;
+   Int_t numSegs   = fNvert*(2*fNz-1);
+   Int_t numPolys  = fNvert*(fNz-1)+2;
+   painter->AddSize3D(numPoints, numSegs, numPolys);
+}
+
diff --git a/geompainter/inc/TGeoPainter.h b/geompainter/inc/TGeoPainter.h
index 2492266db43..4e05d779964 100644
--- a/geompainter/inc/TGeoPainter.h
+++ b/geompainter/inc/TGeoPainter.h
@@ -118,6 +118,7 @@ public:
    virtual void      *MakeTubs3DBuffer(const TGeoVolume *vol);
    virtual void      *MakeSphere3DBuffer(const TGeoVolume *vol);
    virtual void      *MakePcon3DBuffer(const TGeoVolume *vol);
+   virtual void      *MakeXtru3DBuffer(const TGeoVolume *vol);
    virtual void       Paint(Option_t *option="");
    void               PaintShape(X3DBuffer *buff, Bool_t rangeView, TGeoHMatrix *glmat);
    void               PaintBox(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0);
@@ -126,6 +127,7 @@ public:
    void               PaintTube(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0);
    void               PaintTubs(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0);
    void               PaintSphere(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0);
+   void               PaintXtru(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0);
    virtual void       PaintNode(TGeoNode *node, Option_t *option="");
    void               PaintPcon(TGeoShape *shape, Option_t *option="", TGeoHMatrix *glmat=0);
    virtual void       PaintOverlap(void *ovlp, Option_t *option="");
diff --git a/geompainter/src/TGeoPainter.cxx b/geompainter/src/TGeoPainter.cxx
index 0e8ca9ae32f..ed60db4fb6f 100644
--- a/geompainter/src/TGeoPainter.cxx
+++ b/geompainter/src/TGeoPainter.cxx
@@ -1,4 +1,4 @@
-// @(#)root/geompainter:$Name:  $:$Id: TGeoPainter.cxx,v 1.33 2003/11/28 13:52:35 brun Exp $
+// @(#)root/geompainter:$Name:  $:$Id: TGeoPainter.cxx,v 1.34 2003/12/11 10:34:55 brun Exp $
 // Author: Andrei Gheata   05/03/02
 /*************************************************************************
  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
@@ -25,6 +25,7 @@
 #include "TGeoSphere.h"
 #include "TGeoPcon.h"
 #include "TGeoTorus.h"
+#include "TGeoXtru.h"
 #include "TGeoVolume.h"
 #include "TGeoNode.h"
 #include "TGeoManager.h"
@@ -1062,6 +1063,24 @@ void *TGeoPainter::MakeTube3DBuffer(const TGeoVolume *vol)
    return buff;
 }   
 
+//______________________________________________________________________________
+void *TGeoPainter::MakeXtru3DBuffer(const TGeoVolume *vol)
+{
+// Create a box 3D buffer for a given shape.
+   X3DPoints *buff = new X3DPoints;
+   TGeoXtru *xtru = (TGeoXtru*)vol->GetShape();
+   Int_t numpoints = xtru->GetNz()*xtru->GetNvert();
+
+   buff->numPoints = numpoints;
+
+   Double_t *points = new Double_t[3*numpoints];
+
+   xtru->SetPoints(points);
+
+   buff->points = points;
+   return buff;
+}   
+
 //______________________________________________________________________________
 void TGeoPainter::PaintTorus(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
 {
@@ -2095,6 +2114,129 @@ void TGeoPainter::PaintPcon(TGeoShape *shape, Option_t *option, TGeoHMatrix *glm
     if (buff->polys)    delete [] buff->polys;
     if (buff)           delete    buff;
 }
+
+//______________________________________________________________________________
+void TGeoPainter::PaintXtru(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
+{
+// Paint a TGeoXtru
+   TGeoXtru *xtru = (TGeoXtru*)shape;
+   Int_t nz = xtru->GetNz();
+   Int_t nvert = xtru->GetNvert();
+   Int_t numPoints =  nz*nvert;
+   Int_t numSegs   = nvert*(2*nz-1);
+   Int_t numPolys  = nvert*(nz-1)+2;
+   
+   Float_t *points = new Float_t[3*numPoints];
+   if (!points) return;
+   shape->SetPoints(points);
+
+   Bool_t rangeView = strcmp(option,"range")==0 ? kTRUE : kFALSE;
+//   if (!rangeView && gPad->GetView3D()) gVirtualGL->PaintCone(points, -n, nz);
+
+   Bool_t is3d = kFALSE;
+   if (strstr(option, "x3d")) is3d=kTRUE;   
+   X3DBuffer *buff = new X3DBuffer;
+   if (buff) {
+      buff->numPoints = numPoints;
+      buff->numSegs   = numSegs;
+      buff->numPolys  = (is3d)?numPolys:0;
+  }
+
+//*-* Allocate memory for points *-*
+
+   buff->points = points;
+
+   Int_t c = ((fGeom->GetCurrentVolume()->GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
+   if (c < 0) c = 0;
+   if (fPaintingOverlaps) {
+      if (fOverlap->IsExtrusion()) {
+         if (fOverlap->GetVolume()->GetShape()==shape) c=8;
+         else c=12;
+      } else {
+         if (fOverlap->GetNode(0)->GetVolume()->GetShape()==shape) c=8;
+         else c=12;
+      }   
+   }
+
+//*-* Allocate memory for segments *-*
+   buff->segs = new Int_t[buff->numSegs*3];
+   Int_t i,j;
+   Int_t indx, indx2, k;
+   indx = indx2 = 0;
+   for (i=0; i<nz; i++) {
+      // loop Z planes
+      indx2 = i*nvert;
+      // loop polygon segments
+      for (j=0; j<nvert; j++) {
+         k = (j+1)%nvert;
+         buff->segs[indx++] = c;
+         buff->segs[indx++] = indx2+j;
+         buff->segs[indx++] = indx2+k;
+      } 
+   } // total: nz*nvert polygon segments    
+   for (i=0; i<nz-1; i++) {
+      // loop Z planes
+      indx2 = i*nvert;
+      // loop polygon segments
+      for (j=0; j<nvert; j++) {
+         k = j + nvert;
+         buff->segs[indx++] = c;
+         buff->segs[indx++] = indx2+j;
+         buff->segs[indx++] = indx2+k;
+      }
+   } // total (nz-1)*nvert lateral segments
+
+//*-* Allocate memory for polygons *-*
+   indx = 0;
+
+   buff->polys = 0;
+   if (is3d) {
+      buff->polys = new Int_t[(buff->numPolys-2)*6 + 2*(2+nvert)];
+      // fill lateral polygons
+      for (i=0; i<nz-1; i++) {
+         indx2 = i*nvert;
+         for (j=0; j<nvert; j++) {
+            k = (j+1)%nvert;
+            buff->polys[indx++] = c+j%3;
+            buff->polys[indx++] = 4;
+            buff->polys[indx++] = indx2+j;
+            buff->polys[indx++] = nz*nvert+indx2+k;
+            buff->polys[indx++] = indx2+nvert+j;
+            buff->polys[indx++] = nz*nvert+indx2+j;
+         }
+      } // total (nz-1)*nvert polys
+      buff->polys[indx++] = c+2;      
+      buff->polys[indx++] = nvert;
+      indx2 = 0;
+      for (j=0; j<nvert; j++) {
+         buff->polys[indx++] = indx2+j;
+      }   
+      buff->polys[indx++] = c;      
+      buff->polys[indx++] = nvert;
+      indx2 = (nz-1)*nvert;          
+      for (j=0; j<nvert; j++) {
+         buff->polys[indx++] = indx2+j;
+      }   
+   }
+    //*-* Paint in the pad
+    PaintShape(buff,rangeView, glmat);
+
+    if (is3d) {
+        if(buff && buff->points && buff->segs)
+            FillX3DBuffer(buff);
+        else {
+            gSize3D.numPoints -= buff->numPoints;
+            gSize3D.numSegs   -= buff->numSegs;
+            gSize3D.numPolys  -= buff->numPolys;
+        }
+    }
+
+    delete [] points;
+    if (buff->segs)     delete [] buff->segs;
+    if (buff->polys)    delete [] buff->polys;
+    if (buff)           delete    buff;    
+}
+
 //______________________________________________________________________________
 void TGeoPainter::PaintNode(TGeoNode *node, Option_t *option)
 {
diff --git a/minuit/src/TMinuit.cxx b/minuit/src/TMinuit.cxx
index a01cd249369..570ed1de0e7 100644
--- a/minuit/src/TMinuit.cxx
+++ b/minuit/src/TMinuit.cxx
@@ -1,4 +1,4 @@
-// @(#)root/minuit:$Name:  $:$Id: TMinuit.cxx,v 1.36 2003/09/19 08:08:14 brun Exp $
+// @(#)root/minuit:$Name:  $:$Id: TMinuit.cxx,v 1.37 2003/10/30 16:44:19 brun Exp $
 // Author: Rene Brun, Frederick James   12/08/95
 
 /*************************************************************************
@@ -4451,14 +4451,20 @@ void TMinuit::mninex(Double_t *pint)
 
     Int_t i, j;
 
-    for (j = 1; j <= fNpar; ++j) {
-	i = fNexofi[j-1];
-	if (fNvarl[i-1] == 1) {
-	    fU[i-1] = pint[j-1];
+    for (j = 0; j < fNpar; ++j) {
+	i = fNexofi[j]-1;
+	if (fNvarl[i] == 1) {
+	    fU[i] = pint[j];
 	} else {
-	    fU[i-1] = fAlim[i-1] + (TMath::Sin(pint[j-1]) + 1)*.5*(fBlim[i-1] - fAlim[i-1]);
+	    fU[i] = fAlim[i] + (TMath::Sin(pint[j]) + 1)*.5*(fBlim[i] - fAlim[i]);
 	}
     }
+    //printf("mnimex: fU[0]=%g, pint[0]=%g, fAlim[0]=%g, fBlim[0]=%g\n",fU[0],pint[0],fAlim[0],fBlim[0]);
+   if(TMath::IsNaN(fU[0])) {
+      printf("mnimex: fU[0]=%g, pint[0]=%g, fAlim[0]=%g, fBlim[0]=%g\n",fU[0],pint[0],fAlim[0],fBlim[0]);
+      TMinuit *junk=0 ;
+      junk->GetObjectFit()->Paint(); 
+   } 
 } /* mninex_ */
 
 //______________________________________________________________________________
-- 
GitLab