0027434: Wrong result of classification of the point in "infinity"
authoraka <aka@opencascade.com>
Thu, 8 Dec 2016 13:33:47 +0000 (16:33 +0300)
committerapn <apn@opencascade.com>
Thu, 8 Dec 2016 13:34:18 +0000 (16:34 +0300)
In the case of infinite point due to not enough machine precision the distance from the point to each edge of the face is computed the same, and the algorithm cannot correctly select the nearest edge. To solve this problem checking of point was added, if the point is located too far from the bounding box of the face, then it will be replaced with another point located on the line between the point and the center of the bounding box.
    The new point has the same state as initial one but its state can be resolved without ambiguity.

Corrections in CheckPoint method
Small correction of test case for issue CR27434

src/BRepClass/BRepClass_FaceExplorer.cxx
src/BRepClass/BRepClass_FaceExplorer.hxx
src/Geom2dHatch/Geom2dHatch_Elements.cxx
src/Geom2dHatch/Geom2dHatch_Elements.hxx
src/TopClass/TopClass_FaceClassifier.gxx
tests/bugs/modalg_6/bug27434 [new file with mode: 0644]

index cee8ce6..3fb9b5b 100644 (file)
@@ -20,6 +20,7 @@
 #include <BRep_Tool.hxx>
 #include <BRepClass_Edge.hxx>
 #include <BRepClass_FaceExplorer.hxx>
+#include <BRepTools.hxx>
 #include <Geom2d_Curve.hxx>
 #include <gp_Lin2d.hxx>
 #include <gp_Pnt2d.hxx>
@@ -45,6 +46,51 @@ BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
 }
 
 //=======================================================================
+//function : CheckPoint
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean  BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
+{
+  Standard_Real anUMin = 0.0, anUMax = 0.0, aVMin = 0.0, aVMax = 0.0;
+  TopLoc_Location aLocation;
+  const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(myFace, aLocation);
+  aSurface->Bounds(anUMin, anUMax, aVMin, aVMax);
+  if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
+      Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
+  {
+    BRepTools::UVBounds(myFace, anUMin, anUMax, aVMin, aVMax);
+    if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
+        Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
+    {
+      return Standard_True;
+    }
+  }
+
+  gp_Pnt2d aCenterPnt(( anUMin + anUMax ) / 2, ( aVMin + aVMax ) / 2);
+  Standard_Real aDistance = aCenterPnt.Distance(thePoint);
+  if (Precision::IsInfinite(aDistance))
+  {
+    thePoint.SetCoord(anUMin - ( anUMax - anUMin ),
+                       aVMin - ( aVMax - aVMin ));
+    return Standard_False;
+  }
+  else
+  {
+    Standard_Real anEpsilon = Epsilon(aDistance);
+    if (anEpsilon > Max(anUMax - anUMin, aVMax - aVMin))
+    {
+      gp_Vec2d aLinVec(aCenterPnt, thePoint);
+      gp_Dir2d aLinDir(aLinVec);
+      thePoint = aCenterPnt.XY() + aLinDir.XY() * ( 2. * anEpsilon );
+      return Standard_False;
+    }
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
 //function : Reject
 //purpose  : 
 //=======================================================================
index 54e03ec..3e404b8 100644 (file)
@@ -43,6 +43,12 @@ public:
 
   
   Standard_EXPORT BRepClass_FaceExplorer(const TopoDS_Face& F);
+
+  //! Checks the point and change its coords if it is located too far
+  //! from the bounding box of the face. New Coordinates of the point 
+  //! will be on the line between the point and the center of the 
+  //! bounding box. Returns True if point was not changed.
+  Standard_EXPORT Standard_Boolean CheckPoint (gp_Pnt2d& thePoint);
   
   //! Should  return  True  if the  point  is  outside a
   //! bounding volume of the face.
index c9e6354..d487ee7 100644 (file)
@@ -74,6 +74,16 @@ Geom2dHatch_Element& Geom2dHatch_Elements::ChangeFind(const Standard_Integer K)
 }
 
 //=======================================================================
+//function : CheckPoint
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean  Geom2dHatch_Elements::CheckPoint(gp_Pnt2d&)
+{
+  return Standard_True;
+}
+
+//=======================================================================
 //function : Reject
 //purpose  : 
 //=======================================================================
index 3106c52..5ef0623 100644 (file)
@@ -70,7 +70,8 @@ Geom2dHatch_Element& operator() (const Standard_Integer K)
 {
   return ChangeFind(K);
 }
-  
+  Standard_EXPORT Standard_Boolean CheckPoint (gp_Pnt2d& P);
+
   Standard_EXPORT Standard_Boolean Reject (const gp_Pnt2d& P) const;
   
   Standard_EXPORT Standard_Boolean Segment (const gp_Pnt2d& P, gp_Lin2d& L, Standard_Real& Par);
index 8740ed5..7f86749 100644 (file)
 //purpose  : 
 //=======================================================================
 
-TopClass_FaceClassifier::TopClass_FaceClassifier()
+TopClass_FaceClassifier::TopClass_FaceClassifier() :
+myEdgeParameter(0.0),
+rejected(Standard_False),
+nowires(Standard_True)
 {
 }
 
@@ -36,7 +39,10 @@ TopClass_FaceClassifier::TopClass_FaceClassifier()
 
 TopClass_FaceClassifier::TopClass_FaceClassifier(TheFaceExplorer& FExp,
                                                 const gp_Pnt2d& P,
-                                                const Standard_Real Tol)
+                                                const Standard_Real Tol) :
+myEdgeParameter(0.0),
+rejected(Standard_False),
+nowires(Standard_True)
 {
   Perform(FExp,P,Tol);
 }
@@ -50,15 +56,22 @@ void TopClass_FaceClassifier::Perform(TheFaceExplorer& Fexp,
                                      const gp_Pnt2d& P,
                                      const Standard_Real Tol)
 {
+  gp_Pnt2d aPoint(P);
+  Standard_Boolean aResOfPointCheck = Standard_False;
+  while (aResOfPointCheck == Standard_False)
+  {
+    aResOfPointCheck = Fexp.CheckPoint(aPoint);
+  }
+
   // Test for rejection.
-  rejected = Fexp.Reject(P);
+  rejected = Fexp.Reject(aPoint);
 
   if (rejected)
     return;
 
   gp_Lin2d                   aLine;
   Standard_Real              aParam;
-  Standard_Boolean           IsValidSegment = Fexp.Segment(P, aLine, aParam);
+  Standard_Boolean           IsValidSegment = Fexp.Segment(aPoint, aLine, aParam);
   TheEdge                    anEdge;
   TopAbs_Orientation         anEdgeOri;
   Standard_Integer           aClosestInd;
@@ -135,7 +148,7 @@ void TopClass_FaceClassifier::Perform(TheFaceExplorer& Fexp,
       break;
 
     // Bad case for classification. Trying to get another segment.
-    IsValidSegment = Fexp.OtherSegment(P, aLine, aParam);
+    IsValidSegment = Fexp.OtherSegment(aPoint, aLine, aParam);
   }
 }
 
diff --git a/tests/bugs/modalg_6/bug27434 b/tests/bugs/modalg_6/bug27434
new file mode 100644 (file)
index 0000000..efef2c5
--- /dev/null
@@ -0,0 +1,21 @@
+puts "============"
+puts "OCC27434"
+puts "============"
+puts ""
+###############################
+## Wrong result of classification of the point in "infinity".
+###############################
+
+set BugNumber OCC27434
+
+restore [locate_data_file bug27434_ff.brep] ff
+point pp 3.5104958975622309 1.4497931574922160e+031
+
+set info [b2dclassify ff pp]
+set check [regexp "OUT" $info]
+
+if { ${check} == 1 } {
+    puts "OK ${BugNumber}"
+} else {
+    puts "Faulty ${BugNumber}"
+}