// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#include <IntAna_ListOfCurve.hxx>
+#include <algorithm>
+#include <Bnd_Range.hxx>
#include <IntAna_ListIteratorOfListOfCurve.hxx>
+#include <IntAna_ListOfCurve.hxx>
#include <IntPatch_WLine.hxx>
+#include <Standard_DivideByZero.hxx>
+#include <math_Matrix.hxx>
+//If Abs(a) <= aNulValue then it is considered that a = 0.
+static const Standard_Real aNulValue = 1.0e-11;
+
+static void ShortCosForm( const Standard_Real theCosFactor,
+ const Standard_Real theSinFactor,
+ Standard_Real& theCoeff,
+ Standard_Real& theAngle);
//
static
Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
IntAna_Curve& aC,
const Standard_Real aTol,
IntAna_ListOfCurve& aLC);
-static
- Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
- const gp_Cylinder& Cy2,
- const Standard_Real Tol);
-// ------------------------------------------------------------------
-// MinMax : Replaces theParMIN = MIN(theParMIN, theParMAX),
+static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
+ const Standard_Real theUlTarget,
+ Standard_Real& theUGiven,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriod,
+ const Standard_Boolean theFlForce);
+
+
+class ComputationMethods
+{
+ //Every cylinder can be represented by the following equation in parametric form:
+ // S(U,V) = L + R*cos(U)*Xd+R*sin(U)*Yd+V*Zd,
+ //where location L, directions Xd, Yd and Zd have type gp_XYZ.
+
+ //Intersection points between two cylinders can be found from the following system:
+ // S1(U1, V1) = S2(U2, V2)
+ //or
+ // {X01 + R1*cos(U1)*Xx1 + R1*sin(U1)*Yx1 + V1*Zx1 = X02 + R2*cos(U2)*Xx2 + R2*sin(U2)*Yx2 + V2*Zx2
+ // {Y01 + R1*cos(U1)*Xy1 + R1*sin(U1)*Yy1 + V1*Zy1 = Y02 + R2*cos(U2)*Xy2 + R2*sin(U2)*Yy2 + V2*Zy2 (1)
+ // {Z01 + R1*cos(U1)*Xz1 + R1*sin(U1)*Yz1 + V1*Zz1 = Z02 + R2*cos(U2)*Xz2 + R2*sin(U2)*Yz2 + V2*Zz2
+
+ //The formula (1) can be rewritten as follows
+ // {C11*V1+C21*V2=A11*cos(U1)+B11*sin(U1)+A21*cos(U2)+B21*sin(U2)+D1
+ // {C12*V1+C22*V2=A12*cos(U1)+B12*sin(U1)+A22*cos(U2)+B22*sin(U2)+D2 (2)
+ // {C13*V1+C23*V2=A13*cos(U1)+B13*sin(U1)+A23*cos(U2)+B23*sin(U2)+D3
+
+ //Hereafter we consider that in system
+ // {C11*V1+C21*V2=A11*cos(U1)+B11*sin(U1)+A21*cos(U2)+B21*sin(U2)+D1 (3)
+ // {C12*V1+C22*V2=A12*cos(U1)+B12*sin(U1)+A22*cos(U2)+B22*sin(U2)+D2
+ //variables V1 and V2 can be found unambiguously, i.e. determinant
+ // |C11 C21|
+ // | | != 0
+ // |C12 C22|
+ //
+ //In this case, variables V1 and V2 can be found as follows:
+ // {V1 = K11*sin(U1)+K21*sin(U2)+L11*cos(U1)+L21*cos(U2)+M1 = K1*cos(U1-FIV1)+L1*cos(U2-PSIV1)+M1 (4)
+ // {V2 = K12*sin(U1)+K22*sin(U2)+L12*cos(U1)+L22*cos(U2)+M2 = K2*cos(U2-FIV2)+L2*cos(U2-PSIV2)+M2
+
+ //Having substituted result of (4) to the 3rd equation of (2), we will obtain equation
+ // cos(U2-FI2) = B*cos(U1-FI1)+C. (5)
+
+ //I.e. when U1 is taken different given values (from domain), correspond U2 value can be computed
+ //from equation (5). After that, V1 and V2 can be computed from the system (4) (see
+ //CylCylComputeParameters(...) methods).
+
+ //It is important to remark that equation (5) (in general) has two solutions: U2=FI2 +/- f(U1).
+ //Therefore, we are getting here two intersection lines.
+
+public:
+ //Stores equations coefficients
+ struct stCoeffsValue
+ {
+ stCoeffsValue(const gp_Cylinder&, const gp_Cylinder&);
+
+ math_Vector mVecA1;
+ math_Vector mVecA2;
+ math_Vector mVecB1;
+ math_Vector mVecB2;
+ math_Vector mVecC1;
+ math_Vector mVecC2;
+ math_Vector mVecD;
+
+ Standard_Real mK21; //sinU2
+ Standard_Real mK11; //sinU1
+ Standard_Real mL21; //cosU2
+ Standard_Real mL11; //cosU1
+ Standard_Real mM1; //Free member
+
+ Standard_Real mK22; //sinU2
+ Standard_Real mK12; //sinU1
+ Standard_Real mL22; //cosU2
+ Standard_Real mL12; //cosU1
+ Standard_Real mM2; //Free member
+
+ Standard_Real mK1;
+ Standard_Real mL1;
+ Standard_Real mK2;
+ Standard_Real mL2;
+
+ Standard_Real mFIV1;
+ Standard_Real mPSIV1;
+ Standard_Real mFIV2;
+ Standard_Real mPSIV2;
+
+ Standard_Real mB;
+ Standard_Real mC;
+ Standard_Real mFI1;
+ Standard_Real mFI2;
+ };
+
+
+ //! Determines, if U2(U1) function is increasing.
+ static Standard_Boolean CylCylMonotonicity(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ const Standard_Real thePeriod,
+ Standard_Boolean& theIsIncreasing);
+
+ //! Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
+ //! esimates the tolerance of U2-computing (estimation result is
+ //! assigned to *theDelta value).
+ static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real* const theDelta = 0);
+
+ static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1,
+ const Standard_Real theU2,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theV1,
+ Standard_Real& theV2);
+
+ static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real& theV1,
+ Standard_Real& theV2);
+
+};
+
+ComputationMethods::stCoeffsValue::stCoeffsValue(const gp_Cylinder& theCyl1,
+ const gp_Cylinder& theCyl2):
+ mVecA1(-theCyl1.Radius()*theCyl1.XAxis().Direction().XYZ()),
+ mVecA2(theCyl2.Radius()*theCyl2.XAxis().Direction().XYZ()),
+ mVecB1(-theCyl1.Radius()*theCyl1.YAxis().Direction().XYZ()),
+ mVecB2(theCyl2.Radius()*theCyl2.YAxis().Direction().XYZ()),
+ mVecC1(theCyl1.Axis().Direction().XYZ()),
+ mVecC2(theCyl2.Axis().Direction().XYZ().Reversed()),
+ mVecD(theCyl2.Location().XYZ() - theCyl1.Location().XYZ())
+{
+ enum CoupleOfEquation
+ {
+ COENONE = 0,
+ COE12 = 1,
+ COE23 = 2,
+ COE13 = 3
+ }aFoundCouple = COENONE;
+
+
+ Standard_Real aDetV1V2 = 0.0;
+
+ const Standard_Real aDelta1 = mVecC1(1)*mVecC2(2)-mVecC1(2)*mVecC2(1); //1-2
+ const Standard_Real aDelta2 = mVecC1(2)*mVecC2(3)-mVecC1(3)*mVecC2(2); //2-3
+ const Standard_Real aDelta3 = mVecC1(1)*mVecC2(3)-mVecC1(3)*mVecC2(1); //1-3
+ const Standard_Real anAbsD1 = Abs(aDelta1); //1-2
+ const Standard_Real anAbsD2 = Abs(aDelta2); //2-3
+ const Standard_Real anAbsD3 = Abs(aDelta3); //1-3
+
+ if(anAbsD1 >= anAbsD2)
+ {
+ if(anAbsD3 > anAbsD1)
+ {
+ aFoundCouple = COE13;
+ aDetV1V2 = aDelta3;
+ }
+ else
+ {
+ aFoundCouple = COE12;
+ aDetV1V2 = aDelta1;
+ }
+ }
+ else
+ {
+ if(anAbsD3 > anAbsD2)
+ {
+ aFoundCouple = COE13;
+ aDetV1V2 = aDelta3;
+ }
+ else
+ {
+ aFoundCouple = COE23;
+ aDetV1V2 = aDelta2;
+ }
+ }
+
+ // In point of fact, every determinant (aDelta1, aDelta2 and aDelta3) is
+ // cross-product between directions (i.e. sine of angle).
+ // If sine is too small then sine is (approx.) equal to angle itself.
+ // Therefore, in this case we should compare sine with angular tolerance.
+ // This constant is used for check if axes are parallel (see constructor
+ // AxeOperator::AxeOperator(...) in IntAna_QuadQuadGeo.cxx file).
+ if(Abs(aDetV1V2) < Precision::Angular())
+ {
+ Standard_Failure::Raise("Error. Exception in divide by zerro (IntCyCyTrim)!!!!");
+ }
+
+ switch(aFoundCouple)
+ {
+ case COE12:
+ break;
+ case COE23:
+ {
+ math_Vector aVTemp(mVecA1);
+ mVecA1(1) = aVTemp(2);
+ mVecA1(2) = aVTemp(3);
+ mVecA1(3) = aVTemp(1);
+
+ aVTemp = mVecA2;
+ mVecA2(1) = aVTemp(2);
+ mVecA2(2) = aVTemp(3);
+ mVecA2(3) = aVTemp(1);
+
+ aVTemp = mVecB1;
+ mVecB1(1) = aVTemp(2);
+ mVecB1(2) = aVTemp(3);
+ mVecB1(3) = aVTemp(1);
+
+ aVTemp = mVecB2;
+ mVecB2(1) = aVTemp(2);
+ mVecB2(2) = aVTemp(3);
+ mVecB2(3) = aVTemp(1);
+
+ aVTemp = mVecC1;
+ mVecC1(1) = aVTemp(2);
+ mVecC1(2) = aVTemp(3);
+ mVecC1(3) = aVTemp(1);
+
+ aVTemp = mVecC2;
+ mVecC2(1) = aVTemp(2);
+ mVecC2(2) = aVTemp(3);
+ mVecC2(3) = aVTemp(1);
+
+ aVTemp = mVecD;
+ mVecD(1) = aVTemp(2);
+ mVecD(2) = aVTemp(3);
+ mVecD(3) = aVTemp(1);
+
+ break;
+ }
+ case COE13:
+ {
+ math_Vector aVTemp = mVecA1;
+ mVecA1(2) = aVTemp(3);
+ mVecA1(3) = aVTemp(2);
+
+ aVTemp = mVecA2;
+ mVecA2(2) = aVTemp(3);
+ mVecA2(3) = aVTemp(2);
+
+ aVTemp = mVecB1;
+ mVecB1(2) = aVTemp(3);
+ mVecB1(3) = aVTemp(2);
+
+ aVTemp = mVecB2;
+ mVecB2(2) = aVTemp(3);
+ mVecB2(3) = aVTemp(2);
+
+ aVTemp = mVecC1;
+ mVecC1(2) = aVTemp(3);
+ mVecC1(3) = aVTemp(2);
+
+ aVTemp = mVecC2;
+ mVecC2(2) = aVTemp(3);
+ mVecC2(3) = aVTemp(2);
+
+ aVTemp = mVecD;
+ mVecD(2) = aVTemp(3);
+ mVecD(3) = aVTemp(2);
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ //------- For V1 (begin)
+ //sinU2
+ mK21 = (mVecC2(2)*mVecB2(1)-mVecC2(1)*mVecB2(2))/aDetV1V2;
+ //sinU1
+ mK11 = (mVecC2(2)*mVecB1(1)-mVecC2(1)*mVecB1(2))/aDetV1V2;
+ //cosU2
+ mL21 = (mVecC2(2)*mVecA2(1)-mVecC2(1)*mVecA2(2))/aDetV1V2;
+ //cosU1
+ mL11 = (mVecC2(2)*mVecA1(1)-mVecC2(1)*mVecA1(2))/aDetV1V2;
+ //Free member
+ mM1 = (mVecC2(2)*mVecD(1)-mVecC2(1)*mVecD(2))/aDetV1V2;
+ //------- For V1 (end)
+
+ //------- For V2 (begin)
+ //sinU2
+ mK22 = (mVecC1(1)*mVecB2(2)-mVecC1(2)*mVecB2(1))/aDetV1V2;
+ //sinU1
+ mK12 = (mVecC1(1)*mVecB1(2)-mVecC1(2)*mVecB1(1))/aDetV1V2;
+ //cosU2
+ mL22 = (mVecC1(1)*mVecA2(2)-mVecC1(2)*mVecA2(1))/aDetV1V2;
+ //cosU1
+ mL12 = (mVecC1(1)*mVecA1(2)-mVecC1(2)*mVecA1(1))/aDetV1V2;
+ //Free member
+ mM2 = (mVecC1(1)*mVecD(2)-mVecC1(2)*mVecD(1))/aDetV1V2;
+ //------- For V1 (end)
+
+ ShortCosForm(mL11, mK11, mK1, mFIV1);
+ ShortCosForm(mL21, mK21, mL1, mPSIV1);
+ ShortCosForm(mL12, mK12, mK2, mFIV2);
+ ShortCosForm(mL22, mK22, mL2, mPSIV2);
+
+ const Standard_Real aA1=mVecC1(3)*mK21+mVecC2(3)*mK22-mVecB2(3), //sinU2
+ aA2=mVecC1(3)*mL21+mVecC2(3)*mL22-mVecA2(3), //cosU2
+ aB1=mVecB1(3)-mVecC1(3)*mK11-mVecC2(3)*mK12, //sinU1
+ aB2=mVecA1(3)-mVecC1(3)*mL11-mVecC2(3)*mL12; //cosU1
+
+ mC =mVecD(3) - mVecC1(3)*mM1 -mVecC2(3)*mM2; //Free
+
+ Standard_Real aA = 0.0;
+
+ ShortCosForm(aB2,aB1,mB,mFI1);
+ ShortCosForm(aA2,aA1,aA,mFI2);
+
+ mB /= aA;
+ mC /= aA;
+}
+
+class WorkWithBoundaries
+{
+public:
+ enum SearchBoundType
+ {
+ SearchNONE = 0,
+ SearchV1 = 1,
+ SearchV2 = 2
+ };
+
+ struct StPInfo
+ {
+ StPInfo()
+ {
+ mySurfID = 0;
+ myU1 = RealLast();
+ myV1 = RealLast();
+ myU2 = RealLast();
+ myV2 = RealLast();
+ }
+
+ //Equal to 0 for 1st surface non-zerro for 2nd one.
+ Standard_Integer mySurfID;
+
+ Standard_Real myU1;
+ Standard_Real myV1;
+ Standard_Real myU2;
+ Standard_Real myV2;
+
+ bool operator>(const StPInfo& theOther) const
+ {
+ return myU1 > theOther.myU1;
+ }
+
+ bool operator<(const StPInfo& theOther) const
+ {
+ return myU1 < theOther.myU1;
+ }
+
+ bool operator==(const StPInfo& theOther) const
+ {
+ return myU1 == theOther.myU1;
+ }
+ };
+
+ WorkWithBoundaries(const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Bnd_Box2d& theUVSurf1,
+ const Bnd_Box2d& theUVSurf2,
+ const Standard_Integer theNbWLines,
+ const Standard_Real thePeriod,
+ const Standard_Real theTol3D,
+ const Standard_Real theTol2D,
+ const Standard_Boolean isTheReverse) :
+ myQuad1(theQuad1), myQuad2(theQuad2), myCoeffs(theCoeffs),
+ myUVSurf1(theUVSurf1), myUVSurf2(theUVSurf2), myNbWLines(theNbWLines),
+ myPeriod(thePeriod), myTol3D(theTol3D), myTol2D(theTol2D),
+ myIsReverse(isTheReverse)
+ {
+ };
+
+ void AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL,
+ const Standard_Real theU1,
+ const Standard_Real theU2,
+ const Standard_Real theV1,
+ const Standard_Real theV1Prev,
+ const Standard_Real theV2,
+ const Standard_Real theV2Prev,
+ const Standard_Integer theWLIndex,
+ const Standard_Boolean theFlForce,
+ Standard_Boolean& isTheFound1,
+ Standard_Boolean& isTheFound2) const;
+
+ Standard_Boolean BoundariesComputing(Standard_Real theU1f[],
+ Standard_Real theU1l[]) const;
+
+ void BoundaryEstimation(const gp_Cylinder& theCy1,
+ const gp_Cylinder& theCy2,
+ Bnd_Range& theOutBoxS1,
+ Bnd_Range& theOutBoxS2) const;
+
+protected:
+
+ //Solves equation (2) (see declaration of ComputationMethods class) in case,
+ //when V1 or V2 (is set by theSBType argument) is known (corresponds to the boundary
+ //and equal to theVzad) but U1 is unknown. Computation is made by numeric methods and
+ //requires initial values (theVInit, theInitU2 and theInitMainVar).
+ Standard_Boolean
+ SearchOnVBounds(const SearchBoundType theSBType,
+ const Standard_Real theVzad,
+ const Standard_Real theVInit,
+ const Standard_Real theInitU2,
+ const Standard_Real theInitMainVar,
+ Standard_Real& theMainVariableValue) const;
+
+ const WorkWithBoundaries& operator=(const WorkWithBoundaries&);
+
+private:
+ friend class ComputationMethods;
+
+ const IntSurf_Quadric& myQuad1;
+ const IntSurf_Quadric& myQuad2;
+ const ComputationMethods::stCoeffsValue& myCoeffs;
+ const Bnd_Box2d& myUVSurf1;
+ const Bnd_Box2d& myUVSurf2;
+ const Standard_Integer myNbWLines;
+ const Standard_Real myPeriod;
+ const Standard_Real myTol3D;
+ const Standard_Real myTol2D;
+ const Standard_Boolean myIsReverse;
+};
+
+static
+ Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
+ const gp_Cone& aCo,
+ IntAna_Curve& aC,
+ const Standard_Real aTol,
+ IntAna_ListOfCurve& aLC);
+
+static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
+ const IntSurf_Quadric& theQuad2,
+ const Handle(IntSurf_LineOn2S)& theLine,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Integer theWLIndex,
+ const Standard_Integer theMinNbPoints,
+ const Standard_Integer theStartPointOnLine,
+ const Standard_Integer theEndPointOnLine,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriodOfSurf2,
+ const Standard_Boolean isTheReverse);
+
+//=======================================================================
+//function : MinMax
+//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
// theParMAX = MAX(theParMIN, theParMAX).
-// ------------------------------------------------------------------
+//=======================================================================
static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
{
if(theParMIN > theParMAX)
}
}
+//=======================================================================
+//function : ExtremaLineLine
+//purpose : Computes extrema between the given lines. Returns parameters
+// on correspond curve (see correspond method for Extrema_ExtElC class).
+//=======================================================================
+static inline void ExtremaLineLine(const gp_Ax1& theC1,
+ const gp_Ax1& theC2,
+ const Standard_Real theCosA,
+ const Standard_Real theSqSinA,
+ Standard_Real& thePar1,
+ Standard_Real& thePar2)
+{
+ const gp_Dir &aD1 = theC1.Direction(),
+ &aD2 = theC2.Direction();
+
+ const gp_XYZ aL1L2 = theC2.Location().XYZ() - theC1.Location().XYZ();
+ const Standard_Real aD1L = aD1.XYZ().Dot(aL1L2),
+ aD2L = aD2.XYZ().Dot(aL1L2);
+
+ thePar1 = (aD1L - theCosA * aD2L) / theSqSinA;
+ thePar2 = (theCosA * aD1L - aD2L) / theSqSinA;
+}
+
+//=======================================================================
+//function : VBoundaryPrecise
+//purpose : By default, we shall consider, that V1 and V2 will be increased
+// if U1 is increased. But if it is not, new V1set and/or V2set
+// must be computed as [V1current - DeltaV1] (analogically
+// for V2). This function processes this case.
+//=======================================================================
+static void VBoundaryPrecise( const math_Matrix& theMatr,
+ const Standard_Real theV1AfterDecrByDelta,
+ const Standard_Real theV2AfterDecrByDelta,
+ Standard_Real& theV1Set,
+ Standard_Real& theV2Set)
+{
+ //Now we are going to define if V1 (and V2) increases
+ //(or decreases) when U1 will increase.
+ const Standard_Integer aNbDim = 3;
+ math_Matrix aSyst(1, aNbDim, 1, aNbDim);
+
+ aSyst.SetCol(1, theMatr.Col(1));
+ aSyst.SetCol(2, theMatr.Col(2));
+ aSyst.SetCol(3, theMatr.Col(4));
+
+ //We have the system (see comment to StepComputing(...) function)
+ // {a11*dV1 + a12*dV2 + a14*dU2 = -a13*dU1
+ // {a21*dV1 + a22*dV2 + a24*dU2 = -a23*dU1
+ // {a31*dV1 + a32*dV2 + a34*dU2 = -a33*dU1
+
+ const Standard_Real aDet = aSyst.Determinant();
+
+ aSyst.SetCol(1, theMatr.Col(3));
+ const Standard_Real aDet1 = aSyst.Determinant();
+
+ aSyst.SetCol(1, theMatr.Col(1));
+ aSyst.SetCol(2, theMatr.Col(3));
+
+ const Standard_Real aDet2 = aSyst.Determinant();
+
+ //Now,
+ // dV1 = -dU1*aDet1/aDet
+ // dV2 = -dU1*aDet2/aDet
+
+ //If U1 is increased then dU1 > 0.
+ //If (aDet1/aDet > 0) then dV1 < 0 and
+ //V1 will be decreased after increasing U1.
+
+ //We have analogical situation with V2-parameter.
+
+ if(aDet*aDet1 > 0.0)
+ {
+ theV1Set = theV1AfterDecrByDelta;
+ }
+
+ if(aDet*aDet2 > 0.0)
+ {
+ theV2Set = theV2AfterDecrByDelta;
+ }
+}
+
+//=======================================================================
+//function : DeltaU1Computing
+//purpose : Computes new step for U1 parameter.
+//=======================================================================
+static inline
+ Standard_Boolean DeltaU1Computing(const math_Matrix& theSyst,
+ const math_Vector& theFree,
+ Standard_Real& theDeltaU1Found)
+{
+ Standard_Real aDet = theSyst.Determinant();
+
+ if(Abs(aDet) > aNulValue)
+ {
+ math_Matrix aSyst1(theSyst);
+ aSyst1.SetCol(2, theFree);
+
+ theDeltaU1Found = Abs(aSyst1.Determinant()/aDet);
+ return Standard_True;
+ }
+
+ return Standard_False;
+}
+
+//=======================================================================
+//function : StepComputing
+//purpose :
+//
+//Attention!!!:
+// theMatr must have 3*5-dimension strictly.
+// For system
+// {a11*V1+a12*V2+a13*dU1+a14*dU2=b1;
+// {a21*V1+a22*V2+a23*dU1+a24*dU2=b2;
+// {a31*V1+a32*V2+a33*dU1+a34*dU2=b3;
+// theMatr must be following:
+// (a11 a12 a13 a14 b1)
+// (a21 a22 a23 a24 b2)
+// (a31 a32 a33 a34 b3)
+//=======================================================================
+static Standard_Boolean StepComputing(const math_Matrix& theMatr,
+ const Standard_Real theV1Cur,
+ const Standard_Real theV2Cur,
+ const Standard_Real theDeltaV1,
+ const Standard_Real theDeltaV2,
+ Standard_Real& theDeltaU1Found/*,
+ Standard_Real& theDeltaU2Found,
+ Standard_Real& theV1Found,
+ Standard_Real& theV2Found*/)
+{
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ bool flShow = false;
+
+ if(flShow)
+ {
+ printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+ theMatr(1,1), theMatr(1,2), theMatr(1,3), theMatr(1,4), theMatr(1,5));
+ printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+ theMatr(2,1), theMatr(2,2), theMatr(2,3), theMatr(2,4), theMatr(2,5));
+ printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+ theMatr(3,1), theMatr(3,2), theMatr(3,3), theMatr(3,4), theMatr(3,5));
+ }
+#endif
+
+ Standard_Boolean isSuccess = Standard_False;
+ theDeltaU1Found/* = theDeltaU2Found*/ = RealLast();
+ //theV1Found = theV1set;
+ //theV2Found = theV2Set;
+ const Standard_Integer aNbDim = 3;
+
+ math_Matrix aSyst(1, aNbDim, 1, aNbDim);
+ math_Vector aFree(1, aNbDim);
+
+ //By default, increasing V1(U1) and V2(U1) functions is
+ //considered
+ Standard_Real aV1Set = theV1Cur + theDeltaV1,
+ aV2Set = theV2Cur + theDeltaV2;
+
+ //However, what is indeed?
+ VBoundaryPrecise( theMatr, theV1Cur - theDeltaV1,
+ theV2Cur - theDeltaV2, aV1Set, aV2Set);
+
+ aSyst.SetCol(2, theMatr.Col(3));
+ aSyst.SetCol(3, theMatr.Col(4));
+
+ for(Standard_Integer i = 0; i < 2; i++)
+ {
+ if(i == 0)
+ {//V1 is known
+ aSyst.SetCol(1, theMatr.Col(2));
+ aFree.Set(1, aNbDim, theMatr.Col(5)-aV1Set*theMatr.Col(1));
+ }
+ else
+ {//i==1 => V2 is known
+ aSyst.SetCol(1, theMatr.Col(1));
+ aFree.Set(1, aNbDim, theMatr.Col(5)-aV2Set*theMatr.Col(2));
+ }
+
+ Standard_Real aNewDU = theDeltaU1Found;
+ if(DeltaU1Computing(aSyst, aFree, aNewDU))
+ {
+ isSuccess = Standard_True;
+ if(aNewDU < theDeltaU1Found)
+ {
+ theDeltaU1Found = aNewDU;
+ }
+ }
+ }
+
+ if(!isSuccess)
+ {
+ aFree = theMatr.Col(5) - aV1Set*theMatr.Col(1) - aV2Set*theMatr.Col(2);
+ math_Matrix aSyst1(1, aNbDim, 1, 2);
+ aSyst1.SetCol(1, aSyst.Col(2));
+ aSyst1.SetCol(2, aSyst.Col(3));
+
+ //Now we have overdetermined system.
+
+ const Standard_Real aDet1 = theMatr(1,3)*theMatr(2,4) - theMatr(2,3)*theMatr(1,4);
+ const Standard_Real aDet2 = theMatr(1,3)*theMatr(3,4) - theMatr(3,3)*theMatr(1,4);
+ const Standard_Real aDet3 = theMatr(2,3)*theMatr(3,4) - theMatr(3,3)*theMatr(2,4);
+ const Standard_Real anAbsD1 = Abs(aDet1);
+ const Standard_Real anAbsD2 = Abs(aDet2);
+ const Standard_Real anAbsD3 = Abs(aDet3);
+
+ if(anAbsD1 >= anAbsD2)
+ {
+ if(anAbsD1 >= anAbsD3)
+ {
+ //Det1
+ if(anAbsD1 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(1)*theMatr(2,4) - aFree(2)*theMatr(1,4))/anAbsD1;
+ isSuccess = Standard_True;
+ }
+ else
+ {
+ //Det3
+ if(anAbsD3 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(2)*theMatr(3,4) - aFree(3)*theMatr(2,4))/anAbsD3;
+ isSuccess = Standard_True;
+ }
+ }
+ else
+ {
+ if(anAbsD2 >= anAbsD3)
+ {
+ //Det2
+ if(anAbsD2 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(1)*theMatr(3,4) - aFree(3)*theMatr(1,4))/anAbsD2;
+ isSuccess = Standard_True;
+ }
+ else
+ {
+ //Det3
+ if(anAbsD3 <= aNulValue)
+ return isSuccess;
+
+ theDeltaU1Found = Abs(aFree(2)*theMatr(3,4) - aFree(3)*theMatr(2,4))/anAbsD3;
+ isSuccess = Standard_True;
+ }
+ }
+ }
+
+ return isSuccess;
+}
//=======================================================================
//function : ProcessBounds
alig->SetLastPoint(alig->NbVertex());
}
}
+
//=======================================================================
-//function : IntCyCy
-//purpose :
+//function : CyCyAnalyticalIntersect
+//purpose : Checks if intersection curve is analytical (line, circle, ellipse)
+// and returns these curves.
//=======================================================================
-Standard_Boolean IntCyCy(const IntSurf_Quadric& Quad1,
- const IntSurf_Quadric& Quad2,
- const Standard_Real Tol,
- Standard_Boolean& Empty,
- Standard_Boolean& Same,
- Standard_Boolean& Multpoint,
- IntPatch_SequenceOfLine& slin,
- IntPatch_SequenceOfPoint& spnt)
-
+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,
+ IntPatch_SequenceOfLine& slin,
+ IntPatch_SequenceOfPoint& spnt)
{
IntPatch_Point ptsol;
-
+
Standard_Integer i;
IntSurf_TypeTrans trans1,trans2;
gp_Cylinder Cy1(Quad1.Cylinder());
gp_Cylinder Cy2(Quad2.Cylinder());
- IntAna_QuadQuadGeo inter(Cy1,Cy2,Tol);
-
- if (!inter.IsDone())
- {
- return Standard_False;
- }
-
- typint = inter.TypeInter();
- Standard_Integer NbSol = inter.NbSolutions();
+ typint = theInter.TypeInter();
+ Standard_Integer NbSol = theInter.NbSolutions();
Empty = Standard_False;
Same = Standard_False;
switch (typint)
- {
+ {
case IntAna_Empty:
{
Empty = Standard_True;
- }
+ }
break;
case IntAna_Same:
- {
+ {
Same = Standard_True;
- }
+ }
break;
-
+
case IntAna_Point:
{
- gp_Pnt psol(inter.Point(1));
- Standard_Real U1,V1,U2,V2;
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
+ gp_Pnt psol(theInter.Point(1));
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);
+ }
+
ptsol.SetParameters(U1,V1,U2,V2);
spnt.Append(ptsol);
}
gp_Pnt ptref;
if (NbSol == 1)
{ // Cylinders are tangent to each other by line
- linsol = inter.Line(1);
+ linsol = theInter.Line(1);
ptref = linsol.Location();
+
+ //Radius-vectors
gp_Dir crb1(gp_Vec(ptref,Cy1.Location()));
gp_Dir crb2(gp_Vec(ptref,Cy2.Location()));
+
+ //outer normal lines
gp_Vec norm1(Quad1.Normale(ptref));
gp_Vec norm2(Quad2.Normale(ptref));
IntSurf_Situation situcyl1;
if (crb1.Dot(crb2) < 0.)
{ // centre de courbures "opposes"
+ //ATTENTION!!!
+ // Normal and Radius-vector of the 1st(!) cylinder
+ // is used for judging what the situation of the 2nd(!)
+ // cylinder is.
+
if (norm1.Dot(crb1) > 0.)
{
situcyl2 = IntSurf_Inside;
}
}
else
- {
+ {
if (Cy1.Radius() < Cy2.Radius())
{
if (norm1.Dot(crb1) > 0.)
{
for (i=1; i <= NbSol; i++)
{
- linsol = inter.Line(i);
+ linsol = theInter.Line(i);
ptref = linsol.Location();
gp_Vec lsd = linsol.Direction();
+
+ //Theoretically, qwe = +/- 1.0.
Standard_Real qwe = lsd.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
if (qwe >0.00000001)
{
gp_Vec Tgt;
gp_Pnt ptref;
IntPatch_Point pmult1, pmult2;
-
- elipsol = inter.Ellipse(1);
-
+
+ elipsol = theInter.Ellipse(1);
+
gp_Pnt pttang1(ElCLib::Value(0.5*M_PI, elipsol));
gp_Pnt pttang2(ElCLib::Value(1.5*M_PI, elipsol));
-
+
Multpoint = Standard_True;
pmult1.SetValue(pttang1,Tol,Standard_True);
pmult2.SetValue(pttang2,Tol,Standard_True);
pmult1.SetMultiple(Standard_True);
pmult2.SetMultiple(Standard_True);
-
+
Standard_Real oU1,oV1,oU2,oV2;
- Quad1.Parameters(pttang1,oU1,oV1);
- Quad2.Parameters(pttang1,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);
+ }
+
pmult1.SetParameters(oU1,oV1,oU2,oV2);
- Quad1.Parameters(pttang2,oU1,oV1);
- Quad2.Parameters(pttang2,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);
+ }
+
pmult2.SetParameters(oU1,oV1,oU2,oV2);
-
- // on traite la premiere ellipse
+ // on traite la premiere ellipse
+
//-- Calcul de la Transition de la ligne
ElCLib::D1(0.,elipsol,ptref,Tgt);
+
+ //Theoretically, qwe = +/- |Tgt|.
Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
if (qwe>0.00000001)
{
trans2 = IntSurf_Out;
}
else
- {
+ {
trans1=trans2=IntSurf_Undecided;
}
aIP.SetValue(aP,Tol,Standard_False);
aIP.SetMultiple(Standard_False);
//
- Quad1.Parameters(aP, aU1, aV1);
- Quad2.Parameters(aP, aU2, aV2);
+
+ if(isTheReverse)
+ {
+ Quad2.Parameters(aP, aU1, aV1);
+ Quad1.Parameters(aP, aU2, aV2);
+ }
+ else
+ {
+ Quad1.Parameters(aP, aU1, aV1);
+ Quad2.Parameters(aP, aU2, aV2);
+ }
+
aIP.SetParameters(aU1, aV1, aU2, aV2);
//
aIP.SetParameter(0.);
//-- Transitions calculee au point 0 OK
//
// on traite la deuxieme ellipse
- elipsol = inter.Ellipse(2);
+ elipsol = theInter.Ellipse(2);
Standard_Real param1 = ElCLib::Parameter(elipsol,pttang1);
Standard_Real param2 = ElCLib::Parameter(elipsol,pttang2);
//-- Calcul des transitions de ligne pour la premiere ligne
ElCLib::D1(parampourtransition,elipsol,ptref,Tgt);
+
+ //Theoretically, qwe = +/- |Tgt|.
qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
if(qwe> 0.00000001)
{
aIP.SetValue(aP,Tol,Standard_False);
aIP.SetMultiple(Standard_False);
//
- Quad1.Parameters(aP, aU1, aV1);
- Quad2.Parameters(aP, aU2, aV2);
+
+ if(isTheReverse)
+ {
+ Quad2.Parameters(aP, aU1, aV1);
+ Quad1.Parameters(aP, aU2, aV2);
+ }
+ else
+ {
+ Quad1.Parameters(aP, aU1, aV1);
+ Quad2.Parameters(aP, aU2, aV2);
+ }
+
aIP.SetParameters(aU1, aV1, aU2, aV2);
//
aIP.SetParameter(0.);
}
break;
- case IntAna_NoGeometricSolution:
- {
- Standard_Boolean bReverse;
- Standard_Real U1,V1,U2,V2;
- gp_Pnt psol;
- //
- bReverse=IsToReverse(Cy1, Cy2, Tol);
- if (bReverse)
- {
- Cy2=Quad1.Cylinder();
- Cy1=Quad2.Cylinder();
- }
- //
- IntAna_IntQuadQuad anaint(Cy1,Cy2,Tol);
- if (!anaint.IsDone())
- {
- return Standard_False;
- }
-
- if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
- {
- Empty = Standard_True;
- }
- else
- {
- NbSol = anaint.NbPnt();
- for (i = 1; i <= NbSol; i++)
- {
- psol = anaint.Point(i);
- Quad1.Parameters(psol,U1,V1);
- Quad2.Parameters(psol,U2,V2);
- ptsol.SetValue(psol,Tol,Standard_True);
- ptsol.SetParameters(U1,V1,U2,V2);
- spnt.Append(ptsol);
- }
-
- gp_Pnt ptvalid, ptf, ptl;
- gp_Vec tgvalid;
-
- Standard_Real first,last,para;
- IntAna_Curve curvsol;
- Standard_Boolean tgfound;
- Standard_Integer kount;
-
- NbSol = anaint.NbCurve();
- for (i = 1; i <= NbSol; i++)
- {
- curvsol = anaint.Curve(i);
- curvsol.Domain(first,last);
- ptf = curvsol.Value(first);
- ptl = curvsol.Value(last);
-
- para = last;
- kount = 1;
- tgfound = Standard_False;
-
- while (!tgfound)
- {
- para = (1.123*first + para)/2.123;
- tgfound = curvsol.D1u(para,ptvalid,tgvalid);
- if (!tgfound)
- {
- kount ++;
- tgfound = kount > 5;
- }
- }
-
- Handle(IntPatch_ALine) alig;
- if (kount <= 5)
- {
- Standard_Real qwe = tgvalid.DotCross( Quad2.Normale(ptvalid),
- Quad1.Normale(ptvalid));
- if(qwe>0.00000001)
- {
- trans1 = IntSurf_Out;
- trans2 = IntSurf_In;
- }
- else if(qwe<-0.00000001)
- {
- trans1 = IntSurf_In;
- trans2 = IntSurf_Out;
- }
- else
- {
- trans1=trans2=IntSurf_Undecided;
- }
- alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
- }
- else
- {
- alig = new IntPatch_ALine(curvsol,Standard_False);
- //-- cout << "Transition indeterminee" << endl;
- }
-
- Standard_Boolean TempFalse1 = Standard_False;
- Standard_Boolean TempFalse2 = Standard_False;
-
- ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1,ptf,first,
- TempFalse2,ptl,last,Multpoint,Tol);
- slin.Append(alig);
- }
- }
- }
- break;
+ case IntAna_Parabola:
+ case IntAna_Hyperbola:
+ Standard_Failure::Raise("IntCyCy(): Wrong intersection type!");
+ case IntAna_Circle:
+ // Circle is useful when we will work with trimmed surfaces
+ // (two cylinders can be tangent by their basises, e.g. circle)
+ case IntAna_NoGeometricSolution:
default:
return Standard_False;
}
}
}
-enum SearchBoundType
-{
- SearchNONE = 0,
- SearchV1 = 1,
- SearchV2 = 2
-};
-
-//Stores equations coefficients
-struct stCoeffsValue
-{
- stCoeffsValue(const gp_Cylinder&, const gp_Cylinder&);
-
- gp_Vec mVecA1;
- gp_Vec mVecA2;
- gp_Vec mVecB1;
- gp_Vec mVecB2;
- gp_Vec mVecC1;
- gp_Vec mVecC2;
- gp_Vec mVecD;
-
- Standard_Real mK21; //sinU2
- Standard_Real mK11; //sinU1
- Standard_Real mL21; //cosU2
- Standard_Real mL11; //cosU1
- Standard_Real mM1; //Free member
-
- Standard_Real mK22; //sinU2
- Standard_Real mK12; //sinU1
- Standard_Real mL22; //cosU2
- Standard_Real mL12; //cosU1
- Standard_Real mM2; //Free member
-
- Standard_Real mK1;
- Standard_Real mL1;
- Standard_Real mK2;
- Standard_Real mL2;
-
- Standard_Real mFIV1;
- Standard_Real mPSIV1;
- Standard_Real mFIV2;
- Standard_Real mPSIV2;
-
- Standard_Real mB;
- Standard_Real mC;
- Standard_Real mFI1;
- Standard_Real mFI2;
-};
-
-stCoeffsValue::stCoeffsValue( const gp_Cylinder& theCyl1,
- const gp_Cylinder& theCyl2)
+//=======================================================================
+//function : CylCylMonotonicity
+//purpose : Determines, if U2(U1) function is increasing.
+//=======================================================================
+Standard_Boolean ComputationMethods::CylCylMonotonicity(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ const Standard_Real thePeriod,
+ Standard_Boolean& theIsIncreasing)
{
- const Standard_Real aNulValue = 0.01*Precision::PConfusion();
-
- mVecA1 = -theCyl1.Radius()*theCyl1.XAxis().Direction();
- mVecA2 = theCyl2.Radius()*theCyl2.XAxis().Direction();
-
- mVecB1 = -theCyl1.Radius()*theCyl1.YAxis().Direction();
- mVecB2 = theCyl2.Radius()*theCyl2.YAxis().Direction();
-
- mVecC1 = theCyl1.Axis().Direction();
- mVecC2 = -(theCyl2.Axis().Direction());
-
- mVecD = theCyl2.Location().XYZ() - theCyl1.Location().XYZ();
-
- enum CoupleOfEquation
+ // U2(U1) = FI2 + (+/-)acos(B*cos(U1 - FI1) + C);
+ //Accordingly,
+ //Func. U2(X1) = FI2 + X1;
+ //Func. X1(X2) = anArccosFactor*X2;
+ //Func. X2(X3) = acos(X3);
+ //Func. X3(X4) = B*X4 + C;
+ //Func. X4(U1) = cos(U1 - FI1).
+ //
+ //Consequently,
+ //U2(X1) is always increasing.
+ //X1(X2) is increasing if anArccosFactor > 0.0 and
+ //is decreasing otherwise.
+ //X2(X3) is always decreasing.
+ //Therefore, U2(X3) is decreasing if anArccosFactor > 0.0 and
+ //is increasing otherwise.
+ //X3(X4) is increasing if B > 0 and is decreasing otherwise.
+ //X4(U1) is increasing if U1 - FI1 in [PI, 2*PI) and
+ //is decreasing U1 - FI1 in [0, PI) or if (U1 - FI1 == 2PI).
+ //After that, we can predict behaviour of U2(U1) function:
+ //if it is increasing or decreasing.
+
+ //For "+/-" sign. If isPlus == TRUE, "+" is chosen, otherwise, we choose "-".
+ Standard_Boolean isPlus = Standard_False;
+
+ switch(theWLIndex)
{
- COENONE = 0,
- COE12 = 1,
- COE23 = 2,
- COE13 = 3
- }aFoundCouple = COENONE;
+ case 0:
+ isPlus = Standard_True;
+ break;
+ case 1:
+ isPlus = Standard_False;
+ break;
+ default:
+ //Standard_Failure::Raise("Error. Range Error!!!!");
+ return Standard_False;
+ }
+ Standard_Real aU1Temp = theU1par - theCoeffs.mFI1;
+ InscribePoint(0, thePeriod, aU1Temp, 0.0, thePeriod, Standard_False);
- Standard_Real aDetV1V2 = mVecC1.X()*mVecC2.Y()-mVecC1.Y()*mVecC2.X();
+ theIsIncreasing = Standard_True;
- if(Abs(aDetV1V2) < aNulValue)
+ if(((M_PI - aU1Temp) < RealSmall()) && (aU1Temp < thePeriod))
{
- aDetV1V2 = mVecC1.Y()*mVecC2.Z()-mVecC1.Z()*mVecC2.Y();
- if(Abs(aDetV1V2) < aNulValue)
- {
- aDetV1V2 = mVecC1.X()*mVecC2.Z()-mVecC1.Z()*mVecC2.X();
- if(Abs(aDetV1V2) < aNulValue)
- {
- Standard_Failure::Raise("Error. Exception in divide by zerro (IntCyCyTrim)!!!!");
- }
- else
- {
- aFoundCouple = COE13;
- }
- }
- else
- {
- aFoundCouple = COE23;
- }
+ theIsIncreasing = Standard_False;
}
- else
+
+ if(theCoeffs.mB < 0.0)
{
- aFoundCouple = COE12;
+ theIsIncreasing = !theIsIncreasing;
}
- switch(aFoundCouple)
+ if(!isPlus)
{
- case COE12:
- break;
- case COE23:
- {
- gp_Vec aVTemp = mVecA1;
- mVecA1.SetX(aVTemp.Y());
- mVecA1.SetY(aVTemp.Z());
- mVecA1.SetZ(aVTemp.X());
-
- aVTemp = mVecA2;
- mVecA2.SetX(aVTemp.Y());
- mVecA2.SetY(aVTemp.Z());
- mVecA2.SetZ(aVTemp.X());
-
- aVTemp = mVecB1;
- mVecB1.SetX(aVTemp.Y());
- mVecB1.SetY(aVTemp.Z());
- mVecB1.SetZ(aVTemp.X());
-
- aVTemp = mVecB2;
- mVecB2.SetX(aVTemp.Y());
- mVecB2.SetY(aVTemp.Z());
- mVecB2.SetZ(aVTemp.X());
-
- aVTemp = mVecC1;
- mVecC1.SetX(aVTemp.Y());
- mVecC1.SetY(aVTemp.Z());
- mVecC1.SetZ(aVTemp.X());
-
- aVTemp = mVecC2;
- mVecC2.SetX(aVTemp.Y());
- mVecC2.SetY(aVTemp.Z());
- mVecC2.SetZ(aVTemp.X());
-
- aVTemp = mVecD;
- mVecD.SetX(aVTemp.Y());
- mVecD.SetY(aVTemp.Z());
- mVecD.SetZ(aVTemp.X());
+ theIsIncreasing = !theIsIncreasing;
+ }
- break;
- }
- case COE13:
- {
- gp_Vec aVTemp = mVecA1;
- mVecA1.SetY(aVTemp.Z());
- mVecA1.SetZ(aVTemp.Y());
+ return Standard_True;
+}
- aVTemp = mVecA2;
- mVecA2.SetY(aVTemp.Z());
- mVecA2.SetZ(aVTemp.Y());
+//=======================================================================
+//function : CylCylComputeParameters
+//purpose : Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
+// esimates the tolerance of U2-computing (estimation result is
+// assigned to *theDelta value).
+//=======================================================================
+Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real* const theDelta)
+{
+ //This formula is got from some experience and can be changed.
+ const Standard_Real aTol0 = Min(10.0*Epsilon(1.0)*theCoeffs.mB, aNulValue);
+ const Standard_Real aTol = 1.0 - aTol0;
- aVTemp = mVecB1;
- mVecB1.SetY(aVTemp.Z());
- mVecB1.SetZ(aVTemp.Y());
+ if(theWLIndex < 0 || theWLIndex > 1)
+ return Standard_False;
- aVTemp = mVecB2;
- mVecB2.SetY(aVTemp.Z());
- mVecB2.SetZ(aVTemp.Y());
+ const Standard_Real aSign = theWLIndex ? -1.0 : 1.0;
- aVTemp = mVecC1;
- mVecC1.SetY(aVTemp.Z());
- mVecC1.SetZ(aVTemp.Y());
+ Standard_Real anArg = cos(theU1par - theCoeffs.mFI1);
+ anArg = theCoeffs.mB*anArg + theCoeffs.mC;
- aVTemp = mVecC2;
- mVecC2.SetY(aVTemp.Z());
- mVecC2.SetZ(aVTemp.Y());
+ if(anArg > aTol)
+ {
+ if(theDelta)
+ *theDelta = 0.0;
- aVTemp = mVecD;
- mVecD.SetY(aVTemp.Z());
- mVecD.SetZ(aVTemp.Y());
+ anArg = 1.0;
+ }
+ else if(anArg < -aTol)
+ {
+ if(theDelta)
+ *theDelta = 0.0;
- break;
- }
- default:
- break;
+ anArg = -1.0;
+ }
+ else if(theDelta)
+ {
+ //There is a case, when
+ // const double aPar = 0.99999999999721167;
+ // const double aFI2 = 2.3593296083566181e-006;
+
+ //Then
+ // aPar - cos(aFI2) == -5.10703e-015 ==> cos(aFI2) == aPar.
+ //Theoreticaly, in this case
+ // aFI2 == +/- acos(aPar).
+ //However,
+ // acos(aPar) - aFI2 == 2.16362e-009.
+ //Error is quite big.
+
+ //This error should be estimated. Let use following way, which is based
+ //on expanding to Taylor series.
+
+ // acos(p)-acos(p+x) = x/sqrt(1-p*p).
+
+ //If p == (1-d) (when p > 0) or p == (-1+d) (when p < 0) then
+ // acos(p)-acos(p+x) = x/sqrt(d*(2-d)).
+
+ //Here always aTol0 <= d <= 1. Max(x) is considered (!) to be equal to aTol0.
+ //In this case
+ // 8*aTol0 <= acos(p)-acos(p+x) <= sqrt(2/(2-aTol0)-1),
+ // because 0 < aTol0 < 1.
+ //E.g. when aTol0 = 1.0e-11,
+ // 8.0e-11 <= acos(p)-acos(p+x) < 2.24e-6.
+
+ const Standard_Real aDelta = Min(1.0-anArg, 1.0+anArg);
+ Standard_DivideByZero_Raise_if((aDelta*aDelta < RealSmall()) || (aDelta >= 2.0),
+ "IntPatch_ImpImpIntersection_4.gxx, CylCylComputeParameters()");
+ *theDelta = aTol0/sqrt(aDelta*(2.0-aDelta));
}
- //------- For V1 (begin)
- //sinU2
- mK21 = (mVecC2.Y()*mVecB2.X()-mVecC2.X()*mVecB2.Y())/aDetV1V2;
- //sinU1
- mK11 = (mVecC2.Y()*mVecB1.X()-mVecC2.X()*mVecB1.Y())/aDetV1V2;
- //cosU2
- mL21 = (mVecC2.Y()*mVecA2.X()-mVecC2.X()*mVecA2.Y())/aDetV1V2;
- //cosU1
- mL11 = (mVecC2.Y()*mVecA1.X()-mVecC2.X()*mVecA1.Y())/aDetV1V2;
- //Free member
- mM1 = (mVecC2.Y()*mVecD.X()-mVecC2.X()*mVecD.Y())/aDetV1V2;
- //------- For V1 (end)
+ theU2 = acos(anArg);
+ theU2 = theCoeffs.mFI2 + aSign*theU2;
- //------- For V2 (begin)
- //sinU2
- mK22 = (mVecC1.X()*mVecB2.Y()-mVecC1.Y()*mVecB2.X())/aDetV1V2;
- //sinU1
- mK12 = (mVecC1.X()*mVecB1.Y()-mVecC1.Y()*mVecB1.X())/aDetV1V2;
- //cosU2
- mL22 = (mVecC1.X()*mVecA2.Y()-mVecC1.Y()*mVecA2.X())/aDetV1V2;
- //cosU1
- mL12 = (mVecC1.X()*mVecA1.Y()-mVecC1.Y()*mVecA1.X())/aDetV1V2;
- //Free member
- mM2 = (mVecC1.X()*mVecD.Y()-mVecC1.Y()*mVecD.X())/aDetV1V2;
- //------- For V1 (end)
+ return Standard_True;
+}
- ShortCosForm(mL11, mK11, mK1, mFIV1);
- ShortCosForm(mL21, mK21, mL1, mPSIV1);
- ShortCosForm(mL12, mK12, mK2, mFIV2);
- ShortCosForm(mL22, mK22, mL2, mPSIV2);
+Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1,
+ const Standard_Real theU2,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theV1,
+ Standard_Real& theV2)
+{
+ theV1 = theCoeffs.mK21 * sin(theU2) +
+ theCoeffs.mK11 * sin(theU1) +
+ theCoeffs.mL21 * cos(theU2) +
+ theCoeffs.mL11 * cos(theU1) + theCoeffs.mM1;
- const Standard_Real aA1=mVecC1.Z()*mK21+mVecC2.Z()*mK22-mVecB2.Z(), //sinU2
- aA2=mVecC1.Z()*mL21+mVecC2.Z()*mL22-mVecA2.Z(), //cosU2
- aB1=mVecB1.Z()-mVecC1.Z()*mK11-mVecC2.Z()*mK12, //sinU1
- aB2=mVecA1.Z()-mVecC1.Z()*mL11-mVecC2.Z()*mL12; //cosU1
+ theV2 = theCoeffs.mK22 * sin(theU2) +
+ theCoeffs.mK12 * sin(theU1) +
+ theCoeffs.mL22 * cos(theU2) +
+ theCoeffs.mL12 * cos(theU1) + theCoeffs.mM2;
- mC =mVecD.Z() -mVecC1.Z()*mM1 -mVecC2.Z()*mM2; //Free
+ return Standard_True;
+}
- Standard_Real aA = 0.0;
- ShortCosForm(aB2,aB1,mB,mFI1);
- ShortCosForm(aA2,aA1,aA,mFI2);
+Standard_Boolean ComputationMethods::CylCylComputeParameters(const Standard_Real theU1par,
+ const Standard_Integer theWLIndex,
+ const stCoeffsValue& theCoeffs,
+ Standard_Real& theU2,
+ Standard_Real& theV1,
+ Standard_Real& theV2)
+{
+ if(!CylCylComputeParameters(theU1par, theWLIndex, theCoeffs, theU2))
+ return Standard_False;
- mB /= aA;
- mC /= aA;
+ if(!CylCylComputeParameters(theU1par, theU2, theCoeffs, theV1, theV2))
+ return Standard_False;
+
+ return Standard_True;
}
//=======================================================================
//function : SearchOnVBounds
//purpose :
//=======================================================================
-static Standard_Boolean SearchOnVBounds(const SearchBoundType theSBType,
- const stCoeffsValue& theCoeffs,
+Standard_Boolean WorkWithBoundaries::
+ SearchOnVBounds(const SearchBoundType theSBType,
const Standard_Real theVzad,
+ const Standard_Real theVInit,
const Standard_Real theInitU2,
const Standard_Real theInitMainVar,
- Standard_Real& theMainVariableValue)
+ Standard_Real& theMainVariableValue) const
{
+ const Standard_Integer aNbDim = 3;
const Standard_Real aMaxError = 4.0*M_PI; // two periods
- theMainVariableValue = RealLast();
- const Standard_Real aTol2 = Precision::PConfusion()*Precision::PConfusion();
- Standard_Real aMainVarPrev = theInitMainVar, aU2Prev = theInitU2, anOtherVar = theVzad;
+ theMainVariableValue = theInitMainVar;
+ const Standard_Real aTol2 = 1.0e-18;
+ Standard_Real aMainVarPrev = theInitMainVar, aU2Prev = theInitU2, anOtherVar = theVInit;
+ //Structure of aMatr:
+ // C_{1}*U_{1} & C_{2}*U_{2} & C_{3}*V_{*},
+ //where C_{1}, C_{2} and C_{3} are math_Vector.
+ math_Matrix aMatr(1, aNbDim, 1, aNbDim);
+
Standard_Real anError = RealLast();
+ Standard_Real anErrorPrev = anError;
Standard_Integer aNbIter = 0;
do
{
if(++aNbIter > 1000)
return Standard_False;
- gp_Vec aVecMainVar = theCoeffs.mVecA1 * sin(aMainVarPrev) - theCoeffs.mVecB1 * cos(aMainVarPrev);
- gp_Vec aVecFreeMem = (theCoeffs.mVecA2 * aU2Prev + theCoeffs.mVecB2) * sin(aU2Prev) -
- (theCoeffs.mVecB2 * aU2Prev - theCoeffs.mVecA2) * cos(aU2Prev) +
- (theCoeffs.mVecA1 * aMainVarPrev + theCoeffs.mVecB1) * sin(aMainVarPrev) -
- (theCoeffs.mVecB1 * aMainVarPrev - theCoeffs.mVecA1) * cos(aMainVarPrev) + theCoeffs.mVecD;
+ const Standard_Real aSinU1 = sin(aMainVarPrev),
+ aCosU1 = cos(aMainVarPrev),
+ aSinU2 = sin(aU2Prev),
+ aCosU2 = cos(aU2Prev);
- gp_Vec aVecVar1 = theCoeffs.mVecA2 * sin(aU2Prev) - theCoeffs.mVecB2 * cos(aU2Prev);
- gp_Vec aVecVar2;
+ math_Vector aVecFreeMem = (myCoeffs.mVecA2 * aU2Prev +
+ myCoeffs.mVecB2) * aSinU2 -
+ (myCoeffs.mVecB2 * aU2Prev -
+ myCoeffs.mVecA2) * aCosU2 +
+ (myCoeffs.mVecA1 * aMainVarPrev +
+ myCoeffs.mVecB1) * aSinU1 -
+ (myCoeffs.mVecB1 * aMainVarPrev -
+ myCoeffs.mVecA1) * aCosU1 +
+ myCoeffs.mVecD;
+
+ math_Vector aMSum(1, 3);
switch(theSBType)
{
case SearchV1:
- aVecVar2 = theCoeffs.mVecC2;
- aVecFreeMem -= theCoeffs.mVecC1 * theVzad;
+ aMatr.SetCol(3, myCoeffs.mVecC2);
+ aMSum = myCoeffs.mVecC1 * theVzad;
+ aVecFreeMem -= aMSum;
+ aMSum += myCoeffs.mVecC2*anOtherVar;
break;
case SearchV2:
- aVecVar2 = theCoeffs.mVecC1;
- aVecFreeMem -= theCoeffs.mVecC2 * theVzad;
+ aMatr.SetCol(3, myCoeffs.mVecC1);
+ aMSum = myCoeffs.mVecC2 * theVzad;
+ aVecFreeMem -= aMSum;
+ aMSum += myCoeffs.mVecC1*anOtherVar;
break;
default:
return Standard_False;
}
- Standard_Real aDetMainSyst = aVecMainVar.X()*(aVecVar1.Y()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.Y())-
- aVecMainVar.Y()*(aVecVar1.X()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.X())+
- aVecMainVar.Z()*(aVecVar1.X()*aVecVar2.Y()-aVecVar1.Y()*aVecVar2.X());
+ aMatr.SetCol(1, myCoeffs.mVecA1 * aSinU1 - myCoeffs.mVecB1 * aCosU1);
+ aMatr.SetCol(2, myCoeffs.mVecA2 * aSinU2 - myCoeffs.mVecB2 * aCosU2);
+
+ Standard_Real aDetMainSyst = aMatr.Determinant();
- if(IsEqual(aDetMainSyst, 0.0))
+ if(Abs(aDetMainSyst) < aNulValue)
{
return Standard_False;
}
-
- Standard_Real aDetMainVar = aVecFreeMem.X()*(aVecVar1.Y()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.Y())-
- aVecFreeMem.Y()*(aVecVar1.X()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.X())+
- aVecFreeMem.Z()*(aVecVar1.X()*aVecVar2.Y()-aVecVar1.Y()*aVecVar2.X());
-
- Standard_Real aDetVar1 = aVecMainVar.X()*(aVecFreeMem.Y()*aVecVar2.Z()-aVecFreeMem.Z()*aVecVar2.Y())-
- aVecMainVar.Y()*(aVecFreeMem.X()*aVecVar2.Z()-aVecFreeMem.Z()*aVecVar2.X())+
- aVecMainVar.Z()*(aVecFreeMem.X()*aVecVar2.Y()-aVecFreeMem.Y()*aVecVar2.X());
+ math_Matrix aM1(aMatr), aM2(aMatr), aM3(aMatr);
+ aM1.SetCol(1, aVecFreeMem);
+ aM2.SetCol(2, aVecFreeMem);
+ aM3.SetCol(3, aVecFreeMem);
- Standard_Real aDetVar2 = aVecMainVar.X()*(aVecVar1.Y()*aVecFreeMem.Z()-aVecVar1.Z()*aVecFreeMem.Y())-
- aVecMainVar.Y()*(aVecVar1.X()*aVecFreeMem.Z()-aVecVar1.Z()*aVecFreeMem.X())+
- aVecMainVar.Z()*(aVecVar1.X()*aVecFreeMem.Y()-aVecVar1.Y()*aVecFreeMem.X());
+ const Standard_Real aDetMainVar = aM1.Determinant();
+ const Standard_Real aDetVar1 = aM2.Determinant();
+ const Standard_Real aDetVar2 = aM3.Determinant();
Standard_Real aDelta = aDetMainVar/aDetMainSyst-aMainVarPrev;
aDelta = aDetVar2/aDetMainSyst-anOtherVar;
anError += aDelta*aDelta;
anOtherVar += aDelta;
- }
- while(anError > aTol2);
+
+ if(anError > anErrorPrev)
+ {//Method diverges. Keep the best result
+ const Standard_Real aSinU1Last = sin(aMainVarPrev),
+ aCosU1Last = cos(aMainVarPrev),
+ aSinU2Last = sin(aU2Prev),
+ aCosU2Last = cos(aU2Prev);
+ aMSum -= (myCoeffs.mVecA1*aCosU1Last +
+ myCoeffs.mVecB1*aSinU1Last +
+ myCoeffs.mVecA2*aCosU2Last +
+ myCoeffs.mVecB2*aSinU2Last +
+ myCoeffs.mVecD);
+ const Standard_Real aSQNorm = aMSum.Norm2();
+ return (aSQNorm < aTol2);
+ }
+ else
+ {
+ theMainVariableValue = aMainVarPrev;
+ }
+
+ anErrorPrev = anError;
+ }
+ while(anError > aTol2);
theMainVariableValue = aMainVarPrev;
//=======================================================================
//function : InscribePoint
-//purpose :
+//purpose : If theFlForce==TRUE theUGiven will be changed forcefully
+// even if theUGiven is already inscibed in the boundary
+// (if it is possible; i.e. if new theUGiven is inscribed
+// in the boundary, too).
//=======================================================================
-static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
- const Standard_Real theUlTarget,
- Standard_Real& theUGiven,
- const Standard_Real theTol2D,
- const Standard_Real thePeriod)
+Standard_Boolean InscribePoint( const Standard_Real theUfTarget,
+ const Standard_Real theUlTarget,
+ Standard_Real& theUGiven,
+ const Standard_Real theTol2D,
+ const Standard_Real thePeriod,
+ const Standard_Boolean theFlForce)
{
- if((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D))
+ if(Precision::IsInfinite(theUGiven))
+ {
+ return Standard_False;
+ }
+
+ if((theUfTarget - theUGiven <= theTol2D) &&
+ (theUGiven - theUlTarget <= theTol2D))
{//it has already inscribed
/*
+ * +
*/
- return Standard_True;
- }
+ if(theFlForce)
+ {
+ Standard_Real anUtemp = theUGiven + thePeriod;
+ if((theUfTarget - anUtemp <= theTol2D) &&
+ (anUtemp - theUlTarget <= theTol2D))
+ {
+ theUGiven = anUtemp;
+ return Standard_True;
+ }
+
+ anUtemp = theUGiven - thePeriod;
+ if((theUfTarget - anUtemp <= theTol2D) &&
+ (anUtemp - theUlTarget <= theTol2D))
+ {
+ theUGiven = anUtemp;
+ }
+ }
- if(IsEqual(thePeriod, 0.0))
- {//it cannot be inscribed
- return Standard_False;
+ return Standard_True;
}
- Standard_Real aDU = theUGiven - theUfTarget;
+ const Standard_Real aUf = theUfTarget - theTol2D;
+ const Standard_Real aUl = aUf + thePeriod;
- if(aDU > 0.0)
- aDU = -thePeriod;
- else
- aDU = +thePeriod;
-
- while(((theUGiven - theUfTarget)*aDU < 0.0) && !((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D)))
- {
- theUGiven += aDU;
- }
+ theUGiven = ElCLib::InPeriod(theUGiven, aUf, aUl);
- return ((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D));
+ return ((theUfTarget - theUGiven <= theTol2D) &&
+ (theUGiven - theUlTarget <= theTol2D));
}
//=======================================================================
//function : InscribeInterval
-//purpose : Adjusts theUfGiven and after that fits theUlGiven to result
+//purpose : Adjusts theUfGiven and (after that) adjusts theUlGiven to the result
//=======================================================================
static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
const Standard_Real theUlTarget,
{
Standard_Real anUpar = theUfGiven;
const Standard_Real aDelta = theUlGiven - theUfGiven;
- if(InscribePoint(theUfTarget, theUlTarget, anUpar, theTol2D, thePeriod))
+ if(InscribePoint(theUfTarget, theUlTarget, anUpar,
+ theTol2D, thePeriod, Standard_False))
{
theUfGiven = anUpar;
theUlGiven = theUfGiven + aDelta;
else
{
anUpar = theUlGiven;
- if(InscribePoint(theUfTarget, theUlTarget, anUpar, theTol2D, thePeriod))
+ if(InscribePoint(theUfTarget, theUlTarget, anUpar,
+ theTol2D, thePeriod, Standard_False))
{
theUlGiven = anUpar;
theUfGiven = theUlGiven - aDelta;
}
//=======================================================================
-//function : InscribeAndSortArray
-//purpose : Sort from Min to Max value
+//function : ExcludeNearElements
+//purpose : Checks if theArr contains two almost equal elements.
+// If it is true then one of equal elements will be excluded
+// (made infinite).
+// Returns TRUE if at least one element of theArr has been changed.
+//ATTENTION!!!
+// 1. Every not infinite element of theArr is considered to be
+// in [0, T] interval (where T is the period);
+// 2. theArr must be sorted in ascending order.
//=======================================================================
-static void InscribeAndSortArray( Standard_Real theArr[],
- const Standard_Integer theNOfMembers,
- const Standard_Real theUf,
- const Standard_Real theUl,
- const Standard_Real theTol2D,
- const Standard_Real thePeriod)
+static Standard_Boolean ExcludeNearElements(Standard_Real theArr[],
+ const Standard_Integer theNOfMembers,
+ const Standard_Real theUSurf1f,
+ const Standard_Real theUSurf1l,
+ const Standard_Real theTol)
{
- for(Standard_Integer i = 0; i < theNOfMembers; i++)
+ Standard_Boolean aRetVal = Standard_False;
+ for(Standard_Integer i = 1; i < theNOfMembers; i++)
{
- if(Precision::IsInfinite(theArr[i]))
- {
- if(theArr[i] < 0.0)
- theArr[i] = -theArr[i];
+ Standard_Real &anA = theArr[i],
+ &anB = theArr[i-1];
- continue;
- }
+ //Here, anA >= anB
- InscribePoint(theUf, theUl, theArr[i], theTol2D, thePeriod);
+ if(Precision::IsInfinite(anA))
+ break;
- for(Standard_Integer j = i - 1; j >= 0; j--)
+ if((anA-anB) < theTol)
{
+ if((anB != 0.0) && (anB != theUSurf1f) && (anB != theUSurf1l))
+ anA = (anA + anB)/2.0;
+ else
+ anA = anB;
- if(theArr[j+1] < theArr[j])
- {
- Standard_Real anUtemp = theArr[j+1];
- theArr[j+1] = theArr[j];
- theArr[j] = anUtemp;
- }
+ //Make this element infinite an forget it
+ //(we will not use it in next iterations).
+ anB = Precision::Infinite();
+ aRetVal = Standard_True;
}
}
-}
+ return aRetVal;
+}
//=======================================================================
//function : AddPointIntoWL
//=======================================================================
static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1,
const IntSurf_Quadric& theQuad2,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
const Standard_Boolean isTheReverse,
+ const Standard_Boolean isThePrecise,
const gp_Pnt2d& thePntOnSurf1,
const gp_Pnt2d& thePntOnSurf2,
const Standard_Real theUfSurf1,
const Standard_Real theUlSurf1,
+ const Standard_Real theUfSurf2,
+ const Standard_Real theUlSurf2,
+ const Standard_Real theVfSurf1,
+ const Standard_Real theVlSurf1,
+ const Standard_Real theVfSurf2,
+ const Standard_Real theVlSurf2,
const Standard_Real thePeriodOfSurf1,
const Handle(IntSurf_LineOn2S)& theLine,
- const Standard_Real theTol2D)
+ const Standard_Integer theWLIndex,
+ const Standard_Real theTol3D,
+ const Standard_Real theTol2D,
+ const Standard_Boolean theFlForce,
+ const Standard_Boolean theFlBefore = Standard_False)
{
+ //Check if the point is in the domain or can be inscribed in the domain after adjusting.
+
gp_Pnt aPt1(theQuad1.Value(thePntOnSurf1.X(), thePntOnSurf1.Y())),
aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y()));
- Standard_Real anUpar = thePntOnSurf1.X();
- if(!InscribePoint(theUfSurf1, theUlSurf1, anUpar, theTol2D, thePeriodOfSurf1))
+ Standard_Real aU1par = thePntOnSurf1.X();
+ if(!InscribePoint(theUfSurf1, theUlSurf1, aU1par, theTol2D,
+ thePeriodOfSurf1, theFlForce))
+ return Standard_False;
+
+ Standard_Real aU2par = thePntOnSurf2.X();
+ if(!InscribePoint(theUfSurf2, theUlSurf2, aU2par, theTol2D,
+ thePeriodOfSurf1, Standard_False))
return Standard_False;
+ Standard_Real aV1par = thePntOnSurf1.Y();
+ if((aV1par - theVlSurf1 > theTol2D) || (theVfSurf1 - aV1par > theTol2D))
+ return Standard_False;
+
+ Standard_Real aV2par = thePntOnSurf2.Y();
+ if((aV2par - theVlSurf2 > theTol2D) || (theVfSurf2 - aV2par > theTol2D))
+ return Standard_False;
+
+ //Get intersection point and add it in the WL
IntSurf_PntOn2S aPnt;
if(isTheReverse)
{
aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
- thePntOnSurf2.X(), thePntOnSurf2.Y(),
- thePntOnSurf1.X(), thePntOnSurf1.Y());
+ aU2par, aV2par,
+ aU1par, aV1par);
}
else
{
aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
- thePntOnSurf1.X(), thePntOnSurf1.Y(),
- thePntOnSurf2.X(), thePntOnSurf2.Y());
+ aU1par, aV1par,
+ aU2par, aV2par);
+ }
+
+ Standard_Integer aNbPnts = theLine->NbPoints();
+ if(aNbPnts > 0)
+ {
+ Standard_Real aUl = 0.0, aVl = 0.0;
+ const IntSurf_PntOn2S aPlast = theLine->Value(aNbPnts);
+ if(isTheReverse)
+ aPlast.ParametersOnS2(aUl, aVl);
+ else
+ aPlast.ParametersOnS1(aUl, aVl);
+
+ if(!theFlBefore && (aU1par <= aUl))
+ {
+ //Parameter value must be increased if theFlBefore == FALSE.
+
+ aU1par += thePeriodOfSurf1;
+
+ //The condition is as same as in
+ //InscribePoint(...) function
+ if((theUfSurf1 - aU1par > theTol2D) ||
+ (aU1par - theUlSurf1 > theTol2D))
+ {
+ //New aU1par is out of target interval.
+ //Go back to old value.
+
+ return Standard_False;
+ }
+ }
+
+ //theTol2D is minimal step along parameter changed.
+ //Therefore, if we apply this minimal step two
+ //neighbour points will be always "same". Consequently,
+ //we should reduce tolerance for IsSame checking.
+ const Standard_Real aDTol = 1.0-Epsilon(1.0);
+ if(aPnt.IsSame(aPlast, theTol3D*aDTol, theTol2D*aDTol))
+ {
+ theLine->RemovePoint(aNbPnts);
+ }
}
theLine->Add(aPnt);
+
+ if(!isThePrecise)
+ return Standard_True;
+
+ //Try to precise existing WLine
+ aNbPnts = theLine->NbPoints();
+ if(aNbPnts >= 3)
+ {
+ Standard_Real aU1 = 0.0, aU2 = 0.0, aU3 = 0.0, aV = 0.0;
+ if(isTheReverse)
+ {
+ theLine->Value(aNbPnts).ParametersOnS2(aU3, aV);
+ theLine->Value(aNbPnts-1).ParametersOnS2(aU2, aV);
+ theLine->Value(aNbPnts-2).ParametersOnS2(aU1, aV);
+ }
+ else
+ {
+ theLine->Value(aNbPnts).ParametersOnS1(aU3, aV);
+ theLine->Value(aNbPnts-1).ParametersOnS1(aU2, aV);
+ theLine->Value(aNbPnts-2).ParametersOnS1(aU1, aV);
+ }
+
+ const Standard_Real aStepPrev = aU2-aU1;
+ const Standard_Real aStep = aU3-aU2;
+
+ const Standard_Integer aDeltaStep = RealToInt(aStepPrev/aStep);
+
+ if((1 < aDeltaStep) && (aDeltaStep < 2000))
+ {
+ //Add new points in case of non-uniform distribution of existing points
+ SeekAdditionalPoints( theQuad1, theQuad2, theLine,
+ theCoeffs, theWLIndex, aDeltaStep, aNbPnts-2,
+ aNbPnts-1, theTol2D, thePeriodOfSurf1, isTheReverse);
+ }
+ }
+
return Standard_True;
}
//=======================================================================
//function : AddBoundaryPoint
-//purpose :
+//purpose : Find intersection point on V-boundary.
//=======================================================================
-static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
- const IntSurf_Quadric& theQuad2,
- const Handle(IntPatch_WLine)& theWL,
- const stCoeffsValue& theCoeffs,
- const Bnd_Box2d& theUVSurf1,
- const Bnd_Box2d& theUVSurf2,
- const Standard_Real theTol2D,
- const Standard_Real thePeriod,
- const Standard_Real theNulValue,
+void WorkWithBoundaries::AddBoundaryPoint(const Handle(IntPatch_WLine)& theWL,
const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Real theV1,
const Standard_Real theV1Prev,
const Standard_Real theV2,
const Standard_Real theV2Prev,
- const Standard_Boolean isTheReverse,
- const Standard_Real theArccosFactor,
+ const Standard_Integer theWLIndex,
+ const Standard_Boolean theFlForce,
Standard_Boolean& isTheFound1,
- Standard_Boolean& isTheFound2)
+ Standard_Boolean& isTheFound2) const
{
Standard_Real aUSurf1f = 0.0, //const
aUSurf1l = 0.0,
aVSurf2f = 0.0,
aVSurf2l = 0.0;
- theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
- theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
+ myUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
+ myUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
+
+ const Standard_Integer aSize = 4;
+ const Standard_Real anArrVzad[aSize] = {aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l};
- SearchBoundType aTS1 = SearchNONE, aTS2 = SearchNONE;
- Standard_Real aV1zad = aVSurf1f, aV2zad = aVSurf2f;
+ StPInfo aUVPoint[aSize];
- Standard_Real anUpar1 = theU1, anUpar2 = theU1;
- Standard_Real aVf = theV1, aVl = theV1Prev;
- MinMax(aVf, aVl);
- if((aVf <= aVSurf1f) && (aVSurf1f <= aVl))
- {
- aTS1 = SearchV1;
- aV1zad = aVSurf1f;
- isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1f, theU2, theU1, anUpar1);
- }
- else if((aVf <= aVSurf1l) && (aVSurf1l <= aVl))
+ for(Standard_Integer anIDSurf = 0; anIDSurf < 4; anIDSurf+=2)
{
- aTS1 = SearchV1;
- aV1zad = aVSurf1l;
- isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1l, theU2, theU1, anUpar1);
- }
+ const Standard_Real aVf = (anIDSurf == 0) ? theV1 : theV2,
+ aVl = (anIDSurf == 0) ? theV1Prev : theV2Prev;
- aVf = theV2;
- aVl = theV2Prev;
- MinMax(aVf, aVl);
+ const SearchBoundType aTS = (anIDSurf == 0) ? SearchV1 : SearchV2;
- if((aVf <= aVSurf2f) && (aVSurf2f <= aVl))
- {
- aTS2 = SearchV2;
- aV2zad = aVSurf2f;
- isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2f, theU2, theU1, anUpar2);
- }
- else if((aVf <= aVSurf2l) && (aVSurf2l <= aVl))
- {
- aTS2 = SearchV2;
- aV2zad = aVSurf2l;
- isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2l, theU2, theU1, anUpar2);
- }
-
- if(anUpar1 < anUpar2)
- {
- if(isTheFound1)
+ for(Standard_Integer anIDBound = 0; anIDBound < 2; anIDBound++)
{
- Standard_Real anArg = theCoeffs.mB * cos(anUpar1 - theCoeffs.mFI1) + theCoeffs.mC;
- if(theNulValue > 1.0 - anArg)
- anArg = 1.0;
- if(anArg + 1.0 < theNulValue)
- anArg = -1.0;
+ const Standard_Integer anIndex = anIDSurf+anIDBound;
- Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
-
- if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod))
- {
- const Standard_Real aV1 = (aTS1 == SearchV1) ? aV1zad :
- theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar1) +
- theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar1) + theCoeffs.mM1;
- const Standard_Real aV2 = (aTS1 == SearchV2) ? aV2zad :
- theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar1) +
- theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar1) + theCoeffs.mM2;
-
- AddPointIntoWL(theQuad1, theQuad2, isTheReverse, gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2), aUSurf1f, aUSurf1l, thePeriod, theWL->Curve(), theTol2D);
- }
- else
+ aUVPoint[anIndex].mySurfID = anIDSurf;
+
+ if((Abs(aVf-anArrVzad[anIndex]) > myTol2D) &&
+ ((aVf-anArrVzad[anIndex])*(aVl-anArrVzad[anIndex]) > 0.0))
{
- isTheFound1 = Standard_False;
+ continue;
}
- }
- if(isTheFound2)
- {
- Standard_Real anArg = theCoeffs.mB * cos(anUpar2 - theCoeffs.mFI1) + theCoeffs.mC;
+ //Segment [aVf, aVl] intersects at least one V-boundary (first or last)
+ // (in general, case is possible, when aVf > aVl).
- if(theNulValue > 1.0 - anArg)
- anArg = 1.0;
- if(anArg + 1.0 < theNulValue)
- anArg = -1.0;
+ // Precise intersection point
+ const Standard_Boolean aRes = SearchOnVBounds(aTS, anArrVzad[anIndex],
+ (anIDSurf == 0) ? theV2 : theV1,
+ theU2, theU1,
+ aUVPoint[anIndex].myU1);
- Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
- if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod))
+ if(!aRes || aUVPoint[anIndex].myU1 >= theU1)
{
- const Standard_Real aV1 = (aTS2 == SearchV1) ? aV1zad :
- theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar2) +
- theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar2) + theCoeffs.mM1;
- const Standard_Real aV2 = (aTS2 == SearchV2) ? aV2zad :
- theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar2) +
- theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar2) + theCoeffs.mM2;
-
- AddPointIntoWL(theQuad1, theQuad2, isTheReverse, gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2), aUSurf1f, aUSurf1l, thePeriod, theWL->Curve(), theTol2D);
+ //Intersection point is not found or out of the domain
+ aUVPoint[anIndex].myU1 = RealLast();
+ continue;
}
else
{
- isTheFound2 = Standard_False;
+ //intersection point is found
+
+ Standard_Real &aU1 = aUVPoint[anIndex].myU1,
+ &aU2 = aUVPoint[anIndex].myU2,
+ &aV1 = aUVPoint[anIndex].myV1,
+ &aV2 = aUVPoint[anIndex].myV2;
+ aU2 = theU2;
+ aV1 = theV1;
+ aV2 = theV2;
+
+ if(!ComputationMethods::
+ CylCylComputeParameters(aU1, theWLIndex, myCoeffs, aU2, aV1, aV2))
+ {
+ // Found point is wrong
+ aU1 = RealLast();
+ continue;
+ }
+
+ //Point on true V-boundary.
+ if(aTS == SearchV1)
+ aV1 = anArrVzad[anIndex];
+ else //if(aTS[anIndex] == SearchV2)
+ aV2 = anArrVzad[anIndex];
}
}
}
- else
- {
- if(isTheFound2)
- {
- Standard_Real anArg = theCoeffs.mB * cos(anUpar2 - theCoeffs.mFI1) + theCoeffs.mC;
- if(theNulValue > 1.0 - anArg)
- anArg = 1.0;
- if(anArg + 1.0 < theNulValue)
- anArg = -1.0;
+ // Sort with acceding U1-parameter.
+ std::sort(aUVPoint, aUVPoint+aSize);
+
+ isTheFound1 = isTheFound2 = Standard_False;
- Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
-
- if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod))
- {
- const Standard_Real aV1 = (aTS2 == SearchV1) ? aV1zad :
- theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar2) +
- theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar2) + theCoeffs.mM1;
- const Standard_Real aV2 = (aTS2 == SearchV2) ? aV2zad :
- theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar2) +
- theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar2) + theCoeffs.mM2;
-
- AddPointIntoWL(theQuad1, theQuad2, isTheReverse, gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2), aUSurf1f, aUSurf1l, thePeriod, theWL->Curve(), theTol2D);
- }
- else
- {
- isTheFound2 = Standard_False;
- }
- }
+ //Adding found points on boundary in the WLine.
+ for(Standard_Integer i = 0; i < aSize; i++)
+ {
+ if(aUVPoint[i].myU1 == RealLast())
+ break;
- if(isTheFound1)
+ if(!AddPointIntoWL(myQuad1, myQuad2, myCoeffs, myIsReverse, Standard_False,
+ gp_Pnt2d(aUVPoint[i].myU1, aUVPoint[i].myV1),
+ gp_Pnt2d(aUVPoint[i].myU2, aUVPoint[i].myV2),
+ aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
+ aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, myPeriod,
+ theWL->Curve(), theWLIndex, myTol3D, myTol2D, theFlForce))
{
- Standard_Real anArg = theCoeffs.mB*cos(anUpar1-theCoeffs.mFI1)+theCoeffs.mC;
-
- if(theNulValue > 1.0 - anArg)
- anArg = 1.0;
- if(anArg + 1.0 < theNulValue)
- anArg = -1.0;
+ continue;
+ }
- Standard_Real aU2 = theCoeffs.mFI2+theArccosFactor*acos(anArg);
- if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod))
- {
- const Standard_Real aV1 = (aTS1 == SearchV1) ? aV1zad :
- theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar1) +
- theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar1) + theCoeffs.mM1;
- const Standard_Real aV2 = (aTS1 == SearchV2) ? aV2zad :
- theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar1) +
- theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar1) + theCoeffs.mM2;
-
- AddPointIntoWL(theQuad1, theQuad2, isTheReverse, gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2), aUSurf1f, aUSurf1l, thePeriod, theWL->Curve(), theTol2D);
- }
- else
- {
- isTheFound1 = Standard_False;
- }
+ if(aUVPoint[i].mySurfID == 0)
+ {
+ isTheFound1 = Standard_True;
+ }
+ else
+ {
+ isTheFound2 = Standard_True;
}
}
-
- return Standard_True;
}
//=======================================================================
//function : SeekAdditionalPoints
-//purpose :
+//purpose : Inserts additional intersection points between neighbor points.
+// This action is bone with several iterations. During every iteration,
+// new point is inserted in middle of every interval.
+// The process will be finished if NbPoints >= theMinNbPoints.
//=======================================================================
static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
const IntSurf_Quadric& theQuad2,
- const Handle(IntSurf_LineOn2S)& theLile,
- const stCoeffsValue& theCoeffs,
+ const Handle(IntSurf_LineOn2S)& theLine,
+ const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Integer theWLIndex,
const Standard_Integer theMinNbPoints,
- const Standard_Real theU2f,
- const Standard_Real theU2l,
+ const Standard_Integer theStartPointOnLine,
+ const Standard_Integer theEndPointOnLine,
const Standard_Real theTol2D,
const Standard_Real thePeriodOfSurf2,
- const Standard_Real theArccosFactor,
const Standard_Boolean isTheReverse)
{
- Standard_Integer aNbPoints = theLile->NbPoints();
+ if(theLine.IsNull())
+ return;
+
+ Standard_Integer aNbPoints = theEndPointOnLine - theStartPointOnLine + 1;
if(aNbPoints >= theMinNbPoints)
{
return;
}
+ Standard_Real aMinDeltaParam = theTol2D;
+
+ {
+ Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
+
+ if(isTheReverse)
+ {
+ theLine->Value(theStartPointOnLine).ParametersOnS2(u1, v1);
+ theLine->Value(theEndPointOnLine).ParametersOnS2(u2, v2);
+ }
+ else
+ {
+ theLine->Value(theStartPointOnLine).ParametersOnS1(u1, v1);
+ theLine->Value(theEndPointOnLine).ParametersOnS1(u2, v2);
+ }
+
+ aMinDeltaParam = Max(Abs(u2 - u1)/IntToReal(theMinNbPoints), aMinDeltaParam);
+ }
+
+ Standard_Integer aLastPointIndex = theEndPointOnLine;
Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
Standard_Integer aNbPointsPrev = 0;
while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
{
aNbPointsPrev = aNbPoints;
- for(Standard_Integer fp = 1, lp = 2; fp < aNbPoints; fp = lp + 1)
+ for(Standard_Integer fp = theStartPointOnLine, lp = 0; fp < aLastPointIndex; fp = lp + 1)
{
- Standard_Real U1f, V1f; //first point in 1st suraface
- Standard_Real U1l, V1l; //last point in 1st suraface
+ Standard_Real U1f = 0.0, V1f = 0.0; //first point in 1st suraface
+ Standard_Real U1l = 0.0, V1l = 0.0; //last point in 1st suraface
+
+ Standard_Real U2f = 0.0, V2f = 0.0; //first point in 2nd suraface
+ Standard_Real U2l = 0.0, V2l = 0.0; //last point in 2nd suraface
lp = fp+1;
if(isTheReverse)
{
- theLile->Value(fp).ParametersOnS2(U1f, V1f);
- theLile->Value(lp).ParametersOnS2(U1l, V1l);
+ theLine->Value(fp).ParametersOnS2(U1f, V1f);
+ theLine->Value(lp).ParametersOnS2(U1l, V1l);
+
+ theLine->Value(fp).ParametersOnS1(U2f, V2f);
+ theLine->Value(lp).ParametersOnS1(U2l, V2l);
}
else
{
- theLile->Value(fp).ParametersOnS1(U1f, V1f);
- theLile->Value(lp).ParametersOnS1(U1l, V1l);
+ theLine->Value(fp).ParametersOnS1(U1f, V1f);
+ theLine->Value(lp).ParametersOnS1(U1l, V1l);
+
+ theLine->Value(fp).ParametersOnS2(U2f, V2f);
+ theLine->Value(lp).ParametersOnS2(U2l, V2l);
+ }
+
+ if(Abs(U1l - U1f) <= aMinDeltaParam)
+ {
+ //Step is minimal. It is not necessary to divide it.
+ continue;
}
U1prec = 0.5*(U1f+U1l);
- Standard_Real anArg = theCoeffs.mB * cos(U1prec - theCoeffs.mFI1) + theCoeffs.mC;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
-
- U2prec = theCoeffs.mFI2 + theArccosFactor*acos(anArg);
- InscribePoint(theU2f, theU2l, U2prec, theTol2D, thePeriodOfSurf2);
-
- gp_Pnt aP1, aP2;
- gp_Vec aVec1, aVec2;
-
- if(isTheReverse)
+ if(!ComputationMethods::
+ CylCylComputeParameters(U1prec, theWLIndex, theCoeffs, U2prec, V1prec, V2prec))
{
- V1prec = theCoeffs.mK21 * sin(U2prec) + theCoeffs.mK11 * sin(U1prec) + theCoeffs.mL21 * cos(U2prec) + theCoeffs.mL11 * cos(U1prec) + theCoeffs.mM1;
- V2prec = theCoeffs.mK22 * sin(U2prec) + theCoeffs.mK12 * sin(U1prec) + theCoeffs.mL22 * cos(U2prec) + theCoeffs.mL12 * cos(U1prec) + theCoeffs.mM2;
-
- gp_Pnt aP3, aP4;
- theQuad1.D1(U2prec, V2prec, aP3, aVec1, aVec2);
- theQuad2.D1(U1prec, V1prec, aP4, aVec1, aVec2);
-
- theQuad1.D1(U1prec, V1prec, aP1, aVec1, aVec2);
- theQuad2.D1(U2prec, V2prec, aP2, aVec1, aVec2);
+ continue;
}
- else
- {
- V1prec = theCoeffs.mK21 * sin(U2prec) + theCoeffs.mK11 * sin(U1prec) + theCoeffs.mL21 * cos(U2prec) + theCoeffs.mL11 * cos(U1prec) + theCoeffs.mM1;
- V2prec = theCoeffs.mK22 * sin(U2prec) + theCoeffs.mK12 * sin(U1prec) + theCoeffs.mL22 * cos(U2prec) + theCoeffs.mL12 * cos(U1prec) + theCoeffs.mM2;
- theQuad1.D1(U1prec, V1prec, aP1, aVec1, aVec2);
- theQuad2.D1(U2prec, V2prec, aP2, aVec1, aVec2);
+ MinMax(U2f, U2l);
+ if(!InscribePoint(U2f, U2l, U2prec, theTol2D, thePeriodOfSurf2, Standard_False))
+ {
+ continue;
}
- gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
+ const gp_Pnt aP1(theQuad1.Value(U1prec, V1prec)), aP2(theQuad2.Value(U2prec, V2prec));
+ const gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
+
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ std::cout << "|P1Pi| = " << aP1.SquareDistance(aPInt) << "; |P2Pi| = " << aP2.SquareDistance(aPInt) << std::endl;
+#endif
IntSurf_PntOn2S anIP;
if(isTheReverse)
anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
}
- theLile->InsertBefore(lp, anIP);
+ theLine->InsertBefore(lp, anIP);
- aNbPoints = theLile->NbPoints();
- if(aNbPoints >= theMinNbPoints)
- {
- return;
- }
+ aNbPoints++;
+ aLastPointIndex++;
}
- }
-}
-
-//=======================================================================
-//function : CriticalPointsComputing
-//purpose :
-//=======================================================================
-static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
- const Standard_Real theUSurf1f,
- const Standard_Real theUSurf1l,
- const Standard_Real theUSurf2f,
- const Standard_Real theUSurf2l,
- const Standard_Real thePeriod,
- const Standard_Real theTol2D,
- const Standard_Integer theNbCritPointsMax,
- Standard_Real theU1crit[])
-{
- theU1crit[0] = 0.0;
- theU1crit[1] = thePeriod;
- theU1crit[2] = theUSurf1f;
- theU1crit[3] = theUSurf1l;
-
- const Standard_Real aCOS = cos(theCoeffs.mFI2);
- const Standard_Real aBSB = Abs(theCoeffs.mB);
- if((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
- {
- Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
- if(anArg > 1.0)
- anArg = 1.0;
- if(anArg < -1.0)
- anArg = -1.0;
- theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
- theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
- }
-
- Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
- Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
- MinMax(aSf, aSl);
-
- theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
- theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
- theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
- theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
-
- //preparative treatment of array
- InscribeAndSortArray(theU1crit, theNbCritPointsMax, 0.0, thePeriod, theTol2D, thePeriod);
- for(Standard_Integer i = 1; i < theNbCritPointsMax; i++)
- {
- Standard_Real &a = theU1crit[i],
- &b = theU1crit[i-1];
- if(Abs(a - b) < theTol2D)
+ if(aNbPoints >= theMinNbPoints)
{
- a = (a + b)/2.0;
- b = Precision::Infinite();
+ return;
}
}
}
//=======================================================================
-//function : IntCyCyTrim
-//purpose :
+//function : BoundariesComputing
+//purpose : Computes true domain of future intersection curve (allows
+// avoiding excess iterations)
//=======================================================================
-Standard_Boolean IntCyCyTrim( 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,
- IntPatch_SequenceOfLine& theSlin,
- IntPatch_SequenceOfPoint& theSPnt)
+Standard_Boolean WorkWithBoundaries::BoundariesComputing(Standard_Real theU1f[],
+ Standard_Real theU1l[]) const
{
- 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_Real aNulValue = 0.01*Precision::PConfusion();
-
- const gp_Cylinder& aCyl1 = theQuad1.Cylinder(),
- aCyl2 = theQuad2.Cylinder();
-
- IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D);
-
- if (!anInter.IsDone())
- {
- return Standard_False;
- }
-
- IntAna_ResultType aTypInt = anInter.TypeInter();
-
- if(aTypInt != IntAna_NoGeometricSolution)
- { //It is not necessary (because result is an analytic curve) or
- //it is impossible to make Walking-line.
-
- return Standard_False;
- }
-
- theSlin.Clear();
- theSPnt.Clear();
- const Standard_Integer aNbPoints = Min(Max(200, RealToInt(20.0*aCyl1.Radius())), 2000);
- const Standard_Real aPeriod = 2.0*M_PI;
- const Standard_Real aStepMin = theTol2D,
- aStepMax = (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints);
+ //All comments to this method is related to the comment
+ //to ComputationMethods class
- const stCoeffsValue anEquationCoeffs(aCyl1, aCyl2);
+ //So, we have the equation
+ // cos(U2-FI2)=B*cos(U1-FI1)+C
+ //Evidently,
+ // -1 <= B*cos(U1-FI1)+C <= 1
- //Boundaries
- const Standard_Integer aNbOfBoundaries = 2;
- Standard_Real aU1f[aNbOfBoundaries] = {-Precision::Infinite(), -Precision::Infinite()};
- Standard_Real aU1l[aNbOfBoundaries] = {Precision::Infinite(), Precision::Infinite()};
-
- if(anEquationCoeffs.mB > 0.0)
+ if(myCoeffs.mB > 0.0)
{
- if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) < -1.0)
- {//There is NOT intersection
- return Standard_True;
+ // -(1+C)/B <= cos(U1-FI1) <= (1-C)/B
+
+ if(myCoeffs.mB + Abs(myCoeffs.mC) < -1.0)
+ {
+ //(1-C)/B < -1 or -(1+C)/B > 1 ==> No solution
+
+ return Standard_False;
}
- else if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
- {//U=[0;2*PI]+aFI1
- aU1f[0] = anEquationCoeffs.mFI1;
- aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
+ else if(myCoeffs.mB + Abs(myCoeffs.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;
}
- else if((1 + anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
- (anEquationCoeffs.mB <= 1 - anEquationCoeffs.mC))
+ else if((1 + myCoeffs.mC <= myCoeffs.mB) &&
+ (myCoeffs.mB <= 1 - myCoeffs.mC))
{
- Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
+ //(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;
if(anArg > 1.0)
anArg = 1.0;
if(anArg < -1.0)
anArg = -1.0;
const Standard_Real aDAngle = acos(anArg);
- //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
- aU1f[0] = anEquationCoeffs.mFI1;
- aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
- aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
- aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
+ theU1f[0] = myCoeffs.mFI1;
+ theU1l[0] = aDAngle + myCoeffs.mFI1;
+ theU1f[1] = myPeriod - aDAngle + myCoeffs.mFI1;
+ theU1l[1] = myPeriod + myCoeffs.mFI1;
}
- else if((1 - anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
- (anEquationCoeffs.mB <= 1 + anEquationCoeffs.mC))
+ else if((1 - myCoeffs.mC <= myCoeffs.mB) &&
+ (myCoeffs.mB <= 1 + myCoeffs.mC))
{
- Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
+ //(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;
if(anArg > 1.0)
anArg = 1.0;
if(anArg < -1.0)
anArg = -1.0;
const Standard_Real aDAngle = acos(anArg);
- //U=[aDAngle;2*PI-aDAngle]+aFI1
-
- aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
- aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
+ theU1f[0] = aDAngle + myCoeffs.mFI1;
+ theU1l[0] = myPeriod - aDAngle + myCoeffs.mFI1;
}
- else if(anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
+ else if(myCoeffs.mB - Abs(myCoeffs.mC) >= 1.0)
{
- Standard_Real anArg1 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB,
- anArg2 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
+ //(1-C)/B <= 1 and -(1+C)/B >= -1 ==>
+ //(U=[aDAngle1;aDAngle2]+aFI1) ||
+ //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
+ //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;
if(anArg1 > 1.0)
anArg1 = 1.0;
if(anArg1 < -1.0)
//(U=[aDAngle1;aDAngle2]+aFI1) ||
//(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
- aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
- aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
- aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
- aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
+ theU1f[0] = aDAngle1 + myCoeffs.mFI1;
+ theU1l[0] = aDAngle2 + myCoeffs.mFI1;
+ theU1f[1] = myPeriod - aDAngle2 + myCoeffs.mFI1;
+ theU1l[1] = myPeriod - aDAngle1 + myCoeffs.mFI1;
}
else
{
- Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
+ return Standard_False;
}
}
- else if(anEquationCoeffs.mB < 0.0)
+ else if(myCoeffs.mB < 0.0)
{
- if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) > 1.0)
- {//There is NOT intersection
- return Standard_True;
+ // (1-C)/B <= cos(U1-FI1) <= -(1+C)/B
+
+ if(myCoeffs.mB + Abs(myCoeffs.mC) > 1.0)
+ {
+ // -(1+C)/B < -1 or (1-C)/B > 1 ==> No solutions
+ return Standard_False;
}
- else if(-anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
- {//U=[0;2*PI]+aFI1
- aU1f[0] = anEquationCoeffs.mFI1;
- aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
+ else if(-myCoeffs.mB + Abs(myCoeffs.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;
}
- else if((-anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
- ( anEquationCoeffs.mB <= anEquationCoeffs.mC - 1))
+ else if((-myCoeffs.mC - 1 <= myCoeffs.mB) &&
+ ( myCoeffs.mB <= myCoeffs.mC - 1))
{
- Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
+ // -(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;
if(anArg > 1.0)
anArg = 1.0;
if(anArg < -1.0)
anArg = -1.0;
const Standard_Real aDAngle = acos(anArg);
- //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
-
- aU1f[0] = anEquationCoeffs.mFI1;
- aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
- aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
- aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
+ theU1f[0] = myCoeffs.mFI1;
+ theU1l[0] = aDAngle + myCoeffs.mFI1;
+ theU1f[1] = myPeriod - aDAngle + myCoeffs.mFI1;
+ theU1l[1] = myPeriod + myCoeffs.mFI1;
}
- else if((anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
- (anEquationCoeffs.mB <= -anEquationCoeffs.mB - 1))
+ else if((myCoeffs.mC - 1 <= myCoeffs.mB) &&
+ (myCoeffs.mB <= -myCoeffs.mB - 1))
{
- Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
+ // -(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;
if(anArg > 1.0)
anArg = 1.0;
if(anArg < -1.0)
anArg = -1.0;
const Standard_Real aDAngle = acos(anArg);
- //U=[aDAngle;2*PI-aDAngle]+aFI1
-
- aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
- aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
+ theU1f[0] = aDAngle + myCoeffs.mFI1;
+ theU1l[0] = myPeriod - aDAngle + myCoeffs.mFI1;
}
- else if(-anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
+ else if(-myCoeffs.mB - Abs(myCoeffs.mC) >= 1.0)
{
- Standard_Real anArg1 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB,
- anArg2 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
+ // -(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;
if(anArg1 > 1.0)
anArg1 = 1.0;
if(anArg1 < -1.0)
if(anArg2 < -1.0)
anArg2 = -1.0;
- const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
- //(U=[aDAngle1;aDAngle2]+aFI1) ||
- //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
+ 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;
+ }
+ else
+ {
+ return Standard_False;
+ }
+ }
+ else
+ {
+ return Standard_False;
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : CriticalPointsComputing
+//purpose : theNbCritPointsMax contains true number of critical points.
+// It must be initialized correctly before function calling
+//=======================================================================
+static void CriticalPointsComputing(const ComputationMethods::stCoeffsValue& theCoeffs,
+ const Standard_Real theUSurf1f,
+ const Standard_Real theUSurf1l,
+ const Standard_Real theUSurf2f,
+ const Standard_Real theUSurf2l,
+ const Standard_Real thePeriod,
+ const Standard_Real theTol2D,
+ Standard_Integer& theNbCritPointsMax,
+ Standard_Real theU1crit[])
+{
+ //[0...1] - in these points parameter U1 goes through
+ // the seam-edge of the first cylinder.
+ //[2...3] - First and last U1 parameter.
+ //[4...5] - in these points parameter U2 goes through
+ // the seam-edge of the second cylinder.
+ //[6...9] - in these points an intersection line goes through
+ // U-boundaries of the second surface.
+ //[10...11] - Boundary of monotonicity interval of U2(U1) function
+ // (see CylCylMonotonicity() function)
+
+ theU1crit[0] = 0.0;
+ theU1crit[1] = thePeriod;
+ theU1crit[2] = theUSurf1f;
+ theU1crit[3] = theUSurf1l;
+
+ const Standard_Real aCOS = cos(theCoeffs.mFI2);
+ const Standard_Real aBSB = Abs(theCoeffs.mB);
+ if((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
+ {
+ Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
+ if(anArg > 1.0)
+ anArg = 1.0;
+ if(anArg < -1.0)
+ anArg = -1.0;
+
+ theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
+ theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
+ }
+
+ Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
+ Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
+ MinMax(aSf, aSl);
+
+ //In accorance with pure mathematic, theU1crit[6] and [8]
+ //must be -Precision::Infinite() instead of used +Precision::Infinite()
+ theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+ -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+ Precision::Infinite();
+ theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+ -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+ Precision::Infinite();
+ theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+ acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+ Precision::Infinite();
+ theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+ acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+ Precision::Infinite();
+
+ theU1crit[10] = theCoeffs.mFI1;
+ theU1crit[11] = M_PI+theCoeffs.mFI1;
+
+ //preparative treatment of array. This array must have faled to contain negative
+ //infinity number
+
+ for(Standard_Integer i = 0; i < theNbCritPointsMax; i++)
+ {
+ if(Precision::IsInfinite(theU1crit[i]))
+ {
+ continue;
+ }
+
+ theU1crit[i] = fmod(theU1crit[i], thePeriod);
+ if(theU1crit[i] < 0.0)
+ theU1crit[i] += thePeriod;
+ }
+
+ //Here all not infinite elements of theU1crit are in [0, thePeriod) range
+
+ do
+ {
+ std::sort(theU1crit, theU1crit + theNbCritPointsMax);
+ }
+ while(ExcludeNearElements(theU1crit, theNbCritPointsMax,
+ theUSurf1f, theUSurf1l, theTol2D));
+
+ //Here all not infinite elements in theU1crit are different and sorted.
+
+ while(theNbCritPointsMax > 0)
+ {
+ Standard_Real &anB = theU1crit[theNbCritPointsMax-1];
+ if(Precision::IsInfinite(anB))
+ {
+ theNbCritPointsMax--;
+ continue;
+ }
+
+ //1st not infinte element is found
+
+ if(theNbCritPointsMax == 1)
+ break;
+
+ //Here theNbCritPointsMax > 1
+
+ Standard_Real &anA = theU1crit[0];
+
+ //Compare 1st and last significant elements of theU1crit
+ //They may still differs by period.
+
+ if (Abs(anB - anA - thePeriod) < theTol2D)
+ {//E.g. anA == 2.0e-17, anB == (thePeriod-1.0e-18)
+ anA = (anA + anB - thePeriod)/2.0;
+ anB = Precision::Infinite();
+ theNbCritPointsMax--;
+ }
+
+ //Out of "while(theNbCritPointsMax > 0)" cycle.
+ break;
+ }
+
+ //Attention! Here theU1crit may be unsorted.
+}
+
+//=======================================================================
+//function : BoundaryEstimation
+//purpose : Rough estimation of the parameter range.
+//=======================================================================
+void WorkWithBoundaries::BoundaryEstimation(const gp_Cylinder& theCy1,
+ const gp_Cylinder& theCy2,
+ Bnd_Range& theOutBoxS1,
+ Bnd_Range& theOutBoxS2) const
+{
+ const gp_Dir &aD1 = theCy1.Axis().Direction(),
+ &aD2 = theCy2.Axis().Direction();
+ const Standard_Real aR1 = theCy1.Radius(),
+ aR2 = theCy2.Radius();
+
+ //Let consider a parallelogram. Its edges are parallel to aD1 and aD2.
+ //Its altitudes are equal to 2*aR1 and 2*aR2 (diameters of the cylinders).
+ //In fact, this parallelogram is a projection of the cylinders to the plane
+ //created by the intersected axes aD1 and aD2 (if the axes are skewed then
+ //one axis can be translated by parallel shifting till intersection).
+
+ const Standard_Real aCosA = aD1.Dot(aD2);
+ const Standard_Real aSqSinA = aD1.XYZ().CrossSquareMagnitude(aD2.XYZ());
+
+ //If sine is small then it can be compared with angle.
+ if (aSqSinA < Precision::Angular()*Precision::Angular())
+ return;
+
+ //Half of delta V. Delta V is a distance between
+ //projections of two opposite parallelogram vertices
+ //(joined by the maximal diagonal) to the cylinder axis.
+ const Standard_Real aSinA = sqrt(aSqSinA);
+ const Standard_Real anAbsCosA = Abs(aCosA);
+ const Standard_Real aHDV1 = (aR1 * anAbsCosA + aR2) / aSinA,
+ aHDV2 = (aR2 * anAbsCosA + aR1) / aSinA;
+
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ //The code in this block is created for test only.It is stupidly to create
+ //OCCT-test for the method, which will be changed possibly never.
+ std::cout << "Reference values: aHDV1 = " << aHDV1 << "; aHDV2 = " << aHDV2 << std::endl;
+#endif
+
+ //V-parameters of intersection point of the axes (in case of skewed axes,
+ //see comment above).
+ Standard_Real aV01 = 0.0, aV02 = 0.0;
+ ExtremaLineLine(theCy1.Axis(), theCy2.Axis(), aCosA, aSqSinA, aV01, aV02);
+
+ theOutBoxS1.Add(aV01 - aHDV1);
+ theOutBoxS1.Add(aV01 + aHDV1);
+
+ theOutBoxS2.Add(aV02 - aHDV2);
+ theOutBoxS2.Add(aV02 + aHDV2);
+
+ theOutBoxS1.Enlarge(Precision::Confusion());
+ theOutBoxS2.Enlarge(Precision::Confusion());
+
+ Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
+ myUVSurf1.Get(aU1, aV1, aU2, aV2);
+ theOutBoxS1.Common(Bnd_Range(aV1, aV2));
+
+ myUVSurf2.Get(aU1, aV1, aU2, aV2);
+ theOutBoxS2.Common(Bnd_Range(aV1, aV2));
+}
+
+//=======================================================================
+//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,
+ const Standard_Boolean isTheReverse,
+ Standard_Boolean& isTheEmpty,
+ Standard_Boolean& isTheSameSurface,
+ Standard_Boolean& isTheMultiplePoint,
+ IntPatch_SequenceOfLine& theSlin,
+ IntPatch_SequenceOfPoint& theSPnt)
+{
+ isTheEmpty = Standard_True;
+ isTheSameSurface = Standard_False;
+ 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, //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);
+
+ Bnd_Range aRangeS1, aRangeS2;
+ aBoundWork.BoundaryEstimation(aCyl1, aCyl2, aRangeS1, aRangeS2);
+ if (aRangeS1.IsVoid() || aRangeS2.IsVoid())
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
- aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
- aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
- aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
- aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
- }
- else
- {
- Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
- }
- }
- else
{
- Standard_Failure::Raise("Error. Exception. Unhandled case (B-parameter computation)!");
+ //Quotation of the message from issue #26894 (author MSV):
+ //"We should return fail status from intersector if the result should be an
+ //infinite curve of non-analytical type... I propose to define the limit for the
+ //extent as the radius divided by 1e+2 and multiplied by 1e+7.
+ //Thus, taking into account the number of valuable digits (15), we provide reliable
+ //computations with an error not exceeding R/100."
+ const Standard_Real aF = 1.0e+5;
+ const Standard_Real aMaxV1Range = aF*aCyl1.Radius(), aMaxV2Range = aF*aCyl2.Radius();
+ if ((aRangeS1.Delta() > aMaxV1Range) || (aRangeS2.Delta() > aMaxV2Range))
+ return IntPatch_ImpImpIntersection::IntStatus_InfiniteSectionCurve;
}
+ //Boundaries (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;
+
+ //The main idea of the algorithm is to change U1-parameter
+ //(U-parameter of aCyl1) 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++)
{
if(Precision::IsInfinite(aU1f[i]) && Precision::IsInfinite(aU1l[i]))
}
}
- //Critical points
- //[0...1] - in these points parameter U1 goes through
- // the seam-edge of the first cylinder.
- //[2...3] - First and last U1 parameter.
- //[4...5] - in these points parameter U2 goes through
- // the seam-edge of the second cylinder.
- //[6...9] - in these points an intersetion line goes through
- // U-boundaries of the second surface.
- const Standard_Integer aNbCritPointsMax = 10;
+ //Critical points are the value of U1-parameter in the points
+ //where WL must be decomposed.
+
+ //When U1 goes through critical points its value is set up to this
+ //parameter forcefully and the intersection point is added in the line.
+ //After that, the WL is broken (next U1 value will be correspond to the new WL).
+
+ //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()};
- CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
- aPeriod, theTol2D, aNbCritPointsMax, anU1crit);
+ //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.
+ //They are computed by numerical methods on - line (during algorithm working).
+ //The moment is caught, when intersection line goes through V-bounds of any cylinder.
+ Standard_Integer aNbCritPoints = aNbCritPointsMax;
+ CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
+ aPeriod, theTol2D, aNbCritPoints, anU1crit);
//Getting Walking-line
+ enum WLFStatus
+ {
+ // No points have been added in WL
+ WLFStatus_Absent = 0,
+ // WL contains at least one point
+ 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++)
{
+ //Process every continuous region
+
if(Precision::IsInfinite(aU1f[aCurInterval]) && Precision::IsInfinite(aU1l[aCurInterval]))
continue;
- Standard_Boolean isAddedIntoWL1 = Standard_False, isAddedIntoWL2 = Standard_False;
+ Standard_Boolean isAddedIntoWL[aNbWLines];
+ 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);
//Inscribe and sort critical points
- InscribeAndSortArray(anU1crit, aNbCritPointsMax, anUf, anUl, theTol2D, aPeriod);
+ for(Standard_Integer i = 0; i < aNbCritPoints; i++)
+ {
+ InscribePoint(anUf, anUl, anU1crit[i], theTol2D, aPeriod, Standard_False);
+ }
+
+ std::sort(anU1crit, anU1crit + aNbCritPoints);
while(anUf < anUl)
{
- Handle(IntSurf_LineOn2S) aL2S1 = new IntSurf_LineOn2S();
- Handle(IntSurf_LineOn2S) aL2S2 = new IntSurf_LineOn2S();
-
- Handle(IntPatch_WLine) aWLine1 = new IntPatch_WLine(aL2S1, Standard_False);
- Handle(IntPatch_WLine) aWLine2 = new IntPatch_WLine(aL2S2, Standard_False);
+ //Change value of U-parameter on the 1st surface from anUf to anUl
+ //(anUf will be modified in the cycle body).
+ //Step is computed adaptively (see comments below).
+
+ Standard_Real aU2[aNbWLines], aV1[aNbWLines], aV2[aNbWLines];
+ WLFStatus aWLFindStatus[aNbWLines];
+ Standard_Real aV1Prev[aNbWLines], aV2Prev[aNbWLines];
+ Standard_Real anUexpect[aNbWLines];
+ Standard_Boolean isAddingWLEnabled[aNbWLines];
+
+ Handle(IntSurf_LineOn2S) aL2S[aNbWLines];
+ Handle(IntPatch_WLine) aWLine[aNbWLines];
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ aL2S[i] = new IntSurf_LineOn2S();
+ aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False);
+ aWLFindStatus[i] = WLFStatus_Absent;
+ isAddingWLEnabled[i] = Standard_True;
+ aU2[i] = aV1[i] = aV2[i] = 0.0;
+ aV1Prev[i] = aV2Prev[i] = 0.0;
+ anUexpect[i] = anUf;
+ }
+
+ 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
- Standard_Integer aWL1FindStatus = 0, aWL2FindStatus = 0;
+ aCriticalDelta[aCritPID] = anUf - anU1crit[aCritPID];
+ }
Standard_Real anU1 = anUf;
-
- Standard_Real aCriticalDelta[aNbCritPointsMax];
- for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
- aCriticalDelta[i] = anU1 - anU1crit[i];
-
- Standard_Real aV11Prev = 0.0,
- aV12Prev = 0.0,
- aV21Prev = 0.0,
- aV22Prev = 0.0;
Standard_Boolean isFirst = Standard_True;
-
+
while(anU1 <= anUl)
{
- for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
+ //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++)
{
if((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0)
{
+ //WL has gone through i-th critical point
anU1 = anU1crit[i];
- aWL1FindStatus = 2;
- aWL2FindStatus = 2;
+
+ for(Standard_Integer j = 0; j < aNbWLines; j++)
+ {
+ aWLFindStatus[j] = WLFStatus_Broken;
+ anUexpect[j] = anU1;
+ }
+
break;
}
}
- Standard_Real anArg = anEquationCoeffs.mB * cos(anU1 - anEquationCoeffs.mFI1) + anEquationCoeffs.mC;
-
- if(aNulValue > 1.0 - anArg)
- anArg = 1.0;
- if(anArg + 1.0 < aNulValue)
- anArg = -1.0;
+ if(IsEqual(anU1, anUl))
+ {
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken;
+ anUexpect[i] = anU1;
- Standard_Real aU21 = anEquationCoeffs.mFI2 + acos(anArg);
- InscribePoint(aUSurf2f, aUSurf2l, aU21, theTol2D, aPeriod);
-
- Standard_Real aU22 = anEquationCoeffs.mFI2 - acos(anArg);
- InscribePoint(aUSurf2f, aUSurf2l, aU22, theTol2D, aPeriod);
-
- const Standard_Real aV11 = anEquationCoeffs.mK21 * sin(aU21) +
- anEquationCoeffs.mK11 * sin(anU1) +
- anEquationCoeffs.mL21 * cos(aU21) +
- anEquationCoeffs.mL11 * cos(anU1) + anEquationCoeffs.mM1;
- const Standard_Real aV12 = anEquationCoeffs.mK21 * sin(aU22) +
- anEquationCoeffs.mK11 * sin(anU1) +
- anEquationCoeffs.mL21 * cos(aU22) +
- anEquationCoeffs.mL11 * cos(anU1) + anEquationCoeffs.mM1;
- const Standard_Real aV21 = anEquationCoeffs.mK22 * sin(aU21) +
- anEquationCoeffs.mK12 * sin(anU1) +
- anEquationCoeffs.mL22 * cos(aU21) +
- anEquationCoeffs.mL12 * cos(anU1) + anEquationCoeffs.mM2;
- const Standard_Real aV22 = anEquationCoeffs.mK22 * sin(aU22) +
- anEquationCoeffs.mK12 * sin(anU1) +
- anEquationCoeffs.mL22 * cos(aU22) +
- anEquationCoeffs.mL12 * cos(anU1) + anEquationCoeffs.mM2;
-
- if(isFirst)
+ if(isDeltaPeriod)
+ {
+ //if isAddedIntoWL[i] == TRUE WLine contains only one point
+ //(which was end point of previous WLine). If we will
+ //add point found on the current step WLine will contain only
+ //two points. At that both these points will be equal to the
+ //points found earlier. Therefore, new WLine will repeat
+ //already existing WLine. Consequently, it is necessary
+ //to forbid building new line in this case.
+
+ isAddingWLEnabled[i] = (!isAddedIntoWL[i]);
+ }
+ else
+ {
+ isAddingWLEnabled[i] = ((theTol2D >= (anUexpect[i] - anU1)) ||
+ (aWLFindStatus[i] == WLFStatus_Absent));
+ }
+ }//for(Standard_Integer i = 0; i < aNbWLines; i++)
+ }
+ else
{
- aV11Prev = aV11;
- aV12Prev = aV12;
- aV21Prev = aV21;
- aV22Prev = aV22;
- isFirst = Standard_False;
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ isAddingWLEnabled[i] = ((theTol2D >= (anUexpect[i] - anU1)) ||
+ (aWLFindStatus[i] == WLFStatus_Absent));
+ }//for(Standard_Integer i = 0; i < aNbWLines; i++)
}
- if( ((aUSurf2f-aU21) <= theTol2D) &&
- ((aU21-aUSurf2l) <= theTol2D) &&
- ((aVSurf1f - aV11) <= theTol2D) &&
- ((aV11 - aVSurf1l) <= theTol2D) &&
- ((aVSurf2f - aV21) <= theTol2D) && ((aV21 - aVSurf2l) <= theTol2D))
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
{
- if(!aWL1FindStatus)
+ 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;
+ ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs,
+ aU2[i], &aTol);
+ InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
+
+ aTol = Max(aTol, theTol2D);
+
+ if(Abs(aU2[i]) <= aTol)
+ aU2[i] = 0.0;
+ else if(Abs(aU2[i] - aPeriod) <= aTol)
+ aU2[i] = aPeriod;
+ else if(Abs(aU2[i] - aUSurf2f) <= aTol)
+ aU2[i] = aUSurf2f;
+ else if(Abs(aU2[i] - aUSurf2l) <= aTol)
+ aU2[i] = aUSurf2l;
+ }
+ else
{
- Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
-
- AddBoundaryPoint(theQuad1, theQuad2, aWLine1, anEquationCoeffs, theUVSurf1, theUVSurf2,
- theTol2D, aPeriod, aNulValue, anU1, aU21,
- aV11, aV11Prev, aV21, aV21Prev, isTheReverse, 1.0, isFound1, isFound2);
-
- if(isFound1 || isFound2)
+ ComputationMethods::CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]);
+ InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
+ }
+
+ 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)))
{
- aWL1FindStatus = 1;
+ //In this case aU2[i] can have two values: current aU2[i] or
+ //aU2[i]+aPeriod (aU2[i]-aPeriod). It is necessary to choose
+ //correct value.
+
+ Standard_Boolean isIncreasing = Standard_True;
+ ComputationMethods::CylCylMonotonicity(anU1+aStepMin, i, anEquationCoeffs,
+ aPeriod, isIncreasing);
+
+ //If U2(U1) is increasing and U2 is considered to be equal aUSurf2l
+ //then after the next step (when U1 will be increased) U2 will be
+ //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)
+ {
+ aU2[i] = aUSurf2f;
+ }
+ else
+ {
+ aU2[i] = aUSurf2l;
+ }
}
}
-
- if((aWL1FindStatus != 2) || (aWLine1->NbPnts() >= 1))
- {
- if(AddPointIntoWL(theQuad1, theQuad2, isTheReverse, gp_Pnt2d(anU1, aV11),
- gp_Pnt2d(aU21, aV21), aUSurf1f, aUSurf1l, aPeriod, aWLine1->Curve(), theTol2D))
- {
- if(!aWL1FindStatus)
+ else
+ {//aNbPntsWL > 0
+ if(((aUSurf2l - aUSurf2f) >= aPeriod) &&
+ ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
+ (Abs(aU2[i]-aUSurf2l) < theTol2D)))
+ {//end of the line
+ Standard_Real aU2prev = 0.0, aV2prev = 0.0;
+ if(isTheReverse)
+ 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)
{
- aWL1FindStatus = 1;
+ if(aU2prev > aU2[i])
+ aU2[i] += aPeriod;
+ else
+ aU2[i] -= aPeriod;
}
}
}
- }
- else
- {
- if(aWL1FindStatus == 1)
- {
- Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
- AddBoundaryPoint(theQuad1, theQuad2, aWLine1, anEquationCoeffs, theUVSurf1, theUVSurf2,
- theTol2D, aPeriod, aNulValue, anU1, aU21, aV11, aV11Prev, aV21, aV21Prev, isTheReverse, 1.0, isFound1, isFound2);
+ ComputationMethods::CylCylComputeParameters(anU1, aU2[i], anEquationCoeffs,
+ aV1[i], aV2[i]);
- if(isFound1 || isFound2)
- aWL1FindStatus = 2; //start a new line
+ if(isFirst)
+ {
+ aV1Prev[i] = aV1[i];
+ aV2Prev[i] = aV2[i];
}
- }
-
- if( ((aUSurf2f-aU22) <= theTol2D) &&
- ((aU22-aUSurf2l) <= theTol2D) &&
- ((aVSurf1f - aV12) <= theTol2D) &&
- ((aV12 - aVSurf1l) <= theTol2D) &&
- ((aVSurf2f - aV22) <= theTol2D) &&
- ((aV22 - aVSurf2l) <= theTol2D))
+ }//for(Standard_Integer i = 0; i < aNbWLines; i++)
+
+ isFirst = Standard_False;
+
+ //Looking for points into WLine
+ Standard_Boolean isBroken = Standard_False;
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
{
- if(!aWL2FindStatus)
+ if(!isAddingWLEnabled[i])
{
- Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
+ Standard_Boolean isBoundIntersect = Standard_False;
+ if( (Abs(aV1[i] - aVSurf1f) <= theTol2D) ||
+ ((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))
+ {
+ isBoundIntersect = Standard_True;
+ }
+ else if( (Abs(aV2[i] - aVSurf2f) <= theTol2D) ||
+ ( (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))
+ {
+ isBoundIntersect = Standard_True;
+ }
- AddBoundaryPoint(theQuad1, theQuad2, aWLine2, anEquationCoeffs, theUVSurf1, theUVSurf2,
- theTol2D, aPeriod, aNulValue, anU1, aU22,
- aV12, aV12Prev, aV22, aV22Prev, isTheReverse, -1.0, isFound1, isFound2);
-
- if(isFound1 || isFound2)
+ if(aWLFindStatus[i] == WLFStatus_Broken)
+ isBroken = Standard_True;
+
+ if(!isBoundIntersect)
+ {
+ continue;
+ }
+ else
+ {
+ anUexpect[i] = anU1;
+ }
+ }
+
+ // 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);
+
+ //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()));
+
+
+ //isFound1 == TRUE if intersection line intersects V-bounds
+ // (First or Last - no matter) of the 1st cylynder
+ //isFound2 == TRUE if intersection line intersects V-bounds
+ // (First or Last - no matter) of the 2nd cylynder
+ Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
+ Standard_Boolean isForce = Standard_False;
+
+ if (aWLFindStatus[i] == WLFStatus_Absent)
+ {
+ if(((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1-aUSurf1l) < theTol2D))
{
- aWL2FindStatus = 1;
+ isForce = Standard_True;
}
}
- if((aWL2FindStatus != 2) || (aWLine2->NbPnts() >= 1))
+ aBoundWork.AddBoundaryPoint(aWLine[i], anU1, 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));
+
+ aV1Prev[i] = aV1[i];
+ aV2Prev[i] = aV2[i];
+
+ if((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken; //start a new line
+ }
+ else if(isInscribe)
{
- if(AddPointIntoWL(theQuad1, theQuad2, isTheReverse, gp_Pnt2d(anU1, aV12),
- gp_Pnt2d(aU22, aV22), aUSurf1f, aUSurf1l, aPeriod, aWLine2->Curve(), theTol2D))
+ if((aWLFindStatus[i] == WLFStatus_Absent) && (isFound1 || isFound2))
{
- if(!aWL2FindStatus)
+ aWLFindStatus[i] = WLFStatus_Exist;
+ }
+
+ if( (aWLFindStatus[i] != WLFStatus_Broken) ||
+ (aWLine[i]->NbPnts() >= 1) || IsEqual(anU1, anUl))
+ {
+ if(aWLine[i]->NbPnts() > 0)
+ {
+ Standard_Real aU2p = 0.0, aV2p = 0.0;
+ if(isTheReverse)
+ 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(aDelta > 0.0)
+ {
+ aU2[i] -= aPeriod;
+ }
+ else
+ {
+ aU2[i] += aPeriod;
+ }
+ }
+ }
+
+ if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse, 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))
{
- aWL2FindStatus = 1;
+ if(aWLFindStatus[i] == WLFStatus_Absent)
+ {
+ aWLFindStatus[i] = WLFStatus_Exist;
+ }
+ }
+ else if(!isFound1 && !isFound2)
+ {//We do not add any point while doing this iteration
+ if(aWLFindStatus[i] == WLFStatus_Exist)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken;
+ }
}
}
}
- }
- else
- {
- if(aWL2FindStatus == 1)
+ else
+ {//We do not add any point while doing this iteration
+ if(aWLFindStatus[i] == WLFStatus_Exist)
+ {
+ aWLFindStatus[i] = WLFStatus_Broken;
+ }
+ }
+
+ if(aWLFindStatus[i] == WLFStatus_Broken)
+ isBroken = Standard_True;
+ }//for(Standard_Integer i = 0; i < aNbWLines; i++)
+
+ 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++)
{
+ if(isAddingWLEnabled[i])
+ {
+ continue;
+ }
+
+ isAdded = Standard_False;
+
Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
- AddBoundaryPoint(theQuad1, theQuad2, aWLine2, anEquationCoeffs, theUVSurf1, theUVSurf2,
- theTol2D, aPeriod, aNulValue, anU1, aU22,
- aV12, aV12Prev, aV22, aV22Prev, isTheReverse, -1.0, isFound1, isFound2);
+ aBoundWork.AddBoundaryPoint(aWLine[i], anU1, aU2[i], aV1[i], aV1Prev[i],
+ aV2[i], aV2Prev[i], i,
+ Standard_False, isFound1, isFound2);
if(isFound1 || isFound2)
- aWL2FindStatus = 2; //start a new line
+ {
+ isAdded = Standard_True;
+ }
+
+ if(aWLine[i]->NbPnts() > 0)
+ {
+ Standard_Real aU2p = 0.0, aV2p = 0.0;
+ if(isTheReverse)
+ 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(aDelta > 0.0)
+ {
+ aU2[i] -= aPeriod;
+ }
+ else
+ {
+ aU2[i] += aPeriod;
+ }
+ }
+ }
+
+ if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse,
+ 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))
+ {
+ isAdded = Standard_True;
+ }
}
- }
- aV11Prev = aV11;
- aV12Prev = aV12;
- aV21Prev = aV21;
- aV22Prev = aV22;
+ if(!isAdded)
+ {
+ //Before breaking WL, we must complete it correctly
+ //(e.g. to prolong to the surface boundary).
+ //Therefore, we take the point last added in some WL
+ //(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++)
+ {
+ if(aWLFindStatus[i] == WLFStatus_Absent)
+ continue;
+
+ Standard_Real aU1c = 0.0, aV1c = 0.0;
+ if(isTheReverse)
+ aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c);
+ else
+ aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c);
+
+ anUmaxAdded = Max(anUmaxAdded, aU1c);
+ isChanged = Standard_True;
+ }
+
+ 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++)
+ {
+ 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);
+ }
+ }
- if((aWL1FindStatus == 2) || (aWL2FindStatus == 2))
- {//current lines are filled. Go to the next lines
- anUf = anU1;
break;
}
- Standard_Real aFact1 = !IsEqual(sin(aU21 - anEquationCoeffs.mFI2), 0.0) ?
- anEquationCoeffs.mK1 * sin(anU1 - anEquationCoeffs.mFIV1) +
- anEquationCoeffs.mL1 * anEquationCoeffs.mB * sin(aU21 - anEquationCoeffs.mPSIV1) *
- sin(anU1 - anEquationCoeffs.mFI1)/sin(aU21-anEquationCoeffs.mFI2) : 0.0,
- aFact2 = !IsEqual(sin(aU22-anEquationCoeffs.mFI2), 0.0) ?
- anEquationCoeffs.mK1 * sin(anU1 - anEquationCoeffs.mFIV1) +
- anEquationCoeffs.mL1 * anEquationCoeffs.mB * sin(aU22 - anEquationCoeffs.mPSIV1) *
- sin(anU1 - anEquationCoeffs.mFI1)/sin(aU22-anEquationCoeffs.mFI2) : 0.0;
+ //Step computing
- Standard_Real aDeltaV1 = (aVSurf1l - aVSurf1f)/IntToReal(aNbPoints);
+ {
+ //Step of aU1-parameter is computed adaptively. The algorithm
+ //aims to provide given aDeltaV1 and aDeltaV2 values (if it is
+ //possible because the intersection line can go along V-isoline)
+ //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);
+
+ math_Matrix aMatr(1, 3, 1, 5);
- if((aV11 < aVSurf1f) && (aFact1 < 0.0))
- {//Make close to aVSurf1f by increasing anU1 (for the 1st line)
- aDeltaV1 = Min(aDeltaV1, Abs(aV11-aVSurf1f));
- }
+ Standard_Real aMinUexp = RealLast();
+
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if(theTol2D < (anUexpect[i] - anU1))
+ {
+ continue;
+ }
- if((aV12 < aVSurf1f) && (aFact2 < 0.0))
- {//Make close to aVSurf1f by increasing anU1 (for the 2nd line)
- aDeltaV1 = Min(aDeltaV1, Abs(aV12-aVSurf1f));
- }
+ if(aWLFindStatus[i] == WLFStatus_Absent)
+ {
+ anUexpect[i] += aStepMax;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
+ continue;
+ }
- if((aV11 > aVSurf1l) && (aFact1 > 0.0))
- {//Make close to aVSurf1l by increasing anU1 (for the 1st line)
- aDeltaV1 = Min(aDeltaV1, Abs(aV11-aVSurf1l));
- }
-
- if((aV12 > aVSurf1l) && (aFact2 > 0.0))
- {//Make close to aVSurf1l by increasing anU1 (for the 1st line)
- aDeltaV1 = Min(aDeltaV1, Abs(aV12-aVSurf1l));
- }
+ Standard_Real aStepTmp = aStepMax;
- Standard_Real aDeltaU1L1 = !IsEqual(aFact1,0.0)? Abs(aDeltaV1/aFact1) : aStepMax,
- aDeltaU1L2 = !IsEqual(aFact2,0.0)? Abs(aDeltaV1/aFact2) : aStepMax;
-
- const Standard_Real aDeltaU1V1 = Min(aDeltaU1L1, aDeltaU1L2);
-
- ///////////////////////////
- aFact1 = !IsEqual(sin(aU21-anEquationCoeffs.mFI2), 0.0) ?
- anEquationCoeffs.mK2 * sin(anU1 - anEquationCoeffs.mFIV2) +
- anEquationCoeffs.mL2 * anEquationCoeffs.mB * sin(aU21 - anEquationCoeffs.mPSIV2) *
- sin(anU1 - anEquationCoeffs.mFI1)/sin(aU21 - anEquationCoeffs.mFI2) : 0.0;
- aFact2 = !IsEqual(sin(aU22-anEquationCoeffs.mFI2), 0.0) ?
- anEquationCoeffs.mK2 * sin(anU1 - anEquationCoeffs.mFIV2) +
- anEquationCoeffs.mL2 * anEquationCoeffs.mB * sin(aU22 - anEquationCoeffs.mPSIV2) *
- sin(anU1 - anEquationCoeffs.mFI1)/sin(aU22 - anEquationCoeffs.mFI2) : 0.0;
-
- Standard_Real aDeltaV2 = (aVSurf2l - aVSurf2f)/IntToReal(aNbPoints);
+ const Standard_Real aSinU1 = sin(anU1),
+ aCosU1 = cos(anU1),
+ aSinU2 = sin(aU2[i]),
+ aCosU2 = cos(aU2[i]);
- if((aV21 < aVSurf2f) && (aFact1 < 0.0))
- {//Make close to aVSurf2f by increasing anU1 (for the 1st line)
- aDeltaV2 = Min(aDeltaV2, Abs(aV21-aVSurf2f));
- }
+ aMatr.SetCol(1, anEquationCoeffs.mVecC1);
+ aMatr.SetCol(2, anEquationCoeffs.mVecC2);
+ aMatr.SetCol(3, anEquationCoeffs.mVecA1*aSinU1 - anEquationCoeffs.mVecB1*aCosU1);
+ aMatr.SetCol(4, anEquationCoeffs.mVecA2*aSinU2 - anEquationCoeffs.mVecB2*aCosU2);
+ aMatr.SetCol(5, anEquationCoeffs.mVecA1*aCosU1 + anEquationCoeffs.mVecB1*aSinU1 +
+ anEquationCoeffs.mVecA2*aCosU2 + anEquationCoeffs.mVecB2*aSinU2 +
+ anEquationCoeffs.mVecD);
- if((aV22 < aVSurf2f) && (aFact2 < 0.0))
- {//Make close to aVSurf1f by increasing anU1 (for the 2nd line)
- aDeltaV2 = Min(aDeltaV2, Abs(aV22-aVSurf2f));
- }
+ //The main idea is in solving of linearized system (2)
+ //(see description to ComputationMethods class) in order to find new U1-value
+ //to provide new value V1 or V2, which differs from current one by aDeltaV1 or
+ //aDeltaV2 respectively.
- if((aV21 > aVSurf2l) && (aFact1 > 0.0))
- {//Make close to aVSurf1l by increasing anU1 (for the 1st line)
- aDeltaV2 = Min(aDeltaV2, Abs(aV21-aVSurf2l));
- }
+ //While linearizing, following Taylor formulas are used:
+ // cos(x0+dx) = cos(x0) - sin(x0)*dx
+ // sin(x0+dx) = sin(x0) + cos(x0)*dx
- if((aV22 > aVSurf2l) && (aFact2 > 0.0))
- {//Make close to aVSurf1l by increasing anU1 (for the 1st line)
- aDeltaV2 = Min(aDeltaV2, Abs(aV22-aVSurf1l));
- }
+ //Consequently cos(U1), cos(U2), sin(U1) and sin(U2) in the system (2)
+ //must be substituted by corresponding values.
- aDeltaU1L1 = !IsEqual(aFact1,0.0)? Abs(aDeltaV2/aFact1) : aStepMax;
- aDeltaU1L2 = !IsEqual(aFact2,0.0)? Abs(aDeltaV2/aFact2) : aStepMax;
+ //ATTENTION!!!
+ //The solution is approximate. More over, all requirements to the
+ //linearization must be satisfied in order to obtain quality result.
- const Standard_Real aDeltaU1V2 = Min(aDeltaU1L1, aDeltaU1L2);
+ if(!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp))
+ {
+ //To avoid cycling-up
+ anUexpect[i] += aStepMax;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
- Standard_Real aDeltaU1 = Min(aDeltaU1V1, aDeltaU1V2);
+ continue;
+ }
- if(aDeltaU1 < aStepMin)
- aDeltaU1 = aStepMin;
+ if(aStepTmp < aStepMin)
+ aStepTmp = aStepMin;
- if(aDeltaU1 > aStepMax)
- aDeltaU1 = aStepMax;
+ if(aStepTmp > aStepMax)
+ aStepTmp = aStepMax;
- anU1 += aDeltaU1;
+ anUexpect[i] = anU1 + aStepTmp;
+ aMinUexp = Min(aMinUexp, anUexpect[i]);
+ }
+
+ anU1 = aMinUexp;
+ }
- const Standard_Real aDiff = anU1 - anUl;
- if((0.0 < aDiff) && (aDiff < aDeltaU1-Precision::PConfusion()))
+ if(Precision::PConfusion() >= (anUl - anU1))
anU1 = anUl;
anUf = anU1;
- if(aWLine1->NbPnts() != 1)
- isAddedIntoWL1 = Standard_False;
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
+ {
+ if(aWLine[i]->NbPnts() != 1)
+ isAddedIntoWL[i] = Standard_False;
- if(aWLine2->NbPnts() != 1)
- isAddedIntoWL2 = Standard_False;
+ if(anU1 == anUl)
+ {//strictly equal. Tolerance is considered above.
+ anUexpect[i] = anUl;
+ }
+ }
}
- if((aWLine1->NbPnts() == 1) && (!isAddedIntoWL1))
- {
- isTheEmpty = Standard_False;
- Standard_Real u1, v1, u2, v2;
- aWLine1->Point(1).Parameters(u1, v1, u2, v2);
- IntPatch_Point aP;
- aP.SetParameter(u1);
- aP.SetParameters(u1, v1, u2, v2);
- aP.SetTolerance(theTol3D);
- aP.SetValue(aWLine1->Point(1).Value());
-
- theSPnt.Append(aP);
- }
- else if(aWLine1->NbPnts() > 1)
+ for(Standard_Integer i = 0; i < aNbWLines; i++)
{
- isTheEmpty = Standard_False;
- isAddedIntoWL1 = Standard_True;
+ if((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i]))
+ {
+ isTheEmpty = Standard_False;
+ Standard_Real u1, v1, u2, v2;
+ aWLine[i]->Point(1).Parameters(u1, v1, u2, v2);
+ IntPatch_Point aP;
+ aP.SetParameter(u1);
+ aP.SetParameters(u1, v1, u2, v2);
+ aP.SetTolerance(theTol3D);
+ aP.SetValue(aWLine[i]->Point(1).Value());
+
+ theSPnt.Append(aP);
+ }
+ else if(aWLine[i]->NbPnts() > 1)
+ {
+ Standard_Boolean isGood = Standard_True;
+
+ 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()))
+ isGood = Standard_False;
+ }
- SeekAdditionalPoints(theQuad1, theQuad2, aWLine1->Curve(), anEquationCoeffs, aNbPoints, aUSurf2f, aUSurf2l, theTol2D, aPeriod, 1.0, isTheReverse);
+ 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);
+
+ aWLine[i]->ComputeVertexParameters(theTol3D);
+ theSlin.Append(aWLine[i]);
+ }
+ }
+ else
+ {
+ isAddedIntoWL[i] = Standard_False;
+ }
- aWLine1->ComputeVertexParameters(theTol3D);
- theSlin.Append(aWLine1);
+#ifdef INTPATCH_IMPIMPINTERSECTION_DEBUG
+ //aWLine[i]->Dump();
+#endif
}
- else
+ }
+ }
+
+
+ //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 aNbLin = 1; aNbLin <= theSlin.Length(); 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()))
{
- isAddedIntoWL1 = Standard_False;
+ theSPnt.Remove(aNbPnt);
+ aNbPnt--;
+ break;
}
+ }
+ }
+
+ 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++)
+ {
+ const IntPatch_Point& aPnt2S = theSPnt.Value(aNbPnt);
+
+ Standard_Real u1, v1, u2, v2;
+ aPnt2S.Parameters(u1, v1, u2, v2);
+
+ 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)
+ {
+ anUf = Max(u2 - aStepMax, aUSurf1f);
+ anUl = u2;
+ aCurU2 = u1;
+ }
+ else
+ {
+ anUf = Max(u1 - aStepMax, aUSurf1f);
+ anUl = u1;
+ 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;
- if((aWLine2->NbPnts() == 1) && (!isAddedIntoWL2))
+ const Standard_Real aDU2 = Abs(anU2t - aCurU2);
+ if(aDU2 < aDelta)
{
- isTheEmpty = Standard_False;
- Standard_Real u1, v1, u2, v2;
- aWLine2->Point(1).Parameters(u1, v1, u2, v2);
- IntPatch_Point aP;
- aP.SetParameter(u1);
- aP.SetParameters(u1, v1, u2, v2);
- aP.SetTolerance(theTol3D);
- aP.SetValue(aWLine2->Point(1).Value());
-
- theSPnt.Append(aP);
+ aDelta = aDU2;
+ anIndex = i;
}
- else if(aWLine2->NbPnts() > 1)
- {
- isTheEmpty = Standard_False;
- isAddedIntoWL2 = Standard_True;
+ }
- SeekAdditionalPoints(theQuad1, theQuad2, aWLine2->Curve(), anEquationCoeffs, aNbPoints, aUSurf2f, aUSurf2l, theTol2D, aPeriod, -1.0, isTheReverse);
+ //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;
- aWLine2->ComputeVertexParameters(theTol3D);
- theSlin.Append(aWLine2);
+ if(!isDone)
+ {
+ continue;
}
- else
+
+ 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))
{
- isAddedIntoWL2 = Standard_False;
+ break;
}
}
- }
- return Standard_True;
+ if(aWLine->NbPnts() > 1)
+ {
+ SeekAdditionalPoints( theQuad1, theQuad2, aWLine->Curve(),
+ anEquationCoeffs, anIndex, aNbMinPoints,
+ 1, aWLine->NbPnts(), theTol2D, aPeriod,
+ isTheReverse);
+
+ aWLine->ComputeVertexParameters(theTol3D);
+ theSlin.Append(aWLine);
+
+ theSPnt.Remove(aNbPnt);
+ aNbPnt--;
+ }
+ }
+
+ return IntPatch_ImpImpIntersection::IntStatus_OK;
}
//=======================================================================
ptvalid = curvsol.Value(para);
alig = new IntPatch_ALine(curvsol,Standard_False);
kept = Standard_True;
- //-- cout << "Transition indeterminee" << endl;
+ //-- std::cout << "Transition indeterminee" << std::endl;
}
if (kept) {
Standard_Boolean Nfirstp = !firstp;
//
return bFind;
}
-//=======================================================================
-//function : IsToReverse
-//purpose :
-//=======================================================================
-Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
- const gp_Cylinder& Cy2,
- const Standard_Real Tol)
-{
- Standard_Boolean bRet;
- Standard_Real aR1,aR2, dR, aSc1, aSc2;
- //
- bRet=Standard_False;
- //
- aR1=Cy1.Radius();
- aR2=Cy2.Radius();
- dR=aR1-aR2;
- if (dR<0.) {
- dR=-dR;
- }
- if (dR>Tol) {
- bRet=aR1>aR2;
- }
- else {
- gp_Dir aDZ(0.,0.,1.);
- //
- const gp_Dir& aDir1=Cy1.Axis().Direction();
- aSc1=aDir1*aDZ;
- if (aSc1<0.) {
- aSc1=-aSc1;
- }
- //
- const gp_Dir& aDir2=Cy2.Axis().Direction();
- aSc2=aDir2*aDZ;
- if (aSc2<0.) {
- aSc2=-aSc2;
- }
- //
- if (aSc2<aSc1) {
- bRet=!bRet;
- }
- }//if (dR<Tol) {
- return bRet;
-}