From 0b6a0adb3aa45e0437be8d2e65e9d0f80856df42 Mon Sep 17 00:00:00 2001 From: knosulko Date: Thu, 13 Jan 2022 03:17:50 +0300 Subject: [PATCH] 0032767: Mesh - incorrect splitting of edges of seams leading to hang [since OCCT 7.4.0] - fix step by parameter of the edge while split curve in case of seam edges --- src/BRepMesh/BRepMesh_ModelPreProcessor.cxx | 85 +++++++++++++++------ tests/bugs/mesh/bug32767 | 9 +++ 2 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 tests/bugs/mesh/bug32767 diff --git a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx index 5466059a53..4eefa24287 100644 --- a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx +++ b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx @@ -133,7 +133,7 @@ namespace { if (aDEdge->GetCurve()->ParametersNb() == 2) { - if (splitEdge (aDEdge, Abs (getConeStep (aDFace)))) + if (splitEdge (aDEdge, aDFace, Abs (getConeStep (aDFace)))) { TopLoc_Location aLoc; const Handle (Poly_Triangulation)& aTriangulation = @@ -178,48 +178,89 @@ namespace } //! Splits 3D and all pcurves accordingly using the specified step. - Standard_Boolean splitEdge(const IMeshData::IEdgePtr& theDEdge, - const Standard_Real theDU) const + Standard_Boolean splitEdge(const IMeshData::IEdgePtr& theDEdge, + const IMeshData::IFaceHandle& theDFace, + const Standard_Real theDU) const { - if (!splitCurve (theDEdge->GetCurve (), theDU)) + TopoDS_Edge aE = theDEdge->GetEdge(); + const TopoDS_Face& aF = theDFace->GetFace(); + + Standard_Real aFParam, aLParam; + + Handle(Geom_Curve) aHC = BRep_Tool::Curve (aE, aFParam, aLParam); + + const IMeshData::IPCurveHandle& aIPC1 = theDEdge->GetPCurve(0); + const IMeshData::IPCurveHandle& aIPC2 = theDEdge->GetPCurve(1); + + // Calculate the step by parameter of the curve. + const gp_Pnt2d& aFPntOfIPC1 = aIPC1->GetPoint (0); + const gp_Pnt2d& aLPntOfIPC1 = aIPC1->GetPoint (aIPC1->ParametersNb() - 1); + const Standard_Real aMod = Abs (aFPntOfIPC1.Y() - aLPntOfIPC1.Y()); + + if (aMod < gp::Resolution()) { return Standard_False; } - for (Standard_Integer aPCurveIdx = 0; aPCurveIdx < theDEdge->PCurvesNb(); ++aPCurveIdx) + const Standard_Real aDT = Abs (aLParam - aFParam) / aMod * theDU; + + if (!splitCurve (aHC, theDEdge->GetCurve(), aDT)) { - splitCurve (theDEdge->GetPCurve (aPCurveIdx), theDU); + return Standard_False; } + // Define two pcurves of the seam-edge. + Handle(Geom2d_Curve) aPC1, aPC2; + Standard_Real af, al; + + aE.Orientation (TopAbs_FORWARD); + aPC1 = BRep_Tool::CurveOnSurface (aE, aF, af, al); + + aE.Orientation (TopAbs_REVERSED); + aPC2 = BRep_Tool::CurveOnSurface (aE, aF, af, al); + + if (aPC1.IsNull() || aPC2.IsNull()) + { + return Standard_False; + } + + // Select the correct pcurve of the seam-edge. + const gp_Pnt2d& aFPntOfPC1 = aPC1->Value (aPC1->FirstParameter()); + + if (Abs (aLPntOfIPC1.X() - aFPntOfPC1.X()) > Precision::Confusion()) + { + std::swap (aPC1, aPC2); + } + + splitCurve (aPC1, aIPC1, aDT); + splitCurve (aPC2, aIPC2, aDT); + return Standard_True; } //! Splits the given curve using the specified step. - template - Standard_Boolean splitCurve(Curve& theCurve, const Standard_Real theDU) const + template + Standard_Boolean splitCurve(GeomCurve& theGeomCurve, + Curve& theCurve, + const Standard_Real theDT) const { Standard_Boolean isUpdated = Standard_False; - PointType aDir = theCurve->GetPoint(theCurve->ParametersNb() - 1).Coord() - theCurve->GetPoint(0).Coord(); - const Standard_Real aModulus = aDir.Modulus(); - if (aModulus < gp::Resolution()) - { - return isUpdated; - } - aDir /= aModulus; - const Standard_Real aLastParam = theCurve->GetParameter(theCurve->ParametersNb() - 1); - const Standard_Boolean isReversed = theCurve->GetParameter(0) > aLastParam; + const Standard_Real aFirstParam = theCurve->GetParameter (0); + const Standard_Real aLastParam = theCurve->GetParameter (theCurve->ParametersNb() - 1); + const Standard_Boolean isReversed = aFirstParam > aLastParam; + for (Standard_Integer aPointIdx = 1; ; ++aPointIdx) { - const Standard_Real aCurrParam = theCurve->GetParameter(0) + aPointIdx * theDU * (isReversed ? -1.0 : 1.0); - if (( isReversed && (aCurrParam < aLastParam)) || - (!isReversed && !(aCurrParam < aLastParam))) + const Standard_Real aCurrParam = aFirstParam + aPointIdx * theDT * (isReversed ? -1.0 : 1.0); + if (( isReversed && (aCurrParam - aLastParam < Precision::PConfusion())) || + (!isReversed && !(aCurrParam - aLastParam < - Precision::PConfusion()))) { break; } - theCurve->InsertPoint(theCurve->ParametersNb() - 1, - theCurve->GetPoint(0).Translated (aDir * aPointIdx * theDU), + theCurve->InsertPoint (theCurve->ParametersNb() - 1, + theGeomCurve->Value (aCurrParam), aCurrParam); isUpdated = Standard_True; diff --git a/tests/bugs/mesh/bug32767 b/tests/bugs/mesh/bug32767 new file mode 100644 index 0000000000..b5e472cfe6 --- /dev/null +++ b/tests/bugs/mesh/bug32767 @@ -0,0 +1,9 @@ +puts "================" +puts "0032767: Mesh - incorrect splitting of edges of seams leading to hang \[since OCCT 7.4.0\] " +puts "================" +puts "" + +restore [locate_data_file bug32767.brep] s +tclean s +incmesh s 0.01 +checktrinfo s -tri 3220 -nod 1770 -defl 0.018398669654253779 -tol_abs_defl 1e-6 \ No newline at end of file