TCurlyArc.cxx

Go to the documentation of this file.
00001 // @(#)root/graf:$Id: TCurlyArc.cxx 20882 2007-11-19 11:31:26Z rdm $
00002 // Author: Otto Schaile   20/11/99
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //______________________________________________________________________________
00013 //
00014 // This class implements curly or wavy arcs typically used to draw Feynman diagrams.
00015 // Amplitudes and wavelengths may be specified in the constructors,
00016 // via commands or interactively from popup menus.
00017 // The class make use of TCurlyLine by inheritance, ExecuteEvent methods
00018 // are highly inspired from the methods used in TPolyLine and TArc.
00019 // The picture below has been generated by the tutorial feynman.
00020 //Begin_Html
00021 /*
00022 <img src="gif/feynman.gif">
00023 */
00024 //End_Html
00025 //______________________________________________________________________________
00026 
00027 #include "Riostream.h"
00028 #include "TCurlyArc.h"
00029 #include "TROOT.h"
00030 #include "TVirtualPad.h"
00031 #include "TVirtualX.h"
00032 #include "TMath.h"
00033 
00034 Double_t TCurlyArc::fgDefaultWaveLength = 0.02;
00035 Double_t TCurlyArc::fgDefaultAmplitude  = 0.01; 
00036 Bool_t   TCurlyArc::fgDefaultIsCurly    = kTRUE;   
00037 
00038 ClassImp(TCurlyArc)
00039 
00040 
00041 //______________________________________________________________________________
00042 TCurlyArc::TCurlyArc(Double_t x1, Double_t y1,
00043                    Double_t rad, Double_t phimin, Double_t phimax,
00044                    Double_t wl, Double_t amp)
00045          : fR1(rad), fPhimin(phimin),fPhimax(phimax)
00046 {
00047    // create a new TCurlyarc with center (x1, y1) and radius rad.
00048    // The wavelength and amplitude are given in percent of the line length
00049    // phimin and phimax are given in degrees.
00050 
00051    fX1         = x1;
00052    fY1         = y1;
00053    fIsCurly    = fgDefaultIsCurly;
00054    fAmplitude  = amp;
00055    fWaveLength = wl;
00056    fTheta      = 0;
00057    Build();
00058 }
00059 
00060 
00061 //______________________________________________________________________________
00062 void TCurlyArc::Build()
00063 {
00064    // Create a curly (Gluon) or wavy (Gamma) arc.
00065 
00066    Double_t pixeltoX = 1;
00067    Double_t pixeltoY = 1;
00068    Double_t rPix = fR1;
00069    if (gPad) {
00070         Double_t ww = (Double_t)gPad->GetWw();
00071         Double_t wh = (Double_t)gPad->GetWh();
00072         Double_t pxrange = gPad->GetAbsWNDC()*ww;
00073         Double_t pyrange = - gPad->GetAbsHNDC()*wh;
00074         Double_t xrange  = gPad->GetX2() - gPad->GetX1();
00075         Double_t yrange  = gPad->GetY2() - gPad->GetY1();
00076         pixeltoX  = xrange / pxrange;
00077         pixeltoY  = yrange/pyrange;
00078       rPix = fR1 / pixeltoX;
00079    }
00080    Double_t dang = fPhimax - fPhimin;
00081    if(dang < 0) dang += 360;
00082    Double_t length = TMath::Pi() * fR1 * dang/180;
00083    Double_t x1sav = fX1;
00084    Double_t y1sav = fY1;
00085    fX1 = fY1 = 0;
00086    fX2 = length;
00087    fY2 = 0;
00088    TCurlyLine::Build();
00089    fX1 = x1sav;
00090    fY1 = y1sav;
00091    Double_t *xv= GetX();
00092    Double_t *yv= GetY();
00093    Double_t xx, yy, angle;
00094    for(Int_t i = 0; i < fNsteps; i++){
00095       angle = xv[i] / rPix + fPhimin * TMath::Pi()/180;
00096       xx    = (yv[i] + rPix) * cos(angle);
00097       yy    = (yv[i] + rPix) * sin(angle);
00098       xx *= pixeltoX;
00099       yy *= TMath::Abs(pixeltoY);
00100       xv[i] = xx + fX1;
00101       yv[i] = yy + fY1;
00102    }
00103    if (gPad) gPad->Modified();
00104 }
00105 
00106 
00107 //______________________________________________________________________________
00108 Int_t TCurlyArc::DistancetoPrimitive(Int_t px, Int_t py)
00109 {
00110    // Compute distance from point px,py to an arc.
00111    //
00112    //  Compute the closest distance of approach from point px,py to this arc.
00113    //  The distance is computed in pixels units.
00114    //
00115 
00116    // Compute distance of point to center of arc
00117    Int_t pxc    = gPad->XtoAbsPixel(fX1);
00118    Int_t pyc    = gPad->YtoAbsPixel(fY1);
00119    Double_t dist = TMath::Sqrt(Double_t((pxc-px)*(pxc-px)+(pyc-py)*(pyc-py)));
00120    Double_t cosa = (px - pxc)/dist;
00121    Double_t sina = (pyc - py)/dist;
00122    Double_t phi  = TMath::ATan2(sina,cosa);
00123    if(phi < 0) phi += 2 * TMath::Pi();
00124    phi = phi * 180 / TMath::Pi();
00125    if(fPhimax > fPhimin){
00126       if(phi < fPhimin || phi > fPhimax) return 9999;
00127    } else {
00128       if(phi > fPhimin && phi < fPhimax) return 9999;
00129    }
00130    Int_t pxr = gPad->XtoPixel(fR1)- gPad->XtoPixel(0);
00131    Double_t distr = TMath::Abs(dist-pxr);
00132    return Int_t(distr);
00133 }
00134 
00135 
00136 //______________________________________________________________________________
00137 void TCurlyArc::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00138 {
00139    // Execute action corresponding to one event.
00140    //
00141    //  This member function is called when a TCurlyArc is clicked with the locator
00142    //
00143    //  If Left button clicked on one of the line end points, this point
00144    //     follows the cursor until button is released.
00145    //
00146    //  if Middle button clicked, the line is moved parallel to itself
00147    //     until the button is released.
00148 
00149    Int_t kMaxDiff = 10;
00150    const Int_t np = 10;
00151    const Double_t pi = 3.141592;
00152    static Int_t x[np+3], y[np+3];
00153    static Int_t px1,py1,npe,r1;
00154    static Int_t pxold, pyold;
00155    Int_t i, dpx, dpy;
00156    Double_t angle,dx,dy,dphi,rTy,rBy,rLx,rRx;
00157    Double_t  phi0;
00158    static Bool_t pTop, pL, pR, pBot, pINSIDE;
00159    static Int_t pTx,pTy,pLx,pLy,pRx,pRy,pBx,pBy;
00160 
00161    switch (event) {
00162 
00163    case kButton1Down:
00164       gVirtualX->SetLineColor(-1);
00165       TAttLine::Modify();
00166       dphi = (fPhimax-fPhimin) * pi / 180;
00167       if(dphi<0) dphi += 2 * pi;
00168       dphi /= np;
00169       phi0 = fPhimin * pi / 180;
00170       for (i=0;i<=np;i++) {
00171          angle = Double_t(i)*dphi + phi0;
00172          dx    = fR1*TMath::Cos(angle);
00173          dy    = fR1*TMath::Sin(angle);
00174          Int_t rpixY = gPad->XtoAbsPixel(dy) - gPad->XtoAbsPixel(0);
00175          x[i]  = gPad->XtoAbsPixel(fX1 + dx);
00176          y[i]  = gPad->YtoAbsPixel(fY1) + rpixY;
00177       }
00178       if (fPhimax-fPhimin >= 360 ) {
00179          x[np+1] = x[0];
00180          y[np+1] = y[0];
00181          npe = np;
00182       } else {
00183          x[np+1]   = gPad->XtoAbsPixel(fX1);
00184          y[np+1]   = gPad->YtoAbsPixel(fY1);
00185          x[np+2] = x[0];
00186          y[np+2] = y[0];
00187          npe = np + 2;
00188       }
00189       px1 = gPad->XtoAbsPixel(fX1);
00190       py1 = gPad->YtoAbsPixel(fY1);
00191       pTx = pBx = px1;
00192       pLy = pRy = py1;
00193       pLx = gPad->XtoAbsPixel(-fR1+fX1);
00194       pRx = gPad->XtoAbsPixel( fR1+fX1);
00195       r1 = TMath::Abs(pLx-pRx)/2;
00196       // a circle in pixels, radius measured along X     
00197       pTy = gPad->YtoAbsPixel(fY1) + r1;
00198       pBy = gPad->YtoAbsPixel(fY1) - r1;
00199 
00200       gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4);
00201       gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4);
00202       gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4);
00203       gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4);
00204       gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4);
00205       gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4);
00206       gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4);
00207       gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4);
00208       gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4);
00209       gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4);
00210       gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4);
00211       gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4);
00212       gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4);
00213       gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4);
00214       gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4);
00215       gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4);
00216       // No break !!!
00217 
00218    case kMouseMotion:
00219       px1 = gPad->XtoAbsPixel(fX1);
00220       py1 = gPad->YtoAbsPixel(fY1);
00221       pTx = pBx = px1;
00222       pLy = pRy = py1;
00223       pLx = gPad->XtoAbsPixel(-fR1+fX1);
00224       pRx = gPad->XtoAbsPixel( fR1+fX1);
00225       
00226       pTy = gPad->YtoAbsPixel(fY1) + TMath::Abs(pLx-pRx)/2;
00227       pBy = gPad->YtoAbsPixel(fY1) - TMath::Abs(pLx-pRx)/2;
00228 
00229       pTop = pL = pR = pBot = pINSIDE = kFALSE;
00230       if ((TMath::Abs(px - pTx) < kMaxDiff) &&
00231           (TMath::Abs(py - pTy) < kMaxDiff)) {             // top edge
00232          pTop = kTRUE;
00233          gPad->SetCursor(kTopSide);
00234       }
00235       else
00236       if ((TMath::Abs(px - pBx) < kMaxDiff) &&
00237           (TMath::Abs(py - pBy) < kMaxDiff)) {             // bottom edge
00238          pBot = kTRUE;
00239          gPad->SetCursor(kBottomSide);
00240       }
00241       else
00242       if ((TMath::Abs(py - pLy) < kMaxDiff) &&
00243           (TMath::Abs(px - pLx) < kMaxDiff)) {             // left edge
00244          pL = kTRUE;
00245          gPad->SetCursor(kLeftSide);
00246       }
00247       else
00248       if ((TMath::Abs(py - pRy) < kMaxDiff) &&
00249           (TMath::Abs(px - pRx) < kMaxDiff)) {             // right edge
00250          pR = kTRUE;
00251          gPad->SetCursor(kRightSide);
00252       }
00253       else {pINSIDE= kTRUE; gPad->SetCursor(kMove); }
00254       pxold = px;  pyold = py;
00255 
00256       break;
00257 
00258    case kButton1Motion:
00259       gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4);
00260       gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4);
00261       gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4);
00262       gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4);
00263       gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4);
00264       gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4);
00265       gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4);
00266       gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4);
00267       gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4);
00268       gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4);
00269       gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4);
00270       gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4);
00271       gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4);
00272       gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4);
00273       gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4);
00274       gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4);
00275       for (i=0;i<npe;i++) gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]);
00276       if (pTop) {
00277          r1 -= (py - pyold);
00278       }
00279       if (pBot) {
00280          r1 += (py - pyold);
00281       }
00282       if (pL) {
00283          r1 -= (px - pxold);
00284       }
00285       if (pR) {
00286          r1 += (px - pxold);
00287       }
00288       if (pTop || pBot || pL || pR) {
00289          gVirtualX->SetLineColor(-1);
00290          TAttLine::Modify();
00291          dphi = (fPhimax-fPhimin) * pi / 180;
00292          if(dphi<0) dphi += 2 * pi;
00293          dphi /= np;
00294          phi0 = fPhimin * pi / 180;
00295          Double_t ur1 = r1;
00296          Int_t pX1   = gPad->XtoAbsPixel(fX1);
00297          Int_t pY1   = gPad->YtoAbsPixel(fY1);
00298          for (i=0;i<=np;i++) {
00299             angle = Double_t(i)*dphi + phi0;
00300             dx    = ur1 * TMath::Cos(angle);
00301             dy    = ur1 * TMath::Sin(angle);
00302             x[i]  = pX1 + (Int_t)dx;
00303             y[i]  = pY1 + (Int_t)dy;
00304          }
00305          if (fPhimax-fPhimin >= 360 ) {
00306             x[np+1] = x[0];
00307             y[np+1] = y[0];
00308             npe = np;
00309          } else {
00310             x[np+1]   = pX1;
00311             y[np+1]   = pY1;
00312             x[np+2] = x[0];
00313             y[np+2] = y[0];
00314             npe = np + 2;
00315          }
00316          for (i=0;i<npe;i++) {
00317             gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]);
00318          }
00319       }
00320       if (pINSIDE) {
00321          dpx  = px-pxold;  dpy = py-pyold;
00322          px1 += dpx; py1 += dpy;
00323          for (i=0;i<=npe;i++) { x[i] += dpx; y[i] += dpy;}
00324          for (i=0;i<npe;i++) gVirtualX->DrawLine(x[i], y[i], x[i+1], y[i+1]);
00325       }
00326       pTx = pBx = px1;
00327       pRx = px1+r1;
00328       pLx = px1-r1;
00329       pRy = pLy = py1;
00330       pTy = py1-r1;
00331       pBy = py1+r1;
00332       gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4);
00333       gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4);
00334       gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4);
00335       gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4);
00336       gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4);
00337       gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4);
00338       gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4);
00339       gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4);
00340       gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4);
00341       gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4);
00342       gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4);
00343       gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4);
00344       gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4);
00345       gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4);
00346       gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4);
00347       gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4);
00348       pxold = px;
00349       pyold = py;
00350       break;
00351 
00352    case kButton1Up:
00353       fX1 = gPad->AbsPixeltoX(px1);
00354       fY1 = gPad->AbsPixeltoY(py1);
00355       rBy = gPad->AbsPixeltoY(py1+r1);
00356       rTy = gPad->AbsPixeltoY(py1-r1);
00357       rLx = gPad->AbsPixeltoX(px1+r1);
00358       rRx = gPad->AbsPixeltoX(px1-r1);
00359       fR1 = TMath::Abs(rRx-rLx)/2;
00360       Build();
00361       gPad->Modified(kTRUE);
00362       gVirtualX->SetLineColor(-1);
00363    }
00364 }
00365 
00366 
00367 //______________________________________________________________________________
00368 void TCurlyArc::SavePrimitive(ostream &out, Option_t * /*= ""*/)
00369 {
00370    // Save primitive as a C++ statement(s) on output stream out
00371 
00372    if (gROOT->ClassSaved(TCurlyArc::Class())) {
00373       out<<"   ";
00374    } else {
00375       out<<"   TCurlyArc *";
00376    }
00377    out<<"curlyarc = new TCurlyArc("
00378      <<fX1<<","<<fY1<<","<<fR1<<","<<fPhimin<<","<<fPhimax<<","
00379       <<fWaveLength<<","<<fAmplitude<<");"<<endl;
00380    if (!fIsCurly) {
00381       out<<"   curlyarc->SetWavy();"<<endl;
00382    }
00383    SaveLineAttributes(out,"curlyarc",1,1,1);
00384    out<<"   curlyarc->Draw();"<<endl;
00385 }
00386 
00387 
00388 //______________________________________________________________________________
00389 void TCurlyArc::SetCenter(Double_t x, Double_t y)
00390 {
00391    // Set Curly Arc center.
00392 
00393    fX1 = x;
00394    fY1 = y;
00395    Build();
00396 }
00397 
00398 
00399 //______________________________________________________________________________
00400 void TCurlyArc::SetRadius(Double_t x)
00401 {
00402    // Set Curly Arc radius.
00403 
00404    fR1 = x;
00405    Build();
00406 }
00407 
00408 
00409 //______________________________________________________________________________
00410 void TCurlyArc::SetPhimin(Double_t x)
00411 {
00412    // Set Curly Arc minimum Phi.
00413 
00414    fPhimin = x;
00415    Build();
00416 }
00417 
00418 
00419 //______________________________________________________________________________
00420 void TCurlyArc::SetPhimax(Double_t x)
00421 {
00422    // Set Curly Arc maximum Phi.
00423 
00424    fPhimax = x;
00425    Build();
00426 }
00427 
00428 
00429 //______________________________________________________________________________
00430 void TCurlyArc::SetDefaultWaveLength(Double_t WaveLength)
00431 {
00432    // Set default wave length.
00433 
00434    fgDefaultWaveLength = WaveLength;
00435 }
00436 
00437 
00438 //______________________________________________________________________________
00439 void TCurlyArc::SetDefaultAmplitude(Double_t Amplitude)
00440 {
00441    // Set default wave amplitude.
00442 
00443    fgDefaultAmplitude = Amplitude ;
00444 }
00445 
00446 
00447 //______________________________________________________________________________
00448 void TCurlyArc::SetDefaultIsCurly(Bool_t IsCurly)
00449 {
00450    // Set default "IsCurly".
00451 
00452    fgDefaultIsCurly = IsCurly;
00453 }
00454 
00455 
00456 //______________________________________________________________________________
00457 Double_t TCurlyArc::GetDefaultWaveLength()
00458 {
00459    // Get default wave length.
00460 
00461    return fgDefaultWaveLength;
00462 }
00463 
00464 
00465 //______________________________________________________________________________
00466 Double_t TCurlyArc::GetDefaultAmplitude()
00467 {
00468    // Get default wave amplitude.
00469 
00470    return fgDefaultAmplitude;
00471 }
00472 
00473 
00474 //______________________________________________________________________________
00475 Bool_t TCurlyArc::GetDefaultIsCurly()
00476 {
00477    // Get default "IsCurly".
00478 
00479    return fgDefaultIsCurly;
00480 }

Generated on Tue Jul 5 14:14:27 2011 for ROOT_528-00b_version by  doxygen 1.5.1