/* This file is part of the Neper software package. */
/* Copyright (C) 2003-2014, Romain Quey. */
/* See the COPYING file in the top-level directory. */

#include"net_seed_rand_.h"

/* net_seed_rand_coo initializes the variable: SeedCoo */
void
net_seed_rand_coo (int dim, char *morpho, int N, int Random,
		   char* hardcore, double **size,
		   struct TESS Domain, double **SeedCoo)
{
  int i, j, status, iter, iter_max = 1e5;
  double d;
  gsl_rng *r;

  // hardcore distance, d
  if (hardcore)
    ut_math_eval (hardcore, 0, NULL, NULL, &d);
  else
    d = 0;

  /* random number generator initialization */
  r = gsl_rng_alloc (gsl_rng_ranlxd2);
  gsl_rng_set (r, Random);

  for (i = 1; i <= N; i++)
  {
    iter = 1;
    status = 0;

    do
    {
      // don't change the below loop so as to keep 3 gsl_rng_uniform
      // calls per centre whatever the dimension is.
      for (j = 0; j < 3; j++)
	SeedCoo[i][j] =
	  size[j][0] + gsl_rng_uniform (r) * (size[j][1] - size[j][0]);

      // correcting the coordinates if needed --------------------------

      // morphology
      if (strcmp (morpho, "equiaxed") != 0 && strcmp (morpho, "poisson") != 0)
      {
	if (!strcmp (morpho, "columnar(x)"))
	  SeedCoo[i][0] = ut_array_1d_mean (size[0], 2);
	else if (!strcmp (morpho, "columnar(y)"))
	  SeedCoo[i][1] = ut_array_1d_mean (size[1], 2);
	else if (!strcmp (morpho, "columnar(z)"))
	  SeedCoo[i][2] = ut_array_1d_mean (size[2], 2);
	else if (!strcmp (morpho, "bamboo(x)"))
	{
	  SeedCoo[i][1] = ut_array_1d_mean (size[1], 2);
	  SeedCoo[i][2] = ut_array_1d_mean (size[2], 2);
	}
	else if (!strcmp (morpho, "bamboo(y)"))
	{
	  SeedCoo[i][2] = ut_array_1d_mean (size[2], 2);
	  SeedCoo[i][0] = ut_array_1d_mean (size[0], 2);
	}
	else if (!strcmp (morpho, "bamboo(z)"))
	{
	  SeedCoo[i][0] = ut_array_1d_mean (size[0], 2);
	  SeedCoo[i][1] = ut_array_1d_mean (size[1], 2);
	}
      }

      // dimension
      for (j = dim; j < 3; j++)
	SeedCoo[i][j] = .5 * (size[j][0] + size[j][1]);

      status = 1;

      // checking that the point is in the domain
      if (Domain.FaceQty > 0 && neut_tess_point_inpoly (Domain, SeedCoo[i], 1) == 0)
	status = 0;

      // applying the hardcore criterion
      else
      {
	if (d > 0)
	  for (j = 1; j < i; j++)
	    if (ut_space_dist (SeedCoo[i], SeedCoo[j]) < 2 * d)
	    {
	      status = 0;
	      break;
	    }
      }
    }
    while (!status && iter++ <= iter_max);

    if (!status)
      ut_print_message (2, 3,
	"Failed to distribute seeds >= %d with hardcore `%s'.\n", i, hardcore);
  }

  gsl_rng_free (r);

  return;
}
