From 2a34f6f5f251fb86e07858c40b0f6ed02397c402 Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Tue, 21 Sep 2010 14:25:51 +0000
Subject: [PATCH] meshes of spheres should work well !!!

---
 Geo/OCCFace.cpp               |  9 ++++++
 Mesh/BDS.cpp                  | 22 ++++++++++++--
 Mesh/meshGFaceBDS.cpp         | 56 ++++++++++++++++++++++++-----------
 Mesh/meshGFaceOptimize.cpp    | 21 ++++++++++---
 benchmarks/boolean/sphere.lua | 13 +++-----
 benchmarks/step/tank.geo      |  1 +
 6 files changed, 90 insertions(+), 32 deletions(-)

diff --git a/Geo/OCCFace.cpp b/Geo/OCCFace.cpp
index 55dbff4305..f9619ef445 100644
--- a/Geo/OCCFace.cpp
+++ b/Geo/OCCFace.cpp
@@ -96,6 +96,15 @@ void OCCFace::setup()
   occface = BRep_Tool::Surface(s);
   // specific parametrization for a sphere.
   _isSphere = isSphere(_radius,_center);
+  if (_isSphere){
+    for (std::list<GEdge*>::iterator it = l_edges.begin();
+	 it != l_edges.end(); ++it){
+      GEdge *ge = *it;
+      if (ge->isSeam(this)){
+	
+      }
+    }    
+  }
 }
 
 Range<double> OCCFace::parBounds(int i) const
diff --git a/Mesh/BDS.cpp b/Mesh/BDS.cpp
index ec602f3363..1c98232a95 100644
--- a/Mesh/BDS.cpp
+++ b/Mesh/BDS.cpp
@@ -1156,6 +1156,7 @@ bool BDS_Mesh::collapse_edge_parametric(BDS_Edge *e, BDS_Point *p)
 
 bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, bool test_quality)
 {
+
   if(!p->config_modified) return false;
   if(p->g && p->g->classif_degree <= 1) return false;
   if(p->g && p->g->classif_tag < 0) {
@@ -1168,6 +1169,10 @@ bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, bool test_quality)
     eit++;
   }
 
+  /*    TEST    */
+  double R; SPoint3 c; bool isSphere = gf->isSphere(R,c);
+  double XX=0,YY=0,ZZ=0;
+
   double U = 0;
   double V = 0;
   double LC = 0;
@@ -1187,14 +1192,27 @@ bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, bool test_quality)
     sTot += fact;
     U  += n->u * fact;
     V  += n->v * fact;
+    XX += n->X;
+    YY += n->Y;
+    ZZ += n->Z;
     LC += n->lc() * fact;
     ++ited;
   }
   U /= (sTot); 
   V /= (sTot);
   LC /= (sTot);
-
-  GPoint gp = gf->point(U * scalingU, V * scalingV);
+  XX/= (sTot);
+  YY/= (sTot);
+  ZZ/= (sTot);
+
+  GPoint gp;double uv[2];
+  if (isSphere){      
+    gp = gf->closestPoint(SPoint3(XX, YY, ZZ), uv);
+    U = gp.u();
+    V = gp.v();
+  }
+  else
+    gp = gf->point(U * scalingU, V * scalingV);
   
   if (!gp.succeeded()){
     return false;
diff --git a/Mesh/meshGFaceBDS.cpp b/Mesh/meshGFaceBDS.cpp
index b4e0ed943e..5a63eb5125 100644
--- a/Mesh/meshGFaceBDS.cpp
+++ b/Mesh/meshGFaceBDS.cpp
@@ -451,35 +451,52 @@ void delaunayizeBDS(GFace *gf, BDS_Mesh &m, int &nb_swap)
 }
 
 // A test for spheres
-static void midpointsphere(GFace *gf, double u1, double v1, double u2, 
-                           double v2, double &u12, double &v12, double r)
+static void midpointsphere(GFace *gf, 
+			   double u1, 
+			   double v1, 
+			   double u2, 
+                           double v2, 
+			   double &u12, 
+			   double &v12, 
+			   SPoint3 &center,
+			   double r)
 {
   GPoint p1 = gf->point(u1, v1);
   GPoint p2 = gf->point(u2, v2);
+  
+  SVector3 DIR ((p1.x()+p2.x())/2.0 - center.x(),
+		(p1.y()+p2.y())/2.0 - center.y(),
+		(p1.z()+p2.z())/2.0 - center.z());
+  DIR.normalize();
+  
+  double X,Y,Z;
+
   double guess [2] = {0.5 * (u1 + u2), 0.5 * (v1 + v2)};
   u12 = guess[0];
   v12 = guess[1];
-
-  double d = sqrt((p1.x() - p2.x()) * (p1.x() - p2.x()) +
-                  (p1.y() - p2.y()) * (p1.y() - p2.y()) +
-                  (p1.z() - p2.z()) * (p1.z() - p2.z()));
-  
-  if (d > r/3){
+  if ( (v1 > 0.7*M_PI/2 && v2  > 0.7*M_PI/2) ||
+       (v1 < -0.7*M_PI/2 && v2 < -0.7*M_PI/2) ){
+    //    printf("coucou\n");
+    X = center.x() + DIR.x() * r;
+    Y = center.y() + DIR.y() * r;
+    Z = center.z() + DIR.z() * r;
+  }
+  else{
     return;
+    X = center.x() - DIR.x() * r;
+    Y = center.y() - DIR.y() * r;
+    Z = center.z() - DIR.z() * r;
   }
-  const double X = 0.5 * (p1.x() + p2.x());
-  const double Y = 0.5 * (p1.y() + p2.y());
-  const double Z = 0.5 * (p1.z() + p2.z());
-  
+
   GPoint proj = gf->closestPoint(SPoint3(X, Y, Z), guess);
   if (proj.succeeded()){
     u12 = proj.u();
     v12 = proj.v();
   }
-
+  //  printf("%g %g %g -- %g\n",center.x(),center.y(),center.z(),r);
+  //  printf("%g %g -- %g %g -- %g %g -- %g %g\n",
+  //         u1, v1, u2, v2, u12, v12, 0.5 * (u1 + u2), 0.5 * (v1 + v2));
   return;
-  printf("%g %g -- %g %g -- %g %g -- %g %g\n",
-         u1, v1, u2, v2, u12, v12, 0.5 * (u1 + u2), 0.5 * (v1 + v2));
 }
 
 void splitEdgePass(GFace *gf, BDS_Mesh &m, double MAXE_, int &nb_split)
@@ -499,6 +516,10 @@ void splitEdgePass(GFace *gf, BDS_Mesh &m, double MAXE_, int &nb_split)
 
   std::sort(edges.begin(), edges.end());
 
+  double RADIUS;
+  SPoint3 CENTER;
+  bool isSphere = gf->isSphere(RADIUS,CENTER);
+
   for (unsigned int i = 0; i < edges.size(); ++i){
     BDS_Edge *e = edges[i].second;
     if (!e->deleted){
@@ -508,9 +529,9 @@ void splitEdgePass(GFace *gf, BDS_Mesh &m, double MAXE_, int &nb_split)
       BDS_Point *mid ;
 
       double U, V;
-      if (0 && gf->geomType() == GEntity::Sphere){
+      if (0 && isSphere){	
         midpointsphere(gf,e->p1->u,e->p1->v,e->p2->u,e->p2->v,U,V,
-                       gf-> getSurfaceParams().radius);
+                       CENTER,RADIUS);
       }
       else{
         U = coord * e->p1->u + (1 - coord) * e->p2->u;
@@ -603,6 +624,7 @@ void collapseEdgePassUnSorted(GFace *gf, BDS_Mesh &m, double MINE_, int MAXNP,
 
 void smoothVertexPass(GFace *gf, BDS_Mesh &m, int &nb_smooth, bool q)
 {
+  //  return;
   std::set<BDS_Point*,PointLessThan>::iterator itp = m.points.begin();
   while(itp != m.points.end()){      
     if(m.smooth_point_centroid(*itp, gf,q))
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index e2a7d50156..c93707ec0c 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -787,6 +787,9 @@ void laplaceSmoothing(GFace *gf)
   buildVertexToElement(gf->triangles, adj);
   buildVertexToElement(gf->quadrangles, adj);
 
+  /*    TEST    */
+  double R; SPoint3 c; bool isSphere = gf->isSphere(R,c);
+
   for(int i = 0; i < 5; i++){
     v2t_cont :: iterator it = adj.begin();
     while (it != adj.end()){
@@ -799,27 +802,37 @@ void laplaceSmoothing(GFace *gf)
         ver->getParameter(1, initv);
         const std::vector<MElement*> &lt = it->second;
         double cu = 0, cv = 0;
+	double XX=0,YY=0,ZZ=0;
         double pu[4], pv[4];
         double fact  = 0.0;
         for(unsigned int i = 0; i < lt.size(); i++){
           parametricCoordinates(lt[i], gf, pu, pv, ver);
           cu += (pu[0] + pu[1] + pu[2]);
           cv += (pv[0] + pv[1] + pv[2]);
+	  XX += lt[i]->getVertex(0)->x()+lt[i]->getVertex(1)->x()+lt[i]->getVertex(2)->x();
+	  YY += lt[i]->getVertex(0)->y()+lt[i]->getVertex(1)->y()+lt[i]->getVertex(2)->y();
+	  ZZ += lt[i]->getVertex(0)->z()+lt[i]->getVertex(1)->z()+lt[i]->getVertex(2)->z();
           if(lt[i]->getNumVertices() == 4){
             cu += pu[3];
             cv += pv[3];
+	    XX += lt[i]->getVertex(3)->x();
+	    YY += lt[i]->getVertex(3)->y();
+	    ZZ += lt[i]->getVertex(3)->z();
           }         
           fact += lt[i]->getNumVertices();
-
         }
         if(fact != 0.0){
 	  SPoint2 before(initu,initv);
 	  SPoint2 after(cu / fact,cv / fact);
+	  if (isSphere){
+	    GPoint gp = gf->closestPoint(SPoint3(XX/fact, YY/fact, ZZ/fact), after);
+	    after = SPoint2(gp.u(),gp.v());
+	  }
 	  bool success = _isItAGoodIdeaToMoveThatVertex (gf,  it->second, ver,before,after);
 	  if (success){
-	    ver->setParameter(0, cu / fact);
-	    ver->setParameter(1, cv / fact);
-	    GPoint pt = gf->point(SPoint2(cu / fact, cv / fact));
+	    ver->setParameter(0, after.x());
+	    ver->setParameter(1, after.y());
+	    GPoint pt = gf->point(after);
 	    if(pt.succeeded()){
 	      ver->x() = pt.x();
 	      ver->y() = pt.y();
diff --git a/benchmarks/boolean/sphere.lua b/benchmarks/boolean/sphere.lua
index f179218ca6..a826c4c751 100644
--- a/benchmarks/boolean/sphere.lua
+++ b/benchmarks/boolean/sphere.lua
@@ -1,10 +1,5 @@
+R = 1.0;
+myModel = GModel();
+myModel:addSphere(0,0,0,R);
 
-options = gmshOptions()
-options:numberSet('Mesh', 0, 'CharacteristicLengthFactor', 1.5)
-
-myTool = GModel();
-myTool:addSphere(0.0,0.0,0.0,1);
-
-myTool:mesh(1)
-myTool:mesh(2)
-myTool:save('sphere.msh')
+myModel:setAsCurrent();
diff --git a/benchmarks/step/tank.geo b/benchmarks/step/tank.geo
index 123aefd78d..513a3baaac 100644
--- a/benchmarks/step/tank.geo
+++ b/benchmarks/step/tank.geo
@@ -40,3 +40,4 @@ Transfinite Surface {14} = {21,25,26,18};
 Mesh.Smoothing = 10;
 
 Recombine Surface{1:52};
+Mesh.SubdivisionAlgorithm=3;
\ No newline at end of file
-- 
GitLab