The Sphere
Perfect Symmetry
A Sphere is the set of all points in 3D space that are at a fixed distance (the radius) from a single point (the center). In the world of computational geometry, the sphere is the ultimate symbol of symmetry and efficiency.
Unlike a Mesh, which is an approximation made of flat faces, a mathematical Sphere is infinitely smooth.
x² + y² + z² = r²). Implicit geometry never loses precision.Data Structure
Because of its mathematical perfection, a Sphere requires almost no memory. To define a sphere in a CAD system, you only need:
Center: APoint3d.Radius: A singledouble(floating point number).
1class Sphere:2 """3 Represents a mathematical sphere.4 """5 def __init__(self, center: Point3d, radius: float):6 self.Center = center7 self.Radius = radius
PointAt(u, v):
U) and Polar Angle/Colatitude (V) — to a 3D point on the sphere.1def PointAt(self, u_degrees: float, v_degrees: float) -> Point3d:2 """3 Maps azimuth/longitude u (0°..360°) and polar angle/colatitude v (0°..180°)4 to a 3D point on the sphere surface. (Note: latitude = 90° - v).5 """6 u_rad = math.radians(u_degrees)7 v_rad = math.radians(v_degrees)8 x = self.Radius * math.sin(v_rad) * math.cos(u_rad)9 y = self.Radius * math.sin(v_rad) * math.sin(u_rad)10 z = self.Radius * math.cos(v_rad)11 return Point3d(x + self.Center.X, y + self.Center.Y, z + self.Center.Z)
U (0° to 360°) sweeps around the equator as Azimuth / Longitude, while V (0° to 180°) sweeps from the North Pole (+Z) to the South Pole (-Z) as the Polar Angle (Colatitude), related to geographic latitude by Latitude = 90° - V.The Singularities: At the exact top (
V = 0°) and bottom (V = 180°) poles, all longitudinal lines converge to a single point.Translate(vector):
Moving a sphere is computationally trivial — you only need to add a translation vector to its Center point.
1def Translate(self, vector: 'Vector3d'):2 """Moving a sphere only requires moving its Center point."""3 self.Center += vector
Scale(factor):
Radius by a scalar factor.1def Scale(self, factor: float):2 """Scaling a sphere is simply multiplying its Radius."""3 self.Radius *= factor
Rotate(axis, angle):
Center and Radius unchanged, rotating only its local UV frame.1class Sphere:2 def Rotate(self, angle_radians: float, axis: Vector3d, pivot: Point3d):3 """4 Rotates the sphere around a pivot axis.5 If pivot == self.Center, the sphere's position is unchanged,6 and only its local UV orientation frame rotates.7 """8 self.Center = RotatePointAroundAxis(self.Center, angle_radians, axis, pivot)9 self.EquatorialPlane.Rotate(angle_radians, axis, self.Center)
Center point along a circular arc.Volume() & Area():
(4/3)πr³ and surface area is 4πr². These closed-form formulas are exact, unlike mesh-based approximations.1import math23class Sphere:4 def Volume(self) -> float:5 """Computes exact analytical enclosed volume of the sphere."""6 return (4.0 / 3.0) * math.pi * (self.Radius ** 3)78 def SurfaceArea(self) -> float:9 """Computes exact analytical surface area of the sphere."""10 return 4.0 * math.pi * (self.Radius ** 2)
Intersection:
1def RaySphereIntersection(ray: 'Ray3d', sphere: 'Sphere') -> list['Point3d']:2 """Finds intersection points between a ray and a sphere."""34 # Solved using the quadratic formula: at^2 + bt + c = 05 # where t is the distance along the ray67 L = ray.Position - sphere.Center8 a = Vector3d.DotProduct(ray.Direction, ray.Direction)9 b = 2.0 * Vector3d.DotProduct(ray.Direction, L)10 c = Vector3d.DotProduct(L, L) - (sphere.Radius ** 2)1112 discriminant = b*b - 4*a*c1314 if discriminant < 0:15 return [] # No intersection16 elif discriminant == 0:17 t = -b / (2*a)18 return [ray.PointAt(t)] # One hit (tangent)19 else:20 t1 = (-b + math.sqrt(discriminant)) / (2*a)21 t2 = (-b - math.sqrt(discriminant)) / (2*a)22 return [ray.PointAt(t1), ray.PointAt(t2)] # Two hits
SphereSphere(a, b):
1def SphereSphereIntersect(a: Sphere, b: Sphere) -> Circle:2 """Calculates the circle of intersection between two spheres."""3 # Vector from center A to center B4 dx = b.Center.X - a.Center.X5 dy = b.Center.Y - a.Center.Y6 dz = b.Center.Z - a.Center.Z7 d = math.sqrt(dx**2 + dy**2 + dz**2)89 # Check for no intersection10 if d > (a.Radius + b.Radius) or d < abs(a.Radius - b.Radius) or d == 0:11 return None1213 # Distance from center A to the circle plane14 x = (d**2 - b.Radius**2 + a.Radius**2) / (2 * d)1516 # Radius of the intersection circle17 circle_radius = math.sqrt(a.Radius**2 - x**2)1819 # Center of the intersection circle20 cx = a.Center.X + (dx / d) * x21 cy = a.Center.Y + (dy / d) * x22 cz = a.Center.Z + (dz / d) * x23 circle_center = Point3d(cx, cy, cz)2425 # Normal of the circle's plane26 normal = Vector3d(dx/d, dy/d, dz/d)2728 return Circle(circle_center, normal, circle_radius)
Contains:
1def SphereContains(sphere: 'Sphere', pt: 'Point3d', strict: bool) -> bool:2 """Checks if a point is inside a sphere."""34 # Calculate the distance from the point to the sphere's center5 dist = pt.DistanceTo(sphere.Center)67 # Compare with radius8 if strict:9 return dist < sphere.Radius10 else:11 return dist <= sphere.Radius
NormalAt(u, v):
(U, V) — where U is Azimuth/Longitude and V is Polar Angle/Colatitude.1def NormalAt(self, u_degrees: float, v_degrees: float) -> Vector3d:2 """3 Returns the unit outward normal vector at azimuth/longitude u (0°..360°)4 and polar angle/colatitude v (0°..180°).5 """6 u_rad = math.radians(u_degrees)7 v_rad = math.radians(v_degrees)8 x = math.sin(v_rad) * math.cos(u_rad)9 y = math.sin(v_rad) * math.sin(u_rad)10 z = math.cos(v_rad)1112 # The normal of a sphere is the unit vector from the center to the surface point13 return Vector3d(x, y, z)
N = (P - Center) / Radius.Tangent Plane:
(U, V), where U is Azimuth/Longitude and V is Polar Angle/Colatitude.1import math23# Consistent spherical parametrization:4# u = azimuth / longitude (0° to 360°)5# v = polar angle / colatitude (0° to 180°, where latitude = 90° - v)67def GetTangentPlane(sphere: Sphere, u_degrees: float, v_degrees: float) -> Plane:8 """Returns the tangent plane at spherical coordinates (u, v) on the sphere."""9 pt = sphere.PointAt(u_degrees, v_degrees)10 normal = sphere.NormalAt(u_degrees, v_degrees)1112 # Construct a local plane at pt with its Z-axis aligned to the outward normal13 return Plane(pt, normal)
Great Circle:
1def CreateGreatCircle(sphere: Sphere, ptA: Point3d, ptB: Point3d) -> Circle:2 """Creates the great circle passing through two points on a sphere."""34 # A Great Circle is created by slicing the sphere with a plane5 # that passes through the sphere's center and the two target points.67 # Plane through 3 points: Center, A, B8 plane = Plane(sphere.Center, ptA, ptB)910 # The great circle has the exact same radius as the sphere11 great_circle = Circle(plane, sphere.Radius)1213 return great_circle
ClosestPoint:
1def ClosestPoint(sphere: Sphere, test_pt: Point3d) -> Point3d:2 """Projects a point onto the sphere boundary."""3 # 1. Get direction from center4 dir = test_pt - sphere.Center5 if dir.Length < 1e-6:6 dir = Vector3d(1.0, 0.0, 0.0)7 # 2. Force length to match Radius8 dir.Unitize()9 return sphere.Center + (dir * sphere.Radius)
DistanceTo(point):
1def DistanceTo(self, pt: Point3d) -> float:2 """Calculates the shortest distance from a point to the surface of the sphere."""3 # Calculate distance from the test point to the center of the sphere4 dist_to_center = self.Center.DistanceTo(pt)56 # Subtract the radius. If the point is inside, this will be negative,7 # so we return max(0, distance) if we only want exterior distance.8 return max(0.0, dist_to_center - self.Radius)
Plane Intersection:
1def PlaneSphereIntersection(sphere: 'Sphere', plane: 'Plane') -> tuple[bool, 'Circle']:2 """Finds the circle of intersection between a sphere and a plane."""3 # Distance from sphere center to plane4 # Assuming plane is defined by an Origin and Normal5 vector_to_center = sphere.Center - plane.Origin6 dist = Vector3d.DotProduct(vector_to_center, plane.Normal)78 if abs(dist) > sphere.Radius:9 return False, None # No intersection1011 # Radius of the resulting intersection circle12 circle_radius = math.sqrt(sphere.Radius**2 - dist**2)1314 # Center of the intersection circle15 circle_center = sphere.Center - (plane.Normal * dist)1617 return True, Circle(Plane(circle_center, plane.Normal), circle_radius)
Box Intersection:
1def SphereIntersectsBox(sphere: 'Sphere', box_min: Point3d, box_max: Point3d) -> bool:2 """Checks if a sphere intersects an AABB by finding the closest point on the box to the sphere."""3 # Find closest point on box to sphere center4 closest_x = max(box_min.X, min(sphere.Center.X, box_max.X))5 closest_y = max(box_min.Y, min(sphere.Center.Y, box_max.Y))6 closest_z = max(box_min.Z, min(sphere.Center.Z, box_max.Z))78 # Check if distance to closest point is within radius9 closest_point = Point3d(closest_x, closest_y, closest_z)10 distance = sphere.Center.DistanceTo(closest_point)1112 return distance <= sphere.Radius
Bounding Box Extraction:
1def SphereBoundingBox(sphere: 'Sphere') -> 'BoundingBox':2 """Computes the Axis-Aligned Bounding Box (AABB) of a sphere."""3 # A sphere's AABB is perfectly symmetric around its center4 min_pt = Point3d(sphere.Center.X - sphere.Radius,5 sphere.Center.Y - sphere.Radius,6 sphere.Center.Z - sphere.Radius)78 max_pt = Point3d(sphere.Center.X + sphere.Radius,9 sphere.Center.Y + sphere.Radius,10 sphere.Center.Z + sphere.Radius)1112 return BoundingBox(min_pt, max_pt)
BoundingSphere(box):
1def BoundingSphere(bbox: BoundingBox) -> Sphere:2 """Creates a sphere that exactly bounds an Axis-Aligned Bounding Box."""3 # The center of the sphere is the center of the bounding box4 center = bbox.Center56 # The radius is the distance from the center to any of the box's corners7 radius = center.DistanceTo(bbox.Max)89 return Sphere(center, radius)
FitSphere(points):
1def FitSphere(pts: list[Point3d]) -> Sphere:2 """Calculates a bounding sphere for a collection of points."""3 # A simple bounding approach is taking the bounding box,4 # finding its center, and setting the radius to the farthest point.56 # 1. Find bounding box center7 min_pt, max_pt = GetBoundingBox(pts)8 center = Point3d(9 (min_pt.X + max_pt.X) / 2,10 (min_pt.Y + max_pt.Y) / 2,11 (min_pt.Z + max_pt.Z) / 212 )1314 # 2. Find the farthest point from the center15 max_dist = 0.016 for pt in pts:17 dist = center.DistanceTo(pt)18 if dist > max_dist:19 max_dist = dist2021 return Sphere(center, max_dist)
Related Concepts
The mathematical foundation of 1D spatial boundaries.
The mathematical foundation of smooth geometry — defined by control points and parameters to create infinite curvature.
A 2D topological space in a 3D world — defined by a UV control grid to create complex, warpable faces.