用一些三角函数并不难。也许你知道两个(标准化的)向量之间的角度是acos(vec1 * vec2)
。然而,这只计算了投影角度,但可以使用atan2
来计算方向感知角度。
因此,编写一个计算它并将其用作排序时的key
的功能将是一个好方法:
import math
pts = [[2,3], [5,2],[4,1],[3.5,1],[1,2],[2,1],[3,1],[3,3],[4,3]]
origin = [2, 3]
refvec = [0, 1]
def clockwiseangle_and_distance(point):
vector = [point[0]-origin[0], point[1]-origin[1]]
lenvector = math.hypot(vector[0], vector[1])
if lenvector == 0:
return -math.pi, 0
normalized = [vector[0]/lenvector, vector[1]/lenvector]
dotprod = normalized[0]*refvec[0] + normalized[1]*refvec[1]
diffprod = refvec[1]*normalized[0] - refvec[0]*normalized[1]
angle = math.atan2(diffprod, dotprod)
if angle < 0:
return 2*math.pi+angle, lenvector
return angle, lenvector
一个sorted
运行:
>>> sorted(pts, key=clockwiseangle_and_distance)
[[2, 3], [3, 3], [4, 3], [5, 2], [4, 1], [3.5, 1], [3, 1], [2, 1], [1, 2]]
如果原点周围有一个矩形网格,那么这也能按预期工作:
>>> origin = [2,3]
>>> refvec = [0, 1]
>>> pts = [[1,4],[2,4],[3,4],[1,3],[2,3],[3,3],[1,2],[2,2],[3,2]]
>>> sorted(pts, key=clockwiseangle_and_distance)
[[2, 3], [2, 4], [3, 4], [3, 3], [3, 2], [2, 2], [1, 2], [1, 3], [1, 4]]
即使您更改引用向量:
>>> origin = [2,3]
>>> refvec = [1,0]
>>> pts = [[1,4],[2,4],[3,4],[1,3],[2,3],[3,3],[1,2],[2,2],[3,2]]
>>> sorted(pts, key=clockwiseangle_and_distance)
[[2, 3], [3, 3], [3, 2], [2, 2], [1, 2], [1, 3], [1, 4], [2, 4], [3, 4]]
感谢
@Scott Mermelstein
提供更好的函数名和
@f5r5e5d
的
atan2
建议。