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:
@@ -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));
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user