From 3ce6f885105d639a0a6aacbf8c2d1f8201b17cd9 Mon Sep 17 00:00:00 2001 From: jgv Date: Fri, 17 Sep 2021 15:16:20 +0300 Subject: [PATCH] Fix of crash in "thickshell" functionality --- src/BRepOffset/BRepOffset_Analyse.cxx | 148 ++++++++++++++++++++++---- 1 file changed, 127 insertions(+), 21 deletions(-) diff --git a/src/BRepOffset/BRepOffset_Analyse.cxx b/src/BRepOffset/BRepOffset_Analyse.cxx index 1e215a3801..edddededf6 100644 --- a/src/BRepOffset/BRepOffset_Analyse.cxx +++ b/src/BRepOffset/BRepOffset_Analyse.cxx @@ -46,7 +46,11 @@ #include #include #include +#include #include +#include +#include +#include // static void Correct2dPoint(const TopoDS_Face& theF, gp_Pnt2d& theP2d); // @@ -54,10 +58,15 @@ static Standard_Real IntermediatePoint(const Standard_Real aFirst, const Standard_Real aLast); // static BRepOffset_Type DefineConnectType(const TopoDS_Edge& E, - const TopoDS_Face& F1, - const TopoDS_Face& F2, - const Standard_Real SinTol, + const TopoDS_Face& F1, + const TopoDS_Face& F2, + const Standard_Real SinTol, const Standard_Boolean CorrectPoint); + +static Standard_Boolean IsTangentFaces(const TopoDS_Edge &theEdge, + const TopoDS_Face &theFace1, + const TopoDS_Face &theFace2, + const GeomAbs_Shape Order); // static void CorrectOrientationOfTangent(gp_Vec& TangVec, const TopoDS_Vertex& aVertex, @@ -101,27 +110,37 @@ static void EdgeAnalyse(const TopoDS_Edge& E, const Standard_Real SinTol, BRepOffset_ListOfInterval& LI) { - Standard_Real f,l; BRep_Tool::Range(E, F1, f, l); BRepOffset_Interval I; I.First(f); I.Last(l); - // - // Tangent if the regularity is at least G1. - if (BRep_Tool::HasContinuity(E,F1,F2)) { - if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) { - I.Type(BRepOffset_Tangent); - LI.Append(I); - return; - } + // + BRepAdaptor_Surface aBAsurf1(F1, Standard_False); + GeomAbs_SurfaceType aSurfType1 = aBAsurf1.GetType(); + + BRepAdaptor_Surface aBAsurf2(F2, Standard_False); + GeomAbs_SurfaceType aSurfType2 = aBAsurf2.GetType(); + + Standard_Boolean isTwoPlanes = (aSurfType1 == GeomAbs_Plane && aSurfType2 == GeomAbs_Plane); + + BRepOffset_Type ConnectType = BRepOffset_Other; + + if (isTwoPlanes) //then use only strong condition + { + if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) + ConnectType = BRepOffset_Tangent; + else + ConnectType = DefineConnectType(E, F1, F2, SinTol, Standard_False); } - // - BRepOffset_Type aType = DefineConnectType(E, F1, F2, SinTol, Standard_False); - if(aType != BRepOffset_Tangent) + else { - aType = DefineConnectType(E, F1, F2, SinTol, Standard_True); + if (IsTangentFaces(E, F1, F2, GeomAbs_G1)) //weak condition + ConnectType = BRepOffset_Tangent; + else + ConnectType = DefineConnectType(E, F1, F2, SinTol, Standard_False); } - I.Type(aType); + + I.Type(ConnectType); LI.Append(I); } @@ -176,7 +195,7 @@ void BRepOffset_Analyse::Perform (const TopoDS_Shape& S, myShape = S; angle = Angle; - Standard_Real SinTol = Abs(Sin(Angle)); + Standard_Real SinTol = Sin(Angle); // Build ancestors. BuildAncestors (S,ancestors); @@ -550,9 +569,9 @@ Standard_Real IntermediatePoint(const Standard_Real aFirst, //purpose : //======================================================================= BRepOffset_Type DefineConnectType(const TopoDS_Edge& E, - const TopoDS_Face& F1, - const TopoDS_Face& F2, - const Standard_Real SinTol, + const TopoDS_Face& F1, + const TopoDS_Face& F2, + const Standard_Real SinTol, const Standard_Boolean CorrectPoint) { const Handle(Geom_Surface)& S1 = BRep_Tool::Surface(F1); @@ -640,3 +659,90 @@ BRepOffset_Type DefineConnectType(const TopoDS_Edge& E, } } } + +//======================================================================= +//function : IsTangentFaces +//purpose : +//======================================================================= +Standard_Boolean IsTangentFaces(const TopoDS_Edge &theEdge, + const TopoDS_Face &theFace1, + const TopoDS_Face &theFace2, + const GeomAbs_Shape Order) +{ + if (Order == GeomAbs_G1 && + BRep_Tool::Continuity( theEdge, theFace1, theFace2 ) != GeomAbs_C0) + return Standard_True; + + Standard_Real TolC0 = Max(0.001, 1.5*BRep_Tool::Tolerance(theEdge)); + + Standard_Real aFirst; + Standard_Real aLast; + +// Obtaining of pcurves of edge on two faces. + const Handle(Geom2d_Curve) aC2d1 = BRep_Tool::CurveOnSurface + (theEdge, theFace1, aFirst, aLast); + const Handle(Geom2d_Curve) aC2d2 = BRep_Tool::CurveOnSurface + (theEdge, theFace2, aFirst, aLast); + if (aC2d1.IsNull() || aC2d2.IsNull()) + return Standard_False; + +// Obtaining of two surfaces from adjacent faces. + Handle(Geom_Surface) aSurf1 = BRep_Tool::Surface(theFace1); + Handle(Geom_Surface) aSurf2 = BRep_Tool::Surface(theFace2); + + if (aSurf1.IsNull() || aSurf2.IsNull()) + return Standard_False; + +// Computation of the number of samples on the edge. + BRepAdaptor_Surface aBAS1(theFace1); + BRepAdaptor_Surface aBAS2(theFace2); + Handle(BRepAdaptor_HSurface) aBAHS1 = new BRepAdaptor_HSurface(aBAS1); + Handle(BRepAdaptor_HSurface) aBAHS2 = new BRepAdaptor_HSurface(aBAS2); + Handle(BRepTopAdaptor_TopolTool) aTool1 = new BRepTopAdaptor_TopolTool(aBAHS1); + Handle(BRepTopAdaptor_TopolTool) aTool2 = new BRepTopAdaptor_TopolTool(aBAHS2); + Standard_Integer aNbSamples1 = aTool1->NbSamples(); + Standard_Integer aNbSamples2 = aTool2->NbSamples(); + Standard_Integer aNbSamples = Max(aNbSamples1, aNbSamples2); + + +// Computation of the continuity. + Standard_Real aPar; + Standard_Real aDelta = (aLast - aFirst)/(aNbSamples - 1); + Standard_Integer i, nbNotDone = 0; + + for (i = 1, aPar = aFirst; i <= aNbSamples; i++, aPar += aDelta) { + if (i == aNbSamples) aPar = aLast; + + LocalAnalysis_SurfaceContinuity aCont(aC2d1, aC2d2, aPar, + aSurf1, aSurf2, Order, + 0.001, TolC0, 0.1, 0.1, 0.1); + if (!aCont.IsDone()) + { + nbNotDone++; + continue; + } + + if (Order == GeomAbs_G1) + { + if (!aCont.IsG1()) + return Standard_False; + } + else if (!aCont.IsG2()) + return Standard_False; + } + + if (nbNotDone == aNbSamples) + return Standard_False; + + //Compare normals of tangent faces in the middle point + Standard_Real MidPar = (aFirst + aLast)/2.; + gp_Pnt2d uv1 = aC2d1->Value(MidPar); + gp_Pnt2d uv2 = aC2d2->Value(MidPar); + gp_Dir normal1, normal2; + TopOpeBRepTool_TOOL::Nt( uv1, theFace1, normal1 ); + TopOpeBRepTool_TOOL::Nt( uv2, theFace2, normal2 ); + Standard_Real dot = normal1.Dot(normal2); + if (dot < 0.) + return Standard_False; + return Standard_True; +} -- 2.39.5