1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0028222: Intersection of two cylinders fails

1. The reason of exception has been eliminated.

2. Algorithm in IntPatch_WLineTool::JoinWLines(...) method has been modified in order to forbid join curves in the point where more than two intersection lines meet. More over, joining is forbidden if local curvature in the connection point is too big (see function CheckArgumentsToJoin(...) in the file IntPatch_WLineTool.cxx).

3. Interface of IntPatch_WLineTool::JoinWLines(...) method has been modified in order to reduce number of arguments.

4. Small corrections in IsSeamOrBound(...) static function has been made. Namely, check has been added if two boundaries are in the same period region but are too far each to other (see IntPatch_WLineTool.cxx, IsSeamOrBound(...) function, line # 532).

5. "Reversed" flag has been made local. Now, it is pure local characteristic: the algorithm decides itself, shall we reverse the argument order. This correction makes the algorithm more commutative (see issue #25404). However, IntPatch_WLineTool::JoinWLines(...) method can return non-commutative result.

6. Algorithm of searching small intersection curves has been improved.

7. New methods have been added in Bnd_Range class.

Some test cases have been adjusted according to their new behavior.

1. tests\bugs\modalg_6\bug26310_3
   tests\bugs\modalg_6\bug26310_4
   tests\bugs\moddata_2\bug235
   tests\perf\modalg\bug26310_1
   tests\bugs\modalg_5\bug24915

Logic of these cases has been changed. Mover over, additional check has been added in "bug26310_1" test case. Therefore, its performance will be slower than on the current MASTER.

2. tests\bugs\modalg_5\bug25292*

Scripts have been rewritten in order to make it more readable. Logic of these cases has not been changed.
This commit is contained in:
nbv
2016-12-15 17:22:00 +03:00
committed by bugmaster
parent 0609d8ee53
commit 261b7d9e8a
36 changed files with 1739 additions and 1426 deletions

View File

@@ -35,3 +35,143 @@ void Bnd_Range::Common(const Bnd_Range& theOther)
myFirst = Max(myFirst, theOther.myFirst);
myLast = Min(myLast, theOther.myLast);
}
//=======================================================================
//function : Union
//purpose :
//=======================================================================
Standard_Boolean Bnd_Range::Union(const Bnd_Range& theOther)
{
if (IsVoid() || theOther.IsVoid())
return Standard_False;
if (myLast < theOther.myFirst)
return Standard_False;
if (myFirst > theOther.myLast)
return Standard_False;
myFirst = Min(myFirst, theOther.myFirst);
myLast = Max(myLast, theOther.myLast);
return Standard_True;
}
//=======================================================================
//function : IsIntersected
//purpose :
//=======================================================================
Standard_Integer Bnd_Range::IsIntersected(const Standard_Real theVal,
const Standard_Real thePeriod) const
{
if (IsVoid())
return Standard_False;
const Standard_Real aPeriod = Abs(thePeriod);
const Standard_Real aDF = myFirst - theVal,
aDL = myLast - theVal;
if (aPeriod <= RealSmall())
{
const Standard_Real aDelta = aDF*aDL;
if (IsEqual(aDelta, 0.0))
return 2;
if (aDelta > 0.0)
return 0;
return 1;
}
//If <this> intersects theVal then there exists an integer
//number N such as
// (myFirst <= theVal+aPeriod*N <= myLast) <=>
// ((myFirst-theVal)/aPeriod <= N <= (myLast-theVal)/aPeriod).
//I.e. the interval [aDF/aPeriod, aDL/aPeriod] must contain at least one
//integer number.
//In this case, Floor(aDF/aPeriod) and Floor(aDL/aPeriod)
//return different values or aDF/aPeriod (aDL/aPeriod)
//is strictly integer number.
//Examples:
// 1. (aDF/aPeriod==2.8, aDL/aPeriod==3.5 =>
// Floor(aDF/aPeriod) == 2, Floor(aDL/aPeriod) == 3.
// 2. aDF/aPeriod==2.0, aDL/aPeriod==2.6 =>
// Floor(aDF/aPeriod) == Floor(aDL/aPeriod) == 2.
const Standard_Real aVal1 = aDF / aPeriod,
aVal2 = aDL / aPeriod;
const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
if (aPar1 != aPar2)
{//Interval (myFirst, myLast] intersects seam-edge
if (IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
{//aVal2 is an integer number => myLast lies ON the "seam-edge"
return 2;
}
return 1;
}
//Here, aPar1 == aPar2.
if (IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
{//aVal1 is an integer number => myFirst lies ON the "seam-edge"
return 2;
}
#if 0
// This check is excess because always myFirst <= myLast.
// So, this condition is never satisfied.
if (IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
{//aVal2 is an integer number => myLast lies ON the "seam-edge"
return 2;
}
#endif
return 0;
}
//=======================================================================
//function : Split
//purpose :
//=======================================================================
void Bnd_Range::Split(const Standard_Real theVal,
NCollection_List<Bnd_Range>& theList,
const Standard_Real thePeriod) const
{
const Standard_Real aPeriod = Abs(thePeriod);
if (IsIntersected(theVal, aPeriod) != 1)
{
theList.Append(*this);
return;
}
const Standard_Boolean isPeriodic = (aPeriod > 0.0);
if (!isPeriodic)
{
theList.Append(Bnd_Range(myFirst, theVal));
theList.Append(Bnd_Range(theVal, myLast));
return;
}
Standard_Real aValPrev = theVal + aPeriod*Ceiling((myFirst - theVal) / aPeriod);
//Now, (myFirst <= aValPrev < myFirst+aPeriod).
if (aValPrev > myFirst)
{
theList.Append(Bnd_Range(myFirst, aValPrev));
}
for (Standard_Real aVal = aValPrev+aPeriod; aVal <= myLast; aVal += aPeriod)
{
theList.Append(Bnd_Range(aValPrev, aVal));
aValPrev = aVal;
}
if (aValPrev < myLast)
{
theList.Append(Bnd_Range(aValPrev, myLast));
}
}

View File

@@ -19,6 +19,8 @@
#include <Standard_Real.hxx>
#include <Standard_ConstructionError.hxx>
#include <NCollection_List.hxx>
//! This class describes a range in 1D space restricted
//! by two real values.
//! A range can be void indicating there is no point included in the range.
@@ -42,6 +44,39 @@ public:
//! Replaces <this> with common-part of <this> and theOther
Standard_EXPORT void Common(const Bnd_Range& theOther);
//! Joins *this and theOther to one interval.
//! Replaces *this to the result.
//! Returns false if the operation cannot be done (e.g.
//! input arguments are empty or separated).
Standard_EXPORT Standard_Boolean Union(const Bnd_Range& theOther);
//! Splits <this> to several sub-ranges by theVal value
//! (e.g. range [3, 15] will be split by theVal==5 to the two
//! ranges: [3, 5] and [5, 15]). New ranges will be pushed to
//! theList (theList must be initialized correctly before
//! calling this method).
//! If thePeriod != 0.0 then at least one boundary of
//! new ranges (if <*this> intersects theVal+k*thePeriod) will be equal to
//! theVal+thePeriod*k, where k is an integer number (k = 0, +/-1, +/-2, ...).
//! (let thePeriod in above example be 4 ==> we will obtain
//! four ranges: [3, 5], [5, 9], [9, 13] and [13, 15].
Standard_EXPORT void Split(const Standard_Real theVal,
NCollection_List<Bnd_Range>& theList,
const Standard_Real thePeriod = 0.0) const;
//! Checks if <this> intersects values like
//! theVal+k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...).
//! Returns:
//! 0 - if <this> does not intersect the theVal+k*thePeriod.
//! 1 - if <this> intersects theVal+k*thePeriod.
//! 2 - if myFirst or/and myLast are equal to theVal+k*thePeriod.
//!
//! ATTENTION!!!
//! If (myFirst == myLast) then this function will return only either 0 or 2.
Standard_EXPORT Standard_Integer
IsIntersected(const Standard_Real theVal,
const Standard_Real thePeriod = 0.0) const;
//! Extends <this> to include theParameter
void Add(const Standard_Real theParameter)
@@ -82,6 +117,21 @@ public:
return Standard_True;
}
//! Obtain first and last boundary of <this>.
//! If <this> is VOID the method returns false.
Standard_Boolean GetBounds(Standard_Real& theFirstPar,
Standard_Real& theLastPar) const
{
if(IsVoid())
{
return Standard_False;
}
theFirstPar = myFirst;
theLastPar = myLast;
return Standard_True;
}
//! Returns range value (MAX-MIN). Returns negative value for VOID range.
Standard_Real Delta() const
{
@@ -113,6 +163,25 @@ public:
myLast += theDelta;
}
//! Returns the copy of <*this> shifted by theVal
Bnd_Range Shifted(const Standard_Real theVal) const
{
return Bnd_Range(myFirst + theVal, myLast + theVal);
}
//! Shifts <*this> by theVal
void Shift(const Standard_Real theVal)
{
myFirst += theVal;
myLast += theVal;
}
//! Returns TRUE if theOther is equal to <*this>
Standard_Boolean operator==(const Bnd_Range& theOther) const
{
return ((myFirst == theOther.myFirst) && (myLast == theOther.myLast));
}
private:
//! Start of range
Standard_Real myFirst;