/// <summary> /// Creates the smallest <see cref="BoundingSphere"/> that can contain a specified list of points in 3D-space. /// </summary> /// <param name="points">List of point to create the sphere from.</param> /// <returns>The new <see cref="BoundingSphere"/>.</returns> public static BoundingSphere CreateFromPoints(IEnumerable <Vector3> points) { if (points == null) { throw new ArgumentNullException("points"); } // From "Real-Time Collision Detection" (Page 89) Vector3 minx = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 maxx = -minx; Vector3 miny = minx; Vector3 maxy = -minx; Vector3 minz = minx; Vector3 maxz = -minx; // Find the most extreme points along the principle axis. int numPoints = 0; foreach (Vector3 pt in points) { numPoints += 1; if (pt.X < minx.X) { minx = pt; } if (pt.X > maxx.X) { maxx = pt; } if (pt.Y < miny.Y) { miny = pt; } if (pt.Y > maxy.Y) { maxy = pt; } if (pt.Z < minz.Z) { minz = pt; } if (pt.Z > maxz.Z) { maxz = pt; } } if (numPoints == 0) { throw new ArgumentException( "You should have at least one point in points." ); } float sqDistX = Vector3.DistanceSquared(maxx, minx); float sqDistY = Vector3.DistanceSquared(maxy, miny); float sqDistZ = Vector3.DistanceSquared(maxz, minz); // Pick the pair of most distant points. Vector3 min = minx; Vector3 max = maxx; if (sqDistY > sqDistX && sqDistY > sqDistZ) { max = maxy; min = miny; } if (sqDistZ > sqDistX && sqDistZ > sqDistY) { max = maxz; min = minz; } Vector3 center = (min + max) * 0.5f; float radius = Vector3.Distance(max, center); // Test every point and expand the sphere. // The current bounding sphere is just a good approximation and may not enclose all points. // From: Mathematics for 3D Game Programming and Computer Graphics, Eric Lengyel, Third Edition. // Page 218 float sqRadius = radius * radius; foreach (Vector3 pt in points) { Vector3 diff = (pt - center); float sqDist = diff.LengthSquared(); if (sqDist > sqRadius) { float distance = (float)Math.Sqrt(sqDist); // equal to diff.Length(); Vector3 direction = diff / distance; Vector3 G = center - radius * direction; center = (G + pt) / 2; radius = Vector3.Distance(pt, center); sqRadius = radius * radius; } } return(new BoundingSphere(center, radius)); }