How to add braces to a graph?

后端 未结 5 757
北荒
北荒 2020-12-01 12:23

I want to make the following graph in R:

\"enter

How can I plot those horizont

5条回答
  •  鱼传尺愫
    2020-12-01 13:18

    With rotation option / And every lines() aka par() option you want

    I first mixed up Sharons answer and with another answer i found to a new function with more possibilities. But then i added the "shape" package to the game and now u can put curlybraces in every angle you want to. You don't have to use the package, but if u have 2 points that are not on a horizontal or vertical line it will be very ugly, without shape==T.

    CurlyBraces <- function(
      # function to draw curly braces
      x=NA, y=NA,     # Option 1 (Midpoint) if you enter only x, y the position points the middle of the braces
      x1=NA, y1=NA,   # Option 2 (Point to Point) if you additionaly enter x1, y1 then x,y become one
                      #     end of the brace and x1,y1 is the other end
      range=NA,       # (Option 1 only) range is the length of the brace 
      ang=0,          # (Option 1 only, only with shape==T) ang will set the angle for rotation
      depth = 1,      # depth controls width of the shape
      shape=T,        # use of package "shape" necessary for angles other than 0 and 90
      pos=1,          # (only if shape==F) position: 1 vertical, 2 horizontal
      direction=1,    # (only if shape==F)  direction: 1 left/down, 2 right/up
      opt.lines="lty=1,lwd=2,col='red'")   # All posible Options for lines from par (exept: xpd)
                      # enter as 1 character string or as character vector
      {
    
     if(shape==F){
      # only x & y are given so range is for length
      if(is.na(x1) | is.na(y1)){
        a_sequence = rep(x,100)
        b_sequence = seq(y-range/2,y+range/2,length=100)
        if (pos == 2){
          a_sequence = rep(y,100)
          b_sequence = seq(x-range/2,x+range/2,length=100)
        }
      }
      # 2 pairs of coordinates are given range is not needed
      if(!is.na(x1) & !is.na(y1)){
        if (pos == 1){
          a_sequence = seq(x,x1,length=100)
          b_sequence = seq(y,y1,length=100)  
        }
        if (pos == 2){
          b_sequence = seq(x,x1,length=100)
          a_sequence = seq(y,y1,length=100)      
        }
      }  
      # direction
      if(direction==1)
        a_sequence = a_sequence+curve
      if(direction==2)
        a_sequence = a_sequence-curve
    
      # pos
      if(pos==1)
        lines(a_sequence,b_sequence, lwd=lwd, col=col, lty=lty,  xpd=NA) # vertical
      if(pos==2)
        lines(b_sequence,a_sequence, lwd=lwd, col=col, lty=lty, xpd=NA) # horizontal
    }
     if(shape==T) {
      # Enable input of variables of length 2 or 4
      if(!("shape" %in% installed.packages())) install.packages("shape")
      library("shape")
    
      if(length(x)==2) {
        helpx <- x
        x<-helpx[1]
        y<-helpx[2]}
      if(length(x)==4) {
        helpx <- x
        x =helpx[1]
        y =helpx[2]
        x1=helpx[3]
        y1=helpx[4]
      }
    
      # Check input
      if((is.na(x) | is.na(y) )) stop("Set x & y")
      if((!is.na(x1) & is.na(y1)) | ((is.na(x1) & !is.na(y1))))stop("Set x1 & y1")
      if((is.na(x1) & is.na(y1)) & is.na(range)) stop("Set range > 0")
    
      a=c(1,2,3,48,50)    # set flexion point for spline
      b=c(0,.2,.28,.7,.8) # set depth for spline flexion point
    
      curve = spline(a, b, n = 50, method = "natural")$y * depth
      curve = c(curve,rev(curve))
    
      if(!is.na(x1) & !is.na(y1)){
        ang=atan2(y1-y,x1-x)*180/pi-90
        range = sqrt(sum((c(x,y) - c(x1,y1)) ^ 2))
        x = (x + x1)/2
        y = (y + y1)/2
      }
    
      a_sequence = rep(x,100)+curve
      b_sequence = seq(y-range/2,y+range/2,length=100)
    
      eval(parse(text=paste("lines(rotatexy(cbind(a_sequence,b_sequence),mid=c(x,y), angle =ang ),",
                            paste(opt.lines, collapse = ", ")
                            ,", xpd=NA)")))
     }
    }
    
    
    # # Some Examples with shape==T
    # plot(c(),c(),ylim=c(-10,10),xlim=c(-10,10))
    # grid()
    # 
    # CurlyBraces(4,-2,4,2, opt.lines = "lty=1,col='blue' ,lwd=2")
    # CurlyBraces(4,2,2,4, opt.lines = "col=2, lty=1 ,lwd=0.5")
    # points(3,3)
    # segments(4,2,2,4,lty =  2)
    # segments(3,3,4,4,lty =  2)
    # segments(4,2,5,3,lty =  2)
    # segments(2,4,3,5,lty =  2)
    # CurlyBraces(2,4,4,2, opt.lines = "col=2, lty=2 ,lwd=0.5") # Reverse entry of datapoints changes direction of brace
    # 
    # CurlyBraces(2,4,-2,4, opt.lines = "col=3 , lty=1 ,lwd=0.5")
    # CurlyBraces(-2,4,-4,2, opt.lines = "col=4 , lty=1 ,lwd=0.5")
    # CurlyBraces(-4,2,-4,-2, opt.lines = "col=5 , lty=1 ,lwd=0.5")
    # CurlyBraces(-4,-2,-2,-4, opt.lines = "col=6 , lty=1 ,lwd=0.5")
    # CurlyBraces(-2,-4,2,-4, opt.lines = "col=7 , lty=1 ,lwd=0.5")
    # CurlyBraces(2,-4,4,-2, opt.lines = "col=8 , lty=1 ,lwd=0.5")
    # 
    # CurlyBraces( 7.5, 0, ang= 0 , range=5, opt.lines = "col=1 , lty=1 ,lwd=2 " )
    # CurlyBraces( 5, 5, ang= 45 , range=5, opt.lines = "col=2 , lty=1 ,lwd=2 " )
    # CurlyBraces( 0, 7.5, ang= 90 , range=5, opt.lines = "col=3, lty=1 ,lwd=2"  )
    # CurlyBraces( -5, 5, ang= 135 , range=5, opt.lines = "col='blue' , lty=1 ,lwd=2 " )
    # CurlyBraces( -7.5, 0, ang= 180 , range=5, opt.lines = "col=5 , lty=1 ,lwd=2 " )
    # CurlyBraces( -5, -5, ang= 225 , range=5, opt.lines = "col=6 , lty=1 ,lwd=2"  )
    # CurlyBraces( 0, -7.5, ang= 270 , range=5, opt.lines = "col=7, lty=1 ,lwd=2"  )
    # CurlyBraces( 5, -5, ang= 315 , range=5, opt.lines = "col=8 , lty=1 ,lwd=2"  )
    # points(5,5)
    # segments(5,5,6,6,lty =  2)
    # segments(7,3,3,7,lty =  2)
    # 
    # # Or anywhere you klick
    # locator(1) -> where  # klick 1 positions in the plot with your Mouse
    # CurlyBraces( where$x[1], where$y[1], range=3, ang=45 , opt.lines = "col='blue' , depth=1, lty=1 ,lwd=2"  )
    # locator(2) -> where  # klick 2 positions in the plot with your Mouse
    # CurlyBraces( where$x[1], where$y[1], where$x[2], where$y[2],  opt.lines = "col='blue' , depth=2, lty=1 ,lwd=2"  )
    # 
    # # Some Examples with shape == F
    # plot(c(),c(),ylim=c(-10,10),xlim=c(-10,10))
    # grid()
    # 
    # CurlyBraces( 5, 0, shape=F, range= 10, pos = 1, direction = 1 , depth=5 ,opt.lines = " col='red' , lty=1 ,lwd=2"  )
    # CurlyBraces(-5, 0, shape=F,  range= 5,  pos = 1, direction = 2 , opt.lines = "col='red' , lty=2 ,lwd=0.5")
    # CurlyBraces( 1, 4, shape=F,  range= 6,  pos = 2, direction = 1 , opt.lines = "col='red' , lty=3 ,lwd=1.5")
    # CurlyBraces(-1,-3, shape=F,  range= 5,  pos = 2, direction = 2 , opt.lines = "col='red' , lty=4 ,lwd=2"  )
    # 
    # 
    # CurlyBraces( 4, 4, 4,-4, shape=F, pos=1, direction = 1 , opt.lines = "col='blue' , lty=1 ,lwd=2" )
    # CurlyBraces(-4, 4,-4,-4, shape=F, pos=1, direction = 2 , opt.lines = "col='blue' , lty=2 ,lwd=0.5")
    # CurlyBraces(-2, 5, 2, 5, shape=F, pos=2, direction = 1 , opt.lines = "col='blue' , lty=3 ,lwd=1.5")
    # CurlyBraces(-2,-1, 4,-1, shape=F, pos=2, direction = 2 , opt.lines = "col='blue' , lty=4 ,lwd=2"  )
    # 
    # # Or anywhere you klick
    # locator(1) -> where  # klick 1 positions in the plot with your Mouse
    # CurlyBraces( where$x[1], where$y[1], range=3, shape=F, pos=2, direction = 2 , opt.lines = "col='blue' , depth=1, lty=1 ,lwd=2"  )
    # locator(2) -> where  # klick 2 positions in the plot with your Mouse
    # CurlyBraces( where$x[1], where$y[1], where$x[2], where$y[2], shape=F, pos=2, direction = 2 , opt.lines = "col='blue' , depth=0.2, lty=1 ,lwd=2"  )
    # 
    # # Some Examples with shape==T
    # plot(c(),c(),ylim=c(-100,100),xlim=c(-1,1))
    # grid()
    # 
    # CurlyBraces(.4,-20,.4,20, depth=.1, opt.lines = "col=1 , lty=1 ,lwd=0.5")
    # CurlyBraces(.4,20,.2,40, depth=.1, opt.lines = "col=2, lty=1 ,lwd=0.5")
    

提交回复
热议问题