1

I'm trying to determine angle in degrees of a straight line of two points, I came across many solutions online but none of them worked for me, consider this piece of code

import matplotlib.pyplot as plt
data = np.array([7405.,7447.4,7433.99,7410.,7443.15,7429.4,7590.03,7550.,7566.32,7619.62,7549.71,7551.8,7530,7522.99,7499.75,7453.99,7542.16,7564.,7552.77,7552])
y = [7606.672474,7570.240928]
plt.plot(data)
plt.plot([6,17], y)
plt.show()

enter image description here

The target line is y it should be around -5 degrees just by looking at it. It seems like most online solutions suggest that we can find the angle by doing

degree = np.math.atan2(y[-1] - y[0], x[-1] - x[0])
degree = np.degrees(degree)

I omitted the other values of y to just the first and last point for simplicity so the x[-1] - x[0] part here would be 11=17-6 which is the length of y line across the x-axis, this is what most online solutions suggest, however all the approaches failed to get the right angle for this, I should note that during my tests some approaches seemed to give the right angle for a given data unit for example while totally failing on a different data unit like

data = [52.3384984,53.04757978,52.04276249,51.77348257,49.93056673,52.24062341,55.74022485,60.77761392,60.89290148,60.1995072,60.40524964,59.00590344,59.67589831,56.49266698,49.02464746,51.53876823,57.77368203,59.48092106,56.63155446,56.0648491 ]
y = [51.337288,50.331895]
plt.plot(data)
plt.plot([3,15], y)
plt.show()

I also tried to min-max normalize the data but no success, so considering we have the first and last point of a line and its length how can we or is it possible to determine its angle in degrees?

1
  • soh-cah-toa... sin = opposite/hypotenuse, cos = adjacent/hypotenuse, tan = opposite/adjacent. . . and since the length is the hypotenuse, and you have the opposite and adjacent as well. . . any method will work, I think? See: hyperphysics.phy-astr.gsu.edu/hbase/ttrig.html Commented Feb 15, 2020 at 5:51

1 Answer 1

3

There are two angles you need to understand. The first one is calculated based data, the second one is calculated based on figure.

First one

The code you wrote is calculating first one:

degree = np.math.atan2(y[-1] - y[0], x[-1] - x[0])
degree = np.degrees(degree)

It's delta_y = y[-1] - y[0] = -36.43, delta_x = x[-1] - x[0] = 11

degree = -73.20 which totally make sense if you draw a triangle in your mind.

Second one

However, you may question me that you are watching a line around -5 degree. That's second one which involve calculating display ratio, (notice y axis and x axis has different unit length in inches). Here I found a separated question to help you calculate that.

from operator import sub
def get_aspect(ax):
    # Total figure size
    figW, figH = ax.get_figure().get_size_inches()
    # Axis size on figure
    _, _, w, h = ax.get_position().bounds
    # Ratio of display units
    disp_ratio = (figH * h) / (figW * w)
    # Ratio of data units
    # Negative over negative because of the order of subtraction
    data_ratio = sub(*ax.get_ylim()) / sub(*ax.get_xlim())

    return disp_ratio / data_ratio

So you need multiple that ratio to get manhattan distance of line end points.

ax = plt.gca()
ratio = get_aspect(ax)
degree = np.math.atan2((y[-1] - y[0])*ratio, x[-1] - x[0])
degree = np.degrees(degree)

The result is -4.760350735146195 which is around -5.

4
  • Interesting, I've tried with different data but it seems to fail eg: y = [7533, 7638] with length 7=[5,12] image it gives 5.3° while it looks almost 45°
    – 0x3h
    Commented Feb 16, 2020 at 4:27
  • Normalizing y to the range of x (0-19) making them of the same unit/length seem to give the right angle using just the standard equation degrees(atan2(y2-y1,x2-x1))
    – 0x3h
    Commented Feb 16, 2020 at 5:19
  • 1
    @0x3h I'm not totally agree that your ratio is as sample as unit/length. But I think you are right. Something I mentioned is wrong. atan2 isn't linear, so ratio has to be used before calculating atan2. I updated code. Now it should make sense in both cases.
    – Ke Zhang
    Commented Feb 16, 2020 at 16:46
  • Perfect, many thanks, now it gives 11.23 which is real angle as we see it link
    – 0x3h
    Commented Feb 17, 2020 at 3:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.