Jangari
Jangari

Reputation: 868

Gnuplot calculate slope and convert to angle for label alignment

I'm working with a colleague's Gnuplot script for some internal reporting we do, and I'm learning a lot about this awesome tool that I have only dabbled with in the past.

I'm refactoring the code so that I can change global variables that drive the plot, like annual targets and so on. I have managed to get Gnuplot to resize the chart automatically based on the targets. Easy:

set yrange [0:${COURSETARGET}*1.2]
set y2range [0:${ATTENDANCETARGET}*1.2]

What I would like to do now, is automatically adjust the angle of rotation of a label based on the slope of an arrow (e.g., an arrow that plots the gradient of an annual target of courses delivered), but I have no idea how one would do that.

I have an arrow from graph 0, graph 0 to graph 1, second ${TARGET}, so a slope from bottom-left to a point on the right-side of the plot depending on what the target is (fed in from a bash var).

I've manually rotated the label ('Target line') by 16º, which is about right for now, but if my chart area changes, I'll have to figure out the angle by trial-and-error all over again.

So before I start boning up on my trigonometry, I thought I'd ask whether Gnuplot has any built-in way of taking an arrow and returning its gradient, from which I could calculate the angle of rotation needed to align the label to the line.

enter image description here

Upvotes: 2

Views: 1820

Answers (1)

ewcz
ewcz

Reputation: 13087

Perhaps not the most elegant way, but one could for example proceed as:

reset
set terminal pngcairo
set output 'fig.png'
unset key

r = 0.75

xMin = 10.
xMax = 120.

yMin = 0.
yMax = 100.

y2Min = 500.
y2Max = 1000.
y2Ref = 800.

set angles degrees

#explicitly set the ratio of y/y2-axis "display" length to x-axis length
set size ratio r

#set ranges
set xr [xMin:xMax]
set yr [yMin:yMax]
set y2r [y2Min:y2Max]
set y2tics

set arrow from graph 0, graph 0 to graph 1, second y2Ref

#the tangent of the angle of interest is given as dy/dx*r, where
#dy is the fraction of the y2axis (one side of the triangle), dx is
#the fraction of the x-axis spanning the bottom side of the triangle
#(dx=1 in this particular case since the arrow is drawn across the
#entire graph) and r is used in order to convert between the "display
#units on x/y axes". Result is in degrees because of: set angles degrees.
alpha = atan((y2Ref - y2Min)/(y2Max - y2Min) * r)

x0 = (xMin + xMax)/2
y0 = (y2Ref - y2Min)/(xMax - xMin)*(x0 - xMin) + y2Min
set label "some label" at x0, second y0 rotate by alpha offset 0, char 1.*cos(alpha)

plot 1/0 #just to show the plot

this produces

enter image description here

Upvotes: 1

Related Questions