0023777: 2D-Classifier algorithm produces wrong results for a point and face.
authorpkv <pkv@opencascade.com>
Thu, 7 Mar 2013 10:25:51 +0000 (14:25 +0400)
committerpkv <pkv@opencascade.com>
Thu, 7 Mar 2013 10:25:51 +0000 (14:25 +0400)
Adding test case for this fix

src/BRepClass/BRepClass_Intersector.cxx
tests/bugs/modalg_5/bug23777 [new file with mode: 0755]

index f984049..9ddbe6b 100755 (executable)
 #include <IntRes2d_Transition.hxx>
 #include <IntRes2d_IntersectionPoint.hxx>
 
+static 
+  void RefineTolerance(const TopoDS_Face& aF,
+                      const BRepAdaptor_Curve2d& aC,
+                      const Standard_Real aT,
+                      Standard_Real& aTolZ);
+
 //=======================================================================
 //function : BRepClass_Intersector
 //purpose  : 
@@ -53,115 +59,109 @@ BRepClass_Intersector::BRepClass_Intersector()
 //function : Perform
 //purpose  : 
 //=======================================================================
-
 void  BRepClass_Intersector::Perform(const gp_Lin2d& L, 
                                     const Standard_Real P, 
                                     const Standard_Real Tol, 
                                     const BRepClass_Edge& E)
 {
-  
-  Standard_Real pfbid,plbid;
-  if (BRep_Tool::CurveOnSurface(E.Edge(),E.Face(),pfbid,plbid).IsNull()) {
+  Standard_Real deb, fin, aTolZ;
+  Handle(Geom2d_Curve) aC2D;
+  //
+  aTolZ=Tol;
+  const TopoDS_Edge& EE = E.Edge();
+  const TopoDS_Face& F = E.Face();
+  //
+  aC2D=BRep_Tool::CurveOnSurface(EE, F, deb, fin);
+  if (aC2D.IsNull()) {
     done = Standard_False; // !IsDone()
+    return;
   }
-  else {
-    IntRes2d_Domain DL;
-    if(P!=RealLast()) 
-      DL.SetValues(L.Location(),0.,Tol,ElCLib::Value(P,L),P,Tol);
-    else 
-      DL.SetValues(L.Location(),0.,Tol,Standard_True);
-    
-    const TopoDS_Edge& EE = E.Edge();
-    const TopoDS_Face& F = E.Face();
-    TopoDS_Vertex Vdeb, Vfin;
-    TopExp::Vertices(EE, Vdeb, Vfin);
-    BRepAdaptor_Curve2d C(EE,F);
-    Standard_Real deb = C.FirstParameter(), fin = C.LastParameter();
-
-    // Case of "ON": direct check of belonging to edge
-    // taking into account the tolerance
-    Extrema_ExtPC2d theExtPC2d(L.Location(), C);
-    Standard_Real MinDist = RealLast(), aDist;
-    Standard_Integer MinInd = 0, i;
-    if (theExtPC2d.IsDone())
-    {
-      for (i = 1; i <= theExtPC2d.NbExt(); i++)
-      {
-        aDist = theExtPC2d.SquareDistance(i);
-        if (aDist < MinDist)
-        {
-          MinDist = aDist;
-          MinInd = i;
-        }
+  //
+  BRepAdaptor_Curve2d C(EE, F);
+  //
+  deb = C.FirstParameter();
+  fin = C.LastParameter();
+  //
+  // Case of "ON": direct check of belonging to edge
+  // taking into account the tolerance
+  Extrema_ExtPC2d theExtPC2d(L.Location(), C);
+  Standard_Real MinDist = RealLast(), aDist;
+  Standard_Integer MinInd = 0, i;
+  if (theExtPC2d.IsDone()) {
+    for (i = 1; i <= theExtPC2d.NbExt(); ++i) {
+      aDist = theExtPC2d.SquareDistance(i);
+      if (aDist < MinDist) {
+       MinDist = aDist;
+       MinInd = i;
       }
     }
-    if (MinInd)
-      MinDist = sqrt(MinDist);
-    if (MinDist <= Tol)
-    {
-      gp_Pnt2d pnt_exact = (theExtPC2d.Point(MinInd)).Value();
-      Standard_Real par = (theExtPC2d.Point(MinInd)).Parameter();
+  }
+  if (MinInd) {
+    MinDist = sqrt(MinDist);
+  }
+  if (MinDist <= aTolZ) {
+    gp_Pnt2d pnt_exact = (theExtPC2d.Point(MinInd)).Value();
+    Standard_Real par = (theExtPC2d.Point(MinInd)).Parameter();
+    //
+    RefineTolerance(F, C, par, aTolZ);
+    //
+    if (MinDist <= aTolZ) {
       IntRes2d_Transition tr_on_lin(IntRes2d_Head);
       IntRes2d_Position pos_on_curve = IntRes2d_Middle;
-      if (Abs(par - deb) <= Precision::Confusion())
-        pos_on_curve = IntRes2d_Head;
-      else if (Abs(par - fin) <= Precision::Confusion())
-        pos_on_curve = IntRes2d_End;
+      if (Abs(par - deb) <= Precision::Confusion()) {
+       pos_on_curve = IntRes2d_Head;
+      }
+      else if (Abs(par - fin) <= Precision::Confusion()) {
+       pos_on_curve = IntRes2d_End;
+      }
+      //
       IntRes2d_Transition tr_on_curve(pos_on_curve);
       IntRes2d_IntersectionPoint pnt_inter(pnt_exact, 0., par,
-                                           tr_on_lin, tr_on_curve, Standard_False);
-      this->Append(pnt_inter);
+                                          tr_on_lin, tr_on_curve, 
+                                          Standard_False);
+      //
+      Append(pnt_inter);
       done = Standard_True;
       return;
     }
-    ///////////////
-    
-    gp_Pnt2d pdeb,pfin;
-    C.D0(deb,pdeb);
-    C.D0(fin,pfin);
-    Standard_Real toldeb = 1.e-5, tolfin = 1.e-5;
-#if 0 
-    // essai de calcul juste des tolerances du domaine
-    // qui ne couche pas avec les modeles pourris de 
-    // styler !!
-    BRepAdaptor_Surface S(F);
-    gp_Vec2d vdeb,vfin;
-    C.D1(deb,pdeb,vdeb);
-    C.D1(fin,pfin,vfin);
-    gp_Pnt P; gp_Vec DU, DV;
-    S.D1(pdeb.X(),pdeb.Y(),P,DU,DV);
-    Standard_Real scaldeb = (vdeb.X()*DU + vdeb.Y()*DV).Magnitude();
-    scaldeb = Max(scaldeb, 1.e-5);
-    toldeb = BRep_Tool::Tolerance(Vdeb)/scaldeb;
-    S.D1(pfin.X(),pfin.Y(),P,DU,DV);
-    Standard_Real scalfin = (vfin.X()*DU + vfin.Y()*DV).Magnitude();
-    scalfin = Max(scalfin, 1.e-5);
-    tolfin = BRep_Tool::Tolerance(Vfin)/scalfin;
-#endif
-    
-    IntRes2d_Domain DE(pdeb,deb,toldeb,pfin,fin,tolfin);
-    // temporary periodic domain
-    if (C.Curve()->IsPeriodic()) {
-      DE.SetEquivalentParameters(C.FirstParameter(),
-                                C.FirstParameter() + 
-                                C.Curve()->LastParameter() -
-                                C.Curve()->FirstParameter());
-    }
-    
-    Handle(Geom2d_Line) GL= new Geom2d_Line(L);
-    Geom2dAdaptor_Curve CGA(GL);
-    Geom2dInt_GInter Inter(CGA,DL,C,DE,
-                          Precision::PConfusion(),
-                          Precision::PIntersection());
-    this->SetValues(Inter);
   }
+  //  
+  gp_Pnt2d pdeb,pfin;
+  C.D0(deb,pdeb);
+  C.D0(fin,pfin);
+  Standard_Real toldeb = 1.e-5, tolfin = 1.e-5;
+  IntRes2d_Domain DL;
+  //
+  if(P!=RealLast()) {
+    DL.SetValues(L.Location(),0.,aTolZ,ElCLib::Value(P,L),P,aTolZ);
+  }
+  else { 
+    DL.SetValues(L.Location(),0.,aTolZ,Standard_True);
+  }
+  IntRes2d_Domain DE(pdeb,deb,toldeb,pfin,fin,tolfin);
+  // temporary periodic domain
+  if (C.Curve()->IsPeriodic()) {
+    DE.SetEquivalentParameters(C.FirstParameter(),
+                              C.FirstParameter() + 
+                              C.Curve()->LastParameter() -
+                              C.Curve()->FirstParameter());
+  }
+  
+  Handle(Geom2d_Line) GL= new Geom2d_Line(L);
+  Geom2dAdaptor_Curve CGA(GL);
+  Geom2dInt_GInter Inter(CGA,DL,C,DE,
+                        Precision::PConfusion(),
+                        Precision::PIntersection());
+  //
+  SetValues(Inter);
 }
 
 //=======================================================================
 //function : LocalGeometry
 //purpose  : 
 //=======================================================================
-
 void  BRepClass_Intersector::LocalGeometry(const BRepClass_Edge& E, 
                                           const Standard_Real U, 
                                           gp_Dir2d& Tang, 
@@ -179,7 +179,40 @@ void  BRepClass_Intersector::LocalGeometry(const BRepClass_Edge& E,
     Norm.SetCoord(Tang.Y(),-Tang.X());
 }
 
-
-
+//=======================================================================
+//function : RefineTolerance
+//purpose  : 
+//=======================================================================
+void RefineTolerance(const TopoDS_Face& aF,
+                    const BRepAdaptor_Curve2d& aC,
+                    const Standard_Real aT,
+                    Standard_Real& aTolZ)
+{
+  GeomAbs_SurfaceType aTypeS;
+  //
+  BRepAdaptor_Surface aBAS(aF, Standard_False);
+  //
+  aTypeS=aBAS.GetType();
+  if (aTypeS==GeomAbs_Cylinder) {
+    Standard_Real aURes, aVRes, aTolX;
+    gp_Pnt2d aP2D;
+    gp_Vec2d aV2D;
+    //
+    aURes=aBAS.UResolution(aTolZ);
+    aVRes=aBAS.VResolution(aTolZ);
+    //
+    aC.D1(aT, aP2D, aV2D);
+    gp_Dir2d aD2D(aV2D);
+    //
+    aTolX=aURes*aD2D.Y()+aVRes*aD2D.X();
+    if (aTolX<0.) {
+      aTolX=-aTolX;
+    }
+    //
+    if (aTolX<aTolZ) {
+      aTolZ=aTolX;
+    }
+  }
+}
 
 
diff --git a/tests/bugs/modalg_5/bug23777 b/tests/bugs/modalg_5/bug23777
new file mode 100755 (executable)
index 0000000..f02473f
--- /dev/null
@@ -0,0 +1,22 @@
+puts "================"
+puts "OCC23777"
+puts "================"
+puts ""
+#######################################################################
+# 2D-Classifier algorithm produces wrong results for a point and face.
+#######################################################################
+
+set BugNumber OCC23777
+
+restore [locate_data_file bug23777_b1.brep] b1
+
+point p2D 0.062260538576946696 249583.00418413401
+
+set info [b2dclassify b1 p2D]
+set check [regexp "IN" $info]
+
+if { ${check} == 1 } {
+    puts "OK ${BugNumber}"
+} else {
+    puts "Faulty ${BugNumber}"
+}