/*******************************************************************************
+
+  LEDA 3.5
+
+  _gen_points.c
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#include <LEDA/d3_rat_point.h>
#include <math.h>


inline void add_point(integer x, integer y, integer z, list<d3_rat_point>& L)
{ d3_rat_point p(x,y,z,1);
  L.append(p);
 }


void  random_points_in_cube(int n, int maxc, list<d3_rat_point>& L)
{ L.clear();
  while (n--)
  { integer x = rand_int(-maxc,maxc);
    integer y = rand_int(-maxc,maxc);
    integer z = rand_int(-maxc,maxc);
    add_point(x,y,z,L);
   }
}


void  random_points_in_square(int n, int maxc, list<d3_rat_point>& L)
{ L.clear();
  while (n--)
  { integer x = rand_int(-maxc,maxc);
    integer y = rand_int(-maxc,maxc);
    add_point(x,y,0,L);
   }
}

void  random_points_on_segment(int n, int maxc, list<d3_rat_point>& L)
{ L.clear();
  while (n--)
  { integer x = rand_int(-maxc,maxc);
    add_point(x,x,x,L);
   }
}


void  random_points_in_ball(int n, int max_R, list<d3_rat_point>& L)
{ L.clear();
  int Q = 1;
  while (n--)
  { int R = rand_int(1,max_R)*Q;
    double phi1 = rand_int(0,2000) * LEDA_PI/1000;
    double phi2 = rand_int(0,2000) * LEDA_PI/1000;
    double z = cos(phi1);
    double r = sin(phi1);
    double x = r*cos(phi2);
    double y = r*sin(phi2);
    add_point(int(R*x),int(R*y),int(R*z),L);
   }
}


void  random_points_in_disc(int n, int max_R, list<d3_rat_point>& L)
{ L.clear();
  int Q = 1;
  while (n--)
  { int R = rand_int(1,max_R)*Q;
    double phi = rand_int(0,2000) * LEDA_PI/1000;
    double x = cos(phi);
    double y = sin(phi);
    add_point(int(R*x),int(R*y),10,L);
   }
}

void  points_on_paraboloid(int n, int maxc, list<d3_rat_point>& L)
{ L.clear();
  while (n--)
  { double x = rand_int(-maxc,maxc);
    double y = rand_int(-maxc,maxc);
    double z = 0.004*(x*x + y*y) - 1.25*maxc;
    add_point(int(x),int(y),int(z),L);
   }
}


void points_on_sphere(int m, int R, list<d3_rat_point>& L)
{
  int Q = 1;

  R *= Q;
 
  L.clear();

  m = 2*(int)sqrt(float(m));

  int n = m/2;

  list<vector> vl;

  vl.append(vector(0,0,+1));  // north
  vl.append(vector(0,0,-1));  // south


  int i;
  int j;
  double phi1 = 0;
  double phi2 = 0;
  double d1 = LEDA_PI/n;
  double d2 = LEDA_PI/n;

  for(phi1=d1, j=1; j<n; phi1+=d1, j++)
  { double z = cos(phi1);
    double r = sin(phi1);
    for(phi2=0, i=0; i<m; phi2+=d2, i++)
    { double x = r*cos(phi2);
      double y = r*sin(phi2);
      vl.append(vector(x,y,z));
     }
   }

  vector vec;
  forall(vec,vl)
  { //rotate(1.2,0.7,vec);
    add_point(int(R*vec[0]),int(R*vec[1]),int(R*vec[2]),L);
   }

}


void  lattice_points(int n, int maxc, list<d3_rat_point>& L)
{ 
  L.clear();

  int i = 1;
  while (i*i*i < n) i++;
  i--;

  if (i < 2) i = 2;

  int  d = 2*maxc/(i-1);

  for(int x = -maxc; x <= maxc; x += d)
     for(int y = -maxc; y <= maxc; y += d)
        for(int z = -maxc; z <= maxc; z += d)
            add_point(x,y,z,L);
}

