Вычисление углов между отрезками (Python) с помощью math.atan2

Я работаю над проблемой пространственного анализа, и частью этого рабочего процесса является вычисление угла между соединенными отрезками.

Каждый отрезок состоит только из двух точек, и каждая точка имеет пару координат XY (декартову). Вот изображение из GeoGebra.Я всегда заинтересован в получении положительного угла в диапазоне от 0 до 180, Тем не менее, я получаю все виды углов в зависимости от порядка вершин во входных отрезках.

Входные данные, с которыми я работаю, представлены в виде кортежей координат. В зависимости от порядка создания вершин последняя / конечная точка для каждого отрезка может быть разной. Вот некоторые из случаев в коде Python. Порядок сегментов линии, в которых я их получаю, является случайным, но в кортеже кортежей первый элемент является начальной точкой, а второй - конечной точкой.DE отрезок линии, например, будет иметь((1,1.5),(2,2)) и(1,1.5) является начальной точкой, потому что она имеет первую позицию в кортеже координат.

Однако я должен убедиться, что получу одинаковый угол междуDE,DF а такжеED,DF и так далее.

vertexType = "same start point; order 1"
            #X, Y    X Y 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)

Я написал крошечную функцию, которая принимает комбинации линий в качестве аргументов и вычисляет угол между ними. Я используюmath.atan2 который, казалось, лучше всего подходит для этого.

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

Я получаю вывод:

> -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

Как видите, я получаю разные значения в зависимости от порядка вершин в сегменте линии и порядка сегментов линии. Я попытался постобработать углы, выяснив, какое отношение имела исходная линия и перевернув линии, отредактировав угол и т. Д. Я закончил с дюжиной таких случаев, и в какой-то момент они начинают перекрываться, и я больше не могу определить, должно ли значение -119,744 стать 60,255 (острый угол) или оставить значение 119,744 (тупой угол) и т. д.

Есть ли какой-то дискретный способ обработки значений углов выхода, которые я получаю отmath.atan2 получить только положительное значение в диапазоне от 0 до 180? Если нет, какой другой подход я должен выбрать?

Ответы на вопрос(2)

Ваш ответ на вопрос