#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 (opt && !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;
TView *view = gPad->GetView();
if(!view) 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];
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 fValues[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
Int_t size = 0;
if (fPoints) size = fPoints->Size();
if (!size) return;
X3DBuffer *buff = new X3DBuffer;
if (!buff) 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");
}