import functools
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p0 = Point(0, 0)
# Comparator function for sorting points
# in counterclockwise order around p0
def compare(p1, p2):
orientation = (p1.y - p0.y) * (p2.x - p1.x) - (p1.x - p0.x) * (p2.y - p1.y)
if orientation == 0:
return -1 if p1.x + p1.y < p2.x + p2.y else 1
return -1 if orientation < 0 else 1
# Returns the square of the Euclidean
# distance between two points
def dist_sq(p1, p2):
return (p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2
# Returns the orientation of three
# points (p, q, r)
def orientation(p, q, r):
val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)
if val == 0:
return 0
return 1 if val > 0 else 2
# Computes the convex hull of a set of n
# points using Graham's Scan algorithm
def convex_hull(points):
global p0
n = len(points)
# Find the point with the lowest y-coordinate
ymin = points[0].y
min_idx = 0
for i in range(1, n):
y = points[i].y
if y < ymin or (ymin == y and points[i].x < points[min_idx].x):
ymin = points[i].y
min_idx = i
# Swap the lowest point with the first point
points[0], points[min_idx] = points[min_idx], points[0]
p0 = points[0]
# Sort the remaining points in counterclockwise order around p0
points[1:] = sorted(points[1:], key=functools.cmp_to_key(compare))
# If two or more points have the same
# angle with p0, remove all but the farthest
m = 1
i = 1
while i < n:
while i < n - 1 and orientation(p0, points[i], points[i + 1]) == 0:
i += 1
points[m] = points[i]
m += 1
i += 1
# If there are less than 3 unique
# points, there is no convex hull
if m < 3:
return
# Use a stack to keep track of the
# vertices of the convex hull
hull = [points[0], points[1], points[2]]
# Process the remaining points
for i in range(3, n):
while len(hull) > 1 and orientation(hull[-2], hull[-1], points[i]) != 2:
hull.pop()
hull.append(points[i])
# Print the vertices of the
# convex hull
print("Vertices of the convex hull:")
for p in reversed(hull):
print(f"({p.x}, {p.y})")
# Driver's code
if __name__ == "__main__":
# Test the algorithm with a set of points
points = [Point(0, 3), Point(1, 1), Point(2, 2), Point(4, 4), Point(0, 0), Point(1, 2), Point(3, 1), Point(3, 3)]
print("Vertices of the convex hull:")
convex_hull(points)