检查集合中的所有点是否都在同一条线上

时间:2019-05-26 11:20:04

标签: python geometry

我得到一个坐标为n点的列表,比方说:

points = [(1, 2), (2, 3), (3, 4)]

我需要检查它们是否都在同一行上。我还决定考虑3种情况,以避免在x1 == x2时被零除。 所以这是我在Python中的代码:

# 2 points always lie on a line
if n <= 2:
    print("yes")
else:
    # leave only unique points
    points = list(set(points))
    x1, y1 = points[0]
    x2, y2 = points[1]

    # if two points have the same x coordinate
    # then they lie on a vertical line and
    # all other points have to have the same x coordinate too
    if x2 == x1:
        for i in range(2, len(points)):
            if points[i][0] != x1:
                print("no")
                break
        else: print("yes")

    # same with a horizontal line
    elif y2 == y1:
        for i in range(2, len(points)):
            if points[i][1] != y1:
                print("no")
                break
        else: print("yes")

    else:
        a = (y2-y1)/(x2-x1)
        b = y2 - a * x2

        for i in range(2, len(points)):
            x, y = points[i]
            if (y != a * x + b):
                print("no")
                break
        else: print("yes")

似乎我在代码中的某个地方犯了一个错误,但我并不真正理解它是什么。

2 个答案:

答案 0 :(得分:1)

使用向量的叉积消除了必须处理可能发生被零除的特殊情况的复杂性。如果由三个点定义的两个向量形成的向量的叉积等于零,则三个点是共线的:

import math

class Point:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)

class Vector:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def cross(self, other):
        return self.x * other.y - self.y * other.x

def are_collinear(three_points):
    a, b, c = three_points  
    # better use math.isclose than == to check for floats
    return math.isclose((b-a).cross(c-a), 0.0)

points = [Point(1, 2), Point(2, 3), Point(3, 4)]
print(are_collinear(points))
# True


points = [Point(1, 2), Point(3, 3), Point(3, 4)]
print(are_collinear(points))
# False

答案 1 :(得分:0)

从列表中的任意点(例如第一个点)开始,如果所有其他点都与该点具有相同的斜率,则它们位于同一条线上。

def sameLine(points):
    x0,y0  = points[0]
    points = [ (x,y) for x,y in points if x != x0 or y != y0 ]      # Other points
    slopes = [ (y-y0)/(x-x0) if x!=x0 else None for x,y in points ] # None for vertical Line
    return all( s == slopes[0] for s in slopes)