Index: /issm/trunk/src/c/Bamgx/Bamgx.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/Bamgx.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Bamgx.cpp	(revision 2740)
@@ -0,0 +1,375 @@
+/*!\file Bamgx
+ * \brief: use Bamg capabilities.
+ */
+
+#include "./Bamgx.h"
+
+#undef __FUNCT__ 
+#define __FUNCT__ "Bamgx"
+
+#include "../shared/shared.h"
+#include "../include/macros.h"
+#include "../toolkits/toolkits.h"
+#include "../EnumDefinitions/EnumDefinitions.h"
+
+
+/*Bamg: */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+#include <new>
+#include <cassert>
+#include "Meshio.h"
+#include <iomanip>
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include <fstream>
+
+using namespace bamg;
+using namespace std;
+#define   NBVMAX 50000   
+
+
+int Bamgx(double** pelementsout,double** pxout,double** pyout, int* pnelout,int* pnodsout, 
+		double* elements, double* x, double* y, int nel, int nods, double* metric, double gradation, int splitpbedge, int nbv){
+	
+
+	
+	int noerr=1;
+
+	/*output: */
+	double* elementsout=NULL;
+	double* xout=NULL;
+	double* yout=NULL;
+	int     nelout, nodsout;
+
+	/*Bamg variables: */
+	double time0, time1,time2,time3,time4;
+	//   2 way for uses ---
+	//   1 first mesh 
+	//   or adaptation 
+	
+	//  double *sol=0;
+	//  int adaptation = 0 ;
+	Int4 i;
+	hinterpole=1; // by def interpolation a h 
+	//  int Err=0;
+	int fileout=0;
+	int nbvx = NBVMAX;
+	int iso =0,AbsError=0,nbjacoby=1,allquad=0;
+	int NoMeshReconstruction=0;
+	int Rescaling = 1;
+	double costheta=2;
+	Real8 cutoffradian=-1;
+	double anisomax = 1e6;
+	double err=0.01,errg=0.1,coef=1,hmin=1.e-100,hmax=1.e17,raison=0,CutOff=1e-5;
+	int KeepBackVertices=1;
+	double hminaniso=1e-100; 
+	const double  boundmaxsubdiv = 10;
+	double  maxsubdiv=boundmaxsubdiv;
+	double omega=1.8;
+	int NbSmooth=3;
+	double *solMbb =0,*solMBB=0;
+	int  *typesolsBB =0;
+	Int4 nbsolbb=0,lsolbb=0;
+	Int4 nbsolBB=0,lsolBB=0;
+	int SplitEdgeWith2Boundary=0;
+	int rbbeqMbb=0,rBBeqMBB=0;
+	int ChoiseHessien = 0;
+	double power=1;
+	Triangles *Thr=0,*Thb=0;
+
+	char * fgeom=0,*fmeshback=0,*fmeshout=0,*fmeshr=0,*fmetrix=0,*famfmt=0,*fmsh=0,
+		 *fnopo=0,*fftq=0,*fam=0,*famdba=0,*rbb=0,*rBB=0,*wbb=0,*wBB=0,
+		 *fMbb=0,*foM=0,*fMBB=0;
+	
+	long int verbosity =10;
+
+	char *datargv[128] ;
+	int datargc=1;
+	datargv[0]= datargv[1]=0;// for create a error if no parameter 
+
+	//Recover command line options: */
+	nbvx=nbv;
+	if(splitpbedge)SplitEdgeWith2Boundary=1;
+
+	/*Rest of the code taken directly from bamg.cpp, with our own mods: */
+
+	// some verification
+	NoMeshReconstruction= fmeshr !=0;
+	if (!fmeshback) fmeshback=fmeshr;
+	
+	if ( maxsubdiv > boundmaxsubdiv || maxsubdiv <= 1.0)
+	{
+		cerr << " -maxsubdiv " << maxsubdiv << " is not in ]1,"<< boundmaxsubdiv << "]" << endl;
+		exit(3);
+	}
+	if (iso) 
+		anisomax=1;
+	if (!(fmetrix||fMbb))
+		NbSmooth=0; // no metric -> no smoothing 
+	if( ! rbb) // to set the rbb filename by default 
+		rbb=fMbb;
+	if( ! rBB) // to set the rbb filename by default 
+		rBB=fMBB;
+
+	if (fMbb && rbb) 
+		rbbeqMbb = !strcmp(rbb,fMbb);
+	if (fMBB && rBB) 
+		rBBeqMBB = !strcmp(rBB,fMBB);
+
+	time0 = CPUtime();
+
+	/*Read background mesh from simple delaunay triangulation: */
+	Triangles BTh(elements,x,y,nel,nods,nbvx,cutoffradian); // read the background mesh 
+
+	hmin = Max(hmin,BTh.MinimalHmin());
+	hmax = Min(hmax,BTh.MaximalHmax());
+
+	throw ErrorException(__FUNCT__," done");
+
+	BTh.MakeQuadTree();
+	time1 = CPUtime();
+	if (fmetrix) 
+		BTh.ReadMetric(fmetrix,hmin,hmax,coef);
+	else
+	{ // init with hmax 
+		Metric Mhmax(hmax);
+		for (Int4 iv=0;iv<BTh.nbv;iv++)
+			BTh[iv].m = Mhmax;
+	}
+	if (fMbb)
+	{
+		solMbb = ReadbbFile(fMbb,nbsolbb,lsolbb,2,2);
+		if (lsolbb != BTh.nbv) 
+		{
+			cerr << "fatal error  nbsol " << nbsolbb << " " << lsolbb<< " =! " << BTh.nbv << endl;
+			cerr << "  size of sol incorrect " << endl;
+			MeshError(99);
+		}
+		assert(lsolbb==BTh.nbv);
+		BTh.IntersectConsMetric(solMbb,nbsolbb,0,hmin,hmax,sqrt(err)*coef,1e30,AbsError?0.0:CutOff,
+				nbjacoby,Rescaling,power,ChoiseHessien);
+		if(!rbbeqMbb)
+			delete [] solMbb,solMbb =0;
+
+	}
+	if (fMBB)
+	{
+		solMBB = ReadBBFile(fMBB,nbsolBB,lsolBB,typesolsBB,2,2);
+		if (lsolBB != BTh.nbv) 
+		{
+			cerr << "fatal error  nbsol " << nbsolBB << " " << lsolBB << " =! " << BTh.nbv << endl;
+			cerr << "  size of sol incorrect " << endl;
+			MeshError(99);
+		}
+		assert(lsolBB==BTh.nbv);
+		BTh.IntersectConsMetric(solMBB,nbsolBB,0,hmin,hmax,sqrt(err)*coef,1e30,AbsError?0.0:CutOff,
+				nbjacoby,Rescaling,ChoiseHessien);
+		if(!rBBeqMBB)
+			delete [] solMBB,solMBB =0;
+
+	}
+
+	BTh.IntersectGeomMetric(errg,iso);
+	if(raison) 
+		BTh.SmoothMetric(raison);
+	BTh.MaxSubDivision(maxsubdiv);
+	//
+	if (iso) 
+		anisomax=1;
+	BTh.BoundAnisotropy(anisomax,hminaniso);
+	time2 = CPUtime();
+	if(foM)
+	{
+		if(verbosity >2)
+			cout << " -- write Metric  file " << foM <<endl;
+
+		ofstream f(foM);
+		if(f) BTh.WriteMetric(f,iso);
+	}
+
+	if ( fileout) 
+	{
+		if ( NoMeshReconstruction)
+			if (( fmeshback == fmeshr) || (!strcmp(fmeshback,fmeshr)))
+				Thr=&BTh,Thb=0; // back and r mesh are the same 
+			else
+				Thr= new Triangles(fmeshr,cutoffradian),Thb=&BTh; // read the new 
+
+
+
+		Triangles & Th( *(NoMeshReconstruction 
+					?  new Triangles(*Thr,&Thr->Gh,Thb,nbvx) // copy the mesh + free space to modification  
+					:  new Triangles(nbvx,BTh,KeepBackVertices)     // construct a new mesh 
+					));
+		if (Thr != &BTh) delete Thr;
+
+		if(costheta<=1.0)
+			Th.MakeQuadrangles(costheta);
+		if (allquad)
+			Th.SplitElement(allquad==2);
+		if(SplitEdgeWith2Boundary)
+			Th.SplitInternalEdgeWithBorderVertices();
+		Th.ReNumberingTheTriangleBySubDomain();
+		time3 = CPUtime();
+
+		if(verbosity>0){
+			cout << " Cpu time for meshing          : " << time3-time2 << "s  Nb Vertices/s = " <<  (Th.nbv) /(time3-time2) << endl;
+		}
+		if(verbosity>3) Th.ShowHistogram();
+		if(NbSmooth>0) Th.SmoothingVertex(NbSmooth,omega);
+		if(verbosity>3 && NbSmooth>0) Th.ShowHistogram();
+		
+		Th.BTh.ReMakeTriangleContainingTheVertex();
+
+		if (fmeshout) Th.Write(fmeshout  ,Triangles::BDMesh);
+		if (famfmt)   Th.Write(famfmt    ,Triangles::am_fmtMesh);
+		if (fam)      Th.Write(fam       ,Triangles::amMesh);
+		if (famdba)   Th.Write(famdba    ,Triangles::amdbaMesh);
+		if (fftq)     Th.Write(fftq      ,Triangles::ftqMesh);
+		if (fmsh)     Th.Write(fmsh      ,Triangles::mshMesh);
+		if (fnopo)    Th.Write(fnopo     ,Triangles::NOPOMesh);
+
+		if ( ( rbb && wbb)  ||( rBB && wBB)){  // the code for interpolation 
+
+			if(verbosity >1)
+			{
+				if (rbb ) 
+					cout << " -- interpolation P1  files : " << rbb << " -> " << wbb <<endl;
+				if (rBB ) 
+					cout << " -- interpolation P1  files : " << rBB<< " -> " << wBB <<endl;
+			}
+			double time00  = CPUtime();	   
+			const int dim=2;
+			// optimisation read only si rbb != fMbb
+
+			double *solbb=0;
+			double *solBB=0;
+
+			if (rbb) 
+				solbb =  rbbeqMbb? solMbb : ReadbbFile(rbb,nbsolbb,lsolbb,2,2);
+			if (rBB) 
+				solBB =  rBBeqMBB? solMBB : ReadBBFile(rBB,nbsolBB,lsolBB,typesolsBB,2,2);
+
+			// cout << " " << rbbeqMbb << " " <<  sol << " " << nbsol << " " << lsol << endl; 
+			if (!solBB && !solbb ) 
+			{
+				cerr << " Fatal Error "  << "solBB =  " <<  solBB << " solbb= " << solbb << endl;
+				exit(2);}
+
+				ofstream *fbb = wbb ? new ofstream(wbb) :0;
+				ofstream *fBB = wBB ? new ofstream(wBB) :0;
+				Int4   nbfieldBB = 0, nbfieldbb = nbsolbb;
+				if (fbb)
+					*fbb  << dim << " " << nbsolbb << " " << Th.nbv <<" " << 2 << endl; 
+				if (fBB)
+				{
+					int i;
+					*fBB  << dim << " " << nbsolBB ;
+					for ( i=0;i<nbsolBB;i++)
+						*fBB << " " << (typesolsBB ?typesolsBB[i]+1:1) ;
+					*fBB << " " << Th.nbv <<" " << 2 << endl; 
+					assert(dim==2);
+					for ( i=0;i<nbsolBB;i++)
+						nbfieldBB += typesolsBB ? typesolsBB[i]+1 : 1;
+					// this code is good only if dim == 2 
+				}
+				cout << "nb of field BB " << nbfieldBB << endl;
+				//		 if(fBB) fBB->precision(15);
+				//if(fbb) fbb->precision(15);
+				for(i=0;i<Th.nbv;i++)
+				{
+					Int4 i0,i1,i2;
+					double a[3];
+					Icoor2 dete[3];
+					I2 I = Th.BTh.toI2(Th.vertices[i].r);
+					Triangle & tb = *Th.BTh.FindTriangleContening(I,dete);
+
+					if (tb.det>0) { // internal point 
+						a[0]= (Real8) dete[0]/ tb.det;
+						a[1]= (Real8) dete[1] / tb.det;
+						a[2] = (Real8) dete[2] / tb.det;
+						i0=Th.BTh.Number(tb[0]);
+						i1=Th.BTh.Number(tb[1]);
+						i2=Th.BTh.Number(tb[2]);}
+					else {
+						double aa,bb;
+
+						TriangleAdjacent  ta=CloseBoundaryEdge(I,&tb,aa,bb).Adj();
+
+						int k = ta;
+						Triangle & tc = *(Triangle *)ta;
+						i0=Th.BTh.Number(tc[0]);
+						i1=Th.BTh.Number(tc[1]);
+						i2=Th.BTh.Number(tc[2]);
+						a[VerticesOfTriangularEdge[k][1]] =aa;
+						a[VerticesOfTriangularEdge[k][0]] = bb;
+						a[OppositeVertex[k]] = 1- aa -bb;}
+
+						Int4  ibb0 = nbfieldbb*i0;
+						Int4  ibb1 = nbfieldbb*i1;
+						Int4  ibb2 = nbfieldbb*i2;
+
+						Int4  iBB0 = nbfieldBB*i0;
+						Int4  iBB1 = nbfieldBB*i1;
+						Int4  iBB2 = nbfieldBB*i2;
+						Int4 j=0;
+
+						for ( j=0;j<nbfieldbb;j++) 
+							*fbb  << " " << ( a[0] * solbb[ibb0++] + a[1] * solbb[ibb1++] + a[2]* solbb[ibb2++]) ;
+
+						for (j=0;j<nbfieldBB;j++) 
+							*fBB  << " " << ( a[0] * solBB[iBB0++] + a[1] * solBB[iBB1++] + a[2]* solBB[iBB2++]) ;
+
+						if (fbb) *fbb  << endl;
+						if (fBB) *fBB  << endl;
+				}
+				if (fbb)
+					delete fbb  ; // close
+				if (fBB)
+					delete fBB  ; // close
+				if (solbb) 
+					delete [] solbb;
+				if (solBB) 
+					delete [] solBB;
+				double  time04 = CPUtime();
+				if(verbosity>0) 
+					cout << " Cpu time for interpolation " << time04-time00 << " s" <<endl;
+
+		}
+		time4 = CPUtime();
+
+		if(verbosity>0) 
+		{
+			cout << " Cpu time for meshing with io  : " << time4-time0
+				<< "s  Nb Vertices/s = " << Th.nbv/(time4-time0)
+				<< endl
+				<< " Nb vertices = " << Th.nbv;
+			if (Th.nbt-Th.NbOutT-Th.NbOfQuad*2) 
+				cout  << " Nb Triangles = " << (Th.nbt-Th.NbOutT-Th.NbOfQuad*2);
+			if (Th.NbOfQuad ) 
+				cout  << " Nb Quadrilaterals = " << Th.NbOfQuad  ;
+			cout   << endl;
+		}
+
+
+		// cout << "delete &Th " ;
+		delete &Th;
+		//cout << " end " << endl;
+	}
+
+	throw ErrorException(__FUNCT__," almost there\n");
+
+
+	/*Assign output pointers:*/
+	*pelementsout=elementsout;
+	*pxout=xout;
+	*pyout=yout;
+	*pnelout=nelout;
+	*pnodsout=nodsout;
+
+	return noerr;
+}
Index: /issm/trunk/src/c/Bamgx/Bamgx.h
===================================================================
--- /issm/trunk/src/c/Bamgx/Bamgx.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Bamgx.h	(revision 2740)
@@ -0,0 +1,16 @@
+/*!\file:  Bamgx.h
+ * \brief header file for Bamg module
+ */ 
+
+#ifndef _BAMGX_H
+#define _BAMGX_H
+
+#include "../objects/objects.h"
+
+/* local prototypes: */
+int     Bamgx(double** pelementsout,double** pxout,double** pyout, int* pnelout,int* pnodsout, 
+		double* elements, double* x, double* y, int nel, int nods, double* metric, double gradation, int splitpbedge, int nbv);
+
+#endif  /* _BAMGX_H */
+	
+
Index: /issm/trunk/src/c/Bamgx/Makefile.am
===================================================================
--- /issm/trunk/src/c/Bamgx/Makefile.am	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Makefile.am	(revision 2740)
@@ -0,0 +1,12 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id: Makefile.am,v 1.4 2008/11/24 13:22:26 hecht Exp $
+CXXLD=$(STATICTOOL) $(CXX)
+
+bin_PROGRAMS=$(BAMGPROG)
+EXTRA_PROGRAMS=bamg  cvmsh2 drawbdmesh
+bamg_SOURCES=bamg.cpp 
+bamg_DEPENDENCIES=../fflib/libff.a 
+
+LDADD= ../fflib/libff.a
+INCLUDES=-I../fflib -I../bamglib -I../Graphics
Index: /issm/trunk/src/c/Bamgx/Mesh2.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/Mesh2.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Mesh2.cpp	(revision 2740)
@@ -0,0 +1,5189 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+
+   This file is part of Freefem++
+
+   Freefem++ is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+
+   Freefem++  is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with Freefem++; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+   */
+#ifdef __MWERKS__
+#ifdef __INTEL__
+//#pragma global_optimizer off
+//#pragma inline_depth(0)
+//#pragma optimization_level 2
+#endif
+//#pragma inline_depth 0
+#endif
+extern bool withrgraphique;
+#include <stdio.h>
+#include <string.h>
+#include <math.h> 
+#include <time.h>
+#include <iostream>
+using namespace std; 
+
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+
+namespace bamg {
+
+
+#ifdef DEBUG1
+	extern int SHOW ; // for debugging 
+	int SHOW = 0; // for debugging 
+
+#endif
+
+	int  Triangles::counter = 0;
+
+	Triangles * CurrentTh =0;
+
+	int hinterpole=1;
+
+
+	long NbUnSwap =0;
+	int  ForDebugging = 0;
+	const Direction NoDirOfSearch = Direction();
+#ifndef NDEBUG 
+	inline void MyAssert(int i,char*ex,char * file,long line) 
+	{
+		if( i) {
+			cerr << "Error Assert:" << ex << " in " << file << " line: " << line << endl;
+#ifdef  NOTFREEFEM
+			exit(1); 
+#else
+			throw(ErrorExec("exit",1000));
+#endif
+		}
+	}
+#endif
+
+	Int4 AGoodNumberPrimeWith(Int4 n)
+	{
+		const Int4 BigPrimeNumber[] ={ 567890359L,
+			567890431L,  567890437L,  567890461L,  567890471L,
+			567890483L,  567890489L,  567890497L,  567890507L,
+			567890591L,  567890599L,  567890621L,  567890629L , 0};
+
+		Int4 o = 0;
+		Int4 pi = BigPrimeNumber[1];
+		for (int i=0; BigPrimeNumber[i]; i++) {
+			Int4 r = BigPrimeNumber[i] % n;
+			Int4 oo = Min(Min(r,n-r),Min(Abs(n-2*r),Abs(n-3*r)));
+			if ( o < oo) 
+				o=oo,pi=BigPrimeNumber[i];}
+			//  cout << " AGoodNumberPrimeWith " << n << " " <<pi << " "<< o << endl;
+			return pi; 
+	}
+
+	class Triangles;
+	void MeshError(int Err,Triangles *Th){ 
+		cerr << " Fatal error in the meshgenerator " << Err << endl ;
+#ifdef  NOTFREEFEM
+		exit(1); 
+#else
+		throw(ErrorMesh("Bamg",Err,Th));
+#endif
+	}
+
+	ostream& operator <<(ostream& f, const  Triangle & ta)
+	{
+		if(CurrentTh)
+			f << "[" << CurrentTh->Number(ta) << "::" 
+				<<  CurrentTh->Number(ta.ns[0]) << "," 
+				<<  CurrentTh->Number(ta.ns[1]) << "," 
+				<<  CurrentTh->Number(ta.ns[2]) << "," 
+				<< "{" <<  CurrentTh->Number(ta.at[0]) << " " << ta.aa[0] << "} " 
+				<< "{" <<  CurrentTh->Number(ta.at[1]) << " " << ta.aa[1] << "} " 
+				<< "{" <<  CurrentTh->Number(ta.at[2]) << " " << ta.aa[2] << "} " 
+				<< "]" ;
+		else
+			f << "[" 
+				<< ta.ns[0] << "," 
+				<< ta.ns[1] << "," 
+				<< ta.ns[2] << "," 
+				<< "{" << ta.at[0] << " " << ta.aa[0] << "} " 
+				<< "{" << ta.at[1] << " " << ta.aa[1] << "} " 
+				<< "{" << ta.at[2] << " " << ta.aa[2] << "} " 
+				<< "]" ;
+		return f;}
+
+		void  swap(Triangle *t1,Int1 a1,
+				Triangle *t2,Int1 a2,
+				Vertex *s1,Vertex *s2,Icoor2 det1,Icoor2 det2)
+		{ // swap 
+			// --------------------------------------------------------------
+			// Int1 a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+			//                               
+			//               sb                     sb    
+			//             / | \                   /   \                      !
+			//         as1/  |  \                 /a2   \                     !
+			//           /   |   \               /    t2 \                    !
+			//       s1 /t1  | t2 \s2  -->   s1 /___as2___\s2                 !
+			//          \  a1|a2  /             \   as1   /  
+			//           \   |   /               \ t1    /   
+			//            \  |  / as2             \   a1/    
+			//             \ | /                   \   /     
+			//              sa                       sa   
+			//  -------------------------------------------------------------
+			int as1 = NextEdge[a1];
+			int as2 = NextEdge[a2];
+			int ap1 = PreviousEdge[a1];
+			int ap2 = PreviousEdge[a2];
+#ifdef DRAWING1
+			couleur(0);
+			t1->Draw();
+			t2->Draw();
+#endif
+#ifdef DEBUG1
+			t1->check();
+			t2->check();
+#endif
+			(*t1)(VerticesOfTriangularEdge[a1][1]) = s2 ; // avant sb
+			(*t2)(VerticesOfTriangularEdge[a2][1]) = s1  ; // avant sa
+			// mise a jour des 2 adjacences externes 
+			TriangleAdjacent taas1 = t1->Adj(as1),
+							 taas2 = t2->Adj(as2),
+							 tas1(t1,as1), tas2(t2,as2),
+							 ta1(t1,a1),ta2(t2,a2);
+#ifdef DEBUG
+			assert( ! ta1.Locked());
+			assert( ! ta2.Locked());
+#endif
+			// externe haut gauche
+			taas1.SetAdj2(ta2, taas1.GetAllFlag_UnSwap());
+			// externe bas droite
+			taas2.SetAdj2(ta1, taas2.GetAllFlag_UnSwap());
+			// remove the Mark  UnMarkSwap 
+			t1->SetUnMarkUnSwap(ap1);
+			t2->SetUnMarkUnSwap(ap2);
+			// interne 
+			tas1.SetAdj2(tas2);
+
+			t1->det = det1;
+			t2->det = det2;
+
+			t1->SetTriangleContainingTheVertex();
+			t2->SetTriangleContainingTheVertex();
+#ifdef DEBUG1
+			t1->check();
+			t2->check();
+#endif
+#ifdef DRAWING1 
+			couleur(1);
+			t1->Draw();
+			t2->Draw();
+#endif 
+#ifdef DRAWING1
+			if(  CurrentTh)
+				CurrentTh->inquire();
+#endif
+
+		} // end swap 
+
+
+
+
+
+		Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a,int & inside)
+		{
+			CurrentTh=&Th;
+			assert(&Th);
+			I2 I = Th.toI2(R2(Min(Max(Th.pmin.x,x),Th.pmax.x),Min(Max(Th.pmin.y,y),Th.pmax.y))); 
+			Icoor2 dete[3];
+			Triangle & tb = *Th.FindTriangleContening(I,dete);
+
+			if  (tb.link) 
+			{ // internal point in a true triangles
+				a[0]= (Real8) dete[0]/ tb.det;
+				a[1]= (Real8) dete[1] / tb.det;
+				a[2] = (Real8) dete[2] / tb.det;
+				inside = 1;	 
+				return Th.Number(tb);
+			} 
+			else 
+			{
+				inside = 0; 
+				double aa,bb;
+				TriangleAdjacent  ta=CloseBoundaryEdgeV2(I,&tb,aa,bb);	 
+				int k = ta;
+				Triangle * tc = ta;
+				if (!tc->link) 
+				{ ta = ta.Adj();
+					tc=ta;
+					k = ta;
+					Exchange(aa,bb);
+					assert(tc->link);
+				}
+				a[VerticesOfTriangularEdge[k][0]] = aa;
+				a[VerticesOfTriangularEdge[k][1]] = bb;
+				a[OppositeVertex[k]] = 1- aa -bb;
+				return Th.Number(tc);
+			}
+		}
+
+
+		TriangleAdjacent CloseBoundaryEdge(I2 A,Triangle *t, double &a,double &b) {
+			// 
+			//  cout << " - ";   	 
+			int k=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+			int dir=0;
+			assert(k>=0);
+			int kkk=0;  
+			Icoor2 IJ_IA,IJ_AJ;
+			TriangleAdjacent edge(t,OppositeEdge[k]);          
+			for (;;edge = dir >0 ? Next(Adj(Next(edge))) : Previous(Adj(Previous(edge)))) 
+			{  
+
+				assert(kkk++<1000);      
+				Vertex  &vI =  *edge.EdgeVertex(0);
+				Vertex  &vJ =  *edge.EdgeVertex(1);
+				I2 I=vI, J=vJ, IJ= J-I;
+				IJ_IA = (IJ ,(A-I));
+				//   cout << A << vI.i << vJ.i << edge << " " <<  IJ_IA << " dir " << dir <<endl;
+				if (IJ_IA<0) {
+					if (dir>0) {a=1;b=0;return edge;}// change of signe => I
+					else {dir=-1;
+						continue;}};// go in direction i 
+						IJ_AJ = (IJ ,(J-A));
+						if (IJ_AJ<0) {
+							if(dir<0)  {a=0;b=1;return edge;}            
+							else {dir = 1;
+								continue;}}// go in direction j
+								double IJ2 = IJ_IA + IJ_AJ;
+								assert(IJ2);
+								a= IJ_AJ/IJ2;
+								b= IJ_IA/IJ2;
+								//    cout<< "CloseBoundaryEdge a = " << a << " b= " << b << endl;
+								return edge;
+			} 
+		}
+
+		TriangleAdjacent Triangle::FindBoundaryEdge(int i) const
+		{
+			// turn around  the vertex ns[i] also call  s
+#ifdef DEBUG
+			register Vertex * s  =  ns[i];
+#endif
+			Triangle   *t = (Triangle *) this , *ttc;
+			int k=0,j = EdgesVertexTriangle[i][0],jc;
+			int exterieur  = !link  ;
+
+			do 
+			{
+				int exterieurp = exterieur;
+				k++; 
+#ifdef DEBUG
+				assert( s == & (*t)[VerticesOfTriangularEdge[j][1]] );
+#endif
+				ttc =  t->at[j];
+				exterieur = !ttc->link;
+				if (exterieur+exterieurp == 1) 
+					return TriangleAdjacent(t,j);
+				jc = NextEdge[t->aa[j]&3];
+				t = ttc;
+				j = NextEdge[jc];
+				assert(k<2000);
+			} while ( (this!= t)); 
+			return TriangleAdjacent(0,0);
+
+		}
+
+
+		TriangleAdjacent CloseBoundaryEdgeV2(I2 C,Triangle *t, double &a,double &b) 
+		{ 
+			// walk around the vertex 
+			// version 2 for remove the probleme if we fill the hole
+			//int bug=1;
+			//  Triangle *torigine = t;
+			// restart:
+			//   int dir=0;
+			assert(t->link == 0);
+			// to have a starting edges 
+			// try the 3 edge bourna-- in case of internal hole 
+			// and choice  the best 
+			// 
+			// 
+			// the probleme is in case of  the fine and long internal hole
+			// for exemple neart the training edge of a wing
+			// 
+			Vertex * s=0,*s1=0, *s0=0;
+			Icoor2 imax = MaxICoor22;
+			Icoor2 l0 = imax,l1 = imax;
+			double dd2 =  imax;// infinity
+			TriangleAdjacent er; 
+			int  cas=-2;
+			for (int j=0;j<3;j++)
+			{ 
+				TriangleAdjacent ta=t->FindBoundaryEdge(j);
+				if  (! (Triangle *) ta) continue;
+				s0 = ta.EdgeVertex(0);
+				s1 = ta.EdgeVertex(1);
+				I2 A = * s0;
+				I2 B = *ta.EdgeVertex(1);
+				I2 AB = B-A,AC=C-A,BC=B-C;
+				Icoor2  ACAC = (AC,AC), BCBC = (BC,BC);
+				Icoor2  AB2  =   Norme2_2(AB); //  ||AB||^2
+				Icoor2  ABAC  =   (AB,AC);         //  AB.AC|
+
+				double d2;
+				if ( ABAC < 0 )   // DIST A
+				{
+					if ( (d2=(double) ACAC)  <  dd2) 
+					{
+						//  cout << " A "  << d2  << " " <<  dd2;
+						er = ta;
+						l0 = ACAC;
+						l1 = BCBC;
+						cas = 0;
+						s = s0;
+					}
+				}
+				else if (ABAC > AB2)  // DIST B
+				{
+					if ( (d2=(double) BCBC)  <  dd2) 
+					{
+						// cout << " B "  << d2  << " " <<  dd2;
+						dd2 = d2;
+						er = Adj(ta); // other direction
+						l0 = BCBC;
+						l1 = ACAC;
+						cas = 1;
+						s = s1;
+					}
+				}
+				else  // DIST AB
+				{ 
+
+					double det_2 =  (double) Det(AB,AC); 
+					det_2 *= det_2; // square of area*2 of triangle ABC
+					d2 = det_2/ (double) AB2; // hauteur^2 in C of of triangle ABC      
+					//	  cout << " AB " << d2 << " " << dd2 
+					//      << " " << CurrentTh->Number(ta.EdgeVertex(0)) 
+					//     << " " << CurrentTh->Number(ta.EdgeVertex(1)) << " " ;
+
+					if (d2 < dd2) 
+					{
+						dd2 = d2;
+						er = ta;
+						l0 = (AC,AC);
+						l1 = (BC,BC);
+						s = 0;
+						cas = -1;
+						//	 cout << " ABAC " <<  ABAC << " ABAC " << ABAC
+						//	      << " AB2 " << AB2 << endl;
+						b = ((double) ABAC/(double) AB2);
+						a = 1 - b;
+					}
+				}
+			}
+			assert(cas !=-2);
+			// l1 = ||C s1||  , l0 = ||C s0||
+			// where s0,s1 are the vertex of the edge er
+
+			if ( s) 
+			{ 
+				t=er;
+				TriangleAdjacent edge(er); 
+
+				int kkk=0;  
+				int linkp = t->link == 0;
+
+				Triangle * tt=t=edge=Adj(Previous(edge));
+				//  cout << CurrentTh->Number(t) << " " << linkp << endl;
+				do  {  // loop around vertex s
+
+					assert(edge.EdgeVertex(0)==s && kkk++<10000);
+
+					int link = tt->link == 0;
+					//	 cout << CurrentTh->Number(tt) << " " << link << " " << CurrentTh->Number(s) 
+					//	      << " " << CurrentTh->Number(er.EdgeVertex(0)) 
+					//	      << " " << CurrentTh->Number(er.EdgeVertex(1)) 
+					//	      << " " << CurrentTh->Number(edge.EdgeVertex(0)) 
+					//	      << " " << CurrentTh->Number(edge.EdgeVertex(1)) 
+					//	      <<  endl;
+					if ((link + linkp) == 1) 
+					{ // a boundary edge 
+						Vertex * st = edge.EdgeVertex(1);
+						I2 I=*st;
+						Icoor2  ll = Norme2_2 (C-I);
+						if (ll < l1) {  // the other vertex is neart 
+							s1=st;
+							l1=ll;
+							er = edge;
+							if(ll<l0) { // change of direction --
+								s1=s;
+								l1=l0;
+								s=st;
+								l0=ll;
+								t=tt;
+								edge=Adj(edge);
+								link=linkp;
+								er = edge;
+							}
+						}
+					}
+
+					linkp=link;
+					edge=Adj(Previous(edge));
+					tt = edge;
+				} while (t!=tt);
+
+				assert((Triangle *) er);
+				I2 A((I2)*er.EdgeVertex(0));
+				I2 B((I2)*er.EdgeVertex(1));
+				I2 AB=B-A,AC=C-A,CB=B-C;
+				double aa =  (double) (AB,AC);
+				double bb =  (double) (AB,CB);
+				//  cout << " " << aa << " " << bb 
+				//    << " " << CurrentTh->Number(er.EdgeVertex(0)) 
+				//	    << " " << CurrentTh->Number(er.EdgeVertex(1)) ;
+				if (aa<0)       a=1,b=0;
+				else if(bb<0)   a=0,b=1;
+				else  
+				{
+					a  = bb/(aa+bb);
+					b  = aa/(aa+bb);
+				}
+			}
+
+			//   cout <<" return= " <<  CurrentTh->Number(er.EdgeVertex(0)) << " " 
+			//	<<  CurrentTh->Number(er.EdgeVertex(1)) << " " << a 
+			//	<< " " << b <<" " << l0 << " " <<l1 <<endl;
+			return er;
+		} 
+
+
+
+		Metric Triangles::MetricAt  (const R2 & A) const
+		{ //if ((vertices <= &v) && (vertices < v+nbv)) return v.m;
+			I2 a = toI2(A);
+			Icoor2 deta[3];
+			Triangle * t =FindTriangleContening(a,deta);
+			if (t->det <0) { // outside
+				double ba,bb;
+				TriangleAdjacent edge= CloseBoundaryEdge(a,t,ba,bb) ;
+				return Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));}
+			else { // inside
+				Real8   aa[3];
+				Real8 s = deta[0]+deta[1]+deta[2];
+				aa[0]=deta[0]/s;
+				aa[1]=deta[1]/s;
+				aa[2]=deta[2]/s;
+				return Metric(aa,(*t)[0],(*t)[1],(*t)[2]);
+			}
+		}
+
+
+		void ListofIntersectionTriangles::SplitEdge(const Triangles & Bh,
+				const R2 &A,const R2  &B,int nbegin)
+		{ //  SplitEdge
+			//  if(SHOW)  cout << " splitedge " << A << B << " " <<  nbegin << endl;
+			Triangle *tbegin, *t;
+
+			long int verbosity=2;
+			Icoor2 deta[3], deti,detj;
+			Real8 ba[3];
+			int nbt =0,ifirst=-1,ilast;
+			int i0,i1,i2;
+			int ocut,i,j,k=-1;
+			//  int OnAVertices =0;
+			Icoor2 dt[3];
+			I2 a = Bh.toI2(A) ,b= Bh.toI2(B);// compute  the Icoor a,b
+			I2 vi,vj;  
+			int iedge =-1;// not a edge
+
+			if(nbegin)  {// optimisation 
+				// we suppose  knowing the starting  triangle
+				t=tbegin=lIntTria[ilast=(Size-1)].t;
+				if (tbegin->det>=0) 
+					ifirst = ilast;}  
+			else {// not optimisation 
+				init();
+				t=tbegin = Bh.FindTriangleContening(a,deta);
+				//    if(SHOW) cout <<t << " " << Real8(deta[0])/t->det<< " " << Real8(deta[1])/t->det
+				//		  << " " << Real8(deta[2])/t->det << endl;
+				if( t->det>=0)
+					ilast=NewItem(t,Real8(deta[0])/t->det,Real8(deta[1])/t->det,Real8(deta[2])/t->det);
+				else 
+				{// find the nearest boundary edge  of the vertex A
+					// find a edge or such normal projection a the edge IJ is on the edge
+					//   <=> IJ.IA >=0 && IJ.AJ >=0
+					ilast=ifirst;
+					double ba,bb;
+					TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb);
+					Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+					NewItem(A,Metric(ba,v0,bb,v1));
+					t=edge;
+					// test if the point b is in the same side
+					if (det(v0.i,v1.i,b)>=0) {
+						//cout << " All the edge " << A << B << endl;
+						TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb);
+						Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+						NewItem(A,Metric(ba,v0,bb,v1));
+						return;
+					}
+				} // find the nearest boundary edge  of the vertex A
+			} // end not optimisation 
+			if (t->det<0) {  // outside departure
+				while (t->det <0) { // intersection boundary edge and a,b,
+					k=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+					assert(k>=0);
+					ocut = OppositeEdge[k];
+					i=VerticesOfTriangularEdge[ocut][0];
+					j=VerticesOfTriangularEdge[ocut][1];
+					vi=(*t)[i];
+					vj=(*t)[j];
+					deti = bamg::det(a,b,vi);
+					detj = bamg::det(a,b,vj);
+					//  if(SHOW) {  penthickness(3);
+					// 	Move(vi);Line(vj);CurrentTh->inquire();penthickness(1);
+					//         cout << Bh.Number(tbegin) << " " << Bh.Number(t) << " i= " << i <<" j= " <<  j << " k=" << k 
+					//       	   << " deti= " << deti << " detj= " << detj 
+					// 	     << " v = " << Bh.Number((*t)[i]) << (*t)[i].r <<  " " << Bh.Number((*t)[j]) << (*t)[j].r  << endl;}
+					if (deti>0) // go to  i direction on gamma
+						ocut = PreviousEdge[ocut];      
+					else if (detj<=0) // go to j direction on gamma
+						ocut = NextEdge[ocut];         
+					TriangleAdjacent tadj =t->Adj(ocut);
+					t = tadj;
+					iedge= tadj; 
+					if (t == tbegin) { // 
+						double ba,bb;
+						long int verbosity=2;
+						if (verbosity>7) 
+							cout << "       SplitEdge: All the edge " << A << B << nbegin <<  det(vi,vj,b) 
+								<< " deti= " << deti <<  " detj=" <<detj << endl;
+						TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb);
+						Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+						NewItem(A,Metric(ba,v0,bb,v1));
+						return;
+						/*
+						   cerr << nbegin <<  det(vi,vj,b) << " deti= " << deti <<  " detj=" <<detj << endl;
+						   cerr << "SplitEdge on boucle A" << A << " B = " << B << endl;
+
+#ifdef DRAWING
+reffecran();
+Bh.Draw();
+penthickness(5);
+Move(A);
+Line(B);
+penthickness(1);
+
+Bh.inquire();
+penthickness(5);
+Move(A);
+Line(B);
+penthickness(1);
+Bh.inquire();
+#endif	
+MeshError(997);*/
+					}
+				} //  end while (t->det <0)
+				// theoriticaly we have: deti =<0 and detj>0
+
+				// computation of barycentric coor
+				// test if the point b is on size on t
+				// we revert vi,vj because vi,vj is def in Adj triangle
+				if ( det(vi,vj,b)>=0) {
+					if (verbosity>7)
+						cout << "       SplitEdge: all AB outside " << A << B << endl;
+					t=tbegin;
+					Real8 ba,bb;
+					TriangleAdjacent edge=CloseBoundaryEdge(b,t,ba,bb);
+					NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)));
+					return;
+				}
+				else
+				{
+					k = OppositeVertex[iedge];
+					i=VerticesOfTriangularEdge[iedge][0];
+					j=VerticesOfTriangularEdge[iedge][1];
+					Real8 dij = detj-deti;
+					assert(i+j+k == 0 + 1 +2);
+					ba[j] =  detj/dij;
+					ba[i] = -deti/dij;
+					ba[k] = 0;
+					// 	if(SHOW) cout << i << " " << j << " " << k << " " << ba[i] << " " << ba[j] << endl;
+					ilast=NewItem(t,ba[0],ba[1],ba[2]); }
+			}  //  outside departure
+
+
+
+			// recherche the intersection of [a,b] with Bh Mesh.
+			// we know  a triangle ta contening the vertex a
+			// we have 2 case for intersection [a,b] with a edge [A,B] of Bh
+			// 1) the intersection point is in ]A,B[
+			// 2)                        is A or B
+			// first version --- 
+			for (;;) {
+				//    t->Draw();
+				if (iedge < 0) {
+					i0 =0;i1=1;i2=2;
+					dt[0] =bamg::det(a,b,(*t)[0]);
+					dt[1] =bamg::det(a,b,(*t)[1]);
+					dt[2] =bamg::det(a,b,(*t)[2]);}
+				else {
+					i2 = iedge;
+					i0 = NextEdge[i2];
+					i1 = NextEdge[i0]; 
+					dt[VerticesOfTriangularEdge[iedge][0]] = detj;// we revert i,j because
+					dt[VerticesOfTriangularEdge[iedge][1]] = deti;// we take the Triangle by the other side
+					dt[iedge] = det(a,b,(*t)[OppositeVertex[iedge]]);}
+
+					// so we have just to see the transition from - to + of the det0..2 on edge of t
+					// because we are going from a to b
+					if       ((dt[i=VerticesOfTriangularEdge[i0][0]] <  0) &&
+							( dt[j=VerticesOfTriangularEdge[i0][1]] > 0))
+						ocut =i0;
+					else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] <  0) &&
+							(dt[j=VerticesOfTriangularEdge[i1][1]] >  0))
+						ocut =i1;
+					else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] <  0) && 
+							(dt[j=VerticesOfTriangularEdge[i2][1]] >  0))
+						ocut =i2;
+					else if   ((dt[i=VerticesOfTriangularEdge[i0][0]] == 0) &&
+							( dt[j=VerticesOfTriangularEdge[i0][1]] >  0))
+						ocut =i0;
+					else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] == 0) &&
+							(dt[j=VerticesOfTriangularEdge[i1][1]] >  0))
+						ocut =i1;
+					else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] == 0) && 
+							(dt[j=VerticesOfTriangularEdge[i2][1]] >  0))
+						ocut =i2;
+					else if   ((dt[i=VerticesOfTriangularEdge[i0][0]] <  0) &&
+							( dt[j=VerticesOfTriangularEdge[i0][1]] == 0))
+						ocut =i0;
+					else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] <  0) &&
+							(dt[j=VerticesOfTriangularEdge[i1][1]] == 0))
+						ocut =i1;
+					else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] <  0) && 
+							(dt[j=VerticesOfTriangularEdge[i2][1]] == 0))
+						ocut =i2;
+					else { //  On a edge (2 zero)
+						k =0;
+						if (dt[0]) ocut=0,k++; 
+						if (dt[1]) ocut=1,k++; 
+						if (dt[2]) ocut=2,k++;
+						if(k == 1) {
+							if (dt[ocut] >0) // triangle upper AB
+								ocut = NextEdge[ocut];
+							i= VerticesOfTriangularEdge[ocut][0];
+							j= VerticesOfTriangularEdge[ocut][1];
+						}
+						else  {
+							cerr << " Bug Split Edge " << endl;
+							cerr << " dt[0]= " << dt[0] 
+								<< " dt[1]= " << dt[1] 
+								<< " dt[2]= "<< dt[2] << endl;
+							cerr << i0 << " " << i1 << " " << i2 << endl;
+							cerr << " A = " << A << " B= " << B << endl;
+							cerr << " Triangle t = " <<  *t << endl;
+							cerr << (*t)[0] << (*t)[1] << (*t)[0] << endl;
+							cerr << " nbt = " << nbt << endl;
+							MeshError(100);}}
+
+							k = OppositeVertex[ocut];
+
+							Icoor2 detbij = bamg::det((*t)[i],(*t)[j],b);
+
+
+							if (detbij >= 0) { //we find the triangle contening b
+								dt[0]=bamg::det((*t)[1],(*t)[2],b);
+								dt[1]=bamg::det((*t)[2],(*t)[0],b);
+								dt[2]=bamg::det((*t)[0],(*t)[1],b);
+#ifdef DEBUG 
+								assert(dt[0] >= 0);
+								assert(dt[1] >= 0);
+								assert(dt[2] >= 0);
+#endif
+								Real8 dd = t->det;
+								NewItem(t,dt[0]/dd,dt[1]/dd,dt[2]/dd);      
+								return ;}
+							else { // next triangle by  adjacent by edge ocut 
+								deti = dt[i];
+								detj = dt[j];
+								Real4 dij = detj-deti;
+								ba[i] =  detj/dij;
+								ba[j] = -deti/dij;
+								ba[3-i-j ] = 0;
+								ilast=NewItem(t, ba[0],ba[1],ba[2]);      
+
+								TriangleAdjacent ta =t->Adj(ocut);
+								t = ta;
+								iedge= ta; 
+								if (t->det <= 0)  {
+									double ba,bb;
+									TriangleAdjacent edge=CloseBoundaryEdge(b,t,ba,bb);
+									NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)));
+									// 	cout << " return " << ba << " " << bb << endl;
+									// ajoute le 03 frev 1997 par F. hecht
+									return;
+								}
+							}// we  go outside of omega 
+			} // for(;;)
+
+
+		} // routine SplitEdge
+
+
+		int  ListofIntersectionTriangles::NewItem(Triangle * tt,Real8 d0,Real8 d1,Real8 d2) { 
+			register int n;
+			R2 x(0,0);
+			if ( d0) x =      (*tt)[0].r * d0;
+			if ( d1) x = x +  (*tt)[1].r * d1;
+			if ( d2) x = x +  (*tt)[2].r * d2;
+			// newer add same point 
+			if(!Size ||  Norme2_2(lIntTria[Size-1].x-x)) {
+				if (Size==MaxSize) ReShape();
+				lIntTria[Size].t=tt;
+				lIntTria[Size].bary[0]=d0;
+				lIntTria[Size].bary[1]=d1;
+				lIntTria[Size].bary[2]=d2;
+				lIntTria[Size].x = x;
+				Metric m0,m1,m2;
+				register Vertex * v;
+				if ((v=(*tt)(0))) m0    = v->m;
+				if ((v=(*tt)(1))) m1    = v->m;
+				if ((v=(*tt)(2))) m2    = v->m;
+				lIntTria[Size].m =  Metric(lIntTria[Size].bary,m0,m1,m2);
+#ifdef DEBUG1
+				if(SHOW) { cout << "SHOW       ++ NewItem =" << Size << x ;
+					cout << " " << d0 << " " << d1 << " " << d2 <<endl;}
+#endif
+					n=Size++;}
+			else n=Size-1;
+			return n;
+		}
+		int ListofIntersectionTriangles::NewItem(R2 A,const Metric & mm) {  
+			register int n;
+			if(!Size ||  Norme2_2(lIntTria[Size-1].x-A)) {
+				if (Size==MaxSize) ReShape();
+				lIntTria[Size].t=0;
+				lIntTria[Size].x=A;
+				lIntTria[Size].m=mm;
+#ifdef DEBUG1
+				if (SHOW)  cout << "SHOW       ++ NewItem A" << Size << A << endl;
+#endif
+				n=Size++;
+			}
+			else  n=Size-1;
+			return  n; 
+		}
+
+		Real8  ListofIntersectionTriangles::Length()
+		{
+			//  cout << " n= " << Size << ":" ;
+			assert(Size>0);
+			// computation of the length      
+			R2 C;
+			Metric Mx,My;
+			int ii,jj;
+			R2 x,y,xy;
+
+			SegInterpolation *SegI=lSegsI;
+			SegI=lSegsI;
+			lSegsI[NbSeg].last=Size;// improvement 
+
+			int EndSeg=Size;
+
+			y = lIntTria[0].x;
+			Real8 sxy, s = 0;
+			lIntTria[0].s =0;
+			SegI->lBegin=s;
+
+			for (jj=0,ii=1;ii<Size;jj=ii++) 
+			{  
+				// seg jj,ii
+				x=y;
+				y = lIntTria[ii].x;
+				xy = y-x;
+				Mx = lIntTria[ii].m;
+				My = lIntTria[jj].m;
+				//      Real8 &sx=  lIntTria[ii].sp; // previous seg
+				//  Real8 &sy=  lIntTria[jj].sn; // next seg
+				//      sx = Mx(xy);
+				//      sy = My(xy);
+				//   sxy = (Mx(xy)+ My(xy))/2.0;
+				sxy =  LengthInterpole(Mx,My,xy);
+				s += sxy;
+				lIntTria[ii].s = s;
+				if (ii == EndSeg) 
+					SegI->lEnd=s,
+						SegI++,
+						EndSeg=SegI->last,
+						SegI->lBegin=s;
+
+				//    cout << ii << " " << jj << x<< y <<xy << s <<  lIntTria[ii].m  ;
+			}
+			len = s;
+			SegI->lEnd=s;
+
+			//  cout << " len= " << s << endl;
+			return s;
+		}
+
+		Int4 ListofIntersectionTriangles::NewPoints(Vertex * vertices,Int4 & nbv,Int4  nbvx)
+		{
+			long int verbosity=0;
+
+
+			const Int4 nbvold = nbv;
+			Real8 s = Length();
+			if (s <  1.5 ) return 0;
+			//////////////////////   
+			int ii = 1 ;
+			R2 y,x;
+			Metric My,Mx ;
+			Real8 sx =0,sy;
+			int nbi = Max(2,(int) (s+0.5));
+			Real8 sint = s/nbi;
+			Real8 si = sint;
+
+			int EndSeg=Size;
+			SegInterpolation *SegI=0;
+			if (NbSeg) 
+				SegI=lSegsI,EndSeg=SegI->last;
+
+			for (int k=1;k<nbi;k++)
+			{
+				while ((ii < Size) && ( lIntTria[ii].s <= si )) 
+					if (ii++ == EndSeg) 
+						SegI++,EndSeg=SegI->last;
+
+				int ii1=ii-1;
+				x  =lIntTria[ii1].x;
+				sx =lIntTria[ii1].s;
+				Metric Mx=lIntTria[ii1].m;
+#ifdef DEBUG    
+				double lx = lIntTria[ii-1].sn;
+#endif
+				y  =lIntTria[ii].x;
+				sy =lIntTria[ii].s;
+				Metric My=lIntTria[ii].m;
+#ifdef DEBUG    
+				double ly =lIntTria[ii].sp;  
+				assert( sx <= si);
+				assert( si <= sy);
+				assert( sy != sx);
+#endif 
+
+				Real8 lxy = sy-sx;
+				Real8 cy = abscisseInterpole(Mx,My,y-x,(si-sx)/lxy);
+
+				R2 C;
+				Real8 cx = 1-cy;
+				C = SegI ? SegI->F(si): x * cx + y *cy;
+
+				si += sint;
+				if ( nbv<nbvx) {
+					vertices[nbv].r = C;
+					vertices[nbv++].m = Metric(cx,lIntTria[ii-1].m,cy,lIntTria[ii].m);
+					if((verbosity/100%10)==2)
+						cout << "   -- Add point " << nbv-1 << " " << vertices[nbv-1] << " " << vertices[nbv-1].m << endl;
+
+#ifdef DEBUG
+					if(k>1) {
+						R2 AB = vertices[nbv-2].r - vertices[nbv-1].r ;
+						Real8 dp = LengthInterpole(vertices[nbv-2].m,vertices[nbv-1].m,AB);
+						if (dp > 1.6) {
+							cerr << "PB calcul new Int.  points trop loin l=" << dp << " v=" << nbv-1 << " " << nbv-2 <<Mx<<My<<y-x << endl;
+						}
+					}
+#endif
+				}
+				else return nbv-nbvold;
+			}
+			return nbv-nbvold;
+		}
+
+		int SwapForForcingEdge(Vertex   *  & pva ,Vertex  * &   pvb ,
+				TriangleAdjacent & tt1,Icoor2 & dets1, Icoor2 & detsa,Icoor2 & detsb, int & NbSwap)
+		{ // l'arete ta coupe l'arete pva pvb
+			// de cas apres le swap sa coupe toujours
+			// on cherche l'arete suivante 
+			// on suppose que detsa >0 et detsb <0
+			// attention la routine echange pva et pvb 
+
+			if(tt1.Locked()) return 0; // frontiere croise 
+
+			TriangleAdjacent tt2 = Adj(tt1);
+			Triangle *t1=tt1,*t2=tt2;// les 2 triangles adjacent
+			Int1 a1=tt1,a2=tt2;// les 2 numero de l arete dans les 2 triangles
+			assert ( a1 >= 0 && a1 < 3 );
+
+			Vertex & sa= (* t1)[VerticesOfTriangularEdge[a1][0]];
+			Vertex & s1= (*t1)[OppositeVertex[a1]];
+			Vertex & s2= (*t2)[OppositeVertex[a2]];
+
+
+			Icoor2 dets2 = det(*pva,*pvb,s2);
+
+#ifdef DEBUG
+			Vertex & sb= (*t1)[VerticesOfTriangularEdge[a1][1]];
+			Icoor2 wdets1 = det(*pva,*pvb,s1);  
+			Icoor2 wdetsa = det(*pva,*pvb,sa);
+			Icoor2 wdetsb = det(*pva,*pvb,sb);
+			assert(wdets1 == dets1);
+			assert(wdetsa == detsa);
+			assert(wdetsb == detsb);
+#endif
+
+			Icoor2 det1=t1->det , det2=t2->det ;
+#ifdef DEBUG  
+			assert(det1>0 && det2 >0);
+			Icoor2 ddet1 = det((*t1)[0],(*t1)[1],(*t1)[2]);
+			Icoor2 ddet2 = det((*t2)[0],(*t2)[1],(*t2)[2]);
+			if ((det1 != ddet1) || (det2 != ddet2) )
+			{
+				assert(det1 == ddet1);
+				assert(det2 == ddet2);
+			}
+			Icoor2 detvasasb = det(*pva,sa,sb);
+			Icoor2 detvbsasb = det(*pvb,sa,sb);
+			if (  CurrentTh && !  ( ( (detvasasb <= 0) && (detvbsasb >= 0)) || ( (detvasasb >= 0) && (detvbsasb <= 0)))) 
+			{
+				cout << " detvasasb =" <<  detvasasb << "detvbsasb = " <<  detvbsasb 
+					<< " " << pva << " " << pvb << " "  <<CurrentTh <<endl;
+#ifdef DRAWING1
+				reffecran();
+				CurrentTh->Draw();
+				penthickness(10);
+				pva->MoveTo();pvb->LineTo();
+				penthickness(1);
+				CurrentTh->inquire();
+#endif       
+			}
+			assert( ( (detvasasb <= 0) && (detvbsasb >= 0)) || ( (detvasasb >= 0) && (detvbsasb <= 0)));
+#endif
+
+			Icoor2 detT = det1+det2;
+			assert((det1>0 ) && (det2 > 0));
+			assert ( (detsa < 0) && (detsb >0) ); // [a,b] cut infinite line va,bb
+			Icoor2 ndet1 = bamg::det(s1,sa,s2);
+			Icoor2 ndet2 = detT - ndet1;
+
+			int ToSwap =0; //pas de swap
+			if ((ndet1 >0) && (ndet2 >0)) 
+			{ // on peut swaper  
+				if ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0))
+					ToSwap =1; 
+				else // swap alleatoire 
+					if (BinaryRand()) 
+						ToSwap =2; 
+			}
+#ifdef DEBUG
+			if (ForDebugging) {
+				cerr << "swap = " << ToSwap << " ndet1 " << ndet1 << ", ndet2 " << ndet2 << "det1  " << det1 << " det2 " <<  det2  
+					<< " if1 = " << ((ndet1 >0) && (ndet2 >0)) 
+					<< " if2 = " << ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0)) << endl;
+#ifdef DRAWING
+				couleur(0);
+				t1->Draw();
+				t2->Draw();
+#endif
+			}
+#endif
+			if (ToSwap) NbSwap++,
+				bamg::swap(t1,a1,t2,a2,&s1,&s2,ndet1,ndet2);
+
+#ifdef DEBUG
+			if (ForDebugging) {
+#ifdef DRAWING
+				couleur(4);
+				t1->Draw();
+				t2->Draw();
+				rattente(1);
+#endif
+			}
+#endif
+			int ret=1;
+
+			if (dets2 < 0) {// haut
+				dets1 = ToSwap ? dets1 : detsa ;
+				detsa = dets2; 
+				tt1 =  Previous(tt2) ;}
+			else if (dets2 > 0){// bas 
+				dets1 = ToSwap ? dets1 : detsb ;
+				detsb = dets2;
+				//xxxx tt1 = ToSwap ? tt1 : Next(tt2);
+				if(!ToSwap) tt1 =  Next(tt2);
+			}
+			else { // changement de sens 
+				if (ForDebugging)  cout << "changement de sens" << endl;
+				ret = -1;
+				Exchange(pva,pvb);
+				Exchange(detsa,detsb);
+				Exchange(dets1,dets2);
+				Exchange(tt1,tt2);
+				dets1=-dets1;
+				dets2=-dets2;
+				detsa=-detsa;
+				detsb=-detsb;
+
+				if (ToSwap) 
+					if (dets2 < 0) {// haut
+						dets1 = (ToSwap ? dets1 : detsa) ;
+						detsa = dets2; 
+						tt1 =  Previous(tt2) ;}
+					else if (dets2 > 0){// bas 
+						dets1 = (ToSwap ? dets1 : detsb) ;
+						detsb =  dets2;
+						if(!ToSwap) tt1 =  Next(tt2);
+					}
+					else {// on a fin ???
+						tt1 = Next(tt2);
+						ret =0;}
+
+			}
+			return ret;
+		}
+
+		int ForceEdge(Vertex &a, Vertex & b,TriangleAdjacent & taret)  
+		{ 
+#ifdef DEBUG
+restart: // for debug 
+#endif
+			int NbSwap =0;
+			assert(a.t && b.t); // the 2 vertex is in a mesh 
+			int k=0;
+			taret=TriangleAdjacent(0,0); // erreur 
+
+			TriangleAdjacent tta(a.t,EdgesVertexTriangle[a.vint][0]);
+			Vertex   *v1, *v2 = tta.EdgeVertex(0),*vbegin =v2;
+			// we turn around a in the  direct sens  
+
+			Icoor2 det2 = v2 ? det(*v2,a,b): -1 , det1;
+			if(v2) // normal case 
+				det2 = det(*v2,a,b);
+			else { // no chance infini vertex try the next
+				tta= Previous(Adj(tta));
+				v2 = tta.EdgeVertex(0);
+				vbegin =v2;
+				assert(v2);
+				det2 = det(*v2,a,b);
+				//   cout << " No Change try the next" << endl;
+			}
+
+#ifdef DRAWING1
+			a.MoveTo();b.LineTo();
+#endif
+
+			while (v2 != &b) {
+				TriangleAdjacent tc = Previous(Adj(tta));    
+				v1 = v2; 
+				v2 = tc.EdgeVertex(0);
+				det1 = det2;
+#ifdef DEBUG
+				assert( v1 ==  tta.EdgeVertex(0));
+				assert( &a ==  tc.EdgeVertex(1) );
+#endif
+				det2 =  v2 ? det(*v2,a,b): det2; 
+
+				if((det1 < 0) && (det2 >0)) { 
+					// try to force the edge 
+					Vertex * va = &a, *vb = &b;
+					tc = Previous(tc);
+					assert ( v1 && v2);
+					Icoor2 detss = 0,l=0,ks;
+					// cout << "Real ForcingEdge " << *va << *vb << detss << endl;
+#ifdef DEBUG
+					Icoor2 dettt1 =  det(*v1,a,b);
+					Icoor2 dettt2 =  det(*v2,a,b);
+
+					if (!(dettt1==det1 && dettt2==det2))
+					{
+						assert(ForDebugging==0);
+						ForDebugging=1;
+						goto restart;
+					}
+
+#endif 
+					while ((ks=SwapForForcingEdge(  va,  vb, tc, detss, det1,det2,NbSwap)))
+						if(l++ > 10000000) {
+							cerr << " Loop in forcing Egde AB" 
+								<<"\n vertex A " << a 
+								<<"\n vertex B " <<  b 
+								<<"\n nb de swap " << NbSwap 
+								<<"\n nb of try  swap too big = " <<  l << " gearter than " <<  1000000 << endl;
+
+							if ( CurrentTh ) 
+								cerr << " vertex number " << CurrentTh->Number(a) << " " <<  CurrentTh->Number(b) << endl;
+#ifdef DEBUG
+							ForDebugging = 1;
+#endif
+#ifdef DRAWING1
+							if (  CurrentTh ) {
+								reffecran();
+								couleur(6);
+								CurrentTh->Draw();
+								couleur(1);
+								penthickness(10);
+								a.MoveTo();b.LineTo();
+								penthickness(1);
+								CurrentTh->inquire();
+								couleur(6);
+								l=0;
+								reffecran();
+								while (ks=SwapForForcingEdge(  va,  vb, tc, detss, det1,det2,NbSwap) && (l++ < 1000))
+									cerr << " " << CurrentTh->Number(tc.EdgeVertex(0))<<" " <<CurrentTh->Number(tc.EdgeVertex(1)) << " ";
+							}
+#endif	  
+							MeshError(990);
+						}
+					Vertex *aa = tc.EdgeVertex(0), *bb = tc.EdgeVertex(1);
+					if (( aa == &a ) && (bb == &b) ||  (bb ==  &a ) && (aa == &b)) {
+						tc.SetLock();
+						a.Optim(1,0);
+						b.Optim(1,0);
+						taret = tc;
+						return NbSwap;
+					}
+					else 
+					{
+						taret = tc;
+						return -2; // error  boundary is crossing
+						/*	  cerr << "Fatal Error  boundary is crossing  ";
+							  if(CurrentTh)
+							  {
+							  cerr << " edge:  [" << CurrentTh->Number(a) << ", " << CurrentTh->Number(b) <<  " ] and [ ";
+							  cerr    << CurrentTh->Number(aa) << " " << CurrentTh->Number(bb) << " ] " << endl;
+							  }
+							  MeshError(991);
+							  */	  
+					}
+				}
+				tta = tc;
+				assert(k++<2000);
+				if ( vbegin == v2 ) return -1;// error 
+			}
+
+			tta.SetLock();
+			taret=tta;
+			a.Optim(1,0);
+			b.Optim(1,0);
+			return NbSwap; 
+		}
+
+
+		int Triangle::swap(Int2 a,int koption){
+#ifdef DEBUG
+			if(a &4 ) return 0;// arete lock 
+			int munswap1 = a/4;
+			a &=3;
+#else
+			if(a/4 !=0) return 0;// arete lock or MarkUnSwap
+#endif
+
+			register Triangle *t1=this,*t2=at[a];// les 2 triangles adjacent
+			register Int1 a1=a,a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+#ifdef DEBUG
+			if(a2 & 4) return 0; // arete lock
+			int munswap2 = a2/4;
+			a2 &= 3;
+#else
+			if(a2/4 !=0) return 0; // arete lock or MarkUnSwap
+#endif
+
+			register Vertex  *sa=t1->ns[VerticesOfTriangularEdge[a1][0]];
+			register Vertex  *sb=t1->ns[VerticesOfTriangularEdge[a1][1]];
+			register Vertex  *s1=t1->ns[OppositeVertex[a1]];
+			register Vertex  *s2=t2->ns[OppositeVertex[a2]];
+
+#ifdef DEBUG
+			assert ( a >= 0 && a < 3 );  
+#endif
+
+			Icoor2 det1=t1->det , det2=t2->det ;
+			Icoor2 detT = det1+det2;
+			Icoor2 detA = Abs(det1) + Abs(det2);
+			Icoor2 detMin = Min(det1,det2);
+
+			int OnSwap = 0;       
+			// si 2 triangle infini (bord) => detT = -2;
+			if (sa == 0) {// les deux triangles sont frontieres
+				det2=bamg::det(s2->i,sb->i,s1->i);
+				OnSwap = det2 >0;}
+			else if (sb == 0) { // les deux triangles sont frontieres
+				det1=bamg::det(s1->i,sa->i,s2->i);
+				OnSwap = det1 >0;}
+			else if(( s1 != 0) && (s2 != 0) ) {
+				det1 = bamg::det(s1->i,sa->i,s2->i);
+				det2 = detT - det1;
+				OnSwap = (Abs(det1) + Abs(det2)) < detA;
+
+				Icoor2 detMinNew=Min(det1,det2);
+				//     if (detMin<0 && (Abs(det1) + Abs(det2) == detA)) OnSwap=BinaryRand();// just for test   
+				if (! OnSwap &&(detMinNew>0)) {
+					OnSwap = detMin ==0;
+					if (! OnSwap) {
+						int  kopt = koption;
+						while (1)
+							if(kopt) {
+								// critere de Delaunay pure isotrope
+								register Icoor2 xb1 = sb->i.x - s1->i.x,
+										 x21 = s2->i.x - s1->i.x,
+										 yb1 = sb->i.y - s1->i.y,
+										 y21 = s2->i.y - s1->i.y,
+										 xba = sb->i.x - sa->i.x, 
+										 x2a = s2->i.x - sa->i.x,
+										 yba = sb->i.y - sa->i.y,
+										 y2a = s2->i.y - sa->i.y;
+								register double
+									cosb12 =  double(xb1*x21 + yb1*y21),
+										   cosba2 =  double(xba*x2a + yba*y2a) ,
+										   sinb12 = double(det2),
+										   sinba2 = double(t2->det);
+
+
+								// angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2)
+								OnSwap =  ((double) cosb12 * (double)  sinba2) <  ((double) cosba2 * (double) sinb12);
+								//  	 if(CurrentTh) 
+								//  	   cout << "swap " << CurrentTh->Number(sa) << " " << CurrentTh->Number(sb) << " " ;
+								//  	 cout <<  cosb12 << " " <<  sinba2 << " "  <<  cosba2 << " " << sinb12 
+								//  	      << " Onswap = " <<  OnSwap << endl;
+								break;
+							}
+							else 
+							{	
+								// critere de Delaunay anisotrope 
+								Real8 som;
+								I2 AB=(I2) *sb - (I2) *sa;
+								I2 MAB2=((I2) *sb + (I2) *sa);
+								R2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+								I2 A1=(I2) *s1 - (I2) *sa;
+								I2 D = (I2) * s1 - (I2) * sb ;
+								R2 S2(s2->i.x,s2->i.y);
+								R2 S1(s1->i.x,s1->i.y);
+								{
+									Metric M=s1->m;
+									R2 ABo = M.Orthogonal(AB);
+									R2 A1o = M.Orthogonal(A1);
+									// (A+B)+ x ABo = (S1+B)/2+ y A1 
+									// ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+									double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+									double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+									if (Abs(d) > dd*1.e-3) {
+										R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+										som  = M(C - S2)/M(C - S1);
+									} else 
+									{kopt=1;continue;}
+
+								}
+								{
+									Metric M=s2->m;
+									R2 ABo = M.Orthogonal(AB);
+									R2 A1o = M.Orthogonal(A1);
+									// (A+B)+ x ABo = (S1+B)/2+ y A1 
+									// ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+									double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+									double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+									if(Abs(d) > dd*1.e-3) {
+										R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+										som  += M(C - S2)/M(C -  S1);
+									} else 
+									{kopt=1;continue;}
+								}
+								OnSwap = som < 2;
+								break;
+							}
+
+					} // OnSwap 
+				} // (! OnSwap &&(det1 > 0) && (det2 > 0) )
+			}
+#ifdef  DEBUG1   
+			if (OnSwap &&  ( munswap1  || munswap2)) {
+				cout << " erreur Mark unswap T " << CurrentTh->Number(t1) << " " <<  CurrentTh->Number(t2) << endl
+					<< *t1 << endl
+					<< *t2 << endl;
+				return 0;
+			}
+#endif 
+			if( OnSwap ) 
+				bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2);
+			else {
+				NbUnSwap ++;
+				t1->SetMarkUnSwap(a1);     
+			}
+			return OnSwap;
+		}
+
+		Real8  Vertex::Smoothing(Triangles & Th,const Triangles & BTh,Triangle  * & tstart ,Real8 omega)
+		{
+#ifdef DEBUG  
+			register  Int4 NbSwap =0;
+#endif
+			register Vertex * s  = this;
+			Vertex &vP = *s,vPsave=vP;
+			//  if (vP.on) return 0;// Don't move boundary vertex  
+
+			register Triangle * tbegin= t , *tria = t , *ttc;
+
+			register int k=0,kk=0,j = EdgesVertexTriangle[vint][0],jc;
+			R2 P(s->r),PNew(0,0);
+			//  cout << BTh.quadtree << " " <<  BTh.quadtree->root << endl;
+			// assert(BTh.quadtree && BTh.quadtree->root);
+			do {
+				k++; 
+
+#ifdef DEBUG
+				assert( s == & (*tria)[VerticesOfTriangularEdge[j][1]] );
+				assert( tria->det >0);
+#endif
+				if (!tria->Hidden(j))
+				{
+					Vertex &vQ = (*tria)[VerticesOfTriangularEdge[j][0]]; 
+
+					R2 Q = vQ,QP(P-Q);
+					Real8 lQP = LengthInterpole(vP,vQ,QP);
+					PNew += Q+QP/Max(lQP,1e-20);
+					kk ++;
+				}
+				ttc =  tria->TriangleAdj(j);
+				jc = NextEdge[tria->NuEdgeTriangleAdj(j)];
+				tria = ttc;
+				j = NextEdge[jc];
+				assert(k<2000);
+			} while ( tbegin != tria); 
+			if (kk<4) return 0;
+			PNew = PNew/(Real8)kk;
+			R2 Xmove((PNew-P)*omega);
+			PNew = P+Xmove;
+			Real8 delta=Norme2_2(Xmove); 
+
+
+			// 
+			Icoor2 deta[3];
+			I2 IBTh  = BTh.toI2(PNew);
+
+			tstart=BTh.FindTriangleContening(IBTh,deta,tstart);  
+
+			if (tstart->det <0) 
+			{ // outside
+				double ba,bb;
+				TriangleAdjacent edge= CloseBoundaryEdge(IBTh,tstart,ba,bb) ;
+				tstart = edge;
+				vP.m= Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));
+			}
+			else 
+			{ // inside
+				Real8   aa[3];
+				Real8 s = deta[0]+deta[1]+deta[2];
+				aa[0]=deta[0]/s;
+				aa[1]=deta[1]/s;
+				aa[2]=deta[2]/s;
+				vP.m = Metric(aa,(*tstart)[0],(*tstart)[1],(*tstart)[2]);
+			}
+
+			// recompute the det of the triangle
+			vP.r = PNew;
+
+			vP.i = Th.toI2(PNew);
+
+			Vertex vPnew = vP;
+
+			int ok=1;
+			int loop=1;
+			k=0;
+			while (ok) 
+			{
+				ok =0;
+				do {
+					k++; 
+					double detold = tria->det;
+					tria->det =  bamg::det( (*tria)[0],(*tria)[1]  ,(*tria)[2]);
+					if (loop) 
+					{
+						Vertex *v0,*v1,*v2,*v3;
+						if (tria->det<0) ok =1;			       
+						else if (tria->Quadrangle(v0,v1,v2,v3))
+						{
+							vP = vPsave;
+							Real8 qold =QuadQuality(*v0,*v1,*v2,*v3);
+							vP = vPnew;
+							Real8 qnew = QuadQuality(*v0,*v1,*v2,*v3);
+							if (qnew<qold) ok = 1;
+						}
+						else if ( (double)tria->det < detold/2 ) ok=1;
+
+					}
+					tria->SetUnMarkUnSwap(0);
+					tria->SetUnMarkUnSwap(1);
+					tria->SetUnMarkUnSwap(2);
+					ttc =  tria->TriangleAdj(j);
+					jc = NextEdge[tria->NuEdgeTriangleAdj(j)];
+					tria = ttc;
+					j = NextEdge[jc];
+					assert(k<2000);
+				} while ( tbegin != tria); 
+				if (ok && loop) vP=vPsave; // no move 
+				loop=0;
+			}
+			return delta;
+		}
+
+
+
+
+		void Triangles::Add( Vertex & s,Triangle * t, Icoor2 * det3) 
+		{
+			// -------------------------------------------
+			//             s2
+			//                                            !
+			//             /|\                            !
+			//            / | \                           !
+			//           /  |  \                          !
+			//    tt1   /   |   \ tt0                     !
+			//         /    |s   \                        !
+			//        /     .     \                       !
+			//       /  .      `   \                      !
+			//      / .           ` \                     !
+			//      ----------------                      !
+			//   s0       tt2       s1
+			//-------------------------------------------- 
+
+			Triangle * tt[3]; // the 3 new Triangles
+			Vertex &s0 = (* t)[0], &s1=(* t)[1], &s2=(* t)[2];
+			Icoor2  det3local[3];
+			int infv = &s0 ?  ((  &s1 ? ( &s2  ? -1 : 2) : 1  )) : 0;
+			// infv = ordre of the infini vertex (null)
+			register int nbd0 =0; // number of zero det3
+			register int izerodet=-1,iedge; // izerodet = egde contening the vertex s
+			Icoor2 detOld = t->det;
+
+			if ( ( infv <0 ) && (detOld <0) ||  ( infv >=0  ) && (detOld >0) ) 
+			{
+				cerr << "  infv " << infv << " det = " << detOld << endl;
+				cerr << Number(s) << " "<< Number(s0) << " "  
+					<< Number(s1) << " "  << Number(s2) << endl;
+				MeshError(3);
+			}
+
+			// if det3 do not exist then constuct det3
+			if (!det3) { 
+				det3 = det3local; // alloc 
+				if ( infv<0 ) {
+					det3[0]=bamg::det(s ,s1,s2);
+					det3[1]=bamg::det(s0,s ,s2);
+					det3[2]=bamg::det(s0,s1,s );}
+				else { 
+					// one of &s1  &s2  &s0 is NULL so (&si || &sj) <=> !&sk
+					det3[0]=  &s0 ? -1  : bamg::det(s ,s1,s2) ;
+					det3[1]=  &s1 ? -1 : bamg::det(s0,s ,s2) ;
+					det3[2]=  &s2 ? -1 : bamg::det(s0,s1,s ) ;}}
+
+
+					if (!det3[0]) izerodet=0,nbd0++;
+					if (!det3[1]) izerodet=1,nbd0++;
+					if (!det3[2]) izerodet=2,nbd0++;
+
+					if  (nbd0 >0 ) // point s on a egde or on a vertex 
+						if (nbd0 == 1) {
+							iedge = OppositeEdge[izerodet];
+							TriangleAdjacent ta = t->Adj(iedge);
+
+#ifdef DEBUG1      
+							cout << " the point " << Number(s) << " is the edge " <<  izerodet 
+								<< " of " << Number(t)	   << " det3 = " 
+								<< det3[0] << " " <<  det3[1] << " " <<  det3[2] << " " <<  endl;
+							cout  << " ta = "  <<  ta << "ta->det =" << ((Triangle*) ta)->det  
+								<< " "<< t->det<< endl;
+#endif
+
+							// the point is on the edge 
+							// if the point is one the boundary 
+							// add the point in outside part 
+							if ( t->det >=0) { // inside triangle
+								if ((( Triangle *) ta)->det < 0 ) {
+									// add in outside triangle 
+									Add(s,( Triangle *) ta);
+									return;}
+							}}
+						else {
+							cerr << " bug  " << nbd0 <<endl;
+							cerr << " Bug double points in " << endl ;
+							cerr << " s = " << Number(s) << " " <<  s << endl;
+							cerr << " s0 = "<< Number(s0) << " "  << s0 << endl;
+							cerr << " s1 = "<< Number(s1) << " "  << s1 << endl;
+							cerr << " s2 = "<< Number(s2) << " "  << s2 << endl;
+							MeshError(5,this);}
+
+							// remove de MarkUnSwap edge
+							t->SetUnMarkUnSwap(0);     
+							t->SetUnMarkUnSwap(1);     
+							t->SetUnMarkUnSwap(2);
+
+							tt[0]= t;
+							tt[1]= &triangles[nbt++];
+							tt[2]= &triangles[nbt++];
+
+							if (nbt>nbtx) {
+								cerr << " No enougth triangles " << endl;
+								MeshError(999,this);
+							}
+
+							*tt[1]=   *tt[2]= *t;
+							// gestion of the link
+							tt[0]->link=tt[1];
+							tt[1]->link=tt[2]; 
+
+							(* tt[0])(OppositeVertex[0])=&s;
+							(* tt[1])(OppositeVertex[1])=&s;
+							(* tt[2])(OppositeVertex[2])=&s;
+
+							tt[0]->det=det3[0];
+							tt[1]->det=det3[1];
+							tt[2]->det=det3[2];         
+
+							//  update adj des triangles externe 
+							tt[0]->SetAdjAdj(0);
+							tt[1]->SetAdjAdj(1);
+							tt[2]->SetAdjAdj(2);
+							//  update des adj des 3 triangle interne
+							const int i0 = 0;
+							const int i1= NextEdge[i0];
+							const int i2 = PreviousEdge[i0];
+
+							tt[i0]->SetAdj2(i2,tt[i2],i0);
+							tt[i1]->SetAdj2(i0,tt[i0],i1);
+							tt[i2]->SetAdj2(i1,tt[i1],i2);
+
+							tt[0]->SetTriangleContainingTheVertex();
+							tt[1]->SetTriangleContainingTheVertex();
+							tt[2]->SetTriangleContainingTheVertex();
+
+
+							// swap if the point s is on a edge
+							if(izerodet>=0) {
+								//  cout << " the point s is on a edge =>swap " << iedge << " "  << *tt[izerodet] << endl;
+								int rswap =tt[izerodet]->swap(iedge);
+
+								if (!rswap) 
+								{
+									cout << " Pb swap the point s is on a edge =>swap " << iedge << " "  << *tt[izerodet] << endl;
+#ifdef DRAWING
+									if(  CurrentTh &&  withrgraphique) 
+									{
+										reffecran();
+
+										DrawMark(s.r);
+										CurrentTh->inquire();
+										DrawMark(s.r);
+										rattente(1); 
+									}      
+#endif
+								}
+								assert(rswap);
+							}
+
+#ifdef DEBUG 
+							tt[0]->check();
+							tt[1]->check();
+							tt[2]->check();
+#endif
+#ifdef DRAWING1 
+							tt[0]->Draw();
+							tt[1]->Draw();
+							tt[2]->Draw();
+#endif
+
+		}
+
+
+		Int4  Triangles::SplitInternalEdgeWithBorderVertices()
+		{
+			Int4 NbSplitEdge=0;
+			SetVertexFieldOn();  
+			Int4 it;
+			Int4 nbvold=nbv;
+			long int verbosity=2;
+			for (it=0;it<nbt;it++)
+			{
+				Triangle &t=triangles[it];
+				if (t.link)
+					for (int j=0;j<3;j++)
+						if(!t.Locked(j) && !t.Hidden(j)){
+							Triangle &tt = *t.TriangleAdj(j);
+							if ( &tt && tt.link && it < Number(tt)) 
+							{ // an internal edge 
+								Vertex &v0 = t[VerticesOfTriangularEdge[j][0]];
+								Vertex &v1 = t[VerticesOfTriangularEdge[j][1]];
+								if (v0.on && v1.on)
+								{
+									R2 P= ((R2) v0 + (R2) v1)*0.5;
+									if ( nbv<nbvx) {
+										vertices[nbv].r = P;
+										vertices[nbv++].m = Metric(0.5,v0.m,0.5,v1.m);
+										vertices[nbv].ReferenceNumber=0;
+										vertices[nbv].DirOfSearch = NoDirOfSearch ;
+									}
+									NbSplitEdge++;
+									if (verbosity>7)
+										cout <<" Internal edge with two vertices on boundary" 
+											<< Number(v0) << " " << Number(v1) << " by " <<  endl;
+								}
+							}
+						}
+			}
+			ReMakeTriangleContainingTheVertex();    
+			if (nbvold!=nbv) 
+			{
+				Int4  iv = nbvold;
+				Int4 NbSwap = 0;
+				Icoor2 dete[3];  
+				for (Int4 i=nbvold;i<nbv;i++) 
+				{// for all the new point
+					Vertex & vi = vertices[i];
+					vi.i = toI2(vi.r);
+					vi.r = toR2(vi.i);
+					//      if (!quadtree->ToClose(vi,seuil,hi,hj)) {
+					// a good new point 
+					vi.ReferenceNumber=0; 
+					vi.DirOfSearch =NoDirOfSearch;
+					//	cout << " Add " << Number(vi) << " " << vi 
+					// << "   " <<  Number(vi) << " <--> " << Number(vi) <<endl;
+					Triangle *tcvi = FindTriangleContening(vi.i,dete);
+					if (tcvi && !tcvi->link) {
+						cout << i <<  " PB insert point " << Number(vi) << vi << Number(vi) 
+							<< " tcvi = " << tcvi << " " << tcvi->link << endl;
+						cout << (*tcvi)[1] <<  (*tcvi)[2] << endl;
+						tcvi = FindTriangleContening(vi.i,dete);
+						cout << (*tcvi)[1] <<  (*tcvi)[2] << endl;
+#ifdef DRAWING1
+						inquire();
+						penthickness(5);
+						DrawMark(vi.r);
+						penthickness(1);
+						inquire();
+#endif
+
+						MeshError(1001,this);
+					}
+
+
+					quadtree->Add(vi);
+#ifdef DRAWING1
+					DrawMark(vi.r);
+#endif
+					assert (tcvi && tcvi->det >= 0) ;// internal 
+					Add(vi,tcvi,dete);
+					NbSwap += vi.Optim(1);          
+					iv++;
+					//      }
+				}
+				if (verbosity>3) 
+				{
+					cout << "    Nb Of New Point " << iv ;
+					cout << " Nb swap = " << NbSwap << " to  split internal edges with border vertices" ;}
+
+					nbv = iv;
+			}
+			if (NbSplitEdge >  nbv-nbvold)
+				cout << " Warning not enough vertices  to split all internal edges "  << endl
+					<< "    we lost " << NbSplitEdge - ( nbv-nbvold) << " Edges Sorry " << endl;
+			if (verbosity>2)
+				cout << "SplitInternalEdgeWithBorderVertices: Number of splited edge " << NbSplitEdge << endl;
+			return  NbSplitEdge;
+		}
+		Int4 Triangles::InsertNewPoints(Int4 nbvold,Int4 & NbTSwap)
+		{
+			long int verbosity=2;
+			Real8 seuil= 1.414/2 ;// for two close point 
+			Int4 i;
+			// insertion part --- 
+
+			const Int4 nbvnew = nbv-nbvold;
+			if (verbosity>5) 
+				cout << "    Try to Insert the " <<nbvnew<< " new points " << endl;  
+			Int4 NbSwap=0;
+			Icoor2 dete[3];
+
+			// construction d'un ordre aleatoire 
+			if (! nbvnew) 
+				return 0; 
+			if (nbvnew) {
+				const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv)  ;
+				Int4 k3 = rand()%nbvnew ; 
+				for (Int4 is3=0; is3<nbvnew; is3++) {
+					register Int4 j = nbvold +(k3 = (k3 + PrimeNumber)% nbvnew);
+					register Int4 i = nbvold+is3; 
+					ordre[i]= vertices + j;
+					ordre[i]->ReferenceNumber=i;
+				}
+				// be carefull 
+				Int4  iv = nbvold;
+				for (i=nbvold;i<nbv;i++) 
+				{// for all the new point
+					Vertex & vi = *ordre[i];
+					vi.i = toI2(vi.r);
+					vi.r = toR2(vi.i);
+					Real4 hx,hy;
+					vi.m.Box(hx,hy);
+					Icoor1 hi=(Icoor1) (hx*coefIcoor),hj=(Icoor1) (hy*coefIcoor);
+					if (!quadtree->ToClose(vi,seuil,hi,hj)) 
+					{
+						// a good new point 
+						Vertex & vj = vertices[iv];
+						Int4 j = vj.ReferenceNumber; 
+						assert( &vj== ordre[j]);
+						if(i!=j)
+						{ //  for valgring 
+							Exchange(vi,vj);
+							Exchange(ordre[j],ordre[i]);
+						}
+						vj.ReferenceNumber=0; 
+						//	cout << " Add " << Number(vj) << " " << vj 
+						// << "   " <<  Number(vi) << " <--> " << Number(vj) <<endl;
+						Triangle *tcvj = FindTriangleContening(vj.i,dete);
+						if (tcvj && !tcvj->link) 
+						{
+							cerr << i <<  " PB insert point " << Number(vj) << vj << Number(vi) 
+								<< " tcvj = " << tcvj << " " << tcvj->link << endl;
+							cerr << (*tcvj)[1] <<  (*tcvj)[2] << endl;
+							tcvj = FindTriangleContening(vj.i,dete);
+							cout << (*tcvj)[1] <<  (*tcvj)[2] << endl;
+#ifdef DRAWING1
+							inquire();
+							penthickness(5);
+							DrawMark(vj.r);
+							penthickness(1);
+
+							inquire();
+#endif
+
+							MeshError(1001,this);
+						}
+
+
+						quadtree->Add(vj);
+#ifdef DRAWING1
+						DrawMark(vj.r);
+#endif
+						assert (tcvj && tcvj->det >= 0) ;// internal 
+						Add(vj,tcvj,dete);
+						NbSwap += vj.Optim(1);          
+						iv++;
+					}
+				} 
+				if (verbosity>3) {
+					cout << "    Nb Of New Point " << iv << " Nb Of To close Points " << nbv-iv ;
+					cout << " Nb swap = " << NbSwap << " after " ;}
+
+					nbv = iv;
+			}
+
+#ifdef DRAWING1
+			inquire();
+#endif
+
+			for (i=nbvold;i<nbv;i++) 
+				NbSwap += vertices[i].Optim(1);  
+			if (verbosity>3) 
+				cout << " NbSwap = " <<  NbSwap << endl;
+
+
+			NbTSwap +=  NbSwap ;
+#ifdef DEBUG
+			{  
+				Int4 NbErr=0;
+				Int4 i;
+				for (i=0;i<nbt;i++)
+					if (triangles[i].link) 
+					{
+						double dd =Det(triangles[i][1].r-triangles[i][0].r,triangles[i][2].r-triangles[i][0].r);
+						if(dd <=0) 
+						{
+							NbErr++;
+							cerr << " det triangle i " << i << " = " << triangles[i].det ;
+							cerr << " det triangle  " << dd ;
+							cerr << " Les trois sommets " ;
+							cerr << Number(triangles[i][0]) << " "  << Number(triangles[i][1]) << " " 
+								<< Number(triangles[i][2]) << endl;
+							cerr << "I2     " <<triangles[i][0].r << triangles[i][1].r << triangles[i][2].r << endl;
+							cerr << "R2     " << triangles[i][0].i << triangles[i][1].i << triangles[i][2].i << endl;
+							cerr << "I2-R2 =" <<toR2(triangles[i][0].i)-triangles[i][0].r 
+								<< toR2(triangles[i][1].i)-triangles[i][1].r
+								<< toR2(triangles[i][2].i)-triangles[i][2].r << endl;
+						}
+					}
+				if(NbErr) { 
+#ifdef DRAWING
+					Int4 kkk=0;
+					//  UnMarkUnSwapTriangle();
+					//  for (i=0;i<nbv;i++)
+					//  kkk += vertices[i].Optim(0);
+					if(verbosity>3)
+						cout << "    Nb of swap louche " << kkk << endl;
+					if(kkk) {
+						for (i=0;i<nbt;i++)
+							if (triangles[i].link) 
+							{
+								double dd =Det(triangles[i][1].r-triangles[i][0].r,triangles[i][2].r-triangles[i][0].r);
+								if(dd <=0) 
+								{
+									NbErr++;
+									cerr << " xxxdet triangle i " << i << " = " << triangles[i].det ;
+									cerr << " xxxdet triangle  " << dd ;
+									cerr << " xxxLes trois sommets " ;
+									cerr << Number(triangles[i][0]) << " "  << Number(triangles[i][1]) << " " 
+										<< Number(triangles[i][2]) << endl;
+									cerr << triangles[i][0].r << triangles[i][1].r << triangles[i][2].r << endl;
+									cerr << triangles[i][0].i << triangles[i][1].i << triangles[i][2].i << endl;
+								}
+							} }
+					inquire();
+#endif
+					//   MeshError(11);
+				}
+
+			}
+#endif
+			return nbv-nbvold;
+
+		}
+		void  Triangles::NewPoints(Triangles & Bh,int KeepBackVertex)
+		{ // Triangles::NewPoints
+			long int verbosity=2;
+			Int4 nbtold(nbt),nbvold(nbv);
+			if (verbosity>2) 
+				cout << "  -- Triangles::NewPoints ";
+			if (verbosity>3)cout <<  " nbv (in)  on Boundary  = " << nbv  <<endl;
+			Int4 i,k;
+			int j;
+			Int4 *first_np_or_next_t = new Int4[nbtx];
+			Int4 NbTSwap =0;
+			//    insert old point
+			nbtold = nbt;
+
+			if (KeepBackVertex && (&Bh != this) && (nbv+Bh.nbv< nbvx)) 
+			{
+				//   Bh.SetVertexFieldOn();
+				for (i=0;i<Bh.nbv;i++)
+				{ 
+					Vertex & bv = Bh[i];
+					if (!bv.on) {
+						vertices[nbv].r = bv.r;
+						vertices[nbv++].m = bv.m;}
+				}
+				int nbv1=nbv;
+				Bh.ReMakeTriangleContainingTheVertex();     
+				InsertNewPoints(nbvold,NbTSwap)   ;            
+				if (verbosity>2)
+					cout <<  "      (Nb of Points from background mesh  = " 
+						<< nbv-nbvold  << " / " << nbv1-nbvold << ")" << endl;
+			}  
+			else 
+				Bh.ReMakeTriangleContainingTheVertex();     
+
+			Triangle *t;
+			// generation of the list of next Triangle 
+			// at 1 time we test all the triangles
+			Int4 Headt =0,next_t;
+			for(i=0;i<nbt;i++)
+				first_np_or_next_t[i]=-(i+1);
+			// end list i >= nbt 
+			// the list of test triangle is 
+			// the next traingle on i is  -first_np_or_next_t[i]
+			int iter=0;
+			// Big loop 
+			do {
+				iter++;
+				nbtold = nbt;
+				nbvold = nbv;
+#ifdef DRAWING1  
+				inquire();
+#endif  
+
+				// default size of  IntersectionTriangle
+
+				i=Headt;
+				next_t=-first_np_or_next_t[i];
+				for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]) 
+				{ // for each triangle  t
+					// we can change first_np_or_next_t[i]
+					//      cout << " Do the triangle " << i << " Next_t=" << next_t << endl;
+					assert(i>=0 && i < nbt );
+					first_np_or_next_t[i] = iter; 
+					for(j=0;j<3;j++)
+					{ // for each edge 
+						TriangleAdjacent tj(t,j);
+						Vertex & vA = * tj.EdgeVertex(0);
+						Vertex & vB = * tj.EdgeVertex(1);
+
+						if (!t->link) continue;// boundary
+						if (t->det <0) continue;
+						if (t->Locked(j)) continue;
+
+						TriangleAdjacent tadjj = t->Adj(j);	  
+						Triangle * ta= tadjj;
+
+						if (ta->det <0) continue;	  
+
+						R2 A = vA;
+						R2 B = vB;
+
+						k=Number(ta);
+
+						if(first_np_or_next_t[k]==iter)  // this edge is done before 
+							continue; // next edge of the triangle 
+
+						//const Int4 NbvOld = nbv;
+						lIntTria.SplitEdge(Bh,A,B);
+						lIntTria.NewPoints(vertices,nbv,nbvx);
+					} // end loop for each edge 
+
+				}// for triangle   
+
+#ifdef DRAWING1
+				cout << "  -------------------------------------------- " << endl;
+				inquire();
+				reffecran();
+				Draw();
+				penthickness(2);
+#endif
+
+				if (!InsertNewPoints(nbvold,NbTSwap)) 
+					break;
+
+				for (i=nbtold;i<nbt;i++)
+					first_np_or_next_t[i]=iter;
+
+				Headt = nbt; // empty list 
+				for (i=nbvold;i<nbv;i++) 
+				{ // for all the triangle contening the vertex i
+					Vertex * s  = vertices + i;
+					TriangleAdjacent ta(s->t, EdgesVertexTriangle[s->vint][1]);
+					Triangle * tbegin= (Triangle*) ta;
+					Int4 kt;
+					do { 
+						kt = Number((Triangle*) ta);
+						if (first_np_or_next_t[kt]>0) 
+							first_np_or_next_t[kt]=-Headt,Headt=kt;
+						assert( ta.EdgeVertex(0) == s);
+						ta = Next(Adj(ta));
+					} while ( (tbegin != (Triangle*) ta)); 
+				}   
+
+			} while (nbv!=nbvold);
+
+			delete []  first_np_or_next_t;
+
+			Int4 NbSwapf =0,NbSwp;
+
+			// bofbof 
+
+
+			NbSwp = NbSwapf;
+			for (i=0;i<nbv;i++)
+				NbSwapf += vertices[i].Optim(0);
+			/*
+			   for (i=0;i<nbv;i++)
+			   NbSwapf += vertices[i].Optim(0);
+			   for (i=0;i<nbv;i++)
+			   NbSwapf += vertices[i].Optim(0);
+			   for (i=0;i<nbv;i++)
+			   NbSwapf += vertices[i].Optim(0);
+			   for (i=0;i<nbv;i++)
+			   NbSwapf += vertices[i].Optim(0);
+			   */
+			NbTSwap +=  NbSwapf ;
+			if (verbosity>3) cout << "   " ;
+			if (verbosity>2) 
+				cout << " Nb Of Vertices =" << nbv << " Nb of triangles = " << nbt-NbOutT 
+					<< " NbSwap final = " << NbSwapf << " Nb Total Of Swap = " << NbTSwap << endl;
+
+
+		}
+
+		void  Triangles::NewPointsOld(Triangles & Bh)
+		{ // Triangles::NewPointsOld
+			long int verbosity=2;
+			Real8 seuil= 0.7 ;// for two neart point 
+			if (verbosity>1) 
+				cout << " begin :  Triangles::NewPointsOld " << endl;
+			Int4 i,k;
+			int j;
+			Int4 BeginNewPoint[3];
+			Int4 EndNewPoint[3];
+#ifdef TRACETRIANGLE
+			Int4 trace=0;
+#endif
+			int step[3];
+			Int4 *first_np_or_next_t = new Int4[nbtx];
+			Int4 ColorEdge[3];
+			Int4 color=-1;
+			Triangle *t;
+			// generation of the list of next Triangle 
+			// at 1 time we test all the triangles
+			Int4 Headt =0,next_t;
+			for(i=0;i<nbt;i++)
+				first_np_or_next_t[i]=-(i+1);
+			// end list i >= nbt 
+			// the list of test triangle is 
+			// the next Triangle on i is  -first_np_or_next_t[i]
+			Int4 nbtold,nbvold;
+
+			// Big loop 
+			do {
+				nbtold = nbt;
+				nbvold = nbv;
+#ifdef DRAWING1  
+				inquire();
+#endif  
+
+				// default size of  IntersectionTriangle
+
+				i=Headt;
+				next_t=-first_np_or_next_t[i];
+				for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]) 
+				{ // for each triangle  t
+					// we can change first_np_or_next_t[i]
+#ifdef TRACETRIANGLE
+					trace =  TRACETRIANGLE <0 ? 1 : i == TRACETRIANGLE;
+#endif
+					//      cout << " Do the triangle " << i << " Next_t=" << next_t << endl;
+					assert(i>=0 && i < nbt );
+					first_np_or_next_t[i] = nbv; // to save the fist new point of triangle
+					for(j=0;j<3;j++)
+					{ // for each edge 
+						TriangleAdjacent tj(t,j);
+						// color++;// the color is 3i+j
+						color = 3*i + j ;;
+						ColorEdge[j]=color;
+						BeginNewPoint[j]=nbv;
+						EndNewPoint[j]=nbv-1;
+						step[j]=1;// right sens 
+						Vertex & vA = * tj.EdgeVertex(0);
+						Vertex & vB = * tj.EdgeVertex(1);
+
+#ifdef TRACETRIANGLE
+						if(trace) {
+							cout << " i " << Number(vA) <<" j "<<  Number(vB) 
+								<< " "  << t->Locked(j) ;
+						}
+#endif
+						if (!t->link) continue;// boundary
+						if (t->det <0) continue;
+						if (t->Locked(j)) continue;
+
+						TriangleAdjacent tadjj = t->Adj(j);	  
+						Triangle * ta= tadjj;
+
+						if (ta->det <0) continue;	  
+
+						R2 A = vA;
+						R2 B = vB;
+
+						k=Number(ta);
+						// the 2 opposite vertices 
+						const Vertex & vC1  =  *tj.OppositeVertex();
+						const Vertex & vC2 = *tadjj.OppositeVertex();
+
+#ifdef TRACETRIANGLE
+						trace = trace || k == TRACETRIANGLE;
+						if(trace) {
+							cout << "Test Arete " << i << " AB = " << A << B 
+								<< "i "  <<Number(vA)<< "j" <<Number(vB); 
+							cout << " link" <<(int)t->link << " ta=" << Number( ta) 
+								<< " det " <<ta->det ;
+							cout << " hA = " <<vA.m.h << " hB = " <<vB.m.h ;
+							cout << " loc " << ta->Locked(j) << endl;
+						}
+#endif
+
+						if(first_np_or_next_t[k]>0) { // this edge is done before 
+							// find the color of the edge and begin , end of newpoint
+							register int kk = t->NuEdgeTriangleAdj(j);
+							assert ((*t)(VerticesOfTriangularEdge[j][0]) == (*ta)(VerticesOfTriangularEdge[kk][1]));
+							assert ((*t)(VerticesOfTriangularEdge[j][1]) == (*ta)(VerticesOfTriangularEdge[kk][0]));
+							register Int4 kolor =3*k + kk;
+							ColorEdge[j]=kolor;
+							register Int4 kkk= 1;
+							step[j]=-1;// other sens 
+							BeginNewPoint[j]=0;
+							EndNewPoint[j]=-1; // empty list          
+							for (Int4 iv=first_np_or_next_t[k];iv<nbv;iv++) 
+								if (vertices[iv].color > kolor) 
+									break; // the color is passed            
+								else if (vertices[iv].color == kolor) {
+									EndNewPoint[j]=iv; 
+									if (kkk) // one time test
+										kkk=0,BeginNewPoint[j]=iv;}
+									continue; // next edge of the triangle 
+						} // end  if( k < i) 
+
+
+#ifdef DRAWING1
+						penthickness(2); Move(A);Line(B);   penthickness(1);
+#endif
+						const Int4 NbvOld = nbv;
+						lIntTria.SplitEdge(Bh,A,B);
+						// Int4 NbvNp =
+						lIntTria.NewPoints(vertices,nbv,nbvx);
+						Int4 nbvNew=nbv;
+						nbv = NbvOld;
+						for (Int4 iv=NbvOld;iv<nbvNew;iv++) {
+							vertices[nbv].color = color;
+							vertices[nbv].ReferenceNumber=nbv;// circular link
+							R2 C =  vertices[iv].r;
+							vertices[nbv].r =  C;
+							vertices[nbv].m =  vertices[iv].m ;
+							// test if the new point is not to close to the 2 opposite vertex
+							R2 CC1 = C-vC1 , CC2 = C-vC2;
+							if (   (  (vC1.m(CC1) + vertices[nbv].m(CC1)) >  seuil)
+									&& (  (vC2.m(CC2) + vertices[nbv].m(CC2)) >  seuil) )
+								nbv++;
+						}
+
+						EndNewPoint[j] = nbv-1;
+					} // end loop for each edge 
+
+#ifdef TRACETRIANGLE
+					if(trace) {
+						// verification des point cree 
+						cout << "\n ------------ " << t->link << " " << t->det 
+							<< " b " << BeginNewPoint[0] << " " << BeginNewPoint[1]
+							<< " " << BeginNewPoint[2] << " " 
+							<< " e " << EndNewPoint[0] << " " << EndNewPoint[1] 
+							<< " " << EndNewPoint[2] << " " 
+							<< " s " << step[0] << " " << step[1] << " " << step[2] << " " 
+							<<  endl;
+					}
+#endif
+
+					if (!t->link) continue;// boundary
+					if (t->det<=0) continue;// outside 
+					//      continue;
+					for(int j0=0;j0<3;j0++)
+						for (Int4 i0= BeginNewPoint[j0]; i0 <= EndNewPoint[j0];i0++)
+						{
+							// find the neart  point one the opposite edge 
+							// to compute i1
+							Vertex & vi0 = vertices[i0];
+							int kstack = 0;
+							Int4 stack[10];
+							//   Int4 savRef[10];
+							int j1 = j0; 
+							while (j0 != (j1 = NextEdge[j1])) {//loop on the 2 other edge
+								// computation of the intersection of edge j1 and DOrto
+								// take the good sens 
+
+								if (BeginNewPoint[j1]> EndNewPoint[j1])
+									continue; // 
+								else if (EndNewPoint[j1] - BeginNewPoint[j1] <1) {
+									for (Int4 ii1= BeginNewPoint[j1];ii1<=EndNewPoint[j1];ii1++)
+										stack[kstack++] = ii1;
+									continue;}
+
+
+									int k0,k1;
+									if (step[j1]<0) k0=1,k1=0; // reverse
+									else k0=0,k1=1; 
+									R2 V10 = (R2)(*t)[VerticesOfTriangularEdge[j1][k0]];
+									R2 V11 = (R2)(*t)[VerticesOfTriangularEdge[j1][k1]];
+									R2 D = V11-V10;
+									Real8 c0 =  vi0.m(D,(R2) vi0);
+
+									Real8 c10 =  vi0.m(D,V10);
+									Real8 c11 =  vi0.m(D,V11);
+
+									Real8 s;
+									//cout << " --i0 = " << i0  << D  << V10 << V11 << endl ;
+									//cout << "   c10 " <<  c10 << " c0 " << c0 << " c11 " << c11 << endl;
+									if (( c10 < c0 ) && (c0 < c11)) 
+										s = (c11-c0)/(c11-c10);
+									else if  (( c11 < c0 ) && (c0 < c10)) 
+										s = (c11-c0) /(c11-c10);
+									else break;
+									R2 VP = V10*s + V11*(1-s);
+									int sss = (c11-c10) >0 ? 1 : -1;
+#ifdef DRAWING1
+									penthickness(2);
+									Move((R2) vi0);
+									Line(VP);
+									penthickness(1);
+#endif
+									// find the 2 point by dichotomie
+									//cout << "   t =" << Number(t) << " c0 " << c0  ;
+									Int4 ii0 =  BeginNewPoint[j1];
+									Int4 ii1 =  EndNewPoint[j1];	     
+									Real8 ciii=-1,cii0=-1,cii1=-1  ;
+									if ( sss * ((cii0=vi0.m(D,(R2) vertices[ii0]))- c0) >0 )  
+										stack[kstack++] = ii0;//cout << " add+0 " << ii0;
+									else if ( sss * ((cii1=  vi0.m(D ,(R2) vertices[ii1]))- c0) < 0 )  
+										stack[kstack++] = ii1;//cout << " add+1 " << ii1;
+									else {
+										while ((ii1-ii0)> 1) {
+											Int4 iii = (ii0+ii1)/2;
+											ciii = vi0.m( D ,(R2) vertices[iii]);
+											//cout << " (iii = " << iii << " " <<  ciii << ") ";
+											if ( sss * (ciii - c0) <0 )  ii0 = iii;
+											else ii1 = iii;}	        	      
+											stack[kstack++] = ii0;// cout << " add0 " << ii0;
+											if (ii1 != ii0)  stack[kstack++] = ii1;//cout << " add1 " << ii1;
+									}
+#ifdef DEBUG2
+									cout << "ii1 = " << ii1 
+										<< " ii0 = " << ii0 << endl;
+									cout << "   cccc = " << cii0 << " " << ciii 
+										<< " " << cii1 << " sss=" << sss << endl;
+#endif
+									if (kstack >5) // bug ?
+										cout << "NewPoints: bug????? " << kstack << " stack  " << stack[kstack]<< endl;
+							}
+
+							stack[kstack++] = -1; // to stop
+							Int4 i1;
+							kstack =0; 
+							while( (i1=stack[kstack++]) >= 0) 
+							{ // the two parameter is i0 and i1 
+								assert(i1 < nbv && i1 >= 0);
+								assert(i0 < nbv && i0 >= 0);
+								assert(i1 != i0);
+								R2 v01 = (R2) vertices[i1]- (R2) vertices[i0];
+								Real8 d01 = (vertices[i0].m(v01) + vertices[i1].m(v01));
+
+
+#ifdef DRAWING1
+								Move(vertices[i0].r);
+								Line(vertices[i1].r);
+#endif
+#ifdef TRACETRIANGLE
+								if(trace) {
+									cout << "\n test j" << j <<" "  << i0 
+										<< " " << i1 << " d01=" << d01 <<endl;}
+#endif
+								assert (i0 >= nbvold);
+								assert (i1 >= nbvold);
+								assert(i0 != i1);
+								if (d01 == 0) 
+									break; 
+								if ( d01 < seuil) 
+									if (i1<nbvold) {
+										// remove all the points i0;
+										register Int4 ip,ipp;
+										for  (ip=i0;i0 != (ipp = vertices[ip].ReferenceNumber);ip=ipp)
+											vertices[ip].ReferenceNumber = -1;// mark remove
+										vertices[ip].ReferenceNumber = -1;// mark remove
+									}
+									else {
+										// remove on of two points
+										register Int4 ip0, ip1, ipp0,ipp1;
+										register int kk0=1,kk1=1;
+										// count the number of common points to compute weight w0,w1
+										for  (ip0=i0;i0 != (ipp0 = vertices[ip0].ReferenceNumber);ip0=ipp0) kk0++;
+										for  (ip1=i1;i1 != (ipp1 = vertices[ip1].ReferenceNumber);ip1=ipp1) kk1++;
+
+										register Real8 w0 = ((Real8) kk0)/(kk0+kk1);
+										register Real8 w1 = ((Real8) kk1)/(kk0+kk1);
+
+										// make a circular link
+										Exchange(vertices[i0].ReferenceNumber,vertices[i1].ReferenceNumber);
+										// the new coordinate 
+										R2 C //= vertices[i0] ;
+										=  vertices[i0].r *w0 + vertices[i1].r* w1;
+
+#ifdef TRACETRIANGLE
+										if(trace) {
+											cout << "\n ref = "<< vertices[i0].ref << " " <<vertices[i1].ref <<endl;
+										}
+#endif    
+#ifdef DRAWING1  
+										Move(vertices[i0].r);
+										Line(vertices[i1].r);
+										DrawMark(C);
+#endif		
+										// update the new point points of the list 
+										for  (ip0=i0;i0 != (ipp0 = vertices[ip0].ReferenceNumber);ip0=ipp0)
+											vertices[ip0].r = C;	      
+										vertices[ip0].r = C;
+									}
+							}
+						} // for (i0= ....
+				}// for triangle   
+
+#ifdef DRAWING1
+				cout << " -------------------------------------------- " << endl;
+				inquire();
+				reffecran();
+				Draw();
+				penthickness(2);
+#endif
+
+				// remove of all the double points
+
+				Int4 ip,ipp,kkk=nbvold;
+				for (i=nbvold;i<nbv;i++) 
+					if (vertices[i].ReferenceNumber>=0) {// good points
+						//  cout <<" i = " << i ;
+						for  (ip=i;i != (ipp = vertices[ip].ReferenceNumber);ip=ipp)
+							vertices[ip].ReferenceNumber = -1;// mark remove
+						vertices[ip].ReferenceNumber = -1;// mark remove
+						// cout << i << " ---> " << kkk << endl;        
+						vertices[kkk] = vertices[i];
+						vertices[kkk].i = toI2(vertices[kkk].r);
+#ifdef DRAWING1
+						DrawMark(vertices[kkk]);
+#endif
+						vertices[kkk++].ReferenceNumber = 0;
+
+					} 
+#ifdef DRAWING1  
+				penthickness(1);
+#endif
+
+				// insertion part --- 
+
+				const Int4 nbvnew = kkk-nbvold;
+
+				cout << "    Remove " << nbv - kkk  << " to close  vertex " ;
+				cout << " and   Insert the " <<nbvnew<< " new points " << endl;  
+				nbv = kkk;
+				Int4 NbSwap=0;
+				Icoor2 dete[3];
+
+				// construction d'un ordre aleatoire 
+				if (! nbvnew) 
+					break; 
+				if (nbvnew) {
+					const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv)  ;
+					Int4 k3 = rand()%nbvnew ; 
+					for (Int4 is3=0; is3<nbvnew; is3++) 
+						ordre[nbvold+is3]= &vertices[nbvold +(k3 = (k3 + PrimeNumber)% nbvnew)];
+
+					for (i=nbvold;i<nbv;i++) 
+					{ Vertex * vi = ordre[i];
+						Triangle *tcvi = FindTriangleContening(vi->i,dete);
+						//     Vertex * nv =  quadtree->NearestVertex(vi->i.x,vi->i.y);
+						//      cout << " Neart Vertex of "  << Number(vi)<< vi->i << " is " 
+						//   << Number(nv) << nv->i  << endl;
+						// Int4  kt = Number(tcvi);
+						// 
+
+						quadtree->Add(*vi); //
+#ifdef DRAWING1
+						DrawMark(vi->r);
+#endif
+						assert (tcvi->det >= 0) ;// internal 
+						Add(*vi,tcvi,dete),NbSwap += vi->Optim(1);          
+					}  
+				}
+				cout << " Nb swap = " << NbSwap << " after " ;
+#ifdef DRAWING1
+				inquire();
+#endif
+
+				for (i=nbvold;i<nbv;i++) 
+					NbSwap += vertices[i].Optim(1);  
+				cout << NbSwap << endl;
+
+				for (i=nbtold;i<nbt;i++)
+					first_np_or_next_t[i]=1;
+
+				Headt = nbt; // empty list 
+				for (i=nbvold;i<nbv;i++) 
+				{ // for all the triangle contening the vertex i
+					Vertex * s  = vertices + i;
+					TriangleAdjacent ta(s->t, EdgesVertexTriangle[s->vint][1]);
+					Triangle * tbegin= (Triangle*) ta;
+					Int4 kt;
+					do { 
+						kt = Number((Triangle*) ta);
+						if (first_np_or_next_t[kt]>0) 
+							first_np_or_next_t[kt]=-Headt,Headt=kt;
+						assert( ta.EdgeVertex(0) == s);
+						ta = Next(Adj(ta));
+					} while ( (tbegin != (Triangle*) ta)); 
+				}
+
+
+			} while (nbv!=nbvold);
+			delete []  first_np_or_next_t;
+#ifdef  DEBUG
+			int nberr=0;
+			for (int it=0;it<nbt;it++)
+				if(triangles[it].det==0) 
+					if(nberr++<10) cerr << "Bug Triangle nul" << it << triangles[it] << endl;
+			if(nberr) MeshError(992,this);
+#endif
+			cout << " end :  Triangles::NewPoints old  nbv=" << nbv << endl;
+
+		}
+
+		void Triangles::Insert() 
+		{
+			long int verbosity=2;
+			if (verbosity>2) cout << "  -- Insert initial " << nbv << " vertices " << endl ;
+			Triangles * OldCurrentTh =CurrentTh;
+
+			CurrentTh=this;
+			double time0=CPUtime(),time1,time2,time3;
+			SetIntCoor();
+			Int4 i;
+			for (i=0;i<nbv;i++) 
+				ordre[i]= &vertices[i] ;
+
+			// construction d'un ordre aleatoire 
+			const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv) ;
+			Int4 k3 = rand()%nbv ; 
+			for (int is3=0; is3<nbv; is3++) 
+				ordre[is3]= &vertices[k3 = (k3 + PrimeNumber)% nbv];
+
+
+
+
+			for (i=2 ; det( ordre[0]->i, ordre[1]->i, ordre[i]->i ) == 0;) 
+				if  ( ++i >= nbv) {
+					cerr << " All the vertices are aline " << endl;
+					MeshError(998,this); }
+
+					// echange i et 2 dans ordre afin 
+					// que les 3 premiers ne soit pas aligne
+					Exchange( ordre[2], ordre[i]);
+
+					// on ajoute un point a l'infini pour construire le maillage
+					// afin d'avoir une definition simple des aretes frontieres
+					nbt = 2;
+
+
+					// on construit un maillage trivale forme
+					// d'une arete et de 2 triangles
+					// construit avec le 2 aretes orientes et 
+					Vertex *  v0=ordre[0], *v1=ordre[1];
+
+					triangles[0](0) = 0; // sommet pour infini 
+					triangles[0](1) = v0;
+					triangles[0](2) = v1;
+
+					triangles[1](0) = 0;// sommet pour infini 
+					triangles[1](2) = v0;
+					triangles[1](1) = v1;
+					const int e0 = OppositeEdge[0];
+					const int e1 = NextEdge[e0];
+					const int e2 = PreviousEdge[e0];
+					triangles[0].SetAdj2(e0, &triangles[1] ,e0);
+					triangles[0].SetAdj2(e1, &triangles[1] ,e2);
+					triangles[0].SetAdj2(e2, &triangles[1] ,e1);
+
+					triangles[0].det = -1;  // faux triangles
+					triangles[1].det = -1;  // faux triangles
+
+					triangles[0].SetTriangleContainingTheVertex();
+					triangles[1].SetTriangleContainingTheVertex();
+
+					triangles[0].link=&triangles[1];
+					triangles[1].link=&triangles[0];
+
+#ifdef DEBUG 
+					triangles[0].check();
+					triangles[1].check();
+#endif  
+					//  nbtf = 2;
+					if (  !quadtree )  quadtree = new QuadTree(this,0);
+					quadtree->Add(*v0);
+					quadtree->Add(*v1);
+
+					// on ajoute les sommets un Ò un 
+					Int4 NbSwap=0;
+
+					time1=CPUtime();
+
+					if (verbosity>3) cout << "  -- Begin of insertion process " << endl;
+
+					for (Int4 icount=2; icount<nbv; icount++) {
+						Vertex *vi  = ordre[icount];
+						//    cout << " Insert " << Number(vi) << endl;
+						Icoor2 dete[3];
+						Triangle *tcvi = FindTriangleContening(vi->i,dete);
+						quadtree->Add(*vi); 
+						Add(*vi,tcvi,dete);
+						NbSwap += vi->Optim(1,0);
+#ifdef DRAWING1
+						inquire();
+#endif
+
+					}// fin de boucle en icount
+					time2=CPUtime();
+					if (verbosity>3) 
+						cout << "    NbSwap of insertion " <<    NbSwap 
+							<< " NbSwap/Nbv " <<  (float) NbSwap / (float) nbv 
+							<< " NbUnSwap " << NbUnSwap << " Nb UnSwap/Nbv " 
+							<< (float)NbUnSwap /(float) nbv 
+							<<endl;
+					NbUnSwap = 0;
+					// construction d'un ordre aleatoire 
+					//  const int PrimeNumber= (nbv % 999983) ? 1000003: 999983 ;
+#ifdef NBLOOPOPTIM
+
+					k3 = rand()%nbv ; 
+					for (int is4=0; is4<nbv; is4++) 
+						ordre[is4]= &vertices[k3 = (k3 + PrimeNumber)% nbv];
+
+					double timeloop = time2 ;
+					for(int Nbloop=0;Nbloop<NBLOOPOPTIM;Nbloop++) 
+					{
+						double time000 = timeloop;
+						Int4  NbSwap = 0;
+						for (int is1=0; is1<nbv; is1++) 
+							NbSwap += ordre[is1]->Optim(0,0);
+						timeloop = CPUtime();
+						if (verbosity>3) 
+							cout << "    Optim Loop "<<Nbloop<<" NbSwap: " <<  NbSwap 
+								<< " NbSwap/Nbv " 	   <<  (float) NbSwap / (float) nbv 
+								<< " CPU=" << timeloop - time000 << "  s, " 
+								<< " NbUnSwap/Nbv " << (float)NbUnSwap /(float) nbv  
+								<<  endl;
+						NbUnSwap = 0;
+						if(!NbSwap) break;
+					}
+					ReMakeTriangleContainingTheVertex(); 
+					// because we break the TriangleContainingTheVertex
+#endif
+#ifdef  DEBUG
+					int nberr=0;
+					for (int it=0;it<nbt;it++)
+						if(triangles[it].det==0) 
+							if(nberr++<10) cerr << "Bug Triangle nul" << it << triangles[it] << endl;
+					if(nberr) MeshError(991,this);
+#endif
+					time3=CPUtime();
+					if (verbosity>4) 
+						cout << "    init " << time1 - time0 << " initialisation,  " 
+							<< time2 - time1 << "s, insert point  " 
+							<< time3 -time2 << "s, optim " << endl
+							<< "     Init Total Cpu Time = " << time3 - time0 << "s " << endl;
+
+#ifdef DRAWING1
+					inquire();
+#endif  
+					CurrentTh=OldCurrentTh;
+		}
+
+
+		void Triangles::ForceBoundary()
+		{
+			long int verbosity=2;
+			if (verbosity > 2)
+				cout << "  -- ForceBoundary  nb of edge " << nbe << endl;
+			int k=0;
+			Int4  nbfe=0,nbswp=0,Nbswap=0;
+			for (Int4 t = 0; t < nbt; t++)  
+				if (!triangles[t].det)
+					k++,cerr << " det T" << t << " = " << 0 << endl;
+			if (k!=0) {
+				cerr << " ther is  " << k << "  triangles of mes = 0 " << endl;
+				MeshError(11,this);}
+
+				TriangleAdjacent ta(0,0);
+				for (Int4 i = 0; i < nbe; i++) 
+				{
+					nbswp =  ForceEdge(edges[i][0],edges[i][1],ta);
+
+					if ( nbswp < 0) 	k++;
+					else Nbswap += nbswp;
+					if (nbswp) nbfe++;
+					if ( nbswp < 0 && k < 5)
+					{
+						cerr << " Missing  Edge " << i << " v0 =  " << Number(edges[i][0]) << edges[i][0].r
+							<<" v1= " << Number(edges[i][1]) << edges[i][1].r << " " << edges[i].on->Cracked() << "  " << (Triangle *) ta ;
+						if(ta.t)
+						{
+							Vertex *aa = ta.EdgeVertex(0), *bb = ta.EdgeVertex(1);  
+							cerr << " crossing with  [" << Number(aa) << ", " << Number(bb) << "]\n";
+						}
+						else cerr << endl;
+
+					}
+					if ( nbswp >=0 && edges[i].on->Cracked())
+						ta.SetCracked();
+				}
+
+
+				if (k!=0) {
+					cerr << " they is " << k << " lost edges " << endl;
+					cerr << " The boundary is crossing may be!" << endl;
+					MeshError(10,this);
+				}
+				for (Int4 j=0;j<nbv;j++)
+					Nbswap +=  vertices[j].Optim(1,0);
+				if (verbosity > 3)
+					cout << "     Nb of inforced edge = " << nbfe << " Nb of Swap " << Nbswap << endl;
+
+		}
+
+		void Triangles::FindSubDomain(int OutSide=0)
+		{
+			long int verbosity=2;
+			//#define DRAWING1
+
+			if (verbosity >2)
+			{
+				if (OutSide)
+					cout << "  -- Find all external sub-domain ";	
+				else
+					cout << "  -- Find all internal sub-domain ";
+				if(verbosity>99)
+				{
+
+					for(int i=0;i<nbt;++i)
+						cout << i<< " " << triangles[i] << endl;
+				}
+
+			}
+			// if (verbosity > 4) cout << " OutSide=" << OutSide << endl;
+			short * HeapArete = new short[nbt];
+			Triangle  **  HeapTriangle = new Triangle*  [nbt];
+			Triangle *t,*t1;
+			Int4 k,it;
+
+			for (Int4 itt=0;itt<nbt;itt++) 
+				triangles[itt].link=0; // par defaut pas de couleur
+#ifdef DRAWING1
+			reffecran();
+#endif
+
+			Int4  NbSubDomTot =0;
+			for ( it=0;it<nbt;it++)  { 
+				if ( ! triangles[it].link  ) {
+					t = triangles + it;
+					NbSubDomTot++;; // new composante connexe
+					Int4 i = 0; // niveau de la pile 
+					t->link = t ; // sd forme d'un triangle cicular link
+#ifdef DRAWING1
+					t->Draw(NbSubDomTot-1);
+#endif
+
+
+					HeapTriangle[i] =t ; 
+					HeapArete[i] = 3;
+
+					while (i >= 0) // boucle sur la pile
+					{ while ( HeapArete[i]--) // boucle sur les 3 aretes 
+						{ 
+							int na =  HeapArete[i];
+							Triangle * tc =  HeapTriangle[i]; // triangle courant
+							if( ! tc->Locked(na)) // arete non frontiere
+							{
+								Triangle * ta = tc->TriangleAdj(na) ; // næ triangle adjacent
+								if (ta->link == 0 ) // non deja chainer => on enpile
+								{ 
+									i++;
+#ifdef DRAWING1
+									ta->Draw(NbSubDomTot-1);
+#endif
+									ta->link = t->link ;  // on chaine les triangles
+									t->link = ta ;  // d'un meme sous domaine          
+									HeapArete[i] = 3; // pour les 3 triangles adjacents
+									HeapTriangle[i] = ta;
+								}}
+						} // deplie fin de boucle sur les 3 adjacences
+						i--;
+					}          
+				}      
+			}
+
+			// supression de tous les sous domaine infini <=>  contient le sommet NULL
+			it =0;
+			NbOutT = 0;
+			while (it<nbt) {
+				if (triangles[it].link) 
+				{ 
+					if (!( triangles[it](0) &&  triangles[it](1) &&  triangles[it](2) )) 
+					{
+						// infini triangle 
+						NbSubDomTot --;
+						//  cout << " triangle infini " << it << triangles[it] << endl;
+						t=&triangles[it];
+						NbOutT--;  // on fait un coup de trop. 
+						while  (t){ // cout << Number(t) << " " << endl;
+							NbOutT++;
+							t1=t;
+							t=t->link;
+							t1->link=0;}//while (t)
+					}
+				}   
+				it++;} // end while (it<nbt)
+				if (nbt == NbOutT ||  !NbSubDomTot) 
+				{
+					cout << "\n error : " <<  NbOutT << " " << NbSubDomTot <<" " << nbt << endl;
+					cerr << "Error: The boundary is not close => All triangles are outside " << endl;
+					MeshError(888,this);
+				}
+
+				delete [] HeapArete;
+				delete [] HeapTriangle;
+
+
+				if (OutSide|| !Gh.subdomains || !Gh.NbSubDomains ) 
+				{ // No geom sub domain
+					Int4 i;
+					if (subdomains) delete [] subdomains;
+					subdomains = new SubDomain[ NbSubDomTot];
+					NbSubDomains=  NbSubDomTot;
+					for ( i=0;i<NbSubDomains;i++) {
+						subdomains[i].head=NULL;
+						subdomains[i].ref=i+1;
+					}
+					Int4 * mark = new Int4[nbt];
+					for (it=0;it<nbt;it++)
+						mark[it]=triangles[it].link ? -1 : -2;
+
+					it =0;
+					k = 0;
+					while (it<nbt) {
+						if (mark[it] == -1) {
+							t1 = & triangles[it];
+							t = t1->link;
+							mark[it]=k;
+#ifdef DRAWING1  
+							t1->Draw(k);
+#endif
+							subdomains[k].head = t1;
+							// cout << " New -- " << Number(t1) << " " << it << endl;
+							do {// cout << " k " << k << " " << Number(t) << endl;
+								mark[Number(t)]=k;
+#ifdef DRAWING1  
+								t->Draw(k);
+#endif
+								t=t->link;
+							} while (t!=t1);
+#ifdef DRAWING1  
+							t1->Draw(k);
+#endif
+							mark[it]=k++;}
+							//    else if(mark[it] == -2 ) triangles[it].Draw(999);
+							it++;} // end white (it<nbt)
+							assert(k== NbSubDomains);
+							if(OutSide) 
+							{
+								//  to remove all the sub domain by parity adjacents
+								//  because in this case we have only the true boundary edge
+								// so teh boundary is manifold
+								Int4 nbk = NbSubDomains;
+								while (nbk)
+									for (it=0;it<nbt && nbk ;it++)
+										for (int na=0;na<3 && nbk ;na++)
+										{
+											Triangle *ta = triangles[it].TriangleAdj(na);
+											Int4 kl = ta ? mark[Number(ta)] : -2;
+											Int4 kr = mark[it];
+											if(kr !=kl) {
+												//cout << kl << " " << kr << " rl "  << subdomains[kl].ref
+												// << " rr " << subdomains[kr].ref ;
+												if (kl >=0 && subdomains[kl].ref <0 && kr >=0 && subdomains[kr].ref>=0)
+													nbk--,subdomains[kr].ref=subdomains[kl].ref-1;
+												if (kr >=0 && subdomains[kr].ref <0 && kl >=0 && subdomains[kl].ref>=0)
+													nbk--,subdomains[kl].ref=subdomains[kr].ref-1;
+												if(kr<0 && kl >=0 && subdomains[kl].ref>=0)
+													nbk--,subdomains[kl].ref=-1;
+												if(kl<0 && kr >=0 && subdomains[kr].ref>=0)
+													nbk--,subdomains[kr].ref=-1;
+												//   cout << " after \t "   
+												//	 << kl << subdomains[kl].ref << " rr " << kr 
+												// << subdomains[kr].ref << endl;
+											}
+										}
+								//  cout << subdomains[0].ref << subdomains[1].ref << endl;
+								Int4  j=0;
+								for ( i=0;i<NbSubDomains;i++)
+									if((-subdomains[i].ref) %2) { // good 
+										//cout << " sudom ok  = " << i << " " << subdomains[i].ref
+										// << " " << (-subdomains[i].ref) %2 << endl;
+										if(i != j) 
+											Exchange(subdomains[i],subdomains[j]);
+										j++;}
+									else
+									{ //cout << " remove sub domain " << i << endl;
+										t= subdomains[i].head;
+										while  (t){// cout << Number(t) << " " << endl;
+											NbOutT++;
+											t1=t;
+											t=t->link;
+											t1->link=0;}//while (t)
+									}
+
+								if(verbosity>4)
+									cout << " Number of remove sub domain (OutSideMesh) =" << NbSubDomains-j << endl;
+								NbSubDomains=j;
+							}
+
+							delete []  mark; 
+
+				}
+				else
+				{ // find the head for all sub domaine
+					if (Gh.NbSubDomains != NbSubDomains && subdomains)
+						delete [] subdomains, subdomains=0;
+					if (! subdomains  ) 
+						subdomains = new SubDomain[ Gh.NbSubDomains];
+					NbSubDomains =Gh.NbSubDomains;
+					if(verbosity>4)
+						cout << "     find the " << NbSubDomains << " sub domain " << endl;
+					Int4 err=0;
+					ReMakeTriangleContainingTheVertex();
+					Int4 * mark = new Int4[nbt];
+					Edge **GeometricalEdgetoEdge = MakeGeometricalEdgeToEdge();
+
+					for (it=0;it<nbt;it++)
+						mark[it]=triangles[it].link ? -1 : -2;
+					Int4 inew =0;
+					for (Int4 i=0;i<NbSubDomains;i++) 
+					{
+						GeometricalEdge &eg = *Gh.subdomains[i].edge;
+						subdomains[i].ref = Gh.subdomains[i].ref;
+						int ssdlab = subdomains[i].ref;
+						// by carefull is not easy to find a edge create from a GeometricalEdge 
+						// see routine MakeGeometricalEdgeToEdge
+						Edge &e = *GeometricalEdgetoEdge[Gh.Number(eg)];
+						assert(&e);
+						Vertex * v0 =  e(0),*v1 = e(1);
+						Triangle *t  = v0->t;
+						int sens = Gh.subdomains[i].sens;
+						// test if ge and e is in the same sens 
+						//	cout << " geom edge = " <<  Gh.Number(eg) <<" @" << &eg << " ref = " << subdomains[i].ref 
+						//     << " ref edge =" << eg.ref << " sens " << sens ;
+						if (((eg[0].r-eg[1].r),(e[0].r-e[1].r))<0)
+							sens = -sens ;
+						subdomains[i].sens = sens;
+						subdomains[i].edge = &e;
+						//	cout << " sens " << sens << " in geom " << eg[0].r << eg[1].r << " in mesh  " << e[0].r << e[1].r << endl;
+						//	cout << "  v0 , v1 = " << Number(v0) << " "  << Number(v1) << endl;
+						assert(t && sens);
+
+						TriangleAdjacent  ta(t,EdgesVertexTriangle[v0->vint][0]);// previous edges
+
+						while (1) 
+						{
+							assert( v0 == ta.EdgeVertex(1) );
+							//	 cout << " recherche " << Number( ta.EdgeVertex(0)) << endl;
+							if (ta.EdgeVertex(0) == v1) { // ok we find the edge
+								if (sens>0)  
+									subdomains[i].head=t=Adj(ta);
+								else 
+									subdomains[i].head=t=ta;
+								//cout << "      triangle  =" << Number(t) << " = " << (*t)[0].r <<  (*t)[1].r <<  (*t)[2].r << endl;
+								if(t<triangles || t >= triangles+nbt || t->det < 0 
+										|| t->link == 0) // Ajoute aout 200 
+								{
+									cerr << " Error in the def of sub domain "<<i
+										<< " form border " << NbSubDomains - i  << "/" << NbSubDomains
+										<< ": Bad sens  " << Gh.Number(eg) <<" "<< sens <<  endl;  
+									err++;
+									break;}
+									Int4 it = Number(t);
+									if (mark[it] >=0) {
+										if(verbosity>10)
+											cerr << "     Warning: the sub domain " << i << " ref = " << subdomains[i].ref 
+												<< " is previouly defined with "  <<mark[it] << " ref = " << subdomains[mark[it]].ref
+												<< " skip this def " << endl;
+										break;}
+										if(i != inew) 
+											Exchange(subdomains[i],subdomains[inew]);
+										inew++;
+										Triangle *tt=t;
+										Int4 kkk=0;
+										do 
+										{
+											kkk++;
+											assert(mark[Number(tt)]<0);
+#ifdef DRAWING1
+											tt->Draw(i);
+#endif
+											mark[Number(tt)]=i;
+											tt=tt->link;
+										} while (tt!=t);
+										if(verbosity>7)
+											cout << "     Nb de triangles dans le sous domaine " << i << " de ref " << subdomains[i].ref << " = " << kkk << endl;
+										break;}
+										ta = Previous(Adj(ta));         
+										if(t == (Triangle *) ta) {
+											err++;
+											cerr << " Error in the def of sub domain " << i 
+												<< " edge=" << Gh.Number(eg) << " " << sens << endl;
+											break;}
+											//         cout << " NB of remove subdomain " << NbSubDomTot-NbSubDomains<< endl;
+
+						}
+
+					}
+					if (err) MeshError(777,this);
+
+					if (inew < NbSubDomains) {
+						if (verbosity>5) 
+							cout << "     Warning: We remove " << NbSubDomains-inew << " SubDomains " << endl;
+						NbSubDomains=inew;}
+
+
+						for (it=0;it<nbt;it++)
+							if ( mark[it] ==-1 ) 
+								NbOutT++,triangles[it].link =0;
+						delete [] GeometricalEdgetoEdge;
+						delete [] mark;
+
+				}
+
+#ifdef DRAWING1
+				inquire();
+#endif
+				NbOutT=0;
+				for (it=0;it<nbt;it++) 
+					if(!triangles[it].link)  NbOutT++;
+				if (verbosity> 4)
+					cout << "    " ;
+				if (verbosity> 2)
+					cout << " Nb of Sub borned Domain  = " <<  NbSubDomTot << " NbOutTriangles = " << NbOutT <<endl;
+#ifdef DRAWING1
+				inquire();
+#endif
+
+				//#undef DRAWING1
+
+
+		}
+		void Triangles::ReNumberingVertex(Int4 * renu)
+		{
+			// warning be carfull because pointeur
+			// from on mesh to over mesh 
+			//  --  so do ReNumbering a the beginning
+			Vertex * ve = vertices+nbv;
+			Int4 it,ie,i;
+
+			for ( it=0;it<nbt;it++) 
+				triangles[it].ReNumbering(vertices,ve,renu);
+
+			for ( ie=0;ie<nbe;ie++) 
+				edges[ie].ReNumbering(vertices,ve,renu);
+
+			for (i=0;i< NbVerticesOnGeomVertex;i++)
+			{
+				Vertex *v = VerticesOnGeomVertex[i].mv;
+				if (v>=vertices && v < ve)
+					VerticesOnGeomVertex[i].mv=vertices+renu[Number(v)];
+			}
+
+			for (i=0;i< NbVerticesOnGeomEdge;i++)
+			{
+				Vertex *v =VerticesOnGeomEdge[i].mv;
+				if (v>=vertices && v < ve)
+					VerticesOnGeomEdge[i].mv=vertices+renu[Number(v)];
+			}
+
+			for (i=0;i< NbVertexOnBThVertex;i++)
+			{
+				Vertex *v=VertexOnBThVertex[i].v;
+				if (v>=vertices && v < ve)
+					VertexOnBThVertex[i].v=vertices+renu[Number(v)];
+			}
+
+			for (i=0;i< NbVertexOnBThEdge;i++)
+			{
+				Vertex *v=VertexOnBThEdge[i].v;
+				if (v>=vertices && v < ve)
+					VertexOnBThEdge[i].v=vertices+renu[Number(v)];
+			}
+
+			// move the Vertices without a copy of the array 
+			// be carefull not trivial code 
+			Int4 j;
+			for ( it=0;it<nbv;it++) // for all sub cycles of the permutation renu
+				if (renu[it] >= 0) // a new sub cycle
+				{ 
+					i=it;
+					Vertex ti=vertices[i],tj;
+					while ( (j=renu[i]) >= 0) 
+					{ // i is old, and j is new 
+						renu[i] = -1-renu[i]; // mark 
+						tj = vertices[j]; // save new
+						vertices[j]= ti; // new <- old
+						i=j;     // next 
+						ti = tj;
+					}  
+				}
+			if (quadtree) 
+			{  delete quadtree;
+				quadtree = new QuadTree(this);
+			}
+			for ( it=0;it<nbv;it++)
+				renu[i]= -renu[i]-1;
+
+		}
+		void Triangles::ReNumberingTheTriangleBySubDomain(bool justcompress)
+		{
+			long int verbosity=2;
+			Int4 *renu= new Int4[nbt];
+			register Triangle *t0,*t,*te=triangles+nbt;
+			register Int4 k=0,it,i,j;
+
+			for ( it=0;it<nbt;it++) 
+				renu[it]=-1; // outside triangle 
+			for ( i=0;i<NbSubDomains;i++)
+			{ 
+				t=t0=subdomains[i].head;
+				assert(t0); // no empty sub domain
+				do { 
+					Int4 kt = Number(t);
+					assert(kt>=0 && kt < nbt );
+					assert(renu[kt]==-1);
+					renu[kt]=k++;
+				}
+				while (t0 != (t=t->link));
+			}
+			if (verbosity>9)
+				cout << " number of inside triangles " << k << " nbt = " << nbt << endl;
+			// take is same numbering if possible    
+			if(justcompress)
+				for ( k=0,it=0;it<nbt;it++) 
+					if(renu[it] >=0 ) 
+						renu[it]=k++;
+
+			// put the outside triangles at the end
+			for ( it=0;it<nbt;it++) 
+				if (renu[it]==-1) 
+					renu[it]=k++;
+
+			assert(k == nbt);
+			// do the change on all the pointeur 
+			for ( it=0;it<nbt;it++)
+				triangles[it].ReNumbering(triangles,te,renu);
+
+			for ( i=0;i<NbSubDomains;i++)
+				subdomains[i].head=triangles+renu[Number(subdomains[i].head)];
+
+			// move the Triangles  without a copy of the array 
+			// be carefull not trivial code 
+			for ( it=0;it<nbt;it++) // for all sub cycles of the permutation renu
+				if (renu[it] >= 0) // a new sub cycle
+				{ 
+					i=it;
+					Triangle ti=triangles[i],tj;
+					while ( (j=renu[i]) >= 0) 
+					{ // i is old, and j is new 
+						renu[i] = -1; // mark 
+						tj = triangles[j]; // save new
+						triangles[j]= ti; // new <- old
+						i=j;     // next 
+						ti = tj;
+					}  
+				}
+			delete [] renu;
+			nt = nbt - NbOutT;
+
+#ifdef DEBUG
+			// verif 
+			for ( it=0;it<nbt;it++)
+				triangles[it].check();
+#endif   
+		}
+		Int4  Triangles::ConsRefTriangle(Int4 *reft) const
+		{
+			long int verbosity=0;
+			assert(reft);
+			register Triangle *t0,*t;
+			register Int4 k=0, num;   
+			for (Int4 it=0;it<nbt;it++) 
+				reft[it]=-1; // outside triangle 
+			for (Int4 i=0;i<NbSubDomains;i++)
+			{ 
+				t=t0=subdomains[i].head;
+				assert(t0); // no empty sub domain
+				// register Int4 color=i+1;// because the color 0 is outside triangle
+				do { k++;
+					num = Number(t);
+					assert(num>=0 &&num < nbt);
+					reft[num]=i;
+					//  cout << Number(t0) << " " <<Number(t)<< " "  << i << endl;
+				}
+				while (t0 != (t=t->link));
+			}
+			//  NbOutT = nbt - k;
+			if (verbosity>5) 
+				cout << " Nb of Sub Domain =" << NbSubDomains  << " Nb of In Triangles " << k 
+					<< " Nbt = " << nbt << " Out Triangles = " << nbt - k <<  endl;
+
+			return k;   
+
+		}
+
+		/*
+		   void Triangles::ConsLinkTriangle()
+		   {
+		   for (Int4 i=0;i<NbSubDomains;i++)
+		   subdomains[i].head=0;
+		   register Triangle * t=triangles,*tend = triangles+nbt,*hst;
+		   for (;t<tend;t++)
+		   {  
+		   if (t->link) 
+		   {
+		   register Int4 color = t->color-1;
+		   assert(color<NbSubDomains && color>=0);
+		   if (hst=subdomains[color].head) {
+		   t->link=hst->link;
+		   hst->link=t; }
+		   else {
+		   subdomains[color].head = t;
+		   t->link=t;}// circular link         
+		   }
+		   }
+		   {
+		   for (Int4 i=0;i<NbSubDomains;i++)
+		   assert(subdomains[i].head);
+		   }
+
+		   }
+		   */
+		/* void Triangles::RandomInit() 
+		   { 
+		//  Meshbegin = vertices;
+		//  Meshend  = vertices + nbvx;
+		nbv = nbvx;
+		for (int i = 0; i < nbv; i++)
+		{
+		vertices[i].r.x= rand();
+		vertices[i].r.y= rand();
+		vertices[i].ref = 0;
+		}
+		}
+		void Triangles::CubeInit(int n,int m) 
+		{ 
+		//  nbvx = n*m;
+		//  Meshbegin = vertices;
+		// Meshend  = vertices + nbvx;
+		nbv = n*m;
+		assert(nbv <= nbvx);
+		int k =0;
+		for (int i = 0; i < n; i++)
+		for (int j = 0; j < m; j++)
+		{
+		vertices[k].r.x= i;
+		vertices[k].r.y= j;
+		vertices[k++].ref = 0;
+		}
+		}
+		*/
+		Vertex * Triangles::NearestVertex(Icoor1 i,Icoor1 j) 
+		{ return  quadtree->NearestVertex(i,j); } 
+
+
+		void Triangles::PreInit(Int4 inbvx,char *fname)
+		{
+			long int verbosity=0;
+
+			srand(19999999);
+			OnDisk =0;
+			NbRef=0;
+			//  allocGeometry=0;
+			identity=0;
+			NbOfTriangleSearchFind =0;
+			NbOfSwapTriangle =0;
+			nbiv=0;
+			nbv=0;
+			nbvx=inbvx;
+			nbt=0;
+			NbOfQuad = 0;
+			nbtx=2*inbvx-2;
+			NbSubDomains=0;
+			NbVertexOnBThVertex=0;
+			NbVertexOnBThEdge=0;
+			VertexOnBThVertex=0;
+			VertexOnBThEdge=0;
+
+			NbCrackedVertices=0;
+			NbCrackedEdges =0;
+			CrackedEdges  =0;  
+			nbe = 0; 
+			name = fname ;
+
+			if (inbvx) {
+				vertices=new Vertex[nbvx];
+				assert(vertices);
+				ordre=new (Vertex* [nbvx]);
+				assert(ordre);
+				triangles=new Triangle[nbtx];
+				assert(triangles);}
+			else {
+				vertices=0;
+				ordre=0;
+				triangles=0;
+				nbtx=0;
+			}
+			if ( name || inbvx)
+			{
+				time_t timer =time(0);
+				char buf[70];     
+				strftime(buf ,70,", Date: %y/%m/%d %H:%M %Ss",localtime(&timer));
+				counter++; 
+				char countbuf[30];   
+				sprintf(countbuf,"%d",counter);
+				int lg =0 ;
+				if (&BTh != this && BTh.name)
+					lg = strlen(BTh.name)+4;
+				identity = new char[ lg + strlen(buf) + strlen(countbuf)+ 2  + 10 + ( Gh.name ? strlen(Gh.name) + 4 : 0)];
+				identity[0]=0;
+				if (lg)
+					strcat(strcat(strcat(identity,"B="),BTh.name),", ");
+
+				if (Gh.name)
+					strcat(strcat(identity,"G="),Gh.name);
+				strcat(strcat(identity,";"),countbuf);
+				strcat(identity,buf);
+				// cout << "New MAILLAGE "<< identity << endl;
+			} 
+
+			quadtree=0;
+			//  edgescomponante=0;
+			edges=0;
+			VerticesOnGeomVertex=0;
+			VerticesOnGeomEdge=0;
+			NbVerticesOnGeomVertex=0;
+			NbVerticesOnGeomEdge=0;
+			//  nbMaxIntersectionTriangles=0;
+			//  lIntTria;
+			subdomains=0;
+			NbSubDomains=0;
+			//  Meshbegin = vertices;
+			//  Meshend  = vertices + nbvx;
+			if (verbosity>98) 
+				cout << "Triangles::PreInit() " << nbvx << " " << nbtx 
+					<< " " << vertices 
+					<< " " << ordre << " " <<  triangles <<endl;
+
+		}
+
+		void Triangles::GeomToTriangles1(Int4 inbvx,int KeepBackVertices) 
+		{ 
+			//#define DRAWING1
+			Gh.NbRef++;// add a ref to Gh
+
+
+			/************************************************************************* 
+			// methode in 2 step
+			// 1 - compute the number of new edge to allocate
+			// 2 - construct the edge
+remark: 
+in this part we suppose to have a background mesh with the same
+geometry 
+
+To construct the discretisation of the new mesh we have to 
+rediscretize the boundary of background Mesh 
+because we have only the pointeur from the background mesh to the geometry.
+We need the abcisse of the background mesh vertices on geometry
+so a vertex is 
+0 on GeometricalVertex ;
+1 on GeometricalEdge + abcisse
+2 internal 
+
+			 *************************************************************************/
+			assert(&BTh.Gh == &Gh);
+
+			long int verbosity=2;
+			// if(verbosity==100) Gh.Write("/tmp/gg.gmsh");
+			BTh.NbRef++; // add a ref to BackGround Mesh
+			PreInit(inbvx);
+			BTh.SetVertexFieldOn();
+#ifdef DRAWING
+			if (withrgraphique)
+			{ BTh.InitDraw();
+				reffecran(); 
+				CurrentTh = this;}
+#endif
+				int * bcurve = new int[Gh.NbOfCurves]; // 
+
+				// we have 2 ways to make the loop 
+				// 1) on the geometry 
+				// 2) on the background mesh
+				//  if you do the loop on geometry, we don't have the pointeur on background,
+				//  and if you do the loop in background we have the pointeur on geometry
+				// so do the walk on  background
+				//  Int4 NbVerticesOnGeomVertex;
+				//  VertexOnGeom * VerticesOnGeomVertex;  
+				//  Int4 NbVerticesOnGeomEdge;
+				//  VertexOnGeom * VerticesOnGeomEdge;
+
+
+				NbVerticesOnGeomVertex=0;
+				NbVerticesOnGeomEdge=0;
+				//1 copy of the  Required vertex
+				int i; 
+				for ( i=0;i<Gh.nbv;i++)
+					if (Gh[i].Required()) NbVerticesOnGeomVertex++;
+
+				VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+				VertexOnBThVertex = new VertexOnVertex[NbVerticesOnGeomVertex];
+				//
+				if( NbVerticesOnGeomVertex >= nbvx) 
+				{
+					cerr << " Too much vertices on geometry " << NbVerticesOnGeomVertex << " >= " << nbvx << endl; 
+					MeshError(1,this);
+				}
+				assert(vertices);
+				for (i=0;i<Gh.nbv;i++)
+					if (Gh[i].Required()) {//Gh  vertices Required
+						vertices[nbv] =  Gh[i];
+						vertices[nbv].i = I2(0,0);
+						Gh[i].to = vertices + nbv;// save Geom -> Th
+						VerticesOnGeomVertex[nbv]= VertexOnGeom(vertices[nbv],Gh[i]);
+						// cout << "--------- "  <<Number(Gh[i].to) << " " << Gh[i].to << " " << i << endl;
+						nbv++;}
+					else Gh[i].to=0;
+				// 
+				for (i=0;i<BTh.NbVerticesOnGeomVertex;i++)
+				{ 
+					VertexOnGeom & vog = BTh.VerticesOnGeomVertex[i];
+					if (vog.IsRequiredVertex()) {
+						GeometricalVertex * gv = vog;
+						Vertex *bv = vog;
+						assert(gv->to);// use of Geom -> Th
+						VertexOnBThVertex[NbVertexOnBThVertex++] = VertexOnVertex(gv->to,bv);
+						gv->to->m = bv->m; // for taking the metrix of the background mesh
+						;}
+				}
+				assert(NbVertexOnBThVertex == NbVerticesOnGeomVertex);
+				// new stuff FH with curve
+				//  find the begin of the curve in BTh
+				{
+					Gh.UnMarkEdges();	
+					int bfind=0;
+					/*
+					   cout << " nb curves = " << Gh.NbOfCurves << endl;
+					   for(int i=0;i<Gh.NbOfCurves ;i++)
+					   {
+					   cout << " Curve " << i << " begin e=" << Gh.Number(Gh.curves[i].be) << " k=" << Gh.curves[i].kb 
+					   << "  end e= " << Gh.Number(Gh.curves[i].ee) << " k=" << Gh.curves[i].ke << endl;
+					   }*/
+					for (int i=0;i<Gh.NbOfCurves;i++)
+					{
+						bcurve[i]=-1; 
+					}
+
+					for (int iedge=0;iedge<BTh.nbe;iedge++) 
+					{      
+						Edge & ei = BTh.edges[iedge];
+						for(int je=0;je<2;je++) // for the 2 extremites
+							if (!ei.on->Mark() && ei[je].on->IsRequiredVertex() )
+							{
+								// a begin of curve 
+								int nc = ei.on->CurveNumber;
+
+								//cout << "curve " <<  nc << " v " << Gh.Number((GeometricalVertex *) *ei[je].on) << " "
+								//     << " e "  << " " << Gh.Number(ei.on) << " vc " << Gh.Number((*Gh.curves[nc].be)[Gh.curves[nc].kb]) << endl;
+								if(
+										ei.on==Gh.curves[nc].be    && 
+										(GeometricalVertex *) *ei[je].on == &(*Gh.curves[nc].be)[Gh.curves[nc].kb] //  same extremity 
+								  )     
+								{ 
+									// cout << " find " << endl;
+									bcurve[nc]=iedge*2+je;
+									bfind++;	
+								}      
+							}
+					} 
+					assert( bfind==Gh.NbOfCurves);
+				}          
+				// method in 2 + 1 step 
+				//  0.0) compute the length and the number of vertex to do allocation
+				//  1.0)  recompute the length
+				//  1.1)   compute the  vertex 
+				Int4 nbex=0,NbVerticesOnGeomEdgex=0;
+				for (int step=0; step <2;step++)
+				{
+					Int4 NbOfNewPoints=0;
+					Int4 NbOfNewEdge=0;
+					Int4 iedge;
+					Gh.UnMarkEdges();	
+					/*   add Curve loop  FH    
+					// find a starting back groud edges to walk 
+					for (iedge=0;iedge<BTh.nbe;iedge++) {      
+					Edge & ei = BTh.edges[iedge];
+					for(int jedge=0;jedge<2;jedge++) // for the 2 extremites
+					if (!ei.on->Mark() && ei[jedge].on->IsRequiredVertex() )
+					{
+					*/  
+					// new code FH 2004 
+					Real8 L=0;
+					for (int icurve=0;icurve<Gh.NbOfCurves;icurve++)
+					{ 
+						iedge=bcurve[icurve]/2;
+						int jedge=bcurve[icurve]%2;
+						if( ! Gh.curves[icurve].master) continue; // we skip all equi curve
+						Edge & ei = BTh.edges[iedge];
+						// warning: ei.on->Mark() can be change in
+						// loop for(jedge=0;jedge<2;jedge++) 
+						// new curve  
+						// good the find a starting edge 
+						Real8 Lstep=0,Lcurve=0;// step between two points   (phase==1) 
+						Int4 NbCreatePointOnCurve=0;// Nb of new points on curve     (phase==1) 
+
+
+						//    cout.precision(16);
+						for(int phase=0;phase<=step;phase++) 
+						{
+
+							for(Curve * curve= Gh.curves+icurve;curve;curve= curve->next)
+							{
+
+								int icurveequi= Gh.Number(curve);
+
+								if( phase == 0 &&  icurveequi != icurve)  continue;
+
+								int k0=jedge,k1;
+								Edge * pe=  BTh.edges+iedge;
+								//GeometricalEdge *ong = ei.on;
+								int iedgeequi=bcurve[icurveequi]/2;
+								int jedgeequi=bcurve[icurveequi]%2;
+
+								int k0equi=jedgeequi,k1equi;		  
+								Edge * peequi= BTh.edges+iedgeequi;
+								GeometricalEdge *ongequi = peequi->on;
+
+								Real8 sNew=Lstep;// abcisse of the new points (phase==1) 
+								L=0;// length of the curve
+								Int4 i=0;// index of new points on the curve
+								register GeometricalVertex * GA0 = *(*peequi)[k0equi].on;
+								Vertex *A0;
+								A0 = GA0->to;  // the vertex in new mesh
+								Vertex *A1;
+								VertexOnGeom *GA1;
+								Edge * PreviousNewEdge = 0;
+								//  cout << "  --------------New Curve phase " << phase 
+								//       << "---------- A0=" << *A0 << ei[k0]  <<endl;
+								assert (A0-vertices>=0 && A0-vertices <nbv);
+								if(ongequi->Required() ) 
+								{
+									GeometricalVertex *GA1 = *(*peequi)[1-k0equi].on;
+									A1 = GA1->to;  //
+								}       
+								else 
+									for(;;) 
+									{
+										//   assert(pe && BTh.Number(pe)>=0 && BTh.Number(pe)<=BTh.nbe);
+										Edge &ee=*pe; 
+										Edge &eeequi=*peequi; 
+										k1 = 1-k0; // next vertex of the edge 
+										k1equi= 1 - k0equi;
+
+										assert(pe  && ee.on);
+										ee.on->SetMark();
+										Vertex & v0=ee[0], & v1=ee[1];
+										R2 AB= (R2) v1 - (R2) v0;
+										Real8 L0=L,LAB;
+										LAB =  LengthInterpole(v0.m,v1.m,AB);
+										L+= LAB;    
+										if (phase) {// computation of the new points
+											while ((i!=NbCreatePointOnCurve) && sNew <= L) { 
+												//    cout  << " L0= " << L0 << " L " << L << " sN=" 
+												//         << sNew << " LAB=" << LAB << " NBPC =" <<NbCreatePointOnCurve<< " i " << i  << endl;
+												assert (sNew >= L0);
+												assert(LAB);
+
+
+												assert(vertices && nbv<nbvx);
+												assert(edges && nbe < nbex);
+												assert(VerticesOnGeomEdge && NbVerticesOnGeomEdge < NbVerticesOnGeomEdgex);
+												// new vertex on edge
+												A1=vertices+nbv++;
+												GA1=VerticesOnGeomEdge+NbVerticesOnGeomEdge;
+												Edge *e = edges + nbe++;
+												Real8 se= (sNew-L0)/LAB;
+												assert(se>=0 && se < 1.000000001);
+#ifdef DEBUG
+												se =  abscisseInterpole(v0.m,v1.m,AB,se); // because code \ref(xxx)
+#else
+												se =  abscisseInterpole(v0.m,v1.m,AB,se,1);
+#endif
+												assert(se>=0 && se <= 1);
+												//((k1==1) != (k1==k1equi))
+												se = k1 ? se : 1. - se;
+												se = k1==k1equi ? se : 1. - se;
+												VertexOnBThEdge[NbVerticesOnGeomEdge++] = VertexOnEdge(A1,&eeequi,se); // save 
+												ongequi = Gh.ProjectOnCurve(eeequi,se,*A1,*GA1); 
+												A1->ReferenceNumber = eeequi.ref;
+												A1->DirOfSearch =NoDirOfSearch;
+												//cout << icurveequi << " " << i << " " <<  *A1 << endl;
+												e->on = ongequi;
+												e->v[0]=  A0;
+												e->v[1]=  A1;
+												if(verbosity>99)
+													cout << i << "+ New P "<< nbv-1 << " "  <<sNew<< " L0=" << L0 
+														<< " AB=" << LAB << " s=" << (sNew-L0)/LAB << " se= "  
+														<< se <<" B edge " << BTh.Number(ee) << " signe = " << k1 <<" " << A1->r <<endl;
+
+#ifdef DEBUG
+												// code \label(xxx)
+												R2  A1A0 = A1->r - A0->r;
+												Real8 dp = LengthInterpole(A0->m,A1->m,A1A0);
+												if (dp > 1.4) {
+													cerr << " PB new Points "<< nbv-1 ;
+													cerr << " AB=" << LAB << " s=" << (sNew-L0)/LAB << " se= "  ;
+													cerr << se <<" B edge " << BTh.Number(ee) << " signe = " << k1 <<endl;	      
+													cerr << " PB calcul new on cuver points trop loin l=" << dp 
+														<< " v=" << nbv-1 << " " << nbv-2 << " Lcurve = " << Lcurve << AB <<v0.m<< v1.m <<endl;
+												}
+
+#endif
+												e->ref = eeequi.ref;
+												e->adj[0]=PreviousNewEdge;
+
+												if (PreviousNewEdge)
+													PreviousNewEdge->adj[1] =  e;
+												PreviousNewEdge = e;
+#ifdef DRAWING1
+												e->Draw();
+												//         A0->Draw();
+												A1->m.Draw(*A1);
+												A1->Draw(Number(A1));
+#endif
+												A0=A1;
+												sNew += Lstep;
+												//   cout << " sNew = " << sNew << " L = " << L 
+												//        << "  ------" <<NbCreatePointOnCurve << " " << i <<  endl;
+												if (++i== NbCreatePointOnCurve) break;
+											}
+
+										}               
+										assert(ee.on->CurveNumber==ei.on->CurveNumber);
+										if(verbosity>98) cout <<  BTh.Number(ee) << " " << " on=" << *ee[k1].on << " "<< ee[k1].on->IsRequiredVertex() <<  endl;
+										if ( ee[k1].on->IsRequiredVertex()) {
+											assert(eeequi[k1equi].on->IsRequiredVertex());
+											register GeometricalVertex * GA1 = *eeequi[k1equi].on;
+											A1=GA1->to;// the vertex in new mesh
+											assert (A1-vertices>=0 && A1-vertices <nbv);
+											break;}
+											if (!ee.adj[k1])
+											{cerr << "Error adj edge " << BTh.Number(ee) << ", nbe = "  << nbe 
+												<< " Gh.vertices " << Gh.vertices 
+													<< " k1 = " << k1 << " on=" << *ee[k1].on << endl;
+												cerr << ee[k1].on->gv-Gh.vertices << endl;
+											}
+											pe = ee.adj[k1]; // next edge
+											k0 = pe->Intersection(ee); 
+											peequi= eeequi.adj[k1equi];  // next edge
+											k0equi=peequi->Intersection(eeequi);            
+									}// for(;;) end of the curve
+
+
+								if (phase) // construction of the last edge
+								{
+									Edge *e = edges + nbe++;
+									if (verbosity>10) 
+										cout << " Fin curve A1" << *A1 << " " << icurve << " <=> " << icurveequi <<"-----" <<
+											NbCreatePointOnCurve << " == " <<i<<endl;
+									e->on  = ongequi;
+									e->v[0]=  A0;
+									e->v[1]=	A1;
+									e->ref = peequi->ref;
+									e->adj[0]=PreviousNewEdge;
+									e->adj[1]=0;
+									if (PreviousNewEdge)
+										PreviousNewEdge->adj[1] =  e;
+									PreviousNewEdge = e;
+									//		      cout << "Last new edge " << nbe << " " << " on " << Gh.Number(pe->on) 
+									//   << " of curve =" <<pe->on->CurveNumber <<endl;
+
+
+#ifdef DRAWING1 
+									e->Draw();
+									A1->Draw();
+									A0->Draw();
+									//                      inquire();
+#endif
+									assert(i==NbCreatePointOnCurve);
+
+								}
+							} //  end loop on equi curve 
+
+							if (!phase)  { // 
+								Int4 NbSegOnCurve = Max((Int4)(L+0.5),(Int4) 1);// nb of seg
+								Lstep = L/NbSegOnCurve; 
+								Lcurve = L;
+								NbCreatePointOnCurve = NbSegOnCurve-1;
+
+								for(Curve * curve= Gh.curves+icurve;curve;curve= curve->next)
+								{
+									NbOfNewEdge += NbSegOnCurve;
+									NbOfNewPoints += NbCreatePointOnCurve;
+								}
+								if(verbosity>5)
+									cout << icurve << " NbSegOnCurve = " <<  NbSegOnCurve << " Lstep=" 
+										<< Lstep <<" " << NbOfNewPoints<< " NBPC= " << NbCreatePointOnCurve <<endl;
+								// do'nt 
+								//  if(NbCreatePointOnCurve<1) break;
+							}
+						}//for(phase;;)
+						/*  modif FH add Curve class  		  
+							}}//for (iedge=0;iedge<BTh.nbe;iedge++) 
+							*/
+						// new code Curve class  	
+				} //  end of curve loop 
+				// end new code	    
+				// do the allocation
+				if(step==0) 
+				{
+					//if(!NbOfNewPoints) break;// nothing ????? bug 
+					if(nbv+NbOfNewPoints > nbvx) 
+					{
+						cerr << " Too much vertices on geometry " << nbv+NbOfNewPoints  << " >= " << nbvx << endl;
+						MeshError(3,this);
+					}
+					//cout << " NbOfNewEdge" << NbOfNewEdge << " NbOfNewPoints " << NbOfNewPoints << endl;
+					edges = new Edge[NbOfNewEdge];
+					nbex = NbOfNewEdge;
+					if(NbOfNewPoints) { // 
+						VerticesOnGeomEdge = new VertexOnGeom[NbOfNewPoints];
+						NbVertexOnBThEdge =NbOfNewPoints;
+						VertexOnBThEdge = new  VertexOnEdge[NbOfNewPoints];
+						NbVerticesOnGeomEdgex = NbOfNewPoints; }
+						NbOfNewPoints =0;
+						NbOfNewEdge = 0;
+				}
+				} // for(step;;)
+				assert(nbe);
+
+				delete [] bcurve;
+
+
+#ifdef DRAWING1
+				reffecran();
+				InitDraw();
+				Draw();
+				inquire();
+#endif
+
+				Insert();
+				ForceBoundary();
+				FindSubDomain();
+
+#ifdef DRAWING1
+				reffecran();
+				Draw();
+				inquire();
+#endif
+				// NewPointsOld(*this) ;
+				//  BTh.ReMakeTriangleContainingTheVertex(); //  FH change => put in NewPoints
+				//  for (Int4 iv=0;iv<BTh.nbv;iv++)
+				//    BTh[iv].i = toI2(BTh[iv].r);
+				NewPoints(BTh,KeepBackVertices) ;
+				CurrentTh = 0;
+				//#undef  DRAWING1 
+		}
+
+		void Triangles::GeomToTriangles0(Int4 inbvx) 
+		{
+			Gh.NbRef++;// add a ref to GH
+
+
+			Int4 i,NbOfCurves=0,NbNewPoints,NbEdgeCurve;
+			Real8 lcurve, lstep,s;
+#ifdef DRAWING
+			if (withrgraphique)
+			{
+				Gh.InitDraw() ;
+				CurrentTh = this; }
+#endif
+
+				R2 AB;
+				GeometricalVertex *a,*b;
+				Vertex *va,*vb;
+				GeometricalEdge * e;
+				PreInit(inbvx);
+				int  background = &BTh != this;
+				//  int  SameGeom = background && (&BTh.Gh == &Gh);
+				nbv = 0;
+				NbVerticesOnGeomVertex=0;
+				NbVerticesOnGeomEdge=0;
+				for (i=0;i<Gh.nbv;i++)
+					if (Gh[i].Required() && Gh[i].IsThe() ) NbVerticesOnGeomVertex++;
+				VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];  
+				//
+				if( NbVerticesOnGeomVertex >= nbvx) 
+				{
+					cerr << " Too much vertices on geometry " << NbVerticesOnGeomVertex << " >= " << nbvx << endl;
+					MeshError(1,this);
+				}
+				for (i=0;i<Gh.nbv;i++)
+					if (Gh[i].Required()&& Gh[i].IsThe()  ) {//Gh  vertices Required
+						if (nbv < nbvx)
+							vertices[nbv] = Gh[i];
+						Gh[i].to = vertices + nbv;// save Geom -> Th
+						VerticesOnGeomVertex[nbv]= VertexOnGeom(*Gh[i].to,Gh[i]);
+						//  cout << "--------- "  <<Number(Gh[i].to) << " " << Gh[i].to << " " << i << endl;
+						nbv++;
+					}
+				//  assert( Gh.nbv < nbvx);
+
+				// Method in 2 step:  0 and 1 
+				// 1) compute de nb of edge 
+				// 2) construct the edge    
+				// generation of the curves
+				assert(! edges);
+#ifdef DRAWING1
+				reffecran();
+#endif
+				// 2 step 
+				// --step=0 to compute the number of edges + alloc at end
+				// --step=1 to construct the edges
+				for (int step=0;step<2;step++) 
+				{//  for (int step=0;step<2;step++) 
+					Int4 nbex = 0;
+					nbe = 0;
+					Int4 NbVerticesOnGeomEdge0=NbVerticesOnGeomEdge;
+					//  cout <<  "  -------------- step =" << step << endl;
+					Gh.UnMarkEdges();	
+					NbOfCurves = 0;
+					for (i=0;i<Gh.nbe;i++) {
+						GeometricalEdge & ei = Gh.edges[i];   
+						if (!ei.Dup()) // a good curve (not dup )
+							for(int j=0;j<2;j++) 
+								if (!ei.Mark() && ei[j].Required()) { 
+									// warning ei.Mark() can be change in loop for(j=0;j<2;j++) 
+									//  cout << " New curve = " << NbOfCurves << endl;
+									Int4 nbvend  =0;
+
+									Edge * PreviousNewEdge=0;
+
+									lstep = -1;//to do not create points
+									if(ei.Required())
+									{
+										if (j==0)
+											if(step==0)
+												nbe++;
+											else
+											{ 
+												e = & ei;
+												a=ei(0)->The();
+												b=ei(1)->The();
+												assert(edges);
+												edges[nbe].v[0]=a->to;
+												edges[nbe].v[1]=b->to;;
+												edges[nbe].ref = e->ref;
+												edges[nbe].on = e;
+												edges[nbe].adj[0] = 0;
+												edges[nbe].adj[1] = 0;
+#ifdef DRAWING1
+												edges[nbe].Draw();
+#endif
+												nbe++;}
+									}
+									else 
+									{ // on curve ------
+										for ( int kstep=0;kstep<= step;kstep++)
+										{ // begin  for ( int kstep=0;kstep<= step;kstep++)
+											// if 2nd step where 2 step
+											// -- 1 compute le length of the curve
+											// -- create the points and edge
+											PreviousNewEdge=0;
+											NbNewPoints=0;
+											NbEdgeCurve=0;
+											assert(nbvend < nbvx); 
+											lcurve =0;
+											s = lstep;
+											int k=j;
+											e = & ei;
+											a=ei(k)->The();
+											va = a->to;
+											e->SetMark();
+											//  cout << " New curve " ;
+
+											// if SameGeo  We have go in the background geometry 
+											// to find the discretisation of the curve
+
+											for(;;) 
+											{ 
+												k = 1-k;
+												b= (*e)(k)->The();
+												AB = b->r - a->r;
+												Metric MA = background ? BTh.MetricAt(a->r) :a->m ;
+												Metric MB =  background ? BTh.MetricAt(b->r) :b->m ;
+												Real8 ledge = (MA(AB) + MB(AB))/2;
+												// 
+												const int MaxSubEdge = 10;
+												int NbSubEdge = 1;
+												Real8 lSubEdge[MaxSubEdge];
+												R2 A,B;
+												if (ledge < 1.5) 
+													lSubEdge[0] = ledge;
+												else {
+													NbSubEdge = Min( MaxSubEdge, (int) (ledge +0.5));
+													A= a->r;
+													Metric MAs =MA,MBs;
+													// cout << " lSubEdge old=" << ledge 
+													//      << " new " << A << MA << endl;
+													ledge = 0; 
+													Real8 x =0, xstep= 1. /  NbSubEdge;
+													for (int kk=0; kk < NbSubEdge; kk++,A=B,MAs=MBs ) {
+														x += xstep;
+														B =  e->F(k ? x : 1-x);
+														MBs= background ? BTh.MetricAt(B) :Metric(1-x, MA, x ,MB);
+														AB = A-B;
+														lSubEdge[kk]= (ledge += (MAs(AB)+MBs(AB))/2);
+														// cout << "     " << lSubEdge[kk] << " x " << x  
+														//      << " " << A << B << MA << MB<< endl ;
+													}
+													//  cout << endl;
+												}
+
+												Real8 lcurveb = lcurve+ ledge ;
+												while (lcurve<=s && s <= lcurveb && nbv < nbvend)
+												{
+													// New points
+
+													// Real8 aa=(lcurveb-s)/ledge;
+													// Real8 bb=(s-lcurve)/ledge;
+
+													Real8 ss = s-lcurve;
+													// 1) find the SubEdge containing ss by dichotomie
+													int kk0=-1,kk1=NbSubEdge-1,kkk;
+													Real8 ll0=0,ll1=ledge,llk;
+													while (kk1-kk0>1)
+													{
+														if (ss < (llk=lSubEdge[kkk=(kk0+kk1)/2]))
+															kk1=kkk,ll1=llk;
+														else
+															kk0=kkk,ll0=llk;}
+														assert(kk1 != kk0);
+
+														Real8 sbb = (ss-ll0  )/(ll1-ll0);
+														Real8 bb = (kk1+sbb)/NbSubEdge, aa=1-bb;
+
+														// new vertex on edge
+														vb = &vertices[nbv++];
+														vb->m = Metric(aa,a->m,bb,b->m);
+														vb->ReferenceNumber = e->ref;
+														vb->DirOfSearch =NoDirOfSearch;
+														Real8 abcisse = k ? bb : aa;
+														vb->r =  e->F( abcisse );
+														VerticesOnGeomEdge[NbVerticesOnGeomEdge++]= VertexOnGeom(*vb,*e,abcisse);        
+
+														// to take in account the sens of the edge
+
+														s += lstep;
+														edges[nbe].v[0]=va;
+														edges[nbe].v[1]=vb;
+														edges[nbe].ref = e->ref;
+														edges[nbe].on = e;
+														edges[nbe].adj[0] = PreviousNewEdge;
+														if(PreviousNewEdge)
+															PreviousNewEdge->adj[1] = &edges[nbe];
+#ifdef DRAWING1
+														vb->Draw();
+														edges[nbe].Draw();
+#endif
+														PreviousNewEdge = edges + nbe;
+														nbe++;
+#ifdef DEBUG1                 
+														cout << " new points " << nbv-1 << " " << vb->r ;
+														cout << " new edge " << nbe-1 << " " ;
+														cout << va << vb <<  " kk0 = " << kk0 
+															<< " " << kk1 << " ss=" << ss ;
+														cout << " " << sbb << endl;
+														cout << "      " << aa << va->r << bb << vb->r 
+															<<" length=" << Norme(va->r-vb->r) << endl;
+														cout << "      s " << s << " lstep= " << lstep 
+															<< " ledge= " << ledge 
+															<< " lcurve= " << lcurve << endl;
+#endif
+														va = vb;
+												}
+												lcurve = lcurveb;
+												e->SetMark();
+												// cout << e-Gh.edges << ", " << k << " " 
+												//      <<(*e)[k].r <<" " <<(*e)[1-k].r <<" " 
+												//      << lcurve<< ";; " ;                          
+												a=b;
+												if (b->Required() ) break;
+												int kprev=k;
+												k = e->SensAdj[kprev];// next vertices
+												e = e->Adj[kprev];
+												assert(e);
+											}// for(;;)
+											vb = b->to;
+											//            cout << endl;
+											NbEdgeCurve = Max((Int4) (lcurve +0.5), (Int4) 1);
+											NbNewPoints = NbEdgeCurve-1;
+											if(!kstep)
+											{ NbVerticesOnGeomEdge0 += NbNewPoints;
+												NbOfCurves++;}
+
+												nbvend=nbv+NbNewPoints; 
+
+												lstep = lcurve / NbEdgeCurve;
+												//   cout <<"lstep " << lstep << " lcurve " 
+												//    << lcurve << " NbEdgeCurve " << NbEdgeCurve << " " <<NbVerticesOnGeomEdge0<<" " <<NbVerticesOnGeomEdge<<" step =" <<step<<  endl;
+										} 
+										// end of curve --
+										if (edges) { // last edges of the curves 
+											edges[nbe].v[0]=va;
+											edges[nbe].v[1]=vb;
+											edges[nbe].ref = e->ref;
+											edges[nbe].on = e;
+											edges[nbe].adj[0] = PreviousNewEdge;
+											edges[nbe].adj[1] = 0;
+											if(PreviousNewEdge)
+												PreviousNewEdge->adj[1] = & edges[nbe];
+
+
+#ifdef DRAWING1
+											edges[nbe].Draw();
+#endif
+											nbe++;}
+										else
+											nbe += NbEdgeCurve;
+									} // end on  curve ---
+								} // if (edges[i][j].Corner())  
+					} // for (i=0;i<nbe;i++)
+					if(!step) {
+						// cout << "edges " << edges << " VerticesOnGeomEdge " <<VerticesOnGeomEdge << endl;
+						assert(!edges);
+						assert(!VerticesOnGeomEdge);
+						edges = new Edge[nbex=nbe];
+						if(NbVerticesOnGeomEdge0)
+							VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge0];
+						assert(edges);
+						assert(VerticesOnGeomEdge || NbVerticesOnGeomEdge0 ==0);
+						// do the vertex on a geometrical vertex
+						NbVerticesOnGeomEdge0 = NbVerticesOnGeomEdge;       
+					}
+					else 
+						assert(NbVerticesOnGeomEdge == NbVerticesOnGeomEdge0);
+					//     cout << " Nb of Curves = " << NbOfCurves << "nbe = " << nbe 
+					//	  << "== " << nbex << "  nbv = " << nbv <<  endl;
+					assert(nbex=nbe);
+				} // for (step=0;step<2;step++)
+
+#ifdef DRAWING1
+				reffecran();
+				InitDraw();
+				Draw();
+				inquire();
+#endif
+
+				Insert();
+				ForceBoundary();
+				FindSubDomain();
+
+#ifdef DRAWING1
+				reffecran();
+				Draw();
+				inquire();
+#endif
+				// NewPointsOld(*this) ;
+				NewPoints(*this,0) ;
+				CurrentTh = 0;
+		}
+
+		Edge** Triangles::MakeGeometricalEdgeToEdge()
+		{
+			assert(Gh.nbe);
+			Edge **e= new (Edge* [Gh.nbe]);
+
+			Int4 i;
+			for ( i=0;i<Gh.nbe ; i++)
+				e[i]=NULL;
+			for ( i=0;i<nbe ; i++) 
+			{ 
+				Edge * ei = edges+i;
+				GeometricalEdge *on = ei->on; 
+				e[Gh.Number(on)] = ei;    
+			}
+			for ( i=0;i<nbe ; i++) 
+				for (int ii=0;ii<2;ii++) { 
+					Edge * ei = edges+i;
+					GeometricalEdge *on = ei->on;
+					int j= ii;
+					while (!(*on)[j].Required()) { 
+						//	cout << i << " " << ii << " j= " << j << " curve = " 
+						//           <<  on->CurveNumber << "  " << Gh.Number(on) << " on " << j 
+						//   << " s0 " << Gh.Number( (*on)[0]) << " s1  " << Gh.Number( (*on)[1]) 
+						//   << " ->  " ;
+						Adj(on,j); // next geom edge
+						j=1-j;
+						//       cout << Gh.Number(on) << "  " << j  << " e[ON] =  " <<  e[Gh.Number(on)] 
+						//    << " s0 " << Gh.Number( (*on)[0]) << " s1  " << Gh.Number( (*on)[1]) << endl; 
+						if (e[Gh.Number(on)])  break; // optimisation     
+						e[Gh.Number(on)] = ei; 
+					}
+				}
+
+			int kk=0;
+			for ( i=0;i<Gh.nbe ; i++)
+				if (!e[i]) 
+					if(kk++<10) {
+						cerr << " Bug -- the geometrical edge " << i << " is on no edge curve = " << Gh.edges[i].CurveNumber 
+							<< " s0 " << Gh.Number( Gh.edges[i][0]) << " s1  " << Gh.Number( Gh.edges[i][1]) << endl; 
+						//	 assert( e[i]);
+					}
+			if(kk) MeshError(997,this);
+
+			return e;
+		}
+
+		Triangles::~Triangles() 
+		{
+			long int verbosity=2;
+			assert(NbRef<=0);
+			if (CurrentTh == this) CurrentTh=0;
+			if(verbosity>10)
+				cout << " ~Triangles "<< this  <<" "<< identity << endl;
+			if(vertices)  delete [] vertices;
+			if(edges)     delete [] edges;
+			if(triangles) delete [] triangles;
+			if(quadtree)  delete  quadtree;
+			if(ordre)     delete [] ordre;
+			if( subdomains) delete []  subdomains;
+			if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge;
+			if (VerticesOnGeomVertex) delete [] VerticesOnGeomVertex;
+			if (name) delete [] name;
+			if (identity) delete [] identity;
+			if (VertexOnBThVertex) delete [] VertexOnBThVertex;
+			if (VertexOnBThEdge) delete [] VertexOnBThEdge;
+
+			if (&Gh) 
+			{
+				if (Gh.NbRef>0) Gh.NbRef--;
+				else if (Gh.NbRef==0) delete &Gh;
+			}
+			if (&BTh && (&BTh != this))
+			{
+				if (BTh.NbRef>0) BTh.NbRef--;
+				else if (BTh.NbRef==0) delete &BTh;
+			}
+			PreInit(0); // set all to zero 
+
+		}
+
+		void Triangles::SetIntCoor(const char * strfrom)
+		{
+			pmin =  vertices[0].r;
+			pmax =  vertices[0].r;
+
+			// recherche des extrema des vertices pmin,pmax
+			Int4 i;
+			for (i=0;i<nbv;i++) {
+				pmin.x = Min(pmin.x,vertices[i].r.x);
+				pmin.y = Min(pmin.y,vertices[i].r.y);
+				pmax.x = Max(pmax.x,vertices[i].r.x);
+				pmax.y = Max(pmax.y,vertices[i].r.y);
+			}
+			R2 DD = (pmax-pmin)*0.05;
+			pmin = pmin-DD;
+			pmax = pmax+DD; 
+			coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
+			assert(coefIcoor >0);
+
+			// generation of integer coord  
+			for (i=0;i<nbv;i++) {
+				vertices[i].i = toI2(vertices[i].r);    
+			}
+
+			// computation of the det 
+			int Nberr=0;
+			for (i=0;i<nbt;i++)
+			{
+				Vertex & v0 = triangles[i][0];
+				Vertex & v1 = triangles[i][1];
+				Vertex & v2 = triangles[i][2];
+				if ( &v0 && &v1 &&  &v2 ) // a good triangles;
+				{
+					triangles[i].det= det(v0,v1,v2);
+					if (triangles[i].det <=0 && Nberr++ <10)
+					{
+						if(Nberr==1)
+							if (strfrom)
+								cerr << "+++ Fatal Error " << strfrom << "(SetInCoor)  Error :  area of Triangle < 0 " << endl; 
+							else 
+								cerr << "+++  Fatal Error Triangle (in SetInCoor) area of Triangle < 0" << endl;
+						cerr << " Triangle " << i << "  det  (I2) = " << triangles[i].det ;
+						cerr << " (R2) " << Det(v1.r-v0.r,v2.r-v0.r);
+						cerr << "; The 3  vertices " << endl;
+						cerr << Number(v0) << " "  << Number(v1) << " " 
+							<< Number(v2) << " : " ;
+						cerr << v0.r << v1.r << v2.r << " ; ";
+						cerr << v0.i << v1.i << v2.i << endl;
+					}
+				}
+				else
+					triangles[i].det= -1; // Null triangle; 
+			}
+			if (Nberr) MeshError(899,this);
+
+		}
+
+		void Triangles::FillHoleInMesh(){
+
+			Triangles * OldCurrentTh =CurrentTh;
+			long int verbosity=200;
+			
+			CurrentTh=this;
+			//  Int4 NbTold = nbt;
+			// generation of the integer coor
+
+			//  double coef = coefIcoor;
+			// recherche des extrema des vertices pmin,pmax
+			Int4 i;
+			if(verbosity>2)
+				cout << "  -- FillHoleInMesh: Nb of vertices =" << nbv 
+					<< " Pmin = "<< pmin << " Pmax = "<< pmax << endl;
+
+			assert(ordre);
+			for (i=0;i<nbv;i++) 
+				ordre[i]= 0 ;
+
+
+			NbSubDomains =0;
+
+			// generation of the adjacence of the triangles
+			SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv);
+			Int4 * st = new Int4[nbt*3];
+			for (i=0;i<nbt*3;i++)
+				st[i]=-1;
+			Int4 kk =0;
+			for (i=0;i<nbe;i++)
+				kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1])));
+			if (kk != nbe)
+			{ 
+				cerr << " Some Double edge in the mesh, the number is " << kk-nbe << endl;
+				MeshError(1002,this);
+			}
+			for (i=0;i<nbt;i++)
+				for (int j=0;j<3;j++)
+				{
+					// Int4 i0,i1;
+					Int4 k =edge4->addtrie(Number(triangles[i][VerticesOfTriangularEdge[j][0]]),
+							Number(triangles[i][VerticesOfTriangularEdge[j][1]]));
+					Int4 invisible = triangles[i].Hidden(j);
+					if(st[k]==-1)
+						st[k]=3*i+j;
+					else if(st[k]>=0) {
+						assert( ! triangles[i].TriangleAdj(j) && !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3)));
+
+						triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3));
+						if (invisible)  triangles[i].SetHidden(j);
+						if (k<nbe) {
+							triangles[i].SetLocked(j);
+						}
+						st[k]=-2-st[k]; }
+					else {
+						cerr << " The edge (" 
+							<< Number(triangles[i][VerticesOfTriangularEdge[j][0]])
+							<< " , " 
+							<< Number(triangles[i][VerticesOfTriangularEdge[j][1]])
+							<< " ) is in more than 2 triangles " <<k <<endl;
+						cerr << " Edge " << j << " Of Triangle " << i << endl;
+						cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3  << endl;
+						cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3))
+							<< " Of Triangle " <<  Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) << endl;
+						MeshError(9999,this);}	
+
+
+				}
+			
+			if(verbosity>5) {
+				cout << "    On Mesh " << name << endl;
+				cout << "    - The number of Vertices  = " << nbv << endl;
+				cout << "    - The number of Triangles = " << nbt << endl;
+				cout << "    - The number of given edge = " << nbe << endl;
+				cout << "    - The number of all edges = " << edge4->nb() << endl;
+				cout << "    - The Euler number = 1-Nb Of Hole = " << nbt-edge4->nb()+nbv << endl; 
+			}
+
+
+			// check the consistant of edge[].adj and the geometrical required  vertex
+			Int4 k=0;
+			for (i=0;i<edge4->nb();i++)
+				if (st[i] >=0) // edge alone 
+					if (i < nbe) 
+					{
+						Int4 i0=edge4->i(i);ordre[i0] = vertices+i0;
+						Int4 i1=edge4->j(i);ordre[i1] = vertices+i1;
+					}
+					else {
+						k++;
+						if (verbosity>20 && k <20) 
+						{
+							Int4 i0=edge4->i(i);
+							Int4 i1=edge4->j(i);
+							cerr << " Lose boundary edges " << i << " : " << i0 << " " << i1 << endl;
+						}
+					}
+
+			if(k != 0) {
+				if (verbosity>20)
+				{
+					cout << " The given edge are " << endl;
+					for (int i=0;i< nbe;i++)
+						cout <<  " Edge " << i << " : " <<  Number(edges[i][0]) << " " <<  Number(edges[i][1]) 
+							<< " " << edges[i].ref << endl; 
+				}
+				cerr << k << " boundary edges  are not defined as edges " << endl;
+				MeshError(9998,this);
+			}
+			printf("salope1\n");
+
+			// generation of the mesh with boundary points   
+			Int4 nbvb = 0;
+			for (i=0;i<nbv;i++)
+			{ 
+				vertices[i].t=0;
+				vertices[i].vint=0;
+				if (ordre[i]) 
+					ordre[nbvb++] = ordre[i];
+			}
+
+			Triangle *savetriangles= triangles;
+			Int4 savenbt=nbt;
+			Int4 savenbtx=nbtx;
+			SubDomain * savesubdomains = subdomains;
+			subdomains = 0;
+
+			Int4  Nbtriafillhole = 2*nbvb;
+			Triangle * triafillhole =new Triangle[Nbtriafillhole];
+			if (verbosity>9)
+				cout << " Nbtriafillhole triafillhole*" << triafillhole << endl; 
+			triangles =  triafillhole;
+
+			nbt=2;
+			nbtx= Nbtriafillhole;
+
+			for (i=2 ; det( ordre[0]->i, ordre[1]->i, ordre[i]->i ) == 0;){
+				if  ( ++i >= nbvb) {
+					cerr << "FillHoleInMesh: All the vertices are aline " << nbvb << endl;
+					MeshError(998,this); 
+				}
+			}
+			Exchange( ordre[2], ordre[i]);
+
+			Vertex *  v0=ordre[0], *v1=ordre[1];
+
+
+			triangles[0](0) = 0; // sommet pour infini 
+			triangles[0](1) = v0;
+			triangles[0](2) = v1;
+
+			triangles[1](0) = 0;// sommet pour infini 
+			triangles[1](2) = v0;
+			triangles[1](1) = v1;
+			const int e0 = OppositeEdge[0];
+			const int e1 = NextEdge[e0];
+			const int e2 = PreviousEdge[e0];
+			triangles[0].SetAdj2(e0, &triangles[1] ,e0);
+			triangles[0].SetAdj2(e1, &triangles[1] ,e2);
+			triangles[0].SetAdj2(e2, &triangles[1] ,e1);
+
+			triangles[0].det = -1;  // faux triangles
+			triangles[1].det = -1;  // faux triangles
+
+			triangles[0].SetTriangleContainingTheVertex();
+			triangles[1].SetTriangleContainingTheVertex();
+
+			triangles[0].link=&triangles[1];
+			triangles[1].link=&triangles[0];
+
+			printf("salope2\n");
+			//  nbtf = 2;
+			if (  !quadtree ) delete  quadtree; // ->ReInitialise();
+
+			quadtree = new QuadTree(this,0);
+			quadtree->Add(*v0);
+			quadtree->Add(*v1);
+
+			// on ajoute les sommets un a un 
+			Int4 NbSwap=0;
+			for (Int4 icount=2; icount<nbvb; icount++) {
+
+				Vertex *vi  = ordre[icount];
+				//	  cout << " Add vertex " <<  Number(vi) << endl;
+				Icoor2 dete[3];
+				Triangle *tcvi = FindTriangleContening(vi->i,dete);
+				quadtree->Add(*vi); 
+				Add(*vi,tcvi,dete);
+				NbSwap += vi->Optim(1,1);
+
+			}// end loop on  icount	
+			printf("salope3\n");
+
+			//Int4 nbtfillhole = nbt;
+			// inforce the boundary 
+			TriangleAdjacent ta(0,0);
+			Int4 nbloss = 0,knbe=0;
+			for ( i = 0; i < nbe; i++) 
+				if (st[i] >=0)  // edge alone => on border ...  FH oct 2009
+				{
+					Vertex & a=edges[i][0], & b =    edges[i][1];
+					if (a.t && b.t) // le bug est la si maillage avec des bod non raffine 1.
+					{
+						knbe++;
+						if (ForceEdge(a,b,ta)<0)
+							nbloss++;
+					}
+				}
+			if(nbloss)
+			{
+				cerr << " we loss some  " << nbloss << " "  << " edges other " << knbe << endl;
+				MeshError(1100,this);
+			}
+			FindSubDomain(1);
+			// remove all the hole 
+			// remove all the good sub domain
+			Int4 krm =0;
+			for (i=0;i<nbt;i++)
+				if (triangles[i].link) // remove triangles
+				{
+					krm++;
+					for (int j=0;j<3;j++)
+					{
+						TriangleAdjacent ta =  triangles[i].Adj(j);
+						Triangle & tta = * (Triangle *) ta;
+						if(! tta.link) // edge between remove and not remove 
+						{ // change the link of ta;
+							int ja = ta;
+							Vertex *v0= ta.EdgeVertex(0);
+							Vertex *v1= ta.EdgeVertex(1);
+							Int4 k =edge4->addtrie(v0?Number(v0):nbv,v1? Number(v1):nbv);
+							assert(st[k] >=0); 
+							tta.SetAdj2(ja,savetriangles + st[k] / 3,(int) (st[k]%3));
+							ta.SetLock();
+							st[k]=-2-st[k]; 
+						}
+					}
+				}
+			Int4 NbTfillHoll =0;
+			for (i=0;i<nbt;i++)
+				if (triangles[i].link) {
+					triangles[i]=Triangle((Vertex *) NULL,(Vertex *) NULL,(Vertex *) NULL);
+					triangles[i].color=-1;
+				}
+				else
+				{
+					triangles[i].color= savenbt+ NbTfillHoll++;
+				}
+			// cout <<      savenbt+NbTfillHoll << " " <<  savenbtx  << endl;
+			assert(savenbt+NbTfillHoll <= savenbtx );
+			// copy of the outside triangles in saveTriangles 
+			for (i=0;i<nbt;i++)
+				if(triangles[i].color>=0) 
+				{
+					savetriangles[savenbt]=triangles[i];
+					savetriangles[savenbt].link=0;
+					savenbt++;
+				}
+			// gestion of the adj
+			k =0;
+			Triangle * tmax = triangles + nbt;
+			for (i=0;i<savenbt;i++)  
+			{ 
+				Triangle & ti = savetriangles[i];
+				for (int j=0;j<3;j++)
+				{
+					Triangle * ta = ti.TriangleAdj(j);
+					int aa = ti.NuEdgeTriangleAdj(j);
+					int lck = ti.Locked(j);
+					if (!ta) k++; // bug 
+					else if ( ta >= triangles && ta < tmax) 
+					{
+						ta= savetriangles + ta->color;
+						ti.SetAdj2(j,ta,aa);
+						if(lck) ti.SetLocked(j);
+					}
+				}
+			}
+			//	 OutSidesTriangles = triangles;
+			//	Int4 NbOutSidesTriangles = nbt;
+
+			// restore triangles;
+			nbt=savenbt;
+			nbtx=savenbtx;
+			delete [] triangles;
+			delete [] subdomains;
+			triangles = savetriangles;
+			subdomains = savesubdomains;
+			//	 cout <<  triangles << " <> " << OutSidesTriangles << endl; 
+			/*	 k=0;
+				 for (i=0;i<nbt;i++)
+				 for (int j=0;j<3;j++)
+				 if (!triangles[i].TriangleAdj(j))
+				 k++;
+
+*/
+
+			printf("salope4\n");
+			if (k) {
+				cerr << "Error Nb of triangles edge alone = " << k << endl;
+				MeshError(9997,this);
+			}
+			printf("salope4a\n");
+			FindSubDomain();
+			// cout << " NbTOld = " << NbTold << " ==  " << nbt - NbOutT << " " << nbt << endl;
+
+			// 
+
+			printf("salope4b\n");
+			delete edge4;
+			printf("salope4ba\n");
+			delete [] st;
+			printf("salope4bb %i\n",nbv);
+			for (i=0;i<nbv;i++){
+				printf("%i\n",i);
+				quadtree->Add(vertices[i]);
+			}
+			printf("salope4c\n");
+
+			SetVertexFieldOn();
+			printf("salope5a\n");
+
+			for (i=0;i<nbe;i++){
+				if(edges[i].on){
+					for(int j=0;j<2;j++){
+						if (!edges[i].adj[j]){
+							if(!edges[i][j].on->IsRequiredVertex()) {
+								cerr << " Erreur adj et sommet requis edges [" << i <<  "][ " << j << "]= "
+									<<  Number(edges[i][j]) << " : "  << " on = " << Gh.Number(edges[i].on) ;
+								if (edges[i][j].on->OnGeomVertex())
+									cerr << " vertex " << Gh.Number(edges[i][j].on->gv);
+								else if (edges[i][j].on->OnGeomEdge())
+									cerr << "Edges " << Gh.Number(edges[i][j].on->ge);
+								else
+									cerr << " = " << edges[i][j].on ;
+								cerr << endl;
+							}
+						}
+					}
+				}
+			}
+
+			printf("salope5\n");
+			CurrentTh=OldCurrentTh;
+		}
+
+		Triangles::Triangles(Triangles & Th,Geometry * pGh,Triangles * pBth,Int4 nbvxx) // COPY OPERATOR
+			: Gh(*(pGh?pGh:&Th.Gh)), BTh(*(pBth?pBth:this))
+			{
+				Gh.NbRef++;
+				nbvxx = Max(nbvxx,Th.nbv); 
+				Int4 i;
+				// do all the allocation to be sure all the pointer existe
+
+				char * cname = 0;
+				if (Th.name) 
+				{
+					cname = new char[strlen(Th.name)+1];
+					strcpy(cname,Th.name);
+				}
+				PreInit(nbvxx,cname);// to make the allocation 
+				// copy of triangles
+				nt=Th.nt;
+				nbv = Th.nbv;
+				nbt = Th.nbt;
+				nbiv = Th.nbiv;
+				nbe = Th.nbe;
+				NbSubDomains = Th.NbSubDomains;
+				NbOutT = Th.NbOutT;
+				NbOfQuad =  Th.NbOfQuad ;
+				NbOfSwapTriangle =0;
+				NbVerticesOnGeomVertex = Th.NbVerticesOnGeomVertex;
+				if(NbVerticesOnGeomVertex)
+					VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+				NbVerticesOnGeomEdge = Th.NbVerticesOnGeomEdge;
+				if (NbVerticesOnGeomEdge)
+					VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge] ;
+				if (& BTh == & Th.BTh) // same back ground 
+				{
+					BTh.NbRef++;
+					NbVertexOnBThVertex = Th.NbVertexOnBThVertex;
+					if(NbVertexOnBThVertex)
+						VertexOnBThVertex = new VertexOnVertex[NbVertexOnBThVertex];
+					NbVertexOnBThEdge = Th.NbVertexOnBThEdge;
+					if(NbVertexOnBThEdge)
+						VertexOnBThEdge = new VertexOnEdge[NbVertexOnBThEdge];
+				}
+				else 
+				{ // no add on back ground mesh 
+					BTh.NbRef++;
+					NbVertexOnBThVertex=0;
+					VertexOnBThVertex=0;
+					NbVertexOnBThEdge=0;
+					VertexOnBThEdge=0;
+					//       assert (& BTh == this); // --- a voir 
+
+				}
+
+
+				if(nbe)
+					edges = new Edge[nbe];
+				if(NbSubDomains)
+					subdomains = new SubDomain[NbSubDomains];
+				pmin = Th.pmin;
+				pmax = Th.pmax;
+				coefIcoor = Th.coefIcoor;
+				for(i=0;i<nbt;i++)
+					triangles[i].Set(Th.triangles[i],Th,*this);
+				for(i=0;i<nbe;i++)
+					edges[i].Set(Th,i,*this);
+				for(i=0;i<nbv;i++)
+					vertices[i].Set(Th.vertices[i],Th,*this);
+				for(i=0;i<NbSubDomains;i++)  
+					subdomains[i].Set(Th,i,*this);
+				for (i=0;i<NbVerticesOnGeomVertex;i++)
+					VerticesOnGeomVertex[i].Set(Th.VerticesOnGeomVertex[i],Th,*this);
+				for (i=0;i<NbVerticesOnGeomEdge;i++)
+					VerticesOnGeomEdge[i].Set(Th.VerticesOnGeomEdge[i],Th,*this);
+				quadtree=0;
+
+
+				//  assert(!OutSidesTriangles);
+			}
+
+		/** -- old with a bug we loss some time last swap
+
+		  Int4  Triangle::Optim(Int2 i,int koption)
+		  {
+		// turn in the positif sens around vertex s  
+		register  Int4 NbSwap =0;
+		register Vertex * s  = ns[i];
+		register Triangle * tbegin=0 , *t = this , *ttc;
+		register int k=0,j = EdgesVertexTriangle[i][0],jc;
+		tbegin=t;
+		do {
+		k++; 
+#ifdef DEBUG
+assert( s == & (*t)[VerticesOfTriangularEdge[j][1]] );
+#endif
+#ifdef DRAWING1 
+t->Draw();
+DrawMark( s->r);
+#endif
+ttc =  t->at[j];
+jc = NextEdge[t->aa[j]&3];
+cout << *t << " " <<  VerticesOfTriangularEdge[j][1] << "\n\t try swap " << * ttc << " " << jc ;
+while ( ttc->swap(jc,koption)) {
+NbSwap++,assert(k++<20000);
+ttc =  t->at[j];
+jc = NextEdge[t->aa[j]&3];
+cout << "\n\t s  " <<  *ttc << " " << jc << endl;
+}
+cout << endl;
+t = ttc;
+j = NextEdge[jc];
+assert(k<20000);
+} while ( (tbegin != t)); 
+
+return NbSwap;
+}
+*/
+Int4  Triangle::Optim(Int2 i,int koption)
+{
+	// turne around in positif sens
+	Int4 NbSwap =0;
+#ifdef DEBUG
+	Vertex * s  = ns[i];
+#endif
+	Triangle  *t = this;
+	int k=0,j =OppositeEdge[i];
+	int jp = PreviousEdge[j];
+	// initialise   tp, jp the previous triangle & edge
+	Triangle *tp= at[jp];
+	jp = aa[jp]&3;
+#ifdef DEBUG
+	assert(tp->at[jp] == this);
+#endif
+	do {
+#ifdef DEBUG
+		assert(k++<20000);
+		assert( s == & (*t)[OppositeVertex[j]] );
+#endif
+		//    cout << *t << " " <<  j  << "\n\t try swap " ;
+		while (t->swap(j,koption))
+		{
+			NbSwap++;
+			assert(k++<20000);
+			t=  tp->at[jp];      // set unchange t qnd j for previous triangles
+			j=  NextEdge[tp->aa[jp]&3];
+			//   cout << "\n\t s  " <<  *t << " " << j << endl;
+#ifdef DEBUG
+			assert( s == & (*t)[OppositeVertex[j]] );
+#endif
+		}
+		// end on this  Triangle 
+		tp = t;
+		jp = NextEdge[j];
+
+		t=  tp->at[jp];      // set unchange t qnd j for previous triangles
+		j=  NextEdge[tp->aa[jp]&3];
+
+	} while( t != this);
+	return NbSwap;
+}
+
+void Triangles::SmoothingVertex(int nbiter,Real8 omega )
+{ 
+	long int verbosity=0;
+	//  if quatree exist remove it end reconstruct
+	if (quadtree) delete quadtree;
+	quadtree=0;
+	ReMakeTriangleContainingTheVertex();
+	Triangle vide; // a triangle to mark the boundary vertex
+	Triangle   ** tstart= new Triangle* [nbv];
+	Int4 i,j,k;
+	//   attention si Background == Triangle alors on ne peut pas utiliser la rechech rapide 
+	if ( this == & BTh)
+		for ( i=0;i<nbv;i++)
+			tstart[i]=vertices[i].t;     
+	else 
+		for ( i=0;i<nbv;i++)
+			tstart[i]=0;
+	for ( j=0;j<NbVerticesOnGeomVertex;j++ ) 
+		tstart[ Number(VerticesOnGeomVertex[j].mv)]=&vide;
+	for ( k=0;k<NbVerticesOnGeomEdge;k++ ) 
+		tstart[ Number(VerticesOnGeomEdge[k].mv)]=&vide;
+	if(verbosity>2) 
+		cout << "  -- SmoothingVertex: nb Iteration = " << nbiter << " Omega = " << omega << endl;
+	for (k=0;k<nbiter;k++)
+	{
+		Int4 i,NbSwap =0;
+		Real8 delta =0;
+		for ( i=0;i<nbv;i++)
+			if (tstart[i] != &vide) // not a boundary vertex 
+				delta=Max(delta,vertices[i].Smoothing(*this,BTh,tstart[i],omega));
+		if (!NbOfQuad)
+			for ( i=0;i<nbv;i++)
+				if (tstart[i] != &vide) // not a boundary vertex 
+					NbSwap += vertices[i].Optim(1);
+		if (verbosity>3)
+			cout << "    Move max = " <<  sqrt(delta) << " iteration = " 
+				<< k << " Nb of Swap = " << NbSwap << endl;
+	}
+
+	delete [] tstart;
+	if (quadtree) quadtree= new QuadTree(this);
+}
+void Triangles::MakeQuadTree()
+{  
+	long int verbosity=2;
+	if(verbosity>8)
+		cout << "      MakeQuadTree" << endl;
+	if (  !quadtree )  quadtree = new QuadTree(this);
+
+
+#ifdef DRAWING1
+	quadtree->Draw();
+	rattente(1);
+	reffecran();
+	quadtree->Draw();
+	rattente(1);
+#endif
+
+}
+void  Triangles::ShowRegulaty() const// Add FH avril 2007 
+{
+	const  Real8  sqrt32=sqrt(3.)*0.5; 
+	const Real8  aireKh=sqrt32*0.5;
+	D2  Beq(1,0),Heq(0.5,sqrt32);
+	D2xD2 Br(D2xD2(Beq,Heq).t());
+	D2xD2 B1r(Br.inv());
+	/*   D2xD2 BB = Br.t()*Br;
+		 cout << " BB = " << BB << " " << Br*B1r <<  endl; 
+		 MetricAnIso MMM(BB.x.x,BB.x.y,BB.y.y);
+		 MatVVP2x2 VMM(MMM);
+		 cout << " " << VMM.lambda1 << " " << VMM.lambda2 <<  endl; 
+		 */
+	double gammamn=1e100,hmin=1e100;
+	double gammamx=0,hmax=0;
+	double beta=1e100;
+	double beta0=0;
+	double  alpha2=0;
+	double area=0,Marea=0;
+	// Real8 cf= Real8(coefIcoor);
+	// Real8 cf2= 6.*cf*cf;
+	int nt=0;
+	for (int it=0;it<nbt;it++)
+		if ( triangles[it].link) 
+		{
+			nt++;
+			Triangle &K=triangles[it];
+			Real8  area3= Area2((R2) K[0],(R2) K[1],(R2) K[2])/6.;
+			area+= area3;
+			D2xD2 B_Kt(K[0],K[1],K[2]);
+			D2xD2 B_K(B_Kt.t());
+			D2xD2 B1K = Br*B_K.inv();
+			D2xD2 BK =  B_K*B1r;
+			D2xD2 B1B1 = B1K.t()*B1K;
+			MetricAnIso MK(B1B1.x.x,B1B1.x.y,B1B1.y.y);
+			MatVVP2x2 VMK(MK);
+			alpha2 = Max(alpha2,Max(VMK.lambda1/VMK.lambda2,VMK.lambda2/VMK.lambda1));
+			// cout << B_K << " * " << B1r << " == " << BK << " " << B_K*B_K.inv() << endl;
+			Real8 betaK=0;
+
+			for (int j=0;j<3;j++)
+			{
+				Real8 he= Norme2(R2(K[j],K[(j+1)%3]));
+				hmin=Min(hmin,he);
+				hmax=Max(hmax,he);
+				Vertex & v=K[j];
+				D2xD2 M((MetricAnIso)v);
+				betaK += sqrt(M.det());
+
+				D2xD2 BMB = BK.t()*M*BK;
+				MetricAnIso M1(BMB.x.x,BMB.x.y,BMB.y.y);
+				MatVVP2x2 VM1(M1);
+				//cout << B_K <<" " <<  M << " " <<  he << " " << BMB << " " << VM1.lambda1 << " " << VM1.lambda2<<   endl; 
+				gammamn=Min3(gammamn,VM1.lambda1,VM1.lambda2);
+				gammamx=Max3(gammamx,VM1.lambda1,VM1.lambda2);		
+			}
+			betaK *= area3;//  1/2 (somme sqrt(det))* area(K)
+			Marea+= betaK;
+			// cout << betaK << " " << area3 << " " << beta << " " << beta0 << " " << area3*3*3*3 <<endl;
+			beta=min(beta,betaK);
+			beta0=max(beta0,betaK);
+		}   
+	area*=3; 
+	gammamn=sqrt(gammamn);
+	gammamx=sqrt(gammamx);    
+	cout << "  -- adaptmesh Regulary:  Nb triangles " << nt <<  " , h  min " << hmin  << " , h max " << hmax << endl;  
+	cout << "     area =  " << area << " , M area = " << Marea << " , M area/( |Khat| nt) " << Marea/(aireKh*nt) << endl; 
+	cout << "     infiny-regulaty:  min " << gammamn << "  max " << gammamx << endl;  
+	cout << "     anisomax  "<< sqrt(alpha2) << ", beta max = " << 1./sqrt(beta/aireKh) 
+		<< " min  "<<  1./sqrt(beta0/aireKh)  << endl;
+}
+void  Triangles::ShowHistogram() const
+{
+
+	const Int4 kmax=10;
+	const Real8 llmin = 0.5,llmax=2;
+	const Real8 lmin=log(llmin),lmax=log(llmax),delta= kmax/(lmax-lmin);
+	Int4 histo[kmax+1];
+	Int4 i,it,k, nbedges =0;
+	for (i=0;i<=kmax;i++) histo[i]=0;
+	for (it=0;it<nbt;it++)
+		if ( triangles[it].link) 
+		{
+
+			for (int j=0;j<3;j++)
+			{
+				Triangle *ta = triangles[it].TriangleAdj(j);
+				if ( !ta || !ta->link || Number(ta) >= it) 
+				{ 
+					Vertex & vP = triangles[it][VerticesOfTriangularEdge[j][0]];
+					Vertex & vQ = triangles[it][VerticesOfTriangularEdge[j][1]];
+					if ( !& vP || !&vQ) continue;
+					R2 PQ = vQ.r - vP.r;
+					Real8 l = log(LengthInterpole(vP,vQ,PQ));
+#ifdef DRAWING2             
+					if (l>1.4)  {
+						penthickness(3);
+						vP.MoveTo(),vQ.LineTo();
+						penthickness(1);
+						cout << "   l = " << l << Number(vP) << " edge = " << Number(vQ) << endl;
+					}
+#endif             
+					nbedges++;
+					k = (int) ((l - lmin)*delta);
+					k = Min(Max(k,0L),kmax);
+					histo[k]++;
+				}
+			}
+		}  
+	cout << "  -- Histogram of the unit mesh,  nb of edges" << nbedges << endl <<endl;
+
+	cout << "        length of edge in   | % of edge  | Nb of edges " << endl;
+	cout << "        ------------------- | ---------- | ----------- " << endl;
+	for   (i=0;i<=kmax;i++)
+	{ 
+		cout << "    " ;
+		cout.width(10);
+		if (i==0) cout  << " 0 " ;
+		else cout  << exp(lmin+i/delta) ;
+		cout.width(); cout << "," ;
+		cout.width(10);
+		if (i==kmax) cout << " +infty " ;
+		else cout  << exp(lmin+(i+1)/delta) ;
+		cout.width();cout << "   |   " ;
+
+		cout.precision(4);
+		cout.width(6);
+		cout <<  ((long)  ((10000.0 * histo[i])/ nbedges))/100.0 ;
+		cout.width();
+		cout.precision();
+		cout <<  "   |   " << histo[i] <<endl;
+	}
+	cout << "        ------------------- | ---------- | ----------- " << endl <<endl;
+
+}
+
+int  Triangles::Crack()
+{ 
+	assert(NbCrackedEdges ==0 || NbCrackedVertices >0); 
+	for (int i=0;i<NbCrackedEdges;i++)
+		CrackedEdges[i].Crack();
+	return NbCrackedEdges;
+}
+
+int Triangles::UnCrack() 
+{ 
+	assert(NbCrackedEdges ==0 || NbCrackedVertices >0); 
+	for (int i=0;i<NbCrackedEdges;i++)
+		CrackedEdges[i].UnCrack();
+	return NbCrackedEdges;
+}
+
+int Triangles::CrackMesh()
+{
+	long int verbosity=0;
+	Triangles *CurrentThOld = CurrentTh;
+	//  computed the number of cracked edge
+	int i,k;
+	for (k=i=0;i<nbe;i++)
+		if(edges[i].on->Cracked()) k++;
+	if( k==0) return 0;
+	CurrentTh = this;
+	cout << " Nb of Cracked Edges = " << k << endl;
+	NbCrackedEdges =k;
+	CrackedEdges = new  CrackedEdge[k];
+	//  new edge
+	Edge * e = new Edge[ nbe + k];
+
+	// copy
+	for (i=0;i<nbe;i++) 
+		e[i] = edges[i];
+	delete edges;
+	edges = e;
+
+	const int  nbe0  = nbe;
+	for (k=i=0;i<nbe0;i++) // on double les arete cracked 
+		if(edges[i].on->Cracked())
+		{
+			e[nbe] = e[i];
+			//  return the edge 
+			e[nbe].v[0] =  e[i].v[1];
+			e[nbe].v[1] =  e[i].v[0];
+			e[nbe].on = e[i].on->link ; // fqux 
+			CrackedEdges[k++]=CrackedEdge(edges,i,nbe);
+			nbe++;
+		}
+	ReMakeTriangleContainingTheVertex() ; 
+	//  
+	int nbcrakev  =0;
+	Vertex *vlast = vertices + nbv;
+	Vertex *vend = vertices + nbvx; // end of array
+	for (int iv=0;iv<nbv;iv++) // vertex 
+	{
+		Vertex & v= vertices[iv];
+		Vertex * vv = & v;  
+		int kk=0; // nb cracked
+		int kc=0; 
+		int kkk =0; // nb triangle  with same number 
+		Triangle * tbegin = v.t;
+		int i  = v.vint;       
+		assert(tbegin && (i >= 0 ) && (i <3));
+		// turn around the vertex v
+		TriangleAdjacent ta(tbegin,EdgesVertexTriangle[i][0]);// previous edge
+		int k=0;
+		do {
+			int kv = VerticesOfTriangularEdge[ta][1];
+			k++; 
+			Triangle * tt (ta);
+			if ( ta.Cracked() ) 
+			{   
+				TriangleAdjacent tta=(ta.Adj());
+				assert(tta.Cracked());
+				if ( kk == 0) tbegin=ta,kkk=0;  //  begin by a cracked edge  => restart                
+				if (  kkk ) { kc =1;vv = vlast++;  kkk = 0; } // new vertex if use 
+				kk++;// number of cracked edge view                 
+			}
+			if ( tt->link ) { // if good triangles store the value 
+				int it = Number(tt);
+				assert(it < nt);
+				(*tt)(kv)= vv; //   Change the vertex of triangle 
+				if(vv<vend) {*vv= v;vv->ReferenceNumber=iv;} // copy the vertex value + store the old vertex number in ref 
+				//	  tt->SetTriangleContainingTheVertex();
+				kkk++;
+			} else if (kk) { // crack + boundary 
+				if (  kkk ) { kc =1;vv = vlast++;  kkk = 0; } // new vertex if use 
+			}
+
+			ta = Next(ta).Adj(); 
+		} while ( (tbegin != ta)); 
+		assert(k);
+		if (kc)  nbcrakev++;
+	}
+
+	if ( nbcrakev ) 
+		for (int iec =0;iec < NbCrackedEdges; iec ++)
+			CrackedEdges[iec].Set();
+
+	//  set the ref 
+	cout << " set the ref " <<  endl ;
+	NbCrackedVertices =   nbcrakev;
+	// int nbvo = nbv;
+	nbv = vlast - vertices;
+	int nbnewv =  nbv - nbv; // nb of new vrtices 
+	if (nbcrakev && verbosity > 1 )
+		cout << " Nb of craked vertices = " << nbcrakev << " Nb of created vertices " <<   nbnewv<< endl;
+	// all the new vertices are on geometry 
+	//  BOFBO--  A VOIR
+	if (nbnewv)
+	{ // 
+		Int4 n = nbnewv+NbVerticesOnGeomVertex;
+		Int4 i,j,k;
+		VertexOnGeom * vog = new VertexOnGeom[n];
+		for ( i =0; i<NbVerticesOnGeomVertex;i++) 
+			vog[i]=VerticesOnGeomVertex[i];
+		delete [] VerticesOnGeomVertex;
+		VerticesOnGeomVertex = vog;
+		// loop on cracked edge 
+		Vertex * LastOld = vertices + nbv - nbnewv;
+		for (int iec =0;iec < NbCrackedEdges; iec ++)
+			for (k=0;k<2;k++)
+			{
+				Edge & e = *( k ? CrackedEdges[iec].a.edge : CrackedEdges[iec].b.edge);
+				for (j=0;j<2;j++) 
+				{
+					Vertex * v = e(j);
+					if ( v >=  LastOld)
+					{ // a new vertex 
+						Int4 old = v->ReferenceNumber ; // the old same vertex 
+						Int4 i  = ( v - LastOld);
+						//  if the old is on vertex => warning
+						// else the old is on edge => ok 
+						vog[i] = vog[old];
+						//  		    vog[i].mv = v;
+						//g[i].ge = ;
+						//og[i].abcisse = ;
+					}
+
+				}
+			}
+
+		NbVerticesOnGeomVertex = n;
+	}
+	SetVertexFieldOn();
+
+
+	if (vlast >= vend)
+	{  
+		cerr << " Not enougth vertices to crack the mesh we need " << nbv << " vertices " << endl;
+		MeshError(555,this);
+	}
+	cout << "  NbCrackedVertices " <<  NbCrackedVertices << endl;
+	CurrentTh = CurrentThOld;
+	return  NbCrackedVertices;
+}
+
+	Triangles::Triangles(const Triangles & Tho,const int *flag ,const int *bb)
+: Gh(*(new Geometry())), BTh(*this)
+{ // truncature
+	// 
+
+	char cname[] = "trunc";
+
+	int i,k,itadj;
+	int kt=0;
+	int * kk    = new int [Tho.nbv];
+	Int4 * reft = new Int4[Tho.nbt];
+	Int4 nbInT =    Tho.ConsRefTriangle(reft);
+	Int4 * refv = new Int4[Tho.nbv];
+
+	for (i=0;i<Tho.nbv;i++)
+		kk[i]=-1;
+	for (i=0;i<Tho.nbv;i++)
+		refv[i]=0;
+	int nbNewBedge =0;
+	//  int nbOldBedge =0;  
+	for (i=0;i<Tho.nbt;i++)
+		if(  reft[i] >=0 && flag[i]) 
+		{
+			const Triangle & t = Tho.triangles[i];
+			kt++;
+			kk[Tho.Number(t[0])]=1;
+			kk[Tho.Number(t[1])]=1;
+			kk[Tho.Number(t[2])]=1;
+			itadj=Tho.Number(t.TriangleAdj(0));
+			if (  reft[itadj] >=0 && !flag[itadj])
+			{ nbNewBedge++;
+				refv[Tho.Number(t[VerticesOfTriangularEdge[0][0]])]=bb[i];
+				refv[Tho.Number(t[VerticesOfTriangularEdge[0][1]])]=bb[i];
+			}
+			itadj=Tho.Number(t.TriangleAdj(1));
+			if (  reft[itadj] >=0 && !flag[itadj])
+			{ nbNewBedge++;
+				refv[Tho.Number(t[VerticesOfTriangularEdge[1][0]])]=bb[i];
+				refv[Tho.Number(t[VerticesOfTriangularEdge[1][1]])]=bb[i];}
+				itadj=Tho.Number(t.TriangleAdj(2));
+				if (  reft[itadj] >=0 && !flag[itadj])
+				{ nbNewBedge++;
+					refv[Tho.Number(t[VerticesOfTriangularEdge[2][0]])]=bb[i];
+					refv[Tho.Number(t[VerticesOfTriangularEdge[2][1]])]=bb[i];}
+		}
+	k=0;
+	for (i=0;i<Tho.nbv;i++)
+		if (kk[i]>=0) 
+			kk[i]=k++;
+	cout << " number of vertices " << k << " remove = " << Tho.nbv - k << endl;
+	cout << " number of triangles " << kt << " remove = " << nbInT-kt << endl;
+	cout << " number of New boundary edge " << nbNewBedge << endl;
+	Int4 inbvx =k;
+	PreInit(inbvx,cname);
+	for (i=0;i<Tho.nbv;i++)
+		if (kk[i]>=0) 
+		{
+			vertices[nbv] = Tho.vertices[i];
+			if (!vertices[nbv].ref())
+				vertices[nbv].ReferenceNumber = refv[i];
+			nbv++;
+		}
+	assert(inbvx == nbv);
+	for (i=0;i<Tho.nbt;i++)
+		if(  reft[i] >=0 && flag[i]) 
+		{
+			const Triangle & t = Tho.triangles[i];
+			int i0 = Tho.Number(t[0]);
+			int i1 = Tho.Number(t[1]);
+			int i2 = Tho.Number(t[2]);
+			assert(i0>=0 && i1 >= 0 && i2  >= 0);
+			assert(i0<Tho.nbv && i1 <Tho.nbv && i2  <Tho.nbv);
+			// cout <<i<< " F" <<  flag[i] << " T " << nbt << "   = " <<  kk[i0] << " " << kk[i1] << " " << kk[i2] ;
+			// cout << " OT  " <<  i0 << " "  << i1 << " " << i2  << " " << reft[i] << endl;
+			triangles[nbt] = Triangle(this,kk[i0],kk[i1],kk[i2]);
+			triangles[nbt].color = Tho.subdomains[reft[i]].ref; 
+			nbt++;           
+		}
+	assert(kt==nbt);
+	if (nbt ==0 && nbv ==0) {
+		cout << "Error all triangles was remove " << endl;
+		MeshError(999,this);
+	}
+	delete [] kk;
+	delete [] reft;
+	delete [] refv;
+	double cutoffradian = 10.0/180.0*Pi;
+	ConsGeometry(cutoffradian);
+	Gh.AfterRead(); 
+	SetIntCoor();
+	FillHoleInMesh();
+
+	assert(NbSubDomains);
+	assert(subdomains[0].head && subdomains[0].head->link);
+
+}
+
+Triangle * Triangles::FindTriangleContening(const I2 & B,Icoor2 dete[3], Triangle *tstart) const { // in: B 
+	// out: t
+	// out : dete[3]
+	// t the triangle and s0,s1,s2 the 3 vertices of t
+	// in dete[3] = { det(B,s1,s2) , det(s0,B,s2), det(s0,s1,B)}
+	// with det(a,b,c ) = -1 if one of 3 vertices a,b,c is NULL 
+	Triangle * t=0;	
+	int j,jp,jn,jj;
+	if (tstart) 
+		t=tstart;
+	else 
+	{
+		assert(quadtree);
+		Vertex *a = quadtree->NearestVertex(B.x,B.y) ;
+
+		if (! a || !a->t ) {
+			if (a) 
+			{cerr << " Attention PB TriangleConteningTheVertex  vertex number=" << Number(a) << endl;
+				cerr  << "We forget a call to ReMakeTriangleContainingTheVertex" << endl;}
+				cerr << " Pb with " << B << toR2(B) << endl;
+				MeshError(7777);
+		}
+		assert(a>= vertices && a < vertices+nbv);
+#ifdef DRAWING1 
+		a->Draw();
+#endif 
+		//  int k=0;
+		t = a->t;
+		assert(t>= triangles && t < triangles+nbt);
+
+	}
+	Icoor2  detop ;
+	int kkkk =0; // number of test triangle 
+
+	while ( t->det < 0) 
+	{ // the initial triangles is outside  
+		int k0=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+		assert(k0>=0); // k0 the NULL  vertex 
+		int k1=NextVertex[k0],k2=PreviousVertex[k0];
+		dete[k0]=det(B,(*t)[k1],(*t)[k2]);
+		dete[k1]=dete[k2]=-1;     
+		if (dete[k0] > 0) // outside B 
+			return t; 
+		t = t->TriangleAdj(OppositeEdge[k0]);
+		assert(kkkk++ < 2);
+	}
+
+	jj=0;
+	detop = det(*(*t)(VerticesOfTriangularEdge[jj][0]),*(*t)(VerticesOfTriangularEdge[jj][1]),B);
+
+	while(t->det  > 0 ) 
+	{ 
+		assert( kkkk++ < 2000 ); 
+		j= OppositeVertex[jj];
+
+#ifdef DRAWING1
+		t->Draw();
+#endif 
+		dete[j] = detop;  //det(*b,*s1,*s2);
+		jn = NextVertex[j];
+		jp = PreviousVertex[j];
+		dete[jp]= det(*(*t)(j),*(*t)(jn),B);
+		dete[jn] = t->det-dete[j] -dete[jp];
+
+#ifdef DEBUG
+		const Vertex * s0 = (*t)(0);
+		const Vertex * s1 = (*t)(1);
+		const Vertex * s2 = (*t)(2);
+		assert(dete[0] == det(B ,*s1,*s2));
+		assert(dete[1] == det(*s0,B ,*s2));
+		assert(dete[2] == det(*s0,*s1,B ));
+		assert(t->det== (dete[0] + dete[1] +dete[2]));
+#endif
+		// count the number k of  dete <0
+		int k=0,ii[3];
+		if (dete[0] < 0 ) ii[k++]=0; 
+		if (dete[1] < 0 ) ii[k++]=1;
+		if (dete[2] < 0 ) ii[k++]=2;
+		// 0 => ok
+		// 1 => go in way 1
+		// 2 => two way go in way 1 or 2 randomly
+
+		if (k==0) 
+			break;
+		if (k == 2 && BinaryRand())
+			Exchange(ii[0],ii[1]);
+		assert ( k  < 3);
+		TriangleAdjacent t1 = t->Adj(jj=ii[0]);
+		if ((t1.det() < 0 ) && (k == 2))
+			t1 = t->Adj(jj=ii[1]);
+		t=t1;
+		j=t1;// for optimisation we now the -det[OppositeVertex[j]];
+		detop = -dete[OppositeVertex[jj]];
+		jj = j;
+	}
+
+	if (t->det<0) // outside triangle 
+		dete[0]=dete[1]=dete[2]=-1,dete[OppositeVertex[jj]]=detop;
+	//  NbOfTriangleSearchFind += kkkk;  
+	return t;
+}
+
+}
+
Index: /issm/trunk/src/c/Bamgx/Mesh2.h
===================================================================
--- /issm/trunk/src/c/Bamgx/Mesh2.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Mesh2.h	(revision 2740)
@@ -0,0 +1,1503 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef _MESH2_H_
+#define _MESH2_H_
+
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+#include <time.h>
+#if  (defined(unix) || defined(__unix)) && !defined(__AIX)
+#define SYSTIMES
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+#ifdef  DRAWING
+#include "rgraph.hpp"
+#endif
+
+extern int SHOW;
+#include "meshtype.h"
+
+#include "error.hpp"
+
+
+#include "R2.h"
+
+namespace bamg {
+
+
+
+const  double Pi =  3.14159265358979323846264338328;
+const  float fPi =  3.14159265358979323846264338328;
+
+
+class MeshIstream;
+class OFortranUnFormattedFile;
+class IFortranUnFormattedFile;
+
+extern int hinterpole;
+
+
+typedef P2<Icoor1,Icoor2> I2;
+
+inline int BinaryRand(){
+#ifdef RAND_MAX
+ const long HalfRandMax = RAND_MAX/2;
+ return rand() <HalfRandMax;
+#else
+ return rand() & 16384; // 2^14 (for sun because RAND_MAX is not def in stdlib.h)
+#endif
+
+} 
+typedef P2<Real8,Real8> R2;
+typedef P2xP2<Int2,Int4> I2xI2;
+typedef P2<Real4,Real8> R2xR2;
+
+}
+
+#include "Metric.h"
+
+namespace bamg {
+inline float OppositeAngle(float a)
+ {return a<0 ? fPi + a :a - fPi ;}
+inline double OppositeAngle(double a)
+ {return a<0 ? Pi + a :a - Pi ;}
+ 
+#ifdef DRAWING
+extern Real4  xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet;
+extern R2 GrafPMin,GrafPMax;
+extern Real8 Grafh;
+#endif
+
+Icoor2 inline det(const I2 &a,const I2 & b,const I2 &c)
+{
+  register  Icoor2 bax = b.x - a.x ,bay = b.y - a.y; 
+  register  Icoor2 cax = c.x - a.x ,cay = c.y - a.y; 
+  return  bax*cay - bay*cax;}
+
+
+
+// def de numerotation dans un triangles 
+static const Int2 VerticesOfTriangularEdge[3][2] = {{1,2},{2,0},{0,1}};
+static const Int2 EdgesVertexTriangle[3][2] = {{1,2},{2,0},{0,1}};
+static const Int2 OppositeVertex[3] = {0,1,2};
+static const Int2 OppositeEdge[3] =  {0,1,2};
+static const Int2 NextEdge[3] = {1,2,0};
+static const Int2 PreviousEdge[3] = {2,0,1};
+static const Int2 NextVertex[3] = {1,2,0};
+static const Int2 PreviousVertex[3] = {2,0,1};
+
+Int4 AGoodNumberPrimeWith(Int4 n);
+
+// remark all the angle are in radian beetwen [-Pi,Pi]
+
+
+class Geometry;
+//static Geometry *NULLGeometry=0;
+class Triangles;
+class Triangle;
+class QuadTree;
+class GeometricalEdge;
+class VertexOnGeom;
+class VertexOnEdge;
+/////////////////////////////////////////////////////////////////////////////////////
+const int IsVertexOnGeom = 8;
+const int IsVertexOnVertex = 16;
+const int IsVertexOnEdge = 32;
+/////////////////////////////////////////////////////////////////////////////////////
+#ifndef  NOTFREEFEM
+class ErrorMesh : public Error
+{  
+public:
+    Triangles *Th;
+    ErrorMesh(const char * Text,int l,Triangles * TTh=0, const char *t2="") :
+	Error(MESH_ERROR,"Meshing error: ",Text,"\n number : ",l,", ",t2),Th(TTh)  {}
+};
+#endif
+
+class Direction { //   
+  private:
+  Icoor1 dir;
+  public:
+  Direction(): dir(MaxICoor){}; //  no direction set
+  Direction(Icoor1 i,Icoor1 j) { Icoor2  n2 = 2*(Abs(i)+Abs(j));  
+                                 Icoor2 r = MaxICoor* (Icoor2) i;
+                                 Icoor1 r1 = (Icoor1) (2*(r/ n2)); // odd number 
+                                 dir = (j>0) ? r1 : r1+1; //  odd -> j>0 even -> j<0
+                               }
+  int sens(    Icoor1 i,Icoor1 j) { int r =1; 
+                                   if (dir!= MaxICoor) {
+                                     Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1);
+                                     r = (x*i + y*j) >=0;}
+                                   return r;}
+#ifdef DRAWING
+ void  Draw() {
+                         if (dir!= MaxICoor) {
+                                     Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1);
+                                     R2 D(x,y);
+                                     double eps = Grafh/Norme2(D)/20;
+                                     D = D*eps;
+                                     rmoveto(D.x,D.y);
+                                    }
+  }
+#endif                                   
+                                   
+      
+                              
+  
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class Vertex {public:
+  I2 i;  // allow to use i.x, and i.y in long int (beware of scale and centering)
+  R2 r;  // allow to use r.x, and r.y in double
+  Metric m;
+  Int4 ReferenceNumber;
+  Direction DirOfSearch;
+  union {
+    Triangle * t; // one triangle which contained  the vertex
+    Int4 color;
+    Vertex * to;// use in geometry Vertex to now the Mesh Vertex associed 
+    VertexOnGeom * on;     // if vint 8; // set with Triangles::SetVertexFieldOn()
+    Vertex * onbv; // if vint == 16 on Background vertex Triangles::SetVertexFieldOnBTh()
+    VertexOnEdge * onbe;   // if vint == 32 on Background edge
+  };
+  Int1 vint;  // the vertex number in triangle; varies between 0 and 2 in t
+  operator  I2   () const {return i;} // operator de cast 
+  operator  const R2 & () const {return r;}// operator de cast 
+//  operator  R2 & () {return r;}// operator de cast 
+  Real8 operator()(R2 x) const { return m(x);}
+  operator Metric () const {return m;}// operator de cast 
+  Int4  Optim(int  = 1,int =0); 
+  //  Vertex(){}
+  //  ~Vertex(){}
+  Real8  Smoothing(Triangles & ,const Triangles & ,Triangle  * & ,Real8 =1);
+  int ref() const { return ReferenceNumber;}
+
+  friend std::ostream& operator <<(std::ostream& f, const  Vertex & v)
+  {f << "(" << v.i  << "," << v.r << MatVVP2x2(v.m) << ")" ;   return f;}
+  inline void Set(const Vertex & rec,const Triangles &,Triangles &);
+  
+#ifdef DRAWING
+  void  Draw(Int4 =-1) const ;
+  void MoveTo() const  {    rmoveto(r.x,r.y);  }
+  void LineTo() const {    rlineto(r.x,r.y);  }
+#endif  
+};
+
+double QuadQuality(const Vertex &,const Vertex &,const Vertex &,const Vertex &);
+
+// extern Vertex *Meshend , *Meshbegin;
+
+/////////////////////////////////////////////////////////////////////////////////////
+class TriangleAdjacent {
+  friend std::ostream& operator <<(std::ostream& f, const  TriangleAdjacent & ta)
+  {f << "{" << ta.t << "," << ((int) ta.a) << "}" ;
+   return f;}
+
+public:
+  Triangle * t; // le triangle 
+  int  a; // le numero de l arete
+  
+  TriangleAdjacent(Triangle  * tt,int  aa): t(tt),a(aa &3) {};
+  TriangleAdjacent() {};
+  
+  operator Triangle * () const {return t;}
+  operator Triangle & () const {return *t;}
+    operator int() const {return a;}
+  TriangleAdjacent & operator++() 
+  {
+    a= NextEdge[a];
+    return *this;}
+  TriangleAdjacent operator--()
+  { 
+    a= PreviousEdge[a];
+    return *this;}
+  inline  TriangleAdjacent  Adj() const ;
+  int swap();
+  inline void SetAdj2(const TriangleAdjacent& , int =0);
+  inline Vertex *  EdgeVertex(const int &) const ;
+  inline Vertex *  OppositeVertex() const ;
+  inline Icoor2 & det() const;
+  inline int Locked() const  ;
+  inline int GetAllFlag_UnSwap() const ;
+  inline void SetLock();
+  inline int MarkUnSwap()  const;
+  inline void SetMarkUnSwap();
+  inline void SetCracked();
+  inline int Cracked() const ;
+};// end of Vertex class  
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+class Edge { public:
+   Vertex * v[2];
+   Int4 ref;
+    GeometricalEdge * on;
+   Vertex & operator[](int i){return *v[i];};
+   Vertex * operator()(int i){return v[i];};
+
+  void ReNumbering(Vertex *vb,Vertex *ve, Int4 *renu) 
+   {
+    if (v[0] >=vb && v[0] <ve) v[0] = vb + renu[v[0]-vb];
+    if (v[1] >=vb && v[1] <ve) v[1] = vb + renu[v[1]-vb];
+   }
+
+  const Vertex & operator[](int i) const { return *v[i];};
+  R2 operator()(double t) const; // return the point 
+  //                                on the curve edge a t in [0:1]
+  Edge * adj[2]; // the 2 adj edges if on the same curve 
+  int Intersection(const  Edge & e) const { 
+    if (!(adj[0]==&e || adj[1]==&e)) 
+      std::cerr << "Bug : Intersection " << (void*) &e <<  "  " 
+	   << adj[0] << " " <<  adj[1] << std::endl;
+    assert(adj[0]==&e || adj[1]==&e);
+    return adj[0]==&e ? 0 : 1;}
+  Real8 MetricLength() const ;  
+  inline void Set(const Triangles &,Int4,Triangles &);
+  
+#ifdef DRAWING
+  void  Draw(Int4 = -1) const ;
+#endif
+}; // end of Edge class 
+
+/////////////////////////////////////////////////////////////////////////////////////
+class GeometricalVertex :public Vertex {
+  int cas;
+  friend class Geometry;
+  GeometricalVertex * link; //  link all the same GeometricalVertex circular (Crack) 
+public:
+  int Corner() const {return cas&4;}
+  int Required()const {return cas&6;}// a corner is required
+  void  SetCorner(){ cas |= 4;}
+  void  SetRequired(){ cas |= 2;}
+  void  Set(){cas=0;}
+  GeometricalVertex() :cas(0), link(this) {};
+  GeometricalVertex * The() { assert(link); return link;}// return a unique vertices
+  int IsThe() const { return link == this;}  
+  
+inline void Set(const GeometricalVertex & rec,const Geometry & Gh ,const Geometry & GhNew);
+  inline friend std::ostream& operator <<(std::ostream& f, const  GeometricalVertex & s) 
+     { f << s.r << "," << s.cas << ".";return f; }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+class GeometricalEdge {
+  public:
+   GeometricalVertex * v[2];
+   Int4 ref;
+   Int4  CurveNumber;
+  R2 tg[2]; // the 2 tangente 
+  //   if tg[0] =0 => no continuite 
+  GeometricalEdge * Adj [2]; 
+  int SensAdj[2];
+//  private:
+  int flag ;
+  public: 
+  GeometricalEdge * link; // if   Cracked() or Equi()
+
+// end of data 
+  
+  GeometricalVertex & operator[](int i){return *v[i];};
+  const GeometricalVertex & operator[](int i) const { return *v[i];};
+  GeometricalVertex * operator()(int i){return v[i];};  
+ // inline void Set(const Geometry &,Int4,Geometry &);
+
+  R2 F(Real8 theta) const ; // parametrization of the curve edge
+  Real8 R1tg(Real8 theta,R2 &t) const ; // 1/radius of curvature + tangente
+  int Cracked() const {return flag & 1;}
+  int Dup() const { return flag & 32;}
+  int Equi()const {return flag & 2;}
+  int ReverseEqui()const {return flag & 128;}
+  int TgA()const {return flag &4;}
+  int TgB()const {return flag &8;}
+  int Tg(int i) const{return i==0 ? TgA() : TgB();}
+  int Mark()const {return flag &16;}
+  int Required() { return flag & 64;}
+  void SetCracked() { flag |= 1;}
+  void SetDup()     { flag |= 32;} // not a real edge 
+  void SetEqui()    { flag |= 2;}
+  void SetTgA()     { flag|=4;}
+  void SetTgB()     { flag|=8;}
+  void SetMark()    { flag|=16;}
+  void SetUnMark()  { flag &= 1007 /* 1023-16*/;}
+  void SetRequired() { flag |= 64;}
+  void SetReverseEqui() {flag |= 128;}
+  
+  inline void Set(const GeometricalEdge & rec,const Geometry & Th ,Geometry & ThNew);
+
+#ifdef DRAWING 
+  void Draw(Int4  =-1);
+#endif
+  
+};
+  
+class Curve {public:
+ GeometricalEdge * be,*ee; // begin et end edge
+ int kb,ke;  //  begin vetex and end vertex
+ Curve *next; // next curve equi to this
+ bool master; // true => of equi curve point on this curve  
+ inline void Set(const Curve & rec,const Geometry & Th ,Geometry & ThNew);
+ Curve() : be(0),ee(0),kb(0),ke(0),next(0),master(true) {} 
+ void Reverse() { Exchange(be,ee); Exchange(kb,ke);} //  revese the sens of the curse 
+};
+  
+   
+
+/////////////////////////////////////////////////////////////////////////////////////
+class Triangle {
+  friend class TriangleAdjacent;
+  friend std::ostream& operator <<(std::ostream& f, const  Triangle & ta);
+
+
+  private: // les arete sont opposes a un sommet
+  Vertex * ns [3]; // 3 vertices if t is triangle, t[i] allowed by access function, (*t)[i] if pointer
+  Triangle * at [3]; // nu triangle adjacent  
+  Int1  aa[3];  // les nu des arete dans le triangles (mod 4)
+  public: 
+  Icoor2 det; // determinant du triangle (2 fois l aire des vertices entieres)
+  union { 
+    Triangle * link ;
+    Int4 color;
+  };
+  void SetDet() {
+    if(ns[0] && ns[1] && ns[2])    det = bamg::det(*ns[0],*ns[1],*ns[2]);
+    else det = -1; }
+  Triangle() {}
+  Triangle(Triangles *Th,Int4 i,Int4 j,Int4 k);
+  Triangle(Vertex *v0,Vertex *v1,Vertex *v2);
+  inline void Set(const Triangle &,const Triangles &,Triangles &);
+  inline int In(Vertex *v) const { return ns[0]==v || ns[1]==v || ns[2]==v ;}
+  TriangleAdjacent FindBoundaryEdge(int ) const;
+
+  void ReNumbering(Triangle *tb,Triangle *te, Int4 *renu) 
+   {
+    if (link  >=tb && link  <te) link  = tb + renu[link -tb];
+    if (at[0] >=tb && at[0] <te) at[0] = tb + renu[at[0]-tb];
+    if (at[1] >=tb && at[1] <te) at[1] = tb + renu[at[1]-tb];
+    if (at[2] >=tb && at[2] <te) at[2] = tb + renu[at[2]-tb];    
+   }
+  void ReNumbering(Vertex *vb,Vertex *ve, Int4 *renu) 
+   {
+    if (ns[0] >=vb && ns[0] <ve) ns[0] = vb + renu[ns[0]-vb];
+    if (ns[1] >=vb && ns[1] <ve) ns[1] = vb + renu[ns[1]-vb];
+    if (ns[2] >=vb && ns[2] <ve) ns[2] = vb + renu[ns[2]-vb];    
+   }
+
+
+  const Vertex & operator[](int i) const {return *ns[i];};
+  Vertex & operator[](int i)  {return *ns[i];};
+  
+  const Vertex  *  operator()(int i) const {return ns[i];};
+  Vertex  * & operator()(int i)  {return ns[i];};
+  
+  TriangleAdjacent Adj(int  i) const  // triangle adjacent + arete 
+  { return TriangleAdjacent(at[i],aa[i]&3);};
+
+  Triangle * TriangleAdj(int  i) const 
+  {return at[i&3];} // triangle adjacent + arete 
+  Int1  NuEdgeTriangleAdj(int  i) const 
+  {return aa[i&3]&3;} // Number of the  adjacent edge in adj tria  
+
+  inline Real4 qualite() ;
+  
+
+  void SetAdjAdj(Int1 a) 
+  { a &= 3;
+   register  Triangle *tt=at[a];
+   aa [a] &= 55; // remove MarkUnSwap
+   register Int1 aatt = aa[a] & 3;
+   if(tt){ 
+     tt->at[aatt]=this;
+     tt->aa[aatt]=a + (aa[a] & 60 ) ;}// Copy all the mark 
+  }
+  
+  void SetAdj2(Int1 a,Triangle *t,Int1 aat)
+    {  at[a]=t;aa[a]=aat;
+    if(t) {t->at[aat]=this;t->aa[aat]=a;}
+    }
+    
+  void SetTriangleContainingTheVertex()
+   { 
+     if (ns[0]) (ns[0]->t=this,ns[0]->vint=0);
+     if (ns[1]) (ns[1]->t=this,ns[1]->vint=1);
+     if (ns[2]) (ns[2]->t=this,ns[2]->vint=2);
+   }
+   
+  int swap(Int2 a1,int=0);
+  Int4  Optim(Int2 a,int =0);
+
+  int  Locked(int a)const { return aa[a]&4;} 
+  int  Hidden(int a)const { return aa[a]&16;} 
+  int  Cracked(int a) const { return aa[a] & 32;}
+  // for optimisation 
+  int  GetAllflag(int a){return aa[a] & 1020;}
+  void SetAllFlag(int a,int f){aa[a] = (aa[a] &3) + (1020 & f);}
+
+  void SetHidden(int a){
+   register Triangle * t = at[a];
+    if(t) t->aa[aa[a] & 3] |=16;
+    aa[a] |= 16;}
+  void SetCracked(int a){
+   register Triangle * t = at[a];
+    if(t) t->aa[aa[a] & 3] |=32;
+    aa[a] |= 32;}
+  
+  double   QualityQuad(int a,int option=1) const;
+  Triangle * Quadrangle(Vertex * & v0,Vertex * & v1,Vertex * & v2,Vertex * & v3) const ;
+
+  void SetLocked(int a){
+    register Triangle * t = at[a];
+    t->aa[aa[a] & 3] |=4;
+    aa[a] |= 4;}
+
+  void SetMarkUnSwap(int a){
+    register Triangle * t = at[a];
+    t->aa[aa[a] & 3] |=8;
+    aa[a] |=8 ;}
+
+
+  void SetUnMarkUnSwap(int a){ 
+    register Triangle * t = at[a];
+    t->aa[aa[a] & 3] &=55; // 23 + 32 
+    aa[a] &=55 ;}
+  
+
+ 
+#ifdef DEBUG       
+  void inline checka(Int1 a); 
+  void inline check();
+#endif
+
+#ifdef DRAWING
+  void  Draw(Int4 i=-1) const;
+  int swapDRAW(Int2 a1);
+
+#endif
+
+};  // end of Triangle class 
+
+
+
+
+class ListofIntersectionTriangles {
+/////////////////////////////////////////////////////////////////////////////////////
+class IntersectionTriangles {
+public: 
+  Triangle *t;
+  Real8  bary[3];  // use if t != 0
+  R2 x;
+  Metric m;
+  Real8 s;// abscisse curviline
+  Real8 sp; // len of the previous seg in m
+  Real8 sn;// len of the  next seg in m
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class SegInterpolation {
+ public:
+  GeometricalEdge * e;
+  Real8 sBegin,sEnd; // abscisse of the seg on edge parameter
+  Real8 lBegin,lEnd; // length abscisse  set in ListofIntersectionTriangles::Length
+  int last;// last index  in ListofIntersectionTriangles for this Sub seg of edge
+  R2 F(Real8 s){ 
+    Real8 c01=lEnd-lBegin, c0=(lEnd-s)/c01, c1=(s-lBegin)/c01;
+    assert(lBegin<= s && s <=lEnd);
+    return e->F(sBegin*c0+sEnd*c1);}
+};
+ 
+ int MaxSize; // 
+ int Size; //
+ Real8 len; //
+ int state;
+ IntersectionTriangles * lIntTria;
+ int NbSeg;
+ int MaxNbSeg;
+ SegInterpolation * lSegsI;
+ public:
+ IntersectionTriangles & operator[](int i) {return lIntTria[i];}
+ operator int&() {return Size;}
+ ListofIntersectionTriangles(int n=256,int m=16)
+   :   MaxSize(n), Size(0), len(-1),state(-1),lIntTria(new IntersectionTriangles[n]) ,
+    NbSeg(0), MaxNbSeg(m), lSegsI(new SegInterpolation[m])  
+  {
+	  long int verbosity=0;
+
+	  if (verbosity>9) 
+    std::cout << "      construct ListofIntersectionTriangles"
+			  << MaxSize << " " <<  MaxNbSeg<< std::endl;};
+  ~ListofIntersectionTriangles(){
+    if (lIntTria) delete [] lIntTria,lIntTria=0;
+    if (lSegsI) delete [] lSegsI,lSegsI=0;} 
+  void init(){state=0;len=0;Size=0;}
+  
+  int NewItem(Triangle * tt,Real8 d0,Real8 d1,Real8 d2);
+  int NewItem(R2,const Metric & );
+  void NewSubSeg(GeometricalEdge *e,Real8 s0,Real8 s1) 
+    { 
+		long int verbosity=0;
+
+      if (NbSeg>=MaxNbSeg) {
+           int mneo= MaxNbSeg;
+           MaxNbSeg *= 2;
+          if (verbosity>3) 
+	    std::cout <<" reshape lSegsI from " << mneo << " to " 
+		 << MaxNbSeg <<std::endl;
+           SegInterpolation * lEn =  new SegInterpolation[MaxNbSeg];
+           assert(lSegsI && NbSeg < MaxNbSeg);
+           for (int i=0;i< NbSeg;i++) 
+              lEn[i] = lSegsI[MaxNbSeg]; // copy old to new            
+           delete []  lSegsI; // remove old
+           lSegsI = lEn;        
+           }
+       if (NbSeg) 
+         lSegsI[NbSeg-1].last=Size;
+       lSegsI[NbSeg].e=e;
+       lSegsI[NbSeg].sBegin=s0;
+       lSegsI[NbSeg].sEnd=s1;     
+       NbSeg++;           
+    }
+    
+//  void CopyMetric(int i,int j){ lIntTria[j].m=lIntTria[i].m;}
+//  void CopyMetric(const Metric & mm,int j){ lIntTria[j].m=mm;}
+
+  void ReShape() { 
+    register int newsize = MaxSize*2;
+    IntersectionTriangles * nw = new IntersectionTriangles[newsize];
+    assert(nw);
+    for (int i=0;i<MaxSize;i++) // recopy
+      nw[i] = lIntTria[i];       
+    long int verbosity=0;
+	if(verbosity>3)
+      std::cout << " ListofIntersectionTriangles  ReShape MaxSize " 
+	   << MaxSize << " -> " 
+	 <<  newsize << std::endl;
+    MaxSize = newsize; 
+    delete [] lIntTria;// remove old
+    lIntTria = nw; // copy pointer
+  }
+  
+  void SplitEdge(const Triangles & ,const R2 &,const R2  &,int nbegin=0); 
+  Real8 Length(); 
+  Int4 NewPoints(Vertex *,Int4 & nbv,Int4 nbvx);
+};
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+class GeometricalSubDomain {
+public:
+  GeometricalEdge *edge;
+  int sens; // -1 or 1
+  Int4 ref;
+  inline void Set(const GeometricalSubDomain &,const Geometry & ,const Geometry &);
+  
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class SubDomain {
+public:
+  Triangle * head;
+  Int4  ref;  
+  int sens; // -1 or 1
+  Edge * edge; // to  geometrical 	
+  inline void Set(const Triangles &,Int4,Triangles &);
+  	 
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class VertexOnGeom {  public:
+
+  Vertex * mv;
+  Real8 abscisse;  
+  union{ 
+    GeometricalVertex * gv; // if abscisse <0; 
+    GeometricalEdge * ge;  // if abscisse in [0..1]
+  };
+  inline void Set(const VertexOnGeom&,const Triangles &,Triangles &);  
+  int OnGeomVertex()const {return this? abscisse <0 :0;}
+  int OnGeomEdge() const {return this? abscisse >=0 :0;}
+  VertexOnGeom(): mv(0),abscisse(0){gv=0;} 
+  VertexOnGeom(Vertex & m,GeometricalVertex &g) : mv(&m),abscisse(-1){gv=&g;}
+   //  std::cout << "        mv = " <<mv << " gv = "  << gv << std::endl;} 
+  VertexOnGeom(Vertex & m,GeometricalEdge &g,Real8 s) : mv(&m),abscisse(s){ge=&g;}
+    //std::cout << &g << " "  << ge << std::endl; 
+  operator Vertex * () const  {return mv;}
+  operator GeometricalVertex * () const  {return gv;}
+  operator GeometricalEdge * () const  {return ge;}
+//  operator Real8 & () {return abscisse;}
+  operator const Real8 & () const {return abscisse;}
+  int IsRequiredVertex(){ return this? (( abscisse<0 ? (gv?gv->Required():0):0 )) : 0;}
+  void SetOn(){mv->on=this;mv->vint=IsVertexOnGeom;}
+  friend std::ostream& operator <<(std::ostream& f, const  VertexOnGeom & vog){
+    f << vog.abscisse << " " << vog.mv << " " << vog.gv << " ; ";
+    if (vog.abscisse < 0) f << *vog.gv << " ;; " ;
+    //    else f << *vog.ge << " ;; " ;
+    return f;}
+  inline void Set(const Triangles &,Int4,Triangles &);
+    
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class VertexOnVertex {public:
+  Vertex * v, *bv;
+  VertexOnVertex(Vertex * w,Vertex *bw) :v(w),bv(bw){}
+  VertexOnVertex() {};
+  inline void Set(const Triangles &,Int4,Triangles &);
+  void SetOnBTh(){v->onbv=bv;v->vint=IsVertexOnVertex;}
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class VertexOnEdge {public:
+  Vertex * v;
+  Edge * be;
+  Real8 abcisse;
+  VertexOnEdge( Vertex * w, Edge *bw,Real8 s) :v(w),be(bw),abcisse(s) {}
+  VertexOnEdge(){}
+  inline void Set(const Triangles &,Int4,Triangles &);  
+  void SetOnBTh(){v->onbe=this;v->vint=IsVertexOnEdge;}  
+  Vertex & operator[](int i) const { return (*be)[i];}
+  operator Real8 () const { return abcisse;}
+  operator  Vertex *  () const { return v;}  
+  operator  Edge *  () const { return be;}  
+};
+
+ inline TriangleAdjacent FindTriangleAdjacent(Edge &E);
+ inline Vertex * TheVertex(Vertex * a); // for remove crak in mesh 
+/////////////////////////////////////////////////////////////////////////////////////
+ 
+class CrackedEdge { // a small class to store on crack an uncrack information 
+  friend class Triangles;
+  friend std::ostream& operator <<(std::ostream& f, const   Triangles & Th) ;  
+ class CrackedTriangle {
+  friend class Triangles;
+  friend class CrackedEdge;
+  friend std::ostream& operator <<(std::ostream& f, const   Triangles & Th) ;  
+  Triangle * t; // edge of triangle t
+  int i; //  edge number of in triangle
+  Edge *edge; // the  2 edge 
+  Vertex *New[2]; // new vertex number 
+  CrackedTriangle() : t(0),i(0),edge(0) { New[0]=New[1]=0;} 
+  CrackedTriangle(Edge * a) : t(0),i(0),edge(a) { New[0]=New[1]=0;} 
+  void Crack(){ 
+    Triangle & T(*t); 
+    int i0=VerticesOfTriangularEdge[i][0];
+    int i1=VerticesOfTriangularEdge[i][0];
+    assert(New[0] && New[1]);
+    T(i0) = New[0];
+    T(i1) = New[1];}    
+  void UnCrack(){ 
+    Triangle & T(*t); 
+    int i0=VerticesOfTriangularEdge[i][0];
+    int i1=VerticesOfTriangularEdge[i][0];
+    assert(New[0] && New[1]);
+    T(i0) = TheVertex(T(i0));
+    T(i1) = TheVertex(T(i1));} 
+  void Set() {
+     TriangleAdjacent ta ( FindTriangleAdjacent(*edge));
+     t = ta;
+     i = ta;
+     
+     New[0] = ta.EdgeVertex(0);
+     New[1] = ta.EdgeVertex(1);
+     // warning the ref 
+     
+     }    
+     
+  }; // end of class CrackedTriangle
+ public:  
+  CrackedTriangle a,b; 
+  CrackedEdge() :a(),b() {}
+  CrackedEdge(Edge * start, Int4  i,Int4 j) : a(start+i),b(start+j) {};
+  CrackedEdge(Edge * e0, Edge * e1 ) : a(e0),b(e1) {};
+
+  void Crack() { a.Crack(); b.Crack();}
+  void UnCrack() { a.UnCrack(); b.UnCrack();}
+  void Set() { a.Set(), b.Set();}
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+class Triangles {
+public:
+
+  enum TypeFileMesh {
+    AutoMesh=0,BDMesh=1,NOPOMesh=2,amMesh=3,am_fmtMesh=4,amdbaMesh=5,
+    ftqMesh=6,mshMesh=7};
+
+  int static counter; // to kown the number of mesh in memory 
+  int OnDisk;       // true if on disk 
+  Geometry & Gh;   // Geometry
+  Triangles & BTh; // Background Mesh Bth==*this =>no  background 
+  
+  Int4 NbRef; // counter of ref on the this class if 0 we can delete
+  Int4 nbvx,nbtx;  // nombre max  de sommets , de  triangles
+  
+  Int4 nt,nbv,nbt,nbiv,nbe; // nb of legal triangles, nb of vertex, of triangles, 
+  // of initial vertices, of edges with reference,
+  Int4 NbOfQuad; // nb of quadrangle 
+
+  Int4 NbSubDomains; // 
+  Int4 NbOutT; // Nb of oudeside triangle
+  Int4 NbOfTriangleSearchFind;
+  Int4 NbOfSwapTriangle;
+  char * name, *identity;
+  Vertex * vertices;   // data of vertices des sommets
+  
+  Int4 NbVerticesOnGeomVertex;
+  VertexOnGeom * VerticesOnGeomVertex;
+  
+  Int4 NbVerticesOnGeomEdge;
+  VertexOnGeom * VerticesOnGeomEdge;
+
+  Int4 NbVertexOnBThVertex;
+  VertexOnVertex *VertexOnBThVertex;
+
+  Int4 NbVertexOnBThEdge;
+  VertexOnEdge *VertexOnBThEdge;
+
+  
+  Int4 NbCrackedVertices;
+  
+
+  Int4 NbCrackedEdges;
+  CrackedEdge *CrackedEdges;
+  
+  
+  R2 pmin,pmax; // extrema
+  Real8 coefIcoor;  // coef to integer Icoor1;
+
+  Triangle * triangles;
+  Edge * edges; 
+
+  QuadTree *quadtree;
+  Vertex ** ordre;
+  SubDomain * subdomains;
+  ListofIntersectionTriangles  lIntTria;
+// end of variable
+  
+  Triangles(Int4 i);//:BTh(*this),Gh(*new Geometry()){PreInit(i);}
+ 
+
+  ~Triangles(); 
+  Triangles(const char * ,Real8=-1) ;
+  Triangles(double* elements, double* x, double* y, int nel, int nods,int NBV, Real8=-1);
+  
+  Triangles(Int4 nbvx,Triangles & BT,int keepBackVertices=1)
+         :Gh(BT.Gh),BTh(BT) {
+	     try {GeomToTriangles1(nbvx,keepBackVertices);}
+	      catch(...) { this->~Triangles(); throw; } }
+  
+  Triangles(Int4 nbvx,Geometry & G)
+         :Gh(G),BTh(*this){
+	     try { GeomToTriangles0(nbvx);}
+	     catch(...) { this->~Triangles(); throw; } }
+  Triangles(Triangles &,Geometry * pGh=0,Triangles* pBTh=0,Int4 nbvxx=0 ); // COPY OPERATEUR
+  //  Triangles(Triangles &){ std::cerr << " BUG call copy opretor of Triangles" << std::endl;MeshError(111);}
+  Triangles(const Triangles &,const int *flag,const int *bb); // truncature
+  
+  int gibbsv (long int* ptvoi, long int* vois,long int* lvois,long int* w,long int* v);
+  int gibbs(void);
+
+  void SetIntCoor(const char * from =0);
+
+ // void  RandomInit();
+ // void  CubeInit(int ,int);
+  
+  Real8 MinimalHmin() {return 2.0/coefIcoor;}
+  Real8 MaximalHmax() {return Max(pmax.x-pmin.x,pmax.y-pmin.y);}
+  const Vertex & operator[]  (Int4 i) const { return vertices[i];};
+  Vertex & operator[](Int4 i) { return vertices[i];};
+  const Triangle & operator()  (Int4 i) const { return triangles[i];};
+  Triangle & operator()(Int4 i) { return triangles[i];};
+  I2 toI2(const R2 & P) const {
+          return  I2( (Icoor1) (coefIcoor*(P.x-pmin.x))
+	                 ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );}
+  R2 toR2(const I2 & P) const {
+          return  R2( (double) P.x/coefIcoor+pmin.x, (double) P.y/coefIcoor+pmin.y);}
+  void Add( Vertex & s,Triangle * t,Icoor2 *  =0) ;
+  void Insert();
+  //  void InsertOld();
+  void ForceBoundary();
+  void Heap();
+  void FindSubDomain(int );
+  Int4  ConsRefTriangle(Int4 *) const;
+  void ShowHistogram() const;
+  void  ShowRegulaty() const; // Add FH avril 2007 
+//  void ConsLinkTriangle();
+
+  void ReMakeTriangleContainingTheVertex();
+  void UnMarkUnSwapTriangle();
+  void SmoothMetric(Real8 raisonmax) ;
+  void BoundAnisotropy(Real8 anisomax,double hminaniso= 1e-100) ;
+  void MaxSubDivision(Real8 maxsubdiv);
+  void WriteMetric(std::ostream &,int iso) ;
+  Edge** MakeGeometricalEdgeToEdge();
+  void  SetVertexFieldOn();  
+  void  SetVertexFieldOnBTh();
+  Int4 SplitInternalEdgeWithBorderVertices();
+  void MakeQuadrangles(double costheta);
+  int SplitElement(int choice);
+  void MakeQuadTree();
+  void NewPoints( Triangles &,int KeepBackVertex =1 );
+  Int4 InsertNewPoints(Int4 nbvold,Int4 & NbTSwap) ; 
+  void NewPointsOld( Triangles & );
+  void NewPoints(int KeepBackVertex=1){ NewPoints(*this,KeepBackVertex);}
+  void ReNumberingTheTriangleBySubDomain(bool justcompress=false);
+  void ReNumberingVertex(Int4 * renu);
+  void SmoothingVertex(int =3,Real8=0.3);
+  Metric MetricAt (const R2 &) const;
+  GeometricalEdge * ProjectOnCurve( Edge & AB, Vertex &  A, Vertex & B,Real8 theta,
+                      Vertex & R,VertexOnEdge & BR,VertexOnGeom & GR);
+   
+  
+  void WriteElements(std::ostream& f,Int4 * reft ,Int4 nbInT) const;
+
+  
+  Int4 Number(const Triangle & t) const  { return &t - triangles;}
+  Int4 Number(const Triangle * t) const  { return t - triangles;}
+  Int4 Number(const Vertex & t) const  { return &t - vertices;}
+  Int4 Number(const Vertex * t) const  { return t - vertices;}
+  Int4 Number(const Edge & t) const  { return &t - edges;}
+  Int4 Number(const Edge * t) const  { return t - edges;}
+  Int4 Number2(const Triangle * t) const  {
+    //   if(t>= triangles && t < triangles + nbt )
+      return t - triangles;
+      //  else  return t - OutSidesTriangles;
+  }
+  
+  Vertex * NearestVertex(Icoor1 i,Icoor1 j) ;
+  Triangle * FindTriangleContening(const I2 & ,Icoor2 [3],Triangle *tstart=0) const;
+  void Write(const char * filename,const TypeFileMesh type = AutoMesh);
+  void Write_am_fmt(std::ostream &) const ;
+  void Write_am(std::ostream &) const ;
+  void Write_ftq(std::ostream &) const ;
+  void Write_nopo(std::ostream &) const ;
+  void Write_msh(std::ostream &) const ;
+  void Write_amdba(std::ostream &) const ;
+
+  void Read(MeshIstream &,int version,Real8 cutoffradian);
+  void ReadFromMatlabMesh(double* elements,double* x,double* y,int nel,int nods,int inbvx,Real8 cutoffradian);
+  void Read_am_fmt(MeshIstream &);
+  void Read_amdba(MeshIstream &);
+  void Read_am(MeshIstream &);
+  void Read_nopo(MeshIstream &);
+  void Read_ftq(MeshIstream &);
+  void Read_msh(MeshIstream &);
+
+  void ReadMetric(const char * fmetrix,const Real8 hmin,const Real8 hmax,const Real8 coef);
+  void IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols,
+			   const  Real8 hmin,const Real8 hmax, const Real8 coef,
+			   const Real8  anisomax,const Real8 CutOff=1.e-4,const int NbJacobi=1,
+			   const int DoNormalisation=1,
+			   const double power=1.0,
+			   const int choise=0);
+  void IntersectGeomMetric(const Real8 err,const int iso);
+  
+  
+  int  isCracked() const {return NbCrackedVertices != 0;}
+  int  Crack();
+  int UnCrack();
+  
+#ifdef DEBUG
+  void inline Check(); 
+#endif
+#ifdef DRAWING
+  void  Draw() const ;
+  void  InitDraw() const ;
+  void   inquire()  ;
+#endif
+ friend std::ostream& operator <<(std::ostream& f,  const  Triangles & Th); 
+  void  Write(const char * filename);
+  void ConsGeometry(Real8 =-1.0,int *equiedges=0); // construct a geometry if no geo 
+  void FillHoleInMesh() ;
+  int CrackMesh();
+ private:
+  void GeomToTriangles1(Int4 nbvx,int KeepBackVertices=1);// the  real constructor mesh adaption
+  void GeomToTriangles0(Int4 nbvx);// the  real constructor mesh generator
+  void PreInit(Int4,char * =0 );
+  //
+  void Write_nop5(OFortranUnFormattedFile * f,
+			     Int4 &lnop5,Int4 &nef,Int4 &lgpdn,Int4 ndsr) const ;
+
+  
+}; // End Class Triangles
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+class Geometry { 
+public:
+  int OnDisk; 
+  Int4 NbRef; // counter of ref on the this class if 0 we can delete
+
+  char *name;
+  Int4 nbvx,nbtx; // nombre max  de sommets , de  Geometry
+  Int4 nbv,nbt,nbiv,nbe; // nombre de sommets, de Geometry, de sommets initiaux,
+  Int4 NbSubDomains; // 
+  Int4 NbEquiEdges;
+  Int4 NbCrackedEdges; 
+//  Int4 nbtf;//  de triangle frontiere
+  Int4 NbOfCurves;
+  int empty(){return (nbv ==0) && (nbt==0) && (nbe==0) && (NbSubDomains==0); }
+  GeometricalVertex * vertices;   // data of vertices des sommets 
+  Triangle * triangles; 
+  GeometricalEdge * edges;
+  QuadTree *quadtree;
+  GeometricalSubDomain *subdomains;
+  Curve *curves;
+  ~Geometry(); 
+  Geometry(const Geometry & Gh); //Copy  Operator 
+  Geometry(int nbg,const Geometry ** ag); // intersection operator 
+  
+  R2 pmin,pmax; // extrema
+  Real8 coefIcoor;  // coef to integer Icoor1;
+  Real8 MaximalAngleOfCorner;
+  
+//  end of data 
+
+  
+  I2 toI2(const R2 & P) const {
+          return  I2( (Icoor1) (coefIcoor*(P.x-pmin.x))
+	                 ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );}
+  
+  Real8 MinimalHmin() {return 2.0/coefIcoor;}
+  Real8 MaximalHmax() {return Max(pmax.x-pmin.x,pmax.y-pmin.y);}
+  void ReadGeometry(const char * ) ;
+  void ReadGeometry(MeshIstream & ,const char *)  ;
+
+  void EmptyGeometry();
+  Geometry() {EmptyGeometry();}// empty Geometry
+  void AfterRead();
+  Geometry(const char * filename) {EmptyGeometry();OnDisk=1;ReadGeometry(filename);AfterRead();}
+
+  void ReadMetric(const char *,Real8 hmin,Real8 hmax,Real8 coef);
+  const GeometricalVertex & operator[]  (Int4 i) const { return vertices[i];};
+  GeometricalVertex & operator[](Int4 i) { return vertices[i];};
+  const  GeometricalEdge & operator()  (Int4 i) const { return edges[i];};
+  GeometricalEdge & operator()(Int4 i) { return edges[i];}; 
+  Int4 Number(const GeometricalVertex & t) const  { return &t - vertices;}
+  Int4 Number(const GeometricalVertex * t) const  { return t - vertices;}
+  Int4 Number(const GeometricalEdge & t) const  { return &t - edges;}
+  Int4 Number(const GeometricalEdge * t) const  { return t - edges;}
+  Int4 Number(const Curve * c) const  { return c - curves;}
+  
+  void UnMarkEdges() {
+    for (Int4 i=0;i<nbe;i++) edges[i].SetUnMark();}
+
+ GeometricalEdge *  ProjectOnCurve(const Edge & ,Real8,Vertex &,VertexOnGeom &) const ;
+  GeometricalEdge *  Contening(const R2 P,  GeometricalEdge * start) const;
+ friend std::ostream& operator <<(std::ostream& f, const   Geometry & Gh); 
+ void Write(const char * filename);
+ 
+#ifdef DEBUG
+  void inline Check();   
+#endif
+#ifdef DRAWING
+  void  Draw() const ;
+  void  InitDraw() const ;
+#endif
+  
+}; // End Class Geometry
+
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+///////////////////           END CLASS          ////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+
+inline Triangles::Triangles(Int4 i) :Gh(*new Geometry()),BTh(*this){PreInit(i);}
+
+extern Triangles * CurrentTh;
+
+TriangleAdjacent CloseBoundaryEdge(I2 ,Triangle *, double &,double &) ;
+TriangleAdjacent CloseBoundaryEdgeV2(I2 A,Triangle *t, double &a,double &b);
+
+Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a,int & inside);
+
+
+
+inline Triangle *    Triangle::Quadrangle(Vertex * & v0,Vertex * & v1,Vertex * & v2,Vertex * & v3) const
+{
+// return the other triangle of the quad if a quad or 0 if not a quat
+  Triangle * t =0;
+  if (link) {
+    int a=-1;
+    if (aa[0] & 16 ) a=0;
+    if (aa[1] & 16 ) a=1;
+    if (aa[2] & 16 ) a=2;
+    if (a>=0) {
+      t = at[a];
+      //  if (t-this<0) return 0;
+      v2 = ns[VerticesOfTriangularEdge[a][0]];
+      v0 = ns[VerticesOfTriangularEdge[a][1]];
+      v1 = ns[OppositeEdge[a]];
+      v3 = t->ns[OppositeEdge[aa[a]&3]];
+    }
+  }
+  return t;
+}
+
+inline   double   Triangle::QualityQuad(int a,int option) const
+{ // first do the logique part 
+  double q;
+  if (!link || aa[a] &4)
+    q=  -1;
+  else {
+    Triangle * t = at[a];
+    if (t-this<0) q=  -1;// because we do 2 times 
+    else if (!t->link ) q=  -1;
+    else if (aa[0] & 16 || aa[1] & 16  || aa[2] & 16 || t->aa[0] & 16 || t->aa[1] & 16 || t->aa[2] & 16 )
+      q= -1;
+    else if(option) 
+      { 
+	const Vertex & v2 = *ns[VerticesOfTriangularEdge[a][0]];
+	const Vertex & v0 = *ns[VerticesOfTriangularEdge[a][1]];
+	const Vertex & v1 = *ns[OppositeEdge[a]];
+	const Vertex & v3 = * t->ns[OppositeEdge[aa[a]&3]];
+	q =  QuadQuality(v0,v1,v2,v3); // do the float part
+      }
+    else q= 1;
+  }
+  return  q;
+}
+
+
+inline void Vertex::Set(const Vertex & rec,const Triangles & ,Triangles & )
+ { 
+   *this  = rec;
+ }
+inline void GeometricalVertex::Set(const GeometricalVertex & rec,const Geometry & ,const Geometry & )
+ { 
+   *this  = rec;
+ }
+inline void Edge::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+ { 
+   *this = Th.edges[i];
+   v[0] = ThNew.vertices + Th.Number(v[0]);    
+   v[1] = ThNew.vertices + Th.Number(v[1]);
+   if (on) 
+     on =  ThNew.Gh.edges+Th.Gh.Number(on);
+   if (adj[0]) adj[0] =   ThNew.edges +   Th.Number(adj[0]);
+   if (adj[1]) adj[1] =   ThNew.edges +   Th.Number(adj[1]);
+
+ }
+inline void GeometricalEdge::Set(const GeometricalEdge & rec,const Geometry & Gh ,Geometry & GhNew)
+ { 
+   *this = rec;
+   v[0] = GhNew.vertices + Gh.Number(v[0]);    
+   v[1] = GhNew.vertices + Gh.Number(v[1]); 
+   if (Adj[0]) Adj[0] =  GhNew.edges + Gh.Number(Adj[0]);     
+   if (Adj[1]) Adj[1] =  GhNew.edges + Gh.Number(Adj[1]);     
+ }
+ 
+inline void Curve::Set(const Curve & rec,const Geometry & Gh ,Geometry & GhNew)
+{
+  *this = rec;
+   be = GhNew.edges + Gh.Number(be);    
+   ee = GhNew.edges + Gh.Number(ee); 
+   if(next) next= GhNew.curves + Gh.Number(next); 
+}
+
+inline void Triangle::Set(const Triangle & rec,const Triangles & Th ,Triangles & ThNew)
+ { 
+   *this = rec;
+   if ( ns[0] ) ns[0] = ThNew.vertices +  Th.Number(ns[0]);
+   if ( ns[1] ) ns[1] = ThNew.vertices +  Th.Number(ns[1]);
+   if ( ns[2] ) ns[2] = ThNew.vertices +  Th.Number(ns[2]);
+   if(at[0]) at[0] =  ThNew.triangles + Th.Number(at[0]);
+   if(at[1]) at[1] =  ThNew.triangles + Th.Number(at[1]);
+   if(at[2]) at[2] =  ThNew.triangles + Th.Number(at[2]);
+   if (link  >= Th.triangles && link  < Th.triangles + Th.nbt)
+     link = ThNew.triangles + Th.Number(link);
+ }
+inline void VertexOnVertex::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+{ 
+  *this = Th.VertexOnBThVertex[i];  
+  v = ThNew.vertices + Th.Number(v);
+
+}
+inline void SubDomain::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+{
+  *this = Th.subdomains[i];
+  assert( head - Th.triangles >=0 && head - Th.triangles < Th.nbt);
+  head = ThNew.triangles + Th.Number(head) ; 
+  assert(edge - Th.edges >=0 && edge - Th.edges < Th.nbe); 
+  edge = ThNew.edges+ Th.Number(edge);
+}
+ inline void GeometricalSubDomain::Set(const GeometricalSubDomain & rec,const Geometry & Gh ,const Geometry & GhNew)
+{
+   *this = rec;
+   edge = Gh.Number(edge) + GhNew.edges;
+}
+inline void VertexOnEdge::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+{
+  *this = Th.VertexOnBThEdge[i];  
+  v = ThNew.vertices + Th.Number(v);
+}
+
+inline void VertexOnGeom::Set(const VertexOnGeom & rec,const Triangles & Th ,Triangles & ThNew)
+{
+  *this = rec;  
+  mv = ThNew.vertices + Th.Number(mv);
+  if (gv)
+    if (abscisse < 0 )
+      gv = ThNew.Gh.vertices + Th.Gh.Number(gv);
+    else
+      ge = ThNew.Gh.edges + Th.Gh.Number(ge);
+  
+}
+inline Real8 Edge::MetricLength() const
+  { 
+    return LengthInterpole(v[0]->m,v[1]->m,v[1]->r - v[0]->r) ;
+  }
+
+inline  void  Triangles::ReMakeTriangleContainingTheVertex()
+ {
+  register Int4 i;
+  for ( i=0;i<nbv;i++) 
+    {
+	vertices[i].vint = 0;
+	vertices[i].t=0;
+    }
+  for ( i=0;i<nbt;i++) 
+    triangles[i].SetTriangleContainingTheVertex();
+ }
+
+inline  void  Triangles::UnMarkUnSwapTriangle()
+ {
+  register Int4 i;
+  for ( i=0;i<nbt;i++) 
+    for(int  j=0;j<3;j++)
+      triangles[i].SetUnMarkUnSwap(j);
+ }
+
+inline  void   Triangles::SetVertexFieldOn()
+  {
+    for (Int4 i=0;i<nbv;i++) 
+       vertices[i].on=0;
+    for (Int4 j=0;j<NbVerticesOnGeomVertex;j++ ) 
+       VerticesOnGeomVertex[j].SetOn();
+    for (Int4 k=0;k<NbVerticesOnGeomEdge;k++ ) 
+       VerticesOnGeomEdge[k].SetOn();
+    }	       
+inline  void   Triangles::SetVertexFieldOnBTh()
+  {
+    for (Int4 i=0;i<nbv;i++) 
+       vertices[i].on=0;
+    for (Int4 j=0;j<NbVertexOnBThVertex;j++ ) 
+       VertexOnBThVertex[j].SetOnBTh();
+    for (Int4 k=0;k<NbVertexOnBThEdge;k++ ) 
+       VertexOnBThEdge[k].SetOnBTh();
+       
+    }	       
+
+inline  void  TriangleAdjacent::SetAdj2(const TriangleAdjacent & ta, int l  )
+{ // set du triangle adjacent 
+  if(t) {
+    t->at[a]=ta.t;
+    t->aa[a]=ta.a|l;}
+  if(ta.t) {
+    ta.t->at[ta.a] = t ;
+    ta.t->aa[ta.a] = a| l ;
+  }
+}
+
+
+inline int  TriangleAdjacent::Locked() const
+{ return t->aa[a] &4;}
+inline int  TriangleAdjacent::Cracked() const
+{ return t->aa[a] &32;}
+inline int  TriangleAdjacent::GetAllFlag_UnSwap() const
+{ return t->aa[a] & 1012;} // take all flag except MarkUnSwap
+
+inline int  TriangleAdjacent::MarkUnSwap() const
+{ return t->aa[a] &8;}
+
+inline void  TriangleAdjacent::SetLock(){ t->SetLocked(a);}
+
+inline void  TriangleAdjacent::SetCracked() { t->SetCracked(a);}
+
+inline  TriangleAdjacent TriangleAdjacent::Adj() const
+{ return  t->Adj(a);}
+
+inline Vertex  * TriangleAdjacent::EdgeVertex(const int & i) const
+ {return t->ns[VerticesOfTriangularEdge[a][i]]; }
+inline Vertex  * TriangleAdjacent::OppositeVertex() const
+{return t->ns[bamg::OppositeVertex[a]]; }
+inline Icoor2 &  TriangleAdjacent::det() const
+{ return t->det;}
+inline  TriangleAdjacent Adj(const TriangleAdjacent & a)
+{ return  a.Adj();}
+
+inline TriangleAdjacent Next(const TriangleAdjacent & ta) 
+{ return TriangleAdjacent(ta.t,NextEdge[ta.a]);}
+
+inline TriangleAdjacent Previous(const TriangleAdjacent & ta) 
+{ return TriangleAdjacent(ta.t,PreviousEdge[ta.a]);}
+ 
+inline void Adj(GeometricalEdge * & on,int &i) 
+  {int j=i;i=on->SensAdj[i];on=on->Adj[j];}
+  
+inline Real4 qualite(const Vertex &va,const Vertex &vb,const Vertex &vc)
+{
+  Real4 ret; 
+  I2 ia=va,ib=vb,ic=vc;
+  I2 ab=ib-ia,bc=ic-ib,ac=ic-ia;
+  Icoor2 deta=Det(ab,ac);
+  if (deta <=0) ret = -1;
+   else {
+     Real8 a = sqrt((Real8) (ac,ac)),
+       b = sqrt((Real8) (bc,bc)),
+       c = sqrt((Real8) (ab,ab)),
+       p = a+b+c;
+     Real8 h= Max(Max(a,b),c),ro=deta/p;
+   ret = ro/h;}
+  return ret;
+}
+
+
+inline  Triangle::Triangle(Triangles *Th,Int4 i,Int4 j,Int4 k) {
+  Vertex *v=Th->vertices;
+  Int4 nbv = Th->nbv;
+  assert(i >=0 && j >=0 && k >=0);
+  assert(i < nbv && j < nbv && k < nbv);
+  ns[0]=v+i;
+  ns[1]=v+j;
+  ns[2]=v+k;
+  at[0]=at[1]=at[2]=0;
+  aa[0]=aa[1]=aa[2]=0;
+  det=0;
+}
+
+inline  Triangle::Triangle(Vertex *v0,Vertex *v1,Vertex *v2){
+  ns[0]=v0;
+  ns[1]=v1;
+  ns[2]=v2;
+  at[0]=at[1]=at[2]=0;
+  aa[0]=aa[1]=aa[2]=0;
+  if (v0) det=0;
+  else {
+    det=-1;
+    link=NULL;};  
+}
+
+inline    Real4 Triangle::qualite()
+{
+  return det < 0 ? -1 :  bamg::qualite(*ns[0],*ns[1],*ns[2]);
+}
+
+Int4 inline  Vertex::Optim(int i,int koption)
+{ 
+  Int4 ret=0;
+  if ( t && (vint >= 0 ) && (vint <3) )
+    {
+      ret = t->Optim(vint,koption);
+      if(!i) 
+	{
+	  t =0; // for no future optime 
+	  vint= 0; }
+    }
+  return ret;
+}
+
+Icoor2 inline det(const Vertex & a,const Vertex & b,const Vertex & c)
+{
+  register  Icoor2 bax = b.i.x - a.i.x ,bay = b.i.y - a.i.y; 
+  register  Icoor2 cax = c.i.x - a.i.x ,cay = c.i.y - a.i.y; 
+  return  bax*cay - bay*cax;}
+
+
+void  swap(Triangle *t1,Int1 a1,
+	   Triangle *t2,Int1 a2,
+	   Vertex *s1,Vertex *s2,Icoor2 det1,Icoor2 det2);
+
+
+
+int inline TriangleAdjacent::swap()
+{ return  t->swap(a);}
+
+
+
+int SwapForForcingEdge(Vertex   *  & pva ,Vertex  * &   pvb ,
+		       TriangleAdjacent & tt1,Icoor2 & dets1,
+		       Icoor2 & detsa,Icoor2 & detsb, int & nbswap);
+
+int ForceEdge(Vertex &a, Vertex & b,TriangleAdjacent & taret) ;
+
+// inline bofbof   FH 
+inline  TriangleAdjacent FindTriangleAdjacent(Edge &E)
+  {
+    Vertex * a = E.v[0];
+    Vertex * b = E.v[1];
+    
+    Triangle * t = a->t;
+    int i = a->vint;
+    TriangleAdjacent ta(t,EdgesVertexTriangle[i][0]); // Previous edge
+    assert(t && i>=0 && i < 3);
+    assert( a == (*t)(i));
+    int k=0;
+    do { // turn around vertex in direct sens (trigo)
+      k++;assert(k< 20000);
+      //  in no crack => ta.EdgeVertex(1) == a otherwise ??? 
+      if (ta.EdgeVertex(1) ==  a && ta.EdgeVertex(0) ==  b) return ta; // find 
+      ta = ta.Adj();
+      if (ta.EdgeVertex(0) ==  a && ta.EdgeVertex(1) ==  b) return ta; // find 
+      --ta;
+      } while (t != (Triangle *)ta);
+    assert(0);
+    return TriangleAdjacent(0,0);// error 
+  }
+  
+inline Vertex * TheVertex(Vertex * a) // give a unique vertex with smallest number
+{ // in case on crack in mesh 
+    Vertex * r(a), *rr;
+    Triangle * t = a->t;
+    int i = a->vint;
+    TriangleAdjacent ta(t,EdgesVertexTriangle[i][0]); // Previous edge
+    assert(t && i>=0 && i < 3);
+    assert( a == (*t)(i));
+    int k=0;
+    do { // turn around vertex in direct sens (trigo)
+      k++;assert(k< 20000);
+      //  in no crack => ta.EdgeVertex(1) == a
+      if ((rr=ta.EdgeVertex(0)) < r) r = rr;
+      ta = ta.Adj();
+      if ((rr=ta.EdgeVertex(1)) < r) r =rr;
+      --ta;
+     } while (t != (Triangle*) ta);  
+    return r;
+}
+
+inline double CPUtime(){
+#ifdef SYSTIMES
+  struct tms buf;
+  if (times(&buf)!=-1)
+    return ((double)buf.tms_utime+(double)buf.tms_stime)/(long) sysconf(_SC_CLK_TCK);
+  else
+#endif
+    return ((double) clock())/CLOCKS_PER_SEC;
+}
+
+#ifdef DEBUG
+void inline Triangle::checka(Int1 a) {
+  // verif de la coherence des adjacences de l arete a
+  a = a%4;
+  assert(a < 3 && a >= 0 );
+  Triangle *t1=this,*t2=at[a];
+  Int2 a1=a,a2=aa[a]%4;
+  
+  assert(a2 < 3 && a2 >= 0 );
+  if (t2 && ( ((*t1).ns[VerticesOfTriangularEdge[a1][0]] != (*t2).ns[VerticesOfTriangularEdge[a2][1]])
+	      || ((*t1).ns[VerticesOfTriangularEdge[a1][1]] != (*t2).ns[VerticesOfTriangularEdge[a2][0]])))
+    {
+      if (CurrentTh) std::cerr << " In Triangles beetween Triangle " << CurrentTh->Number(t1) << " and " 
+		     <<  CurrentTh->Number(t2) <<  std::endl;
+      std::cerr << "---- t1="<< t1 << " " << a1 <<",  t2="<< t2 << " " << a2 << std::endl;
+      std::cerr <<"t1="<< t1 << " " << a1 << " " << t1->ns[VerticesOfTriangularEdge[a1][0]] 
+	   << " " << t1->ns[VerticesOfTriangularEdge[a1][1]] <<std::endl;
+      if (CurrentTh)
+	std::cerr <<"t1="<< t1 << " " << a1 << " " << CurrentTh->Number(t1->ns[VerticesOfTriangularEdge[a1][0]])
+	   << " " << CurrentTh->Number(t1->ns[VerticesOfTriangularEdge[a1][1]]) <<std::endl;
+      if (t2) std::cerr <<"t2="<< t2 << " " << a2 << " " 
+		   <<  t2->ns[VerticesOfTriangularEdge[a2][0]] 
+		   << " " << t2->ns[VerticesOfTriangularEdge[a2][1]] <<std::endl;
+      if (t2 &&CurrentTh)
+	std::cerr <<"t2="<< t2 << " " << a2 << " " 
+	     <<  CurrentTh->Number(t2->ns[VerticesOfTriangularEdge[a2][0]])
+	     << " " << CurrentTh->Number(t2->ns[VerticesOfTriangularEdge[a2][1]]) <<std::endl;
+      assert(0); 
+    } 
+  if (t2)   assert(t1->aa[a1]/4 == t2->aa[a2]/4); // lock compatibite
+}
+
+
+void inline  Triangle::check() {
+  Icoor2 det2=0;
+  //  std::cout << " check " << this << std::endl;
+  int  infv=ns[0] ?  ((  ns[1] ? ( ns[2] ? -1 : 2) : 1  )) : 0;
+  if (det<0) {
+      if (infv<0 )
+	{  if (CurrentTh) std::cerr << " In Triangles " << CurrentTh->Number(this) << std::endl;
+	std::cerr << " det = " <<  det << " and " << infv << std::endl;
+	MeshError(5);
+	}}
+  else  if (infv>=0 )
+ 	{  if (CurrentTh) std::cerr << " In Triangles " << CurrentTh->Number(this) << std::endl;
+	std::cerr << " det = " << det << " and " << infv << std::endl;
+	MeshError(5);
+	}  
+  
+  if (det >=0) 
+    if( det != (det2=bamg::det(*ns[0],*ns[1],*ns[2])))
+	{ // penthickness(4);Draw();
+	  if (CurrentTh) std::cerr << " In Triangles" << CurrentTh->Number(this) 
+			 << std::endl;
+      std::cerr << *ns[0] << *ns[1] << " " << *ns[2]  << " " << std::endl;
+	   std::cerr << " Bug in triangle " << this 
+		<< ":" << det << " !=  " << det2 << std::endl;
+	   MeshError(5);
+	}
+  checka(0);
+  checka(1);
+  checka(2);
+//  if (ns[0]) assert( ns[0] - Meshbegin  >= 0 );
+//  if (ns[0]) assert( Meshend  - ns[0] >= 0 );
+//  if (ns[1]) assert( ns[1] - Meshbegin  >= 0 );
+//  if (ns[1]) assert( Meshend  - ns[1] >= 0 );
+//  if (ns[2]) assert( ns[2] - Meshbegin  >= 0 );
+//  if (ns[2]) assert( Meshend  - ns[2] >= 0 );
+  assert(ns[0] != ns[2]);
+  assert(ns[1] != ns[2]);
+  assert(ns[0] != ns[1]);
+}
+
+
+#endif
+
+
+
+
+#ifdef DRAWING 
+extern Real4 xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet; // R2 -> I2 transform
+extern R2 Gpmin,Gpmax;
+//extern Real8 Gh;
+// cf routine ILineTo IMoveto
+
+extern void  IMoveTo(long i,long j);
+extern void  ILineTo(long i,long j);
+extern char Getxyc(long &i,long &j);
+extern void Draw(float ,float );
+extern void Draw(long ,long );
+extern void DrawMark(R2 r);
+//inline void DrawMark(D2 r) {DrawMark(R2(r.x,r.y));}
+inline void Move(I2 x) {IMoveTo(x.x,x.y);}
+inline void Move(R2 x) {rmoveto(x.x,x.y);}
+//inline void Move(D2 x) {rmoveto(x.x,x.y);}
+inline void Line(I2 x){ILineTo(x.x,x.y);}
+inline void Line(R2 x) {rlineto(x.x,x.y);}
+//inline void Line(D2 x) {rlineto(x.x,x.y);}
+#endif
+
+}
+
+
+#endif
+
Index: /issm/trunk/src/c/Bamgx/MeshDraw.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/MeshDraw.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/MeshDraw.cpp	(revision 2740)
@@ -0,0 +1,808 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifdef DRAWING
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <iostream>
+using namespace std;
+
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+extern bool withrgraphique;
+
+
+
+namespace bamg {
+Real4  xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet;
+R2 GrafPMin,GrafPMax;
+Real8 Grafh=0;
+
+
+
+void  IMoveTo(long i,long j)
+{  if (!withrgraphique) return;
+   rmoveto(float(i)/xGrafCoef+xGrafOffSet ,float(j)/yGrafCoef+yGrafOffSet );}
+
+void  ILineTo(long i,long j)
+{      if (!withrgraphique) return;
+  rlineto(float(i)/xGrafCoef+xGrafOffSet ,float(j)/yGrafCoef+yGrafOffSet );}
+
+
+void   Triangles::Draw(   ) const {
+    if (!withrgraphique) return;
+  showgraphic();
+//  if (!init) InitDraw();
+  Int4 i;
+//  for (i=0;i<nbv;i++)
+//    vertices[i].Draw(i);    
+  for (i=0;i<nbe;i++)
+    edges[i].Draw();
+  for (i=0;i<nbt;i++) 
+      if (triangles[i].link) 
+	triangles[i].Draw(-2);
+//  for (i=0;i<nbv;i++)
+//   ((Metric) vertices[i]).Draw(vertices[i]);    
+   
+  //  rattente(1);
+  
+}
+
+
+void    Edge::Draw(Int4  i) const 
+{
+      if (!withrgraphique) return;
+  if (InRecScreen(Min(v[0]->r.x,v[1]->r.x),
+		  Max(v[0]->r.y,v[1]->r.y),
+		  Min(v[0]->r.x,v[1]->r.x),
+		  Max(v[0]->r.y,v[1]->r.y))) {
+    v[0]->MoveTo();
+    v[1]->LineTo();
+    R2 M= ((R2) *v[0] + (R2) * v[1])*0.5;
+    Move(M);
+    char VertexDraw_i10[20];
+    if (i<0)
+      sprintf(VertexDraw_i10,"%p",this);
+    else 
+      sprintf(VertexDraw_i10,"%ld",i);
+    if (i>=0)
+      plotstring(&VertexDraw_i10[0]); 
+    
+  }
+}
+void    Vertex::Draw(Int4 i) const 
+{
+      if (!withrgraphique) return;
+  if (CurrentTh && i<0&& i != -2 )
+    {
+      if (CurrentTh->vertices <= this && this < CurrentTh->vertices + CurrentTh->nbv)
+	i = CurrentTh->Number(this);
+    }
+  if (InPtScreen(r.x,r.y)) {
+   char VertexDraw_i10[20];
+   if (i<0)
+     sprintf(VertexDraw_i10,"%p",this);
+   else 
+     sprintf(VertexDraw_i10,"%ld",i);
+  
+  showgraphic();
+  //  float eps = (MaxICoor/yGrafCoef)/100;
+  DrawMark(r);
+  
+  if (i>=0)
+    plotstring(&VertexDraw_i10[0]); }
+}
+
+void  DrawMark(R2 r) 
+{
+      if (!withrgraphique) return;
+  if (InPtScreen(r.x,r.y)) {
+  float eps = Grafh/100;
+  rmoveto(r.x+eps,r.y);
+  rlineto(r.x,r.y+eps);
+  rlineto(r.x-eps,r.y);
+  rlineto(r.x,r.y-eps);
+  rlineto(r.x+eps,r.y);}
+ 
+}
+void  Triangle::Draw(Int4 i ) const
+{
+      if (!withrgraphique) return;
+  //  int cc=LaCouleur();
+  if (CurrentTh && i<0 && i != -2)
+    {
+      if (CurrentTh->triangles <= this && this < CurrentTh->triangles + CurrentTh->nbt)
+	i = CurrentTh->Number(this);
+    }	
+  char i10[20];
+  if (i<0)   sprintf(i10,"%p",this);
+  else  sprintf(i10,"%ld",i);
+  showgraphic();
+
+  if (ns[0] == 0) {
+  if (InRecScreen(Min(ns[1]->r.x,ns[2]->r.x),
+		  Min(ns[1]->r.y,ns[2]->r.y),
+		  Max(ns[1]->r.x,ns[2]->r.x),
+		  Max(ns[1]->r.y,ns[2]->r.y)))
+    { rmoveto(ns[1]->r.x,ns[1]->r.y);
+      rlineto(ns[2]->r.x,ns[2]->r.y);
+      rmoveto( (ns[1]->r.x + ns[2]->r.x)/2.0 + (ns[1]->r.y - ns[2]->r.y)*0.1,
+              (ns[1]->r.y + ns[2]->r.y)/2.0 - (ns[1]->r.x - ns[2]->r.x)*0.1 );
+      if(i>=0)  plotstring(&i10[0]);    
+    }}
+  else
+  if (InRecScreen(Min3(ns[0]->r.x,ns[1]->r.x,ns[2]->r.x),
+		  Min3(ns[0]->r.y,ns[1]->r.y,ns[2]->r.y),
+		  Max3(ns[0]->r.x,ns[1]->r.x,ns[2]->r.x),
+		  Max3(ns[0]->r.y,ns[1]->r.y,ns[2]->r.y))) {
+    { 
+      const int i0=0                               , j01=EdgesVertexTriangle[i0][1];//     j01==2
+      const int i1=VerticesOfTriangularEdge[j01][1], j12=EdgesVertexTriangle[i1][1];//i1=1,j12=0
+      const int i2=VerticesOfTriangularEdge[j12][1], j20=EdgesVertexTriangle[i2][1];//i1=2,j20=1
+
+      rmoveto(ns[i0]->r.x,ns[i0]->r.y);
+      if(Hidden(j01)) rmoveto(ns[i1]->r.x,ns[i1]->r.y); else  rlineto(ns[i1]->r.x,ns[i1]->r.y);
+      if(Hidden(j12)) rmoveto(ns[i2]->r.x,ns[i2]->r.y); else  rlineto(ns[i2]->r.x,ns[i2]->r.y);
+      if(Hidden(j20)) rmoveto(ns[i0]->r.x,ns[i0]->r.y); else  rlineto(ns[i0]->r.x,ns[i0]->r.y);
+      
+    rmoveto( (ns[0]->r.x + ns[1]->r.x + ns[2]->r.x)/3.0 ,
+             (ns[0]->r.y + ns[1]->r.y + ns[2]->r.y)/3.0);
+    
+    }
+  
+  if(i>=0)  plotstring(&i10[0]);    
+  }
+  //  LaCouleur(cc);
+}
+
+void  Triangles::InitDraw() const
+{ 
+   if (!withrgraphique) return; 
+   couleur(1);
+   GrafPMin =  vertices[0].r;
+   GrafPMax =  vertices[0].r;
+  // recherche des extrema des vertices GrafPMin,GrafPMax
+  Int4 i;
+  for (i=0;i<nbv;i++) {
+    //    GrafPMax = Max2(GrafPMax,vertices[i].r);
+    //    GrafPMin = Min2(GrafPMin,vertices[i].r);
+    GrafPMin.x = Min(GrafPMin.x,vertices[i].r.x);
+    GrafPMin.y = Min(GrafPMin.y,vertices[i].r.y);
+    GrafPMax.x = Max(GrafPMax.x,vertices[i].r.x);
+    GrafPMax.y = Max(GrafPMax.y,vertices[i].r.y);
+  }
+  float hx = (GrafPMax.x-GrafPMin.x);
+  float hy = (GrafPMax.y-GrafPMin.y);
+  Grafh = Max(hx,hy)*0.55;
+  cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.5,Grafh);
+  
+}
+void Show(const char * s,int k=1)
+{
+  if (!withrgraphique) return;
+  if(k) {
+  couleur(1);
+  float xmin,xmax,ymin,ymax;
+       getcadre(xmin,xmax,ymin,ymax);
+       rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+       plotstring(s);
+       //  couleur(1);	
+  }
+}
+void Triangles::inquire() 
+{    
+  if (! withrgraphique) return;
+  int PS=0;
+  cout << flush;
+   Triangles *OldCurrentTh=CurrentTh;
+  CurrentTh = this;
+  if (! Grafh ) InitDraw();
+  unsigned  char c;
+  int rd;
+  float x,y;
+  int setv =0;
+  Int4 nbtrel=0;
+  Int4 * reft = new Int4 [Max(nbt,1L)];
+  if (NbSubDomains && subdomains[0].head)
+    nbtrel = ConsRefTriangle(reft);
+  else
+    for (Int4 kkk=0;kkk<nbt;kkk++) reft[kkk]=0;
+  // cout << "inquire **********************************************************************"<<endl ;
+      if (verbosity>2)
+	cout << "inquire: Nb de Triangle reel = " <<ConsRefTriangle(reft)<<endl;
+
+  while (Show("Enter ? for help",PS==0), c=::Getxyc(x,y), ( c && c != 'F'  && c != 'f')  && c < 250 )
+    { rd = 0;
+      couleur(1);
+    //  cout << " #"<< c << "# " << (int) c << " xy=" << x << " "<< y  <<endl ;
+      //     penthickness(2);
+      if (c=='?') { int i=3;
+        reffecran();
+	Show("enter a keyboard character in graphic window to do",i++);
+	i++;
+	Show("f or mouse click: to continue the process",i++);
+	Show("p: openPS file to save plot, P: close PS file ",i++);
+        Show("B: set backgound mesh has drawing mesh",i++);
+	Show("H: show histogramme",i++);
+	Show("i: initDraw",i++);
+	Show("+ or - : zoom + or -",i++);
+	Show("r: redraw  , =: reinit the viewport ",i++);
+	Show("q: quit / abort / stop ",i++);
+	Show("Q: show quadtree",i++);
+	Show("g: show geometry",i++);
+	Show("d: show triangle with det = 0",i++);
+	Show("m: show all the metric",i++);
+	Show("V: show all the vertices",i++);
+	Show("T: show all the sub domain ref number",i++);
+	Show("V: show all the vertices",i++);
+	Show("D: Inforce the mesh to be Delaunay",i++);
+	Show("b: show all the boundary edges ref number",i++);
+	Show("k: find the triangle contening the point",i++);
+	Show("v,o,s : print the nearest vertex  s=> draw metric o=> optim around (debug)",i++);
+	Show("t: find triangle contening the point  with brute force",i++);	
+	Show("e: find the nearest edge of triangle contening the point",i++);
+	Show("C: construct the in-circle in anistrope way",i++);
+	Show("n: show normal for find ",i++);
+      }
+      if (c=='p') openPS(0),PS=1;
+      if (c=='P') closePS(),PS=0;
+      if (c=='B') BTh.inquire();
+      if ( c=='D') {
+	for(int iter=0;iter < 50;iter++)
+	  { int k = 0;
+	  for (Int4 icount=0; icount<nbv; icount++) {
+	    k += vertices[icount].Optim(1,0);
+	  }
+	  if (k !=0) cout << " Bizarre le maillage n'est  pas delaunay  nbswap = " << k << endl;
+	  else break;
+	  }
+	rd =1;
+      }
+      
+      if (c=='H') ShowHistogram();
+      if (c=='i') {InitDraw();
+      }
+      if (c=='+') Grafh /= 2.,rd=1,cadreortho(x,y,Grafh);
+      if (c=='-') Grafh *= 2.,rd=1,cadreortho(x,y,Grafh);
+      if (c=='r') rd =1;
+      if (c=='Q') CurrentTh=0,MeshError(1);
+      if (c=='q' && quadtree) penthickness(2),
+				couleur(6), 
+				quadtree->Draw(),
+				couleur(1),
+				penthickness(1);
+      if (c=='g') couleur(6),Gh.Draw();
+      if (c=='n') {
+        for (int i=0;i<nbv;i++)
+         {
+           vertices[i].MoveTo();
+           vertices[1].DirOfSearch.Draw();;
+         }
+      }
+      if (c=='d')
+	{      
+          couleur(4);
+	  for(int i=0;i<nbt;i++)
+	    if(triangles[i].det == 0) {
+	      triangles[i].Draw();
+	      cout << " Bizzare " << i << endl;
+	    }
+          couleur(1);
+       
+	}
+      if (c=='m')  {Int4 i;
+        couleur(2);
+        for (i=0;i<nbv;i++)
+	((Metric) vertices[i]).Draw(vertices[i]); 
+        couleur(1);}
+      if (c=='V')  {Int4 i;
+        for (i=0;i<nbv;i++)
+	 vertices[i].Draw(); }
+      if (c=='T') {
+	Int4 i;
+	for( i=0;i<nbt;i++)
+	  if(reft[i]>=0)
+	    { couleur(2+(reft[i])%6);
+	      triangles[i].Draw(reft[i]);
+              couleur(1); 
+	    }
+      }
+	
+      if (c=='b') {
+	Int4 i;
+	reffecran();
+	for (i=0;i<nbe;i++)
+	  edges[i].Draw(edges[i].ref);
+	
+      }
+      if (c=='k') 
+	{ 
+	  if(!setv) ReMakeTriangleContainingTheVertex();
+	  R2 P(x,y);
+	  I2 I = toI2(P);
+	  Icoor2 dete[3];
+	  Triangle * tb = FindTriangleContening(I,dete);
+	  penthickness(1);
+	  tb->Draw(Number(tb));
+	  penthickness(1);
+	  if(tb->link==0) {
+	    double a,b;
+	    TriangleAdjacent ta=CloseBoundaryEdgeV2(I,tb,a,b);
+	    R2 A = *ta.EdgeVertex(0);
+	    R2 B = *ta.EdgeVertex(1);
+	    //Triangle * tt  = ta;
+	    //    tt->Draw(Number(tt));
+	    penthickness(5);
+	    //   ta.EdgeVertex(0)->MoveTo();
+	    //  ta.EdgeVertex(1)->LineTo();
+	    DrawMark(A*a+B*b);
+	    penthickness(1);
+	      }
+	}
+      if (c=='v' || c=='o' || c=='s' )
+	{ 
+	  couleur(3);
+	  if(!setv) ReMakeTriangleContainingTheVertex();
+	  setv=1;
+	  
+	  R2 XY(x,y),P;
+	  Real8 d;
+	  Int4 i,j=0;
+	  P  = XY - vertices[0].r;
+	  d = (P,P);
+	  for (i=0;i<nbv;i++) {
+	    P  = XY - vertices[i].r;
+	  Real8 dd = (P,P);
+	  if(dd < d) {
+	    j=i;
+	    d=dd;}}
+	  cout << " sommet " << j << "= " <<	vertices[j]  << ", d = " << d << " " << vertices[j].m << endl;
+	  vertices[j].Draw(j);
+	  DrawMark(vertices[j].r);
+	  if( c=='s')  vertices[j].m.Draw(vertices[j]);
+	  if (c=='o')   cout << " Nb Swap = " << vertices[j].Optim(1) << endl;
+	  couleur(1);
+      }
+      if (c=='t' || c=='c'||c=='e') {
+	    couleur(4);
+            R2 XY(x,y);
+	    Real8 a12,a02,a01;
+	    for (Int4 i=0;i<nbt;i++) {
+	      if(triangles[i].det<=0)  continue;
+	      //	      cout << " T = " << i << " " << triangles[i].det << " ";
+	      //	      cout << Number(triangles[i][0]) << " "
+	      //		   << Number(triangles[i][1]) << " "
+	      //		   << Number(triangles[i][2]) << " ";
+	      //    cout << area2(triangles[i][0].r,triangles[i][1].r,triangles[i][2].r) << " " ;
+	      //	      cout << area2(XY,triangles[i][1].r,triangles[i][2].r) << " " ;
+	      //      cout << area2(triangles[i][0].r,XY,triangles[i][2].r) << " " ;
+	      //     cout << area2(triangles[i][0].r,triangles[i][1].r,XY) << endl;
+			   
+	      if( (a12=Area2(XY,triangles[i][1].r,triangles[i][2].r)) < 0) continue;
+	      if( (a02=Area2(triangles[i][0].r,XY,triangles[i][2].r)) < 0) continue;
+	      if( (a01=Area2(triangles[i][0].r,triangles[i][1].r,XY)) < 0) continue;
+	      if(c=='e'|| c=='E') {
+		int ie =0;
+		Real8 am = a12;
+		if(a02 < am) am=a02,ie=1;
+		if(a01 < am) am=a01,ie=2;
+		TriangleAdjacent tta(triangles+i,ie);
+		Vertex *v0 =tta.EdgeVertex(0);
+		Vertex *v1 =tta.EdgeVertex(1);
+		tta.EdgeVertex(0)->MoveTo();
+		tta.EdgeVertex(1)->LineTo();
+		cout << " Edge " << Number(tta.EdgeVertex(0)) << " " <<  Number(tta.EdgeVertex(1)) << endl;
+		for (Int4 k=0;k<nbe;k++)
+		  if ( ( edges[k](0) == v0 &&  edges[k](1) == v1) ||
+		       ( edges[k](0) == v1 &&  edges[k](1) == v0)	)			
+		    cout << " Edge " << k << "  on Geo = " << Gh.Number(edges[k].on)<< endl;
+		
+		  
+		if(c=='e') {
+		  triangles[i].SetUnMarkUnSwap(ie);
+		  triangles[i].swapDRAW(ie);}
+		else if(c=='E')
+		  {
+		    ;
+		  }
+
+		break;
+	      }
+	      cout << " In triangle " << i << triangles[i];
+	      triangles[i].Draw(i);
+	      if(c=='c') {
+		Vertex *s1=&triangles[i][0];
+		Vertex *sa=&triangles[i][1];
+		Vertex *sb=&triangles[i][2];
+		D2 S1(s1->r.x,s1->r.y);
+		D2 SA(sa->r.x,sa->r.y);
+		D2 SB(sb->r.x,sb->r.y);
+		D2 AB= SB-SA;
+		D2 MAB2=SB + SA;
+		D2 M1A=(S1 + SA)*0.5;
+		D2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+		D2 A1=S1-SA;
+		D2 D = S1 - SB ;
+		{
+		  Metric M=s1->m;
+		  D2 ABo = M.Orthogonal(AB);
+		  D2 A1o = M.Orthogonal(A1);
+		  penthickness(1);
+		  Move(MAB);
+		  Line(MAB+ABo);
+		  Line(MAB-ABo);
+		  Move(M1A);
+		  Line(M1A+A1o);
+		  Line(M1A-A1o);
+		  penthickness(3);
+		  
+		  // (A+B)+ x ABo = (S1+B)/2+ y A1 
+		  // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+		  double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+		  double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+		  cout << " d = " << d << " dd= " << dd << endl;
+		  if (Abs(d) > dd*1.e-10) {
+		    D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		    cout << C << s1->r <<sa->r  <<sb->r << endl;
+		    DrawMark(C);
+		    cout << M << " l = "<<  M(C-S1) << " lnew = 1 == " ;
+		    //M.Draw(R2(C.x,C.y));
+		    M=M/M(C-S1);	
+		    cout << M(C-S1) << M << endl;	 
+		    M.Draw(R2(C.x,C.y));
+		  }
+		  
+		}
+	      }
+	      break;
+	    }
+	    cout << " fin recherche triangle " << endl;
+	   couleur(1); 
+      }            
+      if (c=='='||c==249) {
+	rd=1;
+	float hx = (GrafPMax.x-GrafPMin.x);
+	float hy = (GrafPMax.y-GrafPMin.y);
+	Grafh = Max(hx,hy)*0.55;
+	cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.55,Grafh);
+      }
+       penthickness(1);
+      if (rd) 
+        reffecran(),Draw();
+
+    }
+  // cout << endl;
+  delete [] reft;
+  CurrentTh = OldCurrentTh;
+ }
+void Draw(float x,float y)
+{
+ if (!withrgraphique) return;
+
+  if (InPtScreen(x,y)) {
+  float eps = Max(GrafPMax.x-GrafPMin.x,GrafPMax.y-GrafPMin.y)/100;
+  rmoveto(x+eps,y);
+  rlineto(x,y+eps);
+  rlineto(x-eps,y);
+  rlineto(x,y-eps);
+  rlineto(x+eps,y);}
+}
+char Getxyc(long &i,long &j)
+{ 
+   if (!withrgraphique) return 0;
+ 
+   float x,y;
+   char c=::Getxyc(x,y);
+   i = (long)( (x - xGrafOffSet)*xGrafCoef);
+   j = (long)((y - yGrafOffSet)*yGrafCoef);
+   return c;
+}
+
+
+void Draw(long i,long j)
+{
+  if (!withrgraphique) return;
+  Draw(((float) i)/xGrafCoef+xGrafOffSet ,((float) j)/yGrafCoef+yGrafOffSet );
+}
+
+int Triangle::swapDRAW(Int2 a){
+  int NbUnSwap=0;
+  if(a/4 !=0)  {cout << a << "arete lock"<< a <<endl;return 0;}// arete lock or MarkUnSwap
+
+  register Triangle *t1=this,*t2=at[a];// les 2 triangles adjacent
+  register Int1 a1=a,a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+  
+  if(a2/4 !=0) {cout << a2 << "arete lock adj"<< a2 << endl; return 0;} // arete lock
+  
+  register Vertex  *sa=t1->ns[VerticesOfTriangularEdge[a1][0]];
+  register Vertex  *sb=t1->ns[VerticesOfTriangularEdge[a1][1]];
+  register Vertex  *s1=t1->ns[OppositeVertex[a1]];
+  register Vertex  *s2=t2->ns[OppositeVertex[a2]];
+
+#ifdef DEBUG
+  assert ( a >= 0 && a < 3 );  
+#endif
+  
+   Icoor2 det1=t1->det , det2=t2->det ;
+   Icoor2 detT = det1+det2;
+   Icoor2 detA = Abs(det1) + Abs(det2);
+   Icoor2 detMin = Min(det1,det2);
+
+   int OnSwap = 0;       
+   // si 2 triangle infini (bord) => detT = -2;
+   if (sa == 0) {// les deux triangles sont frontieres
+     det2=bamg::det(s2->i,sb->i,s1->i);
+     OnSwap = det2 >0;}
+   else if (sb == 0) { // les deux triangles sont frontieres
+     det1=bamg::det(s1->i,sa->i,s2->i);
+     OnSwap = det1 >0;}
+   else if(( s1 != 0) && (s2 != 0) ) {
+     det1 = bamg::det(s1->i,sa->i,s2->i);
+     det2 = detT - det1;
+     OnSwap = (Abs(det1) + Abs(det2)) < detA;
+     Icoor2 detMinNew=Min(det1,det2);
+     cout << " detMin = " << detMin << "  detMinNew " <<  detMinNew << endl;
+     if (! OnSwap &&(detMinNew>0)) {
+       OnSwap = detMin ==0;
+       if (! OnSwap) {
+	 int  kopt = 1;
+        while (1)
+	 if(kopt) {
+	 // critere de Delaunay pure 
+	 register Real8 xb1 = sb->i.x - s1->i.x,
+	   x21 = s2->i.x - s1->i.x,
+	   yb1 = sb->i.y - s1->i.y,
+	   y21 = s2->i.y - s1->i.y,
+	   xba = sb->i.x - sa->i.x, 
+	   x2a = s2->i.x - sa->i.x,
+	   yba = sb->i.y - sa->i.y,
+	   y2a = s2->i.y - sa->i.y,
+	   cosb12 =  xb1*x21 + yb1*y21 ,
+	   cosba2 =  xba*x2a + yba*y2a ,
+	   sinb12 = det2,
+	   sinba2 = t2->det,
+	   //zsinba2 = t2->det;
+	 
+	 // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2)
+	 OnSwap =  (cosb12 *  sinba2) <  (cosba2 *  sinb12);
+	 if(CurrentTh) 
+	   cout << "swap s1=" << CurrentTh->Number(sa) << " s2=" << CurrentTh->Number(sb) 
+		<< " t1= " <<  CurrentTh->Number(t1) << " t2=" <<  CurrentTh->Number(t2) << " " ;
+
+
+	 cout <<  cosb12 << " " <<  sinba2 << " "  <<  cosba2 << " " << sinb12 
+	      << " Onswap = " <<  OnSwap << endl;
+
+	  break;
+	 }
+	 else 
+	   {	
+	     // critere de Delaunay pure 
+	     Real8 som;
+	     I2 AB=(I2) *sb - (I2) *sa;
+	     I2 MAB2=((I2) *sb + (I2) *sa);
+	     D2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+	     I2 A1=(I2) *s1 - (I2) *sa;
+	     I2 D = (I2) * s1 - (I2) * sb ;
+	     D2 S2(s2->i.x,s2->i.y);
+	     D2 S1(s1->i.x,s1->i.y);
+	     D2 SA(sa->i.x,sa->i.y);
+	     D2 SB(sb->i.x,sb->i.y);
+	     DrawMark(s2->r);
+	     DrawMark(s1->r);
+	     DrawMark(sa->r);
+	     DrawMark(sb->r);
+	     {
+	       Metric M=s1->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       if (Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M1 r2 =" <<  M(C - S2) << " r1 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) ;
+		 som  = M(C - S2)/M(C - S1);
+		 cout << " r1/r2 = " << som << endl;
+	       } else 
+		{kopt=1;continue;}
+		
+	     }
+	     {
+	       Metric M=s2->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       cout << " d = " << Abs(d) << " dd " << dd << endl;
+	       if(Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M2 r1 =" <<  M(C - S2) << " r2 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) 
+		      << " r1/r2 =  " << M(C - S2)/M(C -  S1)  << endl;
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+	     {
+	       Metric M=sa->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       cout << " d = " << Abs(d) << " dd " << dd << endl;
+	       if(Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M2 r1 =" <<  M(C - S2) << " r2 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) 
+		      << " r1/r2 =  " << M(C - S2)/M(C -  S1)  << endl;
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+  	     {
+	       Metric M=sb->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       cout << " d = " << Abs(d) << " dd " << dd << endl;
+	       if(Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M2 r1 =" <<  M(C - S2) << " r2 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) 
+		      << " r1/r2 =  " << M(C - S2)/M(C -  S1)  << endl;
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+	     cout <<  som  << endl;
+	     OnSwap = som < 4;
+	     break;
+	 }
+
+       } // OnSwap 
+     } // (! OnSwap &&(det1 > 0) && (det2 > 0) )
+   }
+   cout << OnSwap << endl;
+   if( OnSwap ) {
+     couleur(0);
+     t1->Draw();
+     t2->Draw();    
+     bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2);		
+     couleur(1);
+     t1->Draw();
+     t2->Draw();    
+   }
+   else {
+     NbUnSwap ++;
+     t1->SetMarkUnSwap(a1);     
+   }
+   return OnSwap;
+}
+
+
+	   
+
+void GeometricalEdge::Draw(Int4  i)
+{ 
+    if (!withrgraphique) return;
+
+  if (CurrentTh && i<0 && i != -2)
+    {
+      if (CurrentTh->Gh.edges <= this && this < CurrentTh->Gh.edges + CurrentTh->Gh.nbe)
+	i = CurrentTh->Gh.Number((this));
+    }	
+
+    v[0]->MoveTo();
+    R2 x,x50;
+    int k=0,k50=0;
+    for (int ii = 0;ii<100;ii++) {
+      x= F( Real4(ii)/100.0);
+      if(ii==50) x50=x,k50=1;
+      if (InPtScreen(x.x,x.y) )
+	if(k) rlineto(x.x,x.y);
+	else k=1,rmoveto(x.x,x.y);
+    }
+      if (InPtScreen(v[1]->r.x,v[1]->r.y))      
+	v[1]->LineTo();  
+
+      char VertexDraw_i10[20];
+      if( k50) {
+	if (i<0)
+	  sprintf(VertexDraw_i10,"Eg%p",this);
+	else 
+	  sprintf(VertexDraw_i10,"Eg%ld",i);
+	rmoveto(x50.x,x50.y);
+	plotstring(&VertexDraw_i10[0]); }  
+
+}
+
+void  Geometry::InitDraw() const
+{ 
+   GrafPMin =  vertices[0].r;
+   GrafPMax =  vertices[0].r;
+  // recherche des extrema des vertices GrafPMin,GrafPMax
+  Int4 i;
+  for (i=0;i<nbv;i++) {
+    //    GrafPMax = Max2(GrafPMax,vertices[i].r);
+    //    GrafPMin = Min2(GrafPMin,vertices[i].r);
+    GrafPMin.x = Min(GrafPMin.x,vertices[i].r.x);
+    GrafPMin.y = Min(GrafPMin.y,vertices[i].r.y);
+    GrafPMax.x = Max(GrafPMax.x,vertices[i].r.x);
+    GrafPMax.y = Max(GrafPMax.y,vertices[i].r.y);
+  }
+  float hx = (GrafPMax.x-GrafPMin.x);
+  float hy = (GrafPMax.y-GrafPMin.y);
+  Grafh = Max(hx,hy)*7/10;
+  if (withrgraphique)
+   cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.55,Grafh);
+
+  
+}
+
+void   Geometry::Draw() const {
+    if (!withrgraphique) return;
+
+  showgraphic();
+  //  InitDraw();
+  Int4 i;
+  for (i=0;i<nbv;i++)
+    vertices[i].Draw();    
+  for (i=0;i<nbe;i++)
+    {
+	if(edges[i].Cracked()) couleur(4);
+	else couleur(6);
+    edges[i].Draw(i);
+    }
+   couleur(6);
+  for (i=0;i<nbv;i++)
+    if (vertices[i].Required()) {
+      char i10[40];
+      sprintf(i10,"%ld:%d",i,vertices[i].Required());
+      Move(vertices[i].r);
+      if(vertices[i].Corner()) couleur(2);
+      plotstring(i10);  
+      if(vertices[i].Corner()) couleur(6);
+      }
+  // rattente(1);
+ }
+
+}
+#endif
Index: /issm/trunk/src/c/Bamgx/MeshGeom.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/MeshGeom.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/MeshGeom.cpp	(revision 2740)
@@ -0,0 +1,1190 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// #define TRACETRIANGLE 3
+//#define strcasecmp strcmp
+#include <cstdio>
+#include <string.h>
+#include <cmath>
+#include <time.h>
+#include <iostream>
+using namespace std;
+
+
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+namespace bamg {
+void Triangles::ConsGeometry(Real8 cutoffradian,int *equiedges) // construct a geometry if no geo 
+ {
+  //  if equiedges existe taille nbe 
+  //   equiedges[i]/2 == i  original
+  //   equiedges[i]/2 = j  =>   equivalence entre i et j => meme maillage
+  //   equiedges[i]%2   : 0 meme sens , 1 pas meme sens 
+  //       
+  // --------------------------
+  long int verbosity=0;
+  if (verbosity>1) 
+    cout << "  -- construction of the geometry from the 2d mesh " << endl;
+  if (nbt<=0 || nbv <=0 ) { MeshError(101);}
+
+  // construction of the edges 
+  //  Triangles * OldCurrentTh =CurrentTh;
+  CurrentTh=this;
+  //  Int4 NbTold = nbt;
+  // generation of the integer coor
+  // generation of the adjacence of the triangles
+  if (cutoffradian>=0)
+    Gh.MaximalAngleOfCorner = cutoffradian;
+  SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv);
+  Int4 * st = new Int4[nbt*3];
+  Int4 i,k;
+  int j; 
+  if (Gh.name) delete Gh.name;
+  Gh.name = new char [ name ? strlen(name) + 15 : 50 ];
+  Gh.name[0]=0;
+  strcat(Gh.name,"cons from: ");
+  if (name) strcat(Gh.name,name);
+  else strcat(Gh.name," a mesh with no name");
+  for (i=0;i<nbt*3;i++)
+    st[i]=-1;
+  Int4 kk =0;
+
+  Int4 nbeold = nbe;
+  for (i=0;i<nbe;i++)
+    {
+      //      cout << i << " " << Number(edges[i][0]) << " " << Number(edges[i][1]) << endl;
+      edge4->addtrie(Number(edges[i][0]),Number(edges[i][1]));
+    }
+  if (nbe !=  edge4->nb())
+      { 
+      cerr << " Some Double edge in the mesh, the number is " << nbe 
+	   << " nbe4=" << edge4->nb()  << endl;
+      MeshError(1002);
+    }
+  for (i=0;i<nbt;i++)
+    for  (j=0;j<3;j++)
+      {
+	// Int4 i0,i1;
+	Int4 k =edge4->addtrie(Number(triangles[i][VerticesOfTriangularEdge[j][0]]),
+			       Number(triangles[i][VerticesOfTriangularEdge[j][1]]));
+	Int4 invisible = triangles[i].Hidden(j);
+	if(st[k]==-1)
+	  st[k]=3*i+j;
+	else if(st[k]>=0) {
+	  assert( ! triangles[i].TriangleAdj(j) && !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3)));
+	  
+	  triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3));
+	  if (invisible)  triangles[i].SetHidden(j);
+	  if (k<nbe) {
+	    triangles[i].SetLocked(j);
+	  }
+	  st[k]=-2-st[k]; }
+	else {
+	  cerr << " The edge (" 
+	       << Number(triangles[i][VerticesOfTriangularEdge[j][0]])
+	       << " , " 
+	       << Number(triangles[i][VerticesOfTriangularEdge[j][1]])
+	       << " ) is in more than 2 triangles " <<k <<endl;
+	  cerr << " Edge " << j << " Of Triangle " << i << endl;
+	  cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3  << endl;
+	  cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3))
+	       << " Of Triangle " <<  Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) 
+	       << endl;
+	  MeshError(9999);}	
+	
+	
+      }
+  Int4 nbedges = edge4->nb(); // the total number of edges 
+    delete edge4;
+  edge4 =0;
+
+  if(verbosity>5) {
+    if (name)
+     cout << "    On Mesh " << name << endl;
+    cout << "    - The number of Vertices  = " << nbv << endl;
+    cout << "    - The number of Triangles = " << nbt << endl;
+    cout << "    - The number of given edge = " << nbe << endl;
+    cout << "    - The number of all edges = " << nbedges << endl;
+    cout << "    - The Euler number = 1-Nb Of Hole = " << nbt-nbedges+nbv << endl; }
+  
+  
+  // check the consistant of edge[].adj and the geometrical required  vertex
+  k=0;
+  kk=0;
+  Int4 it;
+
+  for (i=0;i<nbedges;i++)
+    if (st[i] <-1) // edge internal
+      { 
+	it =  (-2-st[i])/3;
+	j  =  (int) ((-2-st[i])%3);
+	Triangle & tt = * triangles[it].TriangleAdj(j);
+	//cout << it << " c="  << triangles[it].color <<  " " << Number(tt) << " c="  << tt.color << endl;
+	if (triangles[it].color != tt.color|| i < nbeold) // Modif FH 06122055 // between 2 sub domai
+	  k++;
+      }
+    else if (st[i] >=0) // edge alone 
+       // if (i >= nbeold) 
+	     kk++;
+  
+  if(verbosity>4 && (k+kk) )
+    cout << "    Nb of  ref edge " << kk+k << " (internal " << k << ")"
+	 << " in file " << nbe  << endl;
+  k += kk;
+  kk=0;
+    if (k)
+    {
+      
+      //      if (nbe) {
+      //	cerr << k << " boundary edges  are not defined as edges " << endl;
+      //	MeshError(9998);
+      // }
+      // construction of the edges 
+      nbe = k;
+      Edge * edgessave = edges;
+      edges = new Edge[nbe];
+      k =0;
+      // construction of the edges 
+      if(verbosity>4)
+	cout << "    Construction of the edges  " << nbe << endl;
+
+      for (i=0;i<nbedges;i++)
+	{ 
+	  Int4  add= -1;
+	  
+	  if (st[i] <-1) // edge internal
+	    { 
+	      it =  (-2-st[i])/3;
+	      j  =  (int) ((-2-st[i])%3);
+	      Triangle & tt = * triangles[it].TriangleAdj(j);
+	      if (triangles[it].color !=  tt.color || i < nbeold) // Modif FH 06122055
+		  add=k++;
+	    }
+	  else if (st[i] >=0) // edge alone 
+	    {
+	      it = st[i]/3;
+	      j  = (int) (st[i]%3);
+	      add=k++;
+	    }
+	  
+	  if (add>=0 && add < nbe)
+	    {
+	      
+	      edges[add].v[0] = &triangles[it][VerticesOfTriangularEdge[j][0]];
+	      edges[add].v[1] = &triangles[it][VerticesOfTriangularEdge[j][1]];
+	      edges[add].on=0; 
+	      if (i<nbeold) // in file edge // Modif FH 06122055 
+		{
+		  edges[add].ref = edgessave[i].ref; 		      
+		  edges[add].on = edgessave[i].on; //  HACK pour recuperer les aretes requise midf FH avril 2006 ???? 
+		}
+	      else
+		edges[add].ref = Min(edges[add].v[0]->ref(),edges[add].v[1]->ref()); // no a good choice
+	    }
+	}
+      assert(k==nbe);
+      if (edgessave) delete [] edgessave;
+    }
+    
+    // construction of edges[].adj 
+    for (i=0;i<nbv;i++) 
+      vertices[i].color =0;
+    for (i=0;i<nbe;i++)
+      for (j=0;j<2;j++) 
+	edges[i].v[j]->color++;
+    
+    for (i=0;i<nbv;i++) 
+      vertices[i].color = (vertices[i].color ==2) ? -1 : -2;
+    for (i=0;i<nbe;i++)
+      for (j=0;j<2;j++) 
+	{ 
+	  Vertex *v=edges[i].v[j];
+	  Int4 i0=v->color,j0;
+	  if(i0<0)
+	     edges[i ].adj[ j ]=0;  // Add FH Jan 2008   
+	  if(i0==-1)
+	    v->color=i*2+j;
+	  else if (i0>=0) {// i and i0 edge are adjacent by the vertex v
+	    j0 =  i0%2;
+	    i0 =  i0/2;
+	    assert( v ==  edges[i0 ].v[j0]);
+	    edges[i ].adj[ j ] =edges +i0;
+	    edges[i0].adj[ j0] =edges +i ;
+	    assert(edges[i0].v[j0] == v);
+	    //	    if(verbosity>8)
+	    //  cout << " edges adj " << i0 << " "<< j0 << " <-->  "  << i << " " << j << endl;
+	    v->color = -3;}
+	}
+    // now reconstruct the sub domain info 
+    assert(!NbSubDomains);
+  NbSubDomains=0;
+  
+  { 
+    Int4 it;
+    // find all the sub domain
+    Int4 *colorT = new Int4[nbt];
+    Triangle *tt,*t;
+    Int4 k;
+    for ( it=0;it<nbt;it++)
+      colorT[it]=-1;
+    for (it=0;it<nbt;it++)
+      {
+	if (colorT[it]<0) 
+	  {
+	    colorT[it]=NbSubDomains;
+	    Int4 level =1,j,jt,kolor=triangles[it].color;
+	    st[0]=it; // stack 
+	    st[1]=0;
+	    k=1;
+	    while (level>0)
+	      if( ( j=st[level]++) <3)
+		{ 
+		  t = &triangles[st[level-1]];
+		  tt=t->TriangleAdj((int)j);
+		  
+		  if ( ! t->Locked(j) && tt && (colorT[jt = Number(tt)] == -1) && ( tt->color==kolor))
+		    {
+		      colorT[jt]=NbSubDomains;
+		      st[++level]=jt;
+		      st[++level]=0;
+		      k++;
+		    }
+		}
+	      else 
+		level-=2;
+	    if (verbosity>5) 
+	      cout << "   Nb of triangles " << k << " of Subdomain "  
+		   <<  NbSubDomains << " " << kolor << endl;
+	    NbSubDomains++;
+	  }
+      }
+    if (verbosity> 3)
+      cout << "   The Number of sub domain = " << NbSubDomains << endl;
+    
+    Int4 isd;
+    subdomains = new SubDomain[NbSubDomains];
+    for (isd=0;isd<NbSubDomains;isd++)
+      {
+	subdomains[isd].head =0;
+      }
+    k=0;
+    for (it=0;it<nbt;it++)
+      for (int j=0;j<3;j++)
+	{
+	  tt=triangles[it].TriangleAdj(j);
+	  if ((!tt || tt->color != triangles[it].color) && !subdomains[isd=colorT[it]].head)
+	    {
+	      subdomains[isd].head = triangles+it;
+	      subdomains[isd].ref =  triangles[it].color;
+	      subdomains[isd].sens = j; // hack
+	      subdomains[isd].edge = 0;
+	      k++;
+	    }
+	}  
+    assert(k== NbSubDomains);
+    
+    delete [] colorT;
+    
+    
+  }      
+  delete [] st;
+  // now make the geometry
+  // 1 compress the vertices 
+  Int4 * colorV = new Int4[nbv];
+  for (i=0;i<nbv;i++) 
+    colorV[i]=-1;
+  for (i=0;i<nbe;i++)
+    for ( j=0;j<2;j++)
+      colorV[Number(edges[i][j])]=0;
+  k=0;
+  for (i=0;i<nbv;i++) 
+    if(!colorV[i])
+      colorV[i]=k++;
+  
+  Gh.nbv=k;
+  Gh.nbe = nbe;
+  Gh.vertices = new GeometricalVertex[k];
+  Gh.edges = new GeometricalEdge[nbe];
+  Gh.NbSubDomains = NbSubDomains;
+  Gh.subdomains = new GeometricalSubDomain[NbSubDomains];
+  if (verbosity>3)
+    cout << "    Nb of  vertices  = " << Gh.nbv << " Nb of edges = " << Gh.nbe << endl;
+  NbVerticesOnGeomVertex = Gh.nbv;
+  VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+  NbVerticesOnGeomEdge =0;
+  VerticesOnGeomEdge =0;
+  {
+    Int4 j;
+    for (i=0;i<nbv;i++) 
+      if((j=colorV[i])>=0)
+	{
+	  
+	  Vertex & v = Gh.vertices[j];
+	  v = vertices[i];
+	  v.color =0;
+	  VerticesOnGeomVertex[j] = VertexOnGeom(vertices[i], Gh.vertices[j]);
+	}
+    
+  }
+  edge4= new SetOfEdges4(nbe,nbv);  
+  
+  Real4 * len = new Real4[Gh.nbv];
+  for(i=0;i<Gh.nbv;i++)
+    len[i]=0;
+  
+  Gh.pmin =  Gh.vertices[0].r;
+  Gh.pmax =  Gh.vertices[0].r;
+  // recherche des extrema des vertices pmin,pmax
+  for (i=0;i<Gh.nbv;i++) {
+    Gh.pmin.x = Min(Gh.pmin.x,Gh.vertices[i].r.x);
+    Gh.pmin.y = Min(Gh.pmin.y,Gh.vertices[i].r.y);
+    Gh.pmax.x = Max(Gh.pmax.x,Gh.vertices[i].r.x);
+    Gh.pmax.y = Max(Gh.pmax.y,Gh.vertices[i].r.y);
+  }
+  
+  R2 DD05 = (Gh.pmax-Gh.pmin)*0.05;
+  Gh.pmin -=  DD05;
+  Gh.pmax +=  DD05;
+  
+  Gh.coefIcoor= (MaxICoor)/(Max(Gh.pmax.x-Gh.pmin.x,Gh.pmax.y-Gh.pmin.y));
+  assert(Gh.coefIcoor >0);
+  
+  Real8 hmin = HUGE_VAL;
+     int kreq=0;
+  for (i=0;i<nbe;i++)
+    {
+      Int4 i0 = Number(edges[i][0]);
+      Int4 i1 = Number(edges[i][1]);
+      Int4 j0 =	 colorV[i0];
+      Int4 j1 =  colorV[i1];
+      
+      Gh.edges[i].v[0] = Gh.vertices +  j0;
+      Gh.edges[i].v[1] = Gh.vertices +  j1;
+      Gh.edges[i].flag = 0;
+      Gh.edges[i].tg[0]=R2();
+      Gh.edges[i].tg[1]=R2();
+      bool requis= edges[i].on; 
+	if(requis) kreq++;
+      edges[i].on =  Gh.edges + i;
+      if(equiedges && i < nbeold ) {
+        int j=equiedges[i]/2;
+        int sens=equiedges[i]%2;
+        if(i!=j && equiedges[i]>=0) {
+          if(verbosity>9)  
+             cout << " Edges Equi " << i << " <=> " << j << " sens = " << sens  << endl;
+           if( sens==0)
+           Gh.edges[i].SetEqui();
+           else 
+            Gh.edges[i].SetReverseEqui();
+           Gh.edges[i].link= & Gh.edges[j];
+           //assert(sens==0);//  meme sens pour l'instant
+        }
+	
+       }
+      if(requis)  {  // correction fevr 2009 JYU ...
+	Gh.edges[i].v[0]->SetRequired();
+	Gh.edges[i].v[1]->SetRequired();
+	Gh.edges[i].SetRequired(); // fin modif ... 
+      }
+      R2 x12 = Gh.vertices[j0].r-Gh.vertices[j1].r;
+      Real8 l12=Norme2(x12);        
+      hmin = Min(hmin,l12);
+      
+      Gh.vertices[j1].color++;
+      Gh.vertices[j0].color++;
+      
+      len[j0]+= l12;
+      len[j1] += l12;
+      hmin = Min(hmin,l12);
+      
+      Gh.edges[i].ref  = edges[i].ref;
+      
+      k = edge4->addtrie(i0,i1);
+      
+      assert(k == i);
+      
+    }
+  
+  
+  for (i=0;i<Gh.nbv;i++) 
+    if (Gh.vertices[i].color > 0) 
+      Gh.vertices[i].m=  Metric(len[i] /(Real4) Gh.vertices[i].color);
+    else 
+      Gh.vertices[i].m=  Metric(hmin);
+  delete [] len;
+  for (i=0;i<NbSubDomains;i++)
+    {
+      Int4 it = Number(subdomains[i].head);
+      int j = subdomains[i].sens;
+      Int4 i0 = Number(triangles[it][VerticesOfTriangularEdge[j][0]]);
+      Int4 i1 = Number(triangles[it][VerticesOfTriangularEdge[j][1]]);
+      k = edge4->findtrie(i0,i1);
+      if(k>=0)
+	{
+	  subdomains[i].sens = (vertices + i0 == edges[k].v[0]) ? 1 : -1;
+	  subdomains[i].edge = edges+k;
+	  Gh.subdomains[i].edge = Gh.edges + k;
+	  Gh.subdomains[i].sens  =  subdomains[i].sens;
+	  Gh.subdomains[i].ref =  subdomains[i].ref;
+	}
+      else
+	MeshError(103);
+    }
+  
+  delete edge4;
+  delete [] colorV;
+  //  -- unset adj
+  for (i=0;i<nbt;i++)
+    for ( j=0;j<3;j++)
+      triangles[i].SetAdj2(j,0,triangles[i].GetAllflag(j));
+  
+}
+
+
+void Geometry::EmptyGeometry()  // empty geometry
+  {
+  OnDisk=0;
+  NbRef=0;
+  name =0;
+  quadtree=0;
+  curves=0;
+ // edgescomponante=0;
+  triangles=0;
+  edges=0;
+  vertices=0;
+  NbSubDomains=0;
+  //  nbtf=0;
+//  BeginOfCurve=0;  
+  nbiv=nbv=nbvx=0;
+  nbe=nbt=nbtx=0;
+  NbOfCurves=0;
+//  BeginOfCurve=0;
+  subdomains=0;
+  MaximalAngleOfCorner = 10*Pi/180;
+  }
+
+
+
+Geometry::Geometry(const Geometry & Gh)
+ { Int4 i;
+   *this = Gh;
+   NbRef =0;
+   quadtree=0;
+   name = new char[strlen(Gh.name)+4];
+   strcpy(name,"cp:");
+   strcat(name,Gh.name);
+   vertices = nbv ? new GeometricalVertex[nbv] : NULL;
+   triangles = nbt ? new  Triangle[nbt]:NULL;
+   edges = nbe ? new GeometricalEdge[nbe]:NULL;
+   curves= NbOfCurves ? new Curve[NbOfCurves]:NULL;
+   subdomains = NbSubDomains ? new GeometricalSubDomain[NbSubDomains]:NULL;
+   for (i=0;i<nbv;i++)
+     vertices[i].Set(Gh.vertices[i],Gh,*this);
+   for (i=0;i<nbe;i++)
+     edges[i].Set(Gh.edges[i],Gh,*this);
+   for (i=0;i<NbOfCurves;i++)
+     curves[i].Set(Gh.curves[i],Gh,*this);
+   for (i=0;i<NbSubDomains;i++)
+     subdomains[i].Set(Gh.subdomains[i],Gh,*this);
+     
+   //    for (i=0;i<nbt;i++)
+   //      triangles[i].Set(Gh.triangles[i],Gh,*this);
+   assert(!nbt);   
+ }
+
+
+GeometricalEdge* Geometry::Contening(const R2 P,  GeometricalEdge * start) const
+{
+  GeometricalEdge* on =start,* pon=0;
+  // walk with the cos on geometry
+  //  cout << P ;
+  int k=0;
+   while(pon != on)
+     {  
+       pon = on;
+       assert(k++<100);
+       R2 A= (*on)[0];
+       R2 B= (*on)[1];
+       R2 AB = B-A;
+       R2 AP = P-A;
+       R2 BP = P-B;
+       //   cout << "::  " << on - edges << " "  <<  AB*AP  << " " <<  AB*BP << " " << A << B << endl;
+       if ( (AB,AP) < 0) 
+	 on = on->Adj[0];
+       else if ( (AB,BP)  > 0) 
+	 on = on->Adj[1];
+       else
+	 return on;
+     }
+   return on;
+}
+GeometricalEdge* Geometry::ProjectOnCurve(const Edge & e,Real8 s,Vertex &V,VertexOnGeom &GV ) const 
+ {  
+    Real8 save_s=s;
+    int NbTry=0;
+retry:    
+    s=save_s;
+    GeometricalEdge * on = e.on;
+    assert(on);
+    assert( e[0].on &&  e[1].on);
+    const Vertex &v0=e[0],&v1=e[1];
+    V.m = Metric(1.0-s, v0,s, v1);
+#define MXE__LINE  __LINE__+1
+    const int mxe =100;
+    GeometricalEdge *ge[mxe+1];
+    int    sensge[mxe+1];
+    Real8  lge[mxe+1];
+    int bge=mxe/2,tge=bge;
+    ge[bge] = e.on;
+    sensge[bge]=1;
+
+    R2 V0 = v0,V1=v1,V01=V1-V0;
+    VertexOnGeom  vg0= *v0.on,  vg1=*v1.on;
+    if(NbTry) cout << "bug: s==== " << s << " e=" <<  V0 << " " << V1 << endl;
+
+    //    GeometricalEdge * eg0 = e.on,* eg1 = e.on, *eg=NULL;
+    GeometricalEdge * eg0=on, *eg1=on;
+    R2 Ag=(R2) (*on)[0],Bg=(R2)(*on)[1],AB=Bg-Ag; 
+    if(NbTry) cout <<" G edge= " << Ag << Bg << endl << " v edge" << V01 << " v geom " << AB  <<  (V01,AB) <<endl; 
+    int OppositeSens = (V01,AB) < 0;
+    int sens0=0,sens1=1;
+    if (OppositeSens)
+      s=1-s,Exchange(vg0,vg1),Exchange(V0,V1);
+    // find all the discretisation of the egde 
+#ifdef DEBUG
+    // we supposee  edge on=[Ag,Bg]  intersect edge [V0,V1];
+    // =>   V0Ag.V0V1 > 0 ||  V0Bg.V0V1 >0
+    // =>   V1Ag.V0V1 < 0 ||  V0Bg.V0V1 <0
+    R2 V0V1 = V1-V0;
+    Real8 cos0A = ((Ag-V0),V0V1);
+    Real8 cos0B = ((Bg-V0),V0V1);
+    Real8 cos1A = ((Ag-V1),V0V1);
+    Real8 cos1B = ((Bg-V1),V0V1);
+    if ( (cos0A < 0 && cos0B <0) || (cos1A> 0 && cos1B >0))
+      {
+	cerr << "  Bug on pointer edge  [" << V0 << " , " << V1 << " ] "
+	     << "  on geometrical edge " << Number(on) << " = [" << Ag << " , " << Bg << " ] " << endl;
+	cerr << cos0A << "> 0  ||  " << cos0B <<  " >  0  and  ";
+	cerr << cos1A << "< 0  ||  " << cos1B <<  " <  0  " << endl;
+	
+	exit (1);
+	}
+    
+#endif    
+    if(NbTry) cout << "bug: edge = " << v0.r << " -> " << v1.r << endl 
+		   << "sg 0 = " << vg0 
+		   << " on = " << Number(on) << ":" << Ag << Bg << "; " 
+		   <<  " sg 1= " << vg1 
+		   << "--------------------------------------------" << endl;
+    while (eg0 != (GeometricalEdge*) vg0  &&  (*eg0)(sens0) != (GeometricalVertex*) vg0)
+      { 
+      if (bge<=0) {
+	//          int kkk;
+          // if (NbTry) cout <<"Read (int) to Show Sioux window", cin >> kkk ;
+	       if(NbTry) 
+	          {
+		    cerr << " -- Fatal Error: on the class triangles before call Geometry::ProjectOnCurve" << endl; 
+		    cerr << "   The mesh of the  Geometry is to fine: ";
+		    cerr << "     1)  a mesh edge  contening more than "<< mxe/2 << " geometrical edges." << endl;
+		    cerr << "     2)  code bug : be sure that we call   Triangles::SetVertexFieldOn() before " << endl;
+		    cerr << "   To solve the problem do a coarsening of the geometrical mesh " << endl;
+		    cerr << " or change the constant value of mxe in " << __FILE__ << " line " << MXE__LINE << "( dangerous way )" << endl;	  
+		    MeshError(222);
+		  }
+	    NbTry++;
+	    goto retry;}
+        GeometricalEdge* tmpge = eg0;
+	 if(NbTry)
+		cout << "bug: --Edge @" <<  Number(tmpge)  << " = "<< Number(eg0) << ":" <<Number(eg0->Adj[0]) << "," <<  
+			 Number(eg0->Adj[1]) <<"," ;
+	ge[--bge] =eg0 = eg0->Adj[sens0];
+	assert(bge>=0 && bge <= mxe);
+	sens0 = 1-( sensge[bge] = tmpge->SensAdj[sens0]);
+	if(NbTry)
+		cout << "bug: Edge "  <<  Number(eg0) << " "<< 1-sens0 <<  " S "
+		     << Number((*eg0)[1-sens0]) <<":" << Number(eg0->Adj[0]) << "," 
+		     <<  Number(eg0->Adj[1]) <<"," << endl
+	 	     <<Number(eg0)<< (*eg0)[sens0].r << "v = " << Number((*eg1)(sens0)) << " e = " << eg0 <<  endl;
+     }
+      if(NbTry) cout << Number((GeometricalEdge*) vg1) << " " << Number((GeometricalVertex*) vg1) << endl;
+    while (eg1 != (GeometricalEdge*) vg1  &&  (*eg1)(sens1) != (GeometricalVertex*) vg1)
+      { 
+        if(tge>=mxe ) { 
+	  cerr << " --Fatal Error: on the class triangles before call Geometry::ProjectOnCurve" << endl; 
+	  NbTry++;
+	  if (NbTry<2) goto retry;
+	  cerr << "   The mesh of the  Geometry is to fine:" ;
+	  cerr << "     1)  a mesh edge  contening more than "<< mxe/2 << " geometrical edges." << endl;
+	  cerr << "     2)  code bug : be sure that we call   Triangles::SetVertexFieldOn() before " << endl;
+	  cerr << "   To solve the problem do a coarsening of the geometrical mesh " << endl;
+	  cerr << " or change the constant value of mxe in " << __FILE__ << " line " << MXE__LINE << "( dangerous way )" << endl;	
+	  MeshError(223);
+	}
+
+	GeometricalEdge* tmpge = eg1;
+	if(NbTry)
+		cout << "++Edge @" << tmpge << " = " <<  Number(eg1) <<"%" << Number(eg1->Adj[0]) << "," 
+		 <<  Number(eg1->Adj[1]) <<"," ;
+	ge[++tge] =eg1 = eg1->Adj[sens1];
+	sensge[tge]= sens1 = 1-tmpge->SensAdj[sens1];
+	assert(tge>=0 && tge <= mxe);
+         if(NbTry)
+		cout << "  Edge "  <<  Number(eg1) << " " << sens1 << " S "
+		     <<Number((*eg1)[sens1]) <<"%"<< Number(eg1->Adj[0]) << "," <<  Number(eg1->Adj[1]) <<"," 
+	             <<Number(eg1)<< (*eg1)[sens1].r << "v = " << Number((*eg1)(sens1)) << " e = " << Number(eg1) <<  endl;
+      }
+
+    	if(NbTry)    cout << endl;
+        
+
+    if ( (*eg0)(sens0) == (GeometricalVertex*) vg0 )
+      vg0 = VertexOnGeom( *(Vertex *) vg0,*eg0,sens0);
+    
+    if ( (*eg1)(sens1) == (GeometricalVertex*) vg1)
+       vg1 = VertexOnGeom( *(Vertex *) vg1,*eg1,sens1);
+
+    Real8 sg;
+    //   cout << "           " << Number(on) << " " <<  Number(eg0) << " " <<  Number(eg1) << " "  ; 
+    if (eg0 == eg1) { 
+       register Real8 s0= vg0,s1=vg1;
+       sg =  s0 * (1.0-s) +  s * s1;
+       //    cout <<"                s0=" << s0 << " s1=" << s1 
+       //             << " s = " << s << " sens= " << OppositeSens << "\t\t sg = " << sg << endl ;
+       on=eg0;}
+    else {
+       R2 AA=V0,BB;
+       Real8 s0,s1;
+       
+       //cout << endl << "s= " << s << Number(eg0) << " " << (Real8) vg0 << " " 
+       //	    << Number(eg1) << " " << (Real8) vg1 << V0 << V1 << "  Interpol = " 
+       // << V0*(1-s)+V1*s << ";;; " <<  endl;
+       int i=bge;
+       Real8 ll=0;
+       for(i=bge;i<tge;i++) 
+	 {
+	   assert( i>=0 && i <= mxe);
+	   BB =  (*ge[i])[sensge[i]];
+	   lge[i]=ll += Norme2(AA-BB);
+	   //   cout << " ll " << i << BB << ll << " " <<sensge[i] <<" on = " <<
+	   // Number(ge[i]) << " sens= " << sensge[i] ;
+	   AA=BB ;}
+       lge[tge]=ll+=Norme2(AA-V1); 
+       // cout << " ll " << tge << " " << ll <<  sensge[tge] 
+       //	     <<" on = " << Number(ge[tge]) <<  " sens= " << sensge[tge] << endl;
+    // search the geometrical edge
+      assert(s <= 1.0);
+      Real8 ls= s*ll;
+      on =0;
+      s0 = vg0;
+      s1= sensge[bge];
+      Real8 l0=0,l1;
+      i=bge;
+      while (  (l1=lge[i]) < ls ) {
+	assert(i >= 0 && i <= mxe);
+	i++,s0=1-(s1=sensge[i]),l0=l1;}
+      on=ge[i];
+      if (i==tge) 
+	s1=vg1;
+     
+      s=(ls-l0)/(l1-l0);
+      //  cout << "on =" << Number(on) << sens0 << sens1 <<  "s0  " << s0 << " s1 =" 
+      //	     << s1 << " l0 =" << l0 << " ls= " << ls << " l1= " << l1 << " s= " << s;
+       sg =  s0 * (1.0-s) +  s * s1;    
+       } 
+    assert(on);
+    // assert(sg && sg-1);
+    V.r= on->F(sg);
+    //  if (eg0 != eg1) 
+    //        cout << "----- sg = "<< sg << " Sens =" << OppositeSens << " Edge = " 
+    //     << Number(on) <<"  V=" << V << endl;
+    GV=VertexOnGeom(V,*on,sg);
+    return on;
+ }
+
+void Geometry::AfterRead()
+ {// -----------------
+	 long int verbosity=0;
+
+    if (verbosity>20)
+    cout << "Geometry::AfterRead()" <<  nbv << " " << nbe << endl;
+    Int4 i,k=0;        ;
+    int jj; // jj in [0,1]
+    Int4 * hv = new Int4 [ nbv];
+    Int4 * ev = new Int4 [ 2 * nbe ];
+    float  * eangle = new float[ nbe ];
+    {
+      double eps = 1e-20;
+      QuadTree quadtree; // to find same vertices
+      Vertex * v0 = vertices; 
+      GeometricalVertex  * v0g = (GeometricalVertex  *) (void *) v0;   
+      int k=0;
+      for (i=0;i<nbv;i++) 
+        vertices[i].link = vertices +i;
+      for (i=0;i<nbv;i++) 
+	     {
+	      vertices[i].i = toI2(vertices[i].r); // set integer coordinate
+	      Vertex *v= quadtree.NearestVertex(vertices[i].i.x,vertices[i].i.y); 
+	      if( v && Norme1(v->r - vertices[i]) < eps )
+	       { // link v & vertices[i] 
+	         // vieille ruse pour recuperer j 
+	         GeometricalVertex * vg = (GeometricalVertex  *) (void *) v;
+	         int j = vg-v0g;
+	         assert( v ==  & (Vertex &) vertices[j]);
+	         vertices[i].link = vertices + j;
+            k++;	      
+	       }
+	      else  quadtree.Add(vertices[i]); 
+	     }
+      if (k) {
+	cout << " Number of distinte vertices " << nbv - k << " Over " << nbv << endl;
+	//if (verbosity>10) 
+	{
+	  cout << " The duplicate vertex " << endl;
+	  for (i=0;i<nbv;i++)
+	    if (!vertices[i].IsThe())
+	      cout << " " << i << " and " << Number(vertices[i].The()) << endl;
+	  MeshError(102);
+	  //throw(ErrorExec("exit",1));    
+	}
+      }
+      
+      //  verification of cracked edge
+      int err =0;
+      for (i=0;i<nbe;i++)
+	if (edges[i].Cracked() )
+	  {
+	    //    verification of crack
+	    GeometricalEdge & e1=edges[i];
+	    GeometricalEdge & e2=*e1.link;
+            cerr << i << " " << e1[0].The() << " " << e2[0].The() << " " <<  e1[1].The() << " " << e2[1].The() << endl;
+	    if ( e1[0].The() == e2[0].The() && e1[1].The() == e2[1].The() )
+	      {
+	      }
+	    else 
+	      if ( e1[0].The() == e2[1].The() && e1[1].The() == e2[0].The() )
+		{
+		}
+	      else
+		{
+		  err++;
+		  cerr << " Cracked edges with no same vertex " << &e1-edges << " " << &e2 -edges << endl;
+		}
+	  }
+	else
+	  {
+	    //  if (!edges[i][0].IsThe()) err++;
+	    // if (!edges[i][1].IsThe()) err++;
+	  }
+      if (err)
+	{
+	  cerr << " Some vertex was not distint and not on cracked edge " << err<< endl;
+	  MeshError(222);
+	}
+    }
+    if(verbosity>7) 
+      for (i=0;i<nbv;i++)
+	if (vertices[i].Required())
+	  cout << "     The geo vertices  " << i << " is required" << endl;
+
+    for (i=0;i<nbv;i++) 
+      hv[i]=-1;// empty list
+
+    for (i=0;i<nbe;i++) 
+      {
+        R2 v10  =  edges[i].v[1]->r -  edges[i].v[0]->r;
+        Real8 lv10 = Norme2(v10);
+        if(lv10 == 0) {
+          cerr << "The length  of " <<i<< "th Egde is 0 " << endl ;
+          MeshError(1);}
+        eangle[i] = atan2(v10.y,v10.x)  ; // angle in [ -Pi,Pi ]
+	if(verbosity>9) 
+	  cout << "     angle edge " << i <<" " << eangle[i]*180/Pi<< v10<<endl;
+        for (jj=0;jj<2;jj++)
+          { // generation of list
+            Int4 v =  Number(edges[i].v[jj]);
+            ev[k] = hv[v];
+            hv[v] = k++;
+          }
+      }
+    // bulle sort on the angle of edge  
+    for (i=0;i<nbv;i++) {
+      int exch = 1,ord =0;      
+      while (exch) {
+        exch = 0;
+        Int4  *p =  hv + i, *po = p;
+	Int4 n = *p;
+        register float angleold = -1000 ; // angle = - infini 
+        ord = 0;
+        while (n >=0) 
+        {
+          ord++;
+          register Int4 i1= n /2;
+          register Int4  j1 = n % 2;
+          register Int4 *pn = ev + n;
+          float angle = j1 ? OppositeAngle(eangle[i1]):  eangle[i1];
+          n = *pn;
+          if (angleold > angle) // exch to have : po -> pn -> p 
+            exch=1,*pn = *po,*po=*p,*p=n,po = pn;
+          else //  to have : po -> p -> pn 
+            angleold =  angle, po = p,p  = pn;
+        }
+      } // end while (exch)
+      
+      if (ord >= 1 ) 
+	{ /*
+	  Int4 n = hv[i];
+	  while ( n >=0) 
+	    { Int4 i1 = n/2,j1 = n%2;
+	    //float a = 180*(j1 ? OppositeAngle(eangle[i1]): eangle[i1])/Pi;
+	    n = ev[n];
+	    }
+	  */
+	} 
+      if(ord == 2) { // angulare test to find a corner 
+        Int4 n1 = hv[i];
+        Int4 n2 = ev[n1];
+        Int4 i1 = n1 /2, i2 = n2/2; // edge number
+        Int4  j1 = n1 %2, j2 = n2%2; // vertex in the edge 
+        float angle1= j1 ? OppositeAngle(eangle[i1]) :  eangle[i1];
+        float angle2= !j2 ? OppositeAngle(eangle[i2]) :  eangle[i2];
+	float da12 = Abs(angle2-angle1);
+	if(verbosity>9)
+	  cout <<"     check angle " << i << " " << i1 << " " << i2  << " " << 180*(da12)/Pi 
+	       << " " << 180*MaximalAngleOfCorner/Pi << vertices[i] << endl;
+
+        if (( da12 >= MaximalAngleOfCorner ) 
+            && (da12 <= 2*Pi -MaximalAngleOfCorner)) {
+	  vertices[i].SetCorner() ; 
+	  if(verbosity>7)
+	    cout << "     The vertex " << i << " is a corner (angle) " 
+		 << 180*(da12)/ Pi<< " " << 180*MaximalAngleOfCorner/Pi << endl;}
+	// if the ref a changing then is     SetRequired();
+	
+	if (edges[i1].flag != edges[i2].flag || edges[i1].Required()) 
+	 {
+	  vertices[i].SetRequired();
+	  if(verbosity>7)
+	    cout << "     The vertex " << i << " is Required the flag change (crack or equi, or require)" << endl;}
+	  
+	if (edges[i1].ref != edges[i2].ref) {
+	  vertices[i].SetRequired();
+	  if(verbosity>7)
+	    cout << "     The vertex " << i << " is Required ref" << endl;}
+      } ;
+      
+      if(ord != 2) {
+        vertices[i].SetCorner();
+	if(verbosity>7)
+	  cout << "     the vertex " << i << " is a corner ordre = " << ord << endl;
+      }
+      // close the liste around the vertex 
+      { Int4 no=-1, ne = hv[i];
+        while ( ne >=0) 
+                 ne = ev[no=ne];        
+            if(no>=0) 
+              ev[no] = hv[i];
+          } // now the list around the vertex is circular
+      
+    } // end for (i=0;i<nbv;i++)
+ 
+    k =0;
+    for (i=0;i<nbe;i++)
+      for (jj=0;jj<2;jj++){
+            Int4 n1 = ev[k++]; 
+            Int4 i1 = n1/2 ,j1=n1%2;
+            if( edges[i1].v[j1] != edges[i].v[jj]) 
+              { cerr << " Bug Adj edge " << i << " " << jj << 
+                  " et " << i1 << " " << j1 << " k=" << k;
+                cerr << Number(edges[i].v[jj]) <<" <> " 
+                     << Number(edges[i1].v[j1])  <<endl;
+                cerr << "edge " << Number(edges[i].v[0]) << " " 
+                     << Number(edges[i].v[1]) << endl; 
+            //    cerr << "in file " <<filename <<endl;
+                MeshError(1);
+              }
+            edges[i1].Adj[j1] = edges + i;
+            edges[i1].SensAdj[j1] = jj;
+	    if (verbosity>10)
+	      cout << " edges. Adj " << i1 << " " << j1 << " <--- " << i << " " << jj << endl;
+      }
+    
+    // generation of  all the tangente 
+    for (i=0;i<nbe;i++) {
+        R2 AB = edges[i].v[1]->r -edges[i].v[0]->r;        
+	Real8 lAB = Norme2(AB); // length of current edge AB
+        Real8 ltg2[2];
+        ltg2[0]=0;ltg2[1]=0;
+        for (jj=0;jj<2;jj++) {
+             R2 tg =  edges[i].tg[jj];
+             Real8 ltg = Norme2(tg); // length of tg
+             if(ltg == 0) {// no tg
+	       if( ! edges[i].v[jj]->Corner())   { // not a Corner       
+		 tg =  edges[i].v[1-jj]->r 
+		   - edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r;
+		 ltg =  Norme2(tg);
+		 tg =  tg *(lAB/ltg),ltg=lAB;
+		/*
+		   if(edges[i].ref >=4) 
+		   cout << " tg " << tg.x << " "<< tg.y  << " " << edges[i].v[1-jj]->r << edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r << " y-y = "
+		     << edges[i].v[1-jj]->r.y -edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r.y <<  endl;
+		*/
+	       }
+	       
+	       //else ;// a Corner with no tangent => nothing to do    
+             } // a tg 
+             else 
+               tg = tg *(lAB/ltg),ltg=lAB;
+             ltg2[jj] = ltg;
+             if ( (tg,AB) < 0) 
+               tg = -tg;
+	    //if(edges[i].ref >=4) cout << " tg = " << tg << endl;
+             edges[i].tg[jj] = tg;
+	}     // for (jj=0;jj<2;jj++) 
+	
+	if (ltg2[0]!=0) edges[i].SetTgA();
+	if (ltg2[1]!=0) edges[i].SetTgB();
+    } // for (i=0;i<nbe;i++)
+
+    if(verbosity>7)
+      for (i=0;i<nbv;i++)
+	if (vertices[i].Required())
+	  cout << "     The  geo  vertices " << i << " is required " << endl;
+  
+   for (int step=0;step<2;step++)
+   {
+    for (i=0;i<nbe;i++) 
+      edges[i].SetUnMark();
+    
+    NbOfCurves = 0;
+    Int4  nbgem=0;
+    for (int level=0;level < 2 && nbgem != nbe;level++)
+      for (i=0;i<nbe;i++) {
+	GeometricalEdge & ei = edges[i];   
+	for(jj=0;jj<2;jj++) 
+	  if (!ei.Mark() && (level || ei[jj].Required())) { 
+	    // warning ei.Mark() can be change in loop for(jj=0;jj<2;jj++) 
+	    int k0=jj,k1;
+	    GeometricalEdge *e = & ei;
+	    GeometricalVertex *a=(*e)(k0); // begin 
+	    if(curves) {
+	      curves[NbOfCurves].be=e;
+	      curves[NbOfCurves].kb=k0;
+	    }
+	    int nee=0;
+	    for(;;) { 
+		nee++;
+	      k1 = 1-k0; // next vertex of the edge 
+	      e->SetMark();
+	      nbgem++;
+	      e->CurveNumber=NbOfCurves;
+	      if(curves) {
+	      curves[NbOfCurves].ee=e;
+	      curves[NbOfCurves].ke=k1;
+	      }
+	      
+	      GeometricalVertex *b=(*e)(k1);
+	      if (a == b ||  b->Required() ) break;
+	      k0 = e->SensAdj[k1];//  vertex in next edge
+	      e = e->Adj[k1]; // next edge
+	      
+	    }// for(;;)
+	      if(verbosity>10 && curves==0) cout << NbOfCurves <<" curve :  nb edges=  "<< nee<<  endl; 
+	    NbOfCurves++;
+	    if(level) {
+	      if(verbosity>4)
+		cout << "    Warning: Curve "<< NbOfCurves << " without required vertex " 
+		     << "so the vertex " << Number(a) << " become required " <<endl;
+	      a->SetRequired();
+	    }
+       
+	  }} 
+	  assert(nbgem && nbe);
+
+	  if(step==0) {
+	    curves = new Curve[NbOfCurves];
+	  }
+    	} 
+    for(int i=0;i<NbOfCurves ;i++)
+     {
+       GeometricalEdge * be=curves[i].be, *eqbe=be->link;
+       //GeometricalEdge * ee=curves[i].ee, *eqee=be->link;
+       curves[i].master=true;
+       if(be->Equi() || be->ReverseEqui() ) 
+        {
+          assert(eqbe);
+          int nc = eqbe->CurveNumber;
+          assert(i!=nc);
+          curves[i].next=curves[nc].next;
+          curves[i].master=false;
+          curves[nc].next=curves+i;
+          if(be->ReverseEqui())
+           curves[i].Reverse();           
+        }
+     }
+    	 
+    if(verbosity>3)
+      cout << "    End ReadGeometry: Number of curves in geometry is " << NbOfCurves <<endl; 
+    if(verbosity>4)
+    for(int i=0;i<NbOfCurves ;i++)
+     {
+        cout << " Curve " << i << " begin e=" << Number(curves[i].be) << " k=" << curves[i].kb 
+             << "  end e= " << Number(curves[i].ee) << " k=" << curves[i].ke << endl;
+     }
+    delete []ev;
+    delete []hv;
+    delete []eangle;
+    
+}
+Geometry::~Geometry() 
+{
+	long int verbosity=0;
+
+  assert(NbRef<=0);
+  if(verbosity>9)
+    cout << "DELETE      ~Geometry "<< this  << endl;
+  if(vertices)  delete [] vertices;vertices=0;
+  if(edges)     delete [] edges;edges=0;
+ // if(edgescomponante) delete [] edgescomponante; edgescomponante=0;
+  if(triangles) delete [] triangles;triangles=0;
+  if(quadtree)  delete  quadtree;quadtree=0;
+  if(curves)  delete  []curves;curves=0;NbOfCurves=0;
+  if(name) delete [] name;name=0;
+  if(subdomains) delete [] subdomains;subdomains=0;
+//  if(ordre)     delete [] ordre;
+  EmptyGeometry();
+
+}
+
+Real8 GeometricalEdge::R1tg(Real8 theta,R2 & t) const // 1/R of radius of cuvature
+{ R2 A=v[0]->r,B=v[1]->r;
+ Real8 dca,dcb,dcta,dctb;
+ Real8 ddca,ddcb,ddcta,ddctb;
+ // Real8 t1 = 1 -theta;
+ // Real8 t1t1 = t1*t1;
+ Real8 tt = theta*theta;
+ assert( theta >=0);
+ assert( theta <=1);
+ if (TgA()) 
+  if (TgB()) // interpolation d'hermite
+    { //cb =  theta*theta*(3-2*theta);
+     dcb = 6*theta*(1-theta);
+     ddcb = 6*(1-2*theta);
+     //ca =  1-cb;     
+     dca = -dcb;
+     ddca = -ddcb;
+
+       // cta = (1-theta)*(1-theta)*theta;
+     dcta =  (3*theta - 4)*theta + 1;
+     ddcta=6*theta-4;
+
+     //ctb = (theta-1)*theta*theta ;
+     dctb = 3*tt - 2*theta;
+     ddctb = 6*theta-2;
+    }
+  else { // 1-t*t, t-t*t, t*t
+    Real8 t = theta;
+    // cb = t*t;
+    dcb = 2*t;
+    ddcb = 2;
+    //ca = 1-cb;
+    dca = -dcb;
+    ddca = -2;
+    // cta= t-cb;
+    dcta = 1-dcb;
+    ddcta = -ddcb;
+    // ctb =0;
+    dctb=0;    
+    ddctb=0;    
+  }    
+ else
+  if (TgB()){
+    Real8 t = 1-theta;
+    //ca = t*t;
+    dca = -2*t;
+    ddca = 2;
+    //cb = 1-ca;
+    dcb = -dca;
+    ddcb = -2;
+    //ctb= -t+ca;
+    dctb = 1+dca;
+    ddctb= ddca;
+    //cta=0;    
+    dcta =0;
+    ddcta =0;
+   }
+  else {t=B-A;return 0;} // lagrange P1
+  R2 d =  A*dca + B*dcb + tg[0]* dcta + tg[1] * dctb;
+  
+  R2 dd =  A*ddca + B*ddcb + tg[0]* ddcta + tg[1] * ddctb;
+  Real8 d2=(d,d);
+  Real8 sd2 = sqrt(d2);
+  t=d;
+  if(d2>1.0e-20) {t/=sd2;return Abs(Det(d,dd))/(d2*sd2);}
+  else return 0;
+
+}
+
+
+R2 GeometricalEdge::F(Real8 theta) const // parametrization of the curve edge
+{ R2 A=v[0]->r,B=v[1]->r;
+ Real8 ca,cb,cta,ctb;
+ assert( theta >=-1e-12);
+ assert( theta <=1+1e-12);
+ if (TgA()) 
+  if (TgB()) // interpolation d'hermite
+   { cb =  theta*theta*(3-2*theta);
+     ca =  1-cb;     
+     cta = (1-theta)*(1-theta)*theta;
+     ctb = (theta-1)*theta*theta ;
+   //  if(ref==4 || ref==5)
+   //  cout << " FFF " << tg[0] << tg[1] << A << B << " => " << A*ca + B*cb + tg[0]* cta + tg[1] * ctb << endl;
+    }
+  else { // 1-t*t, t-t*t, t*t
+    Real8 t = theta;
+    cb = t*t;
+    ca = 1-cb;
+    cta= t-cb;
+    ctb=0;    
+  }    
+ else
+  if (TgB()){
+    Real8 t = 1-theta;
+    ca = t*t;
+    cb = 1-ca;
+    ctb= -t+ca;
+    cta=0;    
+   }
+  else {
+      ca =(1-theta),cb = theta,cta=ctb=0; // lagrange P1
+   }
+ return A*ca + B*cb + tg[0]* cta + tg[1] * ctb;
+
+}
+
+}
Index: /issm/trunk/src/c/Bamgx/MeshQuad.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/MeshQuad.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/MeshQuad.cpp	(revision 2740)
@@ -0,0 +1,947 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+// ********** DO NOT REMOVE THIS BANNER **********
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// SUMMARY: Bamg: Bidimensional Anisotrope Mesh Generator
+// RELEASE: 0 
+// AUTHOR:   F. Hecht,    
+// ORG    :  UMPC
+// E-MAIL :   Frederic.Hecht@Inria.fr   
+//
+// ORIG-DATE:     frev 98
+//---------------------------------------------------------
+//  to make quad 
+// -------------------
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+
+namespace bamg {
+
+static const  Direction NoDirOfSearch=Direction();
+
+#ifdef __MWERKS__
+#pragma global_optimizer on
+#pragma optimization_level 1
+//#pragma inline_depth 0
+#endif
+
+class DoubleAndInt4 {
+public: double q; Int4 i3j;
+  int operator<(DoubleAndInt4 a){return q > a.q;}
+};// to sort by decroissant
+
+
+
+template<class T>  inline void  HeapSort(T *c,long n)
+{
+  long l,j,r,i;
+  T crit;
+  c--; // on decale de 1 pour que le tableau commence a 1
+  if( n <= 1) return;
+  l = n/2 + 1;
+  r = n;
+  while (1) { // label 2
+    if(l <= 1 ) { // label 20
+      crit = c[r];
+      c[r--] = c[1];
+    if ( r == 1 ) { c[1]=crit; return;}
+    } else  crit = c[--l]; 
+    j=l;
+    while (1) {// label 4
+      i=j;
+      j=2*j;
+      if  (j>r) {c[i]=crit;break;} // L8 -> G2
+      if ((j<r) && (c[j] < c[j+1])) j++; // L5
+      if (crit < c[j]) c[i]=c[j]; // L6+1 G4
+      else {c[i]=crit;break;} //L8 -> G2
+    }
+  }
+}
+
+Triangle * swapTest(Triangle *t1,Int2 a);
+// 
+
+
+double QuadQuality(const Vertex & a,const Vertex &b,const Vertex &c,const Vertex &d)
+{
+  // calcul de 4 angles --
+  R2 A((R2)a),B((R2)b),C((R2)c),D((R2)d);
+  R2 AB(B-A),BC(C-B),CD(D-C),DA(A-D);
+  //  Move(A),Line(B),Line(C),Line(D),Line(A);
+  const Metric & Ma  = a;
+  const Metric & Mb  = b;
+  const Metric & Mc  = c;
+  const Metric & Md  = d;
+    
+  double lAB=Norme2(AB);
+  double lBC=Norme2(BC);
+  double lCD=Norme2(CD);
+  double lDA=Norme2(DA);
+  AB /= lAB;  BC /= lBC;  CD /= lCD;  DA /= lDA;
+  // version aniso 
+  double cosDAB= Ma(DA,AB)/(Ma(DA)*Ma(AB)),sinDAB= Det(DA,AB);
+  double cosABC= Mb(AB,BC)/(Mb(AB)*Mb(BC)),sinABC= Det(AB,BC);
+  double cosBCD= Mc(BC,CD)/(Mc(BC)*Mc(CD)),sinBCD= Det(BC,CD);
+  double cosCDA= Md(CD,DA)/(Md(CD)*Md(DA)),sinCDA= Det(CD,DA);
+  double sinmin=Min(Min(sinDAB,sinABC),Min(sinBCD,sinCDA));
+  // cout << A << B << C << D ;
+  // cout << " sinmin " << sinmin << " " << cosDAB << " " << cosABC << " " << cosBCD << " " << cosCDA << endl;
+  // rattente(1);
+  if (sinmin<=0) return sinmin;
+  return 1.0-Max(Max(Abs(cosDAB),Abs(cosABC)),Max(Abs(cosBCD),Abs(cosCDA)));
+}
+
+ GeometricalEdge *   Triangles::ProjectOnCurve( Edge & BhAB, Vertex &  vA, Vertex & vB,
+						Real8 theta,
+						Vertex & R,VertexOnEdge &  BR,VertexOnGeom & GR) 
+                      
+{
+   void *pA=0,*pB=0;
+   Real8 tA=0,tB=0;
+   R2 A=vA,B=vB;
+    Vertex * pvA=&vA, * pvB=&vB;
+  if (vA.vint == IsVertexOnVertex)
+    {
+      //  cout << " Debut vertex = " << BTh.Number(vA.onbv) ;
+      pA=vA.onbv;
+    }
+  else if (vA.vint == IsVertexOnEdge)
+    {
+      pA=vA.onbe->be;
+      tA=vA.onbe->abcisse;
+      // cout << " Debut edge = " << BTh.Number(vA.onbv) << " " << tA ;
+
+    }
+  else
+    {cerr << "ProjectOnCurve On Vertex " << BTh.Number(vA) << " " << endl;
+     cerr << " forget call to SetVertexFieldOnBTh" << endl;
+     MeshError(-1);
+    } 
+    
+  if (vB.vint == IsVertexOnVertex)
+    {
+      // cout << " Fin vertex = " << BTh.Number(vB.onbv) << endl;
+      pB=vB.onbv;
+    }
+  else if(vB.vint == IsVertexOnEdge)
+    {
+      pB=vB.onbe->be;
+      tB=vB.onbe->abcisse;
+      // cout << " Fin edge = " << BTh.Number(vB.onbe->be) << " " <<  tB ;
+
+    }
+  else
+    {cerr << "ProjectOnCurve On Vertex " << BTh.Number(vB) << " " << endl;
+     cerr << " forget call to SetVertexFieldOnBTh" << endl;
+     MeshError(-1);
+    } 
+  Edge * e = &BhAB;
+ assert( pA && pB && e);
+ // be carefull the back ground edge e is on same geom edge 
+ // of the initiale edge def by the 2 vertex A B;
+ assert(e>=BTh.edges && e<BTh.edges+BTh.nbe);// Is a background Mesh;   
+// walk on BTh edge 
+ //assert(0 /* not finish ProjectOnCurve with BackGround Mesh*/);
+// 1 first find a back ground edge contening the vertex A
+// 2 walk n back gound boundary to find the final vertex B
+
+
+#ifdef DEBUG
+// we suppose if the vertex A is on a background edge and
+// the abcisse is 0 or 1 when the related point is not
+// a end of curve <=>  !IsRequiredVertex
+    if (vA.vint == IsVertexOnEdge)
+      if (tA<=0)
+	assert(! (*vA.onbe->be)[0].on->IsRequiredVertex());
+      else if (tA>=1) 
+      	assert(!(*vA.onbe->be)[1].on->IsRequiredVertex());
+#endif
+
+     if( vA.vint == IsVertexOnEdge) 
+       { // find the start edge 
+	     e = vA.onbe->be;	 
+
+       } 
+     else if (vB.vint == IsVertexOnEdge) 
+       {
+         theta = 1-theta;
+	 Exchange(tA,tB);
+	 Exchange(pA,pB);
+	 Exchange(pvA,pvB);
+	 Exchange(A,B);
+	 e =  vB.onbe->be;
+
+	 // cout << " EXCHANGE  A et B) " << endl;
+       } 
+     else
+       { // do the search by walking 
+	 assert(0 /* A FAIRE */);
+       }
+
+     // find the direction of walking with sens of edge and pA,PB;
+   R2 AB=B-A;
+
+   Real8 cosE01AB = (( (R2) (*e)[1] - (R2) (*e)[0] ) , AB);
+   int kkk=0;
+   int sens = (cosE01AB>0) ? 1 : 0;
+ 
+   //   Real8 l=0; // length of the edge AB
+   Real8 abscisse = -1;
+ 
+   for (int cas=0;cas<2;cas++)
+     {// 2 times algo:
+       //    1 for computing the length l
+       //    2 for find the vertex 
+       int  iii;
+        Vertex  *v0=pvA,*v1; 
+       Edge *neee,*eee;
+       Real8 lg =0; // length of the curve 
+       Real8 te0;
+       // we suppose take the curve's abcisse 
+       // cout << kkk << " e = " << BTh.Number(e) << "  v0=  " 
+       //    << BTh.Number(v0) << " v1 = " << BTh.Number((*e)[sens]) << endl;
+       for ( eee=e,iii=sens,te0=tA;
+             eee && ((( void*) eee) != pB) && (( void*) (v1=&((*eee)[iii]))) != pB ;
+             neee = eee->adj[iii],iii = 1-neee->Intersection(*eee),eee = neee,v0=v1,te0=1-iii )   
+	      { 
+		//	cout << kkk << " eee = " << BTh.Number(eee) << "  v0=  " 
+		//     << BTh.Number(v0) << " v1 = " << BTh.Number(v1) << endl;
+		
+		assert(kkk++<100);
+		assert(eee);
+		Real8 lg0 = lg;
+		Real8 dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
+	     	lg += dp;
+		if (cas && abscisse <= lg)
+		  { // ok we find the geom edge 
+		    Real8 sss  =   (abscisse-lg0)/dp;
+		    Real8 thetab = te0*(1-sss)+ sss*iii;
+		    assert(thetab>=0 && thetab<=1);
+		    BR = VertexOnEdge(&R,eee,thetab);
+
+		    // cout << Number(R) << " = " <<  thetab << " on  " <<  BTh.Number(eee)
+		    //	 << " = " << R << endl;
+
+		    return  Gh.ProjectOnCurve(*eee,thetab,R,GR);
+
+		  }
+	      }
+       // we find the end 
+       if (v1 != pvB) 
+	 {
+	   if (( void*) v1 == pB)
+	      tB = iii;
+	     
+	   Real8 lg0 = lg;
+	   assert(eee);
+	   v1 = pvB;
+	   Real8 dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
+	   lg += dp;	
+	   abscisse = lg*theta;
+	   if (abscisse <= lg && abscisse >= lg0 ) // small optimisation we know the lenght because end
+	     { // ok we find the geom edge 
+	       Real8 sss  =   (abscisse-lg0)/dp;
+	       Real8 thetab = te0*(1-sss)+ sss*tB;
+	       assert(thetab>=0 && thetab<=1);
+	       BR = VertexOnEdge(&R,eee,thetab);
+	      
+	       //	cout << kkk << " eee = " << BTh.Number(eee) << "  v0=  " 
+	       //     << BTh.Number(v0) << " " << te0
+	       //      << " v1 = " << BTh.Number(v1) <<  " " << tB  << endl;
+
+	       //out << Number(R) << " Opt  = " <<  thetab << " on  " <<  BTh.Number(eee) 
+	       //	    << " = " << R << endl;
+
+	       return  Gh.ProjectOnCurve(*eee,thetab,R,GR);
+	     }
+	 }
+       abscisse = lg*theta;
+       
+     }
+   cerr << " Big Bug" << endl;
+   MeshError(678);
+   return 0; // just for the compiler 
+      
+}                  
+
+
+void Triangles::MakeQuadrangles(double costheta)
+{
+	long int verbosity=0;
+
+  if (verbosity>2) 
+    cout << "  -- MakeQuadrangles costheta = " << costheta << endl;
+  if (verbosity>5)  
+    cout << "    (in)  Nb of Quadrilaterals = " << NbOfQuad 
+	 << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+         << " Nb of outside triangles = " << NbOutT << endl;
+
+  if (costheta >1) {
+    if (verbosity>5)
+      cout << "     do nothing costheta >1 "<< endl;
+    return;}
+
+  
+  Int4 nbqq = (nbt*3)/2;
+  DoubleAndInt4  *qq = new DoubleAndInt4[nbqq];
+
+  Int4 i,ij;
+  int j;
+  Int4 k=0;
+  for (i=0;i<nbt;i++)
+    for (j=0;j<3;j++)
+      if ((qq[k].q=triangles[i].QualityQuad(j))>=costheta)
+ 	   qq[k++].i3j=i*3+j;
+//  sort  qq
+  HeapSort(qq,k);
+  
+  Int4 kk=0;
+  for (ij=0;ij<k;ij++)
+    { 
+      //      cout << qq[ij].q << " " << endl;
+      i=qq[ij].i3j/3;
+      j=(int) (qq[ij].i3j%3);
+      // optisamition no float computation  
+      if (triangles[i].QualityQuad(j,0) >=costheta) 
+        triangles[i].SetHidden(j),kk++;
+    }
+  NbOfQuad = kk;
+  if (verbosity>2) 
+    {
+    cout << "    (out)  Nb of Quadrilaterals = " << NbOfQuad 
+	 << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+         << " Nb of outside triangles = " << NbOutT << endl;
+    }
+  delete [] qq;
+#ifdef DRAWING2 
+  Draw();
+  inquire();
+#endif
+
+}
+/*
+Triangles::BThBoundary(Edge e,Real 8) const 
+{
+  // pointeur of the background must be on 
+  // 
+  Edge be = e.on;
+}
+*/
+int  Triangles::SplitElement(int choice)
+{
+	long int verbosity=0;
+
+  Direction NoDirOfSearch;
+  const  int withBackground = &BTh != this && &BTh;
+ if (verbosity>2) 
+   cout << "  -- SplitElement " << (choice? " Q->4Q and T->4T " : " Q->4Q or T->3Q " ) << endl;;
+ if (verbosity>5)
+   cout << endl << "    (in)  Nb of Quadrilaterals = " << NbOfQuad 
+	<< " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+	<< " Nb of outside triangles = " << NbOutT << endl;
+ 
+ ReNumberingTheTriangleBySubDomain();
+#ifdef DRAWING2 
+  Draw();
+ inquire();
+#endif
+ //int nswap =0;
+  const Int4 nfortria( choice ? 4 : 6);
+    if(withBackground) 
+    {
+      BTh.SetVertexFieldOn();
+      SetVertexFieldOnBTh();
+    }
+   else
+     BTh.SetVertexFieldOn();
+   
+  Int4 newnbt=0,newnbv=0;
+  Int4 * kedge = 0;
+ Int4 newNbOfQuad=NbOfQuad;
+  Int4 * ksplit= 0, * ksplitarray=0;
+  Int4 kkk=0;
+  int ret =0;
+  if (nbvx<nbv+nbe) return 1;//   
+  Triangles *  OCurrentTh= CurrentTh;
+  CurrentTh = this;
+  // 1) create  the new points by spliting the internal edges 
+  // set the 
+  Int4 nbvold = nbv;
+  Int4 nbtold = nbt;
+  Int4 NbOutTold  = NbOutT;
+  Int4  NbEdgeOnGeom=0;
+  Int4 i;
+  
+  nbt = nbt - NbOutT; // remove all the  the ouside triangles 
+  Int4 nbtsave = nbt;
+  Triangle * lastT = triangles + nbt;
+  for (i=0;i<nbe;i++)
+    if(edges[i].on) NbEdgeOnGeom++;
+  Int4 newnbe=nbe+nbe;
+  //  Int4 newNbVerticesOnGeomVertex=NbVerticesOnGeomVertex;
+  Int4 newNbVerticesOnGeomEdge=NbVerticesOnGeomEdge+NbEdgeOnGeom;
+  // Int4 newNbVertexOnBThVertex=NbVertexOnBThVertex;
+  Int4 newNbVertexOnBThEdge=withBackground ? NbVertexOnBThEdge+NbEdgeOnGeom:0;
+
+  // do allocation for pointeur to the geometry and background
+  VertexOnGeom * newVerticesOnGeomEdge = new VertexOnGeom[newNbVerticesOnGeomEdge];
+  VertexOnEdge *newVertexOnBThEdge = newNbVertexOnBThEdge ?  new VertexOnEdge[newNbVertexOnBThEdge]:0;
+  if (NbVerticesOnGeomEdge)
+    memcpy(newVerticesOnGeomEdge,VerticesOnGeomEdge,sizeof(VertexOnGeom)*NbVerticesOnGeomEdge);
+  if (NbVertexOnBThEdge)
+    memcpy(newVertexOnBThEdge,VertexOnBThEdge,sizeof(VertexOnEdge)*NbVertexOnBThEdge);
+  Edge *newedges = new Edge [newnbe];
+  //  memcpy(newedges,edges,sizeof(Edge)*nbe);
+  SetOfEdges4 * edge4= new SetOfEdges4(nbe,nbv);
+#ifdef DEBUG
+  for (i=0;i<nbt;i++)
+    triangles[i].check();
+#endif
+#ifdef DRAWING2  
+  reffecran();
+#endif  
+  Int4 k=nbv;
+  Int4 kk=0;
+  Int4 kvb = NbVertexOnBThEdge;
+  Int4 kvg = NbVerticesOnGeomEdge;
+  Int4 ie =0;
+  Edge ** edgesGtoB=0;
+  if (withBackground)
+   edgesGtoB= BTh.MakeGeometricalEdgeToEdge();
+  Int4 ferr=0;
+  for (i=0;i<nbe;i++)
+     newedges[ie].on=0;
+
+  for (i=0;i<nbe;i++)
+    {
+      GeometricalEdge *ong =  edges[i].on;
+
+      newedges[ie]=edges[i];
+      newedges[ie].adj[0]=newedges+(edges[i].adj[0]-edges) ;
+      newedges[ie].adj[1]=newedges + ie +1;
+      R2 A = edges[i][0],B = edges[i][1];
+      // cout << " ie = " << ie <<"  v0 = " <<  Number(newedges[ie][0]) << endl;
+
+
+      kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1])));
+      if (ong) // a geometrical edges 
+	{ 
+	  if (withBackground)
+	    {
+	      // walk on back ground mesh 
+	      //  newVertexOnBThEdge[ibe++] = VertexOnEdge(vertices[k],bedge,absicsseonBedge); 
+	      // a faire -- difficile 
+	      // the first PB is to now a background edge between the 2 vertices
+	      assert(edgesGtoB); 
+	      // cout << " ie = " << ie <<"  v0 = " <<  Number(newedges[ie][0]) << endl;
+             ong= ProjectOnCurve(*edgesGtoB[Gh.Number(edges[i].on)],
+			     edges[i][0],edges[i][1],0.5,vertices[k],
+                             newVertexOnBThEdge[kvb],
+                             newVerticesOnGeomEdge[kvg++]);
+	     vertices[k].ReferenceNumber= edges[i].ref;
+	     vertices[k].DirOfSearch =   NoDirOfSearch;        
+;
+	     // get the Info on background mesh 
+	     Real8 s =        newVertexOnBThEdge[kvb];
+	     Vertex &  bv0  = newVertexOnBThEdge[kvb][0];
+	     Vertex &  bv1  = newVertexOnBThEdge[kvb][1];
+	     // compute the metrix of the new points 
+	     vertices[k].m =  Metric(1-s,bv0,s,bv1); 
+	     kvb++;
+	     // cout << " ie = " << ie <<"  v0 = " <<  Number(newedges[ie][0]) << endl;
+	    }
+	  else 
+	    {
+	      ong=Gh.ProjectOnCurve(edges[i],
+				    0.5,vertices[k],newVerticesOnGeomEdge[kvg++]);
+	      // vertices[k].i = toI2( vertices[k].r);
+	      vertices[k].ReferenceNumber = edges[i].ref;
+	      vertices[k].DirOfSearch = NoDirOfSearch;
+	      vertices[k].m =  Metric(0.5,edges[i][0],0.5,edges[i][1]);	      
+	    }  
+	}
+      else // straigth line edge ---
+	{ 
+	  vertices[k].r = ((R2) edges[i][0] + (R2)  edges[i][1] )*0.5;
+	  vertices[k].m =  Metric(0.5,edges[i][0],0.5,edges[i][1]);
+	  vertices[k].on = 0;
+	}
+      //vertices[k].i = toI2( vertices[k].r);
+      R2 AB =  vertices[k].r;
+      R2 AA = (A+AB)*0.5;
+      R2 BB = (AB+B)*0.5;
+      vertices[k].ReferenceNumber = edges[i].ref;
+	    vertices[k].DirOfSearch = NoDirOfSearch;
+	    
+      newedges[ie].on = Gh.Contening(AA,ong);
+      newedges[ie++].v[1]=vertices+k;
+
+      newedges[ie]=edges[i];
+      newedges[ie].adj[0]=newedges + ie -1;
+      newedges[ie].adj[1]=newedges+(edges[i].adj[1]-edges) ;
+      newedges[ie].on =  Gh.Contening(BB,ong);
+      newedges[ie++].v[0]=vertices+k;
+      // cout << " ie = " << ie-2 << " vm " << k << " v0 = " <<  Number(newedges[ie-2][0])
+      //	   << " v1 = " << Number(newedges[ie-1][1])  
+      //	   << " ong =" << ong-Gh.edges 
+      //	   << " on 0 =" <<  newedges[ie-2].on -Gh.edges << AA
+      //	   << " on 1 =" <<  newedges[ie-1].on -Gh.edges << BB 
+      //	   << endl;
+      k++;
+    }
+#ifdef DEBUG
+  assert(kvb ==  newNbVertexOnBThEdge);
+  // verif edge 
+  { Vertex *v0 = vertices, *v1 = vertices+ k;
+    for (Int4  i=0;i<ie;i++)
+     {
+       assert( &newedges[i][0] >= v0 &&  &newedges[i][0] < v1);
+       assert( &newedges[i][1] >= v0 &&  &newedges[i][1] < v1);
+     }
+  }
+#endif
+  if (edgesGtoB) delete [] edgesGtoB;
+  edgesGtoB=0;
+
+  newnbv=k;
+  newNbVerticesOnGeomEdge=kvg;
+  if (newnbv> nbvx) goto Error;// bug 
+    
+  nbv = k;
+
+
+  kedge = new Int4[3*nbt+1];
+  ksplitarray = new Int4[nbt+1];
+  ksplit = ksplitarray +1; // because ksplit[-1] == ksplitarray[0]
+ 
+  for (i=0;i<3*nbt;i++)
+    kedge[i]=-1;
+
+  //  
+
+ for (i=0;i<nbt;i++)
+   {  
+
+     Triangle & t = triangles[i];
+     assert(t.link);
+     for(int j=0;j<3;j++)
+       {
+	 const TriangleAdjacent ta = t.Adj(j);
+	 const Triangle & tt = ta;
+	 if (&tt >= lastT)
+	   t.SetAdj2(j,0,0);// unset adj
+	 const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]];
+	 const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]];
+	 Int4  ke =edge4->findtrie(Number(v0),Number(v1));
+	 if (ke>0) 
+	   {
+	     Int4 ii = Number(tt);
+	     int  jj = ta;
+	     Int4 ks = ke + nbvold;
+	     kedge[3*i+j] = ks;
+	     if (ii<nbt) // good triangle
+	       kedge[3*ii+jj] = ks;
+	     Vertex &A=vertices[ks];
+	     Real8 aa,bb,cc,dd;
+	     if ((dd=Area2(v0.r,v1.r,A.r)) >=0)
+	       { // warning PB roundoff error 
+		 if (t.link && ( (aa=Area2( A.r    , t[1].r , t[2].r )) < 0.0 
+				||   (bb=Area2( t[0].r , A.r    , t[2].r )) < 0.0  
+				||   (cc=Area2( t[0].r , t[1].r , A.r    )) < 0.0))
+		   ferr++, cerr << " Error : " <<  ke + nbvold << " not in triangle " 
+				<< i << " In=" << !!t.link
+				<< " " <<  aa  << " " << bb << " " << cc << " " << dd << endl;
+		 
+	       }
+	     
+	     else
+	       {
+		 if (tt.link && ( (aa=Area2( A.r     , tt[1].r , tt[2].r )) < 0 
+				 ||   (bb=Area2( tt[0].r , A.r     , tt[2].r )) < 0 
+				 ||   (cc=Area2( tt[0].r , tt[1].r , A.r     )) < 0)) 
+		   ferr++, cerr << " Warning : " <<  ke + nbvold << " not in triangle " << ii 
+				<< " In=" << !!tt.link 
+				<< " " <<  aa  << " " << bb << " " << cc << " " << dd << endl;
+				
+	       } 
+	     
+	   }
+       }
+   }
+  if(ferr)
+    {
+      cerr << " Number of triangles with P2 interpolation Probleme " << ferr << endl;;
+      MeshError(9);
+    }
+
+  for (i=0;i<nbt;i++)
+    {
+      ksplit[i]=1; // no split by default
+      const Triangle & t = triangles[ i];
+      // cout << " Triangle " << i << " " << t  << !!t.link << ":: " ;
+      int nbsplitedge =0;
+      int nbinvisible =0;
+      int invisibleedge=0;
+      int kkk[3];      
+      for (int j=0;j<3;j++)
+	{
+	  if (t.Hidden(j)) invisibleedge=j,nbinvisible++;
+	  
+	  const TriangleAdjacent ta = t.Adj(j);
+	  const Triangle & tt = ta;
+
+	  
+	  const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]];
+	  const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]];
+	 //  cout << " ke = " << kedge[3*i+j]  << " " << Number(v0) << " " << Number(v1) << "/ ";
+	  if ( kedge[3*i+j] < 0) 
+	    {
+	      Int4  ke =edge4->findtrie(Number(v0),Number(v1));
+	      //  cout << ":" << ke << "," << !!t.link << " " <<  &tt ;
+	      if (ke<0) // new 
+		{
+		  if (&tt) // internal triangles all the boundary 
+		      { // new internal edges 
+			Int4 ii = Number(tt);
+			int  jj = ta;
+	      
+			kedge[3*i+j]=k;// save the vertex number 
+			kedge[3*ii+jj]=k;
+			if (k<nbvx) 
+			  {
+			    vertices[k].r = ((R2) v0+(R2) v1 )/2;
+			    //vertices[k].i = toI2( vertices[k].r);
+			    vertices[k].ReferenceNumber=0;
+	        vertices[k].DirOfSearch =NoDirOfSearch;
+			    vertices[k].m =  Metric(0.5,v0,0.5,v1);
+			  }
+			k++;
+			kkk[nbsplitedge++]=j;		      
+		    } // tt 
+		  else
+		    cerr <<endl <<  " Bug " <<i<< " " << j << " t=" << t << endl;
+		  
+		} // ke<0	       
+	      else
+		{ // ke >=0
+		  kedge[3*i+j]=nbvold+ke;
+		  kkk[nbsplitedge++]=j;// previously splited
+		}
+	    }
+	  else 
+	    kkk[nbsplitedge++]=j;// previously splited
+	  
+	} 
+      assert (nbinvisible<2);
+     // cout << " " <<  nbinvisible << " " <<  nbsplitedge << endl;
+      switch (nbsplitedge) {
+      case 0: ksplit[i]=10; newnbt++; break;   // nosplit
+      case 1: ksplit[i]=20+kkk[0];newnbt += 2; break; // split in 2 
+      case 2: ksplit[i]=30+3-kkk[0]-kkk[1];newnbt += 3; break; // split in 3 
+      case 3:
+	if (nbinvisible) ksplit[i]=40+invisibleedge,newnbt += 4;
+	else   ksplit[i]=10*nfortria,newnbt+=nfortria;
+	break;
+      } 
+    assert(ksplit[i]>=40);
+    }
+  //  now do the element split
+  newNbOfQuad = 4*NbOfQuad;
+  nbv = k;
+#ifdef DRAWING2  
+  inquire();
+#endif  
+//  cout << " Nbv = " << nbv << endl;
+  kkk = nbt;
+  ksplit[-1] = nbt;
+  // look on  old true  triangles 
+
+  for (i=0;i<nbtsave;i++)
+    {
+      //     cout << "Triangle " << i << " " << ksplit[i] << ":" << triangles[i]
+      //	   << "  ----------------------------------------------- " <<endl;
+      // Triangle * tc=0;
+      int  nbmkadj=0;
+      Int4 mkadj [100];
+      mkadj[0]=i;
+      Int4 kk=ksplit[i]/10;
+      int  ke=(int) (ksplit[i]%10);
+      assert(kk<7 && kk >0);
+      
+      // def the numbering   k (edge) i vertex 
+      int k0 = ke;
+      int k1 = NextEdge[k0];
+      int k2 = PreviousEdge[k0];
+      int i0 = OppositeVertex[k0];
+      int i1 = OppositeVertex[k1];
+      int i2 = OppositeVertex[k2];
+       
+       Triangle &t0=triangles[i];
+       Vertex * v0=t0(i0);           
+       Vertex * v1=t0(i1);           
+       Vertex * v2=t0(i2);
+
+       // cout << "nbmkadj " << nbmkadj << " it=" << i <<endl;
+       assert(nbmkadj< 10);
+       // --------------------------
+       TriangleAdjacent ta0(t0.Adj(i0)),ta1(t0.Adj(i1)),ta2(t0.Adj(i2));
+       // save the flag Hidden
+       int hid[]={t0.Hidden(0),t0.Hidden(1),t0.Hidden(2)};
+       // un set all adj -- save Hidden flag --
+       t0.SetAdj2(0,0,hid[0]);
+       t0.SetAdj2(1,0,hid[1]);
+       t0.SetAdj2(2,0,hid[2]);
+       // --  remake 
+       switch  (kk) {
+       case 1: break;// nothing 
+       case 2: // 
+	 {
+	   Triangle &t1=triangles[kkk++];
+	   t1=t0;
+	   assert (kedge[3*i+i0]>=0);
+	   Vertex * v3 = vertices + kedge[3*i+k0];
+	   
+	   t0(i2) = v3;
+	   t1(i1) = v3;
+	   t0.SetAllFlag(k2,0);
+	   t1.SetAllFlag(k1,0);
+	 } 
+	 break; 
+       case 3: //
+	 {
+	   Triangle &t1=triangles[kkk++];
+            Triangle &t2=triangles[kkk++];
+            t2=t1=t0;
+            assert (kedge[3*i+k1]>=0);
+            assert (kedge[3*i+k2]>=0);
+            
+            Vertex * v01 = vertices + kedge[3*i+k2];
+            Vertex * v02 = vertices + kedge[3*i+k1]; 
+            t0(i1) = v01; 
+            t0(i2) = v02; 
+            t1(i2) = v02;
+            t1(i0) = v01; 
+            t2(i0) = v02; 
+	    t0.SetAllFlag(k0,0);
+	    t1.SetAllFlag(k1,0);
+	    t1.SetAllFlag(k0,0);
+	    t2.SetAllFlag(k2,0);
+	 } 
+	 break;
+       case 4: // 
+       case 6: // split in 4 
+	 {
+	   Triangle &t1=triangles[kkk++];
+	   Triangle &t2=triangles[kkk++];
+	   Triangle &t3=triangles[kkk++];
+	   t3=t2=t1=t0;
+	   assert(kedge[3*i+k0] >=0 && kedge[3*i+k1] >=0 && kedge[3*i+k2] >=0);
+	   Vertex * v12 = vertices + kedge[3*i+k0];
+	   Vertex * v02 = vertices + kedge[3*i+k1]; 
+	   Vertex * v01 = vertices + kedge[3*i+k2];
+	   // cout << Number(t0(i0))  << " " << Number(t0(i1)) 
+	   //     << " " <<  Number(t0(i2)) 
+	   //     << " " <<  kedge[3*i+k0] 
+	   //     << " " <<  kedge[3*i+k1] 
+	   //     << " " <<  kedge[3*i+k2] << endl;
+	   t0(i1) = v01;
+	   t0(i2) = v02;
+	   t0.SetAllFlag(k0,hid[k0]);
+
+	   t1(i0) = v01;
+	   t1(i2) = v12;
+	   t0.SetAllFlag(k1,hid[k1]);
+	   
+	   t2(i0) = v02;
+	   t2(i1) = v12;
+	   t2.SetAllFlag(k2,hid[k2]);
+	   
+	   t3(i0) = v12;
+	   t3(i1) = v02;
+	   t3(i2) = v01;
+	   	   
+	   t3.SetAllFlag(0,hid[0]);	   
+	   t3.SetAllFlag(1,hid[1]);	   
+	   t3.SetAllFlag(2,hid[2]);
+
+	   if ( kk == 6)
+	     {
+	       
+	       Triangle &t4=triangles[kkk++];
+	       Triangle &t5=triangles[kkk++];
+	       
+	       t4 = t3;
+	       t5 = t3;
+
+	       t0.SetHidden(k0);
+	       t1.SetHidden(k1);
+	       t2.SetHidden(k2);
+	       t3.SetHidden(0);
+	       t4.SetHidden(1);
+	       t5.SetHidden(2);
+	       
+		if (nbv < nbvx ) 
+		  {
+		    vertices[nbv].r = ((R2) *v01 + (R2) *v12  + (R2) *v02 ) / 3.0;
+		    vertices[nbv].ReferenceNumber =0;
+	      vertices[nbv].DirOfSearch =NoDirOfSearch;
+		    //vertices[nbv].i = toI2(vertices[nbv].r);
+		    Real8 a3[]={1./3.,1./3.,1./3.};
+		    vertices[nbv].m = Metric(a3,v0->m,v1->m,v2->m);
+		    Vertex * vc =  vertices +nbv++;
+		    t3(i0) = vc;
+		    t4(i1) = vc;
+		    t5(i2) = vc;
+
+		  }
+		else
+		  goto Error; 
+	     }
+		    
+	 } 
+	 break;         
+       }
+ 
+       // cout << "  -- " << i << " " << nbmkadj << " " << kkk << " " << tc << endl;
+       //  t0.SetDetf();
+       // save all the new triangles
+       mkadj[nbmkadj++]=i;
+       Int4 jj;
+       if (t0.link) 
+	 for (jj=nbt;jj<kkk;jj++)
+	   {
+	     triangles[jj].link=t0.link;
+	     t0.link= triangles+jj;
+	     mkadj[nbmkadj++]=jj;
+	     // triangles[jj].SetDet();
+	   }
+       // cout << "  -- " << i << " " << nbmkadj << endl;
+       assert(nbmkadj<=13);// 13 = 6 + 4 + 3
+  
+       if (kk==6)  newNbOfQuad+=3;
+	 //	 triangles[i].Draw();       
+
+       for (jj=ksplit[i-1];jj<kkk;jj++)
+	 // triangles[jj].SetDet();
+       //	   triangles[jj].Draw();
+	 
+
+
+       nbt = kkk;
+       ksplit[i]= nbt; // save last adresse of the new triangles
+       kkk = nbt;
+       
+    }
+
+//  cout << " nv = " << nbv << " nbt = " << nbt << endl;
+  for (i=0;i<nbv;i++)
+    vertices[i].m = vertices[i].m*2.;
+  //
+  if(withBackground)
+    for (i=0;i<BTh.nbv;i++)
+      BTh.vertices[i].m =  BTh.vertices[i].m*2.;
+#ifdef DRAWING2
+  Draw();
+  inquire();
+#endif
+  
+  
+  ret = 2;
+  if (nbt>= nbtx) goto Error; // bug 
+  if (nbv>= nbvx) goto Error; // bug 
+  // generation of the new triangles 
+
+  SetIntCoor("In SplitElement"); 
+
+  ReMakeTriangleContainingTheVertex();
+  if(withBackground)
+    BTh.ReMakeTriangleContainingTheVertex();
+
+  delete [] edges;
+  edges = newedges;
+  nbe = newnbe;
+  NbOfQuad = newNbOfQuad;
+
+  for (i=0;i<NbSubDomains;i++)
+    { 
+      Int4 k = subdomains[i].edge- edges;
+      subdomains[i].edge =  edges+2*k; // spilt all edge in 2 
+    }
+    
+  if (ksplitarray) delete [] ksplitarray;
+  if (kedge) delete [] kedge;
+  if (edge4) delete edge4;
+  if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge;
+  VerticesOnGeomEdge= newVerticesOnGeomEdge;
+  if(VertexOnBThEdge) delete []  VertexOnBThEdge;
+  VertexOnBThEdge = newVertexOnBThEdge;
+  NbVerticesOnGeomEdge = newNbVerticesOnGeomEdge;
+  NbVertexOnBThEdge=newNbVertexOnBThEdge;
+  //  ReMakeTriangleContainingTheVertex();
+
+  FillHoleInMesh();
+
+#ifdef DEBUG
+  for (i=0;i<nbt;i++)
+    triangles[i].check();
+#endif
+  
+ if (verbosity>2)
+   cout << "    (out) Nb of Quadrilaterals = " << NbOfQuad 
+	<< " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+	<< " Nb of outside triangles = " << NbOutT << endl;
+
+ CurrentTh=OCurrentTh;
+ return 0; //ok
+
+ Error:
+  nbv = nbvold;
+  nbt = nbtold;
+  NbOutT = NbOutTold;
+  // cleaning memory ---
+  delete newedges;
+  if (ksplitarray) delete [] ksplitarray;
+  if (kedge) delete [] kedge;
+  if (newVerticesOnGeomEdge) delete [] newVerticesOnGeomEdge;
+  if (edge4) delete edge4;
+  if(newVertexOnBThEdge) delete []  newVertexOnBThEdge;
+  
+
+  CurrentTh= OCurrentTh;
+  return ret; // ok 
+}
+
+} //  end of namespcae bamg 
Index: /issm/trunk/src/c/Bamgx/MeshRead.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/MeshRead.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/MeshRead.cpp	(revision 2740)
@@ -0,0 +1,1317 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "../shared/shared.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+#ifdef __MWERKS__
+#pragma optimization_level 2
+//#pragma inline_depth 1
+#endif
+
+#ifdef DRAWING1
+  extern bool withrgraphique ;
+#endif
+
+namespace bamg {
+
+static const  Direction NoDirOfSearch=Direction();
+
+void Triangles::ReadFromMatlabMesh(double* elements,double* x,double* y,int nel,int nods,int NBV,Real8 cutoffradian){
+
+	long int verbosity=0;
+
+	Real8 hmin = HUGE_VAL;// the infinie value 
+	
+	Int4 i;
+	Int4 dim=0;
+	Int4 hvertices =0;
+	Int4 ifgeom=0;
+	Metric M1(1);
+	int field=0;
+	int showfield=0;
+	
+	field=0;
+	dim=2;
+	nbv=NBV;
+	nbvx=NBV;
+	nbiv = NBV;
+
+
+	vertices=(Vertex*)xmalloc(nbvx*sizeof(Vertex));
+	ordre=(Vertex**)xmalloc(nbvx*sizeof(Vertex*));
+
+	for (i=0;i<nods;i++){
+				
+		vertices[i].r.x=x[i];
+		vertices[i].r.y=y[i];
+		vertices[i].ReferenceNumber=1;
+		vertices[i].DirOfSearch =NoDirOfSearch;
+		vertices[i].m=M1;
+		vertices[i].color =0;
+	}
+
+	nbtx =  2*nbvx-2; // for filling The Holes and quadrilaterals 
+
+	triangles =(Triangle*)xmalloc(nbtx*sizeof(Triangle));
+	nbt =0;
+	for (i=0;i<nel;i++){
+		Int4 i1,i2,i3,iref;
+		Triangle & t = triangles[nbt++];
+		i1=(Int4)*(elements+i*3+0);
+		i2=(Int4)*(elements+i*3+1);
+		i3=(Int4)*(elements+i*3+2);
+
+		iref=1;
+		t = Triangle(this,i1-1,i2-1,i3-1);
+		t.color=iref;
+	}
+
+	/*build geometry: */
+	ConsGeometry(cutoffradian);	
+	Gh.AfterRead();
+
+}
+
+void Triangles::Read(MeshIstream & f_in,int Version,Real8 cutoffradian) {
+
+
+	long int verbosity=0;
+
+  Real8 hmin = HUGE_VAL;// the infinie value 
+  //  Real8 MaximalAngleOfCorner = 10*Pi/180;// 
+  Int4 i;
+  Int4 dim=0;
+  Int4 hvertices =0;
+  Int4 ifgeom=0;
+  Metric M1(1);
+  if (verbosity>1)
+    cout << "  -- ReadMesh " << f_in.CurrentFile  << " Version = " << Version << endl;
+  int field=0;
+  int showfield=0;
+  while (f_in.cm()) 
+    {  
+      field=0;
+      char  fieldname[256];
+      if(f_in.eof()) break;
+      f_in.cm() >> fieldname ;;
+      if(f_in.eof()) break;
+      f_in.err() ;
+      if(verbosity>9)
+	cout <<  "    " << fieldname << endl;
+      if (!strcmp(fieldname,"MeshVersionFormatted") )
+         f_in >>   Version ;
+      else if(!strcmp(fieldname,"End"))
+         break;
+      else if (!strcmp(fieldname,"Dimension"))
+         {
+           f_in >>   dim ;
+           assert(dim ==2);
+         }
+      else if  (!strcmp(fieldname,"Geometry"))
+	{ 
+	  char * fgeom ;
+	  f_in >> fgeom;
+	  //	  if (cutoffradian>=0) => bug if change edit the file geometry 
+	  //  Gh.MaximalAngleOfCorner = cutoffradian;
+	  if (strlen(fgeom))
+	      Gh.ReadGeometry(fgeom);
+	  else 
+	    { 
+	      // include geometry 
+	      f_in.cm();
+	      Gh.ReadGeometry(f_in,fgeom);
+	    }
+
+	  Gh.AfterRead();
+	  ifgeom=1;
+	  delete [] fgeom;
+	}
+      else if (!strcmp(fieldname,"Identifier"))
+	{
+	  if (identity) delete [] identity;
+	  f_in >> identity;
+	}
+      else if (!strcmp(fieldname,"hVertices"))
+         { hvertices =1;
+	   Real4 h;
+           for (i=0;i< nbv;i++) {
+            f_in >>  h ;
+	    vertices[i].m = Metric(h);}
+         }
+      else if (!strcmp(fieldname,"Vertices"))
+         { 
+           assert(dim ==2);
+           f_in >>   nbv ;
+	   if(verbosity>3)
+	     cout << "   Nb of Vertices = " << nbv << endl;
+	   nbvx=nbv;
+	   vertices=new Vertex[nbvx];
+	   assert(vertices);
+	   ordre=new (Vertex* [nbvx]);
+	   assert(ordre);
+	   
+	   nbiv = nbv;
+           for (i=0;i<nbv;i++) {
+             f_in >> 
+	       	 	 vertices[i].r.x >>  
+	           vertices[i].r.y >> 
+             vertices[i].ReferenceNumber  ;
+             vertices[i].DirOfSearch =NoDirOfSearch;
+	           vertices[i].m=M1;
+	     vertices[i].color =0;}
+	   nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+	   triangles =new Triangle[nbtx];
+	   assert(triangles);
+	   nbt =0;
+         }
+      else if (!strcmp(fieldname,"Triangles"))
+	{ 
+	  if (dim !=2)
+	    cerr << "ReadMesh: Dimension <> 2" <<endl , f_in.ShowIoErr(0);
+	  if(! vertices || !triangles  || !nbv )
+	    cerr << "ReadMesh:Triangles before Vertices" <<endl,
+	      f_in.ShowIoErr(0);
+	  int NbOfTria;
+	  f_in >>  NbOfTria ;
+	  if(verbosity>3)
+	    cout << "   NbOfTria = " << NbOfTria << endl;
+	  if (nbt+NbOfTria >= nbtx)
+	    cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria  = "
+		 << nbt + NbOfTria<<"  < 2*nbv-2 ="  << nbtx << endl,
+	      f_in.ShowIoErr(0); 
+	  //	  begintria = nbt;
+	  for (i=0;i<NbOfTria;i++)  
+	    {
+	      Int4 i1,i2,i3,iref;
+	      Triangle & t = triangles[nbt++];
+	      f_in >>  i1 >>  i2 >>   i3 >>   iref ;
+	      t = Triangle(this,i1-1,i2-1,i3-1);
+	      t.color=iref;
+	    }
+	  // endtria=nbt;
+	}
+      else if (!strcmp(fieldname,"Quadrilaterals"))
+        { 
+
+	  if (dim !=2)
+	    cerr << "ReadMesh: Dimension <> 2" <<endl , f_in.ShowIoErr(0);
+	  if(! vertices || !triangles  || !nbv )
+	    cerr << "ReadMesh:Quadrilaterals before Vertices" <<endl,
+	      f_in.ShowIoErr(0);
+	  f_in >>   NbOfQuad ;
+	  if(verbosity>3)
+	    cout << "   NbOfQuad= " << NbOfQuad << endl;
+	  if (nbt+2*NbOfQuad >= nbtx)
+	    cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria  = "
+		 << nbt + 2*NbOfQuad <<"  < 2*nbv-2 ="  << nbtx << endl,
+	      f_in.ShowIoErr(0);
+	  //  beginquad=nbt;
+	  for (i=0;i<NbOfQuad;i++)  
+	    { 
+	      Int4 i1,i2,i3,i4,iref;
+	      Triangle & t1 = triangles[nbt++];
+	      Triangle & t2 = triangles[nbt++];
+	      f_in >>  i1 >>  i2 >>   i3 >> i4 >>    iref ;
+	      t1 = Triangle(this,i1-1,i2-1,i3-1);
+	      t1.color=iref;
+	      t2 = Triangle(this,i3-1,i4-1,i1-1);
+	      t2.color=iref;
+	      t1.SetHidden(OppositeEdge[1]); // two time  because the adj was not created 
+	      t2.SetHidden(OppositeEdge[1]); 
+	    }
+	  // endquad=nbt;
+	}
+      else if (!strcmp(fieldname,"VertexOnGeometricVertex"))
+	{ 
+           f_in  >> NbVerticesOnGeomVertex ;
+ 	   if(verbosity>5)
+	     cout << "   NbVerticesOnGeomVertex = "   << NbVerticesOnGeomVertex << endl
+		  << " Gh.vertices " << Gh.vertices << endl;
+	   if( NbVerticesOnGeomVertex) 
+	     {
+	       VerticesOnGeomVertex= new  VertexOnGeom[NbVerticesOnGeomVertex] ;
+	       if(verbosity>7)
+		 cout << "   VerticesOnGeomVertex = " << VerticesOnGeomVertex << endl
+		      << "   Gh.vertices " << Gh.vertices << endl;
+	       assert(VerticesOnGeomVertex);
+	       for (Int4 i0=0;i0<NbVerticesOnGeomVertex;i0++)  
+		 { 
+		   Int4  i1,i2;
+		   //VertexOnGeom & v =VerticesOnGeomVertex[i0];
+		   f_in >>  i1 >> i2 ;
+		   VerticesOnGeomVertex[i0]=VertexOnGeom(vertices[i1-1],Gh.vertices[i2-1]);
+		 }
+	     }
+	 }
+      else if (!strcmp(fieldname,"VertexOnGeometricEdge"))
+         { 
+           f_in >>  NbVerticesOnGeomEdge ;
+ 	   if(verbosity>3)
+	     cout << "   NbVerticesOnGeomEdge = " << NbVerticesOnGeomEdge << endl;
+	   if(NbVerticesOnGeomEdge) 
+	     {
+	       VerticesOnGeomEdge= new  VertexOnGeom[NbVerticesOnGeomEdge] ;
+	       assert(VerticesOnGeomEdge);
+	       for (Int4 i0=0;i0<NbVerticesOnGeomEdge;i0++)  
+		 { 
+		   Int4  i1,i2;
+		   Real8 s;
+		   //VertexOnGeom & v =VerticesOnGeomVertex[i0];
+		   f_in >>  i1 >> i2  >> s;
+		   VerticesOnGeomEdge[i0]=VertexOnGeom(vertices[i1-1],Gh.edges[i2-1],s);
+		 }
+	     }
+         }
+      else if (!strcmp(fieldname,"Edges"))
+	{ 
+          Int4 i,j, i1,i2;
+          f_in >>  nbe ;
+          edges = new Edge[nbe];
+	  if(verbosity>5)
+	    cout << "     Record Edges: Nb of Edge " << nbe << " edges " <<  edges << endl;
+          assert(edges);
+	  Real4 *len =0;
+          if (!hvertices) 
+	    {
+	      len = new Real4[nbv];
+	      for(i=0;i<nbv;i++)
+		len[i]=0;
+	    }
+          for (i=0;i<nbe;i++) 
+	    {
+	      f_in  >> i1  >> i2  >> edges[i].ref ;
+                 
+	      assert(i1 >0 && i2 >0);
+	      assert(i1 <= nbv && i2 <= nbv);
+	      i1--;
+	      i2--;
+	      edges[i].v[0]= vertices +i1;
+	      edges[i].v[1]= vertices +i2;
+	      edges[i].adj[0]=0;
+	      edges[i].adj[1]=0;
+
+	      R2 x12 = vertices[i2].r-vertices[i1].r;
+	      Real8 l12=sqrt( (x12,x12));        
+	      if (!hvertices) {
+		vertices[i1].color++;
+		vertices[i2].color++;
+		len[i1]+= l12;
+		len[i2] += l12;}
+	      hmin = Min(hmin,l12);
+	    }
+	  // definition  the default of the given mesh size 
+          if (!hvertices) 
+	    {
+            for (i=0;i<nbv;i++) 
+	      if (vertices[i].color > 0) 
+		vertices[i].m=  Metric(len[i] /(Real4) vertices[i].color);
+	      else 
+		vertices[i].m=  Metric(hmin);
+	      delete [] len;
+	    }
+	  if(verbosity>5)
+	    cout << "     hmin " << hmin << endl;
+	  // construction of edges[].adj 
+	    for (i=0;i<nbv;i++) 
+	      vertices[i].color = (vertices[i].color ==2) ? -1 : -2;
+	    for (i=0;i<nbe;i++)
+	      for (j=0;j<2;j++) 
+		{ 
+		  Vertex *v=edges[i].v[j];
+		  Int4 i0=v->color,j0;
+		  if(i0==-1)
+		    v->color=i*2+j;
+		  else if (i0>=0) {// i and i0 edge are adjacent by the vertex v
+		    j0 =  i0%2;
+		    i0 =  i0/2;
+		    assert( v ==  edges[i0 ].v[j0]);
+		    edges[i ].adj[ j ] =edges +i0;
+		    edges[i0].adj[ j0] =edges +i ;
+		    assert(edges[i0].v[j0] == v);
+		    //	    if(verbosity>8)
+		    //  cout << " edges adj " << i0 << " "<< j0 << " <-->  "  << i << " " << j << endl;
+		      v->color = -3;}
+		}
+
+	}
+	
+/*   ne peut pas marche car il n'y a pas de flag dans les aretes du maillages
+       else if (!strcmp(fieldname,"RequiredEdges"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbe );
+            assert( j > 0 );
+            j--;
+            edges[j].SetRequired();  }
+      }
+*/	
+      else if (!strcmp(fieldname,"EdgeOnGeometricEdge"))
+	{ 
+	  assert(edges);
+	  int i1,i2,i,j;
+	  f_in >> i2 ;
+	  if(verbosity>3)
+	    cout << "     Record EdgeOnGeometricEdge: Nb " << i2 <<endl;
+	  for (i1=0;i1<i2;i1++)
+	    {
+	      f_in  >> i >> j ;
+	      if(!(i>0 && j >0 && i <= nbe && j <= Gh.nbe))
+		{
+		  cerr << "      Record EdgeOnGeometricEdge i=" << i << " j = " << j;
+		  cerr << " nbe = " << nbe << " Gh.nbe = " <<  Gh.nbe << endl;
+		  cerr << " We must have : (i>0 && j >0 && i <= nbe && j <= Gh.nbe) ";
+		  cerr << " Fatal error in file " << name << " line " << f_in.LineNumber << endl;
+		  MeshError(1);
+		}
+		
+		
+	      edges[i-1].on = Gh.edges + j-1;
+	    }
+	  //	  cout << "end EdgeOnGeometricEdge" << endl;
+	}
+      else if (!strcmp(fieldname,"SubDomain") || !strcmp(fieldname,"SubDomainFromMesh") )
+	{ 
+	  
+	  f_in >> NbSubDomains ;
+	  subdomains = new SubDomain [ NbSubDomains ];
+	    for (i=0;i< NbSubDomains;i++)
+	      { Int4 i3,head,sens;
+	      f_in  >>  i3 >>	head >> sens  >> subdomains[i].ref ;
+		assert (i3==3);
+		head --;
+		assert(head < nbt && head >=0);
+		subdomains[i].head = triangles+head;		
+	      }
+	}
+      else
+	{ // unkown field
+	  field = ++showfield;
+	  if(showfield==1) // just to show one time 
+	    if (verbosity>5)
+	      cout << "     Warning we skip the field " << fieldname << " at line " << f_in.LineNumber << endl;
+	}
+      showfield=field; // just to show one time 
+    }
+    
+    if (ifgeom==0)
+      {
+	if (verbosity)
+	  cout  << " ## Warning: Mesh without geometry we construct a geometry (theta =" 
+		<< cutoffradian*180/Pi << " degres )" << endl;
+	ConsGeometry(cutoffradian);	
+	Gh.AfterRead();
+      }	  
+}
+
+
+
+
+void Triangles::Read_am_fmt(MeshIstream & f_in)
+{
+	long int verbosity=0;
+
+  Metric M1(1);
+
+  if (verbosity>1)
+    cout << "  -- ReadMesh .am_fmt file " <<  f_in.CurrentFile  << endl;
+   	
+     Int4 i;
+     f_in.cm() >> nbv >> nbt ;
+     if (verbosity>3)
+       cout << "    nbv = " << nbv  << " nbt = " << nbt << endl;
+     f_in.eol() ;// 
+     nbvx = nbv;
+     nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+     triangles =new Triangle[nbtx];
+     assert(triangles);
+     vertices=new Vertex[nbvx];
+     ordre=new (Vertex* [nbvx]);
+     
+     for (     i=0;i<nbt;i++)
+       {
+	 Int4 i1,i2,i3;
+	 f_in >>  i1 >>  i2 >>   i3 ;
+	 triangles[i]  = Triangle(this,i1-1,i2-1,i3-1);	 
+       }
+      f_in.eol() ;// 
+      
+      for ( i=0;i<nbv;i++)
+	f_in >> vertices[i].r.x >>   vertices[i].r.y,
+	  vertices[i].m = M1,vertices[i].DirOfSearch =NoDirOfSearch;
+
+      f_in.eol() ;// 
+      
+      for ( i=0;i<nbt;i++)  
+	f_in >> triangles[i].color;
+      f_in.eol() ;// 
+      
+      for ( i=0;i<nbv;i++)  
+	     f_in >> vertices[i].ReferenceNumber;
+      
+      
+}
+
+////////////////////////
+
+void  Triangles::Read_am(MeshIstream &ff)
+{
+	long int verbosity=0;
+
+  if (verbosity>1)
+    cout << "  -- ReadMesh .am_fmt file " <<  ff.CurrentFile  << endl;
+    Metric M1(1);	
+  
+  IFortranUnFormattedFile f_in(ff);
+
+  Int4  l=f_in.Record();
+  assert(l==2*sizeof(Int4));
+  f_in >> nbv >> nbt ;
+  l=f_in.Record();
+  assert((size_t) l==nbt*sizeof(long)*4 + nbv*(2*sizeof(float)+sizeof(long)));
+  if (verbosity>3)
+    cout << "    nbv = " << nbv  << " nbt = " << nbt << endl;
+  
+  nbvx = nbv;
+  nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+  triangles =new Triangle[nbtx];
+  assert(triangles);
+  vertices=new Vertex[nbvx];
+  ordre=new (Vertex* [nbvx]);
+  
+
+  Int4 i;
+  for (     i=0;i<nbt;i++) {
+    long i1,i2,i3;
+    f_in >>  i1 >>  i2 >>   i3 ;
+    triangles[i]  = Triangle(this,i1-1,i2-1,i3-1); }
+  
+  for ( i=0;i<nbv;i++) {
+    float x,y;
+    f_in >> x >> y;
+    vertices[i].r.x =x;
+    vertices[i].r.y=y;
+    vertices[i].m=M1;}
+  
+  for ( i=0;i<nbt;i++) {
+    long i;
+    f_in >> i;
+    triangles[i].color=i;}
+  
+  for ( i=0;i<nbv;i++) {
+    long i;
+    f_in >> i;
+    vertices[i].ReferenceNumber=i;}
+}
+
+//////////////////////////////////
+
+void  Triangles::Read_nopo(MeshIstream & ff)
+{
+	long int verbosity=0;
+
+
+ if (verbosity>1)
+    cout << "  -- ReadMesh .nopo file " <<  ff.CurrentFile  << endl;
+ IFortranUnFormattedFile f_in(ff);
+ 
+ 
+ Int4  l,i,j;
+ l=f_in.Record(); 
+ l=f_in.Record();
+ f_in >> i;
+ assert(i==32);
+ Int4 niveau,netat,ntacm;
+
+ char titre[80+1],  date[2*4+1], nomcre[6*4+1], typesd[5];
+ f_in.read4(titre,20);
+ f_in.read4(date,2);
+ f_in.read4(nomcre,6);
+ f_in.read4(typesd,1);
+
+
+   f_in >> niveau>>netat>>ntacm;
+ if (strcmp("NOPO",typesd))
+   {
+     cout << " where in record  " << f_in.where() << " " << strcmp("NOPO",typesd) << endl;
+     cerr << " not a  nopo file but `" << typesd <<"`"<< " len = " << strlen(typesd) << endl;
+     cerr << (int) typesd[0] << (int) typesd[1] << (int) typesd[2] << (int) typesd[3] << (int) typesd[4] << endl;
+     cout << " nomcre :" << nomcre << endl;
+     cout << " date   :" << date << endl;
+     cout << " titre  :" << titre<< endl;
+     MeshError(112);
+   }
+ if(verbosity>2)
+   cout << "    nb de tableau associe : " << ntacm << " niveau =" << niveau << endl;
+ 
+ for (i=0;i<ntacm;i++)
+   f_in.Record();
+
+ f_in.Record();
+ f_in >> l;
+ assert(l == 27);
+ Int4 nop2[27];
+ for (i=0;i<27;i++)
+   f_in >> nop2[i];
+ Int4 ndim = nop2[0];
+ Int4 ncopnp = nop2[3];
+ Int4 ne = nop2[4];
+ Int4 ntria = nop2[7];
+ Int4 nquad = nop2[8];
+ Int4 np = nop2[21];
+ // Int4 nef = nop2[13];
+ Metric M1(1);
+ if(verbosity>2) 
+   cout << "    ndim = " << ndim << " ncopnp= " << ncopnp << " ne = " << ne 
+	<< "    ntri = " << ntria << " nquad = " << nquad << " np = " << np << endl;
+ nbv = np;
+ nbt = 2*nquad + ntria;
+ if (ne != nquad+ntria || ndim !=2 || ncopnp != 1 )
+   {
+     cerr << " not only tria & quad in nopo mesh on dim != 2 ou ncopnp != 1 " << endl;
+     MeshError(113);
+   }
+ if( nop2[24]>=0)  f_in.Record();
+  NbOfQuad = nquad;
+  nbvx = nbv;
+  nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+  triangles =new Triangle[nbtx];
+  assert(triangles);
+  vertices=new Vertex[nbvx];
+  ordre=new (Vertex* [nbvx]);
+
+
+ f_in >> l;
+
+  if(verbosity>9)
+    cout << " Read cnop4 nb of float  " << l << endl;
+  
+  assert(l==2*np);
+  for (i=0;i<np;i++)
+    {  float x,y;
+    f_in >>  x>> y;
+    vertices[i].r.x=x;
+    vertices[i].r.y=y;
+    vertices[i].m=M1;
+    vertices[i].DirOfSearch =NoDirOfSearch;
+
+    }
+  f_in.Record();
+  // lecture de nop5 bonjour les degats
+  f_in >> l;
+  if(verbosity>9)
+    cout << " Read nop5  nb of int4 " << l << endl;
+ Int4 k=0;
+ Int4 nbe4 =  3*ntria + 4*nquad;
+ // cout << " nbv = " << nbv << " nbe4 " << nbe4 << endl;
+ SetOfEdges4 * edge4= new SetOfEdges4(nbe4,nbv); 
+ Int4 * refe = new Int4[nbe4];
+ Int4 kr =0;
+ for (i=0;i<ne;i++)
+   {
+     // Int4 ng[4]={0,0,0,0};
+     Int4 np[4],rv[4],re[4];
+     Int4 ncge,nmae,ndsde,npo;
+     f_in >> ncge >> nmae >> ndsde >> npo ;
+     //cout << " element " << i << " " << ncge << " "  
+     // << nmae <<" " <<  npo << endl;
+     if (ncge != 3 && ncge != 4)
+       {
+	 cerr << " read nopo type element[" << i << "] =" 
+	      << ncge << " not 3 or 4 " << endl;
+	 MeshError(115);
+       }
+     if (npo != 3 && npo != 4)
+       {
+	 cerr << " read nopo element[" << i << "] npo = "  
+	      << npo << " not 3 or 4 " << endl;
+	 MeshError(115);
+       }
+     
+     for( j=0;j<npo;j++)
+       {f_in >>np[j];np[j]--;}
+     
+     if (ncopnp !=1) 
+       {
+	 f_in >> npo;
+	 if (npo != 3 || npo != 4)
+	   {
+	     cerr << " read nopo type element[" << i << "]= "  
+		  << ncge << " not 3 or 4 " << endl;
+	     MeshError(115);
+	   }
+	 
+	 for(j=0;j<npo;j++)
+	   {f_in >>np[j];np[j]--;}
+	 
+       }
+     if (nmae>0) 
+       {
+	 Int4  ining; // no ref 
+	 
+	 f_in>>ining;
+	 if (ining==1)
+	   MeshError(116);
+	 if (ining==2)
+	   for (j=0;j<npo;j++)
+	     f_in >>re[j];
+	 for (j=0;j<npo;j++)
+	   f_in >>rv[j];
+	 
+	 
+	 // set the ref on vertex and the shift np of -1 to start at 0
+	 for (j=0;j<npo;j++)
+	   vertices[np[j]].ReferenceNumber = rv[j];
+	 
+	 if (ining==2)
+	   for (j=0;j<npo;j++)
+	     if (re[j])
+	       {
+		 kr++;
+		 Int4 i0 = np[j];
+		 Int4 i1 = np[(j+1)%npo];
+		 // cout << kr << " ref  edge " << i0 << " " << i1 << " " << re[j] << endl;
+		 refe[edge4->addtrie(i0,i1)]=re[j];
+	       }
+       }
+     
+     if (npo==3) 
+       { // triangles 
+	 triangles[k]  = Triangle(this,np[0],np[1],np[2]); 
+	 triangles[k].color = ndsde;
+	 k++;
+       }
+     else if (npo==4)
+       { // quad 
+	 Triangle & t1 = triangles[k++];
+	 Triangle & t2 = triangles[k++];
+	 t1 = Triangle(this,np[0],np[1],np[2]);
+	 t2 = Triangle(this,np[2],np[3],np[0]);
+	 t1.SetHidden(OppositeEdge[1]); // two time  because the adj was not created 
+	 t2.SetHidden(OppositeEdge[1]); 
+	 t1.color = ndsde;
+	 t2.color = ndsde;
+       }
+     else
+       {
+	 cerr << " read nopo type element =" << npo << " not 3 or 4 " << endl;
+	 MeshError(114);
+       }
+     
+     
+   }
+ // cout << k << " == " << nbt << endl;
+ assert(k==nbt);
+
+ nbe = edge4->nb();
+ if (nbe)
+   {
+     if (verbosity>7)
+     cout << " Nb of ref edges = " << nbe << endl;
+     if (edges)
+       delete [] edges;
+     edges = new Edge[nbe];
+     for (i=0;i<nbe;i++)
+       {
+	 edges[i].v[0] = vertices + edge4->i(i);
+	 edges[i].v[1] = vertices + edge4->j(i);
+	 edges[i].ref = refe[i];
+	 //	 cout << i << " " <<  edge4->i(i) << " " <<  edge4->j(i) << endl;
+       }
+      if (verbosity>7)
+	cout << " Number of reference edge in the  mesh = " << nbe << endl;
+   }
+ delete [] refe;
+ delete edge4;
+}
+  void  Triangles::Read_ftq(MeshIstream & f_in)
+{
+	long int verbosity=0;
+
+  //  
+  if (verbosity>1)
+    cout << "  -- ReadMesh .ftq file " <<  f_in.CurrentFile  << endl;
+  
+  Int4 i,ne,nt,nq;
+  f_in.cm() >> nbv >> ne >> nt >> nq ;
+  if (verbosity>3)
+    cout << "    nbv = " << nbv  << " nbtra = " << nt << " nbquad = " << nq << endl;
+  nbt = nt+2*nq;
+  
+
+  nbvx = nbv;
+  nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+  triangles =new Triangle[nbtx];
+  assert(triangles);
+  vertices=new Vertex[nbvx];
+  ordre=new (Vertex* [nbvx]);
+  Int4 k=0;
+  
+  for ( i=0;i<ne;i++) 
+    {
+      long ii,i1,i2,i3,i4,ref;
+      f_in >>  ii;
+	if (ii==3) 
+	  { // triangles 
+	    f_in >> i1>>  i2 >>   i3 >> ref ;
+	    triangles[k]  = Triangle(this,i1-1,i2-1,i3-1); 
+	    triangles[k++].color = ref;
+	  }
+	else if (ii==4)
+	  { // quad 
+	    f_in >> i1>>  i2 >>   i3 >> i4 >> ref ;
+	    Triangle & t1 = triangles[k++];
+	    Triangle & t2 = triangles[k++];
+	    t1 = Triangle(this,i1-1,i2-1,i3-1);
+	    t1.color=ref;
+	    t2 = Triangle(this,i3-1,i4-1,i1-1);
+	    t2.color=ref;
+	    t1.SetHidden(OppositeEdge[1]); // two time  because the adj was not created 
+	    t2.SetHidden(OppositeEdge[1]); 	  
+	  }
+	else
+	  {
+	    cout << " read ftq type element =" << ii << " not 3 or 4 " << endl;
+	    MeshError(111);
+	  }
+    }
+  assert(k==nbt);
+  Metric M1(1);
+  for ( i=0;i<nbv;i++)
+    {
+      f_in >> vertices[i].r.x >>   vertices[i].r.y >> vertices[i].ReferenceNumber;
+       vertices[i].DirOfSearch =NoDirOfSearch;
+       vertices[i].m = M1;
+
+    }
+}
+
+///////////////////////////////////////////////
+
+void  Triangles::Read_msh(MeshIstream &f_in)
+{
+	long int verbosity=0;
+
+    Metric M1(1.);
+  if (verbosity>1)
+    cout << "  -- ReadMesh .msh file " <<  f_in.CurrentFile  << endl;
+   	
+     Int4 i;
+     f_in.cm() >> nbv >> nbt ;
+     while (f_in.in.peek()==' ')
+         f_in.in.get();
+     if(isdigit(f_in.in.peek())) 
+       f_in >> nbe;
+     if (verbosity>3)
+       cout << "    nbv = " << nbv  << " nbt = " << nbt << " nbe = " << nbe << endl;
+     nbvx = nbv;
+     nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+     triangles =new Triangle[nbtx];
+     assert(triangles);
+     vertices=new Vertex[nbvx];
+     ordre=new (Vertex* [nbvx]);
+      edges = new Edge[nbe];
+     for ( i=0;i<nbv;i++)
+	{
+	 f_in >> vertices[i].r.x >>   vertices[i].r.y >> vertices[i].ReferenceNumber;
+	    vertices[i].on=0;
+	    vertices[i].m=M1;
+         //if(vertices[i].ReferenceNumber>NbRef)	NbRef=vertices[i].ReferenceNumber;  
+  	}
+     for (     i=0;i<nbt;i++)
+       {
+	 Int4 i1,i2,i3,r;
+	 f_in >>  i1 >>  i2 >>   i3 >> r;
+	 triangles[i]  = Triangle(this,i1-1,i2-1,i3-1);
+	 triangles[i].color = r;	 
+       }
+     for (i=0;i<nbe;i++)
+       {
+	 Int4 i1,i2,r;
+	 f_in >>  i1 >>  i2 >> r;
+	      edges[i].v[0]= vertices +i1-1;
+	      edges[i].v[1]= vertices +i2-1;
+	      edges[i].adj[0]=0;
+	      edges[i].adj[1]=0;
+	      edges[i].ref = r;
+	      edges[i].on=0;
+       }
+      
+}
+
+//////////////////////////////////////////////////
+
+void  Triangles::Read_amdba(MeshIstream &f_in )
+{
+	long int verbosity=0;
+
+  Metric M1(1);
+  if (verbosity>1)
+    cout << "  -- ReadMesh .amdba file " <<  f_in.CurrentFile  << endl;
+   	
+     Int4 i;
+     f_in.cm() >> nbv >> nbt ;
+     //    if (verbosity>3)
+       cout << "    nbv = " << nbv  << " nbt = " << nbt << endl;
+     f_in.eol() ;// 
+     nbvx = nbv;
+     nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+     triangles =new Triangle[nbtx];
+     assert(triangles);
+     vertices=new Vertex[nbvx];
+     ordre=new (Vertex* [nbvx]);
+     Int4 j;
+      for ( i=0;i<nbv;i++)
+	{
+	  f_in >> j ;
+	  assert( j >0 && j <= nbv);
+	  j--;
+	  f_in >> vertices[j].r.x >>   vertices[j].r.y >> vertices[j].ReferenceNumber;
+	   vertices[j].m=M1;
+	   vertices[j].DirOfSearch=NoDirOfSearch;
+	}
+     
+      for (     i=0;i<nbt;i++)
+       {
+	 Int4 i1,i2,i3,ref;
+	   f_in >> j ;
+	   assert( j >0 && j <= nbt);
+	   j--;
+	   f_in >> i1 >>  i2 >>   i3 >> ref;
+	 triangles[j]  = Triangle(this,i1-1,i2-1,i3-1);
+	 triangles[j].color =ref;
+       }
+      f_in.eol() ;// 
+      
+  // cerr << " a faire " << endl;
+  //MeshError(888);
+}
+
+
+Triangles::Triangles(const char * filename,Real8 cutoffradian) 
+: Gh(*(new Geometry())), BTh(*this)
+{ 
+
+  //  Int4 beginquad=0,begintria=0;
+  // Int4 endquad=0;endtria=0;
+  //int type_file=0;
+
+  int lll = strlen(filename);
+  int  am_fmt = !strcmp(filename + lll - 7,".am_fmt");
+  int  amdba = !strcmp(filename + lll - 6,".amdba");
+  int  am = !strcmp(filename + lll - 3,".am");
+  int  nopo = !strcmp(filename + lll - 5,".nopo");
+  int  msh = !strcmp(filename + lll - 4,".msh");
+  int  ftq = !strcmp(filename + lll - 4,".ftq");
+
+ // cout << " Lecture type  :" << filename + lll - 7 <<":" <<am_fmt<<  endl;
+
+  char * cname = new char[lll+1];
+  strcpy(cname,filename);
+  Int4 inbvx =0;
+  PreInit(inbvx,cname);
+  OnDisk = 1;
+  //  allocGeometry = &Gh; // after Preinit ; 
+
+  MeshIstream f_in (filename);
+  
+  if (f_in.IsString("MeshVersionFormatted"))
+    {
+      int version ;
+      f_in >> version ;
+      Read(f_in,version,cutoffradian);
+    }
+  else {     
+    if (am_fmt) Read_am_fmt(f_in);
+    else if (am) Read_am(f_in);
+    else if (amdba) Read_amdba(f_in);
+    else if (msh) Read_msh(f_in);
+    else if (nopo) Read_nopo(f_in);
+    else if (ftq) Read_ftq(f_in);
+    else 
+      { 
+	cerr << " Unkown type mesh " << filename << endl;
+	MeshError(2);
+      }
+      ConsGeometry(cutoffradian);
+      Gh.AfterRead();    
+  }
+
+  SetIntCoor();
+  FillHoleInMesh();
+  // Make the quad ---
+   
+}
+
+Triangles::Triangles(double* elements, double* x, double* y, int nel, int nods,int NBV,Real8 cutoffradian) : Gh(*(new Geometry())), BTh(*this){ 
+
+  PreInit(0,"none");
+  OnDisk = 1;
+  printf("ok1\n");
+
+  ReadFromMatlabMesh(elements,x,y,nel,nods,NBV,cutoffradian);
+printf("ok2\n");
+
+  SetIntCoor();
+  printf("ok3\n");
+
+  FillHoleInMesh();
+  printf("ok4\n");
+
+
+}
+void Geometry::ReadGeometry(const char * filename)
+{
+	long int verbosity=0;
+
+  OnDisk = 1;
+  if(verbosity>1)
+      cout << "  -- ReadGeometry " << filename << endl;
+  MeshIstream f_in (filename);
+  ReadGeometry(f_in,filename);
+}
+
+
+
+void Geometry::ReadGeometry(MeshIstream & f_in,const char * filename)  
+{
+	long int verbosity=2;
+  if(verbosity>1)
+    cout << "  -- ReadGeometry " << filename << endl;
+  assert(empty());
+  nbiv=nbv=nbvx=0;
+  nbe=nbt=nbtx=0;
+  NbOfCurves=0;
+ // BeginOfCurve=0;
+  name=new char [strlen(filename)+1];
+  strcpy(name,filename);
+  Real8 Hmin = HUGE_VAL;// the infinie value 
+//  Real8 MaximalAngleOfCorner = 10*Pi/180; ; 
+  Int4 hvertices =0;
+  Int4 i;
+  Int4 Version,dim=0;
+  int field=0;
+  int showfield=0;
+  int NbErr=0;
+
+  while (f_in.cm()) 
+    { 
+      field=0;
+      // warning ruse for on allocate fiedname at each time 
+      char fieldname[256];
+      f_in.cm() >> fieldname ;
+      f_in.err();
+      if(f_in.eof()) break;
+//      cout <<  fieldname <<  " line " << LineNumber  <<endl;
+      if (!strcmp(fieldname,"MeshVersionFormatted") )
+        f_in  >> Version ;
+      else if (!strcmp(fieldname,"End"))
+	break;
+      else if (!strcmp(fieldname,"end"))
+	break;
+      else if (!strcmp(fieldname,"Dimension"))
+        {
+          f_in   >>  dim ;
+	  if(verbosity>5) 
+	    cout << "     Geom Record Dimension dim = " << dim << endl;        
+          assert(dim ==2);
+         }
+       else if (!strcmp(fieldname,"hVertices"))
+         { 
+	   if (nbv <=0) {
+	     cerr<<"Error: the field Vertex is not found before hVertices " << filename<<endl;
+	     NbErr++;}       
+	   if(verbosity>5) 
+	    cout << "     Geom Record hVertices nbv=" << nbv <<  endl;
+	   hvertices =1;
+           for (i=0;i< nbv;i++) 
+	     {
+	       Real4 h;
+	       f_in  >>  h ; 
+	       vertices[i].m = Metric(h);
+	     }
+	 }
+       else if (!strcmp(fieldname,"MetricVertices"))
+         { hvertices =1;
+	   if (nbv <=0) {
+	     cerr<<"Error: the field Vertex is not found before MetricVertices " << filename<<endl;
+	     NbErr++;}       
+           if(verbosity>5) 
+	     cout << "     Geom Record MetricVertices nbv =" << nbv <<  endl;
+           for (i=0;i< nbv;i++) 
+	     {
+	       Real4 a11,a21,a22;
+	       f_in  >>  a11 >> a21 >> a22  ; 
+	       vertices[i].m = Metric(a11,a21,a22);
+	     }
+	 }
+       else if (!strcmp(fieldname,"h1h2VpVertices"))
+         { hvertices =1;
+	   if (nbv <=0) {
+	     cerr<<"Error: the field Vertex is not found before h1h2VpVertices " << filename<<endl;
+	     NbErr++;}       
+           if(verbosity>5) 
+	     cout << "     Geom Record h1h2VpVertices nbv=" << nbv << endl;
+
+           for (i=0;i< nbv;i++) 
+	     {
+	       Real4 h1,h2,v1,v2;
+	       f_in  >> h1 >> h2 >>v1 >>v2 ; 
+	       vertices[i].m = Metric(MatVVP2x2(1/(h1*h1),1/(h2*h2),D2(v1,v2)));
+	     }
+	 }
+      else if (!strcmp(fieldname,"Vertices"))
+        { 
+          assert(dim ==2);
+          f_in   >>  nbv ;
+	  //          if(LineError) break;
+          nbvx = nbv;
+          
+          vertices = new GeometricalVertex[nbvx];
+	  if(verbosity>5) 
+	    cout << "     Geom Record Vertices nbv = " << nbv << "vertices = " << vertices<<endl;
+          assert(nbvx >= nbv);
+          nbiv = nbv;
+          for (i=0;i<nbv;i++) {
+            f_in  >> vertices[i].r.x  ;
+            // if(LineError) break;
+            f_in  >> vertices[i].r.y ;
+	    // if(LineError) break;
+            f_in >>   vertices[i].ReferenceNumber   ;
+            vertices[i].DirOfSearch=NoDirOfSearch;
+	    //            vertices[i].m.h = 0;
+            vertices[i].color =0;
+            vertices[i].Set();}
+	  // if(LineError) break;
+	    pmin =  vertices[0].r;
+	    pmax =  vertices[0].r;
+	    // recherche des extrema des vertices pmin,pmax
+	    for (i=0;i<nbv;i++) {
+	      pmin.x = Min(pmin.x,vertices[i].r.x);
+	      pmin.y = Min(pmin.y,vertices[i].r.y);
+	      pmax.x = Max(pmax.x,vertices[i].r.x);
+	      pmax.y = Max(pmax.y,vertices[i].r.y);
+	    }
+	    
+	      R2 DD05 = (pmax-pmin)*0.05;
+	      pmin -=  DD05;
+	      pmax +=  DD05;
+	    
+	    coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
+	    assert(coefIcoor >0);
+	    if (verbosity>5) {
+	      cout << "     Geom: min="<< pmin << "max ="<< pmax << " hmin = " << MinimalHmin() <<  endl;}
+        }
+      else if(!strcmp(fieldname,"MaximalAngleOfCorner")||!strcmp(fieldname,"AngleOfCornerBound"))
+        {         
+          f_in >> MaximalAngleOfCorner;
+              
+	  if(verbosity>5) 
+	    cout << "     Geom Record MaximalAngleOfCorner " << MaximalAngleOfCorner <<endl;
+          MaximalAngleOfCorner *= Pi/180;
+        }
+      else if (!strcmp(fieldname,"Edges"))
+        {
+	  if (nbv <=0) {
+	    cerr<<"Error: the field edges is not found before MetricVertices " << filename<<endl;
+	    NbErr++;}   
+	  else 
+	    {
+	      int i1,i2;
+	      R2 zero2(0,0);
+	      f_in   >>  nbe ;
+	      
+	      edges = new GeometricalEdge[nbe];
+	      if(verbosity>5) 
+		cout << "     Record Edges: Nb of Edge " << nbe <<endl;
+	      assert(edges);
+	      assert (nbv >0); 
+	      Real4 *len =0;
+	      if (!hvertices) 
+		{
+		  len = new Real4[nbv];
+		  for(i=0;i<nbv;i++)
+		    len[i]=0;
+		}
+	      
+	      for (i=0;i<nbe;i++) 
+		{
+		  f_in  >> i1   >> i2 >>  edges[i].ref  ;
+		  
+		  i1--;i2--; // for C index
+		  edges[i].v[0]=  vertices + i1;
+		  edges[i].v[1]=  vertices + i2;
+		  R2 x12 = vertices[i2].r-vertices[i1].r;
+		  Real8 l12=sqrt((x12,x12));
+		  edges[i].tg[0]=zero2;
+		  edges[i].tg[1]=zero2;
+		  edges[i].SensAdj[0] = edges[i].SensAdj[1] = -1;
+		  edges[i].Adj[0] = edges[i].Adj[1] = 0;
+		  edges[i].flag = 0;
+		  if (!hvertices) 
+		    {
+		      vertices[i1].color++;
+		      vertices[i2].color++;
+		      len[i1] += l12;
+		      len[i2] += l12;
+		    }
+		  
+		  Hmin = Min(Hmin,l12);
+		}
+	      // definition  the default of the given mesh size 
+	      if (!hvertices) 
+		{
+		  for (i=0;i<nbv;i++) 
+		    if (vertices[i].color > 0) 
+		      vertices[i].m=  Metric(len[i] /(Real4) vertices[i].color);
+		    else 
+		      vertices[i].m=  Metric(Hmin);
+		  delete [] len;
+		  
+		  if(verbosity>3) 
+		    cout << "     Geom Hmin " << Hmin << endl;
+		}
+	      
+	    }
+	}
+      else if (!strcmp(fieldname,"EdgesTangence") ||!strcmp(fieldname,"TangentAtEdges")  )
+        { 
+          int n,i,j,k;
+          R2 tg;
+          f_in  >> n ;
+          
+	  if(verbosity>5) 
+	    cout << "     Record TangentAtEdges: Nb of Edge " << n <<endl;
+          
+          for (k=0;k<n;k++)
+            {
+	      f_in  >>  i  >> j ;
+	      f_in >> tg.x  >> tg.y ;
+	      assert( i <= nbe );
+	      assert( i > 0 );
+	      assert ( j == 1 || j==2 );
+	      i--;j--;// for C index
+	      edges[i].tg[j] = tg;
+            }
+        }
+      else if (!strcmp(fieldname,"Corners"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+	  if(verbosity>5) 
+	    cout << "     Record Corner: Nb of Corner " << n <<endl;
+          
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbv );
+            assert( j > 0 );
+            j--;
+            vertices[j].SetCorner();
+            vertices[j].SetRequired();  }
+        }
+      else if (!strcmp(fieldname,"RequiredVertices"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbv );
+            assert( j > 0 );
+            j--;
+            vertices[j].SetRequired();  }
+      }
+      else if (!strcmp(fieldname,"RequiredEdges"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbe );
+            assert( j > 0 );
+            j--;
+            edges[j].SetRequired();  }
+      }
+    else if (!strcmp(fieldname,"SubDomain") || !strcmp(fieldname,"SubDomainFromGeom"))
+      { 
+	f_in   >>  NbSubDomains ;
+	if (NbSubDomains>0) 
+	  {
+	    subdomains = new GeometricalSubDomain[  NbSubDomains];
+	    Int4 i0,i1,i2,i3;
+	    for (i=0;i<NbSubDomains;i++) 
+	      {
+		f_in  >> i0  >>i1 
+		      >> i2  >>i3 ; 
+		
+		assert(i0 == 2);
+		assert(i1<=nbe && i1>0);
+		subdomains[i].edge=edges + (i1-1);
+		subdomains[i].sens = (int) i2;
+		subdomains[i].ref = i3;
+	      }
+	  }
+      }
+      else
+	{ // unkown field
+	  field = ++showfield;
+	  if(showfield==1) // just to show one time 
+	    if (verbosity>3)
+	      cout << "    Warning we skip the field " << fieldname << " at line " << f_in.LineNumber << endl;
+	}
+      showfield=field; // just to show one time 
+    } // while !eof()
+  // generation  de la geometrie 
+  // 1 construction des aretes 
+  // construire des aretes en chaque sommets 
+  
+  if (nbv <=0) {
+    cerr<<"Error: the field Vertex is not found in " << filename<<endl;
+    NbErr++;}
+  if(nbe <=0) {
+    cerr <<"Error: the field Edges is not found in "<< filename<<endl
+      ;NbErr++;}
+  if(NbErr) MeshError(1);
+
+ 
+}
+
+
+}  // end of namespace bamg 
Index: /issm/trunk/src/c/Bamgx/MeshWrite.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/MeshWrite.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/MeshWrite.cpp	(revision 2740)
@@ -0,0 +1,955 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+
+
+namespace bamg {
+
+void Triangles::Write(const char * filename,const TypeFileMesh typein )
+{
+	long int verbosity=0;
+
+  TypeFileMesh type = typein;
+  const char * gsuffix=".gmsh";
+  int ls=0;
+  int lll = strlen(filename);
+  if (type==AutoMesh)
+    {
+      type = BDMesh;
+      if      (!strcmp(filename + lll - (ls=7),".am_fmt")) type = am_fmtMesh;
+      else if (!strcmp(filename + lll - (ls=6),".amdba"))  type = amdbaMesh;
+      else if (!strcmp(filename + lll - (ls=3),".am"))     type = amMesh;
+      else if (!strcmp(filename + lll - (ls=5),".nopo"))   type = NOPOMesh;
+      else if (!strcmp(filename + lll - (ls=4),".msh"))    type = mshMesh;
+      else if (!strcmp(filename + lll - (ls=4),".ftq"))    type = ftqMesh;
+      else if (!strcmp(filename + lll - (ls=7),".AM_FMT")) type = am_fmtMesh;
+      else if (!strcmp(filename + lll - (ls=6),".AMDBA"))  type = amdbaMesh;
+      else if (!strcmp(filename + lll - (ls=3),".AM"))     type = amMesh;
+      else if (!strcmp(filename + lll - (ls=5),".NOPO"))   type = NOPOMesh;
+      else if (!strcmp(filename + lll - (ls=4),".MSH"))    type = mshMesh;
+      else if (!strcmp(filename + lll - (ls=4),".FTQ"))    type = ftqMesh;
+      else ls=0;
+    } 
+  if (verbosity>1)
+    {
+      cout << "  -- Writing the file " << filename << " of type " ;
+     switch (type) 
+       {
+       case BDMesh     :  cout << " BD Mesh "  ; break;
+       case NOPOMesh   :  cout << " NOPO "     ; break;
+       case amMesh     :  cout << " am "       ; break;
+       case am_fmtMesh :  cout << " am_fmt "   ; break;
+       case amdbaMesh  :  cout << " amdba "    ; break;
+       case ftqMesh    :  cout << " ftq "      ; break;
+       case mshMesh    :  cout << " msh "      ; break;
+	default: 
+	  cerr << endl 
+	       <<  " Unkown type mesh file " << (int) type << " for Writing " << filename <<endl;
+	  MeshError(1);
+       }     
+     Int4 NbOfTria =  nbt-2*NbOfQuad-NbOutT ;
+     if (NbOfTria)      cout << " NbOfTria = " << NbOfTria;
+     if (NbOfQuad)      cout << " NbOfQuad = " << NbOfQuad;
+     if (nbe)   	cout << " NbOfRefEdge = " << nbe ;
+     cout    << endl;
+
+    }
+  ofstream f(filename /*,ios::trunc*/);
+ f.precision(12);
+
+   if (f)
+     switch (type) 
+       {
+       case BDMesh     : 
+          {
+             if ( ! Gh.OnDisk)
+              {
+                 delete [] Gh.name;
+                 Gh.name = new char[lll+1+strlen(gsuffix)];
+                 strcpy(Gh.name,filename);
+                 if (Gh.name[lll-ls-1]=='.') strcpy(Gh.name+lll-ls, gsuffix+1);
+                 else strcpy(Gh.name+lll-ls,gsuffix);
+                cout << " write geo in " << Gh.name << endl;
+                  ofstream f(Gh.name) ;
+                  f << Gh ;
+                  Gh.OnDisk=true;
+              }
+	     f << *this     ;
+	     break;
+           }
+       case NOPOMesh   :  Write_nopo(f)  ; break;
+       case amMesh     :  Write_am(f)    ; break;
+       case am_fmtMesh :  Write_am_fmt(f); break;
+       case amdbaMesh  :  Write_amdba(f) ; break;
+       case ftqMesh    :  Write_ftq(f)   ; break;
+       case mshMesh    :  Write_msh(f)   ; break;
+	default: 
+	  cerr << " Unkown type mesh file " << (int) type << " for Writing " << filename <<endl;
+	  MeshError(1);
+       }
+   else
+     {
+       cerr << " Error openning file " << filename << endl;
+       MeshError(1);
+     }
+   if(verbosity>5)
+   cout << "end write" << endl;
+      
+}
+void Triangles::Write_nop5(OFortranUnFormattedFile * f,
+			   Int4 &lnop5,Int4 &nef,Int4 &lgpdn,Int4 ndsr) const 
+{
+	long int verbosity=0;
+
+  ndsr =0;
+  Int4 * reft = new Int4[nbt];
+  //Int4 nbInT = ;
+  ConsRefTriangle(reft);
+  Int4 no5l[20];
+
+  Int4 i5 = 0;
+  Int4 i,j,k=0,l5;
+  //  Int4 ining=0;
+  Int4 imax,imin;
+
+  lgpdn = 0;
+  nef=0;
+  // construction of a liste linked  of edge
+  Edge ** head  = new Edge *[nbv];
+  Edge  ** link = new Edge * [nbe];
+  for (i=0;i<nbv;i++)
+    head[i]=0; // empty liste
+  
+  for (i=0;i<nbe;i++)
+    { 
+      j = Min(Number(edges[i][0]),Number(edges[i][1]));
+      link[i]=head[j];
+      head[j]=edges +i;
+    }
+  for ( i=0;i<nbt;i++)
+    {
+      no5l[0]    = 0;
+      Int4 kining=0;
+      Int4 ining=0;
+      Int4 nmae =0;
+      Int4 np=0;
+      l5 = 2;
+      Triangle & t = triangles[i];
+      Triangle * ta; // 
+      Vertex *v0,*v1,*v2,*v3;
+      if (reft[i]<0) continue;
+      ta = t.Quadrangle(v0,v1,v2,v3);
+      if (!ta)
+	{ // a triangles
+	  no5l[l5++] = Max(subdomains[reft[i]].ref,(Int4) 1);
+	  np = 3;
+	  no5l[l5++] = np;
+	  no5l[0]    = np;
+	  no5l[l5++] = Number(triangles[i][0]) +1;
+	  no5l[l5++] = Number(triangles[i][1]) +1;
+	  no5l[l5++] = Number(triangles[i][2]) +1;
+	  imax = Max3(no5l[l5-1],no5l[l5-2],no5l[l5-3]);
+	  imin = Min3(no5l[l5-1],no5l[l5-2],no5l[l5-3]);
+	  lgpdn = Max(lgpdn,imax-imin);
+          kining=l5++;
+	  // ref of 3 edges 
+	  for (j=0;j<3;j++)
+	    {
+	      no5l[l5] = 0;
+	      int i0 = (int) j;
+	      int i1 = (i0+1) %3;
+	      Int4 j1= no5l[4+i0];
+	      Int4 j2= no5l[4+i1];
+	      Int4 ji = Min(j1,j2)-1;
+	      Int4 ja = j1+j2-2;
+	      Edge * e=head[ji];
+	      while (e)
+		if(Number((*e)[0])+Number((*e)[1]) == ja) 
+		   {
+		     no5l[l5] = e->ref;
+		     break;
+		   }
+		else
+		  e = link[Number(e)];
+	      l5++;
+	    }
+	  if ( no5l[l5-1] || no5l[l5-2] || no5l[l5-3]  )
+	    ining=2;
+	  else 
+	    l5 -= 3;
+	  
+	  no5l[l5++] = triangles[i][0].ref();
+	  no5l[l5++] = triangles[i][1].ref();
+	  no5l[l5++] = triangles[i][2].ref();
+	  if (ining ||  no5l[l5-1] || no5l[l5-2] || no5l[l5-3]  )
+            ining= ining ? ining : 3;
+	  else
+	    l5 -= 3,ining=0;
+
+	  
+	}
+      else if ( &t<ta)
+	{ 
+	  k++;
+	  no5l[l5++] = Max(subdomains[reft[i]].ref,(Int4) 1);
+	  np =4;
+	  no5l[l5++] = np;
+	  no5l[0]    = np;
+	  
+	  no5l[l5++] = Number(v0) +1;
+	  no5l[l5++] = Number(v1) +1;
+	  no5l[l5++] = Number(v2) +1;
+	  no5l[l5++] = Number(v3) +1;
+	  
+	  imax = Max(Max(no5l[l5-1],no5l[l5-2]),Max(no5l[l5-3],no5l[l5-4]));
+	  imin = Min(Min(no5l[l5-1],no5l[l5-2]),Min(no5l[l5-3],no5l[l5-4]));
+	  lgpdn = Max(lgpdn,imax-imin);
+
+
+          kining=l5++;
+	  // ref of the 4 edges 
+	  // ref of 3 edges 
+	  for (j=0;j<4;j++)
+	    {
+	      no5l[l5] = 0;
+	      int i0 = (int) j;
+	      int i1 = (i0+1) %4;
+	      Int4 j1= no5l[4+i0];
+	      Int4 j2= no5l[4+i1];
+	      Int4 ji = Min(j1,j2)-1;
+	      Int4 ja = j1+j2-2;
+	      Edge *e=head[ji];
+	      while (e)
+		if(Number((*e)[0])+Number((*e)[1]) == ja) 
+		   {
+		     no5l[l5] = e->ref;
+		     break;
+		   }
+		else
+		  e = link[Number(e)];
+	      l5++;
+	    }
+	  if ( no5l[l5-1] || no5l[l5-2] || no5l[l5-3] || no5l[l5-4] )
+	    ining=2;
+	  else 
+	    l5 -= 4;
+
+	  no5l[l5++] = v0->ref();
+	  no5l[l5++] = v1->ref();
+	  no5l[l5++] = v2->ref();
+	  no5l[l5++] = v3->ref();
+	  if (ining || no5l[l5-1] || no5l[l5-2] || no5l[l5-3] || no5l[l5-4] )
+            ining= ining ? ining : 3;
+          else
+	    l5 -= 4;
+
+	}
+      else l5=0;
+
+     if (l5)
+       {
+	 if (ining)
+	   {
+	     nef ++;
+	     nmae = l5-kining;
+	     no5l[kining] = ining;
+	   }
+	 else l5--;
+	 no5l[1]=nmae;
+	 // for all ref  
+	 for (j=kining+1;j<l5;j++)
+	   {
+	     no5l[j] = Abs(no5l[j]);
+	     ndsr = Max(ndsr,no5l[j]);
+	   }
+	 
+	 if (f && i < 10 && verbosity > 10)
+	   { 
+	     cout << " e[ " << i << " @" << i5 << "]=";
+	     for (j=0;j<l5;j++)
+	       cout << " " << no5l[j]; 
+	     cout << endl;
+	   }
+	 
+	 if (f)
+	   for (j=0;j<l5;j++)
+	     *f << no5l[j]; 
+	 i5 += l5;
+       }
+    }
+  if(verbosity>10)
+  cout << "   fin write nopo 5 i5=" << i5 << " " << i5*4 << endl;
+  lnop5=i5; 
+  lgpdn++; // add 1
+  delete [] reft;
+  delete [] head;
+  delete [] link;
+  
+}
+
+void Triangles::Write_nopo(ostream &ff) const
+
+{
+ Int4  nef=0;
+ Int4 lpgdn=0;
+ Int4 ndsr=0;
+ Int4 i;
+ Int4 ndsd=1;
+ Int4 lnop5=0;
+ 
+ OFortranUnFormattedFile f(ff);
+ 
+ for (i=0;i<NbSubDomains ;i++)
+   ndsd=Max(ndsd,subdomains[i].ref);
+ 
+ // to compute the lnop5,nef,lpgdn,ndsr parameter 
+ Write_nop5(0,lnop5,nef,lpgdn,ndsr);
+ 
+ f.Record();
+ 
+ f <<  Int4(13)<<Int4(6)<<Int4(32)<<Int4(0)<<Int4(27)<<Int4(0) ;
+ f << Int4(nbv+nbv) ;
+ f << lnop5;
+ f << Int4(1 )<<Int4(1)<<Int4(1 )<<Int4(1)<<Int4(2)<<Int4(1);
+
+ f.Record(33*sizeof(Int4)); 
+
+ f << Int4(32) ;
+ 
+ //char *c=identity;
+ time_t timer =time(0);
+ char buf[10];
+ strftime(buf ,10,"%y/%m/%d",localtime(&timer));
+ f.write4(identity,20);
+ f.write4(buf,2);
+ f.write4("created with BAMG",6);
+ f.write4("NOPO",1);
+
+ 
+ f << Int4(0) << Int4(1) << Int4(0) ;
+ f.Record();
+ Int4 nbquad= NbOfQuad;
+ Int4 nbtria= nbt-NbOutT - 2*NbOfQuad;
+
+ cout << " lnop5      = " << lnop5 << endl;
+ cout << " nbquad     = " << nbquad << endl;
+ cout << " nbtrai     = " << nbtria << endl;
+ cout << " lpgdn      = " << lpgdn << endl;
+ cout << " nef        = " << nef  << endl;
+ cout << " np         = " << nbv  << endl;
+ cout << " ndsr       = " << ndsr << endl;
+ f << Int4(27)  
+   << Int4(2)  << ndsr     << ndsd    << Int4(1) << nbtria+nbquad
+   << Int4(0)  << Int4(0)  << nbtria  << nbquad  << Int4(0)
+   << Int4(0)  << Int4(0)  << Int4(0) << nef     << Int4(nbv)
+   << Int4(0)  << Int4(0)  << Int4(0) << Int4(0) << Int4(0)
+   << Int4(0)  << nbv      << Int4(2) << lpgdn   << Int4(0)
+   << lnop5    << Int4(1) ;
+  f.Record();
+  f << (Int4) 2*nbv;
+  for (i=0;i<nbv;i++)
+    f << (float) vertices[i].r.x <<  (float) vertices[i].r.y;
+  f.Record();
+  f << lnop5;
+  Write_nop5(&f,lnop5,nef,lpgdn,ndsr);
+  // cout << "fin write nopo" << endl;
+}
+
+void Triangles::Write_am_fmt(ostream &f) const 
+{
+  Int4 i,j;
+  assert(this && nbt);
+  Int4 * reft = new Int4[nbt];
+  Int4 nbInT =    ConsRefTriangle(reft);
+  f.precision(12);
+  f << nbv << " " << nbInT << endl;
+  for (i=0;i<nbt;i++)
+    if(reft[i]>=0)
+      {
+	f << Number(triangles[i][0]) +1 << " " ;
+	f << Number(triangles[i][1]) +1 << " " ;
+	f << Number(triangles[i][2]) +1 << " " ;
+	f << endl;
+      }
+  for (i=0;i<nbv;i++)
+      f << vertices[i].r.x << " " << vertices[i].r.y << endl;
+   for (j=i=0;i<nbt;i++) 
+     if (reft[i]>=0)
+       f << subdomains[reft[i]].ref  << (j++%10 == 9 ?  '\n' : ' ');
+   f << endl;
+   for (i=0;i<nbv;i++)
+     f << vertices[i].ref()  << (i%10 == 9 ?  '\n' : ' ');
+   f << endl;
+   delete [] reft;
+
+
+}
+
+void Triangles::Write_am(ostream &ff) const 
+{
+  OFortranUnFormattedFile f(ff);  
+  Int4 i,j;
+  assert(this && nbt);
+  Int4 * reft = new Int4[nbt];
+  Int4 nbInT =    ConsRefTriangle(reft);
+  f.Record();
+  f << nbv << nbInT ;
+  f.Record();
+  for (i=0;i<nbt;i++)
+    if(reft[i]>=0)
+      {
+	f << Number(triangles[i][0]) +1 ;
+	f << Number(triangles[i][1]) +1 ;
+	f << Number(triangles[i][2]) +1 ;
+      }
+  for (i=0;i<nbv;i++)
+    {
+      float x= vertices[i].r.x;
+      float y= vertices[i].r.y;
+      f << x << y ;
+    }
+  for (j=i=0;i<nbt;i++) 
+    if (reft[i]>=0)
+      f << subdomains[reft[i]].ref;
+  for (i=0;i<nbv;i++)
+    f << vertices[i].ref() ;
+  delete [] reft;
+}
+
+void Triangles::Write_ftq(ostream &f) const 
+{
+
+  Int4 i;
+  assert(this && nbt);
+  Int4 * reft = new Int4[nbt];
+  Int4 nbInT =    ConsRefTriangle(reft);
+  f.precision(12);
+  Int4 nele = nbInT-NbOfQuad;
+  Int4 ntri =  nbInT-2*NbOfQuad;
+  Int4 nqua =  NbOfQuad;
+
+  f << nbv << " " << nele << " " << ntri <<  " " << nqua << endl;
+  Int4 k=0;
+  for( i=0;i<nbt;i++)
+    { 
+      Triangle & t = triangles[i];
+      Triangle * ta; // 
+      Vertex *v0,*v1,*v2,*v3;
+      if (reft[i]<0) continue;
+      ta = t.Quadrangle(v0,v1,v2,v3);
+      if (!ta)
+	{ // a triangles
+	  f << "3 " 
+	    << Number(triangles[i][0]) +1 << " " 
+	    << Number(triangles[i][1]) +1 << " " 
+	    << Number(triangles[i][2]) +1 << " " 
+	    << subdomains[reft[i]].ref << endl;
+	  k++;
+	}
+      if ( &t<ta)
+	{ 
+	  k++;
+	  f << "4 " << Number(v0)+1 << " " << Number(v1)+1  << " "  
+	    << Number(v2)+1 << " "  << Number(v3)+1 << " "  
+	    << subdomains[reft[i]].ref << endl;
+	}
+    }
+  assert(k == nele);
+  
+  for (i=0;i<nbv;i++)
+    f << vertices[i].r.x << " " << vertices[i].r.y 
+      << " " <<  vertices[i].ref() << endl;
+  delete [] reft;
+  
+  
+}
+void Triangles::Write_msh(ostream &f) const 
+{
+  Int4 i;
+  assert(this && nbt);
+  Int4 * reft = new Int4[nbt];
+  Int4 nbInT =    ConsRefTriangle(reft);
+  f.precision(12);
+  f << nbv << " " << nbInT << " " << nbe <<  endl;
+
+  for (i=0;i<nbv;i++)
+    f << vertices[i].r.x << " " << vertices[i].r.y << " " 
+      << vertices[i].ref() <<   endl;
+
+  for (i=0;i<nbt;i++)
+    if(reft[i]>=0)
+      f << Number(triangles[i][0]) +1 << " " 
+	<< Number(triangles[i][1]) +1 << " " 
+	<< Number(triangles[i][2]) +1 << " " 
+	<< subdomains[reft[i]].ref << endl;
+  
+
+  for (i=0;i<nbe;i++)
+    f << Number(edges[i][0]) +1 << " "  << Number(edges[i][1]) +1 
+      << " " << edges[i].ref << endl;
+      
+   delete [] reft;
+
+}
+
+void Triangles::Write_amdba(ostream &f) const 
+{
+  assert(this && nbt);
+
+  Int4 i,j;
+  Int4 * reft = new Int4[nbt];
+  Int4 nbInT =    ConsRefTriangle(reft);
+  f << nbv << " " << nbInT << endl;
+  cout.precision(12);
+  for (i=0;i<nbv;i++)
+    f << i+1 << " " 
+      << vertices[i].r.x 
+      << " " << vertices[i].r.y 
+      << " " << vertices[i].ref() << endl;
+  j=1;
+  for (i=0;i<nbt;i++)
+    if(reft[i]>=0)
+	f << j++ << " " 
+	  << Number(triangles[i][0]) +1 << " " 
+	  << Number(triangles[i][1]) +1 << " " 
+	  << Number(triangles[i][2]) +1 << " " 
+	  << subdomains[reft[i]].ref  << endl ;
+	f << endl;
+   delete [] reft;
+
+
+}
+
+void Triangles::Write(const char * filename)
+{
+  ofstream f(filename);
+  if (f)
+    {
+       if (name) delete name;
+       name = new char[strlen(filename)+1];
+       strcpy(name,filename);
+       OnDisk =1;
+       f << *this;
+    }
+}
+void Triangles::WriteElements(ostream& f,Int4 * reft ,Int4 nbInT) const
+   { 
+     const Triangles & Th= *this;
+	 long int verbosity=0;
+
+     // do triangle and quad 
+     if(verbosity>9) 
+       cout  << " In Triangles::WriteElements " << endl
+	     << "   Nb of In triangles " << nbInT-Th.NbOfQuad*2 << endl
+	     << "   Nb of Quadrilaterals " <<  Th.NbOfQuad << endl
+	     << "   Nb of in+out+quad  triangles " << Th.nbt << " " << nbInT << endl;
+	 
+     Int4 k=nbInT-Th.NbOfQuad*2;
+     Int4 num =0;
+     if (k>0) {
+       f << "\nTriangles\n"<< k << endl;
+       for(Int4 i=0;i<Th.nbt;i++)
+	 { 
+	   Triangle & t = Th.triangles[i];
+	   if (reft[i]>=0 && !( t.Hidden(0) || t.Hidden(1) || t.Hidden(2) ))
+	    { k--;
+	      f << Th.Number(t[0])+1 << " " << Th.Number(t[1])+1 
+		   << " "  << Th.Number(t[2])+1  << " " << Th.subdomains[reft[i]].ref << endl;
+		   reft[i] = ++num;
+		 }
+	 }
+     } 
+     if (Th.NbOfQuad>0) {
+       f << "\nQuadrilaterals\n"<<Th.NbOfQuad << endl;
+       k = Th.NbOfQuad;
+       for(Int4 i=0;i<Th.nbt;i++)
+	 { 
+	   Triangle & t = Th.triangles[i];
+	   Triangle * ta; // 
+	   Vertex *v0,*v1,*v2,*v3;
+	   if (reft[i]<0) continue;
+	   if ((ta=t.Quadrangle(v0,v1,v2,v3)) !=0 && &t<ta)
+	      { 
+		k--;
+		f << Th.Number(v0)+1 << " " << Th.Number(v1)+1  << " "  
+		  << Th.Number(v2)+1 << " "  << Th.Number(v3)+1 << " "  
+		  << Th.subdomains[reft[i]].ref << endl;
+		  reft[i] = ++num;
+		  reft[Number(ta)] = num;
+	      }
+	 }
+       assert(k==0);
+     }
+     // warning reft is now the element number 
+   }
+
+ostream& operator <<(ostream& f, const   Triangles & Th) 
+ {
+  //  Th.FindSubDomain();
+   // warning just on say the class is on the disk
+  //  ((Triangles *) &Th)->OnDisk = 1;
+
+   Int4 * reft = new Int4[Th.nbt];
+   Int4 nbInT =    Th.ConsRefTriangle(reft);
+   {
+     f << "MeshVersionFormatted 0" <<endl;
+     f << "\nDimension\n"  << 2 << endl;
+     f << "\nIdentifier\n" ;
+     WriteStr(f,Th.identity);
+     f << "\n\nGeometry\n" ;
+     if( Th.Gh.OnDisk)
+       WriteStr(f,Th.Gh.name),     f <<endl;
+     else
+       { // empty file name -> geom in same file
+	 f << "\"\"" << endl << endl;
+	 f << "# BEGIN of the include geometry file because geometry is not on the disk"
+	   << Th.Gh << endl;
+	 f << "End" << endl 
+	   << "# END of the include geometrie file because geometry is not on the disk"
+	   << endl ;
+       }
+   }
+   { 
+     f.precision(12);
+     f << "\nVertices\n" << Th.nbv <<endl;
+     for (Int4 i=0;i<Th.nbv;i++)
+       {
+	 Vertex & v =  Th.vertices[i];
+	 f << v.r.x << " " << v.r.y << " " << v.ref() << endl;
+       }
+   }
+  Int4 ie; 
+   {
+     f << "\nEdges\n"<< Th.nbe << endl;
+     for(ie=0;ie<Th.nbe;ie++)
+       { 
+	 Edge & e = Th.edges[ie];
+	 f << Th.Number(e[0])+1 << " " << Th.Number(e[1])+1;
+	f << " " << e.ref <<endl;
+       }
+     if(Th.NbCrackedEdges)
+       {
+	 f << "\nCrackedEdges\n"<< Th.NbCrackedEdges << endl;
+	 for( ie=0;ie<Th.NbCrackedEdges;ie++)
+	   { 
+	     Edge & e1 = *Th.CrackedEdges[ie].a.edge;
+	     Edge & e2 = *Th.CrackedEdges[ie].b.edge;
+	     f << Th.Number(e1)+1 << " " << Th.Number(e2)+1 <<endl;;
+	   }
+       }
+   }
+
+   Th.WriteElements(f,reft,nbInT);
+   {
+     f << "\nSubDomainFromMesh\n" << Th.NbSubDomains<< endl ;
+     for (Int4 i=0;i<Th.NbSubDomains;i++)
+       f << 3 << " " << reft[Th.Number(Th.subdomains[i].head)] << " " << 1 << " " 
+	 <<  Th.subdomains[i].ref << endl;
+     
+   }
+   if (Th.Gh.NbSubDomains)
+     {
+        f << "\nSubDomainFromGeom\n" << Th.Gh.NbSubDomains << endl ;
+       for (Int4 i=0;i<Th.NbSubDomains;i++)
+	 {  
+	 f << 2 << " " << Th.Number(Th.subdomains[i].edge)+1 << " " 
+	   <<  Th.subdomains[i].sens  << " " <<  Th.Gh.subdomains[i].ref << endl;
+	 } 
+   }
+   {
+     f << "\nVertexOnGeometricVertex\n"<<  Th.NbVerticesOnGeomVertex << endl;
+     for (Int4 i0=0;i0<Th.NbVerticesOnGeomVertex;i0++)
+       {
+	 VertexOnGeom & v =Th.VerticesOnGeomVertex[i0];
+	 assert(v.OnGeomVertex()) ;
+	 f << " " << Th.Number(( Vertex *)v)+1  
+	   << " " << Th.Gh.Number(( GeometricalVertex * )v)+1 
+	   << endl;
+       }
+   }
+   { 
+     f << "\nVertexOnGeometricEdge\n"<<  Th.NbVerticesOnGeomEdge << endl;
+     for (Int4 i0=0;i0<Th.NbVerticesOnGeomEdge;i0++)
+       {
+	 const VertexOnGeom & v =Th.VerticesOnGeomEdge[i0];
+	 assert(v.OnGeomEdge()) ;   
+	 f << " " << Th.Number((Vertex * )v)+1  ;
+	 f << " " << Th.Gh.Number((const  GeometricalEdge * )v)+1  ;
+	 f << " " << (Real8 ) v << endl;
+       }
+   }
+   {
+     Int4 i0,k=0;
+
+     for (i0=0;i0<Th.nbe;i0++)
+       if ( Th.edges[i0].on ) k++;
+     
+     f << "\nEdgeOnGeometricEdge\n"<< k << endl;
+      for (i0=0;i0<Th.nbe;i0++)
+	if ( Th.edges[i0].on ) 
+	  f << (i0+1) << " "  << (1+Th.Gh.Number(Th.edges[i0].on)) <<  endl;
+      if (Th.NbCrackedEdges)
+	{
+	  f << "\nCrackedEdges\n"<< Th.NbCrackedEdges << endl;	  
+	  for(i0=0;i0< Th.NbCrackedEdges; i0++) 
+	    {
+	      f << Th.Number(Th.CrackedEdges[i0].a.edge) << " " ;
+	      f  << Th.Number(Th.CrackedEdges[i0].b.edge) << endl;
+	    }
+	}
+   }  
+   if (&Th.BTh != &Th && Th.BTh.OnDisk && Th.BTh.name) 
+     {
+       int *mark=new int[Th.nbv];
+       Int4 i;
+       for (i=0;i<Th.nbv;i++)
+	 mark[i]=-1;
+       f << "\nMeshSupportOfVertices\n" <<endl;
+       WriteStr(f,Th.BTh.name);
+       f <<endl;
+       f << "\nIdentityOfMeshSupport" << endl;
+       WriteStr(f,Th.BTh.identity);
+       f<<endl;
+
+       f << "\nVertexOnSupportVertex" << endl;
+       f<< Th.NbVertexOnBThVertex << endl;
+       for(i=0;i<Th.NbVertexOnBThVertex;i++) {
+	 const VertexOnVertex & vov = Th.VertexOnBThVertex[i];
+	 Int4 iv = Th.Number(vov.v);
+	 mark[iv] =0;
+	 f << iv+1<< " " << Th.BTh.Number(vov.bv)+1 << endl;}
+
+       f << "\nVertexOnSupportEdge" << endl;
+       f << Th.NbVertexOnBThEdge << endl;
+       for(i=0;i<Th.NbVertexOnBThEdge;i++) {
+	 const VertexOnEdge & voe = Th.VertexOnBThEdge[i];
+	 Int4 iv = Th.Number(voe.v);
+	 //	 assert(mark[iv] == -1]);
+	 mark[iv] = 1;
+	 f << iv+1 << " " << Th.BTh.Number(voe.be)+1 << " " << voe.abcisse <<  endl;}
+       
+       f << "\nVertexOnSupportTriangle" << endl;   
+       Int4 k = Th.nbv -  Th.NbVertexOnBThEdge - Th.NbVertexOnBThVertex;
+       f << k << endl;
+       //       Int4 kkk=0;
+       CurrentTh=&Th.BTh;
+       for (i=0;i<Th.nbv;i++) 
+	 if (mark[i] == -1) {
+	   k--;
+	   Icoor2 dete[3];
+	   I2 I = Th.BTh.toI2(Th.vertices[i].r);
+	   Triangle * tb = Th.BTh.FindTriangleContening(I,dete);
+	   if (tb->link) // a true triangle
+	     {
+	       Real8 aa= (Real8) dete[1]/ tb->det, bb= (Real8) dete[2] / tb->det;
+	       f << i+1 << " " << Th.BTh.Number(tb)+1 << " " << aa << " " << bb << endl ;
+	     }
+	   else 
+	     {
+	       double aa,bb,det[3];
+	       TriangleAdjacent ta=CloseBoundaryEdgeV2(I,tb,aa,bb);
+	       int k = ta;
+	       det[VerticesOfTriangularEdge[k][1]] =aa;
+	       det[VerticesOfTriangularEdge[k][0]] = bb;
+	       det[OppositeVertex[k]] = 1- aa -bb;
+	       Triangle * tb = ta;
+	       f << i+1 << Th.BTh.Number(tb)+1 << " " << det[1] << " " << det[2] <<endl;
+	     }
+	 }
+       assert(!k);
+       delete [] mark;
+	 
+
+     }
+   f << "\nEnd" << endl;
+   //  Th.ConsLinkTriangle();
+   delete [] reft;
+   return f;
+   
+}
+
+
+
+void Geometry::Write(const char * filename)
+{
+	long int verbosity=0;
+
+  ofstream f(filename);
+  if (f)
+    {
+      if(verbosity>1)
+	cout << "  -- write geometry in file " << filename << endl;
+       if (name) delete name;
+       name = new char[strlen(filename)+1];
+       strcpy(name,filename);
+       OnDisk =1;
+       f << *this;
+    }
+}
+
+ostream& operator <<(ostream& f, const   Geometry & Gh) 
+{
+   Int4  NbCorner=0;
+   {
+     f << "MeshVersionFormatted 0" <<endl;
+     f << "\nDimension\n"  << 2 << endl;
+//     f << "\nIdentifier\n" ;
+//     WriteStr(f,Gh.identity);
+//     f <<endl;
+   }
+   int nbreqv=0;
+   { 
+     
+     f.precision(12);
+     f << "\nVertices\n" << Gh.nbv <<endl;
+     for (Int4 i=0;i<Gh.nbv;i++)
+       {
+	 GeometricalVertex & v =  Gh.vertices[i];
+	 if (v.Required()) nbreqv++;
+	 f << v.r.x << " " << v.r.y << " " << v.ref() << endl;
+	 if (v.Corner()) NbCorner++;
+       }
+   }
+   
+   int nbcracked=0;
+
+   {
+     int nbreq=0;
+     f << "\nEdges\n"<< Gh.nbe << endl;
+     for(Int4 ie=0;ie<Gh.nbe;ie++)
+       { 
+	 
+	 GeometricalEdge & e = Gh.edges[ie];
+	 if (e.Required()) nbreq++;
+	 if (e.Cracked()) { 
+	   Int4 ie1 = Gh.Number(e.link);
+	   if (ie <= ie1)  ++nbcracked;}
+	 f << Gh.Number(e[0])+1 << " " << Gh.Number(e[1])+1;
+	 f << " " << e.ref <<endl;
+       }
+     
+     if (nbcracked)
+       {
+	 f << "\nCrackedEdges\n"<< nbcracked<< endl;
+	 for(Int4 ie=0;ie<Gh.nbe;ie++)
+	   {
+	     GeometricalEdge & e = Gh.edges[ie];
+	     if (e.Cracked()) { 
+	       Int4  ie1 = Gh.Number(e.link);
+	       if (ie <= ie1)  f << ie+1 << " " << ie1+1<< endl;
+	     }
+	   }
+       }
+     if(nbreq)
+       {
+	 f << "\nRequiredEdges\n"<< nbreq<< endl;
+         for(Int4 ie=0;ie<Gh.nbe;ie++)
+           {
+             GeometricalEdge & e = Gh.edges[ie];
+             if (e.Required()) 
+	       f << ie+1 << endl;
+	   }
+       }
+     
+     
+     
+   }
+
+    f << "\nAngleOfCornerBound\n" 
+     << Gh.MaximalAngleOfCorner*180/Pi << endl;
+    if (NbCorner) 
+      {
+	f << "\nCorners\n" << NbCorner << endl;
+	for (Int4 i=0,j=0;i<Gh.nbv;i++)
+	  {
+	    GeometricalVertex & v =  Gh.vertices[i];
+	    if (v.Corner()) 
+	      j++,f << Gh.Number(v)+1 << (j % 5 ? ' ' : '\n');
+	  }
+        
+      
+      }
+
+    if(nbreqv)
+      {
+	f << "\nRequiredVertices\n"<< nbreqv<< endl;
+	for (Int4 j=0,i=0;i<Gh.nbv;i++)
+	  {
+	    GeometricalVertex & v =  Gh.vertices[i];
+	    
+	    if (v.Required()) 
+	      j++,f << i+1 << (j % 5 ? ' ' : '\n');
+	  }
+	f << endl;
+      }
+    
+    { 
+       Int4 i;
+       f << "\nSubDomainFromGeom\n" ;
+       f << Gh.NbSubDomains<< endl;
+       for (i=0;i<Gh.NbSubDomains;i++) 
+         f << "2 " << Gh.Number(Gh.subdomains[i].edge)+1 << " " << Gh.subdomains[i].sens 
+           << " " << Gh.subdomains[i].ref << endl;        
+     }
+     {
+       Int4 n=0,i;
+
+       for(i=0;i< Gh.nbe;i++)
+	 {
+	   if(Gh.edges[i].TgA() && Gh.edges[i][0].Corner() ) 
+	     n++;
+	   if(Gh.edges[i].TgB() && Gh.edges[i][1].Corner() ) 
+	     n++;
+	 }
+       if (n) {
+	 f << "TangentAtEdges " << n << endl;
+	 for(i=0;i< Gh.nbe;i++)
+	   {
+	     if (Gh.edges[i].TgA() && Gh.edges[i][0].Corner() ) 
+	       f << i+1 << " 1 " << Gh.edges[i].tg[0].x 
+		 << " " << Gh.edges[i].tg[0].y << endl;
+	     if (Gh.edges[i].TgB() && Gh.edges[i][1].Corner() ) 
+	       f << i+1 << " 2 " << Gh.edges[i].tg[1].x 
+		 << " " << Gh.edges[i].tg[1].y << endl;
+	   }
+	 
+       }}
+     //  f << " Not Yet Implemented" << endl;
+     
+     return f;
+}
+
+
+} // end of namespace bamg 
Index: /issm/trunk/src/c/Bamgx/Meshgibbs.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/Meshgibbs.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Meshgibbs.cpp	(revision 2740)
@@ -0,0 +1,1064 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "./Mesh2.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+//#include "vect.h"
+
+
+#define mmax(a,b)(a>b?a:b)
+#define mmin(a,b)(a<b?a:b)
+#define ffalse 0
+#define ttrue 1
+
+/*  -- translated by f2c (version of 23 May 1992  14:18:33).
+   You must link the resulting object file with the libraries:
+	-lF77 -lI77 -lm -lc   (in that order)
+*/
+
+
+#define integer long
+#define logical long
+
+int gibbs1_(integer* n,integer*  record,integer*  ptvois);
+int gibbs2_(integer* n,integer*  record,integer*  criter);
+int gibbsa_(integer* n,integer*  ptvois,integer*  vois,integer*  r,integer*  m,
+             integer*  nv,integer*  nx,integer*  ny,integer*  nn,integer*  w1,integer*  w2, 
+	integer* pfold,integer*  pfnew,integer*  impre,integer*  nfout);
+int gibbsb_(integer* x,integer*  y,integer*  n,integer*  ptvois,
+						integer*  vois,integer*  nx,integer*  ny,integer*  nv,integer*  nn,integer*  m,
+						integer*  wh,integer*  wl,integer* r, integer* impre, integer* nfout);
+int gibbsc_(integer* nz,integer*  nv,integer*  niveau,integer*  n,integer* );
+int gibbsd_(integer* racine,integer*  n,integer*  ptvois,integer*  
+							vois,integer*  nv,integer*  r,integer*  niveau);
+int gibbst_(integer* n,integer*  p,integer*  nv,integer*  nn,integer*  ptvois,integer*  vois,
+						integer*  m,integer*  r,integer*  new_,integer*  option, 
+						integer* pfnew,integer*  impre,integer*  nfout);
+
+/* Subroutine */ int gibbs1_(integer* n,integer*  record,integer*  ptvois)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer crit, i, j, l, r, rec;
+
+/* -----------------------------------------------------------------------
+ */
+/*     routine appele par gibbs0 */
+/* -----------------------------------------------------------------------
+ */
+/*     but: trie record (ensemble de n sommet) telle que l'ordre des somm 
+*/
+/*     soit croissant (ordre du sommet i est ptvois(i+1)-ptvois(i)) */
+/* -----------------------------------------------------------------------
+ */
+
+    /* Parameter adjustments */
+    --ptvois;
+    --record;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    l = *n / 2 + 1;
+    r = *n;
+L2:
+    if (l <= 1) {
+	goto L20;
+    }
+    --l;
+    rec = record[l];
+    crit = ptvois[record[l] + 1] - ptvois[record[l]];
+    goto L3;
+L20:
+    rec = record[r];
+    crit = ptvois[record[r] + 1] - ptvois[record[r]];
+    record[r] = record[1];
+    --r;
+    if (r == 1) {
+	goto L999;
+    }
+L3:
+    j = l;
+L4:
+    i = j;
+    j <<= 1;
+    if ((i__1 = j - r) < 0) {
+	goto L5;
+    } else if (i__1 == 0) {
+	goto L6;
+    } else {
+	goto L8;
+    }
+L5:
+    if (ptvois[record[j] + 1] - ptvois[record[j]] < ptvois[record[j + 1] + 1] 
+	    - ptvois[record[j + 1]]) {
+	++j;
+    }
+L6:
+    if (crit >= ptvois[record[j] + 1] - ptvois[record[j]]) {
+	goto L8;
+    }
+    record[i] = record[j];
+    goto L4;
+L8:
+    record[i] = rec;
+    goto L2;
+L999:
+    record[1] = rec;
+    return 0;
+} /* gibbs1_ */
+
+/* Subroutine */ int gibbs2_(integer* n,integer*  record,integer*  criter)
+{
+    static integer crit, i, j, l, r, rec;
+
+
+/*     trie record selon les valeurs de criter(record(.)) croissantes */
+
+
+    /* Parameter adjustments */
+    --criter;
+    --record;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    l = *n / 2 + 1;
+    r = *n;
+L2:
+    if (l <= 1) {
+	goto L20;
+    }
+    --l;
+    rec = record[l];
+    crit = criter[rec];
+    goto L3;
+L20:
+    rec = record[r];
+    crit = criter[rec];
+    record[r] = record[1];
+    --r;
+    if (r == 1) {
+	goto L999;
+    }
+L3:
+    j = l;
+L4:
+    i = j;
+    j <<= 1;
+    if (j - r < 0) {
+	goto L5;
+    } else if (j == r) {
+	goto L6;
+    } else {
+	goto L8;
+    }
+L5:
+    if (criter[record[j]] < criter[record[j + 1]]) {
+	++j;
+    }
+L6:
+    if (crit >= criter[record[j]]) {
+	goto L8;
+    }
+    record[i] = record[j];
+    goto L4;
+L8:
+    record[i] = rec;
+    goto L2;
+L999:
+    record[1] = rec;
+    return 0;
+} /* gibbs2_ */
+
+/* Subroutine */ 
+int gibbsa_(integer* n,integer*  ptvois,integer*  vois,integer*  r,integer*  m,
+             integer*  nv,integer*  nx,integer*  ny,integer*  nn,integer*  w1,integer*  w2, 
+	integer* pfold,integer*  pfnew,integer*  impre,integer*  nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4;
+
+    /* Builtin functions */
+    /* Subroutine */ int s_stop();
+
+    /* Local variables */
+    static integer nbcc, degi, bold, bnew, i, j, k, p, degre, x, y, p1, p2;
+/*    extern  Subroutine  int gibbs1_();*/
+    static integer pf;
+/*    extern  Subroutine int gibbsb_(), gibbsd_(), gibbst_();*/
+    static integer nbpass, niveau, pf1, option, old, new_, opt, new1;
+
+/* -----------------------------------------------------------------------
+ */
+/*  but: calculer une renumerotation des sommets d'un graphe defini par: 
+*/
+/*     par la methode de gibbs */
+/* -----------------------------------------------------------------------
+ */
+/*  entree */
+/* -------- */
+/*     n = nb de sommet du graphe */
+/*      les voisins d'un sommet i ont pour numero : */
+/*     ( vois(j) , j=ptvois(i),ptvois(i+1)-1 ) */
+
+/*     impre   parametre d'impression */
+/*     nfout   numero du fichier pour impression */
+
+/*  sortie */
+/*  ------ */
+/*     r(1:n) tableau donnant la nouvelle numerotation: */
+/*       r(i) = nouveau numero du sommet i */
+/*     pfolf = ancien  profile */
+/*     pfnew = nouveau profile */
+
+/*  tableau de travail : */
+/*  -------------------- */
+/*     m(n) */
+/*     nv(0:n+n) */
+/*     nx(n) */
+/*     ny(n) */
+/*     nn(0:n) */
+/*     w1(n) */
+/*     w2(n) */
+
+/* -----------------------------------------------------------------------
+ */
+/*     programmeur f. hecht  le 3/02/1987 */
+/* -----------------------------------------------------------------------
+ */
+
+/*     tri des voisins d'un sommet du graphe par degre croissant */
+/* --------------------------------------------------------------- */
+    /* Parameter adjustments */
+    --w2;
+    --w1;
+    --ny;
+    --nx;
+    --m;
+    --r;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    p2 = ptvois[1] - 1;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	p1 = p2 + 1;
+	p2 = ptvois[i + 1] - 1;
+	i__2 = p2 - p1 + 1;
+	gibbs1_(&i__2, &vois[p1], &ptvois[1]);
+/*       if(impre.le.-9) then */
+/*        write (nfout,*) 'les voisin de ',i,'sont: ', (vois(j),j=p1,p
+2) */
+/*       endif */
+/* L10: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	r[i] = 0;
+/* L20: */
+    }
+/*     boucle sur les composante connexe du graphe */
+    new_ = 0;
+    nbcc = 0;
+L30:
+    if (new_ < *n) {
+	++nbcc;
+/*       recherche d'une racine y (un sommet non numerote) de degree m
+ini */
+	y = 0;
+	degre = *n + 1;
+	i__1 = *n;
+	for (i = 1; i <= i__1; ++i) {
+	    if (r[i] <= 0) {
+		degi = ptvois[i + 1] - ptvois[i];
+		if (degi < degre) {
+		    degre = degi;
+		    y = i;
+		}
+	    }
+/* L40: */
+	}
+	if (y == 0) {
+	   return -3;/*  s_stop("fatal erreur  gibbs 2 : pb racine", 33L); */
+	}
+	gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+	nbpass = 0;
+L50:
+	++nbpass;
+	x = y;
+	p = niveau;
+	k = 0;
+	i__1 = nv[p + 1];
+	for (i = nv[p] + 1; i <= i__1; ++i) {
+	    ++k;
+	    m[k] = nv[i];
+/* L60: */
+	}
+	gibbs1_(&k, &m[1], &ptvois[1]);
+	i__1 = k;
+	for (i = 1; i <= i__1; ++i) {
+	    y = m[i];
+	    gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+	    if (niveau > p) {
+		goto L50;
+	    }
+/* L70: */
+	}
+	y = m[1];
+/*        if(impre.lt.0) then */
+/*          write(nfout,*) */
+/*     +  '    nb de pass pour trouver le pseudo diametre',nbpass */
+/*     +         ,' x=',x,',y=',y,' de la composante connexe ',nbcc */
+
+/*          write (nfout,*) ('-',i=1,78) */
+/*        endif */
+/*       optimisation de la descendance de la numerotation */
+/*       ------------------------------------------------- */
+	gibbsb_(&x, &y, n, &ptvois[1], &vois[1], &nx[1], &ny[1], nv, nn, &m[1]
+		, &w1[1], &w2[1], &r[1], impre, nfout);
+
+/*     renumerotation de cuthill mac kee avec la meilleur des 4 option
+s */
+/*     --------------------------------------------------------------
+--- */
+	pf = 1073741824;
+	option = -2;
+	new1 = new_;
+	for (opt = -2; opt <= 2; ++opt) {
+	    new_ = new1;
+	    if (opt != 0) {
+		gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &
+			new_, &opt, &pf1, impre, nfout);
+		if (pf1 < pf) {
+		    pf = pf1;
+		    option = opt;
+		}
+	    }
+/* L80: */
+	}
+/*        if(impre.ne.0) write (nfout,*) '    on a choisi l''option ',
+ */
+/*     +             option,', new =',new */
+	new_ = new1;
+	gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &new_, &
+		option, &pf1, impre, nfout);
+	goto L30;
+    }
+/*      if(impre.ne.0) write(nfout,*) */
+/*     +       '   nb de composante connexe du graphe =',nbcc */
+/*     calcul du profile */
+    *pfold = 0;
+    *pfnew = 0;
+    bnew = 0;
+    bold = 0;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	old = i;
+	new_ = r[i];
+	i__2 = ptvois[i + 1] - 1;
+	for (j = ptvois[i]; j <= i__2; ++j) {
+/* Computing MIN */
+	    i__3 = old, i__4 = vois[j];
+	    old = mmin(i__3,i__4);
+/* Computing MIN */
+	    i__3 = new_, i__4 = r[vois[j]];
+	    new_ = mmin(i__3,i__4);
+/* L100: */
+	}
+	*pfold = *pfold + i - old + 1;
+/* Computing MAX */
+	i__2 = bold, i__3 = i - old + 1;
+	bold = mmax(i__2,i__3);
+	*pfnew = *pfnew + r[i] - new_ + 1;
+/* Computing MAX */
+	i__2 = bnew, i__3 = r[i] - new_ + 1;
+	bnew = mmax(i__2,i__3);
+/* L110: */
+    }
+/*      if(impre.ne.0) then */
+/*        write(nfout,*)'profile  old  = ',pfold,', profile  new = ',pfnew
+ */
+/*        write(nfout,*)'1/2 bande old = ',bold ,', 1/2 band new = ',bnew 
+*/
+/*      endif */
+return 0;
+} /* gibbsa_ */
+
+/* Subroutine */ int gibbsb_(integer* x,integer*  y,integer*  n,integer*  ptvois,
+integer*  vois,integer*  nx,integer*  ny,integer*  nv,integer*  nn,integer*  m,
+integer*  wh,integer*  wl,integer* r, integer* impre, integer* nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static  int flag_;
+    static integer i, j, k, p, s, h0, i1, l0, i2;
+/*    extern  Subroutine  int gibbs1_(); */
+    static integer lg;
+/*    extern  Subroutine  int gibbsd_(), gibbsc_();*/
+    static integer niveau, mxcanx, mxcany, nbc;
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+/* ...................................................................... 
+*/
+/*     attention on met la descente optimiser dans r <0 ou nulle */
+/* .......................................................................
+ */
+    /* Parameter adjustments */
+    --r;
+    --m;
+    --ny;
+    --nx;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    gibbsd_(y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+    gibbsc_(&ny[1], nv, &niveau, n, &mxcany);
+    gibbsd_(x, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+    p = niveau;
+    gibbsc_(&nx[1], nv, &niveau, n, &mxcanx);
+    flag_ = ffalse;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nx[i] + ny[i] == p) {
+	    r[i] = -nx[i];
+	} else if (nx[i] >= 0) {
+	    flag_ = ttrue;
+	    r[i] = -1073741824;
+	} else {
+	    if (r[i] <= 0) {
+		r[i] = -1073741822;
+	    }
+	}
+/* L20: */
+    }
+    if (flag_) {
+/*       calcul des composantes connexe du graphe sans les sommets de 
+nn */
+/*       ------------------------------------------------------------
+--- */
+	j = *n;
+	k = 0;
+	nbc = 0;
+	nv[nbc] = j;
+L30:
+	++k;
+	if (k <= *n) {
+	    if (r[k] == -1073741824) {
+/*           recherche de la fermeture transitive partant de k
+ */
+		++nbc;
+		i = -1;
+		s = k;
+L40:
+		++i;
+		wl[i] = ptvois[s];
+		wh[i] = ptvois[s + 1];
+		++j;
+		nv[j] = s;
+		r[s] = -1073741823;
+L50:
+		if (i >= 0) {
+		    if (wl[i] < wh[i]) {
+			s = vois[wl[i]];
+			++wl[i];
+			if (r[s] == -1073741824) {
+			    goto L40;
+			}
+			goto L50;
+		    }
+		    --i;
+		    goto L50;
+		}
+		nv[nbc] = j;
+		m[nbc] = nbc;
+	    }
+	    goto L30;
+	}
+/*        if(impre.lt.0) write(nfout,*) */
+/*     +         ' nb de composante connexe du graphe reduit =',nbc */
+
+/* --------------- fin de construction des composantes connexes------
+--- */
+/*        nv(0)=n */
+/*        if(impre.le.-10) write(nfout,5555)'nv(0:n+n) = ',(nv(i),i=0,
+n+n) */
+	gibbs1_(&nbc, &m[1], nv);
+/*        if(impre.le.-10)write(nfout,5555)'trie m =',(m(i),i=1,nbc) 
+*/
+	i__1 = p;
+	for (i = 0; i <= i__1; ++i) {
+	    nn[i] = 0;
+/* L60: */
+	}
+	i__1 = *n;
+	for (i = 1; i <= i__1; ++i) {
+	    j = -r[i];
+	    if (j >= 0 && j <= p) {
+		++nn[j];
+	    }
+/* L70: */
+	}
+
+/*       boucle sur les composante connexes par ordre croissantes */
+/*       -------------------------------------------------------- */
+	for (k = nbc; k >= 1; --k) {
+	    i = m[k];
+	    i1 = nv[i - 1] + 1;
+	    i2 = nv[i];
+	    lg = i2 - i1 + 1;
+/*         if(impre.le.-7) */
+/*     +       write(nfout,*) k,' composante ',i,',lg=',lg,',i1,i2
+=',i1,i2 */
+/*         if(impre.le.-8) */
+/*     +       write (nfout,5555)' ',(nv(i),i=i1,i2) */
+	    h0 = 0;
+	    l0 = 0;
+	    i__1 = p;
+	    for (j = 0; j <= i__1; ++j) {
+		wh[j] = nn[j];
+		wl[j] = nn[j];
+/* L90: */
+	    }
+	    i__1 = i2;
+	    for (i = i1; i <= i__1; ++i) {
+		s = nv[i];
+		++wh[nx[s]];
+		++wl[p - ny[s]];
+/* L100: */
+	    }
+	    i__1 = p;
+	    for (j = 0; j <= i__1; ++j) {
+		if (wh[j] != nn[j]) {
+/* Computing MAX */
+		    i__2 = wh[j];
+		    h0 = mmax(i__2,h0);
+		}
+		if (wl[j] != nn[j]) {
+/* Computing MAX */
+		    i__2 = wl[j];
+		    l0 = mmax(i__2,l0);
+		}
+/* L110: */
+	    }
+	    if (h0 < l0 || h0 == l0 && mxcanx <= mxcany) {
+/*           if(impre.le.-2) write(nfout,*) */
+/*     +       '         h0 = ',h0,',l0 = ',l0,'  ------- XXXX
+ --------' */
+		i__1 = i2;
+		for (i = i1; i <= i__1; ++i) {
+		    s = nv[i];
+		    r[s] = -nx[s];
+		    ++nn[-r[s]];
+/* L120: */
+		}
+	    } else {
+/*           if (impre.le.-2) write(nfout,*) */
+/*     +       '         h0 = ',h0,',l0 = ',l0,'  ------- YYYY
+ --------' */
+		i__1 = i2;
+		for (i = i1; i <= i__1; ++i) {
+		    s = nv[i];
+		    r[s] = -p + ny[s];
+		    ++nn[-r[s]];
+/* L130: */
+		}
+	    }
+/* L140: */
+	}
+    }
+/*     on met les nouveaux niveaux de la descendance optimiser dans nn */
+/*     ----------------------------------------------------------------- 
+*/
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (r[i] > 0) {
+	    nn[i] = -1;
+	} else if (r[i] == -1073741822) {
+	    nn[i] = -2;
+	} else {
+	    nn[i] = -r[i];
+	}
+/* L150: */
+    }
+/*      if(impre.le.-10)write (nfout,5555)' nn(i)=',(nn(i),i=1,n) */
+/* 5555  format('            --------   ',a,/,5(15x,10(i5)/)) */
+return 0;} /* gibbsb_ */
+
+/* Subroutine */ int gibbsc_(integer* nz,integer*  nv,integer*  niveau,integer*  n,integer*  mxz)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer i, j;
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+    /* Parameter adjustments */
+    --nz;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	nz[i] = -1;
+/* L10: */
+    }
+    *mxz = 0;
+    i__1 = *niveau;
+    for (i = 0; i <= i__1; ++i) {
+/* Computing MAX */
+	i__2 = *mxz, i__3 = nv[i + 1] - nv[i];
+	*mxz = mmax(i__2,i__3);
+	i__2 = nv[i + 1];
+	for (j = nv[i] + 1; j <= i__2; ++j) {
+	    nz[nv[j]] = i;
+/* L20: */
+	}
+    }
+return 0;} /* gibbsc_ */
+
+/* Subroutine */ int gibbsd_(integer* racine,integer*  n,integer*  ptvois,integer*  vois,integer*  nv,integer*  r,integer*  niveau)
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i, k, s, sv, stk, stk1, stk2;
+
+/* -----------------------------------------------------------------------
+ */
+/*     but construire la structure des descendant de racine  du graphe */
+/* -----------------------------------------------------------------------
+ */
+/*     sortie : */
+/*     -------- */
+/*     nv est la structure des niveaux */
+/*     les sommets du niveau (i =0,niveau_ sont defini par : */
+/*        (nv(j),j=nv(i),nv(i+1)-1) */
+
+/*     le tableau r(i) n'est modifier que sur les sommets */
+/*       de la composante connexe du graphe contenant la racine */
+
+/* -----------------------------------------------------------------------
+ */
+
+/*     on demark tout les sommets non remuneroter */
+/* -------------------------------------------------- */
+    /* Parameter adjustments */
+    --r;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (r[i] < 0) {
+	    r[i] = 0;
+	}
+/* L10: */
+    }
+
+/*    initialisation */
+
+    stk = *n - 1;
+    nv[0] = stk;
+    stk2 = stk;
+    *niveau = 0;
+    ++stk;
+    nv[stk] = *racine;
+    r[*racine] = -1;
+L20:
+    if (stk2 < stk) {
+	++(*niveau);
+	stk1 = stk2 + 1;
+	nv[*niveau] = stk;
+	stk2 = stk;
+/*        print *,' ------- niveau =',niveau,' stk=',stk1,stk2 */
+	i__1 = stk2;
+	for (k = stk1; k <= i__1; ++k) {
+	    s = nv[k];
+/*         print *,'----------------- s=',s */
+	    i__2 = ptvois[s + 1] - 1;
+	    for (i = ptvois[s]; i <= i__2; ++i) {
+/*               pour tout les sommets (sv) voisin */
+/*                d'un sommet (s) du niveau precedent */
+		sv = vois[i];
+/*          print *,' voisin =',sv */
+/*               si le sommet n'est pas marque on le marque et
+ on l'ajout */
+		if (r[sv] == 0) {
+		    ++stk;
+		    nv[stk] = sv;
+		    r[sv] = -1;
+		}
+/* L30: */
+	    }
+/* L40: */
+	}
+	goto L20;
+    }
+    --(*niveau);
+/*      call pnv(' gibbsd ',n,nv,niveau) */
+return 0;} /* gibbsd_ */
+
+
+/* Subroutine */ int gibbst_(integer* n,integer*  p,integer*  nv,integer*  nn,integer*  ptvois,integer*  vois,integer*  m,integer*  r,integer*  new_,integer*  option, 
+	integer* pfnew,integer*  impre,integer*  nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+
+    /* Local variables */
+    static integer nbsc, bnew, knew, step, plus, i, j, k, s, debut, i1, i2;
+/*    extern Subroutine int gibbs2_();*/
+    static integer fin;
+
+
+/*     construction de la stucture de niveau dans nv a partir de nn */
+/*     ------------------------------------------------------------ */
+    /* Parameter adjustments */
+    --r;
+    --m;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    nv[0] = *n;
+    i__1 = *p + 1;
+    for (i = 1; i <= i__1; ++i) {
+	nv[i] = 0;
+/* L150: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nn[i] >= 0) {
+	    ++nv[nn[i] + 1];
+	}
+/* L160: */
+    }
+    i__1 = *p;
+    for (i = 0; i <= i__1; ++i) {
+	nv[i + 1] += nv[i];
+/* L170: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nn[i] >= 0) {
+	    j = nn[i];
+	    ++nv[j];
+	    nv[nv[j]] = i;
+	}
+/* L180: */
+    }
+    for (i = *p; i >= 0; --i) {
+	nv[i + 1] = nv[i];
+/* L190: */
+    }
+    nv[0] = *n;
+    nbsc = nv[*p + 1] - nv[0];
+/*     --- fin de la construction ------------------------------------ */
+    if (*option == -2) {
+	i__1 = *impre - 1;
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	m[i] = *n * 3 + ptvois[i + 1] - ptvois[i];
+/* L10: */
+    }
+    if ((((int)*option) == 1)||(((int)*option) == -1)) {
+	debut = 0;
+	fin = *p;
+	step = 1;
+    } else {
+	debut = *p;
+	fin = 0;
+	step = -1;
+    }
+    i__1 = fin;
+    i__2 = step;
+    for (i = debut; i__2 < 0 ? i >= i__1 : i <= i__1; i += i__2) {
+	i1 = nv[i] + 1;
+	i2 = nv[i + 1];
+	i__3 = i2 - i1 + 1;
+	gibbs2_(&i__3, &nv[i1], &m[1]);
+	i__3 = i2;
+	for (j = i1; j <= i__3; ++j) {
+	    s = nv[j];
+	    i__4 = ptvois[s + 1] - 1;
+	    for (k = ptvois[s]; k <= i__4; ++k) {
+/* Computing MIN */
+		i__5 = m[vois[k]];
+		m[vois[k]] = mmin(i__5,j);
+/* L20: */
+	    }
+/* L30: */
+	}
+/* L40: */
+    }
+    if (*option > 0) {
+	knew = *new_;
+	plus = 1;
+    } else {
+	knew = *new_ + nbsc + 1;
+	plus = -1;
+    }
+    *new_ += nbsc;
+/*      if(option.gt.0) then */
+/*        do 60 k = debut , fin , step */
+/*          do 60 j = nv(k+1),nv(k)+1,-1 */
+/*            knew = knew + plus */
+/*            r(nv(j)) = knew */
+/* 60      continue */
+/*      else */
+    i__2 = fin;
+    i__1 = step;
+    for (k = debut; i__1 < 0 ? k >= i__2 : k <= i__2; k += i__1) {
+	i__3 = nv[k + 1];
+	for (j = nv[k] + 1; j <= i__3; ++j) {
+	    knew += plus;
+	    r[nv[j]] = knew;
+/* L70: */
+	}
+    }
+/*      endif */
+    *pfnew = 0;
+    bnew = 0;
+    i__3 = *n;
+    for (i = 1; i <= i__3; ++i) {
+	k = r[i];
+	if (k > 0) {
+	    i__1 = ptvois[i + 1] - 1;
+	    for (j = ptvois[i]; j <= i__1; ++j) {
+		if (r[vois[j]] > 0) {
+/* Computing MIN */
+		    i__2 = k, i__4 = r[vois[j]];
+		    k = mmin(i__2,i__4);
+		}
+/* L100: */
+	    }
+	    *pfnew = *pfnew + r[i] - k + 1;
+/* Computing MAX */
+	    i__1 = bnew, i__2 = r[i] - k + 1;
+	    bnew = mmax(i__1,i__2);
+	}
+/* L110: */
+    }
+/*      if(impre.lt.0.or.impre.gt.2) then */
+/*        write(nfout,*) '      option =',option,', profile =',pfnew */
+/*     +       ,', 1/2 bande =',bnew,', new=',new,', nbss composante=',nbsc
+ */
+/*      endif */
+return 0;} /* gibbst_ */
+
+/* function */ 
+int bamg::Triangles::gibbsv (integer* ptvoi, integer* vois,integer* lvois,integer* w,integer* v){
+  /* System generated locals */
+  integer  i__2;
+  
+  /* Local variables */
+  integer i, j, k, T, ss, iii, ptv, ptv1;
+  integer nbss = nbv; 
+  /*--- Prepare les donees pour gibbsa en construisant ptvoi, vois, lvois -
+    ------------*/
+  /*     in */
+  /*     ---   nbnt =3 pour des triangles 2D, */
+  /* 			nbt =  nb de triangle */
+  /*    		nbss = nb de sommets */
+  /*           nsea = numeros de 3 sommets de chaque triangle (me) */
+  /*     out */
+  /*     --- 	ptvoi, vois, lvois, err */
+  /*      tableaux de travail w, v */
+  /*-----------------------------------------------------------------------
+    ----------*/
+  /* Parameter adjustments */
+  --v;
+  --w;
+  --vois;
+  --ptvoi;
+  long nt = nbt-NbOutT;
+  /* Function Body */
+  for (i = 1; i <= nbss; ++i) {
+    w[i] = -1;
+    ptvoi[i] = 0; }
+  ptvoi[nbss + 1] = 0;
+  for (i = 0; i < nt; ++i) 
+    { 
+      assert(triangles[i].link);
+      for (j = 0; j < 3; ++j)
+	{
+	  ss = Number(triangles[i][j])+1;
+	  ++ptvoi[ss + 1];
+	  w[ss] = 0;
+	}
+    }
+  
+  for (i = 1; i <= nbss; ++i) 
+    ptvoi[i + 1] += ptvoi[i];
+  
+  for (i = 0; i < nt; ++i)
+    if (triangles[i].link) 
+      for (j = 0; j < 3; ++j) 
+	{
+	  ss = Number(triangles[i][j])+1;
+	  ++ptvoi[ss];
+	  v[ptvoi[ss]] = i;
+	}
+  
+    ptv1 = 0;
+    iii = 1;
+    for (i = 1; i <= nbss; ++i) {
+      ptv = ptv1 + 1;
+      ptv1 = ptvoi[i];
+      ptvoi[i] = iii;
+      i__2 = ptv1;
+      for (j = ptv; j <= i__2; ++j) {
+	T = v[j];
+	for (k = 0; k < 3; ++k) {
+	  ss = Number(triangles[T][k])+1;  /*  nsea[k + T * nsea_dim1]; */
+	  if (w[ss] != i) {
+	    w[ss] = i;
+	    if (iii > *lvois)  return 2 ;
+	    /* print*,'pas assez de place memoire' */
+	    
+	    vois[iii] = ss;
+	    ++iii;}
+	}
+      }
+    }
+    ptvoi[nbss + 1] = iii;
+    *lvois = iii - 1;
+    return 0; /* OK */
+    return 0;} /* gibbsv_ */
+
+int bamg::Triangles::gibbs(void)
+/* -------- 
+	renumber vertices by gibbs method; updates triangle and edge array
+	in:   mesh  
+	out:   mesh
+ 	auxiliary arrays: ptvois,vois,r,m,nv,nx,ny,nn,w1,w2,f 
+ 	all of size nv+1 except vois (10(nv+1)) and nv (2(nv+1))
+ 	err = -1 : memory alloc pb; err = -3: fatal erreur  gibbs 2 : pb racine
+*/
+{
+  long nv = nbv;
+  long nt = nbt-NbOutT;
+    long i, j, pfold, pfnew;
+    long* ptvois=NULL;
+    long* vois=NULL;
+    long* nn =NULL;
+    long* r =NULL;
+    long* m =NULL;
+    long* nnv =NULL;
+    long* nx =NULL;
+    long* ny =NULL;
+    long* w1 =NULL;
+    long* w2=NULL;
+    long nbvoisin =  10*nv;
+    long printint=0, iodev=6;
+    int err=0;
+    ptvois = new long[nv+1]; 		//(long*)calloc((long)(nv + 1) , sizeof(long));
+    nn = 	 new long[3*nt]; 			//(long*)calloc(3 * nt ,sizeof(long));
+    vois = 	 new long[nbvoisin+10];	//(long*)calloc((long)(nbvoisin + 10) , sizeof(long)); 
+    r = 	 new long[nv+1];				//(long*)calloc((long)(nv + 1) , sizeof(long));
+    if((!ptvois)||(!nn)||(!vois)||(!r)) return -1;
+    err = gibbsv(ptvois,vois,&nbvoisin,r,nn) ;
+    delete [] nn;					// free(nn);
+    if(err==0)
+      {
+	m = new long[nv+1];
+	nn = new long[nv+1];
+	nnv = new long[(nv+1)<<1];
+	nx = new long[nv+1];
+	ny = new long[nv+1];
+	w1 = new long[nv+1];
+	w2 = new long[nv+1];
+	long lnv = nv;
+	err = gibbsa_ (&lnv, ptvois, vois, r, m, nnv, nx, ny, nn, w1, w2, &pfold, &pfnew,
+		      &printint, &iodev);
+	delete [] m;
+	delete [] nnv;
+	delete [] nn;
+	delete [] nx;
+	delete [] ny;
+	delete [] w1;
+	delete [] w2;
+      }
+    
+    delete [] vois;
+  delete [] ptvois;
+  /*          
+	      if (err == 0 && (pfnew <= pfold))
+	      {
+	      A<bVertex> f(nv);
+	      for (i = 0; i < nv; ++i)
+	      {	f[i].x = v[i].x;
+	      f[i].y = v[i].y;
+	      f[i].where = v[i].where;
+	      }
+	      for (i = 0; i < nv; ++i)
+	      {	v[r[i] - 1].x = f[i].x;
+	 		v[r[i] - 1].y = f[i].y;
+	 		v[r[i] - 1].where = f[i].where;
+			}
+			
+       for (j = 0; j < nt; ++j)  // updates triangle array
+       for (i = 0; i < 3; i++)
+       t[j].v[i] = &v[r[no(t[j].v[i])] - 1];
+       
+       for (j = 0; j < ne; ++j)	// updates edge array
+       {
+	   		e[j].in = &v[r[no(e[j].in)] - 1];
+	   		e[j].out = &v[r[no(e[j].out)] - 1];
+			}
+			f.destroy();
+       if (!NumThinGrid) 
+       {  NumThinGrid= new int [nv];
+       for (i=0;i<nv;i++) NumThinGrid[i]=i;// Same numbering 
+       }
+       for (i=0;i<nv;i++) NumThinGrid[i]=r[NumThinGrid[i]]-1;  
+       
+       }
+  */
+  delete [] r;
+  return err;
+} 
+			
+/*  message d'erreur:         *err = 2;    print*,'pas assez de place memoire'   */
Index: /issm/trunk/src/c/Bamgx/Meshio.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/Meshio.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Meshio.cpp	(revision 2740)
@@ -0,0 +1,375 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "meshtype.h"
+#include "Meshio.h"
+namespace bamg {
+
+	long int verbosity=2;
+
+const char *OFortranUnFormattedFile::unkown("unkown file name");
+void (*MeshIstreamErrorHandler)(ios & ) =0;
+///////////////////////////////////////////////////////////
+ void WriteStr(ostream & out,char * str)
+{ 
+  int i=0;
+  char c;
+  out << '"' ;
+  while (i++,c=*str++) {
+   if (i==70) 
+      cout << " //\n",i=0;
+   if (c == '"') out << "\"\"" ;
+   else out << c ;}
+ out << '"' ;
+}
+///////////////////////////////////////////////////////////
+double * ReadbbFile(const char * file,long & nbsol,long & lsol,const int typesol,const int dim)
+{
+
+  MeshIstream frbb(file);
+  int dimlu,typesollu;
+  long i;
+ double *sol =0;
+  frbb >>    dimlu >> nbsol >> lsol >> typesollu ;
+  if(typesol != typesollu )
+    { 
+      cerr << " incorrect type of solution (read) " << typesollu << " != (wanted) " <<  typesol << endl;
+      cerr << "  or       dim  of solution (read) " << dimlu  << " != (wanted) " <<  dim << endl;
+      nbsol=0;
+      lsol=0;
+    }
+  else
+    {
+      sol = new double[lsol*nbsol];
+      double *s=sol;
+      for(  i=0;i<lsol;i++)
+	for (long j=0;j<nbsol;j++)
+	  frbb >>  *s++ ;
+      //      frbb.close();
+    }
+
+  
+  return sol;
+}
+
+///////////////////////////////////////////////////////////
+double * ReadBBFile(const char * file,long & nbsol,long & lsol,int *& typesols,
+  const int dim,const int typesol)
+{
+
+  MeshIstream frbb(file);
+  int dimlu,typesollu;
+  typesols = 0;
+  long i,n=0;
+  double *sol =0;
+  int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ;
+  // char * charoftype[] = {  "Scalar" , "dim Vector" ,"dim x dim Sym-Matric","dim x dim Full-Matric" } ;
+  frbb >>    dimlu >> nbsol ;
+  typesols = new int [nbsol] ;
+  for (i=0;i<nbsol;i++)
+    {
+     frbb >> typesols[i];
+     typesols[i]--;
+     if (typesols[i]<0 || typesols[i]>= 4)
+       {
+	 cerr << " Error reading BBFile the type solution " << i+1 << " is " << typesols[i]+1 
+	      << " is not in [1..4] " << endl;
+	   frbb.ShowIoErr(998);
+	 nbsol=0;
+	 lsol=0;
+	 delete [] typesols;
+	 typesols=0;
+	 return 0; 
+       }
+     n += sizeoftype[ typesols[i]];
+    }
+  frbb >> lsol >> typesollu ;
+  if(typesol != typesollu )
+    { 
+      cerr << " incorrect type of solution (read) " << typesollu << " != (wanted) " <<  typesol << endl;
+      cerr << "  or       dim  of solution (read) " << dimlu  << " != (wanted) " <<  dim << endl;
+      frbb.ShowIoErr(999);
+      nbsol=0;
+      lsol=0;
+    }
+  else
+    {
+      if (verbosity> 5)
+	cout << "     read BB file " << file << "  with nbsol " << nbsol << " total nb of field = " << n << endl; 
+      if (verbosity>9) 
+	for (i=0;i<nbsol;i++)
+	  cout << "      the type of solution " << i+1 << " is " <<  sizeoftype[ typesols[i]]  
+	       << " and  the number of sub-field are " << sizeoftype[ typesols[i]] << endl; 
+      sol = new double[lsol*n];
+      double *s=sol;
+      for(  i=0;i<lsol;i++)
+	for (long j=0;j<n;j++)
+	  frbb >>  *s++ ;
+      //      frbb.close();
+    }
+
+  
+  return sol;
+}
+
+
+void MeshIstream::ShowIoErr(int s) {
+  LineError = 1;
+  if (CurrentFile)
+    cerr << " In  file " <<  CurrentFile ;
+  cerr << ", Erreur Lecture "  << s << 
+    ", good="  << (s & ios::goodbit) <<
+    ", bad=" << (s & ios::badbit) <<
+    ", fail=" << (s & ios::failbit) <<
+    ", eof=" << (s & ios::eofbit) << " Line " << LineNumber <<
+    endl;
+  if(!in.eof()) 
+    {
+      in.clear(ios::goodbit);
+      int i=0;
+      char c;
+      cerr << " the next character :" ;
+      while (i++<80 && in.get(c) && (c != '\n' || i < 30 ))
+	cerr.put(c);
+      cerr << endl; 
+    }
+  if (MeshIstreamErrorHandler)
+    MeshIstreamErrorHandler(in);
+  else 
+   { 
+    in.clear(ios::failbit);
+   }
+}
+int  MeshIstream::IsString(const char* s)
+{ 
+  int n=0;
+  char c;
+  const char * ss = s;
+  while (in.get(c) && c ==' ') n++; // eat whitespace 
+  if (in.good())
+    while ( *ss && c == *ss && in.get(c) )
+      ss++; 
+
+  if (*ss) { // no 
+    if (verbosity>9) 
+      cout << "IsString: not " << s << " " << n  << "  putback " << ss-s << " :" << c  ;
+    if (in.good())
+      in.putback(c),ss--;
+    while(ss-s>0)
+      {
+	cout << *ss ;
+	in.putback(*ss--);
+      };
+    if (verbosity>9) 
+      cout << ":"<< endl;
+    return 0;}
+  else return 1;
+}
+
+ char * MeshIstream::ReadStr()
+{ 
+  static char buf[1025];
+  int  instr=0,k=0;
+  char * b=buf, bb=0, *bend=buf+1023;
+  
+  for (b=buf;b<bend &&  in.get(*b);instr && b++)
+    {
+      int kold = k;
+      if(isspace(*b))
+	{
+	  if (*b == '\n') LineNumber++;
+	  if (instr && !bb) break;
+	}
+      else if (*b == bb) 
+	{
+	  if(++k%2) b--;
+	}
+      else if( !instr) 
+	{
+	  instr =1;
+	  if  ((*b == '"') ||  (*b == '\'' ) )
+	    bb=*b--,k=0;
+	}
+      else
+	instr =1;
+      
+      if( k%2 && kold==k ) // even and fin
+	break;
+    }
+  *b=0;
+  in.clear(ios::goodbit);
+  //  cout << " l = " << b-buf << " " ;
+  char * r = new char [b-buf+1];
+  strcpy(r,buf);
+  return r ;  
+}
+///////////////////////////////////////////////////////////
+OFortranUnFormattedFile::~OFortranUnFormattedFile()
+{
+  // save the last record 
+  if (l==0) { // l rec no set --
+    l=where();
+  if (verbosity>9)
+    cout << " size of last record  = " 
+	 << l << " n = " << nb_rec << " i= " << i << endl;
+   if (!f->good()) Error(3);
+    f->seekp(i-sizeof(long));
+   if (!f->good()) Error(3);
+    f->write((char*)&l,sizeof(l)); 
+    if (!f->good()) Error(3);
+   n=j;
+  }
+
+  f->seekp(n);
+  if (!f->good()) Error(3);
+   f->write((char*) &l,sizeof(l));
+  if (!f->good()) Error(3);
+   
+  if (f && to_close) {
+    if (verbosity>9)
+      cout << "delete OFortranUnFormattedFile " << file_name 
+	   << " @end  = " << n <<  endl;
+    delete f;} f=0;
+}
+
+IFortranUnFormattedFile::~IFortranUnFormattedFile()
+{
+  if (f && to_close) {
+    if (verbosity>9)
+      cout << " delete IFortranUnFormattedFile" << file_name 
+	   << "  @end = " << n <<  endl;
+    delete f;} f=0;
+}
+
+long IFortranUnFormattedFile::Record()
+{
+  nb_rec++;
+  n += sizeof(long);
+  f->seekg(n);
+  f->read((char*)&l,sizeof(l));
+  if (!f->good()) Error(3);
+  i=j= n+sizeof(l); 
+  n +=   l + sizeof(l) ; // end 
+  if (verbosity>9)
+  cout << " Read  rec end =" << n << " l=  " << l 
+       << " current= " << j << " begin= " << i << endl;
+  return l;
+}
+
+long OFortranUnFormattedFile::Record(long ll) //
+{
+  if (j==4 && l==0) 
+    { 
+      l=ll;
+      f->seekp(0);
+      f->write((char*)&ll,sizeof(l));
+      if (!f->good()) Error(3);
+      return 0;
+    }
+  if (n>=0) 
+    {
+      if (l==0) 
+	{ // l rec no set --
+	  l=where();
+	  if (verbosity>9)
+	    cout << " set len  of rec  " << nb_rec  << " = " << l 
+		 << " @ " << i-sizeof(long) << endl;
+
+	  f->seekp(i-sizeof(long));
+	  f->write((char*)&l,sizeof(l)); 
+	  n=j;
+	}
+      f->seekp(n);
+      f->write((char*)&l,sizeof(l)); 
+      if (!f->good()) Error(3);
+    }
+  else 
+    f->seekp(0);
+  n += sizeof(long);
+  nb_rec++;
+  f->write((char*)&ll,sizeof(l));
+  if (!f->good()) Error(3);
+  
+  l=ll;
+  n +=  sizeof(long);
+  j = n;
+  i = n;
+  n +=   l;
+  if (verbosity>9)
+    cout << " Write rec end =" << n << " l=  " << l 
+	 << " current= " << j << " begin= " << i << endl;
+  return l;
+}
+void OFortranUnFormattedFile::Error(int err)
+{
+  cerr << "Fatal Error Output FortranUnFormattedFile " << endl;
+  if (err==0) 
+    cerr << "-- Error openning ";
+  else if (err==1)
+    cerr<< "-- OverFlow write ";
+  else if (err==2)
+    cerr<< "-- Erreur  write " ;
+  else if (err==3)
+    cerr<< "-- Erreur  write record info " ;
+  else 
+    cerr << " unkown err " << err ;
+
+  cerr << " Record number = "    << nb_rec << endl
+       << " read position  in file " << j << " < " << n 
+       << " =  end on record " << endl;
+  cerr << " position in the record = " << where() 
+       << " length of record = " << l <<endl;
+  cerr 	<< " file = " << file_name<< endl ;
+  MeshError(900);
+  //  throw(ErrorMesh("exit",1));
+}
+void IFortranUnFormattedFile::Error(int err)
+{
+  cerr << "Fatal Error Input FortranUnFormattedFile " << endl;
+  if (err==0) 
+    cerr << " Error openning ";
+  else if (err==1)
+    cerr<< " OverFlow read";
+  else if (err==2)
+    cerr<< " Erreur  read" ;
+  else if (err==3)
+    cerr<< " Erreur  read record info " ;
+  else 
+    cerr << " unkown err " << err ;
+
+  cerr << " Record number = "    << nb_rec << endl
+       << " read position  in file " << j << " < " << n 
+       << " =  end on record " << endl;
+  cerr << " position in the record = " << where() 
+       << " length of record = " << l <<endl;
+  cerr 	<< " file = " << file_name<< endl ;
+    MeshError(900);
+    //  throw(ErrorMesh("exit",1));
+}
+
+}// end of namespace bamg 
Index: /issm/trunk/src/c/Bamgx/Meshio.h
===================================================================
--- /issm/trunk/src/c/Bamgx/Meshio.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Meshio.h	(revision 2740)
@@ -0,0 +1,244 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cstdio>
+#include <iostream>
+#include <fstream>
+#include "error.hpp"
+#include <cstring>
+#include <cstdlib>
+#include <cctype>
+using namespace std;
+//  PB compilo HP aCC 
+#if defined(__hpux) || defined(__SUNPRO_CC) 
+#define IOS_OPENMODE int
+#else
+#define IOS_OPENMODE ios::openmode
+#endif
+
+namespace bamg {
+
+
+extern  void (*MeshIstreamErrorHandler)(ios & );
+
+void WriteStr(ostream & out,char * str);
+
+double * ReadbbFile(const char * file,long & nbsol,long & lsol,const int dim=2,const int typesol=2);
+double * ReadBBFile(const char * file,long & nbsol,long & lsol,int *& typesols,const int dim=2,const int typesol=2);
+// solution at vertex (P1)
+
+union Char4orLong {  char c[4];    long l;} ;
+
+class  MeshIstream {
+public:
+  istream  & in ;
+  const char * CurrentFile;
+  //  ifstream  fin;
+  int LineNumber,LineError,opened;
+
+
+  istream & cm ()//  mange les blancs et les commentaire 
+  { 
+    char c;
+    int cmm=0;
+    while ( in.get(c) &&  
+	    ( isspace(c) ?
+	      (( ( c=='\n'|| c==char(12) || c==char(15)) && (LineNumber++,cmm=0)),1) 
+	      : (cmm || (c=='#' && (cmm=1) )) ) 
+	    ) ((void ) 0);
+	   if (in.good()) in.putback(c);
+    return in;
+  }
+
+  // void rewind(){ fin.clear();fin.seekg(0);}
+    
+  void eol()// go to end of line
+  { 
+    char c;
+    while ( in.get(c) &&  ( c!='\n') && ( c!='\r')) (void) 0;
+  }
+  void ShowIoErr(int );
+  MeshIstream  & err () 
+  { 
+    if ( ! in.good() ) ShowIoErr(in.rdstate());
+    return *this;
+  }
+  //  MeshIstream(istream & i): in(i),CurrentFile(0),LineNumber(1),LineError(0) {}
+
+  MeshIstream(const char * file_name)
+    : in(*new ifstream(file_name)),CurrentFile(file_name), LineNumber(1),LineError(0) 
+  {    if (!in) {cerr << " Error Opening file " << file_name,CurrentFile=0;ShowIoErr(1);}
+  err();  }
+
+  /*  //  void close()
+  {
+      if (CurrentFile) {
+        if(verbosity>5) cout << "    Closefile: " <<  CurrentFile << endl;
+	CurrentFile=0;in.close();}
+  } */
+  int eof(){return in.eof();}
+  ~MeshIstream(){delete &in;}
+  int IsString(const char* s);
+  char * ReadStr();
+  MeshIstream&   operator>>(short& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(long& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(int& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(float& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(double& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(char * & i ) { i=ReadStr();return err();}
+
+};
+// Fortran unformatted file  interface ----------
+
+class IFortranUnFormattedFile {
+//  template<class T> friend IFortranUnFormattedFile & operator>>(IFortranUnFormattedFile &f,T & l);
+  istream * f;
+  long i,l,n,j,nb_rec;
+  const char * file_name;
+  int to_close;
+ public:
+  IFortranUnFormattedFile(char *name)
+    : f(new ifstream(name)),i(0),l(0),n((long)-sizeof(long)),
+      nb_rec(0),file_name(name), to_close(1)
+    { if(!*f) Error(0);}
+
+  IFortranUnFormattedFile(MeshIstream & ff)
+    : f(&ff.in),i(0),l(0),n((long)-sizeof(long)),nb_rec(0),
+      file_name(ff.CurrentFile), to_close(0)
+    { if(! *f)  Error(0);}
+  
+ ~IFortranUnFormattedFile();
+  long Record();
+  long where(){return j-i;}
+  void  read4(char *c,int );// for the fortran 77 char4
+  void  read(char * p,const size_t lg);
+  void Error(int);
+};
+
+class OFortranUnFormattedFile {
+//  template<class T> friend OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const T & l);
+  ostream * f;
+  long i,l,n,j,nb_rec;
+  const static char * unkown;
+  const char * file_name;
+  int to_close;
+ public:
+  
+  OFortranUnFormattedFile(const char *name,IOS_OPENMODE  mm=ios::trunc)
+    : f(new ofstream(name,mm)),i(0),l(0),n((long) -sizeof(long)),nb_rec(0),file_name(name), to_close(1)
+    { if(!*f) Error(0);}
+  OFortranUnFormattedFile(ostream &ff)
+    : f(&ff),i(0),l(0),n((long) -sizeof(long)),nb_rec(0),file_name(unkown), to_close(0)
+    { if(!*f) Error(0);}
+  
+  ~OFortranUnFormattedFile();
+
+  long Record(long ll=0);
+  long where(){return j-i;} 
+  void write4(const char *c,int );// for the fortran 77 char4
+  void write(const char * p,const size_t lg);
+  void Error(int );
+};
+
+/// ---------- inline -------------------------
+
+inline void  IFortranUnFormattedFile::read(char * p,const size_t lg){  
+  f->read(p,lg);
+  j+=lg;
+  if (j>n) Error(1);
+  else if (!f->good()) Error(2) ;
+}
+
+inline void  OFortranUnFormattedFile::write(const char * p,const size_t lg){  
+   f->write(p,lg);
+   j+=lg;
+   if (l && j>n)  Error(1);
+   else if (!f->good()) Error(2);
+}
+
+template<class T> inline
+IFortranUnFormattedFile & operator>>(IFortranUnFormattedFile &f,T & l)
+{  
+  f.read((char *) &l,sizeof(l));return f;
+}
+/*  bug sur sun  
+template inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const T & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+on ex les template  */ 
+
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const int  & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const long  & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const double  & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const float & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+
+inline void OFortranUnFormattedFile::write4(const char *c,int ll)
+{
+  int i,j;
+  Char4orLong ch4;
+  for ( i=0;i<ll;i++)
+    {
+      ch4.l=0;
+      for (j=0;j<4;j++)
+	ch4.c[j]=*c? *c++:' ';
+      *this << ch4.l;
+    }
+}
+inline void IFortranUnFormattedFile::read4(char *c,int ll)
+{
+  int i,j;
+  Char4orLong ch4;
+
+  for ( i=0;i<ll;i++)
+    {
+      *this >> ch4.l;
+      for (j=0;j<4;j++)
+	*c++= ch4.c[j];
+    }
+  *c=0;// end of string 
+}
+
+}
Index: /issm/trunk/src/c/Bamgx/Metric.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/Metric.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Metric.cpp	(revision 2740)
@@ -0,0 +1,1226 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include "Meshio.h"
+#include "Mesh2.h"
+
+namespace bamg {
+
+
+inline Real8 det3x3(Real8 A[3] ,Real8 B[3],Real8 C[3])
+{ return    A[0] * ( B[1]*C[2]-B[2]*C[1])
+          - A[1] * ( B[0]*C[2]-B[2]*C[0])
+          + A[2] * ( B[0]*C[1]-B[1]*C[0]);
+}
+
+SaveMetricInterpole  LastMetricInterpole;
+
+void ReductionSimultanee( MetricAnIso M1,  MetricAnIso M2,double & l1,double & l2, D2xD2 & V) 
+{
+  double a11=M1.a11,a21=M1.a21,a22=M1.a22;
+  double b11=M2.a11,b21=M2.a21,b22=M2.a22;
+  //  M1 v = l M2 v
+  // (M1 - l M2) v =0
+  // det (M1 - l M2) =0
+  // det (M1 - l M2) = a l^2 + b l + c;
+  // = (a11 - l * b11) * (a22 - l * b22) - (a21 - l * b21 ) ^2
+  //  const double eps = 1.e-5;
+  const double /*c11 = a11*a11,*/ c21= a21*a21;
+  const double /*d11 = b11*b11,*/ d21= b21*b21;
+  const double a=b11*b22 - d21;
+  const double b=-a11*b22-a22*b11+2*a21*b21;
+  const double c=-c21+a11*a22;
+  const double bb = b*b,ac= a*c;
+  const double delta = bb - 4 * ac;
+  //  const double kk=c11+c22+c21+d11+d21+d22;
+  // modif F Hecht feb 1998 
+  // cerr.precision(14);
+  //cerr  <<  bb << " " << ac << " " <<  bb <<  " " <<a << endl;
+  // cerr << a11 << " " << a21 << " " << a22 << endl;
+  //cerr << b11 << " " << b21 << " " << b22 << endl;
+  if (bb + Abs(ac) < 1.0e-20 || (delta< 1.0E-4 * bb ) )
+   {
+   // racine double;
+     // cerr << "double " << endl ;
+    if (Abs(a) < 1.e-30 )
+     l1 = l2 = 0;
+    else 
+     l1=l2=-b/(2*a); 
+    V= D2xD2(1,0,0,1);
+   }
+  else {
+    // cerr << "  -- " << a << endl ;
+    const double delta2 = sqrt(delta);
+    l1= (-b - delta2)/(2*a);
+    l2= (-b + delta2)/(2*a);
+    // M1 v = l M2 v
+    //  ( (M1 - I M2) x,y)  = (x,(M1 - I M2) y) \forall y
+    // so Ker((M1 - I M2)) = Im((M1 - I M2))^\perp
+      double v0 = a11-l1*b11, v1 = a21-l1*b21,v2 = a22 - l1*b22;
+      double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
+      double vp1x,vp1y,vp2x,vp2y;
+
+      if(s1 < s0)
+	s0=sqrt(s0),vp1x=v1/s0,vp1y=-v0/s0;
+      else
+	s1=sqrt(s1),vp1x=v2/s1,vp1y=-v1/s1;
+
+      v0 = a11-l2*b11, v1 = a21-l2*b21,v2 = a22 - l2*b22;
+      s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
+      if(s1 < s0)
+	s0=sqrt(s0),vp2x=v1/s0,vp2y=-v0/s0;
+      else
+	s1=sqrt(s1),vp2x=v2/s1,vp2y=-v1/s1;
+#ifdef DEBUG
+      assert(Abs(vp1y)+Abs(vp2y)>0);
+#endif
+      V=D2xD2(vp1x,vp2x,vp1y,vp2y);
+  }
+  return;
+
+}
+
+MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) ;
+MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) 
+{
+      D2xD2 M;
+      double l1,l2;
+      ReductionSimultanee(M1,M2,l1,l2,M);
+      R2 v0(M.x.x,M.y.x);
+      R2 v1(M.x.y,M.y.y);
+      D2xD2 M_1(M.inv());
+      D2xD2 D(Max(M1(v0,v0),M2(v0,v0)),0,0,Max(M1(v1,v1),M2(v1,v1)));
+      D2xD2 Mi(M_1.t()*D*M_1);
+      return MetricAnIso(Mi.x.x,0.5*(Mi.x.y+Mi.y.x),Mi.y.y);
+}
+
+MetricAnIso::MetricAnIso(const Real8  a[3],const  MetricAnIso m0,
+	   const  MetricAnIso m1,const  MetricAnIso m2 )
+{
+  MetricAnIso mab(a[0]*m0.a11 + a[1]*m1.a11 + a[2]*m2.a11,
+		  a[0]*m0.a21 + a[1]*m1.a21 + a[2]*m2.a21,
+		  a[0]*m0.a22 + a[1]*m1.a22 + a[2]*m2.a22);
+  
+  MatVVP2x2 vab(mab);
+ 
+  R2 v1(vab.v.x,vab.v.y);
+  R2 v2(-v1.y,v1.x);
+  
+  Real8 h1 = a[0] / m0(v1) + a[1] / m1(v1) + a[2] / m2(v1);
+  Real8 h2 = a[0] / m0(v2) + a[1] / m1(v2) + a[2] / m2(v2);
+
+  vab.lambda1 =  1 / (h1*h1);
+  vab.lambda2 =  1 / (h2*h2);
+  *this = vab;
+}
+
+ MetricAnIso::MetricAnIso( Real8  a,const  MetricAnIso ma,
+	                   Real8  b,const  MetricAnIso mb)
+{ 
+  MetricAnIso mab(a*ma.a11+b*mb.a11,a*ma.a21+b*mb.a21,a*ma.a22+b*mb.a22);
+  MatVVP2x2 vab(mab);
+  
+  R2 v1(vab.v.x,vab.v.y);
+  R2 v2(-v1.y,v1.x);
+  
+
+  Real8 h1 = a / ma(v1) + b / mb(v1);
+  Real8 h2 = a / ma(v2) + b / mb(v2);
+  vab.lambda1 =  1 / (h1*h1);
+  vab.lambda2 =  1 / (h2*h2);
+  *this = vab;
+}
+
+
+
+ MatVVP2x2::MatVVP2x2(const MetricAnIso M) 
+{
+  double a11=M.a11,a21=M.a21,a22=M.a22;
+  const double eps = 1.e-5;
+  double c11 = a11*a11, c22 = a22*a22, c21= a21*a21;
+  double b=-a11-a22,c=-c21+a11*a22;
+  double   delta = b*b - 4 * c ;
+  double n2=(c11+c22+c21);
+  if ( n2 < 1e-30) 
+     lambda1=lambda2=0,v.x=1,v.y=0;
+  else if (delta < eps*n2)
+    { 
+      lambda1=lambda2=-b/2, v.x=1,v.y=0;
+    }
+  else 
+    {  //    ---  construction  de 2 vecteur dans (Im ( A - D(i) Id) ortogonal 
+      delta = sqrt(delta);
+      lambda1 = (-b-delta)/2.0,lambda2 = (-b+delta)/2.0;
+      double v0 = a11-lambda1, v1 = a21,v2 = a22 - lambda1;
+      double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
+ 
+      if(s1 < s0)
+	s0=sqrt(s0),v.x=v1/s0,v.y=-v0/s0;
+      else
+	s1=sqrt(s1),v.x=v2/s1,v.y=-v1/s1;
+    };
+}
+
+
+ int MetricAnIso::IntersectWith(const MetricAnIso M2) 
+{
+  //cerr << " - " << *this << M2 <<  endl;
+      int r=0;
+      MetricAnIso & M1 = *this;
+      D2xD2 M;
+      double l1,l2;
+      
+      ReductionSimultanee(*this,M2,l1,l2,M);
+      // cerr << M << endl;
+      R2 v1(M.x.x,M.y.x);
+      R2 v2(M.x.y,M.y.y);
+      double l11=M1(v1,v1);
+      double l12=M1(v2,v2);
+      double l21=M2(v1,v1);
+      double l22=M2(v2,v2);
+      if ( l11 < l21 )  r=1,l11=l21;
+      if ( l12 < l22 )  r=1,l12=l22; 
+      // cerr << r << endl;
+      if (r) { // change
+        D2xD2 M_1(M.inv());
+        D2xD2 D(l11,0,0,l12); 
+        D2xD2 Mi(M_1.t()*D*M_1);
+        a11=Mi.x.x;
+        a21=0.5*(Mi.x.y+Mi.y.x);
+        a22=Mi.y.y; }
+      return r;
+}
+void Triangles::IntersectGeomMetric(const Real8 err=1,const int iso=0)
+
+{
+	long int verbosity=0;
+
+  if(verbosity>1)
+    cout << "  -- IntersectGeomMetric geometric err=" << err << (iso ? " iso " : " aniso "  ) << endl;
+  Real8 ss[2]={0.00001,0.99999};
+  Real8 errC = 2*sqrt(2*err);
+  Real8 hmax = Gh.MaximalHmax();
+  Real8 hmin = Gh.MinimalHmin();
+  Real8 maxaniso = 1e6;
+  assert(hmax>0);
+  SetVertexFieldOn();
+  if (errC > 1) errC = 1;
+  for (Int4  i=0;i<nbe;i++)
+   for (int j=0;j<2;j++)
+    {
+      
+      Vertex V;
+      VertexOnGeom GV;
+      // cerr << Number(edges[i]) << " " << ss[j] << endl;
+      Gh.ProjectOnCurve(edges[i],ss[j],V,GV);
+	{
+	  GeometricalEdge * eg = GV;
+	  Real8 s = GV;
+	  R2 tg;
+	  //	   cerr << i << " " << j << " " << Number(V) << " on = " 
+	  //	<< Gh.Number(eg) << " at s = " << s << " " << endl;
+	  Real8  R1= eg->R1tg(s,tg);
+	  // cerr << " R = " << 1/Max(R1,1e-20) << tg << " on x " 
+	  //    << V.r << errC/ Max(R1,1e-20) <<  " hold=" <<V.m(tg) << " "  << endl;
+	  Real8 ht = hmax;
+          if (R1>1.0e-20) 
+	    {  // err relative to the length of the edge
+	      ht = Min(Max(errC/R1,hmin),hmax);
+	    }
+	  Real8 hn = iso? ht : Min(hmax,ht*maxaniso);
+	  //cerr << ht << " " << hn << "m=" << edges[i][j].m <<  endl;
+	  assert(ht>0 && hn>0);
+	  MatVVP2x2 Vp(1/(ht*ht),1/(hn*hn),tg);
+	  //cerr << " : " ;
+	  Metric MVp(Vp);
+	  // cerr << " : "  << MVp  << endl;
+	  edges[i][j].m.IntersectWith(MVp);
+	  //cerr << " . " << endl;
+	}
+
+    }
+  // the problem is for the vertex on vertex 
+     
+}
+/*
+void  Triangles::BoundAnisotropy(Real8 anisomax)
+{
+  if (verbosity > 1) 
+    cout << "  -- BoundAnisotropy by  " << anisomax << endl; 
+  Real8 h1=1.e30,h2=1e-30,rx=0;
+  Real8 coef = 1./(anisomax*anisomax);
+  Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+  for (Int4 i=0;i<nbv;i++)
+    {
+
+      MatVVP2x2 Vp(vertices[i]);
+      
+      h1=Min(h1,Vp.lmin());
+      h2=Max(h2,Vp.lmax());
+      rx = Max(rx,Vp.Aniso2());
+      
+      Vp.BoundAniso2(coef);
+      
+      hn1=Min(hn1,Vp.lmin());
+      hn2=Max(hn2,Vp.lmax());
+      rnx = Max(rnx,Vp.Aniso2());
+
+      
+      vertices[i].m = Vp;
+
+    }
+
+  if (verbosity>2)
+    {
+      cout << "     input :  Hmin = " << sqrt(1/h2)  << " Hmax = " << sqrt(1/h1) 
+	   << " factor of anisotropy max  = " << sqrt(rx) << endl;
+      cout << "     output:  Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) 
+	   << " factor of anisotropy max  = " << sqrt(rnx) << endl;
+    }
+}
+*/
+void  Triangles::BoundAnisotropy(Real8 anisomax,Real8 hminaniso)
+{
+	long int verbosity=0;
+
+  double lminaniso = 1/ (Max(hminaniso*hminaniso,1e-100));
+  if (verbosity > 1) 
+    cout << "  -- BoundAnisotropy by  " << anisomax << endl; 
+  Real8 h1=1.e30,h2=1e-30,rx=0;
+  Real8 coef = 1./(anisomax*anisomax);
+  Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+  for (Int4 i=0;i<nbv;i++)
+    {
+
+      MatVVP2x2 Vp(vertices[i]);
+      double lmax=Vp.lmax();
+      h1=Min(h1,Vp.lmin());
+      h2=Max(h2,Vp.lmax());
+      rx = Max(rx,Vp.Aniso2());
+
+      Vp *= Min(lminaniso,lmax)/lmax;
+      
+      Vp.BoundAniso2(coef);
+      
+      hn1=Min(hn1,Vp.lmin());
+      hn2=Max(hn2,Vp.lmax());
+      rnx = Max(rnx,Vp.Aniso2());
+
+      
+      vertices[i].m = Vp;
+
+    }
+
+  if (verbosity>2)
+    {
+      cout << "     input :  Hmin = " << sqrt(1/h2)  << " Hmax = " << sqrt(1/h1) 
+	   << " factor of anisotropy max  = " << sqrt(rx) << endl;
+      cout << "     output:  Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) 
+	   << " factor of anisotropy max  = " << sqrt(rnx) << endl;
+    }
+}
+void Triangles::IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols,
+				    const  Real8 hmin1,const Real8 hmax1,const Real8 coef,
+				    const Real8 anisomax ,const Real8 CutOff,const int NbJacobi,
+				    const int DoNormalisation,const double power,const int choice)
+{ //  the array of solution s is store    
+  // sol0,sol1,...,soln    on vertex 0
+  //  sol0,sol1,...,soln   on vertex 1
+  //  etc.
+  //  choise = 0 =>  H is computed with green formule
+  //   otherwise  => H is computed from P2 on 4T 
+  const int dim = 2;
+  
+  long int verbosity=0;
+
+  int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ; 
+
+  // computation of the nb of field 
+  Int4 ntmp = 0;
+  if (typsols)
+    {
+      for (Int4 i=0;i<nbsol;i++)
+	     ntmp += sizeoftype[typsols[i]];
+    }
+  else
+    ntmp = nbsol;
+
+  // n is the total number of fields
+
+  const Int4 n = ntmp;
+
+  Int4 i,k,iA,iB,iC,iv;
+  R2 O(0,0);
+  int RelativeMetric = CutOff>1e-30;
+  Real8 hmin = Max(hmin1,MinimalHmin());
+  Real8 hmax = Min(hmax1,MaximalHmax());
+  Real8 coef2 = 1/(coef*coef);
+
+  if(verbosity>1) 
+    {
+      cout << "  -- Construction of Metric: Nb of field. " << n << " nbt = " 
+	   << nbt << " nbv= " << nbv 
+	   << " coef = " << coef << endl
+	   << "     hmin = " << hmin << " hmax=" << hmax 
+	   << " anisomax = " << anisomax <<  " Nb Jacobi " << NbJacobi << " Power = " << power ;
+      if (RelativeMetric)
+	cout << " RelativeErr with CutOff= "  <<  CutOff << endl;
+      else
+	cout << " Absolute Err" <<endl;
+    }
+  double *ss=(double*)s;//, *ssiii = ss;
+
+  double sA,sB,sC;
+
+  Real8 *detT = new Real8[nbt];
+  Real8 *Mmass= new Real8[nbv];
+  Real8 *Mmassxx= new Real8[nbv];
+  Real8 *dxdx= new Real8[nbv];
+  Real8 *dxdy= new Real8[nbv];
+  Real8 *dydy= new Real8[nbv];
+  Real8 *workT= new Real8[nbt];
+  Real8 *workV= new Real8[nbv];
+  int *OnBoundary = new int[nbv];
+  for (iv=0;iv<nbv;iv++)
+    {
+      Mmass[iv]=0;
+      OnBoundary[iv]=0;
+      Mmassxx[iv]=0;
+    }
+
+  for (i=0;i<nbt;i++) 
+    if(triangles[i].link) // the real triangles 
+      {
+	const Triangle &t=triangles[i];
+	// coor of 3 vertices 
+	R2 A=t[0];
+	R2 B=t[1];
+	R2 C=t[2];
+
+
+	// number of the 3 vertices
+	iA = Number(t[0]);
+	iB = Number(t[1]);
+	iC = Number(t[2]);
+	
+	Real8 dett = bamg::Area2(A,B,C);
+	detT[i]=dett;
+	dett /= 6;
+
+	// construction of on boundary 
+	int nbb =0;
+	for(int j=0;j<3;j++)
+          {
+	    Triangle *ta=t.Adj(j);
+	    if ( ! ta || !ta->link) // no adj triangle => edge on boundary
+	      OnBoundary[Number(t[VerticesOfTriangularEdge[j][0]])]=1,
+		OnBoundary[Number(t[VerticesOfTriangularEdge[j][1]])]=1,
+		nbb++;
+	  }
+	
+	workT[i] = nbb;
+	Mmass[iA] += dett;
+	Mmass[iB] += dett;
+	Mmass[iC] += dett;
+	
+	if((nbb==0)|| !choice)
+	  {
+	    Mmassxx[iA] += dett;
+	    Mmassxx[iB] += dett;
+	    Mmassxx[iC] += dett;
+	  }
+      }
+  else
+    workT[i]=-1;
+
+//  for (Int4 kcount=0;kcount<n;kcount++,ss++)
+    for (Int4 nusol=0;nusol<nbsol;nusol++)
+    { //for all Solution  
+
+      Real8 smin=ss[0],smax=ss[0];
+      
+      Real8 h1=1.e30,h2=1e-30,rx=0;
+      Real8 coef = 1./(anisomax*anisomax);
+      Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+      int nbfield = typsols? sizeoftype[typsols[nusol]] : 1; 
+      if (nbfield == 1) 
+       for ( iv=0,k=0; iv<nbv; iv++,k+=n )
+				{
+				  dxdx[iv]=dxdy[iv]=dydy[iv]=0;
+				  smin=Min(smin,ss[k]);
+				  smax=Max(smax,ss[k]);
+				 }
+			  else
+			   {
+         //  cas vectoriel 
+          for ( iv=0,k=0; iv<nbv; iv++,k+=n )
+          {	
+           double v=0;		     
+			     for (int i=0;i<nbfield;i++) 
+			         v += ss[k+i]*ss[k+i];
+			     v = sqrt(v);
+				   smin=Min(smin,v);
+				   smax=Max(smax,v);
+			    }
+			   }
+      Real8 sdelta = smax-smin;
+      Real8 absmax=Max(Abs(smin),Abs(smax));
+      Real8 cnorm = DoNormalisation ? coef2/sdelta : coef2;
+      
+      if(verbosity>2) 
+	     cout << "    Solution " << nusol <<  " Min = " << smin << " Max = " 
+	       << smax << " Delta =" << sdelta << " cnorm = " << cnorm <<  " Nb of fields =" << nbfield << endl;
+
+      
+      if ( sdelta < 1.0e-10*Max(absmax,1e-20) && (nbfield ==1)) 
+				{
+				  if (verbosity>2)
+				    cout << "      Solution " << nusol << " is constant. We skip. " 
+					 << " Min = " << smin << " Max = " << smax << endl;
+				continue;
+				}
+				
+	 double *sf  = ss; 
+	 for (Int4 nufield=0;nufield<nbfield;nufield++,ss++) 
+	   {
+	     for ( iv=0,k=0; iv<nbv; iv++,k+=n )
+		       dxdx[iv]=dxdy[iv]=dydy[iv]=0;
+       for (i=0;i<nbt;i++) 
+	      if(triangles[i].link)
+	  {// for real all triangles 
+	    // coor of 3 vertices 
+	    R2 A=triangles[i][0];
+	    R2 B=triangles[i][1];
+	    R2 C=triangles[i][2];
+	    
+	    
+	    // warning the normal is internal and the 
+	    //   size is the length of the edge
+	    R2 nAB = Orthogonal(B-A);
+	    R2 nBC = Orthogonal(C-B);
+	    R2 nCA = Orthogonal(A-C);
+	    // remark :  nAB + nBC + nCA == 0 
+
+	    // number of the 3 vertices
+	    iA = Number(triangles[i][0]);
+	    iB = Number(triangles[i][1]);
+	    iC = Number(triangles[i][2]);
+	    
+	    // for the test of  boundary edge
+	    // the 3 adj triangles 
+	    Triangle *tBC = triangles[i].TriangleAdj(OppositeEdge[0]);
+	    Triangle *tCA = triangles[i].TriangleAdj(OppositeEdge[1]);
+	    Triangle *tAB = triangles[i].TriangleAdj(OppositeEdge[2]);
+
+	    // value of the P1 fonction on 3 vertices 
+	    sA = ss[iA*n];
+	    sB = ss[iB*n];
+	    sC = ss[iC*n];
+
+	    R2 Grads = (nAB * sC + nBC * sA + nCA * sB ) /detT[i] ;
+	    if(choice) 
+	      {
+		int nbb = 0;
+		Real8 dd = detT[i];
+		Real8 lla,llb,llc,llf;
+		Real8  taa[3][3],bb[3];
+		// construction of the trans of lin system
+		for (int j=0;j<3;j++)
+		  {
+		    int ie = OppositeEdge[j];
+		    TriangleAdjacent ta = triangles[i].Adj(ie);
+		    Triangle *tt = ta;
+		    if (tt && tt->link)
+		      {
+			Vertex &v = *ta.OppositeVertex();
+			R2 V = v;
+			Int4 iV = Number(v);
+			Real8 lA  = bamg::Area2(V,B,C)/dd;
+			Real8 lB  = bamg::Area2(A,V,C)/dd;
+			Real8 lC  = bamg::Area2(A,B,V)/dd;
+			taa[0][j] =  lB*lC;
+			taa[1][j] =  lC*lA;
+			taa[2][j] =  lA*lB;
+			//Real8 xx = V.x-V.y;
+			//Real8 yy = V.x + V.y;
+			//cout << " iv " << ss[iV*n] << " == " << (8*xx*xx+yy*yy)
+			//     << " l = " << lA << " " << lB << " " << lC 
+			//     << " = " << lA+lB+lC << " " <<  V << " == " << A*lA+B*lB+C*lC << endl;
+			
+			lla = lA,llb=lB,llc=lC,llf=ss[iV*n] ;
+
+			bb[j]     =  ss[iV*n] - ( sA*lA + sB*lB + sC*lC ) ;
+		      }
+		    else
+		      {
+			nbb++;
+			taa[0][j]=0;
+			taa[1][j]=0;
+			taa[2][j]=0;
+			taa[j][j]=1;
+			bb[j]=0;
+		      }
+		  }
+
+		// resolution of 3x3 lineaire system transpose
+		Real8 det33 =  det3x3(taa[0],taa[1],taa[2]);		
+		Real8 cBC   =  det3x3(bb,taa[1],taa[2]);
+		Real8 cCA   =  det3x3(taa[0],bb,taa[2]);
+		Real8 cAB   =  det3x3(taa[0],taa[1],bb);
+		
+		assert(det33);
+		//	det33=1;
+		// verif
+		//	cout << " " << (taa[0][0]*cBC +  taa[1][0]*cCA + taa[2][0] * cAB)/det33 << " == " << bb[0] ;
+		//	cout << " " << (taa[0][1]*cBC +  taa[1][1]*cCA + taa[2][1] * cAB)/det33 << " == " << bb[1];
+		//	cout << " " << (taa[0][2]*cBC +  taa[1][2]*cCA + taa[2][2] * cAB)/det33 << " == " << bb[2] 
+		//	     << "  -- " ;
+		//cout << lla*sA + llb*sB+llc*sC+ (lla*llb* cAB +  llb*llc* cBC + llc*lla*cCA)/det33 
+		//   << " == " << llf <<  endl;
+		// computation of the gradient in the element 
+		
+		// H( li*lj) = grad li grad lj + grad lj grad lj
+		// grad li = njk  / detT ; with i j k ={A,B,C)
+		Real8 Hxx = cAB * ( nBC.x*nCA.x) +  cBC * ( nCA.x*nAB.x) + cCA * (nAB.x*nBC.x);
+		Real8 Hyy = cAB * ( nBC.y*nCA.y) +  cBC * ( nCA.y*nAB.y) + cCA * (nAB.y*nBC.y);
+		Real8 Hxy = cAB * ( nBC.y*nCA.x) +  cBC * ( nCA.y*nAB.x) + cCA * (nAB.y*nBC.x) 
+		          + cAB * ( nBC.x*nCA.y) +  cBC * ( nCA.x*nAB.y) + cCA * (nAB.x*nBC.y);
+		Real8 coef = 1.0/(3*dd*det33);
+		Real8 coef2 = 2*coef;
+		//	cout << " H = " << Hxx << " " << Hyy << " " <<  Hxy/2 << " coef2 = " << coef2 << endl;
+		Hxx *= coef2;
+		Hyy *= coef2;
+		Hxy *= coef2;
+		//cout << i  << " H = " << 3*Hxx/dd << " " << 3*Hyy/dd << " " <<  3*Hxy/(dd*2) << " nbb = " << nbb << endl;
+		if(nbb==0)
+		  {
+		    dxdx[iA] += Hxx;
+		    dydy[iA] += Hyy;
+		    dxdy[iA] += Hxy;
+		    
+		    dxdx[iB] += Hxx;
+		    dydy[iB] += Hyy;
+		    dxdy[iB] += Hxy;
+		    
+		    dxdx[iC] += Hxx;
+		    dydy[iC] += Hyy;
+		    dxdy[iC] += Hxy;
+		  }
+		
+	      }
+	    else
+	      {
+		
+		// if edge on boundary no contribution  => normal = 0
+		if ( ! tBC || ! tBC->link ) nBC = O;
+		if ( ! tCA || ! tCA->link ) nCA = O;
+		if ( ! tAB || ! tAB->link ) nAB = O;
+	    
+		// remark we forgot a 1/2 because
+		//       $\\int_{edge} w_i = 1/2 $ if $i$ is in edge 
+		//                          0  if not
+		// if we don't take the  boundary 
+		// dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;
+		
+		dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;
+		dxdx[iB] += ( nAB.x + nBC.x ) *Grads.x;
+		dxdx[iC] += ( nBC.x + nCA.x ) *Grads.x;
+		
+		// warning optimization (1) the divide by 2 is done on the metrix construction
+		dxdy[iA] += (( nCA.y + nAB.y ) *Grads.x + ( nCA.x + nAB.x ) *Grads.y) ;
+		dxdy[iB] += (( nAB.y + nBC.y ) *Grads.x + ( nAB.x + nBC.x ) *Grads.y) ;
+		dxdy[iC] += (( nBC.y + nCA.y ) *Grads.x + ( nBC.x + nCA.x ) *Grads.y) ; 
+		
+		dydy[iA] += ( nCA.y + nAB.y ) *Grads.y;
+		dydy[iB] += ( nAB.y + nBC.y ) *Grads.y;
+		dydy[iC] += ( nBC.y + nCA.y ) *Grads.y;
+	      }
+	    
+	  } // for real all triangles 
+     Int4 kk=0;
+      for ( iv=0,k=0 ; iv<nbv; iv++,k+=n )
+	if(Mmassxx[iv]>0) 
+	  {
+	    dxdx[iv] /= 2*Mmassxx[iv];
+	    // warning optimization (1) on term dxdy[iv]*ci/2 
+	    dxdy[iv] /= 4*Mmassxx[iv];
+	    dydy[iv] /= 2*Mmassxx[iv];
+	    // Compute the matrix with abs(eigen value)
+	    Metric M(dxdx[iv], dxdy[iv], dydy[iv]);
+	    MatVVP2x2 Vp(M);
+	    //cout <<iv <<  "  M  = " <<  M <<  " aniso= " << Vp.Aniso() ;
+	    Vp.Abs();
+	    M = Vp;
+	      dxdx[iv] = M.a11;
+	      dxdy[iv] = M.a21;
+	      dydy[iv] = M.a22;
+	      //  cout << " (abs)  iv M  = " <<  M <<  " aniso= " << Vp.Aniso() <<endl;
+	  }
+	else kk++;
+      
+      
+      // correction of second derivate
+      // by a laplacien
+
+      Real8 *d2[3] = { dxdx, dxdy, dydy};
+      Real8 *dd;
+      for (int xy = 0;xy<3;xy++)
+	{
+	  dd = d2[xy];
+      // do leat 2 iteration for boundary problem
+	  for (int ijacobi=0;ijacobi<Max(NbJacobi,2);ijacobi++)
+	    {
+	      for (i=0;i<nbt;i++) 
+		if(triangles[i].link) // the real triangles 
+		  {
+		    // number of the 3 vertices
+		    iA = Number(triangles[i][0]);
+		    iB = Number(triangles[i][1]);
+		    iC = Number(triangles[i][2]);
+		    Real8 cc=3;
+		    if(ijacobi==0)
+		      cc = Max((Real8) ((Mmassxx[iA]>0)+(Mmassxx[iB]>0)+(Mmassxx[iC]>0)),1.);
+		    workT[i] = (dd[iA]+dd[iB]+dd[iC])/cc;
+		  }
+	      for (iv=0;iv<nbv;iv++)
+		workV[iv]=0;
+
+	      for (i=0;i<nbt;i++) 
+		if(triangles[i].link) // the real triangles 
+		  {
+		    // number of the 3 vertices
+		    iA = Number(triangles[i][0]);
+		    iB = Number(triangles[i][1]);
+		    iC = Number(triangles[i][2]);
+		    Real8 cc =  workT[i]*detT[i];
+		    workV[iA] += cc;
+		    workV[iB] += cc;
+		    workV[iC] += cc;
+		  }
+
+	      for (iv=0;iv<nbv;iv++)
+		if( ijacobi<NbJacobi || OnBoundary[iv])
+		  dd[iv] = workV[iv]/(Mmass[iv]*6);
+	      
+
+	    }
+
+	  
+	}
+
+      // constuction  of the metrix from the Hessian dxdx. dxdy,dydy
+
+      Real8 rCutOff=CutOff*absmax;// relative cut off 
+
+      for ( iv=0,k=0 ; iv<nbv; iv++,k+=n )
+	{ // for all vertices 
+	  //{
+	  //Metric M(dxdx[iv], dxdy[iv], dydy[iv]);
+	  // MatVVP2x2 Vp(M);	  
+	  //cout << " iv M="<<  M << "  Vp = " << Vp << " aniso  " << Vp.Aniso() << endl;
+	  //}
+	  MetricIso Miso;
+// new code to compute ci ---	  
+	  Real8 ci ;
+	  if (RelativeMetric)
+	    { //   compute the norm of the solution
+	       double xx =0,*sfk=sf+k; 
+	       for (int ifield=0;ifield<nbfield;ifield++,sfk++)
+	          xx += *sfk* *sfk;	       
+	       xx=sqrt(xx);
+	       ci = coef2/Max(xx,rCutOff);
+	    }
+	  else ci = cnorm;
+	  
+ // old 
+//	  Real8 ci = RelativeMetric ? coef2/(Max(Abs(ss[k]),rCutOff)) : cnorm ;
+ //   modif F Hecht 101099
+	  Metric Miv(dxdx[iv]*ci, dxdy[iv]*ci,  dydy[iv]*ci);
+	  MatVVP2x2 Vp(Miv);
+
+	  Vp.Abs();
+	 if(power!=1.0) 
+	      Vp.pow(power);
+	  
+
+
+	  h1=Min(h1,Vp.lmin());
+	  h2=Max(h2,Vp.lmax());
+
+	  Vp.Maxh(hmin);
+	  Vp.Minh(hmax);
+
+	  rx = Max(rx,Vp.Aniso2());
+
+	  Vp.BoundAniso2(coef);
+
+	  hn1=Min(hn1,Vp.lmin());
+	  hn2=Max(hn2,Vp.lmax());
+	  rnx = Max(rnx,Vp.Aniso2());
+
+	  Metric MVp(Vp);
+	  vertices[iv].m.IntersectWith(MVp);
+	}// for all vertices 
+      if (verbosity>2)
+	{ 
+	  cout << "              Field " << nufield << " of solution " << nusol  << endl;
+	  cout << "              before bounding :  Hmin = " << sqrt(1/h2) << " Hmax = " 
+	       << sqrt(1/h1)  << " factor of anisotropy max  = " << sqrt(rx) << endl;
+	  cout << "              after  bounding :  Hmin = " << sqrt(1/hn2) << " Hmax = " 
+	       << sqrt(1/hn1)  << " factor of anisotropy max  = " << sqrt(rnx) << endl;
+	}
+	 } //  end of for all field
+    }// end for all solution 
+
+  delete [] detT;
+  delete [] Mmass;
+  delete [] dxdx;
+  delete [] dxdy;
+  delete [] dydy;
+  delete []  workT;
+  delete [] workV;
+  delete [] Mmassxx;
+  delete []  OnBoundary;
+ 
+}
+
+
+void Triangles::ReadMetric(const char * fmetrix,const Real8 hmin1=1.0e-30,const Real8 hmax1=1.0e30,const Real8 coef=1)
+{
+	long int verbosity=0;
+
+  Real8 hmin = Max(hmin1,MinimalHmin());
+  Real8 hmax = Min(hmax1,MaximalHmax());
+  MeshIstream f_metrix(fmetrix);
+  Int4 k,j;
+  f_metrix >>  k >> j ;
+  if(verbosity>1)
+    cout << " metrix: open " << fmetrix 
+	 << ", le coef = " << coef
+	 << ", hmin = " << hmin 
+	 << ", hmax = " << hmax 
+	 << (  (j == 1)? " Iso " : " AnIso " )<< endl;
+  
+  if (k != nbv || !(j == 1 || j == 3)) 
+    {
+      cerr << " Error Pb metrix " << k << " <> " 
+	   <<  nbv << " or  1 or 3 <> " << j << endl;
+      MeshError(1002);
+    }
+  
+  cout << " j = " << j << endl;
+  //  Int4 nberr = 0;
+  for (Int4 iv=0;iv<nbv;iv++)
+    {
+      Real8 h;
+      if (j == 1) 
+	{
+	f_metrix >>  h ;
+	vertices[iv].m=Metric(Max(hmin,Min(hmax, h*coef)));
+	}
+      else if (j==3) 
+	{
+	  Real8 a,b,c;	     
+	  f_metrix >>  a >> b >> c  ;
+	  MetricAnIso M(a,b,c);
+	  MatVVP2x2 Vp(M/coef);
+	  
+	  Vp.Maxh(hmin);
+	  Vp.Minh(hmax);
+	  vertices[iv].m = Vp;
+	  
+	}
+    }
+ 
+}
+
+void Triangles::WriteMetric(ostream & f,int iso)
+{
+  if (iso)
+    {
+      f <<  nbv <<" " << 1 << endl ;
+      for (Int4 iv=0;iv<nbv;iv++)
+	{
+	  MatVVP2x2 V=vertices[iv].m;
+	  f <<  V.hmin()  << endl;
+	}
+    }
+else
+  {
+    f <<  nbv <<" " << 3 << endl ;
+    for (Int4 iv=0;iv<nbv;iv++)
+      f <<  vertices[iv].m.a11 << " " 
+	<<  vertices[iv].m.a21 << " " 
+	<<  vertices[iv].m.a22 << endl;
+  }
+}
+void  Triangles::MaxSubDivision(Real8 maxsubdiv)
+{
+	long int verbosity=0;
+
+const  Real8 maxsubdiv2 = maxsubdiv*maxsubdiv;
+#ifdef DRAWING2
+  inquire();
+#endif	    
+  if(verbosity>1)
+    cout << "  -- Limit the subdivision of a edges in the new mesh by " << maxsubdiv <<   endl  ;
+  // for all the edges 
+  // if the len of the edge is to long 
+  Int4 it,nbchange=0;    
+  Real8 lmax=0;
+  for (it=0;it<nbt;it++)
+    {
+      Triangle &t=triangles[it];
+      for (int j=0;j<3;j++)
+	{
+	  Triangle &tt = *t.TriangleAdj(j);
+	  if ( ! &tt ||  it < Number(tt) && ( tt.link || t.link)) 
+	    {
+		Vertex &v0 = t[VerticesOfTriangularEdge[j][0]];
+		Vertex &v1 = t[VerticesOfTriangularEdge[j][1]];
+		R2 AB= (R2) v1-(R2) v0;
+		Metric M = v0;
+		Real8 l = M(AB,AB);
+		lmax = Max(lmax,l);
+		if(l> maxsubdiv2)
+		  { R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
+		    Real8 lc = M(AC,AC);
+		    D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
+		    D2xD2 Rt1(Rt.inv());
+		    D2xD2 D(maxsubdiv2,0,0,lc);
+		    D2xD2 MM = Rt1*D*Rt1.t();
+#ifdef DRAWING1
+		    v0.m.Draw(v0);
+#endif	    
+		    v0.m =  M = MetricAnIso(MM.x.x,MM.y.x,MM.y.y);
+#ifdef DRAWING1
+		    v0.m.Draw(v0);
+#endif	    
+		    //		    cout << " M(AB,AB) = " << M(AB,AB) << " == " << maxsubdiv 
+		    //	 << " M(AC,AC) = " << M(AC,AC) << " == " << lc << endl; 
+		    nbchange++;
+		  }
+		M = v1;
+		l = M(AB,AB);
+		lmax = Max(lmax,l);
+		if(l> maxsubdiv2)
+		  { R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
+		    Real8 lc = M(AC,AC);
+		    D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
+		    D2xD2 Rt1(Rt.inv());
+		    D2xD2 D(maxsubdiv2,0,0,lc);
+		    D2xD2  MM = Rt1*D*Rt1.t();
+#ifdef DRAWING1
+		    v1.m.Draw(v1);
+#endif	    
+		    v1.m =  M = MetricAnIso(MM.x.x,MM.y.x,MM.y.y);
+#ifdef DRAWING1
+		    v1.m.Draw(v1);
+		    inquire();
+#endif	    
+		    // cout << " M(AB,AB) = " << M(AB,AB) << " == " << maxsubdiv 
+		    //	 << " M(AC,AC) = " << M(AC,AC) << " == " << lc << endl; 
+		    nbchange++;
+		  }
+		
+		
+	    }
+	}
+    }
+  if(verbosity>3)
+  cout << "    Nb of metric change = " << nbchange 
+       << " Max  of the subdivision of a edges before change  = " << sqrt(lmax) << endl;
+#ifdef DRAWING2
+  inquire();
+#endif	    
+
+}
+
+void Triangles::SmoothMetric(Real8 raisonmax) 
+{ 
+	long int verbosity=0;
+
+  if(raisonmax<1.1) return;
+  if(verbosity > 1)
+     cout << "  -- Triangles::SmoothMetric raisonmax = " << raisonmax << " " <<nbv <<endl;
+  ReMakeTriangleContainingTheVertex();
+  Int4 i,j,kch,kk,ip;
+  Int4 *first_np_or_next_t0 = new Int4[nbv];
+  Int4 *first_np_or_next_t1 = new Int4[nbv];
+  Int4 Head0 =0,Head1=-1;
+  Real8 logseuil= log(raisonmax);
+
+  for(i=0;i<nbv-1;i++)
+    first_np_or_next_t0[i]=i+1; 
+  first_np_or_next_t0[nbv-1]=-1;// end;
+  for(i=0;i<nbv;i++)
+    first_np_or_next_t1[i]=-1;
+  kk=0;
+  while (Head0>=0&& kk++<100) {
+    kch=0;
+    for (i=Head0;i>=0;i=first_np_or_next_t0[ip=i],first_np_or_next_t0[ip]=-1)
+      {  //  pour tous les triangles autour du sommet s
+	// 	cout << kk << " i = " << i << " " << ip << endl;
+	register Triangle * t= vertices[i].t;
+	assert(t);
+	Vertex & vi = vertices[i];
+	TriangleAdjacent ta(t,EdgesVertexTriangle[vertices[i].vint][0]);
+	Vertex *pvj0 = ta.EdgeVertex(0);
+	while (1) {
+	  //	  cout << i << " " <<  Number(ta.EdgeVertex(0)) << " "
+	  //      << Number(ta.EdgeVertex(1)) << "  ---> " ;
+	  ta=Previous(Adj(ta));
+	  // cout <<  Number(ta.EdgeVertex(0)) << " " << Number(ta.EdgeVertex(1)) << endl;
+	  assert(vertices+i == ta.EdgeVertex(1));
+	  Vertex & vj = *(ta.EdgeVertex(0));
+	  if ( &vj ) {
+	    j= &vj-vertices;
+	    assert(j>=0 && j < nbv);
+	    R2 Aij = (R2) vj - (R2) vi;
+	    Real8 ll =  Norme2(Aij);
+	    if (0) {  
+	      Real8 hi = ll/vi.m(Aij);
+	      Real8 hj = ll/vj.m(Aij);
+	      if(hi < hj)
+		{
+		  Real8 dh=(hj-hi)/ll;
+		  //cout << " dh = " << dh << endl;
+		  if (dh>logseuil) {
+		    vj.m.IntersectWith(vi.m/(1 +logseuil*ll/hi));
+		    if(first_np_or_next_t1[j]<0)
+		      kch++,first_np_or_next_t1[j]=Head1,Head1=j;
+		  }
+		}
+	    } 
+	    else
+	      {
+		Real8 li = vi.m(Aij);
+		//Real8 lj = vj.m(Aij);
+		//		if ( i == 2 || j == 2)
+		//  cout << " inter " << i << " " << j << " " << ((1 +logseuil*li)) <<  endl;
+	      	if( vj.m.IntersectWith(vi.m/(1 +logseuil*li)) )
+		  //if( vj.m.IntersectWith(vi.m*(lj/li/(1 +logseuil*lj))) )
+		  if(first_np_or_next_t1[j]<0) // if the metrix change 
+		    kch++,first_np_or_next_t1[j]=Head1,Head1=j;
+	      }
+	  }
+	  if  ( &vj ==  pvj0 ) break;
+	}
+      }
+    Head0 = Head1;
+    Head1 = -1;
+    Exchange(first_np_or_next_t0,first_np_or_next_t1);
+    if(verbosity>5)
+    cout << "     Iteration " << kk << " Nb de  vertices with change  " << kch << endl;
+  }
+  if(verbosity>2 && verbosity < 5) 
+    cout << "    Nb of Loop " << kch << endl;
+  delete [] first_np_or_next_t0;
+  delete [] first_np_or_next_t1;
+}
+
+void Geometry::ReadMetric(const char * fmetrix,Real8 hmin=1.0e-30,Real8 hmax=1.0e30,Real8 coef=1)
+{
+	long int verbosity=0;
+
+  hmin = Max(hmin,MinimalHmin());
+  MeshIstream f_metrix(fmetrix);
+  Int4 k,j;
+  f_metrix >>  k >> j ;
+  if(verbosity>1)
+    cout << "  -- ReadMetric  " << fmetrix 
+	 << ",  coef = " << coef
+	 << ", hmin = " << hmin 
+	 << ", hmax = " << hmax 
+	 << (  (j == 1)? " Iso " : " AnIso " ) << endl;
+  
+  if (k != nbv ||  !(j == 1 || j == 3)) {
+    cerr << " Error Pb metrix " << k << " <> " 
+	 <<  nbv << " or  1 or 3  <> " << j << endl;
+    MeshError(1003);}
+	 
+  
+  //  Int4 nberr = 0;
+  for (Int4 iv=0;iv<nbv;iv++)
+    {
+    Real8 h;
+    if (j == 1) 
+      {
+      f_metrix >>  h ;
+      vertices[iv].m=Metric(Max(hmin,Min(hmax, h*coef)));
+      }
+    else if (j==3) 
+      {
+	Real8 a,b,c;	     
+	f_metrix >>  a >> b >> c  ;
+	MetricAnIso M(a,b,c);
+	MatVVP2x2 Vp(M/coef);
+	Vp.Maxh(hmin);
+      Vp.Minh(hmax);
+      vertices[iv].m = Vp;
+      }
+    }
+  
+}
+
+
+Real8 LengthInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB)
+{
+  Real8 k=1./2.;
+  int level=0;
+  static int kkk=0;
+  static  Metric Ms1[32],Ms2[32];
+  static Real8 lMs1[32],lMs2[32];
+  static double K[32];
+  Real8 l=0,sss=0;
+  Ms1[level]=Ma;
+  Ms2[level]=Mb;
+  Real8 sa =  Ma(AB);
+  Real8 sb =  Mb(AB);
+  lMs1[level]=sa;
+  lMs2[level]=sb;
+  K[level]=k;
+  level++;
+  int i=0;
+  Real8 * L= LastMetricInterpole.L, *S = LastMetricInterpole.S;
+  Real8  sstop = 0.1; // Max(0.6,(sa+sb)/5000);
+  while (level) {
+    level--;
+    Metric M1=Ms1[level];
+    Metric M2=Ms2[level];
+    k=K[level];
+    Real8 s1=  lMs1[level];
+    Real8 s2=  lMs2[level];
+
+    Real8 s= (s1+s2)*k;
+//    if (level >20  && i < 2030-level)
+//    cout << "                  level " << level << " " << i << " " << s << " " << k <<endl;
+    if( s > sstop   && level < 30 && i < 500-level ) {
+      Metric Mi(0.5,M1,0.5,M2);
+      Real8 si = Mi(AB);
+      if( Abs((s1+s2)-(si+si)) > s1*0.001) 
+	{
+	  k=k/2;
+	  // we begin by the end to walk in the correct sens from a to b
+	       // due to the stack 
+	       Ms1[level]=Mi;
+	  Ms2[level]=M2;
+	  lMs1[level]=si;
+	  lMs2[level]=s2;
+	  K[level]=k;
+	  level++;
+	  Ms1[level]=M1;
+	  Ms2[level]=Mi;
+	  lMs1[level]=s1;
+	  lMs2[level]=si;
+	  K[level]=k;
+	  level++;
+	}
+      else
+	L[i]= l += s,S[i]=sss+=k,i++;
+    }
+    else 
+      L[i]= l += s,S[i]=sss+=k,i++;//cout << i << " l = " << l << " sss = " << sss << endl;
+  }
+  // warning for optimisation S is in [0:0.5] not in [0:1]
+  assert(i<512);
+  LastMetricInterpole.lab=l;
+  LastMetricInterpole.opt=i;
+  if (i>200 && kkk++<10)
+     cout << "Warning LengthInterpole: ( i = " << i << " l = " << l << " sss " << sss << " ) " << sstop <<endl;
+  return l;
+}
+
+Real8 abscisseInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB,Real8 s,int optim)
+{ 
+  if(!optim)  LengthInterpole(Ma,Mb,AB);
+  Real8 l  = s* LastMetricInterpole.lab,r;
+  int j=LastMetricInterpole.opt-1,i=0,k;
+  
+  Real8 * L= LastMetricInterpole.L, *S = LastMetricInterpole.S;
+  // warning for optimisation S is the abcisse in [0:0.5]
+  // and L is le lenght 
+  if(l<=L[0])
+    r=2*S[0]*l/L[0];
+  else if (l>=L[j])
+    r=1;
+  else 
+    {
+      while (j-i>1)
+	{
+	  k= (i+j)/2;
+	  if(l<=L[k])
+	    j=k;// l<=L[j] 
+	  else
+	    i=k; //  L[i]<l
+	};
+      //   cout  << i << " " << j  <<" " << L[i] << " " << L[j] << " " << S[i] << " " <<  S[j]  << " l=" << l << endl;
+      if (i==j)
+	r = 2*S[i];
+      else
+	r =  2*(S[i]*(L[j]-l)+ S[j]*(l-L[i]))/(L[j]-L[i]);
+    }
+  assert(r<=1 && r>=0);
+  return r ;
+    
+}
+
+
+#ifdef DRAWING 
+
+void MetricAnIso::Draw(R2 c) const 
+{ 
+  float x= c.x,y= c.y;
+  if (InPtScreen(x,y)) {
+  R2 X(cos(0.0),sin(0.0));
+  X = X / operator()(X);
+  rmoveto(x+X.x,y+X.y);
+  
+  for (int i=1;i<=100;i++)
+   { double t= 2*Pi*i/100.0;
+     R2 X(cos(t),sin(t));
+     X = X / Max(operator()(X),1.0e-5);
+     rlineto(x+X.x,y+X.y); } 
+  }
+}
+
+void MetricIso::Draw(R2 c) const 
+{ 
+  float x= c.x,y= c.y;
+  if (InPtScreen(x,y)) {
+  rmoveto(x+h,y);
+  for (int i=1;i<=40;i++)
+   { double t= Pi*i/20.0;
+     rlineto(x+h*cos(t),y+h*sin(t)); } 
+  }
+}
+
+
+#endif
+}   // end of namespace bamg 
Index: /issm/trunk/src/c/Bamgx/Metric.h
===================================================================
--- /issm/trunk/src/c/Bamgx/Metric.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/Metric.h	(revision 2740)
@@ -0,0 +1,225 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef TYPEMETRIX
+#define TYPEMETRIX MetricAnIso
+#endif
+
+//#include "R2.h"
+namespace bamg {
+
+typedef P2<double,double> D2;
+typedef P2xP2<double,double> D2xD2;
+
+class  MetricAnIso;
+class MatVVP2x2;
+class MetricIso;
+
+typedef TYPEMETRIX Metric;
+
+
+class MetricIso{
+  friend class MatVVP2x2;
+   Real4 h;
+public:
+  MetricIso(Real4 a): h(a){}
+  MetricIso(const MetricAnIso M);// {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));}
+  MetricIso(Real8 a11,Real8 a21,Real8 a22);// {*this=MetricAnIso(a11,a21,a22));}
+  MetricIso(): h(1) {}; // 
+  MetricIso(const Real8  a[3],const  MetricIso m0,
+	   const  MetricIso m1,const  MetricIso m2 )
+    : h(hinterpole 
+	? (a[0]*m0.h+a[1]*m1.h+a[2]*m2.h)
+	: 1/sqrt(a[0]/(m0.h*m0.h)+a[1]/(m1.h*m1.h)+a[2]/(m2.h*m2.h))) {}
+    MetricIso(const Real8  a,const  MetricIso ma,
+	          const Real8  b,const  MetricIso mb)
+    : h(hinterpole
+	? a*ma.h+b*mb.h
+	:1/sqrt(a/(ma.h*ma.h)+b/(mb.h*mb.h))) {}
+  R2 Orthogonal(const R2 A)const {return R2(-h*A.y,h*A.x);}
+  R2 Orthogonal(const I2 A)const {return R2(-h*A.y,h*A.x);}
+//  D2 Orthogonal(const D2 A)const {return D2(-h*A.y,h*A.x);}
+  Real8 operator()(R2 x) const { return sqrt((x,x))/h;};
+  Real8 operator()(R2 x,R2 y) const { return ((x,y))/(h*h);};
+  int  IntersectWith(MetricIso M) {int r=0;if (M.h<h) r=1,h=M.h;return r;}
+  MetricIso operator*(Real8 c) const {return  MetricIso(h/c);} 
+  MetricIso operator/(Real8 c) const {return  MetricIso(h*c);}
+  Real8 det() const {return 1./(h*h*h*h);}    
+  operator D2xD2(){ return D2xD2(1/(h*h),0.,0.,1/(h*h));}
+  void     Box(Real4 & hx,Real4 & hy) { hx=h,hy=h;}
+  friend std::ostream& operator <<(std::ostream& f, const  MetricIso & M)
+  {f << " h=" << M.h<< ";" ;   return f;}
+
+#ifdef DRAWING
+  void Draw(R2 ) const;
+#endif
+};
+
+
+class MetricAnIso{ public:
+  friend class MatVVP2x2;
+  Real8 a11,a21,a22;
+  MetricAnIso(Real8 a): a11(1/(a*a)),a21(0),a22(1/(a*a)){}
+  MetricAnIso(Real8 a,Real8 b,Real8 c) :a11(a),a21(b),a22(c){}
+  MetricAnIso()  {}; // 
+  MetricAnIso(const Real8  a[3],const  MetricAnIso m0,
+	      const  MetricAnIso m1,const  MetricAnIso m2 );
+  R2 mul(const R2 x)const {return R2(a11*x.x+a21*x.y,a21*x.x+a22*x.y);}
+  Real8 det() const {return a11*a22-a21*a21;}  
+  R2 Orthogonal(const R2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}
+  R2 Orthogonal(const I2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}
+//  D2 Orthogonal(const D2 x){return D2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}
+  MetricAnIso( Real8  a,const  MetricAnIso ma,
+	       Real8  b,const  MetricAnIso mb);
+  int  IntersectWith(const MetricAnIso M);
+  MetricAnIso operator*(Real8 c) const {Real8 c2=c*c;return  MetricAnIso(a11*c2,a21*c2,a22*c2);} 
+  MetricAnIso operator/(Real8 c) const {Real8 c2=1/(c*c);return  MetricAnIso(a11*c2,a21*c2,a22*c2);} 
+  operator D2xD2(){ return D2xD2(a11,a21,a21,a22);}
+
+  Real8 operator()(R2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};
+//  Real8 operator()(D2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};
+  Real8 operator()(R2 x,R2 y) const { return x.x*y.x*a11+(x.x*x.y+x.y*y.x)*a21+x.y*y.y*a22;};
+  inline void  Box(Real4 &hx,Real4 &hy) const ;  
+ friend std::ostream& operator <<(std::ostream& f, const  MetricAnIso & M)
+  {f << " mtr a11=" << M.a11 << " a21=a12=" << M.a21 << " a22=" << M.a22 << ";" ;   return f;}
+#ifdef DRAWING
+  void Draw(R2 ) const;
+#endif
+  MetricAnIso(const MatVVP2x2);
+};
+
+
+class MatVVP2x2 
+{
+  friend  class MetricAnIso;
+  friend  class MetricIso;
+public:
+  double lambda1,lambda2;
+  D2 v;
+
+
+  MatVVP2x2(double r1,double r2,const D2 vp1): lambda1(r1),lambda2(r2),v(vp1){}
+  
+  void  Abs(){lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);}
+  void  pow(double p){lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);}
+  void  Min(double a) { lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;}
+  void  Max(double a) { lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;}
+
+  void Minh(double h) {Max(1.0/(h*h));}
+  void Maxh(double h) {Min(1.0/(h*h));}
+  void Isotrope() {lambda1=lambda2=bamg::Max(lambda1,lambda2);}
+  friend std::ostream& operator <<(std::ostream& f, const MatVVP2x2 & c)
+  { f << '{' << 1/sqrt(c.lambda1)<< ',' << 1/sqrt(c.lambda2) << ','<< c.v << '}' <<std::flush ; return f; }
+  friend std::istream& operator >>(std::istream& f,  MatVVP2x2 & c)
+  { f >> c.lambda1 >>c.lambda2 >> c.v.x >> c.v.y ;c.v /= Norme2(c.v); return f; }
+  MatVVP2x2(const MetricAnIso );
+  MatVVP2x2(const MetricIso M) :  lambda1(1/(M.h*M.h)),lambda2(1/(M.h*M.h)),v(1,0) {}
+  Real8 hmin() const {return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));}
+  Real8 hmax() const {return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));}
+  Real8 lmax() const {return bamg::Max3(lambda1,lambda2,1e-30);}
+  Real8 lmin() const {return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);}
+  Real8 Aniso2() const  { return lmax()/lmin();}
+  inline void BoundAniso2(const Real8 coef);
+  Real8 Aniso() const  { return sqrt( Aniso2());}
+  void BoundAniso(const Real8 c){ BoundAniso2(1/(c*c));}
+  void operator *=(double coef){ lambda1*=coef;lambda2*=coef;}
+};
+
+inline void  MatVVP2x2::BoundAniso2(const Real8 coef) 
+{
+  if (coef<=1.00000000001) 
+    if (lambda1 < lambda2)
+      lambda1 = bamg::Max(lambda1,lambda2*coef);
+    else
+      lambda2 = bamg::Max(lambda2,lambda1*coef);
+  else  // a verifier 
+    if (lambda1 > lambda2)
+      lambda1 = bamg::Min(lambda1,lambda2*coef);
+    else
+      lambda2 = bamg::Min(lambda2,lambda1*coef);
+}
+
+
+
+
+void ReductionSimultanee( MetricAnIso M1,  MetricAnIso M2,double & l1,double & l2, D2xD2 & V) ;
+
+inline MetricAnIso::MetricAnIso(const MatVVP2x2 M)  
+{
+ //     recompose M in: M = V^t lambda V 
+  //     V = ( v,v^\perp)
+  //  where v^\perp = (-v_1,v_0)
+  double v00=M.v.x*M.v.x;
+  double v11=M.v.y*M.v.y;
+  double v01=M.v.x*M.v.y;
+  a11=v00*M.lambda1+v11*M.lambda2;
+  a21=v01*(M.lambda1-M.lambda2);
+  a22=v00*M.lambda2+v11*M.lambda1;
+}
+
+
+inline   void  MetricAnIso::Box(Real4 &hx,Real4 &hy) const 
+{
+  Real8 d=  a11*a22-a21*a21;
+  hx = sqrt(a22/d);
+  hy = sqrt(a11/d);
+  //  cerr << " hx = " << hx << " hy =  " << hy << endl;
+}
+
+
+inline MetricIso::MetricIso(const MetricAnIso M) 
+  {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));}
+  
+inline  MetricIso::MetricIso(Real8 a11,Real8 a21,Real8 a22)
+  {MatVVP2x2 vp(MetricAnIso(a11,a21,a22));h=1/sqrt(Max(vp.lambda1,vp.lambda2));}
+
+
+
+class SaveMetricInterpole {
+  friend  Real8 LengthInterpole(const MetricAnIso ,const  MetricAnIso , R2 );
+  friend Real8 abscisseInterpole(const MetricAnIso ,const  MetricAnIso , R2 ,Real8 ,int );
+  int opt;
+  Real8 lab;
+  Real8 L[1024],S[1024];
+};
+
+extern SaveMetricInterpole  LastMetricInterpole; // for optimization 
+
+
+ Real8 LengthInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB);
+ Real8 abscisseInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB,Real8 s,int optim=0);
+
+
+
+inline Real8 LengthInterpole(Real8 la,Real8 lb) 
+{   return ( Abs(la - lb) < 1.0e-6*Max3(la,lb,1.0e-20) ) ?  (la+lb)/2  : la*lb*log(la/lb)/(la-lb);}
+
+inline Real8 abscisseInterpole(Real8 la,Real8 lb,Real8 lab,Real8 s)
+{ return ( Abs(la - lb) <1.0e-6*Max3(la,lb,1.0e-20))  ? s : (exp(s*lab*(la-lb)/(la*lb))-1)*lb/(la-lb);}
+
+}
Index: /issm/trunk/src/c/Bamgx/QuadTree.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/QuadTree.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/QuadTree.cpp	(revision 2740)
@@ -0,0 +1,542 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <limits.h>
+//#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+
+namespace bamg {
+
+#define INTER_SEG(a,b,x,y) (((y) > (a)) && ((x) <(b)))
+#define ABS(i) ((i)<0 ?-(i) :(i))
+#define MAX1(i,j) ((i)>(j) ?(i) :(j))
+#define NORM(i1,j1,i2,j2) MAX1(ABS((i1)-(j1)),ABS((i2)-(j2)))
+
+#define IJ(i,j,l) ( ( j & l) ? (( i & l) ? 3 : 2 ) :( ( i & l)? 1 : 0 ))
+#define I_IJ(k,l)  (( k&1) ? l : 0)
+#define J_IJ(k,l)  (( k&2) ? l : 0)
+
+
+#ifdef DRAWING
+
+void  QuadTree::Draw()
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+  register int l=0; // level
+  register QuadTreeBox * b;
+  IntQuad hb =  MaxISize;
+  if(!root) return;
+  //  Int4 kkk =0;
+  pb[0]=  root;
+  pi[0]= root->n>0 ?(int)  root->n : 4  ;
+  ii[0]=jj[0]=0;
+  do{    
+    b= pb[l];
+
+    while (pi[l]--)
+      { 
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	    { // 
+	      for (int k=0;k<b->n;k++)
+		{
+		  I2 i2 =  b->v[k]->i;
+		  IMoveTo(i2.x,i2.y+50);
+		  ILineTo(i2.x,i2.y-50);
+		  IMoveTo(i2.x+50,i2.y);
+		  ILineTo(i2.x-50,i2.y);
+
+		  assert(ii[l] <= i2.x);
+		  assert(jj[l] <= i2.y);
+		  assert(ii[l] +hb > i2.x);
+		  assert(jj[l] +hb > i2.y);
+
+		}
+	      break;
+	    }
+	else // Pointer QuadTreeBox 
+	    { 
+	      register int lll = pi[l];
+	      register QuadTreeBox *b0=b;
+	      
+	      if ((b=b->b[lll])) 
+		{ 
+		  hb >>=1 ; // div by 2
+		  register Icoor1 iii = ii[l]+I_IJ(lll,hb);
+		  register Icoor1 jjj = jj[l]+J_IJ(lll,hb);
+		  
+		  pb[++l]=  b;
+		  pi[l]= 4;
+		  ii[l]= iii;
+		  jj[l]= jjj;
+		  
+		  IMoveTo(ii[l],jj[l]);
+		  ILineTo(ii[l]+hb,jj[l]);
+		  ILineTo(ii[l]+hb,jj[l]+hb);
+		  ILineTo(ii[l]   ,jj[l]+hb);
+		  ILineTo(ii[l]   ,jj[l]);
+		  
+		  
+		}
+	      else
+		{
+		  register Icoor1 iii = ii[l]+I_IJ(lll,hb/2);
+		  register Icoor1 jjj = jj[l]+J_IJ(lll,hb/2);
+		  b=b0;
+
+		  IMoveTo(iii,     jjj);
+		  ILineTo(iii+hb/2,jjj+hb/2);
+		  IMoveTo(iii+hb/2,jjj);
+		  ILineTo(iii     ,jjj+hb/2);
+
+		}
+	    }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+
+}
+
+#endif
+
+Vertex *  QuadTree::NearestVertex(Icoor1 i,Icoor1 j)
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+  register int l=0; // level
+  register QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  Icoor1  i0=0,j0=0;
+  Icoor1  iplus( i<MaxISize?(i<0?0:i):MaxISize-1);
+  Icoor1  jplus( j<MaxISize?(j<0?0:j):MaxISize-1);
+  
+  Vertex *vn=0;
+  
+  // init for optimisation ---
+  b = root;
+  register Int4  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+      register Icoor1 hb2 = hb >> 1 ;
+      register  int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+      register QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      i0 += I_IJ(k,hb2); // i orign of QuadTreeBox
+      j0 += J_IJ(k,hb2); // j orign of QuadTreeBox 
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for(register int k=0;k<n0;k++)
+	{
+	  I2 i2 =  b->v[k]->i;
+	  h0 = NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];}
+	  NbVerticesSearch++;
+	}
+      return vn;
+    }
+  // general case -----
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+	register int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  b->v[k]->i;
+	    h0 = NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    register QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+		register Icoor1 iii = ii[l]+I_IJ(k,hb);
+		register Icoor1 jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+}
+
+
+
+Vertex *   QuadTree::ToClose(Vertex & v,Real8 seuil,Icoor1 hx,Icoor1 hy)
+{
+  const Icoor1 i=v.i.x;
+  const Icoor1 j=v.i.y;
+  const R2 X(v.r);
+  const Metric  Mx(v.m);
+
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+  register int l=0; // level
+  register QuadTreeBox * b;
+  Icoor1 h=MaxISize;
+  Icoor1 hb =  MaxISize;
+  Icoor1 i0=0,j0=0;
+  
+  //  Vertex *vn=0;
+  
+  if (!root->n)
+    return 0; // empty tree 
+  
+  // general case -----
+  pb[0]=root;
+  pi[0]=root->n>0 ?(int)  root->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+	register int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  b->v[k]->i;
+	    if ( ABS(i-i2.x) <hx && ABS(j-i2.y) <hy )
+	      {
+		R2 XY(X,b->v[k]->r);
+		Real8 dd;
+	      // old code	        if( Mx(XY) + b->v[k]->m(XY) < seuil )
+	        if( (dd= LengthInterpole(Mx(XY), b->v[k]->m(XY)))  < seuil )
+		  {
+		    //  cout <<  CurrentTh->Number(v) << "is To Close " 
+		    // << CurrentTh->Number( b->v[k]) << " l=" <<dd<<endl;
+		    return b->v[k]; 
+		  }
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    register QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k]))
+	      {
+		hb >>=1 ; // div by 2
+		register long iii = ii[l]+I_IJ(k,hb);
+		register long jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,i-hx,i+hx) && INTER_SEG(jjj,jjj+hb,j-hy,j+hy)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return 0;
+}
+
+
+void  QuadTree::Add( Vertex & w)
+{
+  QuadTreeBox ** pb , *b;
+  register long i=w.i.x, j=w.i.y,l=MaxISize;
+  pb = &root;
+  //    cout << pb << " " << &root << endl;
+  while( (b=*pb) && (b->n<0))
+    { 
+      b->n--;
+      l >>= 1;
+      pb = &b->b[IJ(i,j,l)];
+    }
+  if  (b) {      
+    if (b->n > 3 &&  b->v[3] == &w) return;
+    if (b->n > 2 &&  b->v[2] == &w) return;
+    if (b->n > 1 &&  b->v[1] == &w) return;
+    if (b->n > 0 &&  b->v[0] == &w) return;
+  }
+  assert(l);
+  while ((b= *pb) && (b->n == 4)) // the QuadTreeBox is full
+    { 
+      Vertex *v4[4]; // copy of the QuadTreeBox vertices
+      
+      v4[0]= b->v[0];
+      v4[1]= b->v[1];
+      v4[2]= b->v[2];
+      v4[3]= b->v[3];
+      b->n = -b->n; // mark is pointer QuadTreeBox
+      b->b[0]=b->b[1]=b->b[2]=b->b[3]=0; // set empty QuadTreeBox ptr
+      l >>= 1;    // div the size by 2
+      for (register int k=0;k<4;k++) // for the 4 vertices find the sub QuadTreeBox ij
+	{ 
+	  register int ij;
+	  register QuadTreeBox * bb =  b->b[ij=IJ(v4[k]->i.x,v4[k]->i.y,l)];
+	  if (!bb) 
+	    bb=b->b[ij]=NewQuadTreeBox(); // alloc the QuadTreeBox 
+	  //    cout << bb << " " << k << " "  << ij <<  endl;
+	  bb->v[bb->n++] = v4[k];
+	}
+      pb = &b->b[IJ(i,j,l)];
+    }
+  if (!(b = *pb))
+    b=*pb= NewQuadTreeBox(); //  alloc the QuadTreeBox 
+  //   cout << b << " " << b->n << endl;
+  b->v[b->n++]=&w; // we add the vertex 
+  NbVertices++;    
+}
+
+QuadTree::QuadTree(Triangles * t,long nbv) : 
+  lenStorageQuadTreeBox(t->nbvx/8+10),
+  th(t),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0)
+{ 
+  if (nbv == -1) nbv = t->nbv;
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+  assert( MaxISize > MaxICoor);
+  for (Int4 i=0;i<nbv;i++) 
+    Add(t->vertices[i]);
+#ifdef DRAWING1
+  Draw();
+#endif
+}
+
+QuadTree::QuadTree() : 
+  lenStorageQuadTreeBox(100),
+  th(0),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0)
+{
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+}
+QuadTree::StorageQuadTreeBox::StorageQuadTreeBox(long ll,StorageQuadTreeBox *nn)
+{
+  len = ll;
+  n = nn;
+  b = new QuadTreeBox[ll];
+  for (int i = 0; i <ll;i++)
+    b[i].n =0,b[i].b[0]=b[i].b[1]=b[i].b[2]=b[i].b[3]=0;
+  bc =b;
+  be = b +ll;
+  assert(b);
+}
+
+QuadTree::~QuadTree()
+{
+  delete sb; 
+  root=0;
+}
+
+ostream& operator <<(ostream& f, const  QuadTree & qt)
+{ 
+  f << " the quadtree "  << endl;
+  f << " NbQuadTreeBox = " << qt.NbQuadTreeBox 
+    << " Nb Vertices = " <<  qt.NbVertices << endl;
+  f << " NbQuadTreeBoxSearch " << qt.NbQuadTreeBoxSearch  
+    << " NbVerticesSearch " << qt.NbVerticesSearch << endl;
+  f << " SizeOf QuadTree" << qt.SizeOf() << endl;
+  //     return  dump(f,*qt.root);
+  return  f;
+}
+
+Vertex *  QuadTree::NearestVertexWithNormal(Icoor1 i,Icoor1 j)
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+  int l; // level
+  QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  Icoor1  i0=0,j0=0;
+  Icoor1  iplus( i<MaxISize?(i<0?0:i):MaxISize-1);
+  Icoor1  jplus( j<MaxISize?(j<0?0:j):MaxISize-1);
+  
+  Vertex *vn=0;
+  
+  // init for optimisation ---
+  b = root;
+  register Int4  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+      register Icoor1 hb2 = hb >> 1 ;
+      register  int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+      register QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      i0 += I_IJ(k,hb2); // i orign of QuadTreeBox
+      j0 += J_IJ(k,hb2); // j orign of QuadTreeBox 
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for(register int k=0;k<n0;k++)
+	{
+	  I2 i2 =  b->v[k]->i;
+	  //   try if is in the right sens -- 
+	  h0 = NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];}
+	  NbVerticesSearch++;
+	}
+	if (vn) return vn; 
+    }
+  // general case -----
+  // INITIALISATION OF THE HEAP 
+  l =0; // level 
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {   // walk on the tree  
+    b= pb[l];
+    while (pi[l]--) // loop on 4 element of the box
+      { 	      
+       int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  b->v[k]->i;
+	    // if good sens when try -- 
+	    
+	    h0 = NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    register QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+		register Icoor1 iii = ii[l]+I_IJ(k,hb);
+		register Icoor1 jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+}
+
+
+}  // end of namespace bamg
+
Index: /issm/trunk/src/c/Bamgx/QuadTree.h
===================================================================
--- /issm/trunk/src/c/Bamgx/QuadTree.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/QuadTree.h	(revision 2740)
@@ -0,0 +1,111 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+namespace bamg {
+
+const int MaxDeep = 30;
+typedef  long  IntQuad;
+const IntQuad MaxISize = ( 1L << MaxDeep);
+
+
+class Triangles;
+class Vertex;
+
+class QuadTree {
+ public:
+
+  class QuadTreeBox { 
+  public:
+
+    long n; // if n < 4 => Vertex else =>  QuadTreeBox;
+    union {
+      QuadTreeBox *b[4];
+      Vertex * v[4];
+    };
+    
+
+  }; // end class QuadTreeBox  /////////////////
+
+  class StorageQuadTreeBox {
+  public:
+    QuadTreeBox *b,*bc,*be;
+    long len;
+    StorageQuadTreeBox *n; // next StorageQuadTreeBox
+    StorageQuadTreeBox(long ,StorageQuadTreeBox * =0);
+    ~StorageQuadTreeBox()
+    { //cout <<  "~StorageQuadTreeBox " << this << " n " << n << " b " << b << endl;
+      if(n) delete n;
+      delete [] b;
+    }
+    long  SizeOf() const {
+      return len*sizeof(QuadTreeBox)+sizeof(StorageQuadTreeBox)+ (n?n->SizeOf():0);
+    }
+  }; // end class  StorageQuadTreeBox 
+  
+  StorageQuadTreeBox * sb;
+  
+  
+  long  lenStorageQuadTreeBox;
+
+public:
+  QuadTreeBox * root;
+  Triangles *th;
+  long NbQuadTreeBox,NbVertices;
+  long NbQuadTreeBoxSearch,NbVerticesSearch;
+  Vertex * NearestVertex(Icoor1 i,Icoor1 j);
+  Vertex *  NearestVertexWithNormal(Icoor1 i,Icoor1 j); // new version  
+  Vertex * ToClose(Vertex & ,Real8 ,Icoor1,Icoor1);
+  long SizeOf() const {return sizeof(QuadTree)+sb->SizeOf();}
+
+#ifdef DRAWING
+    void Draw();
+#endif
+
+  void  Add( Vertex & w);
+
+  QuadTreeBox* NewQuadTreeBox()
+  {
+    ///cout << "NewQuadTreeBox " << sb << " " << sb->bc << " " 
+    //<< sb->be << " " <<lenStorageQuadTreeBox <<endl;
+    if(! (sb->bc<sb->be)) 
+	sb=new StorageQuadTreeBox(lenStorageQuadTreeBox,sb);
+
+    assert(sb && (sb->bc->n == 0));
+    NbQuadTreeBox++;
+    return sb->bc++;
+  }
+  ~QuadTree();
+  QuadTree(Triangles * t,long nbv=-1);
+  QuadTree();
+  friend ostream& operator <<(ostream& f, const  QuadTree & qt);
+
+
+	
+};
+}
+//#undef IJ
Index: /issm/trunk/src/c/Bamgx/R2.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/R2.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/R2.cpp	(revision 2740)
@@ -0,0 +1,31 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <iostream>
+using namespace std;
+#include "R2.h"
Index: /issm/trunk/src/c/Bamgx/R2.h
===================================================================
--- /issm/trunk/src/c/Bamgx/R2.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/R2.h	(revision 2740)
@@ -0,0 +1,135 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+namespace bamg {
+template <class R,class RR> class P2xP2;
+
+template <class R,class RR>
+class P2 {
+
+public:  
+  R x,y;
+  P2 () :x(0),y(0) {};
+  P2 (R a,R b)  :x(a),y(b)  {}
+  P2 (P2 A,P2 B) : x(B.x-A.x),y(B.y-A.y) {}
+  P2<R,RR>   operator+(const P2<R,RR> & cc) const {return P2<R,RR>(x+cc.x,y+cc.y);}
+  P2<R,RR>   operator-(const P2<R,RR> & cc) const {return P2<R,RR>(x-cc.x,y-cc.y);}
+  P2<R,RR>   operator-()  const{return P2<R,RR>(-x,-y);}
+//  RR   operator*(const P2<R,RR> & cc) const {return  (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} // produit scalaire
+  RR   operator,(const P2<R,RR> & cc) const {return  (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} // produit scalaire
+  P2<R,RR>   operator*(R  cc) const {return P2<R,RR>(x*cc,y*cc);}
+ // P2<R,RR>   operator*(RR  cc) const {return P2<R,RR>((R)(x*cc),(R)(y*cc));}
+  P2<R,RR>   operator/(R  cc) const {return P2<R,RR>(x/cc,y/cc);}
+  P2<R,RR>  operator+=(const  P2<R,RR> & cc) {x += cc.x;y += cc.y;return *this;}
+  P2<R,RR>  operator/=(const  R r) {x /= r;y /= r;return *this;}
+  P2<R,RR>  operator*=(const  R r) {x *= r;y *= r;return *this;}
+  P2<R,RR>  operator-=(const  P2<R,RR> & cc) {x -= cc.x;y -= cc.y;return *this;}
+//  P2<R,RR> Orthogonal(const   P2<R,RR> r) {return P2<R,RR>(-r.y,r.x);}
+ };
+
+template <class R,class RR>
+class P2xP2 { // x ligne 1 y ligne2 
+
+  friend std::ostream& operator <<(std::ostream& f, const P2xP2<R,RR> & c) 
+     { f << '[' << c.x << ',' << c.y << ']' <<std::flush ; return f; }
+     
+  friend P2<R,RR> operator*(P2<R,RR> c,P2xP2<R,RR> cc)
+     {return P2<R,RR>(c.x*cc.x.x + c.y*cc.y.x, c.x*cc.x.y + c.y*cc.y.y);} 
+
+
+ public:
+  P2<R,RR> x,y; 
+  P2xP2 (): x(),y()  {}
+  P2xP2 (P2<R,RR> a,P2<R,RR> b): x(a),y(b) {}
+  P2xP2 (P2<R,RR> a,P2<R,RR> b,P2<R,RR> c ): x(b-a),y(c-a) {}
+  P2xP2 (R xx,R xy,R yx,R yy) :x(xx,xy),y(yx,yy) {}
+  P2<R,RR> operator*(const P2<R,RR> c) const {return P2<R,RR>(x.x*c.x + x.y*c.y, y.x*c.x + y.y*c.y);}
+  P2xP2<R,RR>  operator*(P2xP2<R,RR> c) const 
+    { return  P2xP2<R,RR>(x.x*c.x.x + x.y*c.y.x,
+			  x.x*c.x.y + x.y*c.y.y,
+			  y.x*c.x.x + y.y*c.y.x,
+			  y.x*c.x.y + y.y*c.y.y);}
+  RR det() const {return (RR) x.x* (RR) y.y - (RR) x.y * (RR) y.x;}
+  P2xP2<R,RR> inv()  const
+     { RR d = (*this).det(); 
+       return P2xP2<R,RR>((R)( y.y /d) ,(R)(-x.y/d),(R)( -y.x/d) ,(R)( x.x/d) );
+     };
+   P2xP2<R,RR> t() {return P2xP2<R,RR>(x.x,y.x,x.y,y.y);} //transposer 
+   P2<R,RR>tx() {return P2<R,RR>(x.x,y.x);} 
+   P2<R,RR>ty() {return P2<R,RR>(x.y,y.y);} 
+
+};  
+
+
+
+//template  <class R,class RR>  // transposer
+//inline P2xP2<R,RR> t(P2xP2<R,RR> m) 
+//   {return P2xP2<R,RR>(m.x.x,m.y.x,m.x.y,m.y.y);} 
+
+template  <class R,class RR>  
+inline RR Det(const P2<R,RR> x,const P2<R,RR> y) {
+  return (RR) x.x * (RR) y.y - (RR) x.y * (RR) y.x ;} 
+
+template  <class R,class RR>  
+inline RR Area2 (const P2<R,RR> a,const P2<R,RR> b,const P2<R,RR> c) {
+  return Det(b-a,c-a) ;} 
+
+template  <class R,class RR>  
+inline R Norme1 (const P2<R,RR> x) {
+  return (Abs(x.x)+Abs(x.y)) ;} 
+
+template  <class R,class RR>  
+inline R NormeInfini (const P2<R,RR> x) {
+  return Max(Abs(x.x),Abs(x.y)) ;} 
+
+template  <class R,class RR>  
+inline RR Norme2_2 (const P2<R,RR> x) {
+  return (RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y ;} 
+
+template  <class R,class RR>  
+inline RR Norme2 (const P2<R,RR> x) {
+  return sqrt((RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y) ;} 
+
+template  <class R,class RR>  
+inline P2<R,RR> Orthogonal (const P2<R,RR> x) {
+  return  P2<R,RR>(-x.y,x.x);} 
+
+template <class R,class RR>
+inline  std::ostream& operator <<(std::ostream& f, const P2<R,RR> & c)
+  { f << '[' << c.x << ',' << c.y <<']' <<std::flush ; return f; }
+
+   
+/*template  <class R,class RR>
+inline P2<R,RR> Min2(P2<R,RR> x,P2<R,RR> y) 
+   {return  P2<R,RR>(Min(x.x,y.x),Min(x.y,y.y) ;} 
+
+template  <class R,class RR>
+inline P2<R,RR> Max2(P2<R,RR> x,P2<R,RR> y) 
+   {return  P2<R,RR>(Max(x.x,y.x),Max(x.y,y.y) ;} 
+*/
+}
Index: /issm/trunk/src/c/Bamgx/SetOfE4.cpp
===================================================================
--- /issm/trunk/src/c/Bamgx/SetOfE4.cpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/SetOfE4.cpp	(revision 2740)
@@ -0,0 +1,84 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <iostream> 
+using namespace std;
+#include "meshtype.h"
+#include "SetOfE4.h"
+
+namespace bamg {
+
+ SetOfEdges4::SetOfEdges4(Int4 mmx,Int4 nnx)
+   {nx=nnx;
+    nbax=mmx;
+    NbOfEdges = 0;
+    tete= new Int4 [nx];
+    Int4 i=nx;
+    while (i--)
+      tete[i] = -1;// vide 
+    Edges =new Int4Edge[nbax];
+   }
+    
+ Int4 SetOfEdges4::find(Int4 ii,Int4 jj)
+{ 
+  if (tete == 0 ) {
+    cerr <<"SetOfEdges4::find \nplus de tete de liste\n";
+    MeshError(888);}
+  Int4 n = tete[ Abs( ii ) % nx ];
+  
+  while (n >= 0) 
+    if (ii == Edges[n].i && jj == Edges[n].j)
+      return n;
+    else n = Edges[n].next;
+  return -1; // n'existe pas
+}
+
+ Int4 SetOfEdges4::add(Int4 ii,Int4 jj)
+{
+  if (tete == 0 ) {
+    cerr << "SetOfEdges4::add\n plus de tete de liste \n" << endl;
+    MeshError(888);}
+  
+  Int4 h;
+  Int4 n = tete[ h = Abs( ii ) % nx ];
+  while (n >= 0) 
+   if (ii == Edges[n].i && jj == Edges[n].j)
+            return n;
+   else n = Edges[n].next;
+  if (nbax <=NbOfEdges ) {
+    cerr << " SetOfEdges4::add\noverflow de la pile "  << nbax << " " << NbOfEdges << endl;
+    MeshError(888);}
+  
+   Edges[NbOfEdges].i=ii;
+   Edges[NbOfEdges].j=jj;
+   Edges[NbOfEdges].next= tete[h];
+   tete[h] = NbOfEdges;
+   return NbOfEdges ++;
+}
+
+
+}  // end of namespace bamg 
Index: /issm/trunk/src/c/Bamgx/SetOfE4.h
===================================================================
--- /issm/trunk/src/c/Bamgx/SetOfE4.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/SetOfE4.h	(revision 2740)
@@ -0,0 +1,64 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SetOfEdge4_h
+#define _SetOfEdge4_h
+
+namespace bamg {
+
+class SetOfEdges4 ;
+class Int4Edge{
+friend class SetOfEdges4;
+public:
+  Int4 i,j;
+  Int4 next; 
+};
+
+class SetOfEdges4 {
+  Int4 nx,nbax,NbOfEdges;
+  Int4 * tete; 
+  Int4Edge * Edges;
+
+public:
+  SetOfEdges4(Int4 ,Int4);// nb Edges mx , nb de sommet 
+  ~SetOfEdges4() {// cout << " delete SetofArete " << endl ;
+  delete [] tete; delete [] Edges;}
+   Int4 add (Int4 ii,Int4 jj);
+  Int4 addtrie (Int4 ii,Int4 jj) {return ii <=jj ? add (ii,jj)  : add (jj,ii) ;}
+  Int4  nb(){return NbOfEdges;}
+  Int4 find (Int4 ii,Int4 jj);
+  Int4 findtrie (Int4 ii,Int4 jj) {return ii <=jj ? find (ii,jj)  : find (jj,ii) ;}
+  // inline void close();
+  Int4 i(Int4 k){return Edges[k].i;}
+  Int4 j(Int4 k){return Edges[k].j;}
+  Int4 newarete(Int4 k){return NbOfEdges == k+1;}
+  Int4Edge & operator[](Int4 k){return  Edges[k];}
+};
+}
+
+#endif 
Index: /issm/trunk/src/c/Bamgx/error.hpp
===================================================================
--- /issm/trunk/src/c/Bamgx/error.hpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/error.hpp	(revision 2740)
@@ -0,0 +1,132 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef ERROR_H
+#define ERROR_H
+#include <cassert>
+#include <string>
+#include "throwassert.hpp"
+#include <exception>
+
+extern int TheCurrentLine; 
+
+#if defined(__GNUC__) && __GNUC__+0 < 3
+#include <strstream.h>
+ typedef  istrstream istringstream   ;
+ typedef  ostrstream ostringstream   ;
+#define ENDS << '\0'
+#define OLDCPP 1 
+#else
+// car ostringstream n'est pas encore defin sous g++
+//  
+#include <sstream>
+#define ENDS 
+
+#endif
+
+  using std::exception;
+
+
+class Error : public exception
+{ public:
+  enum CODE_ERROR { NONE, COMPILE_ERROR,EXEC_ERROR, MEM_ERROR,MESH_ERROR,ASSERT_ERROR,INTERNAL_ERROR, UNKNOWN };
+  
+  
+private: 
+  std::string  message;
+  const CODE_ERROR code;
+protected:
+  Error(CODE_ERROR c,const char * t1,const char * t2,const char * t3=0,
+	int n=0,const char * t4=0,const char * t5=0,const char * t6=0,
+	const char * t7=0,const char * t8=0,const char * t9=0)     
+    : message(),code(c)
+  {
+    using namespace std;
+    ostringstream mess;
+    if(t1)  mess << t1;
+    if(t2)  mess << t2;
+    if(t3)  mess << t3 << n ;
+    if(t4)  mess << t4;
+    if(t5)  mess << t5;
+    if(t6)  mess << t6;
+    if(t7)  mess << t7;
+    if(t8)  mess << t8;
+    if(t9)  mess << t9;
+    message = mess.str();
+    if (c!=NONE ) cerr  << message << endl; // cerr << " at exec line  " << TheCurrentLine << endl; 
+    }
+public:
+  virtual int errcode() const {return code;} 
+  virtual const char *  what() const   throw () { return message.c_str(); } 
+  virtual  ~Error() throw () {}      
+};
+
+class ErrorCompile : public Error
+{
+ public:
+  ErrorCompile(const char * Text,int l,const char * t2="") : 
+    Error(COMPILE_ERROR,"Compile error : ",Text,"\n\tline number :",l,", ", t2) {}
+};
+
+class ErrorExec : public Error
+{  
+ public:
+  ErrorExec(const char * Text,int l) :
+    Error(UNKNOWN,"Exec error : ",Text, "\n   -- number :", l)  {}
+};
+
+class ErrorInternal : public Error
+{  
+ public:
+  ErrorInternal(const char * Text,int l,const char * t2="") :
+    Error(INTERNAL_ERROR,"Internal error : ",Text, "\n\tline  :",l,", in file ", t2)  {}
+};
+class ErrorAssert : public Error
+{  
+ public:
+  ErrorAssert(const char * Text,const char *file,const int line) :
+    Error(ASSERT_ERROR,"Assertion fail : (",Text, ")\n\tline :", line,", in file ",file)  {}
+};
+
+
+class ErrorMemory : public Error
+{ public:
+  ErrorMemory(const char * Text,int l=0) : 
+    Error(MEM_ERROR,"Memory Error : ",Text," number: ",l)  {}
+};
+
+class ErrorExit : public Error
+{
+  int codeexit;
+public:
+  ErrorExit(const char * ,int l) :
+    Error(NONE,"exit","(","",l,")"), codeexit(l)   {}
+    // the exit code fo freefem++ is given by l 
+  int errcode() const{return codeexit;}
+};
+
+#endif
Index: /issm/trunk/src/c/Bamgx/meshtype.h
===================================================================
--- /issm/trunk/src/c/Bamgx/meshtype.h	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/meshtype.h	(revision 2740)
@@ -0,0 +1,71 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef MESHTYPE_H
+#define MESHTYPE_H
+#include <limits.h>
+namespace bamg {
+template<class T> inline T Square (const T &a) { return a*a;} 
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+template<class T> inline double Norme (const T &a){return sqrt(a*a);}
+template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;}
+// for pb on microsoft compiler 
+template<class T> inline T Max3 (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min3 (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+
+typedef float  Real4;
+typedef double Real8;
+typedef short  Int1;
+typedef short  Int2;
+typedef long   Int4;
+
+#if LONG_BIT > 63
+// for alpha and silicon 
+ typedef int  Icoor1;  
+ typedef long   Icoor2;
+ const Icoor1 MaxICoor = 1073741823; // 2^30-1
+ const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+
+#elif  defined(BAMG_LONG_LONG)
+ typedef long  Icoor1;
+ typedef long long   Icoor2;
+ const Icoor1 MaxICoor =   1073741823;// 2^30-1
+// not a const due to a bug in hp compiler
+#define  MaxICoor22 2305843004918726658LL
+//const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+#else
+ typedef int  Icoor1;
+ typedef double   Icoor2;
+ const Icoor1 MaxICoor = 8388608; // 2^23
+ const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+#endif
+ class Triangles;
+extern void MeshError(int Err,Triangles *Th=0) ;
+}
+#endif
Index: /issm/trunk/src/c/Bamgx/throwassert.hpp
===================================================================
--- /issm/trunk/src/c/Bamgx/throwassert.hpp	(revision 2740)
+++ /issm/trunk/src/c/Bamgx/throwassert.hpp	(revision 2740)
@@ -0,0 +1,52 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht@ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef THROWASSERT
+#define THROWASSERT
+#include <iostream>
+
+//#ifdef __INTEL__
+#define cerr cout 
+//#endif
+
+#include "error.hpp"
+
+#ifdef NDEBUG
+#define throwassert(i)  ( (void) 0)
+#else
+#define throwassert(condition)  ((condition) ? ( (void) 0) : throw(ErrorAssert(#condition,__FILE__, __LINE__)))
+ 
+#undef assert
+#define assert(condition) throwassert(condition)
+#endif
+// an unremovable assert : ffassert
+#define ffassert(condition)  ((condition) ? ( (void) 0) : throw(ErrorAssert(#condition,__FILE__, __LINE__)))
+//#define AFAIRE(str) ( (cerr << " TO be Done " << str << endl), throw(ErrorAssert("AFAIRE)/TO DO  (FH????",__FILE__, __LINE__))) 
+#define AFAIRE(cmm) ( cerr << "FH: A Faire/ To Do  "<< cmm << " file " << __FILE__<< " line "<< __LINE__ << endl, InternalError(cmm))
+
+#define InternalError(message) throw(ErrorInternal(message,__LINE__,__FILE__))
+#endif
