#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 "TTablePadView3D.h"
#include "TPoint.h"
#include "TVirtualPS.h"
#include "TMath.h"
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      = 0;
   fShapeType   = kNULL;
   fSmooth      = kFALSE;
   fConnection  = 0;
   fPoints      = points;
   fHasDrawn    = kFALSE;
   fSizeX3D     = 0;
   
   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;         
   if (fPoints) {
      Int_t size = fPoints->Size();
      if (marker) {
         Int_t mode;
         if (size > 10000) mode = 1;         
         else if (size > 3000) mode = 2;     
         else mode = 3;                      
         fSizeX3D->numSegs   = size*mode;
         fSizeX3D->numPoints = size*mode*2;
         fSizeX3D->numPolys  = 0;
      } else {
         fSizeX3D->numSegs   = size-1;
         fSizeX3D->numPoints = size;
      }
      fSizeX3D->numPolys  = 0;         
   }
   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)
{
   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)
{
   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;
   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();
}
const char  *TPolyLineShape::GetName()  const
{
   
   return fPoints ? fPoints->GetName() : TShape::GetName();
}
char  *TPolyLineShape::GetObjectInfo(Int_t px, Int_t py) const
{
   
   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
{
   
   return fPoints ? fPoints->GetTitle() : TShape::GetTitle();
}
void TPolyLineShape::PaintNode(Float_t *start,Float_t *end,Option_t *option)
{
  
  
  
   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);
  
   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;
   }
   
   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;
   TTablePadView3D *view3D = 0;
   if (!rangeView  && (view3D = (TTablePadView3D*)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);
      }
   }
}
void  TPolyLineShape::PaintPoints(Int_t n, Float_t *, Option_t *)
{
   if (n < 2) return;
   TAttLine::Modify();  
   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 *)
{
   if (n <= 0) return;
   
   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();      
   if(!view) return;                   
   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();  
   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;        
   buff->polys     = 0;     
   TPoints3D x3dPoints(size);
   buff->points    = fPoints->GetXYZ(x3dPoints.GetP(),0,size);
   Int_t c = ((GetColorAttribute() % 8) - 1) * 4;     
   if (c < 0) c = 0;
   
   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) 
      FillX3DBuffer(buff);
   else {                            
      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;         
   else if (size > 3000) mode = 2;     
   else mode = 3;                      
   fSizeX3D->numSegs   = buff->numSegs   = size*mode;
   fSizeX3D->numPoints = buff->numPoints = buff->numSegs*2;
   fSizeX3D->numPolys  = buff->numPolys  = 0;         
   buff->polys     = 0;      
    
   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;     
   if (c < 0) c = 0;
    
   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)    
      FillX3DBuffer(buff);
   else {                            
      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])
{
   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)
{
  
  
  
  
   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
{
   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");
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.