// @(#)root/graf:$Name: $:$Id: TCurlyLine.cxx,v 1.4 2002/01/24 11:39:28 rdm Exp $
// Author: Otto Schaile 20/11/99
/*************************************************************************
* 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. *
*************************************************************************/
//________________________________________________________________________
//
// This class implements curly or wavy polylines typically used to draw Feynman diagrams.
// Amplitudes and wavelengths may be specified in the constructors,
// via commands or interactively from popup menus.
// The class make use of TPolyLine by inheritance, ExecuteEvent methods
// are highly inspired from the methods used in TPolyLine and TArc.
// The picture below has been generated by the tutorial feynman.
//
/*
*/
//
//________________________________________________________________________
#include "Riostream.h"
#include "TCurlyLine.h"
#include "TROOT.h"
#include "TVirtualPad.h"
#include "TVirtualX.h"
#include "TMath.h"
ClassImp(TCurlyLine)
//______________________________________________________________________________
TCurlyLine::TCurlyLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Double_t tl, Double_t rad)
{
// create a new TCurlyLine with starting point (x1, y1), end point (x2,y2)
// The wavelength and amplitude are given in percent of the pad height
fX1 = x1;
fY1 = y1;
fX2 = x2;
fY2 = y2;
fWaveLength = tl;
fAmplitude = rad;
fIsCurly = kTRUE;
Build();
}
//______________________________________________________________________________
void TCurlyLine::Build()
{
//*-*-*-*-*-*-*-*-*-*-*Create a curly (Gluon) or wavy (Gamma) line*-*-*-*-*-*
//*-* ===========================================
Double_t pixwave,pixampl;
if (gPad) {
Double_t hpixels = gPad->GetAbsHNDC()*gPad->GetWh();
Int_t px1 = gPad->XtoAbsPixel(fX1);
Int_t py1 = gPad->YtoAbsPixel(fY1);
Int_t px2 = gPad->XtoAbsPixel(fX2);
Int_t py2 = gPad->YtoAbsPixel(fY2);
Double_t pl2 = Double_t((px2-px1)*(px2-px1) + (py1-py2)*(py1-py2));
Double_t pixlength = TMath::Sqrt(pl2);
pixwave = hpixels*fWaveLength/pixlength;
pixampl = hpixels*fAmplitude/pixlength;
} else {
pixwave = fWaveLength;
pixampl = fAmplitude;
}
Double_t anglestep = 20;
Double_t phimaxle = TMath::Pi() * 2. / anglestep ;
Double_t length = TMath::Sqrt((fX2-fX1)*(fX2-fX1) + (fY2-fY1)*(fY2-fY1));
Double_t ampl = length*pixampl;
Double_t wave = length*pixwave;
Double_t dx = wave/25;
Double_t len2pi = dx * anglestep;
if(length <= 4 * ampl){
cout << "CurlyLine:: too short " << length << endl;
SetBit(kTooShort);
return;
}
Double_t angle = TMath::ATan2(fY2-fY1, fX2-fX1);
if(angle < 0) angle += 2*TMath::Pi();
Double_t lengthcycle = 0.5*len2pi + 2*ampl;
Int_t nperiods = (Int_t)((length - lengthcycle) / len2pi);
Double_t restlenght = 0.5 * (length - nperiods * len2pi - lengthcycle);
fNsteps = (Int_t)(anglestep * nperiods + anglestep / 2 +4);
SetPolyLine(fNsteps);
Double_t *xv = GetX();
Double_t *yv = GetY();
xv[0] = 0; yv[0] = 0;
xv[1] = restlenght; yv[1] = 0;
Double_t phase = 1.5 * TMath::Pi();
Double_t x0 = ampl + restlenght;
Int_t i;
for(i = 2; i < fNsteps-1; i++){
// distinguish between curly and wavy
if(fIsCurly) xv[i] = x0 + ampl*TMath::Sin(phase);
else xv[i] = x0;
yv[i] = ampl*TMath::Cos(phase);
phase += phimaxle;
x0 += dx;
}
xv[fNsteps-1] = length; yv[fNsteps-1] = 0;
Double_t cosang = TMath::Cos(angle);
Double_t sinang = TMath::Sin(angle);
Double_t xx, yy;
for(i = 0; i < fNsteps; i++){
xx = xv[i] * cosang - yv[i] * sinang;
yy = xv[i] * sinang + yv[i] * cosang;
xv[i] = xx + fX1;
yv[i] = yy + fY1;
}
if (gPad) gPad->Modified();
}
//______________________________________________________________________________
Int_t TCurlyLine::DistancetoPrimitive(Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to a line*-*-*-*-*-*
//*-* ===========================================
return DistancetoLine(px,py,fX1,fY1,fX2,fY2);
}
//______________________________________________________________________________
void TCurlyLine::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-* =========================================
// This member function is called when a TCurlyLine is clicked with the locator
//
// If Left button clicked on one of the line end points, this point
// follows the cursor until button is released.
//
// if Middle button clicked, the line is moved parallel to itself
// until the button is released.
//
Int_t kMaxDiff = 20;
static Int_t d1,d2,px1,px2,py1,py2;
static Int_t pxold, pyold, px1old, py1old, px2old, py2old;
static Bool_t P1, P2, L;
Int_t dx, dy;
switch (event) {
case kButton1Down:
gVirtualX->SetLineColor(-1);
TAttLine::Modify(); //Change line attributes only if necessary
// No break !!!
case kMouseMotion:
px1 = gPad->XtoAbsPixel(fX1);
py1 = gPad->YtoAbsPixel(fY1);
px2 = gPad->XtoAbsPixel(fX2);
py2 = gPad->YtoAbsPixel(fY2);
P1 = P2 = L = kFALSE;
d1 = TMath::Abs(px1 - px) + TMath::Abs(py1-py); //simply take sum of pixels differences
if (d1 < kMaxDiff) { //*-*================>OK take point number 1
px1old = px1; py1old = py1;
P1 = kTRUE;
gPad->SetCursor(kPointer);
return;
}
d2 = TMath::Abs(px2 - px) + TMath::Abs(py2-py); //simply take sum of pixels differences
if (d2 < kMaxDiff) { //*-*================>OK take point number 2
px2old = px2; py2old = py2;
P2 = kTRUE;
gPad->SetCursor(kPointer);
return;
}
L = kTRUE;
pxold = px; pyold = py;
gPad->SetCursor(kMove);
break;
case kButton1Motion:
if (P1) {
gVirtualX->DrawLine(px1old, py1old, px2, py2);
gVirtualX->DrawLine(px, py, px2, py2);
px1old = px;
py1old = py;
}
if (P2) {
gVirtualX->DrawLine(px1, py1, px2old, py2old);
gVirtualX->DrawLine(px1, py1, px, py);
px2old = px;
py2old = py;
}
if (L) {
gVirtualX->DrawLine(px1, py1, px2, py2);
dx = px-pxold; dy = py-pyold;
px1 += dx; py1 += dy; px2 += dx; py2 += dy;
gVirtualX->DrawLine(px1, py1, px2, py2);
pxold = px;
pyold = py;
}
break;
case kButton1Up:
if (P1) {
fX1 = gPad->AbsPixeltoX(px);
fY1 = gPad->AbsPixeltoY(py);
}
if (P2) {
fX2 = gPad->AbsPixeltoX(px);
fY2 = gPad->AbsPixeltoY(py);
}
if (L) {
fX1 = gPad->AbsPixeltoX(px1);
fY1 = gPad->AbsPixeltoY(py1);
fX2 = gPad->AbsPixeltoX(px2);
fY2 = gPad->AbsPixeltoY(py2);
}
Build();
gPad->Modified();
gVirtualX->SetLineColor(-1);
}
}
//_____________________________________________________________________________________
void TCurlyLine::SavePrimitive(ofstream &out, Option_t *){
// Save primitive as a C++ statement(s) on output stream out
if (gROOT->ClassSaved(TCurlyLine::Class())) {
out<<" ";
} else {
out<<" TCurlyLine *";
}
out<<"curlyline = new TCurlyLine("
<<fX1<<","<<fY1<<","<<fX2<<","<<fY2<<","
<<fWaveLength<<","<<fAmplitude<<");"<<endl;
if (!fIsCurly) {
out<<" curlyline->SetWavy();"<<endl;
}
SaveLineAttributes(out,"curlyline",1,1,1);
out<<" curlyline->Draw();"<<endl;
}
//_____________________________________________________________________________________
void TCurlyLine::SetCurly()
{
fIsCurly = kTRUE;
Build();
}
void TCurlyLine::SetWavy()
{
fIsCurly = kFALSE;
Build();
}
void TCurlyLine::SetWaveLength(Double_t x)
{
fWaveLength = x;
Build();
}
void TCurlyLine::SetAmplitude(Double_t x)
{
fAmplitude = x;
Build();
}
void TCurlyLine::SetStartPoint(Double_t x, Double_t y)
{
fX1 = x;
fY1 = y;
Build();
}
void TCurlyLine::SetEndPoint(Double_t x, Double_t y)
{
fX2 = x;
fY2 = y;
Build();
}
ROOT page - Class index - Top of the page
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.