diff --git a/src/BRepOffset/BRepOffset.cdl b/src/BRepOffset/BRepOffset.cdl index 2147e086ba..609b5893e9 100644 --- a/src/BRepOffset/BRepOffset.cdl +++ b/src/BRepOffset/BRepOffset.cdl @@ -72,7 +72,11 @@ is UnCorrectClosingFace, ExtentFaceFailed, RadiusEqualOffset, - UnknownError + UnknownError, + BadNormalsOnGeometry, + C0Geometry, + NullOffset, + NotConnectedShell end Error; class MakeOffset; diff --git a/src/BRepOffset/BRepOffset_MakeOffset.cdl b/src/BRepOffset/BRepOffset_MakeOffset.cdl index e37b08d567..a14db04d68 100644 --- a/src/BRepOffset/BRepOffset_MakeOffset.cdl +++ b/src/BRepOffset/BRepOffset_MakeOffset.cdl @@ -136,6 +136,19 @@ is returns IndexedMapOfShape from TopTools is static; + CheckInputData(me: in out) returns Boolean; + ---Purpose: Makes pre analysis of possibility offset perform. Use method Error() to get more information. + --- Finds first error. List of checks: + --- 1) Check for existence object with non-null offset. + --- 2) Check for connectivity in offset shell. + --- 3) Check continuity of input surfaces. + --- 4) Check for normals existence on grid. + --- @return 1 if possible make computations and 0 if not possible. + + GetBadShape (me) returns Shape from TopoDS; + ---Purpose: Return bad shape, which obtained in CheckInputData. + ---C++: return const & + ---Category: private methods BuildOffsetByArc ( me : in out ) @@ -224,5 +237,6 @@ fields myError : Error from BRepOffset; myMakeLoops : MakeLoops from BRepOffset; + myBadShape : Shape from TopoDS; end MakeOffset; diff --git a/src/BRepOffset/BRepOffset_MakeOffset.cxx b/src/BRepOffset/BRepOffset_MakeOffset.cxx index ce512d870b..9907b57b36 100644 --- a/src/BRepOffset/BRepOffset_MakeOffset.cxx +++ b/src/BRepOffset/BRepOffset_MakeOffset.cxx @@ -118,6 +118,7 @@ #include // POP for NT #include +#include #ifdef DRAW @@ -682,29 +683,12 @@ void BRepOffset_MakeOffset::MakeOffsetShape() RemoveCorks (myShape,myFaces); } - if (! IsConnectedShell(myShape)) - Standard_ConstructionError::Raise("BRepOffset_MakeOffset : Incorrect set of faces to remove, the remaining shell is not connected"); - - if (Abs(myOffset) <= myTol) + if (!CheckInputData()) { - // Check for face with non-null offset value. - Standard_Boolean isFound = Standard_False; - TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset); - for( ; anIter.More(); anIter.Next()) - { - if (Abs(anIter.Value()) > myTol) - { - isFound = Standard_True; - break; - } - } - - if (!isFound) - { - // No face with non-null offset found. + // There is error in input data. + // Check Error() method. return; } - } TopAbs_State Side = TopAbs_IN; if (myOffset < 0.) Side = TopAbs_OUT; @@ -3400,3 +3384,176 @@ void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList) } theSol = aNewSol; } + +//======================================================================= +//function : CheckInputData +//purpose : Check input data for possiblity of offset perform. +//======================================================================= +Standard_Boolean BRepOffset_MakeOffset::CheckInputData() +{ + // Set initial error state. + myError = BRepOffset_NoError; + TopoDS_Shape aTmpShape; + myBadShape = aTmpShape; + + // Non-null offset. + if (Abs(myOffset) <= myTol) + { + Standard_Boolean isFound = Standard_False; + TopTools_DataMapIteratorOfDataMapOfShapeReal anIter(myFaceOffset); + for( ; anIter.More(); anIter.Next()) + { + if (Abs(anIter.Value()) > myTol) + { + isFound = Standard_True; + break; + } + } + + if (!isFound) + { + // No face with non-null offset found. + myError = BRepOffset_NullOffset; + return Standard_False; + } + } + + // Connectivity of input shape. + if (!IsConnectedShell(myShape)) + { + myError = BRepOffset_NotConnectedShell; + return Standard_False; + } + + + // Normals check and continuity check. + const Standard_Integer aPntPerDim = 20; // 21 points on each dimension. + Standard_Real aUmin, aUmax, aVmin, aVmax; + TopExp_Explorer anExpSF(myShape, TopAbs_FACE); + TopLoc_Location L; + gp_Pnt2d aPnt2d; + gp_Pnt aPnt; + gp_Vec aD1U, aD1V; + for( ; anExpSF.More(); anExpSF.Next()) + { + const TopoDS_Face& aF = TopoDS::Face(anExpSF.Current()); + const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, L); + BRepTools::UVBounds(aF, aUmin, aUmax, aVmin, aVmax); + + // Continuity check. + if (aSurf->Continuity() == GeomAbs_C0) + { + myError = BRepOffset_C0Geometry; + return Standard_False; + } + + // Get degenerated points, to avoid check them. + NCollection_Vector aBad3dPnts; + TopExp_Explorer anExpFE(aF, TopAbs_EDGE); + for( ; anExpFE.More(); anExpFE.Next()) + { + const TopoDS_Edge &aE = TopoDS::Edge(anExpFE.Current()); + if (BRep_Tool::Degenerated(aE)) + { + aBad3dPnts.Append(BRep_Tool::Pnt((TopExp::FirstVertex(aE)))); + } + } + + // Geometry grid check. + for(Standard_Integer i = 0; i <= aPntPerDim; i++) + { + Standard_Real aUParam = aUmin + (aUmax - aUmin) * i / aPntPerDim; + for(Standard_Integer j = 0; j <= aPntPerDim; j++) + { + Standard_Real aVParam = aVmin + (aVmax - aVmin) * j / aPntPerDim; + + aSurf->D1(aUParam, aVParam, aPnt, aD1U, aD1V); + + if (aD1U.SquareMagnitude() < Precision::SquareConfusion() || + aD1V.SquareMagnitude() < Precision::SquareConfusion() ) + { + Standard_Boolean isKnownBadPnt = Standard_False; + for(Standard_Integer anIdx = aBad3dPnts.Lower(); + anIdx <= aBad3dPnts.Upper(); + ++anIdx) + { + if (aPnt.SquareDistance(aBad3dPnts(anIdx)) < Precision::SquareConfusion()) + { + isKnownBadPnt = Standard_True; + break; + } + } // for(Standard_Integer anIdx = aBad3dPnts.Lower(); + + if (!isKnownBadPnt) + { + myError = BRepOffset_BadNormalsOnGeometry; + return Standard_False; + } + else + continue; + } // if (aD1U.SquareMagnitude() < Precision::SquareConfusion() || + + + Standard_Real anAngle = aD1U.Angle(aD1V); + if (Abs (anAngle) < Precision::Confusion()) + { + myError = BRepOffset_BadNormalsOnGeometry; + return Standard_False; + } + } + } + + // Vertex list check. + TopExp_Explorer anExpFV(aF, TopAbs_VERTEX); + for( ; anExpFV.More(); anExpFV.Next()) + { + const TopoDS_Vertex &aV = TopoDS::Vertex(anExpFV.Current()); + + aPnt2d = BRep_Tool::Parameters(aV, aF); + aSurf->D1(aPnt2d.X(), aPnt2d.Y(), aPnt, aD1U, aD1V); + + if (aD1U.SquareMagnitude() < Precision::SquareConfusion() || + aD1V.SquareMagnitude() < Precision::SquareConfusion() ) + { + Standard_Boolean isKnownBadPnt = Standard_False; + for(Standard_Integer anIdx = aBad3dPnts.Lower(); + anIdx <= aBad3dPnts.Upper(); + ++anIdx) + { + if (aPnt.SquareDistance(aBad3dPnts(anIdx)) < Precision::SquareConfusion()) + { + isKnownBadPnt = Standard_True; + break; + } + } // for(Standard_Integer anIdx = aBad3dPnts.Lower(); + + if (!isKnownBadPnt) + { + myError = BRepOffset_BadNormalsOnGeometry; + return Standard_False; + } + else + continue; + } // if (aD1U.SquareMagnitude() < Precision::SquareConfusion() || + + Standard_Real anAngle = aD1U.Angle(aD1V); + if ( Abs (anAngle) < Precision::Confusion()) + { + myError = BRepOffset_BadNormalsOnGeometry; + return Standard_False; + } + } + } + + return Standard_True; +} + + +//======================================================================= +//function : CheckInputData +//purpose : Check input data for possiblity of offset perform. +//======================================================================= +const TopoDS_Shape& BRepOffset_MakeOffset::GetBadShape() const +{ + return myBadShape; +} diff --git a/src/BRepTest/BRepTest_FeatureCommands.cxx b/src/BRepTest/BRepTest_FeatureCommands.cxx index 97acc216d0..987ce26f3c 100644 --- a/src/BRepTest/BRepTest_FeatureCommands.cxx +++ b/src/BRepTest/BRepTest_FeatureCommands.cxx @@ -1031,7 +1031,38 @@ Standard_Integer offsetperform(Draw_Interpretor& theCommands, } else { - theCommands << "ERROR. offsetperform operation not done."; + // Return state of problem. + BRepOffset_Error anError = TheOffset.Error(); + + switch(anError) + { + case BRepOffset_BadNormalsOnGeometry: + { + theCommands << "ERROR. Degenerated normal on input data."; + break; + } + case BRepOffset_C0Geometry: + { + theCommands << "ERROR. C0 continuity of input data."; + break; + } + case BRepOffset_NullOffset: + { + theCommands << "ERROR. Null offset of all faces."; + break; + } + case BRepOffset_NotConnectedShell: + { + theCommands << "ERROR. Incorrect set of faces to remove, the remaining shell is not connected."; + break; + } + + default: + { + theCommands << "ERROR. offsetperform operation not done."; + break; + } + } return 1; } diff --git a/tests/bugs/modalg_2/bug21261_15 b/tests/bugs/modalg_2/bug21261_15 index c52710dab7..b9a0b681af 100755 --- a/tests/bugs/modalg_2/bug21261_15 +++ b/tests/bugs/modalg_2/bug21261_15 @@ -1,5 +1,5 @@ -puts "TODO OCC25916 ALL: \\*\\* Exception" -puts "TODO OCC25916 ALL: An exception was caught" +puts "TODO OCC25916 ALL: result is not a topological shape!!!" +puts "TODO OCC25916 ALL: Error: object with name 'result' does not exist!" puts "TODO OCC25916 ALL: TEST INCOMPLETE" puts "========" puts "OCC21261" diff --git a/tests/bugs/modalg_2/bug21261_21 b/tests/bugs/modalg_2/bug21261_21 index 40f2e6134f..ce0ba68801 100755 --- a/tests/bugs/modalg_2/bug21261_21 +++ b/tests/bugs/modalg_2/bug21261_21 @@ -1,5 +1,5 @@ -puts "TODO OCC25916 ALL: \\*\\* Exception" -puts "TODO OCC25916 ALL: An exception was caught" +puts "TODO OCC25916 ALL: result is not a topological shape!!!" +puts "TODO OCC25916 ALL: Error: object with name 'result' does not exist!" puts "TODO OCC25916 ALL: TEST INCOMPLETE" puts "========" puts "OCC21261" diff --git a/tests/offset/shape/A2 b/tests/offset/shape/A2 index 4c9ee74456..20a39da1a3 100644 --- a/tests/offset/shape/A2 +++ b/tests/offset/shape/A2 @@ -1,5 +1,4 @@ -puts "TODO OCC23190 ALL: An exception was caugh.*Offset with no C1 Surface" -puts "TODO OCC23190 ALL: \\*\\* Exception \\*\\*.*Offset with no C1 Surface" +puts "TODO OCC23190 ALL: result is not a topological shape!!!" puts "TODO OCC23068 ALL: TEST INCOMPLETE" # Original bug : hkg60144/pro15325 # Date : 17Juillet98 diff --git a/tests/offset/shape/A3 b/tests/offset/shape/A3 index 4d94a3b9bb..f86361f201 100644 --- a/tests/offset/shape/A3 +++ b/tests/offset/shape/A3 @@ -1,5 +1,4 @@ -puts "TODO OCC23190 ALL: An exception was caught.*Offset with no C1 Surface" -puts "TODO OCC23190 ALL: \\*\\* Exception \\*\\*.*Offset with no C1 Surface" +puts "TODO OCC23190 ALL: result is not a topological shape!!!" puts "TODO OCC23068 ALL: TEST INCOMPLETE" # Original bug : cts21271 # Date : 11Sept98