From 261b7d9e8a7e2f58c3e1316fa98bd88c274d88f1 Mon Sep 17 00:00:00 2001 From: nbv Date: Thu, 15 Dec 2016 17:22:00 +0300 Subject: [PATCH] 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. --- src/Bnd/Bnd_Range.cxx | 140 ++ src/Bnd/Bnd_Range.hxx | 69 + src/ElCLib/ElCLib.cxx | 16 + .../IntPatch_ImpImpIntersection_1.gxx | 1 - .../IntPatch_ImpImpIntersection_2.gxx | 26 +- .../IntPatch_ImpImpIntersection_4.gxx | 1190 ++++++++++------- src/IntPatch/IntPatch_Intersection.cxx | 14 +- src/IntPatch/IntPatch_WLineTool.cxx | 616 ++++----- src/IntPatch/IntPatch_WLineTool.hxx | 23 +- tests/bugs/modalg_5/bug24915 | 15 +- tests/bugs/modalg_5/bug25292_11 | 29 +- tests/bugs/modalg_5/bug25292_12 | 29 +- tests/bugs/modalg_5/bug25292_15 | 101 +- tests/bugs/modalg_5/bug25292_16 | 100 +- tests/bugs/modalg_5/bug25292_21 | 30 +- tests/bugs/modalg_5/bug25292_22 | 30 +- tests/bugs/modalg_5/bug25292_25 | 101 +- tests/bugs/modalg_5/bug25292_26 | 100 +- tests/bugs/modalg_5/bug25292_31 | 28 +- tests/bugs/modalg_5/bug25292_32 | 28 +- tests/bugs/modalg_5/bug25292_33 | 42 +- tests/bugs/modalg_5/bug25292_34 | 42 +- tests/bugs/modalg_5/bug25292_35 | 21 +- tests/bugs/modalg_5/bug25292_36 | 16 +- tests/bugs/modalg_6/bug26310_3 | 23 +- tests/bugs/modalg_6/bug26310_4 | 37 +- tests/bugs/modalg_6/bug27310_1 | 18 +- tests/bugs/modalg_6/bug27310_2 | 20 +- tests/bugs/modalg_6/bug27856_2 | 16 +- tests/bugs/modalg_6/bug28009_2 | 2 +- tests/bugs/modalg_6/bug28222_1 | 45 + tests/bugs/modalg_6/bug28222_2 | 45 + tests/bugs/modalg_6/bug28222_3 | 46 + tests/bugs/modalg_6/bug28706 | 32 + tests/bugs/moddata_2/bug235 | 5 +- tests/perf/modalg/bug26310_1 | 35 +- 36 files changed, 1722 insertions(+), 1409 deletions(-) create mode 100644 tests/bugs/modalg_6/bug28222_1 create mode 100644 tests/bugs/modalg_6/bug28222_2 create mode 100644 tests/bugs/modalg_6/bug28222_3 create mode 100644 tests/bugs/modalg_6/bug28706 diff --git a/src/Bnd/Bnd_Range.cxx b/src/Bnd/Bnd_Range.cxx index d79b211dea..63d0961343 100644 --- a/src/Bnd/Bnd_Range.cxx +++ b/src/Bnd/Bnd_Range.cxx @@ -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 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(Floor(aVal1)); + const Standard_Integer aPar2 = static_cast(Floor(aVal2)); + if (aPar1 != aPar2) + {//Interval (myFirst, myLast] intersects seam-edge + if (IsEqual(aVal2, static_cast(aPar2))) + {//aVal2 is an integer number => myLast lies ON the "seam-edge" + return 2; + } + + return 1; + } + + //Here, aPar1 == aPar2. + + if (IsEqual(aVal1, static_cast(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(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& 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)); + } +} \ No newline at end of file diff --git a/src/Bnd/Bnd_Range.hxx b/src/Bnd/Bnd_Range.hxx index 2afd47f8b2..01021b159d 100644 --- a/src/Bnd/Bnd_Range.hxx +++ b/src/Bnd/Bnd_Range.hxx @@ -19,6 +19,8 @@ #include #include +#include + //! 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 with common-part of 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 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& theList, + const Standard_Real thePeriod = 0.0) const; + + //! Checks if intersects values like + //! theVal+k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...). + //! Returns: + //! 0 - if does not intersect the theVal+k*thePeriod. + //! 1 - if 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 to include theParameter void Add(const Standard_Real theParameter) @@ -82,6 +117,21 @@ public: return Standard_True; } + //! Obtain first and last boundary of . + //! If 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; diff --git a/src/ElCLib/ElCLib.cxx b/src/ElCLib/ElCLib.cxx index 6bfb2de05a..8801ef8a3b 100644 --- a/src/ElCLib/ElCLib.cxx +++ b/src/ElCLib/ElCLib.cxx @@ -49,6 +49,22 @@ static Standard_Real PIPI = M_PI + M_PI; //======================================================================= //function : InPeriod //purpose : Value theULast is never returned. +// Example of some case (checked on WIN64 platform) +// with some surface having period 2*PI = 6.2831853071795862. +// Let theUFirst be equal to 6.1645624650899675. Then, +// theULast must be equal to +// 6.1645624650899675+6.2831853071795862=12.4477477722695537. +// +// However, real result is 12.447747772269555. +// Therefore, new period value to adjust will be equal to +// 12.447747772269555-6.1645624650899675=6.2831853071795871. +// +// As we can see, (6.2831853071795871 != 6.2831853071795862). +// +// According to above said, this method should be used carefully. +// In order to increase reliability of this method, input arguments +// needs to be replaced with following: +// (theU, theUFirst, thePeriod). theULast parameter is excess. //======================================================================= Standard_Real ElCLib::InPeriod(const Standard_Real theU, const Standard_Real theUFirst, diff --git a/src/IntPatch/IntPatch_ImpImpIntersection_1.gxx b/src/IntPatch/IntPatch_ImpImpIntersection_1.gxx index 75d377de48..9ab3fd04c2 100644 --- a/src/IntPatch/IntPatch_ImpImpIntersection_1.gxx +++ b/src/IntPatch/IntPatch_ImpImpIntersection_1.gxx @@ -77,7 +77,6 @@ static 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, diff --git a/src/IntPatch/IntPatch_ImpImpIntersection_2.gxx b/src/IntPatch/IntPatch_ImpImpIntersection_2.gxx index 2567933247..30d0aebed3 100644 --- a/src/IntPatch/IntPatch_ImpImpIntersection_2.gxx +++ b/src/IntPatch/IntPatch_ImpImpIntersection_2.gxx @@ -172,33 +172,13 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1, aBox2.Add(gp_Pnt2d(aU2l, S2->LastVParameter())); // Resolution is too big if the cylinder radius is - // too small. Therefore, we shall bounde its value above. + // too small. Therefore, we shall bind its value above. // Here, we use simple constant. const Standard_Real a2DTol = Min(1.0e-4, Min( S1->UResolution(TolTang), S2->UResolution(TolTang))); - //The bigger range the bigger nunber of points in Walking-line (WLine) - //we will be able to add and, consequently, we will obtain more - //precise intersection line. - //Every point of WLine is determined as function from U1-parameter, - //where U1 is U-parameter on 1st quadric. - //Therefore, we should use quadric with bigger range as 1st parameter - //in IntCyCy() function. - //On the other hand, there is no point in reversing in case of - //analytical intersection (when result is line, ellipse, point...). - //This result is independent of the arguments order. - Standard_Boolean isReversed = ((aU2l - aU2f) < (aU1l - aU1f)); - - if(isReversed) - { - myDone = IntCyCy(quad2, quad1, TolTang, a2DTol, aBox2, aBox1, - Standard_True, empt, SameSurf, multpoint, slin, spnt); - } - else - { - myDone = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2, - Standard_False, empt, SameSurf, multpoint, slin, spnt); - } + myDone = IntCyCy(quad1, quad2, TolTang, a2DTol, aBox1, aBox2, + empt, SameSurf, multpoint, slin, spnt); if (myDone == IntPatch_ImpImpIntersection::IntStatus_Fail) { diff --git a/src/IntPatch/IntPatch_ImpImpIntersection_4.gxx b/src/IntPatch/IntPatch_ImpImpIntersection_4.gxx index 94bfab8b75..1a6cb9b87a 100644 --- a/src/IntPatch/IntPatch_ImpImpIntersection_4.gxx +++ b/src/IntPatch/IntPatch_ImpImpIntersection_4.gxx @@ -16,11 +16,10 @@ #include #include -#include #include -#include -#include #include +#include +#include //If Abs(a) <= aNulValue then it is considered that a = 0. static const Standard_Real aNulValue = 1.0e-11; @@ -372,7 +371,7 @@ public: myV2 = RealLast(); } - //Equal to 0 for 1st surface non-zerro for 2nd one. + //Equal to 0 for 1st surface non-zero for 2nd one. Standard_Integer mySurfID; Standard_Real myU1; @@ -413,8 +412,55 @@ public: { }; + // Returns parameters of system solved while finding + // intersection line + const ComputationMethods::stCoeffsValue &SICoeffs() const + { + return myCoeffs; + } + + // Returns quadric correspond to the index theIdx. + const IntSurf_Quadric& GetQSurface(const Standard_Integer theIdx) const + { + if (theIdx <= 1) + return myQuad1; + + return myQuad2; + } + + // Returns TRUE in case of reverting surfaces + Standard_Boolean IsReversed() const + { + return myIsReverse; + } + + // Returns 2D-tolerance + Standard_Real Get2dTolerance() const + { + return myTol2D; + } + + // Returns 3D-tolerance + Standard_Real Get3dTolerance() const + { + return myTol3D; + } + + // Returns UV-bounds of 1st surface + const Bnd_Box2d& UVS1() const + { + return myUVSurf1; + } + + // Returns UV-bounds of 2nd surface + const Bnd_Box2d& UVS2() const + { + return myUVSurf2; + } + void AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL, const Standard_Real theU1, + const Standard_Real theU1Min, const Standard_Real theU2, const Standard_Real theV1, const Standard_Real theV1Prev, @@ -425,8 +471,9 @@ public: Standard_Boolean& isTheFound1, Standard_Boolean& isTheFound2) const; - Standard_Boolean BoundariesComputing(Standard_Real theU1f[], - Standard_Real theU1l[]) const; + static Standard_Boolean BoundariesComputing(const ComputationMethods::stCoeffsValue &theCoeffs, + const Standard_Real thePeriod, + Bnd_Range theURange[]); void BoundaryEstimation(const gp_Cylinder& theCy1, const gp_Cylinder& theCy2, @@ -898,7 +945,6 @@ Standard_Boolean CyCyAnalyticalIntersect( const IntSurf_Quadric& Quad1, const IntSurf_Quadric& Quad2, const IntAna_QuadQuadGeo& theInter, const Standard_Real Tol, - const Standard_Boolean isTheReverse, Standard_Boolean& Empty, Standard_Boolean& Same, Standard_Boolean& Multpoint, @@ -943,17 +989,8 @@ Standard_Boolean CyCyAnalyticalIntersect( const IntSurf_Quadric& Quad1, ptsol.SetValue(psol,Tol,Standard_True); Standard_Real U1,V1,U2,V2; - - if(isTheReverse) - { - Quad2.Parameters(psol, U1, V1); - Quad1.Parameters(psol, U2, V2); - } - else - { - Quad1.Parameters(psol, U1, V1); - Quad2.Parameters(psol, U2, V2); - } + Quad1.Parameters(psol, U1, V1); + Quad2.Parameters(psol, U2, V2); ptsol.SetParameters(U1,V1,U2,V2); spnt.Append(ptsol); @@ -1100,30 +1137,12 @@ Standard_Boolean CyCyAnalyticalIntersect( const IntSurf_Quadric& Quad1, pmult2.SetMultiple(Standard_True); Standard_Real oU1,oV1,oU2,oV2; - - if(isTheReverse) - { - Quad2.Parameters(pttang1,oU1,oV1); - Quad1.Parameters(pttang1,oU2,oV2); - } - else - { - Quad1.Parameters(pttang1,oU1,oV1); - Quad2.Parameters(pttang1,oU2,oV2); - } + Quad1.Parameters(pttang1, oU1, oV1); + Quad2.Parameters(pttang1, oU2, oV2); pmult1.SetParameters(oU1,oV1,oU2,oV2); - - if(isTheReverse) - { - Quad2.Parameters(pttang2,oU1,oV1); - Quad1.Parameters(pttang2,oU2,oV2); - } - else - { - Quad1.Parameters(pttang2,oU1,oV1); - Quad2.Parameters(pttang2,oU2,oV2); - } + Quad1.Parameters(pttang2,oU1,oV1); + Quad2.Parameters(pttang2,oU2,oV2); pmult2.SetParameters(oU1,oV1,oU2,oV2); @@ -1161,17 +1180,8 @@ Standard_Boolean CyCyAnalyticalIntersect( const IntSurf_Quadric& Quad1, aIP.SetValue(aP,Tol,Standard_False); aIP.SetMultiple(Standard_False); // - - if(isTheReverse) - { - Quad2.Parameters(aP, aU1, aV1); - Quad1.Parameters(aP, aU2, aV2); - } - else - { - Quad1.Parameters(aP, aU1, aV1); - Quad2.Parameters(aP, aU2, aV2); - } + Quad1.Parameters(aP, aU1, aV1); + Quad2.Parameters(aP, aU2, aV2); aIP.SetParameters(aU1, aV1, aU2, aV2); // @@ -1245,16 +1255,8 @@ Standard_Boolean CyCyAnalyticalIntersect( const IntSurf_Quadric& Quad1, aIP.SetMultiple(Standard_False); // - if(isTheReverse) - { - Quad2.Parameters(aP, aU1, aV1); - Quad1.Parameters(aP, aU2, aV2); - } - else - { - Quad1.Parameters(aP, aU1, aV1); - Quad2.Parameters(aP, aU2, aV2); - } + Quad1.Parameters(aP, aU1, aV1); + Quad2.Parameters(aP, aU2, aV2); aIP.SetParameters(aU1, aV1, aU2, aV2); // @@ -1418,7 +1420,7 @@ Standard_Boolean ComputationMethods::CylCylMonotonicity(const Standard_Real theU //======================================================================= //function : CylCylComputeParameters //purpose : Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0, -// esimates the tolerance of U2-computing (estimation result is +// estimates the tolerance of U2-computing (estimation result is // assigned to *theDelta value). //======================================================================= Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par, @@ -1439,14 +1441,14 @@ Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real Standard_Real anArg = cos(theU1par - theCoeffs.mFI1); anArg = theCoeffs.mB*anArg + theCoeffs.mC; - if(anArg > aTol) + if(anArg >= aTol) { if(theDelta) *theDelta = 0.0; anArg = 1.0; } - else if(anArg < -aTol) + else if(anArg <= -aTol) { if(theDelta) *theDelta = 0.0; @@ -1494,6 +1496,10 @@ Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real return Standard_True; } +//======================================================================= +//function : CylCylComputeParameters +//purpose : Computes V1 and V2 (V-parameters of the 1st and 2nd cylinder respectively). +//======================================================================= Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1, const Standard_Real theU2, const stCoeffsValue& theCoeffs, @@ -1513,7 +1519,11 @@ Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real return Standard_True; } - +//======================================================================= +//function : CylCylComputeParameters +//purpose : Computes U2 (U-parameter of the 2nd cylinder), +// V1 and V2 (V-parameters of the 1st and 2nd cylinder respectively). +//======================================================================= Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par, const Standard_Integer theWLIndex, const stCoeffsValue& theCoeffs, @@ -1728,31 +1738,42 @@ Standard_Boolean InscribePoint( const Standard_Real theUfTarget, //======================================================================= //function : InscribeInterval -//purpose : Adjusts theUfGiven and (after that) adjusts theUlGiven to the result +//purpose : Shifts theRange in order to make at least one of its +// boundary in the range [theUfTarget, theUlTarget] //======================================================================= static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget, - const Standard_Real theUlTarget, - Standard_Real& theUfGiven, - Standard_Real& theUlGiven, - const Standard_Real theTol2D, - const Standard_Real thePeriod) + const Standard_Real theUlTarget, + Bnd_Range &theRange, + const Standard_Real theTol2D, + const Standard_Real thePeriod) { - Standard_Real anUpar = theUfGiven; - const Standard_Real aDelta = theUlGiven - theUfGiven; - if(InscribePoint(theUfTarget, theUlTarget, anUpar, - theTol2D, thePeriod, Standard_False)) + Standard_Real anUpar = 0.0; + if (!theRange.GetMin(anUpar)) + { + return Standard_False; + } + + const Standard_Real aDelta = theRange.Delta(); + if(InscribePoint(theUfTarget, theUlTarget, anUpar, + theTol2D, thePeriod, (Abs(theUlTarget-anUpar) < theTol2D))) { - theUfGiven = anUpar; - theUlGiven = theUfGiven + aDelta; + theRange.SetVoid(); + theRange.Add(anUpar); + theRange.Add(anUpar + aDelta); } else { - anUpar = theUlGiven; + if (!theRange.GetMAX(anUpar)) + { + return Standard_False; + } + if(InscribePoint(theUfTarget, theUlTarget, anUpar, - theTol2D, thePeriod, Standard_False)) + theTol2D, thePeriod, (Abs(theUfTarget-anUpar) < theTol2D))) { - theUlGiven = anUpar; - theUfGiven = theUlGiven - aDelta; + theRange.SetVoid(); + theRange.Add(anUpar); + theRange.Add(anUpar - aDelta); } else { @@ -1811,6 +1832,11 @@ static Standard_Boolean ExcludeNearElements(Standard_Real theArr[], //======================================================================= //function : AddPointIntoWL //purpose : Surf1 is a surface, whose U-par is variable. +// If theFlBefore == TRUE then we enable the U1-parameter +// of the added point to be less than U1-parameter of +// previously added point (in general U1-parameter is +// always increased; therefore, this situation is abnormal). +// If theOnlyCheck==TRUE then no point will be added to theLine. //======================================================================= static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, const IntSurf_Quadric& theQuad2, @@ -1832,8 +1858,8 @@ static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, const Standard_Integer theWLIndex, const Standard_Real theTol3D, const Standard_Real theTol2D, - const Standard_Boolean theFlForce, - const Standard_Boolean theFlBefore = Standard_False) + const Standard_Boolean theFlBefore = Standard_False, + const Standard_Boolean theOnlyCheck = Standard_False) { //Check if the point is in the domain or can be inscribed in the domain after adjusting. @@ -1841,10 +1867,39 @@ static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y())); Standard_Real aU1par = thePntOnSurf1.X(); + + // aU1par always increases. Therefore, we must reduce its + // value in order to continue creation of WLine. if(!InscribePoint(theUfSurf1, theUlSurf1, aU1par, theTol2D, - thePeriodOfSurf1, theFlForce)) + thePeriodOfSurf1, aU1par > 0.5*(theUfSurf1+theUlSurf1))) return Standard_False; + if ((theLine->NbPoints() > 0) && + ((theUlSurf1 - theUfSurf1) >= thePeriodOfSurf1) && + (((aU1par + thePeriodOfSurf1 - theUlSurf1) <= theTol2D) || + ((aU1par - thePeriodOfSurf1 - theUfSurf1) >= theTol2D))) + { + // aU1par can be adjusted to both theUlSurf1 and theUfSurf1 + // with equal possibilities. This code fragment allows choosing + // correct parameter from these two variants. + + Standard_Real aU1 = 0.0, aV1 = 0.0; + if (isTheReverse) + { + theLine->Value(theLine->NbPoints()).ParametersOnS2(aU1, aV1); + } + else + { + theLine->Value(theLine->NbPoints()).ParametersOnS1(aU1, aV1); + } + + const Standard_Real aDelta = aU1 - aU1par; + if (2.0*Abs(aDelta) > thePeriodOfSurf1) + { + aU1par += Sign(thePeriodOfSurf1, aDelta); + } + } + Standard_Real aU2par = thePntOnSurf2.X(); if(!InscribePoint(theUfSurf2, theUlSurf2, aU2par, theTol2D, thePeriodOfSurf1, Standard_False)) @@ -1887,7 +1942,7 @@ static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, if(!theFlBefore && (aU1par <= aUl)) { //Parameter value must be increased if theFlBefore == FALSE. - + aU1par += thePeriodOfSurf1; //The condition is as same as in @@ -1902,6 +1957,9 @@ static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, } } + if (theOnlyCheck) + return Standard_True; + //theTol2D is minimal step along parameter changed. //Therefore, if we apply this minimal step two //neighbour points will be always "same". Consequently, @@ -1913,6 +1971,9 @@ static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, } } + if (theOnlyCheck) + return Standard_True; + theLine->Add(aPnt); if(!isThePrecise) @@ -1959,6 +2020,7 @@ static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1, //======================================================================= void WorkWithBoundaries::AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL, const Standard_Real theU1, + const Standard_Real theU1Min, const Standard_Real theU2, const Standard_Real theV1, const Standard_Real theV1Prev, @@ -1995,7 +2057,6 @@ void WorkWithBoundaries::AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL, for(Standard_Integer anIDBound = 0; anIDBound < 2; anIDBound++) { - const Standard_Integer anIndex = anIDSurf+anIDBound; aUVPoint[anIndex].mySurfID = anIDSurf; @@ -2015,7 +2076,10 @@ void WorkWithBoundaries::AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL, theU2, theU1, aUVPoint[anIndex].myU1); - if(!aRes || aUVPoint[anIndex].myU1 >= theU1) + // aUVPoint[anIndex].myU1 is considered to be nearer to theU1 than + // to theU1+/-Period + if (!aRes || (aUVPoint[anIndex].myU1 >= theU1) || + (aUVPoint[anIndex].myU1 < theU1Min)) { //Intersection point is not found or out of the domain aUVPoint[anIndex].myU1 = RealLast(); @@ -2218,8 +2282,10 @@ static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1, //purpose : Computes true domain of future intersection curve (allows // avoiding excess iterations) //======================================================================= -Standard_Boolean WorkWithBoundaries::BoundariesComputing(Standard_Real theU1f[], - Standard_Real theU1l[]) const +Standard_Boolean WorkWithBoundaries:: + BoundariesComputing(const ComputationMethods::stCoeffsValue &theCoeffs, + const Standard_Real thePeriod, + Bnd_Range theURange[]) { //All comments to this method is related to the comment //to ComputationMethods class @@ -2229,59 +2295,58 @@ Standard_Boolean WorkWithBoundaries::BoundariesComputing(Standard_Real theU1f[], //Evidently, // -1 <= B*cos(U1-FI1)+C <= 1 - if(myCoeffs.mB > 0.0) + if (theCoeffs.mB > 0.0) { // -(1+C)/B <= cos(U1-FI1) <= (1-C)/B - if(myCoeffs.mB + Abs(myCoeffs.mC) < -1.0) + if (theCoeffs.mB + Abs(theCoeffs.mC) < -1.0) { //(1-C)/B < -1 or -(1+C)/B > 1 ==> No solution return Standard_False; } - else if(myCoeffs.mB + Abs(myCoeffs.mC) <= 1.0) + else if (theCoeffs.mB + Abs(theCoeffs.mC) <= 1.0) { //(1-C)/B >= 1 and -(1+C)/B <= -1 ==> U=[0;2*PI]+aFI1 - - theU1f[0] = myCoeffs.mFI1; - theU1l[0] = myPeriod + myCoeffs.mFI1; + theURange[0].Add(theCoeffs.mFI1); + theURange[0].Add(thePeriod + theCoeffs.mFI1); } - else if((1 + myCoeffs.mC <= myCoeffs.mB) && - (myCoeffs.mB <= 1 - myCoeffs.mC)) + else if ((1 + theCoeffs.mC <= theCoeffs.mB) && + (theCoeffs.mB <= 1 - theCoeffs.mC)) { //(1-C)/B >= 1 and -(1+C)/B >= -1 ==> //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1), //where aDAngle = acos(-(myCoeffs.mC + 1) / myCoeffs.mB) - Standard_Real anArg = -(myCoeffs.mC + 1) / myCoeffs.mB; + Standard_Real anArg = -(theCoeffs.mC + 1) / theCoeffs.mB; if(anArg > 1.0) anArg = 1.0; if(anArg < -1.0) anArg = -1.0; const Standard_Real aDAngle = acos(anArg); - theU1f[0] = myCoeffs.mFI1; - theU1l[0] = aDAngle + myCoeffs.mFI1; - theU1f[1] = myPeriod - aDAngle + myCoeffs.mFI1; - theU1l[1] = myPeriod + myCoeffs.mFI1; + theURange[0].Add(theCoeffs.mFI1); + theURange[0].Add(aDAngle + theCoeffs.mFI1); + theURange[1].Add(thePeriod - aDAngle + theCoeffs.mFI1); + theURange[1].Add(thePeriod + theCoeffs.mFI1); } - else if((1 - myCoeffs.mC <= myCoeffs.mB) && - (myCoeffs.mB <= 1 + myCoeffs.mC)) + else if ((1 - theCoeffs.mC <= theCoeffs.mB) && + (theCoeffs.mB <= 1 + theCoeffs.mC)) { //(1-C)/B <= 1 and -(1+C)/B <= -1 ==> U=[aDAngle;2*PI-aDAngle]+aFI1 //where aDAngle = acos((1 - myCoeffs.mC) / myCoeffs.mB) - Standard_Real anArg = (1 - myCoeffs.mC) / myCoeffs.mB; + Standard_Real anArg = (1 - theCoeffs.mC) / theCoeffs.mB; if(anArg > 1.0) anArg = 1.0; if(anArg < -1.0) anArg = -1.0; const Standard_Real aDAngle = acos(anArg); - theU1f[0] = aDAngle + myCoeffs.mFI1; - theU1l[0] = myPeriod - aDAngle + myCoeffs.mFI1; + theURange[0].Add(aDAngle + theCoeffs.mFI1); + theURange[0].Add(thePeriod - aDAngle + theCoeffs.mFI1); } - else if(myCoeffs.mB - Abs(myCoeffs.mC) >= 1.0) + else if (theCoeffs.mB - Abs(theCoeffs.mC) >= 1.0) { //(1-C)/B <= 1 and -(1+C)/B >= -1 ==> //(U=[aDAngle1;aDAngle2]+aFI1) || @@ -2289,8 +2354,8 @@ Standard_Boolean WorkWithBoundaries::BoundariesComputing(Standard_Real theU1f[], //where aDAngle1 = acos((1 - myCoeffs.mC) / myCoeffs.mB), // aDAngle2 = acos(-(myCoeffs.mC + 1) / myCoeffs.mB). - Standard_Real anArg1 = (1 - myCoeffs.mC) / myCoeffs.mB, - anArg2 = -(myCoeffs.mC + 1) / myCoeffs.mB; + Standard_Real anArg1 = (1 - theCoeffs.mC) / theCoeffs.mB, + anArg2 = -(theCoeffs.mC + 1) / theCoeffs.mB; if(anArg1 > 1.0) anArg1 = 1.0; if(anArg1 < -1.0) @@ -2304,77 +2369,75 @@ Standard_Boolean WorkWithBoundaries::BoundariesComputing(Standard_Real theU1f[], const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2); //(U=[aDAngle1;aDAngle2]+aFI1) || //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1) - - theU1f[0] = aDAngle1 + myCoeffs.mFI1; - theU1l[0] = aDAngle2 + myCoeffs.mFI1; - theU1f[1] = myPeriod - aDAngle2 + myCoeffs.mFI1; - theU1l[1] = myPeriod - aDAngle1 + myCoeffs.mFI1; + theURange[0].Add(aDAngle1 + theCoeffs.mFI1); + theURange[0].Add(aDAngle2 + theCoeffs.mFI1); + theURange[1].Add(thePeriod - aDAngle2 + theCoeffs.mFI1); + theURange[1].Add(thePeriod - aDAngle1 + theCoeffs.mFI1); } else { return Standard_False; } } - else if(myCoeffs.mB < 0.0) + else if (theCoeffs.mB < 0.0) { // (1-C)/B <= cos(U1-FI1) <= -(1+C)/B - if(myCoeffs.mB + Abs(myCoeffs.mC) > 1.0) + if (theCoeffs.mB + Abs(theCoeffs.mC) > 1.0) { // -(1+C)/B < -1 or (1-C)/B > 1 ==> No solutions return Standard_False; } - else if(-myCoeffs.mB + Abs(myCoeffs.mC) <= 1.0) + else if (-theCoeffs.mB + Abs(theCoeffs.mC) <= 1.0) { // -(1+C)/B >= 1 and (1-C)/B <= -1 ==> U=[0;2*PI]+aFI1 - - theU1f[0] = myCoeffs.mFI1; - theU1l[0] = myPeriod + myCoeffs.mFI1; + theURange[0].Add(theCoeffs.mFI1); + theURange[0].Add(thePeriod + theCoeffs.mFI1); } - else if((-myCoeffs.mC - 1 <= myCoeffs.mB) && - ( myCoeffs.mB <= myCoeffs.mC - 1)) + else if ((-theCoeffs.mC - 1 <= theCoeffs.mB) && + (theCoeffs.mB <= theCoeffs.mC - 1)) { // -(1+C)/B >= 1 and (1-C)/B >= -1 ==> //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1), //where aDAngle = acos((1 - myCoeffs.mC) / myCoeffs.mB) - Standard_Real anArg = (1 - myCoeffs.mC) / myCoeffs.mB; + Standard_Real anArg = (1 - theCoeffs.mC) / theCoeffs.mB; if(anArg > 1.0) anArg = 1.0; if(anArg < -1.0) anArg = -1.0; const Standard_Real aDAngle = acos(anArg); - theU1f[0] = myCoeffs.mFI1; - theU1l[0] = aDAngle + myCoeffs.mFI1; - theU1f[1] = myPeriod - aDAngle + myCoeffs.mFI1; - theU1l[1] = myPeriod + myCoeffs.mFI1; + theURange[0].Add(theCoeffs.mFI1); + theURange[0].Add(aDAngle + theCoeffs.mFI1); + theURange[1].Add(thePeriod - aDAngle + theCoeffs.mFI1); + theURange[1].Add(thePeriod + theCoeffs.mFI1); } - else if((myCoeffs.mC - 1 <= myCoeffs.mB) && - (myCoeffs.mB <= -myCoeffs.mB - 1)) + else if ((theCoeffs.mC - 1 <= theCoeffs.mB) && + (theCoeffs.mB <= -theCoeffs.mB - 1)) { // -(1+C)/B <= 1 and (1-C)/B <= -1 ==> U=[aDAngle;2*PI-aDAngle]+aFI1, //where aDAngle = acos(-(myCoeffs.mC + 1) / myCoeffs.mB). - Standard_Real anArg = -(myCoeffs.mC + 1) / myCoeffs.mB; + Standard_Real anArg = -(theCoeffs.mC + 1) / theCoeffs.mB; if(anArg > 1.0) anArg = 1.0; if(anArg < -1.0) anArg = -1.0; const Standard_Real aDAngle = acos(anArg); - theU1f[0] = aDAngle + myCoeffs.mFI1; - theU1l[0] = myPeriod - aDAngle + myCoeffs.mFI1; + theURange[0].Add(aDAngle + theCoeffs.mFI1); + theURange[0].Add(thePeriod - aDAngle + theCoeffs.mFI1); } - else if(-myCoeffs.mB - Abs(myCoeffs.mC) >= 1.0) + else if (-theCoeffs.mB - Abs(theCoeffs.mC) >= 1.0) { // -(1+C)/B <= 1 and (1-C)/B >= -1 ==> //(U=[aDAngle1;aDAngle2]+aFI1) || (U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1), //where aDAngle1 = acos(-(myCoeffs.mC + 1) / myCoeffs.mB), // aDAngle2 = acos((1 - myCoeffs.mC) / myCoeffs.mB) - Standard_Real anArg1 = -(myCoeffs.mC + 1) / myCoeffs.mB, - anArg2 = (1 - myCoeffs.mC) / myCoeffs.mB; + Standard_Real anArg1 = -(theCoeffs.mC + 1) / theCoeffs.mB, + anArg2 = (1 - theCoeffs.mC) / theCoeffs.mB; if(anArg1 > 1.0) anArg1 = 1.0; if(anArg1 < -1.0) @@ -2386,10 +2449,10 @@ Standard_Boolean WorkWithBoundaries::BoundariesComputing(Standard_Real theU1f[], anArg2 = -1.0; const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2); - theU1f[0] = aDAngle1 + myCoeffs.mFI1; - theU1l[0] = aDAngle2 + myCoeffs.mFI1; - theU1f[1] = myPeriod - aDAngle2 + myCoeffs.mFI1; - theU1l[1] = myPeriod - aDAngle1 + myCoeffs.mFI1; + theURange[0].Add(aDAngle1 + theCoeffs.mFI1); + theURange[0].Add(aDAngle2 + theCoeffs.mFI1); + theURange[1].Add(thePeriod - aDAngle2 + theCoeffs.mFI1); + theURange[1].Add(thePeriod - aDAngle1 + theCoeffs.mFI1); } else { @@ -2595,133 +2658,77 @@ void WorkWithBoundaries::BoundaryEstimation(const gp_Cylinder& theCy1, } //======================================================================= -//function : IntCyCy +//function : CyCyNoGeometric //purpose : //======================================================================= -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 IntPatch_ImpImpIntersection::IntStatus + CyCyNoGeometric(const gp_Cylinder &theCyl1, + const gp_Cylinder &theCyl2, + const WorkWithBoundaries &theBW, + Bnd_Range theRange[], + const Standard_Integer theNbOfRanges /*=2*/, + Standard_Boolean& isTheEmpty, + IntPatch_SequenceOfLine& theSlin, + IntPatch_SequenceOfPoint& theSPnt) { - isTheEmpty = Standard_True; - isTheSameSurface = Standard_False; - isTheMultiplePoint = Standard_False; - theSlin.Clear(); - theSPnt.Clear(); - - const gp_Cylinder &aCyl1 = theQuad1.Cylinder(), - &aCyl2 = theQuad2.Cylinder(); - - IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D); - - if (!anInter.IsDone()) - { - return IntPatch_ImpImpIntersection::IntStatus_Fail; - } - - if(anInter.TypeInter() != IntAna_NoGeometricSolution) - { - if (CyCyAnalyticalIntersect(theQuad1, theQuad2, anInter, - theTol3D, isTheReverse, isTheEmpty, - isTheSameSurface, isTheMultiplePoint, - theSlin, theSPnt)) - { - return IntPatch_ImpImpIntersection::IntStatus_OK; - } - } - - //Here, intersection line is not an analytical curve(line, circle, ellipsis etc.) + Standard_Real aUSurf1f = 0.0, aUSurf1l = 0.0, + aUSurf2f = 0.0, aUSurf2l = 0.0, + aVSurf1f = 0.0, aVSurf1l = 0.0, + aVSurf2f = 0.0, aVSurf2l = 0.0; - Standard_Real aUSurf1f = 0.0, //const - aUSurf1l = 0.0, - aVSurf1f = 0.0, - aVSurf1l = 0.0; - Standard_Real aUSurf2f = 0.0, //const - aUSurf2l = 0.0, - aVSurf2f = 0.0, - aVSurf2l = 0.0; - - theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l); - theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l); - - const Standard_Integer aNbMaxPoints = 2000; - const Standard_Integer aNbMinPoints = 200; - const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, - RealToInt(20.0*aCyl1.Radius())), aNbMaxPoints); - const Standard_Real aPeriod = 2.0*M_PI; - const Standard_Real aStepMin = theTol2D, - aStepMax = (aUSurf1l-aUSurf1f > M_PI/100.0) ? - (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints) : - aUSurf1l-aUSurf1f; - - const Standard_Integer aNbWLines = 2; - - const ComputationMethods::stCoeffsValue anEquationCoeffs(aCyl1, aCyl2); - - const WorkWithBoundaries aBoundWork(theQuad1, theQuad2, anEquationCoeffs, - theUVSurf1, theUVSurf2, aNbWLines, - aPeriod, theTol3D, theTol2D, isTheReverse); + theBW.UVS1().Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l); + theBW.UVS2().Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l); Bnd_Range aRangeS1, aRangeS2; - aBoundWork.BoundaryEstimation(aCyl1, aCyl2, aRangeS1, aRangeS2); + theBW.BoundaryEstimation(theCyl1, theCyl2, aRangeS1, aRangeS2); if (aRangeS1.IsVoid() || aRangeS2.IsVoid()) 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." + //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(); + const Standard_Real aMaxV1Range = aF*theCyl1.Radius(), aMaxV2Range = aF*theCyl2.Radius(); if ((aRangeS1.Delta() > aMaxV1Range) || (aRangeS2.Delta() > aMaxV2Range)) return IntPatch_ImpImpIntersection::IntStatus_InfiniteSectionCurve; } - //Boundaries (it is good idea to use Bnd_Range in the future, instead of aU1f and aU1l) - //Intersection result can include two non-connected regions - //(see WorkWithBoundaries::BoundariesComputing(...) method). - const Standard_Integer aNbOfBoundaries = 2; - Standard_Real aU1f[aNbOfBoundaries] = {-Precision::Infinite(), -Precision::Infinite()}; - Standard_Real aU1l[aNbOfBoundaries] = {Precision::Infinite(), Precision::Infinite()}; - - if(!aBoundWork.BoundariesComputing(aU1f, aU1l)) - return IntPatch_ImpImpIntersection::IntStatus_OK; + const ComputationMethods::stCoeffsValue &anEquationCoeffs = theBW.SICoeffs(); + const IntSurf_Quadric& aQuad1 = theBW.GetQSurface(1); + const IntSurf_Quadric& aQuad2 = theBW.GetQSurface(2); + const Standard_Boolean isReversed = theBW.IsReversed(); + const Standard_Real aTol2D = theBW.Get2dTolerance(); + const Standard_Real aTol3D = theBW.Get3dTolerance(); + const Standard_Real aPeriod = 2.0*M_PI; + const Standard_Integer aNbMaxPoints = 2000; + const Standard_Integer aNbMinPoints = 200; + const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, + RealToInt(20.0*theCyl1.Radius())), aNbMaxPoints); + const Standard_Real aStepMin = aTol2D, + aStepMax = (aUSurf1l - aUSurf1f > M_PI / 100.0) ? + (aUSurf1l - aUSurf1f) / IntToReal(aNbPoints) : + aUSurf1l - aUSurf1f; //The main idea of the algorithm is to change U1-parameter - //(U-parameter of aCyl1) from aU1f to aU1l with some step + //(U-parameter of theCyl1) from aU1f to aU1l with some step //(step is adaptive) and to obtain set of intersection points. - for(Standard_Integer i = 0; i < aNbOfBoundaries; i++) + for (Standard_Integer i = 0; i < theNbOfRanges; i++) { - if(Precision::IsInfinite(aU1f[i]) && Precision::IsInfinite(aU1l[i])) + if (theRange[i].IsVoid()) continue; - InscribeInterval(aUSurf1f, aUSurf1l, aU1f[i], aU1l[i], theTol2D, aPeriod); + InscribeInterval(aUSurf1f, aUSurf1l, theRange[i], aTol2D, aPeriod); } - if( !Precision::IsInfinite(aU1f[0]) && !Precision::IsInfinite(aU1f[1]) && - !Precision::IsInfinite(aU1l[0]) && !Precision::IsInfinite(aU1l[1])) + if (theRange[0].Union(theRange[1])) { - if( ((aU1f[1] <= aU1l[0]) || (aU1l[1] <= aU1l[0])) && - ((aU1f[0] <= aU1l[1]) || (aU1l[0] <= aU1l[1]))) - {//Join all intervals to one - aU1f[0] = Min(aU1f[0], aU1f[1]); - aU1l[0] = Max(aU1l[0], aU1l[1]); - - aU1f[1] = -Precision::Infinite(); - aU1l[1] = Precision::Infinite(); - } + // Works only if (theNbOfRanges == 2). + theRange[1].SetVoid(); } //Critical points are the value of U1-parameter in the points @@ -2733,18 +2740,18 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //See CriticalPointsComputing(...) function to get detail information about this array. const Standard_Integer aNbCritPointsMax = 12; - Standard_Real anU1crit[aNbCritPointsMax] = {Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite(), - Precision::Infinite()}; + Standard_Real anU1crit[aNbCritPointsMax] = { Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite(), + Precision::Infinite() }; //This list of critical points is not full because it does not contain any points //which intersection line goes through V-bounds of cylinders in. @@ -2753,7 +2760,7 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, Standard_Integer aNbCritPoints = aNbCritPointsMax; CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, - aPeriod, theTol2D, aNbCritPoints, anU1crit); + aPeriod, aTol2D, aNbCritPoints, anU1crit); //Getting Walking-line @@ -2762,35 +2769,35 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, // No points have been added in WL WLFStatus_Absent = 0, // WL contains at least one point - WLFStatus_Exist = 1, + WLFStatus_Exist = 1, // WL has been finished in some critical point // We should start new line WLFStatus_Broken = 2 }; - for(Standard_Integer aCurInterval = 0; aCurInterval < aNbOfBoundaries; aCurInterval++) + const Standard_Integer aNbWLines = 2; + for (Standard_Integer aCurInterval = 0; aCurInterval < theNbOfRanges; aCurInterval++) { //Process every continuous region - - if(Precision::IsInfinite(aU1f[aCurInterval]) && Precision::IsInfinite(aU1l[aCurInterval])) - continue; - Standard_Boolean isAddedIntoWL[aNbWLines]; - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) isAddedIntoWL[i] = Standard_False; - Standard_Real anUf = aU1f[aCurInterval], anUl = aU1l[aCurInterval]; - const Standard_Boolean isDeltaPeriod = IsEqual(anUl-anUf, aPeriod); + Standard_Real anUf = 1.0, anUl = 0.0; + if (!theRange[aCurInterval].GetBounds(anUf, anUl)) + continue; + + const Standard_Boolean isDeltaPeriod = IsEqual(anUl - anUf, aPeriod); //Inscribe and sort critical points - for(Standard_Integer i = 0; i < aNbCritPoints; i++) + for (Standard_Integer i = 0; i < aNbCritPoints; i++) { - InscribePoint(anUf, anUl, anU1crit[i], theTol2D, aPeriod, Standard_False); + InscribePoint(anUf, anUl, anU1crit[i], 0.0, aPeriod, Standard_False); } std::sort(anU1crit, anU1crit + aNbCritPoints); - while(anUf < anUl) + while (anUf < anUl) { //Change value of U-parameter on the 1st surface from anUf to anUl //(anUf will be modified in the cycle body). @@ -2804,7 +2811,7 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, Handle(IntSurf_LineOn2S) aL2S[aNbWLines]; Handle(IntPatch_WLine) aWLine[aNbWLines]; - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { aL2S[i] = new IntSurf_LineOn2S(); aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False); @@ -2814,33 +2821,33 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, aV1Prev[i] = aV2Prev[i] = 0.0; anUexpect[i] = anUf; } - - Standard_Real aCriticalDelta[aNbCritPointsMax] = {0}; - for(Standard_Integer aCritPID = 0; aCritPID < aNbCritPoints; aCritPID++) + + Standard_Real aCriticalDelta[aNbCritPointsMax] = { 0 }; + for (Standard_Integer aCritPID = 0; aCritPID < aNbCritPoints; aCritPID++) { //We are not interested in elements of aCriticalDelta array //if their index is greater than or equal to aNbCritPoints aCriticalDelta[aCritPID] = anUf - anU1crit[aCritPID]; } - Standard_Real anU1 = anUf; + Standard_Real anU1 = anUf, aMinCriticalParam = anUf; Standard_Boolean isFirst = Standard_True; - - while(anU1 <= anUl) + + while (anU1 <= anUl) { //Change value of U-parameter on the 1st surface from anUf to anUl //(anUf will be modified in the cycle body). However, this cycle //can be broken if WL goes though some critical point. //Step is computed adaptively (see comments below). - for(Standard_Integer i = 0; i < aNbCritPoints; i++) + for (Standard_Integer i = 0; i < aNbCritPoints; i++) { - if((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0) + if ((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0) { //WL has gone through i-th critical point anU1 = anU1crit[i]; - for(Standard_Integer j = 0; j < aNbWLines; j++) + for (Standard_Integer j = 0; j < aNbWLines; j++) { aWLFindStatus[j] = WLFStatus_Broken; anUexpect[j] = anU1; @@ -2850,14 +2857,14 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } } - if(IsEqual(anU1, anUl)) + if (IsEqual(anU1, anUl)) { - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { aWLFindStatus[i] = WLFStatus_Broken; anUexpect[i] = anU1; - if(isDeltaPeriod) + if (isDeltaPeriod) { //if isAddedIntoWL[i] == TRUE WLine contains only one point //(which was end point of previous WLine). If we will @@ -2871,57 +2878,57 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } else { - isAddingWLEnabled[i] = ((theTol2D >= (anUexpect[i] - anU1)) || + isAddingWLEnabled[i] = ((aTol2D >= (anUexpect[i] - anU1)) || (aWLFindStatus[i] == WLFStatus_Absent)); } }//for(Standard_Integer i = 0; i < aNbWLines; i++) } else { - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - isAddingWLEnabled[i] = ((theTol2D >= (anUexpect[i] - anU1)) || + isAddingWLEnabled[i] = ((aTol2D >= (anUexpect[i] - anU1)) || (aWLFindStatus[i] == WLFStatus_Absent)); }//for(Standard_Integer i = 0; i < aNbWLines; i++) } - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - const Standard_Integer aNbPntsWL = aWLine[i].IsNull() ? 0 : - aWLine[i]->Curve()->NbPoints(); - - if( (aWLFindStatus[i] == WLFStatus_Broken) || - (aWLFindStatus[i] == WLFStatus_Absent)) + const Standard_Integer aNbPntsWL = aWLine[i].IsNull() ? 0 : + aWLine[i]->Curve()->NbPoints(); + + if ((aWLFindStatus[i] == WLFStatus_Broken) || + (aWLFindStatus[i] == WLFStatus_Absent)) {//Begin and end of WLine must be on boundary point //or on seam-edge strictly (if it is possible). - Standard_Real aTol = theTol2D; + Standard_Real aTol = aTol2D; ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i], &aTol); - InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False); + InscribePoint(aUSurf2f, aUSurf2l, aU2[i], aTol2D, aPeriod, Standard_False); - aTol = Max(aTol, theTol2D); + aTol = Max(aTol, aTol2D); - if(Abs(aU2[i]) <= aTol) + if (Abs(aU2[i]) <= aTol) aU2[i] = 0.0; - else if(Abs(aU2[i] - aPeriod) <= aTol) + else if (Abs(aU2[i] - aPeriod) <= aTol) aU2[i] = aPeriod; - else if(Abs(aU2[i] - aUSurf2f) <= aTol) + else if (Abs(aU2[i] - aUSurf2f) <= aTol) aU2[i] = aUSurf2f; - else if(Abs(aU2[i] - aUSurf2l) <= aTol) + else if (Abs(aU2[i] - aUSurf2l) <= aTol) aU2[i] = aUSurf2l; } else { ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]); - InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False); + InscribePoint(aUSurf2f, aUSurf2l, aU2[i], aTol2D, aPeriod, Standard_False); } - - if(aNbPntsWL == 0) + + if (aNbPntsWL == 0) {//the line has not contained any points yet - if(((aUSurf2f + aPeriod - aUSurf2l) <= 2.0*theTol2D) && - ((Abs(aU2[i] - aUSurf2f) < theTol2D) || - (Abs(aU2[i]-aUSurf2l) < theTol2D))) + if (((aUSurf2f + aPeriod - aUSurf2l) <= 2.0*aTol2D) && + ((Abs(aU2[i] - aUSurf2f) < aTol2D) || + (Abs(aU2[i] - aUSurf2l) < aTol2D))) { //In this case aU2[i] can have two values: current aU2[i] or //aU2[i]+aPeriod (aU2[i]-aPeriod). It is necessary to choose @@ -2936,7 +2943,7 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //increased too. And we will go out of surface boundary. //Therefore, If U2(U1) is increasing then U2 must be equal aUSurf2f. //Analogically, if U2(U1) is decreasing. - if(isIncreasing) + if (isIncreasing) { aU2[i] = aUSurf2f; } @@ -2948,19 +2955,19 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } else {//aNbPntsWL > 0 - if(((aUSurf2l - aUSurf2f) >= aPeriod) && - ((Abs(aU2[i] - aUSurf2f) < theTol2D) || - (Abs(aU2[i]-aUSurf2l) < theTol2D))) + if (((aUSurf2l - aUSurf2f) >= aPeriod) && + ((Abs(aU2[i] - aUSurf2f) < aTol2D) || + (Abs(aU2[i] - aUSurf2l) < aTol2D))) {//end of the line Standard_Real aU2prev = 0.0, aV2prev = 0.0; - if(isTheReverse) + if (isReversed) aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS1(aU2prev, aV2prev); else aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS2(aU2prev, aV2prev); - if(2.0*Abs(aU2prev - aU2[i]) > aPeriod) + if (2.0*Abs(aU2prev - aU2[i]) > aPeriod) { - if(aU2prev > aU2[i]) + if (aU2prev > aU2[i]) aU2[i] += aPeriod; else aU2[i] -= aPeriod; @@ -2971,7 +2978,7 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, ComputationMethods::CylCylComputeParameters(anU1, aU2[i], anEquationCoeffs, aV1[i], aV2[i]); - if(isFirst) + if (isFirst) { aV1Prev[i] = aV1[i]; aV2Prev[i] = aV2[i]; @@ -2982,36 +2989,36 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //Looking for points into WLine Standard_Boolean isBroken = Standard_False; - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if(!isAddingWLEnabled[i]) + if (!isAddingWLEnabled[i]) { Standard_Boolean isBoundIntersect = Standard_False; - if( (Abs(aV1[i] - aVSurf1f) <= theTol2D) || - ((aV1[i]-aVSurf1f)*(aV1Prev[i]-aVSurf1f) < 0.0)) + if ((Abs(aV1[i] - aVSurf1f) <= aTol2D) || + ((aV1[i] - aVSurf1f)*(aV1Prev[i] - aVSurf1f) < 0.0)) { isBoundIntersect = Standard_True; } - else if( (Abs(aV1[i] - aVSurf1l) <= theTol2D) || - ( (aV1[i]-aVSurf1l)*(aV1Prev[i]-aVSurf1l) < 0.0)) + else if ((Abs(aV1[i] - aVSurf1l) <= aTol2D) || + ((aV1[i] - aVSurf1l)*(aV1Prev[i] - aVSurf1l) < 0.0)) { isBoundIntersect = Standard_True; } - else if( (Abs(aV2[i] - aVSurf2f) <= theTol2D) || - ( (aV2[i]-aVSurf2f)*(aV2Prev[i]-aVSurf2f) < 0.0)) + else if ((Abs(aV2[i] - aVSurf2f) <= aTol2D) || + ((aV2[i] - aVSurf2f)*(aV2Prev[i] - aVSurf2f) < 0.0)) { isBoundIntersect = Standard_True; } - else if( (Abs(aV2[i] - aVSurf2l) <= theTol2D) || - ( (aV2[i]-aVSurf2l)*(aV2Prev[i]-aVSurf2l) < 0.0)) + else if ((Abs(aV2[i] - aVSurf2l) <= aTol2D) || + ((aV2[i] - aVSurf2l)*(aV2Prev[i] - aVSurf2l) < 0.0)) { isBoundIntersect = Standard_True; } - if(aWLFindStatus[i] == WLFStatus_Broken) + if (aWLFindStatus[i] == WLFStatus_Broken) isBroken = Standard_True; - if(!isBoundIntersect) + if (!isBoundIntersect) { continue; } @@ -3022,19 +3029,18 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } // True if the current point already in the domain - const Standard_Boolean isInscribe = - ((aUSurf2f-aU2[i]) <= theTol2D) && ((aU2[i]-aUSurf2l) <= theTol2D) && - ((aVSurf1f - aV1[i]) <= theTol2D) && ((aV1[i] - aVSurf1l) <= theTol2D) && - ((aVSurf2f - aV2[i]) <= theTol2D) && ((aV2[i] - aVSurf2l) <= theTol2D); + const Standard_Boolean isInscribe = + ((aUSurf2f - aU2[i]) <= aTol2D) && ((aU2[i] - aUSurf2l) <= aTol2D) && + ((aVSurf1f - aV1[i]) <= aTol2D) && ((aV1[i] - aVSurf1l) <= aTol2D) && + ((aVSurf2f - aV2[i]) <= aTol2D) && ((aV2[i] - aVSurf2l) <= aTol2D); //isVIntersect == TRUE if intersection line intersects two (!) //V-bounds of cylinder (1st or 2nd - no matter) const Standard_Boolean isVIntersect = - ( ((aVSurf1f-aV1[i])*(aVSurf1f-aV1Prev[i]) < RealSmall()) && - ((aVSurf1l-aV1[i])*(aVSurf1l-aV1Prev[i]) < RealSmall())) || - ( ((aVSurf2f-aV2[i])*(aVSurf2f-aV2Prev[i]) < RealSmall()) && - ((aVSurf2l-aV2[i])*(aVSurf2l-aV2Prev[i]) < RealSmall())); - + (((aVSurf1f - aV1[i])*(aVSurf1f - aV1Prev[i]) < RealSmall()) && + ((aVSurf1l - aV1[i])*(aVSurf1l - aV1Prev[i]) < RealSmall())) || + (((aVSurf2f - aV2[i])*(aVSurf2f - aV2Prev[i]) < RealSmall()) && + ((aVSurf2l - aV2[i])*(aVSurf2l - aV2Prev[i]) < RealSmall())); //isFound1 == TRUE if intersection line intersects V-bounds // (First or Last - no matter) of the 1st cylynder @@ -3045,52 +3051,52 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, if (aWLFindStatus[i] == WLFStatus_Absent) { - if(((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1-aUSurf1l) < theTol2D)) + if (((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1 - aUSurf1l) < aTol2D)) { isForce = Standard_True; } } - aBoundWork.AddBoundaryPoint(aWLine[i], anU1, aU2[i], aV1[i], aV1Prev[i], - aV2[i], aV2Prev[i], i, isForce, - isFound1, isFound2); + theBW.AddBoundaryPoint(aWLine[i], anU1, aMinCriticalParam, aU2[i], + aV1[i], aV1Prev[i], aV2[i], aV2Prev[i], i, isForce, + isFound1, isFound2); const Standard_Boolean isPrevVBound = !isVIntersect && - ((Abs(aV1Prev[i] - aVSurf1f) <= theTol2D) || - (Abs(aV1Prev[i] - aVSurf1l) <= theTol2D) || - (Abs(aV2Prev[i] - aVSurf2f) <= theTol2D) || - (Abs(aV2Prev[i] - aVSurf2l) <= theTol2D)); + ((Abs(aV1Prev[i] - aVSurf1f) <= aTol2D) || + (Abs(aV1Prev[i] - aVSurf1l) <= aTol2D) || + (Abs(aV2Prev[i] - aVSurf2f) <= aTol2D) || + (Abs(aV2Prev[i] - aVSurf2l) <= aTol2D)); aV1Prev[i] = aV1[i]; aV2Prev[i] = aV2[i]; - if((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound) + if ((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound) { aWLFindStatus[i] = WLFStatus_Broken; //start a new line } - else if(isInscribe) + else if (isInscribe) { - if((aWLFindStatus[i] == WLFStatus_Absent) && (isFound1 || isFound2)) + if ((aWLFindStatus[i] == WLFStatus_Absent) && (isFound1 || isFound2)) { aWLFindStatus[i] = WLFStatus_Exist; } - if( (aWLFindStatus[i] != WLFStatus_Broken) || - (aWLine[i]->NbPnts() >= 1) || IsEqual(anU1, anUl)) + if ((aWLFindStatus[i] != WLFStatus_Broken) || + (aWLine[i]->NbPnts() >= 1) || IsEqual(anU1, anUl)) { - if(aWLine[i]->NbPnts() > 0) + if (aWLine[i]->NbPnts() > 0) { Standard_Real aU2p = 0.0, aV2p = 0.0; - if(isTheReverse) + if (isReversed) aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p); else aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p); const Standard_Real aDelta = aU2[i] - aU2p; - if(2*Abs(aDelta) > aPeriod) + if (2.0 * Abs(aDelta) > aPeriod) { - if(aDelta > 0.0) + if (aDelta > 0.0) { aU2[i] -= aPeriod; } @@ -3101,47 +3107,47 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } } - if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse, Standard_True, + if(AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, Standard_True, gp_Pnt2d(anU1, aV1[i]), gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aPeriod, - aWLine[i]->Curve(), i, theTol3D, theTol2D, isForce)) + aWLine[i]->Curve(), i, aTol3D, aTol2D, isForce)) { - if(aWLFindStatus[i] == WLFStatus_Absent) + if (aWLFindStatus[i] == WLFStatus_Absent) { aWLFindStatus[i] = WLFStatus_Exist; } } - else if(!isFound1 && !isFound2) + else if (!isFound1 && !isFound2) {//We do not add any point while doing this iteration - if(aWLFindStatus[i] == WLFStatus_Exist) + if (aWLFindStatus[i] == WLFStatus_Exist) { aWLFindStatus[i] = WLFStatus_Broken; - } + } } } } else {//We do not add any point while doing this iteration - if(aWLFindStatus[i] == WLFStatus_Exist) + if (aWLFindStatus[i] == WLFStatus_Exist) { aWLFindStatus[i] = WLFStatus_Broken; } } - - if(aWLFindStatus[i] == WLFStatus_Broken) + + if (aWLFindStatus[i] == WLFStatus_Broken) isBroken = Standard_True; }//for(Standard_Integer i = 0; i < aNbWLines; i++) - if(isBroken) + if (isBroken) {//current lines are filled. Go to the next lines anUf = anU1; Standard_Boolean isAdded = Standard_True; - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if(isAddingWLEnabled[i]) + if (isAddingWLEnabled[i]) { continue; } @@ -3150,28 +3156,28 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False; - aBoundWork.AddBoundaryPoint(aWLine[i], anU1, aU2[i], aV1[i], aV1Prev[i], - aV2[i], aV2Prev[i], i, - Standard_False, isFound1, isFound2); + theBW.AddBoundaryPoint(aWLine[i], anU1, aMinCriticalParam, aU2[i], + aV1[i], aV1Prev[i], aV2[i], aV2Prev[i], i, + Standard_False, isFound1, isFound2); - if(isFound1 || isFound2) + if (isFound1 || isFound2) { isAdded = Standard_True; } - if(aWLine[i]->NbPnts() > 0) + if (aWLine[i]->NbPnts() > 0) { Standard_Real aU2p = 0.0, aV2p = 0.0; - if(isTheReverse) + if (isReversed) aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p); else aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p); const Standard_Real aDelta = aU2[i] - aU2p; - if(2*Abs(aDelta) > aPeriod) + if (2 * Abs(aDelta) > aPeriod) { - if(aDelta > 0.0) + if (aDelta > 0.0) { aU2[i] -= aPeriod; } @@ -3182,18 +3188,18 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } } - if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse, + if(AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, Standard_True, gp_Pnt2d(anU1, aV1[i]), gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(), - i, theTol3D, theTol2D, Standard_False)) + i, aTol3D, aTol2D, Standard_False)) { isAdded = Standard_True; } } - if(!isAdded) + if (!isAdded) { //Before breaking WL, we must complete it correctly //(e.g. to prolong to the surface boundary). @@ -3201,16 +3207,16 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //(have maximal U1-parameter) and try to add it in //the current WL. Standard_Real anUmaxAdded = RealFirst(); - + { Standard_Boolean isChanged = Standard_False; - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if(aWLFindStatus[i] == WLFStatus_Absent) + if (aWLFindStatus[i] == WLFStatus_Absent) continue; Standard_Real aU1c = 0.0, aV1c = 0.0; - if(isTheReverse) + if (isReversed) aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c); else aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c); @@ -3219,29 +3225,29 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, isChanged = Standard_True; } - if(!isChanged) + if (!isChanged) { //If anUmaxAdded were not changed in previous cycle then //we would break existing WLines. break; } } - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if(isAddingWLEnabled[i]) + if (isAddingWLEnabled[i]) { continue; } ComputationMethods::CylCylComputeParameters(anUmaxAdded, i, anEquationCoeffs, - aU2[i], aV1[i], aV2[i]); - - AddPointIntoWL( theQuad1, theQuad2, anEquationCoeffs, isTheReverse, - Standard_True, gp_Pnt2d(anUmaxAdded, aV1[i]), - gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l, - aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l, - aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(), - i, theTol3D, theTol2D, Standard_False); + aU2[i], aV1[i], aV2[i]); + + AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, + Standard_True, gp_Pnt2d(anUmaxAdded, aV1[i]), + gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l, + aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l, + aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(), + i, aTol3D, aTol2D, Standard_False); } } @@ -3257,21 +3263,21 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //in every iteration. It allows avoiding "flying" intersection //points too far each from other (see issue #24915). - const Standard_Real aDeltaV1 = aRangeS1.Delta()/IntToReal(aNbPoints), - aDeltaV2 = aRangeS2.Delta()/IntToReal(aNbPoints); - + const Standard_Real aDeltaV1 = aRangeS1.Delta() / IntToReal(aNbPoints), + aDeltaV2 = aRangeS2.Delta() / IntToReal(aNbPoints); + math_Matrix aMatr(1, 3, 1, 5); Standard_Real aMinUexp = RealLast(); - - for(Standard_Integer i = 0; i < aNbWLines; i++) + + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if(theTol2D < (anUexpect[i] - anU1)) + if (aTol2D < (anUexpect[i] - anU1)) { continue; } - if(aWLFindStatus[i] == WLFStatus_Absent) + if (aWLFindStatus[i] == WLFStatus_Absent) { anUexpect[i] += aStepMax; aMinUexp = Min(aMinUexp, anUexpect[i]); @@ -3309,7 +3315,7 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //The solution is approximate. More over, all requirements to the //linearization must be satisfied in order to obtain quality result. - if(!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp)) + if (!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp)) { //To avoid cycling-up anUexpect[i] += aStepMax; @@ -3318,10 +3324,10 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, continue; } - if(aStepTmp < aStepMin) + if (aStepTmp < aStepMin) aStepTmp = aStepMin; - - if(aStepTmp > aStepMax) + + if (aStepTmp > aStepMax) aStepTmp = aStepMax; anUexpect[i] = anU1 + aStepTmp; @@ -3331,26 +3337,26 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, anU1 = aMinUexp; } - if(Precision::PConfusion() >= (anUl - anU1)) + if (Precision::PConfusion() >= (anUl - anU1)) anU1 = anUl; anUf = anU1; - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if(aWLine[i]->NbPnts() != 1) + if (aWLine[i]->NbPnts() != 1) isAddedIntoWL[i] = Standard_False; - if(anU1 == anUl) + if (anU1 == anUl) {//strictly equal. Tolerance is considered above. anUexpect[i] = anUl; } } } - for(Standard_Integer i = 0; i < aNbWLines; i++) + for (Standard_Integer i = 0; i < aNbWLines; i++) { - if((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i])) + if ((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i])) { isTheEmpty = Standard_False; Standard_Real u1, v1, u2, v2; @@ -3358,34 +3364,34 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, IntPatch_Point aP; aP.SetParameter(u1); aP.SetParameters(u1, v1, u2, v2); - aP.SetTolerance(theTol3D); + aP.SetTolerance(aTol3D); aP.SetValue(aWLine[i]->Point(1).Value()); theSPnt.Append(aP); } - else if(aWLine[i]->NbPnts() > 1) + else if (aWLine[i]->NbPnts() > 1) { Standard_Boolean isGood = Standard_True; - if(aWLine[i]->NbPnts() == 2) + if (aWLine[i]->NbPnts() == 2) { const IntSurf_PntOn2S& aPf = aWLine[i]->Point(1); const IntSurf_PntOn2S& aPl = aWLine[i]->Point(2); - - if(aPf.IsSame(aPl, Precision::Confusion())) + + if (aPf.IsSame(aPl, Precision::Confusion())) isGood = Standard_False; } - if(isGood) + if (isGood) { isTheEmpty = Standard_False; isAddedIntoWL[i] = Standard_True; - SeekAdditionalPoints( theQuad1, theQuad2, aWLine[i]->Curve(), - anEquationCoeffs, i, aNbPoints, 1, - aWLine[i]->NbPnts(), theTol2D, aPeriod, - isTheReverse); + SeekAdditionalPoints(aQuad1, aQuad2, aWLine[i]->Curve(), + anEquationCoeffs, i, aNbPoints, 1, + aWLine[i]->NbPnts(), aTol2D, aPeriod, + isReversed); - aWLine[i]->ComputeVertexParameters(theTol3D); + aWLine[i]->ComputeVertexParameters(aTol3D); theSlin.Append(aWLine[i]); } } @@ -3404,19 +3410,19 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, //Delete the points in theSPnt, which //lie at least in one of the line in theSlin. - for(Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++) + for (Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++) { - for(Standard_Integer aNbLin = 1; aNbLin <= theSlin.Length(); aNbLin++) + for (Standard_Integer aNbLin = 1; aNbLin <= theSlin.Length(); aNbLin++) { - Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine):: - DownCast(theSlin.Value(aNbLin))); + Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine):: + DownCast(theSlin.Value(aNbLin))); const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1); const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aWLine1->NbPnts()); const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNbPnt).PntOn2S(); - if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) || - aPntCur.IsSame(aPntLWL1, Precision::Confusion())) + if (aPntCur.IsSame(aPntFWL1, Precision::Confusion()) || + aPntCur.IsSame(aPntLWL1, Precision::Confusion())) { theSPnt.Remove(aNbPnt); aNbPnt--; @@ -3425,10 +3431,20 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, } } - const Standard_Real aDU = aStepMin + Epsilon(aStepMin); - //Try to add new points in the neighbourhood of existing point - for(Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++) + //Try to add new points in the neighborhood of existing point + for (Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++) { + // Standard algorithm (implemented above) could not find any + // continuous curve in neighborhood of aPnt2S (e.g. because + // this curve is too small; see tests\bugs\modalg_5\bug25292_35 and _36). + // Here, we will try to find several new points nearer to aPnt2S. + + // The algorithm below tries to find two points in every + // intervals [u1 - aStepMax, u1] and [u1, u1 + aStepMax] + // and every new point will be in maximal distance from + // u1. If these two points exist they will be joined + // by the intersection curve. + const IntPatch_Point& aPnt2S = theSPnt.Value(aNbPnt); Standard_Real u1, v1, u2, v2; @@ -3436,81 +3452,331 @@ IntPatch_ImpImpIntersection::IntStatus IntCyCy(const IntSurf_Quadric& theQuad1, Handle(IntSurf_LineOn2S) aL2S = new IntSurf_LineOn2S(); Handle(IntPatch_WLine) aWLine = new IntPatch_WLine(aL2S, Standard_False); - aWLine->Curve()->Add(aPnt2S.PntOn2S()); //Define the index of WLine, which lies the point aPnt2S in. - Standard_Real anUf = 0.0, anUl = 0.0, aCurU2 = 0.0; Standard_Integer anIndex = 0; - if(isTheReverse) + + Standard_Real anUf = 0.0, anUl = 0.0, aCurU2 = 0.0; + if (isReversed) { anUf = Max(u2 - aStepMax, aUSurf1f); - anUl = u2; + anUl = Min(u2 + aStepMax, aUSurf1l); aCurU2 = u1; } else { anUf = Max(u1 - aStepMax, aUSurf1f); - anUl = u1; + anUl = Min(u1 + aStepMax, aUSurf1l); aCurU2 = u2; } - Standard_Real aDelta = RealLast(); - for (Standard_Integer i = 0; i < aNbWLines; i++) - { - Standard_Real anU2t = 0.0; - if(!ComputationMethods::CylCylComputeParameters(anUl, i, anEquationCoeffs, anU2t)) - continue; - const Standard_Real aDU2 = Abs(anU2t - aCurU2); - if(aDU2 < aDelta) + const Standard_Real anUinf = anUf, anUsup = anUl, anUmid = 0.5*(anUf + anUl); + + { + //Find the value of anIndex variable. + Standard_Real aDelta = RealLast(); + for (Standard_Integer i = 0; i < aNbWLines; i++) { - aDelta = aDU2; - anIndex = i; + Standard_Real anU2t = 0.0; + if (!ComputationMethods::CylCylComputeParameters(anUmid, i, anEquationCoeffs, anU2t)) + continue; + + Standard_Real aDU2 = fmod(Abs(anU2t - aCurU2), aPeriod); + aDU2 = Min(aDU2, Abs(aDU2 - aPeriod)); + if (aDU2 < aDelta) + { + aDelta = aDU2; + anIndex = i; + } } } - //Try to fill aWLine by additional points - while(anUl - anUf > RealSmall()) - { - Standard_Real anU2 = 0.0, anV1 = 0.0, anV2 = 0.0; - Standard_Boolean isDone = - ComputationMethods::CylCylComputeParameters(anUf, anIndex, anEquationCoeffs, - anU2, anV1, anV2); - anUf += aDU; + // Bisection method is used in order to find every new point. + // I.e. if we need to find intersection point in the interval [anUinf, anUmid] + // we check the point anUC = 0.5*(anUinf+anUmid). If it is an intersection point + // we try to find another point in the interval [anUinf, anUC] (because we find the point in + // maximal distance from anUmid). If it is not then we try to find another point in the + // interval [anUC, anUmid]. Next iterations will be made analogically. + // When we find intersection point in the interval [anUmid, anUsup] we try to find + // another point in the interval [anUC, anUsup] if anUC is intersection point and + // in the interval [anUmid, anUC], otherwise. + + Standard_Real anAddedPar[2] = { anUmid, anUmid }; - if(!isDone) + for (Standard_Integer aParID = 0; aParID < 2; aParID++) + { + if (aParID == 0) { - continue; + anUf = anUinf; + anUl = anUmid; + } + else // if(aParID == 1) + { + anUf = anUmid; + anUl = anUsup; } - if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse, - Standard_True, gp_Pnt2d(anUf, anV1), gp_Pnt2d(anU2, anV2), - aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, - aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, - aPeriod, aWLine->Curve(), anIndex, theTol3D, - theTol2D, Standard_False, Standard_True)) + Standard_Real &aPar1 = (aParID == 0) ? anUf : anUl, + &aPar2 = (aParID == 0) ? anUl : anUf; + + while (Abs(aPar2 - aPar1) > aStepMin) { - break; + Standard_Real anUC = 0.5*(anUf + anUl); + Standard_Real aU2 = 0.0, aV1 = 0.0, aV2 = 0.0; + Standard_Boolean isDone = ComputationMethods:: + CylCylComputeParameters(anUC, anIndex, anEquationCoeffs, aU2, aV1, aV2); + + if (isDone) + { + if (Abs(aV1 - aVSurf1f) <= aTol2D) + aV1 = aVSurf1f; + + if (Abs(aV1 - aVSurf1l) <= aTol2D) + aV1 = aVSurf1l; + + if (Abs(aV2 - aVSurf2f) <= aTol2D) + aV2 = aVSurf2f; + + if (Abs(aV2 - aVSurf2l) <= aTol2D) + aV2 = aVSurf2l; + + isDone = AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, + Standard_True, gp_Pnt2d(anUC, aV1), gp_Pnt2d(aU2, aV2), + aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, + aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, + aPeriod, aWLine->Curve(), anIndex, aTol3D, + aTol2D, Standard_False, Standard_True); + } + + if (isDone) + { + anAddedPar[0] = Min(anAddedPar[0], anUC); + anAddedPar[1] = Max(anAddedPar[1], anUC); + aPar2 = anUC; + } + else + { + aPar1 = anUC; + } } } - if(aWLine->NbPnts() > 1) + //Fill aWLine by additional points + if (anAddedPar[1] - anAddedPar[0] > aStepMin) { - SeekAdditionalPoints( theQuad1, theQuad2, aWLine->Curve(), + for (Standard_Integer aParID = 0; aParID < 2; aParID++) + { + Standard_Real aU2 = 0.0, aV1 = 0.0, aV2 = 0.0; + ComputationMethods::CylCylComputeParameters(anAddedPar[aParID], anIndex, + anEquationCoeffs, aU2, aV1, aV2); + + AddPointIntoWL(aQuad1, aQuad2, anEquationCoeffs, isReversed, Standard_True, + gp_Pnt2d(anAddedPar[aParID], aV1), gp_Pnt2d(aU2, aV2), + aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l, + aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aPeriod, aWLine->Curve(), + anIndex, aTol3D, aTol2D, Standard_False, Standard_False); + } + + SeekAdditionalPoints(aQuad1, aQuad2, aWLine->Curve(), anEquationCoeffs, anIndex, aNbMinPoints, - 1, aWLine->NbPnts(), theTol2D, aPeriod, - isTheReverse); + 1, aWLine->NbPnts(), aTol2D, aPeriod, + isReversed); - aWLine->ComputeVertexParameters(theTol3D); + aWLine->ComputeVertexParameters(aTol3D); theSlin.Append(aWLine); - + theSPnt.Remove(aNbPnt); aNbPnt--; } } - + return IntPatch_ImpImpIntersection::IntStatus_OK; } +//======================================================================= +//function : IntCyCy +//purpose : +//======================================================================= +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, + Standard_Boolean& isTheEmpty, + Standard_Boolean& isTheSameSurface, + Standard_Boolean& isTheMultiplePoint, + IntPatch_SequenceOfLine& theSlin, + IntPatch_SequenceOfPoint& theSPnt) +{ + isTheEmpty = Standard_True; + isTheSameSurface = Standard_False; + isTheMultiplePoint = Standard_False; + theSlin.Clear(); + theSPnt.Clear(); + + const gp_Cylinder aCyl1 = theQuad1.Cylinder(), + aCyl2 = theQuad2.Cylinder(); + + IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D); + + if (!anInter.IsDone()) + { + return IntPatch_ImpImpIntersection::IntStatus_Fail; + } + + if(anInter.TypeInter() != IntAna_NoGeometricSolution) + { + if (CyCyAnalyticalIntersect(theQuad1, theQuad2, anInter, + theTol3D, isTheEmpty, + isTheSameSurface, isTheMultiplePoint, + theSlin, theSPnt)) + { + return IntPatch_ImpImpIntersection::IntStatus_OK; + } + } + + //Here, intersection line is not an analytical curve(line, circle, ellipsis etc.) + + Standard_Real aUSBou[2][2], aVSBou[2][2]; //const + + theUVSurf1.Get(aUSBou[0][0], aVSBou[0][0], aUSBou[0][1], aVSBou[0][1]); + theUVSurf2.Get(aUSBou[1][0], aVSBou[1][0], aUSBou[1][1], aVSBou[1][1]); + + const Standard_Real aPeriod = 2.0*M_PI; + const Standard_Integer aNbWLines = 2; + + const ComputationMethods::stCoeffsValue anEquationCoeffs1(aCyl1, aCyl2); + const ComputationMethods::stCoeffsValue anEquationCoeffs2(aCyl2, aCyl1); + + //Boundaries. + //Intersection result can include two non-connected regions + //(see WorkWithBoundaries::BoundariesComputing(...) method). + const Standard_Integer aNbOfBoundaries = 2; + Bnd_Range anURange[2][aNbOfBoundaries]; //const + + if (!WorkWithBoundaries::BoundariesComputing(anEquationCoeffs1, aPeriod, anURange[0])) + return IntPatch_ImpImpIntersection::IntStatus_OK; + + if (!WorkWithBoundaries::BoundariesComputing(anEquationCoeffs2, aPeriod, anURange[1])) + return IntPatch_ImpImpIntersection::IntStatus_OK; + + //anURange[*] can be in different periodic regions in + //compare with First-Last surface. E.g. the surface + //is full cylinder [0, 2*PI] but anURange is [5, 7]. + //Trivial common range computation returns [5, 2*PI] and + //its summary length is 2*PI-5 == 1.28... only. That is wrong. + //This problem can be solved by the following + //algorithm: + // 1. split anURange[*] by the surface boundary; + // 2. shift every new range in order to inscribe it + // in [Ufirst, Ulast] of cylinder; + // 3. consider only common ranges between [Ufirst, Ulast] + // and new ranges. + // + // In above example, we obtain following: + // 1. two ranges: [5, 2*PI] and [2*PI, 7]; + // 2. after shifting: [5, 2*PI] and [0, 7-2*PI]; + // 3. Common ranges: ([5, 2*PI] and [0, 2*PI]) == [5, 2*PI], + // ([0, 7-2*PI] and [0, 2*PI]) == [0, 7-2*PI]; + // 4. Their summary length is (2*PI-5)+(7-2*PI-0)==7-5==2 ==> GOOD. + + Standard_Real aSumRange[2] = { 0.0, 0.0 }; + Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; + for (Standard_Integer aCID = 0; aCID < 2; aCID++) + { + anAlloc->Reset(); + NCollection_List aListOfRng(anAlloc); + + aListOfRng.Append(anURange[aCID][0]); + aListOfRng.Append(anURange[aCID][1]); + + const Standard_Real aSplitArr[3] = {aUSBou[aCID][0], aUSBou[aCID][1], 0.0}; + + NCollection_List::Iterator anITrRng; + for (Standard_Integer aSInd = 0; aSInd < 3; aSInd++) + { + NCollection_List aLstTemp(aListOfRng); + aListOfRng.Clear(); + for (anITrRng.Init(aLstTemp); anITrRng.More(); anITrRng.Next()) + { + Bnd_Range& aRng = anITrRng.Value(); + aRng.Split(aSplitArr[aSInd], aListOfRng, aPeriod); + } + } + + anITrRng.Init(aListOfRng); + for (; anITrRng.More(); anITrRng.Next()) + { + Bnd_Range& aCurrRange = anITrRng.Value(); + + Bnd_Range aBoundR; + aBoundR.Add(aUSBou[aCID][0]); + aBoundR.Add(aUSBou[aCID][1]); + + if (!InscribeInterval(aUSBou[aCID][0], aUSBou[aCID][1], + aCurrRange, theTol2D, aPeriod)) + { + //If aCurrRange does not have common block with + //[Ufirst, Ulast] of cylinder then we will try + //to inscribe [Ufirst, Ulast] in the boundaries of aCurrRange. + Standard_Real aF = 1.0, aL = 0.0; + if (!aCurrRange.GetBounds(aF, aL)) + continue; + + if ((aL < aUSBou[aCID][0])) + { + aCurrRange.Shift(aPeriod); + } + else if (aF > aUSBou[aCID][1]) + { + aCurrRange.Shift(-aPeriod); + } + } + + aBoundR.Common(aCurrRange); + + const Standard_Real aDelta = aBoundR.Delta(); + + if (aDelta > 0.0) + { + aSumRange[aCID] += aDelta; + } + } + } + + //The bigger range the bigger number of points in Walking-line (WLine) + //we will be able to add and consequently we will obtain more + //precise intersection line. + //Every point of WLine is determined as function from U1-parameter, + //where U1 is U-parameter on 1st quadric. + //Therefore, we should use quadric with bigger range as 1st parameter + //in IntCyCy() function. + //On the other hand, there is no point in reversing in case of + //analytical intersection (when result is line, ellipse, point...). + //This result is independent of the arguments order. + const Standard_Boolean isToReverse = (aSumRange[1] > aSumRange[0]); + + if (isToReverse) + { + const WorkWithBoundaries aBoundWork(theQuad2, theQuad1, anEquationCoeffs2, + theUVSurf2, theUVSurf1, aNbWLines, + aPeriod, theTol3D, theTol2D, Standard_True); + + return CyCyNoGeometric(aCyl2, aCyl1, aBoundWork, anURange[1], aNbOfBoundaries, + isTheEmpty, theSlin, theSPnt); + } + else + { + const WorkWithBoundaries aBoundWork(theQuad1, theQuad2, anEquationCoeffs1, + theUVSurf1, theUVSurf2, aNbWLines, + aPeriod, theTol3D, theTol2D, Standard_False); + + return CyCyNoGeometric(aCyl1, aCyl2, aBoundWork, anURange[0], aNbOfBoundaries, + isTheEmpty, theSlin, theSPnt); + } +} + //======================================================================= //function : IntCySp //purpose : diff --git a/src/IntPatch/IntPatch_Intersection.cxx b/src/IntPatch/IntPatch_Intersection.cxx index 6213b3541a..d1c3173570 100644 --- a/src/IntPatch/IntPatch_Intersection.cxx +++ b/src/IntPatch/IntPatch_Intersection.cxx @@ -1405,19 +1405,7 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the if((theTyps1 == GeomAbs_Cylinder) && (theTyps2 == GeomAbs_Cylinder)) { - IntPatch_WLineTool::JoinWLines( slin, spnt, TolTang, - theS1->IsUPeriodic()? theS1->UPeriod() : 0.0, - theS2->IsUPeriodic()? theS2->UPeriod() : 0.0, - theS1->IsVPeriodic()? theS1->VPeriod() : 0.0, - theS2->IsVPeriodic()? theS2->VPeriod() : 0.0, - theS1->FirstUParameter(), - theS1->LastUParameter(), - theS1->FirstVParameter(), - theS1->LastVParameter(), - theS2->FirstUParameter(), - theS2->LastUParameter(), - theS2->FirstVParameter(), - theS2->LastVParameter()); + IntPatch_WLineTool::JoinWLines(slin, spnt, theS1, theS2, TolTang); } if(isWLExist) diff --git a/src/IntPatch/IntPatch_WLineTool.cxx b/src/IntPatch/IntPatch_WLineTool.cxx index 5ac700ad08..78148f677a 100644 --- a/src/IntPatch/IntPatch_WLineTool.cxx +++ b/src/IntPatch/IntPatch_WLineTool.cxx @@ -15,9 +15,12 @@ #include #include +#include #include #include #include +#include +#include // It is pure empirical value. const Standard_Real IntPatch_WLineTool::myMaxConcatAngle = M_PI/6; @@ -483,64 +486,6 @@ static Handle(IntPatch_WLine) return MakeNewWLine(theWLine, aNewPointsHash); } -//======================================================================= -//function : IsOnPeriod -//purpose : Checks, if [theU1, theU2] intersects the period-value -// (k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...). -// -// Returns: -// 0 - if interval [theU1, theU2] does not intersect the "period-value" -// or if thePeriod == 0.0; -// 1 - if interval (theU1, theU2) intersect the "period-value". -// 2 - if theU1 or/and theU2 lie ON the "period-value" -// -//ATTENTION!!! -// If (theU1 == theU2) then this function will return only both 0 or 2. -//======================================================================= -static Standard_Integer IsOnPeriod(const Standard_Real theU1, - const Standard_Real theU2, - const Standard_Real thePeriod) -{ - if(thePeriod < RealSmall()) - return 0; - - //If interval [theU1, theU2] intersect seam-edge then there exists an integer - //number N such as - // (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T), - //where T is the period. - //I.e. the inerval [theU1/T, theU2/T] must contain at least one - //integer number. In this case, Floor(theU1/T) and Floor(theU2/T) - //return different values or theU1/T is strictly integer number. - //Examples: - // 1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3. - // 2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2. - - const Standard_Real aVal1 = theU1/thePeriod, - aVal2 = theU2/thePeriod; - const Standard_Integer aPar1 = static_cast(Floor(aVal1)); - const Standard_Integer aPar2 = static_cast(Floor(aVal2)); - if(aPar1 != aPar2) - {//Interval (theU1, theU2] intersects seam-edge - if(IsEqual(aVal2, static_cast(aPar2))) - {//aVal2 is an integer number => theU2 lies ON the "seam-edge" - return 2; - } - - return 1; - } - - //Here, aPar1 == aPar2. - - if(IsEqual(aVal1, static_cast(aPar1))) - {//aVal1 is an integer number => theU1 lies ON the "seam-edge" - return 2; - } - - //If aVal2 is a true integer number then always (aPar1 != aPar2). - - return 0; -} - //======================================================================= //function : IsSeamOrBound //purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge" @@ -550,128 +495,89 @@ static Standard_Integer IsOnPeriod(const Standard_Real theU1, // If thePtmid match "seam-edge" or boundaries strictly // (without any tolerance) then the function will return TRUE. // See comments in function body for detail information. +// +// Arrays theArrPeriods, theFBound and theLBound must be filled +// as follows: +// [0] - U-parameter of 1st surface; +// [1] - V-parameter of 1st surface; +// [2] - U-parameter of 2nd surface; +// [3] - V-parameter of 2nd surface. //======================================================================= static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf, const IntSurf_PntOn2S& thePtl, const IntSurf_PntOn2S& thePtmid, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - const Standard_Real theUfSurf1, - const Standard_Real theUlSurf1, - const Standard_Real theVfSurf1, - const Standard_Real theVlSurf1, - const Standard_Real theUfSurf2, - const Standard_Real theUlSurf2, - const Standard_Real theVfSurf2, - const Standard_Real theVlSurf2) + const Standard_Real theArrPeriods[4], + const Standard_Real theFBound[4], + const Standard_Real theLBound[4]) { - Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0; - Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0; - thePtf.Parameters(aU11, aV11, aU12, aV12); - thePtl.Parameters(aU21, aV21, aU22, aV22); - - MinMax(aU11, aU21); - MinMax(aV11, aV21); - MinMax(aU12, aU22); - MinMax(aV12, aV22); - - if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0) - {//Interval [aU11, aU21] intersects theUfSurf1 - return Standard_True; - } + Standard_Real aParF[4] = { 0.0, 0.0, 0.0, 0.0 }; + Standard_Real aParL[4] = { 0.0, 0.0, 0.0, 0.0 }; + thePtf.Parameters(aParF[0], aParF[1], aParF[2], aParF[3]); + thePtl.Parameters(aParL[0], aParL[1], aParL[2], aParL[3]); - if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0) - {//Interval [aU11, aU21] intersects theUlSurf1 - return Standard_True; - } + Bnd_Range aBndR[4]; - if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0) - {//Interval [aV11, aV21] intersects theVfSurf1 - return Standard_True; - } + for (Standard_Integer i = 0; i < 4; i++) + { + aBndR[i].Add(aParF[i]); + aBndR[i].Add(aParL[i]); - if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0) - {//Interval [aV11, aV21] intersects theVlSurf1 - return Standard_True; - } + if (aBndR[i].IsIntersected(theFBound[i], theArrPeriods[i]) == 1) + return Standard_True; - if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0) - {//Interval [aU12, aU22] intersects theUfSurf2 - return Standard_True; + if (aBndR[i].IsIntersected(theLBound[i], theArrPeriods[i]) == 1) + return Standard_True; } - if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0) - {//Interval [aU12, aU22] intersects theUlSurf2 - return Standard_True; - } + for (Standard_Integer i = 0; i < 4; i++) + { + if (theArrPeriods[i] == 0.0) + { + //Strictly equal + continue; + } - if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0) - {//Interval [aV12, aV22] intersects theVfSurf2 - return Standard_True; - } + const Standard_Real aDelta = Abs(aParL[i] - aParF[i]); + if (2.0*aDelta > theArrPeriods[i]) + { + //Most likely, seam is intersected. + return Standard_True; + } - if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0) - {//Interval [aV12, aV22] intersects theVlSurf2 - return Standard_True; + if (aBndR[i].IsIntersected(0.0, theArrPeriods[i]) == 1) + return Standard_True; } - if(IsOnPeriod(aU11, aU21, theU1Period)) - return Standard_True; - - if(IsOnPeriod(aV11, aV21, theV1Period)) - return Standard_True; - - if(IsOnPeriod(aU12, aU22, theU2Period)) - return Standard_True; + //The segment [thePtf, thePtl] does not intersect the boundaries and + //the seam-edge of the surfaces. + //Nevertheless, following situation is possible: - if(IsOnPeriod(aV12, aV22, theV2Period)) - return Standard_True; + // seam or + // bound + // | + // thePtf * | + // | + // * thePtmid + // thePtl * | + // | - /* - The segment [thePtf, thePtl] does not intersect the boundaries and - the seam-edge of the surfaces. - Nevertheless, following situation is possible: + //This case must be processed, too. - seam or - bound - | - thePtf * | - | - * thePtmid - thePtl * | - | + Standard_Real aMPar[4] = { 0.0, 0.0, 0.0, 0.0 }; + thePtmid.Parameters(aMPar[0], aMPar[1], aMPar[2], aMPar[3]); - This case must be processed, too. - */ - - Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0; - thePtmid.Parameters(aU1, aV1, aU2, aV2); - - if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1)) - return Standard_True; - - if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2)) - return Standard_True; - - if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1)) - return Standard_True; - - if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2)) - return Standard_True; - - if(IsOnPeriod(aU1, aU1, theU1Period)) - return Standard_True; - - if(IsOnPeriod(aU2, aU2, theU2Period)) - return Standard_True; + for (Standard_Integer i = 0; i < 4; i++) + { + const Bnd_Range aBR(aMPar[i], aMPar[i]); + if (aBR.IsIntersected(theFBound[i], theArrPeriods[i])) + return Standard_True; - if(IsOnPeriod(aV1, aV1, theV1Period)) - return Standard_True; + if (aBR.IsIntersected(theLBound[i], theArrPeriods[i])) + return Standard_True; - if(IsOnPeriod(aV2, aV2, theV2Period)) - return Standard_True; + if (aBR.IsIntersected(0.0, theArrPeriods[i])) + return Standard_True; + } return Standard_False; } @@ -919,59 +825,75 @@ static IntPatchWT_WLsConnectionType thePtWL2.Parameters(aParWL2[0], aParWL2[1], aParWL2[2], aParWL2[3]); theNewPoint.Parameters(aNewPar[0], aNewPar[1], aNewPar[2], aNewPar[3]); + Bnd_Range aR1, aR2; + Standard_Boolean isOnBoundary = Standard_False; for(Standard_Integer i = 0; i < 4; i++) { - if(IsOnPeriod(aParWL1[i] - aParLBC[i], aParWL2[i] - aParLBC[i], theArrPeriods[i])) + if (theArrPeriods[i] == 0.0) + { + //Strictly equal + continue; + } + + aR1.SetVoid(); + aR1.Add(aParWL1[i]); + aR1.Add(aParWL2[i]); + + if (aR1.IsIntersected(aParLBC[i],theArrPeriods[i])) { //Check, if we intersect surface boundary when we will extend Wline1 or Wline2 //to theNewPoint MinMax(aParWL1[i], aParWL2[i]); - if(theArrPeriods[i] > 0.0) + if(aNewPar[i] > aParWL2[i]) { - if(aNewPar[i] > aParWL2[i]) - { - //Source situation: - // - //---*---------------*------------*----- - // aParWL1[i] aParWL2[i] aNewPar[i] - // - //After possible adjusting: - // - //---*---------------*------------*----- - // aParWL1[i] aNewPar[i] aParWL2[i] - // - //Now we will be able to extend every WLine to - //aNewPar[i] to make them close to each other. - //However, it is necessary to add check if we - //intersect boundary. - const Standard_Real aPar = aParWL1[i] + + //Source situation: + // + //---*---------------*------------*----- + // aParWL1[i] aParWL2[i] aNewPar[i] + // + //After possible adjusting: + // + //---*---------------*------------*----- + // aParWL1[i] aNewPar[i] aParWL2[i] + // + //Now we will be able to extend every WLine to + //aNewPar[i] to make them close to each other. + //However, it is necessary to add check if we + //intersect boundary. + const Standard_Real aPar = aParWL1[i] + theArrPeriods[i]*Ceiling((aNewPar[i]-aParWL1[i])/theArrPeriods[i]); - aParWL1[i] = aParWL2[i]; - aParWL2[i] = aPar; - } - else if(aNewPar[i] < aParWL1[i]) - { - //See comments to main "if". - //Source situation: - // - //---*---------------*------------*----- - // aNewPar[i] aParWL1[i] aParWL2[i] - // - //After possible adjusting: - // - //---*---------------*------------*----- - // aParWL1[i] aNewPar[i] aParWL2[i] + aParWL1[i] = aParWL2[i]; + aParWL2[i] = aPar; + } + else if(aNewPar[i] < aParWL1[i]) + { + //See comments to main "if". + //Source situation: + // + //---*---------------*------------*----- + // aNewPar[i] aParWL1[i] aParWL2[i] + // + //After possible adjusting: + // + //---*---------------*------------*----- + // aParWL1[i] aNewPar[i] aParWL2[i] - const Standard_Real aPar = aParWL2[i] - + const Standard_Real aPar = aParWL2[i] - theArrPeriods[i]*Ceiling((aParWL2[i]-aNewPar[i])/theArrPeriods[i]); - aParWL2[i] = aParWL1[i]; - aParWL1[i] = aPar; - } + aParWL2[i] = aParWL1[i]; + aParWL1[i] = aPar; } - if( IsOnPeriod(aParWL1[i] - aParLBC[i], aNewPar[i] - aParLBC[i], theArrPeriods[i]) || - IsOnPeriod(aNewPar[i] - aParLBC[i], aParWL2[i] - aParLBC[i], theArrPeriods[i])) + aR1.SetVoid(); + aR2.SetVoid(); + aR1.Add(aParWL1[i]); + aR1.Add(aNewPar[i]); + aR2.Add(aNewPar[i]); + aR2.Add(aParWL2[i]); + + if (aR1.IsIntersected(aParLBC[i], theArrPeriods[i]) || + aR2.IsIntersected(aParLBC[i], theArrPeriods[i])) { return IntPatchWT_NotConnected; } @@ -995,13 +917,15 @@ static IntPatchWT_WLsConnectionType //purpose : Check if joining is possible // (see IntPatch_WLineTool::JoinWLines(...)) //======================================================================= -Standard_Boolean CheckArgumentsToJoin(const gp_Vec& theVec1, - const gp_Vec& theVec2) +Standard_Boolean CheckArgumentsToJoin(const Handle(Adaptor3d_HSurface)& theS1, + const Handle(Adaptor3d_HSurface)& theS2, + const IntSurf_PntOn2S& thePnt, + const Standard_Real theMinRad) { - // [0, PI] - range - const Standard_Real anAngle = theVec1.Angle(theVec2); + const Standard_Real aRad = + IntPatch_PointLine::CurvatureRadiusOfIntersLine(theS1, theS2, thePnt); - return (anAngle < IntPatch_WLineTool::myMaxConcatAngle); + return (aRad > theMinRad); } //======================================================================= @@ -1415,33 +1339,38 @@ Handle(IntPatch_WLine) IntPatch_WLineTool:: return aResult; } - //======================================================================= //function : JoinWLines //purpose : //======================================================================= void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin, IntPatch_SequenceOfPoint& theSPnt, - const Standard_Real theTol3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - const Standard_Real theUfSurf1, - const Standard_Real theUlSurf1, - const Standard_Real theVfSurf1, - const Standard_Real theVlSurf1, - const Standard_Real theUfSurf2, - const Standard_Real theUlSurf2, - const Standard_Real theVfSurf2, - const Standard_Real theVlSurf2) + Handle(Adaptor3d_HSurface) theS1, + Handle(Adaptor3d_HSurface) theS2, + const Standard_Real theTol3D) { if(theSlin.Length() == 0) return; - for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++) + // For two cylindrical surfaces only + const Standard_Real aMinRad = 1.0e-3*Min(theS1->Cylinder().Radius(), + theS2->Cylinder().Radius()); + + const Standard_Real anArrPeriods[4] = {theS1->IsUPeriodic() ? theS1->UPeriod() : 0.0, + theS1->IsVPeriodic() ? theS1->VPeriod() : 0.0, + theS2->IsUPeriodic() ? theS2->UPeriod() : 0.0, + theS2->IsVPeriodic() ? theS2->VPeriod() : 0.0}; + + const Standard_Real anArrFBonds[4] = {theS1->FirstUParameter(), theS1->FirstVParameter(), + theS2->FirstUParameter(), theS2->FirstVParameter()}; + const Standard_Real anArrLBonds[4] = {theS1->LastUParameter(), theS1->LastVParameter(), + theS2->LastUParameter(), theS2->LastVParameter()}; + + Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator(); + + for(Standard_Integer aN1 = 1; aN1 <= theSlin.Length(); aN1++) { - Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1))); + Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN1))); if(aWLine1.IsNull()) {//We must have failed to join not-point-lines @@ -1449,184 +1378,169 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin, } const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts(); - const IntSurf_PntOn2S& aPntFW1 = aWLine1->Point(1); - const IntSurf_PntOn2S& aPntLW1 = aWLine1->Point(aNbPntsWL1); + const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1); + const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1); for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++) { const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S(); - if( aPntCur.IsSame(aPntFW1, Precision::Confusion()) || - aPntCur.IsSame(aPntLW1, Precision::Confusion())) + if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) || + aPntCur.IsSame(aPntLWL1, Precision::Confusion())) { theSPnt.Remove(aNPt); aNPt--; } } - Standard_Boolean hasBeenRemoved = Standard_False; - for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++) + anAlloc->Reset(); + NCollection_List aListFC(anAlloc), + aListLC(anAlloc); + + Standard_Boolean isFirstConnected = Standard_False, isLastConnected = Standard_False; + + for (Standard_Integer aN2 = 1; aN2 <= theSlin.Length(); aN2++) { - Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2))); + if (aN2 == aN1) + continue; - if(aWLine2.IsNull()) + Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN2))); + + if (aWLine2.IsNull()) continue; - const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts(); + isFirstConnected = isLastConnected = Standard_False; - const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1); - const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1); + const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts(); const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1); const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2); - if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion())) + Standard_Real aSqDistF = aPntFWL1.Value().SquareDistance(aPntFWL2.Value()); + Standard_Real aSqDistL = aPntFWL1.Value().SquareDistance(aPntLWL2.Value()); + + const Standard_Real aSqMinFDist = Min(aSqDistF, aSqDistL); + if (aSqMinFDist < Precision::SquareConfusion()) { - const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2); - const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2); - - Standard_Boolean aCond = - CheckArgumentsToJoin(gp_Vec(aPntFWL1.Value(), aPt1.Value()), - gp_Vec(aPt2.Value(), aPntFWL2.Value())); - - aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntFWL1, - theU1Period, theU2Period, - theV1Period, theV2Period, - theUfSurf1, theUlSurf1, - theVfSurf1, theVlSurf1, - theUfSurf2, theUlSurf2, - theVfSurf2, theVlSurf2); - - if(aCond) + if (CheckArgumentsToJoin(theS1, theS2, aPntFWL1, aMinRad)) { - aWLine1->ClearVertexes(); - for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++) + const Standard_Boolean isFM = (aSqDistF < aSqDistL); + const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2); + const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) : + aWLine2->Point(aNbPntsWL2 - 1); + + if (!IsSeamOrBound(aPt1, aPt2, aPntFWL1, + anArrPeriods, anArrFBonds, anArrLBonds)) { - const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); - aWLine1->Curve()->InsertBefore(1, aPt); + isFirstConnected = Standard_True; } - - aWLine1->ComputeVertexParameters(theTol3D); - - theSlin.Remove(aNumOfLine2); - aNumOfLine2--; - hasBeenRemoved = Standard_True; - - continue; } } - if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion())) + aSqDistF = aPntLWL1.Value().SquareDistance(aPntFWL2.Value()); + aSqDistL = aPntLWL1.Value().SquareDistance(aPntLWL2.Value()); + + const Standard_Real aSqMinLDist = Min(aSqDistF, aSqDistL); + if (aSqMinLDist < Precision::SquareConfusion()) { - const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2); - const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1); - - Standard_Boolean aCond = - CheckArgumentsToJoin(gp_Vec(aPntFWL1.Value(), aPt1.Value()), - gp_Vec(aPt2.Value(), aPntLWL2.Value())); - - aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntFWL1, - theU1Period, theU2Period, - theV1Period, theV2Period, - theUfSurf1, theUlSurf1, - theVfSurf1, theVlSurf1, - theUfSurf2, theUlSurf2, - theVfSurf2, theVlSurf2); - - if(aCond) + if (CheckArgumentsToJoin(theS1, theS2, aPntLWL1, aMinRad)) { - aWLine1->ClearVertexes(); - for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--) + const Standard_Boolean isFM = (aSqDistF < aSqDistL); + const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1); + const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) : + aWLine2->Point(aNbPntsWL2 - 1); + + if (!IsSeamOrBound(aPt1, aPt2, aPntLWL1, + anArrPeriods, anArrFBonds, anArrLBonds)) { - const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); - aWLine1->Curve()->InsertBefore(1, aPt); + isLastConnected = Standard_True; } - - aWLine1->ComputeVertexParameters(theTol3D); - - theSlin.Remove(aNumOfLine2); - aNumOfLine2--; - hasBeenRemoved = Standard_True; - - continue; } } - if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion())) + if (isFirstConnected && isLastConnected) { - const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1); - const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2); - - Standard_Boolean aCond = - CheckArgumentsToJoin(gp_Vec(aPt1.Value(), aPntLWL1.Value()), - gp_Vec(aPntFWL2.Value(), aPt2.Value())); - - aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntLWL1, - theU1Period, theU2Period, - theV1Period, theV2Period, - theUfSurf1, theUlSurf1, - theVfSurf1, theVlSurf1, - theUfSurf2, theUlSurf2, - theVfSurf2, theVlSurf2); - - if(aCond) + if (aSqMinFDist < aSqMinLDist) { - aWLine1->ClearVertexes(); - for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++) - { - const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); - aWLine1->Curve()->Add(aPt); - } + aListFC.Append(aN2); + } + else + { + aListLC.Append(aN2); + } + } + else if (isFirstConnected) + { + aListFC.Append(aN2); + } + else if (isLastConnected) + { + aListLC.Append(aN2); + } + } + + isFirstConnected = (aListFC.Extent() == 1); + isLastConnected = (aListLC.Extent() == 1); + + if (!(isFirstConnected || isLastConnected)) + { + continue; + } - aWLine1->ComputeVertexParameters(theTol3D); + const Standard_Integer anIndexWL2 = isFirstConnected ? aListFC.First() : aListLC.First(); + Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(anIndexWL2))); + + const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts(); + const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1); - theSlin.Remove(aNumOfLine2); - aNumOfLine2--; - hasBeenRemoved = Standard_True; + aWLine1->ClearVertexes(); - continue; + if (isFirstConnected) + { + if (aPntFWL1.IsSame(aPntFWL2, Precision::Confusion())) + { + //First-First-connection + for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++) + { + const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); + aWLine1->Curve()->InsertBefore(1, aPt); } } - - if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion())) + else { - const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1); - const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1); - - Standard_Boolean aCond = - CheckArgumentsToJoin(gp_Vec(aPt1.Value(), aPntLWL1.Value()), - gp_Vec(aPntLWL2.Value(), aPt2.Value())); - - aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntLWL1, - theU1Period, theU2Period, - theV1Period, theV2Period, - theUfSurf1, theUlSurf1, - theVfSurf1, theVlSurf1, - theUfSurf2, theUlSurf2, - theVfSurf2, theVlSurf2); - - if(aCond) + //First-Last-connection + for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--) { - aWLine1->ClearVertexes(); - for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--) - { - const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); - aWLine1->Curve()->Add(aPt); - } - - aWLine1->ComputeVertexParameters(theTol3D); - - theSlin.Remove(aNumOfLine2); - aNumOfLine2--; - hasBeenRemoved = Standard_True; - - continue; + const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); + aWLine1->Curve()->InsertBefore(1, aPt); + } + } + } + else //if (isLastConnected) + { + if (aPntLWL1.IsSame(aPntFWL2, Precision::Confusion())) + { + //Last-First connection + for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++) + { + const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); + aWLine1->Curve()->Add(aPt); + } + } + else + { + //Last-Last connection + for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--) + { + const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt); + aWLine1->Curve()->Add(aPt); } } } - if(hasBeenRemoved) - aNumOfLine1--; + aWLine1->ComputeVertexParameters(theTol3D); + theSlin.Remove(anIndexWL2); + aN1--; } } diff --git a/src/IntPatch/IntPatch_WLineTool.hxx b/src/IntPatch/IntPatch_WLineTool.hxx index 9a40853f9b..6f72a222a9 100644 --- a/src/IntPatch/IntPatch_WLineTool.hxx +++ b/src/IntPatch/IntPatch_WLineTool.hxx @@ -14,9 +14,10 @@ #ifndef _IntPatch_WLineTool_HeaderFile #define _IntPatch_WLineTool_HeaderFile +#include + #include #include -#include class Adaptor3d_TopolTool; @@ -59,20 +60,9 @@ public: //! this point will be deleted. Standard_EXPORT static void JoinWLines(IntPatch_SequenceOfLine& theSlin, IntPatch_SequenceOfPoint& theSPnt, - const Standard_Real theTol3D, - const Standard_Real theU1Period, - const Standard_Real theU2Period, - const Standard_Real theV1Period, - const Standard_Real theV2Period, - const Standard_Real theUfSurf1, - const Standard_Real theUlSurf1, - const Standard_Real theVfSurf1, - const Standard_Real theVlSurf1, - const Standard_Real theUfSurf2, - const Standard_Real theUlSurf2, - const Standard_Real theVfSurf2, - const Standard_Real theVlSurf2); - + Handle(Adaptor3d_HSurface) theS1, + Handle(Adaptor3d_HSurface) theS2, + const Standard_Real theTol3D); //! Extends every line from theSlin (if it is possible) to be started/finished //! in strictly determined point (in the place of joint of two lines). @@ -80,7 +70,8 @@ public: //! The Walking lines are supposed (algorithm will do nothing for not-Walking line) //! to be computed as a result of intersection. Both theS1 and theS2 //! must be quadrics. Other cases are not supported. -//! theArrPeriods must be filled as follows: +//! theArrPeriods must be filled as follows (every value must not be negative; +//! if the surface is not periodic the period must be equal to 0.0 strictly): //! {, , //! , }. Standard_EXPORT static void diff --git a/tests/bugs/modalg_5/bug24915 b/tests/bugs/modalg_5/bug24915 index b7a3688064..2c25dd4e91 100755 --- a/tests/bugs/modalg_5/bug24915 +++ b/tests/bugs/modalg_5/bug24915 @@ -25,17 +25,26 @@ checkshape r # 2. geometry set MaxTol 1.0e-7 +set GoodNBCurv 3 + set log [bopcurves b1 b2 -2d] if { ! [regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv] } { puts "Error: Cannot find tolerance value in output of bopcurve command" } +if { $NbCurv != $GoodNBCurv } { + puts "Error: Number of curves is wrong!" +} + if {${Toler} > ${MaxTol}} { puts "Error: Tolerance is too big!" } smallview -donly b2 c_2 -fit -checkview -screenshot -2d -path ${imagedir}/${test_image}.png + +for {set i 1} {$i <= $GoodNBCurv} {incr i} { + donly b2 c_$i + fit + checkview -screenshot -2d -path ${imagedir}/${test_image}_$i.png +} diff --git a/tests/bugs/modalg_5/bug25292_11 b/tests/bugs/modalg_5/bug25292_11 index d23102021c..de9171d948 100644 --- a/tests/bugs/modalg_5/bug25292_11 +++ b/tests/bugs/modalg_5/bug25292_11 @@ -44,38 +44,23 @@ if {${NbCurv} != ${GoodNbCurv}} { #------------- -# 1 puts "" mksurface s1 f1 mksurface s2 f2 for {set i 1} {$i <= ${NbCurv}} {incr i} { - set log [dump c_$i] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 - - puts "U1=${U1}" - puts "U2=${U2}" + bounds c_$i U1 U2 + + puts "U2=[dval U1]" + puts "U2=[dval U2]" - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs c_$i s1 ${U1} ${U2} 10 1e-7 - xdistcs c_$i s2 ${U1} ${U2} 10 1e-7 + xdistcs c_$i s1 U1 U2 10 ${Toler} + xdistcs c_$i s2 U1 U2 10 ${Toler} } v2d diff --git a/tests/bugs/modalg_5/bug25292_12 b/tests/bugs/modalg_5/bug25292_12 index 264b1abeb0..61e028aa8f 100644 --- a/tests/bugs/modalg_5/bug25292_12 +++ b/tests/bugs/modalg_5/bug25292_12 @@ -44,38 +44,23 @@ if {${NbCurv} != ${GoodNbCurv}} { #------------- -# 1 puts "" mksurface s1 f1 mksurface s2 f2 for {set i 1} {$i <= ${NbCurv}} {incr i} { - set log [dump c_$i] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 - - puts "U1=${U1}" - puts "U2=${U2}" + bounds c_$i U1 U2 + + puts "U2=[dval U1]" + puts "U2=[dval U2]" - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs c_$i s1 ${U1} ${U2} 10 1e-7 - xdistcs c_$i s2 ${U1} ${U2} 10 1e-7 + xdistcs c_$i s1 U1 U2 10 ${Toler} + xdistcs c_$i s2 U1 U2 10 ${Toler} } v2d diff --git a/tests/bugs/modalg_5/bug25292_15 b/tests/bugs/modalg_5/bug25292_15 index fe414df1eb..efc2c8364d 100644 --- a/tests/bugs/modalg_5/bug25292_15 +++ b/tests/bugs/modalg_5/bug25292_15 @@ -6,27 +6,6 @@ puts "" # Face/Face intersection algorithm gives different results for different order of the arguments ####################################################################### -proc GetRange { curve } { - global U1 - global U2 - - set log [uplevel dump $curve] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 -} - puts "##############################" puts "#!!!Search \"Attention\" keyword on this web-page for additional checking!!!" puts "##############################" @@ -51,62 +30,42 @@ mksurface s2 f2 ################# intersect res s1 s2 ################# + set che [whatis res] set ind [string first "3d curve" $che] if {${ind} >= 0} { #Only variable "res" exists - - if { $GoodNbCurv == 1 } { - puts "OK: Curve Number is good!" + renamevar res res_1 +} + +set ic 1 +set AllowRepeate 1 +while { $AllowRepeate != 0 } { + set che [whatis res_$ic] + set ind [string first "3d curve" $che] + if {${ind} < 0} { + set AllowRepeate 0 } else { - puts "Error: Curve Number is bad!" + display res_$ic + + bounds res_$ic U1 U2 + + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { + puts "Error: Wrong curve's range!" + } + + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 + + incr ic } - - set U1 0.0 - set U2 0.0 - - GetRange res - - puts "U1 = ${U1}" - puts "U2 = ${U2}" +} - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res s1 ${U1} ${U2} 10 1e-7 - xdistcs res s2 ${U1} ${U2} 10 1e-7 +if {[expr {$ic - 1}] == $GoodNbCurv} { + puts "OK: Curve Number is good!" } else { - set ic 1 - set AllowRepeate 1 - while { $AllowRepeate != 0 } { - set che [whatis res_$ic] - set ind [string first "3d curve" $che] - if {${ind} < 0} { - set AllowRepeate 0 - } else { - set U1 0.0 - set U2 0.0 - - GetRange res_$ic - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res_$ic s1 ${U1} ${U2} 10 1e-7 - xdistcs res_$ic s2 0 1 10 1e-7 - - incr ic - } - } - - if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" - } + puts "Error: Curve Number is bad!" } diff --git a/tests/bugs/modalg_5/bug25292_16 b/tests/bugs/modalg_5/bug25292_16 index 7eaf3a70d0..8f791a4d29 100644 --- a/tests/bugs/modalg_5/bug25292_16 +++ b/tests/bugs/modalg_5/bug25292_16 @@ -6,27 +6,6 @@ puts "" # Face/Face intersection algorithm gives different results for different order of the arguments ####################################################################### -proc GetRange { curve } { - global U1 - global U2 - - set log [uplevel dump $curve] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 -} - puts "##############################" puts "#!!!Search \"Attention\" keyword on this web-page for additional checking!!!" puts "##############################" @@ -56,58 +35,37 @@ set che [whatis res] set ind [string first "3d curve" $che] if {${ind} >= 0} { #Only variable "res" exists - - if { $GoodNbCurv == 1 } { - puts "OK: Curve Number is good!" + renamevar res res_1 +} + +set ic 1 +set AllowRepeate 1 +while { $AllowRepeate != 0 } { + set che [whatis res_$ic] + set ind [string first "3d curve" $che] + if {${ind} < 0} { + set AllowRepeate 0 } else { - puts "Error: Curve Number is bad!" + display res_$ic + + bounds res_$ic U1 U2 + + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { + puts "Error: Wrong curve's range!" + } + + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 + + incr ic } - - set U1 0.0 - set U2 0.0 - - GetRange res - - puts "U1 = ${U1}" - puts "U2 = ${U2}" +} - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res s1 ${U1} ${U2} 10 1e-7 - xdistcs res s2 ${U1} ${U2} 10 1e-7 +if {[expr {$ic - 1}] == $GoodNbCurv} { + puts "OK: Curve Number is good!" } else { - set ic 1 - set AllowRepeate 1 - while { $AllowRepeate != 0 } { - set che [whatis res_$ic] - set ind [string first "3d curve" $che] - if {${ind} < 0} { - set AllowRepeate 0 - } else { - set U1 0.0 - set U2 0.0 - - GetRange res_$ic - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res_$ic s1 ${U1} ${U2} 10 1e-7 - xdistcs res_$ic s2 0 1 10 1e-7 - - incr ic - } - } - - if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" - } + puts "Error: Curve Number is bad!" } diff --git a/tests/bugs/modalg_5/bug25292_21 b/tests/bugs/modalg_5/bug25292_21 index fefe9698ea..516f96dac4 100644 --- a/tests/bugs/modalg_5/bug25292_21 +++ b/tests/bugs/modalg_5/bug25292_21 @@ -44,35 +44,23 @@ if {${NbCurv} != ${GoodNbCurv}} { #------------- +puts "" + mksurface s1 f1 mksurface s2 f2 for {set i 1} {$i <= ${NbCurv}} {incr i} { - set log [dump c_$i] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 - - puts "U1=${U1}" - puts "U2=${U2}" + bounds c_$i U1 U2 + + puts "U2=[dval U1]" + puts "U2=[dval U2]" - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs c_$i s1 ${U1} ${U2} 10 1e-7 - xdistcs c_$i s2 ${U1} ${U2} 10 1e-7 + xdistcs c_$i s1 U1 U2 10 ${Toler} + xdistcs c_$i s2 U1 U2 10 ${Toler} } smallview diff --git a/tests/bugs/modalg_5/bug25292_22 b/tests/bugs/modalg_5/bug25292_22 index 9f59bd0a01..b641b0a3b5 100644 --- a/tests/bugs/modalg_5/bug25292_22 +++ b/tests/bugs/modalg_5/bug25292_22 @@ -44,35 +44,23 @@ if {${NbCurv} != ${GoodNbCurv}} { #------------- +puts "" + mksurface s1 f1 mksurface s2 f2 for {set i 1} {$i <= ${NbCurv}} {incr i} { - set log [dump c_$i] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 - - puts "U1=${U1}" - puts "U2=${U2}" + bounds c_$i U1 U2 + + puts "U2=[dval U1]" + puts "U2=[dval U2]" - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs c_$i s1 ${U1} ${U2} 10 1e-7 - xdistcs c_$i s2 ${U1} ${U2} 10 1e-7 + xdistcs c_$i s1 U1 U2 10 ${Toler} + xdistcs c_$i s2 U1 U2 10 ${Toler} } smallview diff --git a/tests/bugs/modalg_5/bug25292_25 b/tests/bugs/modalg_5/bug25292_25 index ac1987c964..dd0effa35a 100644 --- a/tests/bugs/modalg_5/bug25292_25 +++ b/tests/bugs/modalg_5/bug25292_25 @@ -6,27 +6,6 @@ puts "" # Face/Face intersection algorithm gives different results for different order of the arguments ####################################################################### -proc GetRange { curve } { - global U1 - global U2 - - set log [uplevel dump $curve] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 -} - puts "##############################" puts "#!!!Search \"Attention\" keyword on this web-page for additional checking!!!" puts "##############################" @@ -56,59 +35,37 @@ set che [whatis res] set ind [string first "3d curve" $che] if {${ind} >= 0} { #Only variable "res" exists - - if { $GoodNbCurv == 1 } { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" - } - - set U1 0.0 - set U2 0.0 - - GetRange res - - puts "U1 = ${U1}" - puts "U2 = ${U2}" + renamevar res res_1 +} - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res s1 ${U1} ${U2} 10 1e-7 - xdistcs res s2 ${U1} ${U2} 10 1e-7 -} else { - set ic 1 - set AllowRepeate 1 - while { $AllowRepeate != 0 } { - set che [whatis res_$ic] - set ind [string first "3d curve" $che] - if {${ind} < 0} { - set AllowRepeate 0 - } else { - set U1 0.0 - set U2 0.0 - - GetRange res_$ic - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res_$ic s1 ${U1} ${U2} 10 1e-7 - xdistcs res_$ic s2 0 1 10 1e-7 - - incr ic - } - } - - if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Curve Number is good!" +set ic 1 +set AllowRepeate 1 +while { $AllowRepeate != 0 } { + set che [whatis res_$ic] + set ind [string first "3d curve" $che] + if {${ind} < 0} { + set AllowRepeate 0 } else { - puts "Error: Curve Number is bad!" + display res_$ic + + bounds res_$ic U1 U2 + + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { + puts "Error: Wrong curve's range!" + } + + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 + + incr ic } } +if {[expr {$ic - 1}] == $GoodNbCurv} { + puts "OK: Curve Number is good!" +} else { + puts "Error: Curve Number is bad!" +} diff --git a/tests/bugs/modalg_5/bug25292_26 b/tests/bugs/modalg_5/bug25292_26 index 332ec45114..0a75614d86 100644 --- a/tests/bugs/modalg_5/bug25292_26 +++ b/tests/bugs/modalg_5/bug25292_26 @@ -6,27 +6,6 @@ puts "" # Face/Face intersection algorithm gives different results for different order of the arguments ####################################################################### -proc GetRange { curve } { - global U1 - global U2 - - set log [uplevel dump $curve] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 -} - puts "##############################" puts "#!!!Search \"Attention\" keyword on this web-page for additional checking!!!" puts "##############################" @@ -56,58 +35,37 @@ set che [whatis res] set ind [string first "3d curve" $che] if {${ind} >= 0} { #Only variable "res" exists - - if { $GoodNbCurv == 1 } { - puts "OK: Curve Number is good!" + renamevar res res_1 +} + +set ic 1 +set AllowRepeate 1 +while { $AllowRepeate != 0 } { + set che [whatis res_$ic] + set ind [string first "3d curve" $che] + if {${ind} < 0} { + set AllowRepeate 0 } else { - puts "Error: Curve Number is bad!" + display res_$ic + + bounds res_$ic U1 U2 + + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { + puts "Error: Wrong curve's range!" + } + + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 + + incr ic } - - set U1 0.0 - set U2 0.0 - - GetRange res - - puts "U1 = ${U1}" - puts "U2 = ${U2}" +} - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res s1 ${U1} ${U2} 10 1e-7 - xdistcs res s2 ${U1} ${U2} 10 1e-7 +if {[expr {$ic - 1}] == $GoodNbCurv} { + puts "OK: Curve Number is good!" } else { - set ic 1 - set AllowRepeate 1 - while { $AllowRepeate != 0 } { - set che [whatis res_$ic] - set ind [string first "3d curve" $che] - if {${ind} < 0} { - set AllowRepeate 0 - } else { - set U1 0.0 - set U2 0.0 - - GetRange res_$ic - - puts "U1 = ${U1}" - puts "U2 = ${U2}" - - if {[expr {$U2 - $U1}] < 1.0e-20} { - puts "Error: Wrong curve's range!" - } - - xdistcs res_$ic s1 ${U1} ${U2} 10 1e-7 - xdistcs res_$ic s2 0 1 10 1e-7 - - incr ic - } - } - - if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Curve Number is good!" - } else { - puts "Error: Curve Number is bad!" - } + puts "Error: Curve Number is bad!" } diff --git a/tests/bugs/modalg_5/bug25292_31 b/tests/bugs/modalg_5/bug25292_31 index c081b07961..b807823edd 100644 --- a/tests/bugs/modalg_5/bug25292_31 +++ b/tests/bugs/modalg_5/bug25292_31 @@ -38,35 +38,23 @@ if {${NbCurv} != ${GoodNbCurv}} { #------------- +puts "" + mksurface s1 f1 mksurface s2 f2 for {set i 1} {$i <= ${NbCurv}} {incr i} { - set log [dump c_$i] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 + bounds c_$i U1 U2 - puts "U1=${U1}" - puts "U2=${U2}" + puts "U2=[dval U1]" + puts "U2=[dval U2]" - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs c_$i s1 ${U1} ${U2} 10 1e-7 1e-8 - xdistcs c_$i s2 ${U1} ${U2} 10 1e-7 1e-8 + xdistcs c_$i s1 U1 U2 10 ${Toler} + xdistcs c_$i s2 U1 U2 10 ${Toler} } smallview diff --git a/tests/bugs/modalg_5/bug25292_32 b/tests/bugs/modalg_5/bug25292_32 index 9b1e241a2b..04a5a0e620 100644 --- a/tests/bugs/modalg_5/bug25292_32 +++ b/tests/bugs/modalg_5/bug25292_32 @@ -38,35 +38,23 @@ if {${NbCurv} != ${GoodNbCurv}} { #------------- +puts "" + mksurface s1 f1 mksurface s2 f2 for {set i 1} {$i <= ${NbCurv}} {incr i} { - set log [dump c_$i] - - regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles - puts "Degree=${Degree}" - puts "Poles=${Poles}" - puts "KnotsPoles=${KnotsPoles}" - puts "" - - set Knot 1 - set exp_string "Knots :\n\n +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U1 Mult1 - - set Knot ${KnotsPoles} - set exp_string " +${Knot} : +(\[-0-9.+eE\]+) +(\[-0-9.+eE\]+)" - regexp ${exp_string} ${log} full U2 Mult2 + bounds c_$i U1 U2 - puts "U1=${U1}" - puts "U2=${U2}" + puts "U2=[dval U1]" + puts "U2=[dval U2]" - if {[expr {$U2 - $U1}] < 1.0e-20} { + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs c_$i s1 ${U1} ${U2} 10 1e-7 1e-8 - xdistcs c_$i s2 ${U1} ${U2} 10 1e-7 1e-8 + xdistcs c_$i s1 U1 U2 10 ${Toler} + xdistcs c_$i s2 U1 U2 10 ${Toler} } smallview diff --git a/tests/bugs/modalg_5/bug25292_33 b/tests/bugs/modalg_5/bug25292_33 index 4c9a5cafb3..4dc56b478e 100644 --- a/tests/bugs/modalg_5/bug25292_33 +++ b/tests/bugs/modalg_5/bug25292_33 @@ -28,37 +28,39 @@ intersect res s1 s2 set che [whatis res] set ind [string first "3d curve" $che] - -set AllowRepeate 1 -set ic 1 - if {${ind} >= 0} { #Only variable "res" exists renamevar res res_1 } +set ic 1 +set AllowRepeate 1 while { $AllowRepeate != 0 } { set che [whatis res_$ic] set ind [string first "3d curve" $che] if {${ind} < 0} { set AllowRepeate 0 - break - } - - bounds res_$ic U1 U2 - - if {[dval (U2-U1)] < 1.0e-20} { - puts "Error: Wrong curve's range!" + } else { + display res_$ic + + bounds res_$ic U1 U2 + + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { + puts "Error: Wrong curve's range!" + } + + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 + + incr ic } - - xdistcs res_$ic s1 U1 U2 10 1e-6 1e-7 - xdistcs res_$ic s2 U1 U2 10 1e-6 1e-7 - - incr ic } - + if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Good number of intersection curve(s) obtained by Surface/Surface Intersection Algorithm" + puts "OK: Curve Number is good!" } else { - puts "Error: $GoodNbCurv intersection curve(s) expected but [expr {$ic - 1}] found" -} \ No newline at end of file + puts "Error: Curve Number is bad!" +} diff --git a/tests/bugs/modalg_5/bug25292_34 b/tests/bugs/modalg_5/bug25292_34 index 9d23d65990..628a446c4f 100644 --- a/tests/bugs/modalg_5/bug25292_34 +++ b/tests/bugs/modalg_5/bug25292_34 @@ -29,37 +29,39 @@ intersect res s2 s1 set che [whatis res] set ind [string first "3d curve" $che] - -set AllowRepeate 1 -set ic 1 - if {${ind} >= 0} { #Only variable "res" exists renamevar res res_1 } +set ic 1 +set AllowRepeate 1 while { $AllowRepeate != 0 } { set che [whatis res_$ic] set ind [string first "3d curve" $che] if {${ind} < 0} { set AllowRepeate 0 - break - } - - bounds res_$ic U1 U2 - - if {[dval (U2-U1)] < 1.0e-20} { - puts "Error: Wrong curve's range!" + } else { + display res_$ic + + bounds res_$ic U1 U2 + + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { + puts "Error: Wrong curve's range!" + } + + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 + + incr ic } - - xdistcs res_$ic s1 U1 U2 10 1e-6 1e-7 - xdistcs res_$ic s2 U1 U2 10 1e-6 1e-7 - - incr ic } - + if {[expr {$ic - 1}] == $GoodNbCurv} { - puts "OK: Good number of intersection curve(s) obtained by Surface/Surface Intersection Algorithm" + puts "OK: Curve Number is good!" } else { - puts "Error: $GoodNbCurv intersection curve(s) expected but [expr {$ic - 1}] found" -} \ No newline at end of file + puts "Error: Curve Number is bad!" +} diff --git a/tests/bugs/modalg_5/bug25292_35 b/tests/bugs/modalg_5/bug25292_35 index aaea2c2c5a..fd20ff2330 100644 --- a/tests/bugs/modalg_5/bug25292_35 +++ b/tests/bugs/modalg_5/bug25292_35 @@ -37,8 +37,7 @@ set che [whatis res] set ind [string first "3d curve" $che] if {${ind} >= 0} { #Only variable "res" exists - - copy res res_1 + renamevar res res_1 } set ic 1 @@ -49,26 +48,24 @@ while { $AllowRepeate != 0 } { if {${ind} < 0} { set AllowRepeate 0 } else { - set le [length res_$ic] - regexp "The length res_$ic is +(\[-0-9.+eE\]+)" ${le} full ll - - if { $ll < 1.0e-7 } { - puts "Error: Curve is too small!" - } + display res_$ic bounds res_$ic U1 U2 - if {[dval U2-U1] < 1.0e-9} { + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs res_$ic s1 U1 U2 10 1e-7 - xdistcs res_$ic s2 U1 U2 10 1e-7 + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 incr ic } } - + if {[expr {$ic - 1}] == $GoodNbCurv} { puts "OK: Curve Number is good!" } else { diff --git a/tests/bugs/modalg_5/bug25292_36 b/tests/bugs/modalg_5/bug25292_36 index a7a1d58f2f..dd3cac81cb 100644 --- a/tests/bugs/modalg_5/bug25292_36 +++ b/tests/bugs/modalg_5/bug25292_36 @@ -37,8 +37,7 @@ set che [whatis res] set ind [string first "3d curve" $che] if {${ind} >= 0} { #Only variable "res" exists - - copy res res_1 + renamevar res res_1 } set ic 1 @@ -49,19 +48,24 @@ while { $AllowRepeate != 0 } { if {${ind} < 0} { set AllowRepeate 0 } else { + display res_$ic + bounds res_$ic U1 U2 - if {[dval U2-U1] < 1.0e-9} { + dval U1 + dval U2 + + if {[dval U2-U1] < 1.0e-20} { puts "Error: Wrong curve's range!" } - xdistcs res_$ic s1 U1 U2 10 1e-7 - xdistcs res_$ic s2 U1 U2 10 1e-7 + xdistcs res_$ic s1 U1 U2 10 1.0e-7 + xdistcs res_$ic s2 U1 U2 10 1.0e-7 incr ic } } - + if {[expr {$ic - 1}] == $GoodNbCurv} { puts "OK: Curve Number is good!" } else { diff --git a/tests/bugs/modalg_6/bug26310_3 b/tests/bugs/modalg_6/bug26310_3 index 3879f7ca43..771fb120de 100644 --- a/tests/bugs/modalg_6/bug26310_3 +++ b/tests/bugs/modalg_6/bug26310_3 @@ -9,10 +9,21 @@ puts "" restore [locate_data_file OCC26310-b1.brep] b1 restore [locate_data_file OCC26310-b2.brep] b2 -bop b1 b2 +bclearobjects +bcleartools +baddobjects b1 +baddtools b2 +bfillds -bopcut res1 -boptuc res2 + +# SECTION +bbop rr 4 + +# CUT 1-2 +bbop res1 2 + +# CUT 2-1 +bbop res2 3 checkshape res1 checkshape res2 @@ -28,9 +39,13 @@ if { [string compare -nocase $log2 "Shape(s) seem(s) to be valid for BOP.\n"] } puts "ERROR. res2 is not valid for BOP" } +checknbshapes res1 -wire 6 -face 6 -shell 1 -solid 1 -t +checknbshapes res2 -wire 6 -face 6 -shell 1 -solid 1 -t + smallview -donly res1 +donly rr fit +donly res1 xwd ${imagedir}/${casename}_1.png donly res2 fit diff --git a/tests/bugs/modalg_6/bug26310_4 b/tests/bugs/modalg_6/bug26310_4 index b5a9c363f5..80823e2ddf 100644 --- a/tests/bugs/modalg_6/bug26310_4 +++ b/tests/bugs/modalg_6/bug26310_4 @@ -9,10 +9,21 @@ puts "" restore [locate_data_file OCC26310-b1.brep] b1 restore [locate_data_file OCC26310-b2.brep] b2 -bop b2 b1 +bclearobjects +bcleartools +baddobjects b2 +baddtools b1 +bfillds -bopcut res1 -boptuc res2 + +# SECTION +bbop rr 4 + +# CUT 1-2 +bbop res1 2 + +# CUT 2-1 +bbop res2 3 checkshape res1 checkshape res2 @@ -20,26 +31,22 @@ checkshape res2 set log1 [bopargcheck res1 #F] set log2 [bopargcheck res2 #F] -if { [string first "Faulties for FIRST shape found : 2" $log1] >= 0 } { - puts "ERROR in bopargcheck res1" -} - -if { [string first "Shapes with Continuity C0 : YES Cases(2) Total shapes(2)" $log1] >= 0 } { - puts "ERROR. res1 with continuity C0." +if { [string compare -nocase $log1 "Shape(s) seem(s) to be valid for BOP.\n"] } { + puts "ERROR. res1 is not valid for BOP" } -if { [string first "Faulties for FIRST shape found : 2" $log2] >= 0 } { - puts "ERROR in bopargcheck res2" +if { [string compare -nocase $log2 "Shape(s) seem(s) to be valid for BOP.\n"] } { + puts "ERROR. res2 is not valid for BOP" } -if { [string first "Shapes with Continuity C0 : YES Cases(2) Total shapes(2)" $log2] >= 0 } { - puts "ERROR. res2 with continuity C0." -} +checknbshapes res1 -wire 6 -face 6 -shell 1 -solid 1 -t +checknbshapes res2 -wire 6 -face 6 -shell 1 -solid 1 -t smallview donly res1 fit xwd ${imagedir}/${casename}_1.png -donly res2 +donly rr fit +donly res2 xwd ${imagedir}/${casename}_2.png diff --git a/tests/bugs/modalg_6/bug27310_1 b/tests/bugs/modalg_6/bug27310_1 index 3aff9cf90e..146b73dda3 100644 --- a/tests/bugs/modalg_6/bug27310_1 +++ b/tests/bugs/modalg_6/bug27310_1 @@ -6,8 +6,11 @@ puts "" # Huge tolerance obtained in the result of intersection of two cylindrical faces ################################################# +# Number of intersection curves cannot be subject to anything (indeed, output result can be empty). +# The main reason of the bug #27310 was a HUGE TOLERANCE VALUE (TolReached > 10). +# See test "bugs moddata_2 bug496" in case of doubt. + set ExpTol 1.0e-7 -set GoodNbCurv 2 restore [locate_data_file OCC496a.brep] a restore [locate_data_file OCC496b.brep] b @@ -19,15 +22,4 @@ set log [bopcurves a_8 b_2 -2d] regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv -if {${NbCurv} != ${GoodNbCurv}} { - puts "Error: Number of curves is bad!" -} - -checkreal TolReached $Toler $ExpTol 0.0 0.1 - -smallview -don c_* -fit -disp a_8 b_2 - -checkview -screenshot -2d -path ${imagedir}/${test_image}.png +checkreal TolReached $Toler $ExpTol 0.0 0.1 \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27310_2 b/tests/bugs/modalg_6/bug27310_2 index 8c578725be..38eda856fe 100644 --- a/tests/bugs/modalg_6/bug27310_2 +++ b/tests/bugs/modalg_6/bug27310_2 @@ -6,8 +6,11 @@ puts "" # Huge tolerance obtained in the result of intersection of two cylindrical faces ################################################# -set ExpTol 6.9230965382090094e-006 -set GoodNbCurv 2 +# Number of intersection curves cannot be subject to anything (indeed, output result can be empty). +# The main reason of the bug #27310 was a HUGE TOLERANCE VALUE (TolReached > 10). +# See test "bugs moddata_2 bug496" in case of doubt. + +set ExpTol 1.3609186093470008e-005 restore [locate_data_file OCC496a.brep] a restore [locate_data_file OCC496b.brep] b @@ -19,15 +22,4 @@ set log [bopcurves a_10 b_4 -2d] regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv -if {${NbCurv} != ${GoodNbCurv}} { - puts "Error: Number of curves is bad!" -} - -checkreal TolReached $Toler $ExpTol 0.0 0.1 - -smallview -don c_* -fit -disp a_10 b_4 - -checkview -screenshot -2d -path ${imagedir}/${test_image}.png +checkreal TolReached $Toler $ExpTol 0.0 0.1 \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27856_2 b/tests/bugs/modalg_6/bug27856_2 index 17e72d77ec..aabc7a1671 100644 --- a/tests/bugs/modalg_6/bug27856_2 +++ b/tests/bugs/modalg_6/bug27856_2 @@ -23,7 +23,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_1_2 b_2_2 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 0.00026943844817627679 0.0 1.0e-3 +checkreal TolReached $Toler 0.00026207823091004516 0.0 1.0e-3 # ---- @@ -33,7 +33,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_1_4 b_2_4 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 6.5039065434503992e-005 0.0 1.0e-2 +checkreal TolReached $Toler 6.5053102894636701e-005 0.0 1.0e-2 # ---- @@ -50,7 +50,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_3_2 b_4_2 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 0.00030603795647549098 0.0 1.0e-3 +checkreal TolReached $Toler 0.00029706239430643614 0.0 1.0e-3 # ---- @@ -60,7 +60,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_3_4 b_4_4 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 0.00029242900088525842 0.0 1.0e-3 +checkreal TolReached $Toler 0.00029242389138280588 0.0 1.0e-3 # ---- @@ -77,7 +77,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_5_2 b_6_2 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 2.0312181042800029e-005 0.0 1.0e-2 +checkreal TolReached $Toler 1.4980089259007279e-005 0.0 1.0e-2 # ---- @@ -87,7 +87,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_5_4 b_6_4 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 0.00023415774730871651 0.0 1.0e-3 +checkreal TolReached $Toler 0.00023417493528435788 0.0 1.0e-3 # ---- @@ -104,7 +104,7 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_7_2 b_8_2 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 0.00028209392756607551 0.0 1.0e-3 +checkreal TolReached $Toler 0.00027445924390073518 0.0 1.0e-3 # ---- @@ -114,5 +114,5 @@ regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} [bopcurves b_7_4 b_8_4 if {${NbCurv} != 1} { puts "Error: Number of curves is bad!" } -checkreal TolReached $Toler 2.497244318171703e-005 0.0 1.0e-2 +checkreal TolReached $Toler 1.867918118939262e-005 0.0 1.0e-2 diff --git a/tests/bugs/modalg_6/bug28009_2 b/tests/bugs/modalg_6/bug28009_2 index f5b68179a0..4a80364132 100644 --- a/tests/bugs/modalg_6/bug28009_2 +++ b/tests/bugs/modalg_6/bug28009_2 @@ -7,7 +7,7 @@ puts "" ####################################################################### set NbCurvGood 1 -set ExpToler 9.0002189481237598e-008 +set ExpToler 7.1928004468800293e-008 restore [locate_data_file bug28009_shape.brep] a diff --git a/tests/bugs/modalg_6/bug28222_1 b/tests/bugs/modalg_6/bug28222_1 new file mode 100644 index 0000000000..d6bf565cb7 --- /dev/null +++ b/tests/bugs/modalg_6/bug28222_1 @@ -0,0 +1,45 @@ +puts "================" +puts "OCC28222" +puts "================" +puts "" +####################################################################### +# Intersection of two cylinders fails +####################################################################### + +dsetsignal 1 + +set GoodNbCurv 4 + +foreach c [directory result*] { + unset $c +} + +restore [locate_data_file bug28222_s1_cyl_read_d2.draw] s1 +restore [locate_data_file bug28222_s2_cyl_read_d2.draw] s2 + +intersect result s1 s2 + +foreach c [directory result*] { + bounds $c U1 U2 + + if {[dval U2-U1] < 1.0e-9} { + puts "Error: Wrong curve's range!" + } + + xdistcs $c s1 U1 U2 10 2.0e-7 + xdistcs $c s2 U1 U2 10 2.0e-7 +} + +set NbCurv [llength [directory result*]] + +if { $NbCurv == $GoodNbCurv } { + puts "OK: Number of curves is good!" +} else { + puts "Error: $GoodNbCurv is expected but $NbCurv is found!" +} + +smallview +don result* +fit +disp s1 s2 +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_6/bug28222_2 b/tests/bugs/modalg_6/bug28222_2 new file mode 100644 index 0000000000..3fd838d958 --- /dev/null +++ b/tests/bugs/modalg_6/bug28222_2 @@ -0,0 +1,45 @@ +puts "================" +puts "OCC28222" +puts "================" +puts "" +####################################################################### +# Intersection of two cylinders fails +####################################################################### + +dsetsignal 1 + +set GoodNbCurv 4 + +foreach c [directory result*] { + unset $c +} + +cylinder s1 -35 13.3706576198285 30.5814570420266 0 -0.258819045102521 -0.965925826289068 0 0.965925826289068 -0.258819045102521 11 +cylinder s2 0 0 0 1 0 0 0 0 -1 16.5 + +intersect result s1 s2 + +foreach c [directory result*] { + bounds $c U1 U2 + + if {[dval U2-U1] < 1.0e-9} { + puts "Error: Wrong curve's range!" + } + + xdistcs $c s1 U1 U2 10 2.0e-7 + xdistcs $c s2 U1 U2 10 2.0e-7 +} + +set NbCurv [llength [directory result*]] + +if { $NbCurv == $GoodNbCurv } { + puts "OK: Number of curves is good!" +} else { + puts "Error: $GoodNbCurv is expected but $NbCurv is found!" +} + +smallview +don result* +fit +disp s1 s2 +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_6/bug28222_3 b/tests/bugs/modalg_6/bug28222_3 new file mode 100644 index 0000000000..3e1f0ac0f4 --- /dev/null +++ b/tests/bugs/modalg_6/bug28222_3 @@ -0,0 +1,46 @@ +puts "================" +puts "OCC28222" +puts "================" +puts "" +####################################################################### +# Intersection of two cylinders fails +####################################################################### + +dsetsignal 1 + +set GoodNbCurv 2 + +foreach c [directory result*] { + unset $c +} + +cylinder s1 -9 -5 -2.2058 0 -1 0 0.001 +cylinder s2 0 0 -2.2058 0 0 -1 9 + +intersect result s1 s2 + +foreach c [directory result*] { + bounds $c U1 U2 + + if {[dval U2-U1] < 1.0e-9} { + puts "Error: Wrong curve's range!" + } + + xdistcs $c s1 U1 U2 10 2.0e-7 + xdistcs $c s2 U1 U2 10 2.0e-7 +} + +set NbCurv [llength [directory result*]] + +if { $NbCurv == $GoodNbCurv } { + puts "OK: Number of curves is good!" +} else { + puts "Error: $GoodNbCurv is expected but $NbCurv is found!" +} + +smallview +don result* +fit +don s1 s2 +disp result* +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_6/bug28706 b/tests/bugs/modalg_6/bug28706 new file mode 100644 index 0000000000..6c8fdf1008 --- /dev/null +++ b/tests/bugs/modalg_6/bug28706 @@ -0,0 +1,32 @@ +puts "================" +puts "OCC28706" +puts "================" +puts "" +####################################################################### +# Incomplete result of section operation between attached shapes +####################################################################### + +dsetsignal 1 + +# Before the fix, section curve was incomplete + +restore [locate_data_file bug28706_ar_shape.brep] s1 +restore [locate_data_file bug28706_Prism.brep] s2 + +bsection result s1 s2 + +regexp {nb alone Vertices : ([-0-9.+eE]+)} [checksection result] full nbv + +if { $nbv != 0 } { + puts "Error : Section is incorrect" +} else { + puts "Section is correct" +} + +checkprops result -l 6.16832 + +smallview +don result +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/moddata_2/bug235 b/tests/bugs/moddata_2/bug235 index 22a8029e69..81d1fa032a 100755 --- a/tests/bugs/moddata_2/bug235 +++ b/tests/bugs/moddata_2/bug235 @@ -36,6 +36,9 @@ if { $nb_result != 2 } { } } -checkview -display result -2d -path ${imagedir}/${test_image}.png +smallview +don result* +fit +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/perf/modalg/bug26310_1 b/tests/perf/modalg/bug26310_1 index 826d18203b..eda200db04 100644 --- a/tests/perf/modalg/bug26310_1 +++ b/tests/perf/modalg/bug26310_1 @@ -6,27 +6,32 @@ puts "" # Very slow boolean cut operations on cylinders ################################################# -if { [regexp {Debug mode} [dversion]] } { - set max_time 0.3 -} else { - set max_time 0.15 -} +set ExpTol1 3.2300230820477792e-007 +set ExpTol2 3.2198007889220219e-007 -set maxToler 1.5e-5 +set GoodNbCurv 4 restore [locate_data_file OCC26310-b1.brep] b1 -restore [locate_data_file OCC26310-b2.brep] b2 +restore [locate_data_file OCC26310-b2.brep] b2 explode b1 f explode b2 f -dchrono cr restart -set log1 [bopcurves b1_1 b2_1 -2d] -dchrono cr stop counter bopcurves +set log [bopcurves b1_1 b2_1 -2d] +regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv + +checkreal ToleranceReached ${Toler} ${ExpTol1} 0.0 0.01 + +if {${NbCurv} != ${GoodNbCurv}} { + puts "Error: Number of curves is bad!" +} -regexp {Tolerance Reached=+([-0-9.+eE]+)} ${log1} full Toler -puts "TolReached = $Toler" +set log [bopcurves b2_1 b1_1 -2d] +regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv + +checkreal ToleranceReached ${Toler} ${ExpTol2} 0.0 0.01 + +if {${NbCurv} != ${GoodNbCurv}} { + puts "Error: Number of curves is bad!" +} -if { $Toler > $maxToler } { - puts "Error: Tolerance is too big ($Toler > $maxToler)" -} \ No newline at end of file -- 2.39.5