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

0024646: Wrong result done by Boolean Operation algorithm

1. class BOPAlgo_PaveFiller
   method void BOPAlgo_PaveFiller::PerformEF()
   Do not create intersection vertices in case if it lies ON the boundary of the face.
2. class IntTools_Context
   New method
    Standard_Boolean IntTools_Context::IsPointInFace
        (const gp_Pnt& aP,
         const TopoDS_Face& aF,
         const Standard_Real aTol)
   has been implemented to check if the point IN the face.
3. class IntTools_EdgeFace
   method
    void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
                                         const Standard_Real aT12,
                                         const Standard_Real aT21,
                                         const Standard_Real aT22,
                                         Standard_Real& aT1,
                                         Standard_Real& aT2)
   Treatment of the touching cases.

Test cases for issue CR24646

Correction of test cases for issue CR24646
This commit is contained in:
emv
2015-02-19 16:07:21 +03:00
committed by bugmaster
parent 7ad63454a5
commit bd28b2afac
13 changed files with 312 additions and 88 deletions

View File

@@ -188,7 +188,17 @@ is
--- inside the boundaries of the face aF,
--- otherwise returns false
---
IsPointInFace(me:mutable;
aP3D : Pnt from gp;
aF : Face from TopoDS;
aTol : Real from Standard)
returns Boolean from Standard;
---Purpose:
--- Returns true if the point aP2D is
--- inside the boundaries of the face aF,
--- otherwise returns false
---
IsPointInOnFace(me:mutable;
aF : Face from TopoDS;

View File

@@ -553,6 +553,35 @@ Standard_Boolean IntTools_Context::IsPointInFace
return Standard_True;
}
//=======================================================================
//function : IsPointInFace
//purpose :
//=======================================================================
Standard_Boolean IntTools_Context::IsPointInFace
(const gp_Pnt& aP,
const TopoDS_Face& aF,
const Standard_Real aTol)
{
Standard_Boolean bIn;
Standard_Real aDist;
//
GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(aF);
aProjector.Perform(aP);
//
bIn = aProjector.IsDone();
if (bIn) {
aDist = aProjector.LowerDistance();
if (aDist < aTol) {
Standard_Real U, V;
//
aProjector.LowerDistanceParameters(U, V);
gp_Pnt2d aP2D(U, V);
bIn = IsPointInFace(aF, aP2D);
}
}
//
return bIn;
}
//=======================================================================
//function : IsPointInOnFace
//purpose :
//=======================================================================

View File

@@ -48,11 +48,11 @@ static
Standard_Real PointBoxDistance(const Bnd_Box& aB,
const gp_Pnt& aP);
static
void SplitRangeOnSegments(const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theResolution,
const Standard_Integer theNbSeg,
IntTools_SequenceOfRanges& theSegments);
Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theResolution,
const Standard_Integer theNbSeg,
IntTools_SequenceOfRanges& theSegments);
static
Standard_Integer DistPC(const Standard_Real aT1,
const Handle(Geom_Curve)& theC1,
@@ -268,11 +268,9 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
aNb1 = IsClosed(myGeom1, aT11, aT12, myTol1, myRes1) ? 2 : 1;
aNb2 = 2;
//
SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1);
SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2);
aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1);
aNb2 = SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2);
//
aNb1 = aSegments1.Length();
aNb2 = aSegments2.Length();
for (i = 1; i <= aNb1; ++i) {
const IntTools_Range& aR1 = aSegments1(i);
for (j = 1; j <= aNb2; ++j) {
@@ -433,8 +431,7 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
IntTools_Range aR2(aT21, aT22);
BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
//
SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
aNb1 = aSegments1.Length();
aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
for (i = 1; i <= aNb1; ++i) {
const IntTools_Range& aR1 = aSegments1(i);
FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2);
@@ -685,37 +682,64 @@ void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
Standard_Real& aT2)
{
Standard_Integer i, aNbS, iErr;
Standard_Real aDMin, aD, aCrit, aRes1;
Standard_Real aT1x, aT2x, aT1p, aT2p;
GeomAPI_ProjectPointOnCurve aProj;
IntTools_SequenceOfRanges aSeg1;
Standard_Real aDMin, aD, aRes1, aSolCriteria, aTouchCriteria;
Standard_Real aT1A, aT1B, aT1Min, aT2Min;
Standard_Real aT1Im, aT2Im, aT1Touch;
GeomAPI_ProjectPointOnCurve aProjPC;
IntTools_SequenceOfRanges aRanges;
Standard_Boolean bTouch;
//
aT1 = (aT11 + aT12) * .5;
aT2 = (aT21 + aT22) * .5;
//
aDMin = 100.;
aD = 100.;
aCrit = 0.;//1.e-16;
aDMin = Precision::Infinite();
aSolCriteria = 5.e-16;
aTouchCriteria = 5.e-13;
bTouch = Standard_False;
aT1Touch = aT11;
//
aRes1 = Resolution(myCurve1.Curve().Curve(),
myCurve1.GetType(), myResCoeff1, myTol);
aNbS = 10;
SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aSeg1);
aNbS = aSeg1.Length();
aNbS = SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aRanges);
//
aProjPC.Init(myGeom2, aT21, aT22);
//
aT1 = (aT11 + aT12) * 0.5;
iErr = DistPC(aT1, myGeom1, aSolCriteria, aProjPC, aD, aT2, -1);
if (iErr == 1) {
aT2 = (aT21 + aT22) * 0.5;
}
//
aT1Im = aT1;
aT2Im = aT2;
//
aProj.Init(myGeom2, aT21, aT22);
for (i = 1; i <= aNbS; ++i) {
const IntTools_Range& aR1 = aSeg1(i);
aR1.Range(aT1x, aT2x);
const IntTools_Range& aR1 = aRanges(i);
aR1.Range(aT1A, aT1B);
//
iErr = FindDistPC(aT1x, aT2x, myGeom1, aCrit, myPTol1,
aProj, aD, aT1p, aT2p, Standard_False);
if (iErr != 1 && aD < aDMin) {
aT1 = aT1p;
aT2 = aT2p;
aDMin = aD;
if (aDMin <= aCrit) {
break;
aD = myTol;
iErr = FindDistPC(aT1A, aT1B, myGeom1, aSolCriteria, myPTol1,
aProjPC, aD, aT1Min, aT2Min, Standard_False);
if (iErr != 1) {
if (aD < aDMin) {
aT1 = aT1Min;
aT2 = aT2Min;
aDMin = aD;
}
//
if (aD < aTouchCriteria) {
if (bTouch) {
aT1A = (aT1Touch + aT1Min) * 0.5;
iErr = DistPC(aT1A, myGeom1, aTouchCriteria,
aProjPC, aD, aT2Min, -1);
if (aD > aTouchCriteria) {
aT1 = aT1Im;
aT2 = aT2Im;
break;
}
}
else {
aT1Touch = aT1Min;
bTouch = Standard_True;
}
}
}
}
@@ -920,13 +944,14 @@ Standard_Boolean IntTools_EdgeEdge::IsIntersection(const Standard_Real aT11,
//
if (((anAngle1 < anAngleCriteria) || ((M_PI - anAngle1) < anAngleCriteria)) ||
((anAngle2 < anAngleCriteria) || ((M_PI - anAngle2) < anAngleCriteria))) {
GeomAPI_ProjectPointOnCurve aProj;
GeomAPI_ProjectPointOnCurve aProjPC;
Standard_Integer iErr;
Standard_Real aD, aT1p, aT2p;
Standard_Real aD, aT1Min, aT2Min;
//
aD = 100.;
aProj.Init(myGeom2, aT21, aT22);
iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1, aProj, aD, aT1p, aT2p, Standard_False);
aD = Precision::Infinite();
aProjPC.Init(myGeom2, aT21, aT22);
iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1,
aProjPC, aD, aT1Min, aT2Min, Standard_False);
bRet = (iErr == 2);
}
}
@@ -947,7 +972,7 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
Standard_Integer iErr, aNb, aNb1, i;
Standard_Real aT1A, aT1B, aT1max, aT2max, aDmax;
GeomAPI_ProjectPointOnCurve aProjPC;
IntTools_SequenceOfRanges aSeg1;
IntTools_SequenceOfRanges aRanges;
//
iErr = 0;
aDmax = -1.;
@@ -955,10 +980,9 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
//
// 1. Express evaluation
aNb = 10; // Number of intervals on the curve #1
SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aSeg1);
aNb1 = aSeg1.Length();
aNb1 = SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aRanges);
for (i = 1; i < aNb1; ++i) {
const IntTools_Range& aR1 = aSeg1(i);
const IntTools_Range& aR1 = aRanges(i);
aR1.Range(aT1A, aT1B);
//
iErr = DistPC(aT1B, myGeom1, theCriteria, aProjPC, aDmax, aT2max);
@@ -967,7 +991,7 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
}
}
//
// if the ranges in aSeg1 are less than theCurveRes1,
// if the ranges in aRanges are less than theCurveRes1,
// there is no need to do step 2 (deep evaluation)
if (aNb1 < aNb) {
return iErr;
@@ -975,7 +999,7 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
//
// 2. Deep evaluation
for (i = 2; i < aNb1; ++i) {
const IntTools_Range& aR1 = aSeg1(i);
const IntTools_Range& aR1 = aRanges(i);
aR1.Range(aT1A, aT1B);
//
iErr = FindDistPC(aT1A, aT1B, myGeom1, theCriteria, theCurveRes1,
@@ -1017,12 +1041,14 @@ Standard_Integer FindDistPC(const Standard_Real aT1A,
aB = aT1B;
//
// check bounds
iErr = DistPC(aA, theC1, theCriteria, theProjPC, aYP, aT2P, aDmax, aT1max, aT2max, iC);
iErr = DistPC(aA, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
if (iErr == 2) {
return iErr;
}
//
iErr = DistPC(aB, theC1, theCriteria, theProjPC, aYL, aT2L, aDmax, aT1max, aT2max, iC);
iErr = DistPC(aB, theC1, theCriteria, theProjPC,
aYL, aT2L, aDmax, aT1max, aT2max, iC);
if (iErr == 2) {
return iErr;
}
@@ -1030,12 +1056,14 @@ Standard_Integer FindDistPC(const Standard_Real aT1A,
aXP = aA + (aB - aA)*aGS;
aXL = aB - (aB - aA)*aGS;
//
iErr = DistPC(aXP, theC1, theCriteria, theProjPC, aYP, aT2P, aDmax, aT1max, aT2max, iC);
iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
if (iErr) {
return iErr;
}
//
iErr = DistPC(aXL, theC1, theCriteria, theProjPC, aYL, aT2L, aDmax, aT1max, aT2max, iC);
iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
aYL, aT2L, aDmax, aT1max, aT2max, iC);
if (iErr) {
return iErr;
}
@@ -1046,20 +1074,25 @@ Standard_Integer FindDistPC(const Standard_Real aT1A,
aXL = aXP;
aYL = aYP;
aXP = aA + (aB - aA)*aGS;
iErr = DistPC(aXP, theC1, theCriteria, theProjPC, aYP, aT2P, aDmax, aT1max, aT2max, iC);
if (iErr) {
return iErr;
}
iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
}
else {
aB = aXP;
aXP = aXL;
aYP = aYL;
aXL = aB - (aB - aA)*aGS;
iErr = DistPC(aXL, theC1, theCriteria, theProjPC, aYL, aT2L, aDmax, aT1max, aT2max, iC);
if (iErr) {
return iErr;
iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
aYL, aT2L, aDmax, aT1max, aT2max, iC);
}
//
if (iErr) {
if ((iErr == 2) && !bMaxDist) {
aXP = (aA + aB) * 0.5;
DistPC(aXP, theC1, theCriteria, theProjPC,
aYP, aT2P, aDmax, aT1max, aT2max, iC);
}
return iErr;
}
//
if ((aB - aA) < theEps) {
@@ -1087,7 +1120,7 @@ Standard_Integer DistPC(const Standard_Real aT1,
Standard_Integer iErr;
//
iErr = DistPC(aT1, theC1, theCriteria, theProjPC, aD, aT2, iC);
if (iErr) {
if (iErr == 1) {
return iErr;
}
//
@@ -1137,16 +1170,16 @@ Standard_Integer DistPC(const Standard_Real aT1,
//function : SplitRangeOnSegments
//purpose :
//=======================================================================
void SplitRangeOnSegments(const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theResolution,
const Standard_Integer theNbSeg,
IntTools_SequenceOfRanges& theSegments)
Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
const Standard_Real aT2,
const Standard_Real theResolution,
const Standard_Integer theNbSeg,
IntTools_SequenceOfRanges& theSegments)
{
Standard_Real aDiff = aT2 - aT1;
if (aDiff < theResolution || theNbSeg == 1) {
theSegments.Append(IntTools_Range(aT1, aT2));
return;
return 1;
}
//
Standard_Real aDt, aT1x, aT2x, aSeg;
@@ -1172,6 +1205,8 @@ void SplitRangeOnSegments(const Standard_Real aT1,
//
IntTools_Range aR(aT1x, aT2);
theSegments.Append(aR);
//
return aNbSegments;
}
//=======================================================================

View File

@@ -70,14 +70,15 @@
static
Standard_Boolean IsCoplanar (const BRepAdaptor_Curve& ,
const BRepAdaptor_Surface& );
const BRepAdaptor_Surface& );
static
Standard_Boolean IsRadius (const BRepAdaptor_Curve& aCurve ,
const BRepAdaptor_Surface& aSurface);
const BRepAdaptor_Surface& aSurface,
const Standard_Real aCriteria);
static
Standard_Integer AdaptiveDiscret (const Standard_Integer iDiscret,
const BRepAdaptor_Curve& aCurve ,
const BRepAdaptor_Surface& aSurface);
const BRepAdaptor_Curve& aCurve ,
const BRepAdaptor_Surface& aSurface);
//=======================================================================
//function : IntTools_EdgeFace::IntTools_EdgeFace
@@ -1309,14 +1310,14 @@ void IntTools_EdgeFace::Perform()
if (bIsTouch) {
aCP.SetType(TopAbs_VERTEX);
aCP.SetVertexParameter1(aTx);
aCP.SetRange1 (aTx, aTx);
//aCP.SetRange1 (aTx, aTx);
}
}
if (aType==TopAbs_VERTEX) {
else if (aType==TopAbs_VERTEX) {
bIsTouch=CheckTouchVertex (aCP, aTx);
if (bIsTouch) {
aCP.SetVertexParameter1(aTx);
aCP.SetRange1 (aTx, aTx);
//aCP.SetRange1 (aTx, aTx);
}
}
}
@@ -1327,7 +1328,7 @@ void IntTools_EdgeFace::Perform()
if (aCType==GeomAbs_Circle && aSType==GeomAbs_Plane) {
Standard_Boolean bIsCoplanar, bIsRadius;
bIsCoplanar=IsCoplanar(myC, myS);
bIsRadius=IsRadius(myC, myS);
bIsRadius=IsRadius(myC, myS, myCriteria);
if (!bIsCoplanar && !bIsRadius) {
for (i=1; i<=aNb; i++) {
IntTools_CommonPrt& aCP=mySeqOfCommonPrts(i);
@@ -1337,7 +1338,14 @@ void IntTools_EdgeFace::Perform()
if (bIsTouch) {
aCP.SetType(TopAbs_VERTEX);
aCP.SetVertexParameter1(aTx);
aCP.SetRange1 (aTx, aTx);
//aCP.SetRange1 (aTx, aTx);
}
}
else if (aType==TopAbs_VERTEX) {
bIsTouch=CheckTouchVertex (aCP, aTx);
if (bIsTouch) {
aCP.SetVertexParameter1(aTx);
//aCP.SetRange1 (aTx, aTx);
}
}
}
@@ -1483,8 +1491,9 @@ Standard_Boolean IsCoplanar (const BRepAdaptor_Curve& aCurve ,
//function : IsRadius
//purpose :
//=======================================================================
Standard_Boolean IsRadius (const BRepAdaptor_Curve& aCurve ,
const BRepAdaptor_Surface& aSurface)
Standard_Boolean IsRadius (const BRepAdaptor_Curve& aCurve,
const BRepAdaptor_Surface& aSurface,
const Standard_Real aCriteria)
{
Standard_Boolean bFlag=Standard_False;
@@ -1500,7 +1509,7 @@ Standard_Boolean IsRadius (const BRepAdaptor_Curve& aCurve ,
Standard_Real aR=aCirc.Radius();
gp_Pln aPln=aSurface.Plane();
Standard_Real aD=aPln.Distance(aCenter);
if (fabs (aD-aR) < 1.e-7) {
if (fabs (aD-aR) < aCriteria) {
return !bFlag;
}
}