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

void
neut_poly_set_zero (struct POLY *pPoly)
{
  (*pPoly).VerQty = 0;
  (*pPoly).FaceQty = 0;

  (*pPoly).VerFace = NULL;
  (*pPoly).VerCoo = NULL;

  (*pPoly).FacePoly = NULL;
  (*pPoly).FaceEq = NULL;
  (*pPoly).FaceVerQty = NULL;
  (*pPoly).FaceVerNb = NULL;

  return;
}

void
neut_poly_free (struct POLY *pPoly)
{
  ut_free_2d_int ((*pPoly).VerFace, (*pPoly).VerQty + 1);
  ut_free_2d ((*pPoly).VerCoo, (*pPoly).VerQty + 1);

  ut_free_1d_int ((*pPoly).FacePoly);
  ut_free_2d ((*pPoly).FaceEq, (*pPoly).FaceQty + 1);
  ut_free_1d_int ((*pPoly).FaceVerQty);
  ut_free_2d_int ((*pPoly).FaceVerNb, (*pPoly).FaceQty + 1);

  return;
}

void
neut_poly_array_free (struct POLY **pPoly, int size)
{
  int i;

  if ((*pPoly) == NULL)
    return;

  for (i = 1; i <= size; i++)
    neut_poly_free (&((*pPoly)[i]));

  free (*pPoly);
  (*pPoly) = NULL;

  return;
}

void
neut_poly_bbox (struct POLY Poly, double *size)
{
  int i, j;

  size[1] = size[3] = size[5] = DBL_MAX;
  size[2] = size[4] = size[6] = -DBL_MAX;

  for (j = 0; j < 3; j++)
    for (i = 1; i <= Poly.VerQty; i++)
    {
      size[2 * j + 1] = ut_num_min (size[2 * j + 1], Poly.VerCoo[i][j]);
      size[2 * j + 2] = ut_num_max (size[2 * j + 2], Poly.VerCoo[i][j]);
    }

  return;
}

// rough centre
int
neut_poly_centre (struct POLY Poly, double *coo)
{
  int i, j;

  ut_array_1d_zero (coo, 3);
  for (j = 0; j < 3; j++)
  {
    for (i = 1; i <= Poly.VerQty; i++)
      coo[j] += Poly.VerCoo[i][j];

    coo[j] /= Poly.VerQty;
  }

  return 0;
}

int
neut_poly_point_in (struct POLY Poly, double *coo)
{
  int i;
  int status = 0;
  double *C = ut_alloc_1d (3);

  neut_poly_centre (Poly, C);

  status = 1;
  for (i = 1; i <= Poly.FaceQty; i++)
    if (ut_space_planeside (Poly.FaceEq[i], coo - 1)
	!= ut_space_planeside (Poly.FaceEq[i], C - 1))
    {
      status = 0;
      break;
    }

  ut_free_1d (C);

  return status;
}

void
neut_poly_fprintf_gmsh (FILE * file, struct POLY Poly, int beg)
{
  int i, j;

  beg--;

  for (i = 1; i <= Poly.VerQty; i++)
    fprintf (file, "Point (%d) = {%.12f,%.12f,%.12f};\n",
	     beg + i, Poly.VerCoo[i][0], Poly.VerCoo[i][1],
	     Poly.VerCoo[i][2]);

  int lineid = 1;
  for (i = 1; i <= Poly.FaceQty; i++)
  {
    int line1 = lineid;
    for (j = 1; j <= Poly.FaceVerQty[i]; j++)
    {
      fprintf (file, "Line (%d) = {%d,%d};\n",
	       beg + lineid++,
	       beg + Poly.FaceVerNb[i][j],
	       beg +
	       Poly.FaceVerNb[i][ut_num_rotpos
				 (1, Poly.FaceVerQty[i], j, 1)]);
    }

    fprintf (file, "Line Loop (%d) = {", i + beg);
    for (j = 1; j <= Poly.FaceVerQty[i]; j++)
    {
      fprintf (file, "%d%s", beg + line1 + j - 1,
	       (j < Poly.FaceVerQty[i]) ? "," : "");
    }
    fprintf (file, "};\n");
    fprintf (file, "Plane Surface (%d) = {%d}; ", beg + i, beg + i);
    fprintf (file, "Physical Surface (%d) = {%d};\n", beg + i, beg + i);
  }

  fprintf (file, "Surface Loop (%d) = {", beg + 1);
  for (j = 1; j <= Poly.FaceQty; j++)
    fprintf (file, "%d%s", j + beg, (j < Poly.FaceQty) ? "," : "");
  fprintf (file, "};\n");
  fprintf (file, "Volume (%d) = {%d}; ", beg + 1, beg + 1);

  return;
}
