// File:	meshtriangle.cxx
// Created:	Tue Jun 11 17:40:33 1996
// Author:	Open CASCADE Support
//		<support@opencascade.com>
// Copyright:    Open CASCADE 2003

#include <meshtriangle.hxx>

#include <Triangle.hxx>

//=======================================================================
//function : BRepMesh_AddPoint
//purpose  : 
//=======================================================================

Standard_Boolean BRepMesh_AddPoint(const gp_Pnt2d& aPoint,
                                   const Standard_Integer anIndex)
{
  return triangle_AddPoint(aPoint.X(),aPoint.Y(),anIndex);
}

//=======================================================================
//function : BRepMesh_AddEdge
//purpose  : 
//=======================================================================

void BRepMesh_AddEdge(const TColStd_Array1OfInteger& aNodes,
                      const TopAbs_Orientation& anOrient,
                      const Standard_Boolean isFirst)
{
  triangle_AddEdge(&(aNodes.Value(1)),aNodes.Length(),
                   (anOrient == TopAbs_REVERSED ? 1 : 0),(int)isFirst);
}

//=======================================================================
//function : BRepMesh_Triangulate
//purpose  : 
//=======================================================================

Standard_Boolean BRepMesh_Triangulate(const TColgp_Array1OfPnt2d&    aNodes,
                                      const TColStd_Array1OfInteger& anIndices)
{
  Standard_Integer i, nbpoints = aNodes.Length();

  triangle_InitBehavior();

  triangle_InitMesh(nbpoints);

  for (i = 1; i <= nbpoints; i++)
  {
    const gp_Pnt2d& pnt = aNodes(i);
    triangle_AddPointIni(pnt.X(),pnt.Y(),anIndices(i));
  }

  return triangle_Triangulate();
}

//=======================================================================
//function : BRepMesh_InsertHoles
//purpose  : 
//=======================================================================

void BRepMesh_InsertHoles(const TColgp_SequenceOfPnt2d& aHoles)
{
  const Standard_Integer nbholes = aHoles.Length();
  if (nbholes)
  {
    const Standard_Integer nbreals = 2 * nbholes;

    Standard_Real *holelist = (Standard_Real *) malloc(nbreals * sizeof(double));
    if (holelist == (Standard_Real *) NULL)
    {
      Standard_Failure::Raise("BRepMesh_InsertHoles : Out of memory");
    }

    memset(holelist, 0, nbreals * sizeof(double));

    Standard_Integer i, j;
    for (i = 0, j = 1; i < nbreals; i++, j++)
    {
      const gp_Pnt2d& pnt = aHoles(j);
      holelist[i++] = pnt.X();
      holelist[i] = pnt.Y();
    }

    triangle_InsertHoles(holelist,nbholes);
  }
}

//=======================================================================
//function : BRepMesh_FinishTriangulation
//purpose  : 
//=======================================================================

Handle(Poly_Triangulation) BRepMesh_FinishTriangulation(Handle(TColStd_HArray1OfInteger)& anIndices,
                                                        const TopAbs_Orientation          anOrient)
{
  triangle_FinishTriangulation();
  Handle(Poly_Triangulation) aMesh = BRepMesh_GetTriangulation(anIndices, anOrient);
  BRepMesh_FreeTriangulation();
  return aMesh;
}

//=======================================================================
//function : BRepMesh_GetTriangulation
//purpose  : 
//=======================================================================

Handle(Poly_Triangulation) BRepMesh_GetTriangulation(Handle(TColStd_HArray1OfInteger)& anIndices,
                                                     const TopAbs_Orientation          anOrient)
{
  Handle(Poly_Triangulation) aMesh;

  // Read mesh size
  Standard_Integer nbnodes, nbtriangles;
  triangle_GetMeshSize(&nbnodes,&nbtriangles);
  if (nbnodes <= 0 || nbtriangles <= 0) return aMesh;

  aMesh = new Poly_Triangulation(nbnodes, nbtriangles, Standard_True);

  // Read nodes information
  anIndices = new TColStd_HArray1OfInteger(1, nbnodes);
  TColgp_Array1OfPnt2d& theNodes2d = aMesh->ChangeUVNodes();

  triangle_InitPoints();

  Standard_Real x, y;
  Standard_Integer pindex, pnumber = 1;
  while (triangle_NextPoint(pnumber,&x,&y,&pindex))
  {
    theNodes2d(pnumber).SetCoord(x,y);
    anIndices->SetValue(pnumber,pindex);
    pnumber++;
  }

  // Read triangles information
  Poly_Array1OfTriangle& theTriangles = aMesh->ChangeTriangles();

  triangle_InitTriangles();

  Standard_Integer p1, p2, p3, m1, m2, m3, pn, tnumber = 1;
  while (triangle_NextTriangle(&p1,&p2,&p3,&m1,&m2,&m3))
  {
    if (anOrient == TopAbs_REVERSED)
    {
      pn = p2; p2 = p3; p3 = pn;
    }
    theTriangles(tnumber++) = Poly_Triangle(p1,p2,p3);
  }

  return aMesh;
}

//=======================================================================
//function : BRepMesh_FreeTriangulation
//purpose  : 
//=======================================================================

void BRepMesh_FreeTriangulation()
{
  triangle_FreeTriangulation();
}
