mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-14 13:30:48 +03:00
0026894: Intersection algorithm between two infinite cylinders is hanging
1. VRange of intersection curve has been limited. As result, too oblong intersection curve(s) will be never returned. 2. Now, purger algorithm is not called for lines obtained by Geom-Geom intersection method. 3. New statuses are entered in IntPatch_ImpImpIntersection class. It makes intersection algorithm more informative and flexible for using. 4. Method IntPatch_ImpImpIntersection::GetStatus() has been created. Tuning of test case bugs modalg_6/bug26894
This commit is contained in:
@@ -45,10 +45,25 @@ public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
|
||||
enum IntStatus
|
||||
{
|
||||
//! OK. Good intersection result.
|
||||
IntStatus_OK,
|
||||
|
||||
//! Intersection curve is too long (e.g. as in the bug #26894).
|
||||
//! We cannot provide precise computation of value and
|
||||
//! derivatives of this curve having used floating-point model
|
||||
//! determined by IEEE 754 standard. As result, OCCT algorithms
|
||||
//! cannot work with that curve correctly.
|
||||
IntStatus_InfiniteSectionCurve,
|
||||
|
||||
//! Algorithm cannot finish correctly.
|
||||
IntStatus_Fail
|
||||
};
|
||||
|
||||
Standard_EXPORT IntPatch_ImpImpIntersection();
|
||||
|
||||
//! Flag theIsReqToKeepRLine has been enterred only for
|
||||
//! Flag theIsReqToKeepRLine has been entered only for
|
||||
//! compatibility with TopOpeBRep package. It shall be deleted
|
||||
//! after deleting TopOpeBRep.
|
||||
//! When intersection result returns IntPatch_RLine and another
|
||||
@@ -56,7 +71,7 @@ public:
|
||||
//! will always keep both lines even if they are coincided.
|
||||
Standard_EXPORT IntPatch_ImpImpIntersection(const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Handle(Adaptor3d_HSurface)& S2, const Handle(Adaptor3d_TopolTool)& D2, const Standard_Real TolArc, const Standard_Real TolTang, const Standard_Boolean theIsReqToKeepRLine = Standard_False);
|
||||
|
||||
//! Flag theIsReqToKeepRLine has been enterred only for
|
||||
//! Flag theIsReqToKeepRLine has been entered only for
|
||||
//! compatibility with TopOpeBRep package. It shall be deleted
|
||||
//! after deleting TopOpeBRep.
|
||||
//! When intersection result returns IntPatch_RLine and another
|
||||
@@ -71,8 +86,11 @@ public:
|
||||
const Standard_Boolean theIsReqToKeepRLine =
|
||||
Standard_False);
|
||||
|
||||
//! Returns True if the calculus was succesfull.
|
||||
Standard_Boolean IsDone() const;
|
||||
//! Returns True if the calculus was successful.
|
||||
Standard_Boolean IsDone() const;
|
||||
|
||||
//! Returns status
|
||||
IntStatus GetStatus() const;
|
||||
|
||||
//! Returns true if the is no intersection.
|
||||
Standard_Boolean IsEmpty() const;
|
||||
@@ -116,7 +134,7 @@ private:
|
||||
|
||||
|
||||
|
||||
Standard_Boolean done;
|
||||
IntStatus myDone;
|
||||
Standard_Boolean empt;
|
||||
Standard_Boolean tgte;
|
||||
Standard_Boolean oppo;
|
||||
|
@@ -20,48 +20,54 @@
|
||||
|
||||
inline Standard_Boolean IntPatch_ImpImpIntersection::IsDone () const
|
||||
{
|
||||
return done;
|
||||
return (GetStatus() != IntStatus_Fail);
|
||||
}
|
||||
|
||||
inline IntPatch_ImpImpIntersection::IntStatus
|
||||
IntPatch_ImpImpIntersection::GetStatus() const
|
||||
{
|
||||
return myDone;
|
||||
}
|
||||
|
||||
inline Standard_Boolean IntPatch_ImpImpIntersection::IsEmpty () const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
return empt;
|
||||
}
|
||||
|
||||
inline Standard_Boolean IntPatch_ImpImpIntersection::TangentFaces () const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
return tgte;
|
||||
}
|
||||
|
||||
inline Standard_Boolean IntPatch_ImpImpIntersection::OppositeFaces () const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
if (!tgte) {Standard_DomainError::Raise();}
|
||||
return oppo;
|
||||
}
|
||||
|
||||
inline Standard_Integer IntPatch_ImpImpIntersection::NbPnts () const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
return spnt.Length();
|
||||
}
|
||||
|
||||
inline const IntPatch_Point& IntPatch_ImpImpIntersection::Point (const Standard_Integer Index) const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
return spnt(Index);
|
||||
}
|
||||
|
||||
inline Standard_Integer IntPatch_ImpImpIntersection::NbLines () const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
return slin.Length();
|
||||
}
|
||||
|
||||
inline const Handle(IntPatch_Line)& IntPatch_ImpImpIntersection::Line (const Standard_Integer Index) const
|
||||
{
|
||||
if (!done) {StdFail_NotDone::Raise();}
|
||||
if (!IsDone ()) { StdFail_NotDone::Raise(); }
|
||||
return slin(Index);
|
||||
}
|
||||
|
@@ -70,19 +70,19 @@ static void ProcessBounds(const Handle(IntPatch_ALine)&,
|
||||
const Standard_Real);
|
||||
|
||||
|
||||
static Standard_Boolean IntCyCy(const IntSurf_Quadric& theQuad1,
|
||||
const IntSurf_Quadric& theQuad2,
|
||||
const Standard_Real theTol3D,
|
||||
const Standard_Real theTol2D,
|
||||
const Bnd_Box2d& theUVSurf1,
|
||||
const Bnd_Box2d& theUVSurf2,
|
||||
const Standard_Boolean isTheReverse,
|
||||
Standard_Boolean& isTheEmpty,
|
||||
Standard_Boolean& isTheSameSurface,
|
||||
Standard_Boolean& isTheMultiplePoint,
|
||||
IntPatch_SequenceOfLine& theSlin,
|
||||
IntPatch_SequenceOfPoint& theSPnt);
|
||||
|
||||
static
|
||||
IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1,
|
||||
const IntSurf_Quadric& theQuad2,
|
||||
const Standard_Real theTol3D,
|
||||
const Standard_Real theTol2D,
|
||||
const Bnd_Box2d& theUVSurf1,
|
||||
const Bnd_Box2d& theUVSurf2,
|
||||
const Standard_Boolean isTheReverse,
|
||||
Standard_Boolean& isTheEmpty,
|
||||
Standard_Boolean& isTheSameSurface,
|
||||
Standard_Boolean& isTheMultiplePoint,
|
||||
IntPatch_SequenceOfLine& theSlin,
|
||||
IntPatch_SequenceOfPoint& theSPnt);
|
||||
|
||||
static Standard_Boolean IntCySp(const IntSurf_Quadric&,
|
||||
const IntSurf_Quadric&,
|
||||
|
@@ -26,7 +26,7 @@ static
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
IntPatch_ImpImpIntersection::IntPatch_ImpImpIntersection ():
|
||||
done(Standard_False)
|
||||
myDone(IntStatus_Fail)
|
||||
{
|
||||
}
|
||||
//=======================================================================
|
||||
@@ -56,7 +56,7 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
const Standard_Real TolTang,
|
||||
const Standard_Boolean theIsReqToKeepRLine)
|
||||
{
|
||||
done = Standard_False;
|
||||
myDone = IntStatus_Fail;
|
||||
spnt.Clear();
|
||||
slin.Clear();
|
||||
|
||||
@@ -151,7 +151,6 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
//
|
||||
case 22:
|
||||
{ // Cylinder/Cylinder
|
||||
Standard_Boolean isDONE = Standard_False;
|
||||
Bnd_Box2d aBox1, aBox2;
|
||||
|
||||
const Standard_Real aU1f = S1->FirstUParameter();
|
||||
@@ -192,16 +191,16 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
|
||||
if(isReversed)
|
||||
{
|
||||
isDONE = IntCyCy(quad2, quad1, TolTang, a2DTol, aBox2, aBox1,
|
||||
myDone = IntCyCy(quad2, quad1, TolTang, a2DTol, aBox2, aBox1,
|
||||
Standard_True, empt, SameSurf, multpoint, slin, spnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
isDONE = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2,
|
||||
myDone = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2,
|
||||
Standard_False, empt, SameSurf, multpoint, slin, spnt);
|
||||
}
|
||||
|
||||
if (!isDONE)
|
||||
if (myDone == IntPatch_ImpImpIntersection::IntStatus_Fail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -305,7 +304,9 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
}
|
||||
//
|
||||
if (bEmpty) {
|
||||
done = Standard_True;
|
||||
if (myDone == IntStatus_Fail)
|
||||
myDone = IntStatus_OK;
|
||||
|
||||
return;
|
||||
}
|
||||
//
|
||||
@@ -408,7 +409,7 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
}
|
||||
//
|
||||
oppo = quad1.Normale(Ptreference).Dot(quad2.Normale(Ptreference)) < 0.0;
|
||||
done = Standard_True;
|
||||
myDone = IntStatus_OK;
|
||||
return;
|
||||
}// if (SameSurf || (all1 && all2)) {
|
||||
|
||||
@@ -547,7 +548,7 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
}
|
||||
}
|
||||
}
|
||||
done = Standard_True;
|
||||
myDone = IntStatus_OK;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -2487,18 +2487,18 @@ void WorkWithBoundaries::BoundaryEstimation(const gp_Cylinder& theCy1,
|
||||
//function : IntCyCy
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean IntCyCy( const IntSurf_Quadric& theQuad1,
|
||||
const IntSurf_Quadric& theQuad2,
|
||||
const Standard_Real theTol3D,
|
||||
const Standard_Real theTol2D,
|
||||
const Bnd_Box2d& theUVSurf1,
|
||||
const Bnd_Box2d& theUVSurf2,
|
||||
const Standard_Boolean isTheReverse,
|
||||
Standard_Boolean& isTheEmpty,
|
||||
Standard_Boolean& isTheSameSurface,
|
||||
Standard_Boolean& isTheMultiplePoint,
|
||||
IntPatch_SequenceOfLine& theSlin,
|
||||
IntPatch_SequenceOfPoint& theSPnt)
|
||||
IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1,
|
||||
const IntSurf_Quadric& theQuad2,
|
||||
const Standard_Real theTol3D,
|
||||
const Standard_Real theTol2D,
|
||||
const Bnd_Box2d& theUVSurf1,
|
||||
const Bnd_Box2d& theUVSurf2,
|
||||
const Standard_Boolean isTheReverse,
|
||||
Standard_Boolean& isTheEmpty,
|
||||
Standard_Boolean& isTheSameSurface,
|
||||
Standard_Boolean& isTheMultiplePoint,
|
||||
IntPatch_SequenceOfLine& theSlin,
|
||||
IntPatch_SequenceOfPoint& theSPnt)
|
||||
{
|
||||
isTheEmpty = Standard_True;
|
||||
isTheSameSurface = Standard_False;
|
||||
@@ -2513,15 +2513,18 @@ Standard_Boolean IntCyCy( const IntSurf_Quadric& theQuad1,
|
||||
|
||||
if (!anInter.IsDone())
|
||||
{
|
||||
return Standard_False;
|
||||
return IntPatch_ImpImpIntersection::IntStatus_Fail;
|
||||
}
|
||||
|
||||
if(anInter.TypeInter() != IntAna_NoGeometricSolution)
|
||||
{
|
||||
return CyCyAnalyticalIntersect( theQuad1, theQuad2, anInter,
|
||||
theTol3D, isTheReverse, isTheEmpty,
|
||||
isTheSameSurface, isTheMultiplePoint,
|
||||
theSlin, theSPnt);
|
||||
if (CyCyAnalyticalIntersect(theQuad1, theQuad2, anInter,
|
||||
theTol3D, isTheReverse, isTheEmpty,
|
||||
isTheSameSurface, isTheMultiplePoint,
|
||||
theSlin, theSPnt))
|
||||
{
|
||||
return IntPatch_ImpImpIntersection::IntStatus_OK;
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Real aUSurf1f = 0.0, //const
|
||||
@@ -2557,7 +2560,20 @@ Standard_Boolean IntCyCy( const IntSurf_Quadric& theQuad1,
|
||||
Bnd_Range aRangeS1, aRangeS2;
|
||||
aBoundWork.BoundaryEstimation(aCyl1, aCyl2, aRangeS1, aRangeS2);
|
||||
if (aRangeS1.IsVoid() || aRangeS2.IsVoid())
|
||||
return Standard_True;
|
||||
return IntPatch_ImpImpIntersection::IntStatus_OK;
|
||||
|
||||
{
|
||||
//Quotation of the message from issue #26894 (author MSV):
|
||||
//"We should return fail status from intersector if the result should be an
|
||||
//infinite curve of non-analytical type... I propose to define the limit for the
|
||||
//extent as the radius divided by 1e+2 and multiplied by 1e+7.
|
||||
//Thus, taking into account the number of valuable digits (15), we provide reliable
|
||||
//computations with an error not exceeding R/100."
|
||||
const Standard_Real aF = 1.0e+5;
|
||||
const Standard_Real aMaxV1Range = aF*aCyl1.Radius(), aMaxV2Range = aF*aCyl2.Radius();
|
||||
if ((aRangeS1.Delta() > aMaxV1Range) || (aRangeS2.Delta() > aMaxV2Range))
|
||||
return IntPatch_ImpImpIntersection::IntStatus_InfiniteSectionCurve;
|
||||
}
|
||||
|
||||
//Boundaries
|
||||
const Standard_Integer aNbOfBoundaries = 2;
|
||||
@@ -2565,7 +2581,7 @@ Standard_Boolean IntCyCy( const IntSurf_Quadric& theQuad1,
|
||||
Standard_Real aU1l[aNbOfBoundaries] = {Precision::Infinite(), Precision::Infinite()};
|
||||
|
||||
if(!aBoundWork.BoundariesComputing(aU1f, aU1l))
|
||||
return Standard_True;
|
||||
return IntPatch_ImpImpIntersection::IntStatus_OK;
|
||||
|
||||
for(Standard_Integer i = 0; i < aNbOfBoundaries; i++)
|
||||
{
|
||||
@@ -3317,7 +3333,7 @@ Standard_Boolean IntCyCy( const IntSurf_Quadric& theQuad1,
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
return IntPatch_ImpImpIntersection::IntStatus_OK;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -954,6 +954,9 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& theS1,
|
||||
if(aWL.IsNull())
|
||||
continue;
|
||||
|
||||
if (!aWL->IsPurgingAllowed())
|
||||
continue;
|
||||
|
||||
Handle(IntPatch_WLine) aRW =
|
||||
IntPatch_WLineTool::ComputePurgedWLine(aWL, theS1, theS2, theD1, theD2, RestrictLine);
|
||||
|
||||
@@ -1329,10 +1332,9 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the
|
||||
{
|
||||
IntPatch_ImpImpIntersection interii(theS1,theD1,theS2,theD2,
|
||||
myTolArc,myTolTang, theIsReqToKeepRLine);
|
||||
const Standard_Boolean anIS = interii.IsDone();
|
||||
if (anIS)
|
||||
if (interii.IsDone())
|
||||
{
|
||||
done = anIS;
|
||||
done = (interii.GetStatus() == IntPatch_ImpImpIntersection::IntStatus_OK);
|
||||
empt = interii.IsEmpty();
|
||||
if (!empt)
|
||||
{
|
||||
@@ -1650,6 +1652,9 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
|
||||
if(aWL.IsNull())
|
||||
continue;
|
||||
|
||||
if (!aWL->IsPurgingAllowed())
|
||||
continue;
|
||||
|
||||
Handle(IntPatch_WLine) aRW =
|
||||
IntPatch_WLineTool::ComputePurgedWLine(aWL, S1, S2, D1, D2, Standard_True);
|
||||
|
||||
|
Reference in New Issue
Block a user