mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0026938: Boolean operations fail between two ellipsoids
Treatment for single singular point is added. Test cases are updated to the new behavior. New test cases are added, Message of "bad" state is corrected.
This commit is contained in:
@@ -113,7 +113,8 @@ static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
|
||||
|
||||
theIsUparallel = theIsVparallel = Standard_True;
|
||||
|
||||
Standard_Integer aNbPoints = theLine->NbPoints();
|
||||
const Standard_Integer aNbLinePnts = theLine->NbPoints();
|
||||
Standard_Integer aNbPoints = aNbLinePnts;
|
||||
if(aNbPoints > aNbPointsMAX)
|
||||
{
|
||||
aNbPoints = aNbPointsMAX;
|
||||
@@ -131,10 +132,9 @@ static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
|
||||
Standard_Real aUmin = RealLast(), aUmax = RealFirst(), aVmin = RealLast(), aVmax = RealFirst();
|
||||
for(Standard_Integer aNum = 1; aNum <= aNbPoints; aNum++, aNPoint += aStep)
|
||||
{
|
||||
if(aNPoint > aNbPoints)
|
||||
{
|
||||
aNPoint = aNbPoints;
|
||||
}
|
||||
// Fix possible "out of parameter" case.
|
||||
if (aNPoint > aNbLinePnts)
|
||||
aNPoint = aNbLinePnts;
|
||||
|
||||
Standard_Real u, v;
|
||||
if(theCheckSurf1)
|
||||
@@ -159,100 +159,6 @@ static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
|
||||
theIsUparallel = ((aVmax - aVmin) < theToler);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Checking
|
||||
//purpose : Check, if given point is in surface's boundaries.
|
||||
// If "yes" then theFactTol = 0.0, else theFactTol is
|
||||
// equal maximal deviation.
|
||||
//=======================================================================
|
||||
static Standard_Boolean Checking( const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
const Handle(Adaptor3d_HSurface)& theASurf2,
|
||||
Standard_Real& theU1,
|
||||
Standard_Real& theV1,
|
||||
Standard_Real& theU2,
|
||||
Standard_Real& theV2,
|
||||
Standard_Real& theFactTol)
|
||||
{
|
||||
const Standard_Real aTol = Precision::PConfusion();
|
||||
const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
|
||||
const Standard_Real aU1bLast = theASurf1->LastUParameter();
|
||||
const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
|
||||
const Standard_Real aU2bLast = theASurf2->LastUParameter();
|
||||
const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
|
||||
const Standard_Real aV1bLast = theASurf1->LastVParameter();
|
||||
const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
|
||||
const Standard_Real aV2bLast = theASurf2->LastVParameter();
|
||||
|
||||
Standard_Boolean isOnOrIn = Standard_True;
|
||||
theFactTol = 0.0;
|
||||
|
||||
Standard_Real aDelta = aU1bFirst - theU1;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theU1 = aU1bFirst;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = theU1 - aU1bLast;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theU1 = aU1bLast;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = aV1bFirst - theV1;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theV1 = aV1bFirst;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = theV1 - aV1bLast;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theV1 = aV1bLast;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = aU2bFirst - theU2;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theU2 = aU2bFirst;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = theU2 - aU2bLast;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theU2 = aU2bLast;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = aV2bFirst - theV2;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theV2 = aV2bFirst;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
aDelta = theV2 - aV2bLast;
|
||||
if(aDelta > aTol)
|
||||
{
|
||||
theV2 = aV2bLast;
|
||||
theFactTol = Max(theFactTol, aDelta);
|
||||
isOnOrIn = Standard_False;
|
||||
}
|
||||
|
||||
return isOnOrIn;
|
||||
}
|
||||
|
||||
//==================================================================================
|
||||
// function : IntWalk_PWalking::IntWalk_PWalking
|
||||
// purpose :
|
||||
@@ -2260,6 +2166,55 @@ DistanceMinimizeByExtrema(const Handle(Adaptor3d_HSurface)& theASurf,
|
||||
return (aSQDistPrev < aTol);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : HandleSingleSingularPoint
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean IntWalk_PWalking::HandleSingleSingularPoint(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
const Handle(Adaptor3d_HSurface)& theASurf2,
|
||||
const Standard_Real the3DTol,
|
||||
TColStd_Array1OfReal &thePnt)
|
||||
{
|
||||
// u1, v1, u2, v2 order is used.
|
||||
Standard_Real aLowBorder[4] = {theASurf1->FirstUParameter(),
|
||||
theASurf1->FirstVParameter(),
|
||||
theASurf2->FirstUParameter(),
|
||||
theASurf2->FirstVParameter()};
|
||||
Standard_Real aUppBorder[4] = {theASurf1->LastUParameter(),
|
||||
theASurf1->LastVParameter(),
|
||||
theASurf2->LastUParameter(),
|
||||
theASurf2->LastVParameter()};
|
||||
IntImp_ConstIsoparametric aLockedDir[4] = {IntImp_UIsoparametricOnCaro1,
|
||||
IntImp_VIsoparametricOnCaro1,
|
||||
IntImp_UIsoparametricOnCaro2,
|
||||
IntImp_VIsoparametricOnCaro2};
|
||||
|
||||
// Create new intersector with new tolerance.
|
||||
IntWalk_TheInt2S anInt(theASurf1, theASurf2, the3DTol);
|
||||
math_FunctionSetRoot aRsnld(anInt.Function());
|
||||
|
||||
for (Standard_Integer i = 1; i <= 4; ++i)
|
||||
{
|
||||
if ( Abs(thePnt(i) - aLowBorder[i - 1]) < Precision::PConfusion() ||
|
||||
Abs(thePnt(i) - aUppBorder[i - 1]) < Precision::PConfusion())
|
||||
{
|
||||
|
||||
anInt.Perform(thePnt,aRsnld, aLockedDir[i - 1]);
|
||||
|
||||
if (!anInt.IsDone())
|
||||
continue;
|
||||
|
||||
if (anInt.IsEmpty())
|
||||
continue;
|
||||
|
||||
anInt.Point().Parameters(thePnt(1), thePnt(2), thePnt(3), thePnt(4));
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SeekPointOnBoundary
|
||||
//purpose :
|
||||
@@ -2273,79 +2228,64 @@ SeekPointOnBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
const Standard_Real theV2,
|
||||
const Standard_Boolean isTheFirst)
|
||||
{
|
||||
const Standard_Real aTol = 1.0e-14;
|
||||
Standard_Boolean isOK = Standard_False;
|
||||
Standard_Real U1prec = theU1, V1prec = theV1, U2prec = theU2, V2prec = theV2;
|
||||
|
||||
Standard_Boolean flFinish = Standard_False;
|
||||
// Tune solution tolerance according with object size.
|
||||
const Standard_Real aRes1 = Max(Precision::PConfusion() / theASurf1->UResolution(1.0),
|
||||
Precision::PConfusion() / theASurf1->VResolution(1.0));
|
||||
const Standard_Real aRes2 = Max(Precision::PConfusion() / theASurf2->UResolution(1.0),
|
||||
Precision::PConfusion() / theASurf2->VResolution(1.0));
|
||||
const Standard_Real a3DTol = Max(aRes1, aRes2);
|
||||
const Standard_Real aTol = Max(Precision::Confusion(), a3DTol);
|
||||
|
||||
// u1, v1, u2, v2 order is used.
|
||||
TColStd_Array1OfReal aPnt(1,4);
|
||||
aPnt(1) = theU1; aPnt(2) = theV1; aPnt(3) = theU2; aPnt(4) = theV2;
|
||||
TColStd_Array1OfReal aSingularPnt(aPnt);
|
||||
|
||||
Standard_Integer aNbIter = 20;
|
||||
while(!flFinish)
|
||||
Standard_Boolean aStatus = Standard_False;
|
||||
do
|
||||
{
|
||||
flFinish = Standard_False;
|
||||
Standard_Boolean aStatus = Standard_False;
|
||||
|
||||
do
|
||||
{
|
||||
aNbIter--;
|
||||
aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec);
|
||||
if(aStatus)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(U2prec, V2prec), U1prec, V1prec);
|
||||
if(aStatus)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(U1prec, V1prec), U2prec, V2prec);
|
||||
if(aStatus)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!aStatus && (aNbIter > 0));
|
||||
|
||||
aNbIter--;
|
||||
aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, aPnt(1), aPnt(2), aPnt(3), aPnt(4));
|
||||
if(aStatus)
|
||||
{
|
||||
const Standard_Real aTolMax = 1.0e-8;
|
||||
Standard_Real aTolF = 0.0;
|
||||
|
||||
Standard_Real u1 = U1prec, v1 = V1prec, u2 = U2prec, v2 = V2prec;
|
||||
|
||||
flFinish = Checking(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec, aTolF);
|
||||
|
||||
if(aTolF <= aTolMax)
|
||||
{
|
||||
gp_Pnt aP1 = theASurf1->Value(u1, v1),
|
||||
aP2 = theASurf2->Value(u2, v2);
|
||||
gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
|
||||
|
||||
const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
|
||||
aSQDist2 = aPInt.SquareDistance(aP2);
|
||||
if((aSQDist1 < aTol) && (aSQDist2 < aTol))
|
||||
{
|
||||
IntSurf_PntOn2S anIP;
|
||||
anIP.SetValue(aPInt, u1, v1, u2, v2);
|
||||
|
||||
if(isTheFirst)
|
||||
line->InsertBefore(1,anIP);
|
||||
else
|
||||
line->Add(anIP);
|
||||
|
||||
isOK = Standard_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(aNbIter < 0)
|
||||
aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(aPnt(3), aPnt(4)), aPnt(1), aPnt(2));
|
||||
if(aStatus)
|
||||
break;
|
||||
|
||||
aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(aPnt(1), aPnt(2)), aPnt(3), aPnt(4));
|
||||
if(aStatus)
|
||||
break;
|
||||
}
|
||||
while(!aStatus && (aNbIter > 0));
|
||||
|
||||
// Handle singular points.
|
||||
Standard_Boolean aSingularStatus = HandleSingleSingularPoint(theASurf1, theASurf2, aTol, aSingularPnt);
|
||||
if (aSingularStatus)
|
||||
aPnt = aSingularPnt;
|
||||
|
||||
if(aStatus || aSingularStatus)
|
||||
{
|
||||
gp_Pnt aP1 = theASurf1->Value(aPnt(1), aPnt(2)),
|
||||
aP2 = theASurf2->Value(aPnt(3), aPnt(4));
|
||||
gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
|
||||
|
||||
const Standard_Real aSQDist = aPInt.SquareDistance(aP1);
|
||||
if (aSQDist < aTol * aTol)
|
||||
{
|
||||
IntSurf_PntOn2S anIP;
|
||||
anIP.SetValue(aPInt, aPnt(1), aPnt(2), aPnt(3), aPnt(4));
|
||||
|
||||
if(isTheFirst)
|
||||
line->InsertBefore(1,anIP);
|
||||
else
|
||||
line->Add(anIP);
|
||||
|
||||
isOK = Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
return isOK;
|
||||
@@ -2396,7 +2336,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = u1 - aU1bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u1 = aU1bFirst - aDelta;
|
||||
u1 = aU1bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2404,7 +2344,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aU1bLast - u1;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u1 = aU1bLast + aDelta;
|
||||
u1 = aU1bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2415,7 +2355,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = u2 - aU2bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u2 = aU2bFirst - aDelta;
|
||||
u2 = aU2bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2423,7 +2363,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aU2bLast - u2;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u2 = aU2bLast + aDelta;
|
||||
u2 = aU2bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2434,7 +2374,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = v1 - aV1bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v1 = aV1bFirst - aDelta;
|
||||
v1 = aV1bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2442,7 +2382,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aV1bLast - v1;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v1 = aV1bLast + aDelta;
|
||||
v1 = aV1bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2453,7 +2393,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = v2 - aV2bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v2 = aV2bFirst - aDelta;
|
||||
v2 = aV2bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2461,7 +2401,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aV2bLast - v2;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v2 = aV2bLast + aDelta;
|
||||
v2 = aV2bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2483,7 +2423,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = u1 - aU1bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u1 = aU1bFirst - aDelta;
|
||||
u1 = aU1bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2491,7 +2431,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aU1bLast - u1;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u1 = aU1bLast + aDelta;
|
||||
u1 = aU1bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2502,7 +2442,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = u2 - aU2bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u2 = aU2bFirst - aDelta;
|
||||
u2 = aU2bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2510,7 +2450,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aU2bLast - u2;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
u2 = aU2bLast + aDelta;
|
||||
u2 = aU2bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2521,7 +2461,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = v1 - aV1bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v1 = aV1bFirst - aDelta;
|
||||
v1 = aV1bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2529,7 +2469,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aV1bLast - v1;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v1 = aV1bLast + aDelta;
|
||||
v1 = aV1bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
@@ -2540,7 +2480,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = v2 - aV2bFirst;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v2 = aV2bFirst - aDelta;
|
||||
v2 = aV2bFirst;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
else
|
||||
@@ -2548,7 +2488,7 @@ PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
|
||||
aDelta = aV2bLast - v2;
|
||||
if((aTolMin < aDelta) && (aDelta < aTol))
|
||||
{
|
||||
v2 = aV2bLast + aDelta;
|
||||
v2 = aV2bLast;
|
||||
isNeedAdding = Standard_True;
|
||||
}
|
||||
}
|
||||
|
@@ -167,6 +167,11 @@ private:
|
||||
|
||||
Standard_EXPORT Standard_Boolean SeekPointOnBoundary (const Handle(Adaptor3d_HSurface)& theASurf1, const Handle(Adaptor3d_HSurface)& theASurf2, const Standard_Real theU1, const Standard_Real theV1, const Standard_Real theU2, const Standard_Real theV2, const Standard_Boolean isTheFirst);
|
||||
|
||||
// Method to handle single singular point. Sub-method in SeekPointOnBoundary.
|
||||
Standard_Boolean HandleSingleSingularPoint(const Handle(Adaptor3d_HSurface) &theASurf1,
|
||||
const Handle(Adaptor3d_HSurface) &theASurf2,
|
||||
const Standard_Real the3DTol,
|
||||
TColStd_Array1OfReal &thePnt);
|
||||
|
||||
Standard_Boolean done;
|
||||
Handle(IntSurf_LineOn2S) line;
|
||||
|
Reference in New Issue
Block a user