mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-29 14:00:49 +03:00
Analyzer for surface normals is added
This commit is contained in:
342
src/BRepCheck/BRepCheck_SurfNormAnalyzer.cxx
Normal file
342
src/BRepCheck/BRepCheck_SurfNormAnalyzer.cxx
Normal file
@@ -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;
|
||||
}
|
84
src/BRepCheck/BRepCheck_SurfNormAnalyzer.hxx
Normal file
84
src/BRepCheck/BRepCheck_SurfNormAnalyzer.hxx
Normal file
@@ -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
|
1
src/BRepCheck/FILES
Normal file
1
src/BRepCheck/FILES
Normal file
@@ -0,0 +1 @@
|
||||
BRepCheck_SurfNormAnalyzer.hxx
|
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user