]> OCCT Git - occt.git/commitdiff
0032833: Shape Healing - FixShape needs to be improved
authorjgv <jgv@opencascade.com>
Tue, 15 Mar 2022 11:34:17 +0000 (14:34 +0300)
committerjgv <julia.gerasimova@opencascade.com>
Mon, 16 May 2022 13:12:04 +0000 (16:12 +0300)
First version

src/BRepCheck/BRepCheck_Wire.cxx
src/BRepTools/BRepTools_WireExplorer.cxx
src/ShapeAnalysis/ShapeAnalysis_Wire.cxx
src/ShapeAnalysis/ShapeAnalysis_Wire.hxx
src/ShapeFix/ShapeFix_Wire.cxx

index 10e40a816597a76aabdf5c78e170123e643face6..c65357e1a9c7f38755033eb41137d299643374b4 100644 (file)
@@ -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);
index 0cd69bc4864b14fee3f8b634dba794d769d3cd99..52aec1d2371f5bc32581386251a9fd402b04538b 100644 (file)
@@ -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;
index d7fc1edba239f4198cd948386197709247b6eaa7..bb69f20bb4a8bc9dced114345dd77f8ae0145fec 100644 (file)
@@ -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);
 }
 
 //=======================================================================
index 3bce04c331b4f129593bf4c8e5290104532dd1a9..49ff9578b8cf6cb6bb8ea4eadc1f16d8c3449d94 100644 (file)
@@ -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
index fcfe71b8e973994b4cc3b3cd75f9052081edb86c..d1096389647a6a199f23fca87b574bc36e8545c6 100644 (file)
@@ -57,6 +57,7 @@
 #include <BRepBuilderAPI_MakeEdge.hxx>
 #include <BRepBuilderAPI_MakeVertex.hxx>
 #include <BRepTools.hxx>
+#include <BRepLib.hxx>
 #include <Geom2d_BSplineCurve.hxx>
 #include <Geom2d_Curve.hxx>
 #include <Geom2d_Line.hxx>
@@ -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; 
       }