You could split the line into two segments and draw the arrow only for the one that ends at the midpoint. Adding show.legend=FALSE to the arrow-drawing call to geom_segment removes the arrow from the legend:
b +
geom_curve(aes(x = x1, y = y1, xend = x2, yend = y2, colour = "curve"),
data = df) +
geom_segment(aes(x = (x1+x2)/2, y = (y1+y2)/2, xend = x2, yend = y2, colour = "segment"),
data = df) +
geom_segment(aes(x = x1, y = y1, xend = (x1+x2)/2 , yend = (y1+y2)/2, colour = "segment"),
arrow = arrow(),
data = df, show.legend=FALSE)