    // @(#)root/graf:$Name:  $:$Id: TArrow.cxx,v 1.11 2004/02/07 08:54:03 brun Exp $
    // Author: Rene Brun   17/10/95

    /*************************************************************************
     * 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.             *
     *************************************************************************/

    #include "Riostream.h"
    #include "TROOT.h"
    #include "TArrow.h"
    #include "TVirtualPad.h"

    ClassImp(TArrow)

    //______________________________________________________________________________
    //  Different arrow formats as explained in TArrow::TArrow or in
    //  the picture below are provided.
    //  Once an arrow is drawn on the screen:
    //    - One can click on one of the edges and move this edge.
    //    - One can click on any other arrow part to move the entire arrow.
    //

/* */ //

// //______________________________________________________________________________ TArrow::TArrow(): TLine(),TAttFill() { //*-*-*-*-*-*-*-*-*-*-*arrow default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //*-* ======================== fAngle = 60; } //______________________________________________________________________________ TArrow::TArrow(Double_t x1, Double_t y1,Double_t x2, Double_t y2, Float_t arrowsize ,Option_t *option) :TLine(x1,y1,x2,y2), TAttFill(0,1001) { //*-*-*-*-*-*-*-*-*-*-*arrow normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //*-* ======================== // Define an arrow between points x1,y1 and x2,y2 // the arrowsize is in percentage of the pad height // Opening angle between the two sides of the arrow is fAngle (60 degrees) // option = ">" --------> // option = "<" <-------- // option = "->-" ---->---- // option = "-<-" ----<---- // option = "-|>-" ---|>---- // option = "<>" <-------> // option = "<|>" <|-----|> arrow defined by a triangle // If FillColor == 0 draw open triangle // else draw full triangle with fillcolor // fAngle = 60; fArrowSize = arrowsize; fOption = option; SetLineColor(1); SetLineStyle(1); } //______________________________________________________________________________ TArrow::~TArrow() { //*-*-*-*-*-*-*-*-*-*-*arrow default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //*-* ======================== } //______________________________________________________________________________ TArrow::TArrow(const TArrow &arrow) : TLine(arrow), TAttFill(arrow) { ((TArrow&)arrow).Copy(*this); } //______________________________________________________________________________ void TArrow::Copy(TObject &obj) const { //*-*-*-*-*-*-*-*-*-*-*Copy this arrow to arrow*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* //*-* ======================== TLine::Copy(obj); TAttFill::Copy(((TArrow&)obj)); ((TArrow&)obj).fAngle = fAngle; ((TArrow&)obj).fArrowSize = fArrowSize; ((TArrow&)obj).fOption = fOption; } //______________________________________________________________________________ void TArrow::Draw(Option_t *option) { //*-*-*-*-*-*-*-*-*-*-*Draw this arrow with its current attributes*-*-*-*-*-*-* //*-* =========================================== Option_t *opt; if (strlen(option)) opt = option; else opt = (char*)GetOption(); AppendPad(opt); } //______________________________________________________________________________ void TArrow::DrawArrow(Double_t x1, Double_t y1,Double_t x2, Double_t y2, Float_t arrowsize ,Option_t *option) { //*-*-*-*-*-*-*-*-*-*-*Draw this arrow with new coordinates*-*-*-*-*-*-*-*-*-* //*-* ==================================== // if arrowsize is <= 0, arrowsize will be the current arrow size // if option="", option will be the current arrow option Float_t size = arrowsize; if (size <= 0) size = fArrowSize; if (size <= 0) size = 0.05; const char* opt = option; if (!opt || strlen(opt) == 0) opt = fOption.Data(); if (!opt || strlen(opt) == 0) opt = "|>"; TArrow *newarrow = new TArrow(x1,y1,x2,y2,size,opt); newarrow->SetAngle(fAngle); TAttLine::Copy(*newarrow); TAttFill::Copy(*newarrow); newarrow->AppendPad(opt); } //______________________________________________________________________________ void TArrow::Paint(Option_t *option) { //*-*-*-*-*-*-*-*-*-*-*Paint this arrow with its current attributes*-*-*-*-*-*-* //*-* ============================================ PaintArrow(gPad->XtoPad(fX1),gPad->YtoPad(fY1),gPad->XtoPad(fX2),gPad->YtoPad(fY2), fArrowSize, option); } //______________________________________________________________________________ void TArrow::PaintArrow(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Float_t arrowsize, Option_t *option) { //*-*-*-*-*-*-*-*-*-*-*Draw this arrow with new coordinates*-*-*-*-*-*-*-*-*-* //*-* ==================================== // // (P2) // - // . - // . - // . - // -------------------------------------------.(P0)------- (P1) // . - // . - // . - // - // (P3) // // TString opt = option; opt.ToLower(); TAttLine::Modify(); TAttFill::Modify(); //*-*- take u1,v1 as origin. take arrow line as new x axis Int_t px1 = gPad->XtoAbsPixel(x1); Int_t py1 = gPad->YtoAbsPixel(y1); Int_t px2 = gPad->XtoAbsPixel(x2); Int_t py2 = gPad->YtoAbsPixel(y2); Float_t lp = TMath::Sqrt(Double_t((px2-px1)*(px2-px1) + (py2-py1)*(py2-py1))); Float_t rSiz = arrowsize*gPad->GetAbsHNDC()*gPad->GetWh(); Float_t dSiz = rSiz*TMath::Tan(3.141592*fAngle/360); if (lp <= 0) return; Double_t ct = (px2-px1)/lp; Double_t st = (py1-py2)/lp; Int_t P2x,P2y,P3x,P3y,P0x,P0y; // Otto start: define default line before move of origin of arrow Double_t XP0; Double_t YP0; Double_t XP0L; Double_t YP0L; XP0 = gPad->AbsPixeltoX(px2); YP0 = gPad->AbsPixeltoY(py2); XP0L = gPad->AbsPixeltoX(px1); YP0L = gPad->AbsPixeltoY(py1); // move origin of arrow if (opt.Contains("-") && opt.Contains(">")) { px1 = Int_t(0.5 *(px2 + px1) + ct*rSiz/2); py1 = Int_t(0.5 *(py2 + py1) - st*rSiz/2); px2 = px1; py2 = py1; } if (opt.Contains("-") && opt.Contains("<")) { px1 = Int_t(0.5 *(px2 + px1) - ct*rSiz/2); py1 = Int_t(0.5 *(py2 + py1) + st*rSiz/2); px2 = px1; py2 = py1; } // ---------- if (opt.Contains(">")) { P2x = px2 - Int_t(rSiz*ct+st*dSiz-0.5); P2y = py2 + Int_t(rSiz*st-ct*dSiz+0.5); P3x = px2 - Int_t(rSiz*ct-st*dSiz-0.5); P3y = py2 + Int_t(rSiz*st+ct*dSiz+0.5); P0x = px2 - Int_t(rSiz*ct-0.5); P0y = py2 + Int_t(rSiz*st+0.5); } else { P2x = px2; P2y = py2; P3x = px2; P3y = py2; P0x = px2; P0y = py2; } Int_t P2xL,P2yL,P3xL,P3yL,P0xL,P0yL; if (opt.Contains("<")) { P2xL = px1 + Int_t(rSiz*ct-st*dSiz+0.5); P2yL = py1 - Int_t(rSiz*st+ct*dSiz-0.5); P3xL = px1 + Int_t(rSiz*ct+st*dSiz+0.5); P3yL = py1 - Int_t(rSiz*st-ct*dSiz-0.5); P0xL = px1 + Int_t(rSiz*ct+0.5); P0yL = py1 - Int_t(rSiz*st-0.5); } else { P2xL = px1; P2yL = py1; P3xL = px1; P3yL = py1; P0xL = px1; P0yL = py1; } Double_t XP2 = gPad->AbsPixeltoX(P2x); Double_t YP2 = gPad->AbsPixeltoY(P2y); Double_t XP3 = gPad->AbsPixeltoX(P3x); Double_t YP3 = gPad->AbsPixeltoY(P3y); Double_t XP2L = gPad->AbsPixeltoX(P2xL); Double_t YP2L = gPad->AbsPixeltoY(P2yL); Double_t XP3L = gPad->AbsPixeltoX(P3xL); Double_t YP3L = gPad->AbsPixeltoY(P3yL); // move up if (opt.Contains("|") && !opt.Contains("-")) { XP0 = gPad->AbsPixeltoX(P0x); YP0 = gPad->AbsPixeltoY(P0y); XP0L = gPad->AbsPixeltoX(P0xL); YP0L = gPad->AbsPixeltoY(P0yL); } gPad->PaintLine(XP0,YP0,XP0L,YP0L); //*-*- Convert points to pad reference system Double_t xp1[4],yp1[4],xp2[4],yp2[4]; xp1[0] = XP2; yp1[0] = YP2; xp1[1] = gPad->AbsPixeltoX(px2); yp1[1] = gPad->AbsPixeltoY(py2); xp1[2] = XP3; yp1[2] = YP3; xp1[3] = XP2; yp1[3] = YP2; xp2[0] = XP2L; yp2[0] = YP2L; xp2[1] = gPad->AbsPixeltoX(px1); yp2[1] = gPad->AbsPixeltoY(py1); xp2[2] = XP3L; yp2[2] = YP3L; xp2[3] = XP2L; yp2[3] = YP2L; if (opt.Contains(">")) { if (opt.Contains("|>")) { if (GetFillColor()) { gPad->PaintFillArea(3,xp1,yp1); gPad->PaintPolyLine(4,xp1,yp1); } else { gPad->PaintPolyLine(4,xp1,yp1); } } else { gPad->PaintPolyLine(3,xp1,yp1); } } if (opt.Contains("<")) { if (opt.Contains("<|")) { if (GetFillColor()) { gPad->PaintFillArea(3,xp2,yp2); gPad->PaintPolyLine(4,xp2,yp2); } else { gPad->PaintPolyLine(4,xp2,yp2); } } else { gPad->PaintPolyLine(3,xp2,yp2); } } } //______________________________________________________________________________ void TArrow::SavePrimitive(ofstream &out, Option_t *) { // Save primitive as a C++ statement(s) on output stream out char quote = '"'; if (gROOT->ClassSaved(TArrow::Class())) { out<<" "; } else { out<<" TArrow *"; } out<<"arrow = new TArrow("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2 <<","<<fArrowSize<<","<<quote<<fOption<<quote<<");"<<endl; SaveFillAttributes(out,"arrow",0,1); SaveLineAttributes(out,"arrow",1,1,1); if (fAngle !=60) { out << " arrow->SetAngle(" << GetAngle() << ");" << endl; } out<<" arrow->Draw();"<<endl; }