Calculando ângulos entre segmentos de linha (Python) com math.atan2

Estou trabalhando em um problema de análise espacial e parte desse fluxo de trabalho é calcular o ângulo entre os segmentos de linha conectados.

Cada segmento de linha é composto por apenas dois pontos e cada ponto possui um par de coordenadas XY (cartesiana). Aqui está a imagem do GeoGebra.Estou sempre interessado em obter um ângulo positivo na faixa de 0 a 180. No entanto, recebo todos os tipos de ângulos, dependendo da ordem dos vértices nos segmentos de linha de entrada.

Os dados de entrada com os quais trabalho são fornecidos como tuplas de coordenadas. Dependendo da ordem de criação do vértice, o último / ponto final de cada segmento de linha pode ser diferente. Aqui estão alguns dos casos no código Python. A ordem dos segmentos de linha em que eu os obtenho é aleatória, mas em uma tupla de tuplas, o primeiro elemento é o ponto inicial e o segundo é o ponto final.DE segmento de linha, por exemplo, teria((1,1.5),(2,2)) e a(1,1.5) é o ponto de partida porque tem a primeira posição na tupla de coordenadas.

No entanto, preciso garantir que obtenho o mesmo ângulo entreDE,DF eED,DF e assim por diante.

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)

Eu escrevi uma função minúscula que pega combinações das linhas como args e calcula o ângulo entre elas. Estou usando omath.atan2 que parecia ser mais adequado para isso.

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

A saída que recebo é:

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

Como você pode ver, estou obtendo valores diferentes, dependendo da ordem dos vértices em um segmento de linha e na ordem de segmentos de linha. Eu tentei pós-processar os ângulos descobrindo que tipo de relação a linha de origem tinha e invertendo as linhas, editando o ângulo etc. Eu terminei com uma dúzia desses casos e, em algum momento, eles começaram a se sobrepor e eu não é mais possível descobrir se -119.744 deve se tornar 60.255 (ângulo agudo) ou ser deixado como 119.744 (ângulo obtuso) etc.

Existe alguma maneira discreta de processar os valores dos ângulos de saída que recebo demath.atan2 obter apenas um valor positivo no intervalo de 0 a 180? Caso contrário, que tipo de outra abordagem devo adotar?

questionAnswers(2)

yourAnswerToTheQuestion