I am producing the figure below using the following gnuplot code. I want to draw a bended arrow from the point labeled l=0 to l=1 with head.
Code
reset session
# Ranges
set xrange [-1:6]
set yrange [-2:1]
# Term options
set terminal postscript eps
set termoption font "Times, 30"
# set termoption
set style line 1 lc rgb 'black' lw 3 lt 1 pt 7 ps 2
# Data points
$DATA<<EOD
0 0
1 0
2 0
3 0
4 0
5 0
6 0
EOD
set output "Anderson_lattice.eps"
# set arrow
set arrow 1 from -0.5, -1.5 to 5.5, -1.5 lc rgb 'black' lw 5
set arrow 2 from -0.5, -1.5 to -0.5, -0.5 lc rgb 'black' lw 5
set label 1 "{/Times-Italic=30 {/Symbol e}_{l}}" at -0.75, -0.3 tc rgb "black"
set arrow 3 from -0.25, -1.0 to 0.25, -1.0 ls 1 nohead
set arrow 5 from 1 - 0.25, -0.75 to 1 + 0.25, -0.75 ls 1 nohead
set arrow 6 from 2 - 0.25, -0.5 to 2 + 0.25, -0.5 ls 1 nohead
set arrow 7 from 3 - 0.25, -1.35 to 3 + 0.25, -1.35 ls 1 nohead
set arrow 8 from 4 - 0.25, -1.0 to 4 + 0.25, -1 ls 1 nohead
set arrow 9 from 5 - 0.25, -0.85 to 4 + 0.25, -0.85 ls 1 nohead
set arrow 10 from 6 - 0.25, -1.25 to 6 + 0.25, -1.25 ls 1 nohead
set label 2 "{/Times-Italic=30 sites}" at 5.5, -1.65 tc 'black'
set label 3 "{/Times-Italic=30 l=0}" at 2.7, -0.25 tc 'black'
set label 4 "{/Times-Italic=30 l=1}" at 1 + 2.7, -0.25 tc 'black'
unset xtics; unset ytics; unset border
plot $DATA using 1:2 with p ls 1 notitle
unset output
Result
How do I do that?
I'm not aware that gnuplot offers a feature for directly drawing a bent arrow.
Edit:
(I removed my initial approach since it has no advantage over using Cubic Bézier. And added some more flexibility to the second approach.)
I completely agree with #GRSousaJr that Cubic Bézier curves give much more flexibility in drawing bent arrows. At the same time you can also draw straight arrows.
Based on #GRSousaJr's approach, my suggestions would be the following:
instead of entering absolute values for the control points, I would prefer relative or absolute angles and relative distances. This has the advantage that you don't have to care about absolute numbers, especially when two arrows should have the same proportions but have different absolute start/endpoints.
All parameters for the arrows are in the datablock $myArrows.
Some explanations:
for the Cubic Bézier curves 4 points are used: p0,p1,p2,p3, where p0 and p3 are the start and end points, respectively. p1 and p2 are points which control the curvature. p0x, p0y, ... p3x, p3y are the x and y components, respectively.
in contrast to #GRSousaJr's solution the control points p1 and p2 are not given in absolute values but calculated from p0 and p3 and the angles a0 and a3 and the radii r0 and r3.
the angles of the arrow at the points p0 and p3 can be given absolute or relative to the direction of p0 to p3. The parameter e tells which end has relative angle and which end absolute angle. 0=angles at both ends relative, 1=start angle relative, end angle absolute, 2=start angle absolute, end angle relative, 3=angles at both ends absolute. For the relative angle you first need to calculate the angle between p0 and p3 (function AngleP0P3())
the distance of the control points p1 and p2 from the points p0 and p3 are given in relative values r0 and r3 with respect to the distance between p0 and p3. That's why there is the function Length(). 0.5 is a good value to start with.
note that the functions AngleP0P3(n) and Length(n) actually do not depend on n. That is just to shorten the code. These functions use the parameters p1x, ..., p3y, and when calling AngleP0P3(0) the function will take the current values of p1x, ..., p3y. This is shorter than e.g. Angle(p0x,p0y,p3x,p3y).
the function ArrowInit(i) is to collect or initialize the values for p1x, ..., p3y from the ith row of datablock $myArrows.
the line of the arrows are simply plotted in a for loop as parametric function in t with the range t[0:1]. For every i in the plot command ArrowInit(i) is called to get the corresponding parameters from the datablock $myArrows.
The angle of the arrow in point p3 is in the direction from p2 to p3, i.e. the tangent of the Bézier curve in point p3. However you don't want the line, but just the arrow. So far, I don't have a better approach than plotting a short vector from 99% of the arrow path to 100% of the arrow path.
Some comments on usage:
in order to "see" the correct angles you specify in $myArrows, your plot has to have the same aspect ratio as your x and y ranges. In the below examples it is x[0:20] and y[0:10], hence, set the aspect ratio of the graph to 0.5, i.e. at the beginning set size 0.5.
the direction of the arrow head is the tangent in point p3. If you have a strong curvature at p3, the arrow head might look "bad", although the arrow head is in the correct angle. In such cases, increase the length r3 a little.
You can also draw straight arrows, see Arrow1. Just set a0=0,a3=0 and e=0.
Tested with gnuplot 5.2.8
Code:
### workaround for bent arrows
reset session
set size ratio 0.5
# p0x p0y a0 r0 p3x p3y a3 r3 e color
$myArrows <<EOD
1 1.00 1.00 0 0.5 3.00 3.00 0 0.5 0 0xff0000
2 3.00 1.00 0 0.5 5.00 3.00 0 0.5 1 0x00c000
3 5.00 1.00 0 0.5 7.00 3.00 0 0.5 2 0x0000ff
4 7.00 1.00 0 0.5 9.00 3.00 0 0.5 3 0xff00ff
5 1.00 4.00 0 0.5 3.00 6.00 90 0.5 0 0xff0000
6 3.00 4.00 0 0.5 5.00 6.00 90 0.5 1 0x00c000
7 5.00 4.00 0 0.5 7.00 6.00 90 0.5 2 0x0000ff
8 7.00 4.00 0 0.5 9.00 6.00 90 0.5 3 0xff00ff
9 1.00 7.00 90 0.5 3.00 9.00 0 0.5 0 0xff0000
10 3.00 7.00 90 0.5 5.00 9.00 0 0.5 1 0x00c000
11 5.00 7.00 90 0.5 7.00 9.00 0 0.5 2 0x0000ff
12 7.00 7.00 90 0.5 9.00 9.00 0 0.5 3 0xff00ff
13 11.00 1.00 45 0.5 13.00 3.00 -45 0.5 0 0xff0000
14 13.00 1.00 45 0.5 15.00 3.00 -45 0.5 1 0x00c000
15 15.00 1.00 45 0.5 17.00 3.00 -45 0.5 2 0x0000ff
16 17.00 1.00 45 0.5 19.00 3.00 -45 0.5 3 0xff00ff
17 11.00 4.00 -45 0.5 13.00 6.00 -45 0.5 0 0xff0000
18 13.00 4.00 -45 0.5 15.00 6.00 -45 0.5 1 0x00c000
19 15.00 4.00 -45 0.5 17.00 6.00 -45 0.5 2 0x0000ff
20 17.00 4.00 -45 0.5 19.00 6.00 -45 0.5 3 0xff00ff
21 11.00 7.00 0 0.5 15.00 9.00 90 0.5 1 0x00c000
22 15.00 7.00 0 0.5 19.00 9.00 0 0.5 1 0x00c000
EOD
set angle degrees
# Angle between p0 and p3 (range: -90° <= angle < 270°), NaN if dx=dy=0
AngleP0P3(n) = (dy=p3y-p0y,dx=p3x-p0x)==0 ? (dy==0 ? NaN : sgn(dy)*90) : \
(dx<0 ? 180 : 0) + atan(dy/dx)
# Parameter e: determines which ends have relative or absolute angles
# 0: both ends relative
# 1: start relative, end absolute,
# 2: start absolute, end relative
# 3: both ends absolute
AngleAbs(i) = int(word($myArrows[i],10)) # to set all arrows equal, use: AngleAbs(i) = 0,1,2, or 3
Angle(i,p) = word($myArrows[i],p) + \
((p==4 && AngleAbs(i)&2) || (p==8 && AngleAbs(i)&1) ? 0 : AngleP0P3(0))
Length(n) = sqrt((p3x-p0x)**2 + (p3y-p0y)**2)
Color(i) = word($myArrows[i],11)
ArrowInit(i) = (p0x=word($myArrows[i],2),p0y=word($myArrows[i],3), \
p3x=word($myArrows[i],6),p3y=word($myArrows[i],7), \
p1x=p0x+Length(0)*word($myArrows[i],5)*cos(Angle(i,4)), \
p1y=p0y+Length(0)*word($myArrows[i],5)*sin(Angle(i,4)), \
p2x=p3x-Length(0)*word($myArrows[i],9)*cos(Angle(i,8)), \
p2y=p3y-Length(0)*word($myArrows[i],9)*sin(Angle(i,8)))
# Cubic Bézier curves function with t[0:1] as parameter
# p0: start point, p1: 1st control point, p2: 2nd control point, p3: endpoint
px(t) = (-p0x + 3*p1x - 3*p2x + p3x)*t**3 + (3*p0x - 6*p1x + 3*p2x)*t**2 + (-3*p0x + 3*p1x)*t + p0x
py(t) = (-p0y + 3*p1y - 3*p2y + p3y)*t**3 + (3*p0y - 6*p1y + 3*p2y)*t**2 + (-3*p0y + 3*p1y)*t + p0y
# set linestyles and arrowstyles
do for [i=1:|$myArrows|] {
set style line i lw 2 lc rgb Color(i)
set style arrow i head size 0.20,15,45 fixed filled ls i
}
set key out noautotitle below
set xrange [0:20]
set xtics 1
set format x ""
set grid xtics ls -1 lc rgb "gray"
set yrange [0:10]
set ytics 1
set format y ""
set grid ytics ls -1 lc rgb "gray"
plot for [i=1:|$myArrows|] [0:1] '+' u (ArrowInit(i),px($1)):(py($1)) w l ls i, \
for [i=1:|$myArrows|] [0:1] '+' u (ArrowInit(i),px(0.99)):(py(0.99)): \
(px(1)-px(0.99)):(py(1)-py(0.99)) every ::0::0 w vec as i, \
$myArrows u 2:3:1 w labels offset 0,-0.7, \
keyentry w l ls 1 ti "both ends relative angles", \
keyentry w l ls 2 ti "start relative, end absolute angle", \
keyentry w l ls 3 ti "start absolute, end relative angle", \
keyentry w l ls 4 ti "both ends absolute angles"
### end of code
exit
Result:
I created (at least in my mind) an "enhanced" version of #theozh's answer, which allows somewhat control over arrow form.
The idea is to use a Bézier curve to draw the bent arrow. The head is drawn as on #theozh's answer, i.e., using vectors. The initial (xi,yi) and final points (xy,yf), as well the control points (xc1,yc1 and xc2,yc2), are passed to a function using call command. The function creates a datafile using theid, like a tag on standard arrow, defined by user, and associates a variavel (e.g. BentArrow_id) name to such datafile. Each created datafile contain:
the control points
the datapoints to create the arrow, and
the datapoints do create head
as three indexable datablocks (0, 1 and 2, respectively), like this:
# Block index 0 (control points)
1.000000e+00 -1.250000e+00
1.250000e+00 0.000000e+00
2.800000e+00 -5.000000e-01
3.000000e+00 -7.500000e-01
# Block index 1 (arrow)
1.000000e+00 -1.250000e+00
1.016539e+00 -1.177084e+00
1.036070e+00 -1.108272e+00
1.058468e+00 -1.043468e+00
... ...
2.927437e+00 -6.862240e-01
2.949992e+00 -7.027320e-01
2.969690e+00 -7.189280e-01
2.986401e+00 -7.347160e-01
3.000000e+00 -7.500000e-01
# Block index 2 (head)
2.986401e+00 -7.347160e-01 1.359880e-02 -1.528400e-02
3.000000e+00 -7.500000e-01 0.000000e+00 0.000000e+00
To draw the bent arrow, the plot command must be composed by three parts:
plot \
...
BentArrow_id i 0 u 1:2 w lp ...,\
BentArrow_id i 1 u 1:2 w lines ...,\
BentArrow_id i 2 u 1:2:3:4 w vectors ...,\
...
Each part corresponds to a piece of arrow (the control points, the arrow itself, and the head, respectively).
To better show the script (called BentArrow.fct) working, consider the example.
reset
set terminal wxt size 500,500
set size ratio -1
set grid ls -1 lc "gray"
unset key
set tics out nomirror
set xrange [-0.25:9.25]
set yrange [-0.25:9.25]
set style arrow 1 head size 0.25,15,45 fixed filled lc "red"
BentArrow(id,xi,yi,x1,y1,x2,y2,xf,yf) = \
sprintf("call 'BentArrow.fct' '%g' '%f' '%f' '%f' '%f' '%f' '%f' '%f' '%f'", \
id, xi,yi, x1,y1, x2,y2, xf,yf )
# id, xi,yi , xc1,yc1, xc2,yc2, xf,yf
eval BentArrow(1, 1.0,1.0, 2.0,2.0, 3.0,0.0, 4.0,1.0)
eval BentArrow(2, 5.0,1.0, 6.0,0.0, 7.0,2.0, 8.0,1.0)
eval BentArrow(3, 1.0,4.0, 2.0,3.0, 3.0,3.0, 4.0,4.0)
eval BentArrow(4, 5.0,4.0, 6.0,5.0, 7.0,5.0, 8.0,4.0)
eval BentArrow(5, 1.0,7.0, 5.0,5.0, 0.0,5.0, 4.0,7.0)
eval BentArrow(6, 5.0,7.0, 5.0,9.0, 6.0,7.0, 8.0,7.0)
CtrlPoints = "w lp ls -1 pt 6 ps 1 pi -1"
StyleArrow = "w lines lc 'red' lw 2"
StyleHead = "w vec as 1"
plot \
BentArrow_1 i 0 u 1:2 #CtrlPoints ,\
BentArrow_1 i 1 u 1:2 #StyleArrow ,\
BentArrow_1 i 2 u 1:2:3:4 #StyleHead ,\
BentArrow_2 i 0 u 1:2 #CtrlPoints ,\
BentArrow_2 i 1 u 1:2 #StyleArrow ,\
BentArrow_2 i 2 u 1:2:3:4 #StyleHead ,\
BentArrow_3 i 0 u 1:2 #CtrlPoints ,\
BentArrow_3 i 1 u 1:2 #StyleArrow ,\
BentArrow_3 i 2 u 1:2:3:4 #StyleHead ,\
BentArrow_4 i 0 u 1:2 #CtrlPoints ,\
BentArrow_4 i 1 u 1:2 #StyleArrow ,\
BentArrow_4 i 2 u 1:2:3:4 #StyleHead ,\
BentArrow_5 i 0 u 1:2 #CtrlPoints ,\
BentArrow_5 i 1 u 1:2 #StyleArrow ,\
BentArrow_5 i 2 u 1:2:3:4 #StyleHead ,\
BentArrow_6 i 0 u 1:2 #CtrlPoints ,\
BentArrow_6 i 1 u 1:2 #StyleArrow ,\
BentArrow_6 i 2 u 1:2:3:4 #StyleHead
The results
Applying the script to your example, the result look like this
Of course the control points are useful just to defining each arrow.
The variable showCtrlPoints = "False" (default "True") is defined to allows hide the control points on final plot.
The script to last example is:
reset
# The data
$levels<<EOD
1 0.5 -1.25
2 0.5 -1.00
3 0.5 -0.75
4 0.5 -0.50
5 0.5 -0.25
6 0.5 -1.25
7 0.5 -1.00
8 0.5 -0.75
9 0.5 -0.50
10 0.5 -0.25
EOD
# Cubic Bézier function
BentArrow(id,xi,yi,x1,y1,x2,y2,xf,yf) = \
sprintf("call 'BentArrow.fct' '%g' '%f' '%f' '%f' '%f' '%f' '%f' '%f' '%f'", \
id, xi,yi, x1,y1, x2,y2, xf,yf )
# Arrow styles
set style arrow 1 head size 0.2,15,45 fixed filled lc "red"
set style arrow 2 head size 0.2,15,45 fixed filled lc "web-green"
set style arrow 3 head size 0.2,15,45 fixed filled lc "blue"
# To levels
set errorbars small
unset key
# Options to drawing the bent arrows
showCtrlPoints = "False"
ArrowPoints = 50
# Calling the function
eval BentArrow(1, 1.00,-1.25, 1.25, 0.00, 2.80,-0.50, 3.00,-0.75)
eval BentArrow(2, 8.00, 0.50, 8.00, 0.00, 5.00, 0.25, 5.00,-0.25)
eval BentArrow(3, 1.00, 0.50, 2.00,-0.25, 9.00, 0.50, 10.0,-0.25)
# Macros
Points = "w p ls -1 pt 7 ps 2"
Levels = "w xerrorbars ls -1 lw 2"
CtrlPoints = "w lp ls -1 pt 6 ps 1 pi -1"
StyleArrow = "w lines lw 2"
StyleHead = "w vectors"
# Allow to toggle between show/hide the control points
CP(n) = showCtrlPoints eq "True" ? n : NaN
plot \
$levels u 1:2 #Points ,\
"" u 1:3:(0.35) #Levels ,\
BentArrow_1 i 0 u 1:(CP($2)) #CtrlPoints ,\
BentArrow_1 i 1 u 1:2 #StyleArrow lc "red" ,\
BentArrow_1 i 2 u 1:2:3:4 #StyleHead as 1 ,\
BentArrow_2 i 0 u 1:(CP($2)) #CtrlPoints ,\
BentArrow_2 i 1 u 1:2 #StyleArrow lc "web-green" ,\
BentArrow_2 i 2 u 1:2:3:4 #StyleHead as 2 ,\
BentArrow_3 i 0 u 1:(CP($2)) #CtrlPoints ,\
BentArrow_3 i 1 u 1:2 #StyleArrow lc "blue" ,\
BentArrow_3 i 2 u 1:2:3:4 #StyleHead as 3
The BentArrow.fct file contain:
# Implements a bent arrow using Cubic Bézier curves (https://en.wikipedia.org/wiki/Bézier_curve)
#
# Usage: call 'BentArrow.fct' tag xi yi yc1 yc1 xc2 yc2 xf yf
# where
# xi,yi = start point
# xc1,yc1 = control point #1
# xc2,yc2 = control point #2
# xf,yf = final point
#
# The algorithm creates
# 1) a variable named BentArrow_id with 'id' as a integer number,
# defined by user like a standart arrow, and
# 2) a datafile (e.g BentArrow_id.bentarrow) containing
# i) the control points,
# ii) the datapoints to create the curve, and
# iii) the datapoints do ceate head
# as indexable datablocks (0, 1 and 2, respectively).
# The number of datapoint (samples) used on bent arrow construction
# are defined by 'ArrowPoints' (default 50)
# Receiving the arguments from 'call' command
tag = int(ARG1)
x_i = real(ARG2)
y_i = real(ARG3)
x_1 = real(ARG4)
y_1 = real(ARG5)
x_2 = real(ARG6)
y_2 = real(ARG7)
x_f = real(ARG8)
y_f = real(ARG9)
# Defining the variable to filename, based on 'tag', and creating the datafile
eval sprintf( "%s_%g = %s", 'BentArrow', tag, sprintf("'BentArrow_%g.bentarrow'", tag) )
# Checking if 'ArrowPoints' is defined
if ( !exists("ArrowPoints") ) {
ArrowPoints = 50
}
# Quadratic Bézier function
DrawArrow(t,p0,p1,p2,p3) = (1-t)**3*p0 + 3*(1-t)**2*t*p1 + 3*(1-t)*t**2*p2 + t**3*p3 # 0 <= t <= 1
# Creating the datafile containing the datapoints to bent arrow
set print sprintf('BentArrow_%g.bentarrow', tag)
# ----- ControlPoints -----------------------
print "# Block index 0 (control points)"
print sprintf("% e\t% e", x_i, y_i)
print sprintf("% e\t% e", x_1, y_1)
print ""
print sprintf("% e\t% e", x_2, y_2)
print sprintf("% e\t% e", x_f, y_f)
print ""
print ""
# ----- ArrowData -----------------------
print "# Block index 1 (arrow)"
do for [i=0:int(ArrowPoints):1] {
t = i/real(ArrowPoints)
print sprintf("% e\t% e", DrawArrow(t,x_i,x_1,x_2,x_f), DrawArrow(t,y_i,y_1,y_2,y_f))
}
print ""
print ""
# ----- ArrowHead -----------------------
print "# Block index 2 (head)"
do for [i=int(ArrowPoints)-1:int(ArrowPoints):1] {
t = i/real(ArrowPoints)
x_head = x_f - DrawArrow(t,x_i,x_1,x_2,x_f)
y_head = y_f - DrawArrow(t,y_i,y_1,y_2,y_f)
print sprintf("% e\t% e\t% e\t% e", DrawArrow(t,x_i,x_1,x_2,x_f), DrawArrow(t,y_i,y_1,y_2,y_f), x_head, y_head)
}
unset print
Improvements will be well received!
Can gnuplot calculate the distance between two lines or maybe two points?
I'm having a plot where two (main) lines are plotted. For the moment let's assume that the first line is always above the second one. Is there a way to calculate the distance from line 2 to line 1 at a given x-value?
here is a picture of what my plot looks like and which distance I want to calculate:
The vertical lines are just for style and have nothing to do with the actual plot, their data is stored in test.dat and test2.dat.
My data-files of the lines look like this:
line1
0 118.1
2.754 117.77
4.054 117.64
6.131 116.17
7.7 116.04
8.391 115.36
10.535 115.25
11.433 116.03
12.591 116.22
19.519 118.59
line2
19.4 118.51
15.2 116.56
10.9 115.94
10.35 114.93
9.05 114.92
8.3 115.9
5.9 116.19
4.2 116.62
2.2 117.66
-0.3 118.06
My plotting-code looks like this:
set term wxt enhanced
cd 'working directory'
unset key
set size 0.9,0.9
set origin 0.1,0.1
set title 'TITLE'
unset border
set label 21 " rotate by 45" at -3.0,0.0 rotate by 45 point ps 2
set xrange [0:19.519]
set yrange [110:119]
set xtics nomirror(0, 2.745, 4.054, 6.131, 7.7, 8.391, 10.535, 11.433, 12.591, 19.519) rotate by 90 offset 0,-0.1 right
set ytics " ", 30000
plot "line1.dat" using ($1):($2):2 with labels offset 1, 1.8 rotate by 90, "line1.dat" using 1:2 with lines lt 1 lw 1 lc rgb '#000000', +112 lt 1 lw 1 lc rgb '#000000' , 'test.dat' with lines lt 1 lw 1 lc rgb '#000000', +110 lt 1 lw 1 lc rgb '#000000', 'line2.dat' with lines lt 0.5 lw 1 lc rgb '#000000', 'test2.dat' with lines lt 0.5 lw 1 lc rgb '#000000'
You can measure the distance manually. Move the mouse to the first point and type 'r'. Then as you move the mouse around, the x and y offsets, distance and angle are displayed. Type '5' to draw a line segment and to toggle between degrees and tangent display. Zooming in beforehand increases accuracy.
By the way, typing 'h' in the plot window will display a list of keybindings to the console.
An answer to this "rather old" question still might be of interest to OP, if not, maybe to others.
Yes, you can calculate and plot the difference of two lines. It requires some linear interpolation. Simply assign the desired x-value to the variable myX.
Data:
SO17717287_1.dat
0 118.1
2.754 117.77
4.054 117.64
6.131 116.17
7.7 116.04
8.391 115.36
10.535 115.25
11.433 116.03
12.591 116.22
19.519 118.59
SO17717287_2.dat
19.4 118.51
15.2 116.56
10.9 115.94
10.35 114.93
9.05 114.92
8.3 115.9
5.9 116.19
4.2 116.62
2.2 117.66
-0.3 118.06
Script: (works for gnuplot>=4.6.0)
### calculating and plotting a difference between two curves
reset
FILE1 = "SO17717287_1.dat"
FILE2 = "SO17717287_2.dat"
set border 1
unset key
set origin 0.05,0.05
set size 0.9,0.8
set xrange [0:19.519]
set xtics nomirror rotate by 90 offset 0,-0.1 right
set yrange [110:119]
unset ytics
myX = 15.2
getYa(xi) = (x0=x1, x1=$1, y0=y1, y1=$2, x1==xi ? ya=y1 : (sgn(x0-xi)!=sgn(x1-xi)) ? ya=(y1-y0)/(x1-x0)*(xi-x0)+y0 : NaN)
getYb(xi) = (x0=x1, x1=$1, y0=y1, y1=$2, x1==xi ? yb=y1 : (sgn(x0-xi)!=sgn(x1-xi)) ? yb=(y1-y0)/(x1-x0)*(xi-x0)+y0 : NaN)
set samples 2 # set to minimal possible value for plotting '+'
plot x1=y1=NaN FILE1 u 1:2:2:xtic(1) w labels offset 0,0.5 left rotate by 90, \
'' u 1:(getYa(myX),$2) w l lc rgb 'black', \
'' u 1:2:(0):(110-$2) w vec lt 0 nohead, \
+112 w l lc rgb 'black', \
x1=y1=NaN FILE2 u 1:(getYb(myX),$2) w l lt 0 lc rgb 'black', \
'+' u (myX):(ya):(0):(yb-ya) w vec heads lc rgb "red", \
'+' u (myX):(ya):(sprintf("%.3f",yb-ya)):xtic(sprintf("%g",myX)) w labels tc rgb "red" offset 0,1, \
'+' u (myX):(ya):(0):(110-ya) w vec nohead lt 0 lc rgb "red"
### end of script
Result: (created with gnuplot 4.6.0)