我需要实现一个函数,将任意数量的点的坐标作为输入数据,并根据这些点是否位于同一条线上返回True或False。
我使用Python来解决这个问题,现在我有以下实现:
def are_colinear(points, tolerance): # variable "points" is list of lists with points coordinates
for i in range(2, len(points)):
if (points[i][0] - points[i-2][0])/(points[i-1][0] - points[i-2][0]) - (points[i][1] - points[i-2][1])/(points[i-1][1] - points[i-2][1]) < tolerance and \
(points[i][1] - points[i-2][1])/(points[i-1][1] - points[i-2][1]) - (points[i][2] - points[i-2][2])/(points[i-1][2] - points[i-2][2]) < tolerance:
continue
else:
return False
return True
该方法基于穿过两点的直线方程:
这种方法的缺点是,如果您想检查属于同一平面的点,它会引发错误(在这种情况下,三个坐标之一始终等于零,因此分母之一为零)。我需要更好的实施。预先感谢您!
您可以使用下一个方法:
-以参数形式通过前两个点画一条线
-使用标量(点)积查找其他点在这条线上的垂直投影的长度
-比较投影长度与公差
def are_colinear(points, tolerance):
dx01 = points[1][0]-points[0][0]
dy01 = points[1][1]-points[0][1]
dz01 = points[1][2]-points[0][2]
mult = 1.0 / (dx01*dx01+dy01*dy01+dz01*dz01)
for i in range(2, len(points)):
cdx = points[i][0] - points[0][0]
cdy = points[i][1] - points[0][1]
cdz = points[i][2] - points[0][2]
t = (cdx*dx01+cdy*dy01+cdz*dz01) * mult
perplen = math.sqrt((t*dx01-cdx)**2+ (t*dy01-cdy)**2 +(t*dz01-cdz)**2)
if perplen > tolerance:
return False
return True
print(are_colinear([[0,0,0],[2,2,2],[1,0.9999999,1.0000001]], 1e-6))
print(are_colinear([[0,0,0],[2,2,2],[1,0.9999,1.00001]], 1e-6))