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

void
neut_tess_init_domain_memcpy (struct TESS *pTess, struct TESS DomTess)
{
  int i;

  (*pTess).DomType = ut_alloc_1d_char (strlen (DomTess.DomType) + 1);
  strcpy ((*pTess).DomType, DomTess.DomType);

  // Faces

  (*pTess).DomFaceQty = DomTess.FaceQty;
  (*pTess).DomFaceEq = ut_alloc_2d ((*pTess).DomFaceQty + 1, 4);
  (*pTess).DomFaceVerQty = ut_alloc_1d_int ((*pTess).DomFaceQty + 1);
  (*pTess).DomFaceVerNb = ut_alloc_1d_pint ((*pTess).DomFaceQty + 1);
  (*pTess).DomFaceEdgeNb = ut_alloc_1d_pint ((*pTess).DomFaceQty + 1);

  for (i = 1; i <= (*pTess).DomFaceQty; i++)
    ut_array_1d_memcpy ((*pTess).DomFaceEq[i], 4, DomTess.FaceEq[i]);

  ut_array_1d_int_memcpy ((*pTess).DomFaceVerQty, (*pTess).DomFaceQty + 1,
			  DomTess.FaceVerQty);

  for (i = 1; i <= (*pTess).DomFaceQty; i++)
  {
    (*pTess).DomFaceVerNb[i] =
      ut_alloc_1d_int ((*pTess).DomFaceVerQty[i] + 1);
    (*pTess).DomFaceEdgeNb[i] =
      ut_alloc_1d_int ((*pTess).DomFaceVerQty[i] + 1);

    ut_array_1d_int_memcpy ((*pTess).DomFaceVerNb[i] + 1,
			    (*pTess).DomFaceVerQty[i],
			    DomTess.FaceVerNb[i] + 1);

    ut_array_1d_int_memcpy ((*pTess).DomFaceEdgeNb[i] + 1,
			    (*pTess).DomFaceVerQty[i],
			    DomTess.FaceEdgeNb[i] + 1);
  }

  // Edges
  (*pTess).DomEdgeQty = DomTess.EdgeQty;
  (*pTess).DomEdgeVerNb = ut_alloc_2d_int (DomTess.EdgeQty + 1, 2);
  (*pTess).DomEdgeFaceNb = ut_alloc_2d_int (DomTess.EdgeQty + 1, 2);

  for (i = 1; i <= (*pTess).DomEdgeQty; i++)
    ut_array_1d_int_memcpy ((*pTess).DomEdgeVerNb[i], 2,
			    DomTess.EdgeVerNb[i]);

  for (i = 1; i <= (*pTess).DomEdgeQty; i++)
  {
    ut_array_1d_int_memcpy ((*pTess).DomEdgeFaceNb[i], 2,
			    DomTess.EdgeFaceNb[i]);
    if (DomTess.EdgeFaceQty[i] != 2)
      ut_error_reportbug ();
  }

  // Vertices
  (*pTess).DomVerQty = DomTess.VerQty;
  (*pTess).DomVerEdgeQty = ut_alloc_1d_int (DomTess.VerQty + 1);
  (*pTess).DomVerEdgeNb = ut_alloc_1d_pint (DomTess.VerQty + 1);
  (*pTess).DomVerCoo = ut_alloc_2d (DomTess.VerQty + 1, 3);

  ut_array_1d_int_memcpy ((*pTess).DomVerEdgeQty + 1, (*pTess).DomVerQty,
			  DomTess.VerEdgeQty + 1);

  ut_array_2d_memcpy ((*pTess).DomVerCoo + 1, (*pTess).DomVerQty, 3,
			  DomTess.VerCoo + 1);

  for (i = 1; i <= (*pTess).DomVerQty; i++)
  {
    (*pTess).DomVerEdgeNb[i] = ut_alloc_1d_int ((*pTess).DomVerEdgeQty[i]);
    ut_array_1d_int_memcpy ((*pTess).DomVerEdgeNb[i],
			    (*pTess).DomVerEdgeQty[i], DomTess.VerEdgeNb[i]);
  }

  neut_tess_init_domain_label (pTess);

  return;
}


void
neut_tess_init_domain_label (struct TESS *pTess)
{
  if ((*pTess).Dim == 3)
    neut_tess_init_domain_label_3d (pTess);

  else if ((*pTess).Dim == 2)
    neut_tess_init_domain_label_2d (pTess);

  else if ((*pTess).Dim == 1)
    neut_tess_init_domain_label_1d (pTess);

  return;
}

void
neut_tess_init_domain_domedgevernb (struct TESS* pTess)
{
  int i, j, domedge;

  // Init DomEdgeVerNb
  (*pTess).DomEdgeVerNb = ut_alloc_2d_int ((*pTess).DomEdgeQty + 1, 3);

  for (i = 1; i <= (*pTess).DomVerQty; i++)
    for (j = 0; j < (*pTess).DomVerEdgeQty[i]; j++)
    {
      domedge = (*pTess).DomVerEdgeNb[i][j];
      if (ut_array_1d_int_eltpos ((*pTess).DomEdgeVerNb[domedge], 2, i) == -1)
      {
	if ((*pTess).DomEdgeVerNb[domedge][0] == 0)
	  (*pTess).DomEdgeVerNb[domedge][0] = i;
	else if ((*pTess).DomEdgeVerNb[domedge][1] == 0)
	  (*pTess).DomEdgeVerNb[domedge][1] = i;
	else
	  ut_error_reportbug ();
      }
    }

  int x, y;
  if (ut_array_2d_int_eltpos
      ((*pTess).DomEdgeVerNb + 1, (*pTess).DomEdgeQty, 2, 0, &x, &y) != -1)
    ut_error_reportbug ();

  return;
}

void
neut_tess_init_domain_domveredge (struct TESS *pTess)
{
  int i, j, ver;

  (*pTess).DomVerEdgeQty = ut_alloc_1d_int ((*pTess).DomVerQty + 1);
  (*pTess).DomVerEdgeNb = ut_alloc_1d_pint ((*pTess).DomVerQty + 1);
  for (i = 1; i <= (*pTess).DomEdgeQty; i++)
    for (j = 0; j < 2; j++)
    {
      ver = (*pTess).DomEdgeVerNb[i][j];
      (*pTess).DomVerEdgeQty[ver]++;
      (*pTess).DomVerEdgeNb[ver]
	= ut_realloc_1d_int ((*pTess).DomVerEdgeNb[ver],
			     (*pTess).DomVerEdgeQty[ver]);
      (*pTess).DomVerEdgeNb[ver][(*pTess).DomVerEdgeQty[ver] - 1] = i;
    }

  return;
}

void
neut_tess_init_domain_domedgeface (struct TESS *pTess)
{
  int i, j, edge;

  int* DomEdgeFaceQty = ut_alloc_1d_int ((*pTess).DomEdgeQty + 1);

  (*pTess).DomEdgeFaceNb = ut_alloc_1d_pint ((*pTess).DomEdgeQty + 1);
  for (i = 1; i <= (*pTess).DomFaceQty; i++)
    for (j = 1; j <= (*pTess).DomFaceVerQty[i]; j++)
    {
      edge = (*pTess).DomFaceEdgeNb[i][j];
      DomEdgeFaceQty[edge]++;
      (*pTess).DomEdgeFaceNb[edge]
	= ut_realloc_1d_int ((*pTess).DomEdgeFaceNb[edge],
			     DomEdgeFaceQty[edge]);
      (*pTess).DomEdgeFaceNb[edge][DomEdgeFaceQty[edge] - 1] = i;
    }

  ut_free_1d_int (DomEdgeFaceQty);

  return;
}
