0030433: Checkshape: bad solid, created by revolution, is reported as valid.
authorifv <ifv@opencascade.com>
Fri, 15 Mar 2019 13:59:08 +0000 (16:59 +0300)
committerbugmaster <bugmaster@opencascade.com>
Mon, 6 May 2019 12:57:56 +0000 (15:57 +0300)
BRepPrimAPI_MakeRevol.cxx, hxx
Insert checking of self-intersecting of generated surfaces in MakeRevol

BRepTest_SweepCommands.cxx
Adjusting command revol to current behavior of MakeRevol algorithm.

src/BRepPrimAPI/BRepPrimAPI_MakeRevol.cxx
src/BRepPrimAPI/BRepPrimAPI_MakeRevol.hxx
src/BRepTest/BRepTest_SweepCommands.cxx
tests/bugs/modalg_5/bug23954
tests/bugs/modalg_7/bug30433 [new file with mode: 0644]

index 69b34f8..96aa5ff 100644 (file)
 #include <TopoDS_Shape.hxx>
 #include <TopTools_DataMapOfShapeListOfShape.hxx>
 #include <BRepTools_ReShape.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAdaptor_SurfaceOfRevolution.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <Extrema_POnCurv.hxx>
+#include <Geom_Line.hxx>
+
 // perform checks on the argument
 static const TopoDS_Shape& check(const TopoDS_Shape& S)
 {
@@ -41,10 +48,20 @@ static const TopoDS_Shape& check(const TopoDS_Shape& S)
 BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, 
                                     const gp_Ax1& A, 
                                     const Standard_Real D, 
-                                    const Standard_Boolean Copy) :
-       myRevol(check(S),A,D,Copy)
+             const Standard_Boolean Copy) : 
+             myRevol(check(S), A, D, Copy),
+             myIsBuild(Standard_False)
+
 {
-  Build();
+  if (!CheckValidity(check(S), A))
+  {
+    myShape.Nullify();
+    myIsBuild = Standard_True;
+  }
+  else
+  {
+    Build();
+  }
 }
 
 
@@ -55,10 +72,21 @@ BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S,
 
 BRepPrimAPI_MakeRevol::BRepPrimAPI_MakeRevol(const TopoDS_Shape& S, 
                                     const gp_Ax1& A, 
-                                    const Standard_Boolean Copy) :
-       myRevol(check(S),A,Copy)
+             const Standard_Boolean Copy) :
+             
+             myRevol(check(S), A, 2. * M_PI, Copy),
+              myIsBuild(Standard_False)
 {
-  Build();
+
+  if (!CheckValidity(check(S), A))
+  {
+    myShape.Nullify();
+    myIsBuild = Standard_True;
+  }
+  else
+  {
+    Build();
+  }
 }
 
 
@@ -80,10 +108,16 @@ const BRepSweep_Revol&  BRepPrimAPI_MakeRevol::Revol() const
 
 void  BRepPrimAPI_MakeRevol::Build()
 {
+  if (myIsBuild)
+  {
+    return;
+  }
   myShape = myRevol.Shape();
   BRepLib::UpdateInnerTolerances(myShape);
   
   Done();
+  myIsBuild = Standard_True;
+
   myHist.Nullify();
   myDegenerated.Clear();
   TopTools_DataMapOfShapeListOfShape aDegE;
@@ -210,6 +244,98 @@ void  BRepPrimAPI_MakeRevol::Build()
     }
   }
 }
+//=======================================================================
+//function : IsIntersect
+//purpose  : used in CheckValidity to find out is there
+//           intersection between curve and axe of revolution
+//=======================================================================
+static Standard_Boolean IsIntersect(const Handle(Adaptor3d_HCurve)& theC, 
+                                    const gp_Ax1& theAxe)
+{
+  const Handle(Geom_Line) aL = new Geom_Line(theAxe);
+  const GeomAdaptor_Curve aLin(aL);
+  const Standard_Real aParTol = theC->Resolution(Precision::Confusion());
+  const Standard_Real aParF = theC->FirstParameter() + aParTol,
+                      aParL = theC->LastParameter() - aParTol;
+
+  Extrema_ExtCC anExtr(theC->Curve(), aLin);
+  anExtr.Perform();
+  if (anExtr.IsDone() && anExtr.NbExt() > 0)
+  {
+    Extrema_POnCurv aP1, aP2;
+    for (Standard_Integer i = 1; i <= anExtr.NbExt(); i++)
+    {
+      if (anExtr.SquareDistance(i) > Precision::SquareConfusion())
+      {
+        continue;
+      }
+      anExtr.Points(i, aP1, aP2);
+      if ((aParF < aP1.Parameter()) && (aP1.Parameter() < aParL))
+      {
+        return Standard_True;
+      }
+    }
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : CheckValidity
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean BRepPrimAPI_MakeRevol::CheckValidity(const TopoDS_Shape& theShape,
+                                                      const gp_Ax1& theA)
+{
+  TopExp_Explorer anExp(theShape, TopAbs_EDGE);
+  Standard_Boolean IsValid = Standard_True;
+  for (; anExp.More(); anExp.Next())
+  {
+    const TopoDS_Edge& anE = TopoDS::Edge(anExp.Current());
+
+    if (BRep_Tool::Degenerated(anE))
+    {
+      continue;
+    }
+
+    TopLoc_Location L;
+    Standard_Real First, Last;
+    Handle(Geom_Curve) C = BRep_Tool::Curve(anE, L, First, Last);
+    gp_Trsf Tr = L.Transformation();
+    C = Handle(Geom_Curve)::DownCast(C->Copy());
+    C = new Geom_TrimmedCurve(C, First, Last);
+    C->Transform(Tr);
+
+    Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve();
+    HC->ChangeCurve().Load(C, First, Last);
+    //Checking coinsidence axe of revolution and basis curve
+    //This code is taken directly from GeomAdaptor_SurfaceOfRevolution
+    Standard_Integer Ratio = 1;
+    Standard_Real Dist;
+    gp_Pnt PP;
+    do {
+      PP = HC->Value(First + (Last - First) / Ratio);
+      Dist = gp_Lin(theA).Distance(PP);
+      Ratio++;
+    } while (Dist < Precision::Confusion() && Ratio < 100);
+    //
+    if (Ratio >= 100) // edge coinsides with axes
+    {
+      IsValid = Standard_True; //Such edges are allowed by revol algo and treated
+                               //by special way, so they must be concidered as valid
+    }
+    else
+    {
+      IsValid = !IsIntersect(HC, theA);
+    }
+    if (!IsValid)
+    {
+      break;
+    }
+  }
+  //
+  return IsValid;
+}
 
 
 //=======================================================================
@@ -351,4 +477,3 @@ const TopTools_ListOfShape& BRepPrimAPI_MakeRevol::Degenerated () const
 {
   return myDegenerated;
 }
-
index 2068410..a24adba 100644 (file)
@@ -68,7 +68,6 @@ class BRepPrimAPI_MakeRevol  : public BRepPrimAPI_MakeSweep
 public:
 
   DEFINE_STANDARD_ALLOC
-
   
   //! Builds the Revol of base S, axis  A and angle  D. If C
   //! is true, S is copied.
@@ -110,15 +109,15 @@ public:
   
   //! Check if there are degenerated edges in the result.
   Standard_EXPORT Standard_Boolean HasDegenerated() const;
-  
-  Standard_EXPORT const TopTools_ListOfShape& Degenerated() const;
 
+  //! Returns the list of degenerated edges
+  Standard_EXPORT const TopTools_ListOfShape& Degenerated() const;
 
 protected:
 
-
-
-
+  //! Checks possibilities of producing self-intersection surface
+  //! returns true if all surfaces are valid
+  Standard_EXPORT Standard_Boolean CheckValidity(const TopoDS_Shape& theShape, const gp_Ax1& theA);
 
 private:
 
@@ -127,6 +126,7 @@ private:
   BRepSweep_Revol myRevol;
   TopTools_ListOfShape myDegenerated;
   Handle(BRepTools_History) myHist;
+  Standard_Boolean myIsBuild;
 
 
 };
index 25c33e2..3ed5f73 100644 (file)
@@ -114,7 +114,7 @@ static Standard_Integer prism(Draw_Interpretor&, Standard_Integer n, const char*
 //=======================================================================
 // revol
 //=======================================================================
-static Standard_Integer revol(Draw_Interpretor&,
+static Standard_Integer revol(Draw_Interpretor& di,
   Standard_Integer n, const char** a)
 {
   if (n < 10) return 1;
@@ -133,14 +133,21 @@ static Standard_Integer revol(Draw_Interpretor&,
 
   BRepPrimAPI_MakeRevol Revol(base, A, angle, copy);
 
-  TopoDS_Shape res = Revol.Shape();
+  if (Revol.IsDone())
+  {
+    TopoDS_Shape res = Revol.Shape();
 
-  DBRep::Set(a[1], res);
+    DBRep::Set(a[1], res);
 
-  //History 
-  TopTools_ListOfShape anArgs;
-  anArgs.Append(base);
-  BRepTest_Objects::SetHistory(anArgs, Revol);
+    //History 
+    TopTools_ListOfShape anArgs;
+    anArgs.Append(base);
+    BRepTest_Objects::SetHistory(anArgs, Revol);
+  }
+  else
+  {
+    di << "Revol not done \n";
+  }
 
   return 0;
 }
index 80ba5a7..58555b2 100644 (file)
@@ -8,12 +8,11 @@ puts ""
 # BRepPrimAPI_MakeRevol fails to recognize a torus case
 ##########################################################
 
-circle c_1 0 100 0 1 0 0 0 1 0 100
-circle c_2 0 100 0 1 0 0 0 0 1 100
-circle c_3 0 100 0 1 0 0 0 -1 0 100
-circle c_4 0 100 0 1 0 0 0 0 1 10
-circle c_5 0 100 0 1 0 0 0 0 1 120
-for { set i 1 } { $i <= 5 } { incr i } {
+circle c_1 0 100.00001 0 1 0 0 0 1 0 100
+circle c_2 0 100.00001 0 1 0 0 0 0 1 100
+circle c_3 0 100.00001 0 1 0 0 0 -1 0 100
+circle c_4 0 100.00001 0 1 0 0 0 0 1 10
+for { set i 1 } { $i <= 4 } { incr i } {
   mkedge e c_$i
   revol r e 0 0 0 0 0 1 90
   mksurface s_$i r
diff --git a/tests/bugs/modalg_7/bug30433 b/tests/bugs/modalg_7/bug30433
new file mode 100644 (file)
index 0000000..b20782e
--- /dev/null
@@ -0,0 +1,19 @@
+puts "========"
+puts "0030433: Checkshape: bad solid, created by revolution, is reported as valid."
+puts "========"
+puts ""
+
+ellipse e1 0 0 0 200 100
+mkedge ell1 e1
+wire w1 ell1
+plane p1
+mkface fe1 p1 w1
+revol rev1 fe1 0 0 0 1 0 0 180 1
+
+
+
+if { [isdraw rev1] != 1 } {
+  puts "OK: wrong shape is not created"
+} else {
+  puts "Error: algorithm created wrong shape"
+}