From: jgv Date: Tue, 15 Mar 2022 11:34:17 +0000 (+0300) Subject: 0032833: Shape Healing - FixShape needs to be improved X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=6b9da8620106dfd9848dc50f29cca55ba469daf5;p=occt.git 0032833: Shape Healing - FixShape needs to be improved First version --- diff --git a/src/BRepCheck/BRepCheck_Wire.cxx b/src/BRepCheck/BRepCheck_Wire.cxx index 10e40a8165..c65357e1a9 100644 --- a/src/BRepCheck/BRepCheck_Wire.cxx +++ b/src/BRepCheck/BRepCheck_Wire.cxx @@ -425,6 +425,16 @@ Standard_Boolean IsDistanceIn2DTolerance (const BRepAdaptor_Surface& aFaceSurfac const Standard_Boolean = Standard_True) #endif { + gp_Pnt aP; + gp_Vec aDU, aDV; + Standard_Real um = (thePnt.X() + thePntRef.X()) / 2.; + Standard_Real vm = (thePnt.Y() + thePntRef.Y()) / 2.; + aFaceSurface.D1(um, vm, aP, aDU, aDV); + Standard_Real aMDU = aDU.Magnitude(); + Standard_Real aMDV = aDV.Magnitude(); + if (aMDU > Precision::Confusion() && aMDV > Precision::Confusion()) + return Standard_True; //we are not in singularity + Standard_Real dumax = 0.01 * (aFaceSurface.LastUParameter() - aFaceSurface.FirstUParameter()); Standard_Real dvmax = 0.01 * (aFaceSurface.LastVParameter() - aFaceSurface.FirstVParameter()); Standard_Real dumin = Abs(thePnt.X() - thePntRef.X()); @@ -453,17 +463,17 @@ Standard_Boolean IsDistanceIn2DTolerance (const BRepAdaptor_Surface& aFaceSurfac #endif dumax = aFaceSurface.UResolution(aTol3d); dvmax = aFaceSurface.VResolution(aTol3d); - gp_Pnt aP; - gp_Vec aDU, aDV; - Standard_Real um = (thePnt.X() + thePntRef.X()) / 2.; - Standard_Real vm = (thePnt.Y() + thePntRef.Y()) / 2.; - aFaceSurface.D1(um, vm, aP, aDU, aDV); - Standard_Real aMDU = aDU.Magnitude(); + //gp_Pnt aP; + //gp_Vec aDU, aDV; + //Standard_Real um = (thePnt.X() + thePntRef.X()) / 2.; + //Standard_Real vm = (thePnt.Y() + thePntRef.Y()) / 2.; + //aFaceSurface.D1(um, vm, aP, aDU, aDV); + //Standard_Real aMDU = aDU.Magnitude(); if (aMDU > Precision::Confusion()) { dumax = Max((aTol3d / aMDU), dumax); } - Standard_Real aMDV = aDV.Magnitude(); + //Standard_Real aMDV = aDV.Magnitude(); if (aMDV > Precision::Confusion()) { dvmax = Max((aTol3d / aMDV), dvmax); diff --git a/src/BRepTools/BRepTools_WireExplorer.cxx b/src/BRepTools/BRepTools_WireExplorer.cxx index 0cd69bc486..52aec1d237 100644 --- a/src/BRepTools/BRepTools_WireExplorer.cxx +++ b/src/BRepTools/BRepTools_WireExplorer.cxx @@ -54,6 +54,29 @@ static Standard_Real GetNextParamOnPC(const Handle(Geom2d_Curve)& aPC, const Standard_Real& tolV, const Standard_Boolean& reverse); +static Standard_Real LocalUresol (const TopoDS_Vertex& theVertex, + const TopoDS_Face& theFace, + const gp_Pnt2d& theP2d1, + const gp_Pnt2d& theP2d2) +{ + Standard_Real aResol = -1; + + BRepAdaptor_Surface aBAsurf (theFace, Standard_False); + if (aBAsurf.GetType() == GeomAbs_Sphere) + { + Standard_Real aRadius = aBAsurf.Sphere().Radius(); + Standard_Real aVmid = (theP2d1.Y() + theP2d2.Y())/2.; + Standard_Real aLocalRad = aRadius * Cos(aVmid); + if (aLocalRad > Precision::Confusion()) + { + Standard_Real aTolVertex = BRep_Tool::Tolerance (theVertex); + aResol = aTolVertex / aLocalRad; + } + } + + return aResol; +} + //======================================================================= //function : BRepTools_WireExplorer //purpose : @@ -536,56 +559,56 @@ void BRepTools_WireExplorer::Next() it.Initialize(l); while( it.More() ) { - const TopoDS_Edge& E = TopoDS::Edge(it.Value()); - if( E.IsSame(myEdge) ) - { - it.Next(); - k++; - continue; - } - - TopoDS_Vertex aVert1, aVert2; - TopExp::Vertices (E, aVert1, aVert2, Standard_True); - if( aVert1.IsNull() || aVert2.IsNull() ) + const TopoDS_Edge& E = TopoDS::Edge(it.Value()); + if( E.IsSame(myEdge) ) { it.Next(); k++; continue; } - - aPCurve = BRep_Tool::CurveOnSurface (E, myFace, dfFPar, dfLPar); - if( aPCurve.IsNull() ) + + TopoDS_Vertex aVert1, aVert2; + TopExp::Vertices (E, aVert1, aVert2, Standard_True); + if( aVert1.IsNull() || aVert2.IsNull() ) { it.Next(); k++; continue; } - - gp_Pnt2d aPEb, aPEe; - if( aVert1.IsSame(aVert2) == isDegenerated ) - { - if( E.Orientation() == TopAbs_REVERSED ) - aPCurve->D0(dfLPar, aPEb); - else - aPCurve->D0(dfFPar, aPEb); - - if( Abs(dfLPar-dfFPar) > Precision::PConfusion() ) - { - isrevese = ( E.Orientation() == TopAbs_REVERSED ); - isrevese = !isrevese; - Standard_Real aEPm = GetNextParamOnPC(aPCurve,aPEb,dfFPar,dfLPar,myTolU,myTolV,isrevese); - - aPCurve->D0 (aEPm, aPEe); + + aPCurve = BRep_Tool::CurveOnSurface (E, myFace, dfFPar, dfLPar); + if( aPCurve.IsNull() ) + { + it.Next(); + k++; + continue; + } + + gp_Pnt2d aPEb, aPEe; + if( aVert1.IsSame(aVert2) == isDegenerated ) + { + if( E.Orientation() == TopAbs_REVERSED ) + aPCurve->D0(dfLPar, aPEb); + else + aPCurve->D0(dfFPar, aPEb); + + if( Abs(dfLPar-dfFPar) > Precision::PConfusion() ) + { + isrevese = ( E.Orientation() == TopAbs_REVERSED ); + isrevese = !isrevese; + Standard_Real aEPm = GetNextParamOnPC(aPCurve,aPEb,dfFPar,dfLPar,myTolU,myTolV,isrevese); + + aPCurve->D0 (aEPm, aPEe); if(aPEb.SquareDistance(aPEe) <= gp::Resolution()) { //seems to be very short curve gp_Vec2d aD; aPCurve->D1(aEPm, aPEe, aD); - if( E.Orientation() == TopAbs_REVERSED ) + if( E.Orientation() == TopAbs_REVERSED ) aPEe.SetXY(aPEb.XY()-aD.XY()); - else + else aPEe.SetXY(aPEb.XY()+aD.XY()); - + if(aPEb.SquareDistance(aPEe) <= gp::Resolution()) { it.Next(); @@ -593,35 +616,39 @@ void BRepTools_WireExplorer::Next() continue; } } - gp_Vec2d anEDir(aPEb, aPEe); - dfCurAngle = Abs( anEDir.Angle(anERefDir) ); - } - - if( dfCurAngle <= dfMinAngle ) - { - Standard_Real d = PRef.SquareDistance(aPEb); - if( d <= Precision::PConfusion() ) - d = 0.; - if( Abs(aPEb.X()-PRef.X()) < myTolU && Abs(aPEb.Y()-PRef.Y()) < myTolV ) - { - if( d <= dmin ) - { - dfMinAngle = dfCurAngle; - kMin = k; - dmin = d; - } - } - } - } - it.Next(); - k++; + gp_Vec2d anEDir(aPEb, aPEe); + dfCurAngle = Abs( anEDir.Angle(anERefDir) ); + } + + if( dfCurAngle <= dfMinAngle ) + { + Standard_Real d = PRef.SquareDistance(aPEb); + if( d <= Precision::PConfusion() ) + d = 0.; + //jgv + Standard_Real aLocalUresol = LocalUresol (myVertex, myFace, PRef, aPEb); + aLocalUresol = Max (aLocalUresol, myTolU); + ///// + if( Abs(aPEb.X()-PRef.X()) < aLocalUresol && Abs(aPEb.Y()-PRef.Y()) < myTolV ) + { + if( d <= dmin ) + { + dfMinAngle = dfCurAngle; + kMin = k; + dmin = d; + } + } + } + } + it.Next(); + k++; }// while it if( kMin == 0 ) { - isDegenerated = Standard_False; - k = 1; - dmin = RealLast(); + isDegenerated = Standard_False; + k = 1; + dmin = RealLast(); } else break; diff --git a/src/ShapeAnalysis/ShapeAnalysis_Wire.cxx b/src/ShapeAnalysis/ShapeAnalysis_Wire.cxx index d7fc1edba2..bb69f20bb4 100644 --- a/src/ShapeAnalysis/ShapeAnalysis_Wire.cxx +++ b/src/ShapeAnalysis/ShapeAnalysis_Wire.cxx @@ -768,11 +768,15 @@ Standard_Boolean ShapeAnalysis_Wire::CheckSmall (const Standard_Integer num, //======================================================================= Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer num, - gp_Pnt2d& p2d1, gp_Pnt2d& p2d2) + gp_Pnt2d& p2d1, gp_Pnt2d& p2d2, + Standard_Real& theTolerance) { myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK); if ( ! IsReady() || NbEdges() < 1 ) return Standard_False; + theTolerance = -1; + Standard_Real aTol1 = -1, aTol2 = -1; + Standard_Integer n2 = (num > 0)? num : NbEdges(); Standard_Integer n1 = (n2 > 1)? n2-1 : NbEdges(); Standard_Integer n3 = (n2 < NbEdges())? n2+1 : 1; @@ -838,11 +842,19 @@ Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer nu Standard_Boolean forward = ( E2.Orientation() == TopAbs_FORWARD ); // FIX FEV 1998 : recompute singularity according precision + //jgv + TopoDS_Vertex BeginVertex, EndVertex; + gp_Pnt p3d1, p3d2; + ///// + if (p1.Distance(p2) <= precFirst) { // edge DGNR dgnr = mySurf->DegeneratedValues ( p1, precVtx, p2d1, p2d2, par1, par2, forward ); //smh#9 if ( dgnr ) { // abv 24 Feb 00: trj3_as1-ac-214.stp #6065: avoid making closed edge degenerated Standard_Real a, b; Handle(Geom_Curve) C3d = BRep_Tool::Curve ( E2, a, b ); + //jgv + theTolerance = BRep_Tool::Tolerance (E2); + ///// if ( ! C3d.IsNull() ) { gp_Pnt p = C3d->Value ( 0.5 * ( a + b ) ); if ( p.SquareDistance ( p1 ) > precVtx * precVtx ) dgnr = Standard_False; @@ -908,6 +920,12 @@ Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer nu Handle(Geom2d_Curve) c2d; if ( sae.PCurve ( E1, myFace, c2d, a, b, Standard_True ) ) { p2d1 = c2d->Value ( b ); + //jgv + p3d1 = mySurf->Value (p2d1); + BeginVertex = sae.LastVertex(E1); + aTol1 = BRep_Tool::Tolerance (BeginVertex); + ///// + //#84 rln gp_Pnt2d p2d = c2d->Value ( b ); //#84 rln par1 = ( p2d.XY() - aP2d.XY() ) * theDir2d.XY(); } @@ -915,6 +933,12 @@ Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer nu //pdn pcurves (fixing regression in f0 in degenerated case) if ( sae.PCurve ( ( dgnr ? E3 : E2 ), myFace, c2d, a, b, Standard_True ) ) { p2d2 = c2d->Value ( a ); + //jgv + p3d2 = mySurf->Value (p2d2); + EndVertex = sae.FirstVertex (dgnr ? E3 : E2); + aTol2 = BRep_Tool::Tolerance (EndVertex); + ///// + //#84 rln gp_Pnt2d p2d = c2d->Value ( a ); //#84 rln par2 = ( p2d.XY() - aP2d.XY() ) * theDir2d.XY(); } @@ -927,6 +951,23 @@ Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer nu theDir2d.Reverse(); } */ + + //jgv + if (theTolerance == -1) + { + theTolerance = Max (aTol1, aTol2); + if (BeginVertex.IsSame(EndVertex)) + { + if (precVtx > theTolerance) + theTolerance = precVtx; + /* + Standard_Real aDist = p3d1.Distance (p3d2); + if (aDist > theTolerance) + theTolerance = aDist; + */ + } + } + ///// //#84 rln 18.03.99 if pcurve is not degenerate anymore, the fix is postponned //to ShapeFix_Wire::FixLacking @@ -959,7 +1000,8 @@ Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer nu Standard_Boolean ShapeAnalysis_Wire::CheckDegenerated (const Standard_Integer num) { gp_Pnt2d p2d1, p2d2; - return CheckDegenerated ( num, p2d1, p2d2 ); + Standard_Real aTol; + return CheckDegenerated (num, p2d1, p2d2, aTol); } //======================================================================= diff --git a/src/ShapeAnalysis/ShapeAnalysis_Wire.hxx b/src/ShapeAnalysis/ShapeAnalysis_Wire.hxx index 3bce04c331..49ff9578b8 100644 --- a/src/ShapeAnalysis/ShapeAnalysis_Wire.hxx +++ b/src/ShapeAnalysis/ShapeAnalysis_Wire.hxx @@ -300,7 +300,9 @@ public: //! no pcurve //! FAIL2: Edge marked as degenerated and has no pcurve //! but singularity is not detected - Standard_EXPORT Standard_Boolean CheckDegenerated (const Standard_Integer num, gp_Pnt2d& dgnr1, gp_Pnt2d& dgnr2); + Standard_EXPORT Standard_Boolean CheckDegenerated (const Standard_Integer num, + gp_Pnt2d& dgnr1, gp_Pnt2d& dgnr2, + Standard_Real& theTolerance); //! Checks for degenerated edge between two adjacent ones. //! Remark : Calls previous function diff --git a/src/ShapeFix/ShapeFix_Wire.cxx b/src/ShapeFix/ShapeFix_Wire.cxx index fcfe71b8e9..d109638964 100644 --- a/src/ShapeFix/ShapeFix_Wire.cxx +++ b/src/ShapeFix/ShapeFix_Wire.cxx @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -1715,7 +1716,8 @@ Standard_Boolean ShapeFix_Wire::FixDegenerated (const Standard_Integer num) // analysis gp_Pnt2d p2d1, p2d2; - myAnalyzer->CheckDegenerated ( num, p2d1, p2d2 ); + Standard_Real aTol; + myAnalyzer->CheckDegenerated (num, p2d1, p2d2, aTol); if ( myAnalyzer->LastCheckStatus ( ShapeExtend_FAIL1 ) ) { myLastFixStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 ); } @@ -1734,12 +1736,39 @@ Standard_Boolean ShapeFix_Wire::FixDegenerated (const Standard_Integer num) gp_Dir2d dir2d ( vect2d ); Handle(Geom2d_Line) line2d = new Geom2d_Line ( p2d1, dir2d ); + //Temporary + TopoDS_Face aFace = Face(); + /////////// + gp_Pnt2d aP2dMid (0.5*(p2d1.XY() + p2d2.XY())); + gp_Pnt aPntMid; + gp_Vec aDU, aDV; + myAnalyzer->Surface()->TrueAdaptor3d()->D1 (aP2dMid.X(), aP2dMid.Y(), aPntMid, aDU, aDV); + Standard_Real aTolMagnitude = Precision::Confusion(); + Standard_Boolean anIsOnSingularity = (aDU.Magnitude() <= aTolMagnitude || + aDV.Magnitude() <= aTolMagnitude); + /* + TopoDS_Edge anEdge = WireData()->Edge ((num > 0)? num : NbEdges()); + Standard_Real aTolEdge = BRep_Tool::Tolerance (anEdge); + */ + //Standard_Boolean anIsNearSingularity = + //myAnalyzer->Surface()->IsDegenerated (aPntMid, Precision::Confusion()); + Standard_Real aTolDeg = Max (aTol, Precision::Confusion()); + Standard_Boolean anIsNearSingularity = + myAnalyzer->Surface()->IsDegenerated (aPntMid, aTolDeg); + anIsOnSingularity |= anIsNearSingularity; + TopoDS_Edge degEdge; BRep_Builder B; B.MakeEdge ( degEdge ); - B.Degenerated ( degEdge, Standard_True ); B.UpdateEdge ( degEdge, line2d, Face(), ::Precision::Confusion() ); B.Range ( degEdge, Face(), 0., vect2d.Magnitude() ); + /* + if (anIsOnSingularity) + B.Degenerated (degEdge, Standard_True); + else + BRepLib::BuildCurve3d (degEdge); + */ + B.Degenerated (degEdge, Standard_True); Handle(ShapeExtend_WireData) sbwd = WireData(); Standard_Integer n2 = ( num >0 ? num : sbwd->NbEdges() ); @@ -3058,13 +3087,91 @@ Standard_Boolean ShapeFix_Wire::FixLacking (const Standard_Integer num, // else try to add either degenerated or closed edge if ( ! doAddLong ) { gp_Pnt pV = 0.5 * ( BRep_Tool::Pnt(V1).XYZ() + BRep_Tool::Pnt(V2).XYZ() ); - gp_Pnt pm = myAnalyzer->Surface()->Value ( 0.5 * ( p2d1.XY() + p2d2.XY() ) ); - Standard_Real dist = pV.Distance ( pm ); - if ( dist <= tol ) doAddDegen = Standard_True; - else if ( myTopoMode ) doAddClosed = Standard_True; + //Temporary + TopoDS_Face aFace = Face(); + /////////// + gp_Pnt2d aP2dMid (0.5*(p2d1.XY() + p2d2.XY())); + gp_Pnt aPntMid; + gp_Vec aDU, aDV; + myAnalyzer->Surface()->TrueAdaptor3d()->D1 (aP2dMid.X(), aP2dMid.Y(), aPntMid, aDU, aDV); + Standard_Real aTolMagnitude = Precision::Confusion(); + Standard_Boolean anIsOnSingularity = (aDU.Magnitude() <= aTolMagnitude || + aDV.Magnitude() <= aTolMagnitude); + + //////////////////////////////////// + Standard_Real aCoeff = 0.9; + Standard_Real aUmin = myAnalyzer->Surface()->TrueAdaptor3d()->FirstUParameter(); + Standard_Real aUmax = myAnalyzer->Surface()->TrueAdaptor3d()->LastUParameter(); + Standard_Real aVmin = myAnalyzer->Surface()->TrueAdaptor3d()->FirstVParameter(); + Standard_Real aVmax = myAnalyzer->Surface()->TrueAdaptor3d()->LastVParameter(); + Standard_Real aDeltaU = Abs (p2d1.X() - p2d2.X()); + Standard_Real aDeltaV = Abs (p2d1.Y() - p2d2.Y()); + if (!anIsOnSingularity) + { + if (aDeltaU > aDeltaV) + { + anIsOnSingularity = (aDeltaU / (aUmax - aUmin) > aCoeff); + } + else + { + anIsOnSingularity = (aDeltaV / (aVmax - aVmin) > aCoeff); + } + } + //////////////////////////////////// + + if (!anIsOnSingularity) + { + Standard_Real aTolDeg = Precision::Confusion(); + if (V1.IsSame(V2)) + aTolDeg = BRep_Tool::Tolerance(V1); + + //////////////////////////////////// + gp_Pnt2d aPP1 = p2d1, aPP2 = p2d2; + if (aPP1.X() < aUmin) + aPP1.SetX (aUmin); + if (aPP1.X() > aUmax) + aPP1.SetX (aUmax); + if (aPP1.Y() < aVmin) + aPP1.SetY (aVmin); + if (aPP1.Y() > aVmax) + aPP1.SetY (aVmax); + + if (aPP2.X() < aUmin) + aPP2.SetX (aUmin); + if (aPP2.X() > aUmax) + aPP2.SetX (aUmax); + if (aPP2.Y() < aVmin) + aPP2.SetY (aVmin); + if (aPP2.Y() > aVmax) + aPP2.SetY (aVmax); + + gp_Pnt2d aPPmid((aPP1.XY() + aPP2.XY())/2); + gp_Pnt aP1 = myAnalyzer->Surface()->Value (aPP1); + gp_Pnt aP2 = myAnalyzer->Surface()->Value (aPP2); + gp_Pnt aPmid = myAnalyzer->Surface()->Value (aPPmid); + Standard_Real aDist = Max (aP1.Distance(aP2), Max (aP1.Distance(aPmid), aP2.Distance(aPmid))); + aDist *= 1.001; + if (aDist > aTolDeg) + aTolDeg = aDist; + //////////////////////////////////// + + anIsOnSingularity = myAnalyzer->Surface()->IsDegenerated (aPntMid, aTolDeg); + } + + Standard_Real dist = pV.Distance ( aPntMid ); + //Standard_Boolean anIsDistLessTol = Standard_False; + if (dist <= tol) + { + //anIsDistLessTol = Standard_True; + if (anIsOnSingularity) + doAddDegen = Standard_True; + } + else if (myTopoMode) + doAddClosed = Standard_True; else if ( dist <= MaxTolerance() ) { //:r7 abv 12 Apr 99: t3d_opt.stp #14245 after S4136 - doAddDegen = Standard_True; + if (anIsOnSingularity) + doAddDegen = Standard_True; doIncrease = Standard_True; inctol = dist; }