From 1bd5ff605b98227e89d23c81633e64ecf09867a5 Mon Sep 17 00:00:00 2001
From: ama <ama@opencascade.com>
Date: Thu, 15 Mar 2012 12:54:24 +0400
Subject: [PATCH] 0022849: Bad import of a STEP file (error during
 triangulation)

---
 src/BRepMesh/BRepMesh_FastDiscret.cdl |  7 ++-
 src/BRepMesh/BRepMesh_FastDiscret.cxx | 75 ++++++++++++++++++++++++---
 src/ShapeFix/ShapeFix_Wire.cxx        | 16 +++++-
 3 files changed, 89 insertions(+), 9 deletions(-)

diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cdl b/src/BRepMesh/BRepMesh_FastDiscret.cdl
index 60ba3618ac..9b3fad2060 100755
--- a/src/BRepMesh/BRepMesh_FastDiscret.cdl
+++ b/src/BRepMesh/BRepMesh_FastDiscret.cdl
@@ -114,7 +114,11 @@ is
              ancestor : IndexedDataMapOfShapeListOfShape from TopTools;
              defedge: Real     from Standard;
              first  : Real     from Standard;
-             last   : Real     from Standard)
+             last   : Real     from Standard;
+             tolX   : Real     from Standard;
+             tolY   : Real     from Standard;
+             prevPointInd : out Integer from Standard;
+             firstEdge    : out Boolean from Standard)
         is static private;
 
         Add (me     : mutable;
@@ -323,5 +327,6 @@ fields
       myMapdefle     : DataMapOfShapeReal            from TopTools;
       myNottriangulated : ListOfShape                from TopTools;
       myAllocator    : BaseAllocator                 from BRepMesh;
+      myFirstPointInd: Integer                       from Standard;
 
 end FastDiscret;
diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cxx b/src/BRepMesh/BRepMesh_FastDiscret.cxx
index 15f1c4d223..e8a43e25ed 100755
--- a/src/BRepMesh/BRepMesh_FastDiscret.cxx
+++ b/src/BRepMesh/BRepMesh_FastDiscret.cxx
@@ -350,9 +350,12 @@ void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface,
   TopoDS_Iterator exW(face);
 
   for (; exW.More(); exW.Next()) {
-    const TopoDS_Shape& aWire = exW.Value();
+    TopoDS_Shape aWire = exW.Value();
     if (aWire.ShapeType() != TopAbs_WIRE)
       continue;
+    Standard_Boolean aFirstEdge = Standard_True;
+    Standard_Integer aPrevPointInd;
+    aWire.Orientation (TopAbs_FORWARD);
     TopoDS_Iterator ex(aWire);
     for(; ex.More(); ex.Next()) {
       const TopoDS_Edge& edge = TopoDS::Edge(ex.Value());
@@ -389,7 +392,7 @@ void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface,
       aLSeq.Append(l1);
       aCSeq.Append(C);
       aShSeq.Append(edge);
-      Add(edge, face, gFace, C, theAncestors, defedge, f1, l1);
+      Add(edge, face, gFace, C, theAncestors, defedge, f1, l1, aTolU, aTolV, aPrevPointInd, aFirstEdge);
       myAngle = savangle;
     }
   }
@@ -514,7 +517,8 @@ void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface,
           }
         }
         
-        
+        Standard_Boolean aFirstEdge = Standard_True;
+        Standard_Integer aPrevPointInd;
         for( j1 = 1; j1 <= aShSeq.Length(); j1++)
         {
           const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
@@ -522,7 +526,7 @@ void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface,
           defedge = Max(defedge, eps);
           myMapdefle.Bind(edge, defedge);
           const Handle(Geom2d_Curve)& C = aCSeq.Value(j1);
-          Add(edge, face, gFace, C, theAncestors, defedge, aFSeq.Value(j1), aLSeq.Value(j1));
+          Add(edge, face, gFace, C, theAncestors, defedge, aFSeq.Value(j1), aLSeq.Value(j1), aTolU, aTolV, aPrevPointInd, aFirstEdge);
         }
 
         classifier.Nullify();
@@ -779,7 +783,11 @@ void BRepMesh_FastDiscret::Add( const TopoDS_Edge&                  theEdge,
                                 const TopTools_IndexedDataMapOfShapeListOfShape& theAncestors,
                                 const Standard_Real                 theDefEdge,
                                 const Standard_Real                 theFirst,
-                                const Standard_Real                 theLast)
+                                const Standard_Real                 theLast,
+                                const Standard_Real                 theTolX,
+                                const Standard_Real                 theTolY,
+                                Standard_Integer&                   thePrevPointInd,
+                                Standard_Boolean&                   theFirstEdge)
 {
   const TopAbs_Orientation orEdge = theEdge.Orientation();
   if (orEdge == TopAbs_EXTERNAL) return;
@@ -890,7 +898,6 @@ void BRepMesh_FastDiscret::Add( const TopoDS_Edge&                  theEdge,
   }
   theUV = BRepMesh_FastDiscretFace::FindUV(pBegin, uvFirst, ipf, theGFace, mindist, myLocation2d);
   BRepMesh_Vertex vf(theUV, ipf, BRepMesh_Frontier);
-  Standard_Integer ivf = myStructure->AddNode(vf);
 
   // Process last vertex
   Standard_Integer ipl;
@@ -921,8 +928,63 @@ void BRepMesh_FastDiscret::Add( const TopoDS_Edge&                  theEdge,
   }
   theUV = BRepMesh_FastDiscretFace::FindUV(pEnd, uvLast, ipl, theGFace, mindist, myLocation2d);
   BRepMesh_Vertex vl(theUV, ipl, BRepMesh_Frontier);
+
+  if (!theFirstEdge)
+  {
+    const BRepMesh_Vertex& aPrevVert = myStructure->GetNode (thePrevPointInd);
+    const BRepMesh_Vertex& aFirstVert = myStructure->GetNode (myFirstPointInd);
+    gp_Pnt aFirstPoint = myLocation3d.Find (aFirstVert.Location3d());
+    
+    if (orEdge == TopAbs_FORWARD)
+    {
+      if (Abs (uvFirst.X() - aPrevVert.Coord().X()) > theTolX ||
+          Abs (uvFirst.Y() - aPrevVert.Coord().Y()) > theTolY)
+      {
+        vf.Initialize ((uvFirst.Coord() + aPrevVert.Coord())/2, ipf, BRepMesh_Frontier);
+        myStructure->MoveNode (thePrevPointInd, vf);
+      }
+      if ((Abs (uvLast.X() - aFirstVert.Coord().X()) > theTolX ||
+           Abs (uvLast.Y() - aFirstVert.Coord().Y()) > theTolY) &&
+          aFirstPoint.IsEqual (BRep_Tool::Pnt (pEnd), Precision::Confusion()))
+      {
+        vl.Initialize ((uvLast.Coord() + aFirstVert.Coord())/2, ipl, BRepMesh_Frontier);
+        myStructure->MoveNode (myFirstPointInd, vl);
+      }
+    }
+    if (orEdge == TopAbs_REVERSED)
+    {
+      if (Abs (uvLast.X() - aPrevVert.Coord().X()) > theTolX ||
+          Abs (uvLast.Y() - aPrevVert.Coord().Y()) > theTolY)
+      {
+        vl.Initialize ((uvLast.Coord() + aPrevVert.Coord())/2, ipl, BRepMesh_Frontier);
+        myStructure->MoveNode (thePrevPointInd, vl);
+      }
+      if ((Abs (uvFirst.X() - aFirstVert.Coord().X()) > theTolX ||
+           Abs (uvFirst.Y() - aFirstVert.Coord().Y()) > theTolY) &&
+          aFirstPoint.IsEqual (BRep_Tool::Pnt (pBegin), Precision::Confusion()))
+      {
+        vf.Initialize ((uvFirst.Coord() + aFirstVert.Coord())/2, ipf, BRepMesh_Frontier);
+        myStructure->MoveNode (myFirstPointInd, vf);
+      }
+    }
+  }
+
+  Standard_Integer ivf = myStructure->AddNode(vf);
   Standard_Integer ivl= myStructure->AddNode(vl);
 
+  if (orEdge == TopAbs_FORWARD)
+  {
+    thePrevPointInd = ivl;
+    if (theFirstEdge)
+      myFirstPointInd = ivf;  
+  }
+  if (orEdge == TopAbs_REVERSED)
+  {
+    thePrevPointInd = ivf;
+    if (theFirstEdge)
+      myFirstPointInd = ivl;
+  }
+
   Standard_Integer isvf = myVemap.FindIndex(ivf);
   if (isvf == 0) isvf = myVemap.Add(ivf);
   Standard_Integer isvl = myVemap.FindIndex(ivl);
@@ -1235,6 +1297,7 @@ void BRepMesh_FastDiscret::Add( const TopoDS_Edge&                  theEdge,
     pair1.Append(P1);
     myInternaledges.Bind(theEdge, pair1);
   }
+  theFirstEdge = Standard_False;
 }
 
 
diff --git a/src/ShapeFix/ShapeFix_Wire.cxx b/src/ShapeFix/ShapeFix_Wire.cxx
index 5ed835789f..61d3ebf74b 100755
--- a/src/ShapeFix/ShapeFix_Wire.cxx
+++ b/src/ShapeFix/ShapeFix_Wire.cxx
@@ -2723,6 +2723,14 @@ Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
   gp_Pnt p3d1, p3d2;
   Standard_Real tol1=::Precision::Confusion(), tol2=::Precision::Confusion(); //SK
 
+  Standard_Real pf, pl;
+  gp_Vec2d v1, v2;
+  Handle(Geom2d_Curve) c2d1, c2d2;
+  sae.PCurve (E1, face, c2d1, pf, pl, Standard_True);
+  c2d1->D1 (pl, p2d1, v1);
+  sae.PCurve (E2, face, c2d2, pf, pl, Standard_True);
+  c2d2->D1 (pf, p2d2, v2);
+
   //=============
   //:s2 abv 21 Apr 99: Speculation: try bending pcurves
   Standard_Real bendtol1, bendtol2;
@@ -2805,7 +2813,9 @@ Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
     if ( ! doAddLong && inctol < MaxTolerance() && 
 	 ! myAnalyzer->Surface()->IsDegenerated ( p2d1, p2d2, 2.*tol, 10. ) ) { //:p7
       if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
-	   bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
+	   bendtol1 < inctol && bendtol2 < inctol &&
+	   ! (c2d1->IsKind (STANDARD_TYPE (Geom2d_Line)) && c2d2->IsKind (STANDARD_TYPE (Geom2d_Line)) &&
+	   Abs (Abs (v1.Angle (v2)) - M_PI) < Precision::Angular()) ) doBend = Standard_True;
       else doIncrease = Standard_True;
     }
     else 
@@ -2913,7 +2923,9 @@ Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num,
   // else try to increase tol up to MaxTol
   else if ( inctol > tol && inctol < MaxTolerance() ) {
     if ( ! bendc1.IsNull() && ! bendc2.IsNull() &&
-	 bendtol1 < inctol && bendtol2 < inctol ) doBend = Standard_True;
+	 bendtol1 < inctol && bendtol2 < inctol &&
+	 ! (c2d1->IsKind (STANDARD_TYPE (Geom2d_Line)) && c2d2->IsKind (STANDARD_TYPE (Geom2d_Line)) &&
+	 Abs (Abs (v1.Angle (v2)) - M_PI) < Precision::Angular()) ) doBend = Standard_True;
     else doIncrease = Standard_True;
   }