refactor: wrap.py

This commit is contained in:
Matthieu Bessat 2024-07-04 23:06:36 +02:00
parent 547552026b
commit 78c8874102

View file

@ -2,56 +2,29 @@
# https://en.wikipedia.org/wiki/Gift_wrapping_algorithm # https://en.wikipedia.org/wiki/Gift_wrapping_algorithm
# Date: 2021-11-16 # Date: 2021-11-16
import matplotlib.pyplot as plt
import math
import random import random
import matplotlib.pyplot as plt
def generate_points(n=100): def generate_points(n=100):
X = [] X = []
Y = [] Y = []
for i in range(n): for _i in range(n):
X.append(random.random()) X.append(random.random())
Y.append(random.random()) Y.append(random.random())
plt.plot(X, Y, '.') plt.plot(X, Y, ".")
return [(X[i], Y[i]) for i in range(n)] return [(X[i], Y[i]) for i in range(n)]
# def angle(p1, p2, p3):
# p1, p2, p3 = p3, p2, p1
# print(p1, p2, p3)
# if p1 == p3: return math.pi
# x1, y1 = p2[0]-p1[0], p2[1]-p1[1]
# x2, y2 = p3[0]-p2[0], p3[1]-p2[1]
# d = x1*y2-y1*x2
# n1 = math.hypot(x1, y1)
# n2 = math.hypot(x2, y2)
# if d == 0 or n1*n2 == 0:
# l = x1/x2
# if l >= 0: return 0
# return math.pi
# dp = x1*x2 + y1*y2
# c = math.acos(dp/(n1*n2))
# b = (c if d > 0 else -c) % 2*math.pi
# return math.pi*2-b
def cross_product(u, v): def cross_product(u, v):
x1, y1 = u x1, y1 = u
x2, y2 = v x2, y2 = v
n1 = math.hypot(x1, y1) return x1 * y2 - x2 * y1
n2 = math.hypot(x2, y2)
return (x1*y2-x2*y1)
# def angle(p1, p2, p3):
# x1, y1 = p2[0]-p1[0], p2[1]-p1[1]
# x2, y2 = p3[0]-p2[0], p3[1]-p2[1]
# a = (math.atan2(y1, x1) - math.atan2(y2, x2))
# if a < 0:
# a = math.pi
# return a
def gift_wrapping(points): def gift_wrapping(points):
convex_hull = [] convex_hull = []
x_sorted = list(sorted(points, key=lambda point: point[0])) x_sorted = sorted(points, key=lambda point: point[0])
left_most = x_sorted[0] left_most = x_sorted[0]
point_on_hull = left_most point_on_hull = left_most
endpoint = None endpoint = None
@ -59,30 +32,27 @@ def gift_wrapping(points):
convex_hull.append(point_on_hull) convex_hull.append(point_on_hull)
endpoint = points[0] endpoint = points[0]
for point in points: for point in points:
cp = cross_product(( cp = cross_product(
endpoint[0] - point_on_hull[0], (endpoint[0] - point_on_hull[0], endpoint[1] - point_on_hull[1]),
endpoint[1] - point_on_hull[1] (point[0] - point_on_hull[0], point[1] - point_on_hull[1]),
), ( )
point[0] - point_on_hull[0],
point[1] - point_on_hull[1]
))
if endpoint == point_on_hull or cp < 0: if endpoint == point_on_hull or cp < 0:
endpoint = point endpoint = point
point_on_hull = endpoint point_on_hull = endpoint
return convex_hull return convex_hull
def draw_points(points, with_edge=False): def draw_points(points, with_edge=False):
X, Y = [], [] X, Y = [], []
for p in points: for p in points:
X.append(p[0]) X.append(p[0])
Y.append(p[1]) Y.append(p[1])
plt.plot(X, Y, '.' if not with_edge else '') plt.plot(X, Y, "." if not with_edge else "")
pts = generate_points(50) pts = generate_points(50)
#pts = [(0.1, 1), (0.2, 0.4), (0.2, 0.15), (0.4, 0.25), (0.6, 0.8), (0.55, 0.3), (0.7, 0.2), (0.5, 0.5), (0.4, 0.7), (0.3, 0.1)]
print(pts) print(pts)
draw_points(pts) draw_points(pts)
hull = gift_wrapping(pts) hull = gift_wrapping(pts)
draw_points(hull + [hull[0]], True) draw_points(hull + [hull[0]], True)