diff --git a/src/BRepClass/BRepClass_Edge.cxx b/src/BRepClass/BRepClass_Edge.cxx index c4cbc4409e..0774105f1e 100644 --- a/src/BRepClass/BRepClass_Edge.cxx +++ b/src/BRepClass/BRepClass_Edge.cxx @@ -16,8 +16,10 @@ #include -#include -#include +#include +#include +#include +#include //======================================================================= //function : BRepClass_Edge @@ -27,6 +29,37 @@ BRepClass_Edge::BRepClass_Edge() { } +//======================================================================= +//function : SetNextEdge +//purpose : +//======================================================================= +void BRepClass_Edge::SetNextEdge(const TopTools_IndexedDataMapOfShapeListOfShape& theMapVE) +{ + if (theMapVE.IsEmpty() || myEdge.IsNull()) + { + return; + } + TopoDS_Vertex aVF, aVL; + TopExp::Vertices(myEdge, aVF, aVL, Standard_True); + + if (aVL.IsNull() || aVL.IsSame(aVF)) + { + return; + } + const TopTools_ListOfShape* aListE = theMapVE.Seek(aVL); + if ((*aListE).Extent() == 2) + { + for (TopTools_ListIteratorOfListOfShape anIt(*aListE); anIt.More(); anIt.Next()) + { + if ((!anIt.Value().IsNull()) && (!anIt.Value().IsSame(myEdge))) + { + myNextEdge = TopoDS::Edge(anIt.Value()); + } + } + } +} + + //======================================================================= //function : BRepClass_Edge //purpose : diff --git a/src/BRepClass/BRepClass_Edge.hxx b/src/BRepClass/BRepClass_Edge.hxx index 9c07502986..fe742f363c 100644 --- a/src/BRepClass/BRepClass_Edge.hxx +++ b/src/BRepClass/BRepClass_Edge.hxx @@ -20,11 +20,10 @@ #include #include #include +#include #include #include -class TopoDS_Edge; -class TopoDS_Face; //! This class is used to send the description of an @@ -41,13 +40,22 @@ public: Standard_EXPORT BRepClass_Edge(const TopoDS_Edge& E, const TopoDS_Face& F); - TopoDS_Edge& Edge(); + //! Returns the current Edge + TopoDS_Edge& Edge(); const TopoDS_Edge& Edge() const; - TopoDS_Face& Face(); + //! Returns the Face for the current Edge + TopoDS_Face& Face(); const TopoDS_Face& Face() const; + //! Returns the next Edge + const TopoDS_Edge& NextEdge() const + { + return myNextEdge; + } + //! Finds and sets the next Edge for the current + Standard_EXPORT void SetNextEdge(const TopTools_IndexedDataMapOfShapeListOfShape& theMapVE); protected: @@ -62,7 +70,7 @@ private: TopoDS_Edge myEdge; TopoDS_Face myFace; - + TopoDS_Edge myNextEdge; }; diff --git a/src/BRepClass/BRepClass_FaceExplorer.cxx b/src/BRepClass/BRepClass_FaceExplorer.cxx index 1c9c7069e5..93ccbd95ad 100644 --- a/src/BRepClass/BRepClass_FaceExplorer.cxx +++ b/src/BRepClass/BRepClass_FaceExplorer.cxx @@ -22,11 +22,9 @@ #include #include #include -#include -#include #include #include -#include +#include #include static const Standard_Real Probing_Start = 0.123; @@ -311,6 +309,8 @@ Standard_Boolean BRepClass_FaceExplorer::RejectWire void BRepClass_FaceExplorer::InitEdges() { myEExplorer.Init(myWExplorer.Current(),TopAbs_EDGE); + myMapVE.Clear(); + TopExp::MapShapesAndAncestors(myWExplorer.Current(), TopAbs_VERTEX, TopAbs_EDGE, myMapVE); } //======================================================================= @@ -337,5 +337,6 @@ void BRepClass_FaceExplorer::CurrentEdge(BRepClass_Edge& E, E.Edge() = TopoDS::Edge(myEExplorer.Current()); E.Face() = myFace; Or = E.Edge().Orientation(); + E.SetNextEdge(myMapVE); } diff --git a/src/BRepClass/BRepClass_FaceExplorer.hxx b/src/BRepClass/BRepClass_FaceExplorer.hxx index bdb14b1d72..d075136069 100644 --- a/src/BRepClass/BRepClass_FaceExplorer.hxx +++ b/src/BRepClass/BRepClass_FaceExplorer.hxx @@ -20,14 +20,14 @@ #include #include #include +#include +#include #include #include #include #include #include -#include -class TopoDS_Face; class gp_Pnt2d; class gp_Lin2d; class BRepClass_Edge; @@ -112,6 +112,7 @@ private: TopExp_Explorer myEExplorer; Standard_Integer myCurEdgeInd; Standard_Real myCurEdgePar; + TopTools_IndexedDataMapOfShapeListOfShape myMapVE; Standard_Real myUMin; Standard_Real myUMax; diff --git a/src/BRepClass/BRepClass_Intersector.cxx b/src/BRepClass/BRepClass_Intersector.cxx index 0f09a60ee0..8e0cf6d81c 100644 --- a/src/BRepClass/BRepClass_Intersector.cxx +++ b/src/BRepClass/BRepClass_Intersector.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -48,15 +49,225 @@ void RefineTolerance(const TopoDS_Face& aF, const Standard_Real aT, Standard_Real& aTolZ); +static +Standard_Boolean CheckOn(IntRes2d_IntersectionPoint& thePntInter, + const TopoDS_Face& theF, + const gp_Lin2d& theL, + Geom2dAdaptor_Curve& theCur, + Standard_Real theTolZ, + Standard_Real theFin, + Standard_Real theDeb); + +static +void CheckSkip(Geom2dInt_GInter& theInter, + const gp_Lin2d& theL, + const BRepClass_Edge& theE, + const Handle(Geom2d_Curve)& theC2D, + const IntRes2d_Domain& theDL, + Geom2dAdaptor_Curve& theCur, + const Geom2dAdaptor_Curve& theCGA, + Standard_Real theFin, + Standard_Real theDeb, + Standard_Real theMaxTol, + gp_Pnt2d thePdeb, + gp_Pnt2d thePfin); + + //======================================================================= //function : BRepClass_Intersector //purpose : //======================================================================= -BRepClass_Intersector::BRepClass_Intersector() +BRepClass_Intersector::BRepClass_Intersector() : myMaxTolerance(0.1) { } +//======================================================================= +//function : CheckOn +//purpose : +//======================================================================= +Standard_Boolean CheckOn(IntRes2d_IntersectionPoint& thePntInter, + const TopoDS_Face& theF, + const gp_Lin2d& theL, + Geom2dAdaptor_Curve& theCur, + Standard_Real theTolZ, + Standard_Real theFin, + Standard_Real theDeb) +{ + Extrema_ExtPC2d anExtPC2d(theL.Location(), theCur); + Standard_Real aMinDist = RealLast(); + Standard_Integer aMinInd = 0; + if (anExtPC2d.IsDone()) + { + const Standard_Integer aNbPnts = anExtPC2d.NbExt(); + for (Standard_Integer i = 1; i <= aNbPnts; ++i) + { + Standard_Real aDist = anExtPC2d.SquareDistance(i); + + if (aDist < aMinDist) + { + aMinDist = aDist; + aMinInd = i; + } + } + } + + if (aMinInd != 0) { + aMinDist = Sqrt(aMinDist); + } + if (aMinDist <= theTolZ) { + gp_Pnt2d aPntExact = (anExtPC2d.Point(aMinInd)).Value(); + Standard_Real aPar = (anExtPC2d.Point(aMinInd)).Parameter(); + // + RefineTolerance(theF, theCur, aPar, theTolZ); + // + if (aMinDist <= theTolZ) { + IntRes2d_Transition aTrOnLin(IntRes2d_Head); + IntRes2d_Position aPosOnCurve = IntRes2d_Middle; + if (Abs(aPar - theDeb) <= Precision::Confusion()) { + aPosOnCurve = IntRes2d_Head; + } + else if (Abs(aPar - theFin) <= Precision::Confusion()) { + aPosOnCurve = IntRes2d_End; + } + // + IntRes2d_Transition aTrOnCurve(aPosOnCurve); + thePntInter = IntRes2d_IntersectionPoint(aPntExact, 0., aPar, + aTrOnLin, aTrOnCurve, + Standard_False); + // + return Standard_True; + } + } + return Standard_False; +} + +//======================================================================= +//function : CheckSkip +//purpose : +//======================================================================= +void CheckSkip(Geom2dInt_GInter& theInter, + const gp_Lin2d& theL, + const BRepClass_Edge& theE, + const Handle(Geom2d_Curve)& theC2D, + const IntRes2d_Domain& theDL, + Geom2dAdaptor_Curve& theCur, + const Geom2dAdaptor_Curve& theCGA, + Standard_Real theFin, + Standard_Real theDeb, + Standard_Real theMaxTol, + gp_Pnt2d thePdeb, + gp_Pnt2d thePfin) +{ + if (theE.Edge().IsNull() || theE.Face().IsNull()) + { + return; + } + Standard_Boolean anIsLSkip = Standard_False; + TopoDS_Vertex aVl; // the last vertex of current edge + + Handle(Geom2d_Curve) aSkipC2D; + + aVl = TopExp::LastVertex(theE.Edge(), Standard_True); + if (aVl.IsNull()) + { + return; + } + const TopoDS_Edge anEl = theE.NextEdge(); // the next edge + if (!(BRep_Tool::Tolerance(aVl) > theMaxTol) || theE.NextEdge().IsNull()) + { + return; + } + Standard_Real aLdeb = 0.0, aLfin = 0.0; + Handle(Geom2d_Curve) aLC2D; // the next curve + + aLC2D = BRep_Tool::CurveOnSurface(theE.NextEdge(), theE.Face(), aLdeb, aLfin); + if (aLC2D.IsNull()) + { + return; + } + Standard_Real anA, aB, aC; // coefficients of the straight line + Standard_Real aX1, anY1, aX2, anY2; // coordinates of the ends of edges + gp_Pnt2d aP1, aP2; // the ends of edges + + theL.Coefficients(anA, aB, aC); + + Standard_Real at1 = theFin; + if (theE.Edge().Orientation() != TopAbs_FORWARD) + { + at1 = theDeb; + } + + Standard_Real at2 = aLdeb; + if (theE.NextEdge().Orientation() != TopAbs_FORWARD) + { + at2 = aLfin; + } + + aP1 = theC2D->Value(at1); + aP2 = aLC2D->Value(at2); + + // Check if points belong to DL domain + Standard_Real aPar1 = ElCLib::Parameter(theL, aP1); + Standard_Real aPar2 = ElCLib::Parameter(theL, aP2); + + if (!(aPar1 > theDL.FirstParameter() && aPar1 < theDL.LastParameter()) || + !(aPar2 > theDL.FirstParameter() && aPar2 < theDL.LastParameter())) + { + return; + } + aX1 = aP1.X(); anY1 = aP1.Y(); aX2 = aP2.X(); anY2 = aP2.Y(); + Standard_Real aFV = anA * aX1 + aB * anY1 + aC; + Standard_Real aSV = anA * aX2 + aB * anY2 + aC; + + // Check for getting into vertex with high tolerance + if ((aFV * aSV) >= 0) + { + anIsLSkip = Standard_False; + } + else + { + anIsLSkip = Standard_True; + GCE2d_MakeSegment aMkSeg(aP1, aP2); + if (!aMkSeg.IsDone()) + { + return; + } + aSkipC2D = aMkSeg.Value(); + + if (aSkipC2D.IsNull() || !anIsLSkip) + { + return; + } + // if we got + theCur.Load(aSkipC2D); + if (theCur.Curve().IsNull()) + { + return; + } + Standard_Real atoldeb = 1.e-5, atolfin = 1.e-5; + + theDeb = theCur.FirstParameter(); + theFin = theCur.LastParameter(); + theCur.D0(theDeb, thePdeb); + theCur.D0(theFin, thePfin); + + IntRes2d_Domain aDE(thePdeb, theDeb, atoldeb, thePfin, theFin, atolfin); + // temporary periodic domain + if (theCur.Curve()->IsPeriodic()) + { + aDE.SetEquivalentParameters(theCur.FirstParameter(), + theCur.FirstParameter() + + theCur.Curve()->LastParameter() - + theCur.Curve()->FirstParameter()); + } + + theInter = Geom2dInt_GInter(theCGA, theDL, theCur, aDE, + Precision::PConfusion(), + Precision::PIntersection()); + } +} + //======================================================================= //function : Perform //purpose : @@ -86,53 +297,17 @@ void BRepClass_Intersector::Perform(const gp_Lin2d& L, // // Case of "ON": direct check of belonging to edge // taking into account the tolerance - Extrema_ExtPC2d anExtPC2d(L.Location(), C); - Standard_Real MinDist = RealLast(), aDist; - Standard_Integer MinInd = 0, i; - if (anExtPC2d.IsDone()) + Standard_Boolean aStatusOn = Standard_False; + IntRes2d_IntersectionPoint aPntInter; + + aStatusOn = CheckOn(aPntInter, F, L, C, aTolZ, fin, deb); + if (aStatusOn) { - const Standard_Integer aNbPnts = anExtPC2d.NbExt(); - for (i = 1; i <= aNbPnts; ++i) - { - aDist = anExtPC2d.SquareDistance(i); - - if (aDist < MinDist) - { - MinDist = aDist; - MinInd = i; - } - } - } - - if (MinInd) { - MinDist = sqrt(MinDist); - } - if (MinDist <= aTolZ) { - gp_Pnt2d pnt_exact = (anExtPC2d.Point(MinInd)).Value(); - Standard_Real par = (anExtPC2d.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; - } - // - IntRes2d_Transition tr_on_curve(pos_on_curve); - IntRes2d_IntersectionPoint pnt_inter(pnt_exact, 0., par, - tr_on_lin, tr_on_curve, - Standard_False); - // - Append(pnt_inter); - done = Standard_True; - return; - } + Append(aPntInter); + done = Standard_True; + return; } + // gp_Pnt2d pdeb,pfin; C.D0(deb,pdeb); @@ -163,6 +338,15 @@ void BRepClass_Intersector::Perform(const gp_Lin2d& L, Precision::PConfusion(), Precision::PIntersection()); // + // The check is for hitting the intersector to + // a vertex with high tolerance + if (Inter.IsEmpty()) + { + CheckSkip(Inter, L, E, aC2D, DL, + C, CGA, fin, deb, MaxTolerance(), pdeb, pfin); + } + + // SetValues(Inter); } diff --git a/src/BRepClass/BRepClass_Intersector.hxx b/src/BRepClass/BRepClass_Intersector.hxx index e1b174298c..279b34c97a 100644 --- a/src/BRepClass/BRepClass_Intersector.hxx +++ b/src/BRepClass/BRepClass_Intersector.hxx @@ -47,6 +47,18 @@ public: //! . Standard_EXPORT void LocalGeometry (const BRepClass_Edge& E, const Standard_Real U, gp_Dir2d& T, gp_Dir2d& N, Standard_Real& C) const; + //! Returns the maximum tolerance + Standard_Real MaxTolerance() + { + return myMaxTolerance; + } + + //! Sets the maximum tolerance at + //! which to start checking in the intersector + void SetMaxTolerance(const Standard_Real theValue) + { + myMaxTolerance = theValue; + } @@ -59,7 +71,7 @@ protected: private: - + Standard_Real myMaxTolerance; }; diff --git a/tests/bugs/modalg_6/bug31047 b/tests/bugs/modalg_6/bug31047 new file mode 100644 index 0000000000..dae902f778 --- /dev/null +++ b/tests/bugs/modalg_6/bug31047 @@ -0,0 +1,17 @@ +puts "=================================================================" +puts "OCC31047: BRepExtrema_DistShapeShape gives wrong result" +puts "=================================================================" +puts "" + +restore [locate_data_file bug31047.brep] f + +point p1 -79 -282.7 +point p2 -79 -282.6 + +if ![regexp "IN" [b2dclassify f p1]] { + puts "Error: inner point p1 is classified as OUT" +} + +if ![regexp "IN" [b2dclassify f p2]] { + puts "Error: inner point p2 is classified as OUT" +}