From: emv Date: Wed, 4 Sep 2019 13:25:49 +0000 (+0300) Subject: Provide possibility to check the ON status of the point for the face using the real... X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=d7fe70f95c09ae74e820e35505c0c980fc4ba72f;p=occt-copy.git Provide possibility to check the ON status of the point for the face using the real tolerances of the sub-shapes of the face. --- diff --git a/src/BOPTest/BOPTest_LowCommands.cxx b/src/BOPTest/BOPTest_LowCommands.cxx index b863f411d1..9f0fc9a078 100644 --- a/src/BOPTest/BOPTest_LowCommands.cxx +++ b/src/BOPTest/BOPTest_LowCommands.cxx @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -68,9 +69,13 @@ static Standard_Integer bhaspc (Draw_Interpretor& , Standard_Integer , con const char* g = "BOPTest commands"; theCommands.Add("bclassify" , "use bclassify Solid Point [Tolerance=1.e-7]", __FILE__, bclassify , g); - theCommands.Add("b2dclassify" , "use b2dclassify Face Point2d [Tol] ", + theCommands.Add("b2dclassify", "Classifies the point relatively face. If no point is given, classifies the infinite point\n" + "Uses BRepClass_FaceClassifier for classification\n" + "Usage: b2dclassify Face [Point2d] [Tol]", __FILE__, b2dclassify , g); - theCommands.Add("b2dclassifx" , "use b2dclassifx Face Point2d [Tol] ", + theCommands.Add("b2dclassifx", "Classifies the point relatively face. If no point is given, classifies the infinite point\n" + "Uses IntTools_FClass2d for classification\n" + "Usage: b2dclassifx Face [Point2d] [Tol]", __FILE__, b2dclassifx , g); theCommands.Add("bhaspc" , "use bhaspc Edge Face [do]", __FILE__, bhaspc , g); @@ -83,35 +88,48 @@ static Standard_Integer bhaspc (Draw_Interpretor& , Standard_Integer , con //purpose : //======================================================================= Standard_Integer b2dclassifx (Draw_Interpretor& theDI, - Standard_Integer theArgNb, - const char** theArgVec) + Standard_Integer theArgc, + const char** theArgv) { - if (theArgNb < 3) { - theDI << " use b2dclassifx Face Point2d [Tol]\n"; + if (theArgc < 2) + { + theDI.PrintHelp (theArgv[0]); return 1; } - TopoDS_Shape aS = DBRep::Get (theArgVec[1]); - if (aS.IsNull()) { - theDI << " Null Shape is not allowed here\n"; + TopoDS_Shape aS = DBRep::Get (theArgv[1]); + if (aS.IsNull()) + { + theDI << theArgv[1] << " is a null shape\n"; return 1; } - else if (aS.ShapeType() != TopAbs_FACE) { - theDI << " Shape type must be FACE\n"; + + if (aS.ShapeType() != TopAbs_FACE) + { + theDI << theArgv[1] << " is a not a face\n"; return 1; } - TopAbs_State aState; - gp_Pnt2d aP (8., 9.); - // - DrawTrSurf::GetPoint2d (theArgVec[2], aP); - const TopoDS_Face& aF = TopoDS::Face(aS); - const Standard_Real aTol = (theArgNb == 4) ? - Draw::Atof (theArgVec[3]) : BRep_Tool::Tolerance (aF); - // - IntTools_FClass2d aClassifier(aF, aTol); - aState=aClassifier.Perform(aP); + + const TopoDS_Face& aF = TopoDS::Face (aS); + Standard_Real aTol = BRep_Tool::Tolerance (aF); + + gp_Pnt2d aP; + Standard_Boolean isPoint = (theArgc > 2) && DrawTrSurf::GetPoint2d (theArgv[2], aP); + + if (isPoint) + { + if (theArgc > 3) + aTol = Draw::Atof (theArgv[3]); + } + else if (theArgc > 2) + aTol = Draw::Atof (theArgv[2]); + + IntTools_FClass2d aClassifier (aF, aTol); + TopAbs_State aState = isPoint ? + aClassifier.Perform (aP) : + aClassifier.PerformInfinitePoint (); + PrintState (theDI, aState); - // return 0; } // @@ -120,35 +138,54 @@ Standard_Integer b2dclassifx (Draw_Interpretor& theDI, //purpose : //======================================================================= Standard_Integer b2dclassify (Draw_Interpretor& theDI, - Standard_Integer theArgNb, - const char** theArgVec) + Standard_Integer theArgc, + const char** theArgv) { - if (theArgNb < 3) { - theDI << " use b2dclassify Face Point2d [Tol]\n"; + if (theArgc < 2) + { + theDI.PrintHelp (theArgv[0]); return 1; } - TopoDS_Shape aS = DBRep::Get (theArgVec[1]); - if (aS.IsNull()) { - theDI << " Null Shape is not allowed here\n"; + TopoDS_Shape aS = DBRep::Get (theArgv[1]); + if (aS.IsNull()) + { + theDI << theArgv[1] << " is a null shape\n"; return 1; } - else if (aS.ShapeType() != TopAbs_FACE) { - theDI << " Shape type must be FACE\n"; + + if (aS.ShapeType() != TopAbs_FACE) + { + theDI << theArgv[1] << " is a not a face\n"; return 1; } - // - gp_Pnt2d aP (8., 9.); - // - DrawTrSurf::GetPoint2d (theArgVec[2], aP); - const TopoDS_Face& aF = TopoDS::Face(aS); - const Standard_Real aTol = (theArgNb == 4) ? - Draw::Atof (theArgVec[3]) : BRep_Tool::Tolerance (aF); - - BRepClass_FaceClassifier aClassifier; - aClassifier.Perform(aF, aP, aTol); - PrintState (theDI, aClassifier.State()); - // + + const TopoDS_Face& aF = TopoDS::Face (aS); + Standard_Real aTol = BRep_Tool::Tolerance (aF); + + gp_Pnt2d aP; + Standard_Boolean isPoint = (theArgc > 2) && DrawTrSurf::GetPoint2d (theArgv[2], aP); + + TopAbs_State aState = TopAbs_UNKNOWN; + if (isPoint) + { + if (theArgc > 3) + aTol = Draw::Atof (theArgv[3]); + + BRepClass_FaceClassifier aClassifier; + aClassifier.Perform (aF, aP, aTol); + aState = aClassifier.State(); + } + else + { + if (theArgc > 2) + aTol = Draw::Atof (theArgv[2]); + + BRepTopAdaptor_FClass2d aClassifier (aF, aTol); + aState = aClassifier.PerformInfinitePoint(); + } + + PrintState (theDI, aState); return 0; } diff --git a/src/BRepClass/BRepClass_FaceExplorer.cxx b/src/BRepClass/BRepClass_FaceExplorer.cxx index b2255c4cdc..22326bbbe8 100644 --- a/src/BRepClass/BRepClass_FaceExplorer.cxx +++ b/src/BRepClass/BRepClass_FaceExplorer.cxx @@ -27,11 +27,134 @@ #include #include #include +#include +#include static const Standard_Real Probing_Start = 0.123; static const Standard_Real Probing_End = 0.7; static const Standard_Real Probing_Step = 0.2111; +//======================================================================= +//function : BRepClass_FExp_DistanceTool +//purpose : Tool for checking the ON status of a point for the face +// using the real tolerances of sub-shapes of the latter. +//======================================================================= +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class BRepClass_FExp_DistanceTool: + public BVH_Distance , + BVH_BoxSet > +{ +public: + + //! Empty constructor + BRepClass_FExp_DistanceTool() + : BVH_Distance , BVH_BoxSet>() + { + } + +public: //! @name Setters + + void SetPoint (const gp_Pnt& thePoint) + { + SetObject (NCollection_Vec3 (thePoint.X(), thePoint.Y(), thePoint.Z())); + } + +public: //! @name Setters + + const TopoDS_Shape& GetOnShape() const + { + return myOnShape; + } + +public: //! @name Clearing the results + + //! Returns the flag controlling the tree descend + virtual void Clear() Standard_OVERRIDE + { + myDistance = 0.0; + myIsDone = Standard_False; + myOnShape.Nullify(); + } + +public: //! @name Definition of the rules for tree descend + + // Computes the distance from the point to bounding box + virtual Standard_Boolean RejectNode (const BVH_Vec3d& theCMin, + const BVH_Vec3d& theCMax, + Standard_Real& theDistance) const Standard_OVERRIDE + { + theDistance = BVH_Tools::PointBoxSquareDistance (myObject, theCMin, theCMax); + return RejectMetric (theDistance); + } + + // Computes the distance from the point to triangle + virtual Standard_Boolean Accept (const Standard_Integer theIndex, + const Standard_Real&) Standard_OVERRIDE + { + if (myBVHSet->Box (theIndex).IsOut (myObject)) + return Standard_False; + + // Get the shape + const TopoDS_Shape& aS = myBVHSet->Element (theIndex); + + if (aS.ShapeType() == TopAbs_VERTEX) + { + const TopoDS_Vertex& aV = TopoDS::Vertex (aS); + gp_XYZ aP = BRep_Tool::Pnt (aV).XYZ(); + Standard_Real aTolV = BRep_Tool::Tolerance (aV); + Standard_Real aSqTol = aTolV * aTolV; + + Standard_Real aSqDist = (aP - gp_XYZ (myObject.x(), myObject.y(), myObject.z())).SquareModulus(); + if (aSqDist <= aSqTol) + { + myOnShape = aS; + return Standard_True; + } + } + else if (aS.ShapeType() == TopAbs_EDGE) + { + const TopoDS_Edge& aE = TopoDS::Edge (aS); + Standard_Real aFirst, aLast; + const Handle (Geom_Curve)& aC = BRep_Tool::Curve (aE, aFirst, aLast); + if (aC.IsNull()) + return Standard_False; + + GeomAPI_ProjectPointOnCurve aProjPC + (gp_Pnt (myObject.x(), myObject.y(), myObject.z()), aC, aFirst, aLast); + if (aProjPC.NbPoints() > 0) + { + if (aProjPC.LowerDistance() < BRep_Tool::Tolerance (aE)) + { + myOnShape = aS; + return Standard_True; + } + } + } + return Standard_False; + } + + //! Returns the flag controlling the tree descend + virtual Standard_Boolean Stop() const Standard_OVERRIDE + { + return !myOnShape.IsNull(); + } + +private: //! @name Fields + + TopoDS_Shape myOnShape; +}; + //======================================================================= //function : BRepClass_FaceExplorer //purpose : @@ -296,3 +419,68 @@ void BRepClass_FaceExplorer::CurrentEdge(BRepClass_Edge& E, Or = E.Edge().Orientation(); } +//======================================================================= +//function : IsPointOnFace +//purpose : +//======================================================================= +const opencascade::handle>& + BRepClass_FaceExplorer::BVHBoxSet (Standard_Boolean toBuild) const +{ + if (toBuild && myBVHSet.IsNull()) + { + myBVHSet = new BVH_BoxSet (new BVH_LinearBuilder()); + + for (TopExp_Explorer anExpV (myFace, TopAbs_VERTEX); anExpV.More(); anExpV.Next()) + { + const TopoDS_Vertex& aV = TopoDS::Vertex (anExpV.Current()); + const TopAbs_Orientation aVOri = aV.Orientation(); + if (aVOri == TopAbs_FORWARD || aVOri == TopAbs_REVERSED) + { + Bnd_Box aBox; + aBox.Add (BRep_Tool::Pnt (aV)); + aBox.Enlarge (BRep_Tool::Tolerance (aV)); + myBVHSet->Add (anExpV.Current(), Bnd_Tools::Bnd2BVH (aBox)); + } + } + + for (TopExp_Explorer anExpE (myFace, TopAbs_EDGE); anExpE.More(); anExpE.Next()) + { + const TopoDS_Edge& aE = TopoDS::Edge (anExpE.Current()); + const TopAbs_Orientation aEOri = aE.Orientation(); + if (aEOri == TopAbs_FORWARD || aEOri == TopAbs_REVERSED) + { + BRepAdaptor_Curve aBAC (aE); + Bnd_Box aBox; + BndLib_Add3dCurve::Add (aBAC, aBAC.Tolerance(), aBox); + myBVHSet->Add (anExpE.Current(), Bnd_Tools::Bnd2BVH (aBox)); + } + } + myBVHSet->Build(); + } + return myBVHSet; +} + + +//======================================================================= +//function : IsPointOnFace +//purpose : +//======================================================================= +Standard_Boolean BRepClass_FaceExplorer::IsPointOnFace (const gp_Pnt2d& thePoint) const +{ + const Handle (Geom_Surface)& aSurface = BRep_Tool::Surface (myFace); + gp_Pnt aP3d = aSurface->Value (thePoint.X(), thePoint.Y()); + return IsPointOnFace (aP3d); +} + +//======================================================================= +//function : IsPointOnFace +//purpose : +//======================================================================= +Standard_Boolean BRepClass_FaceExplorer::IsPointOnFace (const gp_Pnt& thePoint) const +{ + BRepClass_FExp_DistanceTool aDistTool; + aDistTool.SetBVHSet (BVHBoxSet().get()); + aDistTool.SetPoint (thePoint); + aDistTool.ComputeDistance(); + return aDistTool.IsDone(); +} diff --git a/src/BRepClass/BRepClass_FaceExplorer.hxx b/src/BRepClass/BRepClass_FaceExplorer.hxx index bdb14b1d72..611fd43f44 100644 --- a/src/BRepClass/BRepClass_FaceExplorer.hxx +++ b/src/BRepClass/BRepClass_FaceExplorer.hxx @@ -27,6 +27,7 @@ #include #include #include +#include class TopoDS_Face; class gp_Pnt2d; class gp_Lin2d; @@ -94,7 +95,18 @@ public: //! Current edge in current wire and its orientation. Standard_EXPORT void CurrentEdge (BRepClass_Edge& E, TopAbs_Orientation& Or) const; + //! Returns the cached BVH_BoxSet. + //! @param toBuild controls if the set should be constructed if it is null + Standard_EXPORT const opencascade::handle>& + BVHBoxSet (Standard_Boolean toBuild = Standard_True) const; + //! Checks the On status of a point evaluated from surface for the face using the + //! real tolerances of the sub-shapes of the face + Standard_EXPORT Standard_Boolean IsPointOnFace (const gp_Pnt2d& thePoint) const; + + //! Checks the On status of a point for the face using the + //! real tolerances of the sub-shapes of the face + Standard_EXPORT Standard_Boolean IsPointOnFace (const gp_Pnt& thePoint) const; protected: @@ -117,6 +129,8 @@ private: Standard_Real myUMax; Standard_Real myVMin; Standard_Real myVMax; + + mutable opencascade::handle > myBVHSet; }; diff --git a/src/BRepClass/BRepClass_Intersector.cxx b/src/BRepClass/BRepClass_Intersector.cxx index 5c606e9f4c..f529f8ea45 100644 --- a/src/BRepClass/BRepClass_Intersector.cxx +++ b/src/BRepClass/BRepClass_Intersector.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include static @@ -54,82 +56,74 @@ 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) +void BRepClass_Intersector::Perform (const gp_Lin2d& L, + const Standard_Real P, + const Standard_Real Tol, + const BRepClass_Edge& E) { - Standard_Real deb = 0.0, fin = 0.0, aTolZ = Tol; - Handle(Geom2d_Curve) aC2D; - // - const TopoDS_Edge& EE = E.Edge(); - const TopoDS_Face& F = E.Face(); + const TopoDS_Edge& anEdge = E.Edge(); + const TopoDS_Face& aFace = E.Face(); - // - aC2D=BRep_Tool::CurveOnSurface(EE, F, deb, fin); - if (aC2D.IsNull()) { - done = Standard_False; // !IsDone() + Standard_Real aFirst, aLast; + Handle (Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast); + if (aC2D.IsNull()) + { + done = Standard_False; return; } - // - Geom2dAdaptor_Curve C(aC2D, deb, fin); - // - deb = C.FirstParameter(); - fin = C.LastParameter(); - // - // 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()) + + Geom2dAdaptor_Curve C (aC2D, aFirst, aLast); { - const Standard_Integer aNbPnts = anExtPC2d.NbExt(); - for (i = 1; i <= aNbPnts; ++i) + Extrema_ExtPC2d anExtPC2d (L.Location(), C); + Standard_Real MinDist = RealLast(), aDist; + Standard_Integer MinInd = 0, i; + if (anExtPC2d.IsDone()) { - aDist = anExtPC2d.SquareDistance(i); - - if (aDist < MinDist) + const Standard_Integer aNbPnts = anExtPC2d.NbExt(); + for (i = 1; i <= aNbPnts; ++i) { - MinDist = aDist; - MinInd = 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; + if (MinInd) + MinDist = sqrt (MinDist); + + if (MinDist <= Tol) + { + gp_Pnt2d aPnt = (anExtPC2d.Point (MinInd)).Value(); + Standard_Real aPar = (anExtPC2d.Point (MinInd)).Parameter(); + + Standard_Real aTolZ = Tol; + RefineTolerance (aFace, C, aPar, aTolZ); + + if (MinDist <= aTolZ) + { + IntRes2d_Position aPosOnCurve = IntRes2d_Middle; + if (Abs (aPar - aFirst) <= Tol) + aPosOnCurve = IntRes2d_Head; + else if (Abs (aPar - aLast) <= Tol) + aPosOnCurve = IntRes2d_End; + + IntRes2d_IntersectionPoint pnt_inter (aPnt, 0., aPar, + IntRes2d_Transition (IntRes2d_Head), + IntRes2d_Transition (aPosOnCurve), + Standard_False); + Append (pnt_inter); + done = Standard_True; + return; } - // - 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; } } - // - gp_Pnt2d pdeb,pfin; - C.D0(deb,pdeb); - C.D0(fin,pfin); + + // Intersection of the edge with the line + gp_Pnt2d aPFirst = C.Value (aFirst), + aPLast = C.Value (aLast); IntRes2d_Domain DL; if (P != RealLast()) @@ -138,7 +132,7 @@ void BRepClass_Intersector::Perform(const gp_Lin2d& L, else DL.SetValues (L.Location(), 0., Precision::PConfusion(), Standard_True); - IntRes2d_Domain DE (pdeb, deb, Tol, pfin, fin, Tol); + IntRes2d_Domain DE (aPFirst, aFirst, Tol, aPLast, aLast, Tol); // temporary periodic domain if (C.Curve()->IsPeriodic()) { DE.SetEquivalentParameters(C.FirstParameter(), diff --git a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx index e3190f0ce5..931d4589ad 100644 --- a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx +++ b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx @@ -23,7 +23,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -486,12 +487,20 @@ TopAbs_State BRepTopAdaptor_FClass2d::PerformInfinitePoint() const { return(Perform(P,Standard_False)); } -TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv, - const Standard_Boolean RecadreOnPeriodic) const +TopAbs_State BRepTopAdaptor_FClass2d::Perform (const gp_Pnt2d& _Puv, + const Standard_Boolean RecadreOnPeriodic, + const Standard_Boolean theUseFTolForOnCheck) const { #if LBRCOMPT STAT.NbPerform++; #endif + + if (theUseFTolForOnCheck) + { + if (FExplorer().IsPointOnFace (_Puv)) + return TopAbs_ON; + } + Standard_Integer dedans; Standard_Integer nbtabclass = TabClass.Length(); @@ -568,11 +577,8 @@ TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv, } } if(dedans==0) { - BRepClass_FaceClassifier aClassifier; Standard_Real m_Toluv = (Toluv > 4.0) ? 4.0 : Toluv; - //aClassifier.Perform(Face,Puv,Toluv); - aClassifier.Perform(Face,Puv,m_Toluv); - aStatus = aClassifier.State(); + aStatus = ClassifyByInter (Puv, m_Toluv); } if(dedans == 1) { aStatus = TopAbs_IN; @@ -582,9 +588,7 @@ TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv, } } else { //-- TabOrien(1)=-1 False Wire - BRepClass_FaceClassifier aClassifier; - aClassifier.Perform(Face,Puv,Toluv); - aStatus = aClassifier.State(); + aStatus = ClassifyByInter (Puv, Toluv); } if (!RecadreOnPeriodic || (!IsUPer && !IsVPer)) @@ -712,9 +716,7 @@ TopAbs_State BRepTopAdaptor_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv, } } else { //-- TabOrien(1)=-1 False Wire - BRepClass_FaceClassifier aClassifier; - aClassifier.Perform(Face,Puv,Tol); - aStatus = aClassifier.State(); + aStatus = ClassifyByInter (Puv, Tol); } if (!RecadreOnPeriodic || (!IsUPer && !IsVPer)) @@ -749,6 +751,24 @@ TopAbs_State BRepTopAdaptor_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv, } //for (;;) } +//======================================================================= +//function : FExplorer +//purpose : +//======================================================================= +BRepClass_FaceExplorer& BRepTopAdaptor_FClass2d::FExplorer() const +{ + if (myFExplorer.get() == NULL) + myFExplorer.reset (new BRepClass_FaceExplorer (Face)); + return *myFExplorer; +} + +TopAbs_State BRepTopAdaptor_FClass2d::ClassifyByInter (const gp_Pnt2d& thePnt, + const Standard_Real theTolUV) const +{ + BRepClass_FClassifier aClassifier; + aClassifier.Perform (FExplorer(), thePnt, theTolUV); + return aClassifier.State(); +} void BRepTopAdaptor_FClass2d::Destroy() { #if LBRCOMPT diff --git a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.hxx b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.hxx index 0dc6dce870..57c3571f22 100644 --- a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.hxx +++ b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.hxx @@ -27,11 +27,13 @@ #include #include #include +#include +#include + class TopoDS_Face; class gp_Pnt2d; - class BRepTopAdaptor_FClass2d { public: @@ -43,7 +45,9 @@ public: Standard_EXPORT TopAbs_State PerformInfinitePoint() const; - Standard_EXPORT TopAbs_State Perform (const gp_Pnt2d& Puv, const Standard_Boolean RecadreOnPeriodic = Standard_True) const; + Standard_EXPORT TopAbs_State Perform (const gp_Pnt2d& Puv, + const Standard_Boolean RecadreOnPeriodic = Standard_True, + const Standard_Boolean theUseFTolForOnCheck = Standard_False) const; Standard_EXPORT void Destroy(); ~BRepTopAdaptor_FClass2d() @@ -62,7 +66,12 @@ const BRepTopAdaptor_FClass2d& operator= (const BRepTopAdaptor_FClass2d& Other) //! (Caution: Internal use . see the code for more details) Standard_EXPORT TopAbs_State TestOnRestriction (const gp_Pnt2d& Puv, const Standard_Real Tol, const Standard_Boolean RecadreOnPeriodic = Standard_True) const; + //! Returns FaceExplorer for myFace + Standard_EXPORT BRepClass_FaceExplorer& FExplorer() const; + //! Classifies the point by geometrical classifier + Standard_EXPORT TopAbs_State ClassifyByInter (const gp_Pnt2d& thePnt, + const Standard_Real theTolUV) const; protected: @@ -88,13 +97,16 @@ private: Standard_Real Vmin; Standard_Real Vmax; +#ifdef _MSC_VER +#if _MSC_VER < 1600 + mutable std::auto_ptr myFExplorer; +#else + mutable std::unique_ptr myFExplorer; +#endif +#else + mutable std::unique_ptr myFExplorer; +#endif }; - - - - - - #endif // _BRepTopAdaptor_FClass2d_HeaderFile diff --git a/src/BVH/BVH_Distance.hxx b/src/BVH/BVH_Distance.hxx index 286b08a394..59357f8288 100644 --- a/src/BVH/BVH_Distance.hxx +++ b/src/BVH/BVH_Distance.hxx @@ -53,6 +53,7 @@ public: //! @name Compute the distance //! Computes the distance between object and BVH tree NumType ComputeDistance() { + Clear(); myIsDone = this->Select() > 0; return myDistance; } @@ -65,6 +66,15 @@ public: //! @name Accessing the results //! Returns the computed distance NumType Distance() const { return myDistance; } +public: //! @name Clearing the results + + //! Clears the data + virtual void Clear() + { + myDistance = std::numeric_limits::max(); + myIsDone = Standard_False; + } + public: //! @name Definition of the rules for tree descend //! Compares the two metrics and chooses the best one diff --git a/src/ShapeFix/ShapeFix_Face.cxx b/src/ShapeFix/ShapeFix_Face.cxx index a4529252f5..e4135d99cb 100644 --- a/src/ShapeFix/ShapeFix_Face.cxx +++ b/src/ShapeFix/ShapeFix_Face.cxx @@ -1014,6 +1014,130 @@ Standard_Boolean ShapeFix_Face::FixOrientation() return FixOrientation(MapWires); } +static TopAbs_State classifyWire (const TopoDS_Wire& theWire, + const Bnd_Box2d& aBox1, + const BRepTopAdaptor_FClass2d& theClassifier, + const TopAbs_State theInfPntState, + const TopTools_SequenceOfShape& theAllSubShapes, + const NCollection_Array1& theWireBoxes, + const TopoDS_Face& theFace, + const Handle(ShapeAnalysis_Surface)& theSurf, + const Standard_Boolean theUClosed, + const Standard_Boolean theVClosed, + const Standard_Real theURange, + const Standard_Real theVRange, + TopTools_DataMapOfShapeInteger& theSI, + TopTools_ListOfShape& theIntWires, + const Standard_Boolean theUseToler) +{ + Standard_Boolean CheckShift = Standard_True; + TopAbs_State sta = TopAbs_OUT; + Standard_Integer aWireIt = 0; + const Standard_Integer nbAll = theAllSubShapes.Length(); + for (Standard_Integer j = 1; j <= nbAll; j++) + { + aWireIt++; + //if(i==j) continue; + TopoDS_Shape aSh2 = theAllSubShapes.Value (j); + if (theWire == aSh2) + continue; + TopAbs_State stb = TopAbs_UNKNOWN; + if (aSh2.ShapeType () == TopAbs_VERTEX) { + aWireIt--; + gp_Pnt aP = BRep_Tool::Pnt (TopoDS::Vertex (aSh2)); + gp_Pnt2d p2d = theSurf->ValueOfUV (aP, Precision::Confusion ()); + stb = theClassifier.Perform (p2d, Standard_False, theUseToler); + if (stb == theInfPntState && (theUClosed || theVClosed)) { + gp_Pnt2d p2d1; + if (theUClosed) { + p2d1.SetCoord (p2d.X () + theURange, p2d.Y ()); + stb = theClassifier.Perform (p2d1, Standard_False, theUseToler); + } + if (stb == theInfPntState && theVClosed) { + p2d1.SetCoord (p2d.X (), p2d.Y () + theVRange); + stb = theClassifier.Perform (p2d1, Standard_False, theUseToler); + } + } + } + else if (aSh2.ShapeType () == TopAbs_WIRE) { + CheckShift = Standard_True; + TopoDS_Wire bw = TopoDS::Wire (aSh2); + //Standard_Integer numin =0; + Bnd_Box2d aBox2 = theWireBoxes.Value (aWireIt); + if (aBox2.IsOut (aBox1)) + continue; + + TopoDS_Iterator ew (bw); + for (; ew.More (); ew.Next ()) { + TopoDS_Edge ed = TopoDS::Edge (ew.Value ()); + Standard_Real cf, cl; + Handle (Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed, theFace, cf, cl); + if (cw.IsNull ()) continue; + gp_Pnt2d unp = cw->Value ((cf + cl) / 2.); + TopAbs_State ste = theClassifier.Perform (unp, Standard_False, theUseToler); + std::cout << (ste == TopAbs_ON ? "ON" : (ste == TopAbs_IN ? "IN" : "OUT")) << std::endl; + if (ste == TopAbs_OUT || ste == TopAbs_IN) { + if (stb == TopAbs_UNKNOWN) { + stb = ste; + } + else { + if (!(stb == ste)) { + sta = TopAbs_UNKNOWN; + theSI.Bind (theWire, 0); + break; + } + } + } + + Standard_Boolean found = Standard_False; + gp_Pnt2d unp1; + if (stb == theInfPntState && CheckShift) { + CheckShift = Standard_False; + if (theUClosed) { + unp1.SetCoord (unp.X () + theURange, unp.Y ()); + found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler)); + if (!found) { + unp1.SetX (unp.X () - theURange); + found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler)); + } + } + if (theVClosed && !found) { + unp1.SetCoord (unp.X (), unp.Y () + theVRange); + found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler)); + if (!found) { + unp1.SetY (unp.Y () - theVRange); + found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler)); + } + } + // Additional check of diagonal steps for toroidal surfaces + if (!found && theUClosed && theVClosed) + { + for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0) + for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0) + { + unp1.SetCoord (unp.X () + theURange * dX, unp.Y () + theVRange * dY); + found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler)); + } + } + } + if (found) { + if (stb == TopAbs_IN) stb = TopAbs_OUT; + else stb = TopAbs_IN; + Shift2dWire (bw, theFace, unp1.XY () - unp.XY (), theSurf); + } + } + if (ew.More()) + break; + } + if (stb == theInfPntState) { + sta = TopAbs_IN; + } + else { + theIntWires.Append (aSh2); + } + } + return sta; +} //======================================================================= //function : FixOrientation @@ -1137,9 +1261,6 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap TopTools_DataMapOfShapeListOfShape MW; TopTools_DataMapOfShapeInteger SI; TopTools_MapOfShape MapIntWires; - MW.Clear(); - SI.Clear(); - MapIntWires.Clear(); Standard_Integer NbOuts=0; Standard_Integer i; @@ -1192,121 +1313,149 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap Bnd_Box2d aBox1 = aWireBoxes.Value(i); TopoDS_Shape dummy = myFace.EmptyCopied(); TopoDS_Face af = TopoDS::Face ( dummy ); -// B.MakeFace (af,mySurf->Surface(),::Precision::Confusion()); af.Orientation ( TopAbs_FORWARD ); B.Add (af,aw); // PTV OCC945 06.11.2002 files ie_exhaust-A.stp (entities 3782, 3787) // tolerance is too big. It is seems that to identify placement of 2d point // it is enough Precision::PConfusion(), cause wea re know that 2d point in TopAbs_ON // BRepTopAdaptor_FClass2d clas (af,toluv); - Standard_Boolean CheckShift = Standard_True; BRepTopAdaptor_FClass2d clas (af,::Precision::PConfusion()); - TopAbs_State sta = TopAbs_OUT; TopAbs_State staout = clas.PerformInfinitePoint(); + TopTools_ListOfShape IntWires; - Standard_Integer aWireIt = 0; - for ( Standard_Integer j = 1; j <= nbAll; j ++) { - aWireIt++; - //if(i==j) continue; - TopoDS_Shape aSh2 = allSubShapes.Value(j); - if(aw == aSh2) - continue; - TopAbs_State stb = TopAbs_UNKNOWN; - if(aSh2.ShapeType() == TopAbs_VERTEX) { - aWireIt--; - gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aSh2)); - gp_Pnt2d p2d = mySurf->ValueOfUV(aP,Precision::Confusion()); - stb = clas.Perform (p2d,Standard_False); - if(stb == staout && (uclosed || vclosed)) { - gp_Pnt2d p2d1; - if(uclosed) { - p2d1.SetCoord(p2d.X()+uRange, p2d.Y()); - stb = clas.Perform (p2d1,Standard_False); - - } - if(stb == staout && vclosed) { - p2d1.SetCoord(p2d.X(), p2d.Y()+ vRange); - stb = clas.Perform (p2d1,Standard_False); - } - } - } - else if (aSh2.ShapeType() == TopAbs_WIRE) { - CheckShift = Standard_True; - TopoDS_Wire bw = TopoDS::Wire (aSh2); - //Standard_Integer numin =0; - Bnd_Box2d aBox2 = aWireBoxes.Value(aWireIt); - if (aBox2.IsOut(aBox1)) - continue; + TopTools_DataMapOfShapeInteger SILoc; + TopAbs_State sta = classifyWire (aw, aBox1, clas, staout, + allSubShapes, aWireBoxes, + myFace, mySurf, + uclosed, vclosed, uRange, vRange, + SILoc, IntWires, Standard_False); + if (sta == TopAbs_UNKNOWN) + { + IntWires.Clear(); + SILoc.Clear(); + sta = classifyWire (aw, aBox1, clas, staout, + allSubShapes, aWireBoxes, + myFace, mySurf, + uclosed, vclosed, uRange, vRange, + SILoc, IntWires, Standard_True); + } + { + for (TopTools_ListOfShape::Iterator itIW (IntWires); itIW.More(); itIW.Next()) + MapIntWires.Add (itIW.Value()); - TopoDS_Iterator ew (bw); - for(;ew.More(); ew.Next()) { - TopoDS_Edge ed = TopoDS::Edge (ew.Value()); - Standard_Real cf,cl; - Handle(Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed,myFace,cf,cl); - if (cw.IsNull()) continue; - gp_Pnt2d unp = cw->Value ((cf+cl)/2.); - TopAbs_State ste = clas.Perform (unp,Standard_False); - if( ste==TopAbs_OUT || ste==TopAbs_IN ) { - if(stb==TopAbs_UNKNOWN) { - stb = ste; - } - else { - if(!(stb==ste)) { - sta = TopAbs_UNKNOWN; - SI.Bind(aw,0); - j=nb; - break; - } - } - } - - Standard_Boolean found = Standard_False; - gp_Pnt2d unp1; - if( stb == staout && CheckShift ) { - CheckShift = Standard_False; - if(uclosed) { - unp1.SetCoord(unp.X()+uRange, unp.Y()); - found = (staout != clas.Perform (unp1,Standard_False)); - if(!found) { - unp1.SetX(unp.X()-uRange); - found = (staout != clas.Perform (unp1,Standard_False)); - } - } - if(vclosed&&!found) { - unp1.SetCoord(unp.X(), unp.Y()+vRange); - found = (staout != clas.Perform (unp1,Standard_False)); - if(!found) { - unp1.SetY(unp.Y()-vRange); - found = (staout != clas.Perform (unp1,Standard_False)); - } - } - // Additional check of diagonal steps for toroidal surfaces - if (!found && uclosed && vclosed) - { - for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0) - for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0) - { - unp1.SetCoord(unp.X() + uRange * dX, unp.Y() + vRange * dY); - found = (staout != clas.Perform(unp1, Standard_False)); - } - } - } - if(found) { - if(stb==TopAbs_IN) stb = TopAbs_OUT; - else stb = TopAbs_IN; - Shift2dWire(bw,myFace,unp1.XY()-unp.XY(), mySurf); - } - } - } - if(stb==staout) { - sta = TopAbs_IN; - } - else { - IntWires.Append(aSh2); - MapIntWires.Add(aSh2); - } + for (TopTools_DataMapOfShapeInteger::Iterator itSI (SILoc); itSI.More(); itSI.Next()) + SI.Bind (itSI.Key(), itSI.Value()); } + // + //Standard_Boolean CheckShift = Standard_True; + // + //TopAbs_State staout = clas.PerformInfinitePoint(); + //TopTools_ListOfShape IntWires; + //Standard_Integer aWireIt = 0; + //for ( Standard_Integer j = 1; j <= nbAll; j ++) { + // aWireIt++; + // //if(i==j) continue; + // TopoDS_Shape aSh2 = allSubShapes.Value(j); + // if(aw == aSh2) + // continue; + // TopAbs_State stb = TopAbs_UNKNOWN; + // if(aSh2.ShapeType() == TopAbs_VERTEX) { + // aWireIt--; + // gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aSh2)); + // gp_Pnt2d p2d = mySurf->ValueOfUV(aP,Precision::Confusion()); + // stb = clas.Perform (p2d,Standard_False); + // if(stb == staout && (uclosed || vclosed)) { + // gp_Pnt2d p2d1; + // if(uclosed) { + // p2d1.SetCoord(p2d.X()+uRange, p2d.Y()); + // stb = clas.Perform (p2d1,Standard_False); + // + // } + // if(stb == staout && vclosed) { + // p2d1.SetCoord(p2d.X(), p2d.Y()+ vRange); + // stb = clas.Perform (p2d1,Standard_False); + // } + // } + // } + // else if (aSh2.ShapeType() == TopAbs_WIRE) { + // CheckShift = Standard_True; + // TopoDS_Wire bw = TopoDS::Wire (aSh2); + // //Standard_Integer numin =0; + // Bnd_Box2d aBox2 = aWireBoxes.Value(aWireIt); + // if (aBox2.IsOut(aBox1)) + // continue; + // + // TopoDS_Iterator ew (bw); + // for(;ew.More(); ew.Next()) { + // TopoDS_Edge ed = TopoDS::Edge (ew.Value()); + // Standard_Real cf,cl; + // Handle(Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed,myFace,cf,cl); + // if (cw.IsNull()) continue; + // gp_Pnt2d unp = cw->Value ((cf+cl)/2.); + // TopAbs_State ste = clas.Perform (unp,Standard_False); + // std::cout << (ste == TopAbs_ON ? "ON" : (ste == TopAbs_IN ? "IN" : "OUT")) << std::endl; + // if( ste==TopAbs_OUT || ste==TopAbs_IN ) { + // if(stb==TopAbs_UNKNOWN) { + // stb = ste; + // } + // else { + // if(!(stb==ste)) { + // sta = TopAbs_UNKNOWN; + // SI.Bind(aw,0); + // j=nb; + // break; + // } + // } + // } + // + // Standard_Boolean found = Standard_False; + // gp_Pnt2d unp1; + // if( stb == staout && CheckShift ) { + // CheckShift = Standard_False; + // if(uclosed) { + // unp1.SetCoord(unp.X()+uRange, unp.Y()); + // found = (staout != clas.Perform (unp1,Standard_False)); + // if(!found) { + // unp1.SetX(unp.X()-uRange); + // found = (staout != clas.Perform (unp1,Standard_False)); + // } + // } + // if(vclosed&&!found) { + // unp1.SetCoord(unp.X(), unp.Y()+vRange); + // found = (staout != clas.Perform (unp1,Standard_False)); + // if(!found) { + // unp1.SetY(unp.Y()-vRange); + // found = (staout != clas.Perform (unp1,Standard_False)); + // } + // } + // // Additional check of diagonal steps for toroidal surfaces + // if (!found && uclosed && vclosed) + // { + // for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0) + // for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0) + // { + // unp1.SetCoord(unp.X() + uRange * dX, unp.Y() + vRange * dY); + // found = (staout != clas.Perform(unp1, Standard_False)); + // } + // } + // } + // if(found) { + // if(stb==TopAbs_IN) stb = TopAbs_OUT; + // else stb = TopAbs_IN; + // Shift2dWire(bw,myFace,unp1.XY()-unp.XY(), mySurf); + // } + // } + // } + // if(stb==staout) { + // sta = TopAbs_IN; + // } + // else { + // IntWires.Append(aSh2); + // MapIntWires.Add(aSh2); + // } + //} + if (sta == TopAbs_UNKNOWN) { // ERREUR SendWarning ( aw, Message_Msg ( "FixAdvFace.FixOrientation.MSG11" ) );// Cannot orient wire }