diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7aa94d..4d659e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
## 3.2.0
### Added
- X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)`
-- X10D: Added `Circle`, `CircleF`, `Ellipse`, `EllipseF` `Line`, `LineF`, `Line3D`, `Polygon`, and `PolygonF`, to complement System.Drawing structs such as `Point` and `Rectangle`
+- X10D: Added `Circle`, `CircleF`, `Cuboid`, `Ellipse`, `EllipseF`, `Line3D`, `Line`, `LineF`, `Polygon`, `PolygonF`, `Polyhedron`, and `Sphere`, to complement System.Drawing structs such as `Point` and `Rectangle`
- X10D: Added `Point.ToSize()`
- X10D: Added `Point.ToSizeF()`
- X10D: Added `Point.ToVector2()`
diff --git a/X10D/src/Drawing/Polyhedron.cs b/X10D/src/Drawing/Polyhedron.cs
new file mode 100644
index 0000000..9c2eecc
--- /dev/null
+++ b/X10D/src/Drawing/Polyhedron.cs
@@ -0,0 +1,227 @@
+using System.Drawing;
+using System.Numerics;
+
+namespace X10D.Drawing;
+
+///
+/// Represents a 3D polyhedron composed of single-precision floating-point points.
+///
+public class Polyhedron : IEquatable
+{
+ ///
+ /// The empty polyhedron. That is, a polyhedron with no points.
+ ///
+ public static readonly Polyhedron Empty = new();
+
+ private readonly List _vertices = new();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Polyhedron()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the struct by copying the specified polyhedron.
+ ///
+ public Polyhedron(Polyhedron polyhedron)
+ : this(polyhedron._vertices)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the struct by constructing it from the specified vertices.
+ ///
+ /// An enumerable collection of vertices from which the polyhedron should be constructed.
+ public Polyhedron(IEnumerable vertices)
+ {
+#if NET6_0_OR_GREATER
+ ArgumentNullException.ThrowIfNull(vertices);
+#else
+ if (vertices is null)
+ {
+ throw new ArgumentNullException(nameof(vertices));
+ }
+#endif
+
+ _vertices = new List(vertices);
+ }
+
+ ///
+ /// Returns a value indicating whether this polyhedron is convex.
+ ///
+ /// if this polyhedron is convex; otherwise, .
+ public bool IsConvex
+ {
+ get
+ {
+ if (_vertices.Count < 4)
+ {
+ return false;
+ }
+
+ Vector3[] vertices = _vertices.ToArray();
+ int n = vertices.Length;
+
+ for (var i = 0; i < n; i++)
+ {
+ int j = (i + 1) % n;
+ int k = (i + 2) % n;
+
+ if (Vector3.Cross(vertices[j] - vertices[i], vertices[k] - vertices[j]).LengthSquared() < 1e-6f)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ ///
+ /// Gets the number of vertices in this polyhedron.
+ ///
+ /// An value, representing the number of vertices in this polyhedron.
+ public int VertexCount
+ {
+ get => _vertices.Count;
+ }
+
+ ///
+ /// Gets a read-only view of the vertices in this polyhedron.
+ ///
+ ///
+ /// A of values, representing the vertices of this polyhedron.
+ ///
+ public IReadOnlyList Vertices
+ {
+ get => _vertices.AsReadOnly();
+ }
+
+ ///
+ /// Returns a value indicating whether two instances of are equal.
+ ///
+ /// The first instance.
+ /// The second instance.
+ ///
+ /// if and are considered equal; otherwise,
+ /// .
+ ///
+ public static bool operator ==(Polyhedron left, Polyhedron right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Returns a value indicating whether two instances of are not equal.
+ ///
+ /// The first instance.
+ /// The second instance.
+ ///
+ /// if and are considered not equal; otherwise,
+ /// .
+ ///
+ public static bool operator !=(Polyhedron left, Polyhedron right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ /// Implicitly converts a to a .
+ ///
+ /// The polyhedron to convert.
+ /// The converted polyhedron.
+ public static implicit operator Polyhedron(Polygon polygon)
+ {
+ var points = new List();
+
+ foreach (Point point in polygon.Vertices)
+ {
+ points.Add(new Vector3(point.X, point.Y, 0));
+ }
+
+ return new Polyhedron(points);
+ }
+
+ ///
+ /// Implicitly converts a to a .
+ ///
+ /// The polyhedron to convert.
+ /// The converted polyhedron.
+ public static implicit operator Polyhedron(PolygonF polygon)
+ {
+ var points = new List();
+
+ foreach (PointF point in polygon.Vertices)
+ {
+ points.Add(new Vector3(point.X, point.Y, 0));
+ }
+
+ return new Polyhedron(points);
+ }
+
+ ///
+ /// Adds a vertex to this polyhedron.
+ ///
+ /// The vertex to add.
+ public void AddVertex(Vector3 vertex)
+ {
+ _vertices.Add(vertex);
+ }
+
+ ///
+ /// Adds a collection of vertices to this polyhedron.
+ ///
+ /// An enumerable collection of vertices to add.
+ /// is .
+ public void AddVertices(IEnumerable vertices)
+ {
+#if NET6_0_OR_GREATER
+ ArgumentNullException.ThrowIfNull(vertices);
+#else
+ if (vertices is null)
+ {
+ throw new ArgumentNullException(nameof(vertices));
+ }
+#endif
+
+ foreach (Vector3 vertex in vertices)
+ {
+ AddVertex(vertex);
+ }
+ }
+
+ ///
+ /// Clears all vertices from this polyhedron.
+ ///
+ public void ClearVertices()
+ {
+ _vertices.Clear();
+ }
+
+ ///
+ public override bool Equals(object? obj)
+ {
+ return obj is Polyhedron polyhedron && Equals(polyhedron);
+ }
+
+ ///
+ /// Returns a value indicating whether this instance and another instance are equal.
+ ///
+ /// The instance with which to compare.
+ ///
+ /// if this instance and are considered equal; otherwise,
+ /// .
+ ///
+ public bool Equals(Polyhedron other)
+ {
+ return _vertices.SequenceEqual(other._vertices);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return _vertices.Aggregate(0, HashCode.Combine);
+ }
+}