I am working on a spatial analysis problem, and part of this workflow is calculating the angle between the connected line segments.
Each line segment consists of only two points, and each point has a pair of XY coordinates (Cartesian). Here is an image from GeoGebra. I am always interested in getting a positive angle in the range from 0 to 180 . However, I get all kinds of angles depending on the order of the vertices in the input line segments.

The input data I'm working with is represented as tuples of coordinates. Depending on the order of vertex creation, the last / end point for each line segment may be different. Here are some of the cases in Python code. The order of the line segments in which I get them is random, but in the tuple of tuples, the first element is the start point, and the second is the end point. DE line segment, for example, would have ((1,1.5),(2,2)) , and (1,1.5) be the starting point, because it has the first position in the tuple of coordinates.
However, I need to make sure that I will have the same angle between DE,DF and ED,DF , etc.
vertexType = "same start point; order 1" #X, YXY coords lineA = ((1,1.5),(2,2)) #DE lineB = ((1,1.5),(2.5,0.5)) #DF calcAngle(lineA, lineB,vertexType) #flip lines order vertexType = "same start point; order 2" lineB = ((1,1.5),(2,2)) #DE lineA = ((1,1.5),(2.5,0.5)) #DF calcAngle(lineA, lineB,vertexType) vertexType = "same end point; order 1" lineA = ((2,2),(1,1.5)) #ED lineB = ((2.5,0.5),(1,1.5)) #FE calcAngle(lineA, lineB,vertexType) #flip lines order vertexType = "same end point; order 2" lineB = ((2,2),(1,1.5)) #ED lineA = ((2.5,0.5),(1,1.5)) #FE calcAngle(lineA, lineB,vertexType) vertexType = "one line after another - down; order 1" lineA = ((2,2),(1,1.5)) #ED lineB = ((1,1.5),(2.5,0.5)) #DF calcAngle(lineA, lineB,vertexType) #flip lines order vertexType = "one line after another - down; order 2" lineB = ((2,2),(1,1.5)) #ED lineA = ((1,1.5),(2.5,0.5)) #DF calcAngle(lineA, lineB,vertexType) vertexType = "one line after another - up; line order 1" lineA = ((1,1.5),(2,2)) #DE lineB = ((2.5,0.5),(1,1.5)) #FD calcAngle(lineA, lineB,vertexType) #flip lines order vertexType = "one line after another - up; line order 2" lineB = ((1,1.5),(2,2)) #DE lineA = ((2.5,0.5),(1,1.5)) #FD calcAngle(lineA, lineB,vertexType)
I wrote a tiny function that takes combinations of lines as arguments and calculates the angle between them. I am using math.atan2 which is best suited for this.
def calcAngle(lineA,lineB,vertexType): line1Y1 = lineA[0][1] line1X1 = lineA[0][0] line1Y2 = lineA[1][1] line1X2 = lineA[1][0] line2Y1 = lineB[0][1] line2X1 = lineB[0][0] line2Y2 = lineB[1][1] line2X2 = lineB[1][0] #calculate angle between pairs of lines angle1 = math.atan2(line1Y1-line1Y2,line1X1-line1X2) angle2 = math.atan2(line2Y1-line2Y2,line2X1-line2X2) angleDegrees = (angle1-angle2) * 360 / (2*math.pi) print angleDegrees, vertexType
The output I get is:
> -299.744881297 same start point; order 1 > 299.744881297 same start point; order 2 > 60.2551187031 same end point; order 1 > -60.2551187031 same end point; order 2 > -119.744881297 one line after another - down; order 1 > 119.744881297 one line after another - down; order 2 > -119.744881297 one line after another - up; line order 1 > 119.744881297 one line after another - up; line order 2
As you can see, I get different values ββdepending on the order of the vertices in the line segment and the order of the line segments. I tried to process the corners, finding out what the source line, turning the lines, editing the angle, etc. I ended up with a dozen such cases, and at some point they begin to overlap, and I can no longer find out if -119.744 should become 60.255 (acute angle) or leave it as 119.744 (obtuse angle), etc.
Is there any discrete way to handle the output angle values ββthat I get from math.atan2 to get only a positive value in the range of 0 to 180? If not, what other approach should I take?