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

int
net_tess_centroid_coo (struct TESS Tess, double **coo)
{
  int i;

  for (i = 1; i <= Tess.CellQty; i++)
    neut_tess_cell_centroid (Tess, i, coo[i]);

  return 0;
}

int
net_tess_centroid_test (int dim, struct TESS Tess, double** coo,
                        double centroidconv, double *prdistmax)
{
  int i;
  double dist, distmax, tesssize, avrad;

  neut_tess_size (Tess, &tesssize);
  tesssize /= Tess.CellQty;
  if (dim == 3)
    avrad = pow (tesssize / (4. / 3. * M_PI), 0.33333333);
  else if (dim == 2)
    avrad = sqrt (tesssize / M_PI);
  else if (dim == 1)
    avrad = .5 * tesssize;
  else
    abort ();

  distmax = 0;
  for (i = 1; i <= Tess.CellQty; i++)
  {
    dist = ut_space_dist (coo[i], Tess.SeedCoo[i]);
    distmax = ut_num_max (dist, distmax);
  }

  (*prdistmax) = distmax / avrad;

  /*
  printf ("tesssize = %f\n", tesssize);
  printf ("avrad = %f\n", avrad);
  printf ("distmax = %f\n", distmax);
  printf ("*prdistmax = %f\n", *prdistmax);
  abort ();
  */

  return ((*prdistmax) < centroidconv) ? 0 : 1;
}

int
net_tess_centroid_seedupdate (struct TESS Tess, double** coo,
                              double centroidfact, struct SEEDSET *pSeedSet)
{
  int i, j, id, cooqty = 0;
  int *cooid = ut_alloc_1d_int (3);

  if (!strcmp ((*pSeedSet).morpho, "columnar(x)"))
  {
    cooqty = 2;
    cooid[0] = 1;
    cooid[1] = 2;
  }
  else if (!strcmp ((*pSeedSet).morpho, "columnar(y)"))
  {
    cooqty = 2;
    cooid[0] = 0;
    cooid[1] = 2;
  }
  else if (!strcmp ((*pSeedSet).morpho, "columnar(z)"))
  {
    cooqty = 2;
    cooid[0] = 0;
    cooid[1] = 1;
  }
  else if (!strcmp ((*pSeedSet).morpho, "bamboo(x)"))
  {
    cooqty = 1;
    cooid[0] = 0;
  }
  else if (!strcmp ((*pSeedSet).morpho, "bamboo(y)"))
  {
    cooqty = 1;
    cooid[0] = 1;
  }
  else if (!strcmp ((*pSeedSet).morpho, "bamboo(z)"))
  {
    cooqty = 1;
    cooid[0] = 2;
  }
  else
  {
    cooqty = 3;
    cooid[0] = 0;
    cooid[1] = 1;
    cooid[2] = 2;
  }

  // if 1D/2D tessellation, disabling coordinates
  if ((*pSeedSet).Dim < 3)
    cooqty -= ut_array_1d_int_deletencompress (cooid, cooqty, 2, 1);

  if ((*pSeedSet).Dim < 2)
    cooqty -= ut_array_1d_int_deletencompress (cooid, cooqty, 1, 1);

  for (i = 1; i <= Tess.CellQty; i++)
    for (j = 0; j < cooqty; j++)
    {
      id = cooid[j];
      (*pSeedSet).SeedCoo[i][id] =
	(*pSeedSet).SeedCoo[i][id] * (1 - centroidfact) +
	coo[i][id] * centroidfact;
    }

  ut_free_1d_int (cooid);

  return 0;
}

int
net_tess_set_domain (struct TESS PTess, int poly, int TessId, struct MTESS *pMTess,
	  struct TESS *pTess)
{
  (*pMTess).TessDomVerNb
    = ut_realloc_1d_pint ((*pMTess).TessDomVerNb, TessId + 1);
  (*pMTess).TessDomEdgeNb
    = ut_realloc_1d_pint ((*pMTess).TessDomEdgeNb, TessId + 1);
  (*pMTess).TessDomFaceNb
    = ut_realloc_1d_pint ((*pMTess).TessDomFaceNb, TessId + 1);

  neut_tess_init_domain_poly (pTess, PTess, poly,
			      &((*pMTess).TessDomVerNb[TessId]),
			      &((*pMTess).TessDomEdgeNb[TessId]),
			      &((*pMTess).TessDomFaceNb[TessId]));

  int i, domface, pos;
  for (i = 1; i <= (*pTess).DomFaceQty; i++)
  {
    domface = (*pMTess).TessDomFaceNb[(*pTess).TessId][i];

    pos = ut_array_1d_int_eltpos (PTess.FacePoly[domface], 2, poly);
    if (pos == -1)
      ut_error_reportbug ();

    (*pMTess).DomTessFaceNb[PTess.TessId][domface][pos] = i;
  }

  return 0;
}

int
net_tess_finalize (struct TESS *pTess)
{
  // setting CellTrue and CellBody
  neut_tess_init_celltrue (pTess);
  neut_tess_init_cellbody (pTess);

#ifdef HAVE_DEBUGGING
  if ((*pTess).Dim > 1 && (neut_tess_test (*pTess, 0) != 0 ||
	neut_tess_test_dom (*pTess, 0) != 0))
    ut_print_message (2, 2, "The tessellation is not valid.\n");
#endif

  return 0;
}
