/* 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_lam_.h"

// A possible improvement is to center the lamella in the grain, to
// avoid getting tiny lamella at one end (supposing that the random
// value is very close to 0 or 1).
// Another improvement is to slightly modify the width to get full-width
// lamella at both ends.
void
net_seed_lam (char *width, struct TESS Dom, struct SEEDSET *pGSet)
{
  int i;
  double w, l, distmin, distmax;
  double *dist = ut_alloc_1d (Dom.VerQty + 1);

  gsl_rng *r;

  r = gsl_rng_alloc (gsl_rng_ranlxd2);
  gsl_rng_set (r, (*pGSet).Random);

  // Reading lamella width
  if (sscanf (width, "%lf", &w) != 1)
    ut_error_reportbug ();

  // Setting up equation of the first lamella
  (*pGSet).LamEq = ut_alloc_1d (4);

  // Setting normal (constant is 0)
  ol_nb_r (gsl_rng_uniform (r), gsl_rng_uniform (r), (*pGSet).LamEq + 1);

  for (i = 3; i > (*pGSet).Dim; i--)
    (*pGSet).LamEq[i] = 0;

  ut_array_1d_scale ((*pGSet).LamEq + 1, (*pGSet).Dim,
                     1. / ut_array_1d_norm ((*pGSet).LamEq + 1, (*pGSet).Dim));

  // Shifting the plane to the further down vertex, then adding random shift
  // between 0 and w
  for (i = 1; i <= Dom.VerQty; i++)
    ut_space_point_plane_dist_signed (Dom.VerCoo[i], (*pGSet).LamEq,
				      &(dist[i]));

  distmin = ut_array_1d_min (dist + 1, Dom.VerQty);
  distmax = ut_array_1d_max (dist + 1, Dom.VerQty);

  if (distmax - distmin < w)	// only one lamella
    (*pGSet).N = 1;
  else
  {
    (*pGSet).LamEq[0] = distmin;
    (*pGSet).LamEq[0] += gsl_rng_uniform (r) * w;

    // computing the number of lamella and recording it in (*pGSet).N
    // l is the distance between the first plane and the last vertex
    l = ut_array_1d_max (dist + 1, Dom.VerQty) - (*pGSet).LamEq[0];

    // 1 + to catch the first (partial) lamella;
    // ceil to catch the last (partial) lamella.
    (*pGSet).N = 1 + ceil (l / w);
  }

  (*pGSet).LamWidth = w;

  // Allocating SeedCoo and Size
  (*pGSet).SeedCoo = ut_alloc_2d ((*pGSet).N + 1, 3);
  (*pGSet).SeedWeight = ut_alloc_1d ((*pGSet).N + 1);
  (*pGSet).Size = ut_alloc_2d (3, 2);

  gsl_rng_free (r);
  ut_free_1d (dist);

  return;
}
