tlmfoundationcosmetics.com

Understanding Convex Hulls in Python: A Comprehensive Guide

Written on

Chapter 1: Introduction to Convex Hulls

In recent times, I encountered a challenge involving the determination of the convex hull for a specific collection of points. This led me to delve deeper into the spatial package of Python's SciPy. The convex hull is defined as the smallest convex shape that encloses all points in a dataset. To visualize this concept, think of the points as nails on a board; the convex hull can be likened to a rubber band stretched around the outermost nails, thereby enclosing all points within. In a two-dimensional space, this results in a polygon, while in higher dimensions, it produces a structure known as a simplex.

Chapter 2: The 2D Scenario

The two-dimensional scenario involves working with points that are positioned on a flat plane. Here, the convex hull manifests as a polygon, with its vertices connected by straight lines. Let's begin by generating some random points and visualizing them with a scatter plot.

import matplotlib.pyplot as plt

from scipy.spatial import ConvexHull

import numpy as np

points = np.random.rand(20, 2)

plt.plot(points[:, 0], points[:, 1], 'o')

plt.xlim(0, 1)

plt.ylim(0, 1)

plt.gca().set_aspect("equal")

Next, we will calculate the convex hull using SciPy’s ConvexHull function, which employs the Quickhull algorithm and offers various attributes for analyzing and visualizing the resulting convex hull.

hull = ConvexHull(points)

The vertices property reveals the indices of the points that constitute the vertices of the convex hull, which form the outer boundary.

hull.vertices

The output will look something like this:

array([ 5, 2, 18, 14, 6, 17, 0], dtype=int32)

Similarly, the simplices property indicates the indices of the points that create the simplicial facets of the convex hull. In 2D, these simplices are merely line segments connecting the vertices.

hull.simplices

The output will be:

array([[ 2, 5],

[ 0, 5],

[ 0, 17],

[ 6, 17],

[ 6, 14],

[18, 14],

[18, 2]], dtype=int32)

Now, let’s define a function to visualize the hull. The red circles will represent the vertices of the convex hull, while the red lines will illustrate the line segments forming the perimeter.

def plot_hull():

plt.plot(points[:, 0], points[:, 1], 'o')

plt.plot(points[hull.vertices][:, 0], points[hull.vertices][:, 1], 'ro')

for facet in hull.simplices:

plt.plot(points[facet, 0], points[facet, 1], 'r-')

plt.xlim(0, 1)

plt.ylim(0, 1)

plt.gca().set_aspect("equal")

plot_hull()

The perimeter of the red polygon can be calculated using the area attribute of the hull object, which in 2D represents a length.

hull.area

This might yield a value like:

3.142052162690126

The volume property reflects the interior of the hull, which in a 2D context corresponds to an area.

hull.volume

You may receive an output such as:

0.6449431389347489

For any given facet, the neighbors property can be used to identify its neighboring facets.

hull.neighbors

The output will show the connections between neighboring facets:

array([[1, 6],

[0, 2],

[3, 1],

[2, 4],

[5, 3],

[4, 6],

[0, 5]], dtype=int32)

To clarify this concept, let’s highlight the facet with index 2 and its neighboring facets.

plot_hull()

# Highlighting facet with index 2:

facet = hull.simplices[2]

plt.plot(points[facet].T[0], points[facet].T[1], 'g-', lw=3)

# Identifying the indices of the neighboring facets:

neighbor_inds = hull.neighbors[2, :]

# Getting the point indices for the ends of each neighboring facet:

facets = hull.simplices[neighbor_inds]

for facet in facets:

plt.plot(points[facet].T[0], points[facet].T[1], 'b-', lw=3)

In this visualization, the facet with index 2 is marked in green, while its neighboring facets are shown in blue.

Chapter 3: The 3D Scenario

The three-dimensional scenario involves points situated in a three-dimensional space. Here, the convex hull appears as a polyhedron. The method for computing the convex hull remains similar to the 2D case, but now we need to account for three-dimensional facets and vertices.

from mpl_toolkits.mplot3d.art3d import Poly3DCollection

points = np.random.rand(30, 3)

hull = ConvexHull(points)

fig = plt.figure()

ax = fig.add_subplot(111, projection='3d')

# Plotting the points

ax.scatter(points[:, 0], points[:, 1], points[:, 2], 'o')

# Visualizing the convex hull

vertices = [points[face] for face in hull.simplices]

ax.add_collection3d(Poly3DCollection(vertices, facecolors='cyan', linewidths=1, edgecolors='r'))

In this section, we have created random 3D points and used the ConvexHull function to compute the convex hull. We then utilized Matplotlib's 3D plotting functions to display the hull as a polyhedron with cyan-colored faces.

The vertices property in 3D provides the indices of the points forming the vertices of the polyhedron, which outline the convex hull.

hull.vertices

An example output might be:

array([ 0, 1, 3, 4, 5, 6, 7, 9, 10, 13, 14, 16, 19, 20, 21, 23, 25,

26, 27, 28, 29], dtype=int32)

The simplices property shows the indices of the vertices for each triangular facet of the convex hull. In 3D, these facets are triangles that make up the faces of the polyhedron.

hull.simplices

Example output:

array([[ 1, 9, 29],

[ 0, 25, 10],

[ 0, 19, 10],

[ 5, 19, 29],

[ 5, 19, 10],

[ 5, 1, 29],

...

], dtype=int32)

To highlight a particular facet, let's focus on the facet with index 1.

fig = plt.figure()

ax = fig.add_subplot(111, projection='3d')

# Plotting the points

ax.scatter(points[:, 0], points[:, 1], points[:, 2], 'o')

# Plotting the convex hull

vertices = np.array([points[face] for face in hull.simplices])

ax.add_collection3d(Poly3DCollection(vertices, facecolors='cyan', linewidths=1, edgecolors='r'))

ax.add_collection3d(Poly3DCollection([vertices[1]], facecolors='green', linewidths=1, edgecolors='r'))

In this visualization, we highlight a specific facet (with index 1) in green. Such visual representation aids in the analysis of specific components of the hull and proves beneficial for various geometric and spatial assessments.

Chapter 4: Conclusion

The idea of a convex hull is a crucial concept in computational geometry, with applications spanning computer graphics, pattern recognition, image processing, and optimization. This article has demonstrated how to compute and visualize convex hulls in both two-dimensional and three-dimensional spaces using Python's SciPy spatial package.

The first video titled "Point in Polygon (Python3) - YouTube" provides a detailed exploration of how to determine whether a point is located within a polygon using Python.

The second video titled "Creating Regular Polygons in Python (Tutorial) - YouTube" offers a tutorial on generating regular polygons using Python programming techniques.

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Astonishing Discovery: The Earth-Sized 'Pi Planet' Unveiled

Astronomers have unveiled an Earth-sized exoplanet with a unique 3.14-day orbit, revealing new insights into planetary systems.

Maximizing Windows Update Efficiency: Connectivity Insights

Discover how maintaining adequate online time can enhance Windows update success rates and improve device performance.

Unlocking Focus: Mastering the Art of Present-Moment Engagement

Explore how to overcome distractions and enhance focus in daily tasks through mindfulness and clear objectives.