From: Dmitrii Kulikov <164657232+AtheneNoctuaPt@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:37:51 +0000 (+0100) Subject: Modeling - Crash in BRepOffsetAPI_MakePipeShell (#740) X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=df7e26c79dd1cbcc01cd9dd6ccb86a47d81f3614;p=occt.git Modeling - Crash in BRepOffsetAPI_MakePipeShell (#740) Performed a basic refactoring of BRepFill_SectionPlacement::Perform() and fixed a crash. --- diff --git a/src/ModelingAlgorithms/TKBool/BRepFill/BRepFill_SectionPlacement.cxx b/src/ModelingAlgorithms/TKBool/BRepFill/BRepFill_SectionPlacement.cxx index 6fd418faf5..c9d5950069 100644 --- a/src/ModelingAlgorithms/TKBool/BRepFill/BRepFill_SectionPlacement.cxx +++ b/src/ModelingAlgorithms/TKBool/BRepFill/BRepFill_SectionPlacement.cxx @@ -40,10 +40,6 @@ #include #include -#ifdef OCCT_DEBUG -static Standard_Boolean myDebug = Standard_False; -#endif - static Standard_Real SearchParam(const Handle(BRepFill_LocationLaw)& Law, const Standard_Integer Ind, const TopoDS_Vertex& TheV) @@ -91,282 +87,174 @@ void BRepFill_SectionPlacement::Perform(const Standard_Boolean WithContact, const Standard_Boolean WithCorrection, const TopoDS_Shape& Vertex) { - TopoDS_Vertex TheV; - TheV = TopoDS::Vertex(Vertex); - Standard_Integer ii; - Standard_Integer Ind1 = 0, Ind2 = 0; - Standard_Boolean Bof, isVertex = Standard_False; - Standard_Real First = 0., Last = 0.; - TopExp_Explorer Ex; - TopoDS_Edge E; - TopoDS_Vertex V; - Handle(Geom_Curve) C; - Handle(Geom_TrimmedCurve) TC; + Standard_Real anEdgeStartParam = 0.; + Standard_Real anEdgeEndParam = 0.; + Handle(Geom_Curve) aCurve; - // modified by NIZHNY-OCC629 Thu Jul 24 14:11:45 2003 - Standard_Boolean isFound = Standard_False; - Ex.Init(mySection, TopAbs_EDGE); - for (; Ex.More(); Ex.Next()) + // Here we are simply looking for the first valid curve in the section. + TopExp_Explorer anEdgeExplorer(mySection, TopAbs_EDGE); + for (; anEdgeExplorer.More(); anEdgeExplorer.Next()) { - E = TopoDS::Edge(Ex.Current()); - // avoid null, degenerated edges - if (E.IsNull() || BRep_Tool::Degenerated(E)) + const TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current()); + if (anEdge.IsNull() || BRep_Tool::Degenerated(anEdge)) continue; - C = BRep_Tool::Curve(E, First, Last); - if (C.IsNull()) + + aCurve = BRep_Tool::Curve(anEdge, anEdgeStartParam, anEdgeEndParam); + if (aCurve.IsNull()) continue; - isFound = Standard_True; + break; } - if (!isFound) - isVertex = Standard_True; + + Handle(Geom_Geometry) aSection; + if (aCurve.IsNull()) + { + // No edge found : the section is a vertex + TopExp_Explorer aVertexExplorer(mySection, TopAbs_VERTEX); + const TopoDS_Vertex aFirstVertex = TopoDS::Vertex(aVertexExplorer.Current()); + const gp_Pnt aPoint = BRep_Tool::Pnt(aFirstVertex); + aSection = new Geom_CartesianPoint(aPoint); + } else { - TC = new (Geom_TrimmedCurve)(C, First, Last); - Ex.Next(); + Handle(Geom_TrimmedCurve) aTrimmedCurve = + new Geom_TrimmedCurve(aCurve, anEdgeStartParam, anEdgeEndParam); + anEdgeExplorer.Next(); - if (Ex.More()) + if (anEdgeExplorer.More()) { - Standard_Real tolrac, epsV; - constexpr Standard_Real tol = Precision::Confusion(); - GeomConvert_CompCurveToBSplineCurve Conv(TC); - for (; Ex.More(); Ex.Next()) + constexpr Standard_Real aPrecisionTolerance = Precision::Confusion(); + GeomConvert_CompCurveToBSplineCurve aBSplineConverter(aTrimmedCurve); + for (; anEdgeExplorer.More(); anEdgeExplorer.Next()) { - E = TopoDS::Edge(Ex.Current()); + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current()); // avoid null, degenerated edges - if (E.IsNull() || BRep_Tool::Degenerated(E)) + if (anEdge.IsNull() || BRep_Tool::Degenerated(anEdge)) continue; - TopoDS_Vertex VFirst, VLast; - TopExp::Vertices(E, VFirst, VLast); - epsV = Max(BRep_Tool::Tolerance(VFirst), BRep_Tool::Tolerance(VLast)); - C = BRep_Tool::Curve(E, First, Last); - if (C.IsNull()) + + aCurve = BRep_Tool::Curve(anEdge, anEdgeStartParam, anEdgeEndParam); + if (aCurve.IsNull()) continue; - TC = new (Geom_TrimmedCurve)(C, First, Last); - tolrac = Min(tol, epsV); - Bof = Conv.Add(TC, tolrac); - if (!Bof) + + TopoDS_Vertex aFirstVertex; + TopoDS_Vertex aLastVertex; + TopExp::Vertices(anEdge, aFirstVertex, aLastVertex); + const Standard_Real aVertexTolerance = + Max(BRep_Tool::Tolerance(aFirstVertex), BRep_Tool::Tolerance(aLastVertex)); + + aTrimmedCurve = new Geom_TrimmedCurve(aCurve, anEdgeStartParam, anEdgeEndParam); + if (!aBSplineConverter.Add(aTrimmedCurve, Min(aPrecisionTolerance, aVertexTolerance))) { - tolrac = Max(tol, epsV); - Bof = Conv.Add(TC, tolrac); + aBSplineConverter.Add(aTrimmedCurve, Max(aPrecisionTolerance, aVertexTolerance)); } } - C = Conv.BSplineCurve(); + aCurve = aBSplineConverter.BSplineCurve(); } else - C = TC; // On garde l'unique courbe - } - - // modified by NIZHNY-629 Fri Jul 25 11:10:27 2003 b - - // // punctual section - // Ex.Init(mySection, TopAbs_EDGE); - // Standard_Boolean isPonctual = Standard_False; - // if (Ex.More()) { - // E = TopoDS::Edge(Ex.Current()); - // isPonctual = BRep_Tool::Degenerated(E); - // } - - // Ex.Init(mySection, TopAbs_EDGE); - // if (Ex.More()&&!isPonctual) { - // E = TopoDS::Edge(Ex.Current()); - // C = BRep_Tool::Curve(E, First, Last); - // TC = new (Geom_TrimmedCurve)(C, First, Last); - // Ex.Next(); - // if (Ex.More()) { // On essai d'avoir un echantillon representatif - // Standard_Real tolrac, epsV, tol = Precision::Confusion(); - // GeomConvert_CompCurveToBSplineCurve Conv(TC); - // for (; Ex.More(); Ex.Next()) { - // E = TopoDS::Edge(Ex.Current()); - // TopoDS_Vertex VFirst, VLast; - // TopExp::Vertices(E,VFirst, VLast); - // epsV = Max(BRep_Tool::Tolerance(VFirst), BRep_Tool::Tolerance(VLast)); - // C = BRep_Tool::Curve(E, First, Last); - // TC = new (Geom_TrimmedCurve)(C, First, Last); - // tolrac = Min(tol,epsV); - // Bof = Conv.Add(TC, tolrac); - // if (!Bof) { - // tolrac = Max(tol,epsV); - // Bof = Conv.Add(TC, tolrac); - // } - // } - // C = Conv.BSplineCurve(); - // } - // else C = TC; // On garde l'unique courbe - // } - // else { - // // Localisation par distance Shape/Shape - // Standard_Real Tpos; - // BRepExtrema_DistShapeShape Ext(mySection, myLaw->Wire()); - - // if (! Ext.IsDone()) - // throw Standard_ConstructionError("Distance Vertex/Spine"); - - // if (Ext.SupportTypeShape2(1) == BRepExtrema_IsOnEdge) { - // TopoDS_Shape sbis = Ext.SupportOnShape2(1); - // E = TopoDS::Edge(sbis); - // Ext.ParOnEdgeS2(1, Tpos); - // } - // else { - // TopoDS_Vertex Vf, Vl,V; - // TopoDS_Shape sbis = Ext.SupportOnShape2(1); - // V = TopoDS::Vertex(sbis); - // for (ii=1, Ind1=0 ; ii<=myLaw->NbLaw(); ii++) { - // E = myLaw->Edge(ii); - // TopExp::Vertices(E, Vf, Vl); - // if ((V.IsSame(Vf)) || (V.IsSame(Vl))) { - // if (Ind1 == 0) Ind1 = ii; - // else Ind2 = ii; - // } - // } - - // // On invente une section - // gp_Dir D(0, 0, 1); - // gp_Pnt Origine, PV; - // Origine = BRep_Tool::Pnt(V); - // Standard_Real length; - - // if (Ext.SupportTypeShape1(1) == BRepExtrema_IsVertex) { - // TopoDS_Shape aLocalShape = Ext.SupportOnShape1(1); - // PV = BRep_Tool::Pnt(TopoDS::Vertex(aLocalShape)); - // // PV = BRep_Tool::Pnt(TopoDS::Vertex(Ext.SupportOnShape1(1))); - // } - // else { - // PV = BRep_Tool::Pnt(TopoDS::Vertex(mySection)); - // } - // length = Origine.Distance(PV); - // if (length > Precision::Confusion()) { - // gp_Vec theVec(Origine, PV); - // D.SetXYZ(theVec.XYZ()); - // } - // else length = 10*Precision::Confusion(); - // Handle(Geom_Line) CL = new (Geom_Line) (Origine, D); - // TC = new (Geom_TrimmedCurve)(CL, 0., length); - // C = TC; - // isVertex = Standard_True; - // } - // } - - // // Recherche du Vertex de positionnement - // if (!TheV.IsNull()) { - // Standard_Integer NbV = myLaw->NbLaw()+1; - // for (ii=1, Ind1=0; ii<=NbV && (!Ind1); ii++) - // if (TheV.IsSame(myLaw->Vertex(ii))) Ind1 = ii; - - // if (Ind1 != 0) { - // Ind2 =0; - // isVertex = Standard_True; - // if (Ind1==1) { - // if (myLaw->IsClosed()) Ind2 = NbV-1; - // } - // else { - // Ind1--; - // if (Ind1 < NbV-1) - // Ind2 = Ind1+1; - // } - // } - // else { - // TheV.Nullify(); // On oublie cette option... - // } - // } - - // modified by NIZHNY-629 Fri Jul 25 11:11:06 2003 e + { + aCurve = aTrimmedCurve; + } - // Construction - Handle(Geom_Geometry) theSection = C; - if (isVertex) - { - Ex.Init(mySection, TopAbs_VERTEX); - TopoDS_Vertex theVertex = TopoDS::Vertex(Ex.Current()); - gp_Pnt thePoint = BRep_Tool::Pnt(theVertex); - theSection = new Geom_CartesianPoint(thePoint); + aSection = aCurve; } - GeomFill_SectionPlacement Place(myLaw->Law(1), theSection); + GeomFill_SectionPlacement aSectionPlacement(myLaw->Law(1), aSection); + Handle(BRepAdaptor_CompCurve) aWireAdaptor = new BRepAdaptor_CompCurve(myLaw->Wire()); + aSectionPlacement.Perform(aWireAdaptor, Precision::Confusion()); + const Standard_Real aSectionParam = aSectionPlacement.ParameterOnPath(); + constexpr Standard_Real aParamConfusion = Precision::PConfusion(); + + Standard_Integer aLawIndex1 = 0; + Standard_Integer aLawIndex2 = 0; // In the general case : Localisation via concatenation of the spine - TColStd_Array1OfReal SuperKnot(1, myLaw->NbLaw() + 1); - for (ii = 1; ii <= myLaw->NbLaw(); ii++) + Standard_Boolean anIsIntervalFound = Standard_False; + for (int aLawIndex = 1; aLawIndex <= myLaw->NbLaw() && !anIsIntervalFound; ++aLawIndex) { - SuperKnot(ii + 1) = ii; - } - SuperKnot(1) = 0; - - Handle(BRepAdaptor_CompCurve) adpPath = new (BRepAdaptor_CompCurve)(myLaw->Wire()); + const Standard_Real aCurrKnotParam = aLawIndex - 1; + const Standard_Real aNextKnotParam = aLawIndex; - Place.Perform(adpPath, Precision::Confusion()); - - Standard_Real theParam = Place.ParameterOnPath(); - constexpr Standard_Real eps = Precision::PConfusion(); + // Check if the section parameter is in the interval [aCurrKnotParam, aNextKnotParam] + anIsIntervalFound = (aCurrKnotParam - aParamConfusion <= aSectionParam) + && (aNextKnotParam + aParamConfusion >= aSectionParam); + if (!anIsIntervalFound) + { + continue; + } -#ifdef OCCT_DEBUG - if (myDebug) - { - gp_Pnt P_Path; - P_Path = adpPath->Value(theParam); - std::cout << "Point on Path" << P_Path.X() << ", " << P_Path.Y() << ", " << P_Path.Z() << ", " - << std::endl; + aLawIndex1 = aLawIndex; + if ((Abs(aSectionParam - aCurrKnotParam) < aParamConfusion) && (aLawIndex > 1)) + { + aLawIndex2 = aLawIndex - 1; + } + else if ((Abs(aSectionParam - aNextKnotParam) < aParamConfusion) + && (aLawIndex < myLaw->NbLaw())) + { + aLawIndex2 = aLawIndex + 1; + } } -#endif - for (ii = 1, Bof = Standard_True; ii <= myLaw->NbLaw() && Bof; ii++) + if (!anIsIntervalFound) { - Bof = !((SuperKnot(ii) - eps <= theParam) && (SuperKnot(ii + 1) + eps >= theParam)); - if (!Bof) - { - Ind1 = ii; - if ((Abs(theParam - SuperKnot(ii)) < eps) && (ii > 1)) - Ind2 = ii - 1; - else if ((Abs(theParam - SuperKnot(ii + 1)) < eps) && (ii < myLaw->NbLaw())) - Ind2 = ii + 1; - } + throw Standard_ConstructionError("Interval is not found"); } - if (Bof) - throw Standard_ConstructionError("Interval non trouve !!"); // Search of the by vertex - if (!TheV.IsNull()) - for (Ind1 = 1; Ind1 <= myLaw->NbLaw(); Ind1++) + bool anIsVertexOnLaw = false; + TopoDS_Vertex aVertex = TopoDS::Vertex(Vertex); + if (!aVertex.IsNull()) + { + for (int aCurrentLawIndex = 1; aCurrentLawIndex <= myLaw->NbLaw(); ++aCurrentLawIndex) { - TopoDS_Edge anEdge = myLaw->Edge(Ind1); + TopoDS_Edge anEdge = myLaw->Edge(aCurrentLawIndex); TopoDS_Vertex V1, V2; TopExp::Vertices(anEdge, V1, V2); - if (V1.IsSame(TheV) || V2.IsSame(TheV)) + if (V1.IsSame(aVertex) || V2.IsSame(aVertex)) + { + anIsVertexOnLaw = true; + aLawIndex1 = aCurrentLawIndex; + aLawIndex2 = 0; break; + } } + } //////////////////// // Positioning on the localized edge (or 2 Edges) - Standard_Real Angle; - Place.SetLocation(myLaw->Law(Ind1)); - if (TheV.IsNull()) - Place.Perform(Precision::Confusion()); + + aSectionPlacement.SetLocation(myLaw->Law(aLawIndex1)); + if (!anIsVertexOnLaw) + { + aSectionPlacement.Perform(Precision::Confusion()); + } else { - Place.Perform(SearchParam(myLaw, Ind1, TheV), Precision::Confusion()); + aSectionPlacement.Perform(SearchParam(myLaw, aLawIndex1, aVertex), Precision::Confusion()); } - myTrsf = Place.Transformation(WithContact, WithCorrection); - myIndex = Ind1; - myParam = Place.ParameterOnPath(); - Angle = Place.Angle(); + myTrsf = aSectionPlacement.Transformation(WithContact, WithCorrection); + myIndex = aLawIndex1; + myParam = aSectionPlacement.ParameterOnPath(); + Standard_Real Angle = aSectionPlacement.Angle(); - if (Ind2) + if (aLawIndex2) { - Place.SetLocation(myLaw->Law(Ind2)); - if (TheV.IsNull()) - Place.Perform(Precision::Confusion()); + aSectionPlacement.SetLocation(myLaw->Law(aLawIndex2)); + if (!anIsVertexOnLaw) + { + aSectionPlacement.Perform(Precision::Confusion()); + } else { - if (Ind1 == Ind2) - TheV.Reverse(); - Place.Perform(SearchParam(myLaw, Ind2, TheV), Precision::Confusion()); + if (aLawIndex1 == aLawIndex2) + aVertex.Reverse(); + aSectionPlacement.Perform(SearchParam(myLaw, aLawIndex2, aVertex), Precision::Confusion()); } - if (Place.Angle() > Angle) + if (aSectionPlacement.Angle() > Angle) { - myTrsf = Place.Transformation(WithContact, WithCorrection); - myIndex = Ind2; - myParam = Place.ParameterOnPath(); + myTrsf = aSectionPlacement.Transformation(WithContact, WithCorrection); + myIndex = aLawIndex2; + myParam = aSectionPlacement.ParameterOnPath(); } } }