Salome HOME
NRI : First integration.
[modules/smesh.git] / src / MEFISTO2 / aptrte.cxx
diff --git a/src/MEFISTO2/aptrte.cxx b/src/MEFISTO2/aptrte.cxx
new file mode 100755 (executable)
index 0000000..58da981
--- /dev/null
@@ -0,0 +1,760 @@
+using namespace std;
+#include "Rn.h"
+#include "aptrte.h"
+#include "utilities.h"
+
+extern "C"
+{
+  R aretemaxface_;
+  R areteideale_( R3 xyz, R3 direction )
+  {
+    return aretemaxface_;
+  }
+}
+//calcul de la longueur ideale de l'arete au sommet xyz (z ici inactif)
+//dans la direction donnee
+//a ajuster pour chaque surface plane et selon l'entier notysu (voir plus bas)
+
+
+static double cpunew, cpuold=0;
+
+void tempscpu_( double & tempsec )
+//Retourne le temps CPU utilise en secondes
+{  
+  tempsec = ( (double) clock() ) / CLOCKS_PER_SEC;
+  //MESSAGE( "temps cpu=" << tempsec );
+}
+
+
+void deltacpu_( R & dtcpu )
+//Retourne le temps CPU utilise en secondes depuis le precedent appel
+{
+  tempscpu_( cpunew );
+  dtcpu  = R( cpunew - cpuold );
+  cpuold = cpunew;
+  //MESSAGE( "delta temps cpu=" << dtcpu );
+  return;
+}
+
+
+void  aptrte( Z nutysu, R aretmx,
+             Z nblf,   Z * nudslf, R2 * uvslf,
+             Z nbpti,  R2 *uvpti,
+             Z & nbst, R2 * & uvst, Z & nbt, Z * & nust,
+             Z & ierr )
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// but : appel de la triangulation par un arbre-4 recouvrant
+// ----- de triangles equilateraux
+//       le contour du domaine plan est defini par des lignes fermees
+//       la premiere ligne etant l'enveloppe de toutes les autres
+//       la fonction areteideale(s,d) donne la taille d'arete
+//       au point s dans la direction (actuellement inactive) d
+//       des lors toute arete issue d'un sommet s devrait avoir une longueur
+//       comprise entre 0.65 areteideale_(s,d) et 1.3 areteideale_(s,d)
+//
+//Attention:
+//  Les tableaux uvslf et uvpti sont supposes ne pas avoir de sommets identiques!
+//  De meme, un sommet d'une ligne fermee ne peut appartenir a une autre ligne fermee
+//
+// entrees:
+// --------
+// nutysu : numero de traitement de areteideale_(s,d) selon le type de surface
+//          0 pas d'emploi de la fonction areteideale_() et aretmx est active
+//          1 il existe une fonction areteideale_(s,d)
+//            dont seules les 2 premieres composantes de uv sont actives
+//          ... autres options a definir ...
+// aretmx : longueur maximale des aretes de la future triangulation
+// nblf   : nombre de lignes fermees de la surface
+// nudslf : numero du dernier sommet de chacune des nblf lignes fermees
+//          nudslf(0)=0 pour permettre la difference sans test
+//          Attention le dernier sommet de chaque ligne est raccorde au premier
+//          tous les sommets et les points internes ont des coordonnees
+//          UV differentes <=> Pas de point double!
+// uvslf  : uv des nudslf(nblf) sommets des lignes fermees
+// nbpti  : nombre de points internes futurs sommets de la triangulation
+// uvpti  : uv des points internes futurs sommets de la triangulation
+//
+// sorties:
+// --------
+// nbst   : nombre de sommets de la triangulation finale
+// uvst   : coordonnees uv des nbst sommets de la triangulation
+// nbt    : nombre de triangles de la triangulation finale
+// nust   : 4 numeros dans uvst des sommets des nbt triangles
+//          s1, s2, s3, 0: no dans uvst des 3 sommets et 0 car quadrangle!
+// ierr   : 0 si pas d'erreur
+//        > 0 sinon
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// auteur : Alain Perronnet  Analyse Numerique Paris UPMC   decembre 2001
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+{
+  R  d, tcpu=0;
+  R3 direction=R3(0,0,0);  //direction pour areteideale() inactive ici!
+  Z  nbarfr=nudslf[nblf];  //nombre total d'aretes des lignes fermees
+  Z  mxtrou = Max( 1024, nblf );  //nombre maximal de trous dans la surface
+
+  R3 *mnpxyd=NULL;
+  Z  *mnsoar=NULL, mosoar=7, mxsoar, n1soar; //le hachage des aretes
+  Z  *mnartr=NULL, moartr=3, mxartr, n1artr; //le no des 3 aretes des triangles
+  Z  *mntree=NULL, motree=9, mxtree;   //L'arbre 4 de TE et nombre d'entiers par TE
+  Z  *mnqueu=NULL, mxqueu;
+  Z  *mn1arcf=NULL;
+  Z  *mnarcf=NULL, mxarcf;
+  Z  *mnarcf1=NULL;
+  Z  *mnarcf2=NULL;
+  Z  *mnarcf3=NULL;
+  Z  *mntrsu=NULL;
+  Z  *mndalf=NULL;
+  Z  *mnslig=NULL;
+  Z  *mnarst=NULL;
+  Z  *mnlftr=NULL;
+
+  R3 comxmi[2];            //coordonnees UV Min et Maximales
+  R  aremin, aremax;       //longueur minimale et maximale des aretes
+  R  quamoy, quamin;
+
+  Z  noar0, noar, na;
+  Z  i, l, n, ns, ns0, ns1, ns2, nosotr[3], nt;
+  Z  mxsomm, nbsomm, nbarpi, nbarli, ndtri0, mn;
+  Z  moins1=-1;
+
+  aretemaxface_ = aretmx;
+
+  // initialisation du temps cpu
+  deltacpu_( d );
+  ierr = 0;
+
+  // quelques reservations de tableaux pour faire les calculs
+  // ========================================================
+  // le tableau pointeur sur la premiere arete de chaque ligne fermee
+  if( mndalf!=NULL ) delete [] mndalf;
+  mndalf = new Z[1+nblf];
+  if( mndalf==NULL ) goto ERREUR;
+  mndalf[0]=0;
+
+  // declaration du tableau des coordonnees des sommets de la frontiere
+  // puis des sommets internes ajoutes
+  // majoration empirique du nombre de sommets de la triangulation
+  i =  4*nbarfr/10;
+  mxsomm = Max( 20000, 64*nbpti+i*i );
+  MESSAGE( "APTRTE: Depart de la triangulation avec " );
+  MESSAGE( "nutysu=" << nutysu << "  aretmx=" << aretmx << "  mxsomm=" << mxsomm );
+
+ NEWDEPART:
+  //mnpxyd( 3, mxsomm ) les coordonnees UV des sommets et la taille d'arete aux sommets
+  if( mnpxyd!=NULL ) delete [] mnpxyd;
+  mnpxyd = new R3[mxsomm];
+  if( mnpxyd==NULL ) goto ERREUR;
+
+  // le tableau mnsoar des aretes des triangles
+  // 1: sommet 1 dans pxyd,
+  // 2: sommet 2 dans pxyd,
+  // 3: numero de 1 a nblf de la ligne qui supporte l'arete
+  // 4: numero dans mnartr du triangle 1 partageant cette arete,
+  // 5: numero dans mnartr du triangle 2 partageant cette arete,
+  // 6: chainage des aretes frontalieres ou internes ou
+  //    des aretes simples des etoiles de triangles,
+  // 7: chainage du hachage des aretes
+  // nombre d'aretes = 3 ( nombre de sommets - 1 + nombre de trous )
+  // pour le hachage des aretes mxsoar doit etre > 3*mxsomm!
+  // h(ns1,ns2) = min( ns1, ns2 )
+  if( mnsoar!=NULL ) delete [] mnsoar;
+  mxsoar = 3 * ( mxsomm + mxtrou );
+  mnsoar = new Z[mosoar*mxsoar];
+  if( mnsoar==NULL ) goto ERREUR;
+  //initialiser le tableau mnsoar pour le hachage des aretes
+  insoar_( mxsomm, mosoar, mxsoar, n1soar, mnsoar );
+
+  // mnarst( mxsomm ) numero mnsoar d'une arete pour chacun des sommets
+  if( mnarst!=NULL ) delete [] mnarst;
+  mnarst = new Z[1+mxsomm];
+  if( mnarst==NULL ) goto ERREUR;
+  n = 1+mxsomm;
+  azeroi_( n, mnarst );
+
+  // mnslig( mxsomm ) no de sommet dans sa ligne pour chaque sommet frontalier
+  //               ou no du point si interne forc'e par l'utilisateur
+  //               ou  0 si interne cree par le module
+  if( mnslig!=NULL ) delete [] mnslig;
+  mnslig = new Z[mxsomm];
+  if( mnslig==NULL ) goto ERREUR;
+  azeroi_( mxsomm, mnslig );
+
+  // initialisation des aretes frontalieres de la triangulation future
+  // renumerotation des sommets des aretes des lignes pour la triangulation
+  // mise a l'echelle des coordonnees des sommets pour obtenir une
+  // meilleure precision lors des calculs + quelques verifications
+  // boucle sur les lignes fermees qui forment la frontiere
+  // ======================================================================
+  noar = 0;
+  aremin = 1e100;
+  aremax = 0;
+
+  for (n=1; n<=nblf; n++)
+  {
+    //l'initialisation de la premiere arete de la ligne n dans la triangulation
+    //-------------------------------------------------------------------------
+    //le sommet ns0 est le numero de l'origine de la ligne
+    ns0 = nudslf[n-1];
+    mnpxyd[ns0].x = uvslf[ns0].x;
+    mnpxyd[ns0].y = uvslf[ns0].y;
+    mnpxyd[ns0].z = areteideale_( mnpxyd[ns0], direction );
+//     cout << "Sommet " << ns0 << ": " << mnpxyd[ns0].x
+//      << " " << mnpxyd[ns0].y << " longueur arete=" << mnpxyd[ns0].z << endl;
+
+    //carre de la longueur de l'arete 1 de la ligne fermee n
+    d = pow( uvslf[ns0+1].x - uvslf[ns0].x, 2 ) 
+      + pow( uvslf[ns0+1].y - uvslf[ns0].y, 2 ) ;
+    aremin = Min( aremin, d );
+    aremax = Max( aremax, d );
+
+    //le numero des 2 sommets (ns1,ns2) de la premiere arete de la ligne
+    //initialisation de la 1-ere arete ns1-ns1+1 de cette ligne fermee n
+    //le numero des 2 sommets ns1 ns2 de la 1-ere arete
+    //Attention: les numeros ns debutent a 1 (ils ont >0)
+    //           les tableaux c++ demarrent a zero!
+    //           les tableaux fortran demarrent ou l'on veut!
+    ns0++;
+    ns1 = ns0;
+    ns2 = ns1+1;
+
+     //le numero n de la ligne du sommet et son numero ns1 dans la ligne
+    mnslig[ns0-1] = 1000000 * n + ns1-nudslf[n-1];
+    fasoar_( ns1, ns2, moins1, moins1, n,
+            mosoar, mxsoar, n1soar, mnsoar, mnarst,
+            noar0,  ierr );
+    //pas de test sur ierr car pas de saturation possible a ce niveau
+
+    //le pointeur dans le hachage sur la premiere arete de la ligne fermee n
+    mndalf[n] = noar0;
+
+    //la nouvelle arete est la suivante de l'arete definie juste avant
+    if( noar > 0 )
+      mnsoar[mosoar * noar - mosoar + 5] = noar0;
+
+    //l'initialisation des aretes suivantes de la ligne dans la triangulation
+    //-----------------------------------------------------------------------
+    nbarli = nudslf[n] - nudslf[n-1];  //nombre d'aretes=sommets de la ligne n
+    for (i=2; i<=nbarli; i++)
+    {
+      ns1 = ns2; //le numero de l'arete et le numero du premier sommet de l'arete
+      if( i < nbarli )
+       //nbs+1 est le 2-eme sommet de l'arete i de la ligne fermee n
+       ns2 = ns1+1;
+      else
+       //le 2-eme sommet de la derniere arete est le premier sommet de la ligne
+       ns2 = ns0;
+
+      //l'arete precedente est dotee de sa suivante:celle cree ensuite
+      //les 2 coordonnees du sommet ns2 de la ligne
+      ns = ns1 - 1;
+      mnpxyd[ns].x = uvslf[ns].x;
+      mnpxyd[ns].y = uvslf[ns].y;
+      mnpxyd[ns].z = areteideale_( mnpxyd[ns], direction );
+//       cout << "Sommet " << ns << ": " << mnpxyd[ns].x
+//        << " " << mnpxyd[ns].y << " longueur arete=" << mnpxyd[ns].z << endl;
+
+      //carre de la longueur de l'arete
+      d = pow( uvslf[ns2-1].x - uvslf[ns1-1].x, 2) 
+        + pow( uvslf[ns2-1].y - uvslf[ns1-1].y, 2);
+      aremin = Min( aremin, d );
+      aremax = Max( aremax, d );
+
+      //le numero n de la ligne du sommet et son numero ns1 dans la ligne
+      mnslig[ns] = 1000000 * n + ns1-nudslf[n-1];
+
+      //ajout de l'arete dans la liste
+      fasoar_( ns1, ns2, moins1, moins1, n,
+              mosoar, mxsoar, n1soar, mnsoar,
+              mnarst, noar, ierr );
+      //pas de test sur ierr car pas de saturation possible a ce niveau
+
+      //chainage des aretes frontalieres en position 6 du tableau mnsoar
+      //la nouvelle arete est la suivante de l'arete definie juste avant
+      mnsoar[ mosoar * noar0 - mosoar + 5 ] = noar;
+      noar0 = noar;
+   }
+    //attention: la derniere arete de la ligne fermee enveloppe
+    //           devient en fait la premiere arete de cette ligne
+    //           dans le chainage des aretes de la frontiere!
+  }
+  if( ierr != 0 ) goto ERREUR;
+
+  aremin = sqrt( aremin );  //longueur minimale d'une arete des lignes fermees
+  aremax = sqrt( aremax );  //longueur maximale d'une arete
+
+  aretmx = Min( aretmx, aremax );  //pour homogeneiser
+  cout << "nutysu=" << nutysu << "  aretmx=" << aretmx 
+       << "  arete min=" << aremin << "  arete max=" << aremax << endl;
+
+  //chainage des aretes frontalieres : la derniere arete frontaliere
+  mnsoar[ mosoar * noar - mosoar + 5 ] = 0;
+
+  //tous les sommets et aretes frontaliers sont numerotes de 1 a nbarfr
+  //reservation du tableau des numeros des 3 aretes de chaque triangle
+  //mnartr( moartr, mxartr )
+  //En nombre: Triangles = Aretes Internes + Aretes Frontalieres - Sommets + 1-Trous
+  //          3Triangles = 2 Aretes internes + Aretes frontalieres
+  //       d'ou 3T/2 < AI + AF => T < 3T/2  - Sommets + 1-Trous
+  //nombre de triangles < 2 ( nombre de sommets - 1 + nombre de trous )
+  if( mnartr!=NULL ) delete [] mnartr;
+  mxartr = 2 * ( mxsomm + mxtrou );
+  mnartr = new Z[moartr*mxartr];
+  if( mnartr==NULL ) goto ERREUR;
+
+  //Ajout des points internes
+  ns1 = nudslf[ nblf ];
+  for (i=0; i<nbpti; i++)
+  {
+    //les 2 coordonnees du point i de sommet nbs
+    mnpxyd[ns1].x = uvpti[i].x;
+    mnpxyd[ns1].y = uvpti[i].y;
+    mnpxyd[ns1].z = areteideale_( mnpxyd[ns1], direction );
+    //le numero i du point interne
+    mnslig[ns1] = i+1;
+    ns1++;
+  }
+
+  //nombre de sommets de la frontiere et internes
+  nbarpi = ns1;
+
+  // creation de l'arbre-4 des te (tableau letree)
+  // ajout dans les te des sommets des lignes et des points internes imposes
+  // =======================================================================
+  // premiere estimation de mxtree
+  mxtree = 2 * mxsomm;
+
+ NEWTREE:  //en cas de saturation de l'un des tableaux, on boucle
+  MESSAGE( "Debut triangulation avec mxsomm=" << mxsomm );
+  if( mntree != NULL ) delete [] mntree;
+  nbsomm = nbarpi;
+  mntree = new Z[motree*(1+mxtree)];
+  if( mntree==NULL ) goto ERREUR;
+
+  //initialisation du tableau letree et ajout dans letree des sommets 1 a nbsomm
+  teajte_( mxsomm, nbsomm, mnpxyd, comxmi, aretmx, mxtree, mntree, ierr );
+  comxmi[0].z=0;
+  comxmi[1].z=0;
+
+  if( ierr == 51 )
+  {
+    //saturation de letree => sa taille est augmentee et relance
+    mxtree = mxtree * 2;
+    ierr   = 0;
+    MESSAGE( "Nouvelle valeur de mxtree=" << mxtree );
+    goto NEWTREE;
+  }
+
+  deltacpu_( d );
+  tcpu += d;
+  MESSAGE( "Temps de l'ajout arbre-4 des Triangles Equilateraux=" << d << " secondes" );
+  if( ierr != 0 ) goto ERREUR;
+  //ici le tableau mnpxyd contient les sommets des te et les points frontaliers et internes
+
+  // homogeneisation de l'arbre des te a un saut de taille au plus
+  // prise en compte des tailles d'aretes souhaitees autour des sommets initiaux
+  // ===========================================================================
+  // reservation de la queue pour parcourir les te de l'arbre
+  if( mnqueu != NULL ) delete [] mnqueu;
+  mxqueu = mxtree;
+  mnqueu = new Z[mxqueu];
+  if( mnqueu==NULL) goto ERREUR;
+
+  tehote_( nutysu, nbarpi, mxsomm, nbsomm, mnpxyd,
+          comxmi, aretmx,
+          mntree, mxqueu, mnqueu,
+          ierr );
+
+  deltacpu_( d );
+  tcpu += d;
+  cout << "Temps de l'adaptation et l'homogeneisation de l'arbre-4 des TE="
+       << d << " secondes" << endl;
+  if( ierr != 0 )
+  {
+    //destruction du tableau auxiliaire et de l'arbre
+    if( ierr == 51 )
+    {
+      //letree sature
+      mxtree = mxtree * 2;
+      MESSAGE( "Redemarrage avec la valeur de mxtree=" << mxtree );
+      ierr = 0;
+      goto NEWTREE;
+    }
+    else
+      goto ERREUR;
+  }
+
+  // trianguler les triangles equilateraux feuilles a partir de leurs 3 sommets
+  // et des points de la frontiere, des points internes imposes interieurs
+  // ==========================================================================
+  tetrte_( comxmi, aretmx, nbarpi, mxsomm, mnpxyd,
+          mxqueu, mnqueu, mntree, mosoar, mxsoar, n1soar, mnsoar,
+          moartr, mxartr, n1artr, mnartr, mnarst,
+          ierr );
+
+  // destruction de la queue et de l'arbre devenus inutiles
+  delete [] mnqueu;  mnqueu=NULL;
+  delete [] mntree;  mntree=NULL;
+
+  //Temps calcul
+  deltacpu_( d );
+  tcpu += d;
+  MESSAGE( "Temps de la triangulation des TE=" << d << " secondes" );
+
+  // ierr =0 si pas d'erreur
+  //      =1 si le tableau mnsoar est sature
+  //      =2 si le tableau mnartr est sature
+  //      =3 si aucun des triangles ne contient l'un des points internes
+  //      =5 si saturation de la queue de parcours de l'arbre des te
+  if( ierr != 0 ) goto ERREUR;
+
+  //qualites de la triangulation actuelle
+  qualitetrte( mnpxyd, mosoar, mxsoar, mnsoar, moartr, mxartr, mnartr,
+              nbt, quamoy, quamin );
+
+  // boucle sur les aretes internes (non sur une ligne de la frontiere)
+  // avec echange des 2 diagonales afin de rendre la triangulation delaunay
+  // ======================================================================
+  // formation du chainage 6 des aretes internes a echanger eventuellement
+  aisoar_( mosoar, mxsoar, mnsoar, na );
+  tedela_( mnpxyd, mnarst,
+          mosoar, mxsoar, n1soar, mnsoar, na,
+          moartr, mxartr, n1artr, mnartr, n );
+
+  MESSAGE( "Nombre d'echanges des diagonales de 2 triangles=" << n );
+  deltacpu_( d );
+  tcpu += d;
+  cout << "Temps de la triangulation Delaunay par echange des diagonales="
+       << d << " secondes" << endl;
+
+  //qualites de la triangulation actuelle
+  qualitetrte( mnpxyd, mosoar, mxsoar, mnsoar, moartr, mxartr, mnartr,
+              nbt, quamoy, quamin );
+
+  // detection des aretes frontalieres initiales perdues
+  // triangulation frontale pour les restaurer
+  // ===================================================
+  mxarcf = mxsomm/5;
+  if( mn1arcf != NULL ) delete [] mn1arcf;
+  if( mnarcf  != NULL ) delete [] mnarcf;
+  if( mnarcf1 != NULL ) delete [] mnarcf1;
+  if( mnarcf2 != NULL ) delete [] mnarcf2;
+  mn1arcf = new Z[1+mxarcf];
+  if( mn1arcf == NULL ) goto ERREUR;
+  mnarcf  = new Z[3*mxarcf];
+  if( mnarcf == NULL ) goto ERREUR;
+  mnarcf1 = new Z[mxarcf];
+  if( mnarcf1 == NULL ) goto ERREUR;
+  mnarcf2 = new Z[mxarcf];
+  if( mnarcf2 == NULL ) goto ERREUR;
+
+  terefr_( nbarpi, mnpxyd,
+          mosoar, mxsoar, n1soar, mnsoar,
+          moartr, n1artr, mnartr, mnarst,
+          mxarcf, mn1arcf, mnarcf, mnarcf1, mnarcf2,
+          n, ierr );
+
+  MESSAGE( "Restauration de " << n << " aretes perdues de la frontiere" );
+  deltacpu_( d );
+  tcpu += d;
+  cout << "Temps de la recuperation des aretes perdues de la frontiere="
+       << d << " secondes" << endl;
+
+  if( ierr != 0 ) goto ERREUR;
+
+  //qualites de la triangulation actuelle
+  qualitetrte( mnpxyd, mosoar, mxsoar, mnsoar, moartr, mxartr, mnartr,
+              nbt, quamoy, quamin );
+
+  // fin de la triangulation avec respect des aretes initiales frontalieres
+
+  // suppression des triangles externes a la surface
+  // ===============================================
+  // recherche du dernier triangle utilise
+  mn = mxartr * moartr;
+  for ( ndtri0=mxartr; ndtri0<=1; ndtri0-- )
+  {
+    mn -= moartr;
+    if( mnartr[mn] != 0 ) break;
+  }
+
+  if( mntrsu != NULL ) delete [] mntrsu;
+  mntrsu = new Z[ndtri0];
+  if( mntrsu == NULL ) goto ERREUR;
+
+  if( mnlftr != NULL ) delete [] mnlftr;
+  mnlftr = new Z[nblf];
+  if( mnlftr == NULL ) goto ERREUR;
+
+  for (n=0; n<nblf; n++)  //numero de la ligne fermee de 1 a nblf
+    mnlftr[n] = n+1;
+
+  tesuex_( nblf,   mnlftr,
+          ndtri0, nbsomm, mnpxyd, mnslig,
+          mosoar, mxsoar, mnsoar,
+          moartr, mxartr, n1artr, mnartr, mnarst,
+          nbt, mntrsu, ierr );
+
+  delete [] mnlftr; mnlftr=NULL;
+  delete [] mntrsu; mntrsu=NULL;
+
+  deltacpu_( d );
+  tcpu += d;
+  MESSAGE( "Temps de la suppression des triangles externes=" << d );
+  if( ierr != 0 ) goto ERREUR;
+
+  //qualites de la triangulation actuelle
+  qualitetrte( mnpxyd, mosoar, mxsoar, mnsoar, moartr, mxartr, mnartr,
+              nbt, quamoy, quamin );
+
+  // amelioration de la qualite de la triangulation par
+  // barycentrage des sommets internes a la triangulation
+  // suppression des aretes trop longues ou trop courtes
+  // modification de la topologie des groupes de triangles
+  // mise en delaunay de la triangulation
+  // =====================================================
+  mnarcf3 = new Z[mxarcf];
+  if( mnarcf3 == NULL ) goto ERREUR;
+
+  teamqt_( nutysu,
+          mnarst, mosoar, mxsoar, n1soar, mnsoar,
+          moartr, mxartr, n1artr, mnartr,
+          mxarcf, mnarcf2, mnarcf3,
+          mn1arcf, mnarcf, mnarcf1,
+          comxmi, nbarpi, nbsomm, mxsomm, mnpxyd, mnslig,
+          ierr );
+  if( mn1arcf != NULL ) {delete [] mn1arcf; mn1arcf=NULL;}
+  if( mnarcf  != NULL ) {delete [] mnarcf;  mnarcf =NULL;}
+  if( mnarcf1 != NULL ) {delete [] mnarcf1; mnarcf1=NULL;}
+  if( mnarcf2 != NULL ) {delete [] mnarcf2; mnarcf2=NULL;}
+  if( mnarcf3 != NULL ) {delete [] mnarcf3; mnarcf3=NULL;}
+
+  deltacpu_( d );
+  tcpu += d;
+  MESSAGE( "Temps de l'amelioration de la qualite de la triangulation=" << d );
+  if( ierr != 0 ) goto ERREUR;
+
+  //qualites de la triangulation finale
+  qualitetrte( mnpxyd, mosoar, mxsoar, mnsoar, moartr, mxartr, mnartr,
+              nbt, quamoy, quamin );
+
+  // renumerotation des sommets internes: mnarst(i)=numero final du sommet
+  // ===================================
+  for (i=0; i<=nbsomm; i++)
+    mnarst[i] = 0;
+
+  for (nt=1; nt<=mxartr; nt++)
+  {
+    if( mnartr[nt*moartr-moartr] != 0 )
+    {
+      //le numero des 3 sommets du triangle nt
+      nusotr_( nt, mosoar, mnsoar, moartr, mnartr, nosotr );
+      //les 3 sommets du triangle sont actifs
+      mnarst[ nosotr[0] ] = 1;
+      mnarst[ nosotr[1] ] = 1;
+      mnarst[ nosotr[2] ] = 1;
+    }
+  }
+  nbst = 0;
+  for (i=1; i<=nbsomm; i++)
+  {
+    if( mnarst[i] >0 )
+      mnarst[i] = ++nbst;
+  }
+
+  // generation du tableau uvst de la surface triangulee
+  // ---------------------------------------------------
+  if( uvst != NULL ) delete [] uvst;
+  uvst = new R2[nbst];
+  if( uvst == NULL ) goto ERREUR;
+
+  nbst=-1;
+  for (i=0; i<nbsomm; i++ )
+  {
+    if( mnarst[i+1]>0 )
+    {
+      nbst++;
+      uvst[nbst].x = mnpxyd[i].x;
+      uvst[nbst].y = mnpxyd[i].y;
+
+      //si le sommet est un point ou appartient a une ligne
+      //ses coordonnees initiales sont restaurees
+      n = mnslig[i];
+      if( n > 0 )
+      {
+       if( n >= 1000000 )
+       {
+         //sommet d'une ligne
+         //retour aux coordonnees initiales dans uvslf
+         l = n / 1000000;
+         n = n - 1000000 * l + nudslf[l-1] - 1;
+         uvst[nbst].x = uvslf[n].x;
+         uvst[nbst].y = uvslf[n].y;
+       }
+       else
+       {
+         //point utilisateur n interne impose
+         //retour aux coordonnees initiales dans uvpti
+         uvst[nbst].x = uvpti[n-1].x;
+         uvst[nbst].y = uvpti[n-1].y;
+       }
+      }
+    }
+  }
+  nbst++;
+
+  // generation du tableau 'nsef' de la surface triangulee
+  // -----------------------------------------------------
+  // boucle sur les triangles occupes (internes et externes)
+  if( nust != NULL ) delete [] nust;
+  nust = new Z[4*nbt];
+  if( nust == NULL ) goto ERREUR;
+  nbt = 0;
+  for (i=1; i<=mxartr; i++)
+  {
+    //le triangle i de mnartr
+    if( mnartr[i*moartr-moartr] != 0 )
+    {
+      //le triangle i est interne => nosotr numero de ses 3 sommets
+      nusotr_( i, mosoar, mnsoar, moartr, mnartr,  nosotr );
+      nust[nbt++] = mnarst[ nosotr[0] ];
+      nust[nbt++] = mnarst[ nosotr[1] ];
+      nust[nbt++] = mnarst[ nosotr[2] ];
+      nust[nbt++] = 0;
+    }
+  }
+  nbt /= 4;  //le nombre final de triangles de la surface
+  cout << "Nombre de sommets=" << nbst
+       << "  Nombre de triangles=" << nbt << endl;
+
+  deltacpu_( d );
+  tcpu += d;
+  MESSAGE( "Temps total de la triangulation=" << tcpu << " secondes" );
+
+  // destruction des tableaux auxiliaires
+  // ------------------------------------
+ NETTOYAGE:
+  if( mnarst != NULL ) delete [] mnarst;
+  if( mnartr != NULL ) delete [] mnartr;
+  if( mnslig != NULL ) delete [] mnslig;
+  if( mnsoar != NULL ) delete [] mnsoar;
+  if( mnpxyd != NULL ) delete [] mnpxyd;
+  if( mndalf != NULL ) delete [] mndalf;
+  if( mntree != NULL ) delete [] mntree;
+  if( mnqueu != NULL ) delete [] mnqueu;
+  if( mntrsu != NULL ) delete [] mntrsu;
+  if( mnlftr != NULL ) delete [] mnlftr;
+  if( mn1arcf != NULL ) delete [] mn1arcf;
+  if( mnarcf  != NULL ) delete [] mnarcf;
+  if( mnarcf1 != NULL ) delete [] mnarcf1;
+  if( mnarcf2 != NULL ) delete [] mnarcf2;
+  if( mnarcf3 != NULL ) delete [] mnarcf3;
+  return;
+
+ ERREUR:
+  if( ierr == 51 || ierr == 52 )
+  {
+    //saturation des sommets => redepart avec 2 fois plus de sommets
+    mxsomm = 2 * mxsomm;
+    ierr   = 0;
+    goto NEWDEPART;
+  }
+  else
+  {
+    MESSAGE( "Triangulation non realisee " << ierr );
+    if( ierr == 0 ) ierr=1;
+    goto NETTOYAGE;
+  }
+}
+
+
+void qualitetrte( R3 *mnpxyd,
+                 Z & mosoar, Z & mxsoar, Z *mnsoar,
+                 Z & moartr, Z & mxartr, Z *mnartr,
+                 Z & nbtria, R & quamoy, R & quamin )
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// but :    calculer la qualite moyenne et minimale de la triangulation
+// -----    actuelle definie par les tableaux mnsoar et mnartr
+// entrees:
+// --------
+// mnpxyd : tableau des coordonnees 2d des points
+//          par point : x  y  distance_souhaitee
+// mosoar : nombre maximal d'entiers par arete et
+//          indice dans mnsoar de l'arete suivante dans le hachage
+// mxsoar : nombre maximal d'aretes stockables dans le tableau mnsoar
+//          attention: mxsoar>3*mxsomm obligatoire!
+// mnsoar : numero des 2 sommets , no ligne, 2 triangles de l'arete,
+//          chainage des aretes frontalieres, chainage du hachage des aretes
+//          hachage des aretes = mnsoar(1)+mnsoar(2)*2
+//          avec mxsoar>=3*mxsomm
+//          une arete i de mnsoar est vide <=> mnsoar(1,i)=0 et
+//          mnsoar(2,arete vide)=l'arete vide qui precede
+//          mnsoar(3,arete vide)=l'arete vide qui suit
+// moartr : nombre maximal d'entiers par arete du tableau mnartr
+// mxartr : nombre maximal de triangles declarables
+// mnartr : les 3 aretes des triangles +-arete1, +-arete2, +-arete3
+//          arete1 = 0 si triangle vide => arete2 = triangle vide suivant
+// sorties:
+// --------
+// nbtria : nombre de triangles internes au domaine
+// quamoy : qualite moyenne  des triangles actuels
+// quamin : qualite minimale des triangles actuels
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+{
+  R  d, aire, qualite;
+  Z  nosotr[3], mn, nbtrianeg, nt;
+
+  aire   = 0;
+  quamoy = 0;
+  quamin = 2.0;
+  nbtria = 0;
+  nbtrianeg = 0;
+
+  mn = -moartr;
+  for ( nt=1; nt<=mxartr; nt++ )
+  {
+    mn += moartr;
+    if( mnartr[mn]!=0 )
+    {
+      //un triangle occupe de plus
+      nbtria++;
+
+      //le numero des 3 sommets du triangle nt
+      nusotr_( nt, mosoar, mnsoar, moartr, mnartr,  nosotr );
+
+      //la qualite du triangle ns1 ns2 ns3
+      qutr2d_( mnpxyd[nosotr[0]-1], mnpxyd[nosotr[1]-1], mnpxyd[nosotr[2]-1],
+              qualite );
+
+      //la qualite moyenne
+      quamoy += qualite;
+
+      //la qualite minimale
+      quamin = Min( quamin, qualite );
+
+      //aire signee du triangle nt
+      d = surtd2_( mnpxyd[nosotr[0]-1], mnpxyd[nosotr[1]-1], mnpxyd[nosotr[2]-1] );
+      if( d<0 )
+      {
+       //un triangle d'aire negative de plus
+       nbtrianeg++;
+       cout << "ATTENTION: le triangle " << nt << " de sommets:"
+            << nosotr[0] << " " << nosotr[1] << " " << nosotr[2]
+            << " a une aire " << d <<"<=0" << endl;
+      }
+
+      //aire des triangles actuels
+      aire += Abs(d);
+    }
+  }
+
+  //les affichages
+  quamoy /= nbtria;
+  cout << "Qualite moyenne=" << quamoy
+       << "  Qualite minimale=" << quamin
+       << " des " << nbtria << " triangles de surface totale="
+       << aire << endl;
+
+  if( nbtrianeg>0 )
+    MESSAGE( "ATTENTION: nombre de triangles d'aire negative=" << nbtrianeg );
+  return;
+}