计算多边形的内角
calculate inner angles of a polygon
我有以下数组数组:
[[[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)),
以此类推直到结束...
它应该是哪个循环以及如何实现它?
试试这个:
lst = [[[623,284]] , [[526, 256]] , [[532, 189]]]
tuple(map((lambda x : tuple(x[0])), lst))
输出:
((623, 284), (526, 256), (532, 189))
编辑 作为您的评论:
lst = [[[623,284]], [[526, 256]], [[532, 189]], [[504, 166]], [[323, 175]], [[276, 219]], [[119, 221]], [[ 1, 272]], [[ 0, 473]] , [[615, 479]]]
for l in range(0,len(lst)-2):
f , s , t = (tuple(map((lambda x : tuple(x[0])), lst[l:l+3])))
getAngle(f , s, t)
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)
简单的怎么样
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])
因为你有点(作为一个 numpy 数组)并且你想要角度(有符号 角度),这里有一个完整的解决方案。
- 计算向量
- 使用叉积:
这使用全数组操作。
注意 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")
我有以下数组数组:
[[[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)),
以此类推直到结束... 它应该是哪个循环以及如何实现它?
试试这个:
lst = [[[623,284]] , [[526, 256]] , [[532, 189]]]
tuple(map((lambda x : tuple(x[0])), lst))
输出:
((623, 284), (526, 256), (532, 189))
编辑 作为您的评论:
lst = [[[623,284]], [[526, 256]], [[532, 189]], [[504, 166]], [[323, 175]], [[276, 219]], [[119, 221]], [[ 1, 272]], [[ 0, 473]] , [[615, 479]]]
for l in range(0,len(lst)-2):
f , s , t = (tuple(map((lambda x : tuple(x[0])), lst[l:l+3])))
getAngle(f , s, t)
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)
简单的怎么样
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])
因为你有点(作为一个 numpy 数组)并且你想要角度(有符号 角度),这里有一个完整的解决方案。
- 计算向量
- 使用叉积:
这使用全数组操作。
注意 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")