From 6f2411378bf10949d395bc2f903c9d9ded90ffa6 Mon Sep 17 00:00:00 2001 From: ifv Date: Fri, 15 Mar 2019 16:59:08 +0300 Subject: [PATCH] 0030433: Checkshape: bad solid, created by revolution, is reported as valid. BRepPrimAPI_MakeRevol.cxx, hxx Insert checking of self-intersecting of generated surfaces in MakeRevol BRepTest_SweepCommands.cxx Adjusting command revol to current behavior of MakeRevol algorithm. --- src/BRepPrimAPI/BRepPrimAPI_MakeRevol.cxx | 139 ++++++++++++++++++++-- src/BRepPrimAPI/BRepPrimAPI_MakeRevol.hxx | 12 +- src/BRepTest/BRepTest_SweepCommands.cxx | 21 ++-- tests/bugs/modalg_5/bug23954 | 11 +- tests/bugs/modalg_7/bug30433 | 19 +++ 5 files changed, 176 insertions(+), 26 deletions(-) create mode 100644 tests/bugs/modalg_7/bug30433 diff --git a/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.cxx b/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.cxx index 69b34f8d25..96aa5ffa21 100644 --- a/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.cxx +++ b/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.cxx @@ -26,6 +26,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include + // perform checks on the argument static const TopoDS_Shape& check(const TopoDS_Shape& S) { @@ -41,10 +48,20 @@ static const TopoDS_Shape& check(const TopoDS_Shape& S) BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, const gp_Ax1& A, const Standard_Real D, - const Standard_Boolean Copy) : - myRevol(check(S),A,D,Copy) + const Standard_Boolean Copy) : + myRevol(check(S), A, D, Copy), + myIsBuild(Standard_False) + { - Build(); + if (!CheckValidity(check(S), A)) + { + myShape.Nullify(); + myIsBuild = Standard_True; + } + else + { + Build(); + } } @@ -55,10 +72,21 @@ BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, const gp_Ax1& A, - const Standard_Boolean Copy) : - myRevol(check(S),A,Copy) + const Standard_Boolean Copy) : + + myRevol(check(S), A, 2. * M_PI, Copy), + myIsBuild(Standard_False) { - Build(); + + if (!CheckValidity(check(S), A)) + { + myShape.Nullify(); + myIsBuild = Standard_True; + } + else + { + Build(); + } } @@ -80,10 +108,16 @@ const BRepSweep_Revol& BRepPrimAPI_MakeRevol::Revol() const void BRepPrimAPI_MakeRevol::Build() { + if (myIsBuild) + { + return; + } myShape = myRevol.Shape(); BRepLib::UpdateInnerTolerances(myShape); Done(); + myIsBuild = Standard_True; + myHist.Nullify(); myDegenerated.Clear(); TopTools_DataMapOfShapeListOfShape aDegE; @@ -210,6 +244,98 @@ void BRepPrimAPI_MakeRevol::Build() } } } +//======================================================================= +//function : IsIntersect +//purpose : used in CheckValidity to find out is there +// intersection between curve and axe of revolution +//======================================================================= +static Standard_Boolean IsIntersect(const Handle(Adaptor3d_HCurve)& theC, + const gp_Ax1& theAxe) +{ + const Handle(Geom_Line) aL = new Geom_Line(theAxe); + const GeomAdaptor_Curve aLin(aL); + const Standard_Real aParTol = theC->Resolution(Precision::Confusion()); + const Standard_Real aParF = theC->FirstParameter() + aParTol, + aParL = theC->LastParameter() - aParTol; + + Extrema_ExtCC anExtr(theC->Curve(), aLin); + anExtr.Perform(); + if (anExtr.IsDone() && anExtr.NbExt() > 0) + { + Extrema_POnCurv aP1, aP2; + for (Standard_Integer i = 1; i <= anExtr.NbExt(); i++) + { + if (anExtr.SquareDistance(i) > Precision::SquareConfusion()) + { + continue; + } + anExtr.Points(i, aP1, aP2); + if ((aParF < aP1.Parameter()) && (aP1.Parameter() < aParL)) + { + return Standard_True; + } + } + } + return Standard_False; +} + +//======================================================================= +//function : CheckValidity +//purpose : +//======================================================================= + +Standard_Boolean BRepPrimAPI_MakeRevol::CheckValidity(const TopoDS_Shape& theShape, + const gp_Ax1& theA) +{ + TopExp_Explorer anExp(theShape, TopAbs_EDGE); + Standard_Boolean IsValid = Standard_True; + for (; anExp.More(); anExp.Next()) + { + const TopoDS_Edge& anE = TopoDS::Edge(anExp.Current()); + + if (BRep_Tool::Degenerated(anE)) + { + continue; + } + + TopLoc_Location L; + Standard_Real First, Last; + Handle(Geom_Curve) C = BRep_Tool::Curve(anE, L, First, Last); + gp_Trsf Tr = L.Transformation(); + C = Handle(Geom_Curve)::DownCast(C->Copy()); + C = new Geom_TrimmedCurve(C, First, Last); + C->Transform(Tr); + + Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve(); + HC->ChangeCurve().Load(C, First, Last); + //Checking coinsidence axe of revolution and basis curve + //This code is taken directly from GeomAdaptor_SurfaceOfRevolution + Standard_Integer Ratio = 1; + Standard_Real Dist; + gp_Pnt PP; + do { + PP = HC->Value(First + (Last - First) / Ratio); + Dist = gp_Lin(theA).Distance(PP); + Ratio++; + } while (Dist < Precision::Confusion() && Ratio < 100); + // + if (Ratio >= 100) // edge coinsides with axes + { + IsValid = Standard_True; //Such edges are allowed by revol algo and treated + //by special way, so they must be concidered as valid + } + else + { + IsValid = !IsIntersect(HC, theA); + } + if (!IsValid) + { + break; + } + } + // + return IsValid; +} //======================================================================= @@ -351,4 +477,3 @@ const TopTools_ListOfShape& BRepPrimAPI_MakeRevol::Degenerated () const { return myDegenerated; } - diff --git a/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.hxx b/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.hxx index 2068410e08..a24adbad2b 100644 --- a/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.hxx +++ b/src/BRepPrimAPI/BRepPrimAPI_MakeRevol.hxx @@ -68,7 +68,6 @@ class BRepPrimAPI_MakeRevol : public BRepPrimAPI_MakeSweep public: DEFINE_STANDARD_ALLOC - //! Builds the Revol of base S, axis A and angle D. If C //! is true, S is copied. @@ -110,15 +109,15 @@ public: //! Check if there are degenerated edges in the result. Standard_EXPORT Standard_Boolean HasDegenerated() const; - - Standard_EXPORT const TopTools_ListOfShape& Degenerated() const; + //! Returns the list of degenerated edges + Standard_EXPORT const TopTools_ListOfShape& Degenerated() const; protected: - - - + //! Checks possibilities of producing self-intersection surface + //! returns true if all surfaces are valid + Standard_EXPORT Standard_Boolean CheckValidity(const TopoDS_Shape& theShape, const gp_Ax1& theA); private: @@ -127,6 +126,7 @@ private: BRepSweep_Revol myRevol; TopTools_ListOfShape myDegenerated; Handle(BRepTools_History) myHist; + Standard_Boolean myIsBuild; }; diff --git a/src/BRepTest/BRepTest_SweepCommands.cxx b/src/BRepTest/BRepTest_SweepCommands.cxx index 25c33e2340..3ed5f73256 100644 --- a/src/BRepTest/BRepTest_SweepCommands.cxx +++ b/src/BRepTest/BRepTest_SweepCommands.cxx @@ -114,7 +114,7 @@ static Standard_Integer prism(Draw_Interpretor&, Standard_Integer n, const char* //======================================================================= // revol //======================================================================= -static Standard_Integer revol(Draw_Interpretor&, +static Standard_Integer revol(Draw_Interpretor& di, Standard_Integer n, const char** a) { if (n < 10) return 1; @@ -133,14 +133,21 @@ static Standard_Integer revol(Draw_Interpretor&, BRepPrimAPI_MakeRevol Revol(base, A, angle, copy); - TopoDS_Shape res = Revol.Shape(); + if (Revol.IsDone()) + { + TopoDS_Shape res = Revol.Shape(); - DBRep::Set(a[1], res); + DBRep::Set(a[1], res); - //History - TopTools_ListOfShape anArgs; - anArgs.Append(base); - BRepTest_Objects::SetHistory(anArgs, Revol); + //History + TopTools_ListOfShape anArgs; + anArgs.Append(base); + BRepTest_Objects::SetHistory(anArgs, Revol); + } + else + { + di << "Revol not done \n"; + } return 0; } diff --git a/tests/bugs/modalg_5/bug23954 b/tests/bugs/modalg_5/bug23954 index 80ba5a7c48..58555b2bcb 100644 --- a/tests/bugs/modalg_5/bug23954 +++ b/tests/bugs/modalg_5/bug23954 @@ -8,12 +8,11 @@ puts "" # BRepPrimAPI_MakeRevol fails to recognize a torus case ########################################################## -circle c_1 0 100 0 1 0 0 0 1 0 100 -circle c_2 0 100 0 1 0 0 0 0 1 100 -circle c_3 0 100 0 1 0 0 0 -1 0 100 -circle c_4 0 100 0 1 0 0 0 0 1 10 -circle c_5 0 100 0 1 0 0 0 0 1 120 -for { set i 1 } { $i <= 5 } { incr i } { +circle c_1 0 100.00001 0 1 0 0 0 1 0 100 +circle c_2 0 100.00001 0 1 0 0 0 0 1 100 +circle c_3 0 100.00001 0 1 0 0 0 -1 0 100 +circle c_4 0 100.00001 0 1 0 0 0 0 1 10 +for { set i 1 } { $i <= 4 } { incr i } { mkedge e c_$i revol r e 0 0 0 0 0 1 90 mksurface s_$i r diff --git a/tests/bugs/modalg_7/bug30433 b/tests/bugs/modalg_7/bug30433 new file mode 100644 index 0000000000..b20782e8f1 --- /dev/null +++ b/tests/bugs/modalg_7/bug30433 @@ -0,0 +1,19 @@ +puts "========" +puts "0030433: Checkshape: bad solid, created by revolution, is reported as valid." +puts "========" +puts "" + +ellipse e1 0 0 0 200 100 +mkedge ell1 e1 +wire w1 ell1 +plane p1 +mkface fe1 p1 w1 +revol rev1 fe1 0 0 0 1 0 0 180 1 + + + +if { [isdraw rev1] != 1 } { + puts "OK: wrong shape is not created" +} else { + puts "Error: algorithm created wrong shape" +} -- 2.39.5