计算多边形的内角

2024-09-30 14:21:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下数组:

[[[623 284]]

 [[526 256]]

 [[532 189]]

 [[504 166]]

 [[323 175]]

 [[276 219]]

 [[119 221]]

 [[  1 272]]

 [[  0 473]]

 [[615 479]]]

这些是多边形的点(坐标)。我需要做的是迭代这个数组,取每个点来计算多边形中的每个内角。我有这个函数来计算3个点之间的角度:getAngle((px1, py1), (px2, py2), (px3, py3))。 基本上,我想把这个函数放在一个循环中,它会分别取点,比如:

getAngle((623, 284), (526, 256), (532, 189)),
getAngle((526, 256), (532, 189), (504, 166)),
getAngle((532, 189), (504, 166), (323, 175)),

等等,直到最后。。。 它应该是哪个循环以及如何实现它


Tags: 函数py3数组多边形角度py2py1内角
3条回答

more_itertools是一个很好的库,可以存储以下内容:

import more_itertools

points = [[623,284], [526, 256], [532, 189], [504, 166], [323, 175], [276, 219], [119, 221], [  1, 272], [  0, 473]]
for triplet in more_itertools.windowed(points, n=3, step=3):
    getAngle(*triplet)

因为你有点(作为一个numpy数组)并且你想要角度(符号角度),这里有一个完整的解决方案

  • 计算向量
  • 使用交叉乘积cross product

这将使用整个数组操作

注意Yves Daoust在评论中的非常有效的评论。此演示无法正确处理锐角,但可以通过额外的向量检查和角度校正来处理锐角

import numpy as np

points = np.array([
 [[623, 284]],
 [[526, 256]],
 [[532, 189]],
 [[504, 166]],
 [[323, 175]],
 [[276, 219]],
 [[119, 221]],
 [[  1, 272]],
 [[  0, 473]],
 [[615, 479]]])
# funny shape because OpenCV. it's a Nx1 vector of 2-channel elements
# fix that up, remove the silly dimension
points.shape = (-1, 2)

# the vectors are differences of coordinates
# a points into the point, b out of the point
a = points - np.roll(points, 1, axis=0)
b = np.roll(a, -1, axis=0) # same but shifted

# we'll need to know the length of those vectors
alengths = np.linalg.norm(a, axis=1)
blengths = np.linalg.norm(b, axis=1)

# we need only the length of the cross product,
# and we work in 2D space anyway (not 3D),
# so the cross product can't result in a vector, just its z-component
crossproducts = np.cross(a, b) / alengths / blengths

angles = np.arcsin(crossproducts)
angles_degrees = angles / np.pi * 180

print("angles in degrees:")
print(angles_degrees)

# this is just for printing/displaying, not useful in code
print("point and angle:")
print(np.hstack([points, angles_degrees.reshape((-1, 1))]))

angles in degrees:
[-76.24798  79.01601 -55.71665 -42.24728 -40.2652   42.38197 -22.64432 -66.34078 -89.72609 -88.20969]
point and angle:
[[623.      284.      -76.24798]
 [526.      256.       79.01601]
 [532.      189.      -55.71665]
 [504.      166.      -42.24728]
 [323.      175.      -40.2652 ]
 [276.      219.       42.38197]
 [119.      221.      -22.64432]
 [  1.      272.      -66.34078]
 [  0.      473.      -89.72609]
 [615.      479.      -88.20969]]

一些图纸:

import cv2 as cv

canvas = np.zeros((600, 700, 3)) # floats, range 0..1

cv.polylines(canvas, [points], isClosed=True, color=(1,1,1))

for i,angle in enumerate(angles_degrees):
    cv.circle(canvas, center=tuple(points[i]), radius=5, color=(0,0,1), thickness=cv.FILLED)
    cv.putText(
        canvas,
        f"{angle:+.1f}",
        org=tuple(points[i]),
        fontFace=cv.FONT_HERSHEY_SIMPLEX,
        fontScale=0.75,
        color=(0,1,1),
        thickness=2)

cv.imshow("canvas", canvas)
cv.waitKey(-1)
cv.destroyWindow("canvas")

drawing

一个简单的

for i in range(len(A) - 2):
    getAngle(A[0][i], A[0][i+1], A[0][i+2])

?


勘误表:

for i in range(len(A) - 2):
    getAngle(A[i][0], A[i+1][0], A[i+2][0])

相关问题 更多 >