0026570: Crash on attempt to rotate a shape.
authorvro <vro@opencascade.com>
Wed, 19 Aug 2015 07:25:11 +0000 (10:25 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 8 Dec 2017 13:39:30 +0000 (16:39 +0300)
An extended draw-command trotate (ttranslate, tmirror, ...) by an additional parameter "-copy".
New check of edge range is added in BRepCheck/BRepCheck_Edge.cxx
The same checking is added in ShapeAnalysis_Edge.cxx
Fixing this problem is added in ShapeFix_Wire.cxx
GeomLib::SameRange(...) and BRepTools_TrsfModification::NewCurve2d(...) are modified to avoid exception in TrimmedCurve

13 files changed:
src/BRepCheck/BRepCheck_Edge.cxx
src/BRepTest/BRepTest_BasicCommands.cxx
src/BRepTest/BRepTest_SurfaceCommands.cxx
src/BRepTools/BRepTools_TrsfModification.cxx
src/GeomLib/GeomLib.cxx
src/ShapeAnalysis/ShapeAnalysis_Edge.cxx
src/ShapeAnalysis/ShapeAnalysis_Edge.hxx
src/ShapeFix/ShapeFix_Wire.cxx
tests/bugs/modalg_4/bug697_1
tests/bugs/modalg_4/bug697_5
tests/bugs/modalg_4/bug919
tests/bugs/modalg_7/bug24251
tests/bugs/modalg_7/bug26570 [new file with mode: 0644]

index e0261a0..b65d247 100644 (file)
@@ -42,6 +42,7 @@
 #include <Geom_RectangularTrimmedSurface.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_TrimmedCurve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <GeomAdaptor_HCurve.hxx>
 #include <GeomAdaptor_HSurface.hxx>
@@ -171,6 +172,7 @@ void BRepCheck_Edge::Minimum()
 
     if (!myCref.IsNull()) {
       Handle(BRep_GCurve) GCref (Handle(BRep_GCurve)::DownCast (myCref));
+      Standard_Real eps = Precision::PConfusion();
       Standard_Real First,Last;
       GCref->Range(First,Last);
       if (Last<=First) {
@@ -186,20 +188,82 @@ void BRepCheck_Edge::Minimum()
           Handle(Geom_Curve) C3d = Handle(Geom_Curve)::DownCast
             (myCref->Curve3D()->Transformed
             (/*myCref->Location()*/L.Transformation()));
-          GeomAdaptor_Curve GAC3d(C3d, C3d->TransformedParameter(First, L.Transformation()),
+          Standard_Boolean IsPeriodic = C3d->IsPeriodic();
+          Standard_Real aPeriod = RealLast();
+          if(IsPeriodic)
+          {
+            aPeriod = C3d->Period();
+          }
+          Standard_Real f = C3d->FirstParameter(), l = C3d->LastParameter();
+          if (C3d->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+          {
+            const Handle(Geom_Curve)& aC = Handle(Geom_TrimmedCurve)::DownCast (C3d)->BasisCurve(); 
+            f = aC->FirstParameter();
+            l = aC->LastParameter();
+            IsPeriodic = aC->IsPeriodic();
+            if(IsPeriodic)
+            {
+              aPeriod = aC->Period();
+            }
+          }
+          if(IsPeriodic && (Last - First > aPeriod + eps))
+          {
+            myCref.Nullify();
+            BRepCheck::Add(lst,BRepCheck_InvalidRange);
+          }
+          else if(!IsPeriodic && (First < f - eps || Last > l + eps))
+          {
+            myCref.Nullify();
+            BRepCheck::Add(lst,BRepCheck_InvalidRange);
+          }
+          else
+          {
+            GeomAdaptor_Curve GAC3d(C3d, C3d->TransformedParameter(First, L.Transformation()),
                                        C3d->TransformedParameter(Last, L.Transformation()));
-          myHCurve = new GeomAdaptor_HCurve(GAC3d);
+            myHCurve = new GeomAdaptor_HCurve(GAC3d);
+          }
         }
         else { // curve on surface
           Handle(Geom_Surface) Sref = myCref->Surface();
           Sref = Handle(Geom_Surface)::DownCast
             (Sref->Transformed(myCref->Location().Transformation()));
           const Handle(Geom2d_Curve)& PCref = myCref->PCurve();
-          Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
-          Handle(Geom2dAdaptor_HCurve) GHPCref = 
-            new Geom2dAdaptor_HCurve(PCref,First,Last);
-          Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
-          myHCurve = new Adaptor3d_HCurveOnSurface(ACSref);
+          Standard_Boolean IsPeriodic = PCref->IsPeriodic();
+          Standard_Real aPeriod = RealLast();
+          if(IsPeriodic)
+          {
+            aPeriod = PCref->Period();
+          }
+          Standard_Real f = PCref->FirstParameter(), l = PCref->LastParameter();
+          if (PCref->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+          {
+            const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (PCref)->BasisCurve(); 
+            f = aC->FirstParameter();
+            l = aC->LastParameter();
+            IsPeriodic = aC->IsPeriodic();
+            if(IsPeriodic)
+            {
+              aPeriod = aC->Period();
+            }
+          }
+          if(IsPeriodic && (Last - First > aPeriod + eps))
+          {
+            myCref.Nullify();
+            BRepCheck::Add(lst,BRepCheck_InvalidRange);
+          }
+          else if(!IsPeriodic && (First < f - eps || Last > l + eps))
+          {
+            myCref.Nullify();
+            BRepCheck::Add(lst,BRepCheck_InvalidRange);
+          }
+          else
+          {
+            Handle(GeomAdaptor_HSurface) GAHSref = new GeomAdaptor_HSurface(Sref);
+            Handle(Geom2dAdaptor_HCurve) GHPCref = 
+              new Geom2dAdaptor_HCurve(PCref,First,Last);
+            Adaptor3d_CurveOnSurface ACSref(GHPCref,GAHSref);
+            myHCurve = new Adaptor3d_HCurveOnSurface(ACSref);
+          }
         }
       }
     }
@@ -276,6 +340,7 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S)
       Standard_Boolean pcurvefound = Standard_False;
 
       BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
+      Standard_Real eps = Precision::PConfusion();
       while (itcr.More()) {
         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
         if (cr != myCref && cr->IsCurveOnSurface(Su,L)) {
@@ -291,12 +356,43 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S)
           }
           // gka OCC
           //  Modified by skv - Tue Apr 27 11:50:35 2004 Begin
-          if (Abs(ff-First) > Precision::PConfusion() ||
-              Abs(ll-Last)  > Precision::PConfusion()) {
+          if (Abs(ff-First) > eps ||
+              Abs(ll-Last)  > eps) {
               BRepCheck::Add(lst,BRepCheck_InvalidSameRangeFlag);
               BRepCheck::Add(lst,BRepCheck_InvalidSameParameterFlag);
           }
           //  Modified by skv - Tue Apr 27 11:50:37 2004 End
+          //
+          const Handle(Geom2d_Curve)& pc = cr->PCurve();
+          Standard_Boolean IsPeriodic = pc->IsPeriodic();
+          Standard_Real aPeriod = RealLast();
+          if(IsPeriodic)
+          {
+            aPeriod = pc->Period();
+          }
+          Standard_Real fp = pc->FirstParameter(), lp = pc->LastParameter();
+          if (pc->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+          {
+            const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (pc)->BasisCurve(); 
+            fp = aC->FirstParameter();
+            lp = aC->LastParameter();
+            IsPeriodic = aC->IsPeriodic();
+            if(IsPeriodic)
+            {
+              aPeriod = aC->Period();
+            }
+          }
+          if(IsPeriodic && (l - f > aPeriod + eps))
+          {
+            BRepCheck::Add(lst,BRepCheck_InvalidRange);
+            return;
+          }
+          else if(!IsPeriodic && (f < fp - eps || l > lp + eps))
+          {
+            BRepCheck::Add(lst,BRepCheck_InvalidRange);
+            return;
+          }
+
           if (myGctrl) {
             Handle(Geom_Surface) Sb = cr->Surface();
             Sb = Handle(Geom_Surface)::DownCast
index 19e93bb..87417ef 100644 (file)
@@ -115,6 +115,13 @@ static Standard_Integer transform(Draw_Interpretor& ,Standard_Integer n,const ch
   const char* aName = a[0];
 
   Standard_Boolean isBasic = Standard_False;
+  Standard_Boolean isCopy = Standard_False;
+
+  // Check "copy" flag.
+  if (!strcmp(a[n-1], "-copy")) {
+    isCopy = Standard_True;
+    last = --n;
+  }
 
   if (!strcmp(aName,"reset")) {
   }
@@ -176,7 +183,7 @@ static Standard_Integer transform(Draw_Interpretor& ,Standard_Integer n,const ch
         return 1;
       }
       else {
-        trf.Perform(S);
+        trf.Perform(S, isCopy);
         if (!trf.IsDone())
           return 1;
         DBRep::Set(a[i],trf.Shape());
@@ -1418,27 +1425,27 @@ void  BRepTest::BasicCommands(Draw_Interpretor& theCommands)
                  transform,g);
 
   theCommands.Add("tmove",
-                 "tmove name1 name2 ... name, set location from name",
+                 "tmove name1 name2 ... name, set location from name [-copy]",
                  __FILE__,
                  transform,g);
 
   theCommands.Add("ttranslate",
-                 "ttranslate name1 name2 ... dx dy dz",
+                 "ttranslate name1 name2 ... dx dy dz [-copy]",
                  __FILE__,
                  transform,g);
 
   theCommands.Add("trotate",
-                 "trotate name1 name2 ... x y z dx dy dz angle",
+                 "trotate name1 name2 ... x y z dx dy dz angle [-copy]",
                  __FILE__,
                  transform,g);
 
   theCommands.Add("tmirror",
-                 "tmirror name x y z dx dy dz",
+                 "tmirror name x y z dx dy dz [-copy]",
                  __FILE__,
                  transform,g);
 
   theCommands.Add("tscale",
-                 "tscale name x y z scale",
+                 "tscale name x y z scale [-copy]",
                  __FILE__,
                  transform,g);
 
index 2cfd440..454e3c0 100644 (file)
@@ -261,7 +261,24 @@ static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const cha
       DrawTrSurf_CurveColor(col);
 
       Sprintf(name,"%s_%d",a[1],i);
-      DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
+      Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
+      Standard_Boolean IsPeriodic = c->IsPeriodic();
+      if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+      {
+        const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve(); 
+        IsPeriodic = aC->IsPeriodic();
+        fr = aC->FirstParameter();
+        lr = aC->LastParameter();
+      }
+      if(!IsPeriodic && 
+        ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
+      {
+        DrawTrSurf::Set(name, c);
+      }
+      else
+      {
+        DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
+      }
     }
     DrawTrSurf_CurveColor(savecol);
 
@@ -276,10 +293,27 @@ static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const cha
     Standard_Real f,l;
     const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
       (TopoDS::Edge(SE),TopoDS::Face(SF),f,l);
+    Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
+    Standard_Boolean IsPeriodic = c->IsPeriodic();
+    if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+    {
+      const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve(); 
+      IsPeriodic = aC->IsPeriodic();
+      fr = aC->FirstParameter();
+      lr = aC->LastParameter();
+    }
 
     col = DBRep_ColorOrientation(SE.Orientation());
     DrawTrSurf_CurveColor(col);
-    DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
+    if(!IsPeriodic && 
+      ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
+    {
+      DrawTrSurf::Set(a[1], c);
+    }
+    else
+    {
+      DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
+    }
     DrawTrSurf_CurveColor(savecol);
   }
   else { 
index 698aa71..6bc9249 100644 (file)
@@ -180,6 +180,17 @@ Standard_Boolean BRepTools_TrsfModification::NewCurve2d
   if(!NewC->IsPeriodic()) {
     if(fc - f > Precision::PConfusion()) f = fc;
     if(l - lc > Precision::PConfusion()) l = lc;
+    if(Abs(l - f) < Precision::PConfusion())
+    {
+      if(Abs(f - fc) < Precision::PConfusion())
+      {
+        l = lc;
+      }
+      else
+      {
+        f = fc;
+      }
+    }
   }
 
   newf = f;
index da9ae9a..4d004fa 100644 (file)
@@ -971,14 +971,27 @@ void GeomLib::SameRange(const Standard_Real         Tolerance,
 
     if(aCCheck->IsPeriodic())
     {
-      TC = new Geom2d_TrimmedCurve( CurvePtr, FirstOnCurve, LastOnCurve );
+      if(Abs(LastOnCurve - FirstOnCurve) > Precision::PConfusion())
+      {
+        TC = new Geom2d_TrimmedCurve( CurvePtr, FirstOnCurve, LastOnCurve );
+      }
+      else
+      {
+        TC = new Geom2d_TrimmedCurve( CurvePtr, CurvePtr->FirstParameter(), CurvePtr->LastParameter() );
+      }
     }
     else
     {
       const Standard_Real Udeb = Max(CurvePtr->FirstParameter(), FirstOnCurve);
       const Standard_Real Ufin = Min(CurvePtr->LastParameter(), LastOnCurve);
-
-      TC = new Geom2d_TrimmedCurve( CurvePtr, Udeb, Ufin );
+      if(Abs(Ufin - Udeb) > Precision::PConfusion())
+      {
+        TC = new Geom2d_TrimmedCurve( CurvePtr, Udeb, Ufin );
+      }
+      else
+      {
+        TC = new Geom2d_TrimmedCurve( CurvePtr, CurvePtr->FirstParameter(), CurvePtr->LastParameter());
+      }
     }
 
     //
index 333a3c8..f1bc782 100644 (file)
@@ -32,6 +32,7 @@
 #include <Geom2d_Curve.hxx>
 #include <Geom2dAdaptor_HCurve.hxx>
 #include <Geom_Curve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
 #include <Geom_Plane.hxx>
 #include <Geom_Surface.hxx>
 #include <GeomAdaptor_Curve.hxx>
@@ -1028,3 +1029,44 @@ Standard_Boolean ShapeAnalysis_Edge::CheckOverlapping(const TopoDS_Edge& theEdge
   theTolOverlap = aresTol;
    return isOverlap;
 }
+
+//=======================================================================
+//function : CheckPCurveRange
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean ShapeAnalysis_Edge::CheckPCurveRange (const Standard_Real theFirst, 
+                                                       const Standard_Real theLast,
+                                                       const Handle(Geom2d_Curve)& thePC)
+{
+  const Standard_Real eps = Precision::PConfusion();
+  Standard_Boolean isValid = Standard_True; 
+  Standard_Boolean IsPeriodic = thePC->IsPeriodic();
+  Standard_Real aPeriod = RealLast();
+  if(IsPeriodic)
+  {
+    aPeriod = thePC->Period();
+  }
+  Standard_Real fp = thePC->FirstParameter(), lp = thePC->LastParameter();
+  if (thePC->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+  {
+    const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (thePC)->BasisCurve(); 
+    fp = aC->FirstParameter();
+    lp = aC->LastParameter();
+    IsPeriodic = aC->IsPeriodic();
+    if(IsPeriodic)
+    {
+      aPeriod = aC->Period();
+    }
+  }
+  if(IsPeriodic && (theLast - theFirst > aPeriod + eps))
+  {
+    isValid = Standard_False;
+  }
+  else if(!IsPeriodic && (theFirst < fp - eps || theLast > lp + eps))
+  {
+    isValid = Standard_False;
+  }
+
+  return isValid;
+}
index e7e42f4..d39aca0 100644 (file)
@@ -170,7 +170,12 @@ public:
   //! If deviation is greater than tolerance of the edge (i.e.
   //! incorrect flag) returns False, else returns True.
   Standard_EXPORT Standard_Boolean CheckSameParameter (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace, Standard_Real& theMaxdev, const Standard_Integer theNbControl = 23);
-  
+
+  //! Checks possibility for pcurve thePC to have range [theFirst, theLast] (edge range)
+  //! having respect to real first, last parameters of thePC 
+  Standard_EXPORT Standard_Boolean CheckPCurveRange (const Standard_Real theFirst, const Standard_Real theLast,
+                                                     const Handle(Geom2d_Curve)& thePC);
+
   //! Computes the maximal deviation between the two curve
   //! representations.
   //! dev is an input/output parameter and contains the computed
index 59334cb..e5b273d 100644 (file)
@@ -794,12 +794,26 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
       if(sae.HasPCurve(sbwd->Edge(i),face)) {
         Handle(Geom2d_Curve) C2d;
         Standard_Real fp2d,lp2d;
-        if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d)) {
+        if(sae.PCurve(sbwd->Edge(i),face,C2d,fp2d,lp2d, Standard_False)) {
           if( fabs(First-fp2d)>Precision::PConfusion() ||
-              fabs(Last-lp2d)>Precision::PConfusion() ) {
+              fabs(Last-lp2d)>Precision::PConfusion()    ) 
+          {
             BRep_Builder B;
             B.SameRange(sbwd->Edge(i),Standard_False);
           }
+          else if(!sae.CheckPCurveRange(First, Last, C2d))
+          {
+            //Replace pcurve
+            TopLoc_Location L;
+            const Handle(Geom_Surface)& S = BRep_Tool::Surface(face, L);
+            ShapeBuild_Edge().RemovePCurve (sbwd->Edge(i),  S, L);
+            myFixEdge->FixAddPCurve ( sbwd->Edge(i), face, sbwd->IsSeam(i), 
+                        myAnalyzer->Surface(), Precision() );
+            if ( myFixEdge->Status ( ShapeExtend_DONE ) ) 
+              myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
+            if ( myFixEdge->Status ( ShapeExtend_FAIL ) ) 
+              myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL3 );
+          }
         }
       }
       myFixEdge->FixSameParameter ( sbwd->Edge(i), Face());
index 8e1dd06..54e4fe3 100755 (executable)
@@ -1,3 +1,4 @@
+puts "TODO OCC29351 ALL: Faulty shapes in variables faulty_1 to faulty_2 "
 puts "============"
 puts "OCC697"
 puts "============"
index 49c6f55..6148207 100755 (executable)
@@ -1,3 +1,4 @@
+puts "TODO OCC29351 ALL: Faulty shapes in variables faulty_1 to faulty_2 " 
 puts "============"
 puts "OCC697"
 puts "============"
index 973f8b8..62bba7c 100755 (executable)
@@ -15,7 +15,7 @@ explode a
 # See comment in CR23244:
 restore [locate_data_file OCC919-PROC.brep] a_1 
 #
-
+fixshape a_1 a_1
 checkshape a_1
 checkshape a_2
 
index d679cdf..2ace69d 100644 (file)
@@ -1,6 +1,6 @@
 puts "REQUIRED All: Faulty shapes in variables faulty_1 to faulty_"
 
-puts "TODO OCC24251 ALL: ERROR: OCC24251 is reproduced."
+#puts "TODO OCC24251 ALL: ERROR: OCC24251 is reproduced."
 
 puts "========"
 puts "OCC24251"
diff --git a/tests/bugs/modalg_7/bug26570 b/tests/bugs/modalg_7/bug26570
new file mode 100644 (file)
index 0000000..7b142cb
--- /dev/null
@@ -0,0 +1,15 @@
+puts "========"
+puts "OCC26570"
+puts "========"
+puts ""
+#####################################
+# Crash on attempt to rotate a shape
+#####################################
+
+restore [locate_data_file bug26570.brep] s
+
+fixshape result s
+trotate result 0 0 0 500 0 0 180 -copy
+checkshape result
+
+