Skip to content

Instantly share code, notes, and snippets.

@nicoguaro
Created June 8, 2015 14:55
Show Gist options
  • Save nicoguaro/1cc7474bc2331e48fb64 to your computer and use it in GitHub Desktop.
Save nicoguaro/1cc7474bc2331e48fb64 to your computer and use it in GitHub Desktop.
Plot the convex hull around a set of points as a shaded polygon.
# -*- coding: utf-8 -*-
"""
Plot the convex hull around a set of points as a
shaded polygon.
@author: Nicolas Guarin Zapata
@date: October 15, 2014
"""
import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
points = np.random.rand(30, 2) # 30 random points in 2-D
hull = ConvexHull(points)
plt.plot(points[:,0], points[:,1], 'o')
cent = np.mean(points, 0)
pts = []
for pt in points[hull.simplices]:
pts.append(pt[0].tolist())
pts.append(pt[1].tolist())
pts.sort(key=lambda p: np.arctan2(p[1] - cent[1],
p[0] - cent[0]))
pts = pts[0::2] # Deleting duplicates
pts.insert(len(pts), pts[0])
k = 1.1
color = 'green'
poly = Polygon(k*(np.array(pts)- cent) + cent,
facecolor=color, alpha=0.2)
poly.set_capstyle('round')
plt.gca().add_patch(poly)
plt.savefig('convex.png')
@theRealSuperMario
Copy link

theRealSuperMario commented Apr 3, 2020

I noticed that the polygon is not "tight" around the points. Is there a way to change that to that the vertices of the polygon can be points?

Or am I just doing something wrong?

Edit:

I realized that changing k=1.1 to k=1 does the job. Thanks for sharing the snippet.

@kkew3
Copy link

kkew3 commented Feb 5, 2023

Thanks for the code!

I notice that as of scipy v1.8.0 and in 2-dimensional context, one may get a list of convex hull points in (counter)clockwise order directly from points[hull.vertices]. In addition, pts.insert(len(pts), pts[0]) is not necessary when closed=True is added (which is the default behavior as of matplotlib v3.6.2) to the Polygon constructor. Thus, my code would be:

import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

points = np.random.rand(30, 2)   # 30 random points in 2-D
hull = ConvexHull(points)

plt.plot(points[:,0], points[:,1], 'o')
cent = np.mean(points, axis=0)
pts = points[hull.vertices]

k = 1.1
color = 'green'
poly = Polygon(k*(pts - cent) + cent, closed=True,
               capstyle='round', facecolor=color, alpha=0.2)
plt.gca().add_patch(poly)
plt.savefig('convex.png')

Thanks again!

@nicoguaro
Copy link
Author

@kkew3, I tried and it works finely. That makes the code more compact, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment