Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Placing arrow heads to the middle of the lines in R

Tags:

plot

r

arrows

I have a plot where I draw arrows from points to points. I would like to put this arrow heads not to the end of the line, but to middle. Is there a simple way to do it other than placing extra arrows with half length of the according line? My code is this:

plot(x, y, xlim=range(x), ylim=range(y), xlab="x", ylab="y", pch=16,
     main="Filled Plane")

for(i in 1:20){
  arrows(x[i], y[i], x[i+1], y[i+1], length = 0.25, angle = 30, col = i)
}
like image 421
antetokounmpo Avatar asked Mar 04 '23 21:03

antetokounmpo


2 Answers

Make a custom function myArrow() and add one new argument cut to control the proportion of the arrows

myArrow <- function(x0, y0, x1, y1, cut = 1, ...){
  x.new <- (1 - cut) * x0 + cut * x1
  y.new <- (1 - cut) * y0 + cut * y1
  # segments(x0, y0, x1, y1, ...)
  arrows(x0, y0, x.new, y.new, ...)
}

Note1 : The computation of x.new and y.new in this custom function uses a simple mathematical concept, i.e. the Section Formula. The value of cut must be between 0 to 1.

Note2 : The use of this function is equivalent to that of the original functionarrows() other than that it has one more new argument cut.

Note3 : If you want complete lines behind the arrows, just remove the hash(#) in the function.


Plot and try different cut value. For example, I use cut = 0.7. (If you want the arrowheads to the middle, use cut = 0.5.)

# Toy Data
x <- seq(1, 5.5, by = 0.5)
y <- rep(c(1, 5), 5)

plot(x, y, pch = 16)
for(i in 1:9){
  myArrow(x[i], y[i], x[i+1], y[i+1], cut = 0.7, col = i, lwd = 2)
}

enter image description here

like image 185
Darren Tsai Avatar answered Mar 10 '23 21:03

Darren Tsai


Since you do not provide your x and y, I made up some data. There is no need for the loop. arrows will handle a vector of coordinates. One way is to draw a full-length arrow with no arrowhead and another that just goes halfway but has the arrowhead.

## Some bogus data
set.seed(123)
x = runif(4)
y = runif(4)

## Compute the midpoints
midx = diff(x)/2 + x[-length(x)]
midy = diff(y)/2 + y[-length(y)]

## Draw it
plot(x,y,xlim=range(x), ylim=range(y), xlab="x", ylab="y", 
    main="Filled Plane",pch=16)
arrows(x[-length(x)], y[-length(y)],x[-1],y[-1],
    angle = 0, col = 1:3)
arrows(x[-length(x)], y[-length(y)],midx,midy,
    length = 0.25, angle = 30, col = 1:3)

Arrowhead in center

like image 38
G5W Avatar answered Mar 10 '23 21:03

G5W