Sto lavorando su un problema di analisi spaziale e parte di questo flusso di lavoro consiste nel calcolare l'angolo tra i segmenti di linea collegati.Calcolo degli angoli tra i segmenti di linea (Python) con math.atan2
Ogni segmento di linea è composto da due soli punti e ogni punto ha una coppia di coordinate XY (cartesiane). Ecco l'immagine di GeoGebra. Sono sempre interessato a ottenere un angolo positivo nell'intervallo da 0 a 180. Tuttavia, ottengo tutti i tipi di angoli a seconda dell'ordine dei vertici nei segmenti di linea di input.
I dati di ingresso con cui lavoro è fornito come tuple di coordinate. A seconda dell'ordine di creazione del vertice, il punto finale/finale per ogni segmento di linea può essere diverso. Ecco alcuni dei casi in codice Python. L'ordine dei segmenti di linea in cui li ottengo è casuale, ma in una tupla di tuple, il primo elemento è il punto iniziale e il secondo è il punto finale. DE
segmento di linea, ad esempio, avrebbe ((1,1.5),(2,2))
e (1,1.5)
è il punto di partenza perché ha la prima posizione nella tupla di coordinate.
Tuttavia, è necessario accertarsi di ottenere lo stesso angolo tra DE,DF
e ED,DF
e così via.
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)
Ho scritto una piccola funzione che prende combinazioni di linee come args e calcola l'angolo tra di esse. Sto usando il math.atan2
che sembrava essere il più adatto per questo.
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
L'output che ottengo è:
> -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
Come potete vedere, io sono sempre valori diversi a seconda l'ordine dei vertici in un ordine segmento di linea e segmenti di linea. Ho provato a post-processare gli angoli scoprendo quale tipo di relazione avesse la linea sorgente e sfogliando le righe, modificando l'angolo, ecc. Ho chiuso con una dozzina di casi simili e ad un certo punto iniziano a sovrapporsi e io non può più sapere se -119,744 dovrebbe diventare 60,255 (angolo acuto) oppure essere lasciato come 119,744 (angolo ottuso) ecc
esiste un modo discreto per elaborare i valori di angolo di uscita inviate da math.atan2
per ottenere solo valore positivo nell'intervallo da 0 a 180?In caso negativo, che tipo di altro approccio dovrei prendere?
L'essenza del codice di test e dell'output è [qui] (https://gist.github.com/abhinavrk/2100332f7d7f4c127b8c) –
grazie per lo snippet di codice, ottimo per iniziare. Il problema con il codice è che non riporta mai angoli ottusi (> 90). Mettiti alla prova con '' lineA = ((0.6,3.6), (1,6,3)) riga B = ((1,6,3), (2,3,6)) ''. Segnala 87,27, ma dovrebbe essere 92,73. Cosa si potrebbe fare per risolverlo? –
Ho modificato il mio post. Credo di averlo aggiustato per dare anche degli angoli ottusi. Guarda. –