diff --git a/graf/src/TCurlyArc.cxx b/graf/src/TCurlyArc.cxx index 65cf05882ff7831bd9bcea68450f7b3576e002f3..cbb1b10b191ceb02d6868be841c507700b469138 100644 --- a/graf/src/TCurlyArc.cxx +++ b/graf/src/TCurlyArc.cxx @@ -1,407 +1,407 @@ -// @(#)root/graf:$Name: $:$Id: TCurlyArc.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 arcs 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 TCurlyLine 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. -//Begin_Html -/* -<img src="gif/feynman.gif"> -*/ -//End_Html -//________________________________________________________________________ - -#include "Riostream.h" -#include "TCurlyArc.h" -#include "TROOT.h" -#include "TVirtualPad.h" -#include "TVirtualX.h" -#include "TMath.h" - -ClassImp(TCurlyArc) - -//_____________________________________________________________________________________ -TCurlyArc::TCurlyArc(Double_t x1, Double_t y1, - Double_t rad, Double_t phimin, Double_t phimax, - Double_t tl, Double_t trad) - : fR1(rad), fPhimin(phimin),fPhimax(phimax) -{ - // create a new TCurlyarc with center (x1, y1) and radius rad. - // The wavelength and amplitude are given in percent of the line length - // phimin and phimax are given in degrees. - - fX1 = x1; - fY1 = y1; - fIsCurly = kTRUE; - fAmplitude = trad; - fWaveLength = tl; - fTheta = 0; - Build(); -} - -//_____________________________________________________________________________________ -void TCurlyArc::Build() -{ -//*-*-*-*-*-*-*-*-*-*-*Create a curly (Gluon) or wavy (Gamma) arc*-*-*-*-*-* -//*-* =========================================== - Double_t PixeltoX = 1; - Double_t PixeltoY = 1; - Double_t rPix = fR1; - if (gPad) { - Double_t ww = (Double_t)gPad->GetWw(); - Double_t wh = (Double_t)gPad->GetWh(); - Double_t pxrange = gPad->GetAbsWNDC()*ww; - Double_t pyrange = - gPad->GetAbsHNDC()*wh; - Double_t xrange = gPad->GetX2() - gPad->GetX1(); - Double_t yrange = gPad->GetY2() - gPad->GetY1(); -// PixeltoX = gPad->GetPixeltoX(); -// PixeltoY = gPad->GetPixeltoY(); - PixeltoX = xrange / pxrange; - PixeltoY = yrange/pyrange; - rPix = fR1 / PixeltoX; - } - Double_t dang = fPhimax - fPhimin; - if(dang < 0) dang += 360; - Double_t length = TMath::Pi() * fR1 * dang/180; - Double_t x1sav = fX1; - Double_t y1sav = fY1; - fX1 = fY1 = 0; - fX2 = length; - fY2 = 0; - TCurlyLine::Build(); -// TCurlyLine::Build(kTRUE); - fX1 = x1sav; - fY1 = y1sav; - Double_t *xv= GetX(); - Double_t *yv= GetY(); - Double_t xx, yy, angle; - for(Int_t i = 0; i < fNsteps; i++){ - angle = xv[i] / rPix + fPhimin * TMath::Pi()/180; - xx = (yv[i] + rPix) * cos(angle); - yy = (yv[i] + rPix) * sin(angle); - xx *= PixeltoX; - yy *= TMath::Abs(PixeltoY); - xv[i] = xx + fX1; - yv[i] = yy + fY1; - } - if (gPad) gPad->Modified(); -} - -//______________________________________________________________________________ -Int_t TCurlyArc::DistancetoPrimitive(Int_t px, Int_t py) -{ -//*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to an arc*-*-*-* -//*-* =========================================== -// Compute the closest distance of approach from point px,py to this arc. -// The distance is computed in pixels units. -// -// static Int_t ncalls = 0; -//*-*- Compute distance of point to center of arc - Int_t pxc = gPad->XtoAbsPixel(fX1); - Int_t pyc = gPad->YtoAbsPixel(fY1); - Double_t dist = TMath::Sqrt(Double_t((pxc-px)*(pxc-px)+(pyc-py)*(pyc-py))); - Double_t cosa = (px - pxc)/dist; - Double_t sina = (pyc - py)/dist; - Double_t phi = TMath::ATan2(sina,cosa); - if(phi < 0) phi += 2 * TMath::Pi(); - phi = phi * 180 / TMath::Pi(); - if(fPhimax > fPhimin){ - if(phi < fPhimin || phi > fPhimax) return 9999; - } else { - if(phi > fPhimin && phi < fPhimax) return 9999; - } - Int_t pxr = gPad->XtoPixel(fR1)- gPad->XtoPixel(0); - Double_t distr = TMath::Abs(dist-pxr); - return Int_t(distr); -} - -//______________________________________________________________________________ -void TCurlyArc::ExecuteEvent(Int_t event, Int_t px, Int_t py) -{ -//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-* -//*-* ========================================= -// This member function is called when a TCurlyArc 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 = 10; - const Int_t np = 10; - const Double_t PI = 3.141592; - static Int_t x[np+3], y[np+3]; - static Int_t px1,py1,npe,R1; - static Int_t pxold, pyold; - Int_t i, dpx, dpy; - Double_t angle,dx,dy,dphi,rTy,rBy,rLx,rRx; - Double_t phi0; - static Bool_t T, L, R, B, INSIDE; - static Int_t Tx,Ty,Lx,Ly,Rx,Ry,Bx,By; - - switch (event) { - - case kButton1Down: - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); - dphi = (fPhimax-fPhimin) * PI / 180; - if(dphi<0) dphi += 2 * PI; - dphi /= np; - phi0 = fPhimin * PI / 180; - for (i=0;i<=np;i++) { - angle = Double_t(i)*dphi + phi0; - dx = fR1*TMath::Cos(angle); - dy = fR1*TMath::Sin(angle); - Int_t RpixY = gPad->XtoAbsPixel(dy) - gPad->XtoAbsPixel(0); - x[i] = gPad->XtoAbsPixel(fX1 + dx); - y[i] = gPad->YtoAbsPixel(fY1) + RpixY; - } - if (fPhimax-fPhimin >= 360 ) { - x[np+1] = x[0]; - y[np+1] = y[0]; - npe = np; - } else { - x[np+1] = gPad->XtoAbsPixel(fX1); - y[np+1] = gPad->YtoAbsPixel(fY1); - x[np+2] = x[0]; - y[np+2] = y[0]; - npe = np + 2; - } - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - Tx = Bx = px1; - Ly = Ry = py1; - Lx = gPad->XtoAbsPixel(-fR1+fX1); - Rx = gPad->XtoAbsPixel( fR1+fX1); - R1 = TMath::Abs(Lx-Rx)/2; -// a circle in pixels, radius measured along X - Ty = gPad->YtoAbsPixel(fY1) + R1; - By = gPad->YtoAbsPixel(fY1) - R1; - - gVirtualX->DrawLine(Rx+4, py1+4, Rx-4, py1+4); - gVirtualX->DrawLine(Rx-4, py1+4, Rx-4, py1-4); - gVirtualX->DrawLine(Rx-4, py1-4, Rx+4, py1-4); - gVirtualX->DrawLine(Rx+4, py1-4, Rx+4, py1+4); - gVirtualX->DrawLine(Lx+4, py1+4, Lx-4, py1+4); - gVirtualX->DrawLine(Lx-4, py1+4, Lx-4, py1-4); - gVirtualX->DrawLine(Lx-4, py1-4, Lx+4, py1-4); - gVirtualX->DrawLine(Lx+4, py1-4, Lx+4, py1+4); - gVirtualX->DrawLine(px1+4, By+4, px1-4, By+4); - gVirtualX->DrawLine(px1-4, By+4, px1-4, By-4); - gVirtualX->DrawLine(px1-4, By-4, px1+4, By-4); - gVirtualX->DrawLine(px1+4, By-4, px1+4, By+4); - gVirtualX->DrawLine(px1+4, Ty+4, px1-4, Ty+4); - gVirtualX->DrawLine(px1-4, Ty+4, px1-4, Ty-4); - gVirtualX->DrawLine(px1-4, Ty-4, px1+4, Ty-4); - gVirtualX->DrawLine(px1+4, Ty-4, px1+4, Ty+4); - // No break !!! - - case kMouseMotion: - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - Tx = Bx = px1; - Ly = Ry = py1; - Lx = gPad->XtoAbsPixel(-fR1+fX1); - Rx = gPad->XtoAbsPixel( fR1+fX1); - - Ty = gPad->YtoAbsPixel(fY1) + TMath::Abs(Lx-Rx)/2; - By = gPad->YtoAbsPixel(fY1) - TMath::Abs(Lx-Rx)/2; - - T = L = R = B = INSIDE = kFALSE; - if ((TMath::Abs(px - Tx) < kMaxDiff) && - (TMath::Abs(py - Ty) < kMaxDiff)) { // top edge - T = kTRUE; - gPad->SetCursor(kTopSide); - } - else - if ((TMath::Abs(px - Bx) < kMaxDiff) && - (TMath::Abs(py - By) < kMaxDiff)) { // bottom edge - B = kTRUE; - gPad->SetCursor(kBottomSide); - } - else - if ((TMath::Abs(py - Ly) < kMaxDiff) && - (TMath::Abs(px - Lx) < kMaxDiff)) { // left edge - L = kTRUE; - gPad->SetCursor(kLeftSide); - } - else - if ((TMath::Abs(py - Ry) < kMaxDiff) && - (TMath::Abs(px - Rx) < kMaxDiff)) { // right edge - R = kTRUE; - gPad->SetCursor(kRightSide); - } - else {INSIDE= kTRUE; gPad->SetCursor(kMove); } - pxold = px; pyold = py; - - break; - - case kButton1Motion: - gVirtualX->DrawLine(Rx+4, py1+4, Rx-4, py1+4); - gVirtualX->DrawLine(Rx-4, py1+4, Rx-4, py1-4); - gVirtualX->DrawLine(Rx-4, py1-4, Rx+4, py1-4); - gVirtualX->DrawLine(Rx+4, py1-4, Rx+4, py1+4); - gVirtualX->DrawLine(Lx+4, py1+4, Lx-4, py1+4); - gVirtualX->DrawLine(Lx-4, py1+4, Lx-4, py1-4); - gVirtualX->DrawLine(Lx-4, py1-4, Lx+4, py1-4); - gVirtualX->DrawLine(Lx+4, py1-4, Lx+4, py1+4); - gVirtualX->DrawLine(px1+4, By+4, px1-4, By+4); - gVirtualX->DrawLine(px1-4, By+4, px1-4, By-4); - gVirtualX->DrawLine(px1-4, By-4, px1+4, By-4); - gVirtualX->DrawLine(px1+4, By-4, px1+4, By+4); - gVirtualX->DrawLine(px1+4, Ty+4, px1-4, Ty+4); - gVirtualX->DrawLine(px1-4, Ty+4, px1-4, Ty-4); - gVirtualX->DrawLine(px1-4, Ty-4, px1+4, Ty-4); - gVirtualX->DrawLine(px1+4, Ty-4, px1+4, Ty+4); - for (i=0;i<npe;i++) gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]); - if (T) { - R1 -= (py - pyold); - } - if (B) { - R1 += (py - pyold); - } - if (L) { - R1 -= (px - pxold); - } - if (R) { - R1 += (px - pxold); - } - if (T || B || L || R) { - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); - dphi = (fPhimax-fPhimin) * PI / 180; - if(dphi<0) dphi += 2 * PI; - dphi /= np; - phi0 = fPhimin * PI / 180; -// Double_t uR1 = gPad->PixeltoX(R1) - gPad->GetUxmin(); - Double_t uR1 = R1; - Int_t pX1 = gPad->XtoAbsPixel(fX1); - Int_t pY1 = gPad->YtoAbsPixel(fY1); - for (i=0;i<=np;i++) { - angle = Double_t(i)*dphi + phi0; - dx = uR1 * TMath::Cos(angle); - dy = uR1 * TMath::Sin(angle); - x[i] = pX1 + (Int_t)dx; - y[i] = pY1 + (Int_t)dy; - -// x[i] = gPad->XtoAbsPixel(fX1 + dx); -// y[i] = gPad->YtoAbsPixel(fY1 + dy); - } - if (fPhimax-fPhimin >= 360 ) { - x[np+1] = x[0]; - y[np+1] = y[0]; - npe = np; - } else { - x[np+1] = pX1; - y[np+1] = pY1; - x[np+2] = x[0]; - y[np+2] = y[0]; - npe = np + 2; - } - for (i=0;i<npe;i++) { - gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]); - } - } - if (INSIDE) { - dpx = px-pxold; dpy = py-pyold; - px1 += dpx; py1 += dpy; - for (i=0;i<=npe;i++) { x[i] += dpx; y[i] += dpy;} - for (i=0;i<npe;i++) gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]); - } - Tx = Bx = px1; - Rx = px1+R1; - Lx = px1-R1; - Ry = Ly = py1; - Ty = py1-R1; - By = py1+R1; - gVirtualX->DrawLine(Rx+4, py1+4, Rx-4, py1+4); - gVirtualX->DrawLine(Rx-4, py1+4, Rx-4, py1-4); - gVirtualX->DrawLine(Rx-4, py1-4, Rx+4, py1-4); - gVirtualX->DrawLine(Rx+4, py1-4, Rx+4, py1+4); - gVirtualX->DrawLine(Lx+4, py1+4, Lx-4, py1+4); - gVirtualX->DrawLine(Lx-4, py1+4, Lx-4, py1-4); - gVirtualX->DrawLine(Lx-4, py1-4, Lx+4, py1-4); - gVirtualX->DrawLine(Lx+4, py1-4, Lx+4, py1+4); - gVirtualX->DrawLine(px1+4, By+4, px1-4, By+4); - gVirtualX->DrawLine(px1-4, By+4, px1-4, By-4); - gVirtualX->DrawLine(px1-4, By-4, px1+4, By-4); - gVirtualX->DrawLine(px1+4, By-4, px1+4, By+4); - gVirtualX->DrawLine(px1+4, Ty+4, px1-4, Ty+4); - gVirtualX->DrawLine(px1-4, Ty+4, px1-4, Ty-4); - gVirtualX->DrawLine(px1-4, Ty-4, px1+4, Ty-4); - gVirtualX->DrawLine(px1+4, Ty-4, px1+4, Ty+4); - pxold = px; - pyold = py; - break; - - case kButton1Up: - fX1 = gPad->AbsPixeltoX(px1); - fY1 = gPad->AbsPixeltoY(py1); - rBy = gPad->AbsPixeltoY(py1+R1); - rTy = gPad->AbsPixeltoY(py1-R1); - rLx = gPad->AbsPixeltoX(px1+R1); - rRx = gPad->AbsPixeltoX(px1-R1); - fR1 = TMath::Abs(rRx-rLx)/2; - Build(); - gPad->Modified(kTRUE); - gVirtualX->SetLineColor(-1); - } -} - -//_____________________________________________________________________________________ -void TCurlyArc::SavePrimitive(ofstream &out, Option_t *){ - // Save primitive as a C++ statement(s) on output stream out - - if (gROOT->ClassSaved(TCurlyArc::Class())) { - out<<" "; - } else { - out<<" TCurlyArc *"; - } - out<<"curlyarc = new TCurlyArc(" - <<fX1<<","<<fY1<<","<<fR1<<","<<fPhimin<<","<<fPhimax<<"," - <<fWaveLength<<","<<fAmplitude<<");"<<endl; - if (!fIsCurly) { - out<<" curlyarc->SetWavy();"<<endl; - } - SaveLineAttributes(out,"curlyarc",1,1,1); - out<<" curlyarc->Draw();"<<endl; -} - - -//_____________________________________________________________________________________ -void TCurlyArc::SetCenter(Double_t x, Double_t y) -{ - fX1 = x; - fY1 = y; - Build(); -} -void TCurlyArc::SetRadius(Double_t x) -{ - fR1 = x; - Build(); -} -void TCurlyArc::SetPhimin(Double_t x) -{ - fPhimin = x; - Build(); -} -void TCurlyArc::SetPhimax(Double_t x) -{ - fPhimax = x; - Build(); -} +// @(#)root/graf:$Name: $:$Id: TCurlyArc.cxx,v 1.5 2004/12/06 09:55:38 brun 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 arcs 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 TCurlyLine 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. +//Begin_Html +/* +<img src="gif/feynman.gif"> +*/ +//End_Html +//________________________________________________________________________ + +#include "Riostream.h" +#include "TCurlyArc.h" +#include "TROOT.h" +#include "TVirtualPad.h" +#include "TVirtualX.h" +#include "TMath.h" + +ClassImp(TCurlyArc) + +//_____________________________________________________________________________________ +TCurlyArc::TCurlyArc(Double_t x1, Double_t y1, + Double_t rad, Double_t phimin, Double_t phimax, + Double_t tl, Double_t trad) + : fR1(rad), fPhimin(phimin),fPhimax(phimax) +{ + // create a new TCurlyarc with center (x1, y1) and radius rad. + // The wavelength and amplitude are given in percent of the line length + // phimin and phimax are given in degrees. + + fX1 = x1; + fY1 = y1; + fIsCurly = kTRUE; + fAmplitude = trad; + fWaveLength = tl; + fTheta = 0; + Build(); +} + +//_____________________________________________________________________________________ +void TCurlyArc::Build() +{ +//*-*-*-*-*-*-*-*-*-*-*Create a curly (Gluon) or wavy (Gamma) arc*-*-*-*-*-* +//*-* =========================================== + Double_t PixeltoX = 1; + Double_t PixeltoY = 1; + Double_t rPix = fR1; + if (gPad) { + Double_t ww = (Double_t)gPad->GetWw(); + Double_t wh = (Double_t)gPad->GetWh(); + Double_t pxrange = gPad->GetAbsWNDC()*ww; + Double_t pyrange = - gPad->GetAbsHNDC()*wh; + Double_t xrange = gPad->GetX2() - gPad->GetX1(); + Double_t yrange = gPad->GetY2() - gPad->GetY1(); +// PixeltoX = gPad->GetPixeltoX(); +// PixeltoY = gPad->GetPixeltoY(); + PixeltoX = xrange / pxrange; + PixeltoY = yrange/pyrange; + rPix = fR1 / PixeltoX; + } + Double_t dang = fPhimax - fPhimin; + if(dang < 0) dang += 360; + Double_t length = TMath::Pi() * fR1 * dang/180; + Double_t x1sav = fX1; + Double_t y1sav = fY1; + fX1 = fY1 = 0; + fX2 = length; + fY2 = 0; + TCurlyLine::Build(); +// TCurlyLine::Build(kTRUE); + fX1 = x1sav; + fY1 = y1sav; + Double_t *xv= GetX(); + Double_t *yv= GetY(); + Double_t xx, yy, angle; + for(Int_t i = 0; i < fNsteps; i++){ + angle = xv[i] / rPix + fPhimin * TMath::Pi()/180; + xx = (yv[i] + rPix) * cos(angle); + yy = (yv[i] + rPix) * sin(angle); + xx *= PixeltoX; + yy *= TMath::Abs(PixeltoY); + xv[i] = xx + fX1; + yv[i] = yy + fY1; + } + if (gPad) gPad->Modified(); +} + +//______________________________________________________________________________ +Int_t TCurlyArc::DistancetoPrimitive(Int_t px, Int_t py) +{ +//*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to an arc*-*-*-* +//*-* =========================================== +// Compute the closest distance of approach from point px,py to this arc. +// The distance is computed in pixels units. +// +// static Int_t ncalls = 0; +//*-*- Compute distance of point to center of arc + Int_t pxc = gPad->XtoAbsPixel(fX1); + Int_t pyc = gPad->YtoAbsPixel(fY1); + Double_t dist = TMath::Sqrt(Double_t((pxc-px)*(pxc-px)+(pyc-py)*(pyc-py))); + Double_t cosa = (px - pxc)/dist; + Double_t sina = (pyc - py)/dist; + Double_t phi = TMath::ATan2(sina,cosa); + if(phi < 0) phi += 2 * TMath::Pi(); + phi = phi * 180 / TMath::Pi(); + if(fPhimax > fPhimin){ + if(phi < fPhimin || phi > fPhimax) return 9999; + } else { + if(phi > fPhimin && phi < fPhimax) return 9999; + } + Int_t pxr = gPad->XtoPixel(fR1)- gPad->XtoPixel(0); + Double_t distr = TMath::Abs(dist-pxr); + return Int_t(distr); +} + +//______________________________________________________________________________ +void TCurlyArc::ExecuteEvent(Int_t event, Int_t px, Int_t py) +{ +//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-* +//*-* ========================================= +// This member function is called when a TCurlyArc 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 = 10; + const Int_t np = 10; + const Double_t PI = 3.141592; + static Int_t x[np+3], y[np+3]; + static Int_t px1,py1,npe,R1; + static Int_t pxold, pyold; + Int_t i, dpx, dpy; + Double_t angle,dx,dy,dphi,rTy,rBy,rLx,rRx; + Double_t phi0; + static Bool_t T, L, R, B, INSIDE; + static Int_t Tx,Ty,Lx,Ly,Rx,Ry,Bx,By; + + switch (event) { + + case kButton1Down: + gVirtualX->SetLineColor(-1); + TAttLine::Modify(); + dphi = (fPhimax-fPhimin) * PI / 180; + if(dphi<0) dphi += 2 * PI; + dphi /= np; + phi0 = fPhimin * PI / 180; + for (i=0;i<=np;i++) { + angle = Double_t(i)*dphi + phi0; + dx = fR1*TMath::Cos(angle); + dy = fR1*TMath::Sin(angle); + Int_t RpixY = gPad->XtoAbsPixel(dy) - gPad->XtoAbsPixel(0); + x[i] = gPad->XtoAbsPixel(fX1 + dx); + y[i] = gPad->YtoAbsPixel(fY1) + RpixY; + } + if (fPhimax-fPhimin >= 360 ) { + x[np+1] = x[0]; + y[np+1] = y[0]; + npe = np; + } else { + x[np+1] = gPad->XtoAbsPixel(fX1); + y[np+1] = gPad->YtoAbsPixel(fY1); + x[np+2] = x[0]; + y[np+2] = y[0]; + npe = np + 2; + } + px1 = gPad->XtoAbsPixel(fX1); + py1 = gPad->YtoAbsPixel(fY1); + Tx = Bx = px1; + Ly = Ry = py1; + Lx = gPad->XtoAbsPixel(-fR1+fX1); + Rx = gPad->XtoAbsPixel( fR1+fX1); + R1 = TMath::Abs(Lx-Rx)/2; +// a circle in pixels, radius measured along X + Ty = gPad->YtoAbsPixel(fY1) + R1; + By = gPad->YtoAbsPixel(fY1) - R1; + + gVirtualX->DrawLine(Rx+4, py1+4, Rx-4, py1+4); + gVirtualX->DrawLine(Rx-4, py1+4, Rx-4, py1-4); + gVirtualX->DrawLine(Rx-4, py1-4, Rx+4, py1-4); + gVirtualX->DrawLine(Rx+4, py1-4, Rx+4, py1+4); + gVirtualX->DrawLine(Lx+4, py1+4, Lx-4, py1+4); + gVirtualX->DrawLine(Lx-4, py1+4, Lx-4, py1-4); + gVirtualX->DrawLine(Lx-4, py1-4, Lx+4, py1-4); + gVirtualX->DrawLine(Lx+4, py1-4, Lx+4, py1+4); + gVirtualX->DrawLine(px1+4, By+4, px1-4, By+4); + gVirtualX->DrawLine(px1-4, By+4, px1-4, By-4); + gVirtualX->DrawLine(px1-4, By-4, px1+4, By-4); + gVirtualX->DrawLine(px1+4, By-4, px1+4, By+4); + gVirtualX->DrawLine(px1+4, Ty+4, px1-4, Ty+4); + gVirtualX->DrawLine(px1-4, Ty+4, px1-4, Ty-4); + gVirtualX->DrawLine(px1-4, Ty-4, px1+4, Ty-4); + gVirtualX->DrawLine(px1+4, Ty-4, px1+4, Ty+4); + // No break !!! + + case kMouseMotion: + px1 = gPad->XtoAbsPixel(fX1); + py1 = gPad->YtoAbsPixel(fY1); + Tx = Bx = px1; + Ly = Ry = py1; + Lx = gPad->XtoAbsPixel(-fR1+fX1); + Rx = gPad->XtoAbsPixel( fR1+fX1); + + Ty = gPad->YtoAbsPixel(fY1) + TMath::Abs(Lx-Rx)/2; + By = gPad->YtoAbsPixel(fY1) - TMath::Abs(Lx-Rx)/2; + + T = L = R = B = INSIDE = kFALSE; + if ((TMath::Abs(px - Tx) < kMaxDiff) && + (TMath::Abs(py - Ty) < kMaxDiff)) { // top edge + T = kTRUE; + gPad->SetCursor(kTopSide); + } + else + if ((TMath::Abs(px - Bx) < kMaxDiff) && + (TMath::Abs(py - By) < kMaxDiff)) { // bottom edge + B = kTRUE; + gPad->SetCursor(kBottomSide); + } + else + if ((TMath::Abs(py - Ly) < kMaxDiff) && + (TMath::Abs(px - Lx) < kMaxDiff)) { // left edge + L = kTRUE; + gPad->SetCursor(kLeftSide); + } + else + if ((TMath::Abs(py - Ry) < kMaxDiff) && + (TMath::Abs(px - Rx) < kMaxDiff)) { // right edge + R = kTRUE; + gPad->SetCursor(kRightSide); + } + else {INSIDE= kTRUE; gPad->SetCursor(kMove); } + pxold = px; pyold = py; + + break; + + case kButton1Motion: + gVirtualX->DrawLine(Rx+4, py1+4, Rx-4, py1+4); + gVirtualX->DrawLine(Rx-4, py1+4, Rx-4, py1-4); + gVirtualX->DrawLine(Rx-4, py1-4, Rx+4, py1-4); + gVirtualX->DrawLine(Rx+4, py1-4, Rx+4, py1+4); + gVirtualX->DrawLine(Lx+4, py1+4, Lx-4, py1+4); + gVirtualX->DrawLine(Lx-4, py1+4, Lx-4, py1-4); + gVirtualX->DrawLine(Lx-4, py1-4, Lx+4, py1-4); + gVirtualX->DrawLine(Lx+4, py1-4, Lx+4, py1+4); + gVirtualX->DrawLine(px1+4, By+4, px1-4, By+4); + gVirtualX->DrawLine(px1-4, By+4, px1-4, By-4); + gVirtualX->DrawLine(px1-4, By-4, px1+4, By-4); + gVirtualX->DrawLine(px1+4, By-4, px1+4, By+4); + gVirtualX->DrawLine(px1+4, Ty+4, px1-4, Ty+4); + gVirtualX->DrawLine(px1-4, Ty+4, px1-4, Ty-4); + gVirtualX->DrawLine(px1-4, Ty-4, px1+4, Ty-4); + gVirtualX->DrawLine(px1+4, Ty-4, px1+4, Ty+4); + for (i=0;i<npe;i++) gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]); + if (T) { + R1 -= (py - pyold); + } + if (B) { + R1 += (py - pyold); + } + if (L) { + R1 -= (px - pxold); + } + if (R) { + R1 += (px - pxold); + } + if (T || B || L || R) { + gVirtualX->SetLineColor(-1); + TAttLine::Modify(); + dphi = (fPhimax-fPhimin) * PI / 180; + if(dphi<0) dphi += 2 * PI; + dphi /= np; + phi0 = fPhimin * PI / 180; +// Double_t uR1 = gPad->PixeltoX(R1) - gPad->GetUxmin(); + Double_t uR1 = R1; + Int_t pX1 = gPad->XtoAbsPixel(fX1); + Int_t pY1 = gPad->YtoAbsPixel(fY1); + for (i=0;i<=np;i++) { + angle = Double_t(i)*dphi + phi0; + dx = uR1 * TMath::Cos(angle); + dy = uR1 * TMath::Sin(angle); + x[i] = pX1 + (Int_t)dx; + y[i] = pY1 + (Int_t)dy; + +// x[i] = gPad->XtoAbsPixel(fX1 + dx); +// y[i] = gPad->YtoAbsPixel(fY1 + dy); + } + if (fPhimax-fPhimin >= 360 ) { + x[np+1] = x[0]; + y[np+1] = y[0]; + npe = np; + } else { + x[np+1] = pX1; + y[np+1] = pY1; + x[np+2] = x[0]; + y[np+2] = y[0]; + npe = np + 2; + } + for (i=0;i<npe;i++) { + gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]); + } + } + if (INSIDE) { + dpx = px-pxold; dpy = py-pyold; + px1 += dpx; py1 += dpy; + for (i=0;i<=npe;i++) { x[i] += dpx; y[i] += dpy;} + for (i=0;i<npe;i++) gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]); + } + Tx = Bx = px1; + Rx = px1+R1; + Lx = px1-R1; + Ry = Ly = py1; + Ty = py1-R1; + By = py1+R1; + gVirtualX->DrawLine(Rx+4, py1+4, Rx-4, py1+4); + gVirtualX->DrawLine(Rx-4, py1+4, Rx-4, py1-4); + gVirtualX->DrawLine(Rx-4, py1-4, Rx+4, py1-4); + gVirtualX->DrawLine(Rx+4, py1-4, Rx+4, py1+4); + gVirtualX->DrawLine(Lx+4, py1+4, Lx-4, py1+4); + gVirtualX->DrawLine(Lx-4, py1+4, Lx-4, py1-4); + gVirtualX->DrawLine(Lx-4, py1-4, Lx+4, py1-4); + gVirtualX->DrawLine(Lx+4, py1-4, Lx+4, py1+4); + gVirtualX->DrawLine(px1+4, By+4, px1-4, By+4); + gVirtualX->DrawLine(px1-4, By+4, px1-4, By-4); + gVirtualX->DrawLine(px1-4, By-4, px1+4, By-4); + gVirtualX->DrawLine(px1+4, By-4, px1+4, By+4); + gVirtualX->DrawLine(px1+4, Ty+4, px1-4, Ty+4); + gVirtualX->DrawLine(px1-4, Ty+4, px1-4, Ty-4); + gVirtualX->DrawLine(px1-4, Ty-4, px1+4, Ty-4); + gVirtualX->DrawLine(px1+4, Ty-4, px1+4, Ty+4); + pxold = px; + pyold = py; + break; + + case kButton1Up: + fX1 = gPad->AbsPixeltoX(px1); + fY1 = gPad->AbsPixeltoY(py1); + rBy = gPad->AbsPixeltoY(py1+R1); + rTy = gPad->AbsPixeltoY(py1-R1); + rLx = gPad->AbsPixeltoX(px1+R1); + rRx = gPad->AbsPixeltoX(px1-R1); + fR1 = TMath::Abs(rRx-rLx)/2; + Build(); + gPad->Modified(kTRUE); + gVirtualX->SetLineColor(-1); + } +} + +//_____________________________________________________________________________________ +void TCurlyArc::SavePrimitive(ofstream &out, Option_t *){ + // Save primitive as a C++ statement(s) on output stream out + + if (gROOT->ClassSaved(TCurlyArc::Class())) { + out<<" "; + } else { + out<<" TCurlyArc *"; + } + out<<"curlyarc = new TCurlyArc(" + <<fX1<<","<<fY1<<","<<fR1<<","<<fPhimin<<","<<fPhimax<<"," + <<fWaveLength<<","<<fAmplitude<<");"<<endl; + if (!fIsCurly) { + out<<" curlyarc->SetWavy();"<<endl; + } + SaveLineAttributes(out,"curlyarc",1,1,1); + out<<" curlyarc->Draw();"<<endl; +} + + +//_____________________________________________________________________________________ +void TCurlyArc::SetCenter(Double_t x, Double_t y) +{ + fX1 = x; + fY1 = y; + Build(); +} +void TCurlyArc::SetRadius(Double_t x) +{ + fR1 = x; + Build(); +} +void TCurlyArc::SetPhimin(Double_t x) +{ + fPhimin = x; + Build(); +} +void TCurlyArc::SetPhimax(Double_t x) +{ + fPhimax = x; + Build(); +} diff --git a/graf/src/TCurlyLine.cxx b/graf/src/TCurlyLine.cxx index 7c0302f7469b0f4424cb0b8d75623e203a7b3562..6bf0990987ba566493728fc64ebdfa1144975f5d 100644 --- a/graf/src/TCurlyLine.cxx +++ b/graf/src/TCurlyLine.cxx @@ -1,318 +1,318 @@ -// @(#)root/graf:$Name: $:$Id: TCurlyLine.cxx,v 1.5 2004/12/06 09:55:38 brun 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. -//Begin_Html -/* -<img src="gif/feynman.gif"> -*/ -//End_Html -//________________________________________________________________________ - -#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 PixeltoX = 1; - Double_t PixeltoY = 1; -//--- - Double_t wavelengthPix,amplitudePix, lengthPix, hPix; - Double_t px1, py1, px2, py2; - if (gPad) { - Double_t ww = (Double_t)gPad->GetWw(); - Double_t wh = (Double_t)gPad->GetWh(); - Double_t pxrange = gPad->GetAbsWNDC()*ww; - Double_t pyrange = - gPad->GetAbsHNDC()*wh; - Double_t xrange = gPad->GetX2() - gPad->GetX1(); - Double_t yrange = gPad->GetY2() - gPad->GetY1(); - -// PixeltoX = gPad->GetPixeltoX(); -// PixeltoY = gPad->GetPixeltoY(); - - PixeltoX = xrange / pxrange; - PixeltoY = yrange/pyrange; - hPix = TMath::Max(gPad->GetAbsHNDC() * gPad->GetWh(), gPad->GetAbsWNDC() * gPad->GetWw()); - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - px2 = gPad->XtoAbsPixel(fX2); - py2 = gPad->YtoAbsPixel(fY2); - - lengthPix = TMath::Sqrt((px2-px1)*(px2-px1) + (py1-py2)*(py1-py2)); - wavelengthPix = hPix*fWaveLength; - amplitudePix = hPix*fAmplitude; - } else { - wavelengthPix = fWaveLength; - amplitudePix = fAmplitude; - px1 = fX1; - py1 = fY1; - px2 = fX2; - py2 = fY2; - lengthPix = TMath::Sqrt((px2-px1)*(px2-px1) + (py1-py2)*(py1-py2)); - } - if(lengthPix <= wavelengthPix){ - Warning("Build","CurlyLine is too short, length %g is < wavelength: %g ",lengthPix,wavelengthPix); - SetBit(kTooShort); - return; - } -// construct the curly / wavy line in pixel coordinates at angle 0 - Double_t anglestep = 40; - Double_t phimaxle = TMath::Pi() * 2. / anglestep ; - Double_t dx = wavelengthPix / 40; - Double_t len2pi = dx * anglestep; - -// make sure there is a piece of straight line a both ends - - Double_t lengthcycle = 0.5 * len2pi + 2 * amplitudePix; -// if (fIsCurly) lengthcycle += amplitudePix; - Int_t nperiods = (Int_t)((lengthPix - lengthcycle) / len2pi); - Double_t restlength = 0.5 * (lengthPix - 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] = restlength; yv[1] = 0; - Double_t phase = 1.5 * TMath::Pi(); - Double_t x0 = amplitudePix + restlength; - Int_t i; - for(i = 2; i < fNsteps-1; i++){ -// distinguish between curly and wavy - if(fIsCurly) xv[i] = x0 + amplitudePix * TMath::Sin(phase); - else xv[i] = x0; - yv[i] = amplitudePix*TMath::Cos(phase); - phase += phimaxle; - x0 += dx; - } - xv[fNsteps-1] = lengthPix; yv[fNsteps-1] = 0; - - if (InheritsFrom("TCurlyArc")) return; // called by TCurlyArc - -// rotate object and transform back to user coordinates - Double_t angle = TMath::ATan2(py2-py1, px2-px1); - if(angle < 0) angle += 2*TMath::Pi(); - - 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; - if (gPad) { - xx *= PixeltoX; - yy *= PixeltoY; - } - 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/graf:$Name: $:$Id: TCurlyLine.cxx,v 1.6 2004/12/16 11:16:24 brun 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. +//Begin_Html +/* +<img src="gif/feynman.gif"> +*/ +//End_Html +//________________________________________________________________________ + +#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 PixeltoX = 1; + Double_t PixeltoY = 1; +//--- + Double_t wavelengthPix,amplitudePix, lengthPix, hPix; + Double_t px1, py1, px2, py2; + if (gPad) { + Double_t ww = (Double_t)gPad->GetWw(); + Double_t wh = (Double_t)gPad->GetWh(); + Double_t pxrange = gPad->GetAbsWNDC()*ww; + Double_t pyrange = - gPad->GetAbsHNDC()*wh; + Double_t xrange = gPad->GetX2() - gPad->GetX1(); + Double_t yrange = gPad->GetY2() - gPad->GetY1(); + +// PixeltoX = gPad->GetPixeltoX(); +// PixeltoY = gPad->GetPixeltoY(); + + PixeltoX = xrange / pxrange; + PixeltoY = yrange/pyrange; + hPix = TMath::Max(gPad->GetAbsHNDC() * gPad->GetWh(), gPad->GetAbsWNDC() * gPad->GetWw()); + px1 = gPad->XtoAbsPixel(fX1); + py1 = gPad->YtoAbsPixel(fY1); + px2 = gPad->XtoAbsPixel(fX2); + py2 = gPad->YtoAbsPixel(fY2); + + lengthPix = TMath::Sqrt((px2-px1)*(px2-px1) + (py1-py2)*(py1-py2)); + wavelengthPix = hPix*fWaveLength; + amplitudePix = hPix*fAmplitude; + } else { + wavelengthPix = fWaveLength; + amplitudePix = fAmplitude; + px1 = fX1; + py1 = fY1; + px2 = fX2; + py2 = fY2; + lengthPix = TMath::Sqrt((px2-px1)*(px2-px1) + (py1-py2)*(py1-py2)); + } + if(lengthPix <= wavelengthPix){ + Warning("Build","CurlyLine is too short, length %g is < wavelength: %g ",lengthPix,wavelengthPix); + SetBit(kTooShort); + return; + } +// construct the curly / wavy line in pixel coordinates at angle 0 + Double_t anglestep = 40; + Double_t phimaxle = TMath::Pi() * 2. / anglestep ; + Double_t dx = wavelengthPix / 40; + Double_t len2pi = dx * anglestep; + +// make sure there is a piece of straight line a both ends + + Double_t lengthcycle = 0.5 * len2pi + 2 * amplitudePix; +// if (fIsCurly) lengthcycle += amplitudePix; + Int_t nperiods = (Int_t)((lengthPix - lengthcycle) / len2pi); + Double_t restlength = 0.5 * (lengthPix - 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] = restlength; yv[1] = 0; + Double_t phase = 1.5 * TMath::Pi(); + Double_t x0 = amplitudePix + restlength; + Int_t i; + for(i = 2; i < fNsteps-1; i++){ +// distinguish between curly and wavy + if(fIsCurly) xv[i] = x0 + amplitudePix * TMath::Sin(phase); + else xv[i] = x0; + yv[i] = amplitudePix*TMath::Cos(phase); + phase += phimaxle; + x0 += dx; + } + xv[fNsteps-1] = lengthPix; yv[fNsteps-1] = 0; + + if (InheritsFrom("TCurlyArc")) return; // called by TCurlyArc + +// rotate object and transform back to user coordinates + Double_t angle = TMath::ATan2(py2-py1, px2-px1); + if(angle < 0) angle += 2*TMath::Pi(); + + 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; + if (gPad) { + xx *= PixeltoX; + yy *= PixeltoY; + } + 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(); +}