diff --git a/geom/Module.mk b/geom/Module.mk
index e7c47348ae5d9d08126a1db3d362142cd3145a1f..2e5d1b2e987781046b4542999f31cf6c6230ff5f 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 e866a1cfe8577dd4db15aa4f2ea955e7774f6cd7..4b96745c7406b5b4f116b19a02553c492a46c428 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 b584d27c5445c5c7254e344760a408903977b641..3cec64576005fb81171715ac7be38ad0536506e3 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 d684ef010dc11f794ead9453819a3b61d7531ee8..cf087709545bb9aeea125a1c2fc6f0a028649340 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 0000000000000000000000000000000000000000..1adfa0a675a1ba9740b52293b5a5e9a6c404359a
--- /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 5d72cdb373551d37895b637e9f9436aa5ec3bf84..48a137f0ce645c067729312dac57b3e327fa60fd 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 808ee2bbb6e541b6bfbdd76f15db7b595eddf8be..50e9b091f7aac0ae637454caa004821e7f776531 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 0000000000000000000000000000000000000000..c9d72b6d4d16eb587e9cf6db715a96e2bce24aa0
--- /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 2492266db439f12a959b27d0051471f0b78d4905..4e05d7799646b1e3e772a9f413a3568cd74df867 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 0e8ca9ae32f1ffc485a9e7819e4fe0d366531a5b..ed60db4fb6f5e0272a8c887652d8f67c351a66e9 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 a01cd249369e88b68b1c86279419502b36e8e02d..570ed1de0e7a7f6ae5d287d966c466ba69d02876 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_ */
 
 //______________________________________________________________________________