Salome HOME
Merge from V5_1_4_BR (5_1_4rc2) 09/06/2010
[modules/smesh.git] / src / SMESH / SMESH_MesherHelper.cxx
index 13b06a3965960dc8f883e8f0f3f48ab8f360bca5..8cdacf7edcd0edbb963ddc3dcf233bf61550fab8 100644 (file)
@@ -597,23 +597,43 @@ gp_XY SMESH_MesherHelper::GetMiddleUV(const Handle(Geom_Surface)& surface,
 
 double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge&   E,
                                     const SMDS_MeshNode* n,
+                                    const SMDS_MeshNode* inEdgeNode,
                                     bool*                check)
 {
   double param = 0;
-  const SMDS_PositionPtr Pos = n->GetPosition();
-  if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) {
-    const SMDS_EdgePosition* epos =
-      static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
+  const SMDS_PositionPtr pos = n->GetPosition();
+  if ( pos->GetTypeOfPosition()==SMDS_TOP_EDGE )
+  {
+    const SMDS_EdgePosition* epos = static_cast<const SMDS_EdgePosition*>( pos.get() );
     param =  epos->GetUParameter();
   }
-  else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX) {
-    SMESHDS_Mesh * meshDS = GetMeshDS();
-    int vertexID = n->GetPosition()->GetShapeId();
-    const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
-    param =  BRep_Tool::Parameter( V, E );
+  else if( pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
+  {
+    if ( inEdgeNode && TopExp::FirstVertex( E ).IsSame( TopExp::LastVertex( E ))) // issue 0020128
+    {
+      Standard_Real f,l;
+      BRep_Tool::Range( E, f,l );
+      double uInEdge = GetNodeU( E, inEdgeNode );
+      param = ( fabs( uInEdge - f ) < fabs( l - uInEdge )) ? f : l;
+    }
+    else
+    {
+      SMESHDS_Mesh * meshDS = GetMeshDS();
+      int vertexID = pos->GetShapeId();
+      const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
+      param =  BRep_Tool::Parameter( V, E );
+    }
   }
   if ( check )
-    *check = CheckNodeU( E, n, param, BRep_Tool::Tolerance( E ));
+  {
+    double tol = BRep_Tool::Tolerance( E );
+    double f,l;  BRep_Tool::Range( E, f,l );
+    bool force = ( param < f-tol || param > l+tol );
+    if ( !force && pos->GetTypeOfPosition()==SMDS_TOP_EDGE )
+      force = ( GetMeshDS()->ShapeToIndex( E ) != pos->GetShapeId() );
+
+    *check = CheckNodeU( E, n, param, tol, force );
+  }
   return param;
 }
 
@@ -667,6 +687,20 @@ bool SMESH_MesherHelper::CheckNodeU(const TopoDS_Edge&   E,
       {
         ((SMESH_MesherHelper*) this)->myOkNodePosShapes.insert( n->GetPosition()->GetShapeId() );
       }
+      if (( u < f-tol || u > l+tol ) && force )
+      {
+        // node is on vertex but is set on periodic but trimmed edge (issue 0020890)
+        try
+        {
+          // do not use IsPeriodic() as Geom_TrimmedCurve::IsPeriodic () returns false
+          double period = curve->Period();
+          u = ( u < f ) ? u + period : u - period;
+        }
+        catch (Standard_Failure& exc)
+        {
+          return false;
+        }
+      }
     }
   }
   return true;
@@ -739,8 +773,8 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
       E = TopoDS::Edge(myShape);
       edgeID = myShapeID;
     }
-    u[0] = GetNodeU(E,n1, force3d ? 0 : &uvOK[0]);
-    u[1] = GetNodeU(E,n2, force3d ? 0 : &uvOK[1]);
+    u[0] = GetNodeU(E,n1,n2, force3d ? 0 : &uvOK[0]);
+    u[1] = GetNodeU(E,n2,n1, force3d ? 0 : &uvOK[1]);
   }
   if(!force3d)
   {