    // @(#)root/star:$Name:  $:$Id: TPolyLineShape.cxx,v 1.3 2004/11/18 18:08:48 brun Exp $
    // Author:
    // $Id: TPolyLineShape.cxx,v 1.3 2004/11/18 18:08:48 brun Exp $
    // ***********************************************************************
    // *  C++ class library to define an abstract 3D shape os STAR "event" geometry
    // * Copyright(c) 1997~1999  [BNL] Brookhaven National Laboratory, STAR, All rights reserved
    // * Author                  Valeri Fine  (fine@bnl.gov)
    // * Copyright(c) 1997~1999  Valeri Fine  (fine@bnl.gov)
    // *
    // * This program is distributed in the hope that it will be useful,
    // * but WITHOUT ANY WARRANTY; without even the implied warranty of
    // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    // *
    // * Permission to use, copy, modify and distribute this software and its
    // * documentation for any purpose is hereby granted without fee,
    // * provided that the above copyright notice appear in all copies and
    // * that both that copyright notice and this permission notice appear
    // * in supporting documentation.  Brookhaven National Laboratory makes no
    // * representations about the suitability of this software for any
    // * purpose.  It is provided "as is" without express or implied warranty.
    // ************************************************************************

    #include "TPolyLineShape.h"

    #include "TPoints3D.h"
    #include "TVolume.h"
    #include "TVolumePosition.h"
    #include "TTUBE.h"
    #include "TBRIK.h"
    #include "TSPHE.h"
    #include "TView.h"
    #include "TVirtualPad.h"
    #include "TPadView3D.h"
    #include "TPoint.h"
    #include "TVirtualPS.h"

    //////////////////////////////////////////////////////////////////////////////////////
    //                                                                                  //
    //                           STAR 3D geometry Object Model                          //
    //                           =============================                          //
    //                                                                                  //
    //                           TDataSet            Legend:                            //
    //                              |                  "classA"                         //
    //                              |                     |     "classB" is derived from//
    //                              v                     v       the "classA"          //
    //                           TVolume               "classB"                         //
    //                              ^                                                   //
    //                              |                  "classQ"                         //
    //                              |                      ^     "classQ" has a pointer //
    //                            TShape                   |       to "classT"          //
    //                              |                   "classT"                        //
    //                              v                                                   //
    //           -----------------------------------------------------                  //
    //           |               |      |                     |      |                  //
    //           |               |      |     .    .    .     |      |                  //
    //           |               |      |                     |      |                  //
    //           V               v      v                     v      v                  //
    //      TPolyLineShape     TBRIK  TTUBE                 TPCON  TTRD1                //
    //       |        ^                                                                 //
    //       |        |

R O O T S H A P E S

                              //
    //       V        |       (see

GEANT 3.21 shapes

     as well)                           //
    // St_PolyLine3D  |                                                                 //
    //                |                                                                 //
    //           TPoints3DABC                                                           //
    //                |                                                                 //
    //                |                                                                 //
    //                v                                                                 //
    //      --------------------------------------------------------                    //
    //      |                 |                 |                  |                    //
    //      |                 |                 |                  |                    //
    //      |                 |                 |                  |                    //
    //      V                 v                 v                  v                    //
    //StHits3DPoints   StHelix3DPoints   TTable3Points          TPoints3D               //
    //      ^                 ^                 ^                  ^                    //
    //      |                 |                 |                  |                    //
    //      |                 |                 |                  |                    //
    //  StObjArray    StTrack / StHelixD  TTableSorter       flat floating              //
    //                                          ^              point array              //
    //                                          |        (see St_PolyLine3D as well)    //
    //                                          |                                       //
    //                                        TTable                                    //
    //                                                                                  //
    //                                                                                  //
    //                     S  T  A  R    S  H  A  P  E  S                               //
    //                     -------------------------------                              //
    //                                                                                  //
    //////////////////////////////////////////////////////////////////////////////////////

    ClassImp(TPolyLineShape)

    //______________________________________________________________________________
     TPolyLineShape::TPolyLineShape()
    {
       fShape = 0;
       fSmooth = kFALSE;
       fConnection= 0;
       fPoints=0;
       SetWidthFactor();
       fHasDrawn = kFALSE;
       fShapeType = kNULL;
       fSizeX3D   = 0;
       fPointFlag = kFALSE;
       fLineFlag  = kFALSE;
    }

    //______________________________________________________________________________
     TPolyLineShape::TPolyLineShape(TPoints3DABC  *points,Option_t* option)
    {
      //  fShape       = new TTUBE("tube","tube","void",0.5,0.5);
        fShape      = 0;
       fShapeType   = kNULL;
       fSmooth      = kFALSE;
       fConnection  = 0;
       fPoints      = points;
       fHasDrawn    = kFALSE;
       fSizeX3D     = 0;
       // Take in account the current node if any
       if (!fPoints) {
         Error("TPolyLineShape","No polyline is defined");
         return;
       }
       fPointFlag = strchr(option,'P')?kTRUE:kFALSE;
       fLineFlag  = strchr(option,'L')?kTRUE:kFALSE;

       SetWidthFactor();
       Create();
    }

    //______________________________________________________________________________
     TPolyLineShape::~TPolyLineShape()
    {
      SafeDelete(fShape);
      SafeDelete(fSizeX3D);
    }

    //______________________________________________________________________________
     void TPolyLineShape::Create()
    {
        if (!fConnection) SetConnection(kBrik);
    }

    //______________________________________________________________________________
     Size3D *TPolyLineShape::CreateX3DSize(Bool_t marker)
    {
      if (!fSizeX3D) fSizeX3D = new Size3D;
      fSizeX3D->numPoints = 0;
      fSizeX3D->numSegs   = 0;
      fSizeX3D->numPolys  = 0;         //NOTE: Because of different structure, our
      if (fPoints) {
        Int_t size = fPoints->Size();
        if (marker) {
          Int_t mode;

          if (size > 10000) mode = 1;         // One line marker    '-'
          else if (size > 3000) mode = 2;     // Two lines marker   '+'
          else mode = 3;                      // Three lines marker '*'

          fSizeX3D->numSegs   = size*mode;
          fSizeX3D->numPoints = size*mode*2;
          fSizeX3D->numPolys  = 0;
        }
        else {
          fSizeX3D->numSegs   = size-1;
          fSizeX3D->numPoints = size;
        }
        fSizeX3D->numPolys  = 0;         //NOTE: Because of different structure, our
      }
      return fSizeX3D;
    }

    //______________________________________________________________________________
     Int_t TPolyLineShape::SetConnection(EShapeTypes connection)
    {
     Float_t size = 0.5*GetWidthFactor()*GetLineWidth();

     if (fShapeType != connection) {
       SafeDelete(fConnection);
       fShapeType = connection;
       switch (fShapeType) {
         case  kSphere:
              SetConnection(new TSPHE("connection","sphere","void",0,size,0,90,0,360));
              break;
         default:
              SetConnection(new TBRIK("connection","brik","void",size,size,size));
              break;
         };
      }
      return 0;
    }

    //______________________________________________________________________________
     Int_t TPolyLineShape::DistancetoPrimitive(Int_t px, Int_t py)
    {
    //*-*-*-*-*-*-*-*Compute distance from point px,py to a 3-D polyline*-*-*-*-*-*-*
    //*-*            ===================================================
    //*-*
    //*-*  Compute the closest distance of approach from point px,py to each segment
    //*-*  of the polyline.
    //*-*  Returns when the distance found is below DistanceMaximum.
    //*-*  The distance is computed in pixels units.
    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

     if (fPoints) {
       Int_t ret = fPoints->DistancetoPrimitive( px, py);
       if (ret == -1) ret = PointDistancetoPrimitive(px, py);
       return ret;
     }
     return 999999;
    }

    //______________________________________________________________________________
     Int_t TPolyLineShape::PointDistancetoPrimitive(Int_t px, Int_t py)
    {
    //*-*-*-*-*-*-*Compute distance from point px,py to a 3-D points *-*-*-*-*-*-*
    //*-*          =====================================================
    //*-*
    //*-*  Compute the closest distance of approach from point px,py to each segment
    //*-*  of the polyline.
    //*-*  Returns when the distance found is below DistanceMaximum.
    //*-*  The distance is computed in pixels units.
    //*-*
    //*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

       const Int_t inaxis = 7;
       Float_t dist = 999999;

       Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
       Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
       Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
       Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());

       TView *view = 0;
    //*-*- return if point is not in the user area
       if (px < puxmin - inaxis) goto END;
       if (py > puymin + inaxis) goto END;
       if (px > puxmax + inaxis) goto END;
       if (py < puymax - inaxis) goto END;

       view = gPad->GetView();
       if (view) {
         Int_t i;
         Float_t dpoint;
         Float_t xndc[3];
         Int_t x1,y1;
         Int_t pointSize = fPoints->Size();
         for (i=0;i<pointSize;i++) {
            Float_t thisPoints[3];
            view->WCtoNDC(fPoints->GetXYZ(thisPoints,i), xndc);
            x1     = gPad->XtoAbsPixel(xndc[0]);
            y1     = gPad->YtoAbsPixel(xndc[1]);
            dpoint = (px-x1)*(px-x1) + (py-y1)*(py-y1);
            if (dpoint < dist) dist = dpoint;
         }
         dist = (TMath::Sqrt(dist));
       }
    END:
       return Int_t(dist);
    }

    //______________________________________________________________________________
     void TPolyLineShape::Draw(Option_t *)
    {
      Create();
      AppendPad();
    }

    //______________________________________________________________________________
     void TPolyLineShape::ExecuteEvent(Int_t event, Int_t px, Int_t py)
    {
       // forward the ExecuteEvent call to the decorated object
       if (fPoints) fPoints->ExecuteEvent(event,px, py);
    }

    //______________________________________________________________________________
     Color_t TPolyLineShape::GetColorAttribute() const
    {
      return ((TPolyLineShape *)this)->GetLineColor();
    }
    //______________________________________________________________________________
     const char  *TPolyLineShape::GetName()  const
    {
       // forward the GetName call to the decorated object
       return fPoints ? fPoints->GetName() : TShape::GetName();
    }
    //______________________________________________________________________________
     char  *TPolyLineShape::GetObjectInfo(Int_t px, Int_t py) const
    {
       // forward the GetObjectInfo call to the decorated object
       return fPoints ? fPoints->GetObjectInfo(px, py) : TShape::GetObjectInfo(px,py);
    }

    //______________________________________________________________________________
     Size_t TPolyLineShape::GetSizeAttribute() const
    {
       return ((TPolyLineShape *)this)->GetMarkerSize();
    }

    //______________________________________________________________________________
     Style_t TPolyLineShape::GetStyleAttribute() const
    {
       return ((TPolyLineShape *)this)->GetLineStyle();
    }

    //______________________________________________________________________________
     const char  *TPolyLineShape::GetTitle() const
    {
       // forward the GetObjectInfo call to the decorated object
       return fPoints ? fPoints->GetTitle() : TShape::GetTitle();
    }
    //______________________________________________________________________________
     void TPolyLineShape::PaintNode(Float_t *start,Float_t *end,Option_t *option)
    {
      // Double_t *start - coordinate of the start point of the current segment
      // Double_t *end   - coordinate of the end   point of the current segment

      // Calculate the vector
       const Int_t kDimension = 3;
       Double_t vector[kDimension];
       Double_t nodeposition[kDimension];
       Int_t i=0;
       for (i=0;i<kDimension;i++) {
          vector[i]=end[i]-start[i];
          nodeposition[i]=0.5*(start[i]+end[i]);
       }
       Double_t length = TMath::Normalize(vector);

      // Calculate the rotation axis for Axis Oz

        Double_t Oz[3]={0,0,1};
        Double_t rotate[3];

        Double_t sina = TMath::Normalize(TMath::Cross(vector,Oz,rotate));
        Double_t cosa = Product(vector,Oz);
        Double_t mrot[3][3];

        TShape *shape = fShape;
        if (!shape) shape = fConnection;

        Gyrot(rotate,cosa,sina,mrot);

        Float_t width = GetWidthFactor()*GetLineWidth();

        mrot[0][0] *= width;
        mrot[0][1] *= width;
        mrot[0][2] *= width;

        mrot[1][0] *= width;
        mrot[1][1] *= width;
        mrot[1][2] *= width;

        mrot[2][0] *= length;
        mrot[2][1] *= length;
        mrot[2][2] *= length;

        Color_t color = GetLineColor();

        TVolume node("SegmentNode","SegmentNode", shape);
        node.SetLineColor(color);
        if (!fShape) node.SetVisibility();
        node.SetLineColor(color);

        TRotMatrix matrix ("rotate","rotate",&mrot[0][0]);
        TVolumePosition position(&node,nodeposition[0],nodeposition[1]
                                      ,nodeposition[2],&matrix);

        if (!(fSmooth || fConnection))  {
             node.PaintNodePosition(option, &position);
             return;
        }

        // Add the connection

        memset(mrot,0,9*sizeof(Double_t));

        length = width/length;
        mrot[2][2] = length;
        mrot[0][0] = 1;
        mrot[1][1] = 1;

        TRotMatrix kneeMatrix("knee","knee",&mrot[0][0]);
        TVolume knee("ConnectionNode","ConnectionNode", fConnection);
        TVolumePosition kneePosition(&knee, 0, 0, 0.5, &kneeMatrix);
        knee.SetLineColor(color);
        node.Add(&knee,&kneePosition);

        node.PaintNodePosition(option, &position);
    }

    //______________________________________________________________________________
     void TPolyLineShape::Paint(Option_t *opt)
    {
      if (!GetPoints()) return;

      Bool_t rangeView = opt && opt[0] && strcmp(opt,"range")==0 ? kTRUE : kFALSE;
      TPadView3D *view3D = 0;
      if (!rangeView  && (view3D = (TPadView3D*)gPad->GetView3D()) ) {
        TString mode;

        mode="";
        if (fLineFlag)  mode  = "L";
        if (fPointFlag) mode += "P";

        view3D->SetLineAttr(GetColorAttribute(), (Int_t)GetSizeAttribute());
        view3D->PaintPoints3D(GetPoints(), mode.Data());
      }
      if (!strstr(opt, "x3d")) {
        if (fPointFlag) {
             SetMarkerColor(GetColorAttribute());
             SetMarkerSize(GetSizeAttribute());
             PaintPolyMarker(fPoints->Size());
        }
        if (fLineFlag) {
             SetLineColor(GetColorAttribute());
             SetLineWidth((Width_t)GetSizeAttribute());
             PaintPoints(fPoints->Size());
        }

      }
      else {
        if (fLineFlag) {
           CreateX3DSize(kFALSE); PaintX3DLine(opt);
        } else {
           CreateX3DSize(kTRUE);  PaintX3DMarker(opt);
        }
    //     Paint3d(opt);
      }
    }

    //______________________________________________________________________________
     void  TPolyLineShape::PaintPoints(Int_t n, Float_t *, Option_t *)
    {
    //*-*-*-*-*-*-*-*-*Draw this 3-D polyline with new coordinates*-*-*-*-*-*-*-*-*-*
    //*-*              ===========================================
       if (n < 2) return;

       TAttLine::Modify();  //Change line attributes only if necessary

    //*-*- Loop on each individual line
       for (Int_t i=1;i<n;i++) {
          Float_t xyz[6];
          fPoints->GetXYZ(&xyz[0],i-1,2);
          gPad->PaintLine3D(xyz, &xyz[3]);
       }
    }

    //______________________________________________________________________________
     void TPolyLineShape::PaintPolyMarker(Int_t n, Float_t *, Marker_t, Option_t *)
    {
    //*-*-*-*-*-*-*-*-*Paint polymarker in CurrentPad World coordinates*-*-*-*-*-*-*-*
    //*-*              ================================================

       if (n <= 0) return;

       //Create temorary storage
       TPoint *pxy = new TPoint[n];
       Float_t *x  = new Float_t[n];
       Float_t *y  = new Float_t[n];
       Float_t xndc[3], ptr[3];

       TView *view = gPad->GetView();      //Get current 3-D view
       if(!view) return;                   //Check if `view` is valid

    //*-*- convert points from world to pixel coordinates
       Int_t nin = 0;
       for (Int_t i = 0; i < n; i++) {
          fPoints->GetXYZ(ptr,i);
          view->WCtoNDC(ptr, xndc);
          if (xndc[0] < gPad->GetX1() || xndc[0] > gPad->GetX2()) continue;
          if (xndc[1] < gPad->GetY1() || xndc[1] > gPad->GetY2()) continue;
          x[nin] = xndc[0];
          y[nin] = xndc[1];
          pxy[nin].fX = gPad->XtoPixel(x[nin]);
          pxy[nin].fY = gPad->YtoPixel(y[nin]);
          nin++;
       }

       TAttMarker::Modify();  //Change marker attributes only if necessary

    //*-*- invoke the graphics subsystem
       if (!gPad->IsBatch()) gVirtualX->DrawPolyMarker(nin, pxy);

       if (gVirtualPS) {
          gVirtualPS->DrawPolyMarker(nin, x, y);
       }
       delete [] x;
       delete [] y;

       delete [] pxy;
    }

    //______________________________________________________________________________
     void TPolyLineShape::Paint3d(Option_t *opt)
    {
     if (!fPoints) return;

     Create();

     struct XYZ { Float_t xyz[3]; } *points;
     points  = (XYZ *)(fPoints->GetP());
     Int_t size      = fPoints->GetN()-1;

     for (Int_t i=0;i<size;i++)
          PaintNode((Float_t *)(points+i+1),(Float_t *)(points+i),opt);
     fHasDrawn = kTRUE;
    }

    //______________________________________________________________________________
     void TPolyLineShape::PaintX3DLine(Option_t *)
    {
    #ifndef WIN32
       X3DBuffer *buff = new X3DBuffer;
       if (!buff) return;

       Int_t size = 0;
       if (fPoints) size = fPoints->Size();
       if (!size) return;

       fSizeX3D->numPoints = buff->numPoints = size;
       fSizeX3D->numSegs   = buff->numSegs   = size-1;
       fSizeX3D->numPolys  = buff->numPolys  = 0;        //NOTE: Because of different structure, our

       buff->polys     = NULL;     //      TPolyLine3D can't use polygons
       TPoints3D x3dPoints(size);
       buff->points    = fPoints->GetXYZ(x3dPoints.GetP(),0,size);

    //        Int_t c = (((fAttributes?fAttributes->GetColorAttribute():0) % 8) - 1) * 4;     // Basic colors: 0, 1, ... 8
       Int_t c = ((GetColorAttribute() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 8
       if (c < 0) c = 0;

        //*-* Allocate memory for segments *-*
        buff->segs = new Int_t[buff->numSegs*3];
        if (buff->segs) {
             for (Int_t i = 0; i < buff->numSegs; i++) {
                 buff->segs[3*i  ] = c;
                 buff->segs[3*i+1] = i;
                 buff->segs[3*i+2] = i+1;
             }
         }

         if (buff && buff->points && buff->segs) //If everything seems to be OK ...
             FillX3DBuffer(buff);
         else {                            // ... something very bad was happened
             gSize3D.numPoints -= buff->numPoints;
             gSize3D.numSegs   -= buff->numSegs;
             gSize3D.numPolys  -= buff->numPolys;
         }

         if (buff->segs)     delete [] buff->segs;
         if (buff->polys)    delete [] buff->polys;
         if (buff)           delete    buff;
    #endif
    }

    //______________________________________________________________________________
     void TPolyLineShape::PaintX3DMarker(Option_t *)
    {
    #ifndef WIN32
       Int_t size = 0;
       if (fPoints) size = fPoints->Size();
       if (!size) return;
       Int_t mode;
       Int_t i, j, k, n;

       X3DBuffer *buff = new X3DBuffer;
       if(!buff) return;

       if (size > 10000) mode = 1;         // One line marker    '-'
       else if (size > 3000) mode = 2;     // Two lines marker   '+'
       else mode = 3;                      // Three lines marker '*'

       fSizeX3D->numSegs   = buff->numSegs   = size*mode;
       fSizeX3D->numPoints = buff->numPoints = buff->numSegs*2;
       fSizeX3D->numPolys  = buff->numPolys  = 0;         //NOTE: Because of different structure, our

       buff->polys     = NULL;      //      TPolyMarker3D can't use polygons

        //*-* Allocate memory for points *-*
       Float_t delta = 0.002;

       buff->points = new Float_t[buff->numPoints*3];
       if (buff->points) {
           for (i = 0; i < size; i++) {
               for (j = 0; j < mode; j++) {
                   for (k = 0; k < 2; k++) {
                       delta *= -1;
                       for (n = 0; n < 3; n++) {
                           Float_t xyz[3];
                           fPoints->GetXYZ(xyz,i);
                           buff->points[mode*6*i+6*j+3*k+n] =
                               xyz[n] * (1 + (j == n ? delta : 0));
                       }
                   }
               }
           }
       }

       Int_t c = ((GetColorAttribute() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 8
       if (c < 0) c = 0;

        //*-* Allocate memory for segments *-*
       buff->segs = new Int_t[buff->numSegs*3];
       if (buff->segs) {
           for (i = 0; i < buff->numSegs; i++) {
               buff->segs[3*i  ] = c;
               buff->segs[3*i+1] = 2*i;
               buff->segs[3*i+2] = 2*i+1;
           }
       }

       if (buff->points && buff->segs)    //If everything seems to be OK ...
           FillX3DBuffer(buff);
       else {                            // ... something very bad was happened
           gSize3D.numPoints -= buff->numPoints;
           gSize3D.numSegs   -= buff->numSegs;
           gSize3D.numPolys  -= buff->numPolys;
       }

       if (buff->points)   delete [] buff->points;
       if (buff->segs)     delete [] buff->segs;
       if (buff->polys)    delete [] buff->polys;
       if (buff)           delete    buff;
    #endif
    }

    //______________________________________________________________________________
     Float_t TPolyLineShape::Product(Float_t *v1, Float_t *v2,Int_t ndim)
    {
      Float_t p = 0;
      if (v1 && v2 && ndim > 0)
        for (Int_t i=0; i<ndim; i++) p+= v1[i]*v2[i];
      return p;
    }

    //______________________________________________________________________________
     Double_t TPolyLineShape::Product(Double_t *v1, Double_t *v2,Int_t ndim)
    {
      Double_t p = 0;
      if (v1 && v2 && ndim > 0)
        for (Int_t i=0;i<ndim;i++) p+= v1[i]*v2[i];
      return p;
    }

    //______________________________________________________________________________
     Double_t *TPolyLineShape::Gyrot(Double_t *dirc, Double_t cosang, Double_t sinang, Double_t trans[3][3])
    {
    //************************************************************************
    //*                                                                      *
    //*   call gyrot(dirc,angp,trans,ntrans)                       vp 880722 *
    //*                                       revised              vp 921009 *
    //*                                       revised (f->c++)     vf 981006 *
    //*       routine for filling rotation transformation matrix             *
    //*       from axis and rotation angle around                            *
    //*                                                                      *
    //*   arguments:                                                         *
    //*       dirc    direct cosinuses (may be not normalised)               *
    //*       cosang, sinang - cos and sin of the rotation angle             *
    //*       tranz   rotation & shift matrix 3*3  (input/output)            *
    //*    ---------------------------------------------------------------   *
    //*  This code is provided by Victor Perevoztchikov                      *
    //************************************************************************

          Double_t ax[3];

          memcpy(ax,dirc,3*sizeof(Double_t));
          TMath::Normalize(ax);

          Double_t ca  = cosang;
          Double_t sa  = sinang;
          Double_t ca1;

          if (ca < 0.5)
            ca1 = 1. - ca ;
          else
            ca1 = (sa*sa)/(1.+ca) ;

          Int_t j1 = 0;
          Int_t j2 = 0;
          for(j1 = 0; j1 < 3; j1++) {
            for(j2 = 0; j2 < 3; j2++)
                  trans[j1][j2] = ca1*ax[j1]*ax[j2];
            trans[j1][j1]   += ca;
          }

          trans[0][1] = trans[0][1] - sa*ax[2];
          trans[1][0] = trans[1][0] + sa*ax[2];
          trans[0][2] = trans[0][2] + sa*ax[1];
          trans[2][0] = trans[2][0] - sa*ax[1];
          trans[1][2] = trans[1][2] - sa*ax[0];
          trans[2][1] = trans[2][1] + sa*ax[0];

          return (Double_t *)trans;

    }

    //______________________________________________________________________________
     Color_t TPolyLineShape::SetColorAttribute(Color_t color)
    {
      Color_t currentColor = GetColorAttribute();
      if (color != currentColor)
      {
        SetLineColor(color);
        SetMarkerColor(color);
      }
      return currentColor;
    }

    //______________________________________________________________________________
     Size_t TPolyLineShape::SetSizeAttribute(Size_t size)
    {
      Size_t currentSize = GetSizeAttribute();
      if (size != currentSize)
      {
        SetLineWidth(Width_t(size));
        SetMarkerSize(size);
      }
      return currentSize;
    }

    //______________________________________________________________________________
     Style_t TPolyLineShape::SetStyleAttribute(Style_t style)
    {
      // SetStyleAttribute(Style_t style) - set new style for this line
      // Returns:
      //          previous value of the line style
      //
       Style_t s = 0;
       s = GetStyleAttribute();
       SetLineStyle(style);
       SetMarkerStyle(style);
       return s;
    }

    //______________________________________________________________________________
     void TPolyLineShape::SetShape(TShape *shape)
    {
       SafeDelete(fShape)
       fShape = shape;
    }

    //_______________________________________________________________________
     Int_t TPolyLineShape::Size() const
    {
       return fPoints ? fPoints->Size():0;
    }

    //______________________________________________________________________________
     void TPolyLineShape::Sizeof3D() const
    {
    //*-*-*-*-*-*-*Return total X3D size of this shape with its attributes*-*-*-*-*-*
    //*-*          =======================================================
      TPolyLineShape *line = (TPolyLineShape *)this;
      if (fLineFlag )
        line->CreateX3DSize(kFALSE);
      else
        line->CreateX3DSize(kTRUE);
      if (fSizeX3D) {
         gSize3D.numPoints += fSizeX3D->numPoints;
         gSize3D.numSegs   += fSizeX3D->numSegs;
         gSize3D.numPolys  += fSizeX3D->numPolys;
      }
      else Error("Sizeof3D()","buffer size has not been defined yet");
    }