From 8f9a9b9d104440ba53d4af051b830ba5e3df8152 Mon Sep 17 00:00:00 2001 From: pkv Date: Thu, 7 Mar 2013 14:25:51 +0400 Subject: [PATCH] 0023777: 2D-Classifier algorithm produces wrong results for a point and face. Adding test case for this fix --- src/BRepClass/BRepClass_Intersector.cxx | 209 ++++++++++++++---------- tests/bugs/modalg_5/bug23777 | 22 +++ 2 files changed, 143 insertions(+), 88 deletions(-) create mode 100755 tests/bugs/modalg_5/bug23777 diff --git a/src/BRepClass/BRepClass_Intersector.cxx b/src/BRepClass/BRepClass_Intersector.cxx index f984049971..9ddbe6bf5c 100755 --- a/src/BRepClass/BRepClass_Intersector.cxx +++ b/src/BRepClass/BRepClass_Intersector.cxx @@ -40,6 +40,12 @@ #include #include +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