1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

Compare commits

...

2 Commits

Author SHA1 Message Date
emv
d7fe70f95c Provide possibility to check the ON status of the point for the face using the real tolerances of the sub-shapes of the face. 2019-09-06 07:51:53 +03:00
emv
44053715db 0030880: Bug in BRepExtrema_ExtCF
Correct tolerance management during intersection of the classification ray with edges of the face.
2019-09-02 08:14:56 +03:00
11 changed files with 761 additions and 245 deletions

View File

@@ -23,6 +23,7 @@
#include <BRep_Tool.hxx>
#include <BRepClass3d_SolidClassifier.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <DBRep.hxx>
#include <Draw.hxx>
#include <DrawTrSurf.hxx>
@@ -68,9 +69,13 @@ static Standard_Integer bhaspc (Draw_Interpretor& , Standard_Integer , con
const char* g = "BOPTest commands";
theCommands.Add("bclassify" , "use bclassify Solid Point [Tolerance=1.e-7]",
__FILE__, bclassify , g);
theCommands.Add("b2dclassify" , "use b2dclassify Face Point2d [Tol] ",
theCommands.Add("b2dclassify", "Classifies the point relatively face. If no point is given, classifies the infinite point\n"
"Uses BRepClass_FaceClassifier for classification\n"
"Usage: b2dclassify Face [Point2d] [Tol]",
__FILE__, b2dclassify , g);
theCommands.Add("b2dclassifx" , "use b2dclassifx Face Point2d [Tol] ",
theCommands.Add("b2dclassifx", "Classifies the point relatively face. If no point is given, classifies the infinite point\n"
"Uses IntTools_FClass2d for classification\n"
"Usage: b2dclassifx Face [Point2d] [Tol]",
__FILE__, b2dclassifx , g);
theCommands.Add("bhaspc" , "use bhaspc Edge Face [do]",
__FILE__, bhaspc , g);
@@ -83,35 +88,48 @@ static Standard_Integer bhaspc (Draw_Interpretor& , Standard_Integer , con
//purpose :
//=======================================================================
Standard_Integer b2dclassifx (Draw_Interpretor& theDI,
Standard_Integer theArgNb,
const char** theArgVec)
Standard_Integer theArgc,
const char** theArgv)
{
if (theArgNb < 3) {
theDI << " use b2dclassifx Face Point2d [Tol]\n";
if (theArgc < 2)
{
theDI.PrintHelp (theArgv[0]);
return 1;
}
TopoDS_Shape aS = DBRep::Get (theArgVec[1]);
if (aS.IsNull()) {
theDI << " Null Shape is not allowed here\n";
TopoDS_Shape aS = DBRep::Get (theArgv[1]);
if (aS.IsNull())
{
theDI << theArgv[1] << " is a null shape\n";
return 1;
}
else if (aS.ShapeType() != TopAbs_FACE) {
theDI << " Shape type must be FACE\n";
if (aS.ShapeType() != TopAbs_FACE)
{
theDI << theArgv[1] << " is a not a face\n";
return 1;
}
TopAbs_State aState;
gp_Pnt2d aP (8., 9.);
//
DrawTrSurf::GetPoint2d (theArgVec[2], aP);
const TopoDS_Face& aF = TopoDS::Face(aS);
const Standard_Real aTol = (theArgNb == 4) ?
Draw::Atof (theArgVec[3]) : BRep_Tool::Tolerance (aF);
//
IntTools_FClass2d aClassifier(aF, aTol);
aState=aClassifier.Perform(aP);
const TopoDS_Face& aF = TopoDS::Face (aS);
Standard_Real aTol = BRep_Tool::Tolerance (aF);
gp_Pnt2d aP;
Standard_Boolean isPoint = (theArgc > 2) && DrawTrSurf::GetPoint2d (theArgv[2], aP);
if (isPoint)
{
if (theArgc > 3)
aTol = Draw::Atof (theArgv[3]);
}
else if (theArgc > 2)
aTol = Draw::Atof (theArgv[2]);
IntTools_FClass2d aClassifier (aF, aTol);
TopAbs_State aState = isPoint ?
aClassifier.Perform (aP) :
aClassifier.PerformInfinitePoint ();
PrintState (theDI, aState);
//
return 0;
}
//
@@ -120,35 +138,54 @@ Standard_Integer b2dclassifx (Draw_Interpretor& theDI,
//purpose :
//=======================================================================
Standard_Integer b2dclassify (Draw_Interpretor& theDI,
Standard_Integer theArgNb,
const char** theArgVec)
Standard_Integer theArgc,
const char** theArgv)
{
if (theArgNb < 3) {
theDI << " use b2dclassify Face Point2d [Tol]\n";
if (theArgc < 2)
{
theDI.PrintHelp (theArgv[0]);
return 1;
}
TopoDS_Shape aS = DBRep::Get (theArgVec[1]);
if (aS.IsNull()) {
theDI << " Null Shape is not allowed here\n";
TopoDS_Shape aS = DBRep::Get (theArgv[1]);
if (aS.IsNull())
{
theDI << theArgv[1] << " is a null shape\n";
return 1;
}
else if (aS.ShapeType() != TopAbs_FACE) {
theDI << " Shape type must be FACE\n";
if (aS.ShapeType() != TopAbs_FACE)
{
theDI << theArgv[1] << " is a not a face\n";
return 1;
}
//
gp_Pnt2d aP (8., 9.);
//
DrawTrSurf::GetPoint2d (theArgVec[2], aP);
const TopoDS_Face& aF = TopoDS::Face(aS);
const Standard_Real aTol = (theArgNb == 4) ?
Draw::Atof (theArgVec[3]) : BRep_Tool::Tolerance (aF);
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(aF, aP, aTol);
PrintState (theDI, aClassifier.State());
//
const TopoDS_Face& aF = TopoDS::Face (aS);
Standard_Real aTol = BRep_Tool::Tolerance (aF);
gp_Pnt2d aP;
Standard_Boolean isPoint = (theArgc > 2) && DrawTrSurf::GetPoint2d (theArgv[2], aP);
TopAbs_State aState = TopAbs_UNKNOWN;
if (isPoint)
{
if (theArgc > 3)
aTol = Draw::Atof (theArgv[3]);
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform (aF, aP, aTol);
aState = aClassifier.State();
}
else
{
if (theArgc > 2)
aTol = Draw::Atof (theArgv[2]);
BRepTopAdaptor_FClass2d aClassifier (aF, aTol);
aState = aClassifier.PerformInfinitePoint();
}
PrintState (theDI, aState);
return 0;
}

View File

@@ -27,11 +27,134 @@
#include <Precision.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
static const Standard_Real Probing_Start = 0.123;
static const Standard_Real Probing_End = 0.7;
static const Standard_Real Probing_Step = 0.2111;
//=======================================================================
//function : BRepClass_FExp_DistanceTool
//purpose : Tool for checking the ON status of a point for the face
// using the real tolerances of sub-shapes of the latter.
//=======================================================================
#include <BVH_BoxSet.hxx>
#include <BVH_Distance.hxx>
#include <BVH_Tools.hxx>
#include <BVH_LinearBuilder.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <BRepBndLib.hxx>
#include <TopExp.hxx>
#include <Bnd_Box.hxx>
#include <Bnd_Tools.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BndLib_Add3dCurve.hxx>
class BRepClass_FExp_DistanceTool:
public BVH_Distance <Standard_Real, 3, NCollection_Vec3<Standard_Real>,
BVH_BoxSet<Standard_Real, 3, TopoDS_Shape> >
{
public:
//! Empty constructor
BRepClass_FExp_DistanceTool()
: BVH_Distance <Standard_Real, 3, NCollection_Vec3<Standard_Real>, BVH_BoxSet<Standard_Real, 3, TopoDS_Shape>>()
{
}
public: //! @name Setters
void SetPoint (const gp_Pnt& thePoint)
{
SetObject (NCollection_Vec3<Standard_Real> (thePoint.X(), thePoint.Y(), thePoint.Z()));
}
public: //! @name Setters
const TopoDS_Shape& GetOnShape() const
{
return myOnShape;
}
public: //! @name Clearing the results
//! Returns the flag controlling the tree descend
virtual void Clear() Standard_OVERRIDE
{
myDistance = 0.0;
myIsDone = Standard_False;
myOnShape.Nullify();
}
public: //! @name Definition of the rules for tree descend
// Computes the distance from the point to bounding box
virtual Standard_Boolean RejectNode (const BVH_Vec3d& theCMin,
const BVH_Vec3d& theCMax,
Standard_Real& theDistance) const Standard_OVERRIDE
{
theDistance = BVH_Tools<Standard_Real, 3>::PointBoxSquareDistance (myObject, theCMin, theCMax);
return RejectMetric (theDistance);
}
// Computes the distance from the point to triangle
virtual Standard_Boolean Accept (const Standard_Integer theIndex,
const Standard_Real&) Standard_OVERRIDE
{
if (myBVHSet->Box (theIndex).IsOut (myObject))
return Standard_False;
// Get the shape
const TopoDS_Shape& aS = myBVHSet->Element (theIndex);
if (aS.ShapeType() == TopAbs_VERTEX)
{
const TopoDS_Vertex& aV = TopoDS::Vertex (aS);
gp_XYZ aP = BRep_Tool::Pnt (aV).XYZ();
Standard_Real aTolV = BRep_Tool::Tolerance (aV);
Standard_Real aSqTol = aTolV * aTolV;
Standard_Real aSqDist = (aP - gp_XYZ (myObject.x(), myObject.y(), myObject.z())).SquareModulus();
if (aSqDist <= aSqTol)
{
myOnShape = aS;
return Standard_True;
}
}
else if (aS.ShapeType() == TopAbs_EDGE)
{
const TopoDS_Edge& aE = TopoDS::Edge (aS);
Standard_Real aFirst, aLast;
const Handle (Geom_Curve)& aC = BRep_Tool::Curve (aE, aFirst, aLast);
if (aC.IsNull())
return Standard_False;
GeomAPI_ProjectPointOnCurve aProjPC
(gp_Pnt (myObject.x(), myObject.y(), myObject.z()), aC, aFirst, aLast);
if (aProjPC.NbPoints() > 0)
{
if (aProjPC.LowerDistance() < BRep_Tool::Tolerance (aE))
{
myOnShape = aS;
return Standard_True;
}
}
}
return Standard_False;
}
//! Returns the flag controlling the tree descend
virtual Standard_Boolean Stop() const Standard_OVERRIDE
{
return !myOnShape.IsNull();
}
private: //! @name Fields
TopoDS_Shape myOnShape;
};
//=======================================================================
//function : BRepClass_FaceExplorer
//purpose :
@@ -296,3 +419,68 @@ void BRepClass_FaceExplorer::CurrentEdge(BRepClass_Edge& E,
Or = E.Edge().Orientation();
}
//=======================================================================
//function : IsPointOnFace
//purpose :
//=======================================================================
const opencascade::handle<BVH_BoxSet<Standard_Real, 3, TopoDS_Shape>>&
BRepClass_FaceExplorer::BVHBoxSet (Standard_Boolean toBuild) const
{
if (toBuild && myBVHSet.IsNull())
{
myBVHSet = new BVH_BoxSet<Standard_Real, 3, TopoDS_Shape> (new BVH_LinearBuilder<Standard_Real, 3>());
for (TopExp_Explorer anExpV (myFace, TopAbs_VERTEX); anExpV.More(); anExpV.Next())
{
const TopoDS_Vertex& aV = TopoDS::Vertex (anExpV.Current());
const TopAbs_Orientation aVOri = aV.Orientation();
if (aVOri == TopAbs_FORWARD || aVOri == TopAbs_REVERSED)
{
Bnd_Box aBox;
aBox.Add (BRep_Tool::Pnt (aV));
aBox.Enlarge (BRep_Tool::Tolerance (aV));
myBVHSet->Add (anExpV.Current(), Bnd_Tools::Bnd2BVH (aBox));
}
}
for (TopExp_Explorer anExpE (myFace, TopAbs_EDGE); anExpE.More(); anExpE.Next())
{
const TopoDS_Edge& aE = TopoDS::Edge (anExpE.Current());
const TopAbs_Orientation aEOri = aE.Orientation();
if (aEOri == TopAbs_FORWARD || aEOri == TopAbs_REVERSED)
{
BRepAdaptor_Curve aBAC (aE);
Bnd_Box aBox;
BndLib_Add3dCurve::Add (aBAC, aBAC.Tolerance(), aBox);
myBVHSet->Add (anExpE.Current(), Bnd_Tools::Bnd2BVH (aBox));
}
}
myBVHSet->Build();
}
return myBVHSet;
}
//=======================================================================
//function : IsPointOnFace
//purpose :
//=======================================================================
Standard_Boolean BRepClass_FaceExplorer::IsPointOnFace (const gp_Pnt2d& thePoint) const
{
const Handle (Geom_Surface)& aSurface = BRep_Tool::Surface (myFace);
gp_Pnt aP3d = aSurface->Value (thePoint.X(), thePoint.Y());
return IsPointOnFace (aP3d);
}
//=======================================================================
//function : IsPointOnFace
//purpose :
//=======================================================================
Standard_Boolean BRepClass_FaceExplorer::IsPointOnFace (const gp_Pnt& thePoint) const
{
BRepClass_FExp_DistanceTool aDistTool;
aDistTool.SetBVHSet (BVHBoxSet().get());
aDistTool.SetPoint (thePoint);
aDistTool.ComputeDistance();
return aDistTool.IsDone();
}

View File

@@ -27,6 +27,7 @@
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <TopAbs_Orientation.hxx>
#include <BVH_BoxSet.hxx>
class TopoDS_Face;
class gp_Pnt2d;
class gp_Lin2d;
@@ -94,7 +95,18 @@ public:
//! Current edge in current wire and its orientation.
Standard_EXPORT void CurrentEdge (BRepClass_Edge& E, TopAbs_Orientation& Or) const;
//! Returns the cached BVH_BoxSet.
//! @param toBuild controls if the set should be constructed if it is null
Standard_EXPORT const opencascade::handle<BVH_BoxSet<Standard_Real, 3, TopoDS_Shape>>&
BVHBoxSet (Standard_Boolean toBuild = Standard_True) const;
//! Checks the On status of a point evaluated from surface for the face using the
//! real tolerances of the sub-shapes of the face
Standard_EXPORT Standard_Boolean IsPointOnFace (const gp_Pnt2d& thePoint) const;
//! Checks the On status of a point for the face using the
//! real tolerances of the sub-shapes of the face
Standard_EXPORT Standard_Boolean IsPointOnFace (const gp_Pnt& thePoint) const;
protected:
@@ -117,6 +129,8 @@ private:
Standard_Real myUMax;
Standard_Real myVMin;
Standard_Real myVMax;
mutable opencascade::handle <BVH_BoxSet<Standard_Real, 3, TopoDS_Shape>> myBVHSet;
};

View File

@@ -26,6 +26,7 @@
#include <Geom2d_Line.hxx>
#include <Geom2dInt_GInter.hxx>
#include <Geom2dLProp_CLProps2d.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Lin2d.hxx>
#include <IntRes2d_Domain.hxx>
@@ -33,6 +34,7 @@
#include <IntRes2d_Transition.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
static
@@ -54,94 +56,83 @@ BRepClass_Intersector::BRepClass_Intersector()
//function : Perform
//purpose :
//=======================================================================
void BRepClass_Intersector::Perform(const gp_Lin2d& L,
const Standard_Real P,
const Standard_Real Tol,
const BRepClass_Edge& E)
void BRepClass_Intersector::Perform (const gp_Lin2d& L,
const Standard_Real P,
const Standard_Real Tol,
const BRepClass_Edge& E)
{
Standard_Real deb = 0.0, fin = 0.0, aTolZ = Tol;
Handle(Geom2d_Curve) aC2D;
//
const TopoDS_Edge& EE = E.Edge();
const TopoDS_Face& F = E.Face();
const TopoDS_Edge& anEdge = E.Edge();
const TopoDS_Face& aFace = E.Face();
//
aC2D=BRep_Tool::CurveOnSurface(EE, F, deb, fin);
if (aC2D.IsNull()) {
done = Standard_False; // !IsDone()
Standard_Real aFirst, aLast;
Handle (Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast);
if (aC2D.IsNull())
{
done = Standard_False;
return;
}
//
Geom2dAdaptor_Curve C(aC2D, deb, fin);
//
deb = C.FirstParameter();
fin = C.LastParameter();
//
// Case of "ON": direct check of belonging to edge
// taking into account the tolerance
Extrema_ExtPC2d anExtPC2d(L.Location(), C);
Standard_Real MinDist = RealLast(), aDist;
Standard_Integer MinInd = 0, i;
if (anExtPC2d.IsDone())
Geom2dAdaptor_Curve C (aC2D, aFirst, aLast);
{
const Standard_Integer aNbPnts = anExtPC2d.NbExt();
for (i = 1; i <= aNbPnts; ++i)
Extrema_ExtPC2d anExtPC2d (L.Location(), C);
Standard_Real MinDist = RealLast(), aDist;
Standard_Integer MinInd = 0, i;
if (anExtPC2d.IsDone())
{
aDist = anExtPC2d.SquareDistance(i);
if (aDist < MinDist)
const Standard_Integer aNbPnts = anExtPC2d.NbExt();
for (i = 1; i <= aNbPnts; ++i)
{
MinDist = aDist;
MinInd = i;
aDist = anExtPC2d.SquareDistance(i);
if (aDist < MinDist)
{
MinDist = aDist;
MinInd = i;
}
}
}
if (MinInd)
MinDist = sqrt (MinDist);
if (MinDist <= Tol)
{
gp_Pnt2d aPnt = (anExtPC2d.Point (MinInd)).Value();
Standard_Real aPar = (anExtPC2d.Point (MinInd)).Parameter();
Standard_Real aTolZ = Tol;
RefineTolerance (aFace, C, aPar, aTolZ);
if (MinDist <= aTolZ)
{
IntRes2d_Position aPosOnCurve = IntRes2d_Middle;
if (Abs (aPar - aFirst) <= Tol)
aPosOnCurve = IntRes2d_Head;
else if (Abs (aPar - aLast) <= Tol)
aPosOnCurve = IntRes2d_End;
IntRes2d_IntersectionPoint pnt_inter (aPnt, 0., aPar,
IntRes2d_Transition (IntRes2d_Head),
IntRes2d_Transition (aPosOnCurve),
Standard_False);
Append (pnt_inter);
done = Standard_True;
return;
}
}
}
if (MinInd) {
MinDist = sqrt(MinDist);
}
if (MinDist <= aTolZ) {
gp_Pnt2d pnt_exact = (anExtPC2d.Point(MinInd)).Value();
Standard_Real par = (anExtPC2d.Point(MinInd)).Parameter();
//
RefineTolerance(F, C, par, aTolZ);
//
if (MinDist <= aTolZ) {
IntRes2d_Transition tr_on_lin(IntRes2d_Head);
IntRes2d_Position pos_on_curve = IntRes2d_Middle;
if (Abs(par - deb) <= Precision::Confusion()) {
pos_on_curve = IntRes2d_Head;
}
else if (Abs(par - fin) <= Precision::Confusion()) {
pos_on_curve = IntRes2d_End;
}
//
IntRes2d_Transition tr_on_curve(pos_on_curve);
IntRes2d_IntersectionPoint pnt_inter(pnt_exact, 0., par,
tr_on_lin, tr_on_curve,
Standard_False);
//
Append(pnt_inter);
done = Standard_True;
return;
}
}
//
gp_Pnt2d pdeb,pfin;
C.D0(deb,pdeb);
C.D0(fin,pfin);
Standard_Real toldeb = 1.e-5, tolfin = 1.e-5;
// Intersection of the edge with the line
gp_Pnt2d aPFirst = C.Value (aFirst),
aPLast = C.Value (aLast);
IntRes2d_Domain DL;
//
if(P!=RealLast()) {
DL.SetValues(L.Location(),0.,Precision::PConfusion(),ElCLib::Value(P,L),P,Precision::PConfusion());
}
else {
DL.SetValues(L.Location(),0.,Precision::PConfusion(),Standard_True);
}
if (P != RealLast())
DL.SetValues (L.Location(), 0., Precision::PConfusion(),
ElCLib::Value (P, L), P, Precision::PConfusion());
else
DL.SetValues (L.Location(), 0., Precision::PConfusion(), Standard_True);
IntRes2d_Domain DE(pdeb,deb,toldeb,pfin,fin,tolfin);
IntRes2d_Domain DE (aPFirst, aFirst, Tol, aPLast, aLast, Tol);
// temporary periodic domain
if (C.Curve()->IsPeriodic()) {
DE.SetEquivalentParameters(C.FirstParameter(),

View File

@@ -23,7 +23,8 @@
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Curve2d.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <BRepClass_FaceExplorer.hxx>
#include <BRepClass_FClassifier.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <CSLib_Class2d.hxx>
@@ -486,12 +487,20 @@ TopAbs_State BRepTopAdaptor_FClass2d::PerformInfinitePoint() const {
return(Perform(P,Standard_False));
}
TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv,
const Standard_Boolean RecadreOnPeriodic) const
TopAbs_State BRepTopAdaptor_FClass2d::Perform (const gp_Pnt2d& _Puv,
const Standard_Boolean RecadreOnPeriodic,
const Standard_Boolean theUseFTolForOnCheck) const
{
#if LBRCOMPT
STAT.NbPerform++;
#endif
if (theUseFTolForOnCheck)
{
if (FExplorer().IsPointOnFace (_Puv))
return TopAbs_ON;
}
Standard_Integer dedans;
Standard_Integer nbtabclass = TabClass.Length();
@@ -568,11 +577,8 @@ TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv,
}
}
if(dedans==0) {
BRepClass_FaceClassifier aClassifier;
Standard_Real m_Toluv = (Toluv > 4.0) ? 4.0 : Toluv;
//aClassifier.Perform(Face,Puv,Toluv);
aClassifier.Perform(Face,Puv,m_Toluv);
aStatus = aClassifier.State();
aStatus = ClassifyByInter (Puv, m_Toluv);
}
if(dedans == 1) {
aStatus = TopAbs_IN;
@@ -582,9 +588,7 @@ TopAbs_State BRepTopAdaptor_FClass2d::Perform(const gp_Pnt2d& _Puv,
}
}
else { //-- TabOrien(1)=-1 False Wire
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(Face,Puv,Toluv);
aStatus = aClassifier.State();
aStatus = ClassifyByInter (Puv, Toluv);
}
if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
@@ -712,9 +716,7 @@ TopAbs_State BRepTopAdaptor_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv,
}
}
else { //-- TabOrien(1)=-1 False Wire
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(Face,Puv,Tol);
aStatus = aClassifier.State();
aStatus = ClassifyByInter (Puv, Tol);
}
if (!RecadreOnPeriodic || (!IsUPer && !IsVPer))
@@ -749,6 +751,24 @@ TopAbs_State BRepTopAdaptor_FClass2d::TestOnRestriction(const gp_Pnt2d& _Puv,
} //for (;;)
}
//=======================================================================
//function : FExplorer
//purpose :
//=======================================================================
BRepClass_FaceExplorer& BRepTopAdaptor_FClass2d::FExplorer() const
{
if (myFExplorer.get() == NULL)
myFExplorer.reset (new BRepClass_FaceExplorer (Face));
return *myFExplorer;
}
TopAbs_State BRepTopAdaptor_FClass2d::ClassifyByInter (const gp_Pnt2d& thePnt,
const Standard_Real theTolUV) const
{
BRepClass_FClassifier aClassifier;
aClassifier.Perform (FExplorer(), thePnt, theTolUV);
return aClassifier.State();
}
void BRepTopAdaptor_FClass2d::Destroy() {
#if LBRCOMPT

View File

@@ -27,11 +27,13 @@
#include <TopoDS_Face.hxx>
#include <TopAbs_State.hxx>
#include <Standard_Boolean.hxx>
#include <BRepClass_FaceExplorer.hxx>
#include <memory>
class TopoDS_Face;
class gp_Pnt2d;
class BRepTopAdaptor_FClass2d
{
public:
@@ -43,7 +45,9 @@ public:
Standard_EXPORT TopAbs_State PerformInfinitePoint() const;
Standard_EXPORT TopAbs_State Perform (const gp_Pnt2d& Puv, const Standard_Boolean RecadreOnPeriodic = Standard_True) const;
Standard_EXPORT TopAbs_State Perform (const gp_Pnt2d& Puv,
const Standard_Boolean RecadreOnPeriodic = Standard_True,
const Standard_Boolean theUseFTolForOnCheck = Standard_False) const;
Standard_EXPORT void Destroy();
~BRepTopAdaptor_FClass2d()
@@ -62,7 +66,12 @@ const BRepTopAdaptor_FClass2d& operator= (const BRepTopAdaptor_FClass2d& Other)
//! (Caution: Internal use . see the code for more details)
Standard_EXPORT TopAbs_State TestOnRestriction (const gp_Pnt2d& Puv, const Standard_Real Tol, const Standard_Boolean RecadreOnPeriodic = Standard_True) const;
//! Returns FaceExplorer for myFace
Standard_EXPORT BRepClass_FaceExplorer& FExplorer() const;
//! Classifies the point by geometrical classifier
Standard_EXPORT TopAbs_State ClassifyByInter (const gp_Pnt2d& thePnt,
const Standard_Real theTolUV) const;
protected:
@@ -88,13 +97,16 @@ private:
Standard_Real Vmin;
Standard_Real Vmax;
#ifdef _MSC_VER
#if _MSC_VER < 1600
mutable std::auto_ptr<BRepClass_FaceExplorer> myFExplorer;
#else
mutable std::unique_ptr<BRepClass_FaceExplorer> myFExplorer;
#endif
#else
mutable std::unique_ptr<BRepClass_FaceExplorer> myFExplorer;
#endif
};
#endif // _BRepTopAdaptor_FClass2d_HeaderFile

View File

@@ -53,6 +53,7 @@ public: //! @name Compute the distance
//! Computes the distance between object and BVH tree
NumType ComputeDistance()
{
Clear();
myIsDone = this->Select() > 0;
return myDistance;
}
@@ -65,6 +66,15 @@ public: //! @name Accessing the results
//! Returns the computed distance
NumType Distance() const { return myDistance; }
public: //! @name Clearing the results
//! Clears the data
virtual void Clear()
{
myDistance = std::numeric_limits<NumType>::max();
myIsDone = Standard_False;
}
public: //! @name Definition of the rules for tree descend
//! Compares the two metrics and chooses the best one

View File

@@ -3239,6 +3239,76 @@ static Standard_Integer OCC30869 (Draw_Interpretor& theDI, Standard_Integer theA
return 0;
}
#include <BRepExtrema_ExtCF.hxx>
//=======================================================================
//function : OCC30880
//purpose :
//=======================================================================
static Standard_Integer OCC30880 (Draw_Interpretor& theDI, Standard_Integer theArgc, const char** theArgv)
{
if (theArgc != 3)
{
theDI.PrintHelp (theArgv[0]);
return 1;
}
TopoDS_Shape anEdge = DBRep::Get (theArgv[1]);
if (anEdge.IsNull() || anEdge.ShapeType() != TopAbs_EDGE)
{
theDI << theArgv[1] << " is not an edge.\n";
return 1;
}
TopoDS_Shape aFace = DBRep::Get (theArgv[2]);
if (aFace.IsNull() || aFace.ShapeType() != TopAbs_FACE)
{
theDI << theArgv[2] << " is not a face.\n";
return 1;
}
BRepExtrema_ExtCF anExtCF (TopoDS::Edge (anEdge),
TopoDS::Face (aFace));
if (!anExtCF.IsDone())
{
theDI << "Not done\n";
return 0;
}
if (!anExtCF.NbExt())
{
theDI << "No solutions\n";
return 0;
}
if (anExtCF.IsParallel())
{
theDI << "Infinite number of solutions, distance - " << Sqrt (anExtCF.SquareDistance (1)) << "\n";
return 0;
}
Standard_Real aDistMin = RealLast();
Standard_Integer aSolMin = -1;
// Look for the minimal solution
for (int i = 1; i <= anExtCF.NbExt(); ++i)
{
Standard_Real aDist = anExtCF.SquareDistance (i);
if (aDist < aDistMin)
{
aDistMin = aDist;
aSolMin = i;
}
}
if (aSolMin < 0)
{
theDI << "Failed\n";
return 0;
}
theDI << "Minimal distance - " << Sqrt (aDistMin) << "\n";
return 0;
}
void QABugs::Commands_20(Draw_Interpretor& theCommands) {
const char *group = "QABugs";
@@ -3296,5 +3366,9 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
"Usage: OCC30869 wire",
__FILE__, OCC30869, group);
theCommands.Add ("OCC30880", "Looks for extrema between edge and face.\n"
"Usage: OCC30880 edge face",
__FILE__, OCC30880, group);
return;
}

View File

@@ -1014,6 +1014,130 @@ Standard_Boolean ShapeFix_Face::FixOrientation()
return FixOrientation(MapWires);
}
static TopAbs_State classifyWire (const TopoDS_Wire& theWire,
const Bnd_Box2d& aBox1,
const BRepTopAdaptor_FClass2d& theClassifier,
const TopAbs_State theInfPntState,
const TopTools_SequenceOfShape& theAllSubShapes,
const NCollection_Array1<Bnd_Box2d>& theWireBoxes,
const TopoDS_Face& theFace,
const Handle(ShapeAnalysis_Surface)& theSurf,
const Standard_Boolean theUClosed,
const Standard_Boolean theVClosed,
const Standard_Real theURange,
const Standard_Real theVRange,
TopTools_DataMapOfShapeInteger& theSI,
TopTools_ListOfShape& theIntWires,
const Standard_Boolean theUseToler)
{
Standard_Boolean CheckShift = Standard_True;
TopAbs_State sta = TopAbs_OUT;
Standard_Integer aWireIt = 0;
const Standard_Integer nbAll = theAllSubShapes.Length();
for (Standard_Integer j = 1; j <= nbAll; j++)
{
aWireIt++;
//if(i==j) continue;
TopoDS_Shape aSh2 = theAllSubShapes.Value (j);
if (theWire == aSh2)
continue;
TopAbs_State stb = TopAbs_UNKNOWN;
if (aSh2.ShapeType () == TopAbs_VERTEX) {
aWireIt--;
gp_Pnt aP = BRep_Tool::Pnt (TopoDS::Vertex (aSh2));
gp_Pnt2d p2d = theSurf->ValueOfUV (aP, Precision::Confusion ());
stb = theClassifier.Perform (p2d, Standard_False, theUseToler);
if (stb == theInfPntState && (theUClosed || theVClosed)) {
gp_Pnt2d p2d1;
if (theUClosed) {
p2d1.SetCoord (p2d.X () + theURange, p2d.Y ());
stb = theClassifier.Perform (p2d1, Standard_False, theUseToler);
}
if (stb == theInfPntState && theVClosed) {
p2d1.SetCoord (p2d.X (), p2d.Y () + theVRange);
stb = theClassifier.Perform (p2d1, Standard_False, theUseToler);
}
}
}
else if (aSh2.ShapeType () == TopAbs_WIRE) {
CheckShift = Standard_True;
TopoDS_Wire bw = TopoDS::Wire (aSh2);
//Standard_Integer numin =0;
Bnd_Box2d aBox2 = theWireBoxes.Value (aWireIt);
if (aBox2.IsOut (aBox1))
continue;
TopoDS_Iterator ew (bw);
for (; ew.More (); ew.Next ()) {
TopoDS_Edge ed = TopoDS::Edge (ew.Value ());
Standard_Real cf, cl;
Handle (Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed, theFace, cf, cl);
if (cw.IsNull ()) continue;
gp_Pnt2d unp = cw->Value ((cf + cl) / 2.);
TopAbs_State ste = theClassifier.Perform (unp, Standard_False, theUseToler);
std::cout << (ste == TopAbs_ON ? "ON" : (ste == TopAbs_IN ? "IN" : "OUT")) << std::endl;
if (ste == TopAbs_OUT || ste == TopAbs_IN) {
if (stb == TopAbs_UNKNOWN) {
stb = ste;
}
else {
if (!(stb == ste)) {
sta = TopAbs_UNKNOWN;
theSI.Bind (theWire, 0);
break;
}
}
}
Standard_Boolean found = Standard_False;
gp_Pnt2d unp1;
if (stb == theInfPntState && CheckShift) {
CheckShift = Standard_False;
if (theUClosed) {
unp1.SetCoord (unp.X () + theURange, unp.Y ());
found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler));
if (!found) {
unp1.SetX (unp.X () - theURange);
found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler));
}
}
if (theVClosed && !found) {
unp1.SetCoord (unp.X (), unp.Y () + theVRange);
found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler));
if (!found) {
unp1.SetY (unp.Y () - theVRange);
found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler));
}
}
// Additional check of diagonal steps for toroidal surfaces
if (!found && theUClosed && theVClosed)
{
for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0)
for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0)
{
unp1.SetCoord (unp.X () + theURange * dX, unp.Y () + theVRange * dY);
found = (theInfPntState != theClassifier.Perform (unp1, Standard_False, theUseToler));
}
}
}
if (found) {
if (stb == TopAbs_IN) stb = TopAbs_OUT;
else stb = TopAbs_IN;
Shift2dWire (bw, theFace, unp1.XY () - unp.XY (), theSurf);
}
}
if (ew.More())
break;
}
if (stb == theInfPntState) {
sta = TopAbs_IN;
}
else {
theIntWires.Append (aSh2);
}
}
return sta;
}
//=======================================================================
//function : FixOrientation
@@ -1137,9 +1261,6 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
TopTools_DataMapOfShapeListOfShape MW;
TopTools_DataMapOfShapeInteger SI;
TopTools_MapOfShape MapIntWires;
MW.Clear();
SI.Clear();
MapIntWires.Clear();
Standard_Integer NbOuts=0;
Standard_Integer i;
@@ -1192,120 +1313,148 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
Bnd_Box2d aBox1 = aWireBoxes.Value(i);
TopoDS_Shape dummy = myFace.EmptyCopied();
TopoDS_Face af = TopoDS::Face ( dummy );
// B.MakeFace (af,mySurf->Surface(),::Precision::Confusion());
af.Orientation ( TopAbs_FORWARD );
B.Add (af,aw);
// PTV OCC945 06.11.2002 files ie_exhaust-A.stp (entities 3782, 3787)
// tolerance is too big. It is seems that to identify placement of 2d point
// it is enough Precision::PConfusion(), cause wea re know that 2d point in TopAbs_ON
// BRepTopAdaptor_FClass2d clas (af,toluv);
Standard_Boolean CheckShift = Standard_True;
BRepTopAdaptor_FClass2d clas (af,::Precision::PConfusion());
TopAbs_State sta = TopAbs_OUT;
TopAbs_State staout = clas.PerformInfinitePoint();
TopTools_ListOfShape IntWires;
Standard_Integer aWireIt = 0;
for ( Standard_Integer j = 1; j <= nbAll; j ++) {
aWireIt++;
//if(i==j) continue;
TopoDS_Shape aSh2 = allSubShapes.Value(j);
if(aw == aSh2)
continue;
TopAbs_State stb = TopAbs_UNKNOWN;
if(aSh2.ShapeType() == TopAbs_VERTEX) {
aWireIt--;
gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aSh2));
gp_Pnt2d p2d = mySurf->ValueOfUV(aP,Precision::Confusion());
stb = clas.Perform (p2d,Standard_False);
if(stb == staout && (uclosed || vclosed)) {
gp_Pnt2d p2d1;
if(uclosed) {
p2d1.SetCoord(p2d.X()+uRange, p2d.Y());
stb = clas.Perform (p2d1,Standard_False);
}
if(stb == staout && vclosed) {
p2d1.SetCoord(p2d.X(), p2d.Y()+ vRange);
stb = clas.Perform (p2d1,Standard_False);
}
}
}
else if (aSh2.ShapeType() == TopAbs_WIRE) {
CheckShift = Standard_True;
TopoDS_Wire bw = TopoDS::Wire (aSh2);
//Standard_Integer numin =0;
Bnd_Box2d aBox2 = aWireBoxes.Value(aWireIt);
if (aBox2.IsOut(aBox1))
continue;
TopoDS_Iterator ew (bw);
for(;ew.More(); ew.Next()) {
TopoDS_Edge ed = TopoDS::Edge (ew.Value());
Standard_Real cf,cl;
Handle(Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed,myFace,cf,cl);
if (cw.IsNull()) continue;
gp_Pnt2d unp = cw->Value ((cf+cl)/2.);
TopAbs_State ste = clas.Perform (unp,Standard_False);
if( ste==TopAbs_OUT || ste==TopAbs_IN ) {
if(stb==TopAbs_UNKNOWN) {
stb = ste;
}
else {
if(!(stb==ste)) {
sta = TopAbs_UNKNOWN;
SI.Bind(aw,0);
j=nb;
break;
}
}
}
Standard_Boolean found = Standard_False;
gp_Pnt2d unp1;
if( stb == staout && CheckShift ) {
CheckShift = Standard_False;
if(uclosed) {
unp1.SetCoord(unp.X()+uRange, unp.Y());
found = (staout != clas.Perform (unp1,Standard_False));
if(!found) {
unp1.SetX(unp.X()-uRange);
found = (staout != clas.Perform (unp1,Standard_False));
}
}
if(vclosed&&!found) {
unp1.SetCoord(unp.X(), unp.Y()+vRange);
found = (staout != clas.Perform (unp1,Standard_False));
if(!found) {
unp1.SetY(unp.Y()-vRange);
found = (staout != clas.Perform (unp1,Standard_False));
}
}
// Additional check of diagonal steps for toroidal surfaces
if (!found && uclosed && vclosed)
{
for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0)
for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0)
{
unp1.SetCoord(unp.X() + uRange * dX, unp.Y() + vRange * dY);
found = (staout != clas.Perform(unp1, Standard_False));
}
}
}
if(found) {
if(stb==TopAbs_IN) stb = TopAbs_OUT;
else stb = TopAbs_IN;
Shift2dWire(bw,myFace,unp1.XY()-unp.XY(), mySurf);
}
}
}
if(stb==staout) {
sta = TopAbs_IN;
}
else {
IntWires.Append(aSh2);
MapIntWires.Add(aSh2);
}
TopTools_ListOfShape IntWires;
TopTools_DataMapOfShapeInteger SILoc;
TopAbs_State sta = classifyWire (aw, aBox1, clas, staout,
allSubShapes, aWireBoxes,
myFace, mySurf,
uclosed, vclosed, uRange, vRange,
SILoc, IntWires, Standard_False);
if (sta == TopAbs_UNKNOWN)
{
IntWires.Clear();
SILoc.Clear();
sta = classifyWire (aw, aBox1, clas, staout,
allSubShapes, aWireBoxes,
myFace, mySurf,
uclosed, vclosed, uRange, vRange,
SILoc, IntWires, Standard_True);
}
{
for (TopTools_ListOfShape::Iterator itIW (IntWires); itIW.More(); itIW.Next())
MapIntWires.Add (itIW.Value());
for (TopTools_DataMapOfShapeInteger::Iterator itSI (SILoc); itSI.More(); itSI.Next())
SI.Bind (itSI.Key(), itSI.Value());
}
//
//Standard_Boolean CheckShift = Standard_True;
//
//TopAbs_State staout = clas.PerformInfinitePoint();
//TopTools_ListOfShape IntWires;
//Standard_Integer aWireIt = 0;
//for ( Standard_Integer j = 1; j <= nbAll; j ++) {
// aWireIt++;
// //if(i==j) continue;
// TopoDS_Shape aSh2 = allSubShapes.Value(j);
// if(aw == aSh2)
// continue;
// TopAbs_State stb = TopAbs_UNKNOWN;
// if(aSh2.ShapeType() == TopAbs_VERTEX) {
// aWireIt--;
// gp_Pnt aP = BRep_Tool::Pnt(TopoDS::Vertex(aSh2));
// gp_Pnt2d p2d = mySurf->ValueOfUV(aP,Precision::Confusion());
// stb = clas.Perform (p2d,Standard_False);
// if(stb == staout && (uclosed || vclosed)) {
// gp_Pnt2d p2d1;
// if(uclosed) {
// p2d1.SetCoord(p2d.X()+uRange, p2d.Y());
// stb = clas.Perform (p2d1,Standard_False);
//
// }
// if(stb == staout && vclosed) {
// p2d1.SetCoord(p2d.X(), p2d.Y()+ vRange);
// stb = clas.Perform (p2d1,Standard_False);
// }
// }
// }
// else if (aSh2.ShapeType() == TopAbs_WIRE) {
// CheckShift = Standard_True;
// TopoDS_Wire bw = TopoDS::Wire (aSh2);
// //Standard_Integer numin =0;
// Bnd_Box2d aBox2 = aWireBoxes.Value(aWireIt);
// if (aBox2.IsOut(aBox1))
// continue;
//
// TopoDS_Iterator ew (bw);
// for(;ew.More(); ew.Next()) {
// TopoDS_Edge ed = TopoDS::Edge (ew.Value());
// Standard_Real cf,cl;
// Handle(Geom2d_Curve) cw = BRep_Tool::CurveOnSurface (ed,myFace,cf,cl);
// if (cw.IsNull()) continue;
// gp_Pnt2d unp = cw->Value ((cf+cl)/2.);
// TopAbs_State ste = clas.Perform (unp,Standard_False);
// std::cout << (ste == TopAbs_ON ? "ON" : (ste == TopAbs_IN ? "IN" : "OUT")) << std::endl;
// if( ste==TopAbs_OUT || ste==TopAbs_IN ) {
// if(stb==TopAbs_UNKNOWN) {
// stb = ste;
// }
// else {
// if(!(stb==ste)) {
// sta = TopAbs_UNKNOWN;
// SI.Bind(aw,0);
// j=nb;
// break;
// }
// }
// }
//
// Standard_Boolean found = Standard_False;
// gp_Pnt2d unp1;
// if( stb == staout && CheckShift ) {
// CheckShift = Standard_False;
// if(uclosed) {
// unp1.SetCoord(unp.X()+uRange, unp.Y());
// found = (staout != clas.Perform (unp1,Standard_False));
// if(!found) {
// unp1.SetX(unp.X()-uRange);
// found = (staout != clas.Perform (unp1,Standard_False));
// }
// }
// if(vclosed&&!found) {
// unp1.SetCoord(unp.X(), unp.Y()+vRange);
// found = (staout != clas.Perform (unp1,Standard_False));
// if(!found) {
// unp1.SetY(unp.Y()-vRange);
// found = (staout != clas.Perform (unp1,Standard_False));
// }
// }
// // Additional check of diagonal steps for toroidal surfaces
// if (!found && uclosed && vclosed)
// {
// for (Standard_Real dX = -1.0; dX <= 1.0 && !found; dX += 2.0)
// for (Standard_Real dY = -1.0; dY <= 1.0 && !found; dY += 2.0)
// {
// unp1.SetCoord(unp.X() + uRange * dX, unp.Y() + vRange * dY);
// found = (staout != clas.Perform(unp1, Standard_False));
// }
// }
// }
// if(found) {
// if(stb==TopAbs_IN) stb = TopAbs_OUT;
// else stb = TopAbs_IN;
// Shift2dWire(bw,myFace,unp1.XY()-unp.XY(), mySurf);
// }
// }
// }
// if(stb==staout) {
// sta = TopAbs_IN;
// }
// else {
// IntWires.Append(aSh2);
// MapIntWires.Add(aSh2);
// }
//}
if (sta == TopAbs_UNKNOWN) { // ERREUR
SendWarning ( aw, Message_Msg ( "FixAdvFace.FixOrientation.MSG11" ) );// Cannot orient wire

View File

@@ -0,0 +1,11 @@
puts "========"
puts "0030880: Bug in BRepExtrema_ExtCF"
puts "========"
puts ""
restore [locate_data_file bug30880_edge.brep] e
restore [locate_data_file bug30880_face.brep] f
if {![regexp "No solutions" [OCC30880 e f]]} {
puts "Error: Incorrect extrema solutions"
}

View File

@@ -0,0 +1,10 @@
puts "========"
puts "0030880: Bug in BRepExtrema_ExtCF"
puts "========"
puts ""
restore [locate_data_file bug30880_face.brep] f
point p2d -0.0034857302428251678 0.016350559703980902
if {![regexp "OUT" [b2dclassify f p2d -tol 1.e-7]]} {
puts "Error: Incorrect classification of the point"
}