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

int
net_tess1d (struct TESS Dom, int edge, struct SEEDSET SeedSet,
	    int TessId, struct TESS *pTess)
{
  int i, ver, seed1, seed2;
  double **bbox = ut_alloc_2d (3, 2);
  double *SeedCoo = NULL;
  int *id = NULL;		//id[i] indicates the rank of seed i (x-position)

  // computing the bounding box of the domain
  neut_tess_edge_bbox (Dom, edge, bbox);

  // General information

  (*pTess).Level = 1;
  (*pTess).TessId = SeedSet.Id;
  (*pTess).CellQty = SeedSet.N;
  (*pTess).Dim = 1;
  (*pTess).TessId = TessId;

  (*pTess).SeedCoo = ut_alloc_2d ((*pTess).CellQty + 1, 3);
  ut_array_2d_memcpy ((*pTess).SeedCoo + 1, (*pTess).CellQty, 3,
		      SeedSet.SeedCoo + 1);

  (*pTess).SeedWeight = ut_alloc_1d ((*pTess).CellQty + 1);
  ut_array_1d_memcpy ((*pTess).SeedWeight + 1, (*pTess).CellQty,
		      SeedSet.SeedWeight + 1);

  // Applying tessellation

  id = ut_alloc_1d_int ((SeedSet.N + 1));

  SeedCoo = ut_alloc_1d (SeedSet.N + 1);
  for (i = 1; i <= SeedSet.N; i++)
    SeedCoo[i] = SeedSet.SeedCoo[i][0];

  ut_array_1d_sort_index (SeedCoo + 1, SeedSet.N, id + 1);
  ut_array_1d_int_addval (id + 1, SeedSet.N, 1, id + 1);

  // Vertices

  (*pTess).VerQty = SeedSet.N + 1;
  (*pTess).VerState = ut_alloc_1d_int ((*pTess).VerQty + 1);

  (*pTess).VerDom = ut_alloc_2d_int ((*pTess).VerQty + 1, 2);
  ut_array_2d_int_set ((*pTess).VerDom + 1, (*pTess).VerQty, 2, -1);

  (*pTess).VerCoo = ut_alloc_2d ((*pTess).VerQty + 1, 3);
  (*pTess).VerEdgeQty = ut_alloc_1d_int ((*pTess).VerQty + 1);
  (*pTess).VerEdgeNb = ut_alloc_2d_int ((*pTess).VerQty + 1, 2);

  (*pTess).VerCoo[1][0] = bbox[0][0];
  (*pTess).VerEdgeQty[1] = 1;
  (*pTess).VerEdgeNb[1][0] = id[1];
  (*pTess).VerDom[1][0] = 0;
  (*pTess).VerDom[1][1] = 1;

  for (i = 2; i < (*pTess).VerQty; i++)
  {
    seed1 = id[i - 1];
    seed2 = id[i];

    (*pTess).VerCoo[i][0] =
      .5 * ((SeedCoo[seed1] + SeedCoo[seed2])
	  - (pow ((*pTess).SeedWeight[seed1], 2)
	     - pow ((*pTess).SeedWeight[seed2], 2))
	  / (SeedCoo[seed1] - SeedCoo[seed2]));

    (*pTess).VerEdgeQty[i] = 2;
    (*pTess).VerEdgeNb[i][0] = seed1;
    (*pTess).VerEdgeNb[i][1] = seed2;
  }

  (*pTess).VerCoo[(*pTess).VerQty][0] = bbox[0][1];
  (*pTess).VerEdgeQty[(*pTess).VerQty] = 1;
  (*pTess).VerEdgeNb[(*pTess).VerQty][0] = id[SeedSet.N];
  (*pTess).VerDom[(*pTess).VerQty][0] = 0;
  (*pTess).VerDom[(*pTess).VerQty][1] = 2;

  // Edges

  (*pTess).EdgeQty = SeedSet.N;
  (*pTess).EdgeState = ut_alloc_1d_int ((*pTess).EdgeQty + 1);
  (*pTess).EdgeDel = ut_alloc_1d_int ((*pTess).EdgeQty + 1);
  (*pTess).EdgeDom = ut_alloc_2d_int ((*pTess).EdgeQty + 1, 2);
  ut_array_2d_int_set ((*pTess).EdgeDom + 1, (*pTess).EdgeQty, 2, -1);
  (*pTess).EdgeFaceQty = ut_alloc_1d_int ((*pTess).EdgeQty + 1);

  neut_tess_init_edgetopo_fromver (pTess);

  neut_tess_init_edgelength (pTess);

  // Domain 

  ut_string_string ("line", &((*pTess).DomType));
  (*pTess).DomVerQty = 2;
  (*pTess).DomVerLabel = ut_alloc_2d_char (3, 3);
  (*pTess).DomVerCoo = ut_alloc_2d (3, 3);
  strcpy ((*pTess).DomVerLabel[1], "x0");
  strcpy ((*pTess).DomVerLabel[2], "x1");
  (*pTess).DomVerEdgeQty = ut_alloc_1d_int (3);
  (*pTess).DomTessVerNb = ut_alloc_1d_int (3);
  (*pTess).DomTessVerNb[1] = 1;
  (*pTess).DomTessVerNb[2] = (*pTess).VerQty;

  for (i = 1; i <= 2; i++)
  {
    ver = (*pTess).DomTessVerNb[i];
    ut_array_1d_memcpy ((*pTess).DomVerCoo[i], 3, (*pTess).VerCoo[ver]);
  }

  (*pTess).DomEdgeQty = 0;
  (*pTess).DomFaceQty = 0;

  ut_free_2d (bbox, 3);
  ut_free_1d (SeedCoo);
  ut_free_1d_int (id);

  return 0;
}
