From 0c1af31f5408860fef60c451bb2692ffbc352d63 Mon Sep 17 00:00:00 2001 From: jfa Date: Fri, 27 Jan 2012 10:58:36 +0000 Subject: [PATCH] Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM. --- src/GEOMGUI/GEOM_msg_en.ts | 3 +- src/GEOMImpl/GEOMImpl_Block6Explorer.cxx | 326 ++++++++++++----------- src/GEOMImpl/GEOMImpl_Block6Explorer.hxx | 16 ++ src/GEOM_SWIG/geompyDC.py | 3 +- 4 files changed, 192 insertions(+), 156 deletions(-) diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index ac6f6b94f..14a87c7aa 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -627,7 +627,8 @@ Please, select face, shell or solid and try again MAKE_FACE_TOLERANCE_TOO_BIG - Tolerance of resulting face is too big + Cannot build a planar face: required tolerance is + too big. Non-planar face is built. GEOM_FACE_OR_LCS diff --git a/src/GEOMImpl/GEOMImpl_Block6Explorer.cxx b/src/GEOMImpl/GEOMImpl_Block6Explorer.cxx index 48f179cf8..6ec0ebf1d 100644 --- a/src/GEOMImpl/GEOMImpl_Block6Explorer.cxx +++ b/src/GEOMImpl/GEOMImpl_Block6Explorer.cxx @@ -1202,67 +1202,67 @@ TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire& const Standard_Boolean isPlanarWanted, TopoDS_Shape& theResult) { + if (!isPlanarWanted) + return MakeAnyFace(theWire, theResult); + + // Try to build a planar face. + + // If required tolerance increase will be + // higher than PLANAR_FACE_MAX_TOLERANCE, + // we will try to build a non-planar face. + TCollection_AsciiString aWarning; // Workaround for Mantis issue 0020956 - if (isPlanarWanted) { - // Count the number of points in the wire. - // Collect the first three points. - gp_Pnt p1, p2, p3; - bool is3Pnts(false); - bool p1set(false), p2set(false), p3set(false); - BRepTools_WireExplorer wexpl(theWire); - for (; wexpl.More(); wexpl.Next()) { - if (!p1set) { - p1set = true; - p1 = BRep_Tool::Pnt(wexpl.CurrentVertex()); - } - else if (!p2set) { - p2set = true; - p2 = BRep_Tool::Pnt(wexpl.CurrentVertex()); - } - else if (!p3set) { - p3set = true; - is3Pnts = true; - p3 = BRep_Tool::Pnt(wexpl.CurrentVertex()); - } - else { - is3Pnts = false; - break; - } - } - // Construct a plane for the case of three points in the wire. - gp_Pln plane; - if (is3Pnts) { - gce_MakePln mkPln(p1, p2, p3); - if (mkPln.IsDone()) { - plane = mkPln.Value(); - } - else { - is3Pnts = false; - } + // Count the number of points in the wire. + // Collect the first three points. + gp_Pnt p1, p2, p3; + bool is3Pnts (false); + bool p1set(false), p2set(false), p3set(false); + BRepTools_WireExplorer wexpl (theWire); + for (; wexpl.More(); wexpl.Next()) { + if (!p1set) { + p1set = true; + p1 = BRep_Tool::Pnt(wexpl.CurrentVertex()); + } + else if (!p2set) { + p2set = true; + p2 = BRep_Tool::Pnt(wexpl.CurrentVertex()); + } + else if (!p3set) { + p3set = true; + is3Pnts = true; + p3 = BRep_Tool::Pnt(wexpl.CurrentVertex()); } + else { + is3Pnts = false; + break; + } + } - // Construct a face based on the plane (in case of three points in the wire) or - // allow MakeFace to build the plane itself (in case of the number of points is greater than 3). - if (is3Pnts) { - BRepBuilderAPI_MakeFace MK (plane, theWire, isPlanarWanted); - if (MK.IsDone()) { - theResult = MK.Shape(); - return aWarning; - } + // Construct a plane for the case of three points in the wire. + gp_Pln plane; + if (is3Pnts) { + gce_MakePln mkPln (p1, p2, p3); + if (mkPln.IsDone()) { + plane = mkPln.Value(); } else { - BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted); - if (MK.IsDone()) { - theResult = MK.Shape(); - return aWarning; - } + is3Pnts = false; + } + } + + // Construct a face based on the plane (in case of three points in the wire) or + // allow MakeFace to build the plane itself (in case of the number of points is greater than 3). + if (is3Pnts) { + BRepBuilderAPI_MakeFace MK (plane, theWire, isPlanarWanted); + if (MK.IsDone()) { + theResult = MK.Shape(); + return aWarning; } } else { - // try to build face on plane or on any surface under the edges of the wire BRepBuilderAPI_MakeFace MK (theWire, isPlanarWanted); if (MK.IsDone()) { theResult = MK.Shape(); @@ -1270,123 +1270,141 @@ TCollection_AsciiString GEOMImpl_Block6Explorer::MakeFace (const TopoDS_Wire& } } - if (!isPlanarWanted) { - // try to construct filling surface - BRepOffsetAPI_MakeFilling MF; + // try to update wire tolerances to build a planar face - Standard_Integer nbEdges = 0; - BRepTools_WireExplorer aWE (theWire); - for (; aWE.More(); aWE.Next(), nbEdges++) { - MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0); - } + // Find a deviation + Standard_Real aToleranceReached, aTol; + BRepLib_FindSurface aFS; + aFS.Init(theWire, -1., isPlanarWanted); + aToleranceReached = aFS.ToleranceReached(); + aTol = aFS.Tolerance(); - MF.Build(); - if (MF.IsDone()) { - // Result of filling - TopoDS_Shape aFace = MF.Shape(); - - // 12.04.2006 for PAL12149 begin - Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace)); - BRepBuilderAPI_MakeFace MK1 (aGS, theWire); - if (MK1.IsDone()) { - TopoDS_Shape aFace1 = MK1.Shape(); - - BRepCheck_Analyzer ana (aFace1, false); - if (!ana.IsValid()) { - TopoDS_Shape aFace2; - ShHealOper_ShapeProcess aHealer; - aHealer.Perform(aFace1, aFace2); - if (aHealer.isDone()) - theResult = aFace2; - } - } - // 12.04.2006 for PAL12149 end + if (!aFS.Found()) { + aFS.Init(theWire, aToleranceReached, isPlanarWanted); + if (!aFS.Found()) return aWarning; + aToleranceReached = aFS.ToleranceReached(); + aTol = aFS.Tolerance(); + } + aTol = Max(1.2 * aToleranceReached, aTol); + + // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM + if (aTol > PLANAR_FACE_MAX_TOLERANCE) { + aWarning = MakeAnyFace(theWire, theResult); + if (aWarning.IsEmpty() && !theResult.IsNull()) + aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG"; + return aWarning; + } + + // Copy the wire, bacause it can be updated with very-very big tolerance here + BRepBuilderAPI_Copy aMC (theWire); + if (!aMC.IsDone()) return aWarning; + TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape()); + // Update tolerances to + BRep_Builder B; + for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) { + TopoDS_Edge anE = TopoDS::Edge(expE.Current()); + B.UpdateEdge(anE, aTol); + } + for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) { + TopoDS_Vertex aV = TopoDS::Vertex(expV.Current()); + B.UpdateVertex(aV, aTol); + } + //BRepLib::UpdateTolerances(aWire); + // Build face + BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted); + if (MK1.IsDone()) { + theResult = MK1.Shape(); + // Mantis issue 0021432: EDF GEOM: Faces with huge tolerance can be built in GEOM + //if (aTol > PLANAR_FACE_MAX_TOLERANCE) + // aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG"; + } - if (theResult.IsNull()) { // try to deal with pure result of filling - // Update tolerance - Standard_Real aTol = MF.G0Error(); + return aWarning; +} - TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire - BRepTools_WireExplorer aWE1 (theWire); - Standard_Integer vi = 1; - for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) { - aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex())); - } +//======================================================================= +//function : MakeAnyFace +//purpose : +//======================================================================= +TCollection_AsciiString GEOMImpl_Block6Explorer::MakeAnyFace (const TopoDS_Wire& theWire, + TopoDS_Shape& theResult) +{ + TCollection_AsciiString aWarning; - // Find maximum deviation in vertices - TopExp_Explorer exp (aFace, TopAbs_VERTEX); - TopTools_MapOfShape mapShape; - for (; exp.More(); exp.Next()) { - if (mapShape.Add(exp.Current())) { - TopoDS_Vertex aV = TopoDS::Vertex(exp.Current()); - Standard_Real aTolV = BRep_Tool::Tolerance(aV); - gp_Pnt aP = BRep_Tool::Pnt(aV); - Standard_Real min_dist = aP.Distance(aPnts(1)); - for (vi = 2; vi <= nbEdges; vi++) { - min_dist = Min(min_dist, aP.Distance(aPnts(vi))); - } - aTol = Max(aTol, aTolV); - aTol = Max(aTol, min_dist); - } - } + // try to build a face on any surface under the edges of the wire + BRepBuilderAPI_MakeFace MK (theWire, Standard_False); + if (MK.IsDone()) { + theResult = MK.Shape(); + return aWarning; + } - if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) { - (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol); - } - theResult = aFace; - } - } - } else { - // try to update wire tolerances to build a planar face + // try to construct filling surface + BRepOffsetAPI_MakeFilling MF; -#if 1 //(OCC_VERSION_MAJOR < 6) || (OCC_VERSION_MAJOR == 6 && OCC_VERSION_MINOR <= 1) - // Find a deviation - Standard_Real aToleranceReached, aTol; - BRepLib_FindSurface aFS; - aFS.Init(theWire, -1., isPlanarWanted); - aToleranceReached = aFS.ToleranceReached(); - aTol = aFS.Tolerance(); + Standard_Integer nbEdges = 0; + BRepTools_WireExplorer aWE (theWire); + for (; aWE.More(); aWE.Next(), nbEdges++) { + MF.Add(TopoDS::Edge(aWE.Current()), GeomAbs_C0); + } - if (!aFS.Found()) { - aFS.Init(theWire, aToleranceReached, isPlanarWanted); - if (!aFS.Found()) return aWarning; - aToleranceReached = aFS.ToleranceReached(); - aTol = aFS.Tolerance(); - } - aTol = Max(1.2 * aToleranceReached, aTol); - - // Copy the wire, bacause it can be updated with very-very big tolerance here - BRepBuilderAPI_Copy aMC (theWire); - if (!aMC.IsDone()) return aWarning; - TopoDS_Wire aWire = TopoDS::Wire(aMC.Shape()); - // Update tolerances to - BRep_Builder B; - for (TopExp_Explorer expE (aWire, TopAbs_EDGE); expE.More(); expE.Next()) { - TopoDS_Edge anE = TopoDS::Edge(expE.Current()); - B.UpdateEdge(anE, aTol); + MF.Build(); + if (!MF.IsDone()) { + aWarning = "BRepOffsetAPI_MakeFilling failed"; + return aWarning; + } + + // Result of filling + TopoDS_Shape aFace = MF.Shape(); + + // 12.04.2006 for PAL12149 begin + Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(aFace)); + BRepBuilderAPI_MakeFace MK1 (aGS, theWire); + if (MK1.IsDone()) { + TopoDS_Shape aFace1 = MK1.Shape(); + + BRepCheck_Analyzer ana (aFace1, false); + if (!ana.IsValid()) { + TopoDS_Shape aFace2; + ShHealOper_ShapeProcess aHealer; + aHealer.Perform(aFace1, aFace2); + if (aHealer.isDone()) + theResult = aFace2; } - for (TopExp_Explorer expV (aWire, TopAbs_VERTEX); expV.More(); expV.Next()) { - TopoDS_Vertex aV = TopoDS::Vertex(expV.Current()); - B.UpdateVertex(aV, aTol); + } + // 12.04.2006 for PAL12149 end + + if (theResult.IsNull()) { // try to deal with pure result of filling + // Update tolerance + Standard_Real aTol = MF.G0Error(); + + TColgp_Array1OfPnt aPnts (1,nbEdges); // points of the given wire + BRepTools_WireExplorer aWE1 (theWire); + Standard_Integer vi = 1; + for (; aWE1.More() && vi <= nbEdges; aWE1.Next(), vi++) { + aPnts(vi) = BRep_Tool::Pnt(TopoDS::Vertex(aWE1.CurrentVertex())); } - //BRepLib::UpdateTolerances(aWire); - // Build face - BRepBuilderAPI_MakeFace MK1 (aWire, isPlanarWanted); - if (MK1.IsDone()) { - theResult = MK1.Shape(); - if (aTol > PLANAR_FACE_MAX_TOLERANCE) - aWarning = "MAKE_FACE_TOLERANCE_TOO_BIG"; - return aWarning; + + // Find maximum deviation in vertices + TopExp_Explorer exp (aFace, TopAbs_VERTEX); + TopTools_MapOfShape mapShape; + for (; exp.More(); exp.Next()) { + if (mapShape.Add(exp.Current())) { + TopoDS_Vertex aV = TopoDS::Vertex(exp.Current()); + Standard_Real aTolV = BRep_Tool::Tolerance(aV); + gp_Pnt aP = BRep_Tool::Pnt(aV); + Standard_Real min_dist = aP.Distance(aPnts(1)); + for (vi = 2; vi <= nbEdges; vi++) { + min_dist = Min(min_dist, aP.Distance(aPnts(vi))); + } + aTol = Max(aTol, aTolV); + aTol = Max(aTol, min_dist); + } } -#else // After migration on OCCT version, containing PKV's fix. See bug 8293 - BRepLib_MakeFace aBMF; - aBMF.Init(theWire, isPlanarWanted, Standard_True); - if (aBMF.Error() == BRepLib_FaceDone) { - theResult = aBMF.Shape(); - return aWarning; + if ((*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance() < aTol) { + (*((Handle(BRep_TFace)*)&aFace.TShape()))->Tolerance(aTol); } -#endif + theResult = aFace; } return aWarning; diff --git a/src/GEOMImpl/GEOMImpl_Block6Explorer.hxx b/src/GEOMImpl/GEOMImpl_Block6Explorer.hxx index ea47dfe37..4e1395a70 100644 --- a/src/GEOMImpl/GEOMImpl_Block6Explorer.hxx +++ b/src/GEOMImpl/GEOMImpl_Block6Explorer.hxx @@ -214,10 +214,26 @@ class GEOMImpl_Block6Explorer const Standard_Boolean findAll = Standard_False); // returns number of found faces + /*! + * Build a face, bound by the given wire. + * \param theWire The initial wire to build the face on. + * \param isPlanarWanted. If true, try to build a planar face. + * \note If isPlanarWanted is true, but planar face cannot be built + * with acceptable tolerance, any face will be built. + * \return Error or warning description. Empty string in case of success. + */ static TCollection_AsciiString MakeFace (const TopoDS_Wire& theWire, const Standard_Boolean isPlanarWanted, TopoDS_Shape& theResult); + /*! + * Build a face, bound by the given wire. + * \param theWire The initial wire to build the face on. + * \return Error or warning description. Empty string in case of success. + */ + static TCollection_AsciiString MakeAnyFace (const TopoDS_Wire& theWire, + TopoDS_Shape& theResult); + private: // ---------- PRIVATE FIELDS ---------- diff --git a/src/GEOM_SWIG/geompyDC.py b/src/GEOM_SWIG/geompyDC.py index cc02d2bc6..502b9f219 100644 --- a/src/GEOM_SWIG/geompyDC.py +++ b/src/GEOM_SWIG/geompyDC.py @@ -1732,7 +1732,8 @@ class geompyDC(GEOM._objref_GEOM_Gen): # Example: see GEOM_TestAll.py anObj = self.ShapesOp.MakeFace(theWire, isPlanarWanted) if anObj is not None and self.ShapesOp.GetErrorCode() == "MAKE_FACE_TOLERANCE_TOO_BIG": - print "WARNING: Tolerance of resulting face is too big." + #print "WARNING: Tolerance of resulting face is too big." + print "WARNING: Cannot build a planar face: required tolerance is too big. Non-planar face is built." else: RaiseIfFailed("MakeFace", self.ShapesOp) return anObj -- 2.39.2