MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

RE: Problem: Smallest sphere including all 3D points

  • To: mathgroup at smc.vnet.net
  • Subject: [mg16638] RE: Problem: Smallest sphere including all 3D points
  • From: "Barthelet, Luc" <lucb at ea.com>
  • Date: Fri, 19 Mar 1999 12:53:56 -0500
  • Sender: owner-wri-mathgroup at wolfram.com

It works. Thanks.
I sped it up slightly by testing for pairs, then triangles then tetra...

minimalCircumSphere[points_] := 
  Module[{pairs, triangles, tetrahedra, spheres, coveringSpheres}, 
    pairs = KSubsets[N[points], 2];
    spheres = Map[circumSphere, pairs];
coveringSpheres = 
      DeleteCases[spheres, s_ /; (! includesAllPoints[s, points]), 1];
If[Length[coveringSpheres] > 0, Return[First[Sort[coveringSpheres]]], 
      Print["Found no solution for pairs. "];];
    
    triangles = KSubsets[N[points], 3];
    spheres = Map[circumSphere, triangles];
coveringSpheres = 
      DeleteCases[spheres, s_ /; (! includesAllPoints[s, points]), 1];
If[Length[coveringSpheres] > 0, Return[First[Sort[coveringSpheres]]], 
      Print["Found no solution for triangles. "];];
    
    tetrahedra = KSubsets[N[points], 4];
    spheres = Map[circumSphere, tetrahedra];
coveringSpheres = 
      DeleteCases[spheres, s_ /; (! includesAllPoints[s, points]), 1];
If[Length[coveringSpheres] > 0, Return[First[Sort[coveringSpheres]]], 
      Print["Found no solution for tetrahedra. This is a bug "];]
    
    
    ]

it could be sped up further. you only need to test one sphere in each group
for covering, the largest.
with our data set, so far all solutions have been found in triangles.

This along with the convexHull3D from wouter fixed the problem. The
solutions we tested were 3 percent better than the approximation we were
using, we will probably switch to that method.
thanks to all of you for your help. (I receive about 20 emails on this from
people suggesting solutions, cool).

Luc Barthelet
General Manager, Maxis
http://www.simcity.com (SimCity 3000 is #1 Game on the PC in february
worldwide!)




-----Original Message-----
From: Martin Kraus [mailto:mkraus at theorie3.physik.uni-erlangen.de]
To: mathgroup at smc.vnet.net
Subject: [mg16638] Re: Problem: Smallest sphere including all 3D points


Barthelet, Luc wrote:
> 
> 
>  I was just asked by a friend how to find the smallest sphere that
>  would include all points from a set of 3D points.
>  It feels like finding a 3D convex hull and then finding the best
>  sphere (??)
>  I would appreciate any complete solution or best set of pointers...
> 
>         Thank you,
> 
>         Luc Barthelet
>         General manager, Maxis
>         http://www.simcity.com <http://www.simcity.com>  (we are #1!)
> 
> 

For any practical purpose your suggestions (realized with a
numerical minimization) is probably the best.
However, we found an algorithm for an "exact" solution.
The problem is in fact almost the same in two dimensions;
therefore, I will describe the algorithm in two dimensions first:

1) Take all pairs of points and calculate the minimal circle
covering each pair. (The radius of such a circle is just half
the distance between the pair of points, the center is the
midpoint between them.)

2) Take all triples of points and calculate the minimal circle
covering each triple. (That is just the circum circle.)

3) Throw away all circles which do not cover all points.

4) From the remaining circles take the one with the minimal
radius.

This algorithm guarantees to give the correct result. 
(Problems might arise from numerics, however.)

Here is a simple implementation in Mathematica:


<<DiscreteMath`Combinatorica`;

includesAllPoints[{radius_,center_},points_,epsilon_:10^-8]:=
  Module[{square=radius^2},
    Apply[And,Map[((#-center).(#-center)<=square+epsilon)&,points]]]

circumCircle[{p1_,p2_}]:=Module[{},{Sqrt[(p1-p2).(p1-p2)]/2.,(p1+p2)/2.}]

circumCircle[{p1_,p2_,p3_}]:=
 
Module[{n1=p1-p2,b1=N[(p1+p2)/2],n2=p3-p2,b2=N[(p3+p2)/2],nn1,nn2,x,y},
    nn1=N[n1/Sqrt[n1.n1]];
    nn2=N[n2/Sqrt[n2.n2]];{x,
       
y}={x,y}/.First[Solve[{({x,y}-b1).n1==0,({x,y}-b2).n2==0},{x,y}]];{
      Sqrt[(p2-{x,y}).(p2-{x,y})],{x,y}}]

minimalCircumCircle[points_]:=
  Module[{pairs,triangles,circles,coveringCircles},
    pairs=KSubsets[N[points],2];
			triangles=KSubsets[N[points],3];
    circles=Map[circumCircle,Join[triangles,pairs]];
   
coveringCircles=DeleteCases[circles,c_/;(!includesAllPoints[c,points]),1];
    If[Length[coveringCircles]>0,Return[First[Sort[coveringCircles]]],
      Print["Found no solution. (This is an error.)"];Abort[]]]



minimalCircumCircle[<list of points>] will return
the wanted circle in the form {<radius>, <center>}.
We can check the result with a simple function:

maxDistance[point_,points_]:=Max[Map[Sqrt[(point-#).(point-#)]&,points]]

maxDistance[<center>, <list of points>] should give the 
returned radius.

Warnings arise from identical points or three points on one line.
However, these warnings can be ignored.

The algorithm for three dimensions needs a small extension
but the basic idea is the same:

1) Take all pairs of points and calculate the minimal sphere
covering each pair. (The radius of such a sphere is just half
the distance between the pair of points, the center is the
midpoint between them.)

2) Take all triples of points and calculate the minimal sphere
covering each triple. (That is just the three dimensional 
continuation of the circum circle of the flat polygon.)

3) Take all quadruples of points and calculate the minimal sphere
covering each quadruple. (That is just the circum sphere.)

4) Throw away all spheres which do not cover all points.

5) From the remaining spheres take the one with the minimal
radius.


The implementation is:

<<DiscreteMath`Combinatorica`;

includesAllPoints[{radius_,center_},points_,epsilon_:10^-8]:=
  Module[{square=radius^2},
    Apply[And,Map[((#-center).(#-center)<=square+epsilon)&,points]]]

circumSphere[{p1_,p2_}]:=Module[{},{Sqrt[(p1-p2).(p1-p2)]/2.,(p1+p2)/2.}]

circumSphere[{p1_,p2_,p3_}]:=
 
Module[{n1=p1-p2,b1=N[(p1+p2)/2],n2=p3-p2,b2=N[(p3+p2)/2],n3,b3,nn1,nn2,nn3,
      x,y,z},n3=Cross[n1,n2];b3=N[p2];nn1=N[n1/Sqrt[n1.n1]];
    nn2=N[n2/Sqrt[n2.n2]];nn3=N[n3/Sqrt[n3.n3]];x;y;
    z;{x,y,z}={x,y,z}/.First[
         
Solve[{({x,y,z}-b1).n1==0,({x,y,z}-b2).n2==0,({x,y,z}-b3).n3==0},{x,
              y,z}]];{Sqrt[(p2-{x,y,z}).(p2-{x,y,z})],{x,y,z}}]

circumSphere[{p1_,p2_,p3_,p4_}]:=
  Module[{x,y,
      z},{x,y,z}={x,y,z}/.First[
          Solve[{({x,y,z}-p1).({x,y,z}-p1)==({x,y,z}-p2).({x,y,z}-
                     
p2),({x,y,z}-p1).({x,y,z}-p1)==({x,y,z}-p3).({x,y,z}-
                     
p3),({x,y,z}-p1).({x,y,z}-p1)==({x,y,z}-p4).({x,y,z}-
                      p4)}]];{Sqrt[({x,y,z}-p1).({x,y,z}-p1)],{x,y,z}}]

minimalCircumSphere[points_]:=
  Module[{pairs,triangles,tetrahedra,spheres,coveringSpheres},
    pairs=KSubsets[N[points],2];
	
triangles=KSubsets[N[points],3];tetrahedra=KSubsets[N[points],4];
    spheres=Map[circumSphere,Join[tetrahedra,triangles,pairs]];
   
coveringSpheres=DeleteCases[spheres,s_/;(!includesAllPoints[s,points]),1];
    If[Length[coveringSpheres]>0,Return[First[Sort[coveringSpheres]]],
      Print["Found no solution. (This is an error.)"];Abort[]]]


Checks of the result can be done as above. Note that both 
algorithms need extremely long for more than just a few (about 9)
points.
Therefore, this algorithm has probably no real world applications.

(This solution was created yesterday evening by Oliver Jahn, 
Martin Kraus, Verena Schoen and Christian Winkler; Mathematica 
implementation by Martin Kraus. No optimization was done; better 
algorithms and implementations are surely available.)

Greetings

Martin Kraus


  • Prev by Date: Viewpoint Scaling
  • Next by Date: Smallest sphere problem:final solution-again
  • Previous by thread: Re: Problem: Smallest sphere including all 3D points
  • Next by thread: Re: Re: Problem: Smallest sphere including all 3D points