/*
 * ADAPT2D : a software for automatic mesh adaptation in 2D
 *
 * AUTHOR : Manuel J. Castro Diaz(e-mail:castro@gamba.cie.uma.es)
 * ADAPTED FOR FREEFEM : Prud'homme Christophe (e-mail:prudhomm@ann.jussieu.fr) 
 *
 * this code is public domain
 * 
 * You may copy freely these files and use it for    
 * teaching or research. These or part of these may   
 * not be sold or used for a commercial purpose without
 * our consent
 * 
 * Any problems should be reported to the AUTHOR
 * at the following address : castro@gamba.cie.uma.es
 */


#ifndef _Triangulation_h
#define _Triangulation_h



#include <header.hxx>
#include <r2.hxx>

#if !defined(TRIANGULATION_TYPEDEFS)
#define TRIANGULATION_TYPEDEFS
typedef struct
{
 float x;
 float y;
}rpoint;

typedef long triangle[3];

typedef struct
{
 long np, nt;
 rpoint *rp;
 triangle *tr;
 int* ngt;
 int* ng;
}triangulation;
#endif /* TRIANGULATION_TYPEDEFS */



class Mesh_characteristic {
public:
  R2 df[2];
  Scalar ed_min;
  Scalar ed_max;
  Scalar scale;
  Mesh_characteristic() {
    df[0].set(1e+30,1e+30);
    df[1].set(-1e+30,-1e+30);
    ed_min=1e+30;
    ed_max=-1e-30;
    scale=1.0;
  }
  Mesh_characteristic& operator=(const Mesh_characteristic& mm) { 
    df[0]=mm.df[0];df[1]=mm.df[1];
    ed_min=mm.ed_min;ed_max=mm.ed_max;scale=mm.scale;
    return (*this);
  }
};

class Triangulation {
public:
  long np, nt;
  rpoint *rp;
  triangle *tr;
  int* ngt;
  int* ng;
  
  Triangulation():np(0), nt(0), rp(NULL), tr(NULL), ngt(NULL), ng(NULL) {}
  void set(int nbs, int nbt) {
    this->clear();
    np=long(nbs);
    nt=long(nbt);
    rp=new rpoint[int(np)];
    tr=new triangle[int(nt)];
    ngt=new int[nt];
    ng=new int[np];
    if (rp==NULL || tr==NULL || ngt==NULL || ng==NULL) ERROR();
  }
  int build (char*);
  void build(long,long,rpoint*, int*, triangle*, int*);
  void write (char*);
  Mesh_characteristic* characteristic(); 
  void clear() {
    if (np!=0 || nt!=0) {
      np=0;
      nt=0;
      if (rp) delete[] rp;
      if (tr) delete[] tr;
      if (ngt) delete[] ngt;
      if (ng) delete[] ng;
      rp=NULL; tr=NULL; ngt=NULL; ng=NULL;
    }
  }
  ~Triangulation() {this->clear();}
  void operator delete (void* p) {
    if (p) {
      ((Triangulation*)p)->clear();
      delete p; p=NULL;
    }
  } 
  
};


#endif
