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

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

int mshrt(Triangulo_T1* t0,int a10)
{ 
  Triangulo_T1* t1,*tv1,*tv2,*tv3,*tv4;
  Triangulo_T1 t2;
  Arista_T1* a0,*a1,*a2,*b0,*b1;
  Vertice_T1* s0,*s1,*s2,*s3;
  int p[3];
  int a11,a12;
  int a20,a21,a22;
  int aux,err,reft;
  int err0;
  Metrica mm1,mm2,m0i,m1i,m2i,m3i;
  R2 c0,c1,c2,c3;
  Scalar area1,area2;
  Scalar crit,crit1,crit2,critp;
  p[0]=1;p[1]=2;p[2]=0;
  
/*

               s2                                   s2
                x                                   x
               / \                                 /|\
              /   \                               / | \
             /     \                             /  |  \
            /       \                           /   |   \
   tv2  a2 /         \ a1  tv1              a2 /    |    \  a1
          /           \                       /     |     \
         /     t0      \                     /      |      \
        /               \                   /       |       \
       /                 \                 /        |        \
      /         a0        \               /         |         \
  s0 +---------------------+ s1       s0 +     t0   |a0   t1   + s1
      \                   /               \         |         /
       \                 /                 \        |        /
        \               /                   \       |       /
         \      t1     /                     \      |      /
          \           /                       \     |     /
           \         /                     b0  \    |    /  b1
    tv3 b0  \       /   tv4 b1                  \   |   /
             \     /                             \  |  /
              \   /                               \ | /
               \ /                                 \|/
                x                                   x 
                s3                                  s3

*/

  s0=t0->s[a10];
  t1=t0->t[a10];
  a0=t0->a[a10];
  a11=p[a10];
  a12=p[a11];
  s1=t0->s[a11];
  s2=t0->s[a12];
  a1=t0->a[a11];
  a2=t0->a[a12];
  tv1=t0->t[a11];
  tv2=t0->t[a12];
  
//   cout<<"mshrt 1. arista"<<endl;
  a20=t1->arista(a0);
  a21=p[a20];
  a22=p[a21];
  s3=t1->s[a22];
  b0=t1->a[a21];
  b1=t1->a[a22];
  tv3=t1->t[a21];
  tv4=t1->t[a22];
  
  
  err=1;
  c0=s0->c;
  c1=s1->c;
  c2=s2->c;
  c3=s3->c;
  
  t2.set(s0,s3,s2,NIL,NIL,NIL,NIL,NIL,NIL,0);
  area1=t2.area2D();
  t2.set(s1,s2,s3,NIL,NIL,NIL,NIL,NIL,NIL,0);
  area2=t2.area2D();
  if (area1>0 && area2>0) {
    m0i=s0->mtr.inv(err0);
    m1i=s1->mtr.inv(err0);
    m2i=s2->mtr.inv(err0);
    m3i=s3->mtr.inv(err0);
    //mm1=(s0->mtr+s1->mtr+s2->mtr)/3.0;
    //mm2=(s0->mtr+s1->mtr+s3->mtr)/3.0;
    mm1=((m0i+m1i+m2i)/3.0).inv(err0);
    mm2=((m0i+m1i+m3i)/3.0).inv(err0);
    if (t0->krit==-999.) t0->krit=criter(c0,c1,c2,mm1);
    if (t1->krit==-999.) t1->krit=criter(c0,c1,c3,mm2);
    crit=MIN(t0->krit,t1->krit);
/*
  if (crit<=0) {
  cout <<"Error mshrt. Criterio negativo o cero "<<endl;
  cout<<*t0<<endl<<normal1<<endl<<*t1<<endl<<normal2<<endl;
  //exit (1);
  }
  */
    //mm1=(s2->mtr+s3->mtr+s0->mtr)/3.0;
    //mm2=(s2->mtr+s3->mtr+s1->mtr)/3.0;
    mm1=((m2i+m3i+m0i)/3.0).inv(err0);
    mm2=((m2i+m3i+m1i)/3.0).inv(err0);
    crit1=criter(c0,c3,c2,mm1);
    crit2=criter(c1,c3,c2,mm2);
    critp=MIN(crit1,crit2);
    if (critp<0) {
      cout<<"Error. negative triangle quality"<<endl;
      cout<<"Error in mshrt."<<endl;
      exit (1);
    }
    if (crit<critp) {
      t0->krit=crit1;
      t1->krit=crit2;
      
      // cambios en los vertices.
      
      s0->t=t0;
      s1->t=t1;
      
      // cambios en las aristas.
      
      a0->s[0]=s3;
      a0->s[1]=s2;
      
      b0->tr=t0;
      a1->tr=t1;
      
      //cambios en los triangulos.
      
      if (tv3) {
        aux=tv3->arista(b0);
        if (aux==-1)  {
          cerr<<"Error in mshrt"<<endl;
          exit (1);
          
        }
        else {
          tv3->t[aux]=t0;
        }
      }
      if (tv1) {
        aux=tv1->arista(a1);
        if (aux==-1) {
          cerr<<"Error in mshrt"<<endl;
          exit(1);
        }
        else {
          tv1->t[aux]=t1;
        }
      }
      
      // finalmente los triangulos t0 y t1.
      
      reft=t0->ref;
      t0->set(s0,s3,s2,tv3,t1,tv2,b0,a0,a2,reft);
      reft=t1->ref;
      t1->set(s1,s2,s3,tv1,t0,tv4,a1,a0,b1,reft);
      err=2;
    }
  }
  return err;
}
