diff --git a/Mesh/CenterlineField.cpp b/Mesh/CenterlineField.cpp
index 41dac287f5deac19d81462afe135a4f73049e1b4..e5b892c86f0bb6b9738d9de0ab45b4f8da3a13fe 100644
--- a/Mesh/CenterlineField.cpp
+++ b/Mesh/CenterlineField.cpp
@@ -19,12 +19,12 @@
 #include "OS.h"
 #include "GModel.h"
 #include "MElement.h"
+#include "MTriangle.h"
 #include "MVertex.h"
 #include "MLine.h"
 #include "GEntity.h"
 #include "Field.h"
 #include "GFace.h"
-#include "Integration3D.h"
 
 #if defined(HAVE_ANN)
 #include <ANN/ANN.h>
@@ -44,7 +44,48 @@ double computeLength(std::vector<MLine*> lines){
   return length;
 }
 
-void orderMLines(std::vector<MLine*> &lines) { //, std::set<MVertex*> & junctions, MVertex *vB, MVertex *vE){
+bool isClosed(std::set<MEdge, Less_Edge> &theCut){
+
+  std::multiset<MVertex*> boundV;
+  std::set<MEdge,Less_Edge>::iterator it = theCut.begin();
+  for (; it!= theCut.end(); it++){
+    boundV.insert(it->getVertex(0));
+    boundV.insert(it->getVertex(1));
+  }
+  std::multiset<MVertex*>::iterator itb = boundV.begin();
+  for ( ; itb != boundV.end(); ++itb){
+    if (boundV.count(*itb) != 2) {
+      return false;
+    }
+  }
+  return true;
+
+  // std::list<MEdge> segments;
+  // std::map<MVertex*, MEdge> boundv;
+  // std::set<MEdge,Less_Edge>::iterator it = theCut.begin();
+  // for (; it!= theCut.end(); it++){
+  //   segments.push_back(*it);
+  // }
+
+  // // find a lonely MEdge
+  // for (std::list<MEdge>::iterator it = segments.begin(); 
+  //      it != segments.end(); ++it){
+  //   MVertex *vL = it->getVertex(0);
+  //   MVertex *vR = it->getVertex(1);
+  //   std::map<MVertex*,MEdge>::iterator it1 = boundv.find(vL);
+  //   if (it1 == boundv.end()) boundv.insert(std::make_pair(vL,*it));
+  //   else  boundv.erase(it1);
+  //   std::map<MVertex*,MEdge>::iterator it2 = boundv.find(vR);
+  //   if (it2 == boundv.end()) boundv.insert(std::make_pair(vR,*it));
+  //   else boundv.erase(it2);
+  // }
+
+  // if (boundv.size() == 0) return true; 
+  // else return false;
+
+}
+
+void orderMLines(std::vector<MLine*> &lines, MVertex *vB, MVertex *vE){
 
   std::vector<MLine*> _m;
   std::list<MLine*> segments;
@@ -72,7 +113,13 @@ void orderMLines(std::vector<MLine*> &lines) { //, std::set<MVertex*> & junction
   // find the first MLine and erase it from the list segments
   MLine *firstLine;
   if (boundv.size() == 2){   // non periodic
-    firstLine = (boundv.begin())->second;
+    MVertex *v = (boundv.begin())->first;
+    if ( v == vB) firstLine = (boundv.begin())->second;
+    else{
+      MVertex *v = (boundv.rbegin())->first;
+      if (v == vB) firstLine = (boundv.rbegin())->second;
+      else{ Msg::Error("begin vertex not found for branch"); exit(1);}
+    }
     for (std::list<MLine*>::iterator it = segments.begin(); 
          it != segments.end(); ++it){
       if (*it == firstLine){
@@ -81,13 +128,8 @@ void orderMLines(std::vector<MLine*> &lines) { //, std::set<MVertex*> & junction
       }
     }
   }
-  else if (boundv.size() == 0){ // periodic
-    firstLine = *(segments.begin());
-    segments.erase(segments.begin());
-  }
   else{
-    Msg::Error("line is wrong (it has %d end points)", 
-               boundv.size());
+    Msg::Error("line is wrong (it has %d end points)",  boundv.size());
   }
 
   // loop over all segments to order segments and store it in the list _m
@@ -152,6 +194,92 @@ void orderMLines(std::vector<MLine*> &lines) { //, std::set<MVertex*> & junction
   // printf("in order vB= %d =%d \n", vB->getNum(), vE->getNum());
 }
 
+void cutTriangle(MTriangle *tri, 
+		 std::map<MEdge,MVertex*,Less_Edge> &cutEdges, 
+		 std::set<MVertex*> &cutVertices,
+		 std::vector<MTriangle*> &newTris, 
+		 std::set<MEdge,Less_Edge> &newCut){
+
+  MVertex *c[3] = {0,0,0};
+  for (int j=0;j<3;j++){
+    MEdge ed = tri->getEdge(j); 
+    std::map<MEdge,MVertex*,Less_Edge> :: iterator it = cutEdges.find(ed);
+    if (it != cutEdges.end()){
+      c[j] = it->second;
+    }
+  }
+  if (c[0] && c[1]){
+    newTris.push_back(new MTriangle (c[0],tri->getVertex(1),c[1]));
+    newTris.push_back(new MTriangle (tri->getVertex(0),c[0],tri->getVertex(2)));
+    newTris.push_back(new MTriangle (tri->getVertex(2),c[0],c[1]));
+    newCut.insert(MEdge(c[0],c[1]));
+  }
+  else if (c[0] && c[2]){
+    newTris.push_back(new MTriangle (tri->getVertex(0),c[0],c[2]));
+    newTris.push_back(new MTriangle (c[0],tri->getVertex(1),tri->getVertex(2)));
+    newTris.push_back(new MTriangle (tri->getVertex(2),c[2],c[0]));
+    newCut.insert(MEdge(c[0],c[2]));
+  }
+  else if (c[1] && c[2]){
+    newTris.push_back(new MTriangle (tri->getVertex(2),c[2],c[1]));
+    newTris.push_back(new MTriangle (tri->getVertex(0),tri->getVertex(1),c[2]));
+    newTris.push_back(new MTriangle (c[2],tri->getVertex(1),c[1]));
+    newCut.insert(MEdge(c[1],c[2]));
+  }
+  else if (c[0]){
+    newTris.push_back(new MTriangle (tri->getVertex(0),c[0],tri->getVertex(2)));
+    newTris.push_back(new MTriangle (tri->getVertex(2),c[0],tri->getVertex(1)));
+    if (cutVertices.find (tri->getVertex(0)) != cutVertices.end()){
+      newCut.insert(MEdge(c[0],tri->getVertex(0)));
+    }
+    else if (cutVertices.find (tri->getVertex(1)) != cutVertices.end()) {
+      newCut.insert(MEdge(c[0],tri->getVertex(1)));
+    }
+    else{
+      newCut.insert(MEdge(c[0],tri->getVertex(2)));
+    }
+  }
+  else if (c[1]){
+    newTris.push_back(new MTriangle (tri->getVertex(1),c[1],tri->getVertex(0)));
+    newTris.push_back(new MTriangle (tri->getVertex(0),c[1],tri->getVertex(2)));
+    if (cutVertices.find (tri->getVertex(0)) != cutVertices.end()){
+      newCut.insert(MEdge(c[1],tri->getVertex(0)));
+    }
+    else if (cutVertices.find (tri->getVertex(1)) != cutVertices.end()) {
+      newCut.insert(MEdge(c[1],tri->getVertex(1)));
+    }
+    else{
+      newCut.insert(MEdge(c[1],tri->getVertex(2)));
+    }
+  }
+  else if (c[2]){
+    newTris.push_back(new MTriangle (tri->getVertex(0),tri->getVertex(1), c[2]));
+    newTris.push_back(new MTriangle (tri->getVertex(1),tri->getVertex(2), c[2]));
+    if (cutVertices.find (tri->getVertex(0)) != cutVertices.end()){
+      newCut.insert(MEdge(c[2],tri->getVertex(0)));
+    }
+    else if (cutVertices.find (tri->getVertex(1)) != cutVertices.end()) {
+      newCut.insert(MEdge(c[2],tri->getVertex(1)));
+    }
+    else{
+      newCut.insert(MEdge(c[2],tri->getVertex(2)));
+    }
+  }
+  else {
+    newTris.push_back(tri);
+    if (cutVertices.find (tri->getVertex(0)) != cutVertices.end() &&
+	cutVertices.find (tri->getVertex(1)) != cutVertices.end())
+      newCut.insert(MEdge(tri->getVertex(0),tri->getVertex(1)));
+    if (cutVertices.find (tri->getVertex(0)) != cutVertices.end() &&
+	cutVertices.find (tri->getVertex(1)) != cutVertices.end())
+      newCut.insert(MEdge(tri->getVertex(0),tri->getVertex(2)));
+    if (cutVertices.find (tri->getVertex(2)) != cutVertices.end() &&
+	cutVertices.find (tri->getVertex(1)) != cutVertices.end())
+      newCut.insert(MEdge(tri->getVertex(2),tri->getVertex(1)));
+  }
+
+}
+
 Centerline::Centerline(std::string fileName): kdtree(0), nodes(0){
 
   index = new ANNidx[1];
@@ -186,7 +314,17 @@ void Centerline::importFile(std::string fileName){
   std::vector<GEntity*> entities ;
   current->getEntities(entities) ; 
   for(unsigned int i = 0; i < entities.size(); i++){
-    if(entities[i]->dim() == 2) surfaces.push_back((GFace*)entities[i]);
+    if(entities[i]->dim() != 2) continue; 
+    for(int j = 0; j < entities[i]->getNumMeshElements(); j++){ 
+      MElement *e = entities[i]->getMeshElement(j);
+      if (e->getType() != TYPE_TRI){
+  	Msg::Error("Centerline split only implemented for tri meshes so far ..."); 
+  	exit(1);
+      }
+      else{
+	triangles.push_back((MTriangle*)e);
+      }	
+    }
   }
   entities.clear();
 
@@ -300,7 +438,7 @@ void Centerline::createBranches(int maxN){
 	else itl++;
       }
       if (vB == vE) { Msg::Error("Begin and end points branch are the same \n");break;}
-      orderMLines(myLines); 
+      orderMLines(myLines, vB, vE); 
       std::vector<Branch> children;
       Branch newBranch ={ tag++, myLines, computeLength(myLines), vB, vE, children, 1.e6, 0.0};
       //printf("branch = %d VB = %d VE %d \n", myLines.size(), vB->getNum(), vE->getNum());
@@ -308,7 +446,7 @@ void Centerline::createBranches(int maxN){
     }
   }
   printf("in/outlets =%d branches =%d \n", color_edges.size(), edges.size());
-
+  
   //create children
   for(unsigned int i = 0; i < edges.size(); ++i) {
     MVertex *vE = edges[i].vE;
@@ -342,48 +480,83 @@ void Centerline::createBranches(int maxN){
 void Centerline::distanceToLines(){
   Msg::Info("Centerline: computing distance to lines ");
 
-  //EMI TO DO DO THIS WITH ANN !
-  //MUCH FASTER
-
-  std::vector<SPoint3> pts;
-  std::set<SPoint3> pts_set;
-  std::vector<double> distances;
-  std::vector<double> distancesE;
-  std::vector<SPoint3> closePts;
-
-  for(unsigned int i = 0; i < surfaces.size(); i++){ 
-    for(int j = 0; j < surfaces[i]->getNumMeshElements(); j++){ 
-      MElement *e = surfaces[i]->getMeshElement(j);
-      for (int k = 0; k < e->getNumVertices(); k++){
-	MVertex *v = e->getVertex(k);
-	pts_set.insert(SPoint3(v->x(), v->y(),v->z()));
-      }
-    }
+  //SOLUTION 1: REVERSE ANN TREE (SURFACE POINTS IN TREE)
+  ANNkd_tree *kdtreeR; 
+  ANNpointArray nodesR;
+  ANNidxArray indexR = new ANNidx[1];
+  ANNdistArray distR = new ANNdist[1];
+
+  std::set<MVertex*> allVS; 
+  for(int j = 0; j < triangles.size(); j++)
+    for(int k = 0; k<3; k++) allVS.insert(triangles[j]->getVertex(k));
+  
+  int nbSNodes = allVS.size();
+  nodesR = annAllocPts(nbSNodes, 3);
+  int ind = 0;
+  std::set<MVertex*>::iterator itp = allVS.begin();
+  while (itp != allVS.end()){
+    MVertex *v = *itp;
+    nodesR[ind][0] = v->x(); 
+    nodesR[ind][1] = v->y(); 
+    nodesR[ind][2] = v->z(); 
+    itp++; ind++;
   }
-  std::set<SPoint3>::iterator its =  pts_set.begin();
-  for (; its != pts_set.end(); its++){
-    pts.push_back(*its);
-  } 
-  if (pts.size() == 0) {Msg::Error("Centerline needs a GModel with a surface \n"); exit(1);}
- 
+  kdtreeR = new ANNkd_tree(nodesR, nbSNodes, 3);
+
   for(unsigned int i = 0; i < lines.size(); i++){
-    std::vector<double> iDistances;
-    std::vector<SPoint3> iClosePts;
-    std::vector<double> iDistancesE;
     MLine *l = lines[i];
     MVertex *v1 = l->getVertex(0);
     MVertex *v2 = l->getVertex(1);
-    SPoint3 p1(v1->x(), v1->y(), v1->z());
-    SPoint3 p2(v2->x(), v2->y(), v2->z());
-    signedDistancesPointsLine(iDistances, iClosePts, pts, p1,p2);
-
-    double minRad = std::abs(iDistances[0]);
-    for (unsigned int kk = 1; kk< pts.size(); kk++) {
-      if (std::abs(iDistances[kk]) < minRad)
-	minRad = std::abs(iDistances[kk]);
-    }
+    double midp[3] = {0.5*(v1->x()+v2->x()), 0.5*(v1->y()+v1->y()),0.5*(v1->z()+v2->z())};
+    kdtreeR->annkSearch(midp, 1, indexR, distR);
+    double minRad = sqrt(distR[0]);
     radiusl.insert(std::make_pair(lines[i], minRad)); 
   }
+  delete kdtreeR;
+  annDeallocPts(nodesR);
+  delete[]indexR;
+  delete[]distR;
+  
+  // //SOLUTION 2: DISTANCE TO LINES (QUITE SLOW)
+  // std::vector<SPoint3> pts;
+  // std::set<SPoint3> pts_set;
+  // std::vector<double> distances;
+  // std::vector<double> distancesE;
+  // std::vector<SPoint3> closePts;
+
+  // for(unsigned int i = 0; i < surfaces.size(); i++){ 
+  //   for(int j = 0; j < surfaces[i]->getNumMeshElements(); j++){ 
+  //     MElement *e = surfaces[i]->getMeshElement(j);
+  //     for (int k = 0; k < e->getNumVertices(); k++){
+  // 	MVertex *v = e->getVertex(k);
+  // 	pts_set.insert(SPoint3(v->x(), v->y(),v->z()));
+  //     }
+  //   }
+  // }
+  // std::set<SPoint3>::iterator its =  pts_set.begin();
+  // for (; its != pts_set.end(); its++){
+  //   pts.push_back(*its);
+  // } 
+  // if (pts.size() == 0) {Msg::Error("Centerline needs a GModel with a surface \n"); exit(1);}
+ 
+  // for(unsigned int i = 0; i < lines.size(); i++){
+  //   std::vector<double> iDistances;
+  //   std::vector<SPoint3> iClosePts;
+  //   std::vector<double> iDistancesE;
+  //   MLine *l = lines[i];
+  //   MVertex *v1 = l->getVertex(0);
+  //   MVertex *v2 = l->getVertex(1);
+  //   SPoint3 p1(v1->x(), v1->y(), v1->z());
+  //   SPoint3 p2(v2->x(), v2->y(), v2->z());
+  //   signedDistancesPointsLine(iDistances, iClosePts, pts, p1,p2);
+
+  //   double minRad = std::abs(iDistances[0]);
+  //   for (unsigned int kk = 1; kk< pts.size(); kk++) {
+  //     if (std::abs(iDistances[kk]) < minRad)
+  // 	minRad = std::abs(iDistances[kk]);
+  //   }
+  //   radiusl.insert(std::make_pair(lines[i], minRad)); 
+  // }
      
 }
 void Centerline::computeRadii(){
@@ -448,96 +621,178 @@ void Centerline::buildKdTree(){
 
 void Centerline::splitMesh(){
 
-  Msg::Info("Splitting surface mesh with centerline field ");
-
- for(unsigned int i = 0; i < edges.size(); ++i){
-   std::vector<MLine*> lines = edges[i].lines;
-   MVertex *v1 = edges[i].vE;
-   MVertex *v2;
-   SPoint3 pt(v1->x(), v1->y(), v1->z());
-   if (lines[0]->getVertex(0) == v1) v2 = lines[0]->getVertex(1);
-   else if (lines[0]->getVertex(1) == v1) v2 = lines[0]->getVertex(0);
-   else if (lines.back()->getVertex(0) == v1) v2 = lines.back()->getVertex(1);
-   else if (lines.back()->getVertex(1) == v1) v2 = lines.back()->getVertex(0);
-   SVector3 dir(v2->x()-v1->x(),v2->y()-v1->y(),v2->z()-v1->z());
-   if(edges[i].children.size() > 0.0){
-     cutByDisk(pt, dir, 1.2*edges[i].maxRad);
-   }
+  Msg::Info("Splitting surface mesh (%d tris) with centerline field ", triangles.size());
+
+  for(unsigned int i = 0; i < edges.size(); i++){
+    printf("*** branch =%d \n", i);
+    std::vector<MLine*> lines = edges[i].lines;
+    double L = edges[i].length;
+    double R = edges[i].maxRad;
+    if(edges[i].children.size() > 0.0 && L/R > 1.5){
+      MVertex *v1 = lines[lines.size()-1]->getVertex(1);//end vertex
+      MVertex *v2;
+      if(L/R < 2.0) v2 = lines[0]->getVertex(0);
+      else if (lines.size() > 4) v2 = lines[lines.size()-4]->getVertex(0);
+      else v2 = lines[lines.size()-1]->getVertex(0);
+      SVector3 pt(v1->x(), v1->y(), v1->z());
+      SVector3 dir(v2->x()-v1->x(),v2->y()-v1->y(),v2->z()-v1->z());
+      cutByDisk(pt, dir, edges[i].maxRad);
+    }
  }
 
+  FILE * f2 = fopen("myCUT.pos","w");
+  fprintf(f2, "View \"\"{\n");
+  std::set<MEdge,Less_Edge>::iterator itp =  theCut.begin();
+   while (itp != theCut.end()){
+     MEdge l = *itp;
+     fprintf(f2, "SL(%g,%g,%g,%g,%g,%g){%g,%g};\n",
+              l.getVertex(0)->x(), l.getVertex(0)->y(), l.getVertex(0)->z(),
+              l.getVertex(1)->x(), l.getVertex(1)->y(), l.getVertex(1)->z(),
+              1.0,1.0);
+     itp++; 
+  }
+  //  for (int i= 0; i< triangles.size(); i++){
+  //    MTriangle *t = triangles[i];
+  //    fprintf(f2, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n",
+  //             t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(),
+  //             t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(),
+  //             t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(),
+  //             1.0,1.0,1.0);
+  // }
+  fprintf(f2,"};\n");
+  fclose(f2);
+
+  Msg::Info("Splitting mesh by centerlines done ");
+
 }
 
-void Centerline::cutByDisk(SPoint3 pt, SVector3 norm, double rad){
-  
-  printf("Cutting disk centered at pt  %g %g %g dir %g %g %g \n", pt.x(), pt.y(), pt.z(), norm.x(), norm.y(), norm.z());
-  double a = norm.x();
-  double b = norm.y();
-  double c = norm.z();
-  double d = -a * pt[0] - b * pt[1] - c * pt[2];
-  printf("Plane = %g %g %g %g \n", a, b, c, d);
-  //ls = a * x + b * y + c * z + d;
-
-  //variables for using the cutting tools
-  std::vector<DI_Line *> lines;
-  std::vector<DI_Triangle *> triangles;
-  std::vector<DI_Quad *> quads;
-  DI_Point::Container cp;//cut points
-  std::vector<DI_IntegrationPoint *> ipV;//integration points vol
-  std::vector<DI_IntegrationPoint *> ipS;//integration points surf
-  bool isCut = false;
-  int integOrder = 1;
-  int recur = 0;
-  gLevelset *GLS = new gLevelsetPlane(0., 0., 0., 0.);
-  std::vector<gLevelset *> RPN;
-  RPN.push_back(GLS);
-
-  //loop over all surface mesh elements
-  for(unsigned int i = 0; i < surfaces.size(); i++){ 
-    for(int j = 0; j < surfaces[i]->getNumMeshElements(); j++){ 
-      MElement *e = surfaces[i]->getMeshElement(j);
-      if (e->getNumVertices() != 3){
-  	Msg::Error("Centerline split only implemented for tri meshes so far ..."); 
-  	exit(1);
-      }
-      int nbV = e->getNumVertices();
-
-      double **nodeLs= new double*[nbV];
-      DI_Triangle T(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
-  		    e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
-  		    e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z());
-      SPoint3 cg(0.333*(e->getVertex(0)->x()+e->getVertex(1)->x()+e->getVertex(2)->x()), 
-  		 0.333*(e->getVertex(0)->y()+e->getVertex(1)->y()+e->getVertex(2)->y()),
-  		 0.333*(e->getVertex(0)->z()+e->getVertex(1)->z()+e->getVertex(2)->z()));
-      T.setPolynomialOrder(1);
-      double x0 = e->getVertex(0)->x(), y0= e->getVertex(0)->y(), z0=e->getVertex(0)->z();
-      double val0 = a * x0 + b * y0 + c * z0 + d;
-      double sign0 = val0;
-      bool zeroElem = false;
-      nodeLs[0] = new double[1];//one ls value
-      nodeLs[0][0]= val0;
-      for(int i=1;i<nbV;i++){
-	double x = e->getVertex(i)->x(), y= e->getVertex(i)->y(), z=e->getVertex(i)->z();
-  	double val = a * x + b * y + c * z + d;
-    	double sign = sign0*val;
-  	if (sign < 0.0 && !zeroElem) zeroElem = true;
-  	nodeLs[i] = new double[1];//one ls value
-	nodeLs[i][0]= val;
-      }
-      if (zeroElem){
-  	double radius = sqrt((cg.x()-pt.x())*(cg.x()-pt.x())+(cg.y()-pt.y())*(cg.y()-pt.y())+(cg.z()-pt.z())*(cg.z()-pt.z()));
-  	if (radius <  rad){
-      	  isCut = T.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
-      			quads, triangles, lines, recur, nodeLs);
-  	}
+void Centerline::cutByDisk(SVector3 &PT, SVector3 &NORM, double &maxRad){
+   
+  double a = NORM.x();
+  double b = NORM.y();
+  double c = NORM.z();
+  double d = -a * PT.x() - b * PT.y() - c * PT.z();
+  printf("cut disk (R=%g)= %g %g %g %g \n", maxRad, a, b, c, d);
+ 
+  //EMI STUFF
+  const double EPS = 0.001;
+  std::set<MEdge,Less_Edge> allEdges;
+  for(unsigned int i = 0; i < triangles.size(); i++){ 
+    for ( unsigned int j= 0; j <  3; j++)
+      allEdges.insert(triangles[i]->getEdge(j)); 
+  }
+  bool closedCut = false;
+  int step = 0;
+  while (!closedCut && step < 10){
+    double rad = 1.3*maxRad+0.15*step*maxRad;
+    //printf("radius(%d) =%g \n", step, rad);
+    std::map<MEdge,MVertex*,Less_Edge> cutEdges;
+    std::set<MVertex*> cutVertices;
+    std::vector<MTriangle*> newTris; 
+    std::set<MEdge,Less_Edge> newCut;
+    cutEdges.clear();
+    cutVertices.clear();
+    newTris.clear();
+    newCut.clear();
+    for (std::set<MEdge,Less_Edge>::iterator it = allEdges.begin();
+	 it != allEdges.end() ; ++it){
+      MEdge me = *it;
+      SVector3 P1(me.getVertex(0)->x(),me.getVertex(0)->y(), me.getVertex(0)->z());
+      SVector3 P2(me.getVertex(1)->x(),me.getVertex(1)->y(), me.getVertex(1)->z());
+      double V1 = a * P1.x() + b * P1.y() + c * P1.z() + d;
+      double V2 = a * P2.x() + b * P2.y() + c * P2.z() + d;
+      bool inters = (V1*V2<0.0) ? true: false;
+      double rdist = -V1/(V2-V1);
+      if (inters && rdist > EPS && rdist < 1.-EPS){
+	SVector3 PZ = P1+rdist*(P2-P1);
+	MVertex *newv = new MVertex (PZ.x(), PZ.y(), PZ.z());
+	if ( norm(PZ-PT) < rad ) cutEdges.insert(std::make_pair(*it,newv));
       }
-      else triangles.push_back(&T);
-
-      for(int i=0;i<nbV;i++) delete nodeLs[i];
-      delete []nodeLs;
+      else if (inters && rdist <= EPS && norm(P1-PT) < rad ) 
+	cutVertices.insert(me.getVertex(0));
+      else if (inters && rdist >= 1.-EPS && norm(P2-PT) < rad) 
+	cutVertices.insert(me.getVertex(1));
+    }
+    for(unsigned int i = 0; i < triangles.size(); i++){ 
+      cutTriangle(triangles[i], cutEdges,cutVertices, newTris, newCut);
+    }
+    if (isClosed(newCut)) {
+      printf("closed cut \n");
+      triangles = newTris;
+      theCut.insert(newCut.begin(),newCut.end());
+      //if (step > 1) printf("YOUPIIIIIIIIIIIIIIIIIIIIIII \n");
+      break;
+    }
+    else {
+      if (step ==9) printf("no closed cut %d \n", newCut.size());
+      step++;
+      // // triangles = newTris;
+      // // theCut.insert(newCut.begin(),newCut.end());
+      // char name[256];
+      // sprintf(name, "myCUT-%d.pos", step);
+      // FILE * f2 = fopen(name,"w");
+      // fprintf(f2, "View \"\"{\n");
+      // std::set<MEdge,Less_Edge>::iterator itp =  newCut.begin();
+      // while (itp != newCut.end()){
+      // 	MEdge l = *itp;
+      // 	fprintf(f2, "SL(%g,%g,%g,%g,%g,%g){%g,%g};\n",
+      // 		  l.getVertex(0)->x(), l.getVertex(0)->y(), l.getVertex(0)->z(),
+      // 		  l.getVertex(1)->x(), l.getVertex(1)->y(), l.getVertex(1)->z(),
+      // 		  1.0,1.0);
+      // 	  itp++; 
+      // 	}
+      // 	fprintf(f2,"};\n");
+      // 	fclose(f2);
     }
   }
 
-  printf("split mesh done \n");
+  // //GAETAN STUFF
+  // //variables for using the cutting tools
+  // DI_Point::Container cp;//cut points
+  // std::vector<DI_IntegrationPoint *> ipV;//integration points vol
+  // std::vector<DI_IntegrationPoint *> ipS;//integration points surf
+  // bool isCut = false;
+  // gLevelset *GLS = new gLevelsetPlane(0., 0., 0., 0.);
+  // std::vector<gLevelset *> RPN;
+  // RPN.push_back(GLS);
+
+  // //loop over all surface mesh elements
+  // for(unsigned int i = 0; i < triangles.size(); i++){ 
+  //   MTriangle *e = triangles[i];
+  //   double **nodeLs= new double*[3];
+  //   DI_Triangle *T = new DI_Triangle(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
+  // 				     e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
+  // 				     e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z());
+  //   SPoint3 cg(0.333*(e->getVertex(0)->x()+e->getVertex(1)->x()+e->getVertex(2)->x()), 
+  // 	       0.333*(e->getVertex(0)->y()+e->getVertex(1)->y()+e->getVertex(2)->y()),
+  // 	       0.333*(e->getVertex(0)->z()+e->getVertex(1)->z()+e->getVertex(2)->z()));
+  //   double x0 = e->getVertex(0)->x(), y0= e->getVertex(0)->y(), z0=e->getVertex(0)->z();
+  //   double val0 = a * x0 + b * y0 + c * z0 + d;
+  //   double sign0 = val0;
+  //   bool zeroElem = false;
+  //   nodeLs[0] = new double[1];//one ls value
+  //   nodeLs[0][0]= val0;
+  //   for(int i=1;i<3;i++){
+  //     double x = e->getVertex(i)->x(), y= e->getVertex(i)->y(), z=e->getVertex(i)->z();
+  //     double val = a * x + b * y + c * z + d;
+  //     double sign = sign0*val;
+  //     if (sign < 0.0 && !zeroElem) zeroElem = true;
+  //     nodeLs[i] = new double[1];//one ls value
+  //     nodeLs[i][0]= val;
+  //   }
+  //   if (zeroElem){
+  //     double radius = sqrt((cg.x()-PT.x())*(cg.x()-PT.x())+(cg.y()-PT.y())*(cg.y()-PT.y())+(cg.z()-PT.z())*(cg.z()-PT.z()));
+  //     if (radius <  rad){
+  // 	isCut = T->cut(RPN, ipV, ipS, cp, 1, 1, 1,
+  // 		       cutQUAD, cutTRI, cutLIN, 0, nodeLs);
+  //     }
+  //     else cutTRI.push_back(T);
+  //   }
+  //   else  cutTRI.push_back(T);
+  //   for(int i=0;i<3;i++) delete nodeLs[i];
+  //   delete []nodeLs;
+  // }
+
   return;
 
 }
diff --git a/Mesh/CenterlineField.h b/Mesh/CenterlineField.h
index e773cde8e87771b0bf36e3a26300d5f2315ace30..e7d0450fe038160a906ecf1f7f6f50f032f5f9ac 100644
--- a/Mesh/CenterlineField.h
+++ b/Mesh/CenterlineField.h
@@ -14,11 +14,13 @@
 #include <set>
 #include <string>
 #include "Field.h"
+#include "MEdge.h"
 class GModel;
 class GFace;
 class MLine;
 class MVertex;
 class GEntity;
+class MTriangle;   
 
 #if defined(HAVE_ANN)
 #include <ANN/ANN.h>
@@ -66,7 +68,9 @@ class Centerline : public Field{
   std::map<MLine*,int> colorl;
 
   //the tubular surface mesh
-  std::vector<GFace*> surfaces; 
+  std::vector<MTriangle*> triangles;
+  //the lines cut of the tubular mesh by planes
+  std::set<MEdge,Less_Edge> theCut;
 
  public:
   Centerline(std::string fileName);
@@ -116,7 +120,7 @@ class Centerline : public Field{
 
   // Cut the tubular structure with a disk
   // perpendicular to the tubular structure
-  void cutByDisk(SPoint3 pt, SVector3 dir, double rad);
+  void cutByDisk(SVector3 &pt, SVector3 &dir, double &maxRad);
 
   //Print for debugging
   void printSplit() const;
diff --git a/contrib/DiscreteIntegration/Integration3D.h b/contrib/DiscreteIntegration/Integration3D.h
index 3e5f22156cf2bce5505498a0ee5988c9f85039cd..4e7f1cf3aa5ffb3a5c4adc61f353fec5bf9a777e 100644
--- a/contrib/DiscreteIntegration/Integration3D.h
+++ b/contrib/DiscreteIntegration/Integration3D.h
@@ -324,13 +324,13 @@ class DI_Element
   void getCuttingPoints (const DI_Element *e, const std::vector<gLevelset *> &RPNi,
                          std::vector<DI_CuttingPoint*> &cp) const;
   // return the ith point
-  virtual DI_Point* pt(int i) const {return (i < nbVert()) ? &(pts_[i]) : &(mid_[i - nbVert()]);}
+  DI_Point* pt(int i) const {return (i < nbVert()) ? &(pts_[i]) : &(mid_[i - nbVert()]);}
   // return the ith middle point
   inline DI_Point* mid(int i) const {return mid_ ? &(mid_[i]) : NULL;}
   // return the coordinates of the ith point
-  virtual double x(int i) const {return pt(i)->x();}
-  virtual double y(int i) const {return pt(i)->y();}
-  virtual double z(int i) const {return pt(i)->z();}
+  double x(int i) const {return pt(i)->x(); }
+  double y(int i) const {return pt(i)->y();}
+  double z(int i) const {return pt(i)->z();}
   // return the last levelset value of the ith point
   virtual double ls(int i) const {return pt(i)->ls();}
   // return the jth levelset value of the ith point