Salome HOME
Integration of PAL/SALOME V2.1.0c from OCC
[modules/smesh.git] / src / StdMeshers / StdMeshers_MEFISTO_2D.cxx
index 6229e4c6d0148b058fdf875ee9576667c820a014..0775a9220933dbe2d3ca405dd36f75e87041ad9c 100644 (file)
@@ -58,9 +58,11 @@ using namespace std;
 #include <GCPnts_AbscissaPoint.hxx>
 #include <GCPnts_UniformAbscissa.hxx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
 
 #include <string>
-#include <algorithm>
+//#include <algorithm>
 
 //=============================================================================
 /*!
@@ -158,7 +160,8 @@ bool StdMeshers_MEFISTO_2D::CheckHypothesis
                isOk = false;
                if (_maxElementArea > 0)
                {
-                       _edgeLength = 2 * sqrt(_maxElementArea);        // triangles : minorant
+//                     _edgeLength = 2 * sqrt(_maxElementArea);        // triangles : minorant
+                       _edgeLength = 2 * sqrt(_maxElementArea/sqrt(3.0));
                        isOk = true;
                }
                else
@@ -208,64 +211,57 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
        Z nutysu = 1;                           // 1: il existe un fonction areteideale_()
        // Z  nutysu=0;              // 0: on utilise aretmx
        R aretmx = _edgeLength;         // longueur max aretes future triangulation
-       //SCRUTE(aretmx);
 
        nblf = NumberOfWires(F);
-       //SCRUTE(nblf);
 
        nudslf = new Z[1 + nblf];
        nudslf[0] = 0;
        int iw = 1;
        int nbpnt = 0;
 
-       const TopoDS_Wire OW1 = BRepTools::OuterWire(F);
-       nbpnt += NumberOfPoints(aMesh, OW1);
+       myOuterWire = BRepTools::OuterWire(F);
+       nbpnt += NumberOfPoints(aMesh, myOuterWire);
+        if ( nbpnt < 3 ) // ex: a circle with 2 segments
+          return false;
        nudslf[iw++] = nbpnt;
-       //SCRUTE(nbpnt);
 
        for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
        {
                const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
-               if (!OW1.IsSame(W))
+               if (!myOuterWire.IsSame(W))
                {
                        nbpnt += NumberOfPoints(aMesh, W);
                        nudslf[iw++] = nbpnt;
-                       //SCRUTE(nbpnt);
                }
        }
 
+        // avoid passing same uv points for a vertex common to 2 wires
+        TopTools_IndexedDataMapOfShapeListOfShape VWMap;
+        if ( iw - 1 > 1 ) // nbofWires > 1
+          TopExp::MapShapesAndAncestors( F , TopAbs_VERTEX, TopAbs_WIRE, VWMap );
+
        uvslf = new R2[nudslf[nblf]];
-       //SCRUTE(nudslf[nblf]);
        int m = 0;
 
-       map<int, const SMDS_MeshNode*> mefistoToDS;     // correspondence mefisto index--> points IDNodes
-       TopoDS_Wire OW = BRepTools::OuterWire(F);
-       LoadPoints(aMesh, F, OW, uvslf, m, mefistoToDS);
-       //SCRUTE(m);
+        double scalex, scaley;
+        ComputeScaleOnFace(aMesh, F, scalex, scaley);
+
+        map<int, const SMDS_MeshNode*> mefistoToDS;    // correspondence mefisto index--> points IDNodes
+       if ( !LoadPoints(aMesh, F, myOuterWire, uvslf, m,
+                         mefistoToDS, scalex, scaley, VWMap))
+          return false;
 
        for (TopExp_Explorer exp(F, TopAbs_WIRE); exp.More(); exp.Next())
        {
                const TopoDS_Wire & W = TopoDS::Wire(exp.Current());
-               if (!OW.IsSame(W))
+               if (!myOuterWire.IsSame(W))
                {
-                       LoadPoints(aMesh, F, W, uvslf, m, mefistoToDS);
-                       //SCRUTE(m);
+                       if (! LoadPoints(aMesh, F, W, uvslf, m,
+                                         mefistoToDS, scalex, scaley, VWMap ))
+                          return false;
                }
        }
-//   SCRUTE(nudslf[nblf]);
-//   for (int i=0; i<=nblf; i++)
-//     {
-//       MESSAGE(" -+- " <<i<< " "<< nudslf[i]);
-//     }
-//   for (int i=0; i<nudslf[nblf]; i++)
-//     {
-//       MESSAGE(" -+- " <<i<< " "<< uvslf[i]);
-//     }
-//   SCRUTE(nutysu);
-//   SCRUTE(aretmx);
-//   SCRUTE(nblf);
-
-       MESSAGE("MEFISTO triangulation ...");
+
        uvst = NULL;
        nust = NULL;
        aptrte(nutysu, aretmx,
@@ -275,10 +271,8 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
          {
            MESSAGE("... End Triangulation Generated Triangle Number " << nbt);
            MESSAGE("                                    Node Number " << nbst);
-           //SCRUTE(nbst);
-           //SCRUTE(nbt);
            StoreResult(aMesh, nbst, uvst, nbt, nust, F,
-                       faceIsForward, mefistoToDS);
+                       faceIsForward, mefistoToDS, scalex, scaley);
            isOk = true;
          }
        else
@@ -297,117 +291,319 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh
        return isOk;
 }
 
+//=======================================================================
+//function : fixOverlappedLinkUV
+//purpose  : prevent failure due to overlapped adjacent links
+//=======================================================================
+
+static bool fixOverlappedLinkUV( R2& uv0, const R2& uv1, const R2& uv2 )
+{
+  gp_XY v1( uv0.x - uv1.x, uv0.y - uv1.y );
+  gp_XY v2( uv2.x - uv1.x, uv2.y - uv1.y );
+
+  double tol2 = DBL_MIN * DBL_MIN;
+  double sqMod1 = v1.SquareModulus();
+  if ( sqMod1 <= tol2 ) return false;
+  double sqMod2 = v2.SquareModulus();
+  if ( sqMod2 <= tol2 ) return false;
+
+  double dot = v1*v2;
+
+  // check sinus >= 1.e-3
+  const double minSin = 1.e-3;
+  if ( dot > 0 && 1 - dot * dot / ( sqMod1 * sqMod2 ) < minSin * minSin ) {
+    MESSAGE(" ___ FIX UV ____" << uv0.x << " " << uv0.y);
+    v1.SetCoord( -v1.Y(), v1.X() );
+    double delta = sqrt( sqMod1 ) * minSin;
+    if ( v1.X() < 0 )
+      uv0.x -= delta;
+    else
+      uv0.x += delta;
+    if ( v1.Y() < 0 )
+      uv0.y -= delta;
+    else
+      uv0.y += delta;
+//    MESSAGE(" -> " << uv0.x << " " << uv0.y << " ");
+//     MESSAGE("v1( " << v1.X() << " " << v1.Y() << " ) " <<
+//       "v2( " << v2.X() << " " << v2.Y() << " ) ");
+//    MESSAGE("SIN: " << sqrt(1 - dot * dot / (sqMod1 * sqMod2)));
+//     v1.SetCoord( uv0.x - uv1.x, uv0.y - uv1.y );
+//     v2.SetCoord( uv2.x - uv1.x, uv2.y - uv1.y );
+//     gp_XY v3( uv2.x - uv0.x, uv2.y - uv0.y );
+//     sqMod1 = v1.SquareModulus();
+//     sqMod2 = v2.SquareModulus();
+//     dot = v1*v2;
+//     double sin = sqrt(1 - dot * dot / (sqMod1 * sqMod2));
+//     MESSAGE("NEW SIN: " << sin);
+    return true;
+  }
+  return false;
+}
+
+//=======================================================================
+//function : fixCommonVertexUV
+//purpose  : 
+//=======================================================================
+
+static bool fixCommonVertexUV (gp_Pnt2d &           theUV,
+                               const TopoDS_Vertex& theV,
+                               const TopoDS_Wire&   theW,
+                               const TopoDS_Wire&   theOW,
+                               const TopoDS_Face&   theF,
+                               const TopTools_IndexedDataMapOfShapeListOfShape & theVWMap,
+                               SMESH_Mesh &         theMesh)
+{
+  if( theW.IsSame( theOW ) ||
+      !theVWMap.Contains( theV )) return false;
+
+  // check if there is another wire sharing theV
+  const TopTools_ListOfShape& WList = theVWMap.FindFromKey( theV );
+  TopTools_ListIteratorOfListOfShape aWIt;
+  for ( aWIt.Initialize( WList ); aWIt.More(); aWIt.Next() )
+    if ( !theW.IsSame( aWIt.Value() ))
+      break;
+  if ( !aWIt.More() ) return false;
+
+  TopTools_ListOfShape EList;
+  list< double >       UList;
+
+  // find edges of theW sharing theV
+  // and find 2d normal to them at theV
+  gp_Vec2d N(0.,0.);
+  TopoDS_Iterator itE( theW );
+  for (  ; itE.More(); itE.Next() )
+  {
+    const TopoDS_Edge& E = TopoDS::Edge( itE.Value() );
+    TopoDS_Iterator itV( E );
+    for ( ; itV.More(); itV.Next() )
+    {
+      const TopoDS_Vertex & V = TopoDS::Vertex( itV.Value() );
+      if ( !V.IsSame( theV ))
+        continue;
+      EList.Append( E );
+      Standard_Real u = BRep_Tool::Parameter( V, E );
+      UList.push_back( u );
+      double f, l;
+      Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l);
+      gp_Vec2d d1;
+      gp_Pnt2d p;
+      C2d->D1( u, p, d1 );
+      gp_Vec2d n( d1.Y(), -d1.X() );
+      if ( E.Orientation() == TopAbs_REVERSED )
+        n.Reverse();
+      N += n.Normalized();
+    }
+  }
+
+  // define step size by which to move theUV
+
+  gp_Pnt2d nextUV; // uv of next node on edge, most distant of the four
+  double maxDist = -DBL_MAX;
+  TopTools_ListIteratorOfListOfShape aEIt (EList);
+  list< double >::iterator aUIt = UList.begin();
+  for ( ; aEIt.More(); aEIt.Next(), aUIt++ )
+  {
+    const TopoDS_Edge& E = TopoDS::Edge( aEIt.Value() );
+    double f, l;
+    Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, theF, f, l);
+
+    double umin = DBL_MAX, umax = -DBL_MAX;
+    SMDS_NodeIteratorPtr nIt = theMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
+    if ( !nIt->more() ) // no nodes on edge, only on vertices
+    {
+      umin = l;
+      umax = f;
+    }
+    else
+    {
+      while ( nIt->more() ) {
+        const SMDS_MeshNode* node = nIt->next();
+        const SMDS_EdgePosition* epos =
+          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+        double u = epos->GetUParameter();
+        if ( u < umin )
+          umin = u;
+        if ( u > umax )
+          umax = u;
+      }
+    }
+    bool isFirstCommon = ( *aUIt == f );
+    gp_Pnt2d uv = C2d->Value( isFirstCommon ? umin : umax );
+    double dist = theUV.SquareDistance( uv );
+    if ( dist > maxDist ) {
+      maxDist = dist;
+      nextUV  = uv;
+    }
+  }
+  R2 uv0, uv1, uv2;
+  uv0.x = theUV.X();    uv0.y = theUV.Y(); 
+  uv1.x = nextUV.X();   uv1.y = nextUV.Y(); 
+  uv2.x = uv0.x;        uv2.y = uv0.y;
+  if ( fixOverlappedLinkUV( uv0, uv1, uv2 ))
+  {
+    double step = theUV.Distance( gp_Pnt2d( uv0.x, uv0.y ));
+
+    // move theUV along the normal by the step
+
+    N *= step;
+
+    MESSAGE("--fixCommonVertexUV move(" << theUV.X() << " " << theUV.Y()
+            << ") by (" << N.X() << " " << N.Y() << ")" 
+            << endl << "--- MAX DIST " << maxDist);
+
+    theUV.SetXY( theUV.XY() + N.XY() );
+
+    return true;
+  }
+  return false;
+}
+
 //=============================================================================
 /*!
  *  
  */
 //=============================================================================
 
-void StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh,
-       const TopoDS_Face & FF,
-       const TopoDS_Wire & WW, R2 * uvslf, int &m,
-       map<int, const SMDS_MeshNode*>&mefistoToDS)
+bool StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh &        aMesh,
+                                       const TopoDS_Face & FF,
+                                       const TopoDS_Wire & WW,
+                                       R2 *                uvslf,
+                                       int &               m,
+                                       map<int, const SMDS_MeshNode*>&mefistoToDS,
+                                       double              scalex,
+                                       double              scaley,
+                                       const TopTools_IndexedDataMapOfShapeListOfShape& VWMap)
 {
-       MESSAGE("StdMeshers_MEFISTO_2D::LoadPoints");
-
-       SMDS_Mesh * meshDS = aMesh.GetMeshDS();
-
-       double scalex;
-       double scaley;
-       TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
-       ComputeScaleOnFace(aMesh, F, scalex, scaley);
-
-       TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD));
-       BRepTools_WireExplorer wexp(W, F);
-       for (wexp.Init(W, F); wexp.More(); wexp.Next())
-       {
-               const TopoDS_Edge & E = wexp.Current();
-
-               // --- IDNodes of first and last Vertex
-
-               TopoDS_Vertex VFirst, VLast;
-               TopExp::Vertices(E, VFirst, VLast);     // corresponds to f and l
-
-           ASSERT(!VFirst.IsNull());
-               SMDS_NodeIteratorPtr lid=
-                  aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
-               const SMDS_MeshNode* idFirst = lid->next();
-
-               ASSERT(!VLast.IsNull());
-               lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
-               const SMDS_MeshNode* idLast = lid->next();
-
-               // --- edge internal IDNodes (relies on good order storage, not checked)
-
-               int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
-               //SCRUTE(nbPoints);
-
-               double f, l;
-               Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
-
-               SMDS_NodeIteratorPtr ite= aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
-
-               bool isForward = (E.Orientation() == TopAbs_FORWARD);
-               map<double, const SMDS_MeshNode*> params;
-
-               while(ite->more())
-               {
-                       const SMDS_MeshNode * node = ite->next();
-                       const SMDS_EdgePosition* epos =
-                          static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
-                       double param = epos->GetUParameter();
-                       params[param] = node;
-               }
-               // --- load 2D values into MEFISTO structure,
-               //     add IDNodes in mefistoToDS map
-
-               if (E.Orientation() == TopAbs_FORWARD)
-               {
-                       gp_Pnt2d p = C2d->Value(f);     // first point = Vertex Forward
-                       uvslf[m].x = scalex * p.X();
-                       uvslf[m].y = scaley * p.Y();
-                       mefistoToDS[m + 1] = idFirst;
-                       //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
-                       //MESSAGE("__ f "<<f<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
-                       m++;
-                       map<double, const SMDS_MeshNode*>::iterator itp = params.begin();
-                       for (int i = 1; i <= nbPoints; i++)     // nbPoints internal
-                       {
-                               double param = (*itp).first;
-                               gp_Pnt2d p = C2d->Value(param);
-                               uvslf[m].x = scalex * p.X();
-                               uvslf[m].y = scaley * p.Y();
-                               mefistoToDS[m + 1] = (*itp).second;
-//        MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
-//        MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
-                               m++;
-                               itp++;
-                       }
-               }
-               else
-               {
-                       gp_Pnt2d p = C2d->Value(l);     // last point = Vertex Reversed
-                       uvslf[m].x = scalex * p.X();
-                       uvslf[m].y = scaley * p.Y();
-                       mefistoToDS[m + 1] = idLast;
-//    MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
-//    MESSAGE("__ l "<<l<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
-                       m++;
-                       map<double, const SMDS_MeshNode*>::reverse_iterator itp = params.rbegin();
-                       for (int i = nbPoints; i >= 1; i--)
-                       {
-                               double param = (*itp).first;
-                               gp_Pnt2d p = C2d->Value(param);
-                               uvslf[m].x = scalex * p.X();
-                               uvslf[m].y = scaley * p.Y();
-                               mefistoToDS[m + 1] = (*itp).second;
-//        MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
-//            MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
-                               m++;
-                               itp++;
-                       }
-               }
-       }
+//  MESSAGE("StdMeshers_MEFISTO_2D::LoadPoints");
+
+  SMDS_Mesh * meshDS = aMesh.GetMeshDS();
+
+  TopoDS_Face F = TopoDS::Face(FF.Oriented(TopAbs_FORWARD));
+
+  int mInit = m, mFirst, iEdge;
+  gp_XY scale( scalex, scaley );
+
+  TopoDS_Wire W = TopoDS::Wire(WW.Oriented(TopAbs_FORWARD));
+  BRepTools_WireExplorer wexp(W, F);
+  for (wexp.Init(W, F), iEdge = 0; wexp.More(); wexp.Next(), iEdge++)
+  {
+    const TopoDS_Edge & E = wexp.Current();
+
+    // --- IDNodes of first and last Vertex
+
+    TopoDS_Vertex VFirst, VLast;
+    TopExp::Vertices(E, VFirst, VLast); // corresponds to f and l
+
+    ASSERT(!VFirst.IsNull());
+    SMDS_NodeIteratorPtr lid=
+      aMesh.GetSubMesh(VFirst)->GetSubMeshDS()->GetNodes();
+    if ( !lid->more() ) {
+      MESSAGE (" NO NODE BUILT ON VERTEX ");
+      return false;
+    }
+    const SMDS_MeshNode* idFirst = lid->next();
+
+    ASSERT(!VLast.IsNull());
+    lid=aMesh.GetSubMesh(VLast)->GetSubMeshDS()->GetNodes();
+    if ( !lid->more() ) {
+      MESSAGE (" NO NODE BUILT ON VERTEX ");
+      return false;
+    }
+    const SMDS_MeshNode* idLast = lid->next();
+
+    // --- edge internal IDNodes (relies on good order storage, not checked)
+
+    int nbPoints = aMesh.GetSubMesh(E)->GetSubMeshDS()->NbNodes();
+
+    double f, l;
+    Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
+
+    SMDS_NodeIteratorPtr ite= aMesh.GetSubMesh(E)->GetSubMeshDS()->GetNodes();
+
+    bool isForward = (E.Orientation() == TopAbs_FORWARD);
+    map<double, const SMDS_MeshNode*> params;
+
+    while(ite->more())
+    {
+      const SMDS_MeshNode * node = ite->next();
+      const SMDS_EdgePosition* epos =
+        static_cast<const SMDS_EdgePosition*>(node->GetPosition().get());
+      double param = epos->GetUParameter();
+      params[param] = node;
+    }
+    if ( nbPoints != params.size())
+    {
+      MESSAGE( "BAD NODE ON EDGE POSITIONS" );
+      return false;
+    }
+
+    mFirst = m;
+
+    // --- load 2D values into MEFISTO structure,
+    //     add IDNodes in mefistoToDS map
+    if (E.Orientation() == TopAbs_FORWARD)
+    {
+      gp_Pnt2d p = C2d->Value(f).XY().Multiplied( scale );       // first point = Vertex Forward
+      if ( fixCommonVertexUV( p, VFirst, W, myOuterWire, F, VWMap, aMesh ))
+        myNodesOnCommonV.push_back( idFirst );
+      uvslf[m].x = p.X();
+      uvslf[m].y = p.Y();
+      mefistoToDS[m + 1] = idFirst;
+      //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
+      //MESSAGE("__ f "<<f<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
+      m++;
+      map<double, const SMDS_MeshNode*>::iterator itp = params.begin();
+      for (int i = 1; i <= nbPoints; i++)       // nbPoints internal
+      {
+        double param = (*itp).first;
+        gp_Pnt2d p = C2d->Value(param).XY().Multiplied( scale );
+        uvslf[m].x = p.X();
+        uvslf[m].y = p.Y();
+        mefistoToDS[m + 1] = (*itp).second;
+        //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
+        //MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
+        m++;
+        itp++;
+      }
+    }
+    else
+    {
+      gp_Pnt2d p = C2d->Value(l).XY().Multiplied( scale );       // last point = Vertex Reversed
+      if ( fixCommonVertexUV( p, VLast, W, myOuterWire, F, VWMap, aMesh ))
+        myNodesOnCommonV.push_back( idLast );
+      uvslf[m].x = p.X();
+      uvslf[m].y = p.Y();
+      mefistoToDS[m + 1] = idLast;
+      //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
+      //MESSAGE("__ l "<<l<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
+      m++;
+      map<double, const SMDS_MeshNode*>::reverse_iterator itp = params.rbegin();
+      for (int i = nbPoints; i >= 1; i--)
+      {
+        double param = (*itp).first;
+        gp_Pnt2d p = C2d->Value(param).XY().Multiplied( scale );
+        uvslf[m].x = p.X();
+        uvslf[m].y = p.Y();
+        mefistoToDS[m + 1] = (*itp).second;
+        //MESSAGE(" "<<m<<" "<<mefistoToDS[m+1]);
+        //MESSAGE("__ "<<i<<" "<<param<<" "<<uvslf[m].x <<" "<<uvslf[m].y);
+        m++;
+        itp++;
+      }
+    }
+    // prevent failure on overlapped adjacent links
+    if ( iEdge > 0 )
+      fixOverlappedLinkUV (uvslf[ mFirst - 1],
+                           uvslf[ mFirst ],
+                           uvslf[ mFirst + 1 ]);
+    
+  } // for  wexp
+
+  fixOverlappedLinkUV (uvslf[ m - 1],
+                       uvslf[ mInit ],
+                       uvslf[ mInit + 1 ]);
+
+  return true;
 }
 
 //=============================================================================
@@ -416,76 +612,91 @@ void StdMeshers_MEFISTO_2D::LoadPoints(SMESH_Mesh & aMesh,
  */
 //=============================================================================
 
-// **** a mettre dans SMESH_Algo ou SMESH_2D_Algo
-
 void StdMeshers_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh,
        const TopoDS_Face & aFace, double &scalex, double &scaley)
 {
-       //MESSAGE("StdMeshers_MEFISTO_2D::ComputeScaleOnFace");
-       TopoDS_Face F = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD));
-       TopoDS_Wire W = BRepTools::OuterWire(F);
-
-       BRepTools_WireExplorer wexp(W, F);
-
-       double xmin = 1.e300;           // min & max of face 2D parametric coord.
-       double xmax = -1.e300;
-       double ymin = 1.e300;
-       double ymax = -1.e300;
-       int nbp = 50;
-       scalex = 1;
-       scaley = 1;
-       for (wexp.Init(W, F); wexp.More(); wexp.Next())
-       {
-               const TopoDS_Edge & E = wexp.Current();
-               double f, l;
-               Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
-               for (int i = 0; i <= nbp; i++)
-               {
-                       double param = f + (double (i) / double (nbp))*(l - f);
-                       gp_Pnt2d p = C2d->Value(param);
-                       if (p.X() < xmin)
-                               xmin = p.X();
-                       if (p.X() > xmax)
-                               xmax = p.X();
-                       if (p.Y() < ymin)
-                               ymin = p.Y();
-                       if (p.Y() > ymax)
-                               ymax = p.Y();
-//    MESSAGE(" "<< f<<" "<<l<<" "<<param<<" "<<xmin<<" "<<xmax<<" "<<ymin<<" "<<ymax);
-               }
-       }
-//   SCRUTE(xmin);
-//   SCRUTE(xmax);
-//   SCRUTE(ymin);
-//   SCRUTE(ymax);
-       double xmoy = (xmax + xmin) / 2.;
-       double ymoy = (ymax + ymin) / 2.;
-
-       Handle(Geom_Surface) S = BRep_Tool::Surface(F); // 3D surface
-
-       double length_x = 0;
-       double length_y = 0;
-       gp_Pnt PX0 = S->Value(xmin, ymoy);
-       gp_Pnt PY0 = S->Value(xmoy, ymin);
-       for (int i = 1; i <= nbp; i++)
-       {
-               double x = xmin + (double (i) / double (nbp))*(xmax - xmin);
-               gp_Pnt PX = S->Value(x, ymoy);
-               double y = ymin + (double (i) / double (nbp))*(ymax - ymin);
-               gp_Pnt PY = S->Value(xmoy, y);
-               length_x += PX.Distance(PX0);
-               length_y += PY.Distance(PY0);
-               PX0.SetCoord(PX.X(), PX.Y(), PX.Z());
-               PY0.SetCoord(PY.X(), PY.Y(), PY.Z());
-       }
-//   SCRUTE(length_x);
-//   SCRUTE(length_y);
-       scalex = length_x / (xmax - xmin);
-       scaley = length_y / (ymax - ymin);
-//   SCRUTE(scalex);
-//   SCRUTE(scaley);
-       ASSERT(scalex);
-       ASSERT(scaley);
+  //MESSAGE("StdMeshers_MEFISTO_2D::ComputeScaleOnFace");
+  TopoDS_Face F = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD));
+  TopoDS_Wire W = BRepTools::OuterWire(F);
+
+  double xmin = 1.e300;         // min & max of face 2D parametric coord.
+  double xmax = -1.e300;
+  double ymin = 1.e300;
+  double ymax = -1.e300;
+  int nbp = 23;
+  scalex = 1;
+  scaley = 1;
+
+  TopExp_Explorer wexp(W, TopAbs_EDGE);
+  for ( ; wexp.More(); wexp.Next())
+  {
+    const TopoDS_Edge & E = TopoDS::Edge( wexp.Current() );
+    double f, l;
+    Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
+    if ( C2d.IsNull() ) continue;
+    double du = (l - f) / double (nbp);
+    for (int i = 0; i <= nbp; i++)
+    {
+      double param = f + double (i) * du;
+      gp_Pnt2d p = C2d->Value(param);
+      if (p.X() < xmin)
+        xmin = p.X();
+      if (p.X() > xmax)
+        xmax = p.X();
+      if (p.Y() < ymin)
+        ymin = p.Y();
+      if (p.Y() > ymax)
+        ymax = p.Y();
+      //    MESSAGE(" "<< f<<" "<<l<<" "<<param<<" "<<xmin<<" "<<xmax<<" "<<ymin<<" "<<ymax);
+    }
+  }
+  //   SCRUTE(xmin);
+  //   SCRUTE(xmax);
+  //   SCRUTE(ymin);
+  //   SCRUTE(ymax);
+  double xmoy = (xmax + xmin) / 2.;
+  double ymoy = (ymax + ymin) / 2.;
+  double xsize = xmax - xmin;
+  double ysize = ymax - ymin;
+
+  Handle(Geom_Surface) S = BRep_Tool::Surface(F);       // 3D surface
+
+  double length_x = 0;
+  double length_y = 0;
+  gp_Pnt PX0 = S->Value(xmin, ymoy);
+  gp_Pnt PY0 = S->Value(xmoy, ymin);
+  double dx = xsize / double (nbp);
+  double dy = ysize / double (nbp);
+  for (int i = 1; i <= nbp; i++)
+  {
+    double x = xmin + double (i) * dx;
+    gp_Pnt PX = S->Value(x, ymoy);
+    double y = ymin + double (i) * dy;
+    gp_Pnt PY = S->Value(xmoy, y);
+    length_x += PX.Distance(PX0);
+    length_y += PY.Distance(PY0);
+    PX0 = PX;
+    PY0 = PY;
+  }
+  scalex = length_x / xsize;
+  scaley = length_y / ysize;
+//   SCRUTE(xsize);
+//   SCRUTE(ysize);
+  double xyratio = xsize*scalex/(ysize*scaley);
+  const double maxratio = 1.e2;
+  //SCRUTE(xyratio);
+  if (xyratio > maxratio) {
+    SCRUTE( scaley );
+    scaley *= xyratio / maxratio;
+    SCRUTE( scaley );
+  }
+  else if (xyratio < 1./maxratio) {
+    SCRUTE( scalex );
+    scalex *= 1 / xyratio / maxratio;
+    SCRUTE( scalex );
+  }
+  ASSERT(scalex);
+  ASSERT(scaley);
 }
 
 //=============================================================================
@@ -495,70 +706,90 @@ void StdMeshers_MEFISTO_2D::ComputeScaleOnFace(SMESH_Mesh & aMesh,
 //=============================================================================
 
 void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh,
-       Z nbst, R2 * uvst, Z nbt, Z * nust,
-       const TopoDS_Face & F, bool faceIsForward,
-       map<int, const SMDS_MeshNode*>&mefistoToDS)
+                                        Z nbst, R2 * uvst, Z nbt, Z * nust,
+                                        const TopoDS_Face & F, bool faceIsForward,
+                                        map<int, const SMDS_MeshNode*>&mefistoToDS,
+                                        double scalex, double scaley)
 {
-       double scalex;
-       double scaley;
-       ComputeScaleOnFace(aMesh, F, scalex, scaley);
-
-       SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
-
-       Z n, m;
-       Handle(Geom_Surface) S = BRep_Tool::Surface(F);
+  SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
+
+  Z n, m;
+  Handle(Geom_Surface) S = BRep_Tool::Surface(F);
+
+  for (n = 0; n < nbst; n++)
+  {
+    if (mefistoToDS.find(n + 1) == mefistoToDS.end())
+    {
+      double u = uvst[n][0] / scalex;
+      double v = uvst[n][1] / scaley;
+      gp_Pnt P = S->Value(u, v);
+
+      SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
+      meshDS->SetNodeOnFace(node, F);
+
+      //MESSAGE(P.X()<<" "<<P.Y()<<" "<<P.Z());
+      mefistoToDS[n + 1] = node;
+      //MESSAGE("NEW: "<<n<<" "<<mefistoToDS[n+1]);
+      SMDS_FacePosition* fpos =
+        static_cast<SMDS_FacePosition*>(node->GetPosition().get());
+      fpos->SetUParameter(u);
+      fpos->SetVParameter(v);
+    }
+  }
+
+  m = 0;
+  int mt = 0;
+
+  //SCRUTE(faceIsForward);
+  for (n = 1; n <= nbt; n++)
+  {
+    int inode1 = nust[m++];
+    int inode2 = nust[m++];
+    int inode3 = nust[m++];
+
+    const SMDS_MeshNode *n1, *n2, *n3;
+    n1 = mefistoToDS[inode1];
+    n2 = mefistoToDS[inode2];
+    n3 = mefistoToDS[inode3];
+    //MESSAGE("-- "<<inode1<<" "<<inode2<<" "<<inode3);
+
+    // triangle points must be in trigonometric order if face is Forward
+    // else they must be put clockwise
+
+    bool triangleIsWellOriented = faceIsForward;
+
+    SMDS_MeshElement * elt;
+    if (triangleIsWellOriented)
+      elt = meshDS->AddFace(n1, n2, n3);
+    else
+      elt = meshDS->AddFace(n1, n3, n2);
+
+    meshDS->SetMeshElementOnShape(elt, F);
+    m++;
+  }
+
+  // remove bad elements build on vertices shared by wires
+
+  list<const SMDS_MeshNode*>::iterator itN = myNodesOnCommonV.begin();
+  for ( ; itN != myNodesOnCommonV.end(); itN++ )
+  {
+    const SMDS_MeshNode* node = *itN;
+    SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
+    while ( invElemIt->more() )
+    {
+      const SMDS_MeshElement* elem = invElemIt->next();
+      SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+      int nbSame = 0;
+      while ( itN->more() )
+        if ( itN->next() == node)
+          nbSame++;
+      if (nbSame > 1) {
+        MESSAGE( "RM bad element " << elem->GetID());
+        meshDS->RemoveElement( elem );
+      }
+    }
+  }
 
-       for (n = 0; n < nbst; n++)
-       {
-               double u = uvst[n][0] / scalex;
-               double v = uvst[n][1] / scaley;
-               gp_Pnt P = S->Value(u, v);
-
-               if (mefistoToDS.find(n + 1) == mefistoToDS.end())
-               {
-                       SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
-                       meshDS->SetNodeOnFace(node, F);
-
-                       //MESSAGE(nodeId<<" "<<P.X()<<" "<<P.Y()<<" "<<P.Z());
-                       mefistoToDS[n + 1] = node;
-                       //MESSAGE(" "<<n<<" "<<mefistoToDS[n+1]);
-                       SMDS_FacePosition* fpos =
-                          static_cast<SMDS_FacePosition*>(node->GetPosition().get());
-                       fpos->SetUParameter(u);
-                       fpos->SetVParameter(v);
-               }
-       }
-
-       m = 0;
-       int mt = 0;
-
-       //SCRUTE(faceIsForward);
-       for (n = 1; n <= nbt; n++)
-       {
-               int inode1 = nust[m++];
-               int inode2 = nust[m++];
-               int inode3 = nust[m++];
-
-               const SMDS_MeshNode *n1, *n2, *n3;
-               n1 = mefistoToDS[inode1];
-               n2 = mefistoToDS[inode2];
-               n3 = mefistoToDS[inode3];
-               //MESSAGE("-- "<<inode1<<" "<<inode2<<" "<<inode3<<" ++ "<<nodeId1<<" "<<nodeId2<<" "<<nodeId3);
-
-               // triangle points must be in trigonometric order if face is Forward
-               // else they must be put clockwise
-
-               bool triangleIsWellOriented = faceIsForward;
-
-        SMDS_MeshElement * elt;
-               if (triangleIsWellOriented)
-                       elt = meshDS->AddFace(n1, n2, n3);
-               else
-                       elt = meshDS->AddFace(n1, n3, n2);
-       
-               meshDS->SetMeshElementOnShape(elt, F);
-               m++;
-       }
 }
 
 //=============================================================================
@@ -570,7 +801,7 @@ void StdMeshers_MEFISTO_2D::StoreResult(SMESH_Mesh & aMesh,
 double StdMeshers_MEFISTO_2D::ComputeEdgeElementLength(SMESH_Mesh & aMesh,
        const TopoDS_Shape & aShape)
 {
-       MESSAGE("StdMeshers_MEFISTO_2D::ComputeEdgeElementLength");
+       //MESSAGE("StdMeshers_MEFISTO_2D::ComputeEdgeElementLength");
        // **** a mettre dans SMESH_2D_Algo ?
 
        const TopoDS_Face & FF = TopoDS::Face(aShape);