BerGeo/h2/gift_wrapper.py

72 lines
1.5 KiB
Python
Raw Normal View History

2018-09-17 15:06:20 +00:00
# Use atan2 instead of acos to calc angle; atan2(x,y) of the point we potentially want to add
import random
from collections import namedtuple
import matplotlib.pyplot as plt
2018-09-20 12:50:16 +00:00
from math import acos, sqrt
2018-09-17 15:06:20 +00:00
Point = namedtuple('Point', 'x y')
Vector = namedtuple('Vector', 'x y')
def gen_point():
a = random.uniform(1, 5)
b = random.uniform(1, 5)
x_i = random.uniform(1, 5)
p_i = Point(x_i, a * x_i + b)
return p_i
2018-09-20 12:50:16 +00:00
def calc_angle(v1: Vector, v2: Vector) -> float:
dot = (v1.x * v2.x) + (v1.y * v2.y)
len_1 = sqrt(v1.x**2 + v1.y**2)
len_2 = sqrt(v2.x**2 + v2.y**2)
tmp = dot / (len_1 * len_2)
# pls
hmmmmmmm = round(tmp, 6)
return acos(hmmmmmmm)
2018-09-17 15:06:20 +00:00
def calc_vector(p1: Point, p2: Point) -> Vector:
return Vector((p2.x - p1.x), (p2.y - p1.y))
2018-09-18 09:54:11 +00:00
2018-09-17 15:06:20 +00:00
def display(points, hull):
x = [point.x for point in points]
y = [point.y for point in points]
h_x = [point.x for point in hull]
h_y = [point.y for point in hull]
plt.plot(h_x, h_y, 'ro-')
plt.scatter(x, y)
plt.show()
def rapper(points: set):
min_pt = min(points)
hull = [min_pt]
2018-09-20 12:50:16 +00:00
comp_vec = Vector(0, 1)
2018-09-17 15:06:20 +00:00
while True:
hull.append(min(points - {hull[-1]},
2018-09-20 12:50:16 +00:00
key=lambda p: calc_angle(comp_vec, calc_vector(hull[-1], p))))
comp_vec = calc_vector(hull[-2], hull[-1])
2018-09-17 15:06:20 +00:00
display(points, hull)
2018-09-20 12:50:16 +00:00
2018-09-17 15:06:20 +00:00
if hull[-1] == min_pt:
break
return hull
2018-09-18 09:54:11 +00:00
points = {gen_point() for _ in range(30)}
2018-09-17 15:06:20 +00:00
hull = rapper(points)