// @(#)root/star:$Name:  $:$Id: TPolyLineShape.cxx,v 1.2 2003/01/27 20:41:36 brun Exp $
// Author: 
// $Id: TPolyLineShape.cxx,v 1.2 2003/01/27 20:41:36 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                //
//       |        ^                                                                 //
//       |        |       begin_html <a href="http://root.cern.ch/root/html/TShape.html#TShape:description">R  O  O  T        S  H  A  P  E  S</a>end_html                          //
//       V        |       (see begin_html <a href="http://wwwinfo.cern.ch/asdoc/geant_html3/node109.html#SECTION041000000000000000000000">GEANT 3.21 shapes</a>end_html 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)
{
 if (fPoints) fPoints->ExecuteEvent(event,px, py);
}

//______________________________________________________________________________
Color_t TPolyLineShape::GetColorAttribute() const
{
  return ((TPolyLineShape *)this)->GetLineColor();
}

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

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

//______________________________________________________________________________
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");
}
