topical media & game development

talk show tell print

basic-visual-07-MiniBall.c

? / basic-visual-07-MiniBall.c


  // ------------------------------------------------------------------------
  // This program is complementary material for the book:
  //
  // Frank Nielsen
  //
  // Visual Computing: Geometry, Graphics, and Vision
  //
  // ISBN: 1-58450-427-7
  //
  // Charles River Media, Inc.
  //
  //
  // All programs are available at www.charlesriver.com/visualcomputing/
  //
  // You may use this program for ACADEMIC and PERSONAL purposes ONLY. 
  //
  //
  // The use of this program in a commercial product requires EXPLICITLY
  // written permission from the author. The author is NOT responsible or 
  // liable for damage or loss that may be caused by the use of this program. 
  //
  // Copyright (c) 2005. Frank Nielsen. All rights reserved.
  // ------------------------------------------------------------------------
   
  // ------------------------------------------------------------------------
  // File: MiniBall.cpp
  // 
  // Description: Randomized Recursive Incremental Construction of the Smallest
  // Enclosing Ball of a Set of 2D Points.
  // ------------------------------------------------------------------------
  
  // Miniball: this is a pedagogical implementation. 
  // For efficient implementation, rather update the enclosing balls and consider square radii
  
  include <stdafx.h>
  include <math.h>
  
  using namespace std;
  
  typedef  long double number;
  
  class point {
  public: 
  number x,y;
  
  inline number Distance(point q)
  {return sqrt((q.x-x)*(q.x-x) + (q.y-y)*(q.y-y));}
  };
  
  class disc{
  public: 
  point circumcenter;
  number radius;
  };
  
  inline double drand(){return (double) rand () / RAND_MAX ;}
  
  inline SwapPoint(point& a, point& b)
  {point tmp; tmp=a; a=b; b=tmp;}
  
  // The unique circle passing through exactly three non-collinear points  p1, p2 ,p3
  void SolveDisc3(point p1, point p2, point p3, point & center, number &rad)
  {
  number a = p2.x - p1.x;
  number b = p2.y - p1.y;
  number c = p3.x - p1.x;
  number d = p3.y - p1.y;
  number e = a*(p2.x + p1.x)*0.5 + b*(p2.y + p1.y)*0.5;
  number f = (c*(p3.x + p1.x)*0.5) + (d*(p3.y + p1.y)*0.5);
  number det = a*d - b*c;    
  
  center.x = (d*e - b*f)/det;   
  center.y = (-c*e + a*f)/det;
  
  rad =p1.Distance(center);
  }
  
  // The smallest circle passing through two points
  void SolveDisc2(point p1, point p2, point & center, number &rad)
  {
  center.x = 0.5*(p1.x+p2.x);   
  center.y = 0.5*(p1.y+p2.y);
  
  rad =p1.Distance(center);
  }
  
  void MiniDisc(point* set, int n, point* basis, int b, point& center, number& rad)
  {
  point cl; number rl;
  int k;
  
  // Terminal cases
  if (b==3)  SolveDisc3(basis[0], basis[1], basis[2], cl, rl);
  
  if ((n==1)&&(b==0)) {rl=0.0; cl=set[0];}
  if ((n==2)&&(b==0))  SolveDisc2(set[0],set[1], cl, rl); 
  if ((n==0)&&(b==2))  SolveDisc2(basis[0],basis[1], cl, rl); 
  if ((n==1)&&(b==1))  SolveDisc2(basis[0], set[0], cl, rl); 
  
  // General case
  if ((b<3)&&(n+b>2))
          {
          // Randomization: choosing a pivot
          k=rand()\%n; // between 0 and n-1
          if (k!=0) SwapPoint(set[0],set[k]);
  
          MiniDisc(&set[1],n-1,basis,b,cl,rl);
  
          if (cl.Distance(set[0])>rl)
                  {
                  // Then set[0] necessarily belongs to the basis.
                          basis[b++]=set[0];
                          MiniDisc(&set[1],n-1,basis,b,cl,rl);
                  }        
          }
          center=cl;rad=rl;
  }
  
  // Example
  int _tmain(int argc, _TCHAR* argv[])
  {
  point *set, * basis, center;
  int i, b=0;
  number rad;
  int N=10000;
  
  cout<<"Visual Computing: Geometry, Graphics, and Vision (ISBN:1-58450-427-7)"<<endl;
  cout<<"Demo program\n\n"<<endl;
  
  cout<<"Compute the smallest enclosing ball of a 2D point set."<<endl;
  
  center.x=center.y=0;rad=0;
  set=new point[N];
  basis=new point[3];
  
  for(i=0;i<N;i++) {set[i].x=drand();set[i].y=drand(); 
                                  }
  
  cout <<"Randomized optimization: MiniDisc"<<endl;
  MiniDisc(set,N,basis,b, center, rad);
  
  cout <<"Center ("<<center.x<<","<<center.y<<") rad="<<rad<<endl;
  
  delete [] set;
  
  char line[256];
  cout<<"Press Return key"<<endl;
  gets(line);
  
          return 0;
  }
  
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.