diff --git a/Geo/MElement.h b/Geo/MElement.h
index 0d8bdc168eb54fa49eb29d6fa72e21fad80f1756..248a3d3929235c2d4abe78d9df15dc5eefff70d1 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -347,6 +347,24 @@ class MTriangle6 : public MTriangle {
   }
 };
 
+struct compareMTriangleLexicographic
+{
+  bool operator () ( MTriangle *t1 , MTriangle *t2 ) const
+  {
+    MVertex *_v1[3] = {t1->getVertex(0),t1->getVertex(1),t1->getVertex(2)};
+    MVertex *_v2[3] = {t2->getVertex(0),t2->getVertex(1),t2->getVertex(2)};
+    std::sort(_v1,_v1+3);
+    std::sort(_v2,_v2+3);
+    if (_v1[0] < _v2[0]) return true;
+    if (_v1[0] > _v2[0]) return false;
+    if (_v1[1] < _v2[1]) return true;
+    if (_v1[1] > _v2[1]) return false;
+    if (_v1[2] < _v2[2]) return true;
+    return false;
+  }
+};
+
+
 class MQuadrangle : public MElement {
  protected:
   MVertex *_v[4];
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 2ae5a72370c33828d1092a584c9565d5f4fbeefa..6c729257e3297befe70af72db97abb375b88eac5 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFace.cpp,v 1.48 2007-01-16 11:31:41 geuzaine Exp $
+// $Id: meshGFace.cpp,v 1.49 2007-01-16 14:19:31 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -314,7 +314,8 @@ void RefineMesh ( GFace *gf, BDS_Mesh &m , const int NIT)
 	      double lone = NewGetLc ( *it);
 
 	      const double coord = 0.5;
-	      if (lone < 1.e-12 && computeParametricEdgeLength((*it)->p1,(*it)->p2) > 1.e-5) lone = 2;
+	      // take care with seams :
+	      if (lone < 1.e-10 && computeParametricEdgeLength((*it)->p1,(*it)->p2) > 1.e-5) lone = 2;
 	      if ((*it)->numfaces() == 2 && (lone >  1.3))
 		{
 		  BDS_Point *mid ;
@@ -364,7 +365,7 @@ void RefineMesh ( GFace *gf, BDS_Mesh &m , const int NIT)
 	{
 	  if (NN2++ >= NN1)break;
 	  double lone = NewGetLc ( *it);
-	  if (lone < 1.e-12 && computeParametricEdgeLength((*it)->p1,(*it)->p2) > 1.e-5) lone = 2;
+	  if (lone < 1.e-10 && computeParametricEdgeLength((*it)->p1,(*it)->p2) > 1.e-5) lone = 2;
 
 	  if (!(*it)->deleted && (*it)->numfaces() == 2 && lone < 0.6 )
 	    {
@@ -920,6 +921,9 @@ bool buildConsecutiveListOfVertices (  GFace *gf,
      std::vector<SPoint2> mesh1d_seam;
 
      bool seam = ges.ge->isSeam(gf);
+     
+     printf("face %d edge %d seam %d (%d %d)\n",gf->tag(),ges.ge->tag(),seam,ges.ge->getBeginVertex()->tag(),ges.ge->getEndVertex()->tag());
+     
      Range<double> range = ges.ge->parBounds(0);
 
      MVertex *here = ges.ge->getBeginVertex()->mesh_vertices[0];
@@ -1196,6 +1200,9 @@ bool gmsh2DMeshGeneratorPeriodic ( GFace *gf )
   free (doc.points);
   free (doc.delaunay);
 
+  char name[245];
+  sprintf(name,"param%d.pos",gf->tag());
+  outputScalarField(m->triangles, name,1);
 
  
   // Recover the boundary edges
@@ -1332,7 +1339,12 @@ bool gmsh2DMeshGeneratorPeriodic ( GFace *gf )
 	    MVertex *v2 = recover_map[n[1]];
 	    MVertex *v3 = recover_map[n[2]];
 	    if (!n[3])
-	      gf->triangles.push_back(new MTriangle (v1,v2,v3) );	
+	      {
+		// when a singular point is present, degenerated triangles may be created,
+		// for example on a sphere that contains one pole 
+		if (v1 != v2 && v1 != v3 && v2 != v3)
+		  gf->triangles.push_back(new MTriangle (v1,v2,v3) );	
+	      }
 	    else
 	      {
 		MVertex *v4 = recover_map[n[3]];
@@ -1345,9 +1357,6 @@ bool gmsh2DMeshGeneratorPeriodic ( GFace *gf )
   
   
   // delete the mesh
-  //    char name[245];
-    //   sprintf(name,"param%d.pos",gf->tag());
-   //outputScalarField(m->triangles, name,1);
    //    sprintf(name,"real%d.pos",gf->tag());
     //outputScalarField(m->triangles, name,0);
 
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index 2beeccc3e4c80645c33138b44de8fb6f52f73967..0b28eed08c8e51b1ef60b167abb1cb040300b1f1 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGRegion.cpp,v 1.23 2007-01-16 11:31:42 geuzaine Exp $
+// $Id: meshGRegion.cpp,v 1.24 2007-01-16 14:19:31 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -111,7 +111,9 @@ void buildTetgenStructure(GRegion *gr, tetgenio &in, std::vector<MVertex*> &numb
   }   
 }
 
-void TransferTetgenMesh(GRegion *gr, tetgenio &in, tetgenio &out, 
+void TransferTetgenMesh(GRegion *gr, 
+			tetgenio &in, 
+			tetgenio &out, 
 			std::vector<MVertex*> &numberedV)
 {
   for(int i = numberedV.size(); i < out.numberofpoints; i++){
@@ -439,10 +441,13 @@ void meshGRegion::operator() (GRegion *gr)
   Msg(STATUS2, "Meshing volume %d", gr->tag());
 
   // destroy the mesh if it exists
-  deMeshGRegion dem;
-  dem(gr);
-
-  if(MeshTransfiniteVolume(gr)) return;
+  if(gr->meshAttributes.Method == TRANSFINI)
+    {
+      deMeshGRegion dem;
+      dem(gr);
+      MeshTransfiniteVolume(gr);
+      return;
+    }
 
   std::list<GFace*> faces = gr->faces();
 
@@ -458,9 +463,15 @@ void meshGRegion::operator() (GRegion *gr)
 #if !defined(HAVE_TETGEN)
     Msg(GERROR, "Tetgen is not compiled in this version of Gmsh");
 #else
-    // put all the faces in the same model
+    // delete the mesh for all regions
     GModel::riter rit = gr->model()->firstRegion() ;
     if (gr != *rit)return;    
+    for (; rit != gr->model()->lastRegion();++rit)
+      {
+	deMeshGRegion dem;
+	dem(*rit);
+      }
+    // put all the faces in the same model
     std::list<GFace*> allFaces;
     GModel::fiter fit = gr->model()->firstFace() ;
     while (fit != gr->model()->lastFace()){
@@ -476,14 +487,24 @@ void meshGRegion::operator() (GRegion *gr)
     sprintf(opts, "pe%c", (CTX.verbosity < 3) ? 'Q': (CTX.verbosity > 6)? 'V': '\0');
     tetrahedralize(opts, &in, &out);
     TransferTetgenMesh(gr, in, out, numberedV);
+    // sort triangles in all model faces in order to be able to search in vectors
+    {
+      std::list<GFace*>::iterator itf =  allFaces.begin();
+      while(itf!=allFaces.end())
+	{
+	  compareMTriangleLexicographic cmp;
+	  std::sort((*itf)->triangles.begin(),
+		    (*itf)->triangles.end(),
+		    cmp);
+	  ++itf;
+	}
+    }
 
-    // FIXME: all the volume nodes+tets now belong to the first
-    // region--we need to recategorize them into each separate region
+    // restore the initial set of faces
+    gr->set(faces);
 
     // now do insertion of points
     insertVerticesInRegion(gr); 
-    // restore the initial set of faces
-    gr->set(faces);
     //    meshNormalsPointOutOfTheRegion(gr);
 #endif
   }
@@ -492,6 +513,8 @@ void meshGRegion::operator() (GRegion *gr)
 #if !defined(HAVE_NETGEN)
     Msg(GERROR, "Netgen is not compiled in this version of Gmsh");
 #else
+    deMeshGRegion dem;
+    dem(gr);
     // orient the triangles of with respect to this region
     meshNormalsPointOutOfTheRegion(gr);
     std::vector<MVertex*> numberedV;
diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp
index aec76e24f8adb9bbce9d317346cf2697ec842a09..6684fedca997df6f767a074023b857631f86f755 100644
--- a/Mesh/meshGRegionDelaunayInsertion.cpp
+++ b/Mesh/meshGRegionDelaunayInsertion.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGRegionDelaunayInsertion.cpp,v 1.10 2007-01-12 13:16:59 remacle Exp $
+// $Id: meshGRegionDelaunayInsertion.cpp,v 1.11 2007-01-16 14:19:31 remacle Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -21,6 +21,7 @@
 
 #include "BackgroundMesh.h"
 #include "meshGRegionDelaunayInsertion.h"
+#include "GModel.h"
 #include "GRegion.h"
 #include "Numeric.h"
 #include "Message.h"
@@ -38,7 +39,7 @@ int MTet4::inCircumSphere ( const double *p ) const
   return (result > 0) ? 1 : 0;
 }
 
-int faces[4][3] = {{0,1,2},{0,2,3},{0,1,3},{1,2,3}};
+static int faces[4][3] = {{0,1,2},{0,2,3},{0,1,3},{1,2,3}};
 
 struct faceXtet
 {
@@ -116,10 +117,10 @@ void recurFindCavity ( std::list<faceXtet> & shell,
       MTet4 *neigh =  t->getNeigh(i) ;
       if (!neigh)
 	  shell.push_back ( faceXtet ( t, i ) );
-      else  if (!neigh->isDeleted())
+      else  if (!neigh->isDeleted() )
 	{
 	  int circ =  neigh->inCircumSphere ( v );
-	  if (circ)
+	  if (circ && (neigh->onWhat() == t->onWhat()))
 	    recurFindCavity ( shell, cavity,v , neigh);
 	  else
 	    shell.push_back ( faceXtet ( t, i ) );
@@ -203,10 +204,10 @@ bool insertVertex (MVertex *v ,
 
   while (it != shell.end())
     {
-      MTetrahedron *t = new MTetrahedron ( it->v[0],
-					   it->v[1],
-					   it->v[2],
-					   v);
+      MTetrahedron *tr = new MTetrahedron ( it->v[0],
+					    it->v[1],
+					    it->v[2],
+					    v);
       //      Msg(INFO,"shell %d %d %d",it->v[0]->getNum(),it->v[1]->getNum(),it->v[2]->getNum());
 //            fprintf(ff,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {0,0,0};\n",
 // 		   it->v[0]->x(),
@@ -219,7 +220,8 @@ bool insertVertex (MVertex *v ,
 // 		   it->v[2]->y(),
 // 		   it->v[2]->z());
       
-      MTet4 *t4 = new MTet4 ( t , vSizes); 
+      MTet4 *t4 = new MTet4 ( tr , vSizes); 
+      t4->setOnWhat(t->onWhat());
       newTets[k++]=t4;
       // all new tets are pushed front in order to
       // ba able to destroy them if the cavity is not
@@ -297,6 +299,80 @@ static void setLcs ( MTetrahedron *t, std::map<MVertex*,double> &vSizes)
 // }
 
 
+bool find_triangle_in_model ( GModel *model , MTriangle *tri, GFace **gfound)
+{ 
+  GModel::fiter fit = model->firstFace() ;
+  compareMTriangleLexicographic cmp;
+  while (fit != model->lastFace()){
+
+    bool found = binary_search((*fit)->triangles.begin(), 
+			       (*fit)->triangles.end(), 
+			       tri,cmp);
+    if (found )
+      {
+	*gfound = *fit;
+	return true;
+      }
+    ++fit;
+  }
+  return false;
+
+}
+
+GRegion *getRegionFromBoundingFaces (GModel *model, 		      
+				    std::set<GFace *> &faces_bound)
+{
+  GModel::riter git = model->firstRegion() ;
+  while (git != model->lastRegion()){
+
+    std::list <GFace *> _faces = (*git)->faces();
+    if (_faces.size() == faces_bound.size())
+      {
+	bool ok = true;
+	for (std::list <GFace *>::iterator it = _faces.begin();it != _faces.end();++it)
+	  {
+	    if (faces_bound.find (*it) == faces_bound.end())ok = false;
+	  }
+	if (ok)return *git;
+      }    
+    ++git;
+  }
+  return 0;
+}
+
+ 
+void recur_classify ( MTet4 *t ,
+		      std::set<MTet4*,compareTet4Ptr> &theRegion,		      
+		      std::set<GFace *> &faces_bound,
+		      GRegion *bidon ,
+		      GModel *model)
+{
+  if (!t) Msg (GERROR,"a tet is not connected by a boundary face");
+  if (t->onWhat())return;
+  theRegion.insert(t);
+  t->setOnWhat(bidon);
+  
+  for (int i=0;i<4;i++)
+    {
+      MTriangle tri ( t->tet()->getVertex ( faces[i][0] ),
+		      t->tet()->getVertex ( faces[i][1] ),
+		      t->tet()->getVertex ( faces[i][2] ) );
+      GFace     *gfound;
+      bool found = find_triangle_in_model ( model , &tri, &gfound);
+
+      //      Msg(INFO,"found ? %d",found);
+      if (found)
+	{
+	  faces_bound.insert(gfound);	  
+	}
+      else
+	{
+	  recur_classify ( t->getNeigh(i) , theRegion, faces_bound, bidon, model );
+	}
+    }
+
+}
+
 void insertVerticesInRegion (GRegion *gr) 
 {
 
@@ -319,6 +395,23 @@ void insertVerticesInRegion (GRegion *gr)
   gr->tetrahedra.clear();
   connectTets ( allTets.begin(), allTets.end() );      
 
+  // classify the tets on the right region
+  Msg (INFO,"reclassifying %d tets",allTets.size());
+  for (std::set<MTet4*,compareTet4Ptr>::iterator it = allTets.begin();it!=allTets.end();++it)
+    {
+      if (!(*it)->onWhat())
+	{
+	  std::set<MTet4*,compareTet4Ptr> theRegion;
+	  std::set<GFace *> faces_bound;
+	  GRegion *bidon;
+	  recur_classify ( *it , theRegion, faces_bound, bidon , gr->model());
+	  GRegion *myGRegion = getRegionFromBoundingFaces (gr->model() , faces_bound ); 
+	  Msg (INFO,"found a region with %d tets %p",theRegion.size(),myGRegion);
+	  for (std::set<MTet4*,compareTet4Ptr>::iterator it2 = theRegion.begin();it2!=theRegion.end();++it2)(*it2)->setOnWhat(myGRegion);
+	}
+    }
+
+
   Msg(DEBUG,"All %d tets were connected",allTets.size());
 
   // here the classification should be done
@@ -389,7 +482,7 @@ void insertVerticesInRegion (GRegion *gr)
 	}
       else
 	{
-	  gr->tetrahedra.push_back(worst->tet());
+	  worst->onWhat()->tetrahedra.push_back(worst->tet());
 	}
       delete worst;
       allTets.erase(allTets.begin());      
diff --git a/Mesh/meshGRegionDelaunayInsertion.h b/Mesh/meshGRegionDelaunayInsertion.h
index 24a1e821c6a724468e8967ffd33d5947e1299723..313f2609f618314f9bb416ab51234c2b441b10ff 100644
--- a/Mesh/meshGRegionDelaunayInsertion.h
+++ b/Mesh/meshGRegionDelaunayInsertion.h
@@ -32,13 +32,18 @@ class MTet4
   double circum_radius;
   MTetrahedron *base;
   MTet4 *neigh[4];
+  GRegion *gr;
  public :
+
+  inline GRegion * onWhat () const {return gr;}
+  inline void      setOnWhat (GRegion *g) {gr=g;}
   
   bool isDeleted () const {return deleted;}
   void   forceRadius (double r){circum_radius=r;}
   double getRadius ()const {return circum_radius;}
   
-  MTet4 ( MTetrahedron * t, std::vector<double> & sizes) : deleted(false), base (t)
+
+  MTet4 ( MTetrahedron * t, std::vector<double> & sizes) : deleted(false), base (t), gr(0)
   {
     neigh[0] = neigh[1] = neigh[2] = neigh[3] = 0;
     double center[3];