0026692: BRepMesh hangs on the attached shape due to tessellation points produced...
authoroan <oan@opencascade.com>
Mon, 15 Feb 2016 16:33:29 +0000 (19:33 +0300)
committerabv <abv@opencascade.com>
Sat, 20 Feb 2016 07:10:00 +0000 (10:10 +0300)
BRepMesh_EdgeTessellator: do not use points out of face range and edge tolerance.

Test cases for issue CR26692

src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx
src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx
src/BRepMesh/BRepMesh_EdgeTessellator.cxx
src/BRepMesh/BRepMesh_EdgeTessellator.hxx
src/BRepMesh/BRepMesh_FastDiscret.cxx
src/BRepMesh/BRepMesh_IEdgeTool.hxx
tests/bugs/mesh/bug26692_1 [new file with mode: 0644]
tests/bugs/mesh/bug26692_2 [new file with mode: 0644]

index d01f24d..d85d093 100644 (file)
@@ -45,7 +45,7 @@ BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor(
 //function : Value
 //purpose  : 
 //=======================================================================
-void BRepMesh_EdgeTessellationExtractor::Value(
+Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value(
   const Standard_Integer theIndex,
   Standard_Real&         theParameter,
   gp_Pnt&                thePoint,
@@ -56,4 +56,6 @@ void BRepMesh_EdgeTessellationExtractor::Value(
 
   theParameter = myProvider.Parameter(theIndex, thePoint);
   theUV        = myPCurve->Value(theParameter);
+
+  return Standard_True;
 }
index 82dbc82..5b847d3 100644 (file)
@@ -57,10 +57,12 @@ public:
   //! @param theParameter parameters on PCurve corresponded to the solution.
   //! @param thePoint tessellation point.
   //! @param theUV coordinates of tessellation point in parametric space of face.
-  virtual void Value(const Standard_Integer theIndex,
-                     Standard_Real&         theParameter,
-                     gp_Pnt&                thePoint,
-                     gp_Pnt2d&              theUV) Standard_OVERRIDE;
+  //! @return True in case of valid result, false elewhere.
+  virtual Standard_Boolean Value(
+    const Standard_Integer theIndex,
+    Standard_Real&         theParameter,
+    gp_Pnt&                thePoint,
+    gp_Pnt2d&              theUV) Standard_OVERRIDE;
 
   DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool)
 
index c59079d..d189560 100644 (file)
@@ -54,6 +54,8 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
 
   mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
   mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize);
+  myEdgeSqTol     = BRep_Tool::Tolerance (theEdge);
+  myEdgeSqTol    *= myEdgeSqTol;
 
   Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
   if (isSameParam)
@@ -150,18 +152,54 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
         splitSegment(aSurf, aCurve2d, aParamArray(i), aParamArray(i + 1), 1);
     }
   }
+
+   const Standard_Real aTol = Precision::Confusion();
+   const Standard_Real aDu  = mySurface->UResolution (aTol);
+   const Standard_Real aDv  = mySurface->VResolution (aTol);
+
+   myFaceRangeU[0] = mySurface->FirstUParameter() - aDu;
+   myFaceRangeU[1] = mySurface->LastUParameter()  + aDu;
+
+   myFaceRangeV[0] = mySurface->FirstVParameter() - aDv;
+   myFaceRangeV[1] = mySurface->LastVParameter()  + aDv;
 }
 
 //=======================================================================
 //function : Value
 //purpose  : 
 //=======================================================================
-void BRepMesh_EdgeTessellator::Value(const Standard_Integer theIndex,
-                                     Standard_Real&         theParameter,
-                                     gp_Pnt&                thePoint,
-                                     gp_Pnt2d&              theUV)
+Standard_Boolean BRepMesh_EdgeTessellator::Value(
+  const Standard_Integer theIndex,
+  Standard_Real&         theParameter,
+  gp_Pnt&                thePoint,
+  gp_Pnt2d&              theUV)
 {
   myTool->Value(theIndex, mySurface, theParameter, thePoint, theUV);
+
+  // If point coordinates are out of surface range, 
+  // it is necessary to re-project point.
+  if (mySurface->GetType() != GeomAbs_BSplineSurface &&
+      mySurface->GetType() != GeomAbs_BezierSurface  &&
+      mySurface->GetType() != GeomAbs_OtherSurface)
+  {
+    return Standard_True;
+  }
+
+  // Let skip periodic case.
+  if (mySurface->IsUPeriodic() || mySurface->IsVPeriodic())
+    return Standard_True;
+
+  // Point lies within the surface range - nothing to do.
+  if (theUV.X() > myFaceRangeU[0] && theUV.X() < myFaceRangeU[1] &&
+      theUV.Y() > myFaceRangeV[0] && theUV.Y() < myFaceRangeV[1])
+  {
+    return Standard_True;
+  }
+
+  gp_Pnt aPntOnSurf;
+  mySurface->D0 (theUV.X (), theUV.Y (), aPntOnSurf);
+
+  return (thePoint.SquareDistance (aPntOnSurf) < myEdgeSqTol);
 }
 
 //=======================================================================
index d560f60..80b184d 100644 (file)
@@ -58,10 +58,12 @@ public:
   //! @param theParameter parameters on PCurve corresponded to the solution.
   //! @param thePoint tessellation point.
   //! @param theUV coordinates of tessellation point in parametric space of face.
-  virtual void Value(const Standard_Integer theIndex,
-                     Standard_Real&         theParameter,
-                     gp_Pnt&                thePoint,
-                     gp_Pnt2d&              theUV) Standard_OVERRIDE;
+  //! @return True in case of valid result, false elewhere.
+  virtual Standard_Boolean Value(
+    const Standard_Integer theIndex,
+    Standard_Real&         theParameter,
+    gp_Pnt&                thePoint,
+    gp_Pnt2d&              theUV) Standard_OVERRIDE;
 
   DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool)
 
@@ -80,6 +82,9 @@ private:
   BRepAdaptor_Curve                     myCOnS;
   Standard_Real                         mySquareEdgeDef;
   Standard_Real                         mySquareMinSize;
+  Standard_Real                         myEdgeSqTol;
+  Standard_Real                         myFaceRangeU[2];
+  Standard_Real                         myFaceRangeV[2];
 };
 
 DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
index ff5019d..e78ba1e 100644 (file)
@@ -829,35 +829,44 @@ void BRepMesh_FastDiscret::update(
   else
   {
     const Standard_Integer  aNodesNb = aEdgeTool->NbPoints();
-    TColStd_Array1OfInteger aNewNodes      (1, aNodesNb);
-    TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb);
-    TColStd_Array1OfReal    aNewParams     (1, aNodesNb);
+    TColStd_Array1OfInteger aNewNodesVec        (1, aNodesNb);
+    TColStd_Array1OfInteger aNewNodesInStructVec(1, aNodesNb);
+    TColStd_Array1OfReal    aNewParamsVec       (1, aNodesNb);
 
-    aNewNodInStruct(1) = ipf;
-    aNewNodes      (1) = isvf;
-    aNewParams     (1) = aEAttr.FirstParam;
-
-    aNewNodInStruct(aNodesNb) = ipl;
-    aNewNodes      (aNodesNb) = isvl;
-    aNewParams     (aNodesNb) = aEAttr.LastParam;
+    Standard_Integer aNodesCount = 1;
+    aNewNodesInStructVec(aNodesCount) = ipf;
+    aNewNodesVec        (aNodesCount) = isvf;
+    aNewParamsVec       (aNodesCount) = aEAttr.FirstParam;
 
+    ++aNodesCount;
     Standard_Integer aLastPointId = myAttribute->LastPointId();
     for (Standard_Integer i = 2; i < aNodesNb; ++i)
     {
       gp_Pnt        aPnt;
       gp_Pnt2d      aUV;
       Standard_Real aParam;
-      aEdgeTool->Value(i, aParam, aPnt, aUV);
+      if (!aEdgeTool->Value(i, aParam, aPnt, aUV))
+        continue;
+
       myBoundaryPoints->Bind(++aLastPointId, aPnt);
 
       Standard_Integer iv2, isv;
       myAttribute->AddNode(aLastPointId, aUV.Coord(), BRepMesh_Frontier, iv2, isv);
 
-      aNewNodInStruct(i) = aLastPointId;
-      aNewNodes      (i) = isv;
-      aNewParams     (i) = aParam;
+      aNewNodesInStructVec(aNodesCount) = aLastPointId;
+      aNewNodesVec        (aNodesCount) = isv;
+      aNewParamsVec       (aNodesCount) = aParam;
+      ++aNodesCount;
     }
 
+    aNewNodesInStructVec(aNodesCount) = ipl;
+    aNewNodesVec        (aNodesCount) = isvl;
+    aNewParamsVec       (aNodesCount) = aEAttr.LastParam;
+
+    TColStd_Array1OfInteger aNewNodes      (aNewNodesVec.First (),        1, aNodesCount);
+    TColStd_Array1OfInteger aNewNodInStruct(aNewNodesInStructVec.First(), 1, aNodesCount);
+    TColStd_Array1OfReal    aNewParams     (aNewParamsVec.First(),        1, aNodesCount);
+
     P1 = new Poly_PolygonOnTriangulation(aNewNodes,       aNewParams);
     P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
   }
index c3493e0..6bbd84a 100644 (file)
@@ -33,10 +33,12 @@ public:
   //! @param theParameter parameters on PCurve corresponded to the solution.
   //! @param thePoint tessellation point.
   //! @param theUV coordinates of tessellation point in parametric space of face.
-  virtual void Value(const Standard_Integer theIndex,
-                     Standard_Real&         theParameter,
-                     gp_Pnt&                thePoint,
-                     gp_Pnt2d&              theUV) = 0;
+  //! @return True in case of valid result, false elewhere.
+  virtual Standard_Boolean Value(
+    const Standard_Integer theIndex,
+    Standard_Real&         theParameter,
+    gp_Pnt&                thePoint,
+    gp_Pnt2d&              theUV) = 0;
 
   DEFINE_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient)
 };
diff --git a/tests/bugs/mesh/bug26692_1 b/tests/bugs/mesh/bug26692_1
new file mode 100644 (file)
index 0000000..881959c
--- /dev/null
@@ -0,0 +1,18 @@
+puts "========"
+puts "OCC26692"
+puts "========"
+puts ""
+#######################################################################
+# BRepMesh hangs on the attached shape due to tessellation points produced out of surface range
+#######################################################################
+
+restore [locate_data_file bug26692_face_bad_shading.brep] a
+
+vinit
+vclear
+
+incmesh a 0.1 -a 2
+
+vdisplay a
+vfit
+vdump ${imagedir}/${casename}.png
diff --git a/tests/bugs/mesh/bug26692_2 b/tests/bugs/mesh/bug26692_2
new file mode 100644 (file)
index 0000000..3f8ef7b
--- /dev/null
@@ -0,0 +1,18 @@
+puts "========"
+puts "OCC26692"
+puts "========"
+puts ""
+#######################################################################
+# BRepMesh hangs on the attached shape due to tessellation points produced out of surface range
+#######################################################################
+
+restore [locate_data_file bug26692_face_bad_shading.brep] a
+
+vinit
+vclear
+
+incmesh a 100
+
+vdisplay a
+vfit
+vdump ${imagedir}/${casename}.png