/*
 * 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
 */


#include <header.hxx>
#include <t_t1_dl.hxx>
#include <v_t1.hxx>
#include <front_t1.hxx>
#include <m_t0.hxx>


extern Scalar criter (R2,R2,R2,Metrica);

void   mshreg1(Triangulo_T1_dlist* t_vec, Vertice_T1* so,
	       Scalar crit_min,Mallado_T0* malla,Scalar hwall,
               int refwall,Scalar owall,Frontera_T1* frontera) {
  Triangulo_T1_dlink* Lt_lk;
  Triangulo_T1* t0;
  Triangulo_T0* t0_so,*tri0=malla->saca_triangle(0);
  Triangulo_T1 t_aux;
  Arista_T1 a_aux;
  Metrica mm,mtr0;
  R2 coor[3];
  R2 co_so,despl,pt_pr;
  R2 cor2;
  Scalar* criterios;
  Scalar dist=1e+30;
  Scalar depx,depy;
  Scalar bx,by;
  Scalar area;
  Scalar lg;
  Scalar hreg;
  int num_it=10;
  int p_pos[3];
  int num;
  int conta,err=0,err0;
  int cont=0,i;
  int t_ini,t_fin;
  Boolean area_negativa=FALSE;

  p_pos[0]=1;p_pos[1]=2;p_pos[2]=0;

  num=t_vec->num_elem();
  criterios=new Scalar[num];
  if (criterios==NIL) ERROR();
  conta=0;
  co_so=so->c;
  t0_so=so->t0;
  mtr0=so->mtr;
  cor2.set(0,0);
  cont=0;
  hreg=hwall*so->fluid;
  lg=frontera->d_frontera(so->c,pt_pr,a_aux,t_aux,dist,refwall);
  cor2.set(pt_pr.x-so->c.x,pt_pr.y-so->c.y);
  lg=cor2.norma();
  if (fabs(lg)<1e-20) {
    cerr<<"Error en mshreg0. Punto en la frontera. lg=0."<<endl;
    cor2.set(0,0);
  }
  else {	      
    cor2=(cor2/lg)*(hreg-lg)*owall;
  }
  depx=cor2.x;
  depy=cor2.y;
  Lt_lk=t_vec->principio(); 
  while (Lt_lk) {
    t0=Lt_lk->t;
    criterios[conta]=t0->krit;
    conta++;
    Lt_lk=Lt_lk->sig();
  }
  cont=0;
  do {
    err=0;
    area_negativa=FALSE;
    bx=co_so.x-depx;
    by=co_so.y-depy;
    despl.set(bx,by);
    so->c=despl;
    t_ini=((so->t0)-tri0);
    so->mtr=malla->metrica(so->c,t_ini,t_fin);
    so->t0=malla->saca_triangle(t_fin);
    Lt_lk=t_vec->principio();
    conta=0;
    while (Lt_lk) {             
      t0=Lt_lk->t;
      area=t0->area2D();
      if (area<=0) {
        //if (ang0>45 && area>0) cout<<"mshreg0:"<<ang0<<endl;
        area_negativa=TRUE;
        cont++;
        depx=depx*pow(0.8,cont);
        depy=depy*pow(0.8,cont);
        err=1;
        break; 
      }
      else {
        mm.set(0,0,0);
        for (i=0;i<3;i++) {
          mm=mm+(t0->s[i]->mtr.inv(err0))/3.0;
          coor[i]=t0->s[i]->c;
        } 
        mm=mm.inv(err0);
        t0->krit=criter(coor[0],coor[1],coor[2],mm); 
        if (t0->krit<crit_min) { 
          cont++;
          depx=depx*pow(0.8,cont);
          depy=depy*pow(0.8,cont);
          err=1;
          break;
        }
      }
      conta++;
      Lt_lk=Lt_lk->sig();
    }
  } while (area_negativa==TRUE && cont<num_it-1);
  if (err) {
    conta=0;
    so->c=co_so;
    so->t0=t0_so;
    so->mtr=mtr0;
    Lt_lk=t_vec->principio();
    while (Lt_lk) {
      t0=Lt_lk->t;              
      t0->krit=criterios[conta];
      conta++; 
      Lt_lk=Lt_lk->sig();
    }
  }
  delete[] criterios;
}
