Предполагая, что точки в порядке, вы в основном хотите сбросить точку, если следующая точка находится непосредственно позади нее от предыдущей точки.
from math import isclose
def lined_up(bef, p, aft):
if p[1] - bef[1] == 0:
if aft[1] - p[1] == 0:
# matching signs
return p[0] - bef[0] < 0 == p[0] - bef[0] < 0
else:
return False
elif aft[1] - p[1] == 0:
return False
else:
return isclose(
(p[0] - bef[0]) / (p[1] - bef[1]),
(aft[0] - p[0]) / (aft[1] - p[1]),
rel_tol=1e-8
)
def remove_redundant_points(pts):
# remove redundant end points overlapping with the starting point
while len(pts) > 1 and pts[-1] == pts[0]:
pts = pts[:-1]
return [pts[0]] + [p for bef, p, aft in zip(pts[0:-2], pts[1:-1], pts[2:])
if not lined_up(bef, p, aft)] + [pts[-1]]
points = [(1, 0), (3, 0), (2, 0), (2, 1), (2, 2), (3, 3), (6, 6), (0, 2), (1, 0)]
print(remove_redundant_points(points))
Обратите внимание на использование math.isclose
, чтобы избежать плавающей запятой ошибки деления.
Вывод:
[(1, 0), (2, 0), (2, 2), (6, 6), (0, 2)]