]> OCCT Git - occt-copy.git/commitdiff
Analyzer for surface normals is added
authorifv <ifv@opencascade.com>
Thu, 23 Oct 2014 12:13:26 +0000 (16:13 +0400)
committergka <gka@opencascade.com>
Fri, 24 Oct 2014 08:12:27 +0000 (12:12 +0400)
src/BRepCheck/BRepCheck_SurfNormAnalyzer.cxx [new file with mode: 0644]
src/BRepCheck/BRepCheck_SurfNormAnalyzer.hxx [new file with mode: 0644]
src/BRepCheck/FILES [new file with mode: 0644]
src/BRepTest/BRepTest_CheckCommands.cxx

diff --git a/src/BRepCheck/BRepCheck_SurfNormAnalyzer.cxx b/src/BRepCheck/BRepCheck_SurfNormAnalyzer.cxx
new file mode 100644 (file)
index 0000000..3fcbd50
--- /dev/null
@@ -0,0 +1,342 @@
+
+
+#include <BRepCheck_SurfNormAnalyzer.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepTools.hxx>
+
+#include <Geom_Surface.hxx>
+#include <GeomAdaptor_Surface.hxx>
+#include <GeomAdaptor_HSurface.hxx>
+#include <Adaptor3d_TopolTool.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array2OfReal.hxx>
+#include <gp_VectorWithNullMagnitude.hxx>
+
+static Standard_Real AdjustExtr(const Adaptor3d_Surface& S,
+                                const Standard_Real UMin,
+                                const Standard_Real UMax,
+                                const Standard_Real VMin,
+                                const Standard_Real VMax,
+                                const Standard_Real Extr0,
+                                const Standard_Real Tol,
+                                      Standard_Real& uextr,
+                                      Standard_Real& vextr );
+
+
+
+//=======================================================================
+//function : BRepCheck_Analyzer
+//purpose  : 
+//=======================================================================
+
+BRepCheck_SurfNormAnalyzer::BRepCheck_SurfNormAnalyzer ():
+myAngTol(0.01)
+{
+  
+}
+
+
+//=======================================================================
+//function : BRepCheck_Analyzer
+//purpose  : 
+//=======================================================================
+
+BRepCheck_SurfNormAnalyzer::BRepCheck_SurfNormAnalyzer 
+                                        (const TopoDS_Shape& theS,
+                                                                      const Standard_Real theAngTol):
+myShape(theS), myAngTol(theAngTol)
+{
+  
+}
+
+
+
+//=======================================================================
+//function : IsValid
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean BRepCheck_SurfNormAnalyzer::IsValid() 
+{
+  TopLoc_Location anL;
+  myBadFaces.Clear();
+  Standard_Real umin, umax, vmin, vmax;
+  TopExp_Explorer anEx(myShape, TopAbs_FACE);
+  for(; anEx.More(); anEx.Next())
+  {
+    TopoDS_Face aF = TopoDS::Face(anEx.Current());
+    BRepTools::UVBounds(aF, umin, umax, vmin, vmax);
+    const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aF, anL);
+    if(IsProblemSurf(aSurf, umin, umax, vmin, vmax, myAngTol))
+    {
+      myBadFaces.Append(aF);
+    }
+  }  
+  
+
+  return myBadFaces.IsEmpty();
+}
+//=======================================================================
+//function : BadFaces
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape& BRepCheck_SurfNormAnalyzer::BadFaces() const
+{
+  return myBadFaces;
+}
+//=======================================================================
+//function : SetShape
+//purpose  : 
+//=======================================================================
+
+void BRepCheck_SurfNormAnalyzer::SetShape(const TopoDS_Shape& theShape) 
+{
+  myBadFaces.Clear();
+  myShape = theShape;
+}
+//=======================================================================
+//function : SetTolerance
+//purpose  : 
+//=======================================================================
+
+void BRepCheck_SurfNormAnalyzer::SetTolerance(const Standard_Real theAngTol) 
+{
+  myBadFaces.Clear();
+  myAngTol = theAngTol;
+}
+//=======================================================================
+//function : GetShape
+//purpose  : 
+//=======================================================================
+
+const TopoDS_Shape& BRepCheck_SurfNormAnalyzer::GetShape() const 
+{
+  return myShape;
+}
+//=======================================================================
+//function : GetTolerance
+//purpose  : 
+//=======================================================================
+
+Standard_Real BRepCheck_SurfNormAnalyzer::GetTolerance() const 
+{
+  return myAngTol;
+}
+//=======================================================================
+//function : IsProblemSurf
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean 
+BRepCheck_SurfNormAnalyzer::IsProblemSurf(const Handle_Geom_Surface& theSurf, 
+                                          const Standard_Real theUMin,
+                                          const Standard_Real theUMax,
+                                          const Standard_Real theVMin,
+                                          const Standard_Real theVMax,                                                       
+                                          const Standard_Real theAngTol)
+{
+  Standard_Boolean aStatus = Standard_False;
+  GeomAdaptor_Surface aGAS(theSurf, theUMin, theUMax, theVMin, theVMax);
+  GeomAbs_SurfaceType aSType = aGAS.GetType();
+  //
+  if(aSType <= GeomAbs_Torus)
+  {
+    return aStatus;
+  }
+  //
+  Handle(GeomAdaptor_HSurface) aGAHS = new GeomAdaptor_HSurface(aGAS);
+  Handle(Adaptor3d_TopolTool) aTT = new Adaptor3d_TopolTool(aGAHS);
+  if(aTT->DomainIsInfinite())
+  {
+    return aStatus;
+  }
+  //
+  Standard_Real aDefl = 0.1; //the same as for intersection default
+  Standard_Integer aNbMinU = 10, aNbMinV = 10;
+  aTT->SamplePnts(aDefl, aNbMinU, aNbMinV);
+  Standard_Integer aNbU = aTT->NbSamplesU();
+  Standard_Integer aNbV = aTT->NbSamplesV();
+  TColStd_Array1OfReal anUPars(1, aNbU), aVPars(1, aNbV);
+  aTT->UParameters(anUPars);
+  aTT->VParameters(aVPars);
+  //
+  gp_Pnt aP;
+  gp_Vec aDU, aDV;
+  Standard_Real u, v, ang;
+  TColStd_Array2OfReal aTabN(1, aNbU, 1, aNbV);
+  Standard_Integer i, j;
+  //Check singular point on boundary
+  for(j = 1; j <= aNbV; j += aNbV-1)
+  {
+    aP = theSurf->Value(anUPars(1), aVPars(j));
+    Standard_Real length = 0.;
+    for(i = 2; i <= aNbU; ++i)
+    {
+      gp_Pnt aPcur = theSurf->Value(anUPars(i), aVPars(j));
+      length += aPcur.Distance(aP);
+      if(length > Precision::Confusion())
+      {
+        break;
+      }
+      aP = aPcur;
+    }
+    if(length <= Precision::Confusion())
+    {
+      if(j == 1)
+      {
+        aVPars(j) += (aVPars(2)-aVPars(1)) / 10.;
+      }
+      else
+      {
+        aVPars(aNbV) -= (aVPars(aNbV)-aVPars(aNbV-1)) / 10.;
+      }
+    }
+  }
+  for(j = 1; j <= aNbU; j += aNbU-1)
+  {
+    aP = theSurf->Value(anUPars(j), aVPars(1));
+    Standard_Real length = 0.;
+    for(i = 2; i <= aNbV; ++i)
+    {
+      gp_Pnt aPcur = theSurf->Value(anUPars(j), aVPars(i));
+      length += aPcur.Distance(aP);
+      if(length > Precision::Confusion())
+      {
+        break;
+      }
+      aP = aPcur;
+    }
+    if(length <= Precision::Confusion())
+    {
+      if(j == 1)
+      {
+        anUPars(j) += (anUPars(2)-anUPars(1)) / 10.;
+      }
+      else
+      {
+        anUPars(aNbU) -= (anUPars(aNbU)-anUPars(aNbU-1)) / 10.;
+      }
+    }
+  }
+  //
+  for(i = 1; i <= aNbU; ++i)
+  {
+    u = anUPars(i);
+    for(j = 1; j <= aNbV; ++j)
+    {
+      v = aVPars(j);
+      theSurf->D1(u, v, aP, aDU, aDV);
+      try
+      {
+        ang = aDU.Angle(aDV);
+        if(ang > M_PI/2.)
+        {
+          ang = M_PI - ang;
+        }
+      }
+      catch (gp_VectorWithNullMagnitude)
+      {
+        ang = 0.;
+      }
+
+      aTabN(i, j) = ang;
+    }
+  }
+  //
+  Standard_Real min = RealLast();
+  Standard_Integer imin = 0, jmin = 0;
+  for(i = 1; i <= aNbU; ++i)
+  {
+    for(j = 1; j <= aNbV; ++j)
+    {
+      if(aTabN(i, j) < theAngTol)
+      {
+        return Standard_True;
+      }
+      else
+      {
+        if(aTabN(i, j) < min)
+        {
+          min = aTabN(i, j);
+          imin = i;
+          jmin = j;
+        }
+      }
+    }
+  }
+  //
+  Standard_Real umin = anUPars(Max(1, imin-1));
+  Standard_Real umax = anUPars(Min(aNbU, imin+1));
+  Standard_Real vmin = aVPars(Max(1, jmin-1));
+  Standard_Real vmax = aVPars(Min(aNbV, jmin+1));
+  //
+  Standard_Real min0 = min, uextr = anUPars(imin), vextr = aVPars(jmin);
+  min = AdjustExtr(aGAS, umin, umax, vmin, vmax,
+                      min0,  theAngTol / 10., uextr, vextr  );
+
+  if(min < theAngTol)
+  {
+    aStatus = Standard_True;
+  }
+  return aStatus;
+}
+Standard_Real AdjustExtr(const Adaptor3d_Surface& S,
+                         const Standard_Real UMin,
+                         const Standard_Real UMax,
+                         const Standard_Real VMin,
+                         const Standard_Real VMax,
+                         const Standard_Real Extr0,
+                         const Standard_Real Tol,
+                         Standard_Real& uextr,
+                         Standard_Real& vextr )
+{
+  Standard_Integer Nu = 5, Nv = 5;
+  gp_Pnt P;
+  gp_Vec DU, DV;
+  Standard_Integer i, j;
+  Standard_Real du = (UMax-UMin)/(Nu-1);
+  Standard_Real dv = (VMax-VMin)/(Nv-1);
+  Standard_Real extr = Extr0;
+  Standard_Real u, v, ang;
+  for (i = 1, u = UMin; i <= Nu; i++, u += du){
+    for (j = 1, v = VMin;j <= Nv; j++, v += dv){
+      S.D1(u,v,P,DU,DV);
+      try
+      {
+        ang = DU.Angle(DV);
+        if(ang > M_PI/2.)
+        {
+          ang = M_PI - ang;
+        }
+      }
+      catch (gp_VectorWithNullMagnitude)
+      {
+        ang = 0.;
+      }
+      //
+      if(extr > ang)
+      {
+        extr = ang;
+        uextr = u;
+        vextr = v;
+      }
+    }
+  }
+
+  if(Abs(extr - Extr0) > Tol)
+  {
+    Standard_Real umin, umax, vmin, vmax;
+    umin = Max(UMin, uextr - du);
+    umax = Min(UMax, uextr + du);
+    vmin = Max(VMin, vextr - dv);
+    vmax = Min(VMax, vextr + dv);
+    Standard_Real extr0 = extr;
+    extr = AdjustExtr(S, umin, umax, vmin, vmax,
+                      extr0,  Tol, uextr, vextr);
+  }
+  return extr;
+}
\ No newline at end of file
diff --git a/src/BRepCheck/BRepCheck_SurfNormAnalyzer.hxx b/src/BRepCheck/BRepCheck_SurfNormAnalyzer.hxx
new file mode 100644 (file)
index 0000000..2076992
--- /dev/null
@@ -0,0 +1,84 @@
+
+#ifndef _BRepCheck_SurfNormAnalyzer_HeaderFile
+#define _BRepCheck_SurfNormAnalyzer_HeaderFile
+
+#ifndef _Standard_HeaderFile
+#include <Standard.hxx>
+#endif
+#ifndef _Standard_DefineAlloc_HeaderFile
+#include <Standard_DefineAlloc.hxx>
+#endif
+#ifndef _Standard_Macro_HeaderFile
+#include <Standard_Macro.hxx>
+#endif
+
+#ifndef _TopoDS_Shape_HeaderFile
+#include <TopoDS_Shape.hxx>
+#endif
+
+#ifndef _Standard_Boolean_HeaderFile
+#include <Standard_Boolean.hxx>
+#endif
+
+#ifndef _TopAbs_ShapeEnum_HeaderFile
+#include <TopAbs_ShapeEnum.hxx>
+#endif
+
+#include <TopTools_ListOfShape.hxx>
+
+class Handle_Geom_Surface;
+
+
+//! A class to check the problems with calculations<br>
+//! of normals of face surfaces when dS/du and dS/dv are almost parallel: 
+//! normal to surface is calculated as N = dS/du^dS/dv and when<br>
+//! dS/du || dS/dv N is poor defined. It can cause problems in intersection<br>
+//! and other algoritms.<br>
+//! This class diagnoses whether the area on the surface where angle between dS/du<br>
+//! and dS/dv less then given angular tolerance. <br>
+class BRepCheck_SurfNormAnalyzer  {
+public:
+
+  DEFINE_STANDARD_ALLOC
+    //
+   Standard_EXPORT BRepCheck_SurfNormAnalyzer();
+   Standard_EXPORT BRepCheck_SurfNormAnalyzer(const TopoDS_Shape& theS, const Standard_Real theAngTol);
+   //
+   Standard_EXPORT void SetShape(const TopoDS_Shape& theS);
+   Standard_EXPORT void SetTolerance(const Standard_Real theAngTol);
+   //
+   Standard_EXPORT Standard_Boolean IsValid();
+   //
+   Standard_EXPORT const TopoDS_Shape& GetShape() const;
+   Standard_EXPORT Standard_Real GetTolerance() const;
+   //
+   Standard_EXPORT const TopTools_ListOfShape& BadFaces() const;
+   //
+   Standard_EXPORT static Standard_Boolean 
+     IsProblemSurf(const Handle_Geom_Surface& theSurf, 
+                   const Standard_Real theUMin,
+                   const Standard_Real theUMax,
+                   const Standard_Real theVMin,
+                   const Standard_Real theVMax,                                                       
+                   const Standard_Real theAngTol);
+
+
+protected:
+
+
+
+
+
+private:
+
+TopoDS_Shape myShape;
+TopTools_ListOfShape myBadFaces;
+Standard_Real myAngTol;
+
+
+};
+
+
+
+#endif
diff --git a/src/BRepCheck/FILES b/src/BRepCheck/FILES
new file mode 100644 (file)
index 0000000..23f46ec
--- /dev/null
@@ -0,0 +1 @@
+BRepCheck_SurfNormAnalyzer.hxx
index 03cc77f0221a01ba517cf1fee5c8460de8d9a58d..dcc1bfeb5763ccc8ac2f68d552192c53c1584135 100644 (file)
@@ -23,6 +23,7 @@
 #include <BRepCheck_Analyzer.hxx>
 #include <BRepCheck_Result.hxx>
 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
+#include <BRepCheck_SurfNormAnalyzer.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopTools_DataMapOfShapeListOfShape.hxx>
@@ -243,6 +244,60 @@ static void Print(Standard_OStream& OS,
 
 }
 
+//
+//=======================================================================
+//function : checknorm
+//purpose  : Checks the normals of faces
+//=======================================================================
+static Standard_Integer checknorm(Draw_Interpretor& di,
+                                    Standard_Integer narg, const char** a)
+{
+  if (narg < 3) {
+    return 1;
+  }
+  Standard_Real tol = 1.e-2;
+  TopoDS_Shape S = DBRep::Get(a[2]);
+  if(S.IsNull())
+  {
+    di << "Null shape \n";
+    return 1;
+  }
+  TopExp_Explorer anExp(S, TopAbs_FACE);
+  if(!anExp.More())
+  {
+    di << "There are no faces in shape /n";
+    return 1;
+  }
+  //
+  if(narg > 3)
+  {
+    tol = atof(a[3]);
+  }
+  //
+  BRepCheck_SurfNormAnalyzer aNormChecker(S, tol);
+  if(aNormChecker.IsValid())
+  {
+    di << "All faces seem to be valid \n" ;
+    return 0;
+  }
+  
+  const TopTools_ListOfShape& aBadFaces = aNormChecker.BadFaces();
+  //
+  di << " number of problematic faces : " << aBadFaces.Extent() << "\n";
+  //
+  char Name[32];
+  Standard_Integer ipp=0;
+  TopTools_ListIteratorOfListOfShape itf;
+  for (itf.Initialize(aBadFaces); itf.More(); itf.Next()) {
+    ipp++;
+    Sprintf(Name,"%s_%d",a[1], ipp);
+    DBRep::Set(Name, itf.Value());
+    di << Name << " " ;
+  }
+  di << "\n";
+  return 0;
+}
 //=======================================================================
 //function : computetolerance
 //purpose  : 
@@ -1677,5 +1732,11 @@ theCommands.Add("listfuseedge",
                  "listfuseedge shape",
                  __FILE__,
                  listfuseedge,g);
+
+theCommands.Add("checknorm",
+                 "checknorm name shape tol",
+                 __FILE__,
+                 checknorm,g);
+
 }